Compare commits

..

178 Commits

Author SHA1 Message Date
slawkens
e719725841 Merge branch 'main' into develop 2025-05-09 13:45:54 +02:00
slawkens
4ca58b4178 Fix PHP 8.4 deprecation warnings
"Implicitly marking parameter $var as nullable is deprecated, the explicit nullable type must be used instead"
2025-05-09 13:45:46 +02:00
slawkens
03e2752139 Use optionally separate folder for views (thanks @Scrollog for idea) 2025-05-09 13:38:48 +02:00
slawkens
2fece725a4 Improve cypress workflow: add php 8.4 + ignore upload warnings 2025-05-09 13:23:04 +02:00
slawkens
bb3e90110d Merge branch 'main' into develop 2025-05-09 13:14:12 +02:00
slawkens
c24c580796 Fix installMenus when theme/template was removed from disc 2025-05-09 13:09:44 +02:00
slawkens
620a47da72 Update Hooks.php 2025-05-08 20:05:27 +02:00
slawkens
9b75011224 New filter: HOOK_FILTER_ROUTES 2025-05-08 20:05:18 +02:00
slawkens
5b4b7b8a97 triggerFilter -> pass by reference (faster x5) 2025-05-08 20:05:08 +02:00
Slawomir Boczek
99997eb57d Feature/twig hooks filters (#258)
* feat: Hooks filters

* Cleanup
2025-05-08 20:04:54 +02:00
slawkens
73a5829974 Better monster images (no image not found anymore) + use cache 2025-05-05 21:21:54 +02:00
slawkens
497338c2d6 Update robots.txt 2025-05-04 17:20:23 +02:00
slawkens
beb348fe27 testing something 2025-05-04 17:20:12 +02:00
slawkens
5b1bd4f005 Update robots.txt 2025-05-04 17:00:22 +02:00
slawkens
f09606d01b Just testing something 2025-05-04 16:54:49 +02:00
slawkens
67ab425bb9 Add float & double types to the Settings 2025-05-04 09:14:30 +02:00
slawkens
113473f256 Add optional param _page_only for single-page apps etc. 2025-05-03 22:04:08 +02:00
slawkens
d6ac4e8d85 Update index.php 2025-05-03 21:04:13 +02:00
Slawomir Boczek
6845869838 Hoping for a better appear in search engines.. 2025-04-27 17:50:57 +02:00
slawkens
2f0758e351 Update schema.sql 2025-04-26 06:17:58 +02:00
slawkens
6667c8c364 Merge branch 'main' into develop 2025-04-26 06:17:38 +02:00
slawkens
0fbd4bf1be nginx: block additionally *.sql 2025-04-24 13:44:38 +02:00
slawkens
1e45d5c393 Optimize .htaccess FilesMatch: Block access to *.md/json/dist/sql 2025-04-24 13:43:50 +02:00
slawkens
dbea69f314 Fix if user removes the menu category 2025-04-23 20:41:50 +02:00
slawkens
4e6aa0f262 Fix boostedCreature fetch on login.php 2025-04-23 18:05:14 +02:00
slawkens
fa1f927082 Update login.php 2025-04-23 18:04:54 +02:00
slawkens
de0512f11a Start v1.4.1-dev 2025-04-22 15:57:23 +02:00
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
c13a540878 Merge branch 'main' into develop 2025-04-18 13:58:42 +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
869ec035d9 Merge branch 'main' into develop 2025-04-04 21:09:12 +02:00
slawkens
6c568fd36a Fix uninstall plugin when plugin is disabled 2025-04-04 21:08:49 +02:00
slawkens
9d696d31d8 Merge branch 'main' into develop 2025-04-04 20:08:24 +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
8cc4caf587 Merge branch 'main' into develop 2025-04-01 07:43:57 +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
e1d1c7d5db Merge branch 'main' into develop 2025-03-31 22:21:16 +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
320733c2c1 Merge branch 'main' into develop 2025-03-31 19:51:21 +02:00
slawkens
65696f63e3 Fix debugbar/admin panel menu when using custom base_dir 2025-03-31 18:13:45 +02:00
slawkens
c1809a98d1 Merge branch 'main' into develop 2025-03-30 07:11:15 +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
46ed541015 Merge branch 'main' into develop 2025-03-16 20:54:40 +01:00
slawkens
1a5771ad51 Fix migrate:run command 2025-03-16 20:33:53 +01:00
slawkens
29207361b7 Merge branch 'main' into develop 2025-03-16 12:39:32 +01:00
slawkens
6fac883659 Replace links with from accountmanagement to account/manage 2025-03-16 12:39:07 +01:00
slawkens
25013ae91b Merge branch 'main' into develop 2025-03-15 23:09:14 +01:00
slawkens
5d630ba9dd Fix the second "Save" button -> addition to previous commit 2025-03-15 22:49:43 +01:00
slawkens
feadf1314d Fix: add possibility to remove all menu items 2025-03-15 22:49:37 +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
08b8a716d4 Fix the second "Save" button -> addition to previous commit 2025-03-10 13:04:57 +01:00
slawkens
9239a4f419 Fix the second "Save" button -> addition to previous commit 2025-03-10 12:46:33 +01:00
slawkens
cc26b5c744 Fix: add possibility to remove all menu items 2025-03-10 10:48:19 +01:00
slawkens
00fe1adc15 Fix: add possibility to remove all menu items 2025-03-10 10:48:12 +01:00
Slawomir Boczek
cb6e9a6a88 Feature/twig hooks filters (#258)
* feat: Hooks filters

* Cleanup
2025-03-09 21:39:37 +01:00
slawkens
4adb0758c5 Set version to 2.0-dev 2025-03-09 21:26:24 +01:00
Slawomir Boczek
7312383f73 Account actions rework on ip (Use single column for IP - VARCHAR(45)) (#289)
* Account actions rework on ip (Use single column for IP - VARCHAR(45))

* No foreach needed here
2025-03-09 21:18:12 +01:00
slawkens
c2f55791c0 Nothing important, just better code style 2025-03-03 20:07:59 +01:00
slawkens
3c1210fefa Nothing important, just better code style 2025-03-03 20:07:54 +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
slawkens
9ab25abcdf Release v1.1 2025-01-27 22:30:18 +01:00
slawkens
ea753278a0 Secure direct access to template.php 2025-01-27 22:15:00 +01:00
slawkens
4d749b8815 Fix error in CLI, where BASE_URL is not defined 2025-01-24 21:42:52 +01:00
slawkens
07012f786b Ignore lua/ folder 2025-01-22 21:45:07 +01:00
slawkens
a45ceab83a Make players.comment and guilds.description VARCHAR 2025-01-22 21:44:58 +01:00
slawkens
669c447fca Fix hook ACCOUNT_LOGIN_BEFORE_ACCOUNT location 2025-01-21 21:45:28 +01:00
slawkens
da43b32ff0 Nothing important, code refactor 2025-01-21 20:43:59 +01:00
slawkens
cbe0d187b4 Formatting and types hint 2025-01-20 16:31:54 +01:00
slawkens
c5d5bb8067 Adjust mailer settings to latest gmail 2025-01-18 16:18:47 +01:00
slawkens
e85ce193be Add forum to the list 2025-01-18 11:18:21 +01:00
slawkens
3fb2675b5a Fix tibiacom menus 2025-01-18 11:11:35 +01:00
slawkens
b7de8b32eb Revert "Fix menus like char-bazaar/auctions-history etc."
This reverts commit dd47423157.
2025-01-18 11:05:15 +01:00
slawkens
89be68731e Update CHANGELOG.md 2025-01-18 00:11:18 +01:00
slawkens
10dd818b13 Optimize $player->isOnline() function 2025-01-17 22:49:40 +01:00
slawkens
13a1598a46 Nothing important: Convert spaces to tabs 2025-01-17 22:38:27 +01:00
slawkens
4f6178eca0 Initialize menus with menu_categories
If user add custom categories, it will fix an issue where Menu is not collapsed
2025-01-17 21:07:02 +01:00
slawkens
dc2b5afd99 functions_custom.php are not optional 2025-01-17 17:12:21 +01:00
slawkens
11cee81c5f Additional fix to previous commit 2025-01-17 16:36:05 +01:00
slawkens
d639e77d04 tibiacom: Fix the closing MenuBottom if there are extra categories 2025-01-17 16:24:30 +01:00
slawkens
dd47423157 Fix menus like char-bazaar/auctions-history etc. 2025-01-17 11:16:19 +01:00
slawkens
b02c7f4239 Fix note message 2025-01-14 19:29:47 +01:00
slawkens
b5b2e3fd78 Update CHANGELOG.md 2025-01-14 00:19:16 +01:00
slawkens
030d15f0cd Fix branch name 2025-01-14 00:17:33 +01:00
slawkens
b6b7592226 Release v1.0.1 2025-01-13 23:17:58 +01:00
slawkens
fb10741a02 Fix typo in account word 2025-01-13 23:15:57 +01:00
slawkens
5e9c868dfa Fix tibiacom account & news menu links 2025-01-13 23:05:16 +01:00
slawkens
0904b1bb87 Fix phpstan 2025-01-13 22:23:43 +01:00
slawkens
faa60f5e9a Fix phpstan and phplint branches 2025-01-13 22:15:48 +01:00
slawkens
620e0f62e4 Fix cypress run workflow 2025-01-13 22:10:52 +01:00
slawkens
2ae2ec3353 Fix link to monsters 2025-01-13 22:09:15 +01:00
slawkens
b323d9cee1 Update cypress to ^13.17.0 2025-01-13 22:09:04 +01:00
slawkens
4f1d1d8043 Update tinymce to ^7.2.0 2025-01-13 21:50:37 +01:00
slawkens
8e5a3afc6e Update myaac version 2025-01-13 21:41:49 +01:00
slawkens
a7311301e2 Update composer.lock 2025-01-13 21:40:16 +01:00
slawkens
ac10236154 Update twig dependency to ^3.11 (disable dependabot alert) 2025-01-13 21:40:09 +01:00
slawkens
dc95bc4bad Merge branch 'master' of https://github.com/slawkens/myaac 2025-01-13 21:18:50 +01:00
dependabot[bot]
0dc7da472f Bump nesbot/carbon from 2.72.5 to 2.72.6 (#276)
Bumps [nesbot/carbon](https://github.com/CarbonPHP/carbon) from 2.72.5 to 2.72.6.
- [Release notes](https://github.com/CarbonPHP/carbon/releases)
- [Commits](https://github.com/CarbonPHP/carbon/compare/2.72.5...2.72.6)

---
updated-dependencies:
- dependency-name: nesbot/carbon
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 21:16:29 +01:00
slawkens
43421e56ea Update nginx-sample.conf 2025-01-13 20:34:40 +01:00
slawkens
544d006b6f v1.0 - Hello! 2025-01-12 17:44:18 +01:00
slawkens
085ebbcfde All $cache->set calls should have $ttl 2025-01-12 17:13:25 +01:00
slawkens
77a2c1cec3 Support for plugin themes in menus.php 2025-01-12 16:27:20 +01:00
slawkens
e918591666 Ignore PhpStan error 2025-01-09 22:59:02 +01:00
slawkens
175c2a1f89 Fix PhpStan 2025-01-09 22:52:30 +01:00
slawkens
3b5be1a8db Add player->outfit_url attribute 2025-01-09 22:41:34 +01:00
slawkens
c769962e39 Refactor getTopPlayers function
* Option to getTopPlayers by balance
* use Cache::remember
2025-01-09 22:40:57 +01:00
slawkens
35dfaa28ed Update index.php 2025-01-09 20:57:23 +01:00
slawkens
8e501c0e9c Shorten code with Cache::remember 2025-01-09 15:50:33 +01:00
slawkens
c52ca27126 Fix if someone deletes the default kathrine template 2025-01-09 15:41:22 +01:00
slawkens
41a3cb6f42 vendor should be accessible, cause of 2025-01-09 13:39:05 +01:00
slawkens
eb4b3ada49 Adjust post_ip to support ipv6 2025-01-09 13:10:04 +01:00
slawkens
68bdec7c18 Fix ip size 2025-01-09 13:06:33 +01:00
slawkens
8a612429b2 Use $db->insert instead of manual query 2025-01-09 13:03:55 +01:00
slawkens
16671ea40b Fix change sex price deducted 2025-01-09 09:44:12 +01:00
slawkens
8fb643596f Fix more XSS in forum 2025-01-08 23:22:51 +01:00
slawkens
c2b7286d20 Fix XSS in forum new_post 2025-01-08 23:13:40 +01:00
slawkens
d6c40c836a Fix move_thread by unauthorized user 2025-01-08 22:36:49 +01:00
slawkens
99262c3ebd Fix DataLoader Towns cache 2025-01-07 15:03:39 +01:00
slawkens
b8396d4c84 Fix for TFS 1.4.2 where conditions is NULL 2024-12-29 15:46:02 +01:00
slawkens
b0c8cf2ecd Add $whoopsHandler as variable, can be used by other scripts 2024-12-29 15:45:33 +01:00
110 changed files with 3636 additions and 3395 deletions

View File

@@ -1,65 +0,0 @@
Thumbs.db
.DS_Store
.idea
#
/.htaccess
# composer
composer.phar
vendor
# npm
node_modules
tools/ext
# cypress
cypress.env.json
cypress/e2e/2-advanced-examples
cypress/screenshots
# created by release.sh
releases
tmp
config.local.php
!docker/config.local.php
# all custom templates
templates/*
!templates/tibiacom
!templates/kathrine
# guild images
images/guilds/*
!images/guilds/default.gif
# editor images
images/editor/*
!images/editor/index.html
# gallery images
images/gallery/*
!images/gallery/index.html
!images/gallery/demon.jpg
!images/gallery/demon_thumb.gif
# cache
system/cache/*
!system/cache/index.html
!system/cache/twig/index.html
!system/cache/signatures/index.html
!system/cache/plugins/index.html
!system/cache/persistent/index.html
# logs
system/logs/*
!system/logs/index.html
# data
system/data/*
!system/data/index.html
# php sessions
system/php_sessions/*
!system/php_sessions/index.html

View File

@@ -1,9 +1,9 @@
name: Cypress
on:
pull_request:
branches: [develop]
branches: [main]
push:
branches: [develop]
branches: [main]
jobs:
cypress:
@@ -22,7 +22,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php-versions: [ '8.1', '8.2', '8.3' ]
php-versions: [ '8.1', '8.2', '8.3', '8.4' ]
ots: ['tfs-1.4', 'canary-3.1.2'] # TODO: add 'tfs-master' (actually doesn't work cause AAC doesn't support reading .env configuration)
name: Cypress (PHP ${{ matrix.php-versions }}, ${{ matrix.ots }})
steps:
@@ -35,7 +35,7 @@ jobs:
- name: Checkout MyAAC
uses: actions/checkout@v4
with:
ref: develop
ref: main
- uses: actions/setup-node@v4
with:
@@ -146,6 +146,7 @@ jobs:
with:
name: cypress-screenshots-${{ matrix.php-versions }}-${{ matrix.ots }}
path: cypress/screenshots
if-no-files-found: ignore
- name: Upload Cypress Videos
uses: actions/upload-artifact@v4
@@ -153,6 +154,7 @@ jobs:
with:
name: cypress-videos-${{ matrix.php-versions }}-${{ matrix.ots }}
path: cypress/videos
if-no-files-found: ignore
- name: Upload PHP Logs
uses: actions/upload-artifact@v4

View File

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

View File

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

5
.gitignore vendored
View File

@@ -4,6 +4,7 @@ Thumbs.db
#
/.htaccess
lua
# composer
composer.phar
@@ -23,7 +24,6 @@ releases
tmp
config.local.php
!docker/config.local.php
# all custom templates
templates/*
@@ -76,6 +76,3 @@ landing
# system
system/functions_custom.php
# others/rest
system/pages/downloads.php

View File

@@ -6,7 +6,7 @@
Options -MultiViews
</IfModule>
<FilesMatch "^(CHANGELOG\.md|README\.md|composer\.json|composer\.lock|package\.json|package-lock\.json|cypress\.env\.json)$">
<FilesMatch "^(.*\.md|.*\.json|.*\.dist|.*\.sql|CHANGELOG|README|composer\.lock)$">
Require all denied
</FilesMatch>

266
CHANGELOG-1.x.md Normal file
View File

@@ -0,0 +1,266 @@
# 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]
### Changed
* adjust mailer settings descriptions to latest gmail (https://github.com/slawkens/myaac/commit/c5d5bb80671db135e6b503f53684771c7272e05d)
* optimize $player->isOnline() function, thanks @gesior (https://github.com/slawkens/myaac/commit/10dd818b139d5e1bb1ca9ec81edfb083ba9316b4)
* make players.comment and guilds.description VARCHAR (https://github.com/slawkens/myaac/commit/a45ceab83a74bee2b89cdb72baceda75e577e3cf)
* add lua/ folder to .gitignore (https://github.com/slawkens/myaac/commit/07012f786b1114cb6ab2f064f82c645b136a375a)
### Fixed
* general fixes in the tibiacom template menus, better support for custom menus
* 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)
* hook ACCOUNT_LOGIN_BEFORE_ACCOUNT location (https://github.com/slawkens/myaac/commit/669c447fca8643ce56d9ef8c1374ec647c780998)
## [1.0.1 - 14.01.2025]
### Fixed
* tibiacom account & news menu links not auto expanding
### Updated (Thanks dependabot)
* twig from ^2.0 to ^3.11
* tinymce from ^6.8.3 to ^7.2.0
* cypress from ^12.12.0 to ^13.17.0
* nesbot/carbon from 2.72.5 to 2.72.6
## [1.0 - 12.01.2025]
First stable release in the v1.0 series.
Minimum PHP 8.1 is required.
Changes since RC.2:
### Added
* feature: migrations up/down. Allows to downgrade/upgrade database to specified version (https://github.com/slawkens/myaac/commit/3f6ff3a3326b0475d28d11ffd7fff51f362d799f)
* new hooks for news management (https://github.com/slawkens/myaac/commit/011a85d8ae34283ded6999882833f9d4797028ec, https://github.com/slawkens/myaac/commit/36bd3eb846e829b45313e10f7568dc4e95841143)
* None Vocation to highscores (can be changed to RookStayer in Admin Panel) (https://github.com/slawkens/myaac/commit/a4a248099521bb5b8b2aa5bd592138debd2f19d5)
* support for button_color (green, red, blue) (https://github.com/slawkens/myaac/commit/d8b6b749ee62e88b6af4a05d3d7557f90b94d94e)
* add $whoopsHandler as variable, can be used by plugins (https://github.com/slawkens/myaac/commit/b0c8cf2ecda23045d725aaf43cfb3852ed766a4b)
* PlayerModel->outfit_url attribute (https://github.com/slawkens/myaac/commit/3b5be1a8db5dceecaa388e2925a5536d13b38881)
* support for selecting plugin themes in Admin menus.php (https://github.com/slawkens/myaac/commit/77a2c1cec343ffe4be5c2c2503ee81bc32a14ca1)
### Changed
* schema: Change character set to utf8mb4 (support for Emojis in Menus/Pages/News/Forum etc.) (https://github.com/slawkens/myaac/commit/27c44f1bdfb6234cf0c9d5b4b491123bb205b08f)
* prefer get_browser_real_ip() over REMOTE_ADDR (https://github.com/slawkens/myaac/commit/941846605c00cee83168d2f916410b8ba8d4b7b9)
* automatically set selected current one on highscores filters (https://github.com/slawkens/myaac/commit/e96227fbe41ae281783b2d49edb169a603601813)
* rewrite towns loading code, removed OTBM loader (was too slow) (https://github.com/slawkens/myaac/commit/c980a0914632e7b27f718464f669a200707d217e)
* allow OTS_Player to be passed as object to getPlayerLink (https://github.com/slawkens/myaac/commit/84d37c5a8f2c4535a41c8aa8264752969d3f3a3d)
* do not clear menus by default on install (https://github.com/slawkens/myaac/commit/12d8faa3eda5e798f97b71e941c035187daad96e)
* display warning in admin panel - plugins - if zip extension is not installed (https://github.com/slawkens/myaac/commit/e3ffe5d9e11d78ab064a370d8541bac351c9bcd9)
* set default_socket_timeout for ipinfo.io checkup to 5 seconds (https://github.com/slawkens/myaac/commit/783d96fc6568a607d3198b832fed3a0dd06c4ebb)
* refactor getTopPlayers function (support for balance) (https://github.com/slawkens/myaac/commit/c769962e39fe8dfb72ecd5be1864e145696be794)
### Fixed
* XSS in forum (https://github.com/slawkens/myaac/commit/c2b7286d20d4b579171540f7a774e8a0995d5e8f, https://github.com/slawkens/myaac/commit/8fb643596f9586005976e7bdb484a541a9d8715e)
* price deducted when changing sex (https://github.com/slawkens/myaac/commit/16671ea40b72dcf74037c359ad572f9eb825edf9)
* move_thread by unauthorized user (https://github.com/slawkens/myaac/commit/d6c40c836a53cb1710f911f77f45f28b54ea1b54, thanks @anyeor)
* TFS 1.4.2 where conditions is NULL (https://github.com/slawkens/myaac/commit/b8396d4c8482e951da538b13f2296123732c4545)
* do not show forum new thread show button if not logged in (https://github.com/slawkens/myaac/commit/507402171ba3b6e7ee184bd7fa73e0d55e0cad7a, @anyeor)
* login if limiter is disabled (https://github.com/slawkens/myaac/commit/a0f1971583f0f790013e2145fb5ac573c59fbdef)
* fixes to installMenus function (https://github.com/slawkens/myaac/commit/a2fadc5945fe0a5e39f740827f6ffbda1bb501e2)
* many PHP exceptions in different places
* fixes to tibiacom menus ActiveSubmenuItem
### Removed
* bugtracker SQL table code as the page has been removed/moved to plugins (https://github.com/slawkens/myaac/commit/5782772b901b05fb814bc718d062f6e2cd71df8c)
## [1.0-RC.2 - 25.10.2024]
Still waiting for your reports about bugs found in this release. We are very close to stable release.
### Added
* feat: rate limit settings for blocking accounts login attempts (@gpedro, #266)
* search by email in accounts editor (https://github.com/slawkens/myaac/commit/c2ec46824621468f2a1cb4046805c485ed13fea5)
* New hooks in account manage + create (https://github.com/slawkens/myaac/commit/93641fc68ac9a5f1479329e2bd41380c19534d5d)
### Changed
* chore: drop raw queries + accounts - search by email + accounts - required min size for search by account number (@gpedro, #266)
* Use https for outfit & item images (https://github.com/slawkens/myaac/commit/71c00aa5e01fbdfd88802912e200dd1025976231)
* Do not require players & guilds tables on install (https://github.com/slawkens/myaac/commit/779aa152fa940261c9b161533946f44e288597a2)
* Do not create player if there is no players table in db (https://github.com/slawkens/myaac/commit/201f95caa8b70e88fa651eac8c3c3aa7cd765bd0)
### Fixed
* Highscore frags fixed for TFS 0.3 (@Scrollog, #263)
* Missing groups variable #262. thanks, @Scrollog for reporting (https://github.com/slawkens/myaac/commit/8d8bdb6dac6df21672ac77288fff2f2f8d6eb665)
* Verified email for login.php (@gpedro, #265)
* Warning if core.account_country is disabled (https://github.com/slawkens/myaac/commit/ab73d60c61e14a1cacdb6cfbf7f89f4bf3be0833)
## [1.0-RC.1 - 23.07.2024]
Changes since 1.0-beta:
### Added
* Feat: Hooks priority (https://github.com/slawkens/myaac/commit/dc17b701da053e04bfa64e21be9247a4f07505e1)
* Make autoload of pages, commands and themes configurable (https://github.com/slawkens/myaac/commit/c1d4b4f80cd6bb85507ee9471e47013955a26a91)
* Fraggers in characters page for TFS 1.x and canary (https://github.com/slawkens/myaac/commit/42f99c3edc8de39cccc5632cb42e88b24579c5a6)
* New hooks: HOOK_INSTALL_FINISH, HOOK_ACCOUNT_CREATE_CHARACTER_* (https://github.com/slawkens/myaac/commit/08ac8ebade106521a5c7396faa5ce7006e629f7c, https://github.com/slawkens/myaac/commit/45dda5e834ff2059faea6ef9be2efa76f1723cbd)
### Changed
* Allow account_create_character_create even if account_mail_verify is activated (https://github.com/slawkens/myaac/commit/203e411b626fe62401a4b74a48420769e512aa39)
* Create guild_rank entries, in case MySQL trigger not loaded (https://github.com/slawkens/myaac/commit/d9c1b2507c81f306970642b35e4bf5f7cc04a6f2, https://github.com/slawkens/myaac/commit/47a19e85dd84e9f3b39a1b29cfc2c04b004832b9)
* Set Admin Account verified by default (https://github.com/slawkens/myaac/commit/cd49dfc79942f3301ce9c0b8d899b9f39bda9a41)
* Refactor account routes into sub folders (https://github.com/slawkens/myaac/commit/bdc0c43d3fd3a51030c3e916bdb9f008468f5ecd)
* Order towns by id (https://github.com/slawkens/myaac/commit/9ea2a5067fc4b75de395f381577b18914132ad84)
* Do not create news about myaac, if any news already exist (on installation (https://github.com/slawkens/myaac/commit/504242fb846b73b56b87bc1e39d070687ad7f5b4)
### Fixed
* Not working google recaptcha plugin (https://github.com/slawkens/myaac/commit/a1bcb217ecf4e21fd58da4ba491da1852029898a)
* Not working account create if account_country is disabled (https://github.com/slawkens/myaac/commit/933b681a9fcdbb6283e0469b3806d2ded492d232)
* Account verify - do not allow login without verified email (Thanks @anyeor, https://github.com/slawkens/myaac/commit/fcb13f3c0fb8ceafda0bd614a229a26a269432bd)
* Detect tools/ext exists on install to prevent broken installs (https://github.com/slawkens/myaac/commit/10a739773c4f2911876bc802a0ee0537c3e00a92)
* Cache reloading each time page refreshes (https://github.com/slawkens/myaac/commit/ec96985872057340112f65073efc0c4bf86dddb0)
* Highscores frags for TFS 1.x and canary (https://github.com/slawkens/myaac/commit/a04d186c22912915f0a7873dfe677ef3b5a23c79)
* Monsters page: monster not found exception (https://github.com/slawkens/myaac/commit/ef79b99b8acc179f14b8475547347d9daca27512)
* Fixed bug if \<flags\> are not present in monster.xml (https://github.com/slawkens/myaac/commit/57b47ab7983f625c7c0ef4f5303a4d07ef172786)
* fastRoute duplicate errors (https://github.com/slawkens/myaac/commit/4c0739d3e93812dff0c33849ea3f38e4e49113ac)
* useGuildNick displaying (https://github.com/slawkens/myaac/commit/0db0ec1aa47e044c26bc403ff5078a2115d086f8)
## [1.0-beta - 18.05.2024]
Minimum PHP version for this release is 8.1.
### Added
* reworked Admin Panel (@Leesneaks, @gpedro, @slawkens)
* updated to Bootstrap v4
* new Menu
* new Dashboard: statistics, server status
* new Admin Bar showed on top when admin logged in
* new page: Server Data, to reload server data
* Towns, NPCs & Items are stored in permanent cache
* new pages: mass account & teleport tools
* changelogs editor
* revised Accounts & Players editors
* option to add/modify admin menus with plugins
* option to enable/disable plugins
* better, updated TinyMCE editor (v6.x)
* with option to upload images
* list of open source libraries used in project page
* auto-loading of themes, commands & pages from plugins/ folder. You need just to place them in correct folder and they will be loaded automatically - this allows better customization, without interfering with core AAC folders. This will allow in the future automatic updates for plugins as well the AAC as whole.
* config.php moved to Admin Panel -> Settings page
* new console script: aac - using symfony/console
* usage: `php aac` (will list all commands by default)
* example: `php aac cache:clear`
* example: `php aac plugin:install theme-example.zip`
* replace POT Query Builder to Eloquent ORM. Not 100% yet - in some places there is still old $db approach used (@gpedro) (https://github.com/slawkens/myaac/pull/230)
* brand new charming installation page (by @fernandomatos)
* using Bootstrap
* new pages router: nikic/fast-route, allowing for better customisation
* Plugin cronjobs: central control of the cronjobs
* Guild Wars support (available as plugin)
* support for login and create account only by email (configurable)
* with no need for account name
* Google ReCAPTCHA v3 support (available as plugin)
* support for Account Number
* suggest account number option
* many new functions, hooks and configurables
* better Exception Handler (Whoops - https://github.com/filp/whoops)
* automated website tests (using Cypress)
* csrf protection (https://github.com/slawkens/myaac/pull/235)
* option to restrict Page view to specified group of users (Not-Logged in, logged-in players, tutors, gamemasters etc.)
* phpdebug bar (http://phpdebugbar.com/). Activated if env == 'dev', can be also activated in production by enabling "enable_debugbar" in local config
### Changed
* Composer and NPM is now used for external libraries like: Twig, PHPMailer, fast-route, jQuery, Bootstrap etc.
* mail support is disabled on fresh install, can be manually enabled by user
* disable add php pages in admin panel for security. Option to disable plugins upload
* visitors counter shows now user browser, and also if its bot
* changes in required and optional PHP extensions
* reworked Pages:
* Bans
* works now for TFS 1.x
* Highscores
* frags works for TFS 1.x
* cached
* Monsters
* moved pages to Twig:
* experience stages
* update player_deaths entries on name change
* change_password email to be more informal
### Fixed
* hundreds of bug fixes, mostly patched from 0.8, so it makes no sense writing them again here

View File

@@ -1,119 +0,0 @@
# Changelog
## [1.0-RC.2 - 25.10.2024]
Still waiting for your reports about bugs found in this release. We are very close to stable release.
### Added
* feat: rate limit settings for blocking accounts login attempts (@gpedro, #266)
* search by email in accounts editor (https://github.com/slawkens/myaac/commit/c2ec46824621468f2a1cb4046805c485ed13fea5)
* New hooks in account manage + create (https://github.com/slawkens/myaac/commit/93641fc68ac9a5f1479329e2bd41380c19534d5d)
### Changed
* chore: drop raw queries + accounts - search by email + accounts - required min size for search by account number (@gpedro, #266)
* Use https for outfit & item images (https://github.com/slawkens/myaac/commit/71c00aa5e01fbdfd88802912e200dd1025976231)
* Do not require players & guilds tables on install (https://github.com/slawkens/myaac/commit/779aa152fa940261c9b161533946f44e288597a2)
* Do not create player if there is no players table in db (https://github.com/slawkens/myaac/commit/201f95caa8b70e88fa651eac8c3c3aa7cd765bd0)
### Fixed
* Highscore frags fixed for TFS 0.3 (@Scrollog, #263)
* Missing groups variable #262. thanks, @Scrollog for reporting (https://github.com/slawkens/myaac/commit/8d8bdb6dac6df21672ac77288fff2f2f8d6eb665)
* Verified email for login.php (@gpedro, #265)
* Warning if core.account_country is disabled (https://github.com/slawkens/myaac/commit/ab73d60c61e14a1cacdb6cfbf7f89f4bf3be0833)
## [1.0-RC.1 - 23.07.2024]
Changes since 1.0-beta:
### Added
* Feat: Hooks priority (https://github.com/slawkens/myaac/commit/dc17b701da053e04bfa64e21be9247a4f07505e1)
* Make autoload of pages, commands and themes configurable (https://github.com/slawkens/myaac/commit/c1d4b4f80cd6bb85507ee9471e47013955a26a91)
* Fraggers in characters page for TFS 1.x and canary (https://github.com/slawkens/myaac/commit/42f99c3edc8de39cccc5632cb42e88b24579c5a6)
* New hooks: HOOK_INSTALL_FINISH, HOOK_ACCOUNT_CREATE_CHARACTER_* (https://github.com/slawkens/myaac/commit/08ac8ebade106521a5c7396faa5ce7006e629f7c, https://github.com/slawkens/myaac/commit/45dda5e834ff2059faea6ef9be2efa76f1723cbd)
### Changed
* Allow account_create_character_create even if account_mail_verify is activated (https://github.com/slawkens/myaac/commit/203e411b626fe62401a4b74a48420769e512aa39)
* Create guild_rank entries, in case MySQL trigger not loaded (https://github.com/slawkens/myaac/commit/d9c1b2507c81f306970642b35e4bf5f7cc04a6f2, https://github.com/slawkens/myaac/commit/47a19e85dd84e9f3b39a1b29cfc2c04b004832b9)
* Set Admin Account verified by default (https://github.com/slawkens/myaac/commit/cd49dfc79942f3301ce9c0b8d899b9f39bda9a41)
* Refactor account routes into sub folders (https://github.com/slawkens/myaac/commit/bdc0c43d3fd3a51030c3e916bdb9f008468f5ecd)
* Order towns by id (https://github.com/slawkens/myaac/commit/9ea2a5067fc4b75de395f381577b18914132ad84)
* Do not create news about myaac, if any news already exist (on installation (https://github.com/slawkens/myaac/commit/504242fb846b73b56b87bc1e39d070687ad7f5b4)
### Fixed
* Not working google recaptcha plugin (https://github.com/slawkens/myaac/commit/a1bcb217ecf4e21fd58da4ba491da1852029898a)
* Not working account create if account_country is disabled (https://github.com/slawkens/myaac/commit/933b681a9fcdbb6283e0469b3806d2ded492d232)
* Account verify - do not allow login without verified email (Thanks @anyeor, https://github.com/slawkens/myaac/commit/fcb13f3c0fb8ceafda0bd614a229a26a269432bd)
* Detect tools/ext exists on install to prevent broken installs (https://github.com/slawkens/myaac/commit/10a739773c4f2911876bc802a0ee0537c3e00a92)
* Cache reloading each time page refreshes (https://github.com/slawkens/myaac/commit/ec96985872057340112f65073efc0c4bf86dddb0)
* Highscores frags for TFS 1.x and canary (https://github.com/slawkens/myaac/commit/a04d186c22912915f0a7873dfe677ef3b5a23c79)
* Monsters page: monster not found exception (https://github.com/slawkens/myaac/commit/ef79b99b8acc179f14b8475547347d9daca27512)
* Fixed bug if \<flags\> are not present in monster.xml (https://github.com/slawkens/myaac/commit/57b47ab7983f625c7c0ef4f5303a4d07ef172786)
* fastRoute duplicate errors (https://github.com/slawkens/myaac/commit/4c0739d3e93812dff0c33849ea3f38e4e49113ac)
* useGuildNick displaying (https://github.com/slawkens/myaac/commit/0db0ec1aa47e044c26bc403ff5078a2115d086f8)
## [1.0-beta - 18.05.2024]
Minimum PHP version for this release is 8.1.
### Added
* reworked Admin Panel (@Leesneaks, @gpedro, @slawkens)
* updated to Bootstrap v4
* new Menu
* new Dashboard: statistics, server status
* new Admin Bar showed on top when admin logged in
* new page: Server Data, to reload server data
* Towns, NPCs & Items are stored in permanent cache
* new pages: mass account & teleport tools
* changelogs editor
* revised Accounts & Players editors
* option to add/modify admin menus with plugins
* option to enable/disable plugins
* better, updated TinyMCE editor (v6.x)
* with option to upload images
* list of open source libraries used in project page
* auto-loading of themes, commands & pages from plugins/ folder. You need just to place them in correct folder and they will be loaded automatically - this allows better customization, without interfering with core AAC folders. This will allow in the future automatic updates for plugins as well the AAC as whole.
* config.php moved to Admin Panel -> Settings page
* new console script: aac - using symfony/console
* usage: `php aac` (will list all commands by default)
* example: `php aac cache:clear`
* example: `php aac plugin:install theme-example.zip`
* replace POT Query Builder to Eloquent ORM. Not 100% yet - in some places there is still old $db approach used (@gpedro) (https://github.com/slawkens/myaac/pull/230)
* brand new charming installation page (by @fernandomatos)
* using Bootstrap
* new pages router: nikic/fast-route, allowing for better customisation
* Plugin cronjobs: central control of the cronjobs
* Guild Wars support (available as plugin)
* support for login and create account only by email (configurable)
* with no need for account name
* Google ReCAPTCHA v3 support (available as plugin)
* automatically load towns names from .OTBM file
* support for Account Number
* suggest account number option
* many new functions, hooks and configurables
* better Exception Handler (Whoops - https://github.com/filp/whoops)
* automated website tests (using Cypress)
* csrf protection (https://github.com/slawkens/myaac/pull/235)
* option to restrict Page view to specified group of users (Not-Logged in, logged-in players, tutors, gamemasters etc.)
* phpdebug bar (http://phpdebugbar.com/). Activated if env == 'dev', can be also activated in production by enabling "enable_debugbar" in local config
### Changed
* Composer and NPM is now used for external libraries like: Twig, PHPMailer, fast-route, jQuery, Bootstrap etc.
* mail support is disabled on fresh install, can be manually enabled by user
* disable add php pages in admin panel for security. Option to disable plugins upload
* visitors counter shows now user browser, and also if its bot
* changes in required and optional PHP extensions
* reworked Pages:
* Bans
* works now for TFS 1.x
* Highscores
* frags works for TFS 1.x
* cached
* Monsters
* moved pages to Twig:
* experience stages
* update player_deaths entries on name change
* change_password email to be more informal
### Fixed
* hundrets of bug fixes, mostly patched from 0.8, so it makes no sense writing them again here

View File

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

View File

@@ -1,6 +1,6 @@
# [MyAAC](https://my-aac.org)
MyAAC is a free and open-source Automatic Account Creator (AAC) written in PHP. It is a fork of the [Gesior](https://github.com/gesior/Gesior2012) project. It supports only MySQL databases.
MyAAC is a free and open-source Automatic Account Creator (AAC) for Open Tibia Servers written in PHP. It is a fork of the [Gesior](https://github.com/gesior/Gesior2012) project. It supports only MySQL databases.
Official website: https://my-aac.org
@@ -12,11 +12,18 @@ Official website: https://my-aac.org
| 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.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 |
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
- MySQL database
@@ -47,23 +54,23 @@ Official website: https://my-aac.org
### 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.
### Branches
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:
* master branch, for current stable release
* main branch, for current stable release
* develop branch, for development version (next release)
* feature branches, for features etc.
### Known Problems
- Some compatibility issues with some exotical distibutions.
- Some compatibility issues with some exotic distributions.
### Contributing
@@ -77,7 +84,7 @@ Look: [Contributing](https://github.com/otsoft/myaac/wiki/Contributing) in our w
### 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

View File

@@ -7,7 +7,7 @@ $hooks->register('debugbar_admin_head_end', HOOK_ADMIN_HEAD_END, function ($para
return;
}
$debugBarRenderer = $debugBar->getJavascriptRenderer();
$debugBarRenderer = $debugBar->getJavascriptRenderer(BASE_URL . 'vendor/maximebf/debugbar/src/DebugBar/Resources/');
echo $debugBarRenderer->renderHead();
});
$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;
}
$debugBarRenderer = $debugBar->getJavascriptRenderer();
$debugBarRenderer = $debugBar->getJavascriptRenderer(BASE_URL . 'vendor/maximebf/debugbar/src/DebugBar/Resources/');
echo $debugBarRenderer->render();
});

View File

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

View File

@@ -9,6 +9,7 @@
*/
use MyAAC\Models\Account as AccountModel;
use MyAAC\Models\AccountAction;
use MyAAC\Models\Player;
defined('MYAAC') or die('Direct access not allowed!');
@@ -466,9 +467,8 @@ else if (isset($_REQUEST['search'])) {
</thead>
<tbody>
<?php
$accountActions = \MyAAC\Models\AccountAction::where('account_id', $account->getId())->orderByDesc('date')->get();
$accountActions = AccountAction::where('account_id', $account->getId())->orderByDesc('date')->get();
foreach ($accountActions as $i => $log):
$log->ip = ($log->ip != 0 ? long2ip($log->ip) : inet_ntop($log->ipv6));
?>
<tr>
<td><?php echo $i + 1; ?></td>

View File

@@ -10,6 +10,7 @@
use MyAAC\Cache\Cache;
use MyAAC\Models\Menu;
use MyAAC\Plugins;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Menus';
@@ -21,14 +22,16 @@ if (!hasFlag(FLAG_CONTENT_MENUS) && !superAdmin()) {
return;
}
$pluginThemes = Plugins::getThemes();
if (isset($_POST['template'])) {
$template = $_POST['template'];
if (isset($_POST['menu'])) {
$post_menu = $_POST['menu'];
$post_menu_link = $_POST['menu_link'];
$post_menu_blank = $_POST['menu_blank'];
$post_menu_color = $_POST['menu_color'];
if (isset($_POST['save'])) {
$post_menu = $_POST['menu'] ?? [];
$post_menu_link = $_POST['menu_link'] ?? [];
$post_menu_blank = $_POST['menu_blank'] ?? [];
$post_menu_color = $_POST['menu_color'] ?? [];
if (count($post_menu) != count($post_menu_link)) {
echo 'Menu count is not equal menu links. Something went wrong when sending form.';
return;
@@ -56,54 +59,67 @@ if (isset($_POST['template'])) {
}
}
$cache = Cache::getInstance();
if ($cache->enabled()) {
$cache->delete('template_menus');
}
onTemplateMenusChange();
success('Saved at ' . date('H:i'));
}
$file = TEMPLATES . $template . '/config.php';
if (file_exists($file)) {
require_once $file;
$path = TEMPLATES . $template;
if (isset($pluginThemes[$template])) {
$path = BASE . $pluginThemes[$template];
}
$path .= '/config.php';
if (file_exists($path)) {
require_once $path;
} else {
echo 'Cannot find template config.php file.';
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'])) {
echo "No menu categories set in template config.php.<br/>This template doesn't support dynamic menus.";
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;
$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
$menus = Menu::query()
->select('name', 'link', 'blank', 'color', 'category', 'ordering')
@@ -119,7 +135,7 @@ if (isset($_POST['template'])) {
<form method="post" id="menus-form" action="?p=menus">
<?php csrf(); ?>
<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">
<?php foreach ($config['menu_categories'] as $id => $cat): ?>
<div class="col-md-12 col-lg-6">
@@ -133,12 +149,13 @@ if (isset($_POST['template'])) {
if (isset($menus[$id])) {
$i = 0;
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']); ?>"/>
<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"/>
<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>
<?php $i++; $last_id[$id] = $i;
endforeach;
@@ -151,7 +168,7 @@ if (isset($_POST['template'])) {
</div>
<div class="row pb-2">
<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
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>';
?>
@@ -162,15 +179,19 @@ if (isset($_POST['template'])) {
$twig->display('admin.menus.js.html.twig', array(
'menus' => $menus,
'last_id' => $last_id,
'menu_default_color' => $config['menu_default_color'] ?? '#ffffff'
));
?>
<?php
} else {
$templates = Menu::select('template')->distinct()->get()->toArray();
foreach ($templates as $key => $value) {
$file = TEMPLATES . $value['template'] . '/config.php';
if (!file_exists($file)) {
$path = TEMPLATES . $value['template'];
if (isset($pluginThemes[$value['template']])) {
$path = BASE . $pluginThemes[$value['template']];
}
if (!file_exists($path . '/config.php')) {
unset($templates[$key]);
}
}
@@ -179,3 +200,11 @@ if (isset($_POST['template'])) {
'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;
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>.');
}
else {

View File

@@ -26,8 +26,8 @@
if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.');
const MYAAC = true;
const MYAAC_VERSION = '1.0-RC.2';
const DATABASE_VERSION = 41;
const MYAAC_VERSION = '2.0-dev';
const DATABASE_VERSION = 44;
const TABLE_PREFIX = 'myaac_';
define('START_TIME', microtime(true));
define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX'));

View File

@@ -8,7 +8,7 @@
"ext-dom": "*",
"phpmailer/phpmailer": "^6.1",
"composer/semver": "^3.2",
"twig/twig": "^2.0",
"twig/twig": "^3.11",
"erusev/parsedown": "^1.7",
"nikic/fast-route": "^1.3",
"matomo/device-detector": "^6.0",

295
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "27c63d07ab6337cd8bb5b59f2b2e08d8",
"content-hash": "be4d1489a53a9cd8eec6bcaa7a096f30",
"packages": [
{
"name": "brick/math",
@@ -885,16 +885,16 @@
},
{
"name": "matomo/device-detector",
"version": "6.4.1",
"version": "6.4.2",
"source": {
"type": "git",
"url": "https://github.com/matomo-org/device-detector.git",
"reference": "0d364e0dd6c177da3c24cd4049178026324fd7ac"
"reference": "806e52d214b05ddead1a1d4304c7592f61f95976"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/matomo-org/device-detector/zipball/0d364e0dd6c177da3c24cd4049178026324fd7ac",
"reference": "0d364e0dd6c177da3c24cd4049178026324fd7ac",
"url": "https://api.github.com/repos/matomo-org/device-detector/zipball/806e52d214b05ddead1a1d4304c7592f61f95976",
"reference": "806e52d214b05ddead1a1d4304c7592f61f95976",
"shasum": ""
},
"require": {
@@ -950,20 +950,20 @@
"source": "https://github.com/matomo-org/matomo",
"wiki": "https://dev.matomo.org/"
},
"time": "2024-09-24T13:50:04+00:00"
"time": "2024-12-16T16:38:01+00:00"
},
{
"name": "maximebf/debugbar",
"version": "v1.23.3",
"version": "v1.23.5",
"source": {
"type": "git",
"url": "https://github.com/maximebf/php-debugbar.git",
"reference": "687400043d77943ef95e8417cb44e1673ee57844"
"url": "https://github.com/php-debugbar/php-debugbar.git",
"reference": "eeabd61a1f19ba5dcd5ac4585a477130ee03ce25"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/687400043d77943ef95e8417cb44e1673ee57844",
"reference": "687400043d77943ef95e8417cb44e1673ee57844",
"url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/eeabd61a1f19ba5dcd5ac4585a477130ee03ce25",
"reference": "eeabd61a1f19ba5dcd5ac4585a477130ee03ce25",
"shasum": ""
},
"require": {
@@ -1015,10 +1015,10 @@
"debugbar"
],
"support": {
"issues": "https://github.com/maximebf/php-debugbar/issues",
"source": "https://github.com/maximebf/php-debugbar/tree/v1.23.3"
"issues": "https://github.com/php-debugbar/php-debugbar/issues",
"source": "https://github.com/php-debugbar/php-debugbar/tree/v1.23.5"
},
"time": "2024-10-29T12:24:25+00:00"
"time": "2024-12-15T19:20:42+00:00"
},
{
"name": "mustangostang/spyc",
@@ -1076,16 +1076,16 @@
},
{
"name": "nesbot/carbon",
"version": "2.72.5",
"version": "2.72.6",
"source": {
"type": "git",
"url": "https://github.com/briannesbitt/Carbon.git",
"reference": "afd46589c216118ecd48ff2b95d77596af1e57ed"
"url": "https://github.com/CarbonPHP/carbon.git",
"reference": "1e9d50601e7035a4c61441a208cb5bed73e108c5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/afd46589c216118ecd48ff2b95d77596af1e57ed",
"reference": "afd46589c216118ecd48ff2b95d77596af1e57ed",
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/1e9d50601e7035a4c61441a208cb5bed73e108c5",
"reference": "1e9d50601e7035a4c61441a208cb5bed73e108c5",
"shasum": ""
},
"require": {
@@ -1105,7 +1105,7 @@
"doctrine/orm": "^2.7 || ^3.0",
"friendsofphp/php-cs-fixer": "^3.0",
"kylekatarnls/multi-tester": "^2.0",
"ondrejmirtes/better-reflection": "*",
"ondrejmirtes/better-reflection": "<6",
"phpmd/phpmd": "^2.9",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.12.99 || ^1.7.14",
@@ -1118,10 +1118,6 @@
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev",
"dev-2.x": "2.x-dev"
},
"laravel": {
"providers": [
"Carbon\\Laravel\\ServiceProvider"
@@ -1131,6 +1127,10 @@
"includes": [
"extension.neon"
]
},
"branch-alias": {
"dev-2.x": "2.x-dev",
"dev-master": "3.x-dev"
}
},
"autoload": {
@@ -1179,7 +1179,7 @@
"type": "tidelift"
}
],
"time": "2024-06-03T19:18:41+00:00"
"time": "2024-12-27T09:28:11+00:00"
},
{
"name": "nikic/fast-route",
@@ -1575,16 +1575,16 @@
},
{
"name": "symfony/console",
"version": "v6.4.15",
"version": "v6.4.17",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "f1fc6f47283e27336e7cebb9e8946c8de7bff9bd"
"reference": "799445db3f15768ecc382ac5699e6da0520a0a04"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/f1fc6f47283e27336e7cebb9e8946c8de7bff9bd",
"reference": "f1fc6f47283e27336e7cebb9e8946c8de7bff9bd",
"url": "https://api.github.com/repos/symfony/console/zipball/799445db3f15768ecc382ac5699e6da0520a0a04",
"reference": "799445db3f15768ecc382ac5699e6da0520a0a04",
"shasum": ""
},
"require": {
@@ -1649,7 +1649,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v6.4.15"
"source": "https://github.com/symfony/console/tree/v6.4.17"
},
"funding": [
{
@@ -1665,7 +1665,7 @@
"type": "tidelift"
}
],
"time": "2024-11-06T14:19:14+00:00"
"time": "2024-12-07T12:07:30+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -1686,12 +1686,12 @@
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/contracts",
"name": "symfony/contracts"
},
"branch-alias": {
"dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
@@ -1760,8 +1760,8 @@
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"autoload": {
@@ -1836,8 +1836,8 @@
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"autoload": {
@@ -1914,8 +1914,8 @@
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"autoload": {
@@ -1998,8 +1998,8 @@
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"autoload": {
@@ -2052,71 +2052,6 @@
],
"time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.31.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "fa2ae56c44f03bed91a39bfc9822e31e7c5c38ce"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/fa2ae56c44f03bed91a39bfc9822e31e7c5c38ce",
"reference": "fa2ae56c44f03bed91a39bfc9822e31e7c5c38ce",
"shasum": ""
},
"require": {
"php": ">=7.2"
},
"type": "metapackage",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php72/tree/v1.31.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.31.0",
@@ -2137,8 +2072,8 @@
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"autoload": {
@@ -2197,6 +2132,82 @@
],
"time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/polyfill-php81",
"version": "v1.31.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php81.git",
"reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
"reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
"shasum": ""
},
"require": {
"php": ">=7.2"
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php81\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-09-09T11:45:10+00:00"
},
{
"name": "symfony/service-contracts",
"version": "v3.5.1",
@@ -2221,12 +2232,12 @@
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/contracts",
"name": "symfony/contracts"
},
"branch-alias": {
"dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
@@ -2480,12 +2491,12 @@
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/contracts",
"name": "symfony/contracts"
},
"branch-alias": {
"dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
@@ -2626,38 +2637,38 @@
},
{
"name": "twig/twig",
"version": "v2.16.1",
"version": "v3.19.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "19185947ec75d433a3ac650af32fc05649b95ee1"
"reference": "d4f8c2b86374f08efc859323dbcd95c590f7124e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/19185947ec75d433a3ac650af32fc05649b95ee1",
"reference": "19185947ec75d433a3ac650af32fc05649b95ee1",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/d4f8c2b86374f08efc859323dbcd95c590f7124e",
"reference": "d4f8c2b86374f08efc859323dbcd95c590f7124e",
"shasum": ""
},
"require": {
"php": ">=7.1.3",
"php": ">=8.0.2",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-ctype": "^1.8",
"symfony/polyfill-mbstring": "^1.3",
"symfony/polyfill-php72": "^1.8"
"symfony/polyfill-php81": "^1.29"
},
"require-dev": {
"psr/container": "^1.0",
"symfony/phpunit-bridge": "^5.4.9|^6.3"
"phpstan/phpstan": "^2.0",
"psr/container": "^1.0|^2.0",
"symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.16-dev"
}
},
"autoload": {
"psr-0": {
"Twig_": "lib/"
},
"files": [
"src/Resources/core.php",
"src/Resources/debug.php",
"src/Resources/escaper.php",
"src/Resources/string_loader.php"
],
"psr-4": {
"Twig\\": "src/"
}
@@ -2690,7 +2701,7 @@
],
"support": {
"issues": "https://github.com/twigphp/Twig/issues",
"source": "https://github.com/twigphp/Twig/tree/v2.16.1"
"source": "https://github.com/twigphp/Twig/tree/v3.19.0"
},
"funding": [
{
@@ -2702,7 +2713,7 @@
"type": "tidelift"
}
],
"time": "2024-09-09T17:53:56+00:00"
"time": "2025-01-29T07:06:14+00:00"
},
{
"name": "voku/portable-ascii",
@@ -2840,16 +2851,16 @@
"packages-dev": [
{
"name": "phpstan/phpstan",
"version": "1.12.12",
"version": "1.12.15",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "b5ae1b88f471d3fd4ba1aa0046234b5ca3776dd0"
"reference": "c91d4e8bc056f46cf653656e6f71004b254574d1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/b5ae1b88f471d3fd4ba1aa0046234b5ca3776dd0",
"reference": "b5ae1b88f471d3fd4ba1aa0046234b5ca3776dd0",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/c91d4e8bc056f46cf653656e6f71004b254574d1",
"reference": "c91d4e8bc056f46cf653656e6f71004b254574d1",
"shasum": ""
},
"require": {
@@ -2894,7 +2905,7 @@
"type": "github"
}
],
"time": "2024-11-28T22:13:23+00:00"
"time": "2025-01-05T16:40:22+00:00"
}
],
"aliases": [],
@@ -2911,5 +2922,5 @@
"ext-dom": "*"
},
"platform-dev": [],
"plugin-api-version": "2.6.0"
"plugin-api-version": "2.3.0"
}

View File

@@ -116,9 +116,9 @@ describe('Check Public Pages', () => {
})
// library
it('Go to creatures page', () => {
it('Go to monsters page', () => {
cy.visit({
url: Cypress.env('URL') + '/creatures',
url: Cypress.env('URL') + '/monsters',
method: 'GET',
})
})

View File

@@ -4,7 +4,7 @@ const YOU_ARE_NOT_LOGGEDIN = 'You are not logged in.';
describe('Check Protected Pages', () => {
// character actions
it('Go to accouht character creation page', () => {
it('Go to account character creation page', () => {
cy.visit({
url: Cypress.env('URL') + '/account/character/create',
method: 'GET',
@@ -12,7 +12,7 @@ describe('Check Protected Pages', () => {
cy.contains(REQUIRED_LOGIN_MESSAGE)
})
it('Go to accouht character deletion page', () => {
it('Go to account character deletion page', () => {
cy.visit({
url: Cypress.env('URL') + '/account/character/delete',
method: 'GET',
@@ -21,7 +21,7 @@ describe('Check Protected Pages', () => {
})
// account actions
it('Go to accouht email change page', () => {
it('Go to account email change page', () => {
cy.visit({
url: Cypress.env('URL') + '/account/email',
method: 'GET',
@@ -29,7 +29,7 @@ describe('Check Protected Pages', () => {
cy.contains(REQUIRED_LOGIN_MESSAGE)
})
it('Go to accouht password change page', () => {
it('Go to account password change page', () => {
cy.visit({
url: Cypress.env('URL') + '/account/password',
method: 'GET',
@@ -37,7 +37,7 @@ describe('Check Protected Pages', () => {
cy.contains(REQUIRED_LOGIN_MESSAGE)
})
it('Go to accouht info change page', () => {
it('Go to account info change page', () => {
cy.visit({
url: Cypress.env('URL') + '/account/info',
method: 'GET',
@@ -45,7 +45,7 @@ describe('Check Protected Pages', () => {
cy.contains(REQUIRED_LOGIN_MESSAGE)
})
it('Go to accouht logout change page', () => {
it('Go to account logout change page', () => {
cy.visit({
url: Cypress.env('URL') + '/account/logout',
method: 'GET',

View File

@@ -1,40 +0,0 @@
services:
web:
ports:
- 8001:80
build:
args:
user: www-data
uid: 33
context: ./
dockerfile: ./docker/Dockerfile
restart: unless-stopped
working_dir: /var/www/html
depends_on:
- db
#volumes:
# - ./:/var/www/html
db:
image: mysql:8.0
restart: unless-stopped # always?
environment:
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
MYSQL_DATABASE: myaac
#MYSQL_ROOT_PASSWORD: root
MYSQL_PASSWORD: myaac
MYSQL_USER: myaac
ports:
- 8003:3306
volumes:
- ./docker/tfs_schema.sql:/docker-entrypoint-initdb.d/tfs_schema.sql
- db:/var/lib/mysql
phpmyadmin:
image: phpmyadmin
restart: always
ports:
- 8002:80
volumes:
db:

View File

@@ -1,56 +0,0 @@
FROM php:8.2-apache
ARG APCU_VERSION=5.1.22
# Arguments defined in docker-compose.yml
ARG user
ARG uid
# Install system dependencies
RUN apt-get update && apt-get install -y \
git \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
libzip-dev \
zip \
unzip \
nano \
vim
RUN apt-get install -y nodejs npm
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Install PHP extensions
RUN docker-php-ext-install pdo pdo_mysql gd zip opcache
RUN docker-php-ext-configure opcache --enable-opcache
RUN pecl install apcu-${APCU_VERSION} && docker-php-ext-enable apcu
# Get latest Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Create system user to run Composer Commands
#RUN useradd -G www-data,root -u $uid -d /home/$user $user
RUN mkdir -p /home/$user/.composer && \
chown -R $user:$user /home/$user
RUN chown -R www-data.www-data /var/www
USER $user
WORKDIR /home/$user
RUN git clone https://github.com/otland/forgottenserver.git
COPY --chown=www-data:www-data docker/config.lua /home/$user/forgottenserver
COPY --chown=www-data:www-data docker/config.local.php /var/www/html
#WORKDIR /home/$user/forgottenserver
WORKDIR /var/www/html
COPY --chown=www-data:www-data . .
RUN composer install
RUN npm install

View File

@@ -1,4 +0,0 @@
<?php
$config['installed'] = false;
$config['server_path'] = '/home/www-data/forgottenserver';
$config['install_ignore_ip_check'] = true;

View File

@@ -1,12 +0,0 @@
serverName = "Forgotten"
mysqlHost = "db"
mysqlUser = "myaac"
mysqlPass = "myaac"
mysqlDatabase = "myaac"
mysqlPort = 3306
mysqlSock = ""
ip = "192.168.176.1"
statusPort = 7171
statusTimeout = 2000

View File

@@ -1,384 +0,0 @@
CREATE TABLE IF NOT EXISTS `accounts` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL,
`password` char(40) NOT NULL,
`secret` char(16) DEFAULT NULL,
`type` int NOT NULL DEFAULT '1',
`premium_ends_at` int unsigned NOT NULL DEFAULT '0',
`email` varchar(255) NOT NULL DEFAULT '',
`creation` int NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `players` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`group_id` int NOT NULL DEFAULT '1',
`account_id` int NOT NULL DEFAULT '0',
`level` int NOT NULL DEFAULT '1',
`vocation` int NOT NULL DEFAULT '0',
`health` int NOT NULL DEFAULT '150',
`healthmax` int NOT NULL DEFAULT '150',
`experience` bigint unsigned NOT NULL DEFAULT '0',
`lookbody` int NOT NULL DEFAULT '0',
`lookfeet` int NOT NULL DEFAULT '0',
`lookhead` int NOT NULL DEFAULT '0',
`looklegs` int NOT NULL DEFAULT '0',
`looktype` int NOT NULL DEFAULT '136',
`lookaddons` int NOT NULL DEFAULT '0',
`lookmount` int NOT NULL DEFAULT '0',
`lookmounthead` int NOT NULL DEFAULT '0',
`lookmountbody` int NOT NULL DEFAULT '0',
`lookmountlegs` int NOT NULL DEFAULT '0',
`lookmountfeet` int NOT NULL DEFAULT '0',
`randomizemount` tinyint NOT NULL DEFAULT '0',
`direction` tinyint unsigned NOT NULL DEFAULT '2',
`maglevel` int NOT NULL DEFAULT '0',
`mana` int NOT NULL DEFAULT '0',
`manamax` int NOT NULL DEFAULT '0',
`manaspent` bigint unsigned NOT NULL DEFAULT '0',
`soul` int unsigned NOT NULL DEFAULT '0',
`town_id` int NOT NULL DEFAULT '1',
`posx` int NOT NULL DEFAULT '0',
`posy` int NOT NULL DEFAULT '0',
`posz` int NOT NULL DEFAULT '0',
`conditions` blob DEFAULT NULL,
`cap` int NOT NULL DEFAULT '400',
`sex` int NOT NULL DEFAULT '0',
`lastlogin` bigint unsigned NOT NULL DEFAULT '0',
`lastip` varbinary(16) NOT NULL DEFAULT '0',
`save` tinyint NOT NULL DEFAULT '1',
`skull` tinyint NOT NULL DEFAULT '0',
`skulltime` bigint NOT NULL DEFAULT '0',
`lastlogout` bigint unsigned NOT NULL DEFAULT '0',
`blessings` tinyint NOT NULL DEFAULT '0',
`onlinetime` bigint NOT NULL DEFAULT '0',
`deletion` bigint NOT NULL DEFAULT '0',
`balance` bigint unsigned NOT NULL DEFAULT '0',
`offlinetraining_time` smallint unsigned NOT NULL DEFAULT '43200',
`offlinetraining_skill` int NOT NULL DEFAULT '-1',
`stamina` smallint unsigned NOT NULL DEFAULT '2520',
`skill_fist` int unsigned NOT NULL DEFAULT 10,
`skill_fist_tries` bigint unsigned NOT NULL DEFAULT 0,
`skill_club` int unsigned NOT NULL DEFAULT 10,
`skill_club_tries` bigint unsigned NOT NULL DEFAULT 0,
`skill_sword` int unsigned NOT NULL DEFAULT 10,
`skill_sword_tries` bigint unsigned NOT NULL DEFAULT 0,
`skill_axe` int unsigned NOT NULL DEFAULT 10,
`skill_axe_tries` bigint unsigned NOT NULL DEFAULT 0,
`skill_dist` int unsigned NOT NULL DEFAULT 10,
`skill_dist_tries` bigint unsigned NOT NULL DEFAULT 0,
`skill_shielding` int unsigned NOT NULL DEFAULT 10,
`skill_shielding_tries` bigint unsigned NOT NULL DEFAULT 0,
`skill_fishing` int unsigned NOT NULL DEFAULT 10,
`skill_fishing_tries` bigint unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`),
FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE,
KEY `vocation` (`vocation`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `account_bans` (
`account_id` int NOT NULL,
`reason` varchar(255) NOT NULL,
`banned_at` bigint NOT NULL,
`expires_at` bigint NOT NULL,
`banned_by` int NOT NULL,
PRIMARY KEY (`account_id`),
FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (`banned_by`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `account_ban_history` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`account_id` int NOT NULL,
`reason` varchar(255) NOT NULL,
`banned_at` bigint NOT NULL,
`expired_at` bigint NOT NULL,
`banned_by` int NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (`banned_by`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `account_storage` (
`account_id` int NOT NULL,
`key` int unsigned NOT NULL,
`value` int NOT NULL,
PRIMARY KEY (`account_id`, `key`),
FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `ip_bans` (
`ip` varbinary(16) NOT NULL,
`reason` varchar(255) NOT NULL,
`banned_at` bigint NOT NULL,
`expires_at` bigint NOT NULL,
`banned_by` int NOT NULL,
PRIMARY KEY (`ip`),
FOREIGN KEY (`banned_by`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `player_namelocks` (
`player_id` int NOT NULL,
`reason` varchar(255) NOT NULL,
`namelocked_at` bigint NOT NULL,
`namelocked_by` int NOT NULL,
PRIMARY KEY (`player_id`),
FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (`namelocked_by`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `account_viplist` (
`account_id` int NOT NULL COMMENT 'id of account whose viplist entry it is',
`player_id` int NOT NULL COMMENT 'id of target player of viplist entry',
`description` varchar(128) NOT NULL DEFAULT '',
`icon` tinyint unsigned NOT NULL DEFAULT '0',
`notify` tinyint NOT NULL DEFAULT '0',
UNIQUE KEY `account_player_index` (`account_id`,`player_id`),
FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE,
FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `guilds` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`ownerid` int NOT NULL,
`creationdata` int NOT NULL,
`motd` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
UNIQUE KEY (`name`),
UNIQUE KEY (`ownerid`),
FOREIGN KEY (`ownerid`) REFERENCES `players`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `guild_invites` (
`player_id` int NOT NULL DEFAULT '0',
`guild_id` int NOT NULL DEFAULT '0',
PRIMARY KEY (`player_id`,`guild_id`),
FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE,
FOREIGN KEY (`guild_id`) REFERENCES `guilds` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `guild_ranks` (
`id` int NOT NULL AUTO_INCREMENT,
`guild_id` int NOT NULL COMMENT 'guild',
`name` varchar(255) NOT NULL COMMENT 'rank name',
`level` int NOT NULL COMMENT 'rank level - leader, vice, member, maybe something else',
PRIMARY KEY (`id`),
FOREIGN KEY (`guild_id`) REFERENCES `guilds` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `guild_membership` (
`player_id` int NOT NULL,
`guild_id` int NOT NULL,
`rank_id` int NOT NULL,
`nick` varchar(15) NOT NULL DEFAULT '',
PRIMARY KEY (`player_id`),
FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (`guild_id`) REFERENCES `guilds` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (`rank_id`) REFERENCES `guild_ranks` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `guild_wars` (
`id` int NOT NULL AUTO_INCREMENT,
`guild1` int NOT NULL DEFAULT '0',
`guild2` int NOT NULL DEFAULT '0',
`name1` varchar(255) NOT NULL,
`name2` varchar(255) NOT NULL,
`status` tinyint NOT NULL DEFAULT '0',
`started` bigint NOT NULL DEFAULT '0',
`ended` bigint NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `guild1` (`guild1`),
KEY `guild2` (`guild2`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `guildwar_kills` (
`id` int NOT NULL AUTO_INCREMENT,
`killer` varchar(50) NOT NULL,
`target` varchar(50) NOT NULL,
`killerguild` int NOT NULL DEFAULT '0',
`targetguild` int NOT NULL DEFAULT '0',
`warid` int NOT NULL DEFAULT '0',
`time` bigint NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`warid`) REFERENCES `guild_wars` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `houses` (
`id` int NOT NULL AUTO_INCREMENT,
`owner` int NOT NULL,
`paid` int unsigned NOT NULL DEFAULT '0',
`warnings` int NOT NULL DEFAULT '0',
`name` varchar(255) NOT NULL,
`rent` int NOT NULL DEFAULT '0',
`town_id` int NOT NULL DEFAULT '0',
`bid` int NOT NULL DEFAULT '0',
`bid_end` int NOT NULL DEFAULT '0',
`last_bid` int NOT NULL DEFAULT '0',
`highest_bidder` int NOT NULL DEFAULT '0',
`size` int NOT NULL DEFAULT '0',
`beds` int NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `owner` (`owner`),
KEY `town_id` (`town_id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `house_lists` (
`house_id` int NOT NULL,
`listid` int NOT NULL,
`list` text NOT NULL,
FOREIGN KEY (`house_id`) REFERENCES `houses` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `market_history` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`player_id` int NOT NULL,
`sale` tinyint NOT NULL DEFAULT '0',
`itemtype` smallint unsigned NOT NULL,
`amount` smallint unsigned NOT NULL,
`price` bigint unsigned NOT NULL DEFAULT '0',
`expires_at` bigint unsigned NOT NULL,
`inserted` bigint unsigned NOT NULL,
`state` tinyint unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `player_id` (`player_id`, `sale`),
FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `market_offers` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`player_id` int NOT NULL,
`sale` tinyint NOT NULL DEFAULT '0',
`itemtype` smallint unsigned NOT NULL,
`amount` smallint unsigned NOT NULL,
`created` bigint unsigned NOT NULL,
`anonymous` tinyint NOT NULL DEFAULT '0',
`price` bigint unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `sale` (`sale`,`itemtype`),
KEY `created` (`created`),
FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `players_online` (
`player_id` int NOT NULL,
PRIMARY KEY (`player_id`)
) ENGINE=MEMORY DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `player_deaths` (
`player_id` int NOT NULL,
`time` bigint unsigned NOT NULL DEFAULT '0',
`level` int NOT NULL DEFAULT '1',
`killed_by` varchar(255) NOT NULL,
`is_player` tinyint NOT NULL DEFAULT '1',
`mostdamage_by` varchar(100) NOT NULL,
`mostdamage_is_player` tinyint NOT NULL DEFAULT '0',
`unjustified` tinyint NOT NULL DEFAULT '0',
`mostdamage_unjustified` tinyint NOT NULL DEFAULT '0',
FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE,
KEY `killed_by` (`killed_by`),
KEY `mostdamage_by` (`mostdamage_by`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `player_depotitems` (
`player_id` int NOT NULL,
`sid` int NOT NULL COMMENT 'any given range eg 0-100 will be reserved for depot lockers and all > 100 will be then normal items inside depots',
`pid` int NOT NULL DEFAULT '0',
`itemtype` smallint unsigned NOT NULL,
`count` smallint NOT NULL DEFAULT '0',
`attributes` blob NOT NULL,
UNIQUE KEY `player_id_2` (`player_id`, `sid`),
FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `player_inboxitems` (
`player_id` int NOT NULL,
`sid` int NOT NULL,
`pid` int NOT NULL DEFAULT '0',
`itemtype` smallint unsigned NOT NULL,
`count` smallint NOT NULL DEFAULT '0',
`attributes` blob NOT NULL,
UNIQUE KEY `player_id_2` (`player_id`, `sid`),
FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `player_storeinboxitems` (
`player_id` int NOT NULL,
`sid` int NOT NULL,
`pid` int NOT NULL DEFAULT '0',
`itemtype` smallint unsigned NOT NULL,
`count` smallint NOT NULL DEFAULT '0',
`attributes` blob NOT NULL,
UNIQUE KEY `player_id_2` (`player_id`, `sid`),
FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `player_items` (
`player_id` int NOT NULL DEFAULT '0',
`pid` int NOT NULL DEFAULT '0',
`sid` int NOT NULL DEFAULT '0',
`itemtype` smallint unsigned NOT NULL DEFAULT '0',
`count` smallint NOT NULL DEFAULT '0',
`attributes` blob NOT NULL,
FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE,
KEY `sid` (`sid`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `player_spells` (
`player_id` int NOT NULL,
`name` varchar(255) NOT NULL,
FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `player_storage` (
`player_id` int NOT NULL DEFAULT '0',
`key` int unsigned NOT NULL DEFAULT '0',
`value` int NOT NULL DEFAULT '0',
PRIMARY KEY (`player_id`,`key`),
FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `server_config` (
`config` varchar(50) NOT NULL,
`value` varchar(256) NOT NULL DEFAULT '',
PRIMARY KEY `config` (`config`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `tile_store` (
`house_id` int NOT NULL,
`data` longblob NOT NULL,
FOREIGN KEY (`house_id`) REFERENCES `houses` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE IF NOT EXISTS `towns` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`posx` int NOT NULL DEFAULT '0',
`posy` int NOT NULL DEFAULT '0',
`posz` int NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
INSERT INTO `server_config` (`config`, `value`) VALUES ('db_version', '35'), ('players_record', '0');
DROP TRIGGER IF EXISTS `ondelete_players`;
DROP TRIGGER IF EXISTS `oncreate_guilds`;
DELIMITER //
CREATE TRIGGER `ondelete_players` BEFORE DELETE ON `players`
FOR EACH ROW BEGIN
UPDATE `houses` SET `owner` = 0 WHERE `owner` = OLD.`id`;
END
//
CREATE TRIGGER `oncreate_guilds` AFTER INSERT ON `guilds`
FOR EACH ROW BEGIN
INSERT INTO `guild_ranks` (`name`, `level`, `guild_id`) VALUES ('the Leader', 3, NEW.`id`);
INSERT INTO `guild_ranks` (`name`, `level`, `guild_id`) VALUES ('a Vice-Leader', 2, NEW.`id`);
INSERT INTO `guild_ranks` (`name`, `level`, `guild_id`) VALUES ('a Member', 1, NEW.`id`);
END
//
DELIMITER ;

View File

@@ -31,11 +31,11 @@ require_once 'common.php';
require_once SYSTEM . 'functions.php';
$uri = $_SERVER['REQUEST_URI'];
if(false !== strpos($uri, 'index.php')) {
if(str_contains($uri, 'index.php')) {
$uri = str_replace_first('/index.php', '', $uri);
}
if(0 === strpos($uri, '/')) {
if(str_starts_with($uri, '/')) {
$uri = str_replace_first('/', '', $uri);
}
@@ -76,6 +76,8 @@ require_once SYSTEM . 'status.php';
$twig->addGlobal('config', $config);
$twig->addGlobal('status', $status);
$hooks->trigger(HOOK_STARTUP);
// backward support for gesior
if(setting('core.backward_support')) {
define('INITIALIZED', true);
@@ -117,8 +119,6 @@ if(setting('core.backward_support')) {
require_once SYSTEM . 'router.php';
$hooks->trigger(HOOK_STARTUP);
// anonymous usage statistics
// sent only when user agrees
if(setting('core.anonymous_usage_statistics')) {
@@ -134,7 +134,7 @@ if(setting('core.anonymous_usage_statistics')) {
if(fetchDatabaseConfig('last_usage_report', $value)) {
$should_report = time() > (int)$value + $report_time;
if($cache->enabled()) {
$cache->set('last_usage_report', $value);
$cache->set('last_usage_report', $value, 60 * 60);
}
}
else {
@@ -148,7 +148,7 @@ if(setting('core.anonymous_usage_statistics')) {
updateDatabaseConfig('last_usage_report', time());
if($cache->enabled()) {
$cache->set('last_usage_report', time());
$cache->set('last_usage_report', time(), 60 * 60);
}
}
}
@@ -168,6 +168,7 @@ if ($logged && admin()) {
'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId()
]);
}
$title_full = (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName'];
require $template_path . '/' . $template_index;

View File

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

View File

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

View File

@@ -195,7 +195,7 @@ if(is_writable(CACHE) && (MYAAC_OS != 'WINDOWS' || win_is_writable(CACHE))) {
}
}
if(!$allow && !config('install_ignore_ip_check'))
if(!$allow)
{
$content = warning('In file <b>install/ip.txt</b> must be your IP!<br/>
In file is:<br /><b>' . nl2br($file_content) . '</b><br/>

View File

@@ -11,7 +11,6 @@ foreach($config['clients'] as $client) {
}
$twig->display('install.config.html.twig', array(
'config' => $config,
'clients' => $clients,
'timezones' => DateTimeZone::listIdentifiers(),
'locale' => $locale,

View File

@@ -41,9 +41,6 @@ if(!$error) {
$configToSave['cache_engine'] = 'auto';
$configToSave['cache_prefix'] = 'myaac_' . generateRandomString(8, true, false, true);
$configToSave['database_auto_migrate'] = true;
if (isset($config['install_ignore_ip_check'])) {
$configToSave['install_ignore_ip_check'] = $config['install_ignore_ip_check'];
}
if(!$error) {
$content = '';
@@ -80,7 +77,7 @@ if(!$error) {
$_SESSION['config_content'] = $content;
unset($_SESSION['saved']);
$locale['step_database_error_file'] = str_replace('$FILE$', '<b>' . BASE . 'config.local.php</b>', $locale['step_database_error_file']);
$locale['step_database_error_file'] = str_replace('$FILE$', '<b>' . BASE . 'config.php</b>', $locale['step_database_error_file']);
error($locale['step_database_error_file'] . '<br/>
<textarea cols="70" rows="10">' . $content . '</textarea>');
}

View File

@@ -1,3 +1,4 @@
<?php defined('MYAAC') or die('Direct access not allowed!'); ?>
<!DOCTYPE html>
<html dir="<?php echo $locale['direction']; ?>" lang="<?php echo $locale['lang']; ?>" xml:lang="<?php echo $locale['lang']; ?>">
<head>

View File

@@ -156,9 +156,14 @@ if ($db->hasTable('guilds')) {
}
if (!$db->hasColumn('guilds', 'description')) {
if (query("ALTER TABLE `guilds` ADD `description` TEXT NOT NULL;"))
if (query("ALTER TABLE `guilds` ADD `description` VARCHAR(5000) NOT NULL DEFAULT '';"))
success($locale['step_database_adding_field'] . ' guilds.description...');
}
else {
if (query("ALTER TABLE `guilds` MODIFY `description` VARCHAR(5000) NOT NULL DEFAULT '';")) {
success($locale['step_database_modifying_field'] . ' guilds.description...');
}
}
if ($db->hasColumn('guilds', 'logo_gfx_name')) {
if (query("ALTER TABLE `guilds` CHANGE `logo_gfx_name` `logo_name` VARCHAR( 255 ) NOT NULL DEFAULT 'default.gif';")) {
@@ -197,9 +202,14 @@ if ($db->hasTable('players')) {
}
if (!$db->hasColumn('players', 'comment')) {
if (query("ALTER TABLE `players` ADD `comment` TEXT NOT NULL;"))
if (query("ALTER TABLE `players` ADD `comment` VARCHAR(5000) NOT NULL DEFAULT '';"))
success($locale['step_database_adding_field'] . ' players.comment...');
}
else {
if (query("ALTER TABLE `players` MODIFY `comment` VARCHAR(5000) NOT NULL DEFAULT '';")) {
success($locale['step_database_modifying_field'] . ' players.comment...');
}
}
if ($db->hasColumn('players', 'rank_id')) {
if (query("ALTER TABLE players MODIFY `rank_id` INT(11) NOT NULL DEFAULT 0;"))

View File

@@ -54,12 +54,13 @@ if ($db->hasTable('players')) {
}
}
Plugins::installMenus('kathrine', require TEMPLATES . 'kathrine/menus.php');
Plugins::installMenus('tibiacom', require TEMPLATES . 'tibiacom/menus.php');
DataLoader::setLocale($locale);
DataLoader::load();
// add menus entries
require_once SYSTEM . 'migrations/17.php';
$up();
// update config.highscores_ids_hidden
require_once SYSTEM . 'migrations/20.php';
$up();

View File

@@ -86,7 +86,7 @@ switch ($action) {
die(json_encode(['eventlist' => $eventlist, 'lastupdatetimestamp' => time()]));
case 'boostedcreature':
$boostedCreature = BoostedCreature::latest();
$boostedCreature = BoostedCreature::first();
die(json_encode([
'boostedcreature' => true,
'raceid' => $boostedCreature->raceid
@@ -143,7 +143,7 @@ switch ($action) {
if ($limiter->exceeded($ip)) {
sendError($ban_msg);
}
sendError(($inputEmail != false ? 'Email' : 'Account name') . ' or password is not correct.');
}

View File

@@ -1,6 +1,6 @@
server {
listen 80;
root /home/otserv/www/public;
root /var/www/html;
index index.php;
server_name your-domain.com;
@@ -12,13 +12,9 @@ server {
deny all;
}
location /vendor {
deny all;
}
# block .htaccess, CHANGELOG.md, composer.json etc.
# this is to prevent finding software versions
location ~\.(ht|md|json|dist)$ {
location ~\.(ht|md|json|dist|sql)$ {
deny all;
}
@@ -28,7 +24,7 @@ server {
}
location / {
try_files $uri $uri/ /index.php?$query_string;;
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {

901
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@
"postinstall": "node ./npm-post-install.js"
},
"devDependencies": {
"cypress": "^12.12.0"
"cypress": "^13.17.0"
},
"dependencies": {
"@tinymce/tinymce-jquery": "^2.1.0",
@@ -12,6 +12,6 @@
"fs-extra": "^11.2.0",
"jquery": "^3.7.1",
"jquery-ui": "^1.13.2",
"tinymce": "^6.8.3"
"tinymce": "^7.2.0"
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "create-account-hint",
"description": "This plugin display text 'To play on Forgotten you need an account. All you have to do to create your new account is to enter an account name, password, country and your email address. Also you have to agree to the terms presented below. If you have done so, your account name will be shown on the following page and your account password will be sent to your email address along with further instructions. If you do not receive the email with your password, please check your spam filter.' on the create account page. <strong>Be careful when uninstalling this!</strong>",
"description": "This plugin display text 'To play on Forgotten you need an account. All you have to do to create your new account is to enter an account name, password, country and your email address. Also you have to agree to the terms presented below. If you have done so, your account name will be shown on the following page and your account password will be sent to your email address along with further instructions. If you do not receive the email with your password, please check your spam filter.' on the create account page.",
"version": "1.0",
"author": "slawkens",
"contact": "slawkens@gmail.com",

View File

@@ -9,7 +9,4 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
global $twig_loader;
$twig_loader->prependPath(BASE . 'plugins/account-create-hint');
$twig->display('hint.html.twig');
$twig->display('account-create-hint/hint.html.twig');

View File

@@ -46,8 +46,10 @@
"settings": "plugins/your-plugin-folder/settings.php",
"autoload": {
"pages": true,
"pagesSubFolders": false,
"pages-sub-folders": false,
"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
# get myaac from git archive
git archive --format zip --output tmp/myaac.zip develop
git archive --format zip --output tmp/myaac.zip main
cd tmp/ || exit

View File

@@ -74,7 +74,3 @@ function fieldExist($field, $table)
global $db;
return $db->hasColumn($table, $field);
}
function getCreatureImgPath($creature): string {
return getMonsterImgPath($creature);
}

View File

@@ -9,16 +9,16 @@
*/
use MyAAC\Exceptions\SensitiveException;
use Whoops\Handler\PlainTextHandler;
use Whoops\Handler\PrettyPageHandler;
use Whoops\Run;
if (class_exists(\Whoops\Run::class)) {
$whoops = new \Whoops\Run;
if(IS_CLI) {
$whoops->pushHandler(new \Whoops\Handler\PlainTextHandler);
}
else {
$whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
}
if (class_exists(Run::class)) {
$whoops = new Run;
$whoopsHandler = IS_CLI ? (new PlainTextHandler()) : (new PrettyPageHandler());
$whoops->pushHandler($whoopsHandler);
$whoops->register();
return;
}

View File

@@ -49,7 +49,7 @@ function warning($message, $return = false) {
return message($message, 'warning', $return);
}
function note($message, $return = false) {
return info($message, $return);
return message($message, 'note', $return);
}
function info($message, $return = false) {
return message($message, 'info', $return);
@@ -121,7 +121,7 @@ function getPlayerLink($name, $generate = true, bool $colored = false): 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;
return generateLink($url, $name);
@@ -129,16 +129,14 @@ function getMonsterLink($name, $generate = true): string
function getHouseLink($name, $generate = true): string
{
if(is_numeric($name))
{
if(is_numeric($name)) {
$house = House::find(intval($name), ['name']);
if ($house) {
$name = $house->name;
}
}
$url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'houses/' . urlencode($name);
$url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'houses?name=' . urlencode($name);
if(!$generate) return $url;
return generateLink($url, $name);
@@ -547,33 +545,39 @@ function template_header($is_admin = false): string
*/
function template_footer(): string
{
global $views_counter;
$ret = '';
$footer = [];
if(admin()) {
$ret .= generateLink(ADMIN_URL, 'Admin Panel', true);
$footer[] = generateLink(ADMIN_URL, 'Admin Panel', true);
}
if(setting('core.visitors_counter')) {
global $visitors;
$amount = $visitors->getAmountVisitors();
$ret .= '<br/>Currently there ' . ($amount > 1 ? 'are' : 'is') . ' ' . $amount . ' visitor' . ($amount > 1 ? 's' : '') . '.';
$footer[] = 'Currently there ' . ($amount > 1 ? 'are' : 'is') . ' ' . $amount . ' visitor' . ($amount > 1 ? 's' : '') . '.';
}
if(setting('core.views_counter')) {
$ret .= '<br/>Page has been viewed ' . $views_counter . ' times.';
global $views_counter;
$footer[] = 'Page has been viewed ' . $views_counter . ' times.';
}
if(setting('core.footer_load_time')) {
$ret .= '<br/>Load time: ' . round(microtime(true) - START_TIME, 4) . ' seconds.';
$footer[] = 'Load time: ' . round(microtime(true) - START_TIME, 4) . ' seconds.';
}
$settingFooter = setting('core.footer');
if(isset($settingFooter[0])) {
$ret .= '<br/>' . $settingFooter;
$footer[] = '' . $settingFooter;
}
// please respect my work and help spreading the word, thanks!
return $ret . '<br/>' . base64_decode('UG93ZXJlZCBieSA8YSBocmVmPSJodHRwOi8vbXktYWFjLm9yZyIgdGFyZ2V0PSJfYmxhbmsiPk15QUFDLjwvYT4=');
$footer[] = base64_decode('UG93ZXJlZCBieSA8YSBocmVmPSJodHRwOi8vbXktYWFjLm9yZyIgdGFyZ2V0PSJfYmxhbmsiPk15QUFDLjwvYT4=');
global $hooks;
$hooks->triggerFilter(HOOK_FILTER_THEME_FOOTER, $footer);
return implode('<br/>', $footer);
}
function template_ga_code()
@@ -589,24 +593,12 @@ function template_form()
{
global $template_name;
$cache = Cache::getInstance();
if($cache->enabled())
{
$tmp = '';
if($cache->fetch('templates', $tmp)) {
$templates = unserialize($tmp);
}
else
{
$templates = get_templates();
$cache->set('templates', serialize($templates), 30);
}
}
else
$templates = get_templates();
$templates = Cache::remember('templates', 5 * 60, function() {
return get_templates();
});
$options = '';
foreach($templates as $key => $value)
foreach($templates as $value)
$options .= '<option ' . ($template_name == $value ? 'SELECTED' : '') . '>' . $value . '</option>';
global $twig;
@@ -996,31 +988,29 @@ function load_config_lua($filename)
continue;
}
$tmp_exp = explode('=', $line, 2);
if(strpos($line, 'dofile') !== false)
{
if(str_contains($line, 'dofile')) {
$delimiter = '"';
if(strpos($line, $delimiter) === false)
if(!str_contains($line, $delimiter)) {
$delimiter = "'";
}
$tmp = explode($delimiter, $line);
$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]);
if(0 !== strpos($key, '--'))
{
if(!str_starts_with($key, '--')) {
$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);
}
if(is_numeric($value))
$result[$key] = (float) $value;
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')))
$result[$key] = ($value === 'true') ? true : false;
$result[$key] = $value === 'true';
elseif(@$value[0] === '{') {
// arrays are not supported yet
// just ignore the error
@@ -1028,12 +1018,19 @@ function load_config_lua($filename)
}
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);
$ret = @eval("return $value;");
if((string) $ret == '' && trim($value) !== '""') // = parser error
{
throw new RuntimeException('ERROR: Loading config.lua file. Line <b>' . ($ln + 1) . '</b> of LUA config file is not valid [key: <b>' . $key . '</b>]');
}
try {
$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;
}
@@ -1042,8 +1039,7 @@ function load_config_lua($filename)
}
}
$result = array_merge($result, isset($config['lua']) ? $config['lua'] : array());
return $result;
return array_merge($result, $config['lua'] ?? []);
}
function str_replace_first($search,$replace, $subject) {
@@ -1069,17 +1065,36 @@ function get_browser_real_ip() {
return '0';
}
function setSession($key, $data) {
$_SESSION[setting('core.session_prefix') . $key] = $data;
function setSession($key, $value = null): void {
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) {
$key = setting('core.session_prefix') . $key;
return isset($_SESSION[$key]) ? $_SESSION[$key] : false;
return $_SESSION[setting('core.session_prefix') . $key] ?? null;
}
function unsetSession($key) {
function unsetSession($key): void {
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 {
return CsrfToken::create($return);
}
@@ -1102,20 +1117,16 @@ function csrfProtect(): void
}
}
function getTopPlayers($limit = 5) {
function getTopPlayers($limit = 5, $skill = 'level') {
global $db;
$cache = Cache::getInstance();
if($cache->enabled()) {
$tmp = '';
if($cache->fetch('top_' . $limit . '_level', $tmp)) {
$players = unserialize($tmp);
}
if ($skill === 'level') {
$skill = 'experience';
}
if (!isset($players)) {
return Cache::remember("top_{$limit}_{$skill}", 2 * 60, function () use ($db, $limit, $skill) {
$columns = [
'id', 'name', 'level', 'vocation', 'experience',
'id', 'name', 'level', 'vocation', 'experience', 'balance',
'looktype', 'lookhead', 'lookbody', 'looklegs', 'lookfeet'
];
@@ -1123,36 +1134,27 @@ function getTopPlayers($limit = 5) {
$columns[] = 'lookaddons';
}
if ($db->hasColumn('players', 'online')) {
$columns[] = 'online';
}
$players = Player::query()
return Player::query()
->select($columns)
->withOnlineStatus()
->notDeleted()
->where('group_id', '<', setting('core.highscores_groups_hidden'))
->whereNotIn('id', setting('core.highscores_ids_hidden'))
->where('account_id', '!=', 1)
->orderByDesc('experience')
->orderByDesc($skill)
->limit($limit)
->get()
->map(function ($e, $i) {
$row = $e->toArray();
$row['online'] = $e->online_status;
$row['rank'] = $i + 1;
$row['outfit_url'] = $e->outfit_url;
unset($row['online_table']);
return $row;
})->toArray();
if($cache->enabled()) {
$cache->set('top_' . $limit . '_level', serialize($players), 120);
}
}
return $players;
});
}
function deleteDirectory($dir, $ignore = array(), $contentOnly = false) {
@@ -1576,22 +1578,6 @@ function right($str, $length) {
return substr($str, -$length);
}
function getMonsterImgPath($monster): string
{
$monster_path = setting('core.monsters_images_url');
$monster_gfx_name = trim(strtolower($monster)) . setting('core.monsters_images_extension');
if (!file_exists($monster_path . $monster_gfx_name)) {
$monster_gfx_name = str_replace(" ", "", $monster_gfx_name);
if (file_exists($monster_path . $monster_gfx_name)) {
return $monster_path . $monster_gfx_name;
} else {
return $monster_path . 'nophoto.png';
}
} else {
return $monster_path . $monster_gfx_name;
}
}
function between($x, $lim1, $lim2) {
if ($lim1 < $lim2) {
$lower = $lim1; $upper = $lim2;
@@ -1700,4 +1686,7 @@ function getAccountIdentityColumn(): string
require_once SYSTEM . 'compat/base.php';
// custom functions
require SYSTEM . 'functions_custom.php';
$customFunctions = SYSTEM . 'functions_custom.php';
if (is_file($customFunctions)) {
require $customFunctions;
}

View File

@@ -50,6 +50,7 @@ $cache = Cache::getInstance();
global $hooks;
$hooks = new Hooks();
$hooks->load();
$hooks->trigger(HOOK_INIT);
// twig
require_once SYSTEM . 'twig.php';
@@ -96,8 +97,8 @@ if($config_lua_reload) {
// cache config
if($cache->enabled()) {
$cache->set('config_lua', serialize($config['lua']), 120);
$cache->set('server_path', $config['server_path']);
$cache->set('config_lua', serialize($config['lua']), 2 * 60);
$cache->set('server_path', $config['server_path'], 10 * 60);
}
}
unset($tmp);
@@ -139,7 +140,7 @@ require_once SYSTEM . 'database.php';
// verify myaac tables exists in database
if(!defined('MYAAC_INSTALL') && !$db->hasTable('myaac_account_actions')) {
throw new RuntimeException('Seems that the table myaac_account_actions of MyAAC doesn\'t exist in the database. This is a fatal error. You can try to reinstall MyAAC by visiting ' . BASE_URL . 'install');
throw new RuntimeException('Seems that the table myaac_account_actions of MyAAC doesn\'t exist in the database. This is a fatal error. You can try to reinstall MyAAC by visiting ' . (IS_CLI ? 'http://your-ip.com/' : BASE_URL) . 'install');
}
// execute migrations

View File

@@ -12,6 +12,8 @@
* @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU Lesser General Public License, Version 3
*/
use MyAAC\Models\AccountAction;
/**
* OTServ account abstraction.
*
@@ -443,19 +445,19 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
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'])) {
$col = isset($this->data['premium_ends_at']) ? 'premium_ends_at' : 'premend';
$ret = ceil(($this->data[$col] - time()) / (24 * 60 * 60));
return $ret > 0 ? $ret : 0;
return max($ret, 0);
}
if($this->data['premdays'] == 0) {
return 0;
}
global $config;
if(isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium'])) return -1;
if($this->data['premdays'] == self::GRATIS_PREMIUM_DAYS){
return self::GRATIS_PREMIUM_DAYS;
}
@@ -1010,26 +1012,16 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
public function logAction($action)
{
$ip = get_browser_real_ip();
if(strpos($ip, ":") === false) {
$ipv6 = '0';
}
else {
$ipv6 = $ip;
$ip = '';
}
return $this->db->exec('INSERT INTO `' . TABLE_PREFIX . 'account_actions` (`account_id`, `ip`, `ipv6`, `date`, `action`) VALUES (' . $this->db->quote($this->getId()).', ' . ($ip == '' ? '0' : $this->db->quote(ip2long($ip))) . ', (' . ($ipv6 == '0' ? $this->db->quote('') : $this->db->quote(inet_pton($ipv6))) . '), UNIX_TIMESTAMP(NOW()), ' . $this->db->quote($action).')');
AccountAction::create([
'account_id' => $this->getId(),
'ip' => get_browser_real_ip(),
'date' => time(),
'action' => $action,
]);
}
public function getActionsLog($limit1, $limit2)
{
$actions = array();
foreach($this->db->query('SELECT `ip`, `ipv6`, `date`, `action` FROM `' . TABLE_PREFIX . 'account_actions` WHERE `account_id` = ' . $this->data['id'] . ' ORDER by `date` DESC LIMIT ' . $limit1 . ', ' . $limit2 . '')->fetchAll() as $a)
$actions[] = array('ip' => $a['ip'], 'ipv6' => $a['ipv6'], 'date' => $a['date'], 'action' => $a['action']);
return $actions;
public function getActionsLog($limit) {
return AccountAction::where('account_id', $this->data['id'])->orderByDesc('date')->limit($limit)->get()->toArray();
}
/**
* Returns players iterator.

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);
}
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() {
foreach($this->has_table_cache as $key => $value) {
$this->hasTableInternal($key);

View File

@@ -97,7 +97,7 @@ class OTS_Guild extends OTS_Row_DAO implements IteratorAggregate, Countable
*
* @param IOTS_GuildAction $invites Invites driver (don't pass it to clear driver).
*/
public function setInvitesDriver(IOTS_GuildAction $invites = null)
public function setInvitesDriver(?IOTS_GuildAction $invites = null)
{
$this->invites = $invites;
}
@@ -107,7 +107,7 @@ class OTS_Guild extends OTS_Row_DAO implements IteratorAggregate, Countable
*
* @param IOTS_GuildAction $requests Membership requests driver (don't pass it to clear driver).
*/
public function setRequestsDriver(IOTS_GuildAction $requests = null)
public function setRequestsDriver(?IOTS_GuildAction $requests = null)
{
$this->requests = $requests;
}

View File

@@ -60,7 +60,7 @@ class OTS_GuildRank extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws PDOException On PDO operation error.
* @throws E_OTS_NotLoaded If given <var>$guild</var> object is not loaded.
*/
public function find($name, OTS_Guild $guild = null)
public function find($name, ?OTS_Guild $guild = null)
{
$where = '';

View File

@@ -284,7 +284,7 @@ class OTS_Monster extends DOMDocument
*/
public function getLook()
{
$look = array();
$look = [];
$element = $this->documentElement->getElementsByTagName('look')->item(0);
@@ -292,14 +292,30 @@ class OTS_Monster extends DOMDocument
return $look;
}
$look['type'] = $element->getAttribute('type');
$look['typeex'] = $element->getAttribute('typeex');
$look['head'] = $element->getAttribute('head');
$look['body'] = $element->getAttribute('body');
$look['legs'] = $element->getAttribute('legs');
$look['feet'] = $element->getAttribute('feet');
$look['addons'] = $element->getAttribute('addons');
$look['corpse'] = $element->getAttribute('corpse');
if ($element->hasAttribute('typeex')) {
$look['typeEx'] = (int) $element->getAttribute('typeex');
}
if ($element->hasAttribute('type')) {
$look['type'] = (int) $element->getAttribute('type');
}
if ($element->hasAttribute('head')) {
$look['head'] = (int) $element->getAttribute('head');
}
if ($element->hasAttribute('body')) {
$look['body'] = (int) $element->getAttribute('body');
}
if ($element->hasAttribute('legs')) {
$look['legs'] = (int) $element->getAttribute('legs');
}
if ($element->hasAttribute('feet')) {
$look['feet'] = (int) $element->getAttribute('feet');
}
if ($element->hasAttribute('addons')) {
$look['addons'] = (int) $element->getAttribute('addons');
}
if ($element->hasAttribute('corpse')) {
$look['corpse'] = (int) $element->getAttribute('corpse');
}
return $look;
}

File diff suppressed because it is too large Load Diff

View File

@@ -14,12 +14,12 @@ $account_logged = new OTS_Account();
// stay-logged with sessions
$current_session = getSession('account');
if($current_session !== false)
if($current_session)
{
$account_logged->load($current_session);
if($account_logged->isLoaded() && $account_logged->getPassword() == getSession('password')
//&& (!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;
}
else {

View File

@@ -10,8 +10,13 @@ $up = function () use ($db) {
$db->exec(file_get_contents(__DIR__ . '/17-menu.sql'));
}
Plugins::installMenus('kathrine', require TEMPLATES . 'kathrine/menus.php');
Plugins::installMenus('tibiacom', require TEMPLATES . 'tibiacom/menus.php');
$themes = ['kathrine', 'tibiacom',];
foreach ($themes as $theme) {
$file = TEMPLATES . $theme . '/menus.php';
if (is_file($file)) {
Plugins::installMenus($theme, require $file);
}
}
};
$down = function () use ($db) {

View File

@@ -8,7 +8,7 @@
// the size of ipv6 can be maximal 45 chars
$up = function () use ($db) {
$db->modifyColumn(TABLE_PREFIX . 'visitors', 'ip', 'VARCHAR(15) NOT NULL');
$db->modifyColumn(TABLE_PREFIX . 'visitors', 'ip', 'VARCHAR(45) NOT NULL');
};
$down = function () {

15
system/migrations/42.php Normal file
View File

@@ -0,0 +1,15 @@
<?php
/**
* @var OTS_DB_MySQL $db
*/
// 2025-09-01
// resize forum.post_ip to support ipv6
$up = function () use ($db) {
$db->modifyColumn(TABLE_PREFIX . 'forum', 'post_ip', "varchar(45) NOT NULL default '0.0.0.0'");
};
$down = function () {
// there is no downgrade for this
};

20
system/migrations/43.php Normal file
View File

@@ -0,0 +1,20 @@
<?php
/**
* @var OTS_DB_MySQL $db
*/
// 2025-01-22
// change columns to VARCHAR
$up = function () use ($db) {
$db->query("UPDATE guilds set description = '' WHERE description is NULL;"); // prevent truncate error when column is NULL
$db->modifyColumn('guilds', 'description', "VARCHAR(5000) NOT NULL DEFAULT ''");
$db->query("UPDATE players set comment = '' WHERE comment is NULL;");
$db->modifyColumn('players', 'comment', "VARCHAR(5000) NOT NULL DEFAULT ''");
};
$down = function () use ($db) {
$db->modifyColumn('guilds', 'description', "TEXT NOT NULL");
$db->modifyColumn('players', 'comment', "TEXT NOT NULL");
};

27
system/migrations/44.php Normal file
View File

@@ -0,0 +1,27 @@
<?php
/**
* @var OTS_DB_MySQL $db
*/
// 2025-02-27
// remove ipv6, change to ip (for both ipv4 + ipv6) as VARCHAR(45)
$up = function () use ($db) {
$db->query("ALTER TABLE `myaac_account_actions` DROP KEY `account_id`;");
$db->query("ALTER TABLE `myaac_account_actions` ADD COLUMN `id` INT(11) NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (`id`);");
$db->modifyColumn(TABLE_PREFIX . 'account_actions', 'ip', "VARCHAR(45) NOT NULL DEFAULT ''");
$db->query("UPDATE `" . TABLE_PREFIX . "account_actions` SET `ip` = INET_NTOA(`ip`) WHERE `ip` != '0';");
$db->query("UPDATE `" . TABLE_PREFIX . "account_actions` SET `ip` = INET6_NTOA(`ipv6`) WHERE `ip` = '0';");
$db->dropColumn(TABLE_PREFIX . 'account_actions', 'ipv6');
};
$down = function () use ($db) {
$db->query("ALTER TABLE `" . TABLE_PREFIX . "account_actions` DROP `id`;");
$db->query("ALTER TABLE `" . TABLE_PREFIX . "account_actions` ADD KEY (`account_id`);");
$db->addColumn(TABLE_PREFIX . 'account_actions', 'ipv6', "BINARY(16) NOT NULL DEFAULT 0x00000000000000000000000000000000 AFTER ip");
$db->query("UPDATE `" . TABLE_PREFIX . "account_actions` SET `ipv6` = INET6_ATON(ip) WHERE NOT IS_IPV4(`ip`);");
$db->query("UPDATE `" . TABLE_PREFIX . "account_actions` SET `ip` = INET_ATON(`ip`) WHERE IS_IPV4(`ip`);");
$db->query("UPDATE `" . TABLE_PREFIX . "account_actions` SET `ip` = 0 WHERE `ipv6` != 0x00000000000000000000000000000000;");
$db->modifyColumn(TABLE_PREFIX . 'account_actions', 'ip', "INT(11) UNSIGNED NOT NULL DEFAULT 0;");
};

View File

@@ -66,7 +66,7 @@ else
$new_sex_str = $config['genders'][$new_sex];
$player->save();
$account_logged->setCustomField(setting('core.donate_column'), $points - setting('core.account_change_character_name_price'));
$account_logged->setCustomField(setting('core.donate_column'), $points - setting('core.account_change_character_sex_price'));
$account_logged->logAction('Changed sex on character <b>' . $player->getName() . '</b> from <b>' . $old_sex_str . '</b> to <b>' . $new_sex_str . '</b>.');
$twig->display('success.html.twig', array(
'title' => 'Character Sex Changed',

View File

@@ -85,12 +85,8 @@ if($email_new_time > 1)
}
}
$actions = array();
foreach($account_logged->getActionsLog(0, 1000) as $action) {
$actions[] = array('action' => $action['action'], 'date' => $action['date'], 'ip' => $action['ip'] != 0 ? long2ip($action['ip']) : inet_ntop($action['ipv6']));
}
$actions = $account_logged->getActionsLog(1000);
$players = array();
/** @var OTS_Players_List $account_players */
$account_players = $account_logged->getPlayersList();
$account_players->orderBy('id');

View File

@@ -35,7 +35,7 @@ if(Forum::canPost($account_logged))
$thread = $db->query("SELECT `author_guid`, `author_aid`, `first_post`, `post_topic`, `post_date`, `post_text`, `post_smile`, `post_html`, `id`, `section` FROM `" . FORUM_TABLE_PREFIX . "forum` WHERE `id` = ".$post_id." LIMIT 1")->fetch();
if(isset($thread['id'])) {
$first_post = $db->query("SELECT `" . FORUM_TABLE_PREFIX . "forum`.`author_guid`, `" . FORUM_TABLE_PREFIX . "forum`.`author_aid`, `" . FORUM_TABLE_PREFIX . "forum`.`first_post`, `" . FORUM_TABLE_PREFIX . "forum`.`post_topic`, `" . FORUM_TABLE_PREFIX . "forum`.`post_text`, `" . FORUM_TABLE_PREFIX . "forum`.`post_smile`, `" . FORUM_TABLE_PREFIX . "forum`.`id`, `" . FORUM_TABLE_PREFIX . "forum`.`section` FROM `" . FORUM_TABLE_PREFIX . "forum` WHERE `" . FORUM_TABLE_PREFIX . "forum`.`id` = ".(int) $thread['first_post']." LIMIT 1")->fetch();
echo '<a href="' . getLink('forum') . '">Boards</a> >> <a href="' . getForumBoardLink($thread['section']) . '">'.$sections[$thread['section']]['name'].'</a> >> <a href="' . getForumThreadLink($thread['first_post']) . '">'.$first_post['post_topic'].'</a> >> <b>Edit post</b>';
echo '<a href="' . getLink('forum') . '">Boards</a> >> <a href="' . getForumBoardLink($thread['section']) . '">'.$sections[$thread['section']]['name'].'</a> >> <a href="' . getForumThreadLink($thread['first_post']) . '">'.htmlspecialchars($first_post['post_topic']).'</a> >> <b>Edit post</b>';
if(Forum::hasAccess($thread['section'] && ($account_logged->getId() == $thread['author_aid'] || Forum::isModerator()))) {
$char_id = $post_topic = $text = $smile = $html = null;

View File

@@ -25,6 +25,7 @@ if(!$logged) {
if(!Forum::isModerator()) {
echo 'You are not logged in or you are not moderator.';
return;
}
$save = isset($_REQUEST['save']) && (int)$_REQUEST['save'] == 1;

View File

@@ -40,7 +40,7 @@ if(Forum::canPost($account_logged)) {
$thread = $db->query("SELECT `" . FORUM_TABLE_PREFIX . "forum`.`post_topic`, `" . FORUM_TABLE_PREFIX . "forum`.`id`, `" . FORUM_TABLE_PREFIX . "forum`.`section` FROM `" . FORUM_TABLE_PREFIX . "forum` WHERE `" . FORUM_TABLE_PREFIX . "forum`.`id` = ".(int) $thread_id." AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".$thread_id." LIMIT 1")->fetch();
if(isset($thread['id']) && Forum::hasAccess($thread['section'])) {
echo '<a href="' . getLink('forum') . '">Boards</a> >> <a href="' . getForumBoardLink($thread['section']) . '">'.$sections[$thread['section']]['name'].'</a> >> <a href="' . getForumThreadLink($thread_id) . '">'.$thread['post_topic'].'</a> >> <b>Post new reply</b><br /><h3>'.$thread['post_topic'].'</h3>';
echo '<a href="' . getLink('forum') . '">Boards</a> >> <a href="' . getForumBoardLink($thread['section']) . '">'.$sections[$thread['section']]['name'].'</a> >> <a href="' . getForumThreadLink($thread_id) . '">'.htmlspecialchars($thread['post_topic']).'</a> >> <b>Post new reply</b><br /><h3>'.htmlspecialchars($thread['post_topic']).'</h3>';
$quote = isset($_REQUEST['quote']) ? (int) $_REQUEST['quote'] : NULL;
$text = isset($_REQUEST['text']) ? stripslashes(trim($_REQUEST['text'])) : NULL;

View File

@@ -95,7 +95,23 @@ if(Forum::canPost($account_logged)) {
if (count($errors) == 0) {
$saved = true;
$db->query("INSERT INTO `" . FORUM_TABLE_PREFIX . "forum` (`first_post` ,`last_post` ,`section` ,`replies` ,`views` ,`author_aid` ,`author_guid` ,`post_text` ,`post_topic` ,`post_smile`, `post_html` ,`post_date` ,`last_edit_aid` ,`edit_date`, `post_ip`) VALUES ('0', '" . time() . "', '" . (int)$section_id . "', '0', '0', '" . $account_logged->getId() . "', '" . $char_id . "', " . $db->quote($text) . ", " . $db->quote($post_topic) . ", '" . $smile . "', '" . $html . "', '" . time() . "', '0', '0', '" . get_browser_real_ip() . "')");
$db->insert(FORUM_TABLE_PREFIX . 'forum', [
'first_post' => 0,
'last_post' => time(),
'section' => $section_id,
'replies' => 0,
'views' => 0,
'author_aid' => $account_logged->getId(),
'author_guid' => $char_id,
'post_text' => $text,
'post_topic' => $post_topic,
'post_smile' => $smile,
'post_html' => $html,
'post_date' => time(),
'last_edit_aid' => 0,
'edit_date' => 0,
'post_ip' => get_browser_real_ip(),
]);
$thread_id = $db->lastInsertId();

View File

@@ -68,7 +68,7 @@ if(isset($last_threads[0])) {
echo '<tr bgcolor="' . getStyle($number_of_rows++) . '"><td>';
if(Forum::isModerator()) {
echo '<a href="' . getLink('forum') . '?action=move_thread&id='.$thread['id'].'"\')"><span style="color:darkgreen">[MOVE]</span></a>';
echo '<a href="' . getLink('forum') . '?action=remove_post&id='.$thread['id'].'" onclick="return confirm(\'Are you sure you want remove thread > '.$thread['post_topic'].' <?\')"><span style="color: red">[REMOVE]</span></a> ';
echo '<a href="' . getLink('forum') . '?action=remove_post&id='.$thread['id'].'" onclick="return confirm(\'Are you sure you want remove thread > '.htmlspecialchars($thread['post_topic']).' <?\')"><span style="color: red">[REMOVE]</span></a> ';
}
$player->load($thread['player_id']);
@@ -79,7 +79,7 @@ if(isset($last_threads[0])) {
$player_account = $player->getAccount();
$canEditForum = $player_account->hasFlag(FLAG_CONTENT_FORUM) || $player_account->isAdmin();
echo '<a href="' . getForumThreadLink($thread['id']) . '">'.($canEditForum ? $thread['post_topic'] : htmlspecialchars($thread['post_topic'])) . '</a><br /><small>'.($canEditForum ? substr(strip_tags($thread['post_text']), 0, 50) : htmlspecialchars(substr($thread['post_text'], 0, 50))).'...</small></td><td>' . getPlayerLink($thread['name']) . '</td><td>'.(int) $thread['replies'].'</td><td>'.(int) $thread['views'].'</td><td>';
echo '<a href="' . getForumThreadLink($thread['id']) . '">'.htmlspecialchars($thread['post_topic']). '</a><br /><small>'.($canEditForum ? substr(strip_tags($thread['post_text']), 0, 50) : htmlspecialchars(substr($thread['post_text'], 0, 50))).'...</small></td><td>' . getPlayerLink($thread['name']) . '</td><td>'.(int) $thread['replies'].'</td><td>'.(int) $thread['views'].'</td><td>';
if($thread['last_post'] > 0) {
$last_post = $db->query("SELECT `players`.`name`, `" . FORUM_TABLE_PREFIX . "forum`.`post_date` FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".(int) $thread['id']." AND `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` ORDER BY `post_date` DESC LIMIT 1")->fetch();
if(isset($last_post['name']))

View File

@@ -21,9 +21,9 @@ $settingHighscoresCountryBox = setting('core.highscores_country_box');
if(config('account_country') && $settingHighscoresCountryBox)
require SYSTEM . 'countries.conf.php';
$list = $_GET['list'] ?? 'experience';
$list = urldecode($_GET['list'] ?? 'experience');
$page = $_GET['page'] ?? 1;
$vocation = $_GET['vocation'] ?? 'all';
$vocation = urldecode($_GET['vocation'] ?? 'all');
if(!is_numeric($page) || $page < 1 || $page > PHP_INT_MAX) {
$page = 1;
@@ -207,6 +207,7 @@ if (empty($highscores)) {
$tmp = $row->toArray();
$tmp['online'] = $row->online_status;
$tmp['vocation'] = $row->vocation_name;
$tmp['outfit_url'] = $row->outfit_url; // @phpstan-ignore-line
unset($tmp['online_table']);
return $tmp;
@@ -233,14 +234,10 @@ foreach($highscores as $id => &$player)
$player['experience'] = number_format($player['experience']);
}
if(!$settingHighscoresVocation) {
unset($player['vocation']);
}
$player['link'] = getPlayerLink($player['name'], false);
$player['flag'] = getFlagImage($player['country']);
if($settingHighscoresOutfit) {
$player['outfit'] = '<img style="position:absolute;margin-top:' . (in_array($player['looktype'], setting('core.outfit_images_wrong_looktypes')) ? '-15px;margin-left:5px' : '-45px;margin-left:-25px') . ';" src="' . setting('core.outfit_images_url') . '?id=' . $player['looktype'] . ($outfit_addons ? '&addons=' . $player['lookaddons'] : '') . '&head=' . $player['lookhead'] . '&body=' . $player['lookbody'] . '&legs=' . $player['looklegs'] . '&feet=' . $player['lookfeet'] . '" alt="" />';
$player['outfit'] = '<img style="position:absolute;margin-top:' . (in_array($player['looktype'], setting('core.outfit_images_wrong_looktypes')) ? '-15px;margin-left:5px' : '-45px;margin-left:-25px') . ';" src="' . $player['outfit_url'] . '" alt="" />';
}
$player['rank'] = $offset + $i;
}

View File

@@ -30,11 +30,11 @@ $state = '';
$order = '';
$type = '';
if(isset($_GET['page']) && $_GET['page'] == 'view' && isset($_REQUEST['house']))
if(isset($_REQUEST['name']))
{
$beds = array("", "one", "two", "three", "fourth", "fifth");
$houseName = $_REQUEST['house'];
$houseId = (Validator::number($_REQUEST['house']) ? $_REQUEST['house'] : -1);
$houseName = urldecode($_REQUEST['name']);
$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));
$house = array();
@@ -187,7 +187,7 @@ if(isset($_POST['town']) && isset($_POST['state']) && isset($_POST['order']) &&
$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;

View File

@@ -16,18 +16,22 @@ defined('MYAAC') or die('Direct access not allowed!');
$title = 'Monsters';
if (empty($_REQUEST['name'])) {
// display list of monsters
$preview = setting('core.monsters_images_preview');
$monsters = Monster::where('hide', '!=', 1)->when(!empty($_REQUEST['boss']), function ($query) {
$query->where('rewardboss', 1);
})->get()->toArray();
if ($preview) {
foreach($monsters as $key => &$monster)
{
$monster['img_link'] = getMonsterImgPath($monster['name']);
// display list of monsters
$monsters = MyAAC\Cache::remember('monsters', 30 * 60, function () use ($preview) {
$monsters = Monster::where('hide', '!=', 1)->when(!empty($_REQUEST['boss']), function ($query) {
$query->where('rewardboss', 1);
})->get()->toArray();
if ($preview) {
foreach($monsters as &$monster) {
$monster['img_link'] = getMonsterImage($monster);
}
}
}
return $monsters;
});
$twig->display('monsters.html.twig', array(
'monsters' => $monsters,
@@ -45,7 +49,7 @@ if ($monsterModel && isset($monsterModel->name)) {
/** @var array $monster */
$monster = $monsterModel->toArray();
function sort_by_chance($a, $b)
function sort_by_chance($a, $b): int
{
if ($a['chance'] == $b['chance']) {
return 0;
@@ -55,7 +59,7 @@ if ($monsterModel && isset($monsterModel->name)) {
$title = $monster['name'] . " - Monsters";
$monster['img_link']= getMonsterImgPath($monster_name);
$monster['img_link']= getMonsterImage($monster);
$voices = json_decode($monster['voices'], true);
$summons = json_decode($monster['summons'], true);
@@ -89,3 +93,39 @@ if ($monsterModel && isset($monsterModel->name)) {
// back button
$twig->display('monsters.back_button.html.twig');
function getMonsterImage($monster): string
{
$outfit = json_decode($monster['look'], true);
if (!empty($outfit['typeEx'])) {
return setting('core.item_images_url') . $outfit['typeEx'] . setting('core.item_images_extension');
}
if (isset($outfit['type'])) {
$getValue = function ($val) use ($outfit) {
return (!empty($outfit[$val])
? '&' . $val . '=' . $outfit[$val] : '');
};
return setting('core.outfit_images_url') . '?id=' . $outfit['type'] . $getValue('addons') . $getValue('head') . $getValue('body') . $getValue('legs') . $getValue('feet');
}
return getMonsterImgPath($monster['name']);
}
function getMonsterImgPath($name): string
{
$monster_path = setting('core.monsters_images_url');
$monster_gfx_name = trim(strtolower($name)) . setting('core.monsters_images_extension');
if (!file_exists($monster_path . $monster_gfx_name)) {
$monster_gfx_name = str_replace(" ", "", $monster_gfx_name);
if (file_exists($monster_path . $monster_gfx_name)) {
return $monster_path . $monster_gfx_name;
} else {
return $monster_path . 'nophoto.png';
}
} else {
return $monster_path . $monster_gfx_name;
}
}

View File

@@ -88,7 +88,7 @@ if(isset($_GET['archive']))
foreach($news_DB as $news)
{
$newses[] = array(
'link' => getLink('news') . '/' . $news['id'],
'link' => getLink('news/archive') . '/' . $news['id'],
'icon_id' => $categories[$news['category']]['icon_id'],
'title' => stripslashes($news['title']),
'date' => $news['date']

View File

@@ -100,7 +100,7 @@ function getColorByPercent($percent)
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;
}

View File

@@ -89,8 +89,6 @@ if($logged && $account_logged && $account_logged->isLoaded()) {
* Routes loading
*/
$dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) {
$routes = require SYSTEM . 'routes.php';
$routesFinal = [];
foreach(getDatabasePages() as $page) {
$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) {
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];
}
else {
@@ -314,6 +317,11 @@ $content .= ob_get_contents();
ob_end_clean();
$hooks->trigger(HOOK_AFTER_PAGE);
if (isset($_REQUEST['_page_only'])) {
echo $content;
die;
}
if(!isset($title)) {
$title = str_replace('index.php/', '', $page);
$title = ucfirst($title);
@@ -343,16 +351,16 @@ function getDatabasePages($withHidden = false): array
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)) {
// feature: convert camelCase to snake_case
// so instead of forum/move_thread
// we can write: forum/moveThread
$file = SYSTEM . 'pages/' . camelCaseToUnderscore($page) . '.php';
$file = SYSTEM . 'pages/' . $page . '.php';
if (!is_file($file)) {
// feature: load pages from templates/ dir
global $template_path;
$file = $template_path . '/pages/' . $page . '.php';
// feature: convert camelCase to snake_case
// so instead of forum/move_thread
// we can write: forum/moveThread
$file = SYSTEM . 'pages/' . camelCaseToUnderscore($page) . '.php';
if (!is_file($file)) {
$found = false;
}

View File

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

View File

@@ -11,8 +11,14 @@
* - for number: min, max, step
*/
use MyAAC\Cache;
use MyAAC\Settings;
$templates = Cache::remember('templates', 5 * 60, function () {
return get_templates();
});
$defaultTemplate = in_array('kathrine', $templates) ? 'kathrine' : $templates[0];
return [
'name' => 'MyAAC',
'settings' => [
@@ -88,7 +94,7 @@ return [
'type' => 'options',
'options' => '$templates',
'desc' => 'Name of the template used by website',
'default' => 'kathrine',
'default' => $defaultTemplate,
],
'template_allow_change' => [
'name' => 'Template Allow Change',
@@ -342,7 +348,7 @@ return [
],
'database_password' => [
'name' => 'Database Password',
'type' => 'text',
'type' => 'password',
'default' => '',
'show_if' => [
'database_overwrite', '=', 'true'
@@ -503,7 +509,7 @@ Sent by MyAAC,<br/>
'smtp_port' => [
'name' => 'SMTP Host',
'type' => 'number',
'desc' => '25 (default) / 465 (ssl, GMail) / 587 (tls, Microsoft Outlook)',
'desc' => '25 (default) / 587 (tls - GMail, Microsoft Outlook)',
'default' => 25,
'show_if' => [
'mail_enabled', '=', 'true'
@@ -530,7 +536,8 @@ Sent by MyAAC,<br/>
'smtp_pass' => [
'name' => 'SMTP Password',
'type' => 'password',
'desc' => 'Here your email password to authenticate with SMTP',
'desc' => 'Here your email password to authenticate with SMTP.' . PHP_EOL
. 'For GMail use generated App password - https://myaccount.google.com/apppasswords.',
'default' => '',
'show_if' => [
'mail_enabled', '=', 'true'
@@ -540,7 +547,8 @@ Sent by MyAAC,<br/>
'name' => 'SMTP Security',
'type' => 'options',
'options' => ['None', 'SSL', 'TLS'],
'desc' => 'What kind of encryption to use on the SMTP connection',
'desc' => 'What kind of encryption to use on the SMTP connection.' . PHP_EOL
. '(Gmail, Outlook - tls).',
'default' => 0,
'show_if' => [
'mail_enabled', '=', 'true'
@@ -1395,7 +1403,7 @@ Sent by MyAAC,<br/>
'name' => 'Outfit Images URL',
'type' => 'text',
'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' => [
'name' => 'Outfit Images Wrong Looktypes',
@@ -1465,7 +1473,7 @@ Sent by MyAAC,<br/>
],
'status_timeout' => [
'name' => 'Status Timeout',
'type' => 'number',
'type' => 'double',
'min' => 0,
'max' => 10, // more than 10 seconds waiting makes no sense
'step' => 0.1,
@@ -1614,14 +1622,20 @@ Sent by MyAAC,<br/>
'name' => 'Login Attempts Limit',
'type' => 'number',
'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' => [
'name' => 'Ban Time (Minutes)',
'type' => 'number',
'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' => [

View File

@@ -2,6 +2,7 @@
namespace MyAAC\Commands;
use MyAAC\Hooks;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
@@ -16,7 +17,10 @@ class CacheClearCommand extends Command
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);

View File

@@ -4,6 +4,7 @@ namespace MyAAC\Commands;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
@@ -16,7 +17,8 @@ class MigrateRunCommand extends Command
->addArgument('id',
InputArgument::IS_ARRAY | InputArgument::REQUIRED,
'Id or ids of migration(s)'
);
)
->addOption('down', 'd', InputOption::VALUE_NONE, 'Down');;
}
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) {
$this->executeMigration($id, $io);
$this->executeMigration($id, $io, !$down);
}
return Command::SUCCESS;
@@ -52,13 +56,24 @@ class MigrateRunCommand extends Command
return file_exists(SYSTEM . 'migrations/' . $id . '.php');
}
private function executeMigration($id, $io): void
private function executeMigration($id, $io, $_up = true): void
{
global $db;
$db->revalidateCache();
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

@@ -105,9 +105,6 @@ class CreateCharacter
* @param array $errors
* @return bool
* @throws \E_OTS_NotLoaded
* @throws \Twig_Error_Loader
* @throws \Twig_Error_Runtime
* @throws \Twig_Error_Syntax
*/
public function doCreate($name, $sex, $vocation, $town, $account, &$errors)
{

View File

@@ -82,7 +82,9 @@ class DataLoader
self::$startTime = microtime(true);
$cache = Cache::getInstance();
$cache->delete('towns'); // will be reloaded after next page load
if ($cache->enabled()) {
$cache->delete('towns'); // will be reloaded after next page load
}
global $db;
if ($db->hasTable('towns') && Town::count() > 0) {

View File

@@ -37,6 +37,11 @@ class Hook
return !isset($ret) || $ret == 1 || $ret;
}
public function executeFilter(&$args) {
return include BASE . $this->_file;
}
public function name() {return $this->_name;}
public function type() {return $this->_type;}
public function file() {return $this->_file;}
}

View File

@@ -4,22 +4,23 @@ namespace MyAAC;
class Hooks
{
private static $_hooks = array();
private static array $_hooks = [];
public function register($hook, $type = '', $file = null) {
public function register($hook, $type = '', $file = null): void
{
if(!($hook instanceof Hook))
$hook = new Hook($hook, $type, $file);
self::$_hooks[$hook->type()][] = $hook;
}
public function trigger($type, $params = array())
public function trigger($type, $params = []): bool
{
$ret = true;
if(isset(self::$_hooks[$type]))
{
if(isset(self::$_hooks[$type])) {
foreach(self::$_hooks[$type] as $name => $hook) {
/** @var $hook Hook */
/** @var Hook $hook */
if (!$hook->execute($params)) {
$ret = false;
}
@@ -29,11 +30,21 @@ class Hooks
return $ret;
}
public function exist($type) {
public function triggerFilter($type, &$args): void
{
if(isset(self::$_hooks[$type])) {
foreach(self::$_hooks[$type] as $hook) {
/** @var Hook $hook */
$hook->executeFilter($args);
}
}
}
public function exist($type): bool {
return isset(self::$_hooks[$type]);
}
public function load()
public function load(): void
{
foreach(Plugins::getHooks() as $hook) {
$this->register($hook['name'], $hook['type'], $hook['file']);

View File

@@ -9,6 +9,6 @@ class AccountAction extends Model {
public $timestamps = false;
protected $fillable = ['account_id', 'ip', 'ipv6', 'date', 'action'];
protected $fillable = ['account_id', 'ip', 'date', 'action'];
}

View File

@@ -8,6 +8,13 @@ use Illuminate\Database\Eloquent\Relations\HasOne;
* @property int $level
* @property int $vocation
* @property int $online
* @property int $looktype
* @property int $lookhead
* @property int $lookbody
* @property int $looklegs
* @property int $lookfeet
* @property int $lookaddons
* @property string $outfit_url
* @property hasOne $onlineTable
*/
class Player extends Model {
@@ -42,8 +49,8 @@ class Player extends Model {
public function getVocationNameAttribute()
{
$vocation = $this->vocation;
if (isset($this->promotion)) {
$vocation *= $this->promotion;
if (isset($this->promotion) && $this->promotion > 0) {
$vocation += ($this->promotion * setting('core.vocations_amount'));
}
return config('vocations')[$vocation] ?? 'Unknown';
@@ -73,11 +80,21 @@ class Player extends Model {
$query->where($column, 0);
}
public function scopeWithOnlineStatus($query) {
public function scopeWithOnlineStatus($query)
{
global $db;
$query->when($db->hasTable('players_online'), function ($query) {
$query->with('onlineTable');
});
if ($db->hasColumn('players', 'online')) {
$query->addSelect('online');
}
else {
$query->when($db->hasTable('players_online'), function ($query) {
$query->with('onlineTable');
});
}
}
public function getOutfitUrlAttribute() {
return setting('core.outfit_images_url') . '?id=' . $this->looktype . (!empty($this->lookaddons) ? '&addons=' . $this->lookaddons : '') . '&head=' . $this->lookhead . '&body=' . $this->lookbody . '&legs=' . $this->looklegs . '&feet=' . $this->lookfeet;
}
public function getOnlineStatusAttribute()

View File

@@ -11,6 +11,81 @@ class Plugins {
private static $error = null;
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()
{
$cache = Cache::getInstance();
@@ -76,7 +151,8 @@ class Plugins {
$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
//
@@ -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
//
@@ -121,6 +198,9 @@ class Plugins {
}
}
global $hooks;
$hooks->triggerFilter(HOOK_FILTER_ROUTES, $routes);
usort($routes, function ($a, $b)
{
// key 3 is priority
@@ -411,20 +491,13 @@ class Plugins {
$continue = true;
if(!isset($plugin_json['name']) || empty(trim($plugin_json['name']))) {
self::$warnings[] = 'Plugin "name" tag is not set.';
}
if(!isset($plugin_json['description']) || empty(trim($plugin_json['description']))) {
self::$warnings[] = 'Plugin "description" tag is not set.';
self::$error = 'Plugin "name" tag is not set.';
return false;
}
if(!isset($plugin_json['version']) || empty(trim($plugin_json['version']))) {
self::$warnings[] = 'Plugin "version" tag is not set.';
}
if(!isset($plugin_json['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'])) {
$require = $plugin_json['require'];
@@ -631,6 +704,7 @@ class Plugins {
return false;
}
clearCache();
return true;
}
@@ -675,26 +749,41 @@ class Plugins {
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';
if(!file_exists($filename)) {
self::$error = 'Plugin ' . $plugin_name . ' does not exist.';
$revertEnable();
return false;
}
$string = file_get_contents($filename);
$plugin_info = json_decode($string, true);
if(!$plugin_info) {
self::$error = 'Cannot load plugin info ' . $plugin_name . '.json';
$revertEnable();
return false;
}
if(!isset($plugin_info['uninstall'])) {
self::$error = "Plugin doesn't have uninstall options defined. Skipping...";
$revertEnable();
return false;
}
$success = true;
foreach($plugin_info['uninstall'] as $file) {
if(strpos($file, '/') === 0) {
if(str_starts_with($file, '/')) {
$success = false;
self::$error = "You cannot use absolute paths (starting with slash - '/'): " . $file;
break;
@@ -709,24 +798,19 @@ class Plugins {
}
}
if($success) {
foreach($plugin_info['uninstall'] as $file) {
if(!deleteDirectory(BASE . $file)) {
self::$warnings[] = 'Cannot delete: ' . $file;
}
}
$cache = Cache::getInstance();
if($cache->enabled()) {
$cache->delete('templates');
$cache->delete('hooks');
$cache->delete('template_menus');
}
return true;
if(!$success) {
$revertEnable();
return false;
}
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

View File

@@ -72,24 +72,32 @@ class Settings implements \ArrayAccess
}
}
$this->errors = [];
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;
}
global $db;
try {
$db->beginTransaction();
$this->errors = [];
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([
'name' => $pluginName,
'key' => $key,
'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();
@@ -211,7 +219,7 @@ class Settings implements \ArrayAccess
if ($setting['type'] === 'boolean') {
$value = ($setting['default'] ? 'true' : 'false');
}
else if (in_array($setting['type'], ['text', 'number', 'email', 'password', 'textarea'])) {
else if (in_array($setting['type'], ['text', 'number', 'float', 'double', 'email', 'password', 'textarea'])) {
$value = $setting['default'];
}
else if ($setting['type'] === 'options') {
@@ -237,7 +245,11 @@ class Settings implements \ArrayAccess
$checkbox($key, false, $value);
}
else if (in_array($setting['type'], ['text', 'number', 'email', 'password'])) {
else if (in_array($setting['type'], ['text', 'number', 'float', 'double', 'email', 'password'])) {
if (in_array($setting['type'], ['float', 'double'])) {
$setting['type'] = 'number';
}
if ($setting['type'] === 'number') {
$min = (isset($setting['min']) ? ' min="' . $setting['min'] . '"' : '');
$max = (isset($setting['max']) ? ' max="' . $setting['max'] . '"' : '');
@@ -247,7 +259,15 @@ class Settings implements \ArrayAccess
$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 . '/>';
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') {
@@ -335,7 +355,7 @@ class Settings implements \ArrayAccess
if ($setting['type'] === 'boolean') {
echo ($setting['default'] ? 'Yes' : 'No');
}
else if (in_array($setting['type'], ['text', 'number', 'email', 'password', 'textarea'])) {
else if (in_array($setting['type'], ['text', 'number', 'float', 'double', 'email', 'password', 'textarea'])) {
echo $setting['default'];
}
else if ($setting['type'] === 'options') {
@@ -482,9 +502,12 @@ class Settings implements \ArrayAccess
break;
case 'number':
if (!isset($ret['step']) || (int)$ret['step'] == 1) {
$ret['value'] = (int)$ret['value'];
}
$ret['value'] = (int)$ret['value'];
break;
case 'double':
case 'float':
$ret['value'] = (double)($ret['value']);
break;
default:

View File

@@ -0,0 +1,28 @@
<?php
namespace MyAAC\Twig;
use Twig\Environment;
class EnvironmentBridge extends Environment
{
public function display($name, array $context = []): void
{
global $hooks;
$context['viewName'] = $name;
$hooks->triggerFilter(HOOK_FILTER_TWIG_DISPLAY, $context);
parent::display($name, $context);
}
public function render($name, array $context = []): string
{
global $hooks;
$context['viewName'] = $name;
$hooks->triggerFilter(HOOK_FILTER_TWIG_RENDER, $context);
return parent::render($name, $context);
}
}

View File

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

View File

@@ -41,7 +41,7 @@ if(setting('core.template_allow_change'))
}
else {
$template_session = getSession('template');
if ($template_session !== false) {
if ($template_session) {
if (!preg_match("/[^A-z0-9_\-]/", $template_session)) {
$template_name = $template_session;
}
@@ -95,7 +95,7 @@ else {
unset($file);
if ($cache->enabled()) {
$cache->set('template_ini_' . $template_name, serialize($template_ini));
$cache->set('template_ini_' . $template_name, serialize($template_ini), 10 * 60);
}
}
}
@@ -133,46 +133,65 @@ if($forumSetting != '')
$template['link_forum'] = "<a href='" . $forumSetting . "' target='_blank'>";
}
$twig->addGlobal('template_name', $template_name);
$twig->addGlobal('template_path', $template_path);
if($twig_loader) {
$viewsPath = BASE . $template_path . '/views';
if (is_dir($viewsPath)) {
$twig_loader->prependPath($viewsPath);
}
$twig_loader->prependPath(BASE . $template_path);
}
function get_template_menus() {
function get_template_menus(): array
{
global $template_name;
$cache = Cache::getInstance();
if ($cache->enabled()) {
$tmp = '';
if ($cache->fetch('template_menus', $tmp)) {
$result = unserialize($tmp);
}
}
if (!isset($result)) {
$result = Cache::remember('template_menus', 10 * 60, function () use ($template_name) {
$result = Menu::select(['name', 'link', 'blank', 'color', 'category'])
->where('template', $template_name)
->orderBy('category')
->orderBy('ordering')
->get();
if ($cache->enabled()) {
$cache->set('template_menus', serialize($result->toArray()), 600);
}
}
return $result->toArray();
});
$menus = array();
$configMenuCategories = config('menu_categories');
$configMenuDefaultColor = config('menu_default_links_color') ?? config('menu_default_color');
$menus = [];
foreach($result as $menu) {
$link_full = strpos(trim($menu['link']), 'http') === 0 ? $menu['link'] : getLink($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']);
if (empty($menu['link'])) {
$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
*/
$configMenuCategories = config('menu_categories');
if($configMenuCategories === null) {
return [];
}

View File

@@ -24,21 +24,28 @@ Please enter your account {{ account|lower }} and your password.<br/><a href="{{
<td>
<div class="InnerTableContainer">
<table style="width:100%;" >
{{ hook('HOOK_ACCOUNT_LOGIN_BEFORE_PASSWORD') }}
{{ hook('HOOK_ACCOUNT_LOGIN_BEFORE_ACCOUNT') }}
<tr>
<td class="LabelV" >
<span{% if error is not null %} class="red"{% endif %}>{{ account_login_by }}:</span>
</td>
<td style="width:100%;" ><input type="text" name="account_login" size="30" maxlength="{{ setting('core.account_login_by_email') ? '255' : '30' }}" autofocus/></td>
</tr>
{{ hook('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT') }}
{{ hook('HOOK_ACCOUNT_LOGIN_BEFORE_PASSWORD') }}
<tr>
<td class="LabelV" >
<span{% if error is not null %} class="red"{% endif %}>Password:</span>
</td>
<td><input type="password" name="password_login" size="30" maxlength="29" ></td>
</tr>
{{ hook('HOOK_ACCOUNT_LOGIN_AFTER_PASSWORD') }}
<tr>
<td class="LabelV" ></td>
<td><input type="checkbox" id="remember_me" name="remember_me" value="true" />

View File

@@ -110,7 +110,7 @@ html { margin-top: 32px !important; }
<form method="post" action="{{ constant('ADMIN_URL') }}?p=dashboard">
{{ csrf() }}
<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>
</li>
</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,43 @@
<link type="text/css" rel="stylesheet" href="{{ constant('BASE_URL') }}tools/ext/jquery-ui/themes/base/jquery-ui.min.css">
<script>
var last_id = [];
{% for cat, menu in menus %}
last_id[{{ cat }}] = {{ last_id[cat] }};
{% endfor %}
$(function () {
$(".sortable").sortable();
$(".sortable").disableSelection();
let last_id = [];
let colors = [];
$(".remove-button").click(function () {
{% for cat, menu in menus %}
{% if config('menu_categories')[cat] is not empty %}
last_id[{{ cat }}] = {{ last_id[cat] }};
{% endif %}
{% endfor %}
{% 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");
$('#list-' + id.replace('remove-button-', '')).remove();
});
$(".add-button").click(function () {
$(".add-button").on('click', function () {
var cat = $(this).attr("id").replace('add-button-', '');
var id = 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
$('#remove-button-' + cat + '-' + id).click(function () {
const color = colors[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="#' + 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();
});
initialiceSpectrum();
initializeSpectrum();
});
$("#menus-form").submit(function (e) {
$("#menus-form").on('submit', function (e) {
$('.blank-checkbox:not(:checked)').each(function (i, obj) {
$(obj).parent().prev().val("off");
});
@@ -52,11 +64,11 @@
<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"/>
<script type="text/javascript">
$(document).ready(function () {
initialiceSpectrum();
$(function () {
initializeSpectrum();
});
function initialiceSpectrum() {
function initializeSpectrum() {
$(".color-picker").spectrum({
preferredFormat: "hex",
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();
$.ajax({
@@ -94,6 +113,13 @@
duration: 3000,
escapeMarkup: false,
}).showToast();
let $settings = $('#settings');
$settings.data('serialized', $settings.serialize());
$settings
.find('input:submit, button:submit')
.prop('disabled', true)
.prop('title', noChangesText);
},
error : function(response) {
Toastify({
@@ -109,3 +135,27 @@
});
});
</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

@@ -50,7 +50,7 @@
<table width="100%">
<tr bgcolor="{{ config.vdarkborder }}">
<td colspan="2">
<span style="color: white"><b>Last 5 posts from thread: {{ topic|raw }}</b></span>
<span style="color: white"><b>Last 5 posts from thread: {{ topic }}</b></span>
</td>
</tr>
{% set i = 0 %}

View File

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

View File

@@ -79,57 +79,59 @@
</tr>
{% set showedRank, i = false, 0 %}
{% for rank in guild_members if rank.members|length > 0 %}
{% set rankStyle, i = getStyle(i), i + 1 %}
{% for rank in guild_members %}
{% if rank.members|length > 0 %}
{% set rankStyle, i = getStyle(i), i + 1 %}
{% for player in rank.members %}
<tr bgcolor="{{ rankStyle }}">
<td>
{% if not showedRank %}{{ rank.rank_name }}{% endif %}
{% set showedRank = true %}
</td>
{% for player in rank.members %}
<tr bgcolor="{{ rankStyle }}">
<td>
{% if not showedRank %}{{ rank.rank_name }}{% endif %}
{% set showedRank = true %}
</td>
<td>
{% set playerName = player.getName() %}
<form action="{{ getLink('guilds') }}?action=change_nick&name={{ playerName }}&guild={{ guild_name }}" method="post">
{{ csrf() }}
{{ getPlayerLink(playerName, true)|raw }}
<td>
{% set playerName = player.getName() %}
<form action="{{ getLink('guilds') }}?action=change_nick&name={{ playerName }}&guild={{ guild_name }}" method="post">
{{ csrf() }}
{{ getPlayerLink(playerName, true)|raw }}
{% set showGuildNick = false %}
{% if player.getGuildNick() is not empty %}
{% set showGuildNick = true %}
{% set guildNickRaw = player.getGuildNick()|raw %}
{% endif %}
{% set showGuildNick = false %}
{% if player.getGuildNick() is not empty %}
{% set showGuildNick = true %}
{% set guildNickRaw = player.getGuildNick()|raw %}
{% endif %}
{% if logged %}
{% if player.getId() in players_from_account_ids %}
(<input type="text" name="nick" value="{{ guildNickRaw }}"><input type="submit" value="Change">)
{% if logged %}
{% if player.getId() in players_from_account_ids %}
(<input type="text" name="nick" value="{{ guildNickRaw }}"><input type="submit" value="Change">)
{% else %}
{% if showGuildNick %} ({{ guildNickRaw }}){% endif %}
{% endif %}
{% if level_in_guild > rank.rank_level or isLeader %}
{% if guildOwnerName != playerName %}
<span style="font-size: 10px; float: right">
{<a href="{{ getLink('guilds') }}?action=kick_player&guild={{ guild_name|url_encode }}&name={{ playerName|url_encode }}">KICK</a>}
</span>
{% endif %}
{% endif %}
{% else %}
{% if showGuildNick %} ({{ guildNickRaw }}){% endif %}
{% endif %}
</form>
</td>
{% if level_in_guild > rank.rank_level or isLeader %}
{% if guildOwnerName != playerName %}
<span style="font-size: 10px; float: right">
{<a href="{{ getLink('guilds') }}?action=kick_player&guild={{ guild_name|url_encode }}&name={{ playerName|url_encode }}">KICK</a>}
</span>
{% endif %}
{% endif %}
{% else %}
{% if showGuildNick %} ({{ guildNickRaw }}){% endif %}
{% endif %}
</form>
</td>
<td>{{ player.getVocationName() }}</td>
<td>{{ player.getLevel() }}</td>
<td>
<span style="color: {% if player.isOnline() %} green;"><b>Online{% else %} red;"><b>Offline{% endif %}</b></span>
</td>
</tr>
{% endfor %}
<td>{{ player.getVocationName() }}</td>
<td>{{ player.getLevel() }}</td>
<td>
<span style="color: {% if player.isOnline() %} green;"><b>Online{% else %} red;"><b>Offline{% endif %}</b></span>
</td>
</tr>
{% endfor %}
{% set showedRank = false %}
{% set showedRank = false %}
{% endif %}
{% else %}
<tr bgcolor="{{ getStyle(i) }}">
<td colspan="5">No guild members found.</td>
@@ -162,7 +164,7 @@
</tr>
{% set i = 0 %}
{% for invited_player in invited_list if invited_list|length > 0 %}
{% for invited_player in invited_list %}
{% if invited_player.isLoaded() %}
<tr bgcolor="{{ getStyle(i) }}">
{% set i = i + 1 %}
@@ -213,7 +215,7 @@
<tbody>
<tr>
{% 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() }}
<td>
{{ include('buttons.login.html.twig') }}

View File

@@ -9,19 +9,17 @@
<td>
<label for="skillFilter">Choose a Skill</label>
<select onchange="location = this.value;" id="skillFilter">
{% set i = 0 %}
{% 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 %}
</select>
</td>
<td>
<label for="vocationFilter">Choose a vocation</label>
<select onchange="location = this.value;" id="vocationFilter">
<option value="{{ getLink('highscores') }}/{{ list }}" class="size_xs">[ALL]</option>
{% set i = 0 %}
<option value="{{ getLink('highscores') }}/{{ list|urlencode }}" class="size_xs">[ALL]</option>
{% 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 %}
</select>
</td>
@@ -105,7 +103,7 @@
<tr bgcolor="{{ config.lightborder }}">
<td>
{% 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 %}
</td>
</tr>
@@ -118,9 +116,9 @@
</tr>
<tr bgcolor="{{ config.lightborder }}">
<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 %}
<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 %}
</td>
</tr>

View File

@@ -56,10 +56,9 @@ the search criteria and start a new search.
</td>
<td>
<form action="{{ getLink('houses/view') }}" method="post">
<input type="hidden" name="house" value="{{ house.name }}">
<a href="{{ house.link }}">
{{ include('buttons.view.html.twig') }}
</form>
</a>
</td>
</tr>
{% endfor %}
@@ -85,17 +84,19 @@ the search criteria and start a new search.
<tr bgcolor="{{ config.darkborder }}">
<td valign="top" rowspan="2">
{% set checked = false %}
{% for id, name in config.towns if id > 0 %}
{% if ((townId is empty and name is not empty) or id == townId) and not checked %}
{% set variable = "checked" %}
{% set checked = true %}
{% else %}
{% set variable = "" %}
{% endif %}
{% for id, name in config.towns %}
{% if id > 0 %}
{% if ((townId is empty and name is not empty) or id == townId) and not checked %}
{% set variable = "checked" %}
{% set checked = true %}
{% else %}
{% set variable = "" %}
{% endif %}
<input type="radio" name="town" id="town_{{ id }}" value="{{ id }}"{% if variable is defined %} {{ variable }}{% endif %}>
<label for="town_{{ id }}"> {{ name }}</label>
<br>
<input type="radio" name="town" id="town_{{ id }}" value="{{ id }}"{% if variable is defined %} {{ variable }}{% endif %}>
<label for="town_{{ id }}"> {{ name }}</label>
<br>
{% endif %}
{% endfor %}
</td>

View File

@@ -10,13 +10,9 @@
<input type="hidden" name="step" id="step" value="database" />
{% for value in ['server_path'] %}
{% if value == 'server_path' and config.server_path is not null %}
{% set server_path = { 'var_server_path': config.server_path } %}
{% set session = session | merge (server_path) %}
{% endif %}
<div class="form-group mb-2">
<label for="vars_{{ value }}">{{ locale['step_config_' ~ value] }}</label>
<input class="form-control" type="text" name="vars[{{ value }}]" id="vars_{{ value }}"{% if session['var_' ~ value] is not null %} value="{{ session['var_' ~ value] }}"{% endif %}/>
<input class="form-control" type="{% if value == 'mail_admin' %}email{% else %}text{% endif %}" name="vars[{{ value }}]" id="vars_{{ value }}"{% if session['var_' ~ value] is not null %} value="{{ session['var_' ~ value] }}"{% endif %}/>
<small class="form-text text-muted">{{ locale['step_config_' ~ value ~ '_desc'] }}</small>
</div>
{% endfor %}

View File

@@ -9,8 +9,7 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
use MyAAC\CsrfToken;
use Twig\Environment as Twig_Environment;
use MyAAC\Twig\EnvironmentBridge as MyAAC_Twig_EnvironmentBridge;
use Twig\Extension\DebugExtension as Twig_DebugExtension;
use Twig\Loader\FilesystemLoader as Twig_FilesystemLoader;
use Twig\TwigFilter;
@@ -20,7 +19,7 @@ global $twig, $twig_loader;
$dev_mode = (config('env') === 'dev');
$twig_loader = new Twig_FilesystemLoader(SYSTEM . 'templates');
$twig = new Twig_Environment($twig_loader, array(
$twig = new MyAAC_Twig_EnvironmentBridge($twig_loader, array(
'cache' => CACHE . 'twig/',
'auto_reload' => $dev_mode,
'debug' => $dev_mode
@@ -140,6 +139,11 @@ $function = new TwigFunction('csrfToken', function () {
});
$twig->addFunction($function);
$function = new TwigFunction('session', function ($key) {
return session($key);
});
$twig->addFunction($function);
$filter = new TwigFilter('urlencode', function ($s) {
return urlencode($s);
});

View File

@@ -1,5 +1,5 @@
<?php
$config['menu_default_color'] = '#ffffff';
$config['menu_default_links_color'] = '#ffffff';
$config['menu_categories'] = array(
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_SHOP => array('id' => 'shops', 'name' => 'Shop')
);
$config['menus'] = require __DIR__ . '/menus.php';

Some files were not shown because too many files have changed in this diff Show More