Compare commits

...

370 Commits

Author SHA1 Message Date
slawkens
b5b2e3fd78 Update CHANGELOG.md 2025-01-14 00:19:16 +01:00
slawkens
030d15f0cd Fix branch name 2025-01-14 00:17:33 +01:00
slawkens
b6b7592226 Release v1.0.1 2025-01-13 23:17:58 +01:00
slawkens
fb10741a02 Fix typo in account word 2025-01-13 23:15:57 +01:00
slawkens
5e9c868dfa Fix tibiacom account & news menu links 2025-01-13 23:05:16 +01:00
slawkens
0904b1bb87 Fix phpstan 2025-01-13 22:23:43 +01:00
slawkens
faa60f5e9a Fix phpstan and phplint branches 2025-01-13 22:15:48 +01:00
slawkens
620e0f62e4 Fix cypress run workflow 2025-01-13 22:10:52 +01:00
slawkens
2ae2ec3353 Fix link to monsters 2025-01-13 22:09:15 +01:00
slawkens
b323d9cee1 Update cypress to ^13.17.0 2025-01-13 22:09:04 +01:00
slawkens
4f1d1d8043 Update tinymce to ^7.2.0 2025-01-13 21:50:37 +01:00
slawkens
8e5a3afc6e Update myaac version 2025-01-13 21:41:49 +01:00
slawkens
a7311301e2 Update composer.lock 2025-01-13 21:40:16 +01:00
slawkens
ac10236154 Update twig dependency to ^3.11 (disable dependabot alert) 2025-01-13 21:40:09 +01:00
slawkens
dc95bc4bad Merge branch 'master' of https://github.com/slawkens/myaac 2025-01-13 21:18:50 +01:00
dependabot[bot]
0dc7da472f Bump nesbot/carbon from 2.72.5 to 2.72.6 (#276)
Bumps [nesbot/carbon](https://github.com/CarbonPHP/carbon) from 2.72.5 to 2.72.6.
- [Release notes](https://github.com/CarbonPHP/carbon/releases)
- [Commits](https://github.com/CarbonPHP/carbon/compare/2.72.5...2.72.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 21:16:29 +01:00
slawkens
43421e56ea Update nginx-sample.conf 2025-01-13 20:34:40 +01:00
slawkens
544d006b6f v1.0 - Hello! 2025-01-12 17:44:18 +01:00
slawkens
085ebbcfde All $cache->set calls should have $ttl 2025-01-12 17:13:25 +01:00
slawkens
77a2c1cec3 Support for plugin themes in menus.php 2025-01-12 16:27:20 +01:00
slawkens
e918591666 Ignore PhpStan error 2025-01-09 22:59:02 +01:00
slawkens
175c2a1f89 Fix PhpStan 2025-01-09 22:52:30 +01:00
slawkens
3b5be1a8db Add player->outfit_url attribute 2025-01-09 22:41:34 +01:00
slawkens
c769962e39 Refactor getTopPlayers function
* Option to getTopPlayers by balance
* use Cache::remember
2025-01-09 22:40:57 +01:00
slawkens
35dfaa28ed Update index.php 2025-01-09 20:57:23 +01:00
slawkens
8e501c0e9c Shorten code with Cache::remember 2025-01-09 15:50:33 +01:00
slawkens
c52ca27126 Fix if someone deletes the default kathrine template 2025-01-09 15:41:22 +01:00
slawkens
41a3cb6f42 vendor should be accessible, cause of 2025-01-09 13:39:05 +01:00
slawkens
eb4b3ada49 Adjust post_ip to support ipv6 2025-01-09 13:10:04 +01:00
slawkens
68bdec7c18 Fix ip size 2025-01-09 13:06:33 +01:00
slawkens
8a612429b2 Use $db->insert instead of manual query 2025-01-09 13:03:55 +01:00
slawkens
16671ea40b Fix change sex price deducted 2025-01-09 09:44:12 +01:00
slawkens
8fb643596f Fix more XSS in forum 2025-01-08 23:22:51 +01:00
slawkens
c2b7286d20 Fix XSS in forum new_post 2025-01-08 23:13:40 +01:00
slawkens
d6c40c836a Fix move_thread by unauthorized user 2025-01-08 22:36:49 +01:00
slawkens
99262c3ebd Fix DataLoader Towns cache 2025-01-07 15:03:39 +01:00
slawkens
b8396d4c84 Fix for TFS 1.4.2 where conditions is NULL 2024-12-29 15:46:02 +01:00
slawkens
b0c8cf2ecd Add $whoopsHandler as variable, can be used by other scripts 2024-12-29 15:45:33 +01:00
slawkens
da1816cc13 use https 2024-12-20 22:42:46 +01:00
slawkens
783d96fc65 Set default_socket_timeout for ipinfo.io checkup 2024-12-20 22:42:35 +01:00
slawkens
988a3f2dbe Display created by id 2024-12-19 22:32:28 +01:00
slawkens
8e0978c1ed Adjustments regarding accounts.id in admin panel -> Accounts editor
getAccountIdentityColumn() function
2024-12-19 22:32:05 +01:00
slawkens
023f1dc598 Support for accounts.id when there is no accounts.name and accounts.number 2024-12-19 21:52:05 +01:00
slawkens
ea5e1d4192 Fix IDE warning about form 2024-12-07 18:53:09 +01:00
slawkens
06188be6e1 Fix $vocs not found 2024-12-07 13:52:52 +01:00
slawkens
2c42de688a Fixes to tibiacom menus ActiveSubmenuItem 2024-12-07 10:28:01 +01:00
slawkens
4ac56e6b15 tabs 2024-12-05 21:49:02 +01:00
slawkens
5e60249603 Update buttons.create_character.html.twig 2024-12-05 21:44:48 +01:00
slawkens
d8b6b749ee Support for button_color (green, red, blue) 2024-12-05 21:44:06 +01:00
slawkens
c5e114d550 Update dependencies 2024-12-04 16:00:30 +01:00
slawkens
706fca8868 update phpneon 2024-12-04 15:46:07 +01:00
slawkens
65adf9ccdd Load deprecated classes + add Cache class 2024-12-03 20:12:03 +01:00
slawkens
bc6663dc44 Fix online vocations numbers, thanks Marko999x 2024-11-25 20:28:00 +01:00
slawkens
e3ffe5d9e1 Display warning if zip extension is not installed 2024-11-23 14:29:16 +01:00
slawkens
c0a66037e0 Fix column not found - hidden/hide 2024-11-22 16:04:48 +01:00
slawkens
17210b717f Execute updated migrations with $up() function 2024-11-22 16:04:19 +01:00
slawkens
5782772b90 Remove bugtracker SQL table as the page has been removed 2024-11-22 15:53:57 +01:00
slawkens
27c44f1bdf schema: Change character set to utf8mb4 (support for Emojis in Menus/Pages/News/Forum etc.) 2024-11-22 15:52:54 +01:00
Slawomir Boczek
3f6ff3a332 Feature migrations up/down (#270)
* Migrations up down

* Add forum model

* Syntactic sugar for db structure changes

* Refactor migrations with $up & $down

* Fix migrations upgrade and downgrade

+ Add option to disable auto migrate

* Add migrate:to command

Usage: php aac migrate:to x (x - database version)

* Show error when mail is not enabled

* Fixes regarding to init.php

* Add migrate command to manually upgrade db, incase auto migrate is disabled

* Fixed rest of the migrations

* Limit max version of database

* Don't allow minus number

* Option to clear specified plugin settings by name

* Version is required

* Fix PHPStan errors

* Unset $up after migration, to prevent executing same migration twice

* Add database version to output

* This is not needed

* Update 5.php

* Set database_auto_migrate on install

* Set blank & color only if current db version supports it

* Fix duplicate function declaration
2024-11-22 15:29:23 +01:00
slawkens
79636280a7 Move current password input to the top, makes more sense 2024-11-19 20:55:53 +01:00
slawkens
38e699ba4b PHP 8.1 is required 2024-11-19 14:21:31 +01:00
slawkens
afb055f2dc More obvious name for parameter in -> installMenus 2024-11-19 14:21:15 +01:00
slawkens
6f58df0467 Update twig.php 2024-11-19 14:08:27 +01:00
slawkens
95343cec02 Change to str_contains 2024-11-19 14:08:24 +01:00
slawkens
8055785c81 Fix installMenus function 2024-11-19 07:48:52 +01:00
slawkens
64e4c08950 MyAAC\Cache 2024-11-19 07:19:43 +01:00
slawkens
12d8faa3ed Do not clear menus by default 2024-11-19 07:05:27 +01:00
slawkens
1e6892971b Change spaces to tabs 2024-11-19 07:03:06 +01:00
slawkens
8ae22accc9 Fix for console displaying REQUEST_URI 2024-11-18 23:49:26 +01:00
slawkens
a2fadc5945 Fixes to installMenus function 2024-11-18 23:48:03 +01:00
slawkens
d0b4065ccf Optimise news management 2024-11-18 15:04:53 +01:00
slawkens
84d37c5a8f Allow OTS_Player to be passed as object to getPlayerLink 2024-11-17 18:07:10 +01:00
slawkens
28a2b34cc1 Update account.management.html.twig 2024-11-12 22:19:21 +01:00
slawkens
bab565fbd0 Update init.php 2024-11-12 22:01:15 +01:00
slawkens
36bd3eb846 New hooks for news management
Can be used for example as discord hooks
2024-11-12 22:01:00 +01:00
slawkens
85bc2342cf Fix missing bracket opening 2024-11-12 21:03:43 +01:00
slawkens
507402171b Patching from master some small adjustments (Account Logs typo + forum new thread show button by @anyeor) 2024-11-12 21:01:14 +01:00
slawkens
941846605c Prefer get_browser_real_ip() over REMOTE_ADDR 2024-11-12 20:59:51 +01:00
slawkens
a4a2480995 Add None vocation to highscores (can be changed to RookStayer in Admin Panel) 2024-11-12 20:51:45 +01:00
slawkens
ddced132cf Fix if highscores_vocation box is disabled causing Choose a vocation dropdown to fail 2024-11-12 20:42:06 +01:00
slawkens
749e8e6f02 Fix choose a skill dropdown 2024-11-11 22:04:06 +01:00
slawkens
7d787b4566 Update database.php 2024-11-10 20:25:46 +01:00
slawkens
7e67e11e16 More understandable argument name 2024-11-10 20:25:42 +01:00
slawkens
011a85d8ae new hook: HOOK_ADMIN_NEWS_ADD 2024-11-10 20:25:17 +01:00
slawkens
382f897322 Update settings.php 2024-11-07 19:07:46 +01:00
slawkens
c980a09146 Rewrite towns loading code, removed OTBM loader (was too slow)
By default load from towns table in db
2024-11-07 19:07:15 +01:00
slawkens
18bd325a44 fix label 2024-11-07 14:44:46 +01:00
slawkens
078e20a9a4 cleanup 2024-11-07 14:44:18 +01:00
slawkens
e96227fbe4 Automatically set selected current one on highscores filters 2024-11-07 14:44:08 +01:00
slawkens
c49c9d99a9 Fix PHP Fatal error 2024-10-27 20:40:48 +01:00
slawkens
a0f1971583 Fix login if limiter is disabled 2024-10-25 19:01:28 +02:00
slawkens
cb5fc84e2e Release v1.0-RC.2 2024-10-25 10:54:03 +02:00
slawkens
29b77035be Update CHANGELOG.md 2024-10-25 10:53:50 +02:00
slawkens
b8c0215720 Fix if loot is empty 2024-10-24 15:55:32 +02:00
slawkens
3100faa645 Fix highscores skills for servers that use player_skills table 2024-10-11 20:35:12 +02:00
slawkens
f7c9a67a96 More fixes to displaying online record 2024-10-04 21:36:13 +02:00
slawkens
e8fedb8d16 One bracket to much.. 2024-10-04 21:26:28 +02:00
slawkens
4e4739e8ab Fix displaying players online record 2024-10-04 21:23:41 +02:00
slawkens
c6cc84a668 Fix RateLimit when cache is disabled 2024-09-19 21:25:54 +02:00
slawkens
95a7c23a70 Use PHP 8 functions 2024-09-14 11:48:56 +02:00
slawkens
a7fe400614 Use Validator::characterName 2024-09-14 11:48:43 +02:00
slawkens
2568046a4d nothing important: brackets 2024-09-14 11:16:47 +02:00
slawkens
7161678c4b Add missing Validator::characterName check 2024-09-12 09:40:01 +02:00
slawkens
93641fc68a New hooks in account manage + create 2024-09-08 15:03:18 +02:00
slawkens
ea7e808508 Add more clients (13.22+) 2024-09-08 14:48:59 +02:00
slawkens
da3fc1fc8c Interesting update from opentibiabr (Uptime readable) 2024-09-08 14:48:42 +02:00
slawkens
201f95caa8 Do not create player if there is no players table in db 2024-09-05 15:36:19 +02:00
slawkens
779aa152fa Do not require players & guilds tables 2024-09-05 15:35:55 +02:00
slawkens
d99b22f98b Fix attempts counting 2024-08-26 15:19:37 +02:00
slawkens
35e28350bd Change spaces to tabs 2024-08-26 15:19:17 +02:00
Gabriel Pedro
327dcb5f87 feat: ratelimit (#267)
* feat: rate limit settings

* fix: section label

* fix: real ip

* fix: real ip
2024-08-26 14:53:09 +02:00
Gabriel Pedro
bc8ada6fe2 fix: verified email for login.php (#265)
* fix: required email login verify

* fix: add missing select column

* Revert "fix: add missing select column"

This reverts commit db79e3118a.
2024-08-25 13:40:32 +02:00
Gabriel Pedro
6183b7ee52 chore: drop raw queries (#266)
* chore: eloquent migrate

* fix: typos
2024-08-25 13:38:58 +02:00
Jonatas
760c3ab017 Highscore frags fixed for TFS 0.3 (#263) 2024-08-16 18:19:44 +02:00
slawkens
ab73d60c61 Fix warning if core.account_country is disabled 2024-08-12 23:01:45 +02:00
slawkens
8d8bdb6dac Fix missing groups variable #262. thanks @Scrollog for reporting 2024-08-12 22:54:23 +02:00
slawkens
71c00aa5e0 Use https for outfit & item images 2024-08-01 23:17:07 +02:00
slawkens
1fcdd54c94 Patching from master
OTS_House refactor code + $db->update with nulls
2024-07-25 15:43:42 +02:00
slawkens
c2ec468246 feat: search by email in accounts editor 2024-07-23 22:56:31 +02:00
slawkens
68118fb7c2 Update phpstan.neon 2024-07-23 08:47:22 +02:00
slawkens
5a69b9a802 Update composer.lock 2024-07-23 08:45:55 +02:00
slawkens
45e63b13c3 Update version to 1.0-RC 2024-07-23 08:35:08 +02:00
slawkens
758a8b3330 Prepare changelog for 1.0-RC
Release Candidate.
2024-07-23 08:30:53 +02:00
slawkens
1843728930 Rename to playerSample 2024-07-23 08:07:59 +02:00
slawkens
cff62ccba4 Another try 2024-07-12 20:54:12 +02:00
slawkens
28f98db9de Fix PHPStan errors in monsters.php 2024-07-12 20:48:27 +02:00
slawkens
da14e125e9 Fix highscores skill links (Thanks @vyroq) 2024-07-12 20:01:12 +02:00
slawkens
cd49dfc799 Set Admin Account verified by default 2024-07-10 18:12:05 +02:00
slawkens
ef79b99b8a Fix monster not found exception 2024-07-10 09:54:54 +02:00
slawkens
9a27403e7d Fixes to account_mail_verify 2024-07-09 23:35:39 +02:00
slawkens
5f63c3b227 Invalidate cached setting 2024-07-09 23:33:00 +02:00
slawkens
203e411b62 Allow account_create_character_create even if account_mail_verify is activated 2024-07-09 23:06:12 +02:00
slawkens
fcb13f3c0f Fixes to account verify - do not allow login without verified email (Thanks @anyeor) 2024-07-09 23:05:36 +02:00
slawkens
d94828772c Rework 5th step of installation, to fix some pointless message about Cache 2024-07-09 22:04:47 +02:00
slawkens
10a739773c Detect tools/ext exists on install to prevent broken installs 2024-07-09 21:29:42 +02:00
slawkens
83b3dc803a Fix 5th step of installer 2024-07-08 19:50:05 +02:00
slawkens
33a47137c9 Fix hooks priority default 2024-06-29 15:09:44 +02:00
slawkens
dc17b701da feat: Hooks priority 2024-06-29 14:05:06 +02:00
slawkens
d30811404b Update players.php 2024-06-28 19:03:06 +02:00
slawkens
a631760dbf Order fraggers by time 2024-06-23 16:10:50 +02:00
slawkens
bc3dcab462 deny all is enough 2024-06-23 09:55:15 +02:00
slawkens
a8d255c04b feat: Plugins pages: subSubFolders 2024-06-14 08:07:52 +02:00
slawkens
813786c768 Update cleanup_players.php 2024-06-14 06:42:45 +02:00
slawkens
0db0ec1aa4 Fix useGuildNick displaying 2024-06-14 06:42:42 +02:00
slawkens
bdc0c43d3f Refactor account routes into sub folders 2024-06-13 22:23:43 +02:00
slawkens
c7a6a539a9 Another approach to fix duplicates - priorities
Priority description: (lower number - higher priority)
1-99 Highest priority - overrides everything, even pages from database, use with caption
100 - default for pages in database
101-999 - recommended range for plugins
1000 - default value for plugins if no other specified
1001 - 9999 - no usage currently
10000 - default myaac routes
2024-06-13 21:35:47 +02:00
slawkens
c1d4b4f80c Make autoload of pages, commands and themes configurable
Not everyone might want them to autoload
2024-06-13 14:36:18 +02:00
slawkens
47a19e85dd Reposition code for setting ranks (addition to previous commit) 2024-06-13 13:07:03 +02:00
slawkens
d9c1b2507c Create guild_rank entries, in case MySQL trigger not loaded 2024-06-13 12:51:29 +02:00
slawkens
4c0739d3e9 Fixed fastRoute duplicate errors 2024-06-13 11:29:06 +02:00
slawkens
afe70a03c5 Fix email_change status 2024-06-11 13:32:22 +02:00
slawkens
3fadf87a7a Fix title on login page 2024-06-11 13:14:15 +02:00
slawkens
c24576165c login.php early exit + fix title 2024-06-11 12:55:02 +02:00
slawkens
1e5c9dcd9b Nothing important, just a space for better look! 2024-06-10 19:43:08 +02:00
slawkens
a04d186c22 Fix highscores frags for TFS 1.x and canary 2024-06-10 18:53:17 +02:00
slawkens
42f99c3edc Fraggers in characters page for TFS 1.x and canary 2024-06-08 23:27:19 +02:00
slawkens
4f4965369d spaces -> tabs 2024-06-05 21:53:58 +02:00
slawkens
57b47ab798 Fix if <flags> are not present in monster.xml 2024-06-05 21:51:50 +02:00
slawkens
9ea2a5067f Order towns by id 2024-06-05 15:10:55 +02:00
slawkens
ec96985872 Revert some breaking change 2024-06-01 18:44:06 +02:00
slawkens
9f2a51b351 Spaces and remove useless function 2024-06-01 15:53:34 +02:00
slawkens
a1d7c94166 Closing tag 2024-06-01 15:51:28 +02:00
slawkens
0c3e3e16dd Set default group_id 2024-06-01 15:51:21 +02:00
slawkens
45dda5e834 Add HOOK_ACCOUNT_CREATE_CHARACTER_* hooks 2024-05-31 22:59:52 +02:00
slawkens
32ae4dde20 Fix closing table elements 2024-05-31 22:57:44 +02:00
slawkens
d3f03fa735 Better place for INSTALL_FINISH hook 2024-05-31 19:21:37 +02:00
slawkens
44eff8092c Fix settings title 2024-05-31 18:30:01 +02:00
slawkens
8ef3d06f1e Fix duplicated routes 2024-05-31 17:22:39 +02:00
slawkens
60bd64a639 Update router.php 2024-05-30 20:40:15 +02:00
slawkens
a1bcb217ec Fixes regarding not working google recaptcha (+few previous commits) 2024-05-30 17:36:07 +02:00
slawkens
933b681a9f Fixed if account_country is disabled 2024-05-30 14:25:31 +02:00
slawkens
e9aea17e1b Close form in proper place 2024-05-30 14:21:52 +02:00
slawkens
060400b074 Revert "Use tables headline for account.create.html.twig"
This reverts commit 64387e085b.
2024-05-30 13:48:59 +02:00
slawkens
6be4a42c5a Revert "Fix form id"
This reverts commit d225c2da26.
2024-05-30 13:48:53 +02:00
slawkens
1e8198635e Enable dev mode on install, prevent noobs asking white page questions 2024-05-30 12:00:26 +02:00
slawkens
be78a0fc45 Do adjustments only if table exist 2024-05-30 11:32:03 +02:00
slawkens
08ac8ebade Add HOOK_INSTALL_FINISH 2024-05-30 11:31:41 +02:00
slawkens
66ecc487a1 One more early exit 2024-05-30 11:18:06 +02:00
slawkens
9e23ec6745 Early exit in 7-finish install 2024-05-30 11:14:16 +02:00
slawkens
968899ef77 Pass $playerSample as parameter to hook 2024-05-30 10:09:31 +02:00
slawkens
3844ad0d71 Fix warnings in basic.js 2024-05-30 09:49:02 +02:00
slawkens
c93bf5a984 create_character_name_min_length => 3 2024-05-30 09:02:19 +02:00
slawkens
50336a810b Fix blessings longer than 3 characters 2024-05-30 08:23:31 +02:00
slawkens
48f6ca0eba Tabs + spaces 2024-05-30 08:20:59 +02:00
slawkens
30107222d4 Add getLongLong function to OTS_Buffer 2024-05-30 08:20:33 +02:00
slawkens
f92b275f70 Update version to beta.2 2024-05-23 23:44:29 +02:00
slawkens
504242fb84 Do not create news about myaac, if any news already exist (on installation) 2024-05-23 23:40:27 +02:00
slawkens
e2bab4220b Fix composer install 2024-05-18 22:31:59 +02:00
slawkens
0b4c34a823 Update phpstan.yml 2024-05-18 22:20:00 +02:00
slawkens
c5aa9a4684 Do not include phpstan into release 2024-05-18 22:19:23 +02:00
slawkens
301afe190b Remove node_modules in release script 2024-05-18 22:01:41 +02:00
slawkens
c35cc83e4f They say composer.lock should be commited - let it be! 2024-05-18 22:01:30 +02:00
slawkens
3ba9d8f780 Fix date 2024-05-18 21:56:01 +02:00
slawkens
06f228509b Update release.sh 2024-05-18 21:53:41 +02:00
slawkens
39e682dfd2 htmlspecialchars seems to be better here (?) 2024-05-16 18:58:54 +02:00
slawkens
6f209440e0 Fix XSS in monsters.php, thanks to @gesior 2024-05-15 22:18:39 +02:00
slawkens
b2a1675de3 Fix if account_country is disabled 2024-04-16 13:32:34 +02:00
slawkens
163877d303 Update account.generate_recovery_key.html.twig 2024-04-16 11:38:10 +02:00
slawkens
a4d11c1a12 Rename variables 2024-04-16 10:45:34 +02:00
slawkens
8cf4e3da02 Fix change_info if account_country is disabled 2024-04-15 21:54:18 +02:00
slawkens
e0230c5237 Adjustments in success.html.twig 2024-04-15 21:47:21 +02:00
slawkens
127e03081c Support for subfolders in plugins/pages 2024-04-15 21:21:16 +02:00
slawkens
e9c6017e60 Fix forum table header text color 2024-04-15 20:35:53 +02:00
slawkens
d5915df37e Fix redirects in forum + polls 2024-04-14 16:06:57 +02:00
slawkens
eb0c2a7674 Post-fix redirect 2024-04-14 16:02:55 +02:00
slawkens
d225c2da26 Fix form id 2024-04-14 15:59:23 +02:00
slawkens
d95e280b9a Use tables headline for account.redirect.html.twig 2024-04-14 15:25:13 +02:00
slawkens
64387e085b Use tables headline for account.create.html.twig 2024-04-14 15:06:43 +02:00
slawkens
e1f507cf2d Extend timeout to fix broken workflow-runs 2024-04-12 15:15:23 +02:00
slawkens
c92a410209 Don't allow redirect to external website 2024-04-08 19:08:21 +02:00
slawkens
1186f94e21 Add Twig TypeCastingExtension 2024-04-08 10:08:48 +02:00
slawkens
f837b3133d deny vendor, composer.json, changelog.md etc. in nginx config sample 2024-04-06 19:51:34 +02:00
slawkens
9106f1e4ce Update CHANGELOG.md 2024-04-06 19:16:22 +02:00
slawkens
a62cfc5272 Update CHANGELOG.md 2024-04-06 15:08:39 +02:00
slawkens
6229736d07 getPlayerLink -> colored 2024-04-01 23:40:53 +02:00
slawkens
6807339056 Colored (online/offline) player links 2024-04-01 23:33:00 +02:00
slawkens
ffaa0729ac Add player->getOutfit function 2024-04-01 23:19:12 +02:00
slawkens
03cc09b8c7 Adjust submit button 2024-04-01 23:10:00 +02:00
slawkens
6d4724f4f4 Squashed commit of the following:
commit da18629d16
Author: slawkens <slawkens@gmail.com>
Date:   Mon Apr 1 21:53:53 2024 +0200

    Fixes to tables headline

commit 41c3d9ad21
Author: slawkens <slawkens@gmail.com>
Date:   Sun Mar 31 13:59:25 2024 +0200

    [WIP] Tables headline
2024-04-01 21:54:53 +02:00
slawkens
2afe0c1185 Fill up the equipment variable no matter of config 2024-03-28 21:25:43 +01:00
slawkens
6334f3f4fa Fix admin-lte scripts includes 2024-02-23 17:01:49 +01:00
Slawomir Boczek
fe7ad61abe phpstan support (#250)
* phpstan v1 + workflow

* Fix intend

* More fixes

* Update phpstan.neon

* phpstan level 2

* Move errors ignoring into phpstan.neon

* phpstan level 3

* Don't ignore templates folder

* Something from level 4

* Update phpstan.neon
2024-02-18 14:59:25 +01:00
slawkens
e23a749e4c Ignore cypress screenshots folder 2024-02-17 16:48:15 +01:00
slawkens
ab5e4eff76 Fix if hide already exists 2024-02-17 16:43:33 +01:00
slawkens
fdd3bfd105 Fix config_lua reloading, cache clear problem 2024-02-17 16:43:21 +01:00
slawkens
93ad347571 Restore cypress:open npm command 2024-02-17 16:41:40 +01:00
slawkens
7d4aafda4f Update workflow name
[skip ci]
2024-02-17 15:51:19 +01:00
slawkens
87e8c9eb4d Use NPM for packages: bootstrap, jquery, tinymce 2024-02-17 15:42:09 +01:00
slawkens
d61197b6a1 Delete tinymce, will be included by npm 2024-02-17 10:30:50 +01:00
slawkens
dfba8bc60b Update README.md
[skip ci]
2024-02-17 09:05:36 +01:00
slawkens
d2d497d82c Upgrading to gha-find-replace@v3, fixes some warnings about set-output 2024-02-17 08:51:05 +01:00
slawkens
4204e0a419 Nope, it doesn't work 2024-02-17 08:35:16 +01:00
slawkens
e8e093cc1f Try to do it in one step with regex 2024-02-17 08:30:49 +01:00
slawkens
2b39a1e406 Fix canary build 2024-02-17 08:24:59 +01:00
slawkens
cac592e63a Update workflow name [skip ci] 2024-02-17 08:04:05 +01:00
slawkens
0255d0bef2 Fix upload artifacts error + adjust workflow name 2024-02-17 08:00:12 +01:00
slawkens
a59f0e9244 Cypress test on canary + tfs-master 2024-02-17 07:55:51 +01:00
slawkens
9f3231fff6 Fix delete character exception 2024-02-16 20:27:48 +01:00
slawkens
647eae08b4 Display error message if config.local.php is not writable 2024-02-04 10:10:04 +01:00
slawkens
e2487f97e3 settings:set + settings:reset commands 2024-02-04 09:01:00 +01:00
slawkens
235e69b8da Settings::clearCache function 2024-02-04 08:35:33 +01:00
slawkens
649e37ab0f "php aac migrate:run {ids}" command 2024-02-04 08:16:22 +01:00
slawkens
dff4a98ef5 Fix reload server data 2024-02-04 08:13:57 +01:00
slawkens
b754374585 Update CHANGELOG.md 2024-02-04 07:41:25 +01:00
slawkens
ad789c50ff Create creatures.php 2024-02-03 20:54:50 +01:00
slawkens
ccfd2b4f55 Rename creatures to monsters 2024-02-03 20:54:09 +01:00
slawkens
3f5744964a Get rid of ?subtopic=x links 2024-02-03 20:34:42 +01:00
slawkens
b22dc0014a Change spaces to tabs 2024-02-03 20:30:21 +01:00
slawkens
00cbce20b0 Various fixes in forum
Add new access type: guest - all visitors, player will be now for logged players only
Fixed default forum board access for guests
2024-02-03 20:01:38 +01:00
slawkens
bbe922a65d New migration: update menu links 2024-02-03 18:58:20 +01:00
slawkens
8f23c62708 Update list of contributors 2024-02-03 18:42:35 +01:00
slawkens
58bb6093b0 Update release.sh 2024-02-02 20:29:28 +01:00
slawkens
2faaa037ab Update CHANGELOG.md 2024-02-02 20:17:18 +01:00
slawkens
cc9057324a Fix maxlength for email input 2024-02-02 18:52:21 +01:00
slawkens
f7971a21d8 An attempt to bypass the error 2024-02-01 20:43:46 +01:00
slawkens
08e7cf05b5 Remove link, looks bad on Whoops 2024-02-01 19:00:44 +01:00
slawkens
2e482fdc2a Relocation of myaac tables check
Makes more sense, between $db connection and migrate.php
2024-02-01 18:36:23 +01:00
slawkens
a2c8e2b2ae phpstan: level 1 passed 2024-01-31 00:36:15 +01:00
slawkens
cc3e66cacb according to phpstan: isset is not required here 2024-01-30 23:58:33 +01:00
slawkens
bd86454fea Import missing class 2024-01-30 23:16:33 +01:00
slawkens
1bb6e61583 eAccelerator is dead 2024-01-30 23:13:57 +01:00
slawkens
13a2570ad0 Remove old approach of showing errors to users in database pages
Currently handled by config.env
2024-01-30 23:04:53 +01:00
slawkens
e961f2efcf fix: missing semicolon 2024-01-30 23:02:26 +01:00
slawkens
54609bf90e phpstan adjustments 2024-01-30 23:01:18 +01:00
slawkens
6494bd2c0c Add optional $return = false parameter to the csrf function 2024-01-30 22:40:40 +01:00
slawkens
670812772d Seems that this is better solution to the #245 (output buffering)
This works for both, when output_buffering is enabled, and disabled
2024-01-30 19:20:23 +01:00
slawkens
ae8a9fc44c This is more error resistant 2024-01-30 18:30:42 +01:00
slawkens
f80c5fd8ed Update init.php 2024-01-30 18:16:05 +01:00
slawkens
6bac02bd35 Fix links to some pages that has been renamed 2024-01-30 18:09:57 +01:00
slawkens
ac67555f28 Fix exception when settingsDb are empty 2024-01-30 18:09:57 +01:00
slawkens
6c4fd4ed27 add new constant for cli: SELF_NAME 2024-01-30 18:09:56 +01:00
slawkens
a8a896e0f5 Our command line tool will be named: aac 2024-01-30 17:47:31 +01:00
slawkens
b517a12f8a Avoid duplicate loading of hooks 2024-01-28 23:08:37 +01:00
slawkens
5d741944f7 Fix: cronjob command 2024-01-28 23:07:40 +01:00
slawkens
a3056f5f48 Preparing to release 1.0-beta - update changelog 2024-01-28 23:07:22 +01:00
slawkens
8518f21987 Fix the migration, thanks @gpedro 2024-01-28 18:42:10 +01:00
slawkens
a3a2f05783 Forgot to quote 2024-01-28 18:26:03 +01:00
slawkens
9f3c980ed2 Update commands & downloads pages 2024-01-27 23:58:08 +01:00
slawkens
31f8c99745 $menu['target_blank'] 2024-01-27 23:25:03 +01:00
slawkens
25c0bac7a3 Cache clear hook 2024-01-27 20:30:15 +01:00
slawkens
9a749afc46 1 second should be enough, is ages in IT 2024-01-27 20:19:25 +01:00
slawkens
87df817eae Another way to clear database cache 2024-01-27 19:27:25 +01:00
slawkens
3a58c8a6f9 Revert "Revert "Another try..""
This reverts commit 2ba03e0c99.
2024-01-27 19:23:02 +01:00
slawkens
2ba03e0c99 Revert "Another try.."
This reverts commit ccc91a473c.
2024-01-27 18:58:41 +01:00
slawkens
f7f46bae00 OK so that was that 2024-01-27 18:58:19 +01:00
slawkens
ccc91a473c Another try.. 2024-01-27 18:12:38 +01:00
slawkens
7e347e950f Revert "try mysql 5.7"
This reverts commit 535ae2047d.
2024-01-27 18:12:01 +01:00
slawkens
535ae2047d try mysql 5.7 2024-01-27 17:58:00 +01:00
slawkens
12bc6a0333 Revert "Revert "Revert "just testing"""
This reverts commit 3a86738983.
2024-01-27 17:57:43 +01:00
slawkens
3a86738983 Revert "Revert "just testing""
This reverts commit 76256a7ee6.
2024-01-27 17:49:24 +01:00
slawkens
3b3e9b0e70 Update 1-install.cy.js 2024-01-27 17:33:53 +01:00
slawkens
54b9cc5402 This exception makes no sense, as it redirects to install 2024-01-27 17:33:47 +01:00
slawkens
6d23b285c1 Fixes for PHP 8.3 2024-01-27 17:27:05 +01:00
slawkens
76256a7ee6 Revert "just testing"
This reverts commit 07dafc5118.
2024-01-27 17:23:40 +01:00
slawkens
07dafc5118 just testing 2024-01-27 17:13:32 +01:00
slawkens
b5c1b431d5 Upload php log 2024-01-27 17:06:55 +01:00
slawkens
3a3e434d4e Update cypress.yml 2024-01-27 17:04:20 +01:00
slawkens
d71bab648d Change hidden to hide (Eloquent blocked keyword) 2024-01-27 16:54:48 +01:00
slawkens
3554b41172 Preparing to release v1.0-beta 2024-01-27 15:36:34 +01:00
slawkens
41022727bd Fixes to csrf protection 2024-01-27 15:35:24 +01:00
slawkens
9b781d09a9 Use php 7 str_contains 2024-01-27 14:15:56 +01:00
slawkens
c8d4e7d186 Auto clear old menu entries on install 2024-01-27 14:15:42 +01:00
slawkens
6cd8b7697d Fix plugin menus hook 2024-01-27 14:14:40 +01:00
slawkens
19c4cb810b Update 3-check-public-pages.cy.js 2024-01-27 10:00:23 +01:00
slawkens
ba6119e6d0 Rename pages 2024-01-27 09:58:11 +01:00
slawkens
1ce816040a Remove duplicated placeholder 2024-01-27 09:34:35 +01:00
slawkens
aa8e26f6a3 check if menu table exists 2024-01-27 09:34:23 +01:00
slawkens
f0eb113bc2 Refactor clearCache function 2024-01-27 09:02:38 +01:00
slawkens
6ed8f18115 Move consts to global.php 2024-01-27 08:44:51 +01:00
slawkens
2262c4e882 Clear additional keys on cache clear 2024-01-27 08:18:50 +01:00
slawkens
69b02fa977 Update to actions/upload-artifact@v4 2024-01-27 01:37:25 +01:00
slawkens
6baf49bba8 Default town = 1 2024-01-27 01:35:51 +01:00
slawkens
bb02328b5a Update github actions versions 2024-01-27 01:35:42 +01:00
slawkens
5a4854c205 Disable account_login_by_email by default 2024-01-27 01:26:44 +01:00
slawkens
c661ae36ef #vars_mail_admin has been deleted in 1.0+ 2024-01-27 01:21:09 +01:00
slawkens
df8fb68d5e Fix imports 2024-01-27 01:15:11 +01:00
slawkens
fb0afdcea1 We require PHP 8.1, cause of illuminate/database 2024-01-27 01:05:03 +01:00
slawkens
e3775fed86 Update bans.php 2024-01-27 01:01:59 +01:00
slawkens
93b0d3829d update github actions: branch = develop 2024-01-27 01:01:56 +01:00
slawkens
b6f98ffdee test github actions 2024-01-27 01:00:25 +01:00
slawkens
511e10e78b Same for themes + commands 2024-01-27 00:56:45 +01:00
slawkens
cfdbc2a8b2 Fixed: disabled plugins should not enable pages 2024-01-27 00:46:34 +01:00
slawkens
1a6fb8bee2 Refactoring classes into src/ folder, so they will be auto-loaded by composer 2024-01-27 00:36:49 +01:00
slawkens
410d75c882 Revised Commands -> use symfony/console -> php ma (MyAAC)
Usage:
php ma list
php ma cache:clear
php ma plugin:install guild-wars.zip

More sophisticated:
echo "Hello, this is hello world message" | php ma mail:send test@test.com --subject "This is subject"

Also: custom commands can be added via Plugins: just need to return new class instance that extends \MyAAC\Commands\Command in plugins/*/commands folder
2024-01-26 23:19:39 +01:00
slawkens
c59bacea93 Fix page title if the index.php is present 2024-01-25 23:11:13 +01:00
slawkens
f719c02050 Feature: auto-load themes (previously templates) from plugins/*/themes/* 2024-01-25 23:06:10 +01:00
slawkens
0698e7b5f5 Typo 2024-01-25 22:29:28 +01:00
slawkens
c594dfd14b Feature: auto-load pages in plugins/*/pages/*.php 2024-01-25 22:29:19 +01:00
slawkens
514c4a037a admin.links style 2024-01-25 22:02:08 +01:00
slawkens
b894f75e74 Put admin.links in <table> to fix position + remove bootstrap classes (didnt worked anyway) 2024-01-25 22:01:35 +01:00
slawkens
d2a3a9a8da System-solution for styled tables, that works with every template 2024-01-25 21:57:20 +01:00
slawkens
3f4c02a327 bugtracker has been removed 2024-01-13 10:18:24 +01:00
slawkens
199672e0c8 Fix donate_column 2024-01-13 10:12:08 +01:00
Danilo Pucci
02adb87fac - adding check before flush buffer (#245) 2024-01-01 23:32:26 +01:00
slawkens
b4448f7279 Silently ignore if the hook does not exist 2023-12-28 19:13:14 +01:00
slawkens
687c9a6690 feature: color-styled tables in tinymce editor 2023-12-12 17:58:17 +01:00
slawkens
2b86ba94fe Cleanup tabs 2023-12-12 14:37:12 +01:00
slawkens
a9fb5dffa3 Fix account manage redirect 2023-12-09 09:26:33 +01:00
slawkens
da77ec20ef Delete bugtracker, it will be included as plugin 2023-12-08 23:56:29 +01:00
slawkens
6fd141eca6 composer --prefer-dist --optimize-autoloader 2023-11-29 22:34:26 +01:00
slawkens
e17dde0dca Fix session fixation 2023-11-27 23:52:36 +01:00
slawkens
d1046ba21d Fix forum XSS 2023-11-27 22:56:38 +01:00
slawkens
98332f1483 Fix XSS in bugtracker.php 2023-11-27 22:29:24 +01:00
slawkens
1423046039 Sort changelogs by date + make sortable in admin panel 2023-11-25 20:09:42 +01:00
slawkens
9c60beeed0 I like this color better - teams page adjustment 2023-11-25 16:56:45 +01:00
slawkens
336b6ac530 Fix mango signature warnings 2023-11-25 16:33:48 +01:00
slawkens
c71722fc52 Fix warning 2023-11-25 16:24:18 +01:00
slawkens
4d8d574089 Fix missing query_string in nginx sample config
Causes missing parameters in $_GET query
2023-11-25 16:24:08 +01:00
slawkens
e74fbe5bfd Update account.lost.form.html.twig 2023-11-25 15:47:53 +01:00
slawkens
48e9a1ed51 Fix account lost interface links 2023-11-25 15:44:34 +01:00
slawkens
56631bdf27 New hook: HOOK_ACCOUNT_CREATE_CHARACTER_AFTER
Possibility to change character after create
2023-11-25 13:53:50 +01:00
slawkens
b1224d9d1a clearRouteCache on database pages change 2023-11-25 13:37:24 +01:00
slawkens
e18ada3d9d Fix default access for database pages 2023-11-25 13:30:48 +01:00
slawkens
c8218f69a5 Fix undefined variable 2023-11-25 13:08:56 +01:00
slawkens
f991a8c817 clearCache after install plugin 2023-11-25 11:09:45 +01:00
slawkens
36ec2e1e56 Add option to execute "install" part of the plugin 2023-11-25 10:10:15 +01:00
slawkens
19c06df300 Insert new setting if it doesn't exist yet 2023-11-24 21:03:31 +01:00
slawkens
b2d5d6f115 Fix backward support, needs to be before router.php 2023-11-23 20:03:15 +01:00
slawkens
5769ac8bb4 Fix onlineTable relation, fixed online status in highscores 2023-11-23 20:02:18 +01:00
slawkens
41c9f54e4b Fix the fix 2023-11-11 21:32:00 +01:00
slawkens
8ef238c96c Fix default option for options 2023-11-11 21:30:10 +01:00
slawkens
9ffb7f5fa9 Move monsters page settings to other tab + some small adjustments 2023-11-11 21:18:00 +01:00
slawkens
8b5464f8f8 Update init.php 2023-11-11 21:16:45 +01:00
slawkens
f008591580 Make links in settings desc clickable 2023-11-11 21:16:34 +01:00
slawkens
1d5b751fe1 Fix Settings:save for other plugins 2023-11-11 18:44:48 +01:00
slawkens
37bde7df22 Use str_contains + str_starts_with 2023-11-11 16:09:44 +01:00
slawkens
89deca1adb Fix empty PAGE 2023-11-11 16:09:31 +01:00
slawkens
c996f25d8d Fix guild leave 2023-11-11 15:28:41 +01:00
slawkens
d291f694d2 Update .gitignore 2023-11-11 15:24:49 +01:00
slawkens
cee1e67d3d Fix highscores_ids_hidden 2023-11-11 15:02:38 +01:00
418 changed files with 11782 additions and 10268 deletions

View File

@@ -1,9 +1,9 @@
name: Cypress
on:
pull_request:
branches: [develop]
branches: [master]
push:
branches: [develop]
branches: [master]
jobs:
cypress:
@@ -22,8 +22,9 @@ jobs:
strategy:
fail-fast: false
matrix:
php-versions: [ '7.4', '8.0', '8.1' ]
name: MyAAC on PHP ${{ matrix.php-versions }}
php-versions: [ '8.1', '8.2', '8.3' ]
ots: ['tfs-1.4', 'canary-3.1.2'] # TODO: add 'tfs-master' (actually doesn't work cause AAC doesn't support reading .env configuration)
name: Cypress (PHP ${{ matrix.php-versions }}, ${{ matrix.ots }})
steps:
- name: 📌 MySQL Start & init & show db
run: |
@@ -32,47 +33,81 @@ jobs:
mysql -e "SHOW DATABASES" -uroot -proot
- name: Checkout MyAAC
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
ref: 0.9
ref: master
- uses: actions/setup-node@v4
with:
node-version: 18
- run: npm ci
- name: Checkout TFS
uses: actions/checkout@v3
uses: actions/checkout@v4
if: matrix.ots == 'tfs-1.4'
with:
repository: otland/forgottenserver
ref: 1.4
path: tfs
path: ots
- name: Import TFS Schema
- name: Checkout TFS
uses: actions/checkout@v4
if: matrix.ots == 'tfs-master'
with:
repository: otland/forgottenserver
ref: master
path: ots
- name: Checkout Canary
uses: actions/checkout@v4
if: matrix.ots == 'canary-3.1.2'
with:
repository: opentibiabr/canary
ref: v3.1.2
path: ots
- name: Import OTS Schema
run: |
mysql -uroot -proot myaac < tfs/schema.sql
mysql -uroot -proot myaac < ots/schema.sql
- name: Rename config.lua
run: mv tfs/config.lua.dist tfs/config.lua
run: mv ots/config.lua.dist ots/config.lua
- name: Replace mysqlUser
uses: jacobtomlinson/gha-find-replace@v2
- name: Replace mysqlUser (TFS 1.4)
uses: jacobtomlinson/gha-find-replace@v3
if: matrix.ots == 'tfs-1.4'
with:
find: 'mysqlUser = "forgottenserver"'
replace: 'mysqlUser = "root"'
regex: false
include: 'tfs/config.lua'
include: 'ots/config.lua'
- name: Replace mysqlPass
uses: jacobtomlinson/gha-find-replace@v2
- name: Replace mysqlPass (TFS 1.4)
uses: jacobtomlinson/gha-find-replace@v3
if: matrix.ots == 'tfs-1.4'
with:
find: 'mysqlPass = ""'
replace: 'mysqlPass = "root"'
regex: false
include: 'tfs/config.lua'
include: 'ots/config.lua'
- name: Replace mysqlDatabase
uses: jacobtomlinson/gha-find-replace@v2
- name: Replace mysqlDatabase (TFS 1.4)
uses: jacobtomlinson/gha-find-replace@v3
if: matrix.ots == 'tfs-1.4'
with:
find: 'mysqlDatabase = "forgottenserver"'
replace: 'mysqlDatabase = "myaac"'
regex: false
include: 'tfs/config.lua'
include: 'ots/config.lua'
- name: Replace mysqlDatabase (Canary)
uses: jacobtomlinson/gha-find-replace@v3
if: matrix.ots == 'canary-3.1.2'
with:
find: 'mysqlDatabase = "otservbr-global"'
replace: 'mysqlDatabase = "myaac"'
regex: false
include: 'ots/config.lua'
- name: Setup PHP
uses: shivammathur/setup-php@v2
@@ -85,13 +120,13 @@ jobs:
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache composer dependencies
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
# Use composer.json for key, if composer.lock is not committed.
# key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
#key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
- name: Install Composer dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
@@ -100,21 +135,28 @@ jobs:
run: nohup php -S localhost:8080 > php.log 2>&1 &
- name: Cypress Run
uses: cypress-io/github-action@v5
uses: cypress-io/github-action@v6
env:
CYPRESS_URL: http://localhost:8080
CYPRESS_SERVER_PATH: /home/runner/work/myaac/myaac/tfs
CYPRESS_SERVER_PATH: /home/runner/work/myaac/myaac/ots
- name: Save screenshots
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: always()
with:
name: cypress-screenshots
name: cypress-screenshots-${{ matrix.php-versions }}-${{ matrix.ots }}
path: cypress/screenshots
- name: Upload Cypress Videos
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: always()
with:
name: cypress-videos
name: cypress-videos-${{ matrix.php-versions }}-${{ matrix.ots }}
path: cypress/videos
- name: Upload PHP Logs
uses: actions/upload-artifact@v4
if: always()
with:
name: php-log-${{ matrix.php-versions }}-${{ matrix.ots }}
path: php.log

View File

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

46
.github/workflows/phpstan.yml vendored Normal file
View File

@@ -0,0 +1,46 @@
name: "PHPStan"
on:
pull_request:
branches: [master]
push:
branches: [master]
jobs:
tests:
name: PhpStan on PHP ${{ matrix.php-versions }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php-versions: [ '8.1', '8.2', '8.3' ]
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
with:
coverage: "none"
extensions: "intl, zip"
ini-values: "memory_limit=-1"
php-version: "${{ matrix.php-version }}"
- name: Get composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache composer dependencies
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
# Use composer.json for key, if composer.lock is not committed.
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
- name: "Install composer dependencies"
run: "composer install"
- name: "Run PHPStan"
run: "/usr/bin/php vendor/bin/phpstan analyse"

4
.gitignore vendored
View File

@@ -6,15 +6,17 @@ Thumbs.db
/.htaccess
# composer
composer.lock
composer.phar
vendor
# npm
node_modules
tools/ext
# cypress
cypress.env.json
cypress/e2e/2-advanced-examples
cypress/screenshots
# created by release.sh
releases

View File

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

View File

@@ -8,7 +8,11 @@ Fernando Matos <fernando@pixele.com.br>
Lee <42119604+Leesneaks@users.noreply.github.com>
caio <caio.zucoli@gmail.com>
slawkens <slawkens@gmail.com>
tobi132 <52947952+tobi132@users.noreply.github.com>
tobi132 <tobi132@gmx.net>
vankk <nwtr.otland@hotmail.com>
whiteblXK <krzys16001@gmail.com>
xitobuh <jonas.hockert92@gmail.com>
Danilo Pucci <dnlps@hotmail.com>
gpedro <gpedro831@gmail.com>
Matheus Collier <matheuscollier@gmail.com>
SRNT-GG <95472530+SRNT-GG@users.noreply.github.com>

View File

@@ -10,21 +10,20 @@ Official website: https://my-aac.org
[![OpenTibia Discord](https://img.shields.io/discord/288399552581468162)](https://discord.gg/2J39Wus)
[![Closed Issues](https://img.shields.io/github/issues-closed-raw/slawkens/myaac)](https://github.com/slawkens/myaac/issues?q=is%3Aissue+is%3Aclosed)
| Version | Status | Branch | Requirements |
|:-----------|:------------------------------------------|:--------|:---------------|
| **0.10.x** | **Active development** | develop | **PHP >= 8.0** |
| 0.9.x | Active support | 0.9 | PHP >= 7.2.5 |
| 0.8.x | Active support | master | PHP >= 7.2.5 |
| 0.7.x | End Of Life | 0.7 | PHP >= 5.3.3 |
| Version | Status | Branch | Requirements |
|:--------|:-----------------------|:--------|:---------------|
| **1.x** | **Active development** | develop | **PHP >= 8.1** |
| 0.9.x | Not developed anymore | 0.9 | PHP >= 7.2.5 |
| 0.8.x | Active support | master | PHP >= 7.2.5 |
| 0.7.x | End Of Life | 0.7 | PHP >= 5.3.3 |
### Requirements
- PHP 8.0 or later
- MySQL database
- PDO PHP Extension
- XML PHP Extension
- (optional) ZIP PHP Extension
- (optional) mod_rewrite to use friendly_urls
- PHP Extensions: pdo, xml, json
- (optional) apache2 mod_rewrite (to use friendly_urls)
- (optional) zip PHP Extension (to install plugins)
- (optional) gd PHP Extension (for generating signature images)
### Installation
@@ -48,7 +47,8 @@ Official website: https://my-aac.org
### Configuration
Check *config.php* to get more informations.
Check *config.php* to get more informations. (Notice: MyAAC 1.0+ doesn't use config.php anymore, it has been moved to Admin Panel - Settings page).
Use *config.local.php* for your local configuration changes.
### Branches

36
aac Normal file
View File

@@ -0,0 +1,36 @@
#!/usr/bin/env php
<?php
require_once __DIR__ . '/common.php';
if(!IS_CLI) {
echo 'This script can be run only in command line mode.';
exit(1);
}
require_once SYSTEM . 'functions.php';
define('SELF_NAME', basename(__FILE__));
use MyAAC\Plugins;
use Symfony\Component\Console\Application;
$application = new Application('MyAAC', MYAAC_VERSION);
$commandsGlob = glob(SYSTEM . 'src/Commands/*.php');
foreach ($commandsGlob as $item) {
$name = pathinfo($item, PATHINFO_FILENAME);
if ($name == 'Command') { // ignore base Command class
continue;
}
$commandPre = '\\MyAAC\Commands\\';
$application->add(new ($commandPre . $name));
}
$pluginCommands = Plugins::getCommands();
foreach ($pluginCommands as $item) {
$application->add(require $item);
}
$application->run();

View File

@@ -1,5 +1,7 @@
<?php
use MyAAC\Plugins;
$order = 10;
$settingsMenu = [];

View File

@@ -25,11 +25,6 @@ define('PAGE', $page);
require SYSTEM . 'functions.php';
require SYSTEM . 'init.php';
// verify myaac tables exists in database
if(!$db->hasTable('myaac_account_actions')) {
throw new RuntimeException('Seems that the table <strong>myaac_account_actions</strong> of MyAAC doesn\'t exist in the database. This is a fatal error. You can try to reinstall MyAAC by visiting <a href="' . BASE_URL . 'install">this</a> url.');
}
require __DIR__ . '/includes/debugbar.php';
require SYSTEM . 'status.php';
require SYSTEM . 'login.php';
@@ -50,7 +45,7 @@ if(!$logged || !admin()) {
// include our page
$file = __DIR__ . '/pages/' . $page . '.php';
if(!@file_exists($file)) {
if (strpos($page, 'plugins/') !== false) {
if (str_contains($page, 'plugins/')) {
$file = BASE . $page;
}
else {

View File

@@ -8,6 +8,7 @@
* @link https://my-aac.org
*/
use MyAAC\Models\Account as AccountModel;
use MyAAC\Models\Player;
defined('MYAAC') or die('Direct access not allowed!');
@@ -22,10 +23,7 @@ $use_datatable = true;
if (setting('core.account_country'))
require SYSTEM . 'countries.conf.php';
$nameOrNumberColumn = 'name';
if (USE_ACCOUNT_NUMBER) {
$nameOrNumberColumn = 'number';
}
$nameOrNumberColumn = getAccountIdentityColumn();
$hasSecretColumn = $db->hasColumn('accounts', 'secret');
$hasCoinsColumn = $db->hasColumn('accounts', 'coins');
@@ -51,36 +49,51 @@ $acc_type = setting('core.account_types');
<?php
$id = 0;
$search_account = '';
$search_account = $search_account_email = '';
if (isset($_REQUEST['id']))
$id = (int)$_REQUEST['id'];
else if (isset($_REQUEST['search_email'])) {
$search_account_email = $_REQUEST['search_email'];
$accountModel = AccountModel::where('email', $search_account_email)->limit(11)->get(['email', 'id']);
if (count($accountModel) == 0) {
echo_error('No entries found.');
} else if (count($accountModel) == 1) {
$id = $accountModel->first()->getKey();
} else if (count($accountModel) > 10) {
echo_error('Specified e-mail resulted with too many accounts.');
}
}
else if (isset($_REQUEST['search'])) {
$search_account = $_REQUEST['search'];
if (strlen($search_account) < 3 && !Validator::number($search_account)) {
echo_error('Player name is too short.');
$min_size = 3;
if (in_array($nameOrNumberColumn, ['id', 'number'])) {
$min_size = 1;
}
if (strlen($search_account) < $min_size && !Validator::number($search_account)) {
echo_error('Account ' . $nameOrNumberColumn . ' is too short.');
} else {
$query = $db->query('SELECT `id` FROM `accounts` WHERE `' . $nameOrNumberColumn . '` = ' . $db->quote($search_account));
if ($query->rowCount() == 1) {
$query = $query->fetch();
$id = (int)$query['id'];
$query = AccountModel::where($nameOrNumberColumn, '=', $search_account)->limit(11)->get(['id', $nameOrNumberColumn]);
if (count($query) == 0) {
echo_error('No entries found.');
} else if (count($query) == 1) {
$id = $query->first()->getKey();
} else if (count($query) > 10) {
echo_error('Specified name resulted with too many accounts.');
} else {
$query = $db->query('SELECT `id`, `' . $nameOrNumberColumn . '` FROM `accounts` WHERE `' . $nameOrNumberColumn . '` LIKE ' . $db->quote('%' . $search_account . '%'));
if ($query->rowCount() > 0 && $query->rowCount() <= 10) {
$str_construct = 'Do you mean?<ul class="mb-0">';
foreach ($query as $row)
$str_construct .= '<li><a href="' . $admin_base . '&id=' . $row['id'] . '">' . $row[$nameOrNumberColumn] . '</a></li>';
$str_construct .= '</ul>';
echo_error($str_construct);
} else if ($query->rowCount() > 10)
echo_error('Specified name resulted with too many accounts.');
else
echo_error('No entries found.');
$str_construct = 'Do you mean?<ul class="mb-0">';
foreach ($query as $row) {
$str_construct .= '<li><a href="' . $admin_base . '&id=' . $row->getKey() . '">' . $row->attributes[$nameOrNumberColumn] . '</a></li>';
}
$str_construct .= '</ul>';
echo_error($str_construct);
}
}
}
?>
<div class="row">
<?php
$groups = new OTS_Groups_List();
if ($id > 0) {
$account = new OTS_Account();
$account->load($id);
@@ -143,7 +156,9 @@ else if (isset($_REQUEST['search'])) {
$rl_loca = $_POST['rl_loca'];
//country
$rl_country = $_POST['rl_country'];
if(setting('core.account_country')) {
$rl_country = $_POST['rl_country'];
}
$web_flags = $_POST['web_flags'];
verify_number($web_flags, 'Web Flags', 1);
@@ -190,7 +205,11 @@ else if (isset($_REQUEST['search'])) {
}
$account->setRLName($rl_name);
$account->setLocation($rl_loca);
$account->setCountry($rl_country);
if(setting('core.account_country')) {
$account->setCountry($rl_country);
}
$account->setCustomField('created', $created);
$account->setWebFlags($web_flags);
$account->setCustomField('web_lastlogin', $web_lastlogin);
@@ -214,7 +233,7 @@ else if (isset($_REQUEST['search'])) {
}
}
} else if ($id == 0) {
$accounts_db = $db->query('SELECT `id`, `' . $nameOrNumberColumn . '`' . ($hasTypeColumn ? ',type' : ($hasGroupColumn ? ',group_id' : '')) . ' FROM `accounts` ORDER BY `id` ASC');
$accounts_db = $db->query('SELECT `id`, `' . $nameOrNumberColumn . '`' . ($hasTypeColumn ? ',type' : ($hasGroupColumn ? ',group_id' : '')) . ', email FROM `accounts` ORDER BY `id` ASC');
?>
<div class="col-12 col-sm-12 col-lg-10">
<div class="card card-info card-outline">
@@ -226,8 +245,9 @@ else if (isset($_REQUEST['search'])) {
<thead>
<tr>
<th>ID</th>
<th><?= ($nameOrNumberColumn == 'number' ? 'Number' : 'Name'); ?></th>
<th><?= ($nameOrNumberColumn == 'name' ? 'Name' : 'Number'); ?></th>
<?php if($hasTypeColumn || $hasGroupColumn): ?>
<th>E-Mail</th>
<th>Position</th>
<?php endif; ?>
<th style="width: 40px">Edit</th>
@@ -238,6 +258,7 @@ else if (isset($_REQUEST['search'])) {
<tr>
<th><?php echo $account_lst['id']; ?></th>
<td><?php echo $account_lst[$nameOrNumberColumn]; ?></a></td>
<td><?php echo $account_lst['email']; ?></td>
<?php if($hasTypeColumn || $hasGroupColumn): ?>
<td>
<?php if ($hasTypeColumn) {
@@ -291,7 +312,7 @@ else if (isset($_REQUEST['search'])) {
<div class="card-body">
<div class="tab-content" id="accounts-tabContent">
<div class="tab-pane fade active show" id="accounts-acc">
<form action="<?php echo $admin_base . ((isset($id) && $id > 0) ? '&id=' . $id : ''); ?>" method="post">
<form action="<?php echo $admin_base . ($id > 0 ? '&id=' . $id : ''); ?>" method="post">
<?php csrf(); ?>
<div class="form-group row">
<?php if (USE_ACCOUNT_NAME): ?>
@@ -404,6 +425,7 @@ else if (isset($_REQUEST['search'])) {
autocomplete="off" maxlength="20"
value="<?php echo $account->getLocation(); ?>"/>
</div>
<?php if(setting('core.account_country')): ?>
<div class="col-12 col-sm-12 col-lg-4">
<label for="rl_country">Country:</label>
<select name="rl_country" id="rl_country" class="form-control">
@@ -412,6 +434,7 @@ else if (isset($_REQUEST['search'])) {
<?php endforeach; ?>
</select>
</div>
<?php endif; ?>
</div>
<div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6">
@@ -583,6 +606,16 @@ else if (isset($_REQUEST['search'])) {
</div>
<div class="card-body">
<div class="row">
<div class="col-6 col-lg-12">
<form action="<?php echo $admin_base; ?>" method="post">
<?php csrf(); ?>
<label for="search">Account E-Mail:</label>
<div class="input-group input-group-sm">
<input type="email" class="form-control" id="search_email" name="search_email" value="<?= escapeHtml($search_account_email); ?>" maxlength="255" size="255">
<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span>
</div>
</form>
</div>
<div class="col-6 col-lg-12">
<form action="<?php echo $admin_base; ?>" method="post">
<?php csrf(); ?>

View File

@@ -9,6 +9,7 @@
* @link https://my-aac.org
*/
use MyAAC\Changelog;
use MyAAC\Models\Changelog as ModelsChangelog;
defined('MYAAC') or die('Direct access not allowed!');
@@ -26,9 +27,8 @@ $use_datatable = true;
const CL_LIMIT = 600; // maximum changelog body length
$id = $_GET['id'] ?? 0;
require_once LIBS . 'changelog.php';
if(!empty($action))
if(!empty($action) && isRequestMethod('post'))
{
$id = $_POST['id'] ?? null;
$body = isset($_POST['body']) ? stripslashes($_POST['body']) : null;
@@ -73,7 +73,7 @@ if(!empty($action))
}
}
else if($action == 'hide') {
if (Changelog::toggleHidden($id, $errors, $status)) {
if (Changelog::toggleHide($id, $errors, $status)) {
success(($status == 1 ? 'Hide' : 'Show') . ' successful.');
}
}

View File

@@ -7,6 +7,9 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Account;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Mailer';
@@ -61,15 +64,15 @@ if (!empty($mail_content) && !empty($mail_subject) && empty($mail_to)) {
$add = ' AND `email_verified` = 1';
}
$query = $db->query('SELECT `email` FROM `accounts` WHERE `email` != ""' . $add);
$query = Account::where('email', '!=', '')->get(['email']);
foreach ($query as $email) {
if (_mail($email['email'], $mail_subject, $mail_content)) {
if (_mail($email->email, $mail_subject, $mail_content)) {
$success++;
}
else {
$failed++;
echo '<br />';
error('An error occorred while sending email to <b>' . $email['email'] . '</b>. For Admin: More info can be found in system/logs/mailer-error.log');
error('An error occorred while sending email to <b>' . $email->email . '</b>. For Admin: More info can be found in system/logs/mailer-error.log');
}
}

View File

@@ -24,20 +24,13 @@ $freePremium = $config['lua']['freePremium'];
function admin_give_points($points)
{
global $db, $hasPointsColumn;
global $hasPointsColumn;
if (!$hasPointsColumn) {
displayMessage('Points not supported.');
return;
}
$statement = $db->prepare('UPDATE `accounts` SET `premium_points` = `premium_points` + :points');
if (!$statement) {
displayMessage('Failed to prepare query statement.');
return;
}
if (!Account::query()->increment('premium_points', $points)) {
displayMessage('Failed to add points.');
return;
@@ -47,7 +40,7 @@ function admin_give_points($points)
function admin_give_coins($coins)
{
global $db, $hasCoinsColumn;
global $hasCoinsColumn;
if (!$hasCoinsColumn) {
displayMessage('Coins not supported.');
@@ -62,24 +55,6 @@ function admin_give_coins($coins)
displayMessage($coins . ' coins added to all accounts.', true);
}
function query_add_premium($column, $value_query, $condition_query = '1=1', $params = [])
{
global $db;
$statement = $db->prepare("UPDATE `accounts` SET `{$column}` = $value_query WHERE $condition_query");
if (!$statement) {
displayMessage('Failed to prepare query statement.');
return false;
}
if (!$statement->execute($params)) {
displayMessage('Failed to add premium days.');
return false;
}
return true;
}
function admin_give_premdays($days)
{
global $db, $freePremium;
@@ -94,9 +69,9 @@ function admin_give_premdays($days)
// othire
if ($db->hasColumn('accounts', 'premend')) {
// append premend
if (query_add_premium('premend', '`premend` + :value', '`premend` > :now', ['value' => $value, 'now' => $now])) {
if (Account::where('premend', '>', $now)->increment('premend', $value)) {
// set premend
if (query_add_premium('premend', ':value', '`premend` <= :now', ['value' => $now + $value, 'now' => $now])) {
if (Account::where('premend', '<=', $now)->update(['premend' => $now + $value])) {
displayMessage($days . ' premium days added to all accounts.', true);
return;
} else {
@@ -114,11 +89,11 @@ function admin_give_premdays($days)
// tfs 0.x
if ($db->hasColumn('accounts', 'premdays')) {
// append premdays
if (query_add_premium('premdays', '`premdays` + :value', '1=1', ['value' => $days])) {
if (Account::query()->update(['premdays' => $days])) {
// append lastday
if (query_add_premium('lastday', '`lastday` + :value', '`lastday` > :now', ['value' => $value, 'now' => $now])) {
if (Account::where('lastday', '>', $now)->increment('lastday', $value)) {
// set lastday
if (query_add_premium('lastday', ':value', '`lastday` <= :now', ['value' => $now + $value, 'now' => $now])) {
if (Account::where('lastday', '<=', $now)->update(['lastday' => $now + $value])) {
displayMessage($days . ' premium days added to all accounts.', true);
return;
} else {
@@ -142,9 +117,9 @@ function admin_give_premdays($days)
// tfs 1.x
if ($db->hasColumn('accounts', 'premium_ends_at')) {
// append premium_ends_at
if (query_add_premium('premium_ends_at', '`premium_ends_at` + :value', '`premium_ends_at` > :now', ['value' => $value, 'now' => $now])) {
if (Account::where('premium_ends_at', '>', $now)->increment('premium_ends_at', $value)) {
// set premium_ends_at
if (query_add_premium('premium_ends_at', ':value', '`premium_ends_at` <= :now', ['value' => $now + $value, 'now' => $now])) {
if (Account::where('premium_ends_at', '<=', $now)->update(['premium_ends_at' => $now + $value])) {
displayMessage($days . ' premium days added to all accounts.', true);
return;
} else {
@@ -162,9 +137,9 @@ function admin_give_premdays($days)
displayMessage('Premium Days not supported.');
}
if (isset($_POST['action']) && $_POST['action']) {
if (!empty(ACTION) && isRequestMethod('post')) {
$action = $_POST['action'];
$action = ACTION;
if (preg_match("/[^A-z0-9_\-]/", $action)) {
displayMessage('Invalid action.');

View File

@@ -40,9 +40,9 @@ function admin_teleport_town($town_id) {
displayMessage('Player\'s town updated.', true);
}
if (isset($_POST['action']) && $_POST['action']) {
if (!empty(ACTION) && isRequestMethod('post')) {
$action = $_POST['action'];
$action = ACTION;
if (preg_match("/[^A-z0-9_\-]/", $action)) {
displayMessage('Invalid action.');

View File

@@ -8,7 +8,9 @@
* @link https://my-aac.org
*/
use MyAAC\Cache\Cache;
use MyAAC\Models\Menu;
use MyAAC\Plugins;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Menus';
@@ -20,6 +22,8 @@ if (!hasFlag(FLAG_CONTENT_MENUS) && !superAdmin()) {
return;
}
$pluginThemes = Plugins::getThemes();
if (isset($_POST['template'])) {
$template = $_POST['template'];
@@ -63,9 +67,16 @@ if (isset($_POST['template'])) {
success('Saved at ' . date('H:i'));
}
$file = TEMPLATES . $template . '/config.php';
if (file_exists($file)) {
require_once $file;
$path = TEMPLATES . $template;
if (isset($pluginThemes[$template])) {
$path = BASE . $pluginThemes[$template];
}
$path .= '/config.php';
if (file_exists($path)) {
require_once $path;
} else {
echo 'Cannot find template config.php file.';
return;
@@ -168,8 +179,13 @@ if (isset($_POST['template'])) {
} else {
$templates = Menu::select('template')->distinct()->get()->toArray();
foreach ($templates as $key => $value) {
$file = TEMPLATES . $value['template'] . '/config.php';
if (!file_exists($file)) {
$path = TEMPLATES . $value['template'];
if (isset($pluginThemes[$value['template']])) {
$path = BASE . $pluginThemes[$value['template']];
}
if (!file_exists($path . '/config.php')) {
unset($templates[$key]);
}
}

View File

@@ -7,7 +7,7 @@ defined('MYAAC') or die('Direct access not allowed!');
$accounts = 0;
if ($db->hasColumn('accounts', 'created')) {
$accounts = Account::orderByDesc('created')->limit(10)->get(['created', (USE_ACCOUNT_NAME ? 'name' : 'id')])->toArray();
$accounts = Account::orderByDesc('created')->limit(10)->get(['id', 'created'])->toArray();
}
$twig->display('created.html.twig', array(

View File

@@ -19,7 +19,7 @@
{% set i = i + 1 %}
<tr>
<th>{{ i }}</th>
<td><a href="?p=accounts&search_name={{ result.name }}">{{ result.name }}</a></td>
<td><a href="?p=accounts&id={{ result.id }}">{{ result.id }}</a></td>
<td>{{ result.created|date("M d Y, H:i:s") }}</td>
</tr>
{% endfor %}

View File

@@ -7,6 +7,10 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Forum;
use MyAAC\News;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'News Panel';
@@ -15,9 +19,6 @@ csrfProtect();
$use_datatable = true;
require_once LIBS . 'forum.php';
require_once LIBS . 'news.php';
if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) {
echo 'Access denied.';
return;
@@ -25,7 +26,7 @@ if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) {
header('X-XSS-Protection:0');
// some constants, used mainly by database (cannot by modified without schema changes)
// some constants, used mainly by database (cannot be modified without schema changes)
const NEWS_TITLE_LIMIT = 100;
const NEWS_BODY_LIMIT = 65535; // maximum news body length
const ARTICLE_TEXT_LIMIT = 300;
@@ -46,53 +47,50 @@ if(!empty($action))
$forum_section = $_POST['forum_section'] ?? null;
$errors = [];
if($action == 'new') {
if(isset($forum_section) && $forum_section != '-1') {
$forum_add = Forum::add_thread($p_title, $body, $forum_section, $player_id, $account_logged->getId(), $errors);
}
if (isRequestMethod('post')) {
if ($action == 'new') {
if (isset($forum_section) && $forum_section != '-1') {
$forum_add = Forum::add_thread($p_title, $body, $forum_section, $player_id, $account_logged->getId(), $errors);
}
if(isset($p_title) && News::add($p_title, $body, $type, $category, $player_id, isset($forum_add) && $forum_add != 0 ? $forum_add : 0, $article_text, $article_image, $errors)) {
$p_title = $body = $comments = $article_text = $article_image = '';
$type = $category = $player_id = 0;
success('Added successful.');
}
}
else if($action == 'delete') {
if (News::delete($id, $errors)) {
success('Deleted successful.');
}
}
else if($action == 'edit')
{
if(isset($id) && !isset($p_title)) {
$news = News::get($id);
$p_title = $news['title'];
$body = $news['body'];
$comments = $news['comments'];
$type = $news['type'];
$category = $news['category'];
$player_id = $news['player_id'];
$article_text = $news['article_text'];
$article_image = $news['article_image'];
}
else {
if(News::update($id, $p_title, $body, $type, $category, $player_id, $forum_section, $article_text, $article_image, $errors)) {
// update forum thread if exists
if(isset($forum_section) && Validator::number($forum_section)) {
$db->query("UPDATE `" . TABLE_PREFIX . "forum` SET `author_guid` = ".(int) $player_id.", `post_text` = ".$db->quote($body).", `post_topic` = ".$db->quote($p_title).", `edit_date` = " . time() . " WHERE `id` = " . $db->quote($forum_section));
}
$action = $p_title = $body = $comments = $article_text = $article_image = '';
if (isset($p_title) && News::add($p_title, $body, $type, $category, $player_id, isset($forum_add) && $forum_add != 0 ? $forum_add : 0, $article_text, $article_image, $errors)) {
$p_title = $body = $comments = $article_text = $article_image = '';
$type = $category = $player_id = 0;
success('Updated successful.');
success('Added successful.');
}
} else if ($action == 'delete') {
if (News::delete($id, $errors)) {
success('Deleted successful.');
}
} else if ($action == 'edit') {
if (isset($id) && !isset($p_title)) {
$news = News::get($id);
$p_title = $news['title'];
$body = $news['body'];
$comments = $news['comments'];
$type = $news['type'];
$category = $news['category'];
$player_id = $news['player_id'];
$article_text = $news['article_text'];
$article_image = $news['article_image'];
} else {
if (News::update($id, $p_title, $body, $type, $category, $player_id, $forum_section, $article_text, $article_image, $errors)) {
// update forum thread if exists
if (isset($forum_section) && Validator::number($forum_section)) {
$db->query("UPDATE `" . TABLE_PREFIX . "forum` SET `author_guid` = " . (int)$player_id . ", `post_text` = " . $db->quote($body) . ", `post_topic` = " . $db->quote($p_title) . ", `edit_date` = " . time() . " WHERE `id` = " . $db->quote($forum_section));
}
$action = $p_title = $body = $comments = $article_text = $article_image = '';
$type = $category = $player_id = 0;
success('Updated successful.');
}
}
} else if ($action == 'hide') {
if (News::toggleHide($id, $errors, $status)) {
success(($status == 1 ? 'Hide' : 'Show') . ' successful.');
}
}
}
else if($action == 'hide') {
if (News::toggleHidden($id, $errors, $status)) {
success(($status == 1 ? 'Hide' : 'Show') . ' successful.');
}
}
@@ -101,7 +99,7 @@ if(!empty($action))
}
$categories = array();
foreach($db->query('SELECT `id`, `name`, `icon_id` FROM `' . TABLE_PREFIX . 'news_categories` WHERE `hidden` != 1') as $cat)
foreach($db->query('SELECT `id`, `name`, `icon_id` FROM `' . TABLE_PREFIX . 'news_categories` WHERE `hide` != 1') as $cat)
{
$categories[$cat['id']] = array(
'name' => $cat['name'],
@@ -138,18 +136,27 @@ if($action == 'edit' || $action == 'new') {
$query = $db->query('SELECT * FROM ' . $db->tableName(TABLE_PREFIX . 'news'));
$newses = array();
$cachePlayers = [];
foreach ($query as $_news) {
$_player = new OTS_Player();
$_player->load($_news['player_id']);
$playerId = $_news['player_id'];
if (isset($cachePlayers[$playerId])) {
$_player = $cachePlayers[$playerId];
}
else {
$_player = new OTS_Player();
$_player->load($playerId);
$cachePlayers[$playerId] = $_player;
}
$newses[$_news['type']][] = array(
'id' => $_news['id'],
'hidden' => $_news['hidden'],
'hide' => $_news['hide'],
'archive_link' => getLink('news') . '/archive/' . $_news['id'],
'title' => $_news['title'],
'date' => $_news['date'],
'player_name' => isset($_player) && $_player->isLoaded() ? $_player->getName() : '',
'player_link' => isset($_player) && $_player->isLoaded() ? getPlayerLink($_player->getName(), false) : '',
'player_name' => $_player->isLoaded() ? $_player->getName() : '',
'player_link' => $_player->isLoaded() ? getPlayerLink($_player, false) : '',
);
}

View File

@@ -16,7 +16,7 @@ $title = 'Notepad';
csrfProtect();
/**
* @var $account_logged OTS_Account
* @var OTS_Account $account_logged
*/
$_content = '';
$notepad = ModelsNotepad::where('account_id', $account_logged->getId())->first();

View File

@@ -36,7 +36,7 @@ const PAGE_TITLE_LIMIT = 30;
const PAGE_NAME_LIMIT = 30;
const PAGE_BODY_LIMIT = 65535; // maximum page body length
if (!empty($action)) {
if (!empty($action) && isRequestMethod('post')) {
if ($action == 'delete' || $action == 'edit' || $action == 'hide') {
$id = $_POST['id'];
}
@@ -97,7 +97,7 @@ if (!empty($action)) {
}
}
} else if ($action == 'hide') {
if (Pages::toggleHidden($id, $errors, $status)) {
if (Pages::toggleHide($id, $errors, $status)) {
success(($status == 0 ? 'Show' : 'Hide') . ' successful.');
}
}
@@ -112,7 +112,7 @@ $pages = ModelsPages::all()->map(function ($e) {
'title' => substr($e->title, 0, 20),
'php' => $e->php == '1',
'id' => $e->id,
'hidden' => $e->hidden
'hide' => $e->hide
];
})->toArray();

View File

@@ -8,6 +8,7 @@
* @link https://my-aac.org
*/
use MyAAC\Forum;
use MyAAC\Models\Player;
defined('MYAAC') or die('Direct access not allowed!');
@@ -19,7 +20,6 @@ csrfProtect();
$player_base = ADMIN_URL . '?p=players';
$use_datatable = true;
require_once LIBS . 'forum.php';
$skills = array(
POT::SKILL_FIST => array('Fist fighting', 'fist'),
@@ -51,22 +51,20 @@ else if (isset($_REQUEST['search'])) {
if (strlen($search_player) < 3 && !Validator::number($search_player)) {
echo_error('Player name is too short.');
} else {
$query = $db->query('SELECT `id` FROM `players` WHERE `name` = ' . $db->quote($search_player));
if ($query->rowCount() == 1) {
$query = $query->fetch();
$id = (int)$query['id'];
$query = Player::where('name', 'like', '%' . $search_player . '%')->orderBy('name')->limit(11)->get(['id', 'name']);
if (count($query) == 0) {
echo_error('No entries found.');
} else if (count($query) == 1) {
$id = $query->first()->getKey();
} else if (count($query) > 10) {
echo_error('Specified name resulted with too many players.');
} else {
$query = $db->query('SELECT `id`, `name` FROM `players` WHERE `name` LIKE ' . $db->quote('%' . $search_player . '%'));
if ($query->rowCount() > 0 && $query->rowCount() <= 10) {
$str_construct = 'Do you mean?<ul>';
foreach ($query as $row)
$str_construct .= '<li><a href="' . $player_base . '&id=' . $row['id'] . '">' . $row['name'] . '</a></li>';
$str_construct .= '</ul>';
echo_error($str_construct);
} else if ($query->rowCount() > 10)
echo_error('Specified name resulted with too many players.');
else
echo_error('No entries found.');
$str_construct = 'Do you mean?<ul>';
foreach ($query as $row) {
$str_construct .= '<li><a href="' . $player_base . '&id=' . $row->getKey() . '">' . $row->name . '</a></li>';
}
$str_construct .= '</ul>';
echo_error($str_construct);
}
}
}
@@ -202,7 +200,7 @@ else if (isset($_REQUEST['search'])) {
if ($hasBlessingsColumn) {
$blessings = $_POST['blessings'];
verify_number($blessings, 'Blessings', 2);
verify_number($blessings, 'Blessings', 3);
}
$balance = $_POST['balance'];
@@ -213,7 +211,7 @@ else if (isset($_REQUEST['search'])) {
}
$deleted = (isset($_POST['deleted']) && $_POST['deleted'] == 'true');
$hidden = (isset($_POST['hidden']) && $_POST['hidden'] == 'true');
$hide = (isset($_POST['hide']) && $_POST['hide'] == 'true');
$created = strtotime($_POST['created']);
verify_number($created, 'Created', 11);
@@ -274,7 +272,7 @@ else if (isset($_REQUEST['search'])) {
$player->setLossContainers($loss_containers);
$player->setLossItems($loss_items);
}
if ($db->hasColumn('players', 'blessings'))
if ($hasBlessingsColumn)
$player->setBlessings($blessings);
if ($hasBlessingColumn) {
@@ -290,7 +288,7 @@ else if (isset($_REQUEST['search'])) {
$player->setCustomField('deletion', $deleted ? '1' : '0');
else
$player->setCustomField('deleted', $deleted ? '1' : '0');
$player->setCustomField('hidden', $hidden ? '1' : '0');
$player->setCustomField('hide', $hide ? '1' : '0');
$player->setCustomField('created', $created);
if (isset($comment))
$player->setCustomField('comment', $comment);
@@ -307,7 +305,7 @@ else if (isset($_REQUEST['search'])) {
}
}
} else if ($id == 0) {
$players_db = $db->query('SELECT `id`, `name`, `level` FROM `players` ORDER BY `id` asc');
$players_db = Player::orderBy('id')->get(['id','name', 'level']);
?>
<div class="col-12 col-sm-12 col-lg-10">
<div class="card card-info card-outline">
@@ -327,11 +325,11 @@ else if (isset($_REQUEST['search'])) {
<tbody>
<?php foreach ($players_db as $player_db): ?>
<tr>
<th><?php echo $player_db['id']; ?></th>
<td><?php echo $player_db['name']; ?></a></td>
<td><?php echo $player_db['level']; ?></a></td>
<th><?php echo $player_db->id; ?></th>
<td><?php echo $player_db->name; ?></a></td>
<td><?php echo $player_db->level; ?></a></td>
<td><a href="?p=players&id=<?php echo $player_db['id']; ?>" class="btn btn-success btn-sm" title="Edit">
<td><a href="?p=players&id=<?php echo $player_db->id; ?>" class="btn btn-success btn-sm" title="Edit">
<i class="fas fa-pencil-alt"></i>
</a>
</td>
@@ -375,7 +373,7 @@ else if (isset($_REQUEST['search'])) {
</li>
</ul>
</div>
<form action="<?php echo $player_base . ((isset($id) && $id > 0) ? '&id=' . $id : ''); ?>" method="post">
<form action="<?php echo $player_base . ($id > 0 ? '&id=' . $id : ''); ?>" method="post">
<?php csrf(); ?>
<div class="card-body">
<div class="tab-content" id="tabs-tabContent">
@@ -485,8 +483,8 @@ else if (isset($_REQUEST['search'])) {
</div>
<div class="col-12 col-sm-12 col-lg-6">
<div class="custom-control custom-switch custom-switch-on-success">
<input type="checkbox" class="custom-control-input" name="hidden" id="hidden" value="true" <?php echo($player->isHidden() ? ' checked' : ''); ?>>
<label class="custom-control-label" for="hidden">Hidden</label>
<input type="checkbox" class="custom-control-input" name="hide" id="hide" value="true" <?php echo($player->isHidden() ? ' checked' : ''); ?>>
<label class="custom-control-label" for="hide">Hidden</label>
</div>
</div>
</div>

View File

@@ -7,6 +7,9 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Plugins;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Plugin manager';
@@ -14,13 +17,17 @@ csrfProtect();
$use_datatable = true;
require_once LIBS . 'plugins.php';
if (!getBoolean(setting('core.admin_plugins_manage_enable'))) {
warning('Plugin installation and management is disabled in Settings.<br/>If you wish to enable, go to Settings and enable <strong>Enable Plugins Manage</strong>.');
}
else {
$twig->display('admin.plugins.form.html.twig');
$pluginUploadEnabled = true;
if(!\class_exists('\ZipArchive')) {
error('Please install PHP zip extension. Plugins upload disabled until then.');
$pluginUploadEnabled = false;
}
$twig->display('admin.plugins.form.html.twig', ['pluginUploadEnabled' => $pluginUploadEnabled]);
if (isset($_POST['uninstall'])) {
$uninstall = $_POST['uninstall'];

View File

@@ -7,6 +7,10 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Plugins;
use MyAAC\Settings;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Settings';
@@ -44,7 +48,7 @@ if (!is_array($settingsFile)) {
$settingsKeyName = ($plugin == 'core' ? $plugin : $settingsFile['key']);
$title = ($plugin == 'core' ? 'Settings' : 'Plugin Settings - ' . $plugin);
$title = ($plugin == 'core' ? 'Settings' : 'Plugin Settings - ' . $settingsFile['name']);
$settingsParsed = Settings::display($settingsKeyName, $settingsFile['settings']);

View File

@@ -12,6 +12,7 @@ defined('MYAAC') or die('Direct access not allowed!');
use DeviceDetector\DeviceDetector;
use DeviceDetector\Parser\Client\Browser;
use DeviceDetector\Parser\OperatingSystem;
use MyAAC\Visitors;
$title = 'Visitors';
$use_datatable = true;
@@ -24,7 +25,6 @@ if (!setting('core.visitors_counter')): ?>
return;
endif;
require SYSTEM . 'libs/visitors.php';
$visitors = new Visitors(setting('core.visitors_counter_ttl'));
function compare($a, $b): int {

View File

@@ -1,6 +1,6 @@
<?php
return [
$menus = [
['name' => 'Dashboard', 'icon' => 'tachometer-alt', 'order' => 10, 'link' => 'dashboard'],
['name' => 'Settings', 'icon' => 'edit', 'order' => 19, 'link' =>
require ADMIN . 'includes/settings_menus.php'

View File

@@ -8,3 +8,8 @@
.sidebar-mini.sidebar-collapse .menu-text {
display: none;
}
.myaac-table tbody tr:nth-child(even) {background: #FFF} /* light border */
.myaac-table tbody tr:nth-child(odd) {background: #CCC} /* dark border */
.myaac-table thead td {background: #000000; color: #ffffff !important;} /* vdark border */
.myaac-table tfoot td {background: #000000; color: #ffffff !important;} /* vdark border */

View File

@@ -191,8 +191,8 @@ if ($logged && admin()) {
]);
}
?>
<script src="<?php echo BASE_URL; ?>tools/js/bootstrap.min.js"></script>
<script src="<?php echo BASE_URL; ?>tools/js/jquery-ui.min.js"></script>
<script src="<?php echo BASE_URL; ?>tools/ext/bootstrap/js/bootstrap.min.js"></script>
<script src="<?php echo BASE_URL; ?>tools/ext/jquery-ui/jquery-ui.min.js"></script>
<?php if (isset($use_datatable)) { ?>
<script src="<?php echo BASE_URL; ?>tools/js/datatables.min.js"></script>
<script src="<?php echo BASE_URL; ?>tools/js/datatables.bs.min.js"></script>

View File

@@ -22,7 +22,10 @@
* @copyright 2020 MyAAC
* @link https://my-aac.org
*/
define('MYAAC_ADMIN', true);
use MyAAC\DataLoader;
const MYAAC_ADMIN = true;
require '../../common.php';
require SYSTEM . 'functions.php';
@@ -34,11 +37,9 @@ if (!admin())
ini_set('max_execution_time', 300);
ob_implicit_flush();
ob_end_flush();
@ob_end_flush();
header('X-Accel-Buffering: no');
require LIBS . 'DataLoader.php';
require LOCALE . 'en/main.php';
require LOCALE . 'en/install.php';

View File

@@ -1,4 +1,8 @@
<?php
use MyAAC\Hooks;
use MyAAC\Settings;
const MYAAC_ADMIN = true;
require '../../common.php';
@@ -6,11 +10,6 @@ require SYSTEM . 'functions.php';
require SYSTEM . 'init.php';
require SYSTEM . 'login.php';
// event system
require_once SYSTEM . 'hooks.php';
$hooks = new Hooks();
$hooks->load();
if(!admin()) {
http_response_code(500);
die('Access denied.');

View File

@@ -20,14 +20,14 @@
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @copyright 2024 MyAAC
* @link https://my-aac.org
*/
if (version_compare(phpversion(), '8.0', '<')) die('PHP version 8.0 or higher is required.');
if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.');
const MYAAC = true;
const MYAAC_VERSION = '1.0-dev';
const DATABASE_VERSION = 38;
const MYAAC_VERSION = '1.0.1';
const DATABASE_VERSION = 42;
const TABLE_PREFIX = 'myaac_';
define('START_TIME', microtime(true));
define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX'));
@@ -156,7 +156,7 @@ if (file_exists(BASE . 'config.local.php')) {
/** @var array $config */
ini_set('log_errors', 1);
if(@$config['env'] === 'dev') {
if(@$config['env'] === 'dev' || defined('MYAAC_INSTALL')) {
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

View File

@@ -1,6 +1,6 @@
{
"require": {
"php": "^8.0",
"php": "^8.1",
"ext-pdo": "*",
"ext-pdo_mysql": "*",
"ext-json": "*",
@@ -8,20 +8,25 @@
"ext-dom": "*",
"phpmailer/phpmailer": "^6.1",
"composer/semver": "^3.2",
"twig/twig": "^2.0",
"twig/twig": "^3.11",
"erusev/parsedown": "^1.7",
"nikic/fast-route": "^1.3",
"matomo/device-detector": "^6.0",
"illuminate/database": "^10.18",
"peppeocchi/php-cron-scheduler": "4.*"
"peppeocchi/php-cron-scheduler": "4.*",
"symfony/console": "^6.4",
"symfony/string": "^6.4",
"symfony/var-dumper": "^6.4",
"filp/whoops": "^2.15",
"maximebf/debugbar": "1.*"
},
"require-dev": {
"filp/whoops": "^2.15",
"maximebf/debugbar": "dev-master"
"phpstan/phpstan": "^1.10"
},
"autoload": {
"psr-4": {
"MyAAC\\": "system/src"
}
},
"files": ["system/src/global.php"]
}
}

2926
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -38,7 +38,6 @@ describe('Install MyAAC', () => {
cy.contains('Basic configuration');
cy.get('#vars_server_path').click().clear().type(Cypress.env('SERVER_PATH'))
cy.get('#vars_mail_admin').click().clear().type('noone@example.net')
cy.get('[type="checkbox"]').uncheck() // usage statistics uncheck
@@ -68,7 +67,9 @@ describe('Install MyAAC', () => {
cy.get('form').submit()
cy.contains('[class="alert alert-success"]', 'Congratulations', { timeout: 30000 }).should('be.visible')
cy.contains('[class="alert alert-success"]', 'Congratulations', { timeout: 60000 }).should('be.visible')
cy.wait(2000);
cy.screenshot('install-finish')
})

View File

@@ -82,7 +82,7 @@ describe('Check Public Pages', () => {
it('Go to last kills page', () => {
cy.visit({
url: Cypress.env('URL') + '/lastkills',
url: Cypress.env('URL') + '/last-kills',
method: 'GET',
})
})
@@ -116,9 +116,9 @@ describe('Check Public Pages', () => {
})
// library
it('Go to creatures page', () => {
it('Go to monsters page', () => {
cy.visit({
url: Cypress.env('URL') + '/creatures',
url: Cypress.env('URL') + '/monsters',
method: 'GET',
})
})
@@ -132,7 +132,7 @@ describe('Check Public Pages', () => {
it('Go to server info page', () => {
cy.visit({
url: Cypress.env('URL') + '/serverInfo',
url: Cypress.env('URL') + '/server-info',
method: 'GET',
})
})
@@ -160,7 +160,7 @@ describe('Check Public Pages', () => {
it('Go to experience table page', () => {
cy.visit({
url: Cypress.env('URL') + '/experienceTable',
url: Cypress.env('URL') + '/exp-table',
method: 'GET',
})
})

View File

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

102
index.php
View File

@@ -24,6 +24,9 @@
* @link https://my-aac.org
*/
use MyAAC\UsageStatistics;
use MyAAC\Visitors;
require_once 'common.php';
require_once SYSTEM . 'functions.php';
@@ -59,18 +62,13 @@ if(preg_match("/^(.*)\.(gif|jpg|png|jpeg|tiff|bmp|css|js|less|map|html|zip|rar|g
if((!isset($config['installed']) || !$config['installed']) && file_exists(BASE . 'install'))
{
header('Location: ' . BASE_URL . 'install/');
throw new RuntimeException('Setup detected that <b>install/</b> directory exists. Please visit <a href="' . BASE_URL . 'install">this</a> url to start MyAAC Installation.<br/>Delete <b>install/</b> directory if you already installed MyAAC.<br/>Remember to REFRESH this page when you\'re done!');
exit();
}
$template_place_holders = array();
require_once SYSTEM . 'init.php';
// verify myaac tables exists in database
if(!$db->hasTable('myaac_account_actions')) {
throw new RuntimeException('Seems that the table <strong>myaac_account_actions</strong> of MyAAC doesn\'t exist in the database. This is a fatal error. You can try to reinstall MyAAC by visiting <a href="' . BASE_URL . 'install">this</a> url.');
}
require_once SYSTEM . 'template.php';
require_once SYSTEM . 'login.php';
require_once SYSTEM . 'status.php';
@@ -78,53 +76,6 @@ require_once SYSTEM . 'status.php';
$twig->addGlobal('config', $config);
$twig->addGlobal('status', $status);
require_once SYSTEM . 'router.php';
$hooks->trigger(HOOK_STARTUP);
// anonymous usage statistics
// sent only when user agrees
if(setting('core.anonymous_usage_statistics')) {
$report_time = 30 * 24 * 60 * 60; // report one time per 30 days
$should_report = true;
$value = '';
if($cache->enabled() && $cache->fetch('last_usage_report', $value)) {
$should_report = time() > (int)$value + $report_time;
}
else {
$value = '';
if(fetchDatabaseConfig('last_usage_report', $value)) {
$should_report = time() > (int)$value + $report_time;
if($cache->enabled()) {
$cache->set('last_usage_report', $value);
}
}
else {
registerDatabaseConfig('last_usage_report', time() - ($report_time - (7 * 24 * 60 * 60))); // first report after a week
$should_report = false;
}
}
if($should_report) {
require_once LIBS . 'usage_statistics.php';
Usage_Statistics::report();
updateDatabaseConfig('last_usage_report', time());
if($cache->enabled()) {
$cache->set('last_usage_report', time());
}
}
}
if(setting('core.views_counter'))
require_once SYSTEM . 'counter.php';
if(setting('core.visitors_counter')) {
require_once SYSTEM . 'libs/visitors.php';
$visitors = new Visitors(setting('core.visitors_counter_ttl'));
}
// backward support for gesior
if(setting('core.backward_support')) {
define('INITIALIZED', true);
@@ -164,6 +115,51 @@ if(setting('core.backward_support')) {
$config['status']['serverStatus_' . $key] = $value;
}
require_once SYSTEM . 'router.php';
$hooks->trigger(HOOK_STARTUP);
// anonymous usage statistics
// sent only when user agrees
if(setting('core.anonymous_usage_statistics')) {
$report_time = 30 * 24 * 60 * 60; // report one time per 30 days
$should_report = true;
$value = '';
if($cache->enabled() && $cache->fetch('last_usage_report', $value)) {
$should_report = time() > (int)$value + $report_time;
}
else {
$value = '';
if(fetchDatabaseConfig('last_usage_report', $value)) {
$should_report = time() > (int)$value + $report_time;
if($cache->enabled()) {
$cache->set('last_usage_report', $value, 60 * 60);
}
}
else {
registerDatabaseConfig('last_usage_report', time() - ($report_time - (7 * 24 * 60 * 60))); // first report after a week
$should_report = false;
}
}
if($should_report) {
UsageStatistics::report();
updateDatabaseConfig('last_usage_report', time());
if($cache->enabled()) {
$cache->set('last_usage_report', time(), 60 * 60);
}
}
}
if(setting('core.views_counter'))
require_once SYSTEM . 'counter.php';
if(setting('core.visitors_counter')) {
$visitors = new Visitors(setting('core.visitors_counter_ttl'));
}
/**
* @var OTS_Account $account_logged
*/

View File

@@ -17,7 +17,7 @@ function query($query)
// define php version id if its not already
if(!defined('PHP_VERSION_ID')) {
$version = explode('.', PHP_VERSION);
$version = array_map('intval', explode('.', PHP_VERSION));
define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));
}

View File

@@ -1,4 +1,4 @@
SET @myaac_database_version = 36;
SET @myaac_database_version = 42;
CREATE TABLE `myaac_account_actions`
(
@@ -8,7 +8,7 @@ CREATE TABLE `myaac_account_actions`
`date` INT(11) NOT NULL DEFAULT 0,
`action` VARCHAR(255) NOT NULL DEFAULT '',
KEY (`account_id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_admin_menu`
(
@@ -19,22 +19,7 @@ CREATE TABLE `myaac_admin_menu`
`flags` INT(11) NOT NULL DEFAULT 0,
`enabled` INT(1) NOT NULL DEFAULT 1,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE `myaac_bugtracker`
(
`account` VARCHAR(255) NOT NULL,
`type` INT(11) NOT NULL DEFAULT 0,
`status` INT(11) NOT NULL DEFAULT 0,
`text` text NOT NULL,
`id` INT(11) NOT NULL DEFAULT 0,
`subject` VARCHAR(255) NOT NULL DEFAULT '',
`reply` INT(11) NOT NULL DEFAULT 0,
`who` INT(11) NOT NULL DEFAULT 0,
`uid` INT(11) NOT NULL AUTO_INCREMENT,
`tag` INT(11) NOT NULL DEFAULT 0,
PRIMARY KEY (`uid`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_changelog`
(
@@ -44,11 +29,11 @@ CREATE TABLE `myaac_changelog`
`where` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '1 - server, 2 - site',
`date` INT(11) NOT NULL DEFAULT 0,
`player_id` INT(11) NOT NULL DEFAULT 0,
`hidden` TINYINT(1) NOT NULL DEFAULT 0,
`hide` TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
INSERT INTO `myaac_changelog` (`id`, `type`, `where`, `date`, `body`, `hidden`) VALUES (1, 3, 2, UNIX_TIMESTAMP(), 'MyAAC installed. (:', 0);
INSERT INTO `myaac_changelog` (`id`, `type`, `where`, `date`, `body`, `hide`) VALUES (1, 3, 2, UNIX_TIMESTAMP(), 'MyAAC installed. (:', 0);
CREATE TABLE `myaac_config`
(
@@ -57,7 +42,7 @@ CREATE TABLE `myaac_config`
`value` VARCHAR(1000) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE (`name`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
INSERT INTO `myaac_config` (`name`, `value`) VALUES ('database_version', @myaac_database_version);
@@ -67,9 +52,9 @@ CREATE TABLE `myaac_faq`
`question` VARCHAR(255) NOT NULL DEFAULT '',
`answer` VARCHAR(1020) NOT NULL DEFAULT '',
`ordering` INT(11) NOT NULL DEFAULT 0,
`hidden` TINYINT(1) NOT NULL DEFAULT 0,
`hide` TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_forum_boards`
(
@@ -80,9 +65,9 @@ CREATE TABLE `myaac_forum_boards`
`guild` INT(11) NOT NULL DEFAULT 0,
`access` INT(11) NOT NULL DEFAULT 0,
`closed` TINYINT(1) NOT NULL DEFAULT 0,
`hidden` TINYINT(1) NOT NULL DEFAULT 0,
`hide` TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
) 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);
@@ -106,12 +91,12 @@ CREATE TABLE `myaac_forum`
`post_date` int(20) NOT NULL default '0',
`last_edit_aid` int(20) NOT NULL default '0',
`edit_date` int(20) NOT NULL default '0',
`post_ip` varchar(32) NOT NULL default '0.0.0.0',
`post_ip` varchar(45) NOT NULL default '0.0.0.0',
`sticked` tinyint(1) NOT NULL DEFAULT '0',
`closed` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `section` (`section`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_menu`
(
@@ -125,11 +110,11 @@ CREATE TABLE `myaac_menu`
`ordering` INT(11) NOT NULL DEFAULT 0,
`enabled` INT(1) NOT NULL DEFAULT 1,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_monsters` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`hidden` tinyint(1) NOT NULL default 0,
`hide` tinyint(1) NOT NULL default 0,
`name` varchar(255) NOT NULL,
`mana` int(11) NOT NULL DEFAULT 0,
`exp` int(11) NOT NULL,
@@ -158,7 +143,7 @@ CREATE TABLE `myaac_monsters` (
`loot` text NOT NULL,
`summons` TEXT NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_news`
(
@@ -174,9 +159,9 @@ CREATE TABLE `myaac_news`
`comments` VARCHAR(50) NOT NULL DEFAULT '',
`article_text` VARCHAR(300) NOT NULL DEFAULT '',
`article_image` VARCHAR(100) NOT NULL DEFAULT '',
`hidden` TINYINT(1) NOT NULL DEFAULT 0,
`hide` TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_news_categories`
(
@@ -184,9 +169,9 @@ CREATE TABLE `myaac_news_categories`
`name` VARCHAR(50) NOT NULL DEFAULT "",
`description` VARCHAR(50) NOT NULL DEFAULT "",
`icon_id` INT(2) NOT NULL DEFAULT 0,
`hidden` TINYINT(1) NOT NULL DEFAULT 0,
`hide` TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
) 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);
@@ -202,7 +187,7 @@ CREATE TABLE `myaac_notepad`
`content` TEXT NOT NULL,
/*`public` TINYINT(1) NOT NULL DEFAULT 0*/
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_pages`
(
@@ -215,10 +200,10 @@ CREATE TABLE `myaac_pages`
`php` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '0 - plain html, 1 - php',
`enable_tinymce` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '1 - enabled, 0 - disabled',
`access` TINYINT(2) NOT NULL DEFAULT 0,
`hidden` TINYINT(1) NOT NULL DEFAULT 0,
`hide` TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE (`name`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_gallery`
(
@@ -228,9 +213,9 @@ CREATE TABLE `myaac_gallery`
`thumb` VARCHAR(255) NOT NULL,
`author` VARCHAR(50) NOT NULL DEFAULT '',
`ordering` INT(11) NOT NULL DEFAULT 0,
`hidden` TINYINT(1) NOT NULL DEFAULT 0,
`hide` TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
) 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');
@@ -242,7 +227,7 @@ CREATE TABLE `myaac_settings`
`value` TEXT NOT NULL,
PRIMARY KEY (`id`),
KEY `key` (`key`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_spells`
(
@@ -262,10 +247,10 @@ CREATE TABLE `myaac_spells`
`item_id` INT(11) NOT NULL DEFAULT 0,
`premium` TINYINT(1) NOT NULL DEFAULT 0,
`vocations` VARCHAR(100) NOT NULL DEFAULT '',
`hidden` TINYINT(1) NOT NULL DEFAULT 0,
`hide` TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE (`name`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_visitors`
(
@@ -274,7 +259,7 @@ CREATE TABLE `myaac_visitors`
`page` VARCHAR(2048) NOT NULL,
`user_agent` VARCHAR(255) NOT NULL DEFAULT '',
UNIQUE (`ip`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
CREATE TABLE `myaac_weapons`
(
@@ -283,4 +268,4 @@ CREATE TABLE `myaac_weapons`
`maglevel` INT(11) NOT NULL DEFAULT 0,
`vocations` VARCHAR(100) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;

View File

@@ -3,16 +3,15 @@
use Twig\Environment as Twig_Environment;
use Twig\Loader\FilesystemLoader as Twig_FilesystemLoader;
require '../common.php';
const MYAAC_INSTALL = true;
define('MYAAC_INSTALL', true);
require '../common.php';
// includes
require SYSTEM . 'functions.php';
require BASE . 'install/includes/functions.php';
require BASE . 'install/includes/locale.php';
require SYSTEM . 'clients.conf.php';
require LIBS . 'Settings.php';
// ignore undefined index from Twig autoloader
$config['env'] = 'prod';
@@ -115,7 +114,7 @@ else if($step == 'finish') {
$email = $_SESSION['var_email'];
$password = $_SESSION['var_password'];
$password_confirm = $_SESSION['var_password_confirm'];
$player_name = $_SESSION['var_player_name'];
$player_name = $_SESSION['var_player_name'] ?? null;
// email check
if(empty($email)) {
@@ -126,18 +125,7 @@ else if($step == 'finish') {
}
// account check
if(isset($_SESSION['var_account'])) {
if(empty($_SESSION['var_account'])) {
$errors[] = $locale['step_admin_account_error_empty'];
}
else if(!Validator::accountName($_SESSION['var_account'])) {
$errors[] = $locale['step_admin_account_error_format'];
}
else if(strtoupper($_SESSION['var_account']) == strtoupper($password)) {
$errors[] = $locale['step_admin_account_error_same'];
}
}
else if(isset($_SESSION['var_account_id'])) {
if(isset($_SESSION['var_account_id'])) {
if(empty($_SESSION['var_account_id'])) {
$errors[] = $locale['step_admin_account_id_error_empty'];
}
@@ -148,6 +136,17 @@ else if($step == 'finish') {
$errors[] = $locale['step_admin_account_id_error_same'];
}
}
else if(isset($_SESSION['var_account'])) {
if(empty($_SESSION['var_account'])) {
$errors[] = $locale['step_admin_account_error_empty'];
}
else if(!Validator::accountName($_SESSION['var_account'])) {
$errors[] = $locale['step_admin_account_error_format'];
}
else if(strtoupper($_SESSION['var_account']) == strtoupper($password)) {
$errors[] = $locale['step_admin_account_error_same'];
}
}
// password check
if(empty($password)) {
@@ -160,12 +159,13 @@ else if($step == 'finish') {
$errors[] = $locale['step_admin_password_confirm_error_not_same'];
}
// player name check
if(empty($player_name)) {
$errors[] = $locale['step_admin_player_name_error_empty'];
}
else if(!Validator::characterName($player_name)) {
$errors[] = $locale['step_admin_player_name_error_format'];
if (isset($player_name)) {
// player name check
if (empty($player_name)) {
$errors[] = $locale['step_admin_player_name_error_empty'];
} else if (!Validator::characterName($player_name)) {
$errors[] = $locale['step_admin_player_name_error_format'];
}
}
if(!empty($errors)) {
@@ -183,14 +183,14 @@ clearstatcache();
if(is_writable(CACHE) && (MYAAC_OS != 'WINDOWS' || win_is_writable(CACHE))) {
if(!file_exists(BASE . 'install/ip.txt')) {
$content = warning('AAC installation is disabled. To enable it make file <b>ip.txt</b> in install/ directory and put there your IP.<br/>
Your IP is:<br /><b>' . $_SERVER['REMOTE_ADDR'] . '</b>', true);
Your IP is:<br /><b>' . get_browser_real_ip() . '</b>', true);
}
else {
$file_content = trim(file_get_contents(BASE . 'install/ip.txt'));
$allow = false;
$listIP = preg_split('/\s+/', $file_content);
foreach($listIP as $ip) {
if($_SERVER['REMOTE_ADDR'] == $ip) {
if(get_browser_real_ip() == $ip) {
$allow = true;
}
}
@@ -199,7 +199,7 @@ if(is_writable(CACHE) && (MYAAC_OS != 'WINDOWS' || win_is_writable(CACHE))) {
{
$content = warning('In file <b>install/ip.txt</b> must be your IP!<br/>
In file is:<br /><b>' . nl2br($file_content) . '</b><br/>
Your IP is:<br /><b>' . $_SERVER['REMOTE_ADDR'] . '</b>', true);
Your IP is:<br /><b>' . get_browser_real_ip() . '</b>', true);
}
else {
ob_start();

View File

@@ -2,10 +2,15 @@
defined('MYAAC') or die('Direct access not allowed!');
// configuration
$dirs_required = [
$dirs_required_writable = [
'system/logs',
'system/cache',
];
$dirs_required = [
'tools/ext' => $locale['step_requirements_folder_not_exists_tools_ext'],
];
$dirs_optional = [
GUILD_IMAGES_DIR => $locale['step_requirements_warning_images_guilds'],
GALLERY_DIR => $locale['step_requirements_warning_images_gallery'],
@@ -18,6 +23,7 @@ $extensions_optional = [
'gd' => $locale['step_requirements_warning_player_signatures'],
'zip' => $locale['step_requirements_warning_install_plugins'],
];
/*
*
* @param string $name
@@ -41,7 +47,7 @@ $failed = false;
// start validating
version_check($locale['step_requirements_php_version'], (PHP_VERSION_ID >= 50500), PHP_VERSION);
foreach ($dirs_required as $value)
foreach ($dirs_required_writable as $value)
{
$is_writable = is_writable(BASE . $value) && (MYAAC_OS != 'WINDOWS' || win_is_writable(BASE . $value));
version_check($locale['step_requirements_write_perms'] . ': ' . $value, $is_writable);
@@ -52,6 +58,12 @@ foreach ($dirs_optional as $dir => $errorMsg) {
version_check($locale['step_requirements_write_perms'] . ': ' . $dir, $is_writable, $is_writable ? '' : $errorMsg, true);
}
foreach ($dirs_required as $dir => $errorMsg)
{
$exists = is_dir(BASE . $dir);
version_check($locale['step_requirements_folder_exists'] . ': ' . $dir, $exists, $exists ? '' : $errorMsg);
}
$ini_register_globals = ini_get_bool('register_globals');
version_check('register_long_arrays', !$ini_register_globals, $ini_register_globals ? $locale['on'] : $locale['off']);
@@ -78,4 +90,3 @@ if($failed) {
}
echo '</div>';
?>

View File

@@ -1,4 +1,7 @@
<?php
use MyAAC\Settings;
defined('MYAAC') or die('Direct access not allowed!');
//ini_set('display_errors', false);
@@ -37,58 +40,46 @@ if(!$error) {
$configToSave['gzip_output'] = false;
$configToSave['cache_engine'] = 'auto';
$configToSave['cache_prefix'] = 'myaac_' . generateRandomString(8, true, false, true);
require BASE . 'install/includes/config.php';
$configToSave['database_auto_migrate'] = true;
if(!$error) {
require BASE . 'install/includes/database.php';
$content = '';
$saved = Settings::saveConfig($configToSave, BASE . 'config.local.php', $content);
if ($saved) {
success($locale['step_database_config_saved']);
$_SESSION['saved'] = true;
$locale['step_database_importing'] = str_replace('$DATABASE_NAME$', config('database_name'), $locale['step_database_importing']);
success($locale['step_database_importing']);
require BASE . 'config.local.php';
require BASE . 'install/includes/config.php';
if(isset($database_error)) { // we failed connect to the database
error($database_error);
}
else {
if(!$db->hasTable('accounts')) {
$tmp = str_replace('$TABLE$', 'accounts', $locale['step_database_error_table']);
error($tmp);
$error = true;
}
if (!$error) {
require BASE . 'install/includes/database.php';
if(!$db->hasTable('players')) {
$tmp = str_replace('$TABLE$', 'players', $locale['step_database_error_table']);
error($tmp);
$error = true;
}
if(!$db->hasTable('guilds')) {
$tmp = str_replace('$TABLE$', 'guilds', $locale['step_database_error_table']);
error($tmp);
$error = true;
}
if(!$error) {
$twig->display('install.installer.html.twig', array(
'url' => 'tools/5-database.php',
'message' => $locale['loading_spinner']
));
$content = '';
$saved = Settings::saveConfig($configToSave, BASE . 'config.local.php', $content);
if($saved) {
success($locale['step_database_config_saved']);
$_SESSION['saved'] = true;
if (isset($database_error)) { // we failed connect to the database
error($database_error);
}
else {
$_SESSION['config_content'] = $content;
unset($_SESSION['saved']);
if (!$db->hasTable('accounts')) {
$tmp = str_replace('$TABLE$', 'accounts', $locale['step_database_error_table']);
error($tmp);
$error = true;
}
$locale['step_database_error_file'] = str_replace('$FILE$', '<b>' . BASE . 'config.php</b>', $locale['step_database_error_file']);
error($locale['step_database_error_file'] . '<br/>
<textarea cols="70" rows="10">' . $content . '</textarea>');
if (!$error) {
$twig->display('install.installer.html.twig', array(
'url' => 'tools/5-database.php',
'message' => $locale['loading_spinner']
));
}
}
}
} else {
$_SESSION['config_content'] = $content;
unset($_SESSION['saved']);
$locale['step_database_error_file'] = str_replace('$FILE$', '<b>' . BASE . 'config.php</b>', $locale['step_database_error_file']);
error($locale['step_database_error_file'] . '<br/>
<textarea cols="70" rows="10">' . $content . '</textarea>');
}
}
}

View File

@@ -18,6 +18,7 @@ if(!$error) {
'locale' => $locale,
'session' => $_SESSION,
'account' => $account,
'hasTablePlayers' => $db->hasTable('players'),
'errors' => isset($errors) ? $errors : null,
'buttons' => next_buttons(true, $error ? false : true)
));

View File

@@ -1,169 +1,207 @@
<?php
use MyAAC\Cache\Cache;
use MyAAC\Models\News;
use MyAAC\Settings;
defined('MYAAC') or die('Direct access not allowed!');
ini_set('max_execution_time', 300);
if(isset($config['installed']) && $config['installed'] && !isset($_SESSION['saved'])) {
warning($locale['already_installed']);
return;
}
$cache = Cache::getInstance();
if ($cache->enabled()) {
// clear plugin_hooks to have fresh hooks
$cache->delete('plugins_hooks');
}
require SYSTEM . 'init.php';
if($error) {
return;
}
if(USE_ACCOUNT_NAME || USE_ACCOUNT_NUMBER)
$account = $_SESSION['var_account'] ?? null;
else
$account_id = $_SESSION['var_account_id'] ?? null;
$password = $_SESSION['var_password'];
if(USE_ACCOUNT_SALT)
{
$salt = generateRandomString(10, false, true, true);
$password = $salt . $password;
}
$account_db = new OTS_Account();
if(isset($account))
$account_db->find($account);
else
$account_db->load($account_id);
if ($db->hasTable('players')) {
$player_name = $_SESSION['var_player_name'];
$player_db = new OTS_Player();
$player_db->find($player_name);
if(!$player_db->isLoaded())
{
$player = new OTS_Player();
$player->setName($player_name);
$player_used = &$player;
}
else {
$player_used = &$player_db;
}
$groups = new OTS_Groups_List();
$player_used->setGroupId($groups->getHighestId());
}
$email = $_SESSION['var_email'];
if($account_db->isLoaded()) {
$account_db->setPassword(encrypt($password));
$account_db->setEMail($email);
$account_db->save();
$account_used = &$account_db;
}
else {
require SYSTEM . 'init.php';
if(!$error) {
if(USE_ACCOUNT_NAME || USE_ACCOUNT_NUMBER)
$account = isset($_SESSION['var_account']) ? $_SESSION['var_account'] : null;
else
$account_id = isset($_SESSION['var_account_id']) ? $_SESSION['var_account_id'] : null;
$new_account = new OTS_Account();
if(USE_ACCOUNT_NAME) {
$new_account->create($account);
}
else {
$new_account->create(null, $account_id);
}
$password = $_SESSION['var_password'];
$new_account->setPassword(encrypt($password));
$new_account->setEMail($email);
if(USE_ACCOUNT_SALT)
{
$salt = generateRandomString(10, false, true, true);
$password = $salt . $password;
}
$new_account->save();
$account_db = new OTS_Account();
if(isset($account))
$account_db->find($account);
else
$account_db->load($account_id);
$new_account->setCustomField('created', time());
$new_account->logAction('Account created.');
$player_name = $_SESSION['var_player_name'];
$player_db = new OTS_Player();
$player_db->find($player_name);
$account_used = &$new_account;
}
if(!$player_db->isLoaded())
{
$player = new OTS_Player();
$player->setName($player_name);
if(USE_ACCOUNT_SALT)
$account_used->setCustomField('salt', $salt);
$player_used = &$player;
}
else {
$player_used = &$player_db;
}
$account_used->setCustomField('web_flags', FLAG_ADMIN + FLAG_SUPER_ADMIN);
$account_used->setCustomField('country', 'us');
$account_used->setCustomField('email_verified', 1);
$groups = new OTS_Groups_List();
$player_used->setGroupId($groups->getHighestId());
if($db->hasColumn('accounts', 'group_id'))
$account_used->setCustomField('group_id', $groups->getHighestId());
if($db->hasColumn('accounts', 'type'))
$account_used->setCustomField('type', 6);
$email = $_SESSION['var_email'];
if($account_db->isLoaded()) {
$account_db->setPassword(encrypt($password));
$account_db->setEMail($email);
$account_db->save();
$account_used = &$account_db;
}
else {
$new_account = new OTS_Account();
if(USE_ACCOUNT_NAME) {
$new_account->create($account);
}
else {
$new_account->create(null, $account_id);
}
$new_account->setPassword(encrypt($password));
$new_account->setEMail($email);
$new_account->save();
$new_account->setCustomField('created', time());
$new_account->logAction('Account created.');
$account_used = &$new_account;
}
if(USE_ACCOUNT_SALT)
$account_used->setCustomField('salt', $salt);
$account_used->setCustomField('web_flags', FLAG_ADMIN + FLAG_SUPER_ADMIN);
$account_used->setCustomField('country', 'us');
if($db->hasColumn('accounts', 'group_id'))
$account_used->setCustomField('group_id', $groups->getHighestId());
if($db->hasColumn('accounts', 'type'))
$account_used->setCustomField('type', 6);
if(!$player_db->isLoaded())
$player->setAccountId($account_used->getId());
else
$player_db->setAccountId($account_used->getId());
success($locale['step_database_created_account']);
setSession('account', $account_used->getId());
setSession('password', encrypt($password));
setSession('remember_me', true);
if($player_db->isLoaded()) {
$player_db->save();
}
else {
$player->save();
}
$player_id = 0;
$query = $db->query("SELECT `id` FROM `players` WHERE `name` = " . $db->quote($player_name) . ";");
if($query->rowCount() == 1) {
$query = $query->fetch();
$player_id = $query['id'];
}
$query = $db->query("SELECT `id` FROM `" . TABLE_PREFIX ."news` WHERE `title` LIKE 'Hello!';");
if($query->rowCount() == 0) {
if(query("INSERT INTO `" . TABLE_PREFIX ."news` (`id`, `type`, `date`, `category`, `title`, `body`, `player_id`, `comments`, `hidden`) VALUES (NULL, '1', UNIX_TIMESTAMP(), '2', 'Hello!', 'MyAAC is just READY to use!', " . $player_id . ", 'https://my-aac.org', '0');
INSERT INTO `myaac_news` (`id`, `type`, `date`, `category`, `title`, `body`, `player_id`, `comments`, `hidden`) VALUES (NULL, '2', UNIX_TIMESTAMP(), '4', 'Hello tickets!', 'https://my-aac.org', " . $player_id . ", '', '0');")) {
success($locale['step_database_created_news']);
}
}
$settings = Settings::getInstance();
foreach($_SESSION as $key => $value) {
if (in_array($key, ['var_usage', 'var_date_timezone', 'var_client'])) {
if ($key == 'var_usage') {
$key = 'anonymous_usage_statistics';
$value = ((int)$value == 1 ? 'true' : 'false');
} elseif ($key == 'var_date_timezone') {
$key = 'date_timezone';
} elseif ($key == 'var_client') {
$key = 'client';
}
$settings->updateInDatabase('core', $key, $value);
}
}
success('Settings saved.');
$twig->display('install.installer.html.twig', array(
'url' => 'tools/7-finish.php',
'message' => $locale['importing_spinner']
));
if(!isset($_SESSION['installed'])) {
if (!array_key_exists('CI', getenv())) {
$report_url = 'https://my-aac.org/report_install.php?v=' . MYAAC_VERSION . '&b=' . urlencode(BASE_URL);
if (function_exists('curl_version'))
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $report_url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_exec($curl);
curl_close($curl);
}
else if (ini_get('allow_url_fopen') ) {
file_get_contents($report_url);
}
}
$_SESSION['installed'] = true;
}
foreach($_SESSION as $key => $value) {
if(strpos($key, 'var_') !== false)
unset($_SESSION[$key]);
}
unset($_SESSION['saved']);
if(file_exists(CACHE . 'install.txt')) {
unlink(CACHE . 'install.txt');
}
if ($db->hasTable('players')) {
if(!$player_db->isLoaded()) {
$player->setAccountId($account_used->getId());
$player->save();
}
else {
$player_db->setAccountId($account_used->getId());
$player_db->save();
}
}
success($locale['step_database_created_account']);
setSession('account', $account_used->getId());
setSession('password', encrypt($password));
setSession('remember_me', true);
if(!News::all()->count()) {
$player_id = 0;
if ($db->hasTable('players')) {
$tmpNewsPlayer = \MyAAC\Models\Player::where('name', $player_name)->first();
if($tmpNewsPlayer) {
$player_id = $tmpNewsPlayer->id;
}
}
News::create([
'type' => 1,
'date' => time(),
'category' => 2,
'title' => 'Hello!',
'body' => 'MyAAC is just READY to use!',
'player_id' => $player_id,
'comments' => 'https://my-aac.org',
'hide' => 0,
]);
News::create([
'type' => 2,
'date' => time(),
'category' => 4,
'title' => 'Hello tickers!',
'body' => 'https://my-aac.org',
'player_id' => $player_id,
'comments' => '',
'hide' => 0,
]);
success($locale['step_database_created_news']);
}
$settings = Settings::getInstance();
foreach($_SESSION as $key => $value) {
if (in_array($key, ['var_usage', 'var_date_timezone', 'var_client'])) {
if ($key == 'var_usage') {
$key = 'anonymous_usage_statistics';
$value = ((int)$value == 1 ? 'true' : 'false');
} elseif ($key == 'var_date_timezone') {
$key = 'date_timezone';
} elseif ($key == 'var_client') {
$key = 'client';
}
$settings->updateInDatabase('core', $key, $value);
}
}
success('Settings saved.');
$twig->display('install.installer.html.twig', array(
'url' => 'tools/7-finish.php',
'message' => $locale['importing_spinner']
));
if(!isset($_SESSION['installed'])) {
if (!array_key_exists('CI', getenv())) {
$report_url = 'https://my-aac.org/report_install.php?v=' . MYAAC_VERSION . '&b=' . urlencode(BASE_URL);
if (function_exists('curl_version'))
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $report_url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_exec($curl);
curl_close($curl);
}
else if (ini_get('allow_url_fopen') ) {
file_get_contents($report_url);
}
}
$_SESSION['installed'] = true;
}
foreach($_SESSION as $key => $value) {
if(strpos($key, 'var_') !== false)
unset($_SESSION[$key]);
}
unset($_SESSION['saved']);
if(file_exists(CACHE . 'install.txt')) {
unlink(CACHE . 'install.txt');
}
$hooks->trigger(HOOK_INSTALL_FINISH_END);

View File

@@ -6,7 +6,7 @@
<title>MyAAC - <?php echo $locale['installation']; ?></title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="template/style.css" />
<script type="text/javascript" src="<?php echo BASE_URL; ?>tools/js/jquery.min.js"></script>
<script type="text/javascript" src="<?php echo BASE_URL; ?>tools/ext/jquery/jquery.min.js"></script>
</head>
<body>

View File

@@ -11,8 +11,10 @@ $error = false;
require BASE . 'install/includes/config.php';
ini_set('max_execution_time', 300);
@ob_end_flush();
ob_implicit_flush();
ob_end_flush();
header('X-Accel-Buffering: no');
if(!$error) {
@@ -30,6 +32,9 @@ if($db->hasTable(TABLE_PREFIX . 'account_actions')) {
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'));
$locale['step_database_success_schema'] = str_replace('$PREFIX$', TABLE_PREFIX, $locale['step_database_success_schema']);
@@ -136,73 +141,74 @@ if(!$db->hasColumn('accounts', 'premium_points')) {
success($locale['step_database_adding_field'] . ' accounts.premium_points...');
}
if($db->hasColumn('guilds', 'checkdata')) {
if(query("ALTER TABLE `guilds` MODIFY `checkdata` INT NOT NULL DEFAULT 0;"))
success($locale['step_database_modifying_field'] . ' guilds.checkdata...');
}
if(!$db->hasColumn('guilds', 'motd')) {
if(query("ALTER TABLE `guilds` ADD `motd` VARCHAR(255) NOT NULL DEFAULT '';"))
success($locale['step_database_adding_field'] . ' guilds.motd...');
}
else {
if(query("ALTER TABLE `guilds` MODIFY `motd` VARCHAR(255) NOT NULL DEFAULT '';"))
success($locale['step_database_modifying_field'] . ' guilds.motd...');
}
if(!$db->hasColumn('guilds', 'description')) {
if(query("ALTER TABLE `guilds` ADD `description` TEXT NOT NULL;"))
success($locale['step_database_adding_field'] . ' guilds.description...');
}
if($db->hasColumn('guilds', 'logo_gfx_name')) {
if(query("ALTER TABLE `guilds` CHANGE `logo_gfx_name` `logo_name` VARCHAR( 255 ) NOT NULL DEFAULT 'default.gif';")) {
$tmp = str_replace('$FIELD$', 'guilds.logo_gfx_name', $locale['step_database_changing_field']);
$tmp = str_replace('$FIELD_NEW$', 'guilds.logo_name', $tmp);
success($tmp);
if ($db->hasTable('guilds')) {
if ($db->hasColumn('guilds', 'checkdata')) {
if (query("ALTER TABLE `guilds` MODIFY `checkdata` INT NOT NULL DEFAULT 0;"))
success($locale['step_database_modifying_field'] . ' guilds.checkdata...');
}
}
else if(!$db->hasColumn('guilds', 'logo_name')) {
if(query("ALTER TABLE `guilds` ADD `logo_name` VARCHAR( 255 ) NOT NULL DEFAULT 'default.gif';"))
success($locale['step_database_adding_field'] . ' guilds.logo_name...');
}
if(!$db->hasColumn('players', 'created')) {
if(query("ALTER TABLE `players` ADD `created` INT(11) NOT NULL DEFAULT 0;"))
success($locale['step_database_adding_field'] . ' players.created...');
}
if (!$db->hasColumn('guilds', 'motd')) {
if (query("ALTER TABLE `guilds` ADD `motd` VARCHAR(255) NOT NULL DEFAULT '';"))
success($locale['step_database_adding_field'] . ' guilds.motd...');
} else {
if (query("ALTER TABLE `guilds` MODIFY `motd` VARCHAR(255) NOT NULL DEFAULT '';"))
success($locale['step_database_modifying_field'] . ' guilds.motd...');
}
if(!$db->hasColumn('players', 'deleted') && !$db->hasColumn('players', 'deletion')) {
if(query("ALTER TABLE `players` ADD `deleted` TINYINT(1) NOT NULL DEFAULT 0;"))
success($locale['step_database_adding_field'] . ' players.deleted...');
}
if (!$db->hasColumn('guilds', 'description')) {
if (query("ALTER TABLE `guilds` ADD `description` TEXT NOT NULL;"))
success($locale['step_database_adding_field'] . ' guilds.description...');
}
if($db->hasColumn('players', 'hide_char')) {
if(!$db->hasColumn('players', 'hidden')) {
if(query("ALTER TABLE `players` CHANGE `hide_char` `hidden` TINYINT(1) NOT NULL DEFAULT 0;")) {
$tmp = str_replace('$FIELD$', 'players.hide_char', $locale['step_database_changing_field']);
$tmp = str_replace('$FIELD_NEW$', 'players.hidden', $tmp);
if ($db->hasColumn('guilds', 'logo_gfx_name')) {
if (query("ALTER TABLE `guilds` CHANGE `logo_gfx_name` `logo_name` VARCHAR( 255 ) NOT NULL DEFAULT 'default.gif';")) {
$tmp = str_replace('$FIELD$', 'guilds.logo_gfx_name', $locale['step_database_changing_field']);
$tmp = str_replace('$FIELD_NEW$', 'guilds.logo_name', $tmp);
success($tmp);
}
} else if (!$db->hasColumn('guilds', 'logo_name')) {
if (query("ALTER TABLE `guilds` ADD `logo_name` VARCHAR( 255 ) NOT NULL DEFAULT 'default.gif';"))
success($locale['step_database_adding_field'] . ' guilds.logo_name...');
}
}
else if(!$db->hasColumn('players', 'hidden')) {
if(query("ALTER TABLE `players` ADD `hidden` TINYINT(1) NOT NULL DEFAULT 0;"))
success($locale['step_database_adding_field'] . ' players.hidden...');
}
if(!$db->hasColumn('players', 'comment')) {
if(query("ALTER TABLE `players` ADD `comment` TEXT NOT NULL;"))
success($locale['step_database_adding_field'] . ' players.comment...');
}
if ($db->hasTable('players')) {
if (!$db->hasColumn('players', 'created')) {
if (query("ALTER TABLE `players` ADD `created` INT(11) NOT NULL DEFAULT 0;"))
success($locale['step_database_adding_field'] . ' players.created...');
}
if($db->hasColumn('players', 'rank_id')) {
if(query("ALTER TABLE players MODIFY `rank_id` INT(11) NOT NULL DEFAULT 0;"))
success($locale['step_database_modifying_field'] . ' players.rank_id...');
if (!$db->hasColumn('players', 'deleted') && !$db->hasColumn('players', 'deletion')) {
if (query("ALTER TABLE `players` ADD `deleted` TINYINT(1) NOT NULL DEFAULT 0;"))
success($locale['step_database_adding_field'] . ' players.deleted...');
}
if($db->hasColumn('players', 'guildnick')) {
if(query("ALTER TABLE players MODIFY `guildnick` VARCHAR(255) NOT NULL DEFAULT '';")) {
success($locale['step_database_modifying_field'] . ' players.guildnick...');
if ($db->hasColumn('players', 'hide_char')) {
if (!$db->hasColumn('players', 'hide')) {
if (query("ALTER TABLE `players` CHANGE `hide_char` `hide` TINYINT(1) NOT NULL DEFAULT 0;")) {
$tmp = str_replace('$FIELD$', 'players.hide_char', $locale['step_database_changing_field']);
$tmp = str_replace('$FIELD_NEW$', 'players.hide', $tmp);
success($tmp);
}
}
} else if (!$db->hasColumn('players', 'hide')) {
if (query("ALTER TABLE `players` ADD `hide` TINYINT(1) NOT NULL DEFAULT 0;"))
success($locale['step_database_adding_field'] . ' players.hide...');
}
if (!$db->hasColumn('players', 'comment')) {
if (query("ALTER TABLE `players` ADD `comment` TEXT NOT NULL;"))
success($locale['step_database_adding_field'] . ' players.comment...');
}
if ($db->hasColumn('players', 'rank_id')) {
if (query("ALTER TABLE players MODIFY `rank_id` INT(11) NOT NULL DEFAULT 0;"))
success($locale['step_database_modifying_field'] . ' players.rank_id...');
if ($db->hasColumn('players', 'guildnick')) {
if (query("ALTER TABLE players MODIFY `guildnick` VARCHAR(255) NOT NULL DEFAULT '';")) {
success($locale['step_database_modifying_field'] . ' players.guildnick...');
}
}
}
}

View File

@@ -1,6 +1,10 @@
<?php
define('MYAAC_INSTALL', true);
use MyAAC\DataLoader;
use MyAAC\Models\FAQ as ModelsFAQ;
use MyAAC\Plugins;
require_once '../../common.php';
require SYSTEM . 'functions.php';
@@ -8,8 +12,10 @@ require BASE . 'install/includes/functions.php';
require BASE . 'install/includes/locale.php';
ini_set('max_execution_time', 300);
@ob_end_flush();
ob_implicit_flush();
ob_end_flush();
header('X-Accel-Buffering: no');
/*
if(isset($config['installed']) && $config['installed'] && !isset($_SESSION['saved'])) {
@@ -19,51 +25,59 @@ if(isset($config['installed']) && $config['installed'] && !isset($_SESSION['save
require SYSTEM . 'init.php';
$deleted = 'deleted';
if($db->hasColumn('players', 'deletion'))
$deleted = 'deletion';
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;
$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`, `hidden`, `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;
$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']);
}
}
$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']);
}
require_once LIBS . 'plugins.php';
Plugins::installMenus('kathrine', require TEMPLATES . 'kathrine/menus.php');
Plugins::installMenus('tibiacom', require TEMPLATES . 'tibiacom/menus.php');
require LIBS . 'DataLoader.php';
DataLoader::setLocale($locale);
DataLoader::load();
// update config.highscores_ids_hidden
require_once SYSTEM . 'migrations/20.php';
$up();
// add z_polls tables
require_once SYSTEM . 'migrations/22.php';
$up();
// add myaac_pages pages
require_once SYSTEM . 'migrations/27.php';
$up();
require_once SYSTEM . 'migrations/30.php';
$up();
// new monster columns
require_once SYSTEM . 'migrations/31.php';
$up();
use MyAAC\Models\FAQ as ModelsFAQ;
if(ModelsFAQ::count() == 0) {
ModelsFAQ::create([
'question' => 'What is this?',
@@ -71,6 +85,10 @@ if(ModelsFAQ::count() == 0) {
]);
}
$hooks->trigger(HOOK_INSTALL_FINISH);
$db->setClearCacheAfter(true);
$locale['step_finish_desc'] = str_replace('$ADMIN_PANEL$', generateLink(str_replace('tools/', '',ADMIN_URL), $locale['step_finish_admin_panel'], true), $locale['step_finish_desc']);
$locale['step_finish_desc'] = str_replace('$HOMEPAGE$', generateLink(str_replace('tools/', '', BASE_URL), $locale['step_finish_homepage'], true), $locale['step_finish_desc']);
$locale['step_finish_desc'] = str_replace('$LINK$', generateLink('https://my-aac.org', 'https://my-aac.org', true), $locale['step_finish_desc']);

View File

@@ -4,6 +4,7 @@ use MyAAC\Models\BoostedCreature;
use MyAAC\Models\PlayerOnline;
use MyAAC\Models\Account;
use MyAAC\Models\Player;
use MyAAC\RateLimit;
require_once 'common.php';
require_once SYSTEM . 'functions.php';
@@ -130,12 +131,29 @@ switch ($action) {
}
$account = $account->first();
$ip = get_browser_real_ip();
$limiter = new RateLimit('failed_logins', setting('core.account_login_attempts_limit'), setting('core.account_login_ban_time'));
$limiter->enabled = setting('core.account_login_ipban_protection');
$limiter->load();
$ban_msg = 'A wrong account, password or secret has been entered ' . setting('core.account_login_attempts_limit') . ' times in a row. You are unable to log into your account for the next ' . setting('core.account_login_ban_time') . ' minutes. Please wait.';
if (!$account) {
$limiter->increment($ip);
if ($limiter->exceeded($ip)) {
sendError($ban_msg);
}
sendError(($inputEmail != false ? 'Email' : 'Account name') . ' or password is not correct.');
}
$current_password = encrypt((USE_ACCOUNT_SALT ? $account->salt : '') . $request->password);
if (!$account || $account->password != $current_password) {
$limiter->increment($ip);
if ($limiter->exceeded($ip)) {
sendError($ban_msg);
}
sendError(($inputEmail != false ? 'Email' : 'Account name') . ' or password is not correct.');
}
@@ -145,16 +163,30 @@ switch ($action) {
if ($accountSecret != null && $accountSecret != '') {
$accountHasSecret = true;
if ($inputToken === false) {
$limiter->increment($ip);
if ($limiter->exceeded($ip)) {
sendError($ban_msg);
}
sendError('Submit a valid two-factor authentication token.', 6);
} else {
require_once LIBS . 'rfc6238.php';
if (TokenAuth6238::verify($accountSecret, $inputToken) !== true) {
$limiter->increment($ip);
if ($limiter->exceeded($ip)) {
sendError($ban_msg);
}
sendError('Two-factor authentication failed, token is wrong.', 6);
}
}
}
}
$limiter->reset($ip);
if (setting('core.account_mail_verify') && $account->email_verified !== 1) {
sendError('You need to verify your account, enter in our site and resend verify e-mail!');
}
// common columns
$columns = 'id, name, level, sex, vocation, looktype, lookhead, lookbody, looklegs, lookfeet, lookaddons';

View File

@@ -10,22 +10,21 @@ server {
# this is very important, be sure its in your nginx conf - it prevents access to logs etc.
location ~ /system {
deny all;
return 404;
}
# block .htaccess
location ~ /\.ht {
# block .htaccess, CHANGELOG.md, composer.json etc.
# this is to prevent finding software versions
location ~\.(ht|md|json|dist)$ {
deny all;
}
# block git files and folders
location ~ /\.git {
return 404;
deny all;
}
location / {
try_files $uri $uri/ /index.php;
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {

16
npm-post-install.js Normal file
View File

@@ -0,0 +1,16 @@
const fse = require('fs-extra');
const path = require('path');
const nodeModulesDir = path.join(__dirname, 'node_modules');
const publicDir = path.join(__dirname, 'tools/ext');
fse.emptyDirSync(path.join(publicDir, 'jquery'));
fse.emptyDirSync(path.join(publicDir, 'jquery-ui'));
fse.emptyDirSync(path.join(publicDir, 'bootstrap'));
fse.emptyDirSync(path.join(publicDir, 'tinymce'));
fse.emptyDirSync(path.join(publicDir, 'tinymce-jquery'));
fse.copySync(path.join(nodeModulesDir, 'jquery', 'dist'), path.join(publicDir, 'jquery'), { overwrite: true });
fse.copySync(path.join(nodeModulesDir, 'jquery-ui', 'dist'), path.join(publicDir, 'jquery-ui'), { overwrite: true });
fse.copySync(path.join(nodeModulesDir, 'bootstrap', 'dist'), path.join(publicDir, 'bootstrap'), { overwrite: true });
fse.copySync(path.join(nodeModulesDir, 'tinymce'), path.join(publicDir, 'tinymce'), { overwrite: true });
fse.copySync(path.join(nodeModulesDir, '@tinymce', 'tinymce-jquery', 'dist'), path.join(publicDir, 'tinymce-jquery'), { overwrite: true });

992
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,17 @@
{
"scripts": {
"cypress:open": "cypress open"
"cypress:open": "cypress open",
"postinstall": "node ./npm-post-install.js"
},
"devDependencies": {
"cypress": "^12.12.0"
"cypress": "^13.17.0"
},
"dependencies": {
"@tinymce/tinymce-jquery": "^2.1.0",
"bootstrap": "^4.6.2",
"fs-extra": "^11.2.0",
"jquery": "^3.7.1",
"jquery-ui": "^1.13.2",
"tinymce": "^7.2.0"
}
}

13
phpstan-bootstrap.php Normal file
View File

@@ -0,0 +1,13 @@
<?php
require __DIR__ . '/system/libs/pot/OTS.php';
$ots = POT::getInstance();
require __DIR__ . '/system/libs/pot/InvitesDriver.php';
require __DIR__ . '/system/libs/rfc6238.php';
require __DIR__ . '/common.php';
const ACTION = '';
const PAGE = '';
const URI = '';
define('SELF_NAME', basename(__FILE__));

39
phpstan.neon Normal file
View File

@@ -0,0 +1,39 @@
parameters:
level: 3
paths:
- .
- templates/tibiacom
- templates/kathrine
excludePaths:
- system/cache/*
- vendor/*
- plugins/*
- system/libs
- tools/signature/mango.php
- tools/signature/gd.class.php
bootstrapFiles:
- phpstan-bootstrap.php
ignoreErrors:
- '#Variable \$db might not be defined#'
- '#Variable \$twig might not be defined#'
- '#Variable \$hooks might not be defined#'
- '#Variable \$account_logged might not be defined#'
- '#Variable \$logged might not be defined#'
- '#Variable \$config might not be defined#'
- '#Variable \$action might not be defined#'
- '#Variable \$errors might not be defined#'
- '#Variable \$cache might not be defined#'
- '#Variable \$status might not be defined#'
- '#Variable \$player might not be defined#'
- '#Variable \$guild might not be defined#'
- '#Variable \$[a-zA-Z0-9\\_]+ might not be defined#'
# Eloquent models
- '#Call to an undefined static method [a-zA-Z0-9\\_]+::[a-zA-Z0-9\\_]+\(\)#'
- '#Call to an undefined method object::toArray\(\)#'
# system/pages/highscores.php
- '#Call to an undefined method Illuminate\\Database\\Query\\Builder::withOnlineStatus\(\)#'
- '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::\$online_status#'
- '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::\$vocation_name#'
-
message: '#Variable \$tmp in empty\(\) always exists and is always falsy#'
path: templates\kathrine\javascript.php

View File

@@ -1,8 +1,6 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
$reward = setting('core.account_mail_confirmed_reward');
$hasCoinsColumn = $db->hasColumn('accounts', 'coins');
$rewardCoins = setting('core.account_mail_confirmed_reward_coins');
if ($rewardCoins > 0 && !$hasCoinsColumn) {

View File

@@ -25,7 +25,8 @@
"hooks": {
"Example Hook": {
"type": "BEFORE_PAGE",
"file": "plugins/example/before.php"
"file": "plugins/example/before.php",
"priority": 1000
}
},
"routes": {
@@ -33,12 +34,20 @@
"pattern": "/YourAwesomePage/{name:string}/{page:int}",
"file": "plugins/your-plugin/your-awesome-page.php",
"method": "GET",
"priority": "130"
"priority": 130
},
"Redirect Example": {
"redirect_from": "/redirectExample",
"redirect_to": "account/manage"
}
},
"settings": "plugins/your-plugin-folder/settings.php"
"routes-default-priority": 1000,
"pages-default-priority": 1000,
"settings": "plugins/your-plugin-folder/settings.php",
"autoload": {
"pages": true,
"pagesSubFolders": false,
"commands": true,
"themes": true
}
}

View File

@@ -22,7 +22,7 @@ if [ $1 = "prepare" ]; then
mkdir -p tmp
# get myaac from git archive
git archive --format zip --output tmp/myaac.zip develop
git archive --format zip --output tmp/myaac.zip master
cd tmp/ || exit
@@ -38,7 +38,11 @@ if [ $1 = "prepare" ]; then
cd $dir || exit
# dependencies
composer install --no-dev
composer install --no-dev --prefer-dist --optimize-autoloader
npm install
# node_modules is useless, we already have copy in tools/ext
rm -R node_modules
echo "Now you can make changes to $dir. When you are ready, type 'release.sh pack'"
exit

View File

@@ -1,18 +0,0 @@
<?php
if(PHP_SAPI !== 'cli') {
echo 'This script can be run only in command line mode.';
exit(1);
}
require_once __DIR__ . '/../../common.php';
require_once SYSTEM . 'functions.php';
require_once SYSTEM . 'init.php';
if(clearCache()) {
echo 'Cache cleared.' . PHP_EOL;
}
else {
echo 'Unexpected error.' . PHP_EOL;
exit(2);
}

View File

@@ -1,19 +0,0 @@
<?php
require_once __DIR__ . '/../../common.php';
require_once SYSTEM . 'functions.php';
require_once SYSTEM . 'init.php';
require_once SYSTEM . 'hooks.php';
$hooks = new Hooks();
$hooks->load();
use GO\Scheduler;
// Create a new scheduler
$scheduler = new Scheduler();
$hooks->trigger(HOOK_CRONJOB, ['scheduler' => $scheduler]);
// Let the scheduler execute jobs which are due.
$scheduler->run();

View File

View File

@@ -1,50 +0,0 @@
<?php
require_once __DIR__ . '/../../common.php';
require_once SYSTEM . 'functions.php';
require_once SYSTEM . 'init.php';
if(!IS_CLI) {
echo 'This script can be run only in command line mode.' . PHP_EOL;
exit(1);
}
if (MYAAC_OS !== 'LINUX') {
echo 'This script can be run only on linux.' . PHP_EOL;
exit(1);
}
$job = '* * * * * /usr/bin/php ' . SYSTEM . 'bin/cronjob.php >> ' . SYSTEM . 'logs/cron.log 2>&1';
if (cronjob_exists($job)) {
echo 'MyAAC cronjob already installed.' . PHP_EOL;
exit(0);
}
exec ('crontab -l', $content);
$content = implode(' ', $content);
$content .= PHP_EOL . $job;
file_put_contents(CACHE . 'cronjob', $content . PHP_EOL);
exec('crontab ' . CACHE. 'cronjob');
echo 'Installed crontab successfully.' . PHP_EOL;
function cronjob_exists($command)
{
$cronjob_exists=false;
exec('crontab -l', $crontab);
if(isset($crontab)&&is_array($crontab)) {
$crontab = array_flip($crontab);
if(isset($crontab[$command])){
$cronjob_exists = true;
}
}
return $cronjob_exists;
}

View File

@@ -1,42 +0,0 @@
<?php
if(PHP_SAPI !== 'cli') {
echo 'This script can be run only in command line mode.';
exit(1);
}
require_once __DIR__ . '/../../common.php';
require_once SYSTEM . 'functions.php';
require_once SYSTEM . 'init.php';
require_once SYSTEM . 'hooks.php';
require_once LIBS . 'plugins.php';
if($argc !== 2) {
echo 'This command expects one parameter: zip file name (plugin)' . PHP_EOL;
exit(2);
}
$path_to_file = $argv[1];
$ext = strtolower(pathinfo($path_to_file, PATHINFO_EXTENSION));
if($ext !== 'zip') {// check if it is zipped/compressed file
echo 'Please install only .zip files.' . PHP_EOL;
exit(3);
}
if(!file_exists($path_to_file)) {
echo 'ERROR: File ' . $path_to_file . ' does not exist' . PHP_EOL;
exit(4);
}
if(Plugins::install($path_to_file)) {
foreach(Plugins::getWarnings() as $warning) {
echo 'WARNING: ' . $warning;
}
$info = Plugins::getPluginJson();
echo (isset($info['name']) ? $info['name'] . ' p' : 'P') . 'lugin has been successfully installed.' . PHP_EOL;
}
else {
echo 'ERROR: ' . Plugins::getError() . PHP_EOL;
exit(5);
}

View File

@@ -1,61 +0,0 @@
<?php
if(PHP_SAPI !== 'cli') {
echo 'This script can be run only in command line mode.';
exit(1);
}
require_once __DIR__ . '/../../common.php';
require_once SYSTEM . 'functions.php';
require_once SYSTEM . 'init.php';
if($argc !== 3) {
echo 'This command expects two parameters: account_name_or_id|player_name|email address, subject.' . PHP_EOL;
exit(2);
}
$email_account_name = $argv[1];
$subject = $argv[2];
$message = file_get_contents('php://stdin');
if(strpos($email_account_name, '@') === false) {
$account = new OTS_Account();
if(USE_ACCOUNT_NAME) {
$account->find($email_account_name);
}
else {
$account->load($email_account_name);
}
if($account->isLoaded()) {
$email_account_name = $account->getEMail();
}
else {
$player = new OTS_Player();
$player->find($email_account_name);
if($player->isLoaded()) {
$email_account_name = $player->getAccount()->getEMail();
}
else {
echo 'Cannot find player or account with name: ' . $email_account_name . '.' . PHP_EOL;
exit(3);
}
}
}
if(!Validator::email($email_account_name)) {
echo 'Invalid E-Mail format.' . PHP_EOL;
exit(4);
}
if(strlen($subject) > 255) {
echo 'Subject max length is 255 characters.' . PHP_EOL;
exit(5);
}
if(!_mail($email_account_name, $subject, $message)) {
echo 'An error occurred while sending email. More info can be found in system/logs/mailer-error.log';
exit(6);
}
echo 'Mail sent to ' . $email_account_name . '.' . PHP_EOL;

View File

@@ -105,4 +105,8 @@ $config['clients'] = [
1316,
1320,
1321,
1322,
1330,
1332,
1340,
];

View File

@@ -9,6 +9,8 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
class Validator extends \MyAAC\Validator {}
function check_name($name, &$errors = '') {
if(Validator::characterName($name))
return true;
@@ -72,4 +74,7 @@ function fieldExist($field, $table)
global $db;
return $db->hasColumn($table, $field);
}
?>
function getCreatureImgPath($creature): string {
return getMonsterImgPath($creature);
}

View File

@@ -36,3 +36,5 @@ class Guild extends OTS_Guild {
}
class GuildRank extends OTS_GuildRank {}
class House extends OTS_House {}
class Cache extends \MyAAC\Cache\Cache {}

View File

@@ -44,7 +44,7 @@ switch($page)
break;
case 'killstatistics':
$page = 'lastkills';
$page = 'last-kills';
break;
case 'buypoints':

View File

@@ -7,6 +7,9 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Cache\Cache;
defined('MYAAC') or die('Direct access not allowed!');
define('COUNTER_SYNC', 10); // how often counter is synchronized with database (each x site refreshes)

View File

@@ -106,6 +106,7 @@ try {
'persistent' => @$config['database_persistent']
));
global $db;
$db = POT::getInstance()->getDBHandle();
$capsule = new Capsule;
$capsule->addConnection([
@@ -127,6 +128,7 @@ try {
}
if(defined('MYAAC_INSTALL')) {
$error = $e->getMessage();
return; // installer will take care of this
}

View File

@@ -8,21 +8,21 @@
* @link https://my-aac.org
*/
if (class_exists(\Whoops\Run::class)) {
$whoops = new \Whoops\Run;
if(IS_CLI) {
$whoops->pushHandler(new \Whoops\Handler\PlainTextHandler);
}
else {
$whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
}
use MyAAC\Exceptions\SensitiveException;
use Whoops\Handler\PlainTextHandler;
use Whoops\Handler\PrettyPageHandler;
use Whoops\Run;
if (class_exists(Run::class)) {
$whoops = new Run;
$whoopsHandler = IS_CLI ? (new PlainTextHandler()) : (new PrettyPageHandler());
$whoops->pushHandler($whoopsHandler);
$whoops->register();
return;
}
require LIBS . 'SensitiveException.php';
/**
* @param Exception $exception
*/

View File

@@ -9,12 +9,17 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
use MyAAC\Cache\Cache;
use MyAAC\CsrfToken;
use MyAAC\Items;
use MyAAC\Models\Config;
use MyAAC\Models\Guild;
use MyAAC\Models\House;
use MyAAC\Models\Pages;
use MyAAC\Models\Player;
use MyAAC\News;
use MyAAC\Plugins;
use MyAAC\Settings;
use PHPMailer\PHPMailer\PHPMailer;
use Twig\Loader\ArrayLoader as Twig_ArrayLoader;
@@ -82,25 +87,41 @@ function getForumBoardLink($board_id, $page = NULL): string {
return BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'forum/board/' . (int)$board_id . (isset($page) ? '/' . $page : '');
}
function getPlayerLink($name, $generate = true): string
function getPlayerLink($name, $generate = true, bool $colored = false): string
{
if(is_numeric($name))
{
if (is_object($name) and $name instanceof OTS_Player) {
$player = $name;
}
else {
$player = new OTS_Player();
$player->load((int)$name);
if($player->isLoaded())
$name = $player->getName();
if(is_numeric($name)) {
$player->load((int)$name);
}
else {
$player->find($name);
}
}
if (!$player->isLoaded()) {
return '(error)';
}
$name = $player->getName();
$url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'characters/' . urlencode($name);
if ($colored) {
$name = '<span style="color: ' . ($player->isOnline() ? 'green' : 'red') . ';">' . $name . '</span>';
}
if(!$generate) return $url;
return generateLink($url, $name);
}
function getMonsterLink($name, $generate = true): string
{
$url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'creatures/' . urlencode($name);
$url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'monsters/' . urlencode($name);
if(!$generate) return $url;
return generateLink($url, $name);
@@ -137,7 +158,6 @@ function getGuildLink($name, $generate = true): string
}
function getItemNameById($id) {
require_once LIBS . 'items.php';
$item = Items::get($id);
return !empty($item['name']) ? $item['name'] : '';
}
@@ -197,7 +217,7 @@ function getFlagImage($country): string
* @param mixed $v Variable to check.
* @return bool Value boolean status.
*/
function getBoolean($v): bool
function getBoolean(mixed $v): bool
{
if(is_bool($v)) {
return $v;
@@ -206,6 +226,10 @@ function getBoolean($v): bool
if(is_numeric($v))
return (int)$v > 0;
if (is_null($v)) {
return false;
}
$v = strtolower($v);
return $v === 'yes' || $v === 'true';
}
@@ -253,7 +277,7 @@ function generateRandomString($length, $lowCase = true, $upCase = false, $numeri
function getForumBoards()
{
global $db, $canEdit;
$sections = $db->query('SELECT `id`, `name`, `description`, `closed`, `guild`, `access`' . ($canEdit ? ', `hidden`, `ordering`' : '') . ' FROM `' . TABLE_PREFIX . 'forum_boards` ' . (!$canEdit ? ' WHERE `hidden` != 1' : '') .
$sections = $db->query('SELECT `id`, `name`, `description`, `closed`, `guild`, `access`' . ($canEdit ? ', `hide`, `ordering`' : '') . ' FROM `' . TABLE_PREFIX . 'forum_boards` ' . (!$canEdit ? ' WHERE `hide` != 1' : '') .
' ORDER BY `ordering`;');
if($sections)
return $sections->fetchAll();
@@ -410,7 +434,10 @@ function delete_guild($id)
if(count($rank_list) > 0) {
$rank_list->orderBy('level');
global $db, $ots;
global $db;
/**
* @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`;');
@@ -562,24 +589,12 @@ function template_form()
{
global $template_name;
$cache = Cache::getInstance();
if($cache->enabled())
{
$tmp = '';
if($cache->fetch('templates', $tmp)) {
$templates = unserialize($tmp);
}
else
{
$templates = get_templates();
$cache->set('templates', serialize($templates), 30);
}
}
else
$templates = get_templates();
$templates = Cache::remember('templates', 5 * 60, function() {
return get_templates();
});
$options = '';
foreach($templates as $key => $value)
foreach($templates as $value)
$options .= '<option ' . ($template_name == $value ? 'SELECTED' : '') . '>' . $value . '</option>';
global $twig;
@@ -702,11 +717,8 @@ function getSkillName($skillId, $suffix = true)
/**
* Performs flag check on the current logged in user.
* Table in database: accounts, field: website_flags
*
* @param int @flag Flag to be verified.
* @return bool If user got flag.
*/
function hasFlag($flag) {
function hasFlag(int $flag): bool {
global $logged, $logged_flags;
return ($logged && ($logged_flags & $flag) == $flag);
}
@@ -779,7 +791,7 @@ function get_browser_languages()
$languages = str_replace(' ', '', $languages);
foreach(explode(',', $languages) as $language_list)
$ret[] .= substr($language_list, 0, 2);
$ret[] = substr($language_list, 0, 2);
return $ret;
}
@@ -798,6 +810,10 @@ function get_templates()
$ret[] = $file;
}
foreach (Plugins::getThemes() as $name => $path) {
$ret[] = $name;
}
return $ret;
}
@@ -1018,7 +1034,7 @@ function load_config_lua($filename)
return $result;
}
function str_replace_first($search, $replace, $subject) {
function str_replace_first($search,$replace, $subject) {
$pos = strpos($subject, $search);
if ($pos !== false) {
return substr_replace($subject, $replace, $pos, strlen($search));
@@ -1052,8 +1068,8 @@ function unsetSession($key) {
unset($_SESSION[setting('core.session_prefix') . $key]);
}
function csrf(): void {
CsrfToken::create();
function csrf(bool $return = false): string {
return CsrfToken::create($return);
}
function csrfToken(): string {
@@ -1062,7 +1078,7 @@ function csrfToken(): string {
function isValidToken(): bool {
$token = $_POST['csrf_token'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? null;
return ($_SERVER['REQUEST_METHOD'] !== 'POST' || (isset($token) && CsrfToken::isValid($token)));
return (!isRequestMethod('post') || (isset($token) && CsrfToken::isValid($token)));
}
function csrfProtect(): void
@@ -1074,20 +1090,16 @@ function csrfProtect(): void
}
}
function getTopPlayers($limit = 5) {
function getTopPlayers($limit = 5, $skill = 'level') {
global $db;
$cache = Cache::getInstance();
if($cache->enabled()) {
$tmp = '';
if($cache->fetch('top_' . $limit . '_level', $tmp)) {
$players = unserialize($tmp);
}
if ($skill === 'level') {
$skill = 'experience';
}
if (!isset($players)) {
return Cache::remember("top_{$limit}_{$skill}", 2 * 60, function () use ($db, $limit, $skill) {
$columns = [
'id', 'name', 'level', 'vocation', 'experience',
'id', 'name', 'level', 'vocation', 'experience', 'balance',
'looktype', 'lookhead', 'lookbody', 'looklegs', 'lookfeet'
];
@@ -1099,32 +1111,27 @@ function getTopPlayers($limit = 5) {
$columns[] = 'online';
}
$players = Player::query()
return Player::query()
->select($columns)
->withOnlineStatus()
->notDeleted()
->where('group_id', '<', setting('core.highscores_groups_hidden'))
->whereNotIn('id', setting('core.highscores_ids_hidden'))
->where('account_id', '!=', 1)
->orderByDesc('experience')
->orderByDesc($skill)
->limit($limit)
->get()
->map(function ($e, $i) {
$row = $e->toArray();
$row['online'] = $e->online_status;
$row['rank'] = $i + 1;
$row['outfit_url'] = $e->outfit_url;
unset($row['online_table']);
return $row;
})->toArray();
if($cache->enabled()) {
$cache->set('top_' . $limit . '_level', serialize($players), 120);
}
}
return $players;
});
}
function deleteDirectory($dir, $ignore = array(), $contentOnly = false) {
@@ -1191,72 +1198,48 @@ function setting($key)
function clearCache()
{
require_once LIBS . 'news.php';
News::clearCache();
$cache = Cache::getInstance();
if($cache->enabled()) {
$tmp = '';
if ($cache->fetch('status', $tmp))
$cache->delete('status');
if ($cache->fetch('templates', $tmp))
$cache->delete('templates');
if ($cache->fetch('config_lua', $tmp))
$cache->delete('config_lua');
if ($cache->fetch('vocations', $tmp))
$cache->delete('vocations');
if ($cache->fetch('towns', $tmp))
$cache->delete('towns');
if ($cache->fetch('groups', $tmp))
$cache->delete('groups');
if ($cache->fetch('visitors', $tmp))
$cache->delete('visitors');
if ($cache->fetch('views_counter', $tmp))
$cache->delete('views_counter');
if ($cache->fetch('failed_logins', $tmp))
$cache->delete('failed_logins');
$keysToClear = [
'status', 'templates',
'config_lua',
'towns', 'groups', 'vocations',
'visitors', 'views_counter', 'failed_logins',
'template_menus',
'last_kills',
'hooks', 'plugins_hooks', 'plugins_routes', 'plugins_settings', 'plugins_themes', 'plugins_commands',
'settings',
];
foreach (get_templates() as $template) {
if ($cache->fetch('template_ini_' . $template, $tmp)) {
$cache->delete('template_ini_' . $template);
$keysToClear[] = 'template_ini_' . $template;
}
// highscores cache
$configHighscoresPerPage = setting('core.highscores_per_page');
$skills = [POT::SKILL_FIST, POT::SKILL_CLUB, POT::SKILL_SWORD, POT::SKILL_AXE, POT::SKILL_DIST, POT::SKILL_SHIELD, POT::SKILL_FISH, POT::SKILL_LEVEL, POT::SKILL__MAGLEVEL, SKILL_FRAGS, SKILL_BALANCE];
foreach ($skills as $skill) {
// config('vocations') may be empty after previous cache clear
$vocations = (config('vocations') ?? []) + ['all'];
foreach ($vocations as $vocation) {
for($page = 0; $page < 10; $page++) {
$cacheKey = 'highscores_' . $skill . '_' . strtolower($vocation) . '_' . $page . '_' . $configHighscoresPerPage;
$keysToClear[] = $cacheKey;
}
}
}
if ($cache->fetch('template_menus', $tmp)) {
$cache->delete('template_menus');
}
if ($cache->fetch('database_tables', $tmp)) {
$cache->delete('database_tables');
}
if ($cache->fetch('database_columns', $tmp)) {
$cache->delete('database_columns');
}
if ($cache->fetch('database_checksum', $tmp)) {
$cache->delete('database_checksum');
}
if ($cache->fetch('last_kills', $tmp)) {
$cache->delete('last_kills');
foreach ($keysToClear as $item) {
$tmp = '';
if ($cache->fetch($item, $tmp)) {
$cache->delete($item);
}
}
if ($cache->fetch('hooks', $tmp)) {
$cache->delete('hooks');
}
if ($cache->fetch('plugins_hooks', $tmp)) {
$cache->delete('plugins_hooks');
}
if ($cache->fetch('plugins_routes', $tmp)) {
$cache->delete('plugins_routes');
}
global $db;
$db->setClearCacheAfter(true);
}
deleteDirectory(CACHE . 'signatures', ['index.html'], true);
@@ -1265,12 +1248,20 @@ function clearCache()
deleteDirectory(CACHE, ['signatures', 'twig', 'plugins', 'index.html', 'persistent'], true);
// routes cache
clearRouteCache();
global $hooks;
$hooks->trigger(HOOK_CACHE_CLEAR, ['cache' => Cache::getInstance()]);
return true;
}
function clearRouteCache(): void
{
$routeCacheFile = CACHE . 'route.cache';
if (file_exists($routeCacheFile)) {
unlink($routeCacheFile);
}
return true;
}
function getCustomPageInfo($name)
@@ -1312,13 +1303,6 @@ function getCustomPage($name, &$success): string
else
$tmp = $page['body'];
$php_errors = array();
function error_handler($errno, $errstr) {
global $php_errors;
$php_errors[] = array('errno' => $errno, 'errstr' => $errstr);
}
set_error_handler('error_handler');
global $config;
if(setting('core.backward_support')) {
global $SQL, $main_content, $subtopic;
@@ -1328,11 +1312,6 @@ function getCustomPage($name, &$success): string
eval($tmp);
$content .= ob_get_contents();
ob_end_clean();
restore_error_handler();
if(isset($php_errors[0]) && superAdmin()) {
var_dump($php_errors);
}
}
else {
$oldLoader = $twig->getLoader();
@@ -1576,18 +1555,19 @@ function right($str, $length) {
return substr($str, -$length);
}
function getCreatureImgPath($creature){
$creature_path = setting('core.monsters_images_url');
$creature_gfx_name = trim(strtolower($creature)) . setting('core.monsters_images_extension');
if (!file_exists($creature_path . $creature_gfx_name)) {
$creature_gfx_name = str_replace(" ", "", $creature_gfx_name);
if (file_exists($creature_path . $creature_gfx_name)) {
return $creature_path . $creature_gfx_name;
function getMonsterImgPath($monster): string
{
$monster_path = setting('core.monsters_images_url');
$monster_gfx_name = trim(strtolower($monster)) . setting('core.monsters_images_extension');
if (!file_exists($monster_path . $monster_gfx_name)) {
$monster_gfx_name = str_replace(" ", "", $monster_gfx_name);
if (file_exists($monster_path . $monster_gfx_name)) {
return $monster_path . $monster_gfx_name;
} else {
return $creature_path . 'nophoto.png';
return $monster_path . 'nophoto.png';
}
} else {
return $creature_path . $creature_gfx_name;
return $monster_path . $monster_gfx_name;
}
}
@@ -1638,7 +1618,7 @@ function removeIfFirstSlash(&$text) {
};
function escapeHtml($html) {
return htmlentities($html, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
return htmlspecialchars($html);
}
function getGuildNameById($id)
@@ -1675,8 +1655,27 @@ function displayErrorBoxWithBackButton($errors, $action = null) {
]);
}
function makeLinksClickable($text, $blank = true) {
return preg_replace('!(((f|ht)tp(s)?://)[-a-zA-Zа-яА-Я()0-9@:%_+.~#?&;//=]+)!i', '<a href="$1"' . (!$blank ?: ' target="_blank"') . '>$1</a>', $text);
}
function isRequestMethod(string $method): bool {
return strtolower($_SERVER['REQUEST_METHOD']) == strtolower($method);
}
function getAccountIdentityColumn(): string
{
if (USE_ACCOUNT_NAME) {
return 'name';
}
elseif (USE_ACCOUNT_NUMBER) {
return 'number';
}
return 'id';
}
// validator functions
require_once LIBS . 'validator.php';
require_once SYSTEM . 'compat/base.php';
// custom functions

View File

@@ -8,16 +8,20 @@
* @link https://my-aac.org
*/
use DebugBar\StandardDebugBar;
use MyAAC\Cache\Cache;
use MyAAC\CsrfToken;
use MyAAC\Hooks;
use MyAAC\Models\Town;
use MyAAC\Settings;
defined('MYAAC') or die('Direct access not allowed!');
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.');
}
use DebugBar\StandardDebugBar;
if(config('env') === 'dev') {
require SYSTEM . 'exception.php';
}
@@ -35,15 +39,15 @@ if($config['server_path'][strlen($config['server_path']) - 1] !== '/')
$config['server_path'] .= '/';
// enable gzip compression if supported by the browser
if(isset($config['gzip_output']) && $config['gzip_output'] && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false && function_exists('ob_gzhandler'))
if(isset($config['gzip_output']) && $config['gzip_output'] && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && str_contains($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') && function_exists('ob_gzhandler'))
ob_start('ob_gzhandler');
// cache
require_once SYSTEM . 'libs/cache.php';
global $cache;
$cache = Cache::getInstance();
// event system
require_once SYSTEM . 'hooks.php';
global $hooks;
$hooks = new Hooks();
$hooks->load();
@@ -54,28 +58,24 @@ require_once SYSTEM . 'twig.php';
$action = $_REQUEST['action'] ?? '';
define('ACTION', $action);
// errors, is also often used
$errors = [];
// trim values we receive
if(isset($_POST))
{
foreach($_POST as $var => $value) {
if(is_string($value)) {
$_POST[$var] = trim($value);
}
foreach($_POST as $var => $value) {
if(is_string($value)) {
$_POST[$var] = trim($value);
}
}
if(isset($_GET))
{
foreach($_GET as $var => $value) {
if(is_string($value))
$_GET[$var] = trim($value);
}
foreach($_GET as $var => $value) {
if(is_string($value))
$_GET[$var] = trim($value);
}
if(isset($_REQUEST))
{
foreach($_REQUEST as $var => $value) {
if(is_string($value))
$_REQUEST[$var] = trim($value);
}
foreach($_REQUEST as $var => $value) {
if(is_string($value))
$_REQUEST[$var] = trim($value);
}
// load otserv config file
@@ -96,8 +96,8 @@ if($config_lua_reload) {
// cache config
if($cache->enabled()) {
$cache->set('config_lua', serialize($config['lua']), 120);
$cache->set('server_path', $config['server_path']);
$cache->set('config_lua', serialize($config['lua']), 2 * 60);
$cache->set('server_path', $config['server_path'], 10 * 60);
}
}
unset($tmp);
@@ -131,18 +131,24 @@ if(!isset($foundValue)) {
$config['data_path'] = $foundValue;
unset($foundValue);
// POT
require_once SYSTEM . 'libs/pot/OTS.php';
$ots = POT::getInstance();
$eloquentConnection = null;
require_once SYSTEM . 'database.php';
// verify myaac tables exists in database
if(!defined('MYAAC_INSTALL') && !$db->hasTable('myaac_account_actions')) {
throw new RuntimeException('Seems that the table myaac_account_actions of MyAAC doesn\'t exist in the database. This is a fatal error. You can try to reinstall MyAAC by visiting ' . BASE_URL . 'install');
}
// execute migrations
require SYSTEM . 'migrate.php';
$configDatabaseAutoMigrate = config('database_auto_migrate');
if (!isset($configDatabaseAutoMigrate) || $configDatabaseAutoMigrate) {
require SYSTEM . 'migrate.php';
}
// settings
require_once LIBS . 'Settings.php';
$settings = Settings::getInstance();
$settings->load();
@@ -155,12 +161,15 @@ if (!isset($token) || !$token) {
// deprecated config values
require_once SYSTEM . 'compat/config.php';
// deprecated classes
require_once SYSTEM . 'compat/classes.php';
date_default_timezone_set(setting('core.date_timezone'));
setting(
[
'core.account_create_character_create',
setting('core.account_create_character_create') && (!setting('core.mail_enabled') || !setting('core.account_mail_verify'))
'core.account_mail_verify',
setting('core.account_mail_verify') && setting('core.mail_enabled')
]
);
@@ -173,5 +182,17 @@ define('USE_ACCOUNT_NAME', $db->hasColumn('accounts', 'name'));
define('USE_ACCOUNT_NUMBER', $db->hasColumn('accounts', 'number'));
define('USE_ACCOUNT_SALT', $db->hasColumn('accounts', 'salt'));
require LIBS . 'Towns.php';
Towns::load();
$towns = Cache::remember('towns', 10 * 60, function () use ($db) {
if ($db->hasTable('towns') && Town::count() > 0) {
return Town::orderBy('id', 'ASC')->pluck('name', 'id')->toArray();
}
return [];
});
if (count($towns) <= 0) {
$towns = setting('core.towns');
}
config(['towns', $towns]);
unset($towns);

View File

@@ -1,3 +0,0 @@
<?php
class SensitiveException extends Exception {}

View File

@@ -1,131 +0,0 @@
<?php
/**
* Project: MyAAC
* Automatic Account Creator for Open Tibia Servers
*
* This is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2020 MyAAC
* @link https://my-aac.org
*/
use MyAAC\Models\Town;
/**
* Class Towns
*/
class Towns
{
/**
* @var string
*/
private static $filename = CACHE . 'persistent/' . 'towns.php';
/**
* Determine towns
*
* @return array
*/
public static function determine()
{
global $db;
if($db->hasTable('towns')) {
return self::getFromDatabase();
}
return self::getFromOTBM();
}
/**
* Load cached towns file
*/
public static function load()
{
$towns = config('towns');
if (file_exists(self::$filename)) {
$towns = require self::$filename;
}
config(['towns', $towns]);
}
/**
* Save into cache file
*
* @return bool
*/
public static function save()
{
$towns = self::determine();
if (count($towns) > 0) {
file_put_contents(self::$filename, '<?php return ' . var_export($towns, true) . ';', LOCK_EX);
return true;
}
return false;
}
/**
* Load from OTBM map file
*
* @return array
*/
public static function getFromOTBM()
{
$mapName = configLua('mapName');
if (!isset($mapName)) {
$mapName = configLua('map');
$mapFile = config('server_path') . $mapName;
}
if (strpos($mapName, '.otbm') === false) {
$mapName .= '.otbm';
}
if (!isset($mapFile)) {
$mapFile = config('data_path') . 'world/' . $mapName;
}
if (strpos($mapFile, '.gz') !== false) {
$mapFile = str_replace('.gz', '', $mapFile);
}
$towns = [];
if (file_exists($mapFile)) {
ini_set('memory_limit', '-1');
require LIBS . 'TownsReader.php';
$townsReader = new TownsReader($mapFile);
$townsReader->load();
$towns = $townsReader->get();
}
return $towns;
}
/**
* Load from database
*
* @return array
*/
public static function getFromDatabase()
{
return Town::pluck('name', 'id')->toArray();
}
}

View File

@@ -1,82 +0,0 @@
<?php
/*
This file is part of OTSCMS (http://www.otscms.com/) project.
Copyright (C) 2005 - 2007 Wrzasq (wrzasq@gmail.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
This code bases on oryginal OTServ code for .otbm files - file iomapotbm.cpp rev.2141
*/
class TownsReader
{
// node bytes
const ESCAPE_CHAR = 0xFD;
const NODE_START = 0xFE;
// map node types
const OTBM_TOWN = 13;
// file handler
protected $file;
// towns
private $towns = [];
// loads map .otbm file
public function __construct($file)
{
// opens file for reading
$this->file = fopen($file, 'rb');
}
public function load()
{
// checks if file is opened correctly
if ($this->file) {
// skips version
fseek($this->file, 4);
// reads nodes chain
while (!feof($this->file)) {
// reads byte
switch (ord(fgetc($this->file))) {
// maybe a town node
case self::NODE_START:
// reads node type
if (ord(fgetc($this->file)) == self::OTBM_TOWN) {
$id = unpack('L', fread($this->file, 4));
$length = unpack('S', fread($this->file, 2));
// reads town name
$this->towns[$id[1]] = fread($this->file, $length[1]);
}
break;
// escape next character - it might be NODE_START character which is in fact not
case self::ESCAPE_CHAR:
fgetc($this->file);
break;
}
}
}
}
public function get() {
return $this->towns;
}
}

View File

@@ -1,51 +0,0 @@
<?php
/**
* Cache eAccelerator class
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @author Mark Samman (Talaturen) <marksamman@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
class Cache_eAccelerator
{
private $prefix;
private $enabled;
public function __construct($prefix = '') {
$this->prefix = $prefix;
$this->enabled = function_exists('eaccelerator_get');
}
public function set($key, $var, $ttl = 0)
{
$key = $this->prefix . $key;
eaccelerator_rm($key);
eaccelerator_put($key, $var, $ttl);
}
public function get($key)
{
$tmp = '';
if($this->fetch($this->prefix . $key, $tmp)) {
return $tmp;
}
return '';
}
public function fetch($key, &$var) {
return ($var = eaccelerator_get($this->prefix . $key)) !== null;
}
public function delete($key) {
eaccelerator_rm($this->prefix . $key);
}
public function enabled() {
return $this->enabled;
}
}

View File

@@ -83,38 +83,4 @@ abstract class OTS_Base_DAO implements IOTS_DAO
{
unset($this->data['id']);
}
/**
* Magic PHP5 method.
*
* <p>
* Allows object importing from {@link http://www.php.net/manual/en/function.var-export.php var_export()}.
* </p>
*
* @version 0.1.0
* @param array $properties List of object properties.
*/
public static function __set_state($properties)
{
// deletes database handle
if( isset($properties['db']) )
{
unset($properties['db']);
}
// initializes new object with current database connection
$object = new self();
// loads properties
foreach($properties as $name => $value)
{
$object->$name = $value;
}
return $object;
}
}
/**#@-*/
?>

View File

@@ -184,8 +184,14 @@ abstract class OTS_Base_DB extends PDO implements IOTS_DB
$query = 'UPDATE '.$this->tableName($table).' SET ';
$count = count($fields);
for ($i = 0; $i < $count; $i++)
$query.= $this->fieldName($fields[$i]).' = '.$this->quote($values[$i]).', ';
for ($i = 0; $i < $count; $i++) {
$value = 'NULL';
if ($values[$i] !== null) {
$value = $this->quote($values[$i]);
}
$query.= $this->fieldName($fields[$i]).' = '.$value.', ';
}
$query = substr($query, 0, -2);
$query.=' WHERE (';
@@ -229,6 +235,30 @@ abstract class OTS_Base_DB extends PDO implements IOTS_DB
$this->exec($query);
return true;
}
public function addColumn($table, $column, $definition): void {
$this->exec('ALTER TABLE ' . $this->tableName($table) . ' ADD ' . $this->fieldName($column) . ' ' . $definition . ';');
}
public function modifyColumn($table, $column, $definition): void {
$this->exec('ALTER TABLE ' . $this->tableName($table) . ' MODIFY ' . $this->fieldName($column) . ' ' . $definition . ';');
}
public function changeColumn($table, $from, $to, $definition): void {
$this->exec('ALTER TABLE ' . $this->tableName($table) . ' CHANGE ' . $this->fieldName($from) . ' ' . $this->fieldName($to) . ' ' . $definition . ';');
}
public function dropColumn($table, $column): void {
$this->exec('ALTER TABLE ' . $this->tableName($table) . ' DROP COLUMN ' . $this->fieldName($column) . ';');
}
public function renameTable($from, $to): void {
$this->exec('RENAME TABLE ' . $this->tableName($from) . ' TO ' . $this->tableName($to) . ';');
}
public function dropTable($table, $ifExists = true): void {
$this->exec('DROP TABLE ' . ($ifExists ? 'IF EXISTS' : '') . ' ' . $this->tableName($table) . ';');
}
/**
* LIMIT/OFFSET clause for queries.
*

View File

@@ -42,24 +42,24 @@ class OTS_Buffer
*
* @var string
*/
protected $buffer;
protected $buffer;
/**
* Properties stream pointer.
*
* @var int
*/
protected $pos;
protected $pos;
/**
* Initializes new buffered reader.
*
* @param string $buffer Buffer content.
*/
public function __construct($buffer = '')
{
$this->buffer = $buffer;
$this->pos = 0;
}
public function __construct($buffer = '')
{
$this->buffer = $buffer;
$this->pos = 0;
}
/**
* Magic PHP5 method.
@@ -70,49 +70,49 @@ class OTS_Buffer
*
* @param array $properties List of object properties.
*/
public static function __set_state($properties)
{
$object = new self();
public static function __set_state($properties)
{
$object = new self();
// loads properties
foreach($properties as $name => $value)
{
$object->$name = $value;
}
// loads properties
foreach($properties as $name => $value)
{
$object->$name = $value;
}
return $object;
}
return $object;
}
/**
* Returs properties stream.
*
* @return string Properties stream.
*/
public function getBuffer()
{
return $this->buffer;
}
public function getBuffer()
{
return $this->buffer;
}
/**
* Sets properties stream.
*
* @param string Properties stream.
*/
public function setBuffer($buffer)
{
$this->buffer = $buffer;
$this->pos = 0;
}
public function setBuffer($buffer)
{
$this->buffer = $buffer;
$this->pos = 0;
}
/**
* Checks if there is anything left in stream.
*
* @return bool False if pointer is at the end of stream.
*/
public function isValid()
{
return $this->pos < strlen($this->buffer);
}
public function isValid()
{
return $this->pos < strlen($this->buffer);
}
/**
* Checks stream end state.
@@ -120,13 +120,13 @@ class OTS_Buffer
* @param int $size Amount of bytes that are going to be read.
* @throws E_OTS_OutOfBuffer When there is read attemp after end of stream.
*/
protected function check($size = 1)
{
if( strlen($this->buffer) < $this->pos + $size)
{
throw new E_OTS_OutOfBuffer();
}
}
protected function check($size = 1)
{
if( strlen($this->buffer) < $this->pos + $size)
{
throw new E_OTS_OutOfBuffer();
}
}
/**
* Returns single byte.
@@ -134,25 +134,25 @@ class OTS_Buffer
* @return int Byte (char) value.
* @throws E_OTS_OutOfBuffer When there is read attemp after end of stream.
*/
public function getChar()
{
// checks buffer size
$this->check();
public function getChar()
{
// checks buffer size
$this->check();
$value = ord($this->buffer[$this->pos]);
$this->pos++;
return $value;
}
$value = ord($this->buffer[$this->pos]);
$this->pos++;
return $value;
}
/**
* Appends single byte to buffer.
*
* @param int $char Byte (char) value.
*/
public function putChar($char)
{
$this->buffer .= chr($char);
}
public function putChar($char)
{
$this->buffer .= chr($char);
}
/**
* Returns double byte.
@@ -160,25 +160,25 @@ class OTS_Buffer
* @return int Word (short) value.
* @throws E_OTS_OutOfBuffer When there is read attemp after end of stream.
*/
public function getShort()
{
// checks buffer size
$this->check(2);
public function getShort()
{
// checks buffer size
$this->check(2);
$value = unpack('v', substr($this->buffer, $this->pos, 2) );
$this->pos += 2;
return $value[1];
}
$value = unpack('v', substr($this->buffer, $this->pos, 2) );
$this->pos += 2;
return $value[1];
}
/**
* Appends double byte to buffer.
*
* @param int $short Word (short) value.
*/
public function putShort($short)
{
$this->buffer .= pack('v', $short);
}
public function putShort($short)
{
$this->buffer .= pack('v', $short);
}
/**
* Returns quater byte.
@@ -186,25 +186,35 @@ class OTS_Buffer
* @return int Double word (long) value.
* @throws E_OTS_OutOfBuffer When there is read attemp after end of stream.
*/
public function getLong()
{
// checks buffer size
$this->check(4);
public function getLong()
{
// checks buffer size
$this->check(4);
$value = unpack('V', substr($this->buffer, $this->pos, 4) );
$this->pos += 4;
return $value[1];
}
$value = unpack('V', substr($this->buffer, $this->pos, 4) );
$this->pos += 4;
return $value[1];
}
public function getLongLong()
{
// checks buffer size
$this->check(8);
$value = unpack('P', substr($this->buffer, $this->pos, 8) );
$this->pos += 8;
return $value[1];
}
/**
* Appends quater byte to buffer.
*
* @param int $long Double word (long) value.
*/
public function putLong($long)
{
$this->buffer .= pack('V', $long);
}
public function putLong($long)
{
$this->buffer .= pack('V', $long);
}
/**
* Returns string from buffer.
@@ -217,22 +227,22 @@ class OTS_Buffer
* @return string First substring.
* @throws E_OTS_OutOfBuffer When there is read attemp after end of stream.
*/
public function getString($length = false)
{
// reads string length if not given
if($length === false)
{
$length = $this->getShort();
}
public function getString($length = false)
{
// reads string length if not given
if($length === false)
{
$length = $this->getShort();
}
// checks buffer size
$this->check($length);
// checks buffer size
$this->check($length);
// copies substring
$value = substr($this->buffer, $this->pos, $length);
$this->pos += $length;
return $value;
}
// copies substring
$value = substr($this->buffer, $this->pos, $length);
$this->pos += $length;
return $value;
}
/**
* Appends string to buffer.
@@ -240,54 +250,54 @@ class OTS_Buffer
* @param string $string Binary length.
* @param bool $dynamic Whether if string length is fixed or not (if it is dynamic then length will be inserted as short before string chunk).
*/
public function putString($string, $dynamic = true)
{
// appends string length if requires
if($dynamic)
{
$this->putShort( strlen($string) );
}
public function putString($string, $dynamic = true)
{
// appends string length if requires
if($dynamic)
{
$this->putShort( strlen($string) );
}
$this->buffer .= $string;
}
$this->buffer .= $string;
}
/**
* Empties buffer.
*/
public function reset()
{
$this->__construct();
}
public function reset()
{
$this->__construct();
}
/**
* Returns current read position.
*
* @return int Read position.
*/
public function getPos()
{
return $this->pos;
}
public function getPos()
{
return $this->pos;
}
/**
* Seeks current reading position.
*
* @param int $pos Read position.
*/
public function setPos($pos)
{
$this->pos = $pos;
}
public function setPos($pos)
{
$this->pos = $pos;
}
/**
* Returns buffer size.
*
* @return int Buffer length.
*/
public function getSize()
{
return strlen($this->buffer);
}
public function getSize()
{
return strlen($this->buffer);
}
/**
* Skips given amount of bytes.
@@ -295,11 +305,11 @@ class OTS_Buffer
* @param int $n Bytes to skip.
* @throws E_OTS_OutOfBuffer When there is read attemp after end of stream.
*/
public function skip($n)
{
$this->check($n);
$this->pos += $n;
}
public function skip($n)
{
$this->check($n);
$this->pos += $n;
}
/**
* Magic PHP5 method.
@@ -309,46 +319,46 @@ class OTS_Buffer
* @throws OutOfBoundsException For non-supported properties.
* @throws E_OTS_OutOfBuffer When there is read attemp after end of stream.
*/
public function __get($name)
{
switch($name)
{
// simple properties
case 'buffer':
return $this->buffer;
public function __get($name)
{
switch($name)
{
// simple properties
case 'buffer':
return $this->buffer;
// isValid() wrapper
case 'valid':
return $this->isValid();
// isValid() wrapper
case 'valid':
return $this->isValid();
// getChar() wrapper
case 'char':
return $this->getChar();
// getChar() wrapper
case 'char':
return $this->getChar();
// getShort() wrapper
case 'short':
return $this->getShort();
// getShort() wrapper
case 'short':
return $this->getShort();
// getLong() wrapper
case 'long':
return $this->getLong();
// getLong() wrapper
case 'long':
return $this->getLong();
// getString() wrapper
case 'string':
return $this->getString();
// getString() wrapper
case 'string':
return $this->getString();
// getPos() wrapper
case 'pos':
return $this->getPos();
// getPos() wrapper
case 'pos':
return $this->getPos();
// getSize() wrapper
case 'size':
return $this->getSize();
// getSize() wrapper
case 'size':
return $this->getSize();
default:
throw new OutOfBoundsException();
}
}
default:
throw new OutOfBoundsException();
}
}
/**
* Magic PHP5 method.
@@ -358,62 +368,62 @@ class OTS_Buffer
* @param mixed $value Property value.
* @throws OutOfBoundsException For non-supported properties.
*/
public function __set($name, $value)
{
switch($name)
{
// buffer needs to be reset
case 'buffer':
$this->setBuffer($value);
break;
public function __set($name, $value)
{
switch($name)
{
// buffer needs to be reset
case 'buffer':
$this->setBuffer($value);
break;
// putChar() wrapper
case 'char':
$this->putChar($value);
break;
// putChar() wrapper
case 'char':
$this->putChar($value);
break;
// putShort() wrapper
case 'short':
$this->putShort($value);
break;
// putShort() wrapper
case 'short':
$this->putShort($value);
break;
// putLong() wrapper
case 'long':
$this->putLong($value);
break;
// putLong() wrapper
case 'long':
$this->putLong($value);
break;
// putString() wrapper
case 'string':
$this->putString($value);
break;
// putString() wrapper
case 'string':
$this->putString($value);
break;
// setPos() wrapper
case 'pos':
$this->setPos($value);
break;
// setPos() wrapper
case 'pos':
$this->setPos($value);
break;
default:
throw new OutOfBoundsException();
}
}
default:
throw new OutOfBoundsException();
}
}
/**
* Returns string representation of buffer object.
*
* @return string Object's buffer.
*/
public function __toString()
{
return $this->buffer;
}
public function __toString()
{
return $this->buffer;
}
/**
* Resets pointer of cloned object.
*/
public function __clone()
{
$this->pos = 0;
}
public function __clone()
{
$this->pos = 0;
}
}
/**#@-*/

View File

@@ -12,6 +12,8 @@
* @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU Lesser General Public License, Version 3
*/
use MyAAC\Cache\Cache;
/**
* MySQL connection interface.
*
@@ -26,6 +28,8 @@ class OTS_DB_MySQL extends OTS_Base_DB
{
private $has_table_cache = array();
private $has_column_cache = array();
private $clearCacheAfter = false;
/**
* Creates database connection.
*
@@ -49,52 +53,53 @@ class OTS_DB_MySQL extends OTS_Base_DB
* @param array $params Connection parameters.
* @throws PDOException On PDO operation error.
*/
public function __construct($params)
{
$user = null;
$password = null;
$dns = array();
public function __construct($params)
{
$user = null;
$password = null;
$dns = array();
// host:port support
if( strpos(':', $params['host']) !== false)
{
$host = explode(':', $params['host'], 2);
// host:port support
if( strpos(':', $params['host']) !== false)
{
$host = explode(':', $params['host'], 2);
$params['host'] = $host[0];
$params['port'] = $host[1];
}
$params['host'] = $host[0];
$params['port'] = $host[1];
}
if( isset($params['database']) )
{
$dns[] = 'dbname=' . $params['database'];
}
if( isset($params['database']) )
{
$dns[] = 'dbname=' . $params['database'];
}
if( isset($params['user']) )
{
$user = $params['user'];
}
if( isset($params['user']) )
{
$user = $params['user'];
}
if( isset($params['password']) )
{
$password = $params['password'];
}
if( isset($params['password']) )
{
$password = $params['password'];
}
if( isset($params['prefix']) )
{
$this->prefix = $params['prefix'];
}
if( isset($params['prefix']) )
{
$this->prefix = $params['prefix'];
}
if( isset($params['log']) && $params['log'] )
{
$this->logged = true;
}
if( isset($params['log']) && $params['log'] )
{
$this->logged = true;
}
if( !isset($params['persistent']) ) {
$params['persistent'] = false;
}
if( !isset($params['persistent']) ) {
$params['persistent'] = false;
}
global $config;
if(class_exists('Cache') && ($cache = Cache::getInstance()) && $cache->enabled()) {
$cache = Cache::getInstance();
if($cache->enabled()) {
$tmp = null;
$need_revalidation = true;
if($cache->fetch('database_checksum', $tmp) && $tmp) {
@@ -139,20 +144,29 @@ class OTS_DB_MySQL extends OTS_Base_DB
}
parent::__construct('mysql:' . implode(';', $dns), $user, $password, $driverAttributes);
}
}
public function __destruct()
{
{
global $config;
if(class_exists('Cache') && ($cache = Cache::getInstance()) && $cache->enabled()) {
$cache->set('database_tables', serialize($this->has_table_cache), 3600);
$cache->set('database_columns', serialize($this->has_column_cache), 3600);
$cache->set('database_checksum', serialize(sha1($config['database_host'] . '.' . $config['database_name'])), 3600);
$cache = Cache::getInstance();
if($cache->enabled()) {
if ($this->clearCacheAfter) {
$cache->delete('database_tables');
$cache->delete('database_columns');
$cache->delete('database_checksum');
}
else {
$cache->set('database_tables', serialize($this->has_table_cache), 3600);
$cache->set('database_columns', serialize($this->has_column_cache), 3600);
$cache->set('database_checksum', serialize(sha1($config['database_host'] . '.' . $config['database_name'])), 3600);
}
}
if($this->logged) {
log_append('database.log', $_SERVER['REQUEST_URI'] . PHP_EOL . $this->getLog());
$currentScript = $_SERVER['REQUEST_URI'] ?? $_SERVER['SCRIPT_FILENAME'];
log_append('database.log', $currentScript . PHP_EOL . $this->getLog());
}
}
@@ -162,10 +176,10 @@ class OTS_DB_MySQL extends OTS_Base_DB
* @param string $name Field name.
* @return string Quoted name.
*/
public function fieldName($name)
{
return '`' . $name . '`';
}
public function fieldName($name)
{
return '`' . $name . '`';
}
/**
* LIMIT/OFFSET clause for queries.
@@ -174,26 +188,26 @@ class OTS_DB_MySQL extends OTS_Base_DB
* @param int|bool $offset Number of rows to be skipped before applying query effects (false if no offset).
* @return string LIMIT/OFFSET SQL clause for query.
*/
public function limit($limit = false, $offset = false)
{
// by default this is empty part
$sql = '';
public function limit($limit = false, $offset = false)
{
// by default this is empty part
$sql = '';
if($limit !== false)
{
$sql = ' LIMIT ';
if($limit !== false)
{
$sql = ' LIMIT ';
// OFFSET has no effect if there is no LIMIT
if($offset !== false)
{
$sql .= $offset . ', ';
}
// OFFSET has no effect if there is no LIMIT
if($offset !== false)
{
$sql .= $offset . ', ';
}
$sql .= $limit;
}
$sql .= $limit;
}
return $sql;
}
return $sql;
}
public function hasTable($name) {
if(isset($this->has_table_cache[$name])) {
@@ -236,6 +250,11 @@ class OTS_DB_MySQL extends OTS_Base_DB
}
}
}
public function setClearCacheAfter($clearCache)
{
$this->clearCacheAfter = $clearCache;
}
}
/**#@-*/

View File

@@ -8,6 +8,8 @@
* @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU Lesser General Public License, Version 3
*/
use MyAAC\Cache\Cache;
/**
* List of groups.
*

View File

@@ -60,12 +60,7 @@ class OTS_House extends OTS_Row_DAO
private $tiles = array();
public function load($id) {
$this->data = $this->db->query('SELECT * FROM `houses` WHERE `id` = ' . $id )->fetch();
foreach($this->data as $key => $value) {
if(is_numeric($key)) {
unset($this->data[$key]);
}
}
$this->data = $this->db->query('SELECT * FROM `houses` WHERE `id` = ' . $id )->fetch(PDO::FETCH_ASSOC);
}
public function find($name)

View File

@@ -41,9 +41,10 @@
class OTS_Monster extends DOMDocument
{
private $loaded = false;
public function loadXML($source , $options = 0)
public function loadXML(string $source , int $options = 0): bool
{
$this->loaded = parent::loadXML($source, $options);
return $this->loaded;
}
public function loaded()
@@ -56,10 +57,10 @@ class OTS_Monster extends DOMDocument
* @return string Name.
* @throws DOMException On DOM operation error.
*/
public function getName()
{
return $this->documentElement->getAttribute('name');
}
public function getName()
{
return $this->documentElement->getAttribute('name');
}
/**
* Returns monster race.
@@ -67,10 +68,10 @@ class OTS_Monster extends DOMDocument
* @return string Race.
* @throws DOMException On DOM operation error.
*/
public function getRace()
{
return $this->documentElement->getAttribute('race');
}
public function getRace()
{
return $this->documentElement->getAttribute('race');
}
/**
* Returns amount of experience for killing this monster.
@@ -78,10 +79,10 @@ class OTS_Monster extends DOMDocument
* @return int Experience points.
* @throws DOMException On DOM operation error.
*/
public function getExperience()
{
return (int) $this->documentElement->getAttribute('experience');
}
public function getExperience()
{
return (int) $this->documentElement->getAttribute('experience');
}
/**
* Returns monster speed.
@@ -89,10 +90,10 @@ class OTS_Monster extends DOMDocument
* @return int Speed.
* @throws DOMException On DOM operation error.
*/
public function getSpeed()
{
return (int) $this->documentElement->getAttribute('speed');
}
public function getSpeed()
{
return (int) $this->documentElement->getAttribute('speed');
}
/**
* Returns amount of mana required to summon this monster.
@@ -100,18 +101,18 @@ class OTS_Monster extends DOMDocument
* @return int|bool Mana required (false if not possible).
* @throws DOMException On DOM operation error.
*/
public function getManaCost()
{
// check if it is possible to summon this monster
if( $this->documentElement->hasAttribute('manacost') )
{
return (int) $this->documentElement->getAttribute('manacost');
}
else
{
return false;
}
}
public function getManaCost()
{
// check if it is possible to summon this monster
if( $this->documentElement->hasAttribute('manacost') )
{
return (int) $this->documentElement->getAttribute('manacost');
}
else
{
return false;
}
}
/**
* Returns monster HP.
@@ -119,10 +120,10 @@ class OTS_Monster extends DOMDocument
* @return int Hit points.
* @throws DOMException On DOM operation error.
*/
public function getHealth()
{
return (int) $this->documentElement->getElementsByTagName('health')->item(0)->getAttribute('max');
}
public function getHealth()
{
return (int) $this->documentElement->getElementsByTagName('health')->item(0)->getAttribute('max');
}
/**
* Returns all monster flags (in format flagname => value).
@@ -130,20 +131,21 @@ class OTS_Monster extends DOMDocument
* @return array Flags.
* @throws DOMException On DOM operation error.
*/
public function getFlags()
{
$flags = array();
public function getFlags()
{
$flags = array();
// read all flags
foreach( $this->documentElement->getElementsByTagName('flags')->item(0)->getElementsByTagName('flag') as $flag)
{
$flag = $flag->attributes->item(0);
if ($this->documentElement->getElementsByTagName('flags')->item(0)) {
foreach( $this->documentElement->getElementsByTagName('flags')->item(0)->getElementsByTagName('flag') as $flag)
{
$flag = $flag->attributes->item(0);
$flags[$flag->nodeName] = (int) $flag->nodeValue;
}
$flags[$flag->nodeName] = (int) $flag->nodeValue;
}
}
return $flags;
}
return $flags;
}
/**
* Returns specified flag value.
@@ -152,21 +154,21 @@ class OTS_Monster extends DOMDocument
* @return int|bool Flag value (false if not set).
* @throws DOMException On DOM operation error.
*/
public function getFlag($flag)
{
// searches for flag
foreach( $this->documentElement->getElementsByTagName('flags')->item(0)->getElementsByTagName('flag') as $flag)
{
// found
if( $flag->hasAttribute($flag) )
{
return (int) $flag->getAttribute($flag);
}
}
public function getFlag($flag)
{
// searches for flag
foreach( $this->documentElement->getElementsByTagName('flags')->item(0)->getElementsByTagName('flag') as $flag)
{
// found
if( $flag->hasAttribute($flag) )
{
return (int) $flag->getAttribute($flag);
}
}
// not found
return false;
}
// not found
return false;
}
/**
* Returns voices that monster can sound.
@@ -174,64 +176,64 @@ class OTS_Monster extends DOMDocument
* @return array List of voices.
* @throws DOMException On DOM operation error.
*/
public function getVoices()
{
$voices = array();
public function getVoices()
{
$voices = array();
$element = $this->documentElement->getElementsByTagName('voices')->item(0);
$element = $this->documentElement->getElementsByTagName('voices')->item(0);
// checks if it has any voices
if( isset($element) )
{
// loads all voices
foreach( $element->getElementsByTagName('voice') as $voice)
{
$voices[] = $voice->getAttribute('sentence');
}
}
// checks if it has any voices
if( isset($element) )
{
// loads all voices
foreach( $element->getElementsByTagName('voice') as $voice)
{
$voices[] = $voice->getAttribute('sentence');
}
}
return $voices;
}
return $voices;
}
/**
* @return array List of item IDs.
*/
public function getLoot()
{
$loot = array();
public function getLoot()
{
$loot = array();
$element = $this->documentElement->getElementsByTagName('loot')->item(0);
$element = $this->documentElement->getElementsByTagName('loot')->item(0);
// checks if it has any loot
if( isset($element) )
{
// adds all items
foreach( $element->getElementsByTagName('item') as $item)
{
$chance = $item->getAttribute('chance');
if(empty($chance)) {
$chance = $item->getAttribute('chance1');
if(empty($chance)) {
$chance = 100000;
}
}
// checks if it has any loot
if( isset($element) )
{
// adds all items
foreach( $element->getElementsByTagName('item') as $item)
{
$chance = $item->getAttribute('chance');
if(empty($chance)) {
$chance = $item->getAttribute('chance1');
if(empty($chance)) {
$chance = 100000;
}
}
$count = $item->getAttribute('countmax');
if(empty($count)) {
$count = 1;
}
$count = $item->getAttribute('countmax');
if(empty($count)) {
$count = 1;
}
$id = $item->getAttribute('id');
if(empty($id)) {
$id = $item->getAttribute('name');
}
$id = $item->getAttribute('id');
if(empty($id)) {
$id = $item->getAttribute('name');
}
$loot[] = array('id' => $id, 'count' => $count, 'chance' => $chance);
}
}
$loot[] = array('id' => $id, 'count' => $count, 'chance' => $chance);
}
}
return $loot;
}
return $loot;
}
/**
* Returns all possible loot.
@@ -246,33 +248,33 @@ class OTS_Monster extends DOMDocument
* @throws E_OTS_NotLoaded When there is no items list available in global POT instance.
* @throws DOMException On DOM operation error.
*/
public function getItems()
{
$loot = array();
$keys = array();
$items = POT::getInstance()->getItemsList();
public function getItems()
{
$loot = array();
$keys = array();
$items = POT::getInstance()->getItemsList();
$element = $this->documentElement->getElementsByTagName('loot')->item(0);
$element = $this->documentElement->getElementsByTagName('loot')->item(0);
// checks if it has any loot
if( isset($element) )
{
// adds all items
foreach( $element->getElementsByTagName('item') as $item)
{
$id = $item->getAttribute('id');
// checks if it has any loot
if( isset($element) )
{
// adds all items
foreach( $element->getElementsByTagName('item') as $item)
{
$id = $item->getAttribute('id');
// avoid redundancy
if( !in_array($id, $keys) )
{
$keys[] = $id;
$loot[] = $items->getItemType($id);
}
}
}
// avoid redundancy
if( !in_array($id, $keys) )
{
$keys[] = $id;
$loot[] = $items->getItemType($id);
}
}
}
return $loot;
}
return $loot;
}
/**
* Returns look of the monster.
@@ -280,27 +282,27 @@ class OTS_Monster extends DOMDocument
* @return array Look with all the attributes of the look.
* @throws DOMException On DOM operation error.
*/
public function getLook()
{
$look = array();
public function getLook()
{
$look = array();
$element = $this->documentElement->getElementsByTagName('look')->item(0);
$element = $this->documentElement->getElementsByTagName('look')->item(0);
if (!$element) {
return $look;
}
if (!$element) {
return $look;
}
$look['type'] = $element->getAttribute('type');
$look['typeex'] = $element->getAttribute('typeex');
$look['head'] = $element->getAttribute('head');
$look['body'] = $element->getAttribute('body');
$look['legs'] = $element->getAttribute('legs');
$look['feet'] = $element->getAttribute('feet');
$look['addons'] = $element->getAttribute('addons');
$look['corpse'] = $element->getAttribute('corpse');
$look['type'] = $element->getAttribute('type');
$look['typeex'] = $element->getAttribute('typeex');
$look['head'] = $element->getAttribute('head');
$look['body'] = $element->getAttribute('body');
$look['legs'] = $element->getAttribute('legs');
$look['feet'] = $element->getAttribute('feet');
$look['addons'] = $element->getAttribute('addons');
$look['corpse'] = $element->getAttribute('corpse');
return $look;
}
return $look;
}
/**
* Returns all monster summons.
@@ -310,24 +312,24 @@ class OTS_Monster extends DOMDocument
*/
public function getSummons()
{
$summons = array();
{
$summons = array();
$element = $this->documentElement->getElementsByTagName('summons')->item(0);
$element = $this->documentElement->getElementsByTagName('summons')->item(0);
// checks if it has any Summons
if( isset($element) )
{
// adds all summons
foreach( $element->getElementsByTagName('summon') as $item)
{
$chance = $item->getAttribute('chance');
$id = $item->getAttribute('name');
$summons[] = array('name' => $id, 'chance' => $chance);
}
}
return $summons;
}
// checks if it has any Summons
if( isset($element) )
{
// adds all summons
foreach( $element->getElementsByTagName('summon') as $item)
{
$chance = $item->getAttribute('chance');
$id = $item->getAttribute('name');
$summons[] = array('name' => $id, 'chance' => $chance);
}
}
return $summons;
}
/**
* Returns all monster elements.
@@ -335,30 +337,30 @@ class OTS_Monster extends DOMDocument
* @return array elements.
* @throws DOMException On DOM operation error.
*/
public function getElements()
{
$elements = array();
public function getElements()
{
$elements = array();
$element = $this->documentElement->getElementsByTagName('elements')->item(0);
$element = $this->documentElement->getElementsByTagName('elements')->item(0);
// checks if it has any elements
if( isset($element) )
{
// read all elements
foreach( $element->getElementsByTagName('element') as $elementv)
{
$elementv = $elementv->attributes->item(0);
// checks if it has any elements
if( isset($element) )
{
// read all elements
foreach( $element->getElementsByTagName('element') as $elementv)
{
$elementv = $elementv->attributes->item(0);
// checks if element is set
if($elementv->nodeValue > 0)
{
// checks if element is set
if($elementv->nodeValue > 0)
{
$elements[] = array('name' => ucfirst(str_replace('Percent', '', $elementv->nodeName)), 'percent' => $elementv->nodeValue);
}
}
}
}
}
}
return $elements;
}
return $elements;
}
/**
* Checks if monster has given element.
@@ -367,26 +369,26 @@ class OTS_Monster extends DOMDocument
* @return bool element state.
* @throws DOMException On DOM operation error.
*/
public function hasElement($name)
{
$element = $this->documentElement->getElementsByTagName('elements')->item(0);
public function hasElement($name)
{
$element = $this->documentElement->getElementsByTagName('elements')->item(0);
// if doesn't have any elements obviously doesn't have this one too
if( isset($element) )
{
// read all elements
foreach( $element->getElementsByTagName('element') as $element)
{
// checks if this is what we are searching for
if( $element->hasAttribute($name) )
{
return $element->getAttribute($name) > 0;
}
}
}
// if doesn't have any elements obviously doesn't have this one too
if( isset($element) )
{
// read all elements
foreach( $element->getElementsByTagName('element') as $element)
{
// checks if this is what we are searching for
if( $element->hasAttribute($name) )
{
return $element->getAttribute($name) > 0;
}
}
}
return false;
}
return false;
}
/**
* Returns all monster immunities.
@@ -394,30 +396,30 @@ class OTS_Monster extends DOMDocument
* @return array Immunities.
* @throws DOMException On DOM operation error.
*/
public function getImmunities()
{
$immunities = array();
public function getImmunities()
{
$immunities = array();
$element = $this->documentElement->getElementsByTagName('immunities')->item(0);
$element = $this->documentElement->getElementsByTagName('immunities')->item(0);
// checks if it has any immunities
if( isset($element) )
{
// read all immunities
foreach( $element->getElementsByTagName('immunity') as $immunity)
{
$immunity = $immunity->attributes->item(0);
// checks if it has any immunities
if( isset($element) )
{
// read all immunities
foreach( $element->getElementsByTagName('immunity') as $immunity)
{
$immunity = $immunity->attributes->item(0);
// checks if immunity is set
if($immunity->nodeValue > 0)
{
$immunities[] = $immunity->nodeName;
}
}
}
// checks if immunity is set
if($immunity->nodeValue > 0)
{
$immunities[] = $immunity->nodeName;
}
}
}
return $immunities;
}
return $immunities;
}
/**
* Checks if monster has given immunity.
@@ -426,26 +428,26 @@ class OTS_Monster extends DOMDocument
* @return bool Immunity state.
* @throws DOMException On DOM operation error.
*/
public function hasImmunity($name)
{
$element = $this->documentElement->getElementsByTagName('immunities')->item(0);
public function hasImmunity($name)
{
$element = $this->documentElement->getElementsByTagName('immunities')->item(0);
// if doesn't have any immunities obviously doesn't have this one too
if( isset($element) )
{
// read all immunities
foreach( $element->getElementsByTagName('immunity') as $immunity)
{
// checks if this is what we are searching for
if( $immunity->hasAttribute($name) )
{
return $immunity->getAttribute($name) > 0;
}
}
}
// if doesn't have any immunities obviously doesn't have this one too
if( isset($element) )
{
// read all immunities
foreach( $element->getElementsByTagName('immunity') as $immunity)
{
// checks if this is what we are searching for
if( $immunity->hasAttribute($name) )
{
return $immunity->getAttribute($name) > 0;
}
}
}
return false;
}
return false;
}
/**
* Returns monster defense rate.
@@ -453,18 +455,18 @@ class OTS_Monster extends DOMDocument
* @return int Defense rate.
* @throws DOMException On DOM operation error.
*/
public function getDefense()
{
$element = $this->documentElement->getElementsByTagName('defenses')->item(0);
public function getDefense()
{
$element = $this->documentElement->getElementsByTagName('defenses')->item(0);
// checks if defenses element is set
if( isset($element) )
{
return (int) $element->getAttribute('defense');
}
// checks if defenses element is set
if( isset($element) )
{
return (int) $element->getAttribute('defense');
}
return 0;
}
return 0;
}
/**
* Returns monster armor.
@@ -472,18 +474,18 @@ class OTS_Monster extends DOMDocument
* @return int Armor rate.
* @throws DOMException On DOM operation error.
*/
public function getArmor()
{
$element = $this->documentElement->getElementsByTagName('defenses')->item(0);
public function getArmor()
{
$element = $this->documentElement->getElementsByTagName('defenses')->item(0);
// checks if defenses element is set
if( isset($element) )
{
return (int) $element->getAttribute('armor');
}
// checks if defenses element is set
if( isset($element) )
{
return (int) $element->getAttribute('armor');
}
return 0;
}
return 0;
}
/**
* Returns list of special defenses.
@@ -491,23 +493,23 @@ class OTS_Monster extends DOMDocument
* @return array List of defense effects.
* @throws DOMException On DOM operation error.
*/
public function getDefenses()
{
$defenses = array();
public function getDefenses()
{
$defenses = array();
$element = $this->documentElement->getElementsByTagName('defenses')->item(0);
$element = $this->documentElement->getElementsByTagName('defenses')->item(0);
// checks if it has any defenses
if( isset($element) )
{
foreach( $element->getElementsByTagName('defense') as $defense)
{
$defenses[] = $defense->getAttribute('name');
}
}
// checks if it has any defenses
if( isset($element) )
{
foreach( $element->getElementsByTagName('defense') as $defense)
{
$defenses[] = $defense->getAttribute('name');
}
}
return $defenses;
}
return $defenses;
}
/**
* Returns list of monster attacks.
@@ -515,23 +517,23 @@ class OTS_Monster extends DOMDocument
* @return array List of attafck effects.
* @throws DOMException On DOM operation error.
*/
public function getAttacks()
{
$attacks = array();
public function getAttacks()
{
$attacks = array();
$element = $this->documentElement->getElementsByTagName('attacks')->item(0);
$element = $this->documentElement->getElementsByTagName('attacks')->item(0);
// checks if it has any defenses
if( isset($element) )
{
foreach( $element->getElementsByTagName('attack') as $attack)
{
$attacks[] = $attack->getAttribute('name');
}
}
// checks if it has any defenses
if( isset($element) )
{
foreach( $element->getElementsByTagName('attack') as $attack)
{
$attacks[] = $attack->getAttribute('name');
}
}
return $attacks;
}
return $attacks;
}
/**
* Magic PHP5 method.
@@ -543,59 +545,59 @@ class OTS_Monster extends DOMDocument
* @throws OutOfBoundsException For non-supported properties.
* @throws DOMException On DOM operation error.
*/
public function __get($name)
{
switch($name)
{
case 'name':
return $this->getName();
public function __get($name)
{
switch($name)
{
case 'name':
return $this->getName();
case 'race':
return $this->getRace();
case 'race':
return $this->getRace();
case 'experience':
return $this->getExperience();
case 'experience':
return $this->getExperience();
case 'speed':
return $this->getSpeed();
case 'speed':
return $this->getSpeed();
case 'manaCost':
return $this->getManaCost();
case 'manaCost':
return $this->getManaCost();
case 'health':
return $this->getHealth();
case 'health':
return $this->getHealth();
case 'flags':
return $this->getFlags();
case 'flags':
return $this->getFlags();
case 'voices':
return $this->getVoices();
case 'voices':
return $this->getVoices();
case 'items':
return $this->getItems();
case 'items':
return $this->getItems();
case 'immunities':
return $this->getImmunities();
case 'immunities':
return $this->getImmunities();
case 'defense':
return $this->getDefense();
case 'defense':
return $this->getDefense();
case 'armor':
return $this->getArmor();
case 'armor':
return $this->getArmor();
case 'defenses':
return $this->getDefenses();
case 'defenses':
return $this->getDefenses();
case 'attacks':
return $this->getAttacks();
case 'attacks':
return $this->getAttacks();
case 'look':
return $this->getLook();
case 'look':
return $this->getLook();
default:
throw new OutOfBoundsException();
}
}
default:
throw new OutOfBoundsException();
}
}
/**
* Returns string representation of XML.
@@ -608,18 +610,18 @@ class OTS_Monster extends DOMDocument
* @since 0.1.0
* @return string String representation of object.
*/
public function __toString()
{
$ots = POT::getInstance();
public function __toString()
{
$ots = POT::getInstance();
// checks if display driver is loaded
if( $ots->isDataDisplayDriverLoaded() )
{
return $ots->getDataDisplayDriver()->displayMonster($this);
}
// checks if display driver is loaded
if( $ots->isDataDisplayDriverLoaded() )
{
return $ots->getDataDisplayDriver()->displayMonster($this);
}
return $this->saveXML();
}
return $this->saveXML();
}
}
/**#@-*/

View File

@@ -90,7 +90,7 @@ class OTS_Player extends OTS_Row_DAO
* @version 0.1.2
* @var array
*/
private $data = array('sex' => 0, 'vocation' => 0, 'experience' => 0, 'level' => 1, 'maglevel' => 0, 'health' => 100, 'healthmax' => 100, 'mana' => 100, 'manamax' => 100, 'manaspent' => 0, 'soul' => 0, 'lookbody' => 10, 'lookfeet' => 10, 'lookhead' => 10, 'looklegs' => 10, 'looktype' => 136, 'lookaddons' => 0, 'posx' => 0, 'posy' => 0, 'posz' => 0, 'cap' => 0, 'lastlogin' => 0, 'lastip' => 0, 'save' => true, 'skulltime' => 0, 'skull' => 0, 'balance' => 0, 'lastlogout' => 0, 'blessings' => 0, 'stamina' => 0, 'online' => 0, 'comment' => '', 'created' => 0, 'hidden' => 0);
private $data = array('group_id' => 1, 'sex' => 0, 'vocation' => 0, 'experience' => 0, 'level' => 1, 'maglevel' => 0, 'health' => 100, 'healthmax' => 100, 'mana' => 100, 'manamax' => 100, 'manaspent' => 0, 'soul' => 0, 'lookbody' => 10, 'lookfeet' => 10, 'lookhead' => 10, 'looklegs' => 10, 'looktype' => 136, 'lookaddons' => 0, 'posx' => 0, 'posy' => 0, 'posz' => 0, 'cap' => 0, 'lastlogin' => 0, 'lastip' => 0, 'save' => true, 'skulltime' => 0, 'skull' => 0, 'balance' => 0, 'lastlogout' => 0, 'blessings' => 0, 'stamina' => 0, 'online' => 0, 'comment' => '', 'created' => 0, 'hide' => 0);
/**
* Player skills.
@@ -231,7 +231,7 @@ class OTS_Player extends OTS_Row_DAO
}
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`, `hidden` FROM `players` WHERE `id` = ' . (int)$id)->fetch();
$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();
}
// loads skills
@@ -521,17 +521,17 @@ class OTS_Player extends OTS_Row_DAO
public function isHidden()
{
if( !isset($this->data['hidden']) )
if( !isset($this->data['hide']) )
{
throw new E_OTS_NotLoaded();
}
return $this->data['hidden'] == 1;
return $this->data['hide'] == 1;
}
public function setHidden($hidden)
{
$this->data['hidden'] = (int) $hidden;
$this->data['hide'] = (int) $hidden;
}
public function getMarriage()
@@ -1229,6 +1229,13 @@ class OTS_Player extends OTS_Row_DAO
$this->data['direction'] = (int) $direction;
}
public function getOutfit(): string
{
$hasLookAddons = $this->db->hasColumn('players', 'lookaddons');
return setting('core.outfit_images_url') . '?id=' . $this->getLookType() . ($hasLookAddons ? '&addons=' . $this->getLookAddons() : '') . '&head=' . $this->getLookHead() . '&body=' . $this->getLookBody() . '&legs=' . $this->getLookLegs() . '&feet=' . $this->getLookFeet();
}
/**
* Body color.
*
@@ -1745,11 +1752,6 @@ class OTS_Player extends OTS_Row_DAO
*/
public function getConditions()
{
if( !isset($this->data['conditions']) )
{
throw new E_OTS_NotLoaded();
}
return $this->data['conditions'];
}

View File

@@ -36,6 +36,10 @@ $locale['step_requirements'] = 'Anforderungen';
$locale['step_requirements_title'] = 'Anforderungen überprüfen';
$locale['step_requirements_php_version'] = 'PHP Version';
$locale['step_requirements_write_perms'] = 'Schreibberechtigungen';
$locale['step_requirements_folder_exists'] = 'Ordner ist vorhanden';
$locale['step_requirements_folder_not_exists_tools_ext'] = 'NPM Package Manager wird verwendet für externe JavaScript/CSS Bibliotheken.'
. ' Es sollte via Command Line installiert werden: <a href="https://docs.npmjs.com/downloading-and-installing-node-js-and-npm">https://docs.npmjs.com/downloading-and-installing-node-js-and-npm</a>'
. ' Nachdem das Tool installiert wurde, folgende Befehl sollte ausgeführt in dem Hauptordner des MyAACs: "npm install".';
$locale['step_requirements_failed'] = 'Die Installation wird deaktiviert, bis diese Anforderungen erfüllt sind.</b><br/>Für weitere Informationen siehe <b>README</b> Datei.';
$locale['step_requirements_extension'] = '$EXTENSION$ PHP Erweiterung';

View File

@@ -36,6 +36,10 @@ $locale['step_requirements'] = 'Requirements';
$locale['step_requirements_title'] = 'Requirements check';
$locale['step_requirements_php_version'] = 'PHP Version';
$locale['step_requirements_write_perms'] = 'Write permissions';
$locale['step_requirements_folder_exists'] = 'Directory exists';
$locale['step_requirements_folder_not_exists_tools_ext'] = 'NPM Package Manager is used for external JavaScript/CSS libraries.'
. ' You need to install it through Command Line: <a href="https://docs.npmjs.com/downloading-and-installing-node-js-and-npm">https://docs.npmjs.com/downloading-and-installing-node-js-and-npm</a>'
. ' When you done with installing that tool, execute: "npm install" in the main MyAAC folder.';
$locale['step_requirements_failed'] = 'Installation will be disabled until these requirements will be passed.</b><br/>For more informations see <b>README</b> file.';
$locale['step_requirements_extension'] = '$EXTENSION$ PHP extension';
$locale['step_requirements_warning_images_guilds'] = 'Guild logo upload will not work';
@@ -90,7 +94,7 @@ $locale['step_database_loaded_npcs'] = 'NPCs has been loaded...';
$locale['step_database_error_npcs'] = 'There were some problems loading your NPCs';
$locale['step_database_loaded_spells'] = 'Spells has been loaded...';
$locale['step_database_loaded_towns'] = 'Towns has been loaded...';
$locale['step_database_error_towns'] = 'There were some problems loading your towns. You will need to configure them manually in config.';
$locale['step_database_error_towns'] = 'There were some problems loading your towns. You will need to configure them manually in Settings.';
$locale['step_database_created_account'] = 'Created admin account...';
$locale['step_database_created_news'] = 'Newses has been created...';

View File

@@ -36,6 +36,10 @@ $locale['step_requirements'] = 'Wymagania';
$locale['step_requirements_title'] = 'Sprawdzanie wymagań';
$locale['step_requirements_php_version'] = 'Wersja PHP';
$locale['step_requirements_write_perms'] = 'Uprawnienia do zapisu';
$locale['step_requirements_folder_exists'] = 'Folder istnieje';
$locale['step_requirements_folder_not_exists_tools_ext'] = 'Manadżer Pakietów NPM jest używany do zewnętrznych bibliotek JavaScript/CSS.'
. ' Trzeba go zainstalować poprzez wiersz poleceń: <a href="https://docs.npmjs.com/downloading-and-installing-node-js-and-npm">https://docs.npmjs.com/downloading-and-installing-node-js-and-npm</a>'
. ' Po instalacji narzędzia, wywołaj następujące polecenie w głownym katalogu MyAAC: "npm install".';
$locale['step_requirements_failed'] = 'Instalacja zostanie zablokowana dopóki te wymagania nie zostaną spełnione.</b><br/>Po więcej informacji zasięgnij do pliku <b>README</b>.';
$locale['step_requirements_extension'] = 'Rozszerzenie PHP - $EXTENSION$';
$locale['step_requirements_warning_images_guilds'] = 'Nie będzie możliwości uploadu obrazków gildii';
@@ -89,7 +93,7 @@ $locale['step_database_loaded_npcs'] = 'Załadowano NPCs...';
$locale['step_database_error_npcs'] = 'Wystąpił problem podczas ładowania NPCs';
$locale['step_database_loaded_spells'] = 'Załadowano czary (spells)...';
$locale['step_database_loaded_towns'] = 'Załadowano miasta (towns)...';
$locale['step_database_error_towns'] = 'Wystąpił problem podczas ładowania miast. Trzeba będzie je skonfigurować manualnie.';
$locale['step_database_error_towns'] = 'Wystąpił problem podczas ładowania miast. Trzeba będzie je skonfigurować manualnie w ustawieniach.';
$locale['step_database_created_account'] = 'Utworzono konto admina...';
$locale['step_database_created_news'] = 'Utworzono newsy...';

View File

@@ -22,11 +22,5 @@ if(isset($account_logged) && $account_logged->isLoaded()) {
$logged = false;
unset($account_logged);
if(isset($_REQUEST['redirect']))
{
header('Location: ' . urldecode($_REQUEST['redirect']));
exit;
}
}
}

View File

@@ -17,6 +17,12 @@ if(fetchDatabaseConfig('database_version', $tmp)) { // we got version
$db->revalidateCache();
for($i = $tmp + 1; $i <= DATABASE_VERSION; $i++) {
require SYSTEM . 'migrations/' . $i . '.php';
if (isset($up)) {
$up();
unset($up);
}
updateDatabaseConfig('database_version', $i);
}
}
@@ -26,6 +32,12 @@ else { // register first version
$db->revalidateCache();
for($i = 1; $i <= DATABASE_VERSION; $i++) {
require SYSTEM . 'migrations/' . $i . '.php';
if (isset($up)) {
$up();
unset($up);
}
updateDatabaseConfig('database_version', $i);
}
}

View File

@@ -0,0 +1,8 @@
CREATE TABLE `myaac_hooks`
(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL DEFAULT '',
`type` INT(2) NOT NULL DEFAULT 0,
`file` VARCHAR(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;

View File

@@ -1,16 +1,16 @@
<?php
$db->query("ALTER TABLE `" . TABLE_PREFIX . "account_actions` MODIFY `ip` INT(11) NOT NULL DEFAULT 0;");
$db->query("ALTER TABLE `" . TABLE_PREFIX . "account_actions` MODIFY `date` INT(11) NOT NULL DEFAULT 0;");
$db->query("ALTER TABLE `" . TABLE_PREFIX . "account_actions` MODIFY `action` VARCHAR(255) NOT NULL DEFAULT '';");
$db->query("
CREATE TABLE `myaac_hooks`
(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL DEFAULT '',
`type` INT(2) NOT NULL DEFAULT 0,
`file` VARCHAR(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
");
/**
* @var OTS_DB_MySQL $db
*/
?>
$up = function () use ($db) {
$db->modifyColumn(TABLE_PREFIX . 'account_actions', 'ip', "INT(11) NOT NULL DEFAULT 0");
$db->modifyColumn(TABLE_PREFIX . 'account_actions', 'date', "INT(11) NOT NULL DEFAULT 0");
$db->modifyColumn(TABLE_PREFIX . 'account_actions', 'action', "VARCHAR(255) NOT NULL DEFAULT ''");
$db->query(file_get_contents(__DIR__ . '/1-hooks.sql'));
};
$down = function () use ($db) {
$db->dropTable(TABLE_PREFIX . 'hooks');
};

View File

@@ -0,0 +1,10 @@
CREATE TABLE `myaac_admin_menu`
(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL DEFAULT '',
`page` VARCHAR(255) NOT NULL DEFAULT '',
`ordering` INT(11) NOT NULL DEFAULT 0,
`flags` INT(11) NOT NULL DEFAULT 0,
`enabled` INT(1) NOT NULL DEFAULT 1,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;

View File

@@ -1,17 +1,24 @@
<?php
if(!$db->hasColumn(TABLE_PREFIX . 'hooks', 'ordering'))
$db->query("ALTER TABLE `" . TABLE_PREFIX . "hooks` ADD `ordering` INT(11) NOT NULL DEFAULT 0 AFTER `file`;");
/**
* @var OTS_DB_MySQL $db
*/
if(!$db->hasTable(TABLE_PREFIX . 'admin_menu'))
$db->query("
CREATE TABLE `myaac_admin_menu`
(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL DEFAULT '',
`page` VARCHAR(255) NOT NULL DEFAULT '',
`ordering` INT(11) NOT NULL DEFAULT 0,
`flags` INT(11) NOT NULL DEFAULT 0,
`enabled` INT(1) NOT NULL DEFAULT 1,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
");
$up = function () use ($db) {
if (!$db->hasColumn(TABLE_PREFIX . 'hooks', 'ordering')) {
$db->addColumn(TABLE_PREFIX . 'hooks', 'ordering', "INT(11) NOT NULL DEFAULT 0 AFTER `file`");
}
if (!$db->hasTable(TABLE_PREFIX . 'admin_menu')) {
$db->query(file_get_contents(__DIR__ . '/10-admin_menu.sql'));
}
};
$down = function () use ($db) {
if ($db->hasColumn(TABLE_PREFIX . 'hooks', 'ordering')) {
$db->dropColumn(TABLE_PREFIX . 'hooks', 'ordering');
}
if ($db->hasTable(TABLE_PREFIX . 'admin_menu')) {
$db->dropTable(TABLE_PREFIX . 'admin_menu');
}
};

View File

@@ -1,19 +1,44 @@
<?php
/**
* @var OTS_DB_MySQL $db
*/
$up = function () use ($db) {
// rename database tables
$db->query("RENAME TABLE
" . TABLE_PREFIX . "screenshots TO " . TABLE_PREFIX . "gallery,
" . TABLE_PREFIX . "movies TO " . TABLE_PREFIX . "videos;");
$db->renameTable(TABLE_PREFIX . 'screenshots', TABLE_PREFIX . 'gallery');
$db->renameTable(TABLE_PREFIX . 'movies', TABLE_PREFIX . 'videos');
// rename images dir
if(file_exists(BASE . 'images/screenshots') && !file_exists(BASE . GALLERY_DIR)) {
if (file_exists(BASE . 'images/screenshots') && !file_exists(BASE . GALLERY_DIR)) {
rename(BASE . 'images/screenshots', BASE . GALLERY_DIR);
}
// convert old database screenshots images to gallery
$query = $db->query('SELECT `id`, `image`, `thumb` FROM `' . TABLE_PREFIX . 'gallery`;');
foreach($query->fetchAll() as $item) {
foreach ($query->fetchAll() as $item) {
$db->update(TABLE_PREFIX . 'gallery', array(
'image' => str_replace('/screenshots/', '/gallery/', $item['image']),
'thumb' => str_replace('/screenshots/', '/gallery/', $item['thumb']),
), array('id' => $item['id']));
}
};
$down = function () use ($db) {
// rename database tables
$db->renameTable(TABLE_PREFIX . 'gallery', TABLE_PREFIX . 'screenshots');
$db->renameTable(TABLE_PREFIX . 'videos', TABLE_PREFIX . 'movies');
// rename images dir
if (file_exists(BASE . GALLERY_DIR) && !file_exists(BASE . 'images/screenshots')) {
rename(BASE . GALLERY_DIR, BASE . 'images/screenshots');
}
// convert new database gallery images to screenshots
$query = $db->query('SELECT `id`, `image`, `thumb` FROM `' . TABLE_PREFIX . 'screenshots`;');
foreach ($query->fetchAll() as $item) {
$db->update(TABLE_PREFIX . 'screenshots', [
'image' => str_replace('/gallery/', '/screenshots/', $item['image']),
'thumb' => str_replace('/gallery/', '/screenshots/', $item['thumb']),
], ['id' => $item['id']]);
}
};

View File

@@ -0,0 +1,9 @@
CREATE TABLE `myaac_items`
(
`id` INT(11) NOT NULL,
`article` VARCHAR(5) NOT NULL DEFAULT '',
`name` VARCHAR(50) NOT NULL DEFAULT '',
`plural` VARCHAR(50) NOT NULL DEFAULT '',
`attributes` VARCHAR(500) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;

View File

@@ -0,0 +1,8 @@
CREATE TABLE `myaac_weapons`
(
`id` INT(11) NOT NULL,
`level` INT(11) NOT NULL DEFAULT 0,
`maglevel` INT(11) NOT NULL DEFAULT 0,
`vocations` VARCHAR(100) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;

View File

@@ -1,51 +1,65 @@
<?php
/**
* @var OTS_DB_MySQL $db
*/
// add new item_id field for runes
if(!$db->hasColumn(TABLE_PREFIX . 'spells', 'item_id'))
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` ADD `item_id` INT(11) NOT NULL DEFAULT 0 AFTER `conjure_count`;");
use MyAAC\Models\Spell;
// change unique index from spell to name
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` DROP INDEX `spell`;");
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` ADD UNIQUE INDEX (`name`);");
// change comment of spells.type
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` MODIFY `type` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '1 - instant, 2 - conjure, 3 - rune';");
// new items table
if(!$db->hasTable(TABLE_PREFIX . 'items'))
$db->query("
CREATE TABLE `" . TABLE_PREFIX . "items`
(
`id` INT(11) NOT NULL,
`article` VARCHAR(5) NOT NULL DEFAULT '',
`name` VARCHAR(50) NOT NULL DEFAULT '',
`plural` VARCHAR(50) NOT NULL DEFAULT '',
`attributes` VARCHAR(500) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
");
// new weapons table
if(!$db->hasTable(TABLE_PREFIX . 'weapons'))
$db->query("
CREATE TABLE `" . TABLE_PREFIX . "weapons`
(
`id` INT(11) NOT NULL,
`level` INT(11) NOT NULL DEFAULT 0,
`maglevel` INT(11) NOT NULL DEFAULT 0,
`vocations` VARCHAR(100) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
");
// modify vocations to support json data
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` MODIFY `vocations` VARCHAR(100) NOT NULL DEFAULT '';");
$query = $db->query('SELECT `id`, `vocations` FROM `' . TABLE_PREFIX . 'spells`');
foreach($query->fetchAll() as $spell) {
$tmp = explode(',', $spell['vocations']);
foreach($tmp as &$v) {
$v = (int)$v;
$up = function () use ($db) {
// add new item_id field for runes
if (!$db->hasColumn(TABLE_PREFIX . 'spells', 'item_id')) {
$db->addColumn(TABLE_PREFIX . 'spells', 'item_id', 'INT(11) NOT NULL DEFAULT 0 AFTER `conjure_count`');
}
$db->update(TABLE_PREFIX . 'spells', array('vocations' => json_encode($tmp)), array('id' => $spell['id']));
}
?>
// change unique index from spell to name
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` DROP INDEX `spell`;");
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` ADD UNIQUE INDEX (`name`);");
// change comment of spells.type
$db->modifyColumn(TABLE_PREFIX . 'spells', 'type', "TINYINT(1) NOT NULL DEFAULT 0 COMMENT '1 - instant, 2 - conjure, 3 - rune'");
// new items table
if (!$db->hasTable(TABLE_PREFIX . 'items')) {
$db->query(file_get_contents(__DIR__ . '/12-items.sql'));
}
// new weapons table
if (!$db->hasTable(TABLE_PREFIX . 'weapons')) {
$db->query(file_get_contents(__DIR__ . '/12-weapons.sql'));
}
// modify vocations to support json data
$db->modifyColumn(TABLE_PREFIX . 'spells', 'vocations', "VARCHAR(100) NOT NULL DEFAULT ''");
$spells = Spell::select('id', 'vocations')->get();
foreach ($spells as $spell) {
$tmp = explode(',', $spell->vocations);
foreach ($tmp as &$v) {
$v = (int)$v;
}
Spell::where('id', $spell->id)->update(['vocations' => json_encode($tmp)]);
}
};
$down = function () use ($db) {
// remove item_id field for runes
if ($db->hasColumn(TABLE_PREFIX . 'spells', 'item_id')) {
$db->dropColumn(TABLE_PREFIX . 'spells', 'item_id');
}
// change unique index from spell to name
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` DROP INDEX `name`;");
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` ADD INDEX (`spell`);");
$db->dropTable(TABLE_PREFIX . 'items');
$db->dropTable(TABLE_PREFIX . 'weapons');
$spells = Spell::select('id', 'vocations')->get();
// modify vocations to use vocation separated by comma
foreach ($spells as $spell) {
$vocations = empty($spell->vocations) ? [] : json_decode($spell->vocations);
Spell::where('id', $spell->id)->update(['vocations' => implode(',', $vocations)]);
}
};

View File

@@ -1,3 +1,16 @@
<?php
if($db->hasColumn(TABLE_PREFIX . 'spells', 'spell'))
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` DROP COLUMN `spell`;");
/**
* @var OTS_DB_MySQL $db
*/
$up = function () use ($db) {
if ($db->hasColumn(TABLE_PREFIX . 'spells', 'spell')) {
$db->dropColumn(TABLE_PREFIX . 'spells', 'spell');
}
};
$down = function () use ($db) {
if (!$db->hasColumn(TABLE_PREFIX . 'spells', 'spell')) {
$db->addColumn(TABLE_PREFIX . 'spells', 'spell', "VARCHAR(255) NOT NULL DEFAULT ''");
}
};

View File

@@ -1,18 +1,39 @@
<?php
/**
* @var OTS_DB_MySQL $db
*/
// change monsters.file_path field to loot
if($db->hasColumn(TABLE_PREFIX . 'monsters', 'file_path')) {
$db->query("ALTER TABLE `" . TABLE_PREFIX . "monsters` CHANGE `file_path` `loot` VARCHAR(5000);");
}
$up = function () use ($db) {
// change monsters.file_path field to loot
if ($db->hasColumn(TABLE_PREFIX . 'monsters', 'file_path')) {
$db->changeColumn(TABLE_PREFIX . 'monsters', 'file_path', 'loot', 'VARCHAR(5000)');
}
// update loot to empty string
$db->query("UPDATE `" . TABLE_PREFIX . "monsters` SET `loot` = '';");
// update loot to empty string
$db->query("UPDATE `" . TABLE_PREFIX . "monsters` SET `loot` = '';");
// drop monsters.gfx_name field
$db->query("ALTER TABLE `" . TABLE_PREFIX . "monsters` DROP COLUMN `gfx_name`;");
// drop monsters.gfx_name field
$db->dropColumn(TABLE_PREFIX . 'monsters', 'gfx_name');
// rename hide_creature to hidden
if($db->hasColumn(TABLE_PREFIX . 'monsters', 'hide_creature')) {
$db->query("ALTER TABLE `" . TABLE_PREFIX . "monsters` CHANGE `hide_creature` `hidden` TINYINT(1) NOT NULL DEFAULT 0;");
}
?>
// rename hide_creature to hidden
if ($db->hasColumn(TABLE_PREFIX . 'monsters', 'hide_creature')) {
$db->changeColumn(TABLE_PREFIX . 'monsters', 'hide_creature', 'hidden', "TINYINT(1) NOT NULL DEFAULT 0");
}
};
$down = function () use ($db) {
if ($db->hasColumn(TABLE_PREFIX . 'monsters', 'loot')) {
$db->changeColumn(TABLE_PREFIX . 'monsters', 'loot', 'file_path', 'VARCHAR(5000)');
}
// update file_path to empty string
$db->query("UPDATE `" . TABLE_PREFIX . "monsters` SET `file_path` = '';");
// add monsters.gfx_name field
$db->addColumn(TABLE_PREFIX . 'monsters', 'gfx_name', 'varchar(255) NOT NULL AFTER `race`');
// rename hidden to hide_creature
if ($db->hasColumn(TABLE_PREFIX . 'monsters', 'hidden')) {
$db->changeColumn(TABLE_PREFIX . 'monsters', 'hidden', 'hide_creature', 'TINYINT(1) NOT NULL DEFAULT 0');
}
};

View File

@@ -1,10 +1,26 @@
<?php
/**
* @var OTS_DB_MySQL $db
*/
// add new forum.guild and forum.access fields
if(!$db->hasColumn(TABLE_PREFIX . 'forum_boards', 'guild')) {
$db->query("ALTER TABLE `" . TABLE_PREFIX . "forum_boards` ADD `guild` TINYINT(1) NOT NULL DEFAULT 0 AFTER `closed`;");
}
if(!$db->hasColumn(TABLE_PREFIX . 'forum_boards', 'access')) {
$db->query("ALTER TABLE `" . TABLE_PREFIX . "forum_boards` ADD `access` TINYINT(1) NOT NULL DEFAULT 0 AFTER `guild`;");
}
$up = function () use ($db) {
if (!$db->hasColumn(TABLE_PREFIX . 'forum_boards', 'guild')) {
$db->addColumn(TABLE_PREFIX . 'forum_boards', 'guild', 'TINYINT(1) NOT NULL DEFAULT 0 AFTER `closed`');
}
if (!$db->hasColumn(TABLE_PREFIX . 'forum_boards', 'access')) {
$db->addColumn(TABLE_PREFIX . 'forum_boards', 'access', 'TINYINT(1) NOT NULL DEFAULT 0 AFTER `guild`');
}
};
$down = function () use ($db) {
if ($db->hasColumn(TABLE_PREFIX . 'forum_boards', 'guild')) {
$db->dropColumn(TABLE_PREFIX . 'forum_boards', 'guild');
}
if ($db->hasColumn(TABLE_PREFIX . 'forum_boards', 'access')) {
$db->dropColumn(TABLE_PREFIX . 'forum_boards', 'access');
}
};

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