Compare commits

..

74 Commits
v1.1 ... v1.4

Author SHA1 Message Date
slawkens
93c09b3380 Release v1.4 2025-04-22 13:42:55 +02:00
slawkens
d47195a787 Do not autoload sub-folders if autoload pages is disabled 2025-04-22 13:30:11 +02:00
slawkens
b618084d50 Fix headline.php: change image format to .png cause of black background 2025-04-21 23:43:57 +02:00
slawkens
d0d0af289d Refactor code + use clearCache() instead 2025-04-20 21:32:46 +02:00
slawkens
1d0c173e7d Clear cache on plugin enable/disable, fixes some issues with plugin pages 2025-04-20 21:30:59 +02:00
slawkens
4e7c894cf2 Nothing.. 2025-04-20 21:29:37 +02:00
slawkens
b71555d60d Update router.php 2025-04-20 21:29:22 +02:00
slawkens
c2bf94fb23 Fix: display 404 error instead of 500 when page has been removed from filesystem 2025-04-20 20:40:10 +02:00
João
8cf3409077 SQL Syntax Standardization (#298)
* Update schema.sql

* Update schema.sql
2025-04-18 23:17:35 +02:00
slawkens
e0043b1300 Fix warning 2025-04-18 20:44:11 +02:00
slawkens
86cb5821f6 README.md corrections
* Add links to docs & faq
* add info about 2.x dev version
* fix some grammar typos
2025-04-18 19:42:33 +02:00
slawkens
82a533d88c Add $db->hasTableAndColumns($table, $columns), credits to @opentibiabr Team 2025-04-18 18:12:56 +02:00
slawkens
ceaa0639e6 feat: admin-pages (can add admin pages through plugins)
Also possibility to overwrite default myaac admin pages
2025-04-18 13:57:53 +02:00
slawkens
6844f4392a Change logout button color 2025-04-06 23:46:52 +02:00
slawkens
6d8f4718a1 pages in theme folder have precedence over normal pages 2025-04-06 22:37:36 +02:00
slawkens
f40b986b59 Small changes in account.login.html.twig
* change inputs width to 100%
* fix form closing
* formatting
2025-04-06 17:00:59 +02:00
slawkens
190697ce98 Update config.php 2025-04-06 16:43:30 +02:00
slawkens
64f6d3abca Add noSubmit option to buttons.base 2025-04-06 16:43:19 +02:00
slawkens
e6f05a2731 Plugin name is required, version is optional 2025-04-06 16:41:28 +02:00
slawkens
6a0356aa0f Update version 2025-04-04 21:31:17 +02:00
slawkens
50d649dbde Release v1.3.3 2025-04-04 21:25:19 +02:00
slawkens
6c568fd36a Fix uninstall plugin when plugin is disabled 2025-04-04 21:08:49 +02:00
slawkens
fa6b6aa153 Display more info when error parsing config.lua value 2025-04-04 20:07:42 +02:00
slawkens
ae639d65b0 PHP 8 things 2025-04-03 20:39:27 +02:00
slawkens
35e2483de8 Change root folder to /var/www/html, like in default config 2025-04-02 19:48:23 +02:00
slawkens
bbf923e1a6 Update common.php 2025-04-01 07:56:29 +02:00
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
55 changed files with 861 additions and 453 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,86 @@
# Changelog # Changelog
## [1.4 - 22.04.2025]
### Added
* feat: admin-pages (can add admin pages through plugins) (https://github.com/slawkens/myaac/commit/ceaa0639e66d31e8177ff90791463470367aa45d)
* just place the page in admin-pages folder in the plugin
* Also, possibility to overwrite default myaac admin pages
* Add db->hasTableAndColumns(table, columns), credits to @opentibiabr Team (https://github.com/slawkens/myaac/commit/82a533d88c8a342076891d132b4b409ed9a1fe72)
* Add noSubmit option to buttons.base (https://github.com/slawkens/myaac/commit/64f6d3abcada3bf9fd7599f50d2fac0a1367f383)
### Fixed
* Fix: display 404 error instead of 500 when page has been removed from filesystem (https://github.com/slawkens/myaac/commit/c2bf94fb2370d2009a2eb907f818955132cf8611)
* Fix headline.php: change image format to .png cause of black background (https://github.com/slawkens/myaac/commit/b618084d50918539d9a70abd97e764137b966067)
* Clear cache on plugin enable/disable, fixes some issues with plugin pages being cached (https://github.com/slawkens/myaac/commit/1d0c173e7d000aecbd432800941fc3e38a0e50f2)
* Do not autoload sub-folders if autoload pages is disabled (https://github.com/slawkens/myaac/commit/d47195a7878095336f9c9edc6f96244257f67eec)
### Changed
* SQL Syntax Standardization (by @JoaozinhoBrasil, #298)
* Pages in theme/template folder will now have precedence over normal pages (https://github.com/slawkens/myaac/commit/6d8f4718a1d349fba8f0ebc39cfd3a1a84d104b0)
* Small changes in account.login.html.twig (https://github.com/slawkens/myaac/commit/f40b986b59d4c8fa89ab4745731bf366f8619976)
* Plugin name is required, version is optional (https://github.com/slawkens/myaac/commit/e6f05a2731c61d931be49e121c068e49c0ad5e01)
## [1.3.3 - 04.04.2025]
### Fixed
* Fix uninstall plugin when plugin is disabled (https://github.com/slawkens/myaac/commit/6c568fd36a271270684fc412ccd556b230273a6d)
### Changed
* Display more useful info when error parsing config.lua (https://github.com/slawkens/myaac/commit/fa6b6aa153ffc131e0d1631a4dcd9012a5850c2e)
### Other
* Small adjustments (https://github.com/slawkens/myaac/commit/35e2483de86e295bdf089cceffa25842eeb2e34c, https://github.com/slawkens/myaac/commit/ae639d65b0bfa491e747e907e2ebc77f83f47981)
## [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 +91,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

@@ -12,11 +12,18 @@ Official website: https://my-aac.org
| Version | Status | Branch | Requirements | | Version | Status | Branch | Requirements |
|:--------|:-----------------------|:--------|:---------------| |:--------|:-----------------------|:--------|:---------------|
| **1.x** | **Active development** | develop | **PHP >= 8.1** | | 2.x | Experimental features | develop | PHP >= 8.1 |
| **1.x** | **Active development** | main | **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 |
The recommended version to install is 1.x, which can be found at releases page - [https://github.com/slawkens/myaac/releases](https://github.com/slawkens/myaac/releases).
### Documentation
* [docs.my-aac.org](https://docs.my-aac.org)
* [my-aac.org - FAQ](https://my-aac.org/faqs/)
### Requirements ### Requirements
- MySQL database - MySQL database
@@ -47,23 +54,23 @@ Official website: https://my-aac.org
### Configuration ### Configuration
Check *config.php* to get more informations. (Notice: MyAAC 1.0+ doesn't use config.php anymore, it has been moved to Admin Panel - Settings page). Check *config.php* to get more information. (Notice: MyAAC 1.0+ doesn't use config.php anymore, it has been moved to Admin Panel - Settings page).
Use *config.local.php* for your local configuration changes. Use *config.local.php* for your local configuration changes.
### Branches ### Branches
This repository follows the Git Flow Workflow. This repository follows the Git Flow Workflow.
Cheatsheet: [Git-Flow-Cheetsheet](https://danielkummer.github.io/git-flow-cheatsheet) Cheatsheet: [Git-Flow-Cheatsheet](https://danielkummer.github.io/git-flow-cheatsheet)
That means, we use: That means, we use:
* master branch, for current stable release * main branch, for current stable release
* develop branch, for development version (next release) * develop branch, for development version (next release)
* feature branches, for features etc. * feature branches, for features etc.
### Known Problems ### Known Problems
- Some compatibility issues with some exotical distibutions. - Some compatibility issues with some exotic distributions.
### Contributing ### Contributing
@@ -77,7 +84,7 @@ Look: [Contributing](https://github.com/otsoft/myaac/wiki/Contributing) in our w
### Other Notes ### Other Notes
If you have a great idea or want contribute to the project - visit our website at https://www.my-aac.org If you have a great idea or want to contribute to the project - visit our website at https://www.my-aac.org
## Project supported by JetBrains ## Project supported by JetBrains

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

@@ -1,6 +1,8 @@
<?php <?php
// few things we'll need // few things we'll need
use MyAAC\Plugins;
require '../common.php'; require '../common.php';
const ADMIN_PANEL = true; const ADMIN_PANEL = true;
@@ -42,15 +44,21 @@ if(!$logged || !admin()) {
$page = 'login'; $page = 'login';
} }
// include our page $pluginsAdminPages = Plugins::getAdminPages();
$file = __DIR__ . '/pages/' . $page . '.php'; if(isset($pluginsAdminPages[$page]) && file_exists(BASE . $pluginsAdminPages[$page])) {
if(!@file_exists($file)) { $file = BASE . $pluginsAdminPages[$page];
if (str_contains($page, 'plugins/')) { }
$file = BASE . $page; else {
} // include our page
else { $file = __DIR__ . '/pages/' . $page . '.php';
$page = '404'; if(!@file_exists($file)) {
$file = SYSTEM . 'pages/404.php'; if (str_contains($page, 'plugins/')) {
$file = BASE . $page;
}
else {
$page = '404';
$file = SYSTEM . 'pages/404.php';
}
} }
} }

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

@@ -17,7 +17,7 @@ csrfProtect();
$use_datatable = true; $use_datatable = true;
if (!getBoolean(setting('core.admin_plugins_manage_enable'))) { if (!setting('core.admin_plugins_manage_enable')) {
warning('Plugin installation and management is disabled in Settings.<br/>If you wish to enable, go to Settings and enable <strong>Enable Plugins Manage</strong>.'); warning('Plugin installation and management is disabled in Settings.<br/>If you wish to enable, go to Settings and enable <strong>Enable Plugins Manage</strong>.');
} }
else { else {

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.4';
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

@@ -31,11 +31,11 @@ require_once 'common.php';
require_once SYSTEM . 'functions.php'; require_once SYSTEM . 'functions.php';
$uri = $_SERVER['REQUEST_URI']; $uri = $_SERVER['REQUEST_URI'];
if(false !== strpos($uri, 'index.php')) { if(str_contains($uri, 'index.php')) {
$uri = str_replace_first('/index.php', '', $uri); $uri = str_replace_first('/index.php', '', $uri);
} }
if(0 === strpos($uri, '/')) { if(str_starts_with($uri, '/')) {
$uri = str_replace_first('/', '', $uri); $uri = str_replace_first('/', '', $uri);
} }
@@ -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

@@ -26,6 +26,9 @@ if(!isset($error) || !$error) {
$config['database_type'] = $config['lua']['database_type']; $config['database_type'] = $config['lua']['database_type'];
else if(isset($config['lua']['sql_type'])) // otserv else if(isset($config['lua']['sql_type'])) // otserv
$config['database_type'] = $config['lua']['sql_type']; $config['database_type'] = $config['lua']['sql_type'];
else {
$config['database_type'] = '';
}
$config['database_type'] = strtolower($config['database_type']); $config['database_type'] = strtolower($config['database_type']);
if(empty($config['database_type'])) { if(empty($config['database_type'])) {

View File

@@ -2,34 +2,34 @@ SET @myaac_database_version = 43;
CREATE TABLE `myaac_account_actions` CREATE TABLE `myaac_account_actions`
( (
`account_id` INT(11) NOT NULL, `account_id` int NOT NULL,
`ip` INT(10) UNSIGNED NOT NULL DEFAULT 0, `ip` int unsigned NOT NULL DEFAULT 0,
`ipv6` BINARY(16) NOT NULL DEFAULT 0, `ipv6` binary(16) NOT NULL DEFAULT 0,
`date` INT(11) NOT NULL DEFAULT 0, `date` int NOT NULL DEFAULT 0,
`action` VARCHAR(255) NOT NULL DEFAULT '', `action` varchar(255) NOT NULL DEFAULT '',
KEY (`account_id`) KEY (`account_id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_admin_menu` CREATE TABLE `myaac_admin_menu`
( (
`id` INT(11) NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL DEFAULT '', `name` varchar(255) NOT NULL DEFAULT '',
`page` VARCHAR(255) NOT NULL DEFAULT '', `page` varchar(255) NOT NULL DEFAULT '',
`ordering` INT(11) NOT NULL DEFAULT 0, `ordering` int NOT NULL DEFAULT 0,
`flags` INT(11) NOT NULL DEFAULT 0, `flags` int NOT NULL DEFAULT 0,
`enabled` INT(1) NOT NULL DEFAULT 1, `enabled` int NOT NULL DEFAULT 1,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_changelog` CREATE TABLE `myaac_changelog`
( (
`id` INT(11) NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`body` VARCHAR(500) NOT NULL DEFAULT '', `body` varchar(500) NOT NULL DEFAULT '',
`type` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '1 - added, 2 - removed, 3 - changed, 4 - fixed', `type` tinyint NOT NULL DEFAULT 0 COMMENT '1 - added, 2 - removed, 3 - changed, 4 - fixed',
`where` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '1 - server, 2 - site', `where` tinyint NOT NULL DEFAULT 0 COMMENT '1 - server, 2 - site',
`date` INT(11) NOT NULL DEFAULT 0, `date` int NOT NULL DEFAULT 0,
`player_id` INT(11) NOT NULL DEFAULT 0, `player_id` int NOT NULL DEFAULT 0,
`hide` TINYINT(1) NOT NULL DEFAULT 0, `hide` tinyint NOT NULL DEFAULT 0,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
@@ -37,9 +37,9 @@ INSERT INTO `myaac_changelog` (`id`, `type`, `where`, `date`, `body`, `hide`) VA
CREATE TABLE `myaac_config` CREATE TABLE `myaac_config`
( (
`id` INT(11) NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL, `name` varchar(30) NOT NULL,
`value` VARCHAR(1000) NOT NULL, `value` varchar(1000) NOT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE (`name`) UNIQUE (`name`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
@@ -48,24 +48,24 @@ INSERT INTO `myaac_config` (`name`, `value`) VALUES ('database_version', @myaac_
CREATE TABLE `myaac_faq` CREATE TABLE `myaac_faq`
( (
`id` INT(11) NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`question` VARCHAR(255) NOT NULL DEFAULT '', `question` varchar(255) NOT NULL DEFAULT '',
`answer` VARCHAR(1020) NOT NULL DEFAULT '', `answer` varchar(1020) NOT NULL DEFAULT '',
`ordering` INT(11) NOT NULL DEFAULT 0, `ordering` int NOT NULL DEFAULT 0,
`hide` TINYINT(1) NOT NULL DEFAULT 0, `hide` tinyint NOT NULL DEFAULT 0,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_forum_boards` CREATE TABLE `myaac_forum_boards`
( (
`id` INT(11) NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`name` VARCHAR(32) NOT NULL, `name` varchar(32) NOT NULL,
`description` VARCHAR(255) NOT NULL DEFAULT '', `description` varchar(255) NOT NULL DEFAULT '',
`ordering` INT(11) NOT NULL DEFAULT 0, `ordering` int NOT NULL DEFAULT 0,
`guild` INT(11) NOT NULL DEFAULT 0, `guild` int NOT NULL DEFAULT 0,
`access` INT(11) NOT NULL DEFAULT 0, `access` int NOT NULL DEFAULT 0,
`closed` TINYINT(1) NOT NULL DEFAULT 0, `closed` tinyint NOT NULL DEFAULT 0,
`hide` TINYINT(1) NOT NULL DEFAULT 0, `hide` tinyint NOT NULL DEFAULT 0,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`, `closed`) VALUES (NULL, 'News', 'News commenting', 0, 1); INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`, `closed`) VALUES (NULL, 'News', 'News commenting', 0, 1);
@@ -76,100 +76,100 @@ INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUE
CREATE TABLE `myaac_forum` CREATE TABLE `myaac_forum`
( (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`first_post` int(11) NOT NULL default '0', `first_post` int NOT NULL DEFAULT 0,
`last_post` int(11) NOT NULL default '0', `last_post` int NOT NULL DEFAULT 0,
`section` int(3) NOT NULL default '0', `section` int NOT NULL DEFAULT 0,
`replies` int(20) NOT NULL default '0', `replies` int NOT NULL DEFAULT 0,
`views` int(20) NOT NULL default '0', `views` int NOT NULL DEFAULT 0,
`author_aid` int(20) NOT NULL default '0', `author_aid` int NOT NULL DEFAULT 0,
`author_guid` int(20) NOT NULL default '0', `author_guid` int NOT NULL DEFAULT 0,
`post_text` text NOT NULL, `post_text` text NOT NULL,
`post_topic` varchar(255) NOT NULL DEFAULT '', `post_topic` varchar(255) NOT NULL DEFAULT '',
`post_smile` tinyint(1) NOT NULL default '0', `post_smile` tinyint NOT NULL DEFAULT 0,
`post_html` tinyint(1) NOT NULL default '0', `post_html` tinyint NOT NULL DEFAULT 0,
`post_date` int(20) NOT NULL default '0', `post_date` int NOT NULL DEFAULT 0,
`last_edit_aid` int(20) NOT NULL default '0', `last_edit_aid` int NOT NULL DEFAULT 0,
`edit_date` int(20) NOT NULL default '0', `edit_date` int NOT NULL DEFAULT 0,
`post_ip` varchar(45) NOT NULL default '0.0.0.0', `post_ip` varchar(45) NOT NULL DEFAULT '0.0.0.0',
`sticked` tinyint(1) NOT NULL DEFAULT '0', `sticked` tinyint NOT NULL DEFAULT 0,
`closed` tinyint(1) NOT NULL DEFAULT '0', `closed` tinyint NOT NULL DEFAULT 0,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `section` (`section`) KEY `section` (`section`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_menu` CREATE TABLE `myaac_menu`
( (
`id` INT(11) NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`template` VARCHAR(255) NOT NULL, `template` varchar(255) NOT NULL,
`name` VARCHAR(255) NOT NULL, `name` varchar(255) NOT NULL,
`link` VARCHAR(255) NOT NULL, `link` varchar(255) NOT NULL,
`blank` TINYINT(1) NOT NULL DEFAULT 0, `blank` tinyint NOT NULL DEFAULT 0,
`color` VARCHAR(6) NOT NULL DEFAULT '', `color` varchar(6) NOT NULL DEFAULT '',
`category` INT(11) NOT NULL DEFAULT 1, `category` int NOT NULL DEFAULT 1,
`ordering` INT(11) NOT NULL DEFAULT 0, `ordering` int NOT NULL DEFAULT 0,
`enabled` INT(1) NOT NULL DEFAULT 1, `enabled` int NOT NULL DEFAULT 1,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_monsters` ( CREATE TABLE `myaac_monsters` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`hide` tinyint(1) NOT NULL default 0, `hide` tinyint NOT NULL DEFAULT 0,
`name` varchar(255) NOT NULL, `name` varchar(255) NOT NULL,
`mana` int(11) NOT NULL DEFAULT 0, `mana` int NOT NULL DEFAULT 0,
`exp` int(11) NOT NULL, `exp` int NOT NULL,
`health` int(11) NOT NULL, `health` int NOT NULL,
`look` VARCHAR(255) NOT NULL DEFAULT '', `look` varchar(255) NOT NULL DEFAULT '',
`speed_lvl` int(11) NOT NULL default 1, `speed_lvl` int NOT NULL DEFAULT 1,
`use_haste` tinyint(1) NOT NULL, `use_haste` tinyint NOT NULL,
`voices` text NOT NULL, `voices` text NOT NULL,
`immunities` varchar(255) NOT NULL, `immunities` varchar(255) NOT NULL,
`elements` TEXT NOT NULL, `elements` text NOT NULL,
`summonable` tinyint(1) NOT NULL, `summonable` tinyint NOT NULL,
`convinceable` tinyint(1) NOT NULL, `convinceable` tinyint NOT NULL,
`pushable` TINYINT(1) NOT NULL DEFAULT '0', `pushable` tinyint NOT NULL DEFAULT 0,
`canpushitems` TINYINT(1) NOT NULL DEFAULT '0', `canpushitems` tinyint NOT NULL DEFAULT 0,
`canwalkonenergy` TINYINT(1) NOT NULL DEFAULT '0', `canwalkonenergy` tinyint NOT NULL DEFAULT 0,
`canwalkonpoison` TINYINT(1) NOT NULL DEFAULT '0', `canwalkonpoison` tinyint NOT NULL DEFAULT 0,
`canwalkonfire` TINYINT(1) NOT NULL DEFAULT '0', `canwalkonfire` tinyint NOT NULL DEFAULT 0,
`runonhealth` TINYINT(1) NOT NULL DEFAULT '0', `runonhealth` tinyint NOT NULL DEFAULT 0,
`hostile` TINYINT(1) NOT NULL DEFAULT '0', `hostile` tinyint NOT NULL DEFAULT 0,
`attackable` TINYINT(1) NOT NULL DEFAULT '0', `attackable` tinyint NOT NULL DEFAULT 0,
`rewardboss` TINYINT(1) NOT NULL DEFAULT '0', `rewardboss` tinyint NOT NULL DEFAULT 0,
`defense` INT(11) NOT NULL DEFAULT '0', `defense` int NOT NULL DEFAULT 0,
`armor` INT(11) NOT NULL DEFAULT '0', `armor` int NOT NULL DEFAULT 0,
`canpushcreatures` TINYINT(1) NOT NULL DEFAULT '0', `canpushcreatures` tinyint NOT NULL DEFAULT 0,
`race` varchar(255) NOT NULL, `race` varchar(255) NOT NULL,
`loot` text NOT NULL, `loot` text NOT NULL,
`summons` TEXT NOT NULL, `summons` text NOT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_news` CREATE TABLE `myaac_news`
( (
`id` INT(11) NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`title` VARCHAR(100) NOT NULL, `title` varchar(100) NOT NULL,
`body` TEXT NOT NULL, `body` text NOT NULL,
`type` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '1 - news, 2 - ticker, 3 - article', `type` tinyint NOT NULL DEFAULT 0 COMMENT '1 - news, 2 - ticker, 3 - article',
`date` INT(11) NOT NULL DEFAULT 0, `date` int NOT NULL DEFAULT 0,
`category` TINYINT(1) NOT NULL DEFAULT 0, `category` tinyint NOT NULL DEFAULT 0,
`player_id` INT(11) NOT NULL DEFAULT 0, `player_id` int NOT NULL DEFAULT 0,
`last_modified_by` INT(11) NOT NULL DEFAULT 0, `last_modified_by` int NOT NULL DEFAULT 0,
`last_modified_date` INT(11) NOT NULL DEFAULT 0, `last_modified_date` int NOT NULL DEFAULT 0,
`comments` VARCHAR(50) NOT NULL DEFAULT '', `comments` varchar(50) NOT NULL DEFAULT '',
`article_text` VARCHAR(300) NOT NULL DEFAULT '', `article_text` varchar(300) NOT NULL DEFAULT '',
`article_image` VARCHAR(100) NOT NULL DEFAULT '', `article_image` varchar(100) NOT NULL DEFAULT '',
`hide` TINYINT(1) NOT NULL DEFAULT 0, `hide` tinyint NOT NULL DEFAULT 0,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_news_categories` CREATE TABLE `myaac_news_categories`
( (
`id` INT(11) NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL DEFAULT "", `name` varchar(50) NOT NULL DEFAULT "",
`description` VARCHAR(50) NOT NULL DEFAULT "", `description` varchar(50) NOT NULL DEFAULT "",
`icon_id` INT(2) NOT NULL DEFAULT 0, `icon_id` int NOT NULL DEFAULT 0,
`hide` TINYINT(1) NOT NULL DEFAULT 0, `hide` tinyint NOT NULL DEFAULT 0,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
@@ -181,39 +181,39 @@ INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 4);
CREATE TABLE `myaac_notepad` CREATE TABLE `myaac_notepad`
( (
`id` INT(11) NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`account_id` INT(11) NOT NULL, `account_id` int NOT NULL,
/*`name` VARCHAR(30) NOT NULL,*/ /*`name` varchar(30) NOT NULL,*/
`content` TEXT NOT NULL, `content` text NOT NULL,
/*`public` TINYINT(1) NOT NULL DEFAULT 0*/ /*`public` tinyint NOT NULL DEFAULT 0*/
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_pages` CREATE TABLE `myaac_pages`
( (
`id` INT NOT NULL AUTO_INCREMENT, `id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL, `name` varchar(30) NOT NULL,
`title` VARCHAR(30) NOT NULL, `title` varchar(30) NOT NULL,
`body` TEXT NOT NULL, `body` text NOT NULL,
`date` INT(11) NOT NULL DEFAULT 0, `date` int NOT NULL DEFAULT 0,
`player_id` INT(11) NOT NULL DEFAULT 0, `player_id` int NOT NULL DEFAULT 0,
`php` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '0 - plain html, 1 - php', `php` tinyint NOT NULL DEFAULT 0 COMMENT '0 - plain html, 1 - php',
`enable_tinymce` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '1 - enabled, 0 - disabled', `enable_tinymce` tinyint NOT NULL DEFAULT 1 COMMENT '1 - enabled, 0 - disabled',
`access` TINYINT(2) NOT NULL DEFAULT 0, `access` tinyint NOT NULL DEFAULT 0,
`hide` TINYINT(1) NOT NULL DEFAULT 0, `hide` tinyint NOT NULL DEFAULT 0,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE (`name`) UNIQUE (`name`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_gallery` CREATE TABLE `myaac_gallery`
( (
`id` INT(11) NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`comment` VARCHAR(255) NOT NULL DEFAULT '', `comment` varchar(255) NOT NULL DEFAULT '',
`image` VARCHAR(255) NOT NULL, `image` varchar(255) NOT NULL,
`thumb` VARCHAR(255) NOT NULL, `thumb` varchar(255) NOT NULL,
`author` VARCHAR(50) NOT NULL DEFAULT '', `author` varchar(50) NOT NULL DEFAULT '',
`ordering` INT(11) NOT NULL DEFAULT 0, `ordering` int NOT NULL DEFAULT 0,
`hide` TINYINT(1) NOT NULL DEFAULT 0, `hide` tinyint NOT NULL DEFAULT 0,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
@@ -221,51 +221,51 @@ INSERT INTO `myaac_gallery` (`id`, `ordering`, `comment`, `image`, `thumb`, `aut
CREATE TABLE `myaac_settings` CREATE TABLE `myaac_settings`
( (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL DEFAULT '', `name` varchar(255) NOT NULL DEFAULT '',
`key` VARCHAR(255) NOT NULL DEFAULT '', `key` varchar(255) NOT NULL DEFAULT '',
`value` TEXT NOT NULL, `value` text NOT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `key` (`key`) KEY `key` (`key`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_spells` CREATE TABLE `myaac_spells`
( (
`id` INT(11) NOT NULL AUTO_INCREMENT, `id` int NOT NULL AUTO_INCREMENT,
`spell` VARCHAR(255) NOT NULL DEFAULT '', `spell` varchar(255) NOT NULL DEFAULT '',
`name` VARCHAR(255) NOT NULL, `name` varchar(255) NOT NULL,
`words` VARCHAR(255) NOT NULL DEFAULT '', `words` varchar(255) NOT NULL DEFAULT '',
`category` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '1 - attack, 2 - healing, 3 - summon, 4 - supply, 5 - support', `category` tinyint NOT NULL DEFAULT 0 COMMENT '1 - attack, 2 - healing, 3 - summon, 4 - supply, 5 - support',
`type` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '1 - instant, 2 - conjure, 3 - rune', `type` tinyint NOT NULL DEFAULT 0 COMMENT '1 - instant, 2 - conjure, 3 - rune',
`level` INT(11) NOT NULL DEFAULT 0, `level` int NOT NULL DEFAULT 0,
`maglevel` INT(11) NOT NULL DEFAULT 0, `maglevel` int NOT NULL DEFAULT 0,
`mana` INT(11) NOT NULL DEFAULT 0, `mana` int NOT NULL DEFAULT 0,
`soul` TINYINT(3) NOT NULL DEFAULT 0, `soul` tinyint NOT NULL DEFAULT 0,
`conjure_id` INT(11) NOT NULL DEFAULT 0, `conjure_id` int NOT NULL DEFAULT 0,
`conjure_count` TINYINT(3) NOT NULL DEFAULT 0, `conjure_count` tinyint NOT NULL DEFAULT 0,
`reagent` INT(11) NOT NULL DEFAULT 0, `reagent` int NOT NULL DEFAULT 0,
`item_id` INT(11) NOT NULL DEFAULT 0, `item_id` int NOT NULL DEFAULT 0,
`premium` TINYINT(1) NOT NULL DEFAULT 0, `premium` tinyint NOT NULL DEFAULT 0,
`vocations` VARCHAR(100) NOT NULL DEFAULT '', `vocations` varchar(100) NOT NULL DEFAULT '',
`hide` TINYINT(1) NOT NULL DEFAULT 0, `hide` tinyint NOT NULL DEFAULT 0,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE (`name`) UNIQUE (`name`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_visitors` CREATE TABLE `myaac_visitors`
( (
`ip` VARCHAR(45) NOT NULL, `ip` varchar(45) NOT NULL,
`lastvisit` INT(11) NOT NULL DEFAULT 0, `lastvisit` int NOT NULL DEFAULT 0,
`page` VARCHAR(2048) NOT NULL, `page` varchar(2048) NOT NULL,
`user_agent` VARCHAR(255) NOT NULL DEFAULT '', `user_agent` varchar(255) NOT NULL DEFAULT '',
UNIQUE (`ip`) UNIQUE (`ip`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_weapons` CREATE TABLE `myaac_weapons`
( (
`id` INT(11) NOT NULL, `id` int NOT NULL,
`level` INT(11) NOT NULL DEFAULT 0, `level` int NOT NULL DEFAULT 0,
`maglevel` INT(11) NOT NULL DEFAULT 0, `maglevel` int NOT NULL DEFAULT 0,
`vocations` VARCHAR(100) NOT NULL DEFAULT '', `vocations` varchar(100) NOT NULL DEFAULT '',
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;

View File

@@ -1,6 +1,6 @@
server { server {
listen 80; listen 80;
root /home/otserv/www/public; root /var/www/html;
index index.php; index index.php;
server_name your-domain.com; server_name your-domain.com;

View File

@@ -46,8 +46,10 @@
"settings": "plugins/your-plugin-folder/settings.php", "settings": "plugins/your-plugin-folder/settings.php",
"autoload": { "autoload": {
"pages": true, "pages": true,
"pagesSubFolders": false, "pages-sub-folders": false,
"commands": true, "commands": true,
"themes": true "themes": true,
"admin-pages": true,
"admin-pages-sub-folders": true,
} }
} }

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,12 +1012,19 @@ 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;"); }
if((string) $ret == '' && trim($value) !== '""') // = parser error
{ try {
throw new RuntimeException('ERROR: Loading config.lua file. Line <b>' . ($ln + 1) . '</b> of LUA config file is not valid [key: <b>' . $key . '</b>]'); $ret = eval("return $value;");
}
catch (Throwable $e) {
throw new RuntimeException('ERROR: Loading config.lua file. Line: ' . ($ln + 1) . ' - Unable to parse value "' . $value . '" - ' . $e->getMessage());
}
if((string) $ret == '' && trim($value) !== '""') {
throw new RuntimeException('ERROR: Loading config.lua file. Line ' . ($ln + 1) . ' is not valid [key: ' . $key . ']');
} }
$result[$key] = $ret; $result[$key] = $ret;
} }
@@ -1030,8 +1033,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 +1059,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 +1128,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

@@ -234,6 +234,19 @@ class OTS_DB_MySQL extends OTS_Base_DB
return $this->hasTable($table) && ($this->has_column_cache[$table . '.' . $column] = count($this->query('SHOW COLUMNS FROM `' . $table . "` LIKE '" . $column . "'")->fetchAll()) > 0); return $this->hasTable($table) && ($this->has_column_cache[$table . '.' . $column] = count($this->query('SHOW COLUMNS FROM `' . $table . "` LIKE '" . $column . "'")->fetchAll()) > 0);
} }
public function hasTableAndColumns(string $table, array $columns = []): bool
{
if (!$this->hasTable($table)) return false;
foreach ($columns as $column) {
if (!$this->hasColumn($table, $column)) {
return false;
}
}
return true;
}
public function revalidateCache() { public function revalidateCache() {
foreach($this->has_table_cache as $key => $value) { foreach($this->has_table_cache as $key => $value) {
$this->hasTableInternal($key); $this->hasTableInternal($key);

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

@@ -89,8 +89,6 @@ if($logged && $account_logged && $account_logged->isLoaded()) {
* Routes loading * Routes loading
*/ */
$dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) { $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) {
$routes = require SYSTEM . 'routes.php';
$routesFinal = []; $routesFinal = [];
foreach(getDatabasePages() as $page) { foreach(getDatabasePages() as $page) {
$routesFinal[] = ['*', $page, '__database__/' . $page, 100]; $routesFinal[] = ['*', $page, '__database__/' . $page, 100];
@@ -106,8 +104,13 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r)
*/ */
} }
$routes = require SYSTEM . 'routes.php';
foreach ($routes as $route) { foreach ($routes as $route) {
if (!str_contains($route[2], '__redirect__') && !str_contains($route[2], '__database__')) { if (!str_contains($route[2], '__redirect__') && !str_contains($route[2], '__database__')) {
if (!is_file(BASE . 'system/pages/' . $route[2])) {
continue;
}
$routesFinal[] = [$route[0], $route[1], 'system/pages/' . $route[2], $route[3] ?? 10000]; $routesFinal[] = [$route[0], $route[1], 'system/pages/' . $route[2], $route[3] ?? 10000];
} }
else { else {
@@ -343,16 +346,16 @@ function getDatabasePages($withHidden = false): array
function loadPageFromFileSystem($page, &$found): string function loadPageFromFileSystem($page, &$found): string
{ {
$file = SYSTEM . 'pages/' . $page . '.php'; // feature: load pages from templates/ dir
global $template_path;
$file = $template_path . '/pages/' . $page . '.php';
if (!is_file($file)) { if (!is_file($file)) {
// feature: convert camelCase to snake_case $file = SYSTEM . 'pages/' . $page . '.php';
// so instead of forum/move_thread
// we can write: forum/moveThread
$file = SYSTEM . 'pages/' . camelCaseToUnderscore($page) . '.php';
if (!is_file($file)) { if (!is_file($file)) {
// feature: load pages from templates/ dir // feature: convert camelCase to snake_case
global $template_path; // so instead of forum/move_thread
$file = $template_path . '/pages/' . $page . '.php'; // we can write: forum/moveThread
$file = SYSTEM . 'pages/' . camelCaseToUnderscore($page) . '.php';
if (!is_file($file)) { if (!is_file($file)) {
$found = false; $found = false;
} }

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

@@ -11,6 +11,81 @@ class Plugins {
private static $error = null; private static $error = null;
private static $plugin_json = []; private static $plugin_json = [];
public static function getAdminPages()
{
return Cache::remember('plugins_admin_pages', 10 * 60, function () {
$adminPages = [];
foreach(self::getAllPluginsJson() as $plugin) {
if (!self::getAutoLoadOption($plugin, 'admin-pages', true)) {
continue;
}
$adminPagesDefaultPriority = 1000;
if (isset($plugin['admin-pages-default-priority'])) {
$adminPagesDefaultPriority = $plugin['admin-pages-default-priority'];
}
//
// Get all plugins/*/admin-pages/*.php pages
//
$pluginAdminPages = glob(PLUGINS . $plugin['filename'] . '/admin-pages/*.php');
foreach ($pluginAdminPages as $file) {
$file = str_replace(PLUGINS, 'plugins/', $file);
$name = pathinfo($file, PATHINFO_FILENAME);
$adminPages[] = ['name' => $name, 'file' => $file, 'priority' => $adminPagesDefaultPriority];
}
if (self::getAutoLoadOption($plugin, 'admin-pages-sub-folders', true)) {
//
// Get all plugins/*/admin-pages/subFolder/*.php pages
//
$pluginAdminPagesSubFolders = glob(PLUGINS . $plugin['filename'] . '/admin-pages/*', GLOB_ONLYDIR);
foreach ($pluginAdminPagesSubFolders as $folder) {
$folderName = pathinfo($folder, PATHINFO_FILENAME);
$subFiles = glob(PLUGINS . $plugin['filename'] . '/admin-pages/' . $folderName . '/*.php');
foreach ($subFiles as $file) {
$file = str_replace(PLUGINS, 'plugins/', $file);
$name = $folderName . '/' . pathinfo($file, PATHINFO_FILENAME);
$adminPages[] = ['name' => $name, 'file' => $file, 'priority' => $adminPagesDefaultPriority];
}
$subFolders = glob(PLUGINS . $plugin['filename'] . '/admin-pages/' . $folderName . '/*', GLOB_ONLYDIR);
foreach ($subFolders as $subFolder) {
$subFolderName = pathinfo($subFolder, PATHINFO_FILENAME);
$subSubFiles = glob(PLUGINS . $plugin['filename'] . '/admin-pages/' . $folderName . '/' . $subFolderName . '/*.php');
foreach ($subSubFiles as $subSubFile) {
$subSubFile = str_replace(PLUGINS, 'plugins/', $subSubFile);
$name = $folderName . '/' . $subFolderName . '/' . pathinfo($subSubFile, PATHINFO_FILENAME);
$adminPages[] = ['name' => $name, 'file' => $subSubFile, 'priority' => $adminPagesDefaultPriority];;
}
}
}
}
}
usort($adminPages, function ($a, $b)
{
if ($a['priority'] == $b['priority']) {
return 0;
}
return ($a['priority'] > $b['priority']) ? -1 : 1;
});
$ret = [];
foreach ($adminPages as $value) {
$ret[$value['name']] = $value['file'];
}
return $ret;
});
}
public static function getRoutes() public static function getRoutes()
{ {
$cache = Cache::getInstance(); $cache = Cache::getInstance();
@@ -76,7 +151,8 @@ class Plugins {
$pagesDefaultPriority = $plugin['pages-default-priority']; $pagesDefaultPriority = $plugin['pages-default-priority'];
} }
if (self::getAutoLoadOption($plugin, 'pages', true)) { $autoLoadPages = self::getAutoLoadOption($plugin, 'pages', true);
if ($autoLoadPages) {
// //
// Get all plugins/*/pages/*.php pages // Get all plugins/*/pages/*.php pages
// //
@@ -89,7 +165,8 @@ class Plugins {
} }
} }
if (self::getAutoLoadOption($plugin, 'pagesSubFolders', true)) { if ($autoLoadPages && self::getAutoLoadOption($plugin, 'pagesSubFolders', true) &&
self::getAutoLoadOption($plugin, 'pages-sub-folders', true)) {
// //
// Get all plugins/*/pages/subFolder/*.php pages // Get all plugins/*/pages/subFolder/*.php pages
// //
@@ -411,20 +488,13 @@ class Plugins {
$continue = true; $continue = true;
if(!isset($plugin_json['name']) || empty(trim($plugin_json['name']))) { if(!isset($plugin_json['name']) || empty(trim($plugin_json['name']))) {
self::$warnings[] = 'Plugin "name" tag is not set.'; self::$error = 'Plugin "name" tag is not set.';
} return false;
if(!isset($plugin_json['description']) || empty(trim($plugin_json['description']))) {
self::$warnings[] = 'Plugin "description" tag is not set.';
} }
if(!isset($plugin_json['version']) || empty(trim($plugin_json['version']))) { if(!isset($plugin_json['version']) || empty(trim($plugin_json['version']))) {
self::$warnings[] = 'Plugin "version" tag is not set.'; self::$warnings[] = 'Plugin "version" tag is not set.';
} }
if(!isset($plugin_json['author']) || empty(trim($plugin_json['author']))) {
self::$warnings[] = 'Plugin "author" tag is not set.';
}
if(!isset($plugin_json['contact']) || empty(trim($plugin_json['contact']))) {
self::$warnings[] = 'Plugin "contact" tag is not set.';
}
if(isset($plugin_json['require'])) { if(isset($plugin_json['require'])) {
$require = $plugin_json['require']; $require = $plugin_json['require'];
@@ -631,6 +701,7 @@ class Plugins {
return false; return false;
} }
clearCache();
return true; return true;
} }
@@ -675,26 +746,41 @@ class Plugins {
public static function uninstall($plugin_name): bool public static function uninstall($plugin_name): bool
{ {
$isDisabled = self::existDisabled($plugin_name);
if($isDisabled) {
self::enable($plugin_name);
}
$revertEnable = function() use ($isDisabled, $plugin_name) {
if($isDisabled) {
self::disable($plugin_name);
}
};
$filename = BASE . 'plugins/' . $plugin_name . '.json'; $filename = BASE . 'plugins/' . $plugin_name . '.json';
if(!file_exists($filename)) { if(!file_exists($filename)) {
self::$error = 'Plugin ' . $plugin_name . ' does not exist.'; self::$error = 'Plugin ' . $plugin_name . ' does not exist.';
$revertEnable();
return false; return false;
} }
$string = file_get_contents($filename); $string = file_get_contents($filename);
$plugin_info = json_decode($string, true); $plugin_info = json_decode($string, true);
if(!$plugin_info) { if(!$plugin_info) {
self::$error = 'Cannot load plugin info ' . $plugin_name . '.json'; self::$error = 'Cannot load plugin info ' . $plugin_name . '.json';
$revertEnable();
return false; return false;
} }
if(!isset($plugin_info['uninstall'])) { if(!isset($plugin_info['uninstall'])) {
self::$error = "Plugin doesn't have uninstall options defined. Skipping..."; self::$error = "Plugin doesn't have uninstall options defined. Skipping...";
$revertEnable();
return false; return false;
} }
$success = true; $success = true;
foreach($plugin_info['uninstall'] as $file) { foreach($plugin_info['uninstall'] as $file) {
if(strpos($file, '/') === 0) { if(str_starts_with($file, '/')) {
$success = false; $success = false;
self::$error = "You cannot use absolute paths (starting with slash - '/'): " . $file; self::$error = "You cannot use absolute paths (starting with slash - '/'): " . $file;
break; break;
@@ -709,24 +795,19 @@ class Plugins {
} }
} }
if($success) { if(!$success) {
foreach($plugin_info['uninstall'] as $file) { $revertEnable();
if(!deleteDirectory(BASE . $file)) { return false;
self::$warnings[] = 'Cannot delete: ' . $file;
}
}
$cache = Cache::getInstance();
if($cache->enabled()) {
$cache->delete('templates');
$cache->delete('hooks');
$cache->delete('template_menus');
}
return true;
} }
return false; foreach($plugin_info['uninstall'] as $file) {
if(!deleteDirectory(BASE . $file)) {
self::$warnings[] = 'Cannot delete: ' . $file;
}
}
clearCache();
return true;
} }
public static function is_installed($plugin_name, $version): bool public static function is_installed($plugin_name, $version): bool

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

@@ -1 +1 @@
<input type="submit" name="{{ button_name }}" value="{{ button_name }}" /> <input {% if noSubmit is not defined %}type="submit"{% endif %} name="{{ button_name }}" value="{{ button_name }}" />

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

@@ -4,24 +4,25 @@
<input type="hidden" name="redirect" value="{{ redirect }}" /> <input type="hidden" name="redirect" value="{{ redirect }}" />
{% endif %} {% endif %}
<div class="TableContainer" > <div class="TableContainer" >
<table class="Table4" cellpadding="0" cellspacing="0" > <div class="CaptionContainer" >
<div class="CaptionContainer" > <div class="CaptionInnerContainer" >
<div class="CaptionInnerContainer" > <span class="CaptionEdgeLeftTop" style="background-image:url({{ template_path }}/images/global/content/box-frame-edge.gif);" ></span>
<span class="CaptionEdgeLeftTop" style="background-image:url({{ template_path }}/images/global/content/box-frame-edge.gif);" /></span> <span class="CaptionEdgeRightTop" style="background-image:url({{ template_path }}/images/global/content/box-frame-edge.gif);" ></span>
<span class="CaptionEdgeRightTop" style="background-image:url({{ template_path }}/images/global/content/box-frame-edge.gif);" /></span> <span class="CaptionBorderTop" style="background-image:url({{ template_path }}/images/global/content/table-headline-border.gif);" ></span>
<span class="CaptionBorderTop" style="background-image:url({{ template_path }}/images/global/content/table-headline-border.gif);" ></span> <span class="CaptionVerticalLeft" style="background-image:url({{ template_path }}/images/global/content/box-frame-vertical.gif);" ></span>
<span class="CaptionVerticalLeft" style="background-image:url({{ template_path }}/images/global/content/box-frame-vertical.gif);" /></span> <div class="Text" >Account Login</div>
<div class="Text" >Account Login</div> <span class="CaptionVerticalRight" style="background-image:url({{ template_path }}/images/global/content/box-frame-vertical.gif);" ></span>
<span class="CaptionVerticalRight" style="background-image:url({{ template_path }}/images/global/content/box-frame-vertical.gif);" /></span> <span class="CaptionBorderBottom" style="background-image:url({{ template_path }}/images/global/content/table-headline-border.gif);" ></span>
<span class="CaptionBorderBottom" style="background-image:url({{ template_path }}/images/global/content/table-headline-border.gif);" ></span> <span class="CaptionEdgeLeftBottom" style="background-image:url({{ template_path }}/images/global/content/box-frame-edge.gif);" ></span>
<span class="CaptionEdgeLeftBottom" style="background-image:url({{ template_path }}/images/global/content/box-frame-edge.gif);" /></span> <span class="CaptionEdgeRightBottom" style="background-image:url({{ template_path }}/images/global/content/box-frame-edge.gif);" ></span>
<span class="CaptionEdgeRightBottom" style="background-image:url({{ template_path }}/images/global/content/box-frame-edge.gif);" /></span>
</div>
</div> </div>
</div>
<table class="Table4" cellpadding="0" cellspacing="0" >
<tr> <tr>
<td> <td>
<div class="InnerTableContainer" > <div class="InnerTableContainer" >
<table style="width:100%;" > <table style="width:100%;" >
<tbody>
<tr> <tr>
<td> <td>
<div class="TableShadowContainerRightTop" > <div class="TableShadowContainerRightTop" >
@@ -30,20 +31,21 @@
<div class="TableContentAndRightShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-rm.gif);" > <div class="TableContentAndRightShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-rm.gif);" >
<div class="TableContentContainer" > <div class="TableContentContainer" >
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;" > <table class="TableContent" width="100%" style="border:1px solid #faf0d7;" >
<tbody>
<tr> <tr>
<td> <td>
<table style="float: left; width: 370px;" cellpadding="0" cellspacing="0" > <table style="float: left; width: 100%;" cellpadding="0" cellspacing="0" >
{{ hook('HOOK_ACCOUNT_LOGIN_BEFORE_ACCOUNT') }} {{ hook('HOOK_ACCOUNT_LOGIN_BEFORE_ACCOUNT') }}
<tr> <tr>
<td class="LabelV"> <td class="LabelV">
<span{% if error is not null %} class="red"{% endif %}>{{ account_login_by }}:</span> <span{% if error is not null %} class="red"{% endif %}>{{ account_login_by }}:</span>
</td> </td>
<td><input type="text" name="account_login" size="35" maxlength="{{ setting('core.account_login_by_email') ? '255' : '30' }}" autofocus /></td> <td><input style="width: 100%;" type="text" name="account_login" size="35" maxlength="{{ setting('core.account_login_by_email') ? '255' : '30' }}" autofocus /></td>
</tr> </tr>
{{ hook('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT') }} {{ hook('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT') }}
<tr> <tr>
<td class="LabelV" ><span{% if error is not null %} class="red"{% endif %}>Password:</span></td> <td class="LabelV" ><span{% if error is not null %} class="red"{% endif %}>Password:</span></td>
<td><input type="password" name="password_login" size="35" maxlength="29" /></td> <td><input style="width: 100%;" type="password" name="password_login" size="35" maxlength="29" /></td>
</tr> </tr>
{{ hook('HOOK_ACCOUNT_LOGIN_AFTER_PASSWORD') }} {{ hook('HOOK_ACCOUNT_LOGIN_AFTER_PASSWORD') }}
<tr> <tr>
@@ -53,17 +55,19 @@
</tr> </tr>
{{ hook('HOOK_ACCOUNT_LOGIN_AFTER_REMEMBER_ME') }} {{ hook('HOOK_ACCOUNT_LOGIN_AFTER_REMEMBER_ME') }}
</table> </table>
<div style="float: right; font-size: 1px;" > </td>
<input type="hidden" name="page" value="overview" > <td id="LoginFormButtonCell">
<div style="float: right;" >
{{ include('buttons.login.html.twig') }} {{ include('buttons.login.html.twig') }}
</form>
<div style="width: 2px; height: 2px;" ></div> <div style="width: 2px; height: 2px;" ></div>
<form action="{{ getLink('account/lost') }}" method="post" style="padding:0px;margin:0px;" > <a href="{{ getLink('account/lost') }}" style="padding:0;margin:0;" >
{{ include('buttons.account_lost.html.twig') }} {% set noSubmit = true %}
</form> {{ include('buttons.account_lost.html.twig') }}
</div> </a>
</div>
</td> </td>
</tr> </tr>
</tbody>
</table> </table>
</div> </div>
</div> </div>
@@ -75,35 +79,40 @@
</div> </div>
</td> </td>
</tr> </tr>
</tbody>
</table> </table>
</div> </div>
</td> </td>
</tr> </tr>
</table> </table>
</div> </div>
</form>
<br/> <br/>
<div style="text-align:center"> <div style="text-align:center">
<h1>New to {{ config.lua.serverName }}?</h1> <h1>New to {{ config.lua.serverName }}?</h1>
</div> </div>
<div class="TableContainer" > <div class="TableContainer" >
<table class="Table4" cellpadding="0" cellspacing="0" > <div class="CaptionContainer" >
<div class="CaptionContainer" > <div class="CaptionInnerContainer" >
<div class="CaptionInnerContainer" > <span class="CaptionEdgeLeftTop" style="background-image:url({{ template_path }}/images/global/content/box-frame-edge.gif);"></span>
<span class="CaptionEdgeLeftTop" style="background-image:url({{ template_path }}/images/global/content/box-frame-edge.gif);" /></span> <span class="CaptionEdgeRightTop" style="background-image:url({{ template_path }}/images/global/content/box-frame-edge.gif);"></span>
<span class="CaptionEdgeRightTop" style="background-image:url({{ template_path }}/images/global/content/box-frame-edge.gif);" /></span> <span class="CaptionBorderTop" style="background-image:url({{ template_path }}/images/global/content/table-headline-border.gif);" ></span>
<span class="CaptionBorderTop" style="background-image:url({{ template_path }}/images/global/content/table-headline-border.gif);" ></span> <span class="CaptionVerticalLeft" style="background-image:url({{ template_path }}/images/global/content/box-frame-vertical.gif);"></span>
<span class="CaptionVerticalLeft" style="background-image:url({{ template_path }}/images/global/content/box-frame-vertical.gif);" /></span> <div class="Text" >New Player</div>
<div class="Text" >New Player</div> <span class="CaptionVerticalRight" style="background-image:url({{ template_path }}/images/global/content/box-frame-vertical.gif);"></span>
<span class="CaptionVerticalRight" style="background-image:url({{ template_path }}/images/global/content/box-frame-vertical.gif);" /></span> <span class="CaptionBorderBottom" style="background-image:url({{ template_path }}/images/global/content/table-headline-border.gif);" ></span>
<span class="CaptionBorderBottom" style="background-image:url({{ template_path }}/images/global/content/table-headline-border.gif);" ></span> <span class="CaptionEdgeLeftBottom" style="background-image:url({{ template_path }}/images/global/content/box-frame-edge.gif);"></span>
<span class="CaptionEdgeLeftBottom" style="background-image:url({{ template_path }}/images/global/content/box-frame-edge.gif);" /></span> <span class="CaptionEdgeRightBottom" style="background-image:url({{ template_path }}/images/global/content/box-frame-edge.gif);"></span>
<span class="CaptionEdgeRightBottom" style="background-image:url({{ template_path }}/images/global/content/box-frame-edge.gif);" /></span>
</div>
</div> </div>
</div>
<table class="Table3" cellpadding="0" cellspacing="0" >
<tbody>
<tr> <tr>
<td> <td>
<div class="InnerTableContainer" > <div class="InnerTableContainer" >
<table style="width:100%;" > <table style="width:100%;" >
<tbody>
<tr> <tr>
<td> <td>
<div class="TableShadowContainerRightTop" > <div class="TableShadowContainerRightTop" >
@@ -112,6 +121,7 @@
<div class="TableContentAndRightShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-rm.gif);" > <div class="TableContentAndRightShadow" style="background-image:url({{ template_path }}/images/global/content/table-shadow-rm.gif);" >
<div class="TableContentContainer" > <div class="TableContentContainer" >
<table class="TableContent" width="100%" style="border:1px solid #faf0d7;" > <table class="TableContent" width="100%" style="border:1px solid #faf0d7;" >
<tbody>
<tr> <tr>
<td > <td >
<div style="float: right; margin-top: 20px;" > <div style="float: right; margin-top: 20px;" >
@@ -129,9 +139,12 @@
<div style="margin-left: 10px;" > <div style="margin-left: 10px;" >
<p>... where hardcore gaming meets fantasy.</p> <p>... where hardcore gaming meets fantasy.</p>
<p>... where friendships last a lifetime.</p> <p>... where friendships last a lifetime.</p>
<p>... unites adventurers since 2017!</p> <p>... unites adventurers since 1997!</p>
</div> </div>
</div> </div>
</td>
</tr>
</tbody>
</table> </table>
</div> </div>
</div> </div>
@@ -143,10 +156,12 @@
</div> </div>
</td> </td>
</tr> </tr>
</tbody>
</table> </table>
</div> </div>
</td> </td>
</tr> </tr>
</tbody>
</table> </table>
</div> </div>
{{ hook('HOOK_ACCOUNT_LOGIN_AFTER_PAGE') }} {{ hook('HOOK_ACCOUNT_LOGIN_AFTER_PAGE') }}

View File

@@ -36,6 +36,12 @@ img {
width: expression(document.body.clientWidth > 1200? "1200px": "100%" ); width: expression(document.body.clientWidth > 1200? "1200px": "100%" );
} }
#LoginFormButtonCell {
width: 145px;
vertical-align: top;
padding-right: 10px;
}
#ContentRow { #ContentRow {
position: relative; position: relative;
top: 155px; top: 155px;

View File

@@ -13,7 +13,7 @@
<div class="BigButton" style="background-image:url({{ template_path }}/images/global/buttons/{{ tmp_image }}.gif)"> <div class="BigButton" style="background-image:url({{ template_path }}/images/global/buttons/{{ tmp_image }}.gif)">
<div onMouseOver="MouseOverBigButton(this);" onMouseOut="MouseOutBigButton(this);"> <div onMouseOver="MouseOverBigButton(this);" onMouseOut="MouseOutBigButton(this);">
<div class="BigButtonOver" style="background-image:url({{ template_path }}/images/global/buttons/{{ tmp_image }}_over.gif);" ></div> <div class="BigButtonOver" style="background-image:url({{ template_path }}/images/global/buttons/{{ tmp_image }}_over.gif);" ></div>
<input class="BigButtonText" type="submit" value="{{ button_name }}"> <input class="BigButtonText" {% if noSubmit is not defined %}type="submit"{% endif %} value="{{ button_name }}">
</div> </div>
</div> </div>
{% endapply %} {% endapply %}

View File

@@ -1,3 +1,3 @@
{% set button_name = 'Logout' %} {% set button_name = 'Logout' %}
{% set button_image = '_sbutton_logout' %} {% set button_color = 'red' %}
{% include('buttons.base.html.twig') %} {% include('buttons.base.html.twig') %}

View File

@@ -1,11 +1,13 @@
<?php <?php
$config['menu_default_color'] = '#ffffff'; $config['menu_default_links_color'] = '#ffffff';
$config['menu_categories'] = array( $config['menu_categories'] = [
MENU_CATEGORY_NEWS => array('id' => 'news', 'name' => 'Latest News'), MENU_CATEGORY_NEWS => ['id' => 'news', 'name' => 'Latest News'],
MENU_CATEGORY_ACCOUNT => array('id' => 'account', 'name' => 'Account'), MENU_CATEGORY_ACCOUNT => ['id' => 'account', 'name' => 'Account'],
MENU_CATEGORY_COMMUNITY => array('id' => 'community', 'name' => 'Community'), MENU_CATEGORY_COMMUNITY => ['id' => 'community', 'name' => 'Community'],
MENU_CATEGORY_FORUM => array('id' => 'forum', 'name' => 'Forum'), MENU_CATEGORY_FORUM => ['id' => 'forum', 'name' => 'Forum'],
MENU_CATEGORY_LIBRARY => array('id' => 'library', 'name' => 'Library'), MENU_CATEGORY_LIBRARY => ['id' => 'library', 'name' => 'Library'],
MENU_CATEGORY_SHOP => array('id' => 'shops', 'name' => 'Shop') MENU_CATEGORY_SHOP => ['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));
@@ -17,7 +17,7 @@ $font = getenv('GDFONTPATH') . DIRECTORY_SEPARATOR . 'martel.ttf';
imagettftext($image, 18, 0, 4, 20, imagecolorallocate($image, 240, 209, 164), $font, $text); imagettftext($image, 18, 0, 4, 20, imagecolorallocate($image, 240, 209, 164), $font, $text);
// header mime type // header mime type
header('Content-type: image/gif'); header('Content-type: image/png');
// output image to browser // output image to browser
imagegif($image); imagepng($image);

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>