Compare commits
194 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a113ee72a | ||
|
|
8d78e7090d | ||
|
|
fd457b2fe8 | ||
|
|
108e83806d | ||
|
|
85e8d4d9af | ||
|
|
9d6287ecbc | ||
|
|
16f4cdf40a | ||
|
|
9fa9ec746c | ||
|
|
3e7ee12676 | ||
|
|
b435a2fba4 | ||
|
|
d91de1005b | ||
|
|
88ea9ceee1 | ||
|
|
a92428287d | ||
|
|
c753feeeb0 | ||
|
|
9c8a78a386 | ||
|
|
e33e86053d | ||
|
|
6db738a87c | ||
|
|
e52d9e486f | ||
|
|
6859b86f28 | ||
|
|
c472d5e473 | ||
|
|
e8b47429e8 | ||
|
|
ff4b15ad1d | ||
|
|
c2415e9df3 | ||
|
|
eaa8d9346e | ||
|
|
3e2d4d6686 | ||
|
|
5e4806f891 | ||
|
|
8dcbb66753 | ||
|
|
87509ffe16 | ||
|
|
8d7c36e3eb | ||
|
|
7916cfa85f | ||
|
|
21e6812cf2 | ||
|
|
1edb4743fe | ||
|
|
e3efbdc5a8 | ||
|
|
d4cc47e341 | ||
|
|
5040a93031 | ||
|
|
173b1ace88 | ||
|
|
276aa600e2 | ||
|
|
8103f5e70f | ||
|
|
6661c78dac | ||
|
|
8632cd3191 | ||
|
|
8b6f160a0f | ||
|
|
a60a23b84f | ||
|
|
f640ca636f | ||
|
|
5b841682cd | ||
|
|
c3036e7d49 | ||
|
|
0c4edf625c | ||
|
|
c28dc29391 | ||
|
|
2db4f6a57b | ||
|
|
9bfd0242af | ||
|
|
3ea2b68561 | ||
|
|
dcdaa5ef43 | ||
|
|
7289cce826 | ||
|
|
af9d4c2aeb | ||
|
|
a66edfad31 | ||
|
|
89a35b5335 | ||
|
|
3d6e4c074a | ||
|
|
55da00520d | ||
|
|
efef16ee86 | ||
|
|
2f0b67f840 | ||
|
|
c65d4e4b62 | ||
|
|
fec3f3d297 | ||
|
|
7e6480b380 | ||
|
|
7c9c8d2990 | ||
|
|
ca2e3bb576 | ||
|
|
2d8d35f5c8 | ||
|
|
aba50ca0f1 | ||
|
|
0110bf6ea2 | ||
|
|
ba1c63921d | ||
|
|
5c68fba82a | ||
|
|
18c0212f9a | ||
|
|
e0e0e46701 | ||
|
|
61bcdc0c37 | ||
|
|
6f87d8b322 | ||
|
|
cc220bedc1 | ||
|
|
f966dff5a8 | ||
|
|
402f3bb9b0 | ||
|
|
e98de451d8 | ||
|
|
8ec9bf1068 | ||
|
|
4fffaf6aff | ||
|
|
c44c9f9cf4 | ||
|
|
ccfd6f1a87 | ||
|
|
96b8e00f49 | ||
|
|
11cb1cf97e | ||
|
|
78a3535b6a | ||
|
|
497959fd30 | ||
|
|
6ba00eea96 | ||
|
|
c5d3d3a25f | ||
|
|
9ed06782e6 | ||
|
|
18a1178e4b | ||
|
|
c86257e6da | ||
|
|
fd74f01291 | ||
|
|
3011b969a4 | ||
|
|
8e6749c599 | ||
|
|
e1197515f3 | ||
|
|
ae5df2b704 | ||
|
|
9c327336d3 | ||
|
|
1d21f4d682 | ||
|
|
603d860b56 | ||
|
|
6775a061be | ||
|
|
eebfc600cb | ||
|
|
9a99018dce | ||
|
|
e440c0d6a6 | ||
|
|
780d4ccef7 | ||
|
|
0a6d44bf21 | ||
|
|
4d17001a0b | ||
|
|
946364f59d | ||
|
|
5861efdbe9 | ||
|
|
175e97828b | ||
|
|
9ce55db44c | ||
|
|
88532b0ebb | ||
|
|
1c7af30997 | ||
|
|
7ca05e47ff | ||
|
|
baec6c9ebf | ||
|
|
6367054487 | ||
|
|
ae7a47464f | ||
|
|
d201e75b11 | ||
|
|
4924696943 | ||
|
|
25a3db68e6 | ||
|
|
730a0f2912 | ||
|
|
fd729242ff | ||
|
|
6479546c22 | ||
|
|
effb23f367 | ||
|
|
08657c1599 | ||
|
|
1379c93439 | ||
|
|
19b1cfdd34 | ||
|
|
26c5aa2e51 | ||
|
|
bc4107bd16 | ||
|
|
d24bde2c1d | ||
|
|
a2f8759a52 | ||
|
|
4b8c3ffae2 | ||
|
|
97321c9e80 | ||
|
|
2580edadf8 | ||
|
|
8f47b36dc8 | ||
|
|
6cd38ee1ec | ||
|
|
9d92a11fb7 | ||
|
|
44110a9496 | ||
|
|
727f68a575 | ||
|
|
07fd034fe4 | ||
|
|
13ea68cc0c | ||
|
|
598cec2fe4 | ||
|
|
89fae38caa | ||
|
|
16849e7578 | ||
|
|
470555f268 | ||
|
|
7f60b3d31d | ||
|
|
12e40b2592 | ||
|
|
38902c30d1 | ||
|
|
3e61692780 | ||
|
|
c88b08eb1e | ||
|
|
82d417b590 | ||
|
|
b797908e49 | ||
|
|
90c8463797 | ||
|
|
c91bb5d409 | ||
|
|
fe821c5808 | ||
|
|
9acad15451 | ||
|
|
8c3cb0e06f | ||
|
|
2eae44e075 | ||
|
|
8272f1373c | ||
|
|
901df48d13 | ||
|
|
2da0024c68 | ||
|
|
0d8f68a48e | ||
|
|
0cb9d3a208 | ||
|
|
d8b73f55a3 | ||
|
|
3bb272ebbb | ||
|
|
64acf70d38 | ||
|
|
97f9d3d6f6 | ||
|
|
f54b1bdd2a | ||
|
|
c898fe25ef | ||
|
|
73c07d470d | ||
|
|
56bd7ec5ed | ||
|
|
4c6277c124 | ||
|
|
228780f0ad | ||
|
|
4e9999cc0d | ||
|
|
e719725841 | ||
|
|
bb3e90110d | ||
|
|
2f0758e351 | ||
|
|
6667c8c364 | ||
|
|
c13a540878 | ||
|
|
869ec035d9 | ||
|
|
9d696d31d8 | ||
|
|
8cc4caf587 | ||
|
|
e1d1c7d5db | ||
|
|
320733c2c1 | ||
|
|
c1809a98d1 | ||
|
|
46ed541015 | ||
|
|
29207361b7 | ||
|
|
25013ae91b | ||
|
|
5d630ba9dd | ||
|
|
feadf1314d | ||
|
|
08b8a716d4 | ||
|
|
cc26b5c744 | ||
|
|
cb6e9a6a88 | ||
|
|
4adb0758c5 | ||
|
|
7312383f73 | ||
|
|
3c1210fefa |
49
.github/workflows/cypress.yml
vendored
@@ -1,9 +1,9 @@
|
||||
name: Cypress
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches: [develop]
|
||||
push:
|
||||
branches: [main]
|
||||
branches: [develop]
|
||||
|
||||
jobs:
|
||||
cypress:
|
||||
@@ -22,8 +22,8 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
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)
|
||||
php-versions: [ '8.1', '8.2', '8.3', '8.4', '8.5' ]
|
||||
ots: ['tfs-1.4', 'canary-3.1.2', 'tfs-0.3'] # 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:
|
||||
- name: 📌 MySQL Start & init & show db
|
||||
@@ -58,6 +58,14 @@ jobs:
|
||||
ref: master
|
||||
path: ots
|
||||
|
||||
- name: Checkout TFS 0.3
|
||||
uses: actions/checkout@v4
|
||||
if: matrix.ots == 'tfs-0.3'
|
||||
with:
|
||||
repository: otland/tfs-old-svn
|
||||
ref: 0.3
|
||||
path: ots
|
||||
|
||||
- name: Checkout Canary
|
||||
uses: actions/checkout@v4
|
||||
if: matrix.ots == 'canary-3.1.2'
|
||||
@@ -67,9 +75,15 @@ jobs:
|
||||
path: ots
|
||||
|
||||
- name: Import OTS Schema
|
||||
if: matrix.ots != 'tfs-0.3'
|
||||
run: |
|
||||
mysql -uroot -proot myaac < ots/schema.sql
|
||||
|
||||
- name: Import OTS Schema (TFS 0.3)
|
||||
if: matrix.ots == 'tfs-0.3'
|
||||
run: |
|
||||
mysql -uroot -proot myaac < ots/schemas/mysql.sql
|
||||
|
||||
- name: Rename config.lua
|
||||
run: mv ots/config.lua.dist ots/config.lua
|
||||
|
||||
@@ -109,6 +123,33 @@ jobs:
|
||||
regex: false
|
||||
include: 'ots/config.lua'
|
||||
|
||||
- name: Replace mysqlPass (TFS 0.3.6pl1)
|
||||
uses: jacobtomlinson/gha-find-replace@v3
|
||||
if: matrix.ots == 'tfs-0.3'
|
||||
with:
|
||||
find: 'sqlType = "sqlite"'
|
||||
replace: 'sqlType = "mysql"'
|
||||
regex: false
|
||||
include: 'ots/config.lua'
|
||||
|
||||
- name: Replace mysqlPass (TFS 0.3.6pl1)
|
||||
uses: jacobtomlinson/gha-find-replace@v3
|
||||
if: matrix.ots == 'tfs-0.3'
|
||||
with:
|
||||
find: 'sqlPass = ""'
|
||||
replace: 'sqlPass = "root"'
|
||||
regex: false
|
||||
include: 'ots/config.lua'
|
||||
|
||||
- name: Replace mysqlDatabase (Canary)
|
||||
uses: jacobtomlinson/gha-find-replace@v3
|
||||
if: matrix.ots == 'tfs-0.3'
|
||||
with:
|
||||
find: 'sqlDatabase = "theforgottenserver"'
|
||||
replace: 'sqlDatabase = "myaac"'
|
||||
regex: false
|
||||
include: 'ots/config.lua'
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
|
||||
4
.github/workflows/phplint.yml
vendored
@@ -1,9 +1,9 @@
|
||||
name: PHP Linting
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches: [develop]
|
||||
push:
|
||||
branches: [main]
|
||||
branches: [develop]
|
||||
|
||||
jobs:
|
||||
phplint:
|
||||
|
||||
8
.github/workflows/phpstan.yml
vendored
@@ -2,9 +2,9 @@ name: "PHPStan"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches: [develop]
|
||||
push:
|
||||
branches: [main]
|
||||
branches: [develop]
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php-versions: [ '8.1', '8.2', '8.3', '8.4' ]
|
||||
php-versions: [ '8.1', '8.2', '8.3', '8.4', '8.5' ]
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
uses: "actions/checkout@v4"
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
coverage: "none"
|
||||
extensions: "intl, zip"
|
||||
ini-values: "memory_limit=-1"
|
||||
php-version: "${{ matrix.php-version }}"
|
||||
php-version: "${{ matrix.php-versions }}"
|
||||
|
||||
- name: Get composer cache directory
|
||||
id: composer-cache
|
||||
|
||||
3
.gitignore
vendored
@@ -4,7 +4,7 @@ Thumbs.db
|
||||
|
||||
#
|
||||
/.htaccess
|
||||
lua
|
||||
/lua
|
||||
|
||||
# composer
|
||||
composer.phar
|
||||
@@ -24,6 +24,7 @@ releases
|
||||
tmp
|
||||
|
||||
config.local.php
|
||||
config2.local.php
|
||||
|
||||
# all custom templates
|
||||
templates/*
|
||||
|
||||
@@ -1,5 +1,97 @@
|
||||
# Changelog
|
||||
|
||||
## [1.8.8 - 31.01.2026]
|
||||
### Added
|
||||
* Change Comment: Add missing hooks - patched from 0.8 (https://github.com/slawkens/myaac/commit/a60a23b84f61d41d1503073b52e01e3120f6d92a)
|
||||
|
||||
### Changed
|
||||
* Account Manage: Change the last login to the correct login time – Instead of just "now" (https://github.com/slawkens/myaac/commit/5b841682cdc473b38ef1a5edfcfe1a020802e286)
|
||||
* Twig: Extract renderInline(content, context) as a method to $twig (https://github.com/slawkens/myaac/commit/5e4806f891f8c88c37d45b89bbede23afc2fa37b)
|
||||
* Mail: Remove HTML tags from the email function (https://github.com/slawkens/myaac/commit/6661c78dac69c6aa498b9c79fe7da4fe0150e5c8)
|
||||
|
||||
### Fixed
|
||||
* Forum: Fix XSS in board name (https://github.com/slawkens/myaac/commit/e52d9e486f5bf1dea867f59287f70aef3d538189, https://github.com/slawkens/myaac/commit/6db738a87c44b8d96919191ba5e661c32ab47457)
|
||||
* Forum: Fix edit_post, despite being an author, edit didn't work (https://github.com/slawkens/myaac/commit/e8b47429e8c607c2662a78b65415dfa772aa0e48)
|
||||
* Forum: Fix a player link in the forum thread being not clickable (When outfits are enabled) (https://github.com/slawkens/myaac/commit/f640ca636f34cd2dfc1fa8de6fdbed0674908b30)
|
||||
* Settings: Fix variable overlapping if the same var name as in core (https://github.com/slawkens/myaac/commit/c2415e9df3a5ffaf768f6f9668bdd38b5efd0771)
|
||||
* Settings: fix show_if for the selects (https://github.com/slawkens/myaac/commit/8dcbb66753914322706216cfd01436eb1478a5ce)
|
||||
|
||||
## [1.8.7 - 04.01.2026]
|
||||
|
||||
### Fixed
|
||||
* Fixed [player/guild/house] bb code in forum (https://github.com/slawkens/myaac/commit/8ec9bf10682c73f1fe40967a106ccda2a5073ed0)
|
||||
|
||||
### Changed
|
||||
* Settings: better responsiveness on mobile (https://github.com/slawkens/myaac/commit/c65d4e4b62ef26fb4e24ecb1d2bcc4556d746adf)
|
||||
* Signatures: Return 404 when the signature player is not found (https://github.com/slawkens/myaac/commit/7e6480b380799add7a2b1b7ce1d3c1f2b6819ff1)
|
||||
|
||||
### Removed
|
||||
* Remove setting: outfit_images_wrong_looktypes - is obsolete, the bug doesn't exist in the latest outfit images (https://github.com/slawkens/myaac/commit/cc220bedc1f01535eaac23f6961135e2e7a6e310)
|
||||
|
||||
## [1.8.6 - 14.12.2025]
|
||||
|
||||
### Added
|
||||
* Added hook for adding custom rules to validate new character name (https://github.com/slawkens/myaac/commit/8e6749c59984631288e8e9803819b2f0ff389761)
|
||||
|
||||
### Fixed
|
||||
* Highscores: Fix ordering by different skills (Adjust order by desc: skill_tries, manaspent, experience) - More exact results (https://github.com/slawkens/myaac/commit/c86257e6dacbad773aa09c0958eeaa106a967f2d)
|
||||
* Fix exception shown on first install, when there is no vendor - Before it displayed 500 white page, now it display the exception (https://github.com/slawkens/myaac/commit/18a1178e4b93607a350259679e0366cb83fb4126)
|
||||
* Fix typo $up -> $down, in migration nr 7, was failing due that (https://github.com/slawkens/myaac/commit/fd74f01291d0e9cdb92ee1b95021c9d7b591ad7c)
|
||||
|
||||
### Changed
|
||||
* Ini set html_errors = 0, to show html code in exceptions (https://github.com/slawkens/myaac/commit/9ed06782e67772826d927ad847a077b99df5060d)
|
||||
|
||||
## [1.8.5 - 21.11.2025]
|
||||
|
||||
### Added
|
||||
* New Setting: Account Countries Most Popular (https://github.com/slawkens/myaac/commit/946364f59d7cd01472877108ab27ec78fb28307a)
|
||||
|
||||
### Changed
|
||||
* Status: Write to status-error.log if there is connection error (https://github.com/slawkens/myaac/commit/780d4ccef741c1dd45a00bfc121fba9f1a175313)
|
||||
* Settings: escapeHtml in values (support for html code) (https://github.com/slawkens/myaac/commit/5861efdbe900ccd35309913af0c0a5f3d4cdc1a8)
|
||||
* News Page: Don't display hidden news for admin - it's confusing (https://github.com/slawkens/myaac/commit/175e97828b9a08ec3080cc8d3fb4eb3f1c08649f)
|
||||
* Plugins System: Add plugin:remove + plugin:delete as alias for plugin:uninstall + plugin:activate/deactivate (https://github.com/slawkens/myaac/commit/6367054487368c92741bfd1dc7c70c52aea9ee87, https://github.com/slawkens/myaac/commit/baec6c9ebf5c342b3b2f7123427c6ba21dbb93bc)
|
||||
|
||||
### Fixed
|
||||
* Status: Fix $status['uptimeReadable'], was totally wrong (https://github.com/slawkens/myaac/commit/0a6d44bf21417562491aabc93543a2bc3a44b2df)
|
||||
* Guilds: Detect "deletion" column in guilds show/delete (https://github.com/slawkens/myaac/commit/6775a061bebc9ff449522f0173556d4a7a44fa5e, https://github.com/slawkens/myaac/commit/603d860b56bc7418db09e206f40aa06d0682c00e)
|
||||
* General: Ensure some cache folders & index.html exists (https://github.com/slawkens/myaac/commit/730a0f29124811f525207c24c06eb0d088fa3434)
|
||||
|
||||
## [1.8.4 - 27.10.2025]
|
||||
|
||||
### Changed
|
||||
* Reimport myaac_ tables on every install, this fixes errors when one table is missing or is duplicated (https://github.com/slawkens/myaac/commit/2580edadf84779f09fd395c21f92019b2c762f83)
|
||||
* Use custom env init on migrate, migrate:run and migrate:to (https://github.com/slawkens/myaac/commit/13ea68cc0c9349380c8e4051d702a6c2c8256f44, https://github.com/slawkens/myaac/commit/07fd034fe4cb0ffdb88667b1e400f414d0c6d06f)
|
||||
|
||||
### Fixed
|
||||
* Show if there is mysql error on import schema (https://github.com/slawkens/myaac/commit/44110a9496b4385e42c31b75de301037e711b6c3)
|
||||
* Fix the premium checks, introduced in v1.8.3 (https://github.com/slawkens/myaac/commit/9d92a11fb7cb6d7a1619d79c12faaa0b1c01f980)
|
||||
|
||||
## [1.8.3 - 21.10.2025]
|
||||
|
||||
### Added
|
||||
* Feature: resend email verify (https://github.com/slawkens/myaac/commit/fe821c58085483e70491dcf76376ad5b96de3fdd)
|
||||
* New config: hooks_debug (To view where hooks are located in .twig files) (https://github.com/slawkens/myaac/commit/8c3cb0e06f9709c1de3398b48221241e7cbdd310)
|
||||
* Functions: Add db->getColumnInfo(table, column) (https://github.com/slawkens/myaac/commit/c898fe25efff6793a01d11c26fc153cb23fcb858)
|
||||
* Plugins: Add option to use ?subtopic=x for plugins pages (https://github.com/slawkens/myaac/commit/97f9d3d6f6c28aef6d824973058d7133f56e09c4)
|
||||
* getTopPlayers() Function - Add lookmount & promotion (https://github.com/slawkens/myaac/commit/2da0024c68f1cedc38a16ebbc6f52ffa55e65f7a, https://github.com/slawkens/myaac/commit/901df48d134079d648a18f9d82b60182e818ac02)
|
||||
* New hooks for account/change-password (https://github.com/slawkens/myaac/commit/470555f2687809a0c12491bbb27597e64b8929c1)
|
||||
|
||||
### Changed
|
||||
* Feature: show vip days in account management (https://github.com/slawkens/myaac/commit/c88b08eb1ec1f560cbfdaaa16b24e3a0f26da7b3, by @andreoam)
|
||||
* Allow links in error_box.html.twig (https://github.com/slawkens/myaac/commit/9acad15451071639acf7a7d4e81619b0a9742b12)
|
||||
* Canary - Comment code to update lastday in login.php (https://github.com/slawkens/myaac/commit/38902c30d114fdbce259467f5820f97037b393e9)
|
||||
* Cache::remember $ttl = -1 = infinite (https://github.com/slawkens/myaac/commit/64acf70d3854182d88aaf0b67f77cea2a254f179)
|
||||
|
||||
### Fixed
|
||||
* Online - Allow for html code (example - img) in online_datacenter (https://github.com/slawkens/myaac/commit/3bb272ebbbd2eb7769d174b7082061d14a17bd44)
|
||||
* Guilds - Fix guild create with freePremium enabled (https://github.com/slawkens/myaac/commit/c91bb5d4097647dca2196d3dea87bc90c89181d2)
|
||||
* Canary - Fix premDays count (https://github.com/slawkens/myaac/commit/3e61692780d4add93b7b0e9f12f7a283bd8f4b7a)
|
||||
* Template Change: Ignore set last visit for AJAX pages - Fixes template change redirect (https://github.com/slawkens/myaac/commit/89fae38caa7e4f645957fcf1a9330a36358ac04f)
|
||||
* Admin Panel - Accounts: Fix lastip v6 (TFS master) (https://github.com/slawkens/myaac/commit/f54b1bdd2af4c16c64ddff0e87a6c96bc4cf9eeb)
|
||||
* Functions - Prevent injection in $db->hasColumn (https://github.com/slawkens/myaac/commit/56bd7ec5ed904666074492f2e4f13e4fce226bee)
|
||||
* Compat Config: Add missing config: email_lai_sec_interval (https://github.com/slawkens/myaac/commit/2eae44e0755e624a91be68b4d1ec26d01eb4d9a1)
|
||||
|
||||
## [1.8.2 - 26.09.2025]
|
||||
|
||||
### Added
|
||||
|
||||
21
CHANGELOG-2.x.md
Normal file
@@ -0,0 +1,21 @@
|
||||
## [2.0-dev - x.x.2025]
|
||||
|
||||
### Added
|
||||
* Add an "access" option to Menus (#340)
|
||||
* Possibility to hide menus for unauthorized users
|
||||
* Add the possibility to fetch skills in the getTopPlayers function (#347)
|
||||
|
||||
### Changed
|
||||
* Better handling of vocations: (#345)
|
||||
* Load from vocations.xml (No need to manually set)
|
||||
* Support for Monk vocation
|
||||
* Better gallery, loads images from images/gallery folder
|
||||
* Reworked account action logs to use a single IP column as varchar(45) for both ipv4 and ipv6 (#289)
|
||||
* Admin Panel: save menu collapse state (https://github.com/slawkens/myaac/commit/55da00520df7463a1d1ca41931df1598e9f2ffeb)
|
||||
|
||||
### Internal
|
||||
* Refactor account/lost pages (#326)
|
||||
* Refactor OTS_Player to support more distros (#348)
|
||||
* Refactor PHP cache to store expiration and improve typing (https://github.com/slawkens/myaac/commit/96b8e00f4999f8b4c4c97b54b97d91c6fd7df298)
|
||||
* Move forum show_board code to Twig (https://github.com/slawkens/myaac/commit/e0e0e467012a5fb9979cc4387af6bad1d4540279)
|
||||
* Save db cache only if it has changed (https://github.com/slawkens/myaac/commit/11cb1cf97e74f3bccf59360e1efb800a426b3d43)
|
||||
4
aac
@@ -25,7 +25,9 @@ foreach ($commandsGlob as $item) {
|
||||
}
|
||||
|
||||
$commandPre = '\\MyAAC\Commands\\';
|
||||
$application->add(new ($commandPre . $name));
|
||||
if (!trait_exists($class = $commandPre . $name)) {
|
||||
$application->add(new $class);
|
||||
}
|
||||
}
|
||||
|
||||
$pluginCommands = Plugins::getCommands();
|
||||
|
||||
@@ -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!');
|
||||
@@ -182,39 +183,7 @@ else if (isset($_REQUEST['search'])) {
|
||||
$account->setName($name);
|
||||
}
|
||||
|
||||
if ($hasTypeColumn) {
|
||||
$account->setCustomField('type', $group);
|
||||
} elseif ($hasGroupColumn) {
|
||||
$account->setCustomField('group_id', $group);
|
||||
}
|
||||
|
||||
if ($hasSecretColumn) {
|
||||
$account->setCustomField('secret', $secret);
|
||||
}
|
||||
|
||||
$account->setCustomField('key', $key);
|
||||
$account->setEMail($email);
|
||||
|
||||
if (HAS_ACCOUNT_COINS) {
|
||||
$account->setCustomField('coins', $t_coins);
|
||||
}
|
||||
|
||||
if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) {
|
||||
$account->setCustomField(ACCOUNT_COINS_TRANSFERABLE_COLUMN, $t_coins_transferable);
|
||||
}
|
||||
|
||||
$lastDay = 0;
|
||||
if($p_days != 0 && $p_days != OTS_Account::GRATIS_PREMIUM_DAYS) {
|
||||
$lastDay = time();
|
||||
} else if ($lastDay != 0) {
|
||||
$lastDay = 0;
|
||||
}
|
||||
|
||||
$account->setPremDays($p_days);
|
||||
$account->setLastLogin($lastDay);
|
||||
if ($hasPointsColumn) {
|
||||
$account->setCustomField('premium_points', $p_points);
|
||||
}
|
||||
$account->setRLName($rl_name);
|
||||
$account->setLocation($rl_loca);
|
||||
|
||||
@@ -222,9 +191,18 @@ else if (isset($_REQUEST['search'])) {
|
||||
$account->setCountry($rl_country);
|
||||
}
|
||||
|
||||
$account->setCustomField('created', $created);
|
||||
$account->setWebFlags($web_flags);
|
||||
$account->setCustomField('web_lastlogin', $web_lastlogin);
|
||||
|
||||
if (!isCanary()) {
|
||||
$lastDay = 0;
|
||||
if($p_days != 0 && $p_days != OTS_Account::GRATIS_PREMIUM_DAYS) {
|
||||
$lastDay = time();
|
||||
}
|
||||
|
||||
$account->setLastLogin($lastDay);
|
||||
}
|
||||
|
||||
$account->setPremDays($p_days);
|
||||
|
||||
if (isset($password)) {
|
||||
if (USE_ACCOUNT_SALT) {
|
||||
@@ -238,6 +216,34 @@ else if (isset($_REQUEST['search'])) {
|
||||
}
|
||||
|
||||
$account->save();
|
||||
|
||||
if ($hasTypeColumn) {
|
||||
$account->setCustomField('type', $group);
|
||||
} elseif ($hasGroupColumn) {
|
||||
$account->setCustomField('group_id', $group);
|
||||
}
|
||||
|
||||
if ($hasSecretColumn) {
|
||||
$account->setCustomField('secret', $secret);
|
||||
}
|
||||
|
||||
$account->setCustomField('key', $key);
|
||||
|
||||
if (HAS_ACCOUNT_COINS) {
|
||||
$account->setCustomField('coins', $t_coins);
|
||||
}
|
||||
|
||||
if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) {
|
||||
$account->setCustomField(ACCOUNT_COINS_TRANSFERABLE_COLUMN, $t_coins_transferable);
|
||||
}
|
||||
|
||||
if ($hasPointsColumn) {
|
||||
$account->setCustomField('premium_points', $p_points);
|
||||
}
|
||||
|
||||
$account->setCustomField('created', $created);
|
||||
$account->setCustomField('web_lastlogin', $web_lastlogin);
|
||||
|
||||
echo_success('Account saved at: ' . date('G:i'));
|
||||
}
|
||||
}
|
||||
@@ -481,9 +487,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>
|
||||
@@ -631,6 +636,7 @@ else if (isset($_REQUEST['search'])) {
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<?php if (USE_ACCOUNT_NAME): ?>
|
||||
<div class="col-6 col-lg-12">
|
||||
<form action="<?php echo $admin_base; ?>" method="post">
|
||||
<?php csrf(); ?>
|
||||
@@ -641,6 +647,7 @@ else if (isset($_REQUEST['search'])) {
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="col-6 col-lg-12">
|
||||
<form action="<?php echo $admin_base; ?>" method="post">
|
||||
<?php csrf(); ?>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
* @package MyAAC
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @author Lee
|
||||
* @author gpedro
|
||||
* @copyright 2020 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
@@ -19,9 +20,9 @@ $title = 'Mass Account Actions';
|
||||
csrfProtect();
|
||||
|
||||
$hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
|
||||
$freePremium = $config['lua']['freePremium'];
|
||||
$freePremium = getBoolean(configLua('freePremium'));
|
||||
|
||||
function admin_give_points($points)
|
||||
function admin_give_points($points): void
|
||||
{
|
||||
global $hasPointsColumn;
|
||||
|
||||
@@ -37,7 +38,7 @@ function admin_give_points($points)
|
||||
displayMessage($points . ' points added to all accounts.', true);
|
||||
}
|
||||
|
||||
function admin_give_coins($coins)
|
||||
function admin_give_coins($coins): void
|
||||
{
|
||||
if (!HAS_ACCOUNT_COINS) {
|
||||
displayMessage('Coins not supported.');
|
||||
@@ -52,7 +53,7 @@ function admin_give_coins($coins)
|
||||
displayMessage($coins . ' coins added to all accounts.', true);
|
||||
}
|
||||
|
||||
function admin_give_premdays($days)
|
||||
function admin_give_premdays($days): void
|
||||
{
|
||||
global $db, $freePremium;
|
||||
|
||||
@@ -63,6 +64,7 @@ function admin_give_premdays($days)
|
||||
|
||||
$value = $days * 86400;
|
||||
$now = time();
|
||||
|
||||
// othire
|
||||
if ($db->hasColumn('accounts', 'premend')) {
|
||||
// append premend
|
||||
@@ -70,14 +72,11 @@ function admin_give_premdays($days)
|
||||
// set premend
|
||||
if (Account::where('premend', '<=', $now)->update(['premend' => $now + $value])) {
|
||||
displayMessage($days . ' premium days added to all accounts.', true);
|
||||
return;
|
||||
} else {
|
||||
displayMessage('Failed to execute set query.');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
displayMessage('Failed to execute append query.');
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -92,20 +91,14 @@ function admin_give_premdays($days)
|
||||
// set lastday
|
||||
if (Account::where('lastday', '<=', $now)->update(['lastday' => $now + $value])) {
|
||||
displayMessage($days . ' premium days added to all accounts.', true);
|
||||
return;
|
||||
} else {
|
||||
displayMessage('Failed to execute set query.');
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
} else {
|
||||
displayMessage('Failed to execute append query.');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
displayMessage('Failed to execute set days query.');
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -118,14 +111,11 @@ function admin_give_premdays($days)
|
||||
// set premium_ends_at
|
||||
if (Account::where('premium_ends_at', '<=', $now)->update(['premium_ends_at' => $now + $value])) {
|
||||
displayMessage($days . ' premium days added to all accounts.', true);
|
||||
return;
|
||||
} else {
|
||||
displayMessage('Failed to execute set query.');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
displayMessage('Failed to execute append query.');
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -170,7 +160,8 @@ else {
|
||||
));
|
||||
}
|
||||
|
||||
function displayMessage($message, $success = false) {
|
||||
function displayMessage($message, $success = false): void
|
||||
{
|
||||
global $twig, $hasPointsColumn, $freePremium;
|
||||
|
||||
$success ? success($message): error($message);
|
||||
|
||||
@@ -23,6 +23,7 @@ if (!hasFlag(FLAG_CONTENT_MENUS) && !superAdmin()) {
|
||||
}
|
||||
|
||||
$pluginThemes = Plugins::getThemes();
|
||||
$groups = new OTS_Groups_List();
|
||||
|
||||
if (isset($_POST['template'])) {
|
||||
$template = $_POST['template'];
|
||||
@@ -32,6 +33,8 @@ if (isset($_POST['template'])) {
|
||||
$post_menu_link = $_POST['menu_link'] ?? [];
|
||||
$post_menu_blank = $_POST['menu_blank'] ?? [];
|
||||
$post_menu_color = $_POST['menu_color'] ?? [];
|
||||
$post_menu_access = $_POST['menu_access'] ?? [];
|
||||
|
||||
if (count($post_menu) != count($post_menu_link)) {
|
||||
echo 'Menu count is not equal menu links. Something went wrong when sending form.';
|
||||
return;
|
||||
@@ -50,6 +53,7 @@ if (isset($_POST['template'])) {
|
||||
'link' => $post_menu_link[$category][$i],
|
||||
'blank' => $post_menu_blank[$category][$i] == 'on' ? 1 : 0,
|
||||
'color' => str_replace('#', '', $post_menu_color[$category][$i]),
|
||||
'access' => $post_menu_access[$category][$i],
|
||||
'category' => $category,
|
||||
'ordering' => $i
|
||||
]);
|
||||
@@ -122,7 +126,7 @@ if (isset($_POST['template'])) {
|
||||
?>
|
||||
<?php
|
||||
$menus = Menu::query()
|
||||
->select('name', 'link', 'blank', 'color', 'category', 'ordering')
|
||||
->select('name', 'link', 'access', 'blank', 'color', 'category', 'ordering')
|
||||
->where('enabled', 1)
|
||||
->where('template', $template)
|
||||
->orderBy('ordering')
|
||||
@@ -151,11 +155,34 @@ if (isset($_POST['template'])) {
|
||||
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 $color; ?>"/>
|
||||
<li class="ui-state-default" id="list-<?php echo $id ?>-<?php echo $i ?>">
|
||||
<label class="label_menu_name">Name: <input type="text" name="menu[<?php echo $id ?>][]" class="form-control menu-name" value="<?php echo escapeHtml($menu['name']); ?>"/>
|
||||
</label>
|
||||
|
||||
<label class="label_menu_link">Link: <input type="text" name="menu_link[<?= $id ?>][]" class="form-control menu-link" value="<?php echo $menu['link'] ?>"/>
|
||||
</label>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="menu-options-row">
|
||||
|
||||
<label>Access:
|
||||
<select name="menu_access[<?= $id ?>][]" class="form-control menu-access">
|
||||
<option value="0" <?= ($menu['access'] == 0 ? 'selected' : ''); ?>>Guest*</option>
|
||||
<?php foreach ($groups->getGroups() as $group): ?>
|
||||
<option value="<?= $group->getId(); ?>" <?= ($menu['access'] == $group->getId() ? 'selected' : ''); ?>><?= ucfirst($group->getName()); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>Color: <input class="menu-color" type="color" name="menu_color[<?php echo $id ?>][]" value="<?php echo $color; ?>"/>
|
||||
</label>
|
||||
|
||||
<input type="hidden" name="menu_blank[<?php echo $id ?>][]" class="menu-blank" value="0"/>
|
||||
<label><input type="checkbox" class="menu-blank-checkbox" <?php echo($menu['blank'] == 1 ? 'checked' : '') ?>/><span title="Open in New Window">New Window</span></label>
|
||||
|
||||
</div>
|
||||
|
||||
<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;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
use MyAAC\Forum;
|
||||
use MyAAC\Models\Player;
|
||||
use MyAAC\Server\XML\Vocations;
|
||||
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
@@ -34,6 +35,7 @@ $skills = array(
|
||||
$hasBlessingsColumn = $db->hasColumn('players', 'blessings');
|
||||
$hasBlessingColumn = $db->hasColumn('players', 'blessings1');
|
||||
$hasLookAddons = $db->hasColumn('players', 'lookaddons');
|
||||
$hasCapColumn = $db->hasColumn('players', 'cap');
|
||||
|
||||
$skull_type = array("None", "Yellow", "Green", "White", "Red", "Black", "Orange");
|
||||
?>
|
||||
@@ -166,8 +168,11 @@ else if (isset($_REQUEST['search'])) {
|
||||
$town = $_POST['town'];
|
||||
verify_number($town, 'Town', 11);
|
||||
|
||||
if ($hasCapColumn) {
|
||||
$capacity = $_POST['capacity'];
|
||||
verify_number($capacity, 'Capacity', 11);
|
||||
}
|
||||
|
||||
$sex = $_POST['sex'];
|
||||
verify_number($sex, 'Sex', 1);
|
||||
|
||||
@@ -237,7 +242,30 @@ else if (isset($_REQUEST['search'])) {
|
||||
$player->setGroup($groups->getGroup($group));
|
||||
$player->setLevel($level);
|
||||
$player->setExperience($experience);
|
||||
|
||||
if ($db->hasColumn('players', 'promotion')) {
|
||||
$promotion = 0;
|
||||
|
||||
$vocationOriginal = Vocations::getOriginal($vocation);
|
||||
if ($vocation != $vocationOriginal) {
|
||||
$tmpId = $vocationOriginal;
|
||||
while($promoted = Vocations::getPromoted($tmpId)) {
|
||||
$promotion++;
|
||||
|
||||
$tmpId = $promoted;
|
||||
if ($promoted == $vocation) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$vocation = $vocationOriginal;
|
||||
}
|
||||
|
||||
$player->setPromotion($promotion);
|
||||
}
|
||||
|
||||
$player->setVocation($vocation);
|
||||
|
||||
$player->setHealth($health);
|
||||
$player->setHealthMax($health_max);
|
||||
$player->setMagLevel($magic_level);
|
||||
@@ -249,16 +277,20 @@ else if (isset($_REQUEST['search'])) {
|
||||
$player->setLookHead($look_head);
|
||||
$player->setLookLegs($look_legs);
|
||||
$player->setLookType($look_type);
|
||||
if ($hasLookAddons)
|
||||
if ($hasLookAddons) {
|
||||
$player->setLookAddons($look_addons);
|
||||
if ($db->hasColumn('players', 'offlinetraining_time'))
|
||||
$player->setCustomField('offlinetraining_time', $offlinetraining);
|
||||
}
|
||||
|
||||
$player->setPosX($pos_x);
|
||||
$player->setPosY($pos_y);
|
||||
$player->setPosZ($pos_z);
|
||||
$player->setSoul($soul);
|
||||
$player->setTownId($town);
|
||||
|
||||
if ($hasCapColumn) {
|
||||
$player->setCap($capacity);
|
||||
}
|
||||
|
||||
$player->setSex($sex);
|
||||
$player->setLastLogin($lastlogin);
|
||||
$player->setLastLogout($lastlogout);
|
||||
@@ -275,23 +307,11 @@ else if (isset($_REQUEST['search'])) {
|
||||
if ($hasBlessingsColumn)
|
||||
$player->setBlessings($blessings);
|
||||
|
||||
if ($hasBlessingColumn) {
|
||||
for ($i = 1; $i <= $bless_count; $i++) {
|
||||
$a = 'blessing' . $i;
|
||||
$player->setCustomField('blessings' . $i, ${'blessing' . $i} ? '1' : '0');
|
||||
}
|
||||
}
|
||||
$player->setBalance($balance);
|
||||
if ($db->hasColumn('players', 'stamina'))
|
||||
$player->setStamina($stamina);
|
||||
if ($db->hasColumn('players', 'deletion'))
|
||||
$player->setCustomField('deletion', $deleted ? '1' : '0');
|
||||
else
|
||||
$player->setCustomField('deleted', $deleted ? '1' : '0');
|
||||
$player->setCustomField('hide', $hide ? '1' : '0');
|
||||
$player->setCustomField('created', $created);
|
||||
if (isset($comment))
|
||||
$player->setCustomField('comment', $comment);
|
||||
|
||||
$player->setDeleted($deleted ? '1' : '0');
|
||||
|
||||
foreach ($_POST['skills'] as $skill => $value) {
|
||||
$player->setSkill($skill, $value);
|
||||
@@ -300,6 +320,24 @@ else if (isset($_REQUEST['search'])) {
|
||||
$player->setSkillTries($skill, $value);
|
||||
}
|
||||
$player->save();
|
||||
|
||||
if ($db->hasColumn('players', 'offlinetraining_time')) {
|
||||
$player->setCustomField('offlinetraining_time', $offlinetraining);
|
||||
}
|
||||
|
||||
if ($hasBlessingColumn) {
|
||||
for ($i = 1; $i <= $bless_count; $i++) {
|
||||
$a = 'blessing' . $i;
|
||||
$player->setCustomField('blessings' . $i, ${'blessing' . $i} ? '1' : '0');
|
||||
}
|
||||
}
|
||||
|
||||
$player->setCustomField('hide', $hide ? '1' : '0');
|
||||
$player->setCustomField('created', $created);
|
||||
if (isset($comment)) {
|
||||
$player->setCustomField('comment', $comment);
|
||||
}
|
||||
|
||||
echo_success('Player saved at: ' . date('G:i'));
|
||||
$player->load($id);
|
||||
}
|
||||
@@ -531,10 +569,12 @@ else if (isset($_REQUEST['search'])) {
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<?php if($hasCapColumn): ?>
|
||||
<div class="col-12 col-sm-12 col-lg-6">
|
||||
<label for="capacity" class="control-label">Capacity:</label>
|
||||
<input type="text" class="form-control" id="capacity" name="capacity" autocomplete="off" size="3" maxlength="11" value="<?php echo $player->getCap(); ?>"/>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="col-12 col-sm-12 col-lg-6">
|
||||
<label for="soul" class="control-label">Soul:</label>
|
||||
<input type="text" class="form-control" id="soul" name="soul" autocomplete="off" size="3" maxlength="10" value="<?php echo $player->getSoul(); ?>"/>
|
||||
@@ -669,12 +709,18 @@ else if (isset($_REQUEST['search'])) {
|
||||
<div class="col-12 col-sm-12 col-lg-6">
|
||||
<label for="lastip" class="control-label">Last IP:</label>
|
||||
<input type="text" class="form-control" id="lastip" name="lastip" autocomplete="off" maxlength="10" value="<?php
|
||||
if (strlen($player->getLastIP()) > 11) {
|
||||
$lastIPColumnInfo = $db->getColumnInfo('players', 'lastip');
|
||||
if ($lastIPColumnInfo && is_array($lastIPColumnInfo)) {
|
||||
if (str_contains($lastIPColumnInfo['type'], 'varbinary')) {
|
||||
echo inet_ntop($player->getLastIP());
|
||||
}
|
||||
else {
|
||||
echo longToIp($player->getLastIP());
|
||||
}
|
||||
}
|
||||
else {
|
||||
echo 'Error';
|
||||
}
|
||||
?>" readonly/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -60,7 +60,7 @@ usort($menus, function ($a, $b) {
|
||||
|
||||
foreach ($menus as $i => $menu) {
|
||||
if (isset($menu['link']) && is_array($menu['link'])) {
|
||||
usort($menus[$i]['link'], function ($a, $b) {
|
||||
usort($menu['link'], function ($a, $b) {
|
||||
return $a['order'] - $b['order'];
|
||||
});
|
||||
}
|
||||
|
||||
@@ -19,14 +19,14 @@
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic">
|
||||
<?php $hooks->trigger(HOOK_ADMIN_HEAD_END); ?>
|
||||
</head>
|
||||
<body class="sidebar-mini ">
|
||||
<body class="sidebar-mini <?= (session('admin.menu-collapse') ? 'sidebar-collapse' : ''); ?>">
|
||||
<?php $hooks->trigger(HOOK_ADMIN_BODY_START); ?>
|
||||
<?php if ($logged && admin()) { ?>
|
||||
<div class="wrapper">
|
||||
<nav class="main-header navbar navbar-expand navbar-white navbar-light">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-widget="pushmenu" href="#"><i class="fas fa-bars"></i></a>
|
||||
<a class="nav-link sidebar-toggle" data-widget="pushmenu" href="#"><i class="fas fa-bars"></i></a>
|
||||
</li>
|
||||
<li class="nav-item d-none d-sm-inline-block">
|
||||
<a href="<?php echo ADMIN_URL; ?>" class="nav-link">Home</a>
|
||||
@@ -198,6 +198,7 @@ if ($logged && admin()) {
|
||||
<script src="<?php echo BASE_URL; ?>tools/js/datatables.bs.min.js"></script>
|
||||
<?php } ?>
|
||||
<script src="<?php echo BASE_URL; ?>tools/js/adminlte.min.js"></script>
|
||||
<?php $twig->display('admin.menu-collapse.html.twig'); ?>
|
||||
<?php $hooks->trigger(HOOK_ADMIN_BODY_END); ?>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
23
admin/tools/menu_collapse.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
const MYAAC_ADMIN = true;
|
||||
const IGNORE_SET_LAST_VISIT = true;
|
||||
|
||||
require '../../common.php';
|
||||
require SYSTEM . 'functions.php';
|
||||
require SYSTEM . 'init.php';
|
||||
require SYSTEM . 'login.php';
|
||||
|
||||
if(!admin()) {
|
||||
http_response_code(500);
|
||||
die('You are not logged in. Probably session expired. Please login again.');
|
||||
}
|
||||
|
||||
if (!isset($_POST['collapse'])) {
|
||||
http_response_code(500);
|
||||
die('Something went wrong.');
|
||||
}
|
||||
|
||||
csrfProtect();
|
||||
|
||||
setSession('admin.menu-collapse', $_POST['collapse'] == 'true');
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
define('MYAAC_ADMIN', true);
|
||||
const MYAAC_ADMIN = true;
|
||||
const IGNORE_SET_LAST_VISIT = true;
|
||||
|
||||
require '../../common.php';
|
||||
require SYSTEM . 'functions.php';
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
use MyAAC\DataLoader;
|
||||
|
||||
const MYAAC_ADMIN = true;
|
||||
const IGNORE_SET_LAST_VISIT = true;
|
||||
|
||||
require '../../common.php';
|
||||
require SYSTEM . 'functions.php';
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
use MyAAC\Settings;
|
||||
|
||||
const MYAAC_ADMIN = true;
|
||||
const IGNORE_SET_LAST_VISIT = true;
|
||||
|
||||
require '../../common.php';
|
||||
require SYSTEM . 'functions.php';
|
||||
@@ -11,7 +12,7 @@ require SYSTEM . 'login.php';
|
||||
|
||||
if(!admin()) {
|
||||
http_response_code(500);
|
||||
die('Access denied.');
|
||||
die('You are not logged in. Probably session expired. Please login again.');
|
||||
}
|
||||
|
||||
csrfProtect();
|
||||
@@ -39,3 +40,6 @@ if (count($errors) > 0) {
|
||||
if ($success) {
|
||||
echo 'Saved at ' . date('H:i');
|
||||
}
|
||||
else {
|
||||
echo 'Something unexpected happened - it was impossible to save the settings, please try again later. If problem persists - contact MyAAC developers.';
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
define('MYAAC_ADMIN', true);
|
||||
const MYAAC_ADMIN = true;
|
||||
const IGNORE_SET_LAST_VISIT = true;
|
||||
|
||||
require '../../common.php';
|
||||
require SYSTEM . 'init.php';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
define('MYAAC_ADMIN', true);
|
||||
const MYAAC_ADMIN = true;
|
||||
const IGNORE_SET_LAST_VISIT = true;
|
||||
|
||||
require '../../common.php';
|
||||
require SYSTEM . 'functions.php';
|
||||
|
||||
17
common.php
@@ -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.8.2';
|
||||
const DATABASE_VERSION = 45;
|
||||
const MYAAC_VERSION = '2.0-dev';
|
||||
const DATABASE_VERSION = 50;
|
||||
const TABLE_PREFIX = 'myaac_';
|
||||
define('START_TIME', microtime(true));
|
||||
define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX'));
|
||||
@@ -148,16 +148,17 @@ if(!IS_CLI) {
|
||||
|
||||
/** @var array $config */
|
||||
ini_set('log_errors', 1);
|
||||
if(@$config['env'] === 'dev' || defined('MYAAC_INSTALL')) {
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
}
|
||||
else {
|
||||
if(isset($config['env']) && $config['env'] !== 'dev' && !defined('MYAAC_INSTALL')) {
|
||||
ini_set('display_errors', 0);
|
||||
ini_set('display_startup_errors', 0);
|
||||
error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT);
|
||||
}
|
||||
else {
|
||||
ini_set('html_errors', 0);
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
}
|
||||
|
||||
$autoloadFile = VENDOR . 'autoload.php';
|
||||
if (!is_file($autoloadFile)) {
|
||||
|
||||
BIN
images/druid.png
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 33 KiB |
BIN
images/facebook_16x16.png
Normal file
|
After Width: | Height: | Size: 718 B |
BIN
images/instagram_16x16.png
Normal file
|
After Width: | Height: | Size: 721 B |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 33 KiB |
BIN
images/monk.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 1005 B |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 31 KiB |
BIN
images/whatsapp_16x16.png
Normal file
|
After Width: | Height: | Size: 688 B |
67
install/includes/import_base_data.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
use MyAAC\Models\Changelog;
|
||||
use MyAAC\Models\Config;
|
||||
use MyAAC\Models\FAQ;
|
||||
use MyAAC\Models\ForumBoard;
|
||||
use MyAAC\Models\Gallery;
|
||||
use MyAAC\Models\NewsCategory;
|
||||
|
||||
if (Changelog::count() === 0) {
|
||||
Changelog::create([
|
||||
'type' => 3,
|
||||
'where' => 2,
|
||||
'date' => time(),
|
||||
'body' => 'MyAAC installed. (:',
|
||||
'hide' => 0,
|
||||
]);
|
||||
}
|
||||
|
||||
if (Config::where('name', 'database_version')->count() === 0) {
|
||||
Config::create([
|
||||
'name' => 'database_version',
|
||||
'value' => DATABASE_VERSION,
|
||||
]);
|
||||
}
|
||||
|
||||
if (ForumBoard::count() === 0) {
|
||||
$forumBoards = [
|
||||
['name' => 'News', 'description' => 'News commenting', 'closed' => 1],
|
||||
['name' => 'Trade', 'description' => 'Trade offers.', 'closed' => 0],
|
||||
['name' => 'Quests', 'description' => 'Quest making.', 'closed' => 0],
|
||||
['name' => 'Pictures', 'description' => 'Your pictures.', 'closed' => 0],
|
||||
['name' => 'Bug Report', 'description' => 'Report bugs there.', 'closed' => 0],
|
||||
];
|
||||
|
||||
$i = 0;
|
||||
foreach ($forumBoards as $forumBoard) {
|
||||
ForumBoard::create([
|
||||
'name' => $forumBoard['name'],
|
||||
'description' => $forumBoard['description'],
|
||||
'ordering' => $i++,
|
||||
'closed' => $forumBoard['closed'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (NewsCategory::count() === 0) {
|
||||
$newsCategoriesIcons = [
|
||||
0, 1, 2, 3, 4
|
||||
];
|
||||
|
||||
foreach ($newsCategoriesIcons as $iconId) {
|
||||
NewsCategory::create([
|
||||
'icon_id' => $iconId,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if(FAQ::count() == 0) {
|
||||
FAQ::create([
|
||||
'question' => 'What is this?',
|
||||
'answer' => 'This is website for OTS powered by MyAAC.',
|
||||
]);
|
||||
}
|
||||
|
||||
success($locale['step_database_success_import_data']);
|
||||
@@ -1,16 +1,23 @@
|
||||
SET @myaac_database_version = 45;
|
||||
|
||||
CREATE TABLE `myaac_account_actions`
|
||||
CREATE TABLE IF NOT EXISTS `myaac_account_actions`
|
||||
(
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`account_id` int NOT NULL,
|
||||
`ip` int unsigned NOT NULL DEFAULT 0,
|
||||
`ipv6` binary(16) NOT NULL DEFAULT 0,
|
||||
`ip` varchar(45) NOT NULL DEFAULT '',
|
||||
`date` int NOT NULL DEFAULT 0,
|
||||
`action` varchar(255) NOT NULL DEFAULT '',
|
||||
KEY (`account_id`)
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||
|
||||
CREATE TABLE `myaac_admin_menu`
|
||||
CREATE TABLE IF NOT EXISTS `myaac_account_emails_verify`
|
||||
(
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`account_id` int NOT NULL,
|
||||
`hash` varchar(32) NOT NULL,
|
||||
`sent_at` int NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `myaac_admin_menu`
|
||||
(
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
@@ -21,7 +28,7 @@ CREATE TABLE `myaac_admin_menu`
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||
|
||||
CREATE TABLE `myaac_changelog`
|
||||
CREATE TABLE IF NOT EXISTS `myaac_changelog`
|
||||
(
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`body` varchar(500) NOT NULL DEFAULT '',
|
||||
@@ -33,9 +40,7 @@ CREATE TABLE `myaac_changelog`
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||
|
||||
INSERT INTO `myaac_changelog` (`id`, `type`, `where`, `date`, `body`, `hide`) VALUES (1, 3, 2, UNIX_TIMESTAMP(), 'MyAAC installed. (:', 0);
|
||||
|
||||
CREATE TABLE `myaac_config`
|
||||
CREATE TABLE IF NOT EXISTS `myaac_config`
|
||||
(
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(30) NOT NULL,
|
||||
@@ -44,9 +49,7 @@ CREATE TABLE `myaac_config`
|
||||
UNIQUE (`name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||
|
||||
INSERT INTO `myaac_config` (`name`, `value`) VALUES ('database_version', @myaac_database_version);
|
||||
|
||||
CREATE TABLE `myaac_faq`
|
||||
CREATE TABLE IF NOT EXISTS `myaac_faq`
|
||||
(
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`question` varchar(255) NOT NULL DEFAULT '',
|
||||
@@ -56,7 +59,7 @@ CREATE TABLE `myaac_faq`
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||
|
||||
CREATE TABLE `myaac_forum_boards`
|
||||
CREATE TABLE IF NOT EXISTS `myaac_forum_boards`
|
||||
(
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(32) NOT NULL,
|
||||
@@ -68,13 +71,8 @@ CREATE TABLE `myaac_forum_boards`
|
||||
`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);
|
||||
INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Trade', 'Trade offers.', 1);
|
||||
INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Quests', 'Quest making.', 2);
|
||||
INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Pictures', 'Your pictures.', 3);
|
||||
INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Bug Report', 'Report bugs there.', 4);
|
||||
|
||||
CREATE TABLE `myaac_forum`
|
||||
CREATE TABLE IF NOT EXISTS `myaac_forum`
|
||||
(
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`first_post` int NOT NULL DEFAULT 0,
|
||||
@@ -98,12 +96,13 @@ CREATE TABLE `myaac_forum`
|
||||
KEY `section` (`section`)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||
|
||||
CREATE TABLE `myaac_menu`
|
||||
CREATE TABLE IF NOT EXISTS `myaac_menu`
|
||||
(
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`template` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`link` varchar(255) NOT NULL,
|
||||
`access` tinyint NOT NULL DEFAULT 0,
|
||||
`blank` tinyint NOT NULL DEFAULT 0,
|
||||
`color` varchar(6) NOT NULL DEFAULT '',
|
||||
`category` int NOT NULL DEFAULT 1,
|
||||
@@ -112,7 +111,7 @@ CREATE TABLE `myaac_menu`
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||
|
||||
CREATE TABLE `myaac_monsters` (
|
||||
CREATE TABLE IF NOT EXISTS `myaac_monsters` (
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`hide` tinyint NOT NULL DEFAULT 0,
|
||||
`name` varchar(255) NOT NULL,
|
||||
@@ -145,7 +144,7 @@ CREATE TABLE `myaac_monsters` (
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||
|
||||
CREATE TABLE `myaac_news`
|
||||
CREATE TABLE IF NOT EXISTS `myaac_news`
|
||||
(
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(100) NOT NULL,
|
||||
@@ -163,7 +162,7 @@ CREATE TABLE `myaac_news`
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||
|
||||
CREATE TABLE `myaac_news_categories`
|
||||
CREATE TABLE IF NOT EXISTS `myaac_news_categories`
|
||||
(
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(50) NOT NULL DEFAULT "",
|
||||
@@ -173,13 +172,7 @@ CREATE TABLE `myaac_news_categories`
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||
|
||||
INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 0);
|
||||
INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 1);
|
||||
INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 2);
|
||||
INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 3);
|
||||
INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 4);
|
||||
|
||||
CREATE TABLE `myaac_notepad`
|
||||
CREATE TABLE IF NOT EXISTS `myaac_notepad`
|
||||
(
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`account_id` int NOT NULL,
|
||||
@@ -189,7 +182,7 @@ CREATE TABLE `myaac_notepad`
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||
|
||||
CREATE TABLE `myaac_pages`
|
||||
CREATE TABLE IF NOT EXISTS `myaac_pages`
|
||||
(
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(30) NOT NULL,
|
||||
@@ -205,21 +198,7 @@ CREATE TABLE `myaac_pages`
|
||||
UNIQUE (`name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||
|
||||
CREATE TABLE `myaac_gallery`
|
||||
(
|
||||
`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;
|
||||
|
||||
INSERT INTO `myaac_gallery` (`id`, `ordering`, `comment`, `image`, `thumb`, `author`) VALUES (NULL, 1, 'Demon', 'images/gallery/demon.jpg', 'images/gallery/demon_thumb.gif', 'MyAAC');
|
||||
|
||||
CREATE TABLE `myaac_settings`
|
||||
CREATE TABLE IF NOT EXISTS `myaac_settings`
|
||||
(
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
@@ -229,7 +208,7 @@ CREATE TABLE `myaac_settings`
|
||||
KEY `key` (`key`)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||
|
||||
CREATE TABLE `myaac_spells`
|
||||
CREATE TABLE IF NOT EXISTS `myaac_spells`
|
||||
(
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`spell` varchar(255) NOT NULL DEFAULT '',
|
||||
@@ -252,7 +231,7 @@ CREATE TABLE `myaac_spells`
|
||||
UNIQUE (`name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||
|
||||
CREATE TABLE `myaac_visitors`
|
||||
CREATE TABLE IF NOT EXISTS `myaac_visitors`
|
||||
(
|
||||
`ip` varchar(45) NOT NULL,
|
||||
`lastvisit` int NOT NULL DEFAULT 0,
|
||||
@@ -261,7 +240,7 @@ CREATE TABLE `myaac_visitors`
|
||||
UNIQUE (`ip`)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||
|
||||
CREATE TABLE `myaac_weapons`
|
||||
CREATE TABLE IF NOT EXISTS `myaac_weapons`
|
||||
(
|
||||
`id` int NOT NULL,
|
||||
`level` int NOT NULL DEFAULT 0,
|
||||
|
||||
@@ -30,17 +30,12 @@ if(!$error) {
|
||||
}
|
||||
}
|
||||
|
||||
if($db->hasTable(TABLE_PREFIX . 'account_actions')) {
|
||||
$locale['step_database_error_table_exist'] = str_replace('$TABLE$', TABLE_PREFIX . 'account_actions', $locale['step_database_error_table_exist']);
|
||||
warning($locale['step_database_error_table_exist']);
|
||||
}
|
||||
else {
|
||||
// import schema
|
||||
try {
|
||||
$locale['step_database_importing'] = str_replace('$DATABASE_NAME$', config('database_name'), $locale['step_database_importing']);
|
||||
success($locale['step_database_importing']);
|
||||
|
||||
$db->query(file_get_contents(BASE . 'install/includes/schema.sql'));
|
||||
$db->exec(file_get_contents(BASE . 'install/includes/schema.sql'));
|
||||
|
||||
$locale['step_database_success_schema'] = str_replace('$PREFIX$', TABLE_PREFIX, $locale['step_database_success_schema']);
|
||||
success($locale['step_database_success_schema']);
|
||||
@@ -49,7 +44,8 @@ else {
|
||||
error($locale['step_database_error_schema'] . ' ' . $error_);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
require BASE . 'install/includes/import_base_data.php';
|
||||
|
||||
if(!$db->hasColumn('accounts', 'email')) {
|
||||
if(query("ALTER TABLE `accounts` ADD `email` varchar(255) NOT NULL DEFAULT '';"))
|
||||
@@ -102,18 +98,13 @@ if(!$db->hasColumn('accounts', 'web_flags')) {
|
||||
success($locale['step_database_adding_field'] . ' accounts.web_flags...');
|
||||
}
|
||||
|
||||
if(!$db->hasColumn('accounts', 'email_hash')) {
|
||||
if(query("ALTER TABLE `accounts` ADD `email_hash` VARCHAR(32) NOT NULL DEFAULT '' AFTER `web_flags`;"))
|
||||
success($locale['step_database_adding_field'] . ' accounts.email_hash...');
|
||||
}
|
||||
|
||||
if(!$db->hasColumn('accounts', 'email_verified')) {
|
||||
if(query("ALTER TABLE `accounts` ADD `email_verified` TINYINT(1) NOT NULL DEFAULT 0 AFTER `email_hash`;"))
|
||||
if(query("ALTER TABLE `accounts` ADD `email_verified` TINYINT(1) NOT NULL DEFAULT 0 AFTER `web_flags`;"))
|
||||
success($locale['step_database_adding_field'] . ' accounts.email_verified...');
|
||||
}
|
||||
|
||||
if(!$db->hasColumn('accounts', 'email_new')) {
|
||||
if(query("ALTER TABLE `accounts` ADD `email_new` VARCHAR(255) NOT NULL DEFAULT '' AFTER `email_hash`;"))
|
||||
if(query("ALTER TABLE `accounts` ADD `email_new` VARCHAR(255) NOT NULL DEFAULT '' AFTER `email_verified`;"))
|
||||
success($locale['step_database_adding_field'] . ' accounts.email_new...');
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
define('MYAAC_INSTALL', true);
|
||||
|
||||
use MyAAC\DataLoader;
|
||||
use MyAAC\Models\FAQ as ModelsFAQ;
|
||||
use MyAAC\Plugins;
|
||||
|
||||
require_once '../../common.php';
|
||||
|
||||
@@ -25,34 +23,9 @@ if(isset($config['installed']) && $config['installed'] && !isset($_SESSION['save
|
||||
|
||||
require SYSTEM . 'init.php';
|
||||
|
||||
if ($db->hasTable('players')) {
|
||||
$deleted = 'deleted';
|
||||
if ($db->hasColumn('players', 'deletion'))
|
||||
$deleted = 'deletion';
|
||||
|
||||
$time = time();
|
||||
function insert_sample_if_not_exist($p)
|
||||
{
|
||||
global $db, $success, $deleted, $time;
|
||||
|
||||
$query = $db->query('SELECT `id` FROM `players` WHERE `name` = ' . $db->quote($p['name']));
|
||||
if ($query->rowCount() == 0) {
|
||||
if (!query("INSERT INTO `players` (`id`, `name`, `group_id`, `account_id`, `level`, `vocation`, `health`, `healthmax`, `experience`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`, `maglevel`, `mana`, `manamax`, `manaspent`, `soul`, `town_id`, `posx`, `posy`, `posz`, `conditions`, `cap`, `sex`, `lastlogin`, `lastip`, `save`, `lastlogout`, `balance`, `$deleted`, `created`, `hide`, `comment`) VALUES (null, " . $db->quote($p['name']) . ", 1, " . getSession('account') . ", " . $p['level'] . ", " . $p['vocation_id'] . ", " . $p['health'] . ", " . $p['healthmax'] . ", " . $p['experience'] . ", 118, 114, 38, 57, " . $p['looktype'] . ", 0, " . $p['mana'] . ", " . $p['manamax'] . ", 0, " . $p['soul'] . ", 1, 1000, 1000, 7, '', " . $p['cap'] . ", 1, " . $time . ", 2130706433, 1, " . $time . ", 0, 0, " . $time . ", 1, '');"))
|
||||
$success = false;
|
||||
}
|
||||
}
|
||||
|
||||
$success = true;
|
||||
insert_sample_if_not_exist(array('name' => 'Rook Sample', 'level' => 1, 'vocation_id' => 0, 'health' => 150, 'healthmax' => 150, 'experience' => 0, 'looktype' => 130, 'mana' => 0, 'manamax' => 0, 'soul' => 100, 'cap' => 400));
|
||||
insert_sample_if_not_exist(array('name' => 'Sorcerer Sample', 'level' => 8, 'vocation_id' => 1, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 130, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470));
|
||||
insert_sample_if_not_exist(array('name' => 'Druid Sample', 'level' => 8, 'vocation_id' => 2, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 130, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470));
|
||||
insert_sample_if_not_exist(array('name' => 'Paladin Sample', 'level' => 8, 'vocation_id' => 3, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 129, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470));
|
||||
insert_sample_if_not_exist(array('name' => 'Knight Sample', 'level' => 8, 'vocation_id' => 4, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 131, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470));
|
||||
|
||||
if ($success) {
|
||||
success($locale['step_database_imported_players']);
|
||||
}
|
||||
}
|
||||
// add player samples
|
||||
require_once SYSTEM . 'migrations/49.php';
|
||||
$up();
|
||||
|
||||
DataLoader::setLocale($locale);
|
||||
DataLoader::load();
|
||||
@@ -61,10 +34,6 @@ DataLoader::load();
|
||||
require_once SYSTEM . 'migrations/17.php';
|
||||
$up();
|
||||
|
||||
// update config.highscores_ids_hidden
|
||||
require_once SYSTEM . 'migrations/20.php';
|
||||
$up();
|
||||
|
||||
// add z_polls tables
|
||||
require_once SYSTEM . 'migrations/22.php';
|
||||
$up();
|
||||
@@ -83,13 +52,6 @@ $up();
|
||||
require_once SYSTEM . 'migrations/45.php';
|
||||
$up();
|
||||
|
||||
if(ModelsFAQ::count() == 0) {
|
||||
ModelsFAQ::create([
|
||||
'question' => 'What is this?',
|
||||
'answer' => 'This is website for OTS powered by MyAAC.',
|
||||
]);
|
||||
}
|
||||
|
||||
$hooks->trigger(HOOK_INSTALL_FINISH);
|
||||
|
||||
$db->setClearCacheAfter(true);
|
||||
|
||||
@@ -220,6 +220,8 @@ switch ($action) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* not needed anymore?
|
||||
if (fieldExist('premdays', 'accounts') && fieldExist('lastday', 'accounts')) {
|
||||
$save = false;
|
||||
$timeNow = time();
|
||||
@@ -256,6 +258,7 @@ switch ($action) {
|
||||
$account->save();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
$worlds = [$world];
|
||||
$playdata = compact('worlds', 'characters');
|
||||
|
||||
22
package-lock.json
generated
@@ -18,9 +18,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@cypress/request": {
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.8.tgz",
|
||||
"integrity": "sha512-h0NFgh1mJmm1nr4jCwkGHwKneVYKghUyWe6TMNrk0B9zsjAJxpg8C4/+BAcmLgCPa1vj1V8rNUaILl+zYRUWBQ==",
|
||||
"version": "3.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.10.tgz",
|
||||
"integrity": "sha512-hauBrOdvu08vOsagkZ/Aju5XuiZx6ldsLfByg1htFeldhex+PeMrYauANzFsMJeAA0+dyPLbDoX2OYuvVoLDkQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
@@ -30,14 +30,14 @@
|
||||
"combined-stream": "~1.0.6",
|
||||
"extend": "~3.0.2",
|
||||
"forever-agent": "~0.6.1",
|
||||
"form-data": "~4.0.0",
|
||||
"form-data": "~4.0.4",
|
||||
"http-signature": "~1.4.0",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "~2.1.19",
|
||||
"performance-now": "^2.1.0",
|
||||
"qs": "6.14.0",
|
||||
"qs": "~6.14.1",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"tough-cookie": "^5.0.0",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
@@ -1431,9 +1431,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"version": "4.17.23",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
|
||||
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -1743,9 +1743,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.14.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
|
||||
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
|
||||
"version": "6.14.1",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
|
||||
"integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
|
||||
@@ -5,8 +5,6 @@ $deprecatedConfig = [
|
||||
'genders',
|
||||
'template',
|
||||
'template_allow_change',
|
||||
'vocations_amount',
|
||||
'vocations',
|
||||
'client',
|
||||
'session_prefix',
|
||||
'friendly_urls',
|
||||
@@ -21,7 +19,6 @@ $deprecatedConfig = [
|
||||
'visitors_counter_ttl',
|
||||
'views_counter',
|
||||
'outfit_images_url',
|
||||
'outfit_images_wrong_looktypes',
|
||||
'item_images_url',
|
||||
'account_country',
|
||||
'towns',
|
||||
@@ -52,6 +49,7 @@ $deprecatedConfig = [
|
||||
'online_skulls',
|
||||
'online_outfit',
|
||||
'online_afk',
|
||||
'team_style',
|
||||
'team_display_outfit' => 'team_outfit',
|
||||
'team_display_status' => 'team_status',
|
||||
'team_display_world' => 'team_world',
|
||||
@@ -81,6 +79,7 @@ $deprecatedConfig = [
|
||||
'account_change_character_name_points' => 'account_change_character_name_price',
|
||||
'account_change_character_sex',
|
||||
'account_change_character_sex_points' => 'account_change_character_name_price',
|
||||
'email_lai_sec_interval' => 'mail_lost_account_interval',
|
||||
];
|
||||
|
||||
foreach ($deprecatedConfig as $key => $value) {
|
||||
|
||||
@@ -17,11 +17,12 @@ use MyAAC\Models\Guild;
|
||||
use MyAAC\Models\House;
|
||||
use MyAAC\Models\Pages;
|
||||
use MyAAC\Models\Player;
|
||||
use MyAAC\Models\PlayerDeath;
|
||||
use MyAAC\Models\PlayerKillers;
|
||||
use MyAAC\News;
|
||||
use MyAAC\Plugins;
|
||||
use MyAAC\Settings;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use Twig\Loader\ArrayLoader as Twig_ArrayLoader;
|
||||
|
||||
function message($message, $type, $return)
|
||||
{
|
||||
@@ -433,16 +434,22 @@ function delete_guild($id)
|
||||
$rank_list->orderBy('level');
|
||||
|
||||
global $db;
|
||||
|
||||
$deletedColumn = 'deleted';
|
||||
if ($db->hasColumn('players', 'deletion')) {
|
||||
$deletedColumn = 'deletion';
|
||||
}
|
||||
|
||||
/**
|
||||
* @var OTS_GuildRank $rank_in_guild
|
||||
*/
|
||||
foreach($rank_list as $rank_in_guild) {
|
||||
if($db->hasTable('guild_members'))
|
||||
$players_with_rank = $db->query('SELECT `players`.`id` as `id`, `guild_members`.`rank_id` as `rank_id` FROM `players`, `guild_members` WHERE `guild_members`.`rank_id` = ' . $rank_in_guild->getId() . ' AND `players`.`id` = `guild_members`.`player_id` ORDER BY `name`;');
|
||||
$players_with_rank = $db->query('SELECT `players`.`id` as `id`, `guild_members`.`rank_id` as `rank_id` FROM `players`, `guild_members` WHERE `guild_members`.`rank_id` = ' . $rank_in_guild->getId() . ' AND `players`.`id` = `guild_members`.`player_id` AND `' . $deletedColumn . '` = 0 ORDER BY `name`;');
|
||||
else if($db->hasTable('guild_membership'))
|
||||
$players_with_rank = $db->query('SELECT `players`.`id` as `id`, `guild_membership`.`rank_id` as `rank_id` FROM `players`, `guild_membership` WHERE `guild_membership`.`rank_id` = ' . $rank_in_guild->getId() . ' AND `players`.`id` = `guild_membership`.`player_id` ORDER BY `name`;');
|
||||
$players_with_rank = $db->query('SELECT `players`.`id` as `id`, `guild_membership`.`rank_id` as `rank_id` FROM `players`, `guild_membership` WHERE `guild_membership`.`rank_id` = ' . $rank_in_guild->getId() . ' AND `players`.`id` = `guild_membership`.`player_id` AND `' . $deletedColumn . '` = 0 ORDER BY `name`;');
|
||||
else
|
||||
$players_with_rank = $db->query('SELECT `id`, `rank_id` FROM `players` WHERE `rank_id` = ' . $rank_in_guild->getId() . ' AND `deleted` = 0;');
|
||||
$players_with_rank = $db->query('SELECT `id`, `rank_id` FROM `players` WHERE `rank_id` = ' . $rank_in_guild->getId() . ' AND `' . $deletedColumn . '` = 0;');
|
||||
|
||||
$players_with_rank_number = $players_with_rank->rowCount();
|
||||
if($players_with_rank_number > 0) {
|
||||
@@ -510,7 +517,12 @@ function template_place_holder($type): string
|
||||
$ret .= $debugBarRenderer->renderHead();
|
||||
}
|
||||
}
|
||||
elseif ($type === 'head_end') {
|
||||
$ret .= setting('core.html_head');
|
||||
}
|
||||
elseif ($type === 'body_start') {
|
||||
$ret .= setting('core.html_body');
|
||||
|
||||
$ret .= $twig->render('browsehappy.html.twig');
|
||||
|
||||
if (admin()) {
|
||||
@@ -521,6 +533,8 @@ function template_place_holder($type): string
|
||||
}
|
||||
}
|
||||
elseif($type === 'body_end') {
|
||||
$ret .= setting('core.html_footer');
|
||||
|
||||
$ret .= template_ga_code();
|
||||
if (isset($debugBar)) {
|
||||
$ret .= $debugBarRenderer->render();
|
||||
@@ -872,11 +886,12 @@ function getWorldName($id)
|
||||
*
|
||||
* @param string $to Recipient email address.
|
||||
* @param string $subject Subject of the message.
|
||||
* @param string $body Message body in html format.
|
||||
* @param string $body Message body in HTML format.
|
||||
* @param string $altBody Alternative message body, plain text.
|
||||
* @return bool PHPMailer status returned (success/failure).
|
||||
* @throws \PHPMailer\PHPMailer\Exception
|
||||
*/
|
||||
function _mail($to, $subject, $body, $altBody = '', $add_html_tags = true)
|
||||
function _mail(string $to, string $subject, string $body, string $altBody = ''): bool
|
||||
{
|
||||
global $mailer, $config;
|
||||
|
||||
@@ -894,12 +909,6 @@ function _mail($to, $subject, $body, $altBody = '', $add_html_tags = true)
|
||||
$mailer->clearAllRecipients();
|
||||
}
|
||||
|
||||
$signature_html = setting('core.mail_signature_html');
|
||||
if($add_html_tags && isset($body[0]))
|
||||
$tmp_body = '<html><head></head><body>' . $body . '<br/><br/>' . $signature_html . '</body></html>';
|
||||
else
|
||||
$tmp_body = $body . '<br/><br/>' . $signature_html;
|
||||
|
||||
$mailOption = setting('core.mail_option');
|
||||
if($mailOption == MAIL_SMTP)
|
||||
{
|
||||
@@ -926,6 +935,9 @@ function _mail($to, $subject, $body, $altBody = '', $add_html_tags = true)
|
||||
$mailer->isMail();
|
||||
}
|
||||
|
||||
$signature_html = setting('core.mail_signature_html');
|
||||
$tmp_body = $body . '<br/><br/>' . $signature_html;
|
||||
|
||||
$mailer->isHTML(isset($body[0]) > 0);
|
||||
$mailer->From = setting('core.mail_address');
|
||||
$mailer->Sender = setting('core.mail_address');
|
||||
@@ -1129,11 +1141,44 @@ function csrfProtect(): void
|
||||
}
|
||||
}
|
||||
|
||||
function getTopPlayers($limit = 5, $skill = 'level') {
|
||||
function getSkillIdByName(string $name): int|null
|
||||
{
|
||||
$skills = [
|
||||
'level' => POT::SKILL_LEVEL,
|
||||
'experience' => POT::SKILL_LEVEL,
|
||||
|
||||
'magic' => POT::SKILL_MAGIC,
|
||||
'maglevel' => POT::SKILL_MAGIC,
|
||||
|
||||
'balance' => SKILL_BALANCE,
|
||||
'frags' => SKILL_FRAGS,
|
||||
|
||||
'club' => POT::SKILL_CLUB,
|
||||
'sword' => POT::SKILL_SWORD,
|
||||
'axe' => POT::SKILL_AXE,
|
||||
'dist' => POT::SKILL_DIST,
|
||||
'distance' => POT::SKILL_DIST,
|
||||
'shield' => POT::SKILL_SHIELD,
|
||||
'shielding' => POT::SKILL_SHIELD,
|
||||
'fish' => POT::SKILL_FISH,
|
||||
'fishing' => POT::SKILL_FISH,
|
||||
];
|
||||
|
||||
return $skills[$name] ?? null;
|
||||
}
|
||||
|
||||
function getTopPlayers($limit = 5, $skill = POT::SKILL_LEVEL)
|
||||
{
|
||||
global $db;
|
||||
|
||||
if ($skill === 'level') {
|
||||
$skill = 'experience';
|
||||
$skillOriginal = $skill;
|
||||
|
||||
if (is_string($skill)) {
|
||||
$skill = getSkillIdByName($skill);
|
||||
}
|
||||
|
||||
if (!is_numeric($skill)) {
|
||||
throw new RuntimeException("getTopPlayers: Invalid skill: $skillOriginal");
|
||||
}
|
||||
|
||||
return Cache::remember("top_{$limit}_{$skill}", 2 * 60, function () use ($db, $limit, $skill) {
|
||||
@@ -1142,19 +1187,76 @@ function getTopPlayers($limit = 5, $skill = 'level') {
|
||||
'looktype', 'lookhead', 'lookbody', 'looklegs', 'lookfeet'
|
||||
];
|
||||
|
||||
if ($db->hasColumn('players', 'promotion')) {
|
||||
$columns[] = 'promotion';
|
||||
}
|
||||
|
||||
if ($db->hasColumn('players', 'lookaddons')) {
|
||||
$columns[] = 'lookaddons';
|
||||
}
|
||||
|
||||
return Player::query()
|
||||
if ($db->hasColumn('players', 'lookmount')) {
|
||||
$columns[] = 'lookmount';
|
||||
}
|
||||
|
||||
$query = 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($skill)
|
||||
->limit($limit)
|
||||
->orderByDesc('value');
|
||||
|
||||
if ($limit > 0) {
|
||||
$query->limit($limit);
|
||||
}
|
||||
|
||||
if ($skill >= POT::SKILL_FIRST && $skill <= POT::SKILL_LAST) { // skills
|
||||
if ($db->hasColumn('players', 'skill_fist')) {// tfs 1.0
|
||||
$skill_ids = array(
|
||||
POT::SKILL_FIST => 'skill_fist',
|
||||
POT::SKILL_CLUB => 'skill_club',
|
||||
POT::SKILL_SWORD => 'skill_sword',
|
||||
POT::SKILL_AXE => 'skill_axe',
|
||||
POT::SKILL_DIST => 'skill_dist',
|
||||
POT::SKILL_SHIELD => 'skill_shielding',
|
||||
POT::SKILL_FISH => 'skill_fishing',
|
||||
);
|
||||
|
||||
$query
|
||||
->addSelect($skill_ids[$skill] . ' as value')
|
||||
->orderByDesc($skill_ids[$skill] . '_tries');
|
||||
} else {
|
||||
$query
|
||||
->join('player_skills', 'player_skills.player_id', '=', 'players.id')
|
||||
->where('skillid', $skill)
|
||||
->addSelect('player_skills.value as value');
|
||||
}
|
||||
} else if ($skill == SKILL_FRAGS) // frags
|
||||
{
|
||||
if ($db->hasTable('player_killers')) {
|
||||
$query->addSelect(['value' => PlayerKillers::whereColumn('player_killers.player_id', 'players.id')->selectRaw('COUNT(*)')]);
|
||||
} else {
|
||||
$query->addSelect(['value' => PlayerDeath::unjustified()->whereColumn('player_deaths.killed_by', 'players.name')->selectRaw('COUNT(*)')]);
|
||||
}
|
||||
} else if ($skill == SKILL_BALANCE) // balance
|
||||
{
|
||||
$query
|
||||
->addSelect('players.balance as value');
|
||||
} else {
|
||||
if ($skill == POT::SKILL_MAGIC) {
|
||||
$query
|
||||
->addSelect('players.maglevel as value', 'players.maglevel')
|
||||
->orderByDesc('manaspent');
|
||||
} else { // level
|
||||
$query
|
||||
->addSelect('players.level as value', 'players.experience')
|
||||
->orderByDesc('experience');
|
||||
}
|
||||
}
|
||||
|
||||
return $query
|
||||
->get()
|
||||
->map(function ($e, $i) {
|
||||
$row = $e->toArray();
|
||||
@@ -1169,7 +1271,8 @@ function getTopPlayers($limit = 5, $skill = 'level') {
|
||||
});
|
||||
}
|
||||
|
||||
function deleteDirectory($dir, $ignore = array(), $contentOnly = false) {
|
||||
function deleteDirectory($dir, $ignore = array(), $contentOnly = false): bool
|
||||
{
|
||||
if(!file_exists($dir)) {
|
||||
return true;
|
||||
}
|
||||
@@ -1195,6 +1298,21 @@ function deleteDirectory($dir, $ignore = array(), $contentOnly = false) {
|
||||
return rmdir($dir);
|
||||
}
|
||||
|
||||
function ensureFolderExists($dir): void
|
||||
{
|
||||
if (!file_exists($dir)) {
|
||||
mkdir($dir, 0777, true);
|
||||
}
|
||||
}
|
||||
|
||||
function ensureIndexExists($dir): void
|
||||
{
|
||||
$dir = rtrim($dir, '/');
|
||||
if (!file_exists($file = $dir . '/index.html')) {
|
||||
touch($file);
|
||||
}
|
||||
}
|
||||
|
||||
function config($key) {
|
||||
global $config;
|
||||
if (is_array($key)) {
|
||||
@@ -1351,17 +1469,7 @@ function getCustomPage($name, &$success): string
|
||||
ob_end_clean();
|
||||
}
|
||||
else {
|
||||
$oldLoader = $twig->getLoader();
|
||||
|
||||
$twig_loader_array = new Twig_ArrayLoader(array(
|
||||
'content.html' => $page['body']
|
||||
));
|
||||
|
||||
$twig->setLoader($twig_loader_array);
|
||||
|
||||
$content .= $twig->render('content.html');
|
||||
|
||||
$twig->setLoader($oldLoader);
|
||||
$content .= $twig->renderInline($page['body']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1632,13 +1740,14 @@ function camelCaseToUnderscore($input)
|
||||
return ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_');
|
||||
}
|
||||
|
||||
function removeIfFirstSlash(&$text) {
|
||||
function removeIfFirstSlash(&$text): void
|
||||
{
|
||||
if(strpos($text, '/') === 0) {
|
||||
$text = str_replace_first('/', '', $text);
|
||||
}
|
||||
};
|
||||
|
||||
function escapeHtml($html) {
|
||||
function escapeHtml($html): string {
|
||||
return htmlspecialchars($html);
|
||||
}
|
||||
|
||||
@@ -1652,7 +1761,7 @@ function getGuildNameById($id)
|
||||
return false;
|
||||
}
|
||||
|
||||
function getGuildLogoById($id)
|
||||
function getGuildLogoById($id): string
|
||||
{
|
||||
$logo = 'default.gif';
|
||||
|
||||
@@ -1668,7 +1777,8 @@ function getGuildLogoById($id)
|
||||
return BASE_URL . GUILD_IMAGES_DIR . $logo;
|
||||
}
|
||||
|
||||
function displayErrorBoxWithBackButton($errors, $action = null) {
|
||||
function displayErrorBoxWithBackButton($errors, $action = null): void
|
||||
{
|
||||
global $twig;
|
||||
$twig->display('error_box.html.twig', ['errors' => $errors]);
|
||||
$twig->display('account.back_button.html.twig', [
|
||||
@@ -1696,6 +1806,49 @@ function getAccountIdentityColumn(): string
|
||||
return 'id';
|
||||
}
|
||||
|
||||
function isCanary(): bool
|
||||
{
|
||||
$dataPackDirectory = configLua('dataPackDirectory');
|
||||
return isset($dataPackDirectory);
|
||||
}
|
||||
|
||||
function getStatusUptimeReadable(int $uptime): string
|
||||
{
|
||||
$fullMinute = 60;
|
||||
$fullHour = (60 * $fullMinute);
|
||||
$fullDay = (24 * $fullHour);
|
||||
$fullMonth = (30 * $fullDay);
|
||||
$fullYear = (365 * $fullDay);
|
||||
|
||||
// years
|
||||
$years = floor($uptime / $fullYear);
|
||||
$y = ($years > 1 ? "$years years, " : ($years == 1 ? 'year, ' : ''));
|
||||
|
||||
$uptime -= $years * $fullYear;
|
||||
|
||||
// months
|
||||
$months = floor($uptime / $fullMonth);
|
||||
$m = ($months > 1 ? "$months months, " : ($months == 1 ? 'month, ' : ''));
|
||||
|
||||
$uptime -= $months * $fullMonth;
|
||||
|
||||
// days
|
||||
$days = floor($uptime / $fullDay);
|
||||
$d = ($days > 1 ? "$days days, " : ($days == 1 ? 'day, ' : ''));
|
||||
|
||||
$uptime -= $days * $fullDay;
|
||||
|
||||
// hours
|
||||
$hours = floor($uptime / $fullHour);
|
||||
|
||||
$uptime -= $hours * $fullHour;
|
||||
|
||||
// minutes
|
||||
$min = floor($uptime / $fullMinute);
|
||||
|
||||
return "{$y}{$m}{$d}{$hours}h {$min}m";
|
||||
}
|
||||
|
||||
// validator functions
|
||||
require_once SYSTEM . 'compat/base.php';
|
||||
|
||||
|
||||
@@ -14,10 +14,14 @@ use MyAAC\CsrfToken;
|
||||
use MyAAC\Hooks;
|
||||
use MyAAC\Plugins;
|
||||
use MyAAC\Models\Town;
|
||||
use MyAAC\Server\XML\Vocations;
|
||||
use MyAAC\Settings;
|
||||
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
ensureIndexExists(CACHE);
|
||||
ensureIndexExists(CACHE . 'twig/');
|
||||
|
||||
global $config;
|
||||
if(!isset($config['installed']) || !$config['installed']) {
|
||||
throw new RuntimeException('MyAAC has not been installed yet or there was error during installation. Please install again.');
|
||||
@@ -211,3 +215,5 @@ if (count($towns) <= 0) {
|
||||
|
||||
config(['towns', $towns]);
|
||||
unset($towns);
|
||||
|
||||
new Vocations();
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU Lesser General Public License, Version 3
|
||||
*/
|
||||
|
||||
use MyAAC\Models\Account as AccountModel;
|
||||
use MyAAC\Models\AccountAction;
|
||||
|
||||
/**
|
||||
* OTServ account abstraction.
|
||||
*
|
||||
@@ -40,7 +43,11 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
|
||||
*/
|
||||
private $data = array('email' => '', 'rlname' => '','location' => '', 'country' => '','web_flags' => 0, 'lastday' => 0, 'premdays' => 0, 'created' => 0);
|
||||
|
||||
public static $cache = array();
|
||||
private array $columns = ['password', 'email', 'rlname', 'location', 'country', 'web_flags', 'created'];
|
||||
|
||||
private array $optionalColumns = ['name', 'number', 'lastday', 'premdays', 'premium_ends_at', 'premend'];
|
||||
|
||||
public static array $cache = [];
|
||||
|
||||
const GRATIS_PREMIUM_DAYS = 65535;
|
||||
/**
|
||||
@@ -325,27 +332,50 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
if( !isset($this->data['id']) )
|
||||
{
|
||||
if (!isset($this->data['id'])) {
|
||||
throw new E_OTS_NotLoaded();
|
||||
}
|
||||
|
||||
$field = 'lastday';
|
||||
if($this->db->hasColumn('accounts', 'premend')) { // othire
|
||||
$field = 'premend';
|
||||
if(!isset($this->data['premend'])) {
|
||||
$this->data['premend'] = 0;
|
||||
}
|
||||
}
|
||||
else if($this->db->hasColumn('accounts', 'premium_ends_at')) {
|
||||
$field = 'premium_ends_at';
|
||||
if(!isset($this->data['premium_ends_at'])) {
|
||||
$this->data['premium_ends_at'] = 0;
|
||||
$defaultValues = [
|
||||
'premium_ends_at' => 0,
|
||||
'lastday' => 0,
|
||||
'premend' => 0,
|
||||
'premdays' => 0,
|
||||
];
|
||||
|
||||
foreach ($defaultValues as $key => $value) {
|
||||
if (!isset($this->data[$key])) {
|
||||
$this->data[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// UPDATE query on database
|
||||
$this->db->exec('UPDATE `accounts` SET ' . ($this->db->hasColumn('accounts', 'name') ? '`name` = ' . $this->db->quote($this->data['name']) . ',' : '') . '`password` = ' . $this->db->quote($this->data['password']) . ', `email` = ' . $this->db->quote($this->data['email']) . ', `rlname` = ' . $this->db->quote($this->data['rlname']) . ', `location` = ' . $this->db->quote($this->data['location']) . ', `country` = ' . $this->db->quote($this->data['country']) . ', `web_flags` = ' . (int) $this->data['web_flags'] . ', ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays` = ' . (int) $this->data['premdays'] . ',' : '') . '`' . $field . '` = ' . (int) $this->data[$field] . ' WHERE `id` = ' . $this->data['id']);
|
||||
$columns = $this->columns;
|
||||
foreach ($this->optionalColumns as $column) {
|
||||
if ($this->db->hasColumn('accounts', $column)) {
|
||||
$columns[] = $column;
|
||||
}
|
||||
}
|
||||
|
||||
$values = [];
|
||||
foreach ($columns as $column) {
|
||||
$value = $this->data[$column];
|
||||
|
||||
$values[$column] = $value;
|
||||
}
|
||||
|
||||
// updates existing player
|
||||
if( isset($this->data['id']) ) {
|
||||
AccountModel::where('id', $this->data['id'])->update($values);
|
||||
}
|
||||
// creates new player
|
||||
else {
|
||||
$values['created'] = time();
|
||||
|
||||
$account = AccountModel::create($values);
|
||||
|
||||
// ID of new player
|
||||
$this->data['id'] = $account->id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -443,8 +473,9 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
|
||||
throw new E_OTS_NotLoaded();
|
||||
}
|
||||
|
||||
if(isset($this->data['premium_ends_at']) || isset($this->data['premend'])) {
|
||||
$col = isset($this->data['premium_ends_at']) ? 'premium_ends_at' : 'premend';
|
||||
if(isset($this->data['premium_ends_at']) || isset($this->data['premend']) ||
|
||||
(isCanary() && isset($this->data['lastday']))) {
|
||||
$col = (isset($this->data['premium_ends_at']) ? 'premium_ends_at' : (isset($this->data['lastday']) ? 'lastday' : 'premend'));
|
||||
$ret = ceil(($this->data[$col] - time()) / (24 * 60 * 60));
|
||||
return max($ret, 0);
|
||||
}
|
||||
@@ -471,14 +502,16 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
|
||||
return $this->data['lastday'];
|
||||
}
|
||||
|
||||
public function isPremium()
|
||||
public function isPremium(): bool
|
||||
{
|
||||
if(isset($this->data['premium_ends_at'])) {
|
||||
return $this->data['premium_ends_at'] > time();
|
||||
if(isset($this->data['premium_ends_at']) || isset($this->data['premend']) ||
|
||||
(isCanary() && isset($this->data['lastday']))) {
|
||||
$col = (isset($this->data['premium_ends_at']) ? 'premium_ends_at' : (isset($this->data['lastday']) ? 'lastday' : 'premend'));
|
||||
return $this->data[$col] > time();
|
||||
}
|
||||
|
||||
if(isset($this->data['premend'])) {
|
||||
return $this->data['premend'] > time();
|
||||
if($this->data['premdays'] == self::GRATIS_PREMIUM_DAYS){
|
||||
return true;
|
||||
}
|
||||
|
||||
return ($this->data['premdays'] - (date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->data['lastday']))) - date("z", $this->data['lastday'])) > 0);
|
||||
@@ -501,11 +534,17 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
|
||||
* @since 0.7.5
|
||||
* @throws E_OTS_NotLoaded If account is not loaded.
|
||||
*/
|
||||
public function setPremDays($premdays)
|
||||
public function setPremDays($premdays): void
|
||||
{
|
||||
$this->data['premdays'] = (int) $premdays;
|
||||
$this->data['premend'] = time() + ($premdays * 24 * 60 * 60);
|
||||
$this->data['premium_ends_at'] = time() + ($premdays * 24 * 60 * 60);
|
||||
|
||||
$premiumTimeInSeconds = time() + ($premdays * 24 * 60 * 60);
|
||||
$this->data['premend'] = $premiumTimeInSeconds;
|
||||
$this->data['premium_ends_at'] = $premiumTimeInSeconds;
|
||||
|
||||
if (isCanary()) {
|
||||
$this->data['lastday'] = $premiumTimeInSeconds;
|
||||
}
|
||||
}
|
||||
|
||||
public function setRLName($name)
|
||||
@@ -1004,26 +1043,16 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
|
||||
|
||||
public function logAction($action)
|
||||
{
|
||||
$ip = get_browser_real_ip();
|
||||
if(!str_contains($ip, ":")) {
|
||||
$ipv6 = '0';
|
||||
}
|
||||
else {
|
||||
$ipv6 = $ip;
|
||||
$ip = '';
|
||||
AccountAction::create([
|
||||
'account_id' => $this->getId(),
|
||||
'ip' => get_browser_real_ip(),
|
||||
'date' => time(),
|
||||
'action' => $action,
|
||||
]);
|
||||
}
|
||||
|
||||
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).')');
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
@@ -26,10 +26,12 @@ use MyAAC\Cache\Cache;
|
||||
*/
|
||||
class OTS_DB_MySQL extends OTS_Base_DB
|
||||
{
|
||||
private $has_table_cache = array();
|
||||
private $has_column_cache = array();
|
||||
private bool $hasCacheChanged = false;
|
||||
private array $has_table_cache = [];
|
||||
private array $has_column_cache = [];
|
||||
private array $get_column_info_cache = [];
|
||||
|
||||
private $clearCacheAfter = false;
|
||||
private bool $clearCacheAfter = false;
|
||||
/**
|
||||
* Creates database connection.
|
||||
*
|
||||
@@ -119,6 +121,11 @@ class OTS_DB_MySQL extends OTS_Base_DB
|
||||
if($cache->fetch('database_columns', $tmp) && $tmp) {
|
||||
$this->has_column_cache = unserialize($tmp);
|
||||
}
|
||||
|
||||
$tmp = null;
|
||||
if($cache->fetch('database_columns_info', $tmp) && $tmp) {
|
||||
$this->get_column_info_cache = unserialize($tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,11 +162,13 @@ class OTS_DB_MySQL extends OTS_Base_DB
|
||||
if ($this->clearCacheAfter) {
|
||||
$cache->delete('database_tables');
|
||||
$cache->delete('database_columns');
|
||||
$cache->delete('database_columns_info');
|
||||
$cache->delete('database_checksum');
|
||||
}
|
||||
else {
|
||||
else if ($this->hasCacheChanged) {
|
||||
$cache->set('database_tables', serialize($this->has_table_cache), 3600);
|
||||
$cache->set('database_columns', serialize($this->has_column_cache), 3600);
|
||||
$cache->set('database_columns_info', serialize($this->get_column_info_cache), 3600);
|
||||
$cache->set('database_checksum', serialize(sha1($config['database_host'] . '.' . $config['database_name'])), 3600);
|
||||
}
|
||||
}
|
||||
@@ -209,7 +218,8 @@ class OTS_DB_MySQL extends OTS_Base_DB
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function hasTable($name) {
|
||||
public function hasTable($name): bool
|
||||
{
|
||||
if(isset($this->has_table_cache[$name])) {
|
||||
return $this->has_table_cache[$name];
|
||||
}
|
||||
@@ -217,12 +227,15 @@ class OTS_DB_MySQL extends OTS_Base_DB
|
||||
return $this->hasTableInternal($name);
|
||||
}
|
||||
|
||||
private function hasTableInternal($name) {
|
||||
global $config;
|
||||
return ($this->has_table_cache[$name] = $this->query('SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `TABLE_SCHEMA` = ' . $this->quote($config['database_name']) . ' AND `TABLE_NAME` = ' . $this->quote($name) . ' LIMIT 1;')->rowCount() > 0);
|
||||
private function hasTableInternal($name): bool
|
||||
{
|
||||
$this->hasCacheChanged = true;
|
||||
|
||||
return ($this->has_table_cache[$name] = $this->query('SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `TABLE_SCHEMA` = ' . $this->quote(config('database_name')) . ' AND `TABLE_NAME` = ' . $this->quote($name) . ' LIMIT 1;')->rowCount() > 0);
|
||||
}
|
||||
|
||||
public function hasColumn($table, $column) {
|
||||
public function hasColumn($table, $column): bool
|
||||
{
|
||||
if(isset($this->has_column_cache[$table . '.' . $column])) {
|
||||
return $this->has_column_cache[$table . '.' . $column];
|
||||
}
|
||||
@@ -230,8 +243,10 @@ class OTS_DB_MySQL extends OTS_Base_DB
|
||||
return $this->hasColumnInternal($table, $column);
|
||||
}
|
||||
|
||||
private function hasColumnInternal($table, $column) {
|
||||
return $this->hasTable($table) && ($this->has_column_cache[$table . '.' . $column] = count($this->query('SHOW COLUMNS FROM `' . $table . "` LIKE '" . $column . "'")->fetchAll()) > 0);
|
||||
private function hasColumnInternal($table, $column): bool {
|
||||
$this->hasCacheChanged = true;
|
||||
|
||||
return $this->hasTable($table) && ($this->has_column_cache[$table . '.' . $column] = count($this->query('SHOW COLUMNS FROM `' . $table . "` LIKE " . $this->quote($column))->fetchAll()) > 0);
|
||||
}
|
||||
|
||||
public function hasTableAndColumns(string $table, array $columns = []): bool
|
||||
@@ -247,7 +262,56 @@ class OTS_DB_MySQL extends OTS_Base_DB
|
||||
return true;
|
||||
}
|
||||
|
||||
public function revalidateCache() {
|
||||
public function getColumnInfo(string $table, string $column): bool|array
|
||||
{
|
||||
if(isset($this->get_column_info_cache[$table . '.' . $column])) {
|
||||
return $this->get_column_info_cache[$table . '.' . $column];
|
||||
}
|
||||
|
||||
return $this->getColumnInfoInternal($table, $column);
|
||||
}
|
||||
|
||||
private function getColumnInfoInternal(string $table, string $column): bool|array
|
||||
{
|
||||
if (!$this->hasTable($table) || !$this->hasColumn($table, $column)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->hasCacheChanged = true;
|
||||
|
||||
$formatResult = function ($result) {
|
||||
return [
|
||||
'field' => $result['Field'],
|
||||
'type' => $result['Type'],
|
||||
'null' => strtolower($result['Null']),
|
||||
'key' => strtolower($result['Key'] ?? ''),
|
||||
'default' => $result['Default'],
|
||||
'extra' => $result['Extra'],
|
||||
];
|
||||
};
|
||||
|
||||
$query = $this->query('SHOW COLUMNS FROM `' . $table . "` LIKE " . $this->quote($column));
|
||||
$rowCount = $query->rowCount();
|
||||
if ($rowCount > 1) {
|
||||
$tmp = [];
|
||||
|
||||
$results = $query->fetchAll(PDO::FETCH_ASSOC);
|
||||
foreach ($results as $result) {
|
||||
$tmp[] = $formatResult($result);
|
||||
}
|
||||
|
||||
return ($this->get_column_info_cache[$table . '.' . $column] = $tmp);
|
||||
}
|
||||
else if ($rowCount == 1) {
|
||||
$result = $query->fetch(PDO::FETCH_ASSOC);
|
||||
return ($this->get_column_info_cache[$table . '.' . $column] = $formatResult($result));
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public function revalidateCache(): void
|
||||
{
|
||||
foreach($this->has_table_cache as $key => $value) {
|
||||
$this->hasTableInternal($key);
|
||||
}
|
||||
@@ -262,6 +326,21 @@ class OTS_DB_MySQL extends OTS_Base_DB
|
||||
$this->hasColumnInternal($explode[0], $explode[1]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach($this->get_column_info_cache as $key => $value) {
|
||||
$explode = explode('.', $key);
|
||||
if(!isset($this->has_table_cache[$explode[0]])) { // first check if table exist
|
||||
$this->hasTableInternal($explode[0]);
|
||||
}
|
||||
|
||||
if($this->has_table_cache[$explode[0]]) {
|
||||
$this->hasColumnInternal($explode[0], $explode[1]);
|
||||
}
|
||||
|
||||
if($this->has_table_cache[$explode[0]]) {
|
||||
$this->getColumnInfoInternal($explode[0], $explode[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function setClearCacheAfter($clearCache)
|
||||
|
||||
@@ -1,20 +1,6 @@
|
||||
<?php
|
||||
$__load = array();
|
||||
/*
|
||||
'loss_experience' => NULL,
|
||||
'loss_items' => NULL,
|
||||
'guild_info' => NULL,
|
||||
'skull_type' => NULL,
|
||||
'skull_time' => NULL,
|
||||
'blessings' => NULL,
|
||||
'direction' => NULL,
|
||||
'stamina' => NULL,
|
||||
'world_id' => NULL,
|
||||
'online' => NULL,
|
||||
'deletion' => NULL,
|
||||
'promotion' => NULL,
|
||||
'marriage' => NULL
|
||||
);*/
|
||||
|
||||
use MyAAC\Models\Player as PlayerModel;
|
||||
|
||||
/**#@+
|
||||
* @version 0.0.1
|
||||
@@ -109,6 +95,10 @@ class OTS_Player extends OTS_Row_DAO
|
||||
POT::SKILL_FISH => array('value' => 0, 'tries' => 0)
|
||||
);
|
||||
|
||||
private array $columns = ['name', 'account_id', 'group_id', 'sex', 'vocation', 'experience', 'level', 'maglevel', 'health', 'healthmax', 'mana', 'manamax', 'manaspent', 'soul', 'lookbody', 'lookfeet', 'lookhead', 'looklegs', 'looktype', 'posx', 'posy', 'posz', 'lastlogin', 'lastlogout', 'lastip', 'town_id', 'balance', 'created', 'comment', 'hide'];
|
||||
|
||||
private array $optionalColumns = ['cap', 'skull', 'skull_type', 'skull_time', 'loss_experience', 'loss_mana', 'loss_skills', 'loss_items', 'loss_containers', 'guildnick', 'rank_id', 'promotion', 'direction', 'blessings', 'stamina', 'lookaddons', 'save', 'conditions', 'world_id', 'online', 'deletion', 'deleted', 'marriage'];
|
||||
|
||||
private static array $playersOnline;
|
||||
/**
|
||||
* Magic PHP5 method.
|
||||
@@ -133,90 +123,14 @@ class OTS_Player extends OTS_Row_DAO
|
||||
*/
|
||||
public function load($id, $fields = null, $load_skills = true)
|
||||
{
|
||||
global $__load;
|
||||
|
||||
if(!isset($__load['loss_experience']))
|
||||
{
|
||||
$loss = '';
|
||||
if($this->db->hasColumn('players', 'loss_experience')) {
|
||||
$loss = ', `loss_experience`, `loss_mana`, `loss_skills`';
|
||||
$columns = $this->columns;
|
||||
foreach ($this->optionalColumns as $column) {
|
||||
if ($this->db->hasColumn('players', $column)) {
|
||||
$columns[] = $column;
|
||||
}
|
||||
|
||||
$__load['loss_experience'] = $loss;
|
||||
}
|
||||
|
||||
if(!isset($__load['loss_items']))
|
||||
{
|
||||
$loss_items = '';
|
||||
if($this->db->hasColumn('players', 'loss_items')) {
|
||||
$loss_items = ', `loss_items`, `loss_containers`';
|
||||
}
|
||||
|
||||
$__load['loss_items'] = $loss_items;
|
||||
}
|
||||
|
||||
if(!isset($__load['guild_info']))
|
||||
{
|
||||
$guild_info = '';
|
||||
if(!$this->db->hasTable('guild_members') && $this->db->hasColumn('players', 'guildnick')) {
|
||||
$guild_info = ', `guildnick`, `rank_id`';
|
||||
}
|
||||
|
||||
$__load['guild_info'] = $guild_info;
|
||||
}
|
||||
|
||||
if(!isset($__load['skull_type']))
|
||||
{
|
||||
$skull_type = 'skull';
|
||||
if($this->db->hasColumn('players', 'skull_type')) {
|
||||
$skull_type = 'skull_type';
|
||||
}
|
||||
|
||||
$__load['skull_type'] = $skull_type;
|
||||
}
|
||||
|
||||
if(!isset($__load['skull_time']))
|
||||
{
|
||||
$skull_time = 'skulltime';
|
||||
if($this->db->hasColumn('players', 'skull_time')) {
|
||||
$skull_time = 'skull_time';
|
||||
}
|
||||
|
||||
$__load['skull_time'] = $skull_time;
|
||||
}
|
||||
|
||||
if(!isset($__load['blessings'])) {
|
||||
$__load['blessings'] = $this->db->hasColumn('players', 'blessings');
|
||||
}
|
||||
if(!isset($__load['direction'])) {
|
||||
$__load['direction'] = $this->db->hasColumn('players', 'direction');
|
||||
}
|
||||
if(!isset($__load['stamina'])) {
|
||||
$__load['stamina'] = $this->db->hasColumn('players', 'stamina');
|
||||
}
|
||||
if(!isset($__load['world_id'])) {
|
||||
$__load['world_id'] = $this->db->hasColumn('players', 'world_id');
|
||||
}
|
||||
if(!isset($__load['online'])) {
|
||||
$__load['online'] = $this->db->hasColumn('players', 'online');
|
||||
}
|
||||
if(!isset($__load['deletion'])) {
|
||||
$__load['deletion'] = $this->db->hasColumn('players', 'deletion');
|
||||
}
|
||||
if(!isset($__load['promotion'])) {
|
||||
$__load['promotion'] = $this->db->hasColumn('players', 'promotion');
|
||||
}
|
||||
if(!isset($__load['marriage'])) {
|
||||
$__load['marriage'] = $this->db->hasColumn('players', 'marriage');
|
||||
}
|
||||
|
||||
if(isset($fields)) { // load only what we wish
|
||||
if(in_array('promotion', $fields)) {
|
||||
if(!$this->db->hasColumn('players', 'promotion')) {
|
||||
unset($fields[array_search('promotion', $fields)]);
|
||||
}
|
||||
}
|
||||
|
||||
if(in_array('deleted', $fields)) {
|
||||
if($this->db->hasColumn('players', 'deletion')) {
|
||||
unset($fields[array_search('deleted', $fields)]);
|
||||
@@ -224,21 +138,21 @@ class OTS_Player extends OTS_Row_DAO
|
||||
}
|
||||
}
|
||||
|
||||
if(in_array('online', $fields)) {
|
||||
if(!$this->db->hasColumn('players', 'online')) {
|
||||
unset($fields[array_search('online', $fields)]);
|
||||
$columns = [];
|
||||
foreach ($fields as $field) {
|
||||
if ($this->db->hasColumn('players', $field)) {
|
||||
$columns[] = $field;
|
||||
}
|
||||
}
|
||||
$this->data = $this->db->query('SELECT ' . implode(', ', $fields) . ' FROM `players` WHERE `id` = ' . (int)$id)->fetch();
|
||||
}
|
||||
else {
|
||||
// SELECT query on database
|
||||
$this->data = $this->db->query('SELECT `id`, `name`, `account_id`, `group_id`, `sex`, `vocation`, `experience`, `level`, `maglevel`, `health`, `healthmax`, `mana`, `manamax`, `manaspent`, `soul`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`' . ($this->db->hasColumn('players', 'lookaddons') ? ', `lookaddons`' : '') . ', `posx`, `posy`, `posz`, `cap`, `lastlogin`, `lastlogout`, `lastip`, `save`, `conditions`, `' . $__load['skull_time'] . '` as `skulltime`, `' . $__load['skull_type'] . '` as `skull`' . $__load['guild_info'] . ', `town_id`' . $__load['loss_experience'] . $__load['loss_items'] . ', `balance`' . ($__load['blessings'] ? ', `blessings`' : '') . ($__load['direction'] ? ', `direction`' : '') . ($__load['stamina'] ? ', `stamina`' : '') . ($__load['world_id'] ? ', `world_id`' : '') . ($__load['online'] ? ', `online`' : '') . ', `' . ($__load['deletion'] ? 'deletion' : 'deleted') . '`' . ($__load['promotion'] ? ', `promotion`' : '') . ($__load['marriage'] ? ', `marriage`' : '') . ', `comment`, `created`, `hide` FROM `players` WHERE `id` = ' . (int)$id)->fetch();
|
||||
}
|
||||
|
||||
array_unshift($columns, 'id');
|
||||
|
||||
$query = PlayerModel::where('id', $id)->first($columns);
|
||||
$this->data = $query ? $query->toArray() : [];
|
||||
|
||||
// loads skills
|
||||
if( $this->isLoaded() && $load_skills)
|
||||
{
|
||||
if( $this->isLoaded() && $load_skills) {
|
||||
if($this->db->hasColumn('players', 'skill_fist')) {
|
||||
|
||||
$skill_ids = array(
|
||||
@@ -318,153 +232,65 @@ class OTS_Player extends OTS_Row_DAO
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
$skull_type = 'skull';
|
||||
if($this->db->hasColumn('players', 'skull_type')) {
|
||||
$skull_type = 'skull_type';
|
||||
$defaultValues = [
|
||||
'cap' => 0,
|
||||
'skull' => 0,
|
||||
'skull_type' => 0,
|
||||
'skull_time' => 0,
|
||||
'loss_experience' => 100,
|
||||
'loss_mana' => 100,
|
||||
'loss_skills' => 100,
|
||||
'loss_items' => 100,
|
||||
'loss_containers' => 100,
|
||||
'guildnick' => '',
|
||||
'rank_id' => 0,
|
||||
'promotion' => 0,
|
||||
'direction' => 0,
|
||||
'blessings' => 0,
|
||||
'stamina' => 0,
|
||||
'lookaddons' => 0,
|
||||
'save' => 1,
|
||||
'conditions' => '',
|
||||
'town_id' => 1,
|
||||
'world_id' => 1,
|
||||
'online' => 0,
|
||||
'deletion' => 0,
|
||||
'deleted' => 0,
|
||||
'marriage' => 0,
|
||||
];
|
||||
|
||||
foreach ($defaultValues as $key => $value) {
|
||||
if (!isset($this->data[$key])) {
|
||||
$this->data[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$skull_time = 'skulltime';
|
||||
if($this->db->hasColumn('players', 'skull_time')) {
|
||||
$skull_time = 'skull_time';
|
||||
$columns = $this->columns;
|
||||
foreach ($this->optionalColumns as $column) {
|
||||
if ($this->db->hasColumn('players', $column)) {
|
||||
$columns[] = $column;
|
||||
}
|
||||
}
|
||||
|
||||
if(!isset($this->data['loss_experience']))
|
||||
$this->data['loss_experience'] = 100;
|
||||
$values = [];
|
||||
foreach ($columns as $column) {
|
||||
$value = $this->data[$column];
|
||||
|
||||
if(!isset($this->data['loss_mana']))
|
||||
$this->data['loss_mana'] = 100;
|
||||
|
||||
if(!isset($this->data['loss_skills']))
|
||||
$this->data['loss_skills'] = 100;
|
||||
|
||||
if(!isset($this->data['loss_items']))
|
||||
$this->data['loss_items'] = 10;
|
||||
|
||||
if(!isset($this->data['loss_containers']))
|
||||
$this->data['loss_containers'] = 100;
|
||||
|
||||
if(!isset($this->data['guildnick']))
|
||||
$this->data['guildnick'] = '';
|
||||
|
||||
if(!isset($this->data['rank_id']))
|
||||
$this->data['rank_id'] = 0;
|
||||
|
||||
if(!isset($this->data['promotion']))
|
||||
$this->data['promotion'] = 0;
|
||||
|
||||
if(!isset($this->data['direction']))
|
||||
$this->data['direction'] = 0;
|
||||
|
||||
if(!isset($this->data['conditions']))
|
||||
$this->data['conditions'] = '';
|
||||
|
||||
if(!isset($this->data['town_id']))
|
||||
$this->data['town_id'] = 1;
|
||||
$values[$column] = $value;
|
||||
}
|
||||
|
||||
// updates existing player
|
||||
if( isset($this->data['id']) )
|
||||
{
|
||||
$loss = '';
|
||||
if($this->db->hasColumn('players', 'loss_experience')) {
|
||||
$loss = ', `loss_experience` = ' . $this->data['loss_experience'] . ', `loss_mana` = ' . $this->data['loss_mana'] . ', `loss_skills` = ' . $this->data['loss_skills'];
|
||||
}
|
||||
|
||||
$loss_items = '';
|
||||
if($this->db->hasColumn('players', 'loss_items')) {
|
||||
$loss_items = ', `loss_items` = ' . $this->data['loss_items'] . ', `loss_containers` = ' . $this->data['loss_containers'];
|
||||
}
|
||||
|
||||
$guild_info = '';
|
||||
if(!$this->db->hasTable('guild_members') && $this->db->hasColumn('players', 'guildnick')) {
|
||||
$guild_info = ', `guildnick` = ' . $this->db->quote($this->data['guildnick']) . ', ' . $this->db->fieldName('rank_id') . ' = ' . $this->data['rank_id'];
|
||||
}
|
||||
|
||||
$direction = '';
|
||||
if($this->db->hasColumn('players', 'direction')) {
|
||||
$direction = ', `direction` = ' . $this->db->quote($this->data['direction']);
|
||||
}
|
||||
|
||||
$blessings = '';
|
||||
if($this->db->hasColumn('players', 'blessings')) {
|
||||
$blessings = ', `blessings` = ' . $this->db->quote($this->data['blessings']);
|
||||
}
|
||||
|
||||
$stamina = '';
|
||||
if($this->db->hasColumn('players', 'stamina')) {
|
||||
$stamina = ', `stamina` = ' . $this->db->quote($this->data['stamina']);
|
||||
}
|
||||
|
||||
$lookaddons = '';
|
||||
if($this->db->hasColumn('players', 'lookaddons')) {
|
||||
$lookaddons = ', `lookaddons` = ' . $this->db->quote($this->data['lookaddons']);
|
||||
}
|
||||
|
||||
// UPDATE query on database
|
||||
$this->db->query('UPDATE ' . $this->db->tableName('players') . ' SET ' . $this->db->fieldName('name') . ' = ' . $this->db->quote($this->data['name']) . ', ' . $this->db->fieldName('account_id') . ' = ' . $this->data['account_id'] . ', ' . $this->db->fieldName('group_id') . ' = ' . $this->data['group_id'] . ', ' . $this->db->fieldName('sex') . ' = ' . $this->data['sex'] . ', ' . $this->db->fieldName('vocation') . ' = ' . $this->data['vocation'] . ', ' . $this->db->fieldName('experience') . ' = ' . $this->data['experience'] . ', ' . $this->db->fieldName('level') . ' = ' . $this->data['level'] . ', ' . $this->db->fieldName('maglevel') . ' = ' . $this->data['maglevel'] . ', ' . $this->db->fieldName('health') . ' = ' . $this->data['health'] . ', ' . $this->db->fieldName('healthmax') . ' = ' . $this->data['healthmax'] . ', ' . $this->db->fieldName('mana') . ' = ' . $this->data['mana'] . ', ' . $this->db->fieldName('manamax') . ' = ' . $this->data['manamax'] . ', ' . $this->db->fieldName('manaspent') . ' = ' . $this->data['manaspent'] . ', ' . $this->db->fieldName('soul') . ' = ' . $this->data['soul'] . ', ' . $this->db->fieldName('lookbody') . ' = ' . $this->data['lookbody'] . ', ' . $this->db->fieldName('lookfeet') . ' = ' . $this->data['lookfeet'] . ', ' . $this->db->fieldName('lookhead') . ' = ' . $this->data['lookhead'] . ', ' . $this->db->fieldName('looklegs') . ' = ' . $this->data['looklegs'] . ', ' . $this->db->fieldName('looktype') . ' = ' . $this->data['looktype'] . $lookaddons . ', ' . $this->db->fieldName('posx') . ' = ' . $this->data['posx'] . ', ' . $this->db->fieldName('posy') . ' = ' . $this->data['posy'] . ', ' . $this->db->fieldName('posz') . ' = ' . $this->data['posz'] . ', ' . $this->db->fieldName('cap') . ' = ' . $this->data['cap'] . ', ' . $this->db->fieldName('lastlogin') . ' = ' . $this->data['lastlogin'] . ', ' . $this->db->fieldName('lastlogout') . ' = ' . $this->data['lastlogout'] . ', ' . $this->db->fieldName('lastip') . ' = ' . $this->db->quote($this->data['lastip']) . ', ' . $this->db->fieldName('save') . ' = ' . (int) $this->data['save'] . ', ' . $this->db->fieldName('conditions') . ' = ' . $this->db->quote($this->data['conditions']) . ', `' . $skull_time . '` = ' . $this->data['skulltime'] . ', `' . $skull_type . '` = ' . (int) $this->data['skull'] . $guild_info . ', ' . $this->db->fieldName('town_id') . ' = ' . $this->data['town_id'] . $loss . $loss_items . ', ' . $this->db->fieldName('balance') . ' = ' . $this->data['balance'] . $blessings . $stamina . $direction . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id']);
|
||||
if( isset($this->data['id']) ) {
|
||||
PlayerModel::where('id', $this->data['id'])->update($values);
|
||||
}
|
||||
// creates new player
|
||||
else
|
||||
{
|
||||
$loss = '';
|
||||
$loss_data = '';
|
||||
if($this->db->hasColumn('players', 'loss_experience')) {
|
||||
$loss = ', `loss_experience`, `loss_mana`, `loss_skills`';
|
||||
$loss_data = ', ' . $this->data['loss_experience'] . ', ' . $this->data['loss_mana'] . ', ' . $this->data['loss_skills'];
|
||||
}
|
||||
else {
|
||||
$values['created'] = time();
|
||||
|
||||
$loss_items = '';
|
||||
$loss_items_data = '';
|
||||
if($this->db->hasColumn('players', 'loss_items')) {
|
||||
$loss_items = ', `loss_items`, `loss_containers`';
|
||||
$loss_items_data = ', ' . $this->data['loss_items'] . ', ' . $this->data['loss_containers'];
|
||||
}
|
||||
$player = PlayerModel::create($values);
|
||||
|
||||
$guild_info = '';
|
||||
$guild_info_data = '';
|
||||
if(!$this->db->hasTable('guild_members') && $this->db->hasColumn('players', 'guildnick')) {
|
||||
$guild_info = ', `guildnick`, `rank_id`';
|
||||
$guild_info_data = ', ' . $this->db->quote($this->data['guildnick']) . ', ' . $this->data['rank_id'];
|
||||
}
|
||||
|
||||
$promotion = '';
|
||||
$promotion_data = '';
|
||||
if($this->db->hasColumn('players', 'promotion')) {
|
||||
$promotion = ', `promotion`';
|
||||
$promotion_data = ', ' . $this->data['promotion'];
|
||||
}
|
||||
|
||||
$direction = '';
|
||||
$direction_data = '';
|
||||
if($this->db->hasColumn('players', 'direction')) {
|
||||
$direction = ', `direction`';
|
||||
$direction_data = ', ' . $this->data['direction'];
|
||||
}
|
||||
|
||||
$blessings = '';
|
||||
$blessings_data = '';
|
||||
if($this->db->hasColumn('players', 'blessings')) {
|
||||
$blessings = ', `blessings`';
|
||||
$blessings_data = ', ' . $this->data['blessings'];
|
||||
}
|
||||
|
||||
$stamina = '';
|
||||
$stamina_data = '';
|
||||
if($this->db->hasColumn('players', 'stamina')) {
|
||||
$stamina = ', `stamina`';
|
||||
$stamina_data = ', ' . $this->data['stamina'];
|
||||
}
|
||||
|
||||
$lookaddons = '';
|
||||
$lookaddons_data = '';
|
||||
if($this->db->hasColumn('players', 'lookaddons')) {
|
||||
$lookaddons = ', `lookaddons`';
|
||||
$lookaddons_data = ', ' . $this->data['lookaddons'];
|
||||
}
|
||||
|
||||
// INSERT query on database
|
||||
$this->db->query('INSERT INTO `players` (`name`, `account_id`, `group_id`, `sex`, `vocation`, `experience`, `level`, `maglevel`, `health`, `healthmax`, `mana`, `manamax`, `manaspent`, `soul`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`' . $lookaddons . ', `posx`, `posy`, `posz`, `cap`, `lastlogin`, `lastlogout`, `lastip`, `save`, `conditions`, `' . $skull_time . '`, `' . $skull_type . '`' . $guild_info . ', `town_id`' . $loss . $loss_items . ', `balance`' . $blessings . $stamina . $direction . ', `created`' . $promotion . ', `comment`) VALUES (' . $this->db->quote($this->data['name']) . ', ' . $this->data['account_id'] . ', ' . $this->data['group_id'] . ', ' . $this->data['sex'] . ', ' . $this->data['vocation'] . ', ' . $this->data['experience'] . ', ' . $this->data['level'] . ', ' . $this->data['maglevel'] . ', ' . $this->data['health'] . ', ' . $this->data['healthmax'] . ', ' . $this->data['mana'] . ', ' . $this->data['manamax'] . ', ' . $this->data['manaspent'] . ', ' . $this->data['soul'] . ', ' . $this->data['lookbody'] . ', ' . $this->data['lookfeet'] . ', ' . $this->data['lookhead'] . ', ' . $this->data['looklegs'] . ', ' . $this->data['looktype'] . $lookaddons_data . ', ' . $this->data['posx'] . ', ' . $this->data['posy'] . ', ' . $this->data['posz'] . ', ' . $this->data['cap'] . ', ' . $this->data['lastlogin'] . ', ' . $this->data['lastlogout'] . ', ' . $this->data['lastip'] . ', ' . (int) $this->data['save'] . ', ' . $this->db->quote($this->data['conditions']) . ', ' . $this->data['skulltime'] . ', ' . (int) $this->data['skull'] . $guild_info_data . ', ' . $this->data['town_id'] . $loss_data . $loss_items_data . ', ' . $this->data['balance'] . $blessings_data . $stamina_data . $direction_data . ', ' . time() . $promotion_data . ', "")');
|
||||
// ID of new group
|
||||
$this->data['id'] = $this->db->lastInsertId();
|
||||
// ID of new player
|
||||
$this->data['id'] = $player->id;
|
||||
}
|
||||
|
||||
// updates skills - doesn't matter if we have just created character - trigger inserts new skills
|
||||
@@ -490,7 +316,7 @@ class OTS_Player extends OTS_Row_DAO
|
||||
$set .= ',';
|
||||
}
|
||||
|
||||
$skills = $this->db->query('UPDATE `players` SET ' . $set . ' WHERE `id` = ' . $this->data['id']);
|
||||
$this->db->query('UPDATE `players` SET ' . $set . ' WHERE `id` = ' . $this->data['id']);
|
||||
}
|
||||
else if($this->db->hasTable('player_skills')) {
|
||||
foreach($this->skills as $id => $skill)
|
||||
@@ -748,21 +574,25 @@ class OTS_Player extends OTS_Row_DAO
|
||||
|
||||
public function isDeleted()
|
||||
{
|
||||
$field = 'deleted';
|
||||
$column = 'deleted';
|
||||
if($this->db->hasColumn('players', 'deletion'))
|
||||
$field = 'deletion';
|
||||
$column = 'deletion';
|
||||
|
||||
if( !isset($this->data[$field]) )
|
||||
if( !isset($this->data[$column]) )
|
||||
{
|
||||
throw new E_OTS_NotLoaded();
|
||||
}
|
||||
|
||||
return $this->data[$field] > 0;
|
||||
return $this->data[$column] > 0;
|
||||
}
|
||||
|
||||
public function setDeleted($deleted)
|
||||
{
|
||||
$this->data['deleted'] = (int) $deleted;
|
||||
$column = 'deleted';
|
||||
if($this->db->hasColumn('players', 'deletion'))
|
||||
$column = 'deletion';
|
||||
|
||||
$this->data[$column] = (int) $deleted;
|
||||
}
|
||||
|
||||
public function isOnline()
|
||||
@@ -852,13 +682,7 @@ class OTS_Player extends OTS_Row_DAO
|
||||
throw new E_OTS_NotLoaded();
|
||||
}
|
||||
|
||||
if(isset($this->data['promotion'])) {
|
||||
global $config;
|
||||
if((int)$this->data['promotion'] > 0)
|
||||
return ($this->data['vocation'] + ($this->data['promotion'] * $config['vocations_amount']));
|
||||
}
|
||||
|
||||
return $this->data['vocation'];
|
||||
return \OTS_Toolbox::getVocationFromPromotion($this->data['vocation'], $this->data['promotion'] ?? 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1574,12 +1398,7 @@ class OTS_Player extends OTS_Row_DAO
|
||||
*/
|
||||
public function getCap()
|
||||
{
|
||||
if( !isset($this->data['cap']) )
|
||||
{
|
||||
throw new E_OTS_NotLoaded();
|
||||
}
|
||||
|
||||
return $this->data['cap'];
|
||||
return $this->data['cap'] ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1792,12 +1611,12 @@ class OTS_Player extends OTS_Row_DAO
|
||||
*/
|
||||
public function getSkullTime()
|
||||
{
|
||||
if( !isset($this->data['skulltime']) )
|
||||
{
|
||||
throw new E_OTS_NotLoaded();
|
||||
$column = 'skulltime';
|
||||
if($this->db->hasColumn('players', 'skull_time')) {
|
||||
$column = 'skull_time';
|
||||
}
|
||||
|
||||
return $this->data['skulltime'];
|
||||
return $this->data[$column] ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1811,7 +1630,12 @@ class OTS_Player extends OTS_Row_DAO
|
||||
*/
|
||||
public function setSkullTime($skulltime)
|
||||
{
|
||||
$this->data['skulltime'] = (int) $skulltime;
|
||||
$column = 'skulltime';
|
||||
if($this->db->hasColumn('players', 'skull_time')) {
|
||||
$column = 'skull_time';
|
||||
}
|
||||
|
||||
$this->data[$column] = (int) $skulltime;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3250,6 +3074,10 @@ class OTS_Player extends OTS_Row_DAO
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function setData(array $data): void{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic PHP5 method.
|
||||
*
|
||||
|
||||
@@ -97,6 +97,8 @@ class OTS_ServerInfo
|
||||
return new OTS_Buffer($data);
|
||||
}
|
||||
|
||||
log_append('status-error.log', "Cannot connect to {$this->server}:{$this->port} - Error code: $error, message: $message");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU Lesser General Public License, Version 3
|
||||
*/
|
||||
|
||||
use MyAAC\Server\XML\Vocations;
|
||||
|
||||
/**
|
||||
* Toolbox for common operations.
|
||||
*
|
||||
@@ -110,14 +112,21 @@ class OTS_Toolbox
|
||||
$list->setFilter($filter);
|
||||
return $list;
|
||||
}
|
||||
|
||||
public static function getVocationName($id, $promotion = 0): string
|
||||
public static function getVocationFromPromotion($id, $promotion = 0): int
|
||||
{
|
||||
if($promotion > 0) {
|
||||
$id = ($id + ($promotion * config('vocations_amount')));
|
||||
for ($i = 0; $i < $promotion; $i++) {
|
||||
if ($_id = Vocations::getPromoted($id)) {
|
||||
$id = $_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return config('vocations')[$id] ?? 'Unknown';
|
||||
return $id;
|
||||
}
|
||||
|
||||
public static function getVocationName($id, $promotion = 0): string {
|
||||
return config('vocations')[self::getVocationFromPromotion($id, $promotion)] ?? 'Unknown';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ $locale['step_database_error_mysql_connect_3'] = 'MySQL ist nicht richtig konfig
|
||||
$locale['step_database_error_mysql_connect_4'] = 'MySQL-Server läuft nicht.';
|
||||
$locale['step_database_error_schema'] = 'Fehler beim Importieren des Schemas:';
|
||||
$locale['step_database_success_schema'] = '$PREFIX$ Tabellen wurden erfolgreich installiert.';
|
||||
$locale['step_database_success_import_data'] = 'Import von Daten für Tabellen was erfolgreich.';
|
||||
$locale['step_database_error_file'] = '$FILE$ konnte nicht geöffnet werden. Bitte kopieren Sie diesen Inhalt und fügen Sie ihn dort ein:';
|
||||
$locale['step_database_adding_field'] = 'Folgendes Feld wurde hinzugefügt: ';
|
||||
$locale['step_database_modifying_field'] = 'Folgendes Feld wurde geändert: ';
|
||||
|
||||
@@ -83,6 +83,7 @@ $locale['step_database_error_mysql_connect_3'] = 'MySQL is not configured proper
|
||||
$locale['step_database_error_mysql_connect_4'] = 'MySQL server is not running.';
|
||||
$locale['step_database_error_schema'] = 'Error while importing schema:';
|
||||
$locale['step_database_success_schema'] = 'Successfully installed $PREFIX$ tables.';
|
||||
$locale['step_database_success_import_data'] = 'Successfully imported base data for tables.';
|
||||
$locale['step_database_error_file'] = '$FILE$ couldn\'t be opened. Please copy this content and paste there:';
|
||||
$locale['step_database_adding_field'] = 'Adding field';
|
||||
$locale['step_database_modifying_field'] = 'Modifying field';
|
||||
|
||||
@@ -81,7 +81,8 @@ $locale['step_database_error_mysql_connect_2'] = 'Możliwe przyczyny:';
|
||||
$locale['step_database_error_mysql_connect_3'] = 'MySQL nie jest poprawnie skonfigurowane w <i>config.lua</i>.';
|
||||
$locale['step_database_error_mysql_connect_4'] = 'Serwer MySQL nie jest uruchomiony.';
|
||||
$locale['step_database_error_schema'] = 'Błąd podczas importowania struktury bazy danych:';
|
||||
$locale['step_database_success_schema'] = 'Pomyślnie zainstalowano tabele $PREFIX$.';
|
||||
$locale['step_database_success_schema'] = 'Pomyślnie zaimportowano tabele $PREFIX$.';
|
||||
$locale['step_database_success_import_data'] = 'Pomyślnie załadowano bazowe dane dla tabel.';
|
||||
$locale['step_database_error_file'] = '$FILE$ nie mógł zostać otwarty. Proszę skopiować zawartość pola tekstowego i wkleić do tego pliku:';
|
||||
$locale['step_database_adding_field'] = 'Dodawanie pola';
|
||||
$locale['step_database_modifying_field'] = 'Modyfikacja pola';
|
||||
|
||||
@@ -34,8 +34,10 @@ if($logged) {
|
||||
$twig->addGlobal('account_logged', $account_logged);
|
||||
}
|
||||
|
||||
if (!defined('IGNORE_SET_LAST_VISIT') || !IGNORE_SET_LAST_VISIT) {
|
||||
setSession('last_visit', time());
|
||||
if(defined('PAGE')) {
|
||||
setSession('last_page', PAGE);
|
||||
}
|
||||
setSession('last_uri', $_SERVER['REQUEST_URI']);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
*/
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
global $db;
|
||||
|
||||
// database migrations
|
||||
$tmp = '';
|
||||
if(fetchDatabaseConfig('database_version', $tmp)) { // we got version
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
use MyAAC\Models\Player as PlayerModel;
|
||||
use MyAAC\Settings;
|
||||
|
||||
function updateHighscoresIdsHidden(): void
|
||||
@@ -10,12 +11,22 @@ function updateHighscoresIdsHidden(): void
|
||||
return;
|
||||
}
|
||||
|
||||
$query = $db->query("SELECT `id` FROM `players` WHERE (`name` = " . $db->quote("Rook Sample") . " OR `name` = " . $db->quote("Sorcerer Sample") . " OR `name` = " . $db->quote("Druid Sample") . " OR `name` = " . $db->quote("Paladin Sample") . " OR `name` = " . $db->quote("Knight Sample") . " OR `name` = " . $db->quote("Account Manager") . ") ORDER BY `id`;");
|
||||
$players = PlayerModel::where('name', 'Rook Sample')
|
||||
->orWhere('name', 'Sorcerer Sample')
|
||||
->orWhere('name', 'Druid Sample')
|
||||
->orWhere('name', 'Paladin Sample')
|
||||
->orWhere('name', 'Knight Sample')
|
||||
->orWhere('name', 'Monk Sample')
|
||||
->orWhere('name', 'Account Manager')
|
||||
->orderBy('id')
|
||||
->select('id')
|
||||
->get();
|
||||
|
||||
$highscores_ignored_ids = array();
|
||||
if ($query->rowCount() > 0) {
|
||||
foreach ($query->fetchAll() as $result)
|
||||
$highscores_ignored_ids[] = $result['id'];
|
||||
$highscores_ignored_ids = [];
|
||||
if (count($players) > 0) {
|
||||
foreach ($players as $result) {
|
||||
$highscores_ignored_ids[] = $result->id;
|
||||
}
|
||||
} else {
|
||||
$highscores_ignored_ids[] = 0;
|
||||
}
|
||||
|
||||
8
system/migrations/46-account_emails_verify.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
CREATE TABLE `myaac_account_emails_verify`
|
||||
(
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`account_id` int NOT NULL,
|
||||
`hash` varchar(32) NOT NULL,
|
||||
`sent_at` int NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
|
||||
24
system/migrations/46.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* @var OTS_DB_MySQL $db
|
||||
*/
|
||||
|
||||
$up = function () use ($db) {
|
||||
if ($db->hasColumn('accounts', 'email_hash')) {
|
||||
$db->dropColumn('accounts', 'email_hash');
|
||||
}
|
||||
|
||||
if (!$db->hasTable(TABLE_PREFIX . 'account_emails_verify')) {
|
||||
$db->query(file_get_contents(__DIR__ . '/46-account_emails_verify.sql'));
|
||||
}
|
||||
};
|
||||
|
||||
$down = function () use ($db) {
|
||||
if (!$db->hasColumn('accounts', 'email_hash')) {
|
||||
$db->addColumn('accounts', 'email_hash', "varchar(32) NOT NULL DEFAULT ''");
|
||||
}
|
||||
|
||||
if ($db->hasTable(TABLE_PREFIX . 'account_emails_verify')) {
|
||||
$db->dropTable(TABLE_PREFIX . 'account_emails_verify');
|
||||
}
|
||||
};
|
||||
42
system/migrations/47.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?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) {
|
||||
$accountActionsInfo = $db->getColumnInfo(TABLE_PREFIX . 'account_actions', 'account_id');
|
||||
if ($accountActionsInfo && is_array($accountActionsInfo) && $accountActionsInfo['key'] == 'pri') {
|
||||
$db->query("ALTER TABLE `myaac_account_actions` DROP KEY `account_id`;");
|
||||
}
|
||||
|
||||
if (!$db->hasColumn(TABLE_PREFIX . 'account_actions', 'id')) {
|
||||
$db->addColumn(TABLE_PREFIX . 'account_actions', 'id', 'INT 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';");
|
||||
|
||||
if ($db->hasColumn(TABLE_PREFIX . 'account_actions', 'ipv6')) {
|
||||
$db->dropColumn(TABLE_PREFIX . 'account_actions', 'ipv6');
|
||||
}
|
||||
};
|
||||
|
||||
$down = function () use ($db) {
|
||||
if ($db->hasColumn(TABLE_PREFIX . 'account_actions', 'id')) {
|
||||
$db->query("ALTER TABLE `" . TABLE_PREFIX . "account_actions` DROP `id`;");
|
||||
}
|
||||
|
||||
$db->query("ALTER TABLE `" . TABLE_PREFIX . "account_actions` ADD KEY (`account_id`);");
|
||||
|
||||
if (!$db->hasColumn(TABLE_PREFIX . 'account_actions', 'ipv6')) {
|
||||
$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;");
|
||||
};
|
||||
16
system/migrations/48.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* @var OTS_DB_MySQL $db
|
||||
*/
|
||||
|
||||
$up = function () use ($db) {
|
||||
if (!$db->hasColumn(TABLE_PREFIX . 'menu', 'access')) {
|
||||
$db->addColumn(TABLE_PREFIX . 'menu', 'access', 'TINYINT NOT NULL DEFAULT 0 AFTER `link`');
|
||||
}
|
||||
};
|
||||
|
||||
$down = function () use ($db) {
|
||||
if ($db->hasColumn(TABLE_PREFIX . 'menu', 'access')) {
|
||||
$db->dropColumn(TABLE_PREFIX . 'menu', 'access');
|
||||
}
|
||||
};
|
||||
91
system/migrations/49.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/**
|
||||
* @var OTS_DB_MySQL $db
|
||||
*/
|
||||
|
||||
use MyAAC\Models\Account as AccountModel;
|
||||
|
||||
$time = time();
|
||||
|
||||
$accountId = getSession('account') ?? 1;
|
||||
if (!defined('MYAAC_INSTALL')) {
|
||||
$accountModel = AccountModel::where('web_flags', 3)->first();
|
||||
if ($accountModel) {
|
||||
$accountId = $accountModel->id;
|
||||
}
|
||||
}
|
||||
|
||||
function insert_sample_if_not_exist($p): void
|
||||
{
|
||||
global $time, $accountId;
|
||||
|
||||
$player = new OTS_Player();
|
||||
$player->find($p['name']);
|
||||
|
||||
if (!$player->isLoaded()) {
|
||||
|
||||
$player->setData([
|
||||
'name' => $p['name'],
|
||||
'group_id' => 1,
|
||||
'account_id' => $accountId,
|
||||
'level' => $p['level'],
|
||||
'vocation' => $p['vocation_id'],
|
||||
'health' => $p['health'],
|
||||
'healthmax' => $p['healthmax'],
|
||||
'experience' => $p['experience'],
|
||||
'lookbody' => 118,
|
||||
'lookfeet' => 114,
|
||||
'lookhead' => 38,
|
||||
'looklegs' => 57,
|
||||
'looktype' => $p['looktype'],
|
||||
'maglevel' => 0,
|
||||
'mana' => $p['mana'],
|
||||
'manamax' => $p['manamax'],
|
||||
'manaspent' => 0,
|
||||
'soul' => $p['soul'],
|
||||
'town_id' => 1,
|
||||
'posx' => 1000,
|
||||
'posy' => 1000,
|
||||
'posz' => 7,
|
||||
'conditions' => '',
|
||||
'cap' => $p['cap'],
|
||||
'sex' => 1,
|
||||
'lastlogin' => $time,
|
||||
'lastip' => 2130706433,
|
||||
'save' => 1,
|
||||
'lastlogout' => $time,
|
||||
'balance' => 0,
|
||||
'created' => $time,
|
||||
'hide' => 1,
|
||||
'comment' => '',
|
||||
]);
|
||||
|
||||
$player->save();
|
||||
}
|
||||
}
|
||||
|
||||
$up = function () use ($db) {
|
||||
if (!$db->hasTable('players')) {
|
||||
return;
|
||||
}
|
||||
|
||||
insert_sample_if_not_exist(['name' => 'Rook Sample', 'level' => 1, 'vocation_id' => 0, 'health' => 150, 'healthmax' => 150, 'experience' => 0, 'looktype' => 130, 'mana' => 0, 'manamax' => 0, 'soul' => 100, 'cap' => 400]);
|
||||
insert_sample_if_not_exist(['name' => 'Sorcerer Sample', 'level' => 8, 'vocation_id' => 1, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 130, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470]);
|
||||
insert_sample_if_not_exist(['name' => 'Druid Sample', 'level' => 8, 'vocation_id' => 2, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 130, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470]);
|
||||
insert_sample_if_not_exist(['name' => 'Paladin Sample', 'level' => 8, 'vocation_id' => 3, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 129, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470]);
|
||||
insert_sample_if_not_exist(['name' => 'Knight Sample', 'level' => 8, 'vocation_id' => 4, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 131, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470]);
|
||||
insert_sample_if_not_exist(['name' => 'Monk Sample', 'level' => 8, 'vocation_id' => 9, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 128, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470]);
|
||||
|
||||
if (defined('MYAAC_INSTALL')) {
|
||||
global $locale;
|
||||
|
||||
success($locale['step_database_imported_players']);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/20.php';
|
||||
updateHighscoresIdsHidden();
|
||||
};
|
||||
|
||||
$down = function () {
|
||||
// nothing
|
||||
};
|
||||
11
system/migrations/50-gallery.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
CREATE TABLE IF NOT EXISTS `myaac_gallery`
|
||||
(
|
||||
`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;
|
||||
16
system/migrations/50.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* @var OTS_DB_MySQL $db
|
||||
*/
|
||||
|
||||
$up = function () use ($db) {
|
||||
if ($db->hasTable(TABLE_PREFIX . 'gallery')) {
|
||||
$db->dropTable(TABLE_PREFIX . 'gallery');
|
||||
}
|
||||
};
|
||||
|
||||
$down = function () use ($db) {
|
||||
if (!$db->hasTable(TABLE_PREFIX . 'gallery')) {
|
||||
$db->query(file_get_contents(__DIR__ . '/50-gallery.sql'));
|
||||
}
|
||||
};
|
||||
@@ -9,7 +9,7 @@ $up = function () use ($db) {
|
||||
}
|
||||
};
|
||||
|
||||
$up = function () use ($db) {
|
||||
$down = function () use ($db) {
|
||||
if (!$db->hasColumn(TABLE_PREFIX . 'screenshots', 'name')) {
|
||||
$db->addColumn(TABLE_PREFIX . 'screenshots', 'name', 'VARCHAR(30) NOT NULL');
|
||||
}
|
||||
|
||||
29
system/pages/#examples/top-5.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* Example of using getTopPlayers() function
|
||||
* to display the best players for each skill
|
||||
*/
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
$skills = [
|
||||
'magic', 'level',
|
||||
'balance', 'frags',
|
||||
POT::SKILL_FIST, POT::SKILL_CLUB,
|
||||
POT::SKILL_SWORD, POT::SKILL_AXE,
|
||||
POT::SKILL_DISTANCE, POT::SKILL_SHIELD,
|
||||
POT::SKILL_FISH
|
||||
];
|
||||
|
||||
foreach ($skills as $skill) {?>
|
||||
<ul>
|
||||
<?php
|
||||
echo '<strong>' . ucwords(is_string($skill) ? $skill : getSkillName($skill)) . '</strong>';
|
||||
foreach (getTopPlayers(5, $skill) as $player) {?>
|
||||
<li><?= $player['rank'] . '. ' . $player['name'] . ' - ' . $player['value']; ?></li>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
<?php
|
||||
}
|
||||
|
||||
@@ -19,18 +19,17 @@ if(!$logged) {
|
||||
|
||||
csrfProtect();
|
||||
|
||||
$new_password = $_POST['newpassword'] ?? NULL;
|
||||
$new_password_confirm = $_POST['newpassword_confirm'] ?? NULL;
|
||||
$old_password = $_POST['oldpassword'] ?? NULL;
|
||||
if(empty($new_password) && empty($new_password_confirm) && empty($old_password)) {
|
||||
$new_password = $_POST['new_password'] ?? null;
|
||||
$new_password_confirm = $_POST['new_password_confirm'] ?? null;
|
||||
$old_password = $_POST['old_password'] ?? null;
|
||||
if(is_null($new_password) && is_null($new_password_confirm) && is_null($old_password)) {
|
||||
$twig->display('account.change-password.html.twig');
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
if(empty($new_password) || empty($new_password_confirm) || empty($old_password)){
|
||||
$errors[] = 'Please fill in form.';
|
||||
}
|
||||
$password_strlen = strlen($new_password);
|
||||
|
||||
if($new_password != $new_password_confirm) {
|
||||
$errors[] = 'The new passwords do not match!';
|
||||
}
|
||||
@@ -41,10 +40,13 @@ else
|
||||
}
|
||||
|
||||
/** @var OTS_Account $account_logged */
|
||||
$old_password = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $old_password);
|
||||
if($old_password != $account_logged->getPassword()) {
|
||||
$old_password_hashed = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $old_password);
|
||||
if($old_password_hashed != $account_logged->getPassword()) {
|
||||
$errors[] = 'Current password is incorrect!';
|
||||
}
|
||||
else if ($old_password == $new_password) {
|
||||
$errors[] = 'The old password is same as the new password!';
|
||||
}
|
||||
|
||||
$hooks->trigger(HOOK_ACCOUNT_CHANGE_PASSWORD_POST);
|
||||
}
|
||||
|
||||
@@ -51,6 +51,8 @@ if($player_name != null) {
|
||||
'description' => 'The character information has been changed.'
|
||||
));
|
||||
$show_form = false;
|
||||
|
||||
$hooks->trigger(HOOK_ACCOUNT_CHARACTERS_CHANGE_COMMENT_AFTER_SUCCESS, ['player' => $player]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -70,9 +72,11 @@ if($show_form) {
|
||||
}
|
||||
|
||||
if(isset($player) && $player) {
|
||||
$twig->display('account.characters.change-comment.html.twig', array(
|
||||
'player' => $player->toArray()
|
||||
));
|
||||
$_player = $player->toArray();
|
||||
$_player['id'] = $player->id; // Hack, as it's somehow missing in the toArray() function
|
||||
|
||||
$twig->display('account.characters.change-comment.html.twig', [
|
||||
'player' => $_player,
|
||||
]);
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
use MyAAC\Models\Account;
|
||||
use MyAAC\Models\AccountEmailVerify;
|
||||
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
@@ -20,16 +21,20 @@ if(empty($hash)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!Account::where('email_hash', $hash)->exists()) {
|
||||
note("Your email couldn't be verified. Please contact staff to do it manually.");
|
||||
// by default link is valid for 30 days
|
||||
$accountEmailVerify = AccountEmailVerify::where('hash', $hash)->where('sent_at', '>', time() - 30 * 24 * 60 * 60)->first();
|
||||
if(!$accountEmailVerify) {
|
||||
note("Wrong link or link has expired.");
|
||||
}
|
||||
else
|
||||
{
|
||||
$accountModel = Account::where('email_hash', $hash)->where('email_verified', 0)->first();
|
||||
$accountModel = Account::where('id', $accountEmailVerify->account_id)->where('email_verified', 0)->first();
|
||||
if ($accountModel) {
|
||||
$accountModel->email_verified = 1;
|
||||
$accountModel->save();
|
||||
|
||||
AccountEmailVerify::where('account_id', $accountModel->id)->delete();
|
||||
|
||||
success('You have now verified your e-mail, this will increase the security of your account. Thank you for doing this. You can now <a href=' . getLink('account/manage') . '>log in</a>.');
|
||||
|
||||
$account = new OTS_Account();
|
||||
@@ -39,6 +44,6 @@ else
|
||||
}
|
||||
}
|
||||
else {
|
||||
error('Link has expired.');
|
||||
error('Your account is already verified.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
use MyAAC\CreateCharacter;
|
||||
use MyAAC\Models\AccountEmailVerify;
|
||||
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
$title = 'Create Account';
|
||||
@@ -191,6 +192,21 @@ if($save)
|
||||
|
||||
$new_account->setPassword(encrypt($password));
|
||||
$new_account->setEMail($email);
|
||||
|
||||
$settingAccountPremiumDays = setting('core.account_premium_days');
|
||||
if($settingAccountPremiumDays && $settingAccountPremiumDays > 0) {
|
||||
$new_account->setPremDays($settingAccountPremiumDays);
|
||||
|
||||
if (!isCanary()) {
|
||||
$lastDay = 0;
|
||||
if($settingAccountPremiumDays != 0 && $settingAccountPremiumDays != OTS_Account::GRATIS_PREMIUM_DAYS) {
|
||||
$lastDay = time();
|
||||
}
|
||||
|
||||
$new_account->setLastLogin($lastDay);
|
||||
}
|
||||
}
|
||||
|
||||
$new_account->save();
|
||||
|
||||
$hooks->trigger(HOOK_ACCOUNT_CREATE_AFTER_SAVED, ['account' => $new_account]);
|
||||
@@ -205,22 +221,6 @@ if($save)
|
||||
$new_account->setCustomField('country', $country);
|
||||
}
|
||||
|
||||
$settingAccountPremiumDays = setting('core.account_premium_days');
|
||||
if($settingAccountPremiumDays && $settingAccountPremiumDays > 0) {
|
||||
if($db->hasColumn('accounts', 'premend')) { // othire
|
||||
$new_account->setCustomField('premend', time() + $settingAccountPremiumDays * 86400);
|
||||
}
|
||||
else { // rest
|
||||
if ($db->hasColumn('accounts', 'premium_ends_at')) { // TFS 1.4+
|
||||
$new_account->setCustomField('premium_ends_at', time() + $settingAccountPremiumDays * (60 * 60 * 24));
|
||||
}
|
||||
else {
|
||||
$new_account->setCustomField('premdays', $settingAccountPremiumDays);
|
||||
$new_account->setCustomField('lastday', time());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$accountDefaultPremiumPoints = setting('core.account_premium_points');
|
||||
if($accountDefaultPremiumPoints > 0) {
|
||||
$new_account->setCustomField('premium_points', $accountDefaultPremiumPoints);
|
||||
@@ -244,7 +244,12 @@ if($save)
|
||||
if(setting('core.mail_enabled') && setting('core.account_mail_verify'))
|
||||
{
|
||||
$hash = md5(generateRandomString(16, true, true) . $email);
|
||||
$new_account->setCustomField('email_hash', $hash);
|
||||
|
||||
AccountEmailVerify::create([
|
||||
'account_id' => $new_account->getId(),
|
||||
'hash' => $hash,
|
||||
'sent_at' => time(),
|
||||
]);
|
||||
|
||||
$verify_url = getLink('account/confirm-email/' . $hash);
|
||||
$body_html = $twig->render('mail.account.verify.html.twig', array(
|
||||
@@ -361,7 +366,7 @@ if(!empty($errors))
|
||||
|
||||
if (setting('core.account_country')) {
|
||||
$countries = array();
|
||||
foreach (array('pl', 'se', 'br', 'us', 'gb') as $c)
|
||||
foreach (setting('core.account_countries_most_popular') ?? [] as $c)
|
||||
$countries[$c] = $config['countries'][$c];
|
||||
|
||||
$countries['--'] = '----------';
|
||||
|
||||
@@ -48,7 +48,9 @@ if(!empty($login_account) && !empty($login_password))
|
||||
)
|
||||
{
|
||||
if (setting('core.account_mail_verify') && (int)$account_logged->getCustomField('email_verified') !== 1) {
|
||||
$errors[] = 'Your account is not verified. Please verify your email address. If the message is not coming check the SPAM folder in your E-Mail client.';
|
||||
$link = getLink('account/resend-email-verify');
|
||||
$errors[] = 'Your account is not verified. Please verify your email address. If the message is not coming check the SPAM folder in your E-Mail client.<br/>' .
|
||||
'You can resend the Email here: <a href="' . $link . '">' . $link . '</a>';
|
||||
} else {
|
||||
session_regenerate_id();
|
||||
setSession('account', $account_logged->getId());
|
||||
|
||||
@@ -9,540 +9,11 @@
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
$title = 'Lost Account Interface';
|
||||
$title = 'Lost Account';
|
||||
|
||||
if(!setting('core.mail_enabled'))
|
||||
{
|
||||
echo '<b>Account maker is not configured to send e-mails, you can\'t use Lost Account Interface. Contact with admin to get help.</b>';
|
||||
if(!setting('core.mail_enabled')) {
|
||||
echo "<b>Account maker is not configured to send e-mails, you can't use Lost Account Interface. Contact with admin to get help.</b>";
|
||||
return;
|
||||
}
|
||||
|
||||
$action_type = isset($_REQUEST['action_type']) ? $_REQUEST['action_type'] : '';
|
||||
if($action == '')
|
||||
{
|
||||
$twig->display('account.lost.form.html.twig');
|
||||
}
|
||||
else if($action == 'step1' && $action_type == '') {
|
||||
$twig->display('account.lost.noaction.html.twig');
|
||||
}
|
||||
elseif($action == 'step1' && $action_type == 'email')
|
||||
{
|
||||
$nick = stripslashes($_REQUEST['nick']);
|
||||
if(Validator::characterName($nick))
|
||||
{
|
||||
$player = new OTS_Player();
|
||||
$account = new OTS_Account();
|
||||
$player->find($nick);
|
||||
if($player->isLoaded())
|
||||
$account = $player->getAccount();
|
||||
|
||||
if($account->isLoaded())
|
||||
{
|
||||
if($account->getCustomField('email_next') < time())
|
||||
echo 'Please enter e-mail to account with this character.<BR>
|
||||
<form action="' . getLink('account/lost') . '?action=sendcode" method=post>
|
||||
<input type=hidden name="character">
|
||||
<table cellspacing=1 cellpadding=4 border=0 width=100%>
|
||||
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Please enter e-mail to account</B></TD></TR>
|
||||
<TR><TD BGCOLOR="'.$config['darkborder'].'">
|
||||
Character: <INPUT TYPE=text NAME="nick" VALUE="'.$nick.'" SIZE="40" readonly="readonly"><BR>
|
||||
E-mail to account:<INPUT TYPE=text NAME="email" VALUE="" SIZE="40"><BR>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<BR>
|
||||
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
|
||||
' . $twig->render('buttons.submit.html.twig') . '</div>
|
||||
</TD></TR></FORM></TABLE></TABLE>';
|
||||
else
|
||||
{
|
||||
$insec = (int)$account->getCustomField('email_next') - time();
|
||||
$minutesleft = floor($insec / 60);
|
||||
$secondsleft = $insec - ($minutesleft * 60);
|
||||
$timeleft = $minutesleft.' minutes '.$secondsleft.' seconds';
|
||||
echo 'Account of selected character (<b>'.$nick.'</b>) received e-mail in last '.ceil(setting('core.mail_lost_account_interval') / 60).' minutes. You must wait '.$timeleft.' before you can use Lost Account Interface again.';
|
||||
}
|
||||
}
|
||||
else
|
||||
echo 'Player or account of player <b>' . $nick . '</b> doesn\'t exist.';
|
||||
}
|
||||
else
|
||||
echo 'Invalid player name format. If you have other characters on account try with other name.';
|
||||
echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
|
||||
<a href="' . getLink('account/lost') . '" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
|
||||
</TD></TR></FORM></TABLE></TABLE>';
|
||||
}
|
||||
elseif($action == 'sendcode')
|
||||
{
|
||||
$email = $_REQUEST['email'];
|
||||
$nick = stripslashes($_REQUEST['nick']);
|
||||
if(Validator::characterName($nick))
|
||||
{
|
||||
$player = new OTS_Player();
|
||||
$account = new OTS_Account();
|
||||
$player->find($nick);
|
||||
if($player->isLoaded())
|
||||
$account = $player->getAccount();
|
||||
|
||||
if($account->isLoaded())
|
||||
{
|
||||
if($account->getCustomField('email_next') < time())
|
||||
{
|
||||
if($account->getEMail() == $email)
|
||||
{
|
||||
$newcode = generateRandomString(30, true, false, true);
|
||||
$mailBody = '
|
||||
You asked to reset your ' . $config['lua']['serverName'] . ' password.<br/>
|
||||
<p>Account name: '.$account->getName().'</p>
|
||||
<br />
|
||||
To do so, please click this link:
|
||||
<p><a href="' . getLink('account/lost') . '?action=checkcode&code='.$newcode.'&character='.urlencode($nick).'">' . getLink('account/lost') . '?action=checkcode&code='.$newcode.'&character='.urlencode($nick).'</a></p>
|
||||
<p>or open page: <i>' . getLink('account/lost') . '?action=checkcode</i> and in field "code" write <b>'.$newcode.'</b></p>
|
||||
<br/>
|
||||
<p>If you did not request a password change, you may ignore this message and your password will remain unchanged.';
|
||||
|
||||
$account_mail = $account->getCustomField('email');
|
||||
if(_mail($account_mail, $config['lua']['serverName'].' - Recover your account', $mailBody))
|
||||
{
|
||||
$account->setCustomField('email_code', $newcode);
|
||||
$account->setCustomField('email_next', (time() + setting('core.mail_lost_account_interval')));
|
||||
echo '<br />Details about steps required to recover your account has been sent to <b>' . $account_mail . '</b>. You should receive this email within 15 minutes. Please check your inbox/spam directory.';
|
||||
}
|
||||
else
|
||||
{
|
||||
$account->setCustomField('email_next', (time() + 60));
|
||||
echo '<br /><p class="error">An error occurred while sending email! Try again later or contact with admin. For Admin: More info can be found in system/logs/mailer-error.log</p>';
|
||||
}
|
||||
}
|
||||
else
|
||||
echo 'Invalid e-mail to account of character <b>'.$nick.'</b>. Try again.';
|
||||
}
|
||||
else
|
||||
{
|
||||
$insec = (int)$account->getCustomField('email_next') - time();
|
||||
$minutesleft = floor($insec / 60);
|
||||
$secondsleft = $insec - ($minutesleft * 60);
|
||||
$timeleft = $minutesleft.' minutes '.$secondsleft.' seconds';
|
||||
echo 'Account of selected character (<b>'.$nick.'</b>) received e-mail in last '.ceil(setting('core.mail_lost_account_interval') / 60).' minutes. You must wait '.$timeleft.' before you can use Lost Account Interface again.';
|
||||
}
|
||||
}
|
||||
else
|
||||
echo 'Player or account of player <b>'.$nick.'</b> doesn\'t exist.';
|
||||
}
|
||||
else
|
||||
echo 'Invalid player name format. If you have other characters on account try with other name.';
|
||||
echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
|
||||
<a href="' . getLink('account/lost') . '?action=step1&action_type=email&nick='.urlencode($nick).'" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
|
||||
</TD></TR></FORM></TABLE></TABLE>';
|
||||
}
|
||||
elseif($action == 'step1' && $action_type == 'reckey')
|
||||
{
|
||||
$nick = stripslashes($_REQUEST['nick']);
|
||||
if(Validator::characterName($nick))
|
||||
{
|
||||
$player = new OTS_Player();
|
||||
$account = new OTS_Account();
|
||||
$player->find($nick);
|
||||
if($player->isLoaded())
|
||||
$account = $player->getAccount();
|
||||
if($account->isLoaded())
|
||||
{
|
||||
$account_key = $account->getCustomField('key');
|
||||
if(!empty($account_key))
|
||||
{
|
||||
echo 'If you enter right recovery key you will see form to set new e-mail and password to account. To this e-mail will be send your new password and account name.<BR>
|
||||
<FORM ACTION="' . getLink('account/lost') . '?action=step2" METHOD=post>
|
||||
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
|
||||
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Please enter your recovery key</B></TD></TR>
|
||||
<TR><TD BGCOLOR="'.$config['darkborder'].'">
|
||||
Character name: <INPUT TYPE=text NAME="nick" VALUE="'.$nick.'" SIZE="40" readonly="readonly"><BR />
|
||||
Recovery key: <INPUT TYPE=text NAME="key" VALUE="" SIZE="40"><BR>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<BR>
|
||||
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
|
||||
' . $twig->render('buttons.submit.html.twig') . '</div>
|
||||
</TD></TR></FORM></TABLE></TABLE>';
|
||||
}
|
||||
else
|
||||
echo 'Account of this character has no recovery key!';
|
||||
}
|
||||
else
|
||||
echo 'Player or account of player <b>'.$nick.'</b> doesn\'t exist.';
|
||||
}
|
||||
else
|
||||
echo 'Invalid player name format. If you have other characters on account try with other name.';
|
||||
echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
|
||||
<a href="' . getLink('account/lost') . '" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
|
||||
</TD></TR></FORM></TABLE></TABLE>';
|
||||
}
|
||||
elseif($action == 'step2')
|
||||
{
|
||||
$rec_key = trim($_REQUEST['key']);
|
||||
$nick = stripslashes($_REQUEST['nick']);
|
||||
if(Validator::characterName($nick))
|
||||
{
|
||||
$player = new OTS_Player();
|
||||
$account = new OTS_Account();
|
||||
$player->find($nick);
|
||||
if($player->isLoaded())
|
||||
$account = $player->getAccount();
|
||||
if($account->isLoaded())
|
||||
{
|
||||
$account_key = $account->getCustomField('key');
|
||||
if(!empty($account_key))
|
||||
{
|
||||
if($account_key == $rec_key)
|
||||
{
|
||||
echo '<script type="text/javascript">
|
||||
function validate_required(field,alerttxt)
|
||||
{
|
||||
with (field)
|
||||
{
|
||||
if (value==null||value==""||value==" ")
|
||||
{alert(alerttxt);return false;}
|
||||
else {return true}
|
||||
}
|
||||
}
|
||||
function validate_email(field,alerttxt)
|
||||
{
|
||||
with (field)
|
||||
{
|
||||
apos=value.indexOf("@");
|
||||
dotpos=value.lastIndexOf(".");
|
||||
if (apos<1||dotpos-apos<2)
|
||||
{alert(alerttxt);return false;}
|
||||
else {return true;}
|
||||
}
|
||||
}
|
||||
function validate_form(thisform)
|
||||
{
|
||||
with (thisform)
|
||||
{
|
||||
if (validate_required(email,"Please enter your e-mail!")==false)
|
||||
{email.focus();return false;}
|
||||
if (validate_email(email,"Invalid e-mail format!")==false)
|
||||
{email.focus();return false;}
|
||||
if (validate_required(passor,"Please enter password!")==false)
|
||||
{passor.focus();return false;}
|
||||
if (validate_required(passor2,"Please repeat password!")==false)
|
||||
{passor2.focus();return false;}
|
||||
if (passor2.value!=passor.value)
|
||||
{alert(\'Repeated password is not equal to password!\');return false;}
|
||||
}
|
||||
}
|
||||
</script>';
|
||||
echo 'Set new password and e-mail to your account.<BR>
|
||||
<FORM ACTION="' . getLink('account/lost') . '?action=step3" onsubmit="return validate_form(this)" METHOD=post>
|
||||
<INPUT TYPE=hidden NAME="character" VALUE="">
|
||||
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
|
||||
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Please enter new password and e-mail</B></TD></TR>
|
||||
<TR><TD BGCOLOR="'.$config['darkborder'].'">
|
||||
Account of character: <INPUT TYPE=text NAME="nick" VALUE="'.$nick.'" SIZE="40" readonly="readonly"><BR />
|
||||
New password: <INPUT id="passor" TYPE=password NAME="passor" VALUE="" SIZE="40"><BR>
|
||||
Repeat new password: <INPUT id="passor2" TYPE=password NAME="passor" VALUE="" SIZE="40"><BR>
|
||||
New e-mail address: <INPUT id="email" TYPE=text NAME="email" VALUE="" SIZE="40"><BR>
|
||||
<INPUT TYPE=hidden NAME="key" VALUE="'.$rec_key.'">
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<BR>
|
||||
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
|
||||
' . $twig->render('buttons.submit.html.twig') . '</div>
|
||||
</TD></TR></FORM></TABLE></TABLE>';
|
||||
}
|
||||
else
|
||||
echo 'Wrong recovery key!';
|
||||
}
|
||||
else
|
||||
echo 'Account of this character has no recovery key!';
|
||||
}
|
||||
else
|
||||
echo 'Player or account of player <b>'.$nick.'</b> doesn\'t exist.';
|
||||
}
|
||||
else
|
||||
echo 'Invalid player name format. If you have other characters on account try with other name.';
|
||||
echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
|
||||
<a href="' . getLink('account/lost') . '?action=step1&action_type=reckey&nick='.urlencode($nick).'" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
|
||||
</TD></TR></FORM></TABLE></TABLE>';
|
||||
}
|
||||
elseif($action == 'step3')
|
||||
{
|
||||
$rec_key = trim($_REQUEST['key']);
|
||||
$nick = stripslashes($_REQUEST['nick']);
|
||||
$new_pass = trim($_REQUEST['passor']);
|
||||
$new_email = trim($_REQUEST['email']);
|
||||
if(Validator::characterName($nick))
|
||||
{
|
||||
$player = new OTS_Player();
|
||||
$account = new OTS_Account();
|
||||
$player->find($nick);
|
||||
if($player->isLoaded())
|
||||
$account = $player->getAccount();
|
||||
if($account->isLoaded())
|
||||
{
|
||||
$account_key = $account->getCustomField('key');
|
||||
if(!empty($account_key))
|
||||
{
|
||||
if($account_key == $rec_key)
|
||||
{
|
||||
if(Validator::password($new_pass))
|
||||
{
|
||||
if(Validator::email($new_email))
|
||||
{
|
||||
$account->setEMail($new_email);
|
||||
|
||||
$tmp_new_pass = $new_pass;
|
||||
if(USE_ACCOUNT_SALT)
|
||||
{
|
||||
$salt = generateRandomString(10, false, true, true);
|
||||
$tmp_new_pass = $salt . $new_pass;
|
||||
}
|
||||
|
||||
$account->setPassword(encrypt($tmp_new_pass));
|
||||
$account->save();
|
||||
|
||||
if(USE_ACCOUNT_SALT)
|
||||
$account->setCustomField('salt', $salt);
|
||||
|
||||
echo 'Your account name, new password and new e-mail.<BR>
|
||||
<FORM ACTION="' . getLink('account/manage') . '" onsubmit="return validate_form(this)" METHOD=post>
|
||||
<INPUT TYPE=hidden NAME="character" VALUE="">
|
||||
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
|
||||
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Your account name, new password and new e-mail</B></TD></TR>
|
||||
<TR><TD BGCOLOR="'.$config['darkborder'].'">
|
||||
Account name: <b>'.$account->getName().'</b><BR>
|
||||
New password: <b>'.$new_pass.'</b><BR>
|
||||
New e-mail address: <b>'.$new_email.'</b><BR>';
|
||||
if($account->getCustomField('email_next') < time())
|
||||
{
|
||||
$mailBody = '
|
||||
<h3>Your account name and new password!</h3>
|
||||
<p>Changed password and e-mail to your account in Lost Account Interface on server <a href="'.BASE_URL.'"><b>'.$config['lua']['serverName'].'</b></a></p>
|
||||
<p>Account name: <b>'.$account->getName().'</b></p>
|
||||
<p>New password: <b>'.$new_pass.'</b></p>
|
||||
<p>E-mail: <b>'.$new_email.'</b> (this e-mail)</p>
|
||||
<br />
|
||||
<p><u>It\'s automatic e-mail from OTS Lost Account System. Do not reply!</u></p>';
|
||||
|
||||
if(_mail($account->getCustomField('email'), $config['lua']['serverName']." - New password to your account", $mailBody))
|
||||
{
|
||||
echo '<br /><small>Sent e-mail with your account name and password to new e-mail. You should receive this e-mail in 15 minutes. You can login now with new password!</small>';
|
||||
}
|
||||
else
|
||||
{
|
||||
echo '<br /><p class="error">An error occurred while sending email! You will not receive e-mail with this informations. For Admin: More info can be found in system/logs/mailer-error.log</p>';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
echo '<br /><small>You will not receive e-mail with this informations.</small>';
|
||||
}
|
||||
echo '<INPUT TYPE=hidden NAME="account_login" VALUE="'.$account->getId().'">
|
||||
<INPUT TYPE=hidden NAME="password_login" VALUE="'.$new_pass.'">
|
||||
</TD></TR></TABLE><BR>
|
||||
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
|
||||
<INPUT TYPE=image NAME="Login" ALT="Login" SRC="'.$template_path.'/images/global/buttons/sbutton_login.gif" BORDER=0 WIDTH=120 HEIGHT=18></div>
|
||||
</TD></TR></FORM></TABLE></TABLE>';
|
||||
}
|
||||
else
|
||||
echo Validator::getLastError();
|
||||
}
|
||||
else
|
||||
echo Validator::getLastError();
|
||||
}
|
||||
else
|
||||
echo 'Wrong recovery key!';
|
||||
}
|
||||
else
|
||||
echo 'Account of this character has no recovery key!';
|
||||
}
|
||||
else
|
||||
echo 'Player or account of player <b>'.$nick.'</b> doesn\'t exist.';
|
||||
}
|
||||
else
|
||||
echo 'Invalid player name format. If you have other characters on account try with other name.';
|
||||
echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
|
||||
<a href="' . getLink('account/lost') . '?action=step1&action_type=reckey&nick='.urlencode($nick).'" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
|
||||
</TD></TR></FORM></TABLE></TABLE>';
|
||||
}
|
||||
elseif($action == 'checkcode')
|
||||
{
|
||||
$code = trim($_REQUEST['code']);
|
||||
$character = stripslashes(trim($_REQUEST['character']));
|
||||
if(empty($code) || empty($character))
|
||||
echo 'Please enter code from e-mail and name of one character from account. Then press Submit.<BR>
|
||||
<FORM ACTION="' . getLink('account/lost') . '?action=checkcode" METHOD=post>
|
||||
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
|
||||
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Code & character name</B></TD></TR>
|
||||
<TR><TD BGCOLOR="'.$config['darkborder'].'">
|
||||
Your code: <INPUT TYPE=text NAME="code" VALUE="" SIZE="40")><BR />
|
||||
Character: <INPUT TYPE=text NAME="character" VALUE="" SIZE="40")><BR />
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<BR>
|
||||
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
|
||||
' . $twig->render('buttons.submit.html.twig') . '</div>
|
||||
</TD></TR></FORM></TABLE></TABLE>';
|
||||
else
|
||||
{
|
||||
$player = new OTS_Player();
|
||||
$account = new OTS_Account();
|
||||
$player->find($character);
|
||||
if($player->isLoaded())
|
||||
$account = $player->getAccount();
|
||||
if($account->isLoaded())
|
||||
{
|
||||
if($account->getCustomField('email_code') == $code)
|
||||
{
|
||||
echo '<script type="text/javascript">
|
||||
function validate_required(field,alerttxt)
|
||||
{
|
||||
with (field)
|
||||
{
|
||||
if (value==null||value==""||value==" ")
|
||||
{alert(alerttxt);return false;}
|
||||
else {return true}
|
||||
}
|
||||
}
|
||||
|
||||
function validate_form(thisform)
|
||||
{
|
||||
with (thisform)
|
||||
{
|
||||
if (validate_required(passor,"Please enter password!")==false)
|
||||
{passor.focus();return false;}
|
||||
if (validate_required(passor2,"Please repeat password!")==false)
|
||||
{passor2.focus();return false;}
|
||||
if (passor2.value!=passor.value)
|
||||
{alert(\'Repeated password is not equal to password!\');return false;}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Please enter new password to your account and repeat to make sure you remember password.<BR>
|
||||
<FORM ACTION="' . getLink('account/lost') . '?action=setnewpassword" onsubmit="return validate_form(this)" METHOD=post>
|
||||
<INPUT TYPE=hidden NAME="character" VALUE="'.$character.'">
|
||||
<INPUT TYPE=hidden NAME="code" VALUE="'.$code.'">
|
||||
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
|
||||
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Code & account name</B></TD></TR>
|
||||
<TR><TD BGCOLOR="'.$config['darkborder'].'">
|
||||
New password: <INPUT TYPE=password ID="passor" NAME="passor" VALUE="" SIZE="40")><BR />
|
||||
Repeat new password: <INPUT TYPE=password ID="passor2" NAME="passor2" VALUE="" SIZE="40")><BR />
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<BR>
|
||||
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
|
||||
' . $twig->render('buttons.submit.html.twig') . '</div>
|
||||
</TD></TR></FORM></TABLE></TABLE>';
|
||||
}
|
||||
else
|
||||
$error= 'Wrong code to change password.';
|
||||
}
|
||||
else
|
||||
$error = 'Account of this character or this character doesn\'t exist.';
|
||||
}
|
||||
if(!empty($error))
|
||||
echo '<span style="color: red"><b>'.$error.'</b></span><br />Please enter code from e-mail and name of one character from account. Then press Submit.<BR>
|
||||
<FORM ACTION="' . getLink('account/lost') . '?action=checkcode" METHOD=post>
|
||||
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
|
||||
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Code & character name</B></TD></TR>
|
||||
<TR><TD BGCOLOR="'.$config['darkborder'].'">
|
||||
Your code: <INPUT TYPE=text NAME="code" VALUE="" SIZE="40")><BR />
|
||||
Character: <INPUT TYPE=text NAME="character" VALUE="" SIZE="40")><BR />
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<BR>
|
||||
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
|
||||
' . $twig->render('buttons.submit.html.twig') . '</div>
|
||||
</TD></TR></FORM></TABLE></TABLE>';
|
||||
}
|
||||
elseif($action == 'setnewpassword')
|
||||
{
|
||||
$newpassword = $_REQUEST['passor'];
|
||||
$code = $_REQUEST['code'];
|
||||
$character = stripslashes($_REQUEST['character']);
|
||||
echo '';
|
||||
if(empty($code) || empty($character) || empty($newpassword))
|
||||
echo '<span style="color: red"><b>Error. Try again.</b></span><br />Please enter code from e-mail and name of one character from account. Then press Submit.<BR>
|
||||
<BR><FORM ACTION="' . getLink('account/lost') . '?action=checkcode" METHOD=post>
|
||||
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
|
||||
<INPUT TYPE=image NAME="Back" ALT="Back" SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" BORDER=0 WIDTH=120 HEIGHT=18></div>
|
||||
</TD></TR></FORM></TABLE></TABLE>';
|
||||
else
|
||||
{
|
||||
$player = new OTS_Player();
|
||||
$account = new OTS_Account();
|
||||
$player->find($character);
|
||||
if($player->isLoaded())
|
||||
$account = $player->getAccount();
|
||||
if($account->isLoaded())
|
||||
{
|
||||
if($account->getCustomField('email_code') == $code)
|
||||
{
|
||||
if(Validator::password($newpassword))
|
||||
{
|
||||
$tmp_new_pass = $newpassword;
|
||||
if(USE_ACCOUNT_SALT)
|
||||
{
|
||||
$salt = generateRandomString(10, false, true, true);
|
||||
$tmp_new_pass = $salt . $newpassword;
|
||||
$account->setCustomField('salt', $salt);
|
||||
}
|
||||
|
||||
$account->setPassword(encrypt($tmp_new_pass ));
|
||||
$account->save();
|
||||
$account->setCustomField('email_code', '');
|
||||
echo 'New password to your account is below. Now you can login.<BR>
|
||||
<INPUT TYPE=hidden NAME="character" VALUE="'.$character.'">
|
||||
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
|
||||
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Changed password</B></TD></TR>
|
||||
<TR><TD BGCOLOR="'.$config['darkborder'].'">
|
||||
New password: <b>'.$newpassword.'</b><BR />
|
||||
Account name: <i>(Already on your e-mail)</i><BR />';
|
||||
|
||||
$mailBody = '
|
||||
<h3>Your account name and password!</h3>
|
||||
<p>Changed password to your account in Lost Account Interface on server <a href="'.BASE_URL.'"><b>'.$config['lua']['serverName'].'</b></a></p>
|
||||
<p>Account name: <b>'.$account->getName().'</b></p>
|
||||
<p>New password: <b>'.$newpassword.'</b></p>
|
||||
<br />
|
||||
<p><u>It\'s automatic e-mail from OTS Lost Account System. Do not reply!</u></p>';
|
||||
|
||||
if(_mail($account->getCustomField('email'), $config['lua']['serverName']." - Your new password", $mailBody))
|
||||
{
|
||||
echo '<br /><small>New password work! Sent e-mail with your password and account name. You should receive this e-mail in 15 minutes. You can login now with new password!';
|
||||
}
|
||||
else
|
||||
{
|
||||
echo '<br /><p class="error">New password work! An error occurred while sending email! You will not receive e-mail with new password. For Admin: More info can be found in system/logs/mailer-error.log';
|
||||
}
|
||||
echo '</TD></TR>
|
||||
</TABLE>
|
||||
<BR>
|
||||
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
|
||||
<FORM ACTION="' . getLink('account/manage') . '" METHOD=post>
|
||||
<INPUT TYPE=image NAME="Login" ALT="Login" SRC="'.$template_path.'/images/global/buttons/sbutton_login.gif" BORDER=0 WIDTH=120 HEIGHT=18></div>
|
||||
</TD></TR></FORM></TABLE></TABLE>';
|
||||
}
|
||||
else
|
||||
$error= Validator::getLastError();
|
||||
}
|
||||
else
|
||||
$error= 'Wrong code to change password.';
|
||||
}
|
||||
else
|
||||
$error = 'Account of this character or this character doesn\'t exist.';
|
||||
}
|
||||
if(!empty($error))
|
||||
echo '<span style="color: red"><b>'.$error.'</b></span><br />Please enter code from e-mail and name of one character from account. Then press Submit.<BR>
|
||||
<FORM ACTION="' . getLink('account/lost') . '?action=checkcode" METHOD=post>
|
||||
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
|
||||
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Code & character name</B></TD></TR>
|
||||
<TR><TD BGCOLOR="'.$config['darkborder'].'">
|
||||
Your code: <INPUT TYPE=text NAME="code" VALUE="" SIZE="40")><BR />
|
||||
Character: <INPUT TYPE=text NAME="character" VALUE="" SIZE="40")><BR />
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<BR>
|
||||
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
|
||||
' . $twig->render('buttons.submit.html.twig') . '</div>
|
||||
</TD></TR></FORM></TABLE></TABLE>';
|
||||
}
|
||||
$twig->display('account/lost/form.html.twig');
|
||||
|
||||
18
system/pages/account/lost/base.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
function lostAccountWriteCooldown(string $nick, int $time): void
|
||||
{
|
||||
global $twig;
|
||||
|
||||
$inSec = $time - time();
|
||||
$minutesLeft = floor($inSec / 60);
|
||||
$secondsLeft = $inSec - ($minutesLeft * 60);
|
||||
$timeLeft = "$minutesLeft minutes $secondsLeft seconds";
|
||||
|
||||
$timeRounded = ceil(setting('core.mail_lost_account_interval') / 60);
|
||||
|
||||
$twig->display('error_box.html.twig', [
|
||||
'errors' => ["Account of selected character (<b>" . escapeHtml($nick) . "</b>) received e-mail in last $timeRounded minutes. You must wait $timeLeft before you can use Lost Account Interface again."]
|
||||
]);
|
||||
}
|
||||
51
system/pages/account/lost/check-code.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
csrfProtect();
|
||||
|
||||
$title = 'Lost Account';
|
||||
|
||||
$code = $_REQUEST['code'] ?? '';
|
||||
$character = $_REQUEST['character'] ?? '';
|
||||
|
||||
if(empty($code) || empty($character)) {
|
||||
$twig->display('account/lost/check-code.html.twig', [
|
||||
'code' => $code,
|
||||
'characters' => $character,
|
||||
]);
|
||||
}
|
||||
else {
|
||||
$player = new OTS_Player();
|
||||
$account = new OTS_Account();
|
||||
$player->find($character);
|
||||
if($player->isLoaded()) {
|
||||
$account = $player->getAccount();
|
||||
}
|
||||
|
||||
if($account->isLoaded()) {
|
||||
if($account->getCustomField('email_code') == $code) {
|
||||
$twig->display('account/lost/check-code.finish.html.twig', [
|
||||
'character' => $character,
|
||||
'code' => $code,
|
||||
]);
|
||||
}
|
||||
else {
|
||||
$error = 'Wrong code to change password.';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$error = "Account of this character or this character doesn't exist.";
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($error)) {
|
||||
$twig->display('error_box.html.twig', [
|
||||
'errors' => [$error],
|
||||
]);
|
||||
|
||||
echo '<br/>';
|
||||
|
||||
$twig->display('account/lost/check-code.html.twig', [
|
||||
|
||||
]);
|
||||
}
|
||||
75
system/pages/account/lost/email/send-code.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
csrfProtect();
|
||||
|
||||
require __DIR__ . '/../base.php';
|
||||
|
||||
$title = 'Lost Account';
|
||||
|
||||
$email = $_POST['email'] ?? '';
|
||||
$nick = $_POST['nick'] ?? '';
|
||||
|
||||
$player = new OTS_Player();
|
||||
$account = new OTS_Account();
|
||||
$player->find($nick);
|
||||
if($player->isLoaded()) {
|
||||
$account = $player->getAccount();
|
||||
}
|
||||
|
||||
if($account->isLoaded()) {
|
||||
if($account->getCustomField('email_next') < time()) {
|
||||
if($account->getEMail() == $email) {
|
||||
$newCode = generateRandomString(30, true, false, true);
|
||||
$mailBody = $twig->render('mail.account.lost.code.html.twig', [
|
||||
'newCode' => $newCode,
|
||||
'account' => $account,
|
||||
'nick' => $nick,
|
||||
]);
|
||||
|
||||
$accountEMail = $account->getCustomField('email');
|
||||
if(_mail($accountEMail, configLua('serverName') . ' - Recover your account', $mailBody)) {
|
||||
$account->setCustomField('email_code', $newCode);
|
||||
$account->setCustomField('email_next', (time() + setting('core.mail_lost_account_interval')));
|
||||
|
||||
$twig->display('success.html.twig', [
|
||||
'title' => 'Email has been sent',
|
||||
'description' => 'Details about steps required to recover your account has been sent to <b>' . $accountEMail . '</b>. You should receive this email within 15 minutes. Please check your inbox/spam directory.',
|
||||
'custom_buttons' => '',
|
||||
]);
|
||||
|
||||
$twig->display('account.back_button.html.twig', [
|
||||
'new_line' => true,
|
||||
'center' => true,
|
||||
'action' => getLink('news'),
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$account->setCustomField('email_next', (time() + 60));
|
||||
error('An error occurred while sending email! Try again later or contact with admin. For Admin: More info can be found in system/logs/mailer-error.log</p>');
|
||||
}
|
||||
else {
|
||||
$errors[] = 'Invalid e-mail to account of character <b>' . escapeHtml($nick) . '</b>. Try again.';
|
||||
}
|
||||
}
|
||||
else {
|
||||
lostAccountWriteCooldown($nick, (int)$account->getCustomField('email_next'));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$errors[] = "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
|
||||
}
|
||||
|
||||
if (!empty($errors)) {
|
||||
$twig->display('error_box.html.twig', [
|
||||
'errors' => $errors,
|
||||
]);
|
||||
}
|
||||
|
||||
$twig->display('account.back_button.html.twig', [
|
||||
'new_line' => true,
|
||||
'center' => true,
|
||||
'action' => getLink('account/lost/step-1') . '?action=email&nick=' . urlencode($nick),
|
||||
]);
|
||||
128
system/pages/account/lost/email/set-new-password.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
csrfProtect();
|
||||
|
||||
$title = 'Lost Account';
|
||||
|
||||
$newPassword = $_POST['password'] ?? '';
|
||||
$passwordRepeat = $_POST['password_repeat'] ?? '';
|
||||
$code = $_POST['code'] ?? '';
|
||||
$character = $_POST['character'] ?? '';
|
||||
|
||||
if(empty($code) || empty($character)) {
|
||||
$errors[] = 'Please enter code from e-mail and name of one character from account.';
|
||||
|
||||
$twig->display('error_box.html.twig', [
|
||||
'errors' => $errors,
|
||||
]);
|
||||
|
||||
$twig->display('account/lost/check-code.html.twig', [
|
||||
'code' => $code,
|
||||
'character' => $character,
|
||||
]);
|
||||
|
||||
$twig->display('account.back_button.html.twig', [
|
||||
'new_line' => true,
|
||||
'center' => true,
|
||||
'action' => getLink('account/lost/check-code')
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($newPassword) || empty($passwordRepeat)) {
|
||||
$errors[] = 'Please enter both passwords.';
|
||||
|
||||
$twig->display('error_box.html.twig', [
|
||||
'errors' => $errors,
|
||||
]);
|
||||
|
||||
$twig->display('account/lost/check-code.finish.html.twig', [
|
||||
'character' => $character,
|
||||
'code' => $code,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$player = new OTS_Player();
|
||||
$account = new OTS_Account();
|
||||
$player->find($character);
|
||||
if($player->isLoaded()) {
|
||||
$account = $player->getAccount();
|
||||
}
|
||||
|
||||
$passwordFailed = false;
|
||||
|
||||
if($account->isLoaded()) {
|
||||
if($account->getCustomField('email_code') == $code) {
|
||||
if ($newPassword == $passwordRepeat) {
|
||||
if (Validator::password($newPassword)) {
|
||||
|
||||
$hooks->trigger(HOOK_ACCOUNT_LOST_EMAIL_SET_NEW_PASSWORD_POST);
|
||||
|
||||
if (empty($errors)) {
|
||||
$tmp_new_pass = $newPassword;
|
||||
if (USE_ACCOUNT_SALT) {
|
||||
$salt = generateRandomString(10, false, true, true);
|
||||
$tmp_new_pass = $salt . $newPassword;
|
||||
$account->setCustomField('salt', $salt);
|
||||
}
|
||||
|
||||
$account->setPassword(encrypt($tmp_new_pass));
|
||||
$account->save();
|
||||
$account->setCustomField('email_code', '');
|
||||
|
||||
$mailBody = $twig->render('mail.account.lost.new-password.html.twig', [
|
||||
'account' => $account,
|
||||
'newPassword' => $newPassword,
|
||||
]);
|
||||
|
||||
$statusMsg = '';
|
||||
if (_mail($account->getCustomField('email'), configLua('serverName') . ' - Your new password', $mailBody)) {
|
||||
$statusMsg = '<br /><small>New password work! Sent e-mail with your password and account name. You should receive this e-mail in 15 minutes. You can login now with new password!';
|
||||
} else {
|
||||
$statusMsg = '<br /><p class="error">New password work! An error occurred while sending email! You will not receive e-mail with new password. For Admin: More info can be found in system/logs/mailer-error.log';
|
||||
}
|
||||
|
||||
$twig->display('account/lost/finish.new-password.html.twig', [
|
||||
'statusMsg' => $statusMsg,
|
||||
'newPassword' => $newPassword,
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
$passwordFailed = true;
|
||||
$errors[] = Validator::getLastError();
|
||||
}
|
||||
}
|
||||
else {
|
||||
$passwordFailed = true;
|
||||
$errors[] = 'Passwords are not the same!';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$errors[] = 'Wrong code to change password.';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$errors[] = "Account of this character or this character doesn't exist.";
|
||||
}
|
||||
|
||||
if(!empty($errors)) {
|
||||
$twig->display('error_box.html.twig', [
|
||||
'errors' => $errors,
|
||||
]);
|
||||
|
||||
echo '<br/>';
|
||||
|
||||
$template = 'account/lost/check-code.html.twig';
|
||||
if($passwordFailed) {
|
||||
$template = 'account/lost/check-code.finish.html.twig';
|
||||
}
|
||||
|
||||
$twig->display($template, [
|
||||
'code' => $code,
|
||||
'character' => $character,
|
||||
]);
|
||||
}
|
||||
36
system/pages/account/lost/email/step-1.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
require __DIR__ . '/../base.php';
|
||||
|
||||
csrfProtect();
|
||||
|
||||
$title = 'Lost Account';
|
||||
|
||||
$nick = $_REQUEST['nick'] ?? '';
|
||||
|
||||
if($account->isLoaded()) {
|
||||
if($account->getCustomField('email_next') < time()) {
|
||||
$twig->display('account/lost/email.html.twig', [
|
||||
'nick' => $nick,
|
||||
]);
|
||||
}
|
||||
else {
|
||||
lostAccountWriteCooldown($nick, (int)$account->getCustomField('email_next'));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$errors[] = "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
|
||||
}
|
||||
|
||||
if (!empty($errors)) {
|
||||
$twig->display('error_box.html.twig', [
|
||||
'errors' => $errors,
|
||||
]);
|
||||
}
|
||||
|
||||
$twig->display('account.back_button.html.twig', [
|
||||
'new_line' => true,
|
||||
'center' => true,
|
||||
'action' => getLink('account/lost'),
|
||||
]);
|
||||
38
system/pages/account/lost/recovery-key/step-1.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
csrfProtect();
|
||||
|
||||
$title = 'Lost Account';
|
||||
|
||||
$nick = $_REQUEST['nick'] ?? '';
|
||||
$key = $_REQUEST['key'] ?? '';
|
||||
|
||||
if($account->isLoaded()) {
|
||||
$account_key = $account->getCustomField('key');
|
||||
|
||||
if(!empty($account_key)) {
|
||||
$twig->display('account/lost/recovery-key.step-1.html.twig', [
|
||||
'nick' => $nick,
|
||||
'key' => $key,
|
||||
]);
|
||||
}
|
||||
else {
|
||||
$errors[] = 'Account of this character has no recovery key!';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$errors[] = "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
|
||||
}
|
||||
|
||||
if (!empty($errors)) {
|
||||
$twig->display('error_box.html.twig', [
|
||||
'errors' => $errors,
|
||||
]);
|
||||
}
|
||||
|
||||
$twig->display('account.back_button.html.twig', [
|
||||
'new_line' => true,
|
||||
'center' => true,
|
||||
'action' => getLink('account/lost'),
|
||||
]);
|
||||
49
system/pages/account/lost/recovery-key/step-2.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
csrfProtect();
|
||||
|
||||
$title = 'Lost Account';
|
||||
|
||||
$key = $_REQUEST['key'] ?? '';
|
||||
$nick = $_REQUEST['nick'] ?? '';
|
||||
|
||||
$player = new OTS_Player();
|
||||
$account = new OTS_Account();
|
||||
$player->find($nick);
|
||||
if($player->isLoaded()) {
|
||||
$account = $player->getAccount();
|
||||
}
|
||||
|
||||
if($account->isLoaded()) {
|
||||
$accountKey = $account->getCustomField('key');
|
||||
if(!empty($accountKey)) {
|
||||
if($accountKey == $key) {
|
||||
$twig->display('account/lost/recovery-key.step-2.html.twig', [
|
||||
'nick' => $nick,
|
||||
'key' => $key,
|
||||
]);
|
||||
}
|
||||
else {
|
||||
$errors[] = 'Wrong recovery key!';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$errors[] = 'Account of this character has no recovery key!';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$errors[] = "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
|
||||
}
|
||||
|
||||
if (!empty($errors)) {
|
||||
$twig->display('error_box.html.twig', [
|
||||
'errors' => $errors,
|
||||
]);
|
||||
}
|
||||
|
||||
$twig->display('account.back_button.html.twig', [
|
||||
'new_line' => true,
|
||||
'center' => true,
|
||||
'action' => getLink('account/lost/step-1') . '?action=recovery-key&nick=' . urlencode($nick) . '&key=' . urlencode($key),
|
||||
]);
|
||||
117
system/pages/account/lost/recovery-key/step-3.php
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
use MyAAC\Models\Account as AccountModel;
|
||||
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
csrfProtect();
|
||||
|
||||
$title = 'Lost Account';
|
||||
|
||||
$key = $_POST['key'];
|
||||
$nick = $_POST['nick'] ?? '';
|
||||
$newPassword = $_POST['password'] ?? '';
|
||||
$passwordRepeat = $_POST['password_repeat'] ?? '';
|
||||
$newEmail = $_POST['email'] ?? '';
|
||||
|
||||
$player = new OTS_Player();
|
||||
$account = new OTS_Account();
|
||||
$player->find($nick);
|
||||
if($player->isLoaded()) {
|
||||
$account = $player->getAccount();
|
||||
}
|
||||
|
||||
if($account->isLoaded()) {
|
||||
$accountKey = $account->getCustomField('key');
|
||||
|
||||
if(!empty($accountKey)) {
|
||||
if($accountKey == $key) {
|
||||
if(Validator::password($newPassword)) {
|
||||
if ($newPassword == $passwordRepeat) {
|
||||
if (Validator::email($newEmail)) {
|
||||
$emailExists = AccountModel::where('email', $newEmail)->count() > 0;
|
||||
if (!$emailExists) {
|
||||
|
||||
$hooks->trigger(HOOK_ACCOUNT_LOST_RECOVERY_KEY_STEP_3_POST);
|
||||
|
||||
if (empty($errors)) {
|
||||
$account->setEMail($newEmail);
|
||||
|
||||
$tmp_new_pass = $newPassword;
|
||||
if (USE_ACCOUNT_SALT) {
|
||||
$salt = generateRandomString(10, false, true, true);
|
||||
$tmp_new_pass = $salt . $newPassword;
|
||||
}
|
||||
|
||||
$account->setPassword(encrypt($tmp_new_pass));
|
||||
$account->save();
|
||||
|
||||
if (USE_ACCOUNT_SALT) {
|
||||
$account->setCustomField('salt', $salt);
|
||||
}
|
||||
|
||||
$statusMsg = '';
|
||||
if ($account->getCustomField('email_next') < time()) {
|
||||
$mailBody = $twig->render('mail.account.lost.new-email.html.twig', [
|
||||
'account' => $account,
|
||||
'newPassword' => $newPassword,
|
||||
'newEmail' => $newEmail,
|
||||
]);
|
||||
|
||||
if (_mail($account->getCustomField('email'), configLua('serverName') . ' - New password to your account', $mailBody)) {
|
||||
$statusMsg = '<br /><small>Sent e-mail with your account name and password to new e-mail. You should receive this e-mail in 15 minutes. You can login now with new password!</small>';
|
||||
} else {
|
||||
$statusMsg = '<br /><p class="error">An error occurred while sending email! You will not receive e-mail with this informations. For Admin: More info can be found in system/logs/mailer-error.log</p>';
|
||||
}
|
||||
} else {
|
||||
$statusMsg = '<br /><small>You will not receive e-mail with this informations.</small>';
|
||||
}
|
||||
|
||||
$twig->display('account/lost/finish.new-email.html.twig', [
|
||||
'statusMsg' => $statusMsg,
|
||||
'account' => $account,
|
||||
'newPassword' => $newPassword,
|
||||
'newEmail' => $newEmail,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$errors[] = 'This email is already registered!';
|
||||
}
|
||||
} else {
|
||||
$errors[] = Validator::getLastError();
|
||||
}
|
||||
}
|
||||
else {
|
||||
$errors[] = 'Passwords are not the same!';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$errors[] = Validator::getLastError();
|
||||
}
|
||||
}
|
||||
else {
|
||||
$errors[] = 'Wrong recovery key!';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$errors[] = 'Account of this character has no recovery key!';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$errors[] = "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
|
||||
}
|
||||
|
||||
if (!empty($errors)) {
|
||||
$twig->display('error_box.html.twig', [
|
||||
'errors' => $errors,
|
||||
]);
|
||||
}
|
||||
|
||||
$twig->display('account.back_button.html.twig', [
|
||||
'new_line' => true,
|
||||
'center' => true,
|
||||
'action' => getLink('account/lost/recovery-key/step-2') . '?nick=' . urlencode($nick) . '&key=' . urlencode($key),
|
||||
]);
|
||||
26
system/pages/account/lost/step-1.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
csrfProtect();
|
||||
|
||||
$title = 'Lost Account';
|
||||
|
||||
$nick = $_REQUEST['nick'] ?? '';
|
||||
|
||||
$player = new OTS_Player();
|
||||
$account = new OTS_Account();
|
||||
$player->find($nick);
|
||||
if($player->isLoaded()) {
|
||||
$account = $player->getAccount();
|
||||
}
|
||||
|
||||
if (ACTION == 'email') {
|
||||
require __DIR__ . '/email/step-1.php';
|
||||
}
|
||||
else if (ACTION == 'recovery-key') {
|
||||
require __DIR__ . '/recovery-key/step-1.php';
|
||||
}
|
||||
else {
|
||||
$twig->display('account/lost/no-action.html.twig');
|
||||
}
|
||||
|
||||
@@ -38,15 +38,24 @@ csrfProtect();
|
||||
|
||||
$groups = new OTS_Groups_List();
|
||||
|
||||
$freePremium = isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium']) || $account_logged->getPremDays() == OTS_Account::GRATIS_PREMIUM_DAYS;
|
||||
$dayOrDays = $account_logged->getPremDays() == 1 ? 'day' : 'days';
|
||||
/**
|
||||
* @var OTS_Account $account_logged
|
||||
*/
|
||||
if(!$account_logged->isPremium())
|
||||
$premDays = $account_logged->getPremDays();
|
||||
|
||||
$freePremium = isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium']) || $premDays == OTS_Account::GRATIS_PREMIUM_DAYS;
|
||||
$dayOrDays = ($premDays == 1 ? 'day' : 'days');
|
||||
|
||||
$vipSystemEnabled = isset($config['lua']['vipSystemEnabled']) && getBoolean($config['lua']['vipSystemEnabled']);
|
||||
$premiumLabel = $vipSystemEnabled ? 'VIP' : 'Premium Account';
|
||||
|
||||
if ($freePremium && !$vipSystemEnabled) {
|
||||
$account_status = '<b><span style="color: green">Gratis Premium Account</span></b>';
|
||||
} else if(!$account_logged->isPremium()) {
|
||||
$account_status = '<b><span style="color: red">Free Account</span></b>';
|
||||
else
|
||||
$account_status = '<b><span style="color: green">' . ($freePremium ? 'Gratis Premium Account' : 'Premium Account, ' . $account_logged->getPremDays() . ' '.$dayOrDays.' left') . '</span></b>';
|
||||
} else {
|
||||
$account_status = '<b><span style="color: green">' . $premiumLabel . ', ' . $premDays . ' '.$dayOrDays.' left</span></b>';
|
||||
}
|
||||
|
||||
$recovery_key = $account_logged->getCustomField('key');
|
||||
if(empty($recovery_key))
|
||||
@@ -87,12 +96,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');
|
||||
|
||||
@@ -48,7 +48,7 @@ else
|
||||
$account_logged->setCustomField('key', $new_rec_key);
|
||||
$account_logged->setCustomField(setting('core.donate_column'), $account_logged->getCustomField(setting('core.donate_column')) - setting('core.account_generate_new_reckey_price'));
|
||||
$account_logged->logAction('Generated new recovery key for ' . setting('core.account_generate_new_reckey_price') . ' premium points.');
|
||||
$message = '<br />Your recovery key were send on email address <b>'.$account_logged->getEMail().'</b> for '.setting('core.account_generate_new_reckey_price').' premium points.';
|
||||
$message = '<br />Your recovery key was sent on email address <b>'.$account_logged->getEMail().'</b> for '.setting('core.account_generate_new_reckey_price').' premium points.';
|
||||
}
|
||||
else
|
||||
$message = '<br /><p class="error">An error occurred while sending email ( <b>'.$account_logged->getEMail().'</b> ) with recovery key! Recovery key not changed. Try again later. For Admin: More info can be found in system/logs/mailer-error.log</p>';
|
||||
|
||||
94
system/pages/account/resend-email-verify.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
use MyAAC\Models\AccountEmailVerify;
|
||||
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
$title = 'Resend Email';
|
||||
|
||||
$errorWithBackButton = function ($msg) use ($twig) {
|
||||
$errors = [$msg];
|
||||
|
||||
$twig->display('error_box.html.twig', ['errors' => $errors]);
|
||||
$twig->display('account.back_button.html.twig', [
|
||||
'action' => getLink('account/resend-email-verify'),
|
||||
]);
|
||||
};
|
||||
|
||||
if (!setting('core.mail_enabled') || !setting('core.account_mail_verify')) {
|
||||
$errorWithBackButton('Resending email is not possible on this server.');
|
||||
return;
|
||||
}
|
||||
|
||||
$showForm = true;
|
||||
|
||||
if (isset($_POST['submit']) && $_POST['submit'] == '1') {
|
||||
$email = $_REQUEST['email'];
|
||||
|
||||
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$errorWithBackButton('Please enter valid Email.');
|
||||
return;
|
||||
}
|
||||
|
||||
$account = new OTS_Account();
|
||||
$account->findByEMail($email);
|
||||
if ($account->isLoaded()) {
|
||||
if ($account->getCustomField('email_verified') == '1') {
|
||||
$errorWithBackButton('This account is already verified! You can <a href=' . getLink('account/manage') . '>log in</a> on the website.');
|
||||
return;
|
||||
}
|
||||
|
||||
$accountEmailVerify = AccountEmailVerify::where('account_id', $account->getId())->orderBy('sent_at', 'DESC')->first();
|
||||
if ($accountEmailVerify && time() - $accountEmailVerify->sent_at < 60) {
|
||||
$errorWithBackButton('Only one Email per minute is allowed. Please try again later.');
|
||||
return;
|
||||
}
|
||||
|
||||
$tmp_account = $email;
|
||||
if (!config('account_login_by_email')) {
|
||||
$tmp_account = (USE_ACCOUNT_NAME ? $account->getName() : $account->getId());
|
||||
}
|
||||
|
||||
$hash = md5(generateRandomString(16, true, true) . $email);
|
||||
|
||||
AccountEmailVerify::create([
|
||||
'account_id' => $account->getId(),
|
||||
'hash' => $hash,
|
||||
'sent_at' => time(),
|
||||
]);
|
||||
|
||||
$verify_url = getLink('account/confirm-email/' . $hash);
|
||||
$body_html = $twig->render('mail.account.resend-email-verify.html.twig', array(
|
||||
'account' => $tmp_account,
|
||||
'verify_url' => generateLink($verify_url, $verify_url, true)
|
||||
));
|
||||
|
||||
if (_mail($account->getEMail(), configLua('serverName') . ' - Verify Account', $body_html)) {
|
||||
$message = "If account with this email exists - you will become an email with verification link.";
|
||||
$showForm = false;
|
||||
} else {
|
||||
$message = "<p class='error'>An error occurred while sending email (<b>{$email}</b> )! Try again later. For Admin: More info can be found in system/logs/mailer-error.log</p>";
|
||||
}
|
||||
}
|
||||
else {
|
||||
$message = "<br />If account with this email exists - you will become an email with verification link.";
|
||||
$showForm = false;
|
||||
}
|
||||
|
||||
$twig->display('success.html.twig', array(
|
||||
'title' => 'Verify Email Sent',
|
||||
'description' => $message,
|
||||
));
|
||||
}
|
||||
|
||||
//show errors if not empty
|
||||
if (!empty($errors)) {
|
||||
$twig->display('error_box.html.twig', ['errors' => $errors]);
|
||||
$twig->display('account.back_button.html.twig', [
|
||||
'action' => getLink('account/resend-email-verify'),
|
||||
]);
|
||||
}
|
||||
|
||||
if ($showForm) {
|
||||
$twig->display('account.resend-email-verify.html.twig');
|
||||
}
|
||||
@@ -202,35 +202,37 @@ if($player->isLoaded() && !$player->isDeleted())
|
||||
unset($storage);
|
||||
}
|
||||
|
||||
if($db->hasTable('player_items') && $db->hasColumn('player_items', 'pid') && $db->hasColumn('player_items', 'sid') && $db->hasColumn('player_items', 'itemtype')) {
|
||||
if ($db->hasTableAndColumns('player_items', ['pid', 'sid', 'itemtype'])) {
|
||||
$eq_sql = $db->query('SELECT `pid`, `itemtype` FROM player_items WHERE player_id = '.$player->getId().' AND (`pid` >= 1 and `pid` <= 10)');
|
||||
$equipment = array();
|
||||
foreach($eq_sql as $eq)
|
||||
$equipment = [];
|
||||
foreach($eq_sql as $eq) {
|
||||
$equipment[$eq['pid']] = $eq['itemtype'];
|
||||
}
|
||||
|
||||
$empty_slots = array("", "no_helmet", "no_necklace", "no_backpack", "no_armor", "no_handleft", "no_handright", "no_legs", "no_boots", "no_ring", "no_ammo");
|
||||
for($i = 0; $i <= 10; $i++)
|
||||
{
|
||||
$empty_slots = ["", "no_helmet", "no_necklace", "no_backpack", "no_armor", "no_handleft", "no_handright", "no_legs", "no_boots", "no_ring", "no_ammo"];
|
||||
|
||||
for($i = 0; $i <= 10; $i++) {
|
||||
if(!isset($equipment[$i]) || $equipment[$i] == 0)
|
||||
$equipment[$i] = $empty_slots[$i];
|
||||
}
|
||||
|
||||
for($i = 1; $i < 11; $i++)
|
||||
{
|
||||
if(Validator::number($equipment[$i]))
|
||||
for($i = 1; $i < 11; $i++) {
|
||||
if(Validator::number($equipment[$i])) {
|
||||
$equipment[$i] = getItemImage($equipment[$i]);
|
||||
else
|
||||
}
|
||||
else {
|
||||
$equipment[$i] = '<img src="images/items/' . $equipment[$i] . '.gif" width="32" height="32" border="0" alt=" ' . $equipment[$i] . '" />';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$skulls = array(
|
||||
$skulls = [
|
||||
1 => 'yellow_skull',
|
||||
2 => 'green_skull',
|
||||
3 => 'white_skull',
|
||||
4 => 'red_skull',
|
||||
5 => 'black_skull'
|
||||
);
|
||||
}
|
||||
5 => 'black_skull',
|
||||
];
|
||||
|
||||
$dead_add_content = '';
|
||||
$deaths = array();
|
||||
@@ -450,10 +452,8 @@ WHERE killers.death_id = '".$death['id']."' ORDER BY killers.final_hit DESC, kil
|
||||
if($query->rowCount() > 0) {
|
||||
echo 'Did you mean:<ul>';
|
||||
foreach($query as $player) {
|
||||
if(isset($player['promotion'])) {
|
||||
if((int)$player['promotion'] > 0)
|
||||
$player['vocation'] += ($player['promotion'] * $config['vocations_amount']);
|
||||
}
|
||||
$player['vocation'] = OTS_Toolbox::getVocationFromPromotion($player['vocation'], $player['promotion'] ?? 0);
|
||||
|
||||
echo '<li>' . getPlayerLink($player['name']) . ' (<small><strong>level ' . $player['level'] . ', ' . $config['vocations'][$player['vocation']] . '</strong></small>)</li>';
|
||||
}
|
||||
echo '</ul>';
|
||||
|
||||
@@ -36,9 +36,9 @@ 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']) . '">'.htmlspecialchars($first_post['post_topic']).'</a> >> <b>Edit post</b>';
|
||||
echo '<a href="' . getLink('forum') . '">Boards</a> >> <a href="' . getForumBoardLink($thread['section']) . '">'.escapeHtml($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()))) {
|
||||
if(Forum::hasAccess($thread['section']) && ($account_logged->getId() == $thread['author_aid'] || Forum::isModerator())) {
|
||||
$char_id = $post_topic = $text = $smile = $html = null;
|
||||
$players_from_account = $db->query("SELECT `players`.`name`, `players`.`id` FROM `players` WHERE `players`.`account_id` = ".(int) $account_logged->getId())->fetchAll();
|
||||
$saved = false;
|
||||
|
||||
@@ -42,7 +42,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) . '">'.htmlspecialchars($thread['post_topic']).'</a> >> <b>Post new reply</b><br /><h3>'.htmlspecialchars($thread['post_topic']).'</h3>';
|
||||
echo '<a href="' . getLink('forum') . '">Boards</a> >> <a href="' . getForumBoardLink($thread['section']) . '">'.escapeHtml($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($_POST['text']) ? stripslashes(trim($_POST['text'])) : NULL;
|
||||
|
||||
@@ -34,7 +34,7 @@ if(Forum::canPost($account_logged)) {
|
||||
$players_from_account = $db->query('SELECT `players`.`name`, `players`.`id` FROM `players` WHERE `players`.`account_id` = '.(int) $account_logged->getId())->fetchAll();
|
||||
$section_id = $_REQUEST['section_id'] ?? null;
|
||||
if($section_id !== null) {
|
||||
echo '<a href="' . getLink('forum') . '">Boards</a> >> <a href="' . getForumBoardLink($section_id) . '">' . $sections[$section_id]['name'] . '</a> >> <b>Post new thread</b><br />';
|
||||
echo '<a href="' . getLink('forum') . '">Boards</a> >> <a href="' . getForumBoardLink($section_id) . '">' . escapeHtml($sections[$section_id]['name']) . '</a> >> <b>Post new thread</b><br />';
|
||||
|
||||
if(isset($sections[$section_id]['name']) && Forum::hasAccess($section_id)) {
|
||||
if ($sections[$section_id]['closed'] && !Forum::isModerator())
|
||||
|
||||
@@ -42,35 +42,12 @@ for($i = 0; $i < $threads_count['threads_count'] / setting('core.forum_threads_p
|
||||
$links_to_pages .= '<b>'.($i + 1).' </b>';
|
||||
}
|
||||
|
||||
echo '<a href="' . getLink('forum') . '">Boards</a> >> <b>'.$sections[$section_id]['name'].'</b>';
|
||||
|
||||
if($logged && (!$sections[$section_id]['closed'] || Forum::isModerator())) {
|
||||
echo '<br /><br />
|
||||
<a href="' . getLink('forum') . '?action=new_thread§ion_id='.$section_id.'"><img src="images/forum/topic.gif" border="0" /></a>';
|
||||
}
|
||||
|
||||
echo '<br /><br />Page: '.$links_to_pages.'<br />';
|
||||
$last_threads = $db->query("SELECT `players`.`id` as `player_id`, `players`.`name`, `" . FORUM_TABLE_PREFIX . "forum`.`first_post`, `" . FORUM_TABLE_PREFIX . "forum`.`post_text`, `" . FORUM_TABLE_PREFIX . "forum`.`post_topic`, `" . FORUM_TABLE_PREFIX . "forum`.`id`, `" . FORUM_TABLE_PREFIX . "forum`.`last_post`, `" . FORUM_TABLE_PREFIX . "forum`.`replies`, `" . FORUM_TABLE_PREFIX . "forum`.`views`, `" . FORUM_TABLE_PREFIX . "forum`.`post_date` FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`section` = ".$section_id." AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = `" . FORUM_TABLE_PREFIX . "forum`.`id` ORDER BY `" . FORUM_TABLE_PREFIX . "forum`.`last_post` DESC LIMIT ".setting('core.forum_threads_per_page')." OFFSET ".($_page * setting('core.forum_threads_per_page')))->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if(isset($last_threads[0])) {
|
||||
echo '<table width="100%">
|
||||
<tr bgcolor="'.$config['vdarkborder'].'" align="center">
|
||||
<td class="white">
|
||||
<span style="font-size: 10px"><b>Thread</b></span></td>
|
||||
<td><span style="font-size: 10px"><b>Thread Starter</b></span></td>
|
||||
<td><span style="font-size: 10px"><b>Replies</b></span></td>
|
||||
<td><span style="font-size: 10px"><b>Views</b></span></td>
|
||||
<td><span style="font-size: 10px"><b>Last Post</b></span></td>
|
||||
</tr>';
|
||||
|
||||
$threads = [];
|
||||
if(count($last_threads) > 0) {
|
||||
$player = new OTS_Player();
|
||||
foreach($last_threads as $thread) {
|
||||
echo '<tr bgcolor="' . getStyle($number_of_rows++) . '"><td>';
|
||||
if(Forum::isModerator()) {
|
||||
echo '<a href="' . getLink('forum') . '?action=move_thread&id=' . $thread['id'] . '" title="Move Thread"><img src="images/icons/arrow_right.gif"/></a>';
|
||||
$twig->display('forum.remove_post.html.twig', ['post' => $thread]);
|
||||
}
|
||||
|
||||
$player->load($thread['player_id']);
|
||||
if(!$player->isLoaded()) {
|
||||
throw new RuntimeException('Forum error: Player not loaded.');
|
||||
@@ -79,28 +56,29 @@ 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']) . '">'.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>';
|
||||
$thread['link'] = getForumThreadLink($thread['id']);
|
||||
|
||||
$thread['post_shortened'] = ($canEditForum ? substr(strip_tags($thread['post_text']), 0, 50) : htmlspecialchars(substr($thread['post_text'], 0, 50)));
|
||||
|
||||
$thread['player'] = $player;
|
||||
$thread['player_link'] = getPlayerLink($thread['name']);
|
||||
|
||||
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'])) {
|
||||
echo date('d.m.y H:i:s', $last_post['post_date']) . '<br />by ' . getPlayerLink($last_post['name']);
|
||||
}
|
||||
else {
|
||||
echo 'No posts.';
|
||||
}
|
||||
}
|
||||
else {
|
||||
echo date('d.m.y H:i:s', $thread['post_date']) . '<br />by ' . getPlayerLink($thread['name']);
|
||||
}
|
||||
echo '</td></tr>';
|
||||
$last_post['player_link'] = getPlayerLink($last_post['name']);
|
||||
$thread['latest_post'] = $last_post;
|
||||
}
|
||||
|
||||
echo '</table>';
|
||||
if($logged && (!$sections[$section_id]['closed'] || Forum::isModerator())) {
|
||||
echo '<br /><a href="' . getLink('forum') . '?action=new_thread§ion_id=' . $section_id . '"><img src="images/forum/topic.gif" border="0" /></a>';
|
||||
$threads[] = $thread;
|
||||
}
|
||||
}
|
||||
else {
|
||||
echo '<h3>No threads in this board.</h3>';
|
||||
}
|
||||
|
||||
$twig->display('forum.show_board.html.twig', [
|
||||
'threads' => $threads,
|
||||
'section_id' => $section_id,
|
||||
'section_name' => $sections[$section_id]['name'],
|
||||
'links_to_pages' => $links_to_pages,
|
||||
'is_moderator' => Forum::isModerator(),
|
||||
'closed' => $sections[$section_id]['closed'],
|
||||
]);
|
||||
|
||||
@@ -70,7 +70,7 @@ foreach($posts as &$post) {
|
||||
}
|
||||
|
||||
$post['group'] = $groupName;
|
||||
$post['player_link'] = getPlayerLink($player->getName());
|
||||
$post['player_link'] = '<a href="' . getPlayerLink($player, false) . '" style="position: relative;">' . $player->getName() . '</a>';
|
||||
|
||||
$post['vocation'] = $player->getVocationName();
|
||||
|
||||
|
||||
@@ -9,316 +9,25 @@
|
||||
*/
|
||||
|
||||
use MyAAC\Cache\Cache;
|
||||
use MyAAC\Models\Gallery as ModelsGallery;
|
||||
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
$title = 'Gallery';
|
||||
|
||||
$canEdit = hasFlag(FLAG_CONTENT_GALLERY) || superAdmin();
|
||||
if($canEdit) {
|
||||
if(function_exists('imagecreatefrompng')) {
|
||||
if (!empty($action)) {
|
||||
if ($action == 'delete' || $action == 'edit' || $action == 'hide' || $action == 'moveup' || $action == 'movedown')
|
||||
$id = $_REQUEST['id'];
|
||||
const ALLOWED_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
||||
|
||||
if (isset($_REQUEST['comment']))
|
||||
$comment = stripslashes($_REQUEST['comment']);
|
||||
$images = Cache::remember('gallery', 5 * 60, function () {
|
||||
$images = glob(BASE . GALLERY_DIR . '*.*');
|
||||
|
||||
if (isset($_REQUEST['image']))
|
||||
$image = $_REQUEST['image'];
|
||||
$images = array_filter($images, function ($image) {
|
||||
$ext = pathinfo($image, PATHINFO_EXTENSION);
|
||||
|
||||
if (isset($_REQUEST['author']))
|
||||
$author = $_REQUEST['author'];
|
||||
|
||||
$errors = array();
|
||||
|
||||
if ($action == 'add') {
|
||||
if (Gallery::add($comment, $image, $author, $errors))
|
||||
$comment = $image = $author = '';
|
||||
} else if ($action == 'delete') {
|
||||
Gallery::delete($id, $errors);
|
||||
} else if ($action == 'edit') {
|
||||
if (isset($id) && !isset($name)) {
|
||||
$tmp = Gallery::get($id);
|
||||
$comment = $tmp['comment'];
|
||||
$image = $tmp['image'];
|
||||
$author = $tmp['author'];
|
||||
} else {
|
||||
Gallery::update($id, $comment, $image, $author);
|
||||
$action = $comment = $image = $author = '';
|
||||
}
|
||||
} else if ($action == 'hide') {
|
||||
Gallery::toggleHide($id, $errors);
|
||||
} else if ($action == 'moveup') {
|
||||
Gallery::move($id, -1, $errors);
|
||||
} else if ($action == 'movedown') {
|
||||
Gallery::move($id, 1, $errors);
|
||||
}
|
||||
|
||||
if (!empty($errors))
|
||||
$twig->display('error_box.html.twig', array('errors' => $errors));
|
||||
}
|
||||
|
||||
if(!isset($_GET['image'])) {
|
||||
$twig->display('gallery.form.html.twig', array(
|
||||
'link' => getLink('gallery/' . ($action == 'edit' ? 'edit' : 'add')),
|
||||
'action' => $action,
|
||||
'id' => isset($id) ? $id : null,
|
||||
'comment' => isset($comment) ? $comment : null,
|
||||
'image' => isset($image) ? $image : null,
|
||||
'author' => isset($author) ? $author : null
|
||||
));
|
||||
}
|
||||
}
|
||||
else
|
||||
echo 'You cannot edit/add gallery items as it seems your PHP installation doesnt have GD support enabled. Visit <a href="http://be2.php.net/manual/en/image.installation.php">PHP Manual</a> for more info.';
|
||||
}
|
||||
|
||||
if(isset($_GET['image']))
|
||||
{
|
||||
$image = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'gallery` WHERE `id` = ' . $db->quote($_GET['image']) . ' ORDER by `ordering` LIMIT 1;');
|
||||
if($image->rowCount() == 1)
|
||||
$image = $image->fetch();
|
||||
else
|
||||
{
|
||||
echo 'Image with this id does not exists.';
|
||||
return;
|
||||
}
|
||||
|
||||
$previous_image = $db->query('SELECT `id` FROM `' . TABLE_PREFIX . 'gallery` WHERE `id` = ' . $db->quote($image['id'] - 1) . ' ORDER by `ordering`;');
|
||||
if($previous_image->rowCount() == 1)
|
||||
$previous_image = $previous_image->fetch();
|
||||
else
|
||||
$previous_image = NULL;
|
||||
|
||||
$next_image = $db->query('SELECT `id` FROM `' . TABLE_PREFIX . 'gallery` WHERE `id` = ' . $db->quote($image['id'] + 1) . ' ORDER by `ordering`;');
|
||||
if($next_image->rowCount() == 1)
|
||||
$next_image = $next_image->fetch();
|
||||
else
|
||||
$next_image = NULL;
|
||||
|
||||
$twig->display('gallery.get.html.twig', array(
|
||||
'previous' => $previous_image ? $previous_image['id'] : null,
|
||||
'next' => $next_image ? $next_image['id'] : null,
|
||||
'image' => $image
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
$images = Cache::remember('gallery_' . ($canEdit ? '1' : '0'), 60, function () use ($db, $canEdit) {
|
||||
return $db->query('SELECT `id`, `comment`, `image`, `author`, `thumb`' .
|
||||
($canEdit ? ', `hide`, `ordering`' : '') .
|
||||
' FROM `' . TABLE_PREFIX . 'gallery`' .
|
||||
(!$canEdit ? ' WHERE `hide` != 1' : '') .
|
||||
' ORDER BY `ordering`;')->fetchAll(PDO::FETCH_ASSOC);
|
||||
return (in_array($ext, ALLOWED_EXTENSIONS) && !str_contains($image, '_thumb'));
|
||||
});
|
||||
|
||||
$last = count($images);
|
||||
if(!$last)
|
||||
{
|
||||
?>
|
||||
There are no images added to gallery yet.
|
||||
<?php
|
||||
return;
|
||||
}
|
||||
return array_map(function ($image) {
|
||||
return basename($image);
|
||||
}, $images);
|
||||
});
|
||||
|
||||
$twig->display('gallery.html.twig', array(
|
||||
$twig->display('gallery.html.twig', [
|
||||
'images' => $images,
|
||||
'last' => $last,
|
||||
'canEdit' => $canEdit
|
||||
));
|
||||
|
||||
class Gallery
|
||||
{
|
||||
static public function add($comment, $image, $author, &$errors)
|
||||
{
|
||||
global $db;
|
||||
if(isset($comment[0]) && isset($image[0]) && isset($author[0]))
|
||||
{
|
||||
$query =
|
||||
$db->query(
|
||||
'SELECT `ordering`' .
|
||||
' FROM `' . TABLE_PREFIX . 'gallery`' .
|
||||
' ORDER BY `ordering`' . ' DESC LIMIT 1'
|
||||
);
|
||||
|
||||
$ordering = 0;
|
||||
if($query->rowCount() > 0) {
|
||||
$query = $query->fetch();
|
||||
$ordering = $query['ordering'] + 1;
|
||||
}
|
||||
|
||||
$pathinfo = pathinfo($image);
|
||||
$extension = strtolower($pathinfo['extension']);
|
||||
$thumb_filename = GALLERY_DIR . $pathinfo['filename'] . '_thumb.' . $extension;
|
||||
$filename = GALLERY_DIR . $pathinfo['filename'] . '.' . $extension;
|
||||
if($db->insert(TABLE_PREFIX . 'gallery', array(
|
||||
'comment' => $comment,
|
||||
'image' => $filename, 'author' => $author,
|
||||
'thumb' => $thumb_filename,
|
||||
'ordering' => $ordering))) {
|
||||
if(self::generateThumb($db->lastInsertId(), $image, $errors))
|
||||
self::resize($image, 650, 500, $filename, $errors);
|
||||
}
|
||||
}
|
||||
else
|
||||
$errors[] = 'Please fill all inputs.';
|
||||
|
||||
return !count($errors);
|
||||
}
|
||||
|
||||
static public function get($id) {
|
||||
return ModelsGallery::find($id)->toArray();
|
||||
}
|
||||
|
||||
static public function update($id, $comment, $image, $author) {
|
||||
$pathinfo = pathinfo($image);
|
||||
$extension = strtolower($pathinfo['extension']);
|
||||
$filename = GALLERY_DIR . $pathinfo['filename'] . '.' . $extension;
|
||||
|
||||
if(ModelsGallery::where('id', $id)->update([
|
||||
'comment' => $comment,
|
||||
'image' => $filename,
|
||||
'author' => $author
|
||||
])) {
|
||||
if(self::generateThumb($id, $image, $errors))
|
||||
self::resize($image, 650, 500, $filename, $errors);
|
||||
}
|
||||
}
|
||||
|
||||
static public function delete($id, &$errors)
|
||||
{
|
||||
if(isset($id))
|
||||
{
|
||||
$row = ModelsGallery::find($id);
|
||||
if($row)
|
||||
if (!$row->delete()) {
|
||||
$errors[] = 'Fail during delete Gallery';
|
||||
}
|
||||
else
|
||||
$errors[] = 'Image with id ' . $id . ' does not exists.';
|
||||
}
|
||||
else
|
||||
$errors[] = 'id not set';
|
||||
|
||||
return !count($errors);
|
||||
}
|
||||
|
||||
static public function toggleHide($id, &$errors)
|
||||
{
|
||||
if(isset($id))
|
||||
{
|
||||
$row = ModelsGallery::find($id);
|
||||
if($row) {
|
||||
$row->hide = $row->hide == 1 ? 0 : 1;
|
||||
if (!$row->save()) {
|
||||
$errors[] = 'Fail during toggle hide Gallery';
|
||||
}
|
||||
} else
|
||||
$errors[] = 'Image with id ' . $id . ' does not exists.';
|
||||
}
|
||||
else
|
||||
$errors[] = 'id not set';
|
||||
|
||||
return !count($errors);
|
||||
}
|
||||
|
||||
static public function move($id, $i, &$errors)
|
||||
{
|
||||
global $db;
|
||||
$query = self::get($id);
|
||||
if($query !== false)
|
||||
{
|
||||
$ordering = $query['ordering'] + $i;
|
||||
$old_record = $db->select(TABLE_PREFIX . 'gallery', array('ordering' => $ordering));
|
||||
if($old_record !== false) {
|
||||
ModelsGallery::where('ordering', $ordering)->update([
|
||||
'ordering' => $query['ordering'],
|
||||
]);
|
||||
}
|
||||
|
||||
ModelsGallery::where('id', $id)->update([
|
||||
'ordering' => $ordering,
|
||||
]);
|
||||
}
|
||||
else
|
||||
$errors[] = 'Image with id ' . $id . ' does not exists.';
|
||||
|
||||
return !count($errors);
|
||||
}
|
||||
|
||||
static public function resize($file, $new_width, $new_height, $new_file, &$errors)
|
||||
{
|
||||
$pathinfo = pathinfo($file);
|
||||
$extension = strtolower($pathinfo['extension']);
|
||||
|
||||
switch ($extension)
|
||||
{
|
||||
case 'gif': // GIF
|
||||
$image = imagecreatefromgif($file);
|
||||
break;
|
||||
case 'jpg': // JPEG
|
||||
case 'jpeg':
|
||||
$image = imagecreatefromjpeg($file);
|
||||
break;
|
||||
case 'png': // PNG
|
||||
$image = imagecreatefrompng($file);
|
||||
break;
|
||||
default:
|
||||
$errors[] = 'Unsupported file format.';
|
||||
return false;
|
||||
}
|
||||
|
||||
$width = imagesx($image);
|
||||
$height = imagesy($image);
|
||||
|
||||
// create a new temporary image
|
||||
$tmp_img = imagecreatetruecolor($new_width, $new_height);
|
||||
|
||||
// copy and resize old image into new image
|
||||
imagecopyresized($tmp_img, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
|
||||
|
||||
// save thumbnail into a file
|
||||
switch($extension)
|
||||
{
|
||||
case 'gif':
|
||||
imagegif($tmp_img, $new_file);
|
||||
break;
|
||||
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
imagejpeg($tmp_img, $new_file);
|
||||
break;
|
||||
|
||||
case 'png':
|
||||
imagepng($tmp_img, $new_file);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static public function generateThumb($id, $file, &$errors)
|
||||
{
|
||||
$pathinfo = pathinfo($file);
|
||||
$extension = strtolower($pathinfo['extension']);
|
||||
$thumb_filename = GALLERY_DIR . $pathinfo['filename'] . '_thumb.' . $extension;
|
||||
|
||||
if(!self::resize($file, 170, 110, $thumb_filename, $errors))
|
||||
return false;
|
||||
|
||||
if(isset($id))
|
||||
{
|
||||
$row = ModelsGallery::find($id);
|
||||
if($row) {
|
||||
$row->thumb = $thumb_filename;
|
||||
$row->save();
|
||||
} else
|
||||
$errors[] = 'Image with id ' . $id . ' does not exists.';
|
||||
}
|
||||
else
|
||||
$errors[] = 'id not set';
|
||||
|
||||
return !count($errors);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ if(!$logged) {
|
||||
$errors[] = 'You are not logged in. You can\'t create guild.';
|
||||
}
|
||||
|
||||
$configLuaFreePremium = configLua('freePremium');
|
||||
$freePremium = (isset($configLuaFreePremium) && getBoolean($configLuaFreePremium));
|
||||
|
||||
$array_of_player_nig = array();
|
||||
if(empty($errors))
|
||||
{
|
||||
@@ -31,7 +34,7 @@ if(empty($errors))
|
||||
if(!$player_rank->isLoaded())
|
||||
{
|
||||
if($player->getLevel() >= setting('core.guild_need_level')) {
|
||||
if(!setting('core.guild_need_premium') || $account_logged->isPremium()) {
|
||||
if(!setting('core.guild_need_premium') || $account_logged->isPremium() || $freePremium) {
|
||||
$array_of_player_nig[] = $player->getName();
|
||||
}
|
||||
}
|
||||
@@ -95,7 +98,7 @@ if($todo == 'save')
|
||||
if($player->getLevel() < setting('core.guild_need_level')) {
|
||||
$errors[] = 'Character <b>'.$name.'</b> has too low level. To create guild you need character with level <b>' . setting('core.guild_need_level') . '</b>.';
|
||||
}
|
||||
if(setting('core.guild_need_premium') && !$account_logged->isPremium()) {
|
||||
if(setting('core.guild_need_premium') && !$account_logged->isPremium() && !$freePremium) {
|
||||
$errors[] = 'Character <b>'.$name.'</b> is on FREE account. To create guild you need PREMIUM account.';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,13 +91,18 @@ $guild_owner = $guild->getOwner();
|
||||
if($guild_owner->isLoaded())
|
||||
$guild_owner_name = $guild_owner->getName();
|
||||
|
||||
$deletedColumn = 'deleted';
|
||||
if ($db->hasColumn('players', 'deletion')) {
|
||||
$deletedColumn = 'deletion';
|
||||
}
|
||||
|
||||
$guild_members = array();
|
||||
foreach($rank_list as $rank)
|
||||
{
|
||||
if($db->hasTable(GUILD_MEMBERS_TABLE))
|
||||
$players_with_rank = $db->query('SELECT `players`.`id` as `id`, `' . GUILD_MEMBERS_TABLE . '`.`rank_id` as `rank_id` FROM `players`, `' . GUILD_MEMBERS_TABLE . '` WHERE `' . GUILD_MEMBERS_TABLE . '`.`rank_id` = ' . $rank->getId() . ' AND `players`.`id` = `' . GUILD_MEMBERS_TABLE . '`.`player_id` ORDER BY `name`;');
|
||||
$players_with_rank = $db->query('SELECT `players`.`id` as `id`, `' . GUILD_MEMBERS_TABLE . '`.`rank_id` as `rank_id` FROM `players`, `' . GUILD_MEMBERS_TABLE . '` WHERE `' . GUILD_MEMBERS_TABLE . '`.`rank_id` = ' . $rank->getId() . ' AND `players`.`id` = `' . GUILD_MEMBERS_TABLE . '`.`player_id` AND `' . $deletedColumn . '` = 0 ORDER BY `name`;');
|
||||
else if($db->hasColumn('players', 'rank_id'))
|
||||
$players_with_rank = $db->query('SELECT `id`, `rank_id` FROM `players` WHERE `rank_id` = ' . $rank->getId() . ' AND `deleted` = 0;');
|
||||
$players_with_rank = $db->query('SELECT `id`, `rank_id` FROM `players` WHERE `rank_id` = ' . $rank->getId() . ' AND `' . $deletedColumn . '` = 0;');
|
||||
|
||||
$players_with_rank_number = $players_with_rank->rowCount();
|
||||
if($players_with_rank_number > 0)
|
||||
|
||||
@@ -13,6 +13,7 @@ use MyAAC\Cache\Cache;
|
||||
use MyAAC\Models\Player;
|
||||
use MyAAC\Models\PlayerDeath;
|
||||
use MyAAC\Models\PlayerKillers;
|
||||
use MyAAC\Server\XML\Vocations;
|
||||
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
$title = 'Highscores';
|
||||
@@ -35,24 +36,20 @@ if(!is_numeric($page) || $page < 1 || $page > PHP_INT_MAX) {
|
||||
$query = Player::query();
|
||||
|
||||
$configVocations = config('vocations');
|
||||
$configVocationsAmount = config('vocations_amount');
|
||||
|
||||
$vocationId = null;
|
||||
if($vocation !== 'all') {
|
||||
foreach($configVocations as $id => $name) {
|
||||
if(strtolower($name) == $vocation) {
|
||||
$vocationId = $id;
|
||||
$add_vocs = [$id];
|
||||
$filterVocations = [$id];
|
||||
|
||||
if ($id !== 0) {
|
||||
$i = $id + $configVocationsAmount;
|
||||
while (isset($configVocations[$i])) {
|
||||
$add_vocs[] = $i;
|
||||
$i += $configVocationsAmount;
|
||||
}
|
||||
while($tmpVoc = Vocations::getPromoted($id)) {
|
||||
$id = $tmpVoc;
|
||||
$filterVocations[] = $tmpVoc;
|
||||
}
|
||||
|
||||
$query->whereIn('players.vocation', $add_vocs);
|
||||
$query->whereIn('players.vocation', $filterVocations);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -176,7 +173,9 @@ if (empty($highscores)) {
|
||||
POT::SKILL_FISH => 'skill_fishing',
|
||||
);
|
||||
|
||||
$query->addSelect($skill_ids[$skill] . ' as value');
|
||||
$query
|
||||
->addSelect($skill_ids[$skill] . ' as value')
|
||||
->orderByDesc($skill_ids[$skill] . '_tries');
|
||||
} else {
|
||||
$query
|
||||
->join('player_skills', 'player_skills.player_id', '=', 'players.id')
|
||||
@@ -198,11 +197,11 @@ if (empty($highscores)) {
|
||||
if ($skill == POT::SKILL__MAGLEVEL) {
|
||||
$query
|
||||
->addSelect('players.maglevel as value', 'players.maglevel')
|
||||
->orderBy('manaspent');
|
||||
->orderByDesc('manaspent');
|
||||
} else { // level
|
||||
$query
|
||||
->addSelect('players.level as value', 'players.experience')
|
||||
->orderBy('experience');
|
||||
->orderByDesc('experience');
|
||||
$list = 'experience';
|
||||
}
|
||||
}
|
||||
@@ -247,7 +246,7 @@ foreach($highscores as $id => &$player)
|
||||
|
||||
$player['link'] = getPlayerLink($player['name'], false);
|
||||
$player['flag'] = getFlagImage($player['country']);
|
||||
$player['outfit'] = '<img style="position:absolute;margin-top:' . (in_array($player['looktype'], setting('core.outfit_images_wrong_looktypes')) ? '-15px;margin-left:5px' : '-45px;margin-left:-25px') . ';" src="' . $player['outfit_url'] . '" alt="" />';
|
||||
$player['outfit'] = '<img style="position:absolute;margin-top:-50px;margin-left:-30px" src="' . $player['outfit_url'] . '" alt="" />';
|
||||
|
||||
if ($skill != POT::SKILL__LEVEL) {
|
||||
if (isset($lastValue) && $lastValue == $player['value']) {
|
||||
@@ -323,4 +322,5 @@ $twig->display('highscores.html.twig', [
|
||||
'page' => $page,
|
||||
'baseLink' => $baseLink,
|
||||
'updatedAt' => $updatedAt,
|
||||
'baseVocations' => Vocations::getBase(true),
|
||||
]);
|
||||
|
||||
@@ -122,7 +122,7 @@ if(!$news_cached)
|
||||
);
|
||||
}
|
||||
|
||||
$tickers_db = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'news` WHERE `type` = ' . TICKER .($canEdit ? '' : ' AND `hide` != 1') .' ORDER BY `date` DESC LIMIT ' . setting('core.news_ticker_limit'));
|
||||
$tickers_db = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'news` WHERE `type` = ' . TICKER . ' AND `hide` != 1 ORDER BY `date` DESC LIMIT ' . setting('core.news_ticker_limit'));
|
||||
$tickers_content = '';
|
||||
if($tickers_db->rowCount() > 0)
|
||||
{
|
||||
@@ -142,7 +142,8 @@ if(!$news_cached)
|
||||
if($cache->enabled() && !$canEdit)
|
||||
$cache->set('news_' . $template_name . '_' . TICKER, $tickers_content, 60 * 60);
|
||||
|
||||
$featured_article_db =$db->query('SELECT `id`, `title`, `article_text`, `article_image`, `hide` FROM `' . TABLE_PREFIX . 'news` WHERE `type` = ' . ARTICLE . ($canEdit ? '' : ' AND `hide` != 1') .' ORDER BY `date` DESC LIMIT 1');
|
||||
$featured_article_db =$db->query('SELECT `id`, `title`, `article_text`, `article_image`, `hide` FROM `' . TABLE_PREFIX . 'news` WHERE `type` = ' . ARTICLE . ' AND `hide` != 1 ORDER BY `date` DESC LIMIT 1');
|
||||
|
||||
$article = '';
|
||||
if($featured_article_db->rowCount() > 0) {
|
||||
$article = $featured_article_db->fetch();
|
||||
@@ -175,7 +176,7 @@ else {
|
||||
if(!$news_cached)
|
||||
{
|
||||
ob_start();
|
||||
$newses = $db->query('SELECT * FROM ' . $db->tableName(TABLE_PREFIX . 'news') . ' WHERE type = ' . NEWS . ($canEdit ? '' : ' AND hide != 1') . ' ORDER BY date' . ' DESC LIMIT ' . setting('core.news_limit'));
|
||||
$newses = $db->query('SELECT * FROM ' . $db->tableName(TABLE_PREFIX . 'news') . ' WHERE type = ' . NEWS . ' AND hide != 1 ORDER BY date' . ' DESC LIMIT ' . setting('core.news_limit'));
|
||||
if($newses->rowCount() > 0)
|
||||
{
|
||||
foreach($newses as $news)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
use MyAAC\Cache\Cache;
|
||||
use MyAAC\Models\ServerConfig;
|
||||
use MyAAC\Models\ServerRecord;
|
||||
use MyAAC\Server\XML\Vocations;
|
||||
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
$title = 'Who is online?';
|
||||
@@ -56,15 +57,14 @@ $cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60
|
||||
|
||||
$vocations = array_map(function ($name) {
|
||||
return 0;
|
||||
}, setting('core.vocations'));
|
||||
}, config('vocations'));
|
||||
|
||||
if($db->hasTable('players_online')) // tfs 1.0
|
||||
$playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql);
|
||||
else
|
||||
$playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', ' . $promotion . ' `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players` WHERE `players`.`online` > 0 AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql);
|
||||
|
||||
$settingVocations = setting('core.vocations');
|
||||
$settingVocationsAmount = setting('core.vocations_amount');
|
||||
$configVocations = config('vocations');
|
||||
|
||||
$players = [];
|
||||
foreach($playersOnline as $player) {
|
||||
@@ -81,22 +81,19 @@ $cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($player['promotion'])) {
|
||||
if((int)$player['promotion'] > 0)
|
||||
$player['vocation'] += ($player['promotion'] * $settingVocationsAmount);
|
||||
}
|
||||
$player['vocation'] = OTS_Toolbox::getVocationFromPromotion($player['vocation'], $player['promotion'] ?? 0);
|
||||
|
||||
$players[] = array(
|
||||
'name' => getPlayerLink($player['name']),
|
||||
'player' => $player,
|
||||
'level' => $player['level'],
|
||||
'vocation' => $settingVocations[$player['vocation']],
|
||||
'vocation' => $configVocations[$player['vocation']],
|
||||
'skull' => $skull,
|
||||
'country_image' => getFlagImage($player['country']),
|
||||
'outfit' => setting('core.outfit_images_url') . '?id=' . $player['looktype'] . ($outfit_addons ? '&addons=' . $player['lookaddons'] : '') . '&head=' . $player['lookhead'] . '&body=' . $player['lookbody'] . '&legs=' . $player['looklegs'] . '&feet=' . $player['lookfeet'],
|
||||
);
|
||||
|
||||
$vocations[($player['vocation'] > $settingVocationsAmount ? $player['vocation'] - $settingVocationsAmount : $player['vocation'])]++;
|
||||
$vocations[Vocations::getOriginal($player['vocation'])]++;
|
||||
}
|
||||
|
||||
$record = '';
|
||||
@@ -142,6 +139,7 @@ $twig->display('online.html.twig', array(
|
||||
'vocations' => $cached['vocations'],
|
||||
'vocs' => $cached['vocations'], // deprecated, to be removed
|
||||
'order' => $order,
|
||||
'baseVocations' => Vocations::getBase(false),
|
||||
));
|
||||
|
||||
// search bar
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
use MyAAC\Models\Menu;
|
||||
use MyAAC\Models\Pages;
|
||||
use MyAAC\Plugins;
|
||||
|
||||
@@ -88,8 +89,10 @@ if($logged && $account_logged && $account_logged->isLoaded()) {
|
||||
/**
|
||||
* Routes loading
|
||||
*/
|
||||
$dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) {
|
||||
$routesFinal = [];
|
||||
$dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) {
|
||||
global $cache, $routesFinal;
|
||||
|
||||
foreach(getDatabasePages() as $page) {
|
||||
$routesFinal[] = ['*', $page, '__database__/' . $page, 100];
|
||||
}
|
||||
@@ -165,7 +168,7 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r)
|
||||
echo '</pre>';
|
||||
die;
|
||||
*/
|
||||
foreach ($routesFinal as $route) {
|
||||
foreach ($routesFinal as &$route) {
|
||||
if ($route[0] === '*') {
|
||||
$route[0] = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD'];
|
||||
}
|
||||
@@ -198,6 +201,10 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r)
|
||||
log_append('router.log', $warning);
|
||||
}
|
||||
}
|
||||
|
||||
if ($cache->enabled()) {
|
||||
$cache->set('routes_final', serialize($routesFinal), 10 * 365 * 24 * 60 * 60); // 10 years / infinite
|
||||
}
|
||||
},
|
||||
[
|
||||
'cacheFile' => CACHE . 'route.cache',
|
||||
@@ -212,7 +219,7 @@ $found = true;
|
||||
|
||||
// old support for pages like /?subtopic=accountmanagement
|
||||
$page = $_REQUEST['p'] ?? ($_REQUEST['subtopic'] ?? '');
|
||||
if(!empty($page) && preg_match('/^[A-z0-9\-]+$/', $page)) {
|
||||
if(!empty($page) && preg_match('/^[A-z0-9\/\-]+$/', $page)) {
|
||||
if (isset($_REQUEST['p'])) { // some plugins may require this
|
||||
$_REQUEST['subtopic'] = $_REQUEST['p'];
|
||||
}
|
||||
@@ -221,11 +228,28 @@ if(!empty($page) && preg_match('/^[A-z0-9\-]+$/', $page)) {
|
||||
require SYSTEM . 'compat/pages.php';
|
||||
}
|
||||
|
||||
$foundRoute = false;
|
||||
|
||||
$tmp = null;
|
||||
if ($cache->enabled() && $cache->fetch('routes_final', $tmp)) {
|
||||
$routesFinal = unserialize($tmp);
|
||||
}
|
||||
|
||||
foreach ($routesFinal as $route) {
|
||||
if ($page === $route[1]) {
|
||||
$file = $route[2];
|
||||
$foundRoute = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$foundRoute) {
|
||||
$file = loadPageFromFileSystem($page, $found);
|
||||
if(!$found) {
|
||||
$file = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$routeInfo = $dispatcher->dispatch($httpMethod, $uri);
|
||||
switch ($routeInfo[0]) {
|
||||
@@ -308,7 +332,20 @@ else {
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
$tmpPageOriginal = $page;
|
||||
$pagesWithDynamicPart = ['characters', 'forum', 'highscores', 'monsters'];
|
||||
foreach ($pagesWithDynamicPart as $_page) {
|
||||
if (str_contains($page, $_page)) {
|
||||
$tmpPageOriginal = $_page;
|
||||
}
|
||||
}
|
||||
|
||||
$themeMenu = Menu::select(['name'])
|
||||
->where('template', $template_name)
|
||||
->where('link', $tmpPageOriginal)
|
||||
->where('access', '>', $logged_access);
|
||||
|
||||
if (!$found || $themeMenu->count() >= 1) {
|
||||
$page = '404';
|
||||
$file = SYSTEM . 'pages/404.php';
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ return [
|
||||
'footer' => [
|
||||
'name' => 'Custom Text',
|
||||
'type' => 'textarea',
|
||||
'desc' => 'Text displayed in the footer.<br/>For example: <i>' . escapeHtml('<br/>') . 'Your Server © 2023. All rights reserved.</i>',
|
||||
'desc' => 'Text displayed in the footer.<br/>For example: <i>' . escapeHtml('<br/>') . 'Your Server © ' . date("Y") . '. All rights reserved.</i>',
|
||||
'default' => '',
|
||||
],
|
||||
'footer_load_time' => [
|
||||
@@ -219,7 +219,14 @@ return [
|
||||
'cache_engine' => [
|
||||
'name' => 'Cache Engine',
|
||||
'type' => 'options',
|
||||
'options' => ['auto' => 'Auto', 'file' => 'Files', 'apc' => 'APC', 'apcu' => 'APCu', 'disable' => 'Disable'],
|
||||
'options' => [
|
||||
'auto' => 'Auto',
|
||||
'file' => 'Files',
|
||||
'apc' => 'APC',
|
||||
'apcu' => 'APCu',
|
||||
'php' => 'PHP',
|
||||
'disable' => 'Disable',
|
||||
],
|
||||
'desc' => 'Auto is most reasonable. It will detect the best cache engine',
|
||||
'default' => 'auto',
|
||||
'is_config' => true,
|
||||
@@ -251,6 +258,28 @@ return [
|
||||
'desc' => 'Allow MyAAC to report anonymous usage statistics to developers? The data is sent only once per 30 days and is fully confidential. It won\'t affect the performance of your website',
|
||||
'default' => true,
|
||||
],
|
||||
[
|
||||
'type' => 'section',
|
||||
'title' => 'Custom HTML',
|
||||
],
|
||||
'html_head' => [
|
||||
'name' => 'HTML Head',
|
||||
'type' => 'textarea',
|
||||
'desc' => escapeHtml('These scripts will be printed in the <head> section. Can be, for example, Google Analytics code.'),
|
||||
'default' => '',
|
||||
],
|
||||
'html_body' => [
|
||||
'name' => 'HTML Body',
|
||||
'type' => 'textarea',
|
||||
'desc' => escapeHtml('These scripts will be printed just below the opening <body> tag.'),
|
||||
'default' => '',
|
||||
],
|
||||
'html_footer' => [
|
||||
'name' => 'HTML Footer',
|
||||
'type' => 'textarea',
|
||||
'desc' => escapeHtml('These scripts will be printed above the closing </body> tag.'),
|
||||
'default' => '',
|
||||
],
|
||||
[
|
||||
'type' => 'category',
|
||||
'title' => 'Game',
|
||||
@@ -312,20 +341,31 @@ return [
|
||||
},
|
||||
],
|
||||
],
|
||||
/**
|
||||
* @deprecated
|
||||
* To be removed in v3.0
|
||||
*/
|
||||
'vocations_amount' => [
|
||||
'name' => 'Vocations Amount',
|
||||
'hidden' => true,
|
||||
'type' => 'number',
|
||||
'desc' => 'How much basic vocations your server got (without promotion)',
|
||||
//'name' => 'Vocations Amount',
|
||||
//'desc' => 'How many basic vocations your server got (without promotion)',
|
||||
'default' => 4,
|
||||
'callbacks' => [
|
||||
'get' => function () {
|
||||
return config('vocations_amount');
|
||||
},
|
||||
],
|
||||
],
|
||||
'vocations' => [
|
||||
'name' => 'Vocation Names',
|
||||
'hidden' => true,
|
||||
'type' => 'textarea',
|
||||
'desc' => 'Separated by comma. Must be in the same order as in vocations.xml, starting with id: 0.',
|
||||
//'name' => 'Vocation Names',
|
||||
//'desc' => 'Separated by comma. Must be in the same order as in vocations.xml, starting with id: 0.',
|
||||
'default' => 'None, Sorcerer, Druid, Paladin, Knight, Master Sorcerer, Elder Druid,Royal Paladin, Elite Knight',
|
||||
'callbacks' => [
|
||||
'get' => function ($value) {
|
||||
return array_map('trim', explode(',', $value));
|
||||
'get' => function () {
|
||||
return config('vocations');
|
||||
},
|
||||
],
|
||||
],
|
||||
@@ -737,6 +777,18 @@ Sent by MyAAC,<br/>
|
||||
'desc' => 'should country of user be automatically recognized by his IP? This makes an external API call to http://ipinfo.io',
|
||||
'default' => true,
|
||||
],
|
||||
'account_countries_most_popular' => [
|
||||
'name' => 'Account Countries Most Popular',
|
||||
'type' => 'text',
|
||||
'desc' => 'Those countries will be display at the top of the list on the create account page. The short codes of countries can be found in file <i>system/countries.conf.php</i>',
|
||||
'default' => 'pl,se,br,us,gb',
|
||||
'callbacks' => [
|
||||
'get' => function ($value) {
|
||||
$tmp = array_map('trim', explode(',', $value));
|
||||
return array_filter($tmp, function ($v) {return !empty($v); });
|
||||
},
|
||||
],
|
||||
],
|
||||
'characters_per_account' => [
|
||||
'name' => 'Characters per Account',
|
||||
'type' => 'number',
|
||||
@@ -1470,17 +1522,6 @@ Sent by MyAAC,<br/>
|
||||
'desc' => 'Set to animoutfit.php for animated outfit',
|
||||
'default' => 'https://outfit-images.ots.me/latest/outfit.php',
|
||||
],
|
||||
'outfit_images_wrong_looktypes' => [
|
||||
'name' => 'Outfit Images Wrong Looktypes',
|
||||
'type' => 'text',
|
||||
'desc' => 'This looktypes needs to have different margin-top and margin-left because they are wrong positioned',
|
||||
'default' => '75, 126, 127, 266, 302',
|
||||
'callbacks' => [
|
||||
'get' => function ($value) {
|
||||
return array_map('trim', explode(',', $value));
|
||||
},
|
||||
],
|
||||
],
|
||||
[
|
||||
'type' => 'section',
|
||||
'title' => 'Monster Images'
|
||||
|
||||
@@ -13,8 +13,8 @@ namespace MyAAC\Cache;
|
||||
|
||||
class APC
|
||||
{
|
||||
private $prefix;
|
||||
private $enabled;
|
||||
private string $prefix;
|
||||
private bool $enabled;
|
||||
|
||||
public function __construct($prefix = '')
|
||||
{
|
||||
@@ -22,14 +22,14 @@ class APC
|
||||
$this->enabled = function_exists('apc_fetch');
|
||||
}
|
||||
|
||||
public function set($key, $var, $ttl = 0)
|
||||
public function set($key, $var, $ttl = 0): void
|
||||
{
|
||||
$key = $this->prefix . $key;
|
||||
apc_delete($key);
|
||||
apc_store($key, $var, $ttl);
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
public function get($key): string
|
||||
{
|
||||
$tmp = '';
|
||||
if ($this->fetch($this->prefix . $key, $tmp)) {
|
||||
@@ -39,18 +39,15 @@ class APC
|
||||
return '';
|
||||
}
|
||||
|
||||
public function fetch($key, &$var)
|
||||
{
|
||||
public function fetch($key, &$var): bool {
|
||||
return ($var = apc_fetch($this->prefix . $key)) !== false;
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
public function delete($key): void {
|
||||
apc_delete($this->prefix . $key);
|
||||
}
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
public function enabled(): bool {
|
||||
return $this->enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ namespace MyAAC\Cache;
|
||||
|
||||
class APCu
|
||||
{
|
||||
private $prefix;
|
||||
private $enabled;
|
||||
private string $prefix;
|
||||
private bool $enabled;
|
||||
|
||||
public function __construct($prefix = '')
|
||||
{
|
||||
@@ -22,14 +22,14 @@ class APCu
|
||||
$this->enabled = function_exists('apcu_fetch');
|
||||
}
|
||||
|
||||
public function set($key, $var, $ttl = 0)
|
||||
public function set($key, $var, $ttl = 0): void
|
||||
{
|
||||
$key = $this->prefix . $key;
|
||||
apcu_delete($key);
|
||||
apcu_store($key, $var, $ttl);
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
public function get($key): string
|
||||
{
|
||||
$tmp = '';
|
||||
if ($this->fetch($this->prefix . $key, $tmp)) {
|
||||
@@ -39,18 +39,15 @@ class APCu
|
||||
return '';
|
||||
}
|
||||
|
||||
public function fetch($key, &$var)
|
||||
{
|
||||
public function fetch($key, &$var): bool {
|
||||
return ($var = apcu_fetch($this->prefix . $key)) !== false;
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
public function delete($key): void {
|
||||
apcu_delete($this->prefix . $key);
|
||||
}
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
public function enabled(): bool {
|
||||
return $this->enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,35 +47,15 @@ class Cache
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
switch (strtolower($engine)) {
|
||||
case 'apc':
|
||||
self::$instance = new APC($prefix);
|
||||
break;
|
||||
|
||||
case 'apcu':
|
||||
self::$instance = new APCu($prefix);
|
||||
break;
|
||||
|
||||
case 'xcache':
|
||||
self::$instance = new XCache($prefix);
|
||||
break;
|
||||
|
||||
case 'file':
|
||||
self::$instance = new File($prefix, CACHE);
|
||||
break;
|
||||
|
||||
case 'php':
|
||||
self::$instance = new PHP($prefix, CACHE);
|
||||
break;
|
||||
|
||||
case 'auto':
|
||||
self::$instance = self::generateInstance(self::detect(), $prefix);
|
||||
break;
|
||||
|
||||
default:
|
||||
self::$instance = new self();
|
||||
break;
|
||||
}
|
||||
self::$instance = match (strtolower($engine)) {
|
||||
'apc' => new APC($prefix),
|
||||
'apcu' => new APCu($prefix),
|
||||
'xcache' => new XCache($prefix),
|
||||
'file' => new File($prefix, CACHE),
|
||||
'php' => new PHP($prefix, CACHE),
|
||||
'auto' => self::generateInstance(self::detect(), $prefix),
|
||||
default => new self(),
|
||||
};
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
@@ -83,7 +63,7 @@ class Cache
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function detect()
|
||||
public static function detect(): string
|
||||
{
|
||||
if (function_exists('apc_fetch'))
|
||||
return 'apc';
|
||||
@@ -98,8 +78,7 @@ class Cache
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function enabled()
|
||||
{
|
||||
public function enabled(): bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -115,6 +94,11 @@ class Cache
|
||||
return unserialize($value);
|
||||
}
|
||||
|
||||
// -1 for infinite cache
|
||||
if ($ttl == -1) {
|
||||
$ttl = 10 * 365 * 24 * 60 * 60; // 10 years should be enough
|
||||
}
|
||||
|
||||
$value = $callback();
|
||||
$cache->set($key, serialize($value), $ttl);
|
||||
return $value;
|
||||
|
||||
@@ -12,18 +12,22 @@ namespace MyAAC\Cache;
|
||||
|
||||
class File
|
||||
{
|
||||
private $prefix;
|
||||
private $dir;
|
||||
private $enabled;
|
||||
private string $prefix;
|
||||
private string $dir;
|
||||
private bool $enabled;
|
||||
|
||||
public function __construct($prefix = '', $dir = '')
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
$this->dir = $dir;
|
||||
|
||||
ensureFolderExists($this->dir);
|
||||
ensureIndexExists($this->dir);
|
||||
|
||||
$this->enabled = (file_exists($this->dir) && is_dir($this->dir) && is_writable($this->dir));
|
||||
}
|
||||
|
||||
public function set($key, $var, $ttl = 0)
|
||||
public function set($key, $var, $ttl = 0): void
|
||||
{
|
||||
$file = $this->_name($key);
|
||||
file_put_contents($file, $var);
|
||||
@@ -35,7 +39,7 @@ class File
|
||||
touch($file, time() + $ttl);
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
public function get($key): string
|
||||
{
|
||||
$tmp = '';
|
||||
if ($this->fetch($key, $tmp)) {
|
||||
@@ -45,7 +49,7 @@ class File
|
||||
return '';
|
||||
}
|
||||
|
||||
public function fetch($key, &$var)
|
||||
public function fetch($key, &$var): bool
|
||||
{
|
||||
$file = $this->_name($key);
|
||||
if (!file_exists($file) || filemtime($file) < time()) {
|
||||
@@ -56,7 +60,7 @@ class File
|
||||
return true;
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
public function delete($key): void
|
||||
{
|
||||
$file = $this->_name($key);
|
||||
if (file_exists($file)) {
|
||||
@@ -64,13 +68,11 @@ class File
|
||||
}
|
||||
}
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
public function enabled(): bool {
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
private function _name($key)
|
||||
{
|
||||
private function _name($key): string {
|
||||
return sprintf('%s%s%s', $this->dir, $this->prefix, sha1($key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,33 +12,37 @@ namespace MyAAC\Cache;
|
||||
|
||||
class PHP
|
||||
{
|
||||
private $prefix;
|
||||
private $dir;
|
||||
private $enabled;
|
||||
private string $prefix;
|
||||
private string $dir;
|
||||
private bool $enabled;
|
||||
|
||||
public function __construct($prefix = '', $dir = '')
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
$this->dir = $dir;
|
||||
|
||||
ensureFolderExists($this->dir);
|
||||
ensureIndexExists($this->dir);
|
||||
|
||||
$this->enabled = (file_exists($this->dir) && is_dir($this->dir) && is_writable($this->dir));
|
||||
}
|
||||
|
||||
public function set($key, $var, $ttl = 0)
|
||||
public function set($key, $var, $ttl = 0): void
|
||||
{
|
||||
$var = var_export($var, true);
|
||||
|
||||
// Write to temp file first to ensure atomicity
|
||||
$tmp = $this->dir . "tmp_$key." . uniqid('', true) . '.tmp';
|
||||
file_put_contents($tmp, '<?php $var = ' . $var . ';', LOCK_EX);
|
||||
|
||||
$file = $this->_name($key);
|
||||
rename($tmp, $file);
|
||||
|
||||
if ($ttl === 0) {
|
||||
$ttl = 365 * 24 * 60 * 60; // 365 days
|
||||
}
|
||||
|
||||
touch($file, time() + $ttl);
|
||||
$expires = time() + $ttl;
|
||||
|
||||
// Write to temp file first to ensure atomicity
|
||||
$tmp = $this->dir . "tmp_$key." . uniqid('', true) . '.tmp';
|
||||
file_put_contents($tmp, "<?php return ['expires' => $expires, 'var' => $var];", LOCK_EX);
|
||||
|
||||
$file = $this->_name($key);
|
||||
rename($tmp, $file);
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
@@ -51,19 +55,23 @@ class PHP
|
||||
return '';
|
||||
}
|
||||
|
||||
public function fetch($key, &$var)
|
||||
public function fetch($key, &$var): bool
|
||||
{
|
||||
$file = $this->_name($key);
|
||||
if (!file_exists($file) || filemtime($file) < time()) {
|
||||
if (!file_exists($file)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@include $file;
|
||||
$var = isset($var) ? $var : null;
|
||||
$content = include $file;
|
||||
if (!isset($content) || $content['expires'] < time()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$var = $content['var'];
|
||||
return true;
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
public function delete($key): void
|
||||
{
|
||||
$file = $this->_name($key);
|
||||
if (file_exists($file)) {
|
||||
@@ -71,13 +79,11 @@ class PHP
|
||||
}
|
||||
}
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
public function enabled(): bool {
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
private function _name($key)
|
||||
{
|
||||
private function _name($key): string {
|
||||
return sprintf('%s%s%s', $this->dir, $this->prefix, sha1($key) . '.php');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ namespace MyAAC\Cache;
|
||||
|
||||
class XCache
|
||||
{
|
||||
private $prefix;
|
||||
private $enabled;
|
||||
private string $prefix;
|
||||
private bool $enabled;
|
||||
|
||||
public function __construct($prefix = '')
|
||||
{
|
||||
@@ -22,14 +22,14 @@ class XCache
|
||||
$this->enabled = function_exists('xcache_get') && ini_get('xcache.var_size');
|
||||
}
|
||||
|
||||
public function set($key, $var, $ttl = 0)
|
||||
public function set($key, $var, $ttl = 0): void
|
||||
{
|
||||
$key = $this->prefix . $key;
|
||||
xcache_unset($key);
|
||||
xcache_set($key, $var, $ttl);
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
public function get($key): string
|
||||
{
|
||||
$tmp = '';
|
||||
if ($this->fetch($this->prefix . $key, $tmp)) {
|
||||
@@ -39,7 +39,7 @@ class XCache
|
||||
return '';
|
||||
}
|
||||
|
||||
public function fetch($key, &$var)
|
||||
public function fetch($key, &$var): bool
|
||||
{
|
||||
$key = $this->prefix . $key;
|
||||
if (!xcache_isset($key)) {
|
||||
@@ -50,13 +50,11 @@ class XCache
|
||||
return true;
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
public function delete($key): void {
|
||||
xcache_unset($this->prefix . $key);
|
||||
}
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
public function enabled(): bool {
|
||||
return $this->enabled;
|
||||
}
|
||||
}
|
||||
|
||||
33
system/src/Commands/Env.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace MyAAC\Commands;
|
||||
|
||||
use POT;
|
||||
|
||||
trait Env
|
||||
{
|
||||
protected function init(): void
|
||||
{
|
||||
global $config;
|
||||
if (!isset($config['installed']) || !$config['installed']) {
|
||||
throw new \RuntimeException('MyAAC has not been installed yet or there was error during installation. Please install again.');
|
||||
}
|
||||
|
||||
if(empty($config['server_path'])) {
|
||||
throw new \RuntimeException('Server Path has been not set. Go to config.php and set it.');
|
||||
}
|
||||
|
||||
// take care of trailing slash at the end
|
||||
if($config['server_path'][strlen($config['server_path']) - 1] !== '/')
|
||||
$config['server_path'] .= '/';
|
||||
|
||||
$config['lua'] = load_config_lua($config['server_path'] . 'config.lua');
|
||||
|
||||
// POT
|
||||
require_once SYSTEM . 'libs/pot/OTS.php';
|
||||
$ots = POT::getInstance();
|
||||
$eloquentConnection = null;
|
||||
|
||||
require_once SYSTEM . 'database.php';
|
||||
}
|
||||
}
|
||||
50
system/src/Commands/GiveAdminCommand.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace MyAAC\Commands;
|
||||
|
||||
use MyAAC\Plugins;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
class GiveAdminCommand extends Command
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setName('give:admin')
|
||||
->setDescription('This command adds super admin privileges to selected user')
|
||||
->addArgument('account', InputArgument::REQUIRED, 'Account E-Mail, name or id');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
require SYSTEM . 'init.php';
|
||||
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$account = new \OTS_Account();
|
||||
|
||||
$accountParam = $input->getArgument('account');
|
||||
if (str_contains($accountParam, '@')) {
|
||||
$account->findByEMail($accountParam);
|
||||
}
|
||||
else {
|
||||
if (USE_ACCOUNT_NAME || USE_ACCOUNT_NUMBER) {
|
||||
$account->find($accountParam);
|
||||
}
|
||||
else {
|
||||
$account->load($accountParam);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$account->isLoaded()) {
|
||||
$io->error('Cannot find account mit supplied parameter: ' . $accountParam);
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
$account->setCustomField('web_flags', 3);
|
||||
$io->success('Successfully added admin privileges to ' . $accountParam . ' (E-Mail: ' . $account->getEMail() . ')');
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@ use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
class MigrateCommand extends Command
|
||||
{
|
||||
use Env;
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setName('migrate')
|
||||
@@ -17,9 +19,19 @@ class MigrateCommand extends Command
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
require SYSTEM . 'init.php';
|
||||
$this->init();
|
||||
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$tmp = '';
|
||||
if(fetchDatabaseConfig('database_version', $tmp)) { // we got version
|
||||
$tmp = (int)$tmp;
|
||||
if ($tmp >= DATABASE_VERSION) {
|
||||
$io->success('Already on latest version.');
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
require SYSTEM . 'migrate.php';
|
||||
|
||||
$io->success('Migrated to latest version (' . DATABASE_VERSION . ')');
|
||||
|
||||
@@ -10,6 +10,8 @@ use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
class MigrateRunCommand extends Command
|
||||
{
|
||||
use Env;
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setName('migrate:run')
|
||||
@@ -23,12 +25,12 @@ class MigrateRunCommand extends Command
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
require SYSTEM . 'init.php';
|
||||
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$ids = $input->getArgument('id');
|
||||
|
||||
$this->init();
|
||||
|
||||
// pre-check
|
||||
// in case one of the migrations doesn't exist - we won't execute any of them
|
||||
foreach ($ids as $id) {
|
||||
|
||||