From da151051186c913dd0dd091aabe893649c2b9ee7 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 12 May 2025 17:36:34 +0200 Subject: [PATCH 001/222] Fix typo, @gpedro I hate you! :PPP --- system/src/Models/Visitor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Models/Visitor.php b/system/src/Models/Visitor.php index 93d5f2be..0c78b0b0 100644 --- a/system/src/Models/Visitor.php +++ b/system/src/Models/Visitor.php @@ -10,6 +10,6 @@ class Visitor extends Model { public $timestamps = false; - protected $fillable = ['ip', 'lastivist', 'page', 'user_agent']; + protected $fillable = ['ip', 'lastvisit', 'page', 'user_agent']; } From 629fd18ea166860d5898a822f44f9277da6ce43d Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 12 May 2025 17:36:50 +0200 Subject: [PATCH 002/222] Update cypress version to ^14.3.3 --- package-lock.json | 169 +++++++++++++++++++++++++++------------------- package.json | 2 +- 2 files changed, 102 insertions(+), 69 deletions(-) diff --git a/package-lock.json b/package-lock.json index a8c17859..7cdffe23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,24 +14,13 @@ "tinymce": "^7.2.0" }, "devDependencies": { - "cypress": "^13.17.0" - } - }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.90" + "cypress": "^14.3.3" } }, "node_modules/@cypress/request": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.7.tgz", - "integrity": "sha512-LzxlLEMbBOPYB85uXrDqvD4MgcenjRBLIns3zyhx7vTPj/0u2eQhzXvPiGcaJrV38Q9dbkExWp6cOHPJ+EtFYg==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.8.tgz", + "integrity": "sha512-h0NFgh1mJmm1nr4jCwkGHwKneVYKghUyWe6TMNrk0B9zsjAJxpg8C4/+BAcmLgCPa1vj1V8rNUaILl+zYRUWBQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -48,7 +37,7 @@ "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "performance-now": "^2.1.0", - "qs": "6.13.1", + "qs": "6.14.0", "safe-buffer": "^5.1.2", "tough-cookie": "^5.0.0", "tunnel-agent": "^0.6.0", @@ -387,9 +376,9 @@ } }, "node_modules/call-bind-apply-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", - "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "dev": true, "license": "MIT", "dependencies": { @@ -401,14 +390,14 @@ } }, "node_modules/call-bound": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", - "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "get-intrinsic": "^1.2.6" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -504,9 +493,9 @@ } }, "node_modules/cli-table3": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", - "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.1.tgz", + "integrity": "sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==", "dev": true, "license": "MIT", "dependencies": { @@ -516,7 +505,7 @@ "node": "10.* || >= 12.*" }, "optionalDependencies": { - "@colors/colors": "1.5.0" + "colors": "1.4.0" } }, "node_modules/cli-truncate": { @@ -563,6 +552,17 @@ "dev": true, "license": "MIT" }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -619,14 +619,14 @@ } }, "node_modules/cypress": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.17.0.tgz", - "integrity": "sha512-5xWkaPurwkIljojFidhw8lFScyxhtiFHl/i/3zov+1Z5CmY4t9tjIdvSXfu82Y3w7wt0uR9KkucbhkVvJZLQSA==", + "version": "14.3.3", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-14.3.3.tgz", + "integrity": "sha512-1Rz7zc9iqLww6BysaESqUhtIuaFHS7nL3wREovAKYsNhLTfX3TbcBWHWgEz70YimH2NkSOsm4oIcJJ9HYHOlew==", "dev": true, "hasInstallScript": true, "license": "MIT", "dependencies": { - "@cypress/request": "^3.0.6", + "@cypress/request": "^3.0.8", "@cypress/xvfb": "^1.2.4", "@types/sinonjs__fake-timers": "8.1.1", "@types/sizzle": "^2.3.2", @@ -637,9 +637,9 @@ "cachedir": "^2.3.0", "chalk": "^4.1.0", "check-more-types": "^2.24.0", - "ci-info": "^4.0.0", + "ci-info": "^4.1.0", "cli-cursor": "^3.1.0", - "cli-table3": "~0.6.1", + "cli-table3": "0.6.1", "commander": "^6.2.1", "common-tags": "^1.8.0", "dayjs": "^1.10.4", @@ -663,7 +663,7 @@ "process": "^0.11.10", "proxy-from-env": "1.0.0", "request-progress": "^3.0.0", - "semver": "^7.5.3", + "semver": "^7.7.1", "supports-color": "^8.1.1", "tmp": "~0.2.3", "tree-kill": "1.2.2", @@ -674,7 +674,7 @@ "cypress": "bin/cypress" }, "engines": { - "node": "^16.0.0 || ^18.0.0 || >=20.0.0" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" } }, "node_modules/cypress/node_modules/fs-extra": { @@ -819,9 +819,9 @@ } }, "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "dev": true, "license": "MIT", "dependencies": { @@ -831,6 +831,22 @@ "node": ">= 0.4" } }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -960,14 +976,15 @@ } }, "node_modules/form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12" }, "engines": { @@ -999,18 +1016,18 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", - "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", + "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "get-proto": "^1.0.0", + "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", @@ -1131,6 +1148,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -1560,9 +1593,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, "license": "MIT", "engines": { @@ -1709,13 +1742,13 @@ } }, "node_modules/qs": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.1.tgz", - "integrity": "sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -1794,9 +1827,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, "license": "ISC", "bin": { @@ -2031,22 +2064,22 @@ "license": "GPL-2.0-or-later" }, "node_modules/tldts": { - "version": "6.1.71", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.71.tgz", - "integrity": "sha512-LQIHmHnuzfZgZWAf2HzL83TIIrD8NhhI0DVxqo9/FdOd4ilec+NTNZOlDZf7EwrTNoutccbsHjvWHYXLAtvxjw==", + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.71" + "tldts-core": "^6.1.86" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.71", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.71.tgz", - "integrity": "sha512-LRbChn2YRpic1KxY+ldL1pGXN/oVvKfCVufwfVzEQdFYNo39uF7AJa/WXdo+gYO7PTvdfkCPCed6Hkvz/kR7jg==", + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", "dev": true, "license": "MIT" }, @@ -2061,9 +2094,9 @@ } }, "node_modules/tough-cookie": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.0.tgz", - "integrity": "sha512-rvZUv+7MoBYTiDmFPBrhL7Ujx9Sk+q9wwm22x8c8T5IJaR+Wsyc7TNxbVxo84kZoRJZZMazowFLqpankBEQrGg==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", "dev": true, "license": "BSD-3-Clause", "dependencies": { diff --git a/package.json b/package.json index 7bf43b48..82c079dd 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "postinstall": "node ./npm-post-install.js" }, "devDependencies": { - "cypress": "^13.17.0" + "cypress": "^14.3.3" }, "dependencies": { "@tinymce/tinymce-jquery": "^2.1.0", From ef6549c17c4ae30a8d9ba1776178b678ddaf8404 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 13 May 2025 15:20:25 +0200 Subject: [PATCH 003/222] nothing important: tabs & spaces --- templates/tibiacom/account.login.html.twig | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/templates/tibiacom/account.login.html.twig b/templates/tibiacom/account.login.html.twig index 8aeba805..f406d0c1 100644 --- a/templates/tibiacom/account.login.html.twig +++ b/templates/tibiacom/account.login.html.twig @@ -20,9 +20,9 @@ From c48b8006319f6c3b5f082befd16785420bb98110 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 13 May 2025 16:29:19 +0200 Subject: [PATCH 004/222] Fix login.php boosted creature & boss (not sure exact version, but should be 14.12 or around) Thanks @opentibiabr team --- login.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/login.php b/login.php index d51ae57b..88d5d88a 100644 --- a/login.php +++ b/login.php @@ -86,12 +86,25 @@ switch ($action) { die(json_encode(['eventlist' => $eventlist, 'lastupdatetimestamp' => time()])); case 'boostedcreature': + $clientVersion = (int)setting('core.client'); + + // 14.00 and up + if ($clientVersion >= 1400) { + $creatureBoost = $db->query("SELECT * FROM " . $db->tableName('boosted_creature'))->fetchAll(); + $bossBoost = $db->query("SELECT * FROM " . $db->tableName('boosted_boss'))->fetchAll(); + die(json_encode([ + 'boostedcreature' => true, + 'creatureraceid' => intval($creatureBoost[0]['raceid']), + 'bossraceid' => intval($bossBoost[0]['raceid']) + ])); + } + + // lower clients $boostedCreature = BoostedCreature::first(); die(json_encode([ 'boostedcreature' => true, 'raceid' => $boostedCreature->raceid ])); - break; case 'login': From 5367df23812c6182863353c9a39fd7fb0b743f4b Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 13 May 2025 16:29:40 +0200 Subject: [PATCH 005/222] Add latest client versions (14.00 - 15.01) --- system/clients.conf.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/system/clients.conf.php b/system/clients.conf.php index fce41bb1..3f5b12f0 100644 --- a/system/clients.conf.php +++ b/system/clients.conf.php @@ -109,4 +109,12 @@ $config['clients'] = [ 1330, 1332, 1340, + + 1400, + 1405, + 1410, + 1411, + 1412, + 1500, + 1501, ]; From 3befde2a1e4d24a011311e785f15185db57e19b8 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 14 May 2025 09:18:55 +0200 Subject: [PATCH 006/222] Do not return -1 in case of freePremium, makes things harder --- system/libs/pot/OTS_Account.php | 3 --- system/src/Models/Account.php | 3 --- 2 files changed, 6 deletions(-) diff --git a/system/libs/pot/OTS_Account.php b/system/libs/pot/OTS_Account.php index fe134a71..8528cf3f 100644 --- a/system/libs/pot/OTS_Account.php +++ b/system/libs/pot/OTS_Account.php @@ -443,9 +443,6 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable throw new E_OTS_NotLoaded(); } - $configFreePremium = configLua('freePremium'); - if(isset($configFreePremium) && getBoolean($configFreePremium)) {return -1;} - if(isset($this->data['premium_ends_at']) || isset($this->data['premend'])) { $col = isset($this->data['premium_ends_at']) ? 'premium_ends_at' : 'premend'; $ret = ceil(($this->data[$col] - time()) / (24 * 60 * 60)); diff --git a/system/src/Models/Account.php b/system/src/Models/Account.php index 613b3029..b11c2a48 100644 --- a/system/src/Models/Account.php +++ b/system/src/Models/Account.php @@ -43,9 +43,6 @@ class Account extends Model { return 0; } - global $config; - if(isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium'])) return -1; - if($this->premdays == 65535){ return 65535; } From a161cff00329da6f970f3a70967fe8346fe92bbc Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 14 May 2025 10:00:27 +0200 Subject: [PATCH 007/222] Add note about highscores being updated x minutes + allow ttl 0 to disable --- system/pages/highscores.php | 15 +++++++++++---- system/settings.php | 4 ++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/system/pages/highscores.php b/system/pages/highscores.php index 91ba2e2b..6deb842c 100644 --- a/system/pages/highscores.php +++ b/system/pages/highscores.php @@ -18,8 +18,11 @@ defined('MYAAC') or die('Direct access not allowed!'); $title = 'Highscores'; $settingHighscoresCountryBox = setting('core.highscores_country_box'); -if(config('account_country') && $settingHighscoresCountryBox) +if(config('account_country') && $settingHighscoresCountryBox) { require SYSTEM . 'countries.conf.php'; +} + +$highscoresTTL = setting('core.highscores_cache_ttl'); $list = urldecode($_GET['list'] ?? 'experience'); $page = $_GET['page'] ?? 1; @@ -140,7 +143,7 @@ $needReCache = true; $cacheKey = 'highscores_' . $skill . '_' . $vocation . '_' . $page . '_' . $configHighscoresPerPage; $cache = Cache::getInstance(); -if ($cache->enabled()) { +if ($cache->enabled() && $highscoresTTL > 0) { $tmp = ''; if ($cache->fetch($cacheKey, $tmp)) { $highscores = unserialize($tmp); @@ -214,8 +217,8 @@ if (empty($highscores)) { })->toArray(); } -if ($cache->enabled() && $needReCache) { - $cache->set($cacheKey, serialize($highscores), setting('core.highscores_cache_ttl') * 60); +if ($highscoresTTL > 0 && $cache->enabled() && $needReCache) { + $cache->set($cacheKey, serialize($highscores), $highscoresTTL * 60); } $show_link_to_next_page = false; @@ -278,6 +281,10 @@ if(setting('core.highscores_frags')) { if(setting('core.highscores_balance')) $types['balance'] = 'Balance'; +if ($highscoresTTL > 0 && $cache->enabled()) { + echo '*Note: Highscores are updated every' . ($highscoresTTL > 1 ? ' ' . $highscoresTTL : '') . ' minute' . ($highscoresTTL > 1 ? 's' : '') . '.

'; +} + /** @var Twig\Environment $twig */ $twig->display('highscores.html.twig', [ 'highscores' => $highscores, diff --git a/system/settings.php b/system/settings.php index 729527c0..d0a705a0 100644 --- a/system/settings.php +++ b/system/settings.php @@ -1035,8 +1035,8 @@ Sent by MyAAC,
'highscores_cache_ttl' => [ 'name' => 'Highscores Cache TTL (in minutes)', 'type' => 'number', - 'min' => 1, - 'desc' => 'How often to update highscores from database in minutes (default 15 minutes). Too low may cause lags on website.', + 'min' => 0, + 'desc' => 'How often to update highscores from database in minutes. Too low may slow down your website.
0 to disable.', 'default' => 15, ], 'highscores_vocation_box' => [ From 3949d84e5d7631f332111b6d00278bddbd0ad10a Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 14 May 2025 10:22:25 +0200 Subject: [PATCH 008/222] Rename server-info -> ots-info, changelog -> change-log + move rules to admin panel Due to conflict with apache2 server-info mod --- common.php | 2 +- system/migrations/44.php | 39 +++++++++++++++++++ .../pages/{changelog.php => change-log.php} | 0 .../pages/{server-info.php => ots-info.php} | 0 system/pages/rules.php | 14 ------- system/templates/rules.html.twig | 2 - 6 files changed, 40 insertions(+), 17 deletions(-) create mode 100644 system/migrations/44.php rename system/pages/{changelog.php => change-log.php} (100%) rename system/pages/{server-info.php => ots-info.php} (100%) delete mode 100644 system/pages/rules.php delete mode 100644 system/templates/rules.html.twig diff --git a/common.php b/common.php index 4c903f5b..0cba1145 100644 --- a/common.php +++ b/common.php @@ -27,7 +27,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is const MYAAC = true; const MYAAC_VERSION = '1.4.1-dev'; -const DATABASE_VERSION = 43; +const DATABASE_VERSION = 44; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX')); diff --git a/system/migrations/44.php b/system/migrations/44.php new file mode 100644 index 00000000..0d9d18bb --- /dev/null +++ b/system/migrations/44.php @@ -0,0 +1,39 @@ +update(['link' => 'ots-info']); + Menu::where('link', 'changelog')->update(['link' => 'change-log']); + + Pages::where('name', 'rules_on_the_page')->update(['hide' => 1]); + + $rules = Pages::where('name', 'rules')->first(); + if (!$rules) { + Pages::create([ + 'name' => 'rules', + 'title' => 'Server Rules', + 'body' => '{{ config.lua.serverName }} Rules
' . nl2br(file_get_contents(__DIR__ . '/30-rules.txt')), + 'date' => time(), + 'player_id' => 1, + 'php' => 0, + 'enable_tinymce' => 0, + 'access' => 0, + 'hide' => 0, + ]); + } +}; + +$down = function() { + Menu::where('link', 'ots-info')->update(['link' => 'server-info']); + Menu::where('link', 'change-log')->update(['link' => 'changelog']); + + Pages::where('name', 'rules_on_the_page')->update(['hide' => 0]); +}; + diff --git a/system/pages/changelog.php b/system/pages/change-log.php similarity index 100% rename from system/pages/changelog.php rename to system/pages/change-log.php diff --git a/system/pages/server-info.php b/system/pages/ots-info.php similarity index 100% rename from system/pages/server-info.php rename to system/pages/ots-info.php diff --git a/system/pages/rules.php b/system/pages/rules.php deleted file mode 100644 index 4ee0e4aa..00000000 --- a/system/pages/rules.php +++ /dev/null @@ -1,14 +0,0 @@ - - * @author Slawkens - * @copyright 2019 MyAAC - * @link https://my-aac.org - */ -defined('MYAAC') or die('Direct access not allowed!'); -$title = 'Server Rules'; - -$twig->display('rules.html.twig'); diff --git a/system/templates/rules.html.twig b/system/templates/rules.html.twig deleted file mode 100644 index 55490047..00000000 --- a/system/templates/rules.html.twig +++ /dev/null @@ -1,2 +0,0 @@ -{{ config.lua.serverName }} Rules
-{{ getCustomPage('rules_on_the_page') | nl2br }} From bf06bed385e9513730bfeffbd6827aeb9a70a938 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 14 May 2025 10:22:42 +0200 Subject: [PATCH 009/222] Update schema.sql --- install/includes/schema.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/includes/schema.sql b/install/includes/schema.sql index 36f5eb31..9c2a0ac8 100644 --- a/install/includes/schema.sql +++ b/install/includes/schema.sql @@ -1,4 +1,4 @@ -SET @myaac_database_version = 43; +SET @myaac_database_version = 44; CREATE TABLE `myaac_account_actions` ( From ee360386d879ea60e1e797b6a17c7b6104c2e1aa Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 14 May 2025 10:39:11 +0200 Subject: [PATCH 010/222] Addition to previous commit --- cypress/e2e/3-check-public-pages.cy.js | 4 ++-- system/pages/changelog.php | 3 +++ system/pages/server-info.php | 3 +++ templates/kathrine/menus.php | 4 ++-- templates/tibiacom/menus.php | 4 ++-- 5 files changed, 12 insertions(+), 6 deletions(-) create mode 100644 system/pages/changelog.php create mode 100644 system/pages/server-info.php diff --git a/cypress/e2e/3-check-public-pages.cy.js b/cypress/e2e/3-check-public-pages.cy.js index 9460739b..be7b7702 100644 --- a/cypress/e2e/3-check-public-pages.cy.js +++ b/cypress/e2e/3-check-public-pages.cy.js @@ -17,7 +17,7 @@ describe('Check Public Pages', () => { it('Go to changelog page', () => { cy.visit({ - url: Cypress.env('URL') + '/changelog', + url: Cypress.env('URL') + '/change-log', method: 'GET', }) }) @@ -132,7 +132,7 @@ describe('Check Public Pages', () => { it('Go to server info page', () => { cy.visit({ - url: Cypress.env('URL') + '/server-info', + url: Cypress.env('URL') + '/ots-info', method: 'GET', }) }) diff --git a/system/pages/changelog.php b/system/pages/changelog.php new file mode 100644 index 00000000..d57ec47b --- /dev/null +++ b/system/pages/changelog.php @@ -0,0 +1,3 @@ + [ 'Latest News' => 'news', 'News Archive' => 'news/archive', - 'Changelog' => 'changelog', + 'Changelog' => 'change-log', ], MENU_CATEGORY_ACCOUNT => [ 'Account Management' => 'account/manage', @@ -28,7 +28,7 @@ return [ MENU_CATEGORY_LIBRARY => [ 'Monsters' => 'monsters', 'Spells' => 'spells', - 'Server Info' => 'server-info', + 'Server Info' => 'ots-info', 'Commands' => 'commands', 'Exp Stages' => 'exp-stages', 'Gallery' => 'gallery', diff --git a/templates/tibiacom/menus.php b/templates/tibiacom/menus.php index bf85c7b6..9cb062d9 100644 --- a/templates/tibiacom/menus.php +++ b/templates/tibiacom/menus.php @@ -4,7 +4,7 @@ return [ MENU_CATEGORY_NEWS => [ 'Latest News' => 'news', 'News Archive' => 'news/archive', - 'Changelog' => 'changelog', + 'Changelog' => 'change-log', ], MENU_CATEGORY_ACCOUNT => [ 'Account Management' => 'account/manage', @@ -33,7 +33,7 @@ return [ 'Commands' => 'commands', 'Exp Stages' => 'exp-stages', 'Gallery' => 'gallery', - 'Server Info' => 'server-info', + 'Server Info' => 'ots-info', 'Exp Table' => 'exp-table', 'FAQ' => 'faq', ], From 83a6f4b61db3e1d6b23c121432b7f0c82ef4a1ba Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 14 May 2025 10:42:18 +0200 Subject: [PATCH 011/222] Add php 8.4 to phpstan --- .github/workflows/phpstan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index 2e60e570..8a1e73a3 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false matrix: - php-versions: [ '8.1', '8.2', '8.3' ] + php-versions: [ '8.1', '8.2', '8.3', '8.4' ] steps: - name: "Checkout" uses: "actions/checkout@v4" From ae5be41e11153784e6cbb09d4929cef60d70dfe5 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 14 May 2025 10:52:06 +0200 Subject: [PATCH 012/222] Separate migration 44 with 45 --- common.php | 2 +- install/includes/schema.sql | 2 +- install/tools/7-finish.php | 4 ++++ system/migrations/44.php | 19 ------------------- system/migrations/45.php | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 38 insertions(+), 21 deletions(-) create mode 100644 system/migrations/45.php diff --git a/common.php b/common.php index 0cba1145..6bbc97e9 100644 --- a/common.php +++ b/common.php @@ -27,7 +27,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is const MYAAC = true; const MYAAC_VERSION = '1.4.1-dev'; -const DATABASE_VERSION = 44; +const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX')); diff --git a/install/includes/schema.sql b/install/includes/schema.sql index 9c2a0ac8..eccaee54 100644 --- a/install/includes/schema.sql +++ b/install/includes/schema.sql @@ -1,4 +1,4 @@ -SET @myaac_database_version = 44; +SET @myaac_database_version = 45; CREATE TABLE `myaac_account_actions` ( diff --git a/install/tools/7-finish.php b/install/tools/7-finish.php index 6f6b2d30..c1ab5c1d 100644 --- a/install/tools/7-finish.php +++ b/install/tools/7-finish.php @@ -79,6 +79,10 @@ $up(); require_once SYSTEM . 'migrations/31.php'; $up(); +// rules page +require_once SYSTEM . 'migrations/45.php'; +$up(); + if(ModelsFAQ::count() == 0) { ModelsFAQ::create([ 'question' => 'What is this?', diff --git a/system/migrations/44.php b/system/migrations/44.php index 0d9d18bb..6db23412 100644 --- a/system/migrations/44.php +++ b/system/migrations/44.php @@ -11,29 +11,10 @@ use MyAAC\Models\Pages; $up = function() { Menu::where('link', 'server-info')->update(['link' => 'ots-info']); Menu::where('link', 'changelog')->update(['link' => 'change-log']); - - Pages::where('name', 'rules_on_the_page')->update(['hide' => 1]); - - $rules = Pages::where('name', 'rules')->first(); - if (!$rules) { - Pages::create([ - 'name' => 'rules', - 'title' => 'Server Rules', - 'body' => '{{ config.lua.serverName }} Rules
' . nl2br(file_get_contents(__DIR__ . '/30-rules.txt')), - 'date' => time(), - 'player_id' => 1, - 'php' => 0, - 'enable_tinymce' => 0, - 'access' => 0, - 'hide' => 0, - ]); - } }; $down = function() { Menu::where('link', 'ots-info')->update(['link' => 'server-info']); Menu::where('link', 'change-log')->update(['link' => 'changelog']); - - Pages::where('name', 'rules_on_the_page')->update(['hide' => 0]); }; diff --git a/system/migrations/45.php b/system/migrations/45.php new file mode 100644 index 00000000..a3fd45b9 --- /dev/null +++ b/system/migrations/45.php @@ -0,0 +1,32 @@ +update(['hide' => 1]); + + $rules = Pages::where('name', 'rules')->first(); + if (!$rules) { + Pages::create([ + 'name' => 'rules', + 'title' => 'Server Rules', + 'body' => '{{ config.lua.serverName }} Rules
' . nl2br(file_get_contents(__DIR__ . '/30-rules.txt')), + 'date' => time(), + 'player_id' => 1, + 'php' => 0, + 'enable_tinymce' => 0, + 'access' => 0, + 'hide' => 0, + ]); + } +}; + +$down = function() { + Pages::where('name', 'rules_on_the_page')->update(['hide' => 0]); +}; + From 6fe3bff163315151b7871dbce4cf0b948406aca3 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 14 May 2025 10:56:12 +0200 Subject: [PATCH 013/222] Update 45.php --- system/migrations/45.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/migrations/45.php b/system/migrations/45.php index a3fd45b9..c2d8aaec 100644 --- a/system/migrations/45.php +++ b/system/migrations/45.php @@ -19,7 +19,7 @@ $up = function() { 'date' => time(), 'player_id' => 1, 'php' => 0, - 'enable_tinymce' => 0, + 'enable_tinymce' => 1, 'access' => 0, 'hide' => 0, ]); From 3b2669fb3b8a94509939c90bb6a5c5d33d32fde2 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 14 May 2025 13:23:25 +0200 Subject: [PATCH 014/222] Update tables.headline.html.twig --- templates/tibiacom/tables.headline.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/tibiacom/tables.headline.html.twig b/templates/tibiacom/tables.headline.html.twig index 5db3dedb..3eb1bc4f 100644 --- a/templates/tibiacom/tables.headline.html.twig +++ b/templates/tibiacom/tables.headline.html.twig @@ -5,7 +5,7 @@ -
{{ title|raw }}
+
{{ title|raw }}
From 7e4d28c64854e6c88d0303c8c849c8483cb8727f Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 14 May 2025 13:23:34 +0200 Subject: [PATCH 015/222] Fix more php 8.4 warnings --- system/libs/pot/OTS.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/libs/pot/OTS.php b/system/libs/pot/OTS.php index 9c988210..a7327401 100644 --- a/system/libs/pot/OTS.php +++ b/system/libs/pot/OTS.php @@ -1115,7 +1115,7 @@ class POT * * @param IOTS_FileCache $cache Cache handler (skip this parameter to reset cache handler to null). */ - public function setItemsCache(IOTS_FileCache $cache = null) + public function setItemsCache(?IOTS_FileCache $cache = null) { $this->itemsCache = $cache; } @@ -1253,7 +1253,7 @@ class POT * * @param IOTS_FileCache $cache Cache handler (skip this parameter to reset cache handler to null). */ - public function setMapCache(IOTS_FileCache $cache = null) + public function setMapCache(?IOTS_FileCache $cache = null) { $this->mapCache = $cache; } From 5ed1aec28e146b871a75597411d12e42a067f4e6 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 14 May 2025 13:37:23 +0200 Subject: [PATCH 016/222] Add db variable to twig --- system/database.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/database.php b/system/database.php index b9dc6cc6..32877224 100644 --- a/system/database.php +++ b/system/database.php @@ -122,6 +122,8 @@ try { $eloquentConnection = $capsule->getConnection(); + $twig->addGlobal('db', $db); + } catch (Exception $e) { if(isset($cache) && $cache->enabled()) { $cache->delete('config_lua'); From e45dd88a930920f175c4ff06875e8511d36c1055 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 14 May 2025 14:03:03 +0200 Subject: [PATCH 017/222] Release v1.5 --- CHANGELOG-1.x.md | 28 ++++++++++++++++++++++++++++ common.php | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index c6feb09d..291b5441 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,33 @@ # Changelog +## [1.5 - 14.05.2025] + +### Added +* Feature/twig hooks filters (#258) +* Add latest client versions (14.00 - 15.01) (https://github.com/slawkens/myaac/commit/5367df23812c6182863353c9a39fd7fb0b743f4b) +* db variable to twig (https://github.com/slawkens/myaac/commit/5ed1aec28e146b871a75597411d12e42a067f4e6) +* New filter: HOOK_FILTER_ROUTES (https://github.com/slawkens/myaac/commit/9b75011224f385db8b27e109bfeb28e75b9d779c) +* Allow optionally separate folder for views (thanks @Scrollog for idea) (https://github.com/slawkens/myaac/commit/03e275213901a89edb0ebb8974b776a992ab391f) +* Add float & double types to the Settings (https://github.com/slawkens/myaac/commit/67ab425bb9796d9d123296e3fda542fa8f7f05ee) +* Add optional param _page_only for single-page apps etc. (https://github.com/slawkens/myaac/commit/113473f2560aab6d364c301cc14a8b5ba8f309f4) + +### Changed +* Change OTS_Account->getPremDays to not return -1 in case of freePremium (https://github.com/slawkens/myaac/commit/3befde2a1e4d24a011311e785f15185db57e19b8) +* Add note about highscores being updated x minutes + allow ttl 0 to disable cache (https://github.com/slawkens/myaac/commit/a161cff00329da6f970f3a70967fe8346fe92bbc) +* Better monster images (no image not found anymore) + use cache (https://github.com/slawkens/myaac/commit/73a5829974ceca3f02d7925d5cfbd5fa50b1bbd2) +* Rename server-info -> ots-info, changelog -> change-log (Due to conflict with apache2 server-info mod) (https://github.com/slawkens/myaac/commit/3949d84e5d7631f332111b6d00278bddbd0ad10a) +* Move rules page to admin panel (https://github.com/slawkens/myaac/commit/3949d84e5d7631f332111b6d00278bddbd0ad10a) + +### Fixed +* php 8.4 warnings +* Visitors counter not working properly on dev mode (https://github.com/slawkens/myaac/commit/da151051186c913dd0dd091aabe893649c2b9ee7) +* Fix login.php boosted creature & boss (not sure exact version, but should be 14.12 or around) (https://github.com/slawkens/myaac/commit/c48b8006319f6c3b5f082befd16785420bb98110) +* Fix installMenus when theme/template was removed from disc (https://github.com/slawkens/myaac/commit/c24c580796bccd54bf9e95b864763f4642684d55) +* Fix if user removes the menu category (https://github.com/slawkens/myaac/commit/dbea69f31478391dacfbbc02c8353c39b4245daf) + +### Updated: +* Update cypress from version ^13.17.0 to ^14.3.3 (https://github.com/slawkens/myaac/commit/629fd18ea166860d5898a822f44f9277da6ce43d) + ## [1.4 - 22.04.2025] ### Added diff --git a/common.php b/common.php index 6bbc97e9..2ac2c2de 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.4.1-dev'; +const MYAAC_VERSION = '1.5'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 3111d66df9e28401a51441bdc2d08a5f3568dff2 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 14 May 2025 14:09:28 +0200 Subject: [PATCH 018/222] Fix install, where $twig is not present in tools --- system/database.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/system/database.php b/system/database.php index 32877224..8fa8f869 100644 --- a/system/database.php +++ b/system/database.php @@ -122,7 +122,9 @@ try { $eloquentConnection = $capsule->getConnection(); - $twig->addGlobal('db', $db); + if (isset($twig)) { + $twig->addGlobal('db', $db); + } } catch (Exception $e) { if(isset($cache) && $cache->enabled()) { From 7c92d1c19734b912b1ed0587e6ba680fc18d409f Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 14 May 2025 15:11:20 +0200 Subject: [PATCH 019/222] Start v1.5.1-dev --- common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.php b/common.php index 2ac2c2de..7fc7f95f 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.5'; +const MYAAC_VERSION = '1.5.1-dev'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 1e9b10d6489c488cadf7f6ed17b42f1ea6c767a8 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 15 May 2025 19:11:20 +0200 Subject: [PATCH 020/222] Fix twig variables: logged + account_logged being not set directly after login --- system/init.php | 3 +++ system/pages/account/login.php | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/system/init.php b/system/init.php index ba2990db..44634265 100644 --- a/system/init.php +++ b/system/init.php @@ -138,6 +138,9 @@ $ots = POT::getInstance(); $eloquentConnection = null; require_once SYSTEM . 'database.php'; +$twig->addGlobal('logged', false); +$twig->addGlobal('account_logged', new \OTS_Account()); + // 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 ' . (IS_CLI ? 'http://your-ip.com/' : BASE_URL) . 'install'); diff --git a/system/pages/account/login.php b/system/pages/account/login.php index 3e8ebba3..c95019d6 100644 --- a/system/pages/account/login.php +++ b/system/pages/account/login.php @@ -95,3 +95,8 @@ else { } $hooks->trigger(HOOK_ACCOUNT_LOGIN_POST); + +if($logged) { + $twig->addGlobal('logged', true); + $twig->addGlobal('account_logged', $account_logged); +} From e5749437074c3b3556628a2aeb5bad2edf97bde0 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 23 May 2025 08:39:09 +0200 Subject: [PATCH 021/222] feat: autoload settings.php --- system/src/Plugins.php | 31 +++++++++++++++++++++++++++++-- system/src/Settings.php | 4 ++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/system/src/Plugins.php b/system/src/Plugins.php index 4acca75e..2e55cce8 100644 --- a/system/src/Plugins.php +++ b/system/src/Plugins.php @@ -346,6 +346,25 @@ class Plugins { } $settings = []; + foreach (self::getAllPluginsJson() as $plugin) { + if (!self::getAutoLoadOption($plugin, 'settings', true)) { + continue; + } + + $settingsFileName = PLUGINS . $plugin['filename'] . '/settings.php'; + if (!is_file($settingsFileName)) { + continue; + } + + $settingsFile = require $settingsFileName; + if (!isset($settingsFile['key'])) { + warning("Settings file for plugin - {$plugin['name']} does not contain 'key' field"); + continue; + } + + $settings[$settingsFile['key']] = ['pluginFilename' => $plugin['filename'], 'settingsFilename' => 'plugins/' . $plugin['filename'] . '/settings.php']; + } + foreach (self::getAllPluginsJson() as $plugin) { if (isset($plugin['settings'])) { $settingsFile = require BASE . $plugin['settings']; @@ -401,8 +420,14 @@ class Plugins { return false; } - if (!isset($plugin_json['settings']) || !file_exists(BASE . $plugin_json['settings'])) { - return false; + $settingsFileName = PLUGINS . $plugin_json['filename'] . '/settings.php'; + if (!is_file($settingsFileName)) { + if (!isset($plugin_json['settings']) || !is_file(BASE . $plugin_json['settings'])) { + return false; + } + } + else { + return 'plugins/' . $plugin_json['filename'] . '/settings.php'; } return $plugin_json['settings']; @@ -432,6 +457,8 @@ class Plugins { return false; } + $plugin_json['filename'] = $filename; + return $plugin_json; } diff --git a/system/src/Settings.php b/system/src/Settings.php index 0df8fa81..ca4192ad 100644 --- a/system/src/Settings.php +++ b/system/src/Settings.php @@ -560,8 +560,8 @@ class Settings implements \ArrayAccess $settingsFilePath = BASE . $settings[$pluginKeyName]['settingsFilename']; } - if (!file_exists($settingsFilePath)) { - throw new \RuntimeException('Failed to load settings file for plugin: ' . $pluginKeyName); + if (!is_file($settingsFilePath)) { + throw new \RuntimeException('Failed to load settings file for plugin: ' . $pluginKeyName . ' (Tried: ' . $settingsFilePath . ')'); } $this->settingsFile[$pluginKeyName] = require $settingsFilePath; From 7d213f479a7e40c6254069b5fc4e578dc32bf8d9 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 23 May 2025 08:50:38 +0200 Subject: [PATCH 022/222] feat: autoload install.php --- system/src/Plugins.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/system/src/Plugins.php b/system/src/Plugins.php index 2e55cce8..8e284484 100644 --- a/system/src/Plugins.php +++ b/system/src/Plugins.php @@ -677,10 +677,15 @@ class Plugins { return false; } - if (isset($plugin_json['install'])) { - if (file_exists(BASE . $plugin_json['install'])) { + $install = $plugin_json['install'] ?? ''; + if (self::getAutoLoadOption($plugin_json, 'install', true) && is_file(PLUGINS . $pluginFilename . '/install.php')) { + $install = 'plugins/' . $pluginFilename . '/install.php'; + } + + if (!empty($install)) { + if (file_exists(BASE . $install)) { $db->revalidateCache(); - require BASE . $plugin_json['install']; + require BASE . $install; $db->revalidateCache(); } else From be7b27c31aa3bbd6c0289c34d1e61139a3fe015c Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 23 May 2025 09:04:45 +0200 Subject: [PATCH 023/222] Fix links not working in admin dashboard modules --- admin/pages/modules/balance.php | 2 +- admin/pages/modules/coins.php | 7 ++++++- admin/pages/modules/lastlogin.php | 2 +- admin/pages/modules/templates/balance.html.twig | 2 +- admin/pages/modules/templates/coins.html.twig | 2 +- admin/pages/modules/templates/lastlogin.html.twig | 2 +- admin/pages/modules/templates/points.html.twig | 2 +- 7 files changed, 12 insertions(+), 7 deletions(-) diff --git a/admin/pages/modules/balance.php b/admin/pages/modules/balance.php index d700ef16..82070469 100644 --- a/admin/pages/modules/balance.php +++ b/admin/pages/modules/balance.php @@ -7,7 +7,7 @@ defined('MYAAC') or die('Direct access not allowed!'); $balance = 0; if ($db->hasColumn('players', 'balance')) { - $balance = Player::orderByDesc('balance')->limit(10)->get(['balance', 'id','name', 'level'])->toArray(); + $balance = Player::orderByDesc('balance')->limit(10)->get(['id', 'name', 'balance'])->toArray(); } $twig->display('balance.html.twig', array( diff --git a/admin/pages/modules/coins.php b/admin/pages/modules/coins.php index 725c2e45..939ee16c 100644 --- a/admin/pages/modules/coins.php +++ b/admin/pages/modules/coins.php @@ -7,7 +7,12 @@ defined('MYAAC') or die('Direct access not allowed!'); $coins = 0; if ($db->hasColumn('accounts', 'coins')) { - $coins = Account::orderByDesc('coins')->limit(10)->get(['coins', (USE_ACCOUNT_NAME ? 'name' : 'id')])->toArray(); + $whatToGet = ['id', 'coins']; + if (USE_ACCOUNT_NAME) { + $whatToGet[] = 'name'; + } + + $coins = Account::orderByDesc('coins')->limit(10)->get($whatToGet)->toArray(); } $twig->display('coins.html.twig', array( diff --git a/admin/pages/modules/lastlogin.php b/admin/pages/modules/lastlogin.php index 7fae3469..f20b11d2 100644 --- a/admin/pages/modules/lastlogin.php +++ b/admin/pages/modules/lastlogin.php @@ -7,7 +7,7 @@ defined('MYAAC') or die('Direct access not allowed!'); $players = 0; if ($db->hasColumn('players', 'lastlogin')) { - $players = Player::orderByDesc('lastlogin')->limit(10)->get(['name', 'level', 'lastlogin'])->toArray(); + $players = Player::orderByDesc('lastlogin')->limit(10)->get(['id', 'name', 'level', 'lastlogin'])->toArray(); } $twig->display('lastlogin.html.twig', array( diff --git a/admin/pages/modules/templates/balance.html.twig b/admin/pages/modules/templates/balance.html.twig index 70f0dc62..ee4a1771 100644 --- a/admin/pages/modules/templates/balance.html.twig +++ b/admin/pages/modules/templates/balance.html.twig @@ -19,7 +19,7 @@ {% set i = i + 1 %}
- + {% endfor %} diff --git a/admin/pages/modules/templates/coins.html.twig b/admin/pages/modules/templates/coins.html.twig index a822dfd5..722064f8 100644 --- a/admin/pages/modules/templates/coins.html.twig +++ b/admin/pages/modules/templates/coins.html.twig @@ -19,7 +19,7 @@ {% set i = i + 1 %} - + {% endfor %} diff --git a/admin/pages/modules/templates/lastlogin.html.twig b/admin/pages/modules/templates/lastlogin.html.twig index 4127671d..dbf628e0 100644 --- a/admin/pages/modules/templates/lastlogin.html.twig +++ b/admin/pages/modules/templates/lastlogin.html.twig @@ -19,7 +19,7 @@ {% set i = i + 1 %} - + {% endfor %} diff --git a/admin/pages/modules/templates/points.html.twig b/admin/pages/modules/templates/points.html.twig index 019a9964..d30a3e36 100644 --- a/admin/pages/modules/templates/points.html.twig +++ b/admin/pages/modules/templates/points.html.twig @@ -19,7 +19,7 @@ {% set i = i + 1 %} - + {% endfor %} From 4d8f5f31ae3c12553b7aad1da555101b8084f3cd Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 23 May 2025 09:04:48 +0200 Subject: [PATCH 024/222] Update Plugins.php --- system/src/Plugins.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/src/Plugins.php b/system/src/Plugins.php index 8e284484..438fe32e 100644 --- a/system/src/Plugins.php +++ b/system/src/Plugins.php @@ -688,8 +688,9 @@ class Plugins { require BASE . $install; $db->revalidateCache(); } - else + else { self::$warnings[] = 'Cannot load install script. Your plugin might be not working correctly.'; + } } clearCache(); From 4a30fb495dbfbe1d434e8d52419eaf44fe517aee Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 23 May 2025 09:13:20 +0200 Subject: [PATCH 025/222] Fix CHANGELOG-1.x.md loading --- admin/pages/clmd.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/pages/clmd.php b/admin/pages/clmd.php index f0ad49d3..fa06a130 100644 --- a/admin/pages/clmd.php +++ b/admin/pages/clmd.php @@ -11,12 +11,12 @@ defined('MYAAC') or die('Direct access not allowed!'); $title = 'MyAAC Changelog'; -if (!file_exists(BASE . 'CHANGELOG.md')) { +if (!file_exists(BASE . 'CHANGELOG-1.x.md')) { echo 'File CHANGELOG.md doesn\'t exist.'; return; } -$changelog = file_get_contents(BASE . 'CHANGELOG.md'); +$changelog = file_get_contents(BASE . 'CHANGELOG-1.x.md'); $Parsedown = new Parsedown(); From 2ea549002a4796d1c9eb064340796ea3fb5279cc Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 23 May 2025 15:58:23 +0200 Subject: [PATCH 026/222] Nothing important: tabs --- system/libs/pot/OTS_ServerInfo.php | 204 ++++++++++++++--------------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/system/libs/pot/OTS_ServerInfo.php b/system/libs/pot/OTS_ServerInfo.php index eebe0d2e..e39f9fe7 100644 --- a/system/libs/pot/OTS_ServerInfo.php +++ b/system/libs/pot/OTS_ServerInfo.php @@ -26,14 +26,14 @@ class OTS_ServerInfo * * @var string */ - private $server; + private $server; /** * Connection port. * * @var int */ - private $port; + private $port; /** * Creates handler for new server. @@ -41,11 +41,11 @@ class OTS_ServerInfo * @param string $server Server IP/domain. * @param int $port OTServ port. */ - public function __construct($server, $port) - { - $this->server = $server; - $this->port = $port; - } + public function __construct($server, $port) + { + $this->server = $server; + $this->port = $port; + } /** * Sends packet to server. @@ -54,46 +54,46 @@ class OTS_ServerInfo * @return OTS_Buffer|null Respond buffer (null if server is offline). * @throws E_OTS_OutOfBuffer When there is read attemp after end of packet stream. */ - private function send(OTS_Buffer $packet) - { - // connects to server - $socket = @fsockopen($this->server, $this->port, $error, $message, setting('core.status_timeout')); + private function send(OTS_Buffer $packet) + { + // connects to server + $socket = @fsockopen($this->server, $this->port, $error, $message, setting('core.status_timeout')); - // if connected then checking statistics - if($socket) - { - // sets 5 second timeout for reading and writing - stream_set_timeout($socket, 5); + // if connected then checking statistics + if($socket) + { + // sets 5 second timeout for reading and writing + stream_set_timeout($socket, 5); - // creates real packet - $packet = $packet->getBuffer(); - $packet = pack('v', strlen($packet) ) . $packet; + // creates real packet + $packet = $packet->getBuffer(); + $packet = pack('v', strlen($packet) ) . $packet; - // sends packet with request - // 06 - length of packet, 255, 255 is the comamnd identifier, 'info' is a request - fwrite($socket, $packet); + // sends packet with request + // 06 - length of packet, 255, 255 is the comamnd identifier, 'info' is a request + fwrite($socket, $packet); - // reads respond - //$data = stream_get_contents($socket); + // reads respond + //$data = stream_get_contents($socket); $data = ''; while (!feof($socket)) $data .= fgets($socket, 1024); - // closing connection to current server - fclose($socket); + // closing connection to current server + fclose($socket); - // sometimes server returns empty info - if( empty($data) ) - { - // returns offline state - return false; - } + // sometimes server returns empty info + if( empty($data) ) + { + // returns offline state + return false; + } - return new OTS_Buffer($data); - } + return new OTS_Buffer($data); + } - return false; - } + return false; + } /** * Queries server status. @@ -108,30 +108,30 @@ class OTS_ServerInfo * @example examples/info.php info.php * @tutorial POT/Server_status.pkg */ - public function status() - { - // request packet - $request = new OTS_Buffer(); - $request->putChar(255); - $request->putChar(255); - $request->putString('info', false); + public function status() + { + // request packet + $request = new OTS_Buffer(); + $request->putChar(255); + $request->putChar(255); + $request->putString('info', false); - $status = $this->send($request); + $status = $this->send($request); - // checks if server is online - if($status) - { - // loads respond XML - $info = new OTS_InfoRespond(); - if(!$info->loadXML( $status->getBuffer())) + // checks if server is online + if($status) + { + // loads respond XML + $info = new OTS_InfoRespond(); + if(!$info->loadXML( $status->getBuffer())) return false; - return $info; - } + return $info; + } - // offline - return false; - } + // offline + return false; + } /** * Queries server information. @@ -146,26 +146,26 @@ class OTS_ServerInfo * @example examples/server.php info.php * @tutorial POT/Server_status.pkg */ - public function info($flags) - { - // request packet - $request = new OTS_Buffer(); - $request->putChar(255); - $request->putChar(1); - $request->putShort($flags); + public function info($flags) + { + // request packet + $request = new OTS_Buffer(); + $request->putChar(255); + $request->putChar(1); + $request->putShort($flags); - $status = $this->send($request); + $status = $this->send($request); - // checks if server is online - if($status) - { - // loads respond - return new OTS_ServerStatus($status); - } + // checks if server is online + if($status) + { + // loads respond + return new OTS_ServerStatus($status); + } - // offline - return false; - } + // offline + return false; + } /** * Checks player online status. @@ -180,27 +180,27 @@ class OTS_ServerInfo * @example examples/server.php info.php * @tutorial POT/Server_status.pkg */ - public function playerStatus($name) - { - // request packet - $request = new OTS_Buffer(); - $request->putChar(255); - $request->putChar(1); - $request->putShort(OTS_ServerStatus::REQUEST_PLAYER_STATUS_INFO); - $request->putString($name); + public function playerStatus($name) + { + // request packet + $request = new OTS_Buffer(); + $request->putChar(255); + $request->putChar(1); + $request->putShort(OTS_ServerStatus::REQUEST_PLAYER_STATUS_INFO); + $request->putString($name); - $status = $this->send($request); + $status = $this->send($request); - // checks if server is online - if($status) - { - $status->getChar(); - return (bool) $status->getChar(); - } + // checks if server is online + if($status) + { + $status->getChar(); + return (bool) $status->getChar(); + } - // offline - return false; - } + // offline + return false; + } /** * Magic PHP5 method. @@ -210,20 +210,20 @@ class OTS_ServerInfo * @throws OutOfBoundsException For non-supported properties. * @throws E_OTS_OutOfBuffer When there is read attemp after end of packet stream. */ - public function __get($name) - { - switch($name) - { - case 'status': - return $this->status(); + public function __get($name) + { + switch($name) + { + case 'status': + return $this->status(); - case 'info': - return $this->info(OTS_ServerStatus::REQUEST_BASIC_SERVER_INFO | OTS_ServerStatus::REQUEST_OWNER_SERVER_INFO | OTS_ServerStatus::REQUEST_MISC_SERVER_INFO | OTS_ServerStatus::REQUEST_PLAYERS_INFO | OTS_ServerStatus::REQUEST_MAP_INFO | OTS_ServerStatus::REQUEST_PLAYER_STATUS_INFO); + case 'info': + return $this->info(OTS_ServerStatus::REQUEST_BASIC_SERVER_INFO | OTS_ServerStatus::REQUEST_OWNER_SERVER_INFO | OTS_ServerStatus::REQUEST_MISC_SERVER_INFO | OTS_ServerStatus::REQUEST_PLAYERS_INFO | OTS_ServerStatus::REQUEST_MAP_INFO | OTS_ServerStatus::REQUEST_PLAYER_STATUS_INFO); - default: - throw new OutOfBoundsException(); - } - } + default: + throw new OutOfBoundsException(); + } + } } /**#@-*/ From 43153b2b0c2a4865b4bcf4cd616b3f7d5cafefa5 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 23 May 2025 16:08:02 +0200 Subject: [PATCH 027/222] Nothing important: tabs --- system/libs/pot/OTS.php | 1006 +++++++++++++++++++-------------------- 1 file changed, 503 insertions(+), 503 deletions(-) diff --git a/system/libs/pot/OTS.php b/system/libs/pot/OTS.php index a7327401..f739c709 100644 --- a/system/libs/pot/OTS.php +++ b/system/libs/pot/OTS.php @@ -32,19 +32,19 @@ class POT /** * North. */ - const DIRECTION_NORTH = 0; + const DIRECTION_NORTH = 0; /** * East. */ - const DIRECTION_EAST = 1; + const DIRECTION_EAST = 1; /** * South. */ - const DIRECTION_SOUTH = 2; + const DIRECTION_SOUTH = 2; /** * West. */ - const DIRECTION_WEST = 3; + const DIRECTION_WEST = 3; /** @@ -80,70 +80,70 @@ class POT * @version 0.0.3 * @since 0.0.3 */ - const SLOT_HEAD = 1; + const SLOT_HEAD = 1; /** * Necklace slot. * * @version 0.0.3 * @since 0.0.3 */ - const SLOT_NECKLACE = 2; + const SLOT_NECKLACE = 2; /** * Backpack slot. * * @version 0.0.3 * @since 0.0.3 */ - const SLOT_BACKPACK = 3; + const SLOT_BACKPACK = 3; /** * Armor slot. * * @version 0.0.3 * @since 0.0.3 */ - const SLOT_ARMOR = 4; + const SLOT_ARMOR = 4; /** * Right hand slot. * * @version 0.0.3 * @since 0.0.3 */ - const SLOT_RIGHT = 5; + const SLOT_RIGHT = 5; /** * Left hand slot. * * @version 0.0.3 * @since 0.0.3 */ - const SLOT_LEFT = 6; + const SLOT_LEFT = 6; /** * Legs slot. * * @version 0.0.3 * @since 0.0.3 */ - const SLOT_LEGS = 7; + const SLOT_LEGS = 7; /** * Boots slot. * * @version 0.0.3 * @since 0.0.3 */ - const SLOT_FEET = 8; + const SLOT_FEET = 8; /** * Ring slot. * * @version 0.0.3 * @since 0.0.3 */ - const SLOT_RING = 9; + const SLOT_RING = 9; /** * Ammunition slot. * * @version 0.0.3 * @since 0.0.3 */ - const SLOT_AMMO = 10; + const SLOT_AMMO = 10; /** * First depot item sid. @@ -151,7 +151,7 @@ class POT * @version 0.0.4 * @since 0.0.4 */ - const DEPOT_SID_FIRST = 100; + const DEPOT_SID_FIRST = 100; /** * IP ban. @@ -159,21 +159,21 @@ class POT * @version 0.0.5 * @since 0.0.5 */ - const BAN_IP = 1; + const BAN_IP = 1; /** * Player ban. * * @version 0.0.5 * @since 0.0.5 */ - const BAN_PLAYER = 2; + const BAN_PLAYER = 2; /** * Account ban. * * @version 0.0.5 * @since 0.0.5 */ - const BAN_ACCOUNT = 3; + const BAN_ACCOUNT = 3; /** * Ascencind sorting order. @@ -181,33 +181,33 @@ class POT * @version 0.0.5 * @since 0.0.5 */ - const ORDER_ASC = 1; + const ORDER_ASC = 1; /** * Descending sorting order. * * @version 0.0.5 * @since 0.0.5 */ - const ORDER_DESC = 2; + const ORDER_DESC = 2; /** * @version 0.0.7 * @since 0.0.7 * @deprecated 0.1.0 Use OTS_SpellsList::SPELL_RUNE. */ - const SPELL_RUNE = 0; + const SPELL_RUNE = 0; /** * @version 0.0.7 * @since 0.0.7 * @deprecated 0.1.0 Use OTS_SpellsList::SPELL_INSTANT. */ - const SPELL_INSTANT = 1; + const SPELL_INSTANT = 1; /** * @version 0.0.7 * @since 0.0.7 * @deprecated 0.1.0 Use OTS_SpellsList::SPELL_CONJURE. */ - const SPELL_CONJURE = 2; + const SPELL_CONJURE = 2; /** * Singleton. @@ -220,18 +220,18 @@ class POT * @example examples/quickstart.php quickstart.php * @tutorial POT/Basics.pkg#basics.instance */ - public static function getInstance() - { - static $instance; + public static function getInstance() + { + static $instance; - // creates new instance - if( !isset($instance) ) - { - $instance = new self(); - } + // creates new instance + if( !isset($instance) ) + { + $instance = new self(); + } - return $instance; - } + return $instance; + } /** * POT classes directory. @@ -242,7 +242,7 @@ class POT * * @var string */ - private $path = ''; + private $path = ''; /** * Set POT directory. @@ -255,16 +255,16 @@ class POT * @example examples/fakeroot.php fakeroot.php * @tutorial POT/Basics.pkg#basics.fakeroot */ - public function setPOTPath($path) - { - $this->path = str_replace('\\', '/', $path); + public function setPOTPath($path) + { + $this->path = str_replace('\\', '/', $path); - // appends ending slash to directory path - if( substr($this->path, -1) !== '/') - { - $this->path .= '/'; - } - } + // appends ending slash to directory path + if( substr($this->path, -1) !== '/') + { + $this->path .= '/'; + } + } /** * Class initialization tools. @@ -283,13 +283,13 @@ class POT * * @version 0.0.3 */ - private function __construct() - { - // default POT directory - $this->path = __DIR__ . '/'; - // registers POT autoload mechanism - spl_autoload_register( array($this, 'loadClass') ); - } + private function __construct() + { + // default POT directory + $this->path = __DIR__ . '/'; + // registers POT autoload mechanism + spl_autoload_register( array($this, 'loadClass') ); + } /** * Loads POT class file. @@ -309,13 +309,13 @@ class POT * @version 0.0.3 * @param string $class Class name. */ - public function loadClass($class) - { - if( preg_match('/^(I|E_)?OTS_/', $class) > 0) - { - include_once($this->path . $class . '.php'); - } - } + public function loadClass($class) + { + if( preg_match('/^(I|E_)?OTS_/', $class) > 0) + { + include_once($this->path . $class . '.php'); + } + } /** * Database connection. @@ -326,7 +326,7 @@ class POT * * @var OTS_DB_MySQL */ - private $db; + private $db; /** * Connects to database. @@ -363,14 +363,14 @@ class POT * @example examples/quickstart.php quickstart.php * @tutorial POT/Basics.pkg#basics.database */ - public function connect($params) - { - // checks if PDO extension is loaded - if( !extension_loaded('PDO') ) { - throw new RuntimeException('Please install PHP pdo extension. MyAAC will not work without it.'); - } + public function connect($params) + { + // checks if PDO extension is loaded + if( !extension_loaded('PDO') ) { + throw new RuntimeException('Please install PHP pdo extension. MyAAC will not work without it.'); + } - global $debugBar; + global $debugBar; if (isset($debugBar)) { $this->db = new DebugBar\DataCollector\PDO\TraceablePDO(new OTS_DB_MySQL($params)); $debugBar->addCollector(new DebugBar\DataCollector\PDO\PDOCollector($this->db)); @@ -379,8 +379,8 @@ class POT $this->db = new OTS_DB_MySQL($params); } - $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - } + $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + } /** * @version 0.1.0 @@ -388,11 +388,11 @@ class POT * @return IOTS_DAO OTServ database object. * @deprecated 0.1.0 Create objects directly from now. */ - public function createObject($class) - { - $class = 'OTS_' . $class; - return new $class(); - } + public function createObject($class) + { + $class = 'OTS_' . $class; + return new $class(); + } /** * Queries server status. @@ -415,11 +415,11 @@ class POT * @tutorial POT/Server_status.pkg * @deprecated 0.1.4 Use OTS_ServerInfo->status(). */ - public static function serverStatus($server, $port) - { - $status = new OTS_ServerInfo($server, $port); - return $status->status(); - } + public static function serverStatus($server, $port) + { + $status = new OTS_ServerInfo($server, $port); + return $status->status(); + } /** * Returns database connection handle. @@ -440,10 +440,10 @@ class POT * @since 0.0.4 * @return OTS_DB_MySQL Database connection handle. */ - public function getDBHandle() - { - return $this->db; - } + public function getDBHandle() + { + return $this->db; + } /** * Bans given IP number. @@ -464,37 +464,37 @@ class POT * @throws PDOException On PDO operation error. * @deprecated 0.1.5 Use OTS_IPBan class. */ - public function banIP($ip, $mask = '255.255.255.255', $time = 0) - { - // long2ip( ip2long('255.255.255.255') ) != '255.255.255.255' -.-' - // it's because that PHP integer types are signed - if($ip === '255.255.255.255') - { - $ip = 4294967295; - } - else - { - $ip = sprintf('%u', ip2long($ip) ); - } + public function banIP($ip, $mask = '255.255.255.255', $time = 0) + { + // long2ip( ip2long('255.255.255.255') ) != '255.255.255.255' -.-' + // it's because that PHP integer types are signed + if($ip === '255.255.255.255') + { + $ip = 4294967295; + } + else + { + $ip = sprintf('%u', ip2long($ip) ); + } - if($mask === '255.255.255.255') - { - $mask = 4294967295; - } - else - { - $mask = sprintf('%u', ip2long($mask) ); - } + if($mask === '255.255.255.255') + { + $mask = 4294967295; + } + else + { + $mask = sprintf('%u', ip2long($mask) ); + } - // creates ban entry - $ban = new OTS_IPBan(); - $ban->setValue($ip); - $ban->setParam($mask); - $ban->setExpires($time); - $ban->setAdded( time() ); - $ban->activate(); - $ban->save(); - } + // creates ban entry + $ban = new OTS_IPBan(); + $ban->setValue($ip); + $ban->setParam($mask); + $ban->setExpires($time); + $ban->setAdded( time() ); + $ban->activate(); + $ban->save(); + } /** * Deletes ban from given IP number. @@ -510,26 +510,26 @@ class POT * @throws PDOException On PDO operation error. * @deprecated 0.1.5 Use OTS_IPBan class. */ - public function unbanIP($ip, $mask = '255.255.255.255') - { - // long2ip( ip2long('255.255.255.255') ) != '255.255.255.255' -.-' - // it's because that PHP integer types are signed - if($ip === '255.255.255.255') - { - $ip = 4294967295; - } - else - { - $ip = sprintf('%u', ip2long($ip) ); - } + public function unbanIP($ip, $mask = '255.255.255.255') + { + // long2ip( ip2long('255.255.255.255') ) != '255.255.255.255' -.-' + // it's because that PHP integer types are signed + if($ip === '255.255.255.255') + { + $ip = 4294967295; + } + else + { + $ip = sprintf('%u', ip2long($ip) ); + } - // mask is not used anymore + // mask is not used anymore - // deletes ban entry - $ban = new OTS_IPBan(); - $ban->find($ip); - $ban->delete(); - } + // deletes ban entry + $ban = new OTS_IPBan(); + $ban->find($ip); + $ban->delete(); + } /** * Checks if given IP is banned. @@ -541,24 +541,24 @@ class POT * @throws PDOException On PDO operation error. * @deprecated 0.1.5 Use OTS_IPBan class. */ - public function isIPBanned($ip) - { - // long2ip( ip2long('255.255.255.255') ) != '255.255.255.255' -.-' - // it's because that PHP integer types are signed - if($ip === '255.255.255.255') - { - $ip = 4294967295; - } - else - { - $ip = sprintf('%u', ip2long($ip) ); - } + public function isIPBanned($ip) + { + // long2ip( ip2long('255.255.255.255') ) != '255.255.255.255' -.-' + // it's because that PHP integer types are signed + if($ip === '255.255.255.255') + { + $ip = 4294967295; + } + else + { + $ip = sprintf('%u', ip2long($ip) ); + } - // finds ban entry - $ban = new OTS_IPBan(); - $ban->find($ip); - return $ban->isLoaded() && $ban->isActive() && ( $ban->getExpires() == 0 || $ban->getExpires() > time() ); - } + // finds ban entry + $ban = new OTS_IPBan(); + $ban->find($ip); + return $ban->isLoaded() && $ban->isActive() && ( $ban->getExpires() == 0 || $ban->getExpires() > time() ); + } /** * Returns list of banned IPs as list of pairs (ip => IP, mask => MASK). @@ -569,22 +569,22 @@ class POT * @throws PDOException On PDO operation error. * @deprecated 0.1.5 Use OTS_IPBans_List class. */ - public function bannedIPs() - { - $list = array(); + public function bannedIPs() + { + $list = array(); - // generates bans array - foreach( new OTS_IPBans_List() as $ban) - { - // checks if ban is active - if( $ban->isActive() && ( $ban->getExpires() == 0 || $ban->getExpires() > time() ) ) - { - $list[] = array('ip' => $ban->getValue(), 'mask' => $ban->getParam() ); - } - } + // generates bans array + foreach( new OTS_IPBans_List() as $ban) + { + // checks if ban is active + if( $ban->isActive() && ( $ban->getExpires() == 0 || $ban->getExpires() > time() ) ) + { + $list[] = array('ip' => $ban->getValue(), 'mask' => $ban->getParam() ); + } + } - return $list; - } + return $list; + } /** * @version 0.1.0 @@ -592,10 +592,10 @@ class POT * @return OTS_SQLFilter Filter object. * @deprecated 0.1.0 Create objects directly from now. */ - public function createFilter() - { - return new OTS_SQLFilter(); - } + public function createFilter() + { + return new OTS_SQLFilter(); + } /** * List of vocations. @@ -604,7 +604,7 @@ class POT * @since 0.0.5 * @var OTS_VocationsList */ - private $vocations; + private $vocations; /** * Loads vocations list. @@ -622,11 +622,11 @@ class POT * @param string $file vocations.xml file location. * @throws DOMException On DOM operation error. */ - public function loadVocations($file) - { - // loads DOM document - $this->vocations = new OTS_VocationsList($file); - } + public function loadVocations($file) + { + // loads DOM document + $this->vocations = new OTS_VocationsList($file); + } /** * Checks if vocations are loaded. @@ -639,10 +639,10 @@ class POT * @since 0.1.0 * @return bool True if vocations are loaded. */ - public function areVocationsLoaded() - { - return isset($this->vocations); - } + public function areVocationsLoaded() + { + return isset($this->vocations); + } /** * Unloads vocations list. @@ -650,10 +650,10 @@ class POT * @version 0.1.0 * @since 0.1.0 */ - public function unloadVocations() - { - unset($this->vocations); - } + public function unloadVocations() + { + unset($this->vocations); + } /** * Returns vocations list object. @@ -667,15 +667,15 @@ class POT * @return OTS_VocationsList List of vocations. * @throws E_OTS_NotLoaded If vocations list is not loaded. */ - public function getVocationsList() - { - if( isset($this->vocations) ) - { - return $this->vocations; - } + public function getVocationsList() + { + if( isset($this->vocations) ) + { + return $this->vocations; + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * @version 0.1.3 @@ -685,15 +685,15 @@ class POT * @throws E_OTS_NotLoaded If vocations list is not loaded. * @deprecated 0.1.3 Use POT::getVocationsList()->getVocationId(). */ - public function getVocationId($name) - { - if( isset($this->vocations) ) - { - return $this->vocations->getVocationId($name); - } + public function getVocationId($name) + { + if( isset($this->vocations) ) + { + return $this->vocations->getVocationId($name); + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * @version 0.1.3 @@ -703,15 +703,15 @@ class POT * @throws E_OTS_NotLoaded If vocations list is not loaded. * @deprecated 0.1.3 Use POT::getVocationsList()->getVocationName(). */ - public function getVocationName($id) - { - if( isset($this->vocations) ) - { - return $this->vocations->getVocationName($id); - } + public function getVocationName($id) + { + if( isset($this->vocations) ) + { + return $this->vocations->getVocationName($id); + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * List of loaded monsters. @@ -720,7 +720,7 @@ class POT * @since 0.0.6 * @var OTS_MonstersList */ - private $monsters; + private $monsters; /** * Loads monsters mapping file. @@ -738,10 +738,10 @@ class POT * @param string $path Monsters directory. * @throws DOMException On DOM operation error. */ - public function loadMonsters($path) - { - $this->monsters = new OTS_MonstersList($path); - } + public function loadMonsters($path) + { + $this->monsters = new OTS_MonstersList($path); + } /** * Checks if monsters are loaded. @@ -754,10 +754,10 @@ class POT * @since 0.1.0 * @return bool True if monsters are loaded. */ - public function areMonstersLoaded() - { - return isset($this->monsters); - } + public function areMonstersLoaded() + { + return isset($this->monsters); + } /** * Unloads monsters list. @@ -765,10 +765,10 @@ class POT * @version 0.1.0 * @since 0.1.0 */ - public function unloadMonsters() - { - unset($this->monsters); - } + public function unloadMonsters() + { + unset($this->monsters); + } /** * Returns list of laoded monsters. @@ -782,15 +782,15 @@ class POT * @return OTS_MonstersList List of monsters. * @throws E_OTS_NotLoaded If monsters list is not loaded. */ - public function getMonstersList() - { - if( isset($this->monsters) ) - { - return $this->monsters; - } + public function getMonstersList() + { + if( isset($this->monsters) ) + { + return $this->monsters; + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * @version 0.1.3 @@ -800,15 +800,15 @@ class POT * @throws E_OTS_NotLoaded If monsters list is not loaded. * @deprecated 0.1.3 Use POT::getMonstersList()->getMonster(). */ - public function getMonster($name) - { - if( isset($this->monsters) ) - { - return $this->monsters->getMonster($name); - } + public function getMonster($name) + { + if( isset($this->monsters) ) + { + return $this->monsters->getMonster($name); + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * Spells list. @@ -817,7 +817,7 @@ class POT * @since 0.1.0 * @var OTS_SpellsList */ - private $spells; + private $spells; /** * Loads spells list. @@ -835,10 +835,10 @@ class POT * @param string $file Spells file name. * @throws DOMException On DOM operation error. */ - public function loadSpells($file) - { - $this->spells = new OTS_SpellsList($file); - } + public function loadSpells($file) + { + $this->spells = new OTS_SpellsList($file); + } /** * Checks if spells are loaded. @@ -851,10 +851,10 @@ class POT * @since 0.1.0 * @return bool True if spells are loaded. */ - public function areSpellsLoaded() - { - return isset($this->spells); - } + public function areSpellsLoaded() + { + return isset($this->spells); + } /** * Unloads spells list. @@ -862,10 +862,10 @@ class POT * @version 0.1.0 * @since 0.1.0 */ - public function unloadSpells() - { - unset($this->spells); - } + public function unloadSpells() + { + unset($this->spells); + } /** * Returns list of laoded spells. @@ -875,15 +875,15 @@ class POT * @return OTS_SpellsList List of spells. * @throws E_OTS_NotLoaded If spells list is not loaded. */ - public function getSpellsList() - { - if( isset($this->spells) ) - { - return $this->spells; - } + public function getSpellsList() + { + if( isset($this->spells) ) + { + return $this->spells; + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * @version 0.1.3 @@ -892,15 +892,15 @@ class POT * @throws E_OTS_NotLoaded If spells list is not loaded. * @deprecated 0.1.3 Use POT::getSpellsList()->getRunesList(). */ - public function getRunesList() - { - if( isset($this->spells) ) - { - return $this->spells->getRunesList(); - } + public function getRunesList() + { + if( isset($this->spells) ) + { + return $this->spells->getRunesList(); + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * @version 0.1.3 @@ -910,15 +910,15 @@ class POT * @throws E_OTS_NotLoaded If spells list is not loaded. * @deprecated 0.1.3 Use POT::getSpellsList()->getRune(). */ - public function getRune($name) - { - if( isset($this->spells) ) - { - return $this->spells->getRune($name); - } + public function getRune($name) + { + if( isset($this->spells) ) + { + return $this->spells->getRune($name); + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * @version 0.1.3 @@ -927,15 +927,15 @@ class POT * @throws E_OTS_NotLoaded If spells list is not loaded. * @deprecated 0.1.3 Use POT::getSpellsList()->getInstantsList(). */ - public function getInstantsList() - { - if( isset($this->spells) ) - { - return $this->spells->getInstantsList(); - } + public function getInstantsList() + { + if( isset($this->spells) ) + { + return $this->spells->getInstantsList(); + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * @version 0.1.3 @@ -945,15 +945,15 @@ class POT * @throws E_OTS_NotLoaded If spells list is not loaded. * @deprecated 0.1.3 Use POT::getSpellsList()->getInstant(). */ - public function getInstant($name) - { - if( isset($this->spells) ) - { - return $this->spells->getInstant($name); - } + public function getInstant($name) + { + if( isset($this->spells) ) + { + return $this->spells->getInstant($name); + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * @version 0.1.3 @@ -962,15 +962,15 @@ class POT * @throws E_OTS_NotLoaded If spells list is not loaded. * @deprecated 0.1.3 Use POT::getSpellsList()->getConjuresList(). */ - public function getConjuresList() - { - if( isset($this->spells) ) - { - return $this->spells->getConjuresList(); - } + public function getConjuresList() + { + if( isset($this->spells) ) + { + return $this->spells->getConjuresList(); + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * @version 0.1.3 @@ -980,15 +980,15 @@ class POT * @throws E_OTS_NotLoaded If spells list is not loaded. * @deprecated 0.1.3 Use POT::getSpellsList()->getConjure(). */ - public function getConjure($name) - { - if( isset($this->spells) ) - { - return $this->spells->getConjure($name); - } + public function getConjure($name) + { + if( isset($this->spells) ) + { + return $this->spells->getConjure($name); + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * List of loaded houses. @@ -997,7 +997,7 @@ class POT * @since 0.1.0 * @var OTS_HousesList */ - private $houses; + private $houses; /** * Loads houses list file. @@ -1011,10 +1011,10 @@ class POT * @param string $path Houses file. * @throws DOMException On DOM operation error. */ - public function loadHouses($path) - { - $this->houses = new OTS_HousesList($path); - } + public function loadHouses($path) + { + $this->houses = new OTS_HousesList($path); + } /** * Checks if houses are loaded. @@ -1027,10 +1027,10 @@ class POT * @since 0.1.0 * @return bool True if houses are loaded. */ - public function areHousesLoaded() - { - return isset($this->houses); - } + public function areHousesLoaded() + { + return isset($this->houses); + } /** * Unloads houses list. @@ -1038,10 +1038,10 @@ class POT * @version 0.1.0 * @since 0.1.0 */ - public function unloadHouses() - { - unset($this->houses); - } + public function unloadHouses() + { + unset($this->houses); + } /** * Returns list of laoded houses. @@ -1051,15 +1051,15 @@ class POT * @return OTS_HousesList List of houses. * @throws E_OTS_NotLoaded If houses list is not loaded. */ - public function getHousesList() - { - if( isset($this->houses) ) - { - return $this->houses; - } + public function getHousesList() + { + if( isset($this->houses) ) + { + return $this->houses; + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * @version 0.1.3 @@ -1069,15 +1069,15 @@ class POT * @throws E_OTS_NotLoaded If houses list is not loaded. * @deprecated 0.1.3 Use POT::getHousesList()->getHouse(). */ - public function getHouse($id) - { - if( isset($this->houses) ) - { - return $this->houses->getHouse($id); - } + public function getHouse($id) + { + if( isset($this->houses) ) + { + return $this->houses->getHouse($id); + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * @version 0.1.3 @@ -1087,15 +1087,15 @@ class POT * @throws E_OTS_NotLoaded If houses list is not loaded. * @deprecated 0.1.3 Use POT::getHousesList()->getHouseId(). */ - public function getHouseId($name) - { - if( isset($this->houses) ) - { - return $this->houses->getHouseId($name); - } + public function getHouseId($name) + { + if( isset($this->houses) ) + { + return $this->houses->getHouseId($name); + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * Cache handler for items loading. @@ -1104,7 +1104,7 @@ class POT * @since 0.1.0 * @var IOTS_FileCache */ - private $itemsCache; + private $itemsCache; /** * Presets cache handler for items loader. @@ -1115,10 +1115,10 @@ class POT * * @param IOTS_FileCache $cache Cache handler (skip this parameter to reset cache handler to null). */ - public function setItemsCache(?IOTS_FileCache $cache = null) - { - $this->itemsCache = $cache; - } + public function setItemsCache(?IOTS_FileCache $cache = null) + { + $this->itemsCache = $cache; + } /** * List of loaded items. @@ -1127,7 +1127,7 @@ class POT * @since 0.1.0 * @var OTS_ItemsList */ - private $items; + private $items; /** * Loads items list. @@ -1141,18 +1141,18 @@ class POT * @param string $path Items information directory. * @throws E_OTS_FileLoaderError On binary file loading error. */ - public function loadItems($path) - { - $this->items = new OTS_ItemsList(); + public function loadItems($path) + { + $this->items = new OTS_ItemsList(); - // sets items cache if any - if( isset($this->itemsCache) ) - { - $this->items->setCacheDriver($this->itemsCache); - } + // sets items cache if any + if( isset($this->itemsCache) ) + { + $this->items->setCacheDriver($this->itemsCache); + } - $this->items->loadItems($path); - } + $this->items->loadItems($path); + } /** * Checks if items are loaded. @@ -1165,10 +1165,10 @@ class POT * @since 0.1.0 * @return bool True if items are loaded. */ - public function areItemsLoaded() - { - return isset($this->items); - } + public function areItemsLoaded() + { + return isset($this->items); + } /** * Unloads items list. @@ -1176,10 +1176,10 @@ class POT * @version 0.1.0 * @since 0.1.0 */ - public function unloadItems() - { - unset($this->items); - } + public function unloadItems() + { + unset($this->items); + } /** * Returns list of laoded items. @@ -1189,15 +1189,15 @@ class POT * @return OTS_ItemsList List of items. * @throws E_OTS_NotLoaded If items list is not loaded. */ - public function getItemsList() - { - if( isset($this->items) ) - { - return $this->items; - } + public function getItemsList() + { + if( isset($this->items) ) + { + return $this->items; + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * @version 0.1.3 @@ -1207,15 +1207,15 @@ class POT * @throws E_OTS_NotLoaded If items list is not loaded. * @deprecated 0.1.3 Use POT::getItemsList()->getItemType(). */ - public function getItemType($id) - { - if( isset($this->items) ) - { - return $this->items->getItemType($id); - } + public function getItemType($id) + { + if( isset($this->items) ) + { + return $this->items->getItemType($id); + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * @version 0.1.3 @@ -1225,15 +1225,15 @@ class POT * @throws E_OTS_NotLoaded If items list is not loaded. * @deprecated 0.1.3 Use POT::getItemsList()->getItemTypeId(). */ - public function getItemTypeId($name) - { - if( isset($this->items) ) - { - return $this->items->getItemTypeId($name); - } + public function getItemTypeId($name) + { + if( isset($this->items) ) + { + return $this->items->getItemTypeId($name); + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * Cache handler for OTBM loading. @@ -1242,7 +1242,7 @@ class POT * @since 0.1.0 * @var IOTS_FileCache */ - private $mapCache; + private $mapCache; /** * Presets cache handler for OTBM loader. @@ -1253,10 +1253,10 @@ class POT * * @param IOTS_FileCache $cache Cache handler (skip this parameter to reset cache handler to null). */ - public function setMapCache(?IOTS_FileCache $cache = null) - { - $this->mapCache = $cache; - } + public function setMapCache(?IOTS_FileCache $cache = null) + { + $this->mapCache = $cache; + } /** * Loaded map. @@ -1265,7 +1265,7 @@ class POT * @since 0.1.0 * @var OTS_OTBMFile */ - private $map; + private $map; /** * Loads OTBM map. @@ -1282,19 +1282,19 @@ class POT * @since 0.1.0 * @param string $path Map file path. */ - public function loadMap($path) - { - $this->map = new OTS_OTBMFile(); + public function loadMap($path) + { + $this->map = new OTS_OTBMFile(); - // sets items cache if any - if( isset($this->mapCache) ) - { - $this->map->setCacheDriver($this->mapCache); - } + // sets items cache if any + if( isset($this->mapCache) ) + { + $this->map->setCacheDriver($this->mapCache); + } - $this->map->loadFile($path); - $this->houses = $this->map->getHousesList(); - } + $this->map->loadFile($path); + $this->houses = $this->map->getHousesList(); + } /** * Checks if OTBM is loaded. @@ -1307,10 +1307,10 @@ class POT * @since 0.1.0 * @return bool True if map is loaded. */ - public function isMapLoaded() - { - return isset($this->map); - } + public function isMapLoaded() + { + return isset($this->map); + } /** * Unloads OTBM map. @@ -1318,10 +1318,10 @@ class POT * @version 0.1.0 * @since 0.1.0 */ - public function unloadMap() - { - unset($this->map); - } + public function unloadMap() + { + unset($this->map); + } /** * Returns loaded map. @@ -1331,15 +1331,15 @@ class POT * @return OTS_OTBMFile Loaded OTBM file. * @throws E_OTS_NotLoaded If map is not loaded. */ - public function getMap() - { - if( isset($this->map) ) - { - return $this->map; - } + public function getMap() + { + if( isset($this->map) ) + { + return $this->map; + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * @version 0.1.3 @@ -1348,15 +1348,15 @@ class POT * @throws E_OTS_NotLoaded If map is not loaded. * @deprecated 0.1.3 Use POT::getMap()->getMapWidth(). */ - public function getMapWidth() - { - if( isset($this->map) ) - { - return $this->map->getWidth(); - } + public function getMapWidth() + { + if( isset($this->map) ) + { + return $this->map->getWidth(); + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * @version 0.1.3 @@ -1365,15 +1365,15 @@ class POT * @throws E_OTS_NotLoaded If map is not loaded. * @deprecated 0.1.3 Use POT::getMap()->getMapHeight(). */ - public function getMapHeight() - { - if( isset($this->map) ) - { - return $this->map->getHeight(); - } + public function getMapHeight() + { + if( isset($this->map) ) + { + return $this->map->getHeight(); + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * @version 0.1.3 @@ -1382,15 +1382,15 @@ class POT * @throws E_OTS_NotLoaded If map is not loaded. * @deprecated 0.1.3 Use POT::getMap()->getMapDescription(). */ - public function getMapDescription() - { - if( isset($this->map) ) - { - return $this->map->getDescription(); - } + public function getMapDescription() + { + if( isset($this->map) ) + { + return $this->map->getDescription(); + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * @version 0.1.3 @@ -1400,15 +1400,15 @@ class POT * @throws E_OTS_NotLoaded If map is not loaded. * @deprecated 0.1.3 Use POT::getMap()->getTownId(). */ - public function getTownId($name) - { - if( isset($this->map) ) - { - return $this->map->getTownId($name); - } + public function getTownId($name) + { + if( isset($this->map) ) + { + return $this->map->getTownId($name); + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * @version 0.1.3 @@ -1418,15 +1418,15 @@ class POT * @throws E_OTS_NotLoaded If map is not loaded. * @deprecated 0.1.3 Use POT::getMap()->getTownName(). */ - public function getTownName($id) - { - if( isset($this->map) ) - { - return $this->map->getTownName($id); - } + public function getTownName($id) + { + if( isset($this->map) ) + { + return $this->map->getTownName($id); + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * Display driver. @@ -1435,7 +1435,7 @@ class POT * @since 0.1.0 * @var IOTS_Display */ - private $display; + private $display; /** * Sets display driver for database-related resources. @@ -1444,10 +1444,10 @@ class POT * @since 0.1.0 * @param IOTS_Display $display Display driver. */ - public function setDisplayDriver(IOTS_Display $display) - { - $this->display = $display; - } + public function setDisplayDriver(IOTS_Display $display) + { + $this->display = $display; + } /** * Checks if any display driver is loaded. @@ -1460,10 +1460,10 @@ class POT * @since 0.1.0 * @return bool True if driver is loaded. */ - public function isDisplayDriverLoaded() - { - return isset($this->display); - } + public function isDisplayDriverLoaded() + { + return isset($this->display); + } /** * Unloads display driver. @@ -1471,10 +1471,10 @@ class POT * @version 0.1.0 * @since 0.1.0 */ - public function unloadDisplayDriver() - { - unset($this->display); - } + public function unloadDisplayDriver() + { + unset($this->display); + } /** * Returns current display driver. @@ -1488,15 +1488,15 @@ class POT * @return IOTS_Display Current display driver. * @throws E_OTS_NotLoaded If display driver is not loaded. */ - public function getDisplayDriver() - { - if( isset($this->display) ) - { - return $this->display; - } + public function getDisplayDriver() + { + if( isset($this->display) ) + { + return $this->display; + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } /** * Display driver for non-database resources. @@ -1505,7 +1505,7 @@ class POT * @since 0.1.3 * @var IOTS_DataDisplay */ - private $dataDisplay; + private $dataDisplay; /** * Sets display driver for non-database resources. @@ -1514,10 +1514,10 @@ class POT * @since 0.1.3 * @param IOTS_DataDisplay $dataDisplay Display driver. */ - public function setDataDisplayDriver(IOTS_DataDisplay $dataDisplay) - { - $this->dataDisplay = $dataDisplay; - } + public function setDataDisplayDriver(IOTS_DataDisplay $dataDisplay) + { + $this->dataDisplay = $dataDisplay; + } /** * Checks if any display driver for non-database resources is loaded. @@ -1530,10 +1530,10 @@ class POT * @since 0.1.3 * @return bool True if driver is loaded. */ - public function isDataDisplayDriverLoaded() - { - return isset($this->dataDisplay); - } + public function isDataDisplayDriverLoaded() + { + return isset($this->dataDisplay); + } /** * Unloads display driver. @@ -1541,10 +1541,10 @@ class POT * @version 0.1.3 * @since 0.1.3 */ - public function unloadDataDisplayDriver() - { - unset($this->dataDisplay); - } + public function unloadDataDisplayDriver() + { + unset($this->dataDisplay); + } /** * Returns current display driver. @@ -1558,15 +1558,15 @@ class POT * @return IOTS_DataDisplay Current display driver. * @throws E_OTS_NotLoaded If display driver is not loaded. */ - public function getDataDisplayDriver() - { - if( isset($this->dataDisplay) ) - { - return $this->dataDisplay; - } + public function getDataDisplayDriver() + { + if( isset($this->dataDisplay) ) + { + return $this->dataDisplay; + } - throw new E_OTS_NotLoaded(); - } + throw new E_OTS_NotLoaded(); + } } /* @@ -1581,7 +1581,7 @@ if( !defined('PDO_PARAM_STR') ) * @since 0.0.7 * @deprecated Will be dropped after dropping IOTS_DB::SQLquote() since only this deprecated method uses it. */ - define('PDO_PARAM_STR', PDO::PARAM_STR); + define('PDO_PARAM_STR', PDO::PARAM_STR); } if( !defined('PDO_ATTR_STATEMENT_CLASS') ) @@ -1592,7 +1592,7 @@ if( !defined('PDO_ATTR_STATEMENT_CLASS') ) * @since 0.0.7 * @deprecated Use PDO::ATTR_STATEMENT_CLASS, this is for PHP 5.0 compatibility. */ - define('PDO_ATTR_STATEMENT_CLASS', PDO::ATTR_STATEMENT_CLASS); + define('PDO_ATTR_STATEMENT_CLASS', PDO::ATTR_STATEMENT_CLASS); } if( !defined('PDO_ATTR_ERRMODE') ) @@ -1603,7 +1603,7 @@ if( !defined('PDO_ATTR_ERRMODE') ) * @since 0.1.3 * @deprecated Use PDO::ATTR_ERRMODE, this is for PHP 5.0 compatibility. */ - define('PDO_ATTR_ERRMODE', PDO::ATTR_ERRMODE); + define('PDO_ATTR_ERRMODE', PDO::ATTR_ERRMODE); } if( !defined('PDO_ERRMODE_EXCEPTION') ) @@ -1614,7 +1614,7 @@ if( !defined('PDO_ERRMODE_EXCEPTION') ) * @since 0.1.3 * @deprecated Use PDO::ERRMODE_EXCEPTION, this is for PHP 5.0 compatibility. */ - define('PDO_ERRMODE_EXCEPTION', PDO::ERRMODE_EXCEPTION); + define('PDO_ERRMODE_EXCEPTION', PDO::ERRMODE_EXCEPTION); } /**#@-*/ From 40d65a6613149fda51bdceb82c807e5301a3388b Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 23 May 2025 16:11:57 +0200 Subject: [PATCH 028/222] OTS_ServerInfo -> set timeout out of class Possibility to use the class without MyAAC --- system/libs/pot/OTS.php | 4 +++- system/libs/pot/OTS_ServerInfo.php | 15 ++++++++++++--- system/status.php | 2 ++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/system/libs/pot/OTS.php b/system/libs/pot/OTS.php index f739c709..fb93afea 100644 --- a/system/libs/pot/OTS.php +++ b/system/libs/pot/OTS.php @@ -415,9 +415,11 @@ class POT * @tutorial POT/Server_status.pkg * @deprecated 0.1.4 Use OTS_ServerInfo->status(). */ - public static function serverStatus($server, $port) + public static function serverStatus($server, $port, $timeout = 2.0) { $status = new OTS_ServerInfo($server, $port); + $status->setTimeout($timeout); + return $status->status(); } diff --git a/system/libs/pot/OTS_ServerInfo.php b/system/libs/pot/OTS_ServerInfo.php index e39f9fe7..76ebcaf7 100644 --- a/system/libs/pot/OTS_ServerInfo.php +++ b/system/libs/pot/OTS_ServerInfo.php @@ -26,14 +26,19 @@ class OTS_ServerInfo * * @var string */ - private $server; + private string $server; /** * Connection port. * * @var int */ - private $port; + private int $port; + + /** + * Status timeout + */ + private float $timeout = 2.0; /** * Creates handler for new server. @@ -57,7 +62,7 @@ class OTS_ServerInfo private function send(OTS_Buffer $packet) { // connects to server - $socket = @fsockopen($this->server, $this->port, $error, $message, setting('core.status_timeout')); + $socket = @fsockopen($this->server, $this->port, $error, $message, $this->timeout); // if connected then checking statistics if($socket) @@ -224,6 +229,10 @@ class OTS_ServerInfo throw new OutOfBoundsException(); } } + + public function setTimeout($timeout) { + $this->timeout = $timeout; + } } /**#@-*/ diff --git a/system/status.php b/system/status.php index 835f204d..8e8225dd 100644 --- a/system/status.php +++ b/system/status.php @@ -114,6 +114,8 @@ function updateStatus() { // get server status and save it to database $serverInfo = new OTS_ServerInfo($status_ip, $status_port); + $serverInfo->setTimeout(setting('core.status_timeout')); + $serverStatus = $serverInfo->status(); if(!$serverStatus) { From 72cdd290da4819e7128ca66162afa201745fca06 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 23 May 2025 17:38:14 +0200 Subject: [PATCH 029/222] Fix link to Contributing --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e34e806a..54b27d07 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ Pull requests should be made to the *develop* branch as that is the working bran Bug fixes to current release should be done to master branch. -Look: [Contributing](https://github.com/otsoft/myaac/wiki/Contributing) in our wiki. +Look: [Contributing](https://docs.my-aac.org/misc/contributing) in our wiki. ### Other Notes @@ -95,4 +95,4 @@ Many thanks to Jetbrains for kindly providing a license for me to work on this a ### License This program and all associated files are released under the GNU Public License. -See [LICENSE](https://github.com/slawkens/myaac/blob/master/LICENSE) for details. +See [LICENSE](https://github.com/slawkens/myaac/blob/main/LICENSE) for details. From 6eda38603c8ed7e99b92a78a4600b1245377f74d Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 24 May 2025 09:52:56 +0200 Subject: [PATCH 030/222] Protect against csrf in more places (accounts & guilds pages) --- system/pages/account/change-email.php | 2 ++ system/pages/account/change-info.php | 2 ++ system/pages/account/change-password.php | 2 ++ system/pages/account/characters/change-comment.php | 2 ++ system/pages/account/characters/change-name.php | 2 ++ system/pages/account/characters/change-sex.php | 2 ++ system/pages/account/characters/create.php | 2 ++ system/pages/account/characters/delete.php | 2 ++ system/pages/account/create.php | 2 ++ system/pages/account/login.php | 2 ++ system/pages/account/manage.php | 2 ++ system/pages/account/register-new.php | 2 ++ system/pages/account/register.php | 2 ++ system/pages/forum/edit_post.php | 2 ++ system/pages/forum/move_thread.php | 2 ++ system/pages/forum/new_post.php | 2 ++ system/pages/forum/new_thread.php | 2 ++ system/pages/forum/remove_post.php | 2 ++ system/pages/guilds/base.php | 2 ++ system/src/CsrfToken.php | 5 +++-- system/templates/forum.move_thread.html.twig | 4 ++-- 21 files changed, 43 insertions(+), 4 deletions(-) diff --git a/system/pages/account/change-email.php b/system/pages/account/change-email.php index c97b5541..857623f9 100644 --- a/system/pages/account/change-email.php +++ b/system/pages/account/change-email.php @@ -17,6 +17,8 @@ if(!$logged) { return; } +csrfProtect(); + $email_new_time = $account_logged->getCustomField("email_new_time"); if($email_new_time > 10) { diff --git a/system/pages/account/change-info.php b/system/pages/account/change-info.php index 709dce27..4aa64be5 100644 --- a/system/pages/account/change-info.php +++ b/system/pages/account/change-info.php @@ -20,6 +20,8 @@ if(!$logged) { return; } +csrfProtect(); + if(setting('core.account_country')) require SYSTEM . 'countries.conf.php'; diff --git a/system/pages/account/change-password.php b/system/pages/account/change-password.php index bf172455..35058d3d 100644 --- a/system/pages/account/change-password.php +++ b/system/pages/account/change-password.php @@ -17,6 +17,8 @@ if(!$logged) { return; } +csrfProtect(); + $new_password = $_POST['newpassword'] ?? NULL; $new_password_confirm = $_POST['newpassword_confirm'] ?? NULL; $old_password = $_POST['oldpassword'] ?? NULL; diff --git a/system/pages/account/characters/change-comment.php b/system/pages/account/characters/change-comment.php index 7fa10c69..919e6aa6 100644 --- a/system/pages/account/characters/change-comment.php +++ b/system/pages/account/characters/change-comment.php @@ -20,6 +20,8 @@ if(!$logged) { return; } +csrfProtect(); + $player = null; $player_name = isset($_REQUEST['name']) ? stripslashes(urldecode($_REQUEST['name'])) : null; $new_comment = isset($_POST['comment']) ? htmlspecialchars(stripslashes(substr($_POST['comment'],0,2000))) : NULL; diff --git a/system/pages/account/characters/change-name.php b/system/pages/account/characters/change-name.php index 975369d1..3e9254fb 100644 --- a/system/pages/account/characters/change-name.php +++ b/system/pages/account/characters/change-name.php @@ -17,6 +17,8 @@ if(!$logged) { return; } +csrfProtect(); + $player_id = isset($_POST['player_id']) ? (int)$_POST['player_id'] : NULL; $name = isset($_POST['name']) ? stripslashes(ucwords(strtolower($_POST['name']))) : NULL; if((!setting('core.account_change_character_name'))) diff --git a/system/pages/account/characters/change-sex.php b/system/pages/account/characters/change-sex.php index efefe7c9..101feb22 100644 --- a/system/pages/account/characters/change-sex.php +++ b/system/pages/account/characters/change-sex.php @@ -17,6 +17,8 @@ if(!$logged) { return; } +csrfProtect(); + $sex_changed = false; $player_id = isset($_POST['player_id']) ? (int)$_POST['player_id'] : NULL; $new_sex = isset($_POST['new_sex']) ? (int)$_POST['new_sex'] : NULL; diff --git a/system/pages/account/characters/create.php b/system/pages/account/characters/create.php index 5ad21dab..6469319d 100644 --- a/system/pages/account/characters/create.php +++ b/system/pages/account/characters/create.php @@ -20,6 +20,8 @@ if(!$logged) { return; } +csrfProtect(); + $character_name = isset($_POST['name']) ? stripslashes($_POST['name']) : null; $character_sex = isset($_POST['sex']) ? (int)$_POST['sex'] : null; $character_vocation = isset($_POST['vocation']) ? (int)$_POST['vocation'] : null; diff --git a/system/pages/account/characters/delete.php b/system/pages/account/characters/delete.php index af32070b..c737ad5c 100644 --- a/system/pages/account/characters/delete.php +++ b/system/pages/account/characters/delete.php @@ -17,6 +17,8 @@ if(!$logged) { return; } +csrfProtect(); + $player_name = isset($_POST['delete_name']) ? stripslashes($_POST['delete_name']) : null; $password_verify = isset($_POST['delete_password']) ? $_POST['delete_password'] : null; $password_verify = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $password_verify); diff --git a/system/pages/account/create.php b/system/pages/account/create.php index 1c8f1e9f..0befa362 100644 --- a/system/pages/account/create.php +++ b/system/pages/account/create.php @@ -23,6 +23,8 @@ if($logged) return; } +csrfProtect(); + if(setting('core.account_create_character_create')) { $createCharacter = new CreateCharacter(); } diff --git a/system/pages/account/login.php b/system/pages/account/login.php index c95019d6..d6771c91 100644 --- a/system/pages/account/login.php +++ b/system/pages/account/login.php @@ -18,6 +18,8 @@ if($logged || !isset($_POST['account_login']) || !isset($_POST['password_login'] return; } +csrfProtect(); + $login_account = $_POST['account_login']; $login_password = $_POST['password_login']; $remember_me = isset($_POST['remember_me']); diff --git a/system/pages/account/manage.php b/system/pages/account/manage.php index eff71c78..3776a732 100644 --- a/system/pages/account/manage.php +++ b/system/pages/account/manage.php @@ -34,6 +34,8 @@ if(isset($_REQUEST['redirect'])) return; } +csrfProtect(); + $groups = new OTS_Groups_List(); $freePremium = isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium']) || $account_logged->getPremDays() == OTS_Account::GRATIS_PREMIUM_DAYS; diff --git a/system/pages/account/register-new.php b/system/pages/account/register-new.php index 04e8bf33..bca3b798 100644 --- a/system/pages/account/register-new.php +++ b/system/pages/account/register-new.php @@ -17,6 +17,8 @@ if(!$logged) { return; } +csrfProtect(); + if(isset($_POST['reg_password'])) $reg_password = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $_POST['reg_password']); diff --git a/system/pages/account/register.php b/system/pages/account/register.php index f33f0b17..8aa3089e 100644 --- a/system/pages/account/register.php +++ b/system/pages/account/register.php @@ -17,6 +17,8 @@ if(!$logged) { return; } +csrfProtect(); + $_POST['reg_password'] = $_POST['reg_password'] ?? ''; $reg_password = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $_POST['reg_password']); $old_key = $account_logged->getCustomField("key"); diff --git a/system/pages/forum/edit_post.php b/system/pages/forum/edit_post.php index 53fcdb71..d795aa99 100644 --- a/system/pages/forum/edit_post.php +++ b/system/pages/forum/edit_post.php @@ -18,6 +18,8 @@ if ($ret === false) { return; } +csrfProtect(); + if(!$logged) { echo 'You are not logged in. Log in to post on the forum.

'; return; diff --git a/system/pages/forum/move_thread.php b/system/pages/forum/move_thread.php index d9731e5b..7200fffb 100644 --- a/system/pages/forum/move_thread.php +++ b/system/pages/forum/move_thread.php @@ -18,6 +18,8 @@ if ($ret === false) { return; } +csrfProtect(); + if(!$logged) { echo 'You are not logged in. Log in to post on the forum.

'; return; diff --git a/system/pages/forum/new_post.php b/system/pages/forum/new_post.php index b0db84fd..6e373945 100644 --- a/system/pages/forum/new_post.php +++ b/system/pages/forum/new_post.php @@ -28,6 +28,8 @@ if(!$logged) { return; } +csrfProtect(); + if(Forum::canPost($account_logged)) { $players_from_account = $db->query("SELECT `players`.`name`, `players`.`id` FROM `players` WHERE `players`.`account_id` = ".(int) $account_logged->getId())->fetchAll(); $thread_id = isset($_REQUEST['thread_id']) ? (int) $_REQUEST['thread_id'] : 0; diff --git a/system/pages/forum/new_thread.php b/system/pages/forum/new_thread.php index e6c8fe80..2e9e74b3 100644 --- a/system/pages/forum/new_thread.php +++ b/system/pages/forum/new_thread.php @@ -28,6 +28,8 @@ if(!$logged) { return; } +csrfProtect(); + if(Forum::canPost($account_logged)) { $players_from_account = $db->query('SELECT `players`.`name`, `players`.`id` FROM `players` WHERE `players`.`account_id` = '.(int) $account_logged->getId())->fetchAll(); $section_id = $_REQUEST['section_id'] ?? null; diff --git a/system/pages/forum/remove_post.php b/system/pages/forum/remove_post.php index 690b3f75..a1dc15af 100644 --- a/system/pages/forum/remove_post.php +++ b/system/pages/forum/remove_post.php @@ -23,6 +23,8 @@ if(!$logged) { return; } +csrfProtect(); + if(Forum::isModerator()) { $id = (int) $_REQUEST['id']; $post = $db->query("SELECT `id`, `first_post`, `section` FROM `" . FORUM_TABLE_PREFIX . "forum` WHERE `id` = ".$id." LIMIT 1")->fetch(); diff --git a/system/pages/guilds/base.php b/system/pages/guilds/base.php index 07fc432d..e096c56e 100644 --- a/system/pages/guilds/base.php +++ b/system/pages/guilds/base.php @@ -15,3 +15,5 @@ else define('GUILD_MEMBERS_TABLE', 'guild_membership'); define('MOTD_EXISTS', $db->hasColumn('guilds', 'motd')); + +csrfProtect(); diff --git a/system/src/CsrfToken.php b/system/src/CsrfToken.php index 7e002928..baa7c74d 100644 --- a/system/src/CsrfToken.php +++ b/system/src/CsrfToken.php @@ -25,8 +25,9 @@ class CsrfToken * * @access public * @static true + * @param bool $return * @return string - **/ + */ public static function create(bool $return = false): string { $input = ''; if ($return) { @@ -58,7 +59,7 @@ class CsrfToken * @static true * @return boolean **/ - public static function isValid($post): bool + public static function isValid(string|null $post): bool { if (!setting('core.csrf_protection')) { return true; diff --git a/system/templates/forum.move_thread.html.twig b/system/templates/forum.move_thread.html.twig index be62d9c7..c9480199 100644 --- a/system/templates/forum.move_thread.html.twig +++ b/system/templates/forum.move_thread.html.twig @@ -8,7 +8,8 @@
-
- - +
+
+ - +
@@ -30,7 +30,7 @@
- +
- + {{ hook('HOOK_ACCOUNT_LOGIN_AFTER_PASSWORD') }} @@ -67,7 +67,7 @@ - +
@@ -45,7 +45,7 @@ {{ hook('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT') }}
Password:
@@ -79,7 +79,7 @@
{{ i }}{{ result.name }}{{ result.name }} {{ result.balance }}
{{ i }}{{ result.name }}{{ result.name }} {{ result.coins }}
{{ i }}{{ result.name }}{{ result.name }} {{ result.lastlogin|date("M d Y, H:i:s") }}
{{ i }}{{ result.name }}{{ result.name }} {{ result.premium_points }}
From 6e793390c6f446cb017f5f59a4ca19179d6866b5 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 24 May 2025 11:20:36 +0200 Subject: [PATCH 031/222] Remove unneeded enctype="multipart/form-data" --- system/templates/guilds.change_description.html.twig | 2 +- system/templates/guilds.change_motd.html.twig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/system/templates/guilds.change_description.html.twig b/system/templates/guilds.change_description.html.twig index 9c656920..33b1db84 100644 --- a/system/templates/guilds.change_description.html.twig +++ b/system/templates/guilds.change_description.html.twig @@ -5,7 +5,7 @@ {% if canEdit %} {% endif %} From 84d502bf105f2a789481fba1acc820d236b4de66 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 24 May 2025 11:42:42 +0200 Subject: [PATCH 033/222] Fixes regarding csrf + refactor some parts of AAC (guilds + forum) Replace $account_logged->getPlayers() with getPlayersList() $_REQUEST['todo'] -> $_REQUEST['post'] $guild_errors -> $errors --- system/pages/forum/admin.php | 13 ++- system/pages/forum/edit_post.php | 19 ++--- system/pages/forum/move_thread.php | 10 +-- system/pages/forum/new_post.php | 19 ++--- system/pages/forum/new_thread.php | 13 ++- system/pages/forum/remove_post.php | 6 +- system/pages/forum/show_board.php | 17 ++-- system/pages/forum/show_thread.php | 4 +- system/pages/guilds/accept_invite.php | 12 +-- system/pages/guilds/add_rank.php | 4 +- system/pages/guilds/change_description.php | 6 +- system/pages/guilds/change_logo.php | 11 ++- system/pages/guilds/change_motd.php | 6 +- system/pages/guilds/change_nick.php | 4 +- system/pages/guilds/change_rank.php | 27 +++--- system/pages/guilds/cleanup_players.php | 45 +++++----- system/pages/guilds/create.php | 43 +++++----- system/pages/guilds/delete_by_admin.php | 5 +- system/pages/guilds/delete_guild.php | 4 +- system/pages/guilds/delete_invite.php | 84 +++++++++---------- system/pages/guilds/delete_rank.php | 44 +++++----- system/pages/guilds/invite.php | 8 +- system/pages/guilds/kick_player.php | 4 +- system/pages/guilds/leave.php | 6 +- system/pages/guilds/list.php | 15 ++-- system/pages/guilds/manager.php | 14 ++-- system/pages/guilds/pass_leadership.php | 43 +++++----- system/pages/guilds/save_ranks.php | 7 +- system/pages/guilds/show.php | 14 ++-- system/templates/forum.new_thread.html.twig | 2 +- system/templates/forum.remove_post.html.twig | 12 +++ system/templates/forum.show_thread.html.twig | 7 +- .../templates/guilds.accept_invite.html.twig | 9 +- system/templates/guilds.change_logo.html.twig | 2 +- system/templates/guilds.change_rank.html.twig | 3 +- system/templates/guilds.create.html.twig | 3 +- .../templates/guilds.delete_invite.html.twig | 7 +- system/templates/guilds.invite.html.twig | 3 +- system/templates/guilds.kick_player.html.twig | 3 +- system/templates/guilds.leave_guild.html.twig | 3 +- system/templates/guilds.manager.html.twig | 7 +- templates/tibiacom/account.login.html.twig | 5 +- 42 files changed, 301 insertions(+), 272 deletions(-) create mode 100644 system/templates/forum.remove_post.html.twig diff --git a/system/pages/forum/admin.php b/system/pages/forum/admin.php index 1260cfb2..73be2dc2 100644 --- a/system/pages/forum/admin.php +++ b/system/pages/forum/admin.php @@ -64,7 +64,7 @@ if(!empty($action)) { else if($action == 'delete_board') { Forum::delete_board($id, $errors); header('Location: ' . getLink('forum')); - $action = ''; + exit; } else if($action == 'edit_board') { @@ -78,28 +78,27 @@ if(!empty($action)) { else { Forum::update_board($id, $name, $access, $guild, $description); header('Location: ' . getLink('forum')); - $action = $name = $description = ''; - $access = $guild = 0; + exit; } } else if($action == 'hide_board') { Forum::toggleHide_board($id, $errors); header('Location: ' . getLink('forum')); - $action = ''; + exit; } else if($action == 'moveup_board') { Forum::move_board($id, -1, $errors); header('Location: ' . getLink('forum')); - $action = ''; + exit; } else if($action == 'movedown_board') { Forum::move_board($id, 1, $errors); header('Location: ' . getLink('forum')); - $action = ''; + exit; } if(!empty($errors)) { - $twig->display('error_box.html.twig', array('errors' => $errors)); + $twig->display('error_box.html.twig', ['errors' => $errors]); $action = ''; } } diff --git a/system/pages/forum/edit_post.php b/system/pages/forum/edit_post.php index d795aa99..b9f2890d 100644 --- a/system/pages/forum/edit_post.php +++ b/system/pages/forum/edit_post.php @@ -18,15 +18,14 @@ if ($ret === false) { return; } -csrfProtect(); - if(!$logged) { echo 'You are not logged in. Log in to post on the forum.

'; return; } -if(Forum::canPost($account_logged)) -{ +csrfProtect(); + +if(Forum::canPost($account_logged)) { $post_id = isset($_REQUEST['id']) ? (int) $_REQUEST['id'] : false; if(!$post_id) { $errors[] = 'Please enter post id.'; @@ -43,12 +42,12 @@ if(Forum::canPost($account_logged)) $char_id = $post_topic = $text = $smile = $html = null; $players_from_account = $db->query("SELECT `players`.`name`, `players`.`id` FROM `players` WHERE `players`.`account_id` = ".(int) $account_logged->getId())->fetchAll(); $saved = false; - if(isset($_REQUEST['save'])) { - $text = stripslashes(trim($_REQUEST['text'])); - $char_id = (int) $_REQUEST['char_id']; - $post_topic = stripslashes(trim($_REQUEST['topic'])); - $smile = isset($_REQUEST['smile']) ? (int)$_REQUEST['smile'] : 0; - $html = isset($_REQUEST['html']) ? (int)$_REQUEST['html'] : 0; + if(isset($_POST['save'])) { + $text = stripslashes(trim($_POST['text'])); + $char_id = (int) $_POST['char_id']; + $post_topic = stripslashes(trim($_POST['topic'])); + $smile = isset($_POST['smile']) ? (int)$_POST['smile'] : 0; + $html = isset($_POST['html']) ? (int)$_POST['html'] : 0; if (!superAdmin()) { $html = 0; diff --git a/system/pages/forum/move_thread.php b/system/pages/forum/move_thread.php index 7200fffb..aa101b08 100644 --- a/system/pages/forum/move_thread.php +++ b/system/pages/forum/move_thread.php @@ -18,22 +18,22 @@ if ($ret === false) { return; } -csrfProtect(); - if(!$logged) { echo 'You are not logged in. Log in to post on the forum.

'; return; } +csrfProtect(); + if(!Forum::isModerator()) { echo 'You are not logged in or you are not moderator.'; return; } -$save = isset($_REQUEST['save']) && (int)$_REQUEST['save'] == 1; +$save = isset($_POST['save']) && (int)$_POST['save'] == 1; if($save) { - $post_id = (int)$_REQUEST['id']; - $board = (int)$_REQUEST['section']; + $post_id = (int)$_POST['id']; + $board = (int)$_POST['section']; if(!Forum::hasAccess($board)) { $errors[] = "You don't have access to this board."; displayErrorBoxWithBackButton($errors, getLink('forum')); diff --git a/system/pages/forum/new_post.php b/system/pages/forum/new_post.php index 6e373945..71bc3417 100644 --- a/system/pages/forum/new_post.php +++ b/system/pages/forum/new_post.php @@ -45,11 +45,11 @@ if(Forum::canPost($account_logged)) { echo 'Boards >> '.$sections[$thread['section']]['name'].' >> '.htmlspecialchars($thread['post_topic']).' >> Post new reply

'.htmlspecialchars($thread['post_topic']).'

'; $quote = isset($_REQUEST['quote']) ? (int) $_REQUEST['quote'] : NULL; - $text = isset($_REQUEST['text']) ? stripslashes(trim($_REQUEST['text'])) : NULL; - $char_id = (int) ($_REQUEST['char_id'] ?? 0); - $post_topic = isset($_REQUEST['topic']) ? stripslashes(trim($_REQUEST['topic'])) : ''; - $smile = (int)($_REQUEST['smile'] ?? 0); - $html = (int)($_REQUEST['html'] ?? 0); + $text = isset($_POST['text']) ? stripslashes(trim($_POST['text'])) : NULL; + $char_id = (int) ($_POST['char_id'] ?? 0); + $post_topic = isset($_POST['topic']) ? stripslashes(trim($_POST['topic'])) : ''; + $smile = (int)($_POST['smile'] ?? 0); + $html = (int)($_POST['html'] ?? 0); $saved = false; if (!superAdmin()) { @@ -62,10 +62,10 @@ if(Forum::canPost($account_logged)) { $text = '[i]Originally posted by ' . $quoted_post[0]['name'] . ' on ' . date('d.m.y H:i:s', $quoted_post[0]['post_date']) . ':[/i][quote]' . $quoted_post[0]['post_text'] . '[/quote]'; } } - elseif(isset($_REQUEST['save'])) { + elseif(isset($_POST['save'])) { $length = strlen($text); if($length < 1 || strlen($text) > 15000) { - $errors[] = 'Too short or too long post (Length: $length letters). Minimum 1 letter, maximum 15000 letters.'; + $errors[] = "Too short or too long post (Length: $length letters). Minimum 1 letter, maximum 15000 letters."; } if($char_id == 0) { @@ -81,15 +81,14 @@ if(Forum::canPost($account_logged)) { } if(!$player_on_account) { - $errors[] = 'Player with selected ID ' . $char_id . ' doesn\'t exist or isn\'t on your account'; + $errors[] = "Player with selected ID $char_id doesn't exist or isn't on your account"; } } if(count($errors) == 0) { $last_post = 0; $query = $db->query('SELECT post_date FROM ' . FORUM_TABLE_PREFIX . 'forum ORDER BY post_date DESC LIMIT 1'); - if($query->rowCount() > 0) - { + if($query->rowCount() > 0) { $query = $query->fetch(); $last_post = $query['post_date']; } diff --git a/system/pages/forum/new_thread.php b/system/pages/forum/new_thread.php index 2e9e74b3..4f311977 100644 --- a/system/pages/forum/new_thread.php +++ b/system/pages/forum/new_thread.php @@ -40,19 +40,18 @@ if(Forum::canPost($account_logged)) { if ($sections[$section_id]['closed'] && !Forum::isModerator()) $errors[] = 'You cannot create topic on this board.'; - $quote = (int)(isset($_REQUEST['quote']) ? $_REQUEST['quote'] : 0); - $text = isset($_REQUEST['text']) ? stripslashes($_REQUEST['text']) : ''; - $char_id = (int)(isset($_REQUEST['char_id']) ? $_REQUEST['char_id'] : 0); - $post_topic = isset($_REQUEST['topic']) ? stripslashes($_REQUEST['topic']) : ''; - $smile = (isset($_REQUEST['smile']) ? (int)$_REQUEST['smile'] : 0); - $html = (isset($_REQUEST['html']) ? (int)$_REQUEST['html'] : 0); + $text = isset($_POST['text']) ? stripslashes($_POST['text']) : ''; + $char_id = (int)(isset($_POST['char_id']) ? $_POST['char_id'] : 0); + $post_topic = isset($_POST['topic']) ? stripslashes($_POST['topic']) : ''; + $smile = (isset($_POST['smile']) ? (int)$_POST['smile'] : 0); + $html = (isset($_POST['html']) ? (int)$_POST['html'] : 0); if (!superAdmin()) { $html = 0; } $saved = false; - if (isset($_REQUEST['save'])) { + if (isset($_POST['save'])) { $length = strlen($post_topic); if ($length < 1 || $length > 60) { $errors[] = "Too short or too long topic (Length: $length letters). Minimum 1 letter, maximum 60 letters."; diff --git a/system/pages/forum/remove_post.php b/system/pages/forum/remove_post.php index a1dc15af..ec3a38ec 100644 --- a/system/pages/forum/remove_post.php +++ b/system/pages/forum/remove_post.php @@ -26,10 +26,10 @@ if(!$logged) { csrfProtect(); if(Forum::isModerator()) { - $id = (int) $_REQUEST['id']; + $id = (int) ($_POST['id'] ?? 0); $post = $db->query("SELECT `id`, `first_post`, `section` FROM `" . FORUM_TABLE_PREFIX . "forum` WHERE `id` = ".$id." LIMIT 1")->fetch(); - if($post['id'] == $id && Forum::hasAccess($post['section'])) { + if($post && $post['id'] == $id && Forum::hasAccess($post['section'])) { if($post['id'] == $post['first_post']) { $db->query("DELETE FROM `" . FORUM_TABLE_PREFIX . "forum` WHERE `first_post` = ".$post['id']); header('Location: ' . getForumBoardLink($post['section'])); @@ -38,7 +38,7 @@ if(Forum::isModerator()) { $post_page = $db->query("SELECT COUNT(`" . FORUM_TABLE_PREFIX . "forum`.`id`) AS posts_count FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`id` < ".$id." AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".(int) $post['first_post'])->fetch(); $_page = (int) ceil($post_page['posts_count'] / setting('core.forum_threads_per_page')) - 1; $db->query("DELETE FROM `" . FORUM_TABLE_PREFIX . "forum` WHERE `id` = ".$post['id']); - header('Location: ' . getForumThreadLink($post['first_post'], (int) $_page)); + header('Location: ' . getForumThreadLink($post['first_post'], $_page)); } } else { diff --git a/system/pages/forum/show_board.php b/system/pages/forum/show_board.php index 5997bdba..e899cc99 100644 --- a/system/pages/forum/show_board.php +++ b/system/pages/forum/show_board.php @@ -33,7 +33,7 @@ if(!Forum::hasAccess($section_id)) { return; } -$_page = (int) (isset($_REQUEST['page']) ? $_REQUEST['page'] : 0); +$_page = (int) ($_REQUEST['page'] ?? 0); $threads_count = $db->query("SELECT COUNT(`" . FORUM_TABLE_PREFIX . "forum`.`id`) AS threads_count FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`section` = ".(int) $section_id." AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = `" . FORUM_TABLE_PREFIX . "forum`.`id`")->fetch(); for($i = 0; $i < $threads_count['threads_count'] / setting('core.forum_threads_per_page'); $i++) { if($i != $_page) @@ -50,7 +50,7 @@ if($logged && (!$sections[$section_id]['closed'] || Forum::isModerator())) { } echo '

Page: '.$links_to_pages.'
'; -$last_threads = $db->query("SELECT `players`.`id` as `player_id`, `players`.`name`, `" . FORUM_TABLE_PREFIX . "forum`.`post_text`, `" . FORUM_TABLE_PREFIX . "forum`.`post_topic`, `" . FORUM_TABLE_PREFIX . "forum`.`id`, `" . FORUM_TABLE_PREFIX . "forum`.`last_post`, `" . FORUM_TABLE_PREFIX . "forum`.`replies`, `" . FORUM_TABLE_PREFIX . "forum`.`views`, `" . FORUM_TABLE_PREFIX . "forum`.`post_date` FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`section` = ".$section_id." AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = `" . FORUM_TABLE_PREFIX . "forum`.`id` ORDER BY `" . FORUM_TABLE_PREFIX . "forum`.`last_post` DESC LIMIT ".setting('core.forum_threads_per_page')." OFFSET ".($_page * setting('core.forum_threads_per_page')))->fetchAll(); +$last_threads = $db->query("SELECT `players`.`id` as `player_id`, `players`.`name`, `" . FORUM_TABLE_PREFIX . "forum`.`first_post`, `" . FORUM_TABLE_PREFIX . "forum`.`post_text`, `" . FORUM_TABLE_PREFIX . "forum`.`post_topic`, `" . FORUM_TABLE_PREFIX . "forum`.`id`, `" . FORUM_TABLE_PREFIX . "forum`.`last_post`, `" . FORUM_TABLE_PREFIX . "forum`.`replies`, `" . FORUM_TABLE_PREFIX . "forum`.`views`, `" . FORUM_TABLE_PREFIX . "forum`.`post_date` FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`section` = ".$section_id." AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = `" . FORUM_TABLE_PREFIX . "forum`.`id` ORDER BY `" . FORUM_TABLE_PREFIX . "forum`.`last_post` DESC LIMIT ".setting('core.forum_threads_per_page')." OFFSET ".($_page * setting('core.forum_threads_per_page')))->fetchAll(PDO::FETCH_ASSOC); if(isset($last_threads[0])) { echo '
-
+ + {{ csrf() }} @@ -25,7 +26,6 @@
- {{ csrf() }}
Here you can change description of your guild.
-
+ {{ csrf() }}
diff --git a/system/templates/guilds.change_motd.html.twig b/system/templates/guilds.change_motd.html.twig index 4313c4c9..e827a4ac 100644 --- a/system/templates/guilds.change_motd.html.twig +++ b/system/templates/guilds.change_motd.html.twig @@ -5,7 +5,7 @@
Here you can change MOTD (Message of the Day, showed in game!) of your guild.
- + {{ csrf() }}
From e776bd52beb3064a9e694efd1b9021ec972ee2f6 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 24 May 2025 11:28:56 +0200 Subject: [PATCH 032/222] Forum boards admin links: csrf + refactor --- system/pages/forum/admin.php | 24 ++++++----- system/templates/forum.admin.links.html.twig | 43 ++++++++++++++++++++ system/templates/forum.boards.html.twig | 20 +-------- 3 files changed, 58 insertions(+), 29 deletions(-) create mode 100644 system/templates/forum.admin.links.html.twig diff --git a/system/pages/forum/admin.php b/system/pages/forum/admin.php index 6e35bba5..1260cfb2 100644 --- a/system/pages/forum/admin.php +++ b/system/pages/forum/admin.php @@ -17,6 +17,8 @@ if(!$canEdit) { return; } +csrfProtect(); + $groupsList = new OTS_Groups_List(); $groups = [ ['id' => 0, 'name' => 'Guest'], @@ -30,23 +32,24 @@ foreach ($groupsList as $group) { } if(!empty($action)) { - if($action == 'delete_board' || $action == 'edit_board' || $action == 'hide_board' || $action == 'moveup_board' || $action == 'movedown_board') + if($action == 'delete_board' || $action == 'edit_board' || $action == 'hide_board' || $action == 'moveup_board' || $action == 'movedown_board') { $id = $_REQUEST['id']; - - if(isset($_REQUEST['access'])) { - $access = $_REQUEST['access']; } - if(isset($_REQUEST['guild'])) { - $guild = $_REQUEST['guild']; + if(isset($_POST['access'])) { + $access = $_POST['access']; } - if(isset($_REQUEST['name'])) { - $name = $_REQUEST['name']; + if(isset($_POST['guild'])) { + $guild = $_POST['guild']; } - if(isset($_REQUEST['description'])) { - $description = stripslashes($_REQUEST['description']); + if(isset($_POST['name'])) { + $name = $_POST['name']; + } + + if(isset($_POST['description'])) { + $description = stripslashes($_POST['description']); } $errors = []; @@ -55,6 +58,7 @@ if(!empty($action)) { if(Forum::add_board($name, $description, $access, $guild, $errors)) { $action = $name = $description = ''; header('Location: ' . getLink('forum')); + exit; } } else if($action == 'delete_board') { diff --git a/system/templates/forum.admin.links.html.twig b/system/templates/forum.admin.links.html.twig new file mode 100644 index 00000000..2449e616 --- /dev/null +++ b/system/templates/forum.admin.links.html.twig @@ -0,0 +1,43 @@ + + + + +
+ + {{ csrf() }} + + + + + +
+ {{ csrf() }} + + + +
+ +
+ {{ csrf() }} + + + +
+ + {% if i != 1 %} +
+ {{ csrf() }} + + + +
+ {% endif %} + {% if i != loop.last %} +
+ {{ csrf() }} + + + +
+ {% endif %} +
diff --git a/system/templates/forum.boards.html.twig b/system/templates/forum.boards.html.twig index 5ac3e88b..aa2772f9 100644 --- a/system/templates/forum.boards.html.twig +++ b/system/templates/forum.boards.html.twig @@ -39,25 +39,7 @@
- - Edit - - - Delete - - - {% if board.hide != 1 %}Hide{% else %}Show{% endif %} - - {% if i != 1 %} - - Move up - - {% endif %} - {% if i != last %} - - Move down - - {% endif %} + {{ include('forum.admin.links.html.twig', {id: board.id, hide: board.hide, i: i }) }}
@@ -67,8 +67,8 @@ if(isset($last_threads[0])) { foreach($last_threads as $thread) { echo '
'; if(Forum::isModerator()) { - echo '[MOVE]'; - echo '[REMOVE] '; + echo ''; + $twig->display('forum.remove_post.html.twig', ['post' => $thread]); } $player->load($thread['player_id']); @@ -82,10 +82,13 @@ if(isset($last_threads[0])) { echo ''.htmlspecialchars($thread['post_topic']). '
'.($canEditForum ? substr(strip_tags($thread['post_text']), 0, 50) : htmlspecialchars(substr($thread['post_text'], 0, 50))).'...
' . getPlayerLink($thread['name']) . ''.(int) $thread['replies'].''.(int) $thread['views'].''; if($thread['last_post'] > 0) { $last_post = $db->query("SELECT `players`.`name`, `" . FORUM_TABLE_PREFIX . "forum`.`post_date` FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".(int) $thread['id']." AND `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` ORDER BY `post_date` DESC LIMIT 1")->fetch(); - if(isset($last_post['name'])) - echo date('d.m.y H:i:s', $last_post['post_date']).'
by ' . getPlayerLink($last_post['name']); - else + + if(isset($last_post['name'])) { + echo date('d.m.y H:i:s', $last_post['post_date']) . '
by ' . getPlayerLink($last_post['name']); + } + else { echo 'No posts.'; + } } else { echo date('d.m.y H:i:s', $thread['post_date']) . '
by ' . getPlayerLink($thread['name']); diff --git a/system/pages/forum/show_thread.php b/system/pages/forum/show_thread.php index e4c53f16..ceeb2602 100644 --- a/system/pages/forum/show_thread.php +++ b/system/pages/forum/show_thread.php @@ -35,7 +35,7 @@ if(!Forum::hasAccess($thread_starter['section'])) { return; } -$posts_count = $db->query("SELECT COUNT(`" . FORUM_TABLE_PREFIX . "forum`.`id`) AS posts_count FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".(int) $thread_id)->fetch(); +$posts_count = $db->query("SELECT COUNT(`" . FORUM_TABLE_PREFIX . "forum`.`id`) AS posts_count FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".$thread_id)->fetch(); for($i = 0; $i < $posts_count['posts_count'] / setting('core.forum_threads_per_page'); $i++) { if($i != $_page) $links_to_pages .= ''.($i + 1).' '; @@ -46,7 +46,7 @@ for($i = 0; $i < $posts_count['posts_count'] / setting('core.forum_threads_per_p $posts = $db->query("SELECT `players`.`id` as `player_id`, `" . FORUM_TABLE_PREFIX . "forum`.`id`,`" . FORUM_TABLE_PREFIX . "forum`.`first_post`, `" . FORUM_TABLE_PREFIX . "forum`.`section`,`" . FORUM_TABLE_PREFIX . "forum`.`post_text`, `" . FORUM_TABLE_PREFIX . "forum`.`post_topic`, `" . FORUM_TABLE_PREFIX . "forum`.`post_date` AS `date`, `" . FORUM_TABLE_PREFIX . "forum`.`post_smile`, `" . FORUM_TABLE_PREFIX . "forum`.`post_html`, `" . FORUM_TABLE_PREFIX . "forum`.`author_aid`, `" . FORUM_TABLE_PREFIX . "forum`.`author_guid`, `" . FORUM_TABLE_PREFIX . "forum`.`last_edit_aid`, `" . FORUM_TABLE_PREFIX . "forum`.`edit_date` FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".$thread_id." ORDER BY `" . FORUM_TABLE_PREFIX . "forum`.`post_date` LIMIT " . setting('core.forum_posts_per_page') . " OFFSET ".($_page * setting('core.forum_posts_per_page')))->fetchAll(); if(isset($posts[0]['player_id'])) { - $db->query("UPDATE `" . FORUM_TABLE_PREFIX . "forum` SET `views`=`views`+1 WHERE `id` = ".(int) $thread_id); + $db->query("UPDATE `" . FORUM_TABLE_PREFIX . "forum` SET `views`=`views`+1 WHERE `id` = " . $thread_id); } $lookaddons = $db->hasColumn('players', 'lookaddons'); diff --git a/system/pages/guilds/accept_invite.php b/system/pages/guilds/accept_invite.php index bc782480..14c55c25 100644 --- a/system/pages/guilds/accept_invite.php +++ b/system/pages/guilds/accept_invite.php @@ -12,11 +12,11 @@ defined('MYAAC') or die('Direct access not allowed!'); require __DIR__ . '/base.php'; -//set rights in guild +// set rights in guild $guild_name = isset($_REQUEST['guild']) ? urldecode($_REQUEST['guild']) : null; $name = isset($_REQUEST['name']) ? stripslashes($_REQUEST['name']) : null; if(!$logged) { - $errors[] = 'You are not logged in. You can\'t accept invitations.'; + $errors[] = "You are not logged in. You can't accept invitations."; } if(!Validator::guildName($guild_name)) { @@ -27,11 +27,11 @@ if(empty($errors)) { $guild = new OTS_Guild(); $guild->find($guild_name); if(!$guild->isLoaded()) { - $errors[] = 'Guild with name '.$guild_name.' doesn\'t exist.'; + $errors[] = "Guild with name $guild_name doesn't exist."; } } -if(isset($_REQUEST['todo']) && $_REQUEST['todo'] == 'save') { +if(isset($_POST['todo']) && $_POST['todo'] == 'save') { if(!Validator::characterName($name)) { $errors[] = 'Invalid name format.'; } @@ -51,7 +51,7 @@ if(isset($_REQUEST['todo']) && $_REQUEST['todo'] == 'save') { } } -if(isset($_REQUEST['todo']) && $_REQUEST['todo'] == 'save') { +if(isset($_POST['todo']) && $_POST['todo'] == 'save') { if(empty($errors)) { $is_invited = false; include(SYSTEM . 'libs/pot/InvitesDriver.php'); @@ -104,7 +104,7 @@ if(!empty($errors)) { )); } else { - if(isset($_REQUEST['todo']) && $_REQUEST['todo'] == 'save') { + if(isset($_POST['todo']) && $_POST['todo'] == 'save') { $guild->acceptInvite($player); $twig->display('success.html.twig', array( 'title' => 'Accept invitation', diff --git a/system/pages/guilds/add_rank.php b/system/pages/guilds/add_rank.php index e66ba49e..b24ff03d 100644 --- a/system/pages/guilds/add_rank.php +++ b/system/pages/guilds/add_rank.php @@ -13,7 +13,7 @@ defined('MYAAC') or die('Direct access not allowed!'); require __DIR__ . '/base.php'; $guild_name = isset($_REQUEST['guild']) ? urldecode($_REQUEST['guild']) : null; -$rank_name = isset($_REQUEST['rank_name']) ? $_REQUEST['rank_name'] : null; +$rank_name = $_POST['rank_name'] ?? null; if(!Validator::guildName($guild_name)) { $errors[] = Validator::getLastError(); } @@ -35,7 +35,7 @@ if(empty($errors)) { $rank_list = $guild->getGuildRanksList(); $rank_list->orderBy('level', POT::ORDER_DESC); $guild_leader = false; - $account_players = $account_logged->getPlayers(); + $account_players = $account_logged->getPlayersList(); foreach($account_players as $player) { if($guild_leader_char->getId() == $player->getId()) { $guild_vice = true; diff --git a/system/pages/guilds/change_description.php b/system/pages/guilds/change_description.php index 765665bf..e3c24522 100644 --- a/system/pages/guilds/change_description.php +++ b/system/pages/guilds/change_description.php @@ -31,7 +31,7 @@ if(empty($errors)) { $rank_list = $guild->getGuildRanksList(); $rank_list->orderBy('level', POT::ORDER_DESC); $guild_leader = false; - $account_players = $account_logged->getPlayers(); + $account_players = $account_logged->getPlayersList(); foreach($account_players as $player) { if($guild->getOwner()->getId() == $player->getId()) { $guild_vice = true; @@ -42,8 +42,8 @@ if(empty($errors)) { $saved = false; if($guild_leader) { - if(isset($_REQUEST['todo']) && $_REQUEST['todo'] == 'save') { - $description = htmlspecialchars(stripslashes(substr(trim($_REQUEST['description']),0, setting('core.guild_description_chars_limit')))); + if(isset($_POST['todo']) && $_POST['todo'] == 'save') { + $description = htmlspecialchars(stripslashes(substr(trim($_POST['description']),0, setting('core.guild_description_chars_limit')))); $guild->setCustomField('description', $description); $saved = true; } diff --git a/system/pages/guilds/change_logo.php b/system/pages/guilds/change_logo.php index d8257e66..7fa72d99 100644 --- a/system/pages/guilds/change_logo.php +++ b/system/pages/guilds/change_logo.php @@ -30,7 +30,7 @@ if(empty($errors)) { if($logged) { $guild_leader_char = $guild->getOwner(); $guild_leader = false; - $account_players = $account_logged->getPlayers(); + $account_players = $account_logged->getPlayersList(); foreach($account_players as $player) { if($guild_leader_char->getId() == $player->getId()) { @@ -40,14 +40,13 @@ if(empty($errors)) { } } - if($guild_leader) - { + if($guild_leader) { $max_image_size_b = setting('core.guild_image_size_kb') * 1024; $allowed_ext = array('image/gif', 'image/jpg', 'image/pjpeg', 'image/jpeg', 'image/bmp', 'image/png', 'image/x-png'); $ext_name = array('image/gif' => 'gif', 'image/jpg' => 'jpg', 'image/jpeg' => 'jpg', 'image/pjpeg' => 'jpg', 'image/bmp' => 'bmp', 'image/png' => 'png', 'image/x-png' => 'png'); $save_file_name = str_replace(' ', '_', strtolower($guild->getName())); $save_path = GUILD_IMAGES_DIR . $save_file_name; - if(isset($_REQUEST['todo']) && $_REQUEST['todo'] == 'save') + if(isset($_POST['todo']) && $_POST['todo'] == 'save') { $file = $_FILES['newlogo']; if(is_uploaded_file($file['tmp_name'])) @@ -97,13 +96,13 @@ if(empty($errors)) { $guild_logo = $guild->getCustomField('logo_name'); if(empty($guild_logo) || !file_exists(GUILD_IMAGES_DIR . $guild_logo)) { - $guild_logo = "default.gif"; + $guild_logo = 'default.gif'; } $twig->display('guilds.change_logo.html.twig', array( 'guild_logo' => $guild_logo, 'guild' => $guild, - 'max_image_size_b' => $max_image_size_b + //'max_image_size_b' => $max_image_size_b )); } diff --git a/system/pages/guilds/change_motd.php b/system/pages/guilds/change_motd.php index babb806c..8d478377 100644 --- a/system/pages/guilds/change_motd.php +++ b/system/pages/guilds/change_motd.php @@ -34,7 +34,7 @@ if(empty($errors)) { $rank_list = $guild->getGuildRanksList(); $rank_list->orderBy('level', POT::ORDER_DESC); $guild_leader = false; - $account_players = $account_logged->getPlayers(); + $account_players = $account_logged->getPlayersList(); foreach($account_players as $player) { if($guild->getOwner()->getId() == $player->getId()) { $guild_vice = true; @@ -45,8 +45,8 @@ if(empty($errors)) { $saved = false; if($guild_leader) { - if(isset($_REQUEST['todo']) && $_REQUEST['todo'] == 'save') { - $motd = htmlspecialchars(stripslashes(substr($_REQUEST['motd'],0, setting('core.guild_motd_chars_limit')))); + if(isset($_POST['todo']) && $_POST['todo'] == 'save') { + $motd = htmlspecialchars(stripslashes(substr($_POST['motd'],0, setting('core.guild_motd_chars_limit')))); $guild->setCustomField('motd', $motd); $saved = true; } diff --git a/system/pages/guilds/change_nick.php b/system/pages/guilds/change_nick.php index bf773124..5016ef3e 100644 --- a/system/pages/guilds/change_nick.php +++ b/system/pages/guilds/change_nick.php @@ -20,17 +20,15 @@ if(!$logged) { } $name = isset($_REQUEST['name']) ? stripslashes($_REQUEST['name']) : null; -$new_nick = isset($_REQUEST['nick']) ? stripslashes($_REQUEST['nick']) : null; +$new_nick = isset($_POST['nick']) ? stripslashes($_POST['nick']) : null; $guild_name = isset($_REQUEST['guild']) ? urldecode($_REQUEST['guild']) : null; if(!$name) { $errors[] = 'Please enter new name.'; - return; } if(!$new_nick) { $errors[] = 'Please enter new nick.'; - return; } if(empty($errors)) diff --git a/system/pages/guilds/change_rank.php b/system/pages/guilds/change_rank.php index 4341db16..6d36bdf1 100644 --- a/system/pages/guilds/change_rank.php +++ b/system/pages/guilds/change_rank.php @@ -17,8 +17,9 @@ if(!$logged) { } else { $guild_name = isset($_REQUEST['guild']) ? urldecode($_REQUEST['guild']) : null; - if(!Validator::guildName($guild_name)) + if(!Validator::guildName($guild_name)) { $errors[] = Validator::getLastError(); + } } if(empty($errors)) @@ -42,7 +43,7 @@ $rank_list = $guild->getGuildRanksList(); $rank_list->orderBy('level', POT::ORDER_DESC); $guild_leader = false; $guild_vice = false; -$account_players = $account_logged->getPlayers(); +$account_players = $account_logged->getPlayersList(); foreach($account_players as $player) { $player_rank = $player->getRank(); @@ -65,22 +66,23 @@ foreach($account_players as $player) } } -if($guild_vice) -{ - if(isset($_REQUEST['todo']) && $_REQUEST['todo'] === 'save') - { +if($guild_vice) { + if(isset($_POST['todo']) && $_POST['todo'] === 'save') { $player_name = stripslashes($_REQUEST['name']); - $new_rank = (int) $_REQUEST['rankid']; - if(!Validator::characterName($player_name)) + $new_rank = (int) $_POST['rankid']; + + if(!Validator::characterName($player_name)) { $errors[] = 'Invalid player name format.'; + } + $rank = new OTS_GuildRank(); $rank->load($new_rank); if(!$rank->isLoaded()) $errors[] = "Rank with this ID doesn't exist."; if($level_in_guild <= $rank->getLevel() && !$guild_leader) $errors[] = "You can't set ranks with equal or higher level than your."; - if(empty($errors)) - { + + if(empty($errors)) { $player_to_change = new OTS_Player(); $player_to_change->find($player_name); if(!$player_to_change->isLoaded()) @@ -108,8 +110,7 @@ if($guild_vice) $errors[] = 'This player has higher rank in guild than you. You can\'t change his/her rank.'; } - if(empty($errors)) - { + if(empty($errors)) { $player_to_change->setRank($rank); $twig->display('success.html.twig', array( 'title' => 'Rank Changed', @@ -125,7 +126,7 @@ if($guild_vice) $result = getPlayersWithLowerRank($rank_list, $guild_leader, $db, $level_in_guild, $guild); $twig->display('guilds.change_rank.html.twig', array( - 'players' => isset($result['players']) ? $result['players'] : array(), + 'players' => $result['players'] ?? [], 'guild_name' => $guild->getName(), 'ranks' => $result['ranks'] )); diff --git a/system/pages/guilds/cleanup_players.php b/system/pages/guilds/cleanup_players.php index 7e02fbeb..ad110feb 100644 --- a/system/pages/guilds/cleanup_players.php +++ b/system/pages/guilds/cleanup_players.php @@ -12,33 +12,27 @@ defined('MYAAC') or die('Direct access not allowed!'); require __DIR__ . '/base.php'; -if(!$logged) -{ +if(!$logged) { echo "You are not logged in."; $twig->display('guilds.back_button.html.twig'); return; } -if(admin()) -{ +if(admin()) { $players_list = new OTS_Players_List(); $players_list->init(); } -else +else { $players_list = $account_logged->getPlayersList(); +} -if(count($players_list) > 0) -{ - foreach($players_list as $player) - { +if(count($players_list) > 0) { + foreach($players_list as $player) { $player_rank = $player->getRank(); - if($player_rank->isLoaded()) - { - if($player_rank->isLoaded()) - { + if($player_rank->isLoaded()) { + if($player_rank->isLoaded()) { $rank_guild = $player_rank->getGuild(); - if(!$rank_guild->isLoaded()) - { + if(!$rank_guild->isLoaded()) { $player->setRank(); $player->setGuildNick(''); $changed_ranks_of[] = $player->getName(); @@ -46,8 +40,7 @@ if(count($players_list) > 0) $player_rank->delete(); } } - else - { + else { $player->setRank(); $player->setGuildNick(''); $changed_ranks_of[] = $player->getName(); @@ -55,14 +48,20 @@ if(count($players_list) > 0) } } + echo "Deleted ranks (this ranks guilds doesn't exist [bug fix]):"; - if(!empty($deleted_ranks)) - foreach($deleted_ranks as $rank) - echo "
  • ".$rank; + if(!empty($deleted_ranks)) { + foreach ($deleted_ranks as $rank) { + echo "
  • " . $rank; + } + } echo "

    Changed ranks of players (rank or guild of rank doesn't exist [bug fix]):"; - if(!empty($changed_ranks_of)) - foreach($changed_ranks_of as $name) - echo "
  • ".$name; + + if(!empty($changed_ranks_of)) { + foreach ($changed_ranks_of as $name) { + echo "
  • " . $name; + } + } } else echo "0 players found."; diff --git a/system/pages/guilds/create.php b/system/pages/guilds/create.php index b404c494..ef0117e8 100644 --- a/system/pages/guilds/create.php +++ b/system/pages/guilds/create.php @@ -14,15 +14,15 @@ use MyAAC\Models\GuildRank; require __DIR__ . '/base.php'; -$guild_name = isset($_REQUEST['guild']) ? urldecode($_REQUEST['guild']) : NULL; -$name = isset($_REQUEST['name']) ? stripslashes($_REQUEST['name']) : NULL; -$todo = isset($_REQUEST['todo']) ? $_REQUEST['todo'] : NULL; +$guild_name = isset($_POST['guild']) ? urldecode($_POST['guild']) : NULL; +$name = isset($_POST['name']) ? stripslashes($_POST['name']) : NULL; +$todo = isset($_POST['todo']) ? $_POST['todo'] : NULL; if(!$logged) { - $guild_errors[] = 'You are not logged in. You can\'t create guild.'; + $errors[] = 'You are not logged in. You can\'t create guild.'; } $array_of_player_nig = array(); -if(empty($guild_errors)) +if(empty($errors)) { $account_players = $account_logged->getPlayersList(false); foreach($account_players as $player) @@ -41,45 +41,44 @@ if(empty($guild_errors)) if(empty($todo)) { if(count($array_of_player_nig) == 0) { - $guild_errors[] = 'On your account all characters are in guilds, have too low level to create new guild' . (setting('core.guild_need_premium') ? ' or you don\' have a premium account' : '') . '.'; + $errors[] = 'On your account all characters are in guilds, have too low level to create new guild' . (setting('core.guild_need_premium') ? ' or you don\' have a premium account' : '') . '.'; } } if($todo == 'save') { if(!Validator::guildName($guild_name)) { - $guild_errors[] = Validator::getLastError(); + $errors[] = Validator::getLastError(); $guild_name = ''; } if(!Validator::characterName($name)) { - $guild_errors[] = 'Invalid character name format.'; + $errors[] = 'Invalid character name format.'; $name = ''; } - if(empty($guild_errors)) { + if(empty($errors)) { $player = new OTS_Player(); $player->find($name); if(!$player->isLoaded()) { - $guild_errors[] = 'Character '.$name.' doesn\'t exist.'; + $errors[] = 'Character '.$name.' doesn\'t exist.'; } } - - if(empty($guild_errors)) + if(empty($errors)) { $guild = new OTS_Guild(); $guild->find($guild_name); if($guild->isLoaded()) { - $guild_errors[] = 'Guild '.$guild_name.' already exist. Select other name.'; + $errors[] = 'Guild '.$guild_name.' already exist. Select other name.'; } } - if(empty($guild_errors) && $player->isDeleted()) { - $guild_errors[] = "Character $name has been deleted."; + if(empty($errors) && $player->isDeleted()) { + $errors[] = "Character $name has been deleted."; } - if(empty($guild_errors)) + if(empty($errors)) { $bad_char = true; foreach($array_of_player_nig as $nick_from_list) { @@ -88,22 +87,22 @@ if($todo == 'save') } } if($bad_char) { - $guild_errors[] = 'Character '.$name.' isn\'t on your account or is already in guild.'; + $errors[] = 'Character '.$name.' isn\'t on your account or is already in guild.'; } } - if(empty($guild_errors)) { + if(empty($errors)) { if($player->getLevel() < setting('core.guild_need_level')) { - $guild_errors[] = 'Character '.$name.' has too low level. To create guild you need character with level ' . setting('core.guild_need_level') . '.'; + $errors[] = 'Character '.$name.' has too low level. To create guild you need character with level ' . setting('core.guild_need_level') . '.'; } if(setting('core.guild_need_premium') && !$account_logged->isPremium()) { - $guild_errors[] = 'Character '.$name.' is on FREE account. To create guild you need PREMIUM account.'; + $errors[] = 'Character '.$name.' is on FREE account. To create guild you need PREMIUM account.'; } } } -if(!empty($guild_errors)) { - $twig->display('error_box.html.twig', array('errors' => $guild_errors)); +if(!empty($errors)) { + $twig->display('error_box.html.twig', array('errors' => $errors)); unset($todo); } diff --git a/system/pages/guilds/delete_by_admin.php b/system/pages/guilds/delete_by_admin.php index e403cbda..f453cd7a 100644 --- a/system/pages/guilds/delete_by_admin.php +++ b/system/pages/guilds/delete_by_admin.php @@ -45,7 +45,10 @@ if(empty($errors)) { $twig->display('success.html.twig', array( 'title' => 'Delete Guild', 'description' => 'Are you sure you want delete guild ' . $guild_name . '?
    -
    ', +
    + ' . csrf(true) . ' + +
    ', 'custom_buttons' => $twig->render('guilds.back_button.html.twig') )); } diff --git a/system/pages/guilds/delete_guild.php b/system/pages/guilds/delete_guild.php index 978ac513..0e4bd0ba 100644 --- a/system/pages/guilds/delete_guild.php +++ b/system/pages/guilds/delete_guild.php @@ -21,7 +21,7 @@ if(empty($errors)) { $guild = new OTS_Guild(); $guild->find($guild_name); if(!$guild->isLoaded()) { - $errors[] = 'Guild with name '.$guild_name.' doesn\'t exist.'; + $errors[] = "Guild with name $guild_name doesn't exist."; } } @@ -31,7 +31,7 @@ if(empty($errors)) { $rank_list = $guild->getGuildRanksList(); $rank_list->orderBy('level', POT::ORDER_DESC); $guild_leader = false; - $account_players = $account_logged->getPlayers(); + $account_players = $account_logged->getPlayersList(); foreach($account_players as $player) { if($guild->getOwner()->getId() == $player->getId()) { diff --git a/system/pages/guilds/delete_invite.php b/system/pages/guilds/delete_invite.php index 7bf4067a..485ca9d0 100644 --- a/system/pages/guilds/delete_invite.php +++ b/system/pages/guilds/delete_invite.php @@ -15,47 +15,43 @@ require __DIR__ . '/base.php'; $guild_name = isset($_REQUEST['guild']) ? urldecode($_REQUEST['guild']) : null; $name = stripslashes($_REQUEST['name']); -if(!$logged) +if(!$logged) { $errors[] = 'You are not logged in. You can\'t delete invitations.'; +} -if(!Validator::guildName($guild_name)) +if(!Validator::guildName($guild_name)) { $errors[] = Validator::getLastError(); +} -if(!Validator::characterName($name)) +if(!Validator::characterName($name)) { $errors[] = 'Invalid name format.'; +} -if(empty($errors)) -{ +if(empty($errors)) { $guild = new OTS_Guild(); $guild->find($guild_name); if(!$guild->isLoaded()) $errors[] = "Guild with name " . $guild_name . " doesn't exist."; } -if(empty($errors)) -{ +if(empty($errors)) { $rank_list = $guild->getGuildRanksList(); $rank_list->orderBy('level', POT::ORDER_DESC); $guild_leader = false; $guild_vice = false; - $account_players = $account_logged->getPlayers(); - foreach($account_players as $player) - { + $account_players = $account_logged->getPlayersList(); + foreach($account_players as $player) { $player_rank = $player->getRank(); - if($player_rank->isLoaded()) - { - foreach($rank_list as $rank_in_guild) - { - if($rank_in_guild->getId() == $player_rank->getId()) - { + if($player_rank->isLoaded()) { + foreach($rank_list as $rank_in_guild) { + if($rank_in_guild->getId() == $player_rank->getId()) { $players_from_account_in_guild[] = $player->getName(); - if($player_rank->getLevel() > 1) - { + if($player_rank->getLevel() > 1) { $guild_vice = true; $level_in_guild = $player_rank->getLevel(); } - if($guild->getOwner()->getId() == $player->getId()) - { + + if($guild->getOwner()->getId() == $player->getId()) { $guild_vice = true; $guild_leader = true; } @@ -64,44 +60,46 @@ if(empty($errors)) } } - if(!$guild_vice) + if(!$guild_vice) { $errors[] = 'You are not a leader or vice leader of guild ' . $guild_name . '.'; -} -if(empty($errors)) -{ - $player = new OTS_Player(); - $player->find($name); - if(!$player->isLoaded()) - $errors[] = 'Player with name ' . $name . ' doesn\'t exist.'; + } } -if(empty($errors)) -{ +if(empty($errors)) { + $player = new OTS_Player(); + $player->find($name); + if(!$player->isLoaded()) { + $errors[] = "Player with name $name doesn't exist."; + } +} + +if(empty($errors)) { include(SYSTEM . 'libs/pot/InvitesDriver.php'); new InvitesDriver($guild); $invited_list = $guild->listInvites(); - if(count($invited_list) > 0) - { + if(count($invited_list) > 0) { $is_invited = false; - foreach($invited_list as $invited) - if($invited->getName() == $player->getName()) + foreach($invited_list as $invited) { + if ($invited->getName() == $player->getName()) { $is_invited = true; - if(!$is_invited) - $errors[] = ''.$player->getName().' isn\'t invited to your guild.'; + } + } + if(!$is_invited) { + $errors[] = '' . $player->getName() . ' isn\'t invited to your guild.'; + } } - else + else { $errors[] = 'No one is invited to your guild.'; + } } -if(!empty($errors)) -{ + +if(!empty($errors)) { $twig->display('error_box.html.twig', array('errors' => $errors)); $twig->display('guilds.back_button.html.twig', array('action' => getLink('guilds') . '?action=show&guild=' . $guild_name)); } -else -{ - if(isset($_REQUEST['todo']) && $_REQUEST['todo'] == 'save') - { +else { + if(isset($_POST['todo']) && $_POST['todo'] == 'save') { $guild->deleteInvite($player); $twig->display('success.html.twig', array( 'title' => 'Deleted player invitation', diff --git a/system/pages/guilds/delete_rank.php b/system/pages/guilds/delete_rank.php index 56322cd9..ce783137 100644 --- a/system/pages/guilds/delete_rank.php +++ b/system/pages/guilds/delete_rank.php @@ -13,25 +13,27 @@ defined('MYAAC') or die('Direct access not allowed!'); require __DIR__ . '/base.php'; $guild_name = isset($_REQUEST['guild']) ? urldecode($_REQUEST['guild']) : null; -$rank_to_delete = isset($_REQUEST['rankid']) ? (int) $_REQUEST['rankid'] : null; +$rank_to_delete = isset($_POST['rankid']) ? (int) $_POST['rankid'] : null; if(!Validator::guildName($guild_name)) { - $guild_errors[] = Validator::getLastError(); + $errors[] = Validator::getLastError(); } -if(empty($guild_errors)) { + +if(empty($errors)) { $guild = new OTS_Guild(); $guild->find($guild_name); if(!$guild->isLoaded()) { - $guild_errors[] = 'Guild with name '.$guild_name.' doesn\'t exist.'; + $errors[] = 'Guild with name '.$guild_name.' doesn\'t exist.'; } } -if(empty($guild_errors)) { + +if(empty($errors)) { if($logged) { $guild_leader_char = $guild->getOwner(); $rank_list = $guild->getGuildRanksList(); $rank_list->orderBy('level', POT::ORDER_DESC); $guild_leader = false; - $account_players = $account_logged->getPlayers(); + $account_players = $account_logged->getPlayersList(); foreach($account_players as $player) { if($guild->getOwner()->getId() == $player->getId()) { $guild_vice = true; @@ -39,21 +41,21 @@ if(empty($guild_errors)) { $level_in_guild = 3; } } + if($guild_leader) { $rank = new OTS_GuildRank(); $rank->load($rank_to_delete); if(!$rank->isLoaded()) { - $guild_errors2[] = 'Rank with ID '.$rank_to_delete.' doesn\'t exist.'; + $errors2[] = 'Rank with ID '.$rank_to_delete.' doesn\'t exist.'; } - else - { + else { if($rank->getGuild()->getId() != $guild->getId()) { - $guild_errors2[] = 'Rank with ID '.$rank_to_delete.' isn\'t from your guild.'; + $errors2[] = 'Rank with ID '.$rank_to_delete.' isn\'t from your guild.'; } else { if(count($rank_list) < 2) { - $guild_errors2[] = 'You have only 1 rank in your guild. You can\'t delete this rank.'; + $errors2[] = 'You have only 1 rank in your guild. You can\'t delete this rank.'; } else { @@ -87,19 +89,21 @@ if(empty($guild_errors)) { $player->setRank($new_rank); } } + $rank->delete(); $saved = true; } } } - if($saved) { + + if(isset($saved) && $saved) { $twig->display('success.html.twig', array( 'title' => 'Rank Deleted', 'description' => 'Rank '.$rank->getName().' has been deleted. Players with this rank has now other rank.', 'custom_buttons' => '' )); } else { - $twig->display('error_box.html.twig', array('errors' => $guild_errors2)); + $twig->display('error_box.html.twig', array('errors' => $errors2)); } $twig->display('guilds.back_button.html.twig', array( @@ -107,18 +111,16 @@ if(empty($guild_errors)) { 'action' => getLink('guilds') . '?guild='.$guild->getName().'&action=manager' )); } - else - { - $guild_errors[] = 'You are not a leader of guild!'; + else { + $errors[] = 'You are not a leader of guild!'; } } - else - { - $guild_errors[] = 'You are not logged. You can\'t manage guild.'; + else { + $errors[] = 'You are not logged. You can\'t manage guild.'; } } -if(!empty($guild_errors)) { - $twig->display('error_box.html.twig', array('errors' => $guild_errors)); +if(!empty($errors)) { + $twig->display('error_box.html.twig', array('errors' => $errors)); $twig->display('guilds.back_button.html.twig', array( 'new_line' => true, diff --git a/system/pages/guilds/invite.php b/system/pages/guilds/invite.php index 8fae8e27..9d6c9c06 100644 --- a/system/pages/guilds/invite.php +++ b/system/pages/guilds/invite.php @@ -36,7 +36,7 @@ if(empty($errors)) { $rank_list->orderBy('level', POT::ORDER_DESC); $guild_leader = false; $guild_vice = false; - $account_players = $account_logged->getPlayers(); + $account_players = $account_logged->getPlayersList(); foreach($account_players as $player) { $player_rank = $player->getRank(); if($player_rank->isLoaded()) { @@ -62,7 +62,7 @@ if(!$guild_vice) { $errors[] = 'You are not a leader or vice leader of guild '.$guild_name.'.'.$level_in_guild; } -if(isset($_REQUEST['todo']) && $_REQUEST['todo'] == 'save') { +if(isset($_POST['todo']) && $_POST['todo'] == 'save') { if(!Validator::characterName($name)) { $errors[] = 'Invalid name format.'; } @@ -71,7 +71,7 @@ if(isset($_REQUEST['todo']) && $_REQUEST['todo'] == 'save') { $player = new OTS_Player(); $player->find($name); if(!$player->isLoaded()) { - $errors[] = 'Player with name ' . $name . ' doesn\'t exist.'; + $errors[] = "Player with name $name doesn't exist."; } else if ($player->isDeleted()) { $errors[] = "Character with name $name has been deleted."; } @@ -102,7 +102,7 @@ if(!empty($errors)) { $twig->display('error_box.html.twig', array('errors' => $errors)); } else { - if(isset($_REQUEST['todo']) && $_REQUEST['todo'] == 'save') { + if(isset($_POST['todo']) && $_POST['todo'] == 'save') { $guild->invite($player); $twig->display('success.html.twig', array( 'title' => 'Invite player', diff --git a/system/pages/guilds/kick_player.php b/system/pages/guilds/kick_player.php index 5ce79187..736617b0 100644 --- a/system/pages/guilds/kick_player.php +++ b/system/pages/guilds/kick_player.php @@ -41,7 +41,7 @@ if(empty($errors)) { $rank_list->orderBy('level', POT::ORDER_DESC); $guild_leader = false; $guild_vice = false; - $account_players = $account_logged->getPlayers(); + $account_players = $account_logged->getPlayersList(); foreach($account_players as $player) { $player_rank = $player->getRank(); if($player_rank->isLoaded()) { @@ -102,7 +102,7 @@ if(!empty($errors)) { } else { - if(isset($_REQUEST['todo']) && $_REQUEST['todo'] == 'save') { + if(isset($_POST['todo']) && $_POST['todo'] == 'save') { $player->setRank(); $twig->display('success.html.twig', array( diff --git a/system/pages/guilds/leave.php b/system/pages/guilds/leave.php index 9a11595d..50f52a6c 100644 --- a/system/pages/guilds/leave.php +++ b/system/pages/guilds/leave.php @@ -34,7 +34,7 @@ if(empty($errors)) { $array_of_player_ig = array(); if(empty($errors)) { $guild_owner_name = $guild->getOwner()->getName(); - if(isset($_REQUEST['todo']) && $_REQUEST['todo'] == 'save') { + if(isset($_POST['todo']) && $_POST['todo'] == 'save') { if(!Validator::characterName($name)) { $errors[] = 'Invalid name format.'; } @@ -72,7 +72,7 @@ if(empty($errors)) { } else { - $account_players = $account_logged->getPlayers(); + $account_players = $account_logged->getPlayersList(); foreach($account_players as $player_fac) { $player_rank = $player_fac->getRank(); if($player_rank->isLoaded()) { @@ -94,7 +94,7 @@ if(!empty($errors)) { } else { - if(isset($_REQUEST['todo']) && $_REQUEST['todo'] == 'save') { + if(isset($_POST['todo']) && $_POST['todo'] == 'save') { $player->setRank(); $twig->display('success.html.twig', array( 'title' => 'Leave guild', diff --git a/system/pages/guilds/list.php b/system/pages/guilds/list.php index 96d7bf08..26d77d3a 100644 --- a/system/pages/guilds/list.php +++ b/system/pages/guilds/list.php @@ -14,23 +14,24 @@ defined('MYAAC') or die('Direct access not allowed!'); require __DIR__ . '/base.php'; $guilds_list = new OTS_Guilds_List(); -$guilds_list->orderBy("name"); +$guilds_list->orderBy('name'); $guilds = array(); -if(count($guilds_list) > 0) -{ +if(count($guilds_list) > 0) { /** * @var OTS_Guild $guild */ foreach ($guilds_list as $guild) { $guild_logo = $guild->getCustomField('logo_name'); - if (empty($guild_logo) || !file_exists(GUILD_IMAGES_DIR . $guild_logo)) - $guild_logo = "default.gif"; + if (empty($guild_logo) || !file_exists(GUILD_IMAGES_DIR . $guild_logo)) { + $guild_logo = 'default.gif'; + } $description = $guild->getCustomField('description'); $description_with_lines = str_replace(array("\r\n", "\n", "\r"), '
    ', $description, $count); - if ($count < setting('core.guild_description_lines_limit')) + if ($count < setting('core.guild_description_lines_limit')) { $description = nl2br($description); + } $guildName = $guild->getName(); $guilds[] = array('name' => $guildName, 'logo' => $guild_logo, 'link' => getGuildLink($guildName, false), 'description' => $description); @@ -39,6 +40,6 @@ if(count($guilds_list) > 0) $twig->display('guilds.list.html.twig', array( 'guilds' => $guilds, - 'logged' => isset($logged) ? $logged : false, + 'logged' => $logged ?? false, 'isAdmin' => admin(), )); diff --git a/system/pages/guilds/manager.php b/system/pages/guilds/manager.php index 4d59c22e..cfcc00c6 100644 --- a/system/pages/guilds/manager.php +++ b/system/pages/guilds/manager.php @@ -21,7 +21,7 @@ if(empty($errors)) { $guild = new OTS_Guild(); $guild->find($guild_name); if(!$guild->isLoaded()) { - $errors[] = 'Guild with name '.$guild_name.' doesn\'t exist.'; + $errors[] = "Guild with name $guild_name doesn't exist."; } } @@ -31,7 +31,7 @@ if(empty($errors)) { $rank_list = $guild->getGuildRanksList(); $rank_list->orderBy('level', POT::ORDER_DESC); $guild_leader = false; - $account_players = $account_logged->getPlayers(); + $account_players = $account_logged->getPlayersList(); foreach($account_players as $player) { if($guild_leader_char->getId() == $player->getId()) { $guild_vice = true; @@ -39,22 +39,22 @@ if(empty($errors)) { $level_in_guild = 3; } } + if($guild_leader) { $twig->display('guilds.manager.html.twig', array( 'guild' => $guild, 'rank_list' => $rank_list )); } - else - { + else { $errors[] = 'You are not a leader of guild!'; } } - else - { - $errors[] = 'You are not logged. You can\'t manage guild.'; + else { + $errors[] = "You are not logged. You can't manage guild."; } } + if(!empty($errors)) { $twig->display('error_box.html.twig', array('errors' => $errors)); } diff --git a/system/pages/guilds/pass_leadership.php b/system/pages/guilds/pass_leadership.php index c09b4285..40633b8a 100644 --- a/system/pages/guilds/pass_leadership.php +++ b/system/pages/guilds/pass_leadership.php @@ -15,51 +15,52 @@ require __DIR__ . '/base.php'; $guild_name = isset($_REQUEST['guild']) ? urldecode($_REQUEST['guild']) : NULL; $pass_to = isset($_REQUEST['player']) ? stripslashes($_REQUEST['player']) : NULL; if(!Validator::guildName($guild_name)) { - $guild_errors[] = Validator::getLastError(); + $errors[] = Validator::getLastError(); } -if(empty($guild_errors)) { +if(empty($errors)) { $guild = new OTS_Guild(); $guild->find($guild_name); if(!$guild->isLoaded()) { - $guild_errors[] = "Guild with name " . $guild_name . " doesn't exist."; + $errors[] = "Guild with name " . $guild_name . " doesn't exist."; } } -if(empty($guild_errors)) { + +if(empty($errors)) { if(isset($_POST['todo']) && $_POST['todo'] == 'save') { if(!Validator::characterName($pass_to)) { - $guild_errors2[] = 'Invalid player name format.'; + $errors2[] = 'Invalid player name format.'; } - if(empty($guild_errors2)) { + if(empty($errors2)) { $to_player = new OTS_Player(); $to_player->find($pass_to); if(!$to_player->isLoaded()) { - $guild_errors2[] = 'Player with name '.$pass_to.' doesn\'t exist.'; + $errors2[] = 'Player with name '.$pass_to.' doesn\'t exist.'; } else if ($to_player->isDeleted()) { - $guild_errors2[] = "Character with name $pass_to has been deleted."; + $errors2[] = "Character with name $pass_to has been deleted."; } - if(empty($guild_errors2)) { + if(empty($errors2)) { $to_player_rank = $to_player->getRank(); if($to_player_rank->isLoaded()) { $to_player_guild = $to_player_rank->getGuild(); if($to_player_guild->getId() != $guild->getId()) { - $guild_errors2[] = 'Player with name '.$to_player->getName().' isn\'t from your guild.'; + $errors2[] = 'Player with name '.$to_player->getName().' isn\'t from your guild.'; } } else { - $guild_errors2[] = 'Player with name '.$to_player->getName().' isn\'t from your guild.'; + $errors2[] = 'Player with name '.$to_player->getName().' isn\'t from your guild.'; } } } } } -if(empty($guild_errors) && empty($guild_errors2)) { +if(empty($errors) && empty($errors2)) { if($logged) { $guild_leader_char = $guild->getOwner(); $guild_leader = false; - $account_players = $account_logged->getPlayers(); + $account_players = $account_logged->getPlayersList(); foreach($account_players as $player) { if($guild_leader_char->getId() == $player->getId()) { $guild_vice = true; @@ -99,23 +100,23 @@ if(empty($guild_errors) && empty($guild_errors2)) { } } else { - $guild_errors[] = 'You are not a leader of guild!'; + $errors[] = 'You are not a leader of guild!'; } } else { - $guild_errors[] = "You are not logged. You can't manage guild."; + $errors[] = "You are not logged. You can't manage guild."; } } -if(empty($guild_errors) && !empty($guild_errors2)) { - $twig->display('error_box.html.twig', array('errors' => $guild_errors2)); +if(empty($errors) && !empty($errors2)) { + $twig->display('error_box.html.twig', array('errors' => $errors2)); echo '
    ' . $twig->render('buttons.back.html.twig') . '
    '; } -if(!empty($guild_errors)) { - if(!empty($guild_errors2)) { - $guild_errors = array_merge($guild_errors, $guild_errors2); +if(!empty($errors)) { + if(!empty($errors2)) { + $errors = array_merge($errors, $errors2); } - $twig->display('error_box.html.twig', array('errors' => $guild_errors)); + $twig->display('error_box.html.twig', array('errors' => $errors)); echo '
    ' . $twig->render('buttons.back.html.twig') . '
    '; } diff --git a/system/pages/guilds/save_ranks.php b/system/pages/guilds/save_ranks.php index e1483659..2a36e595 100644 --- a/system/pages/guilds/save_ranks.php +++ b/system/pages/guilds/save_ranks.php @@ -31,7 +31,7 @@ if(empty($errors)) { $rank_list = $guild->getGuildRanksList(); $rank_list->orderBy('level', POT::ORDER_DESC); $guild_leader = false; - $account_players = $account_logged->getPlayers(); + $account_players = $account_logged->getPlayersList(); foreach($account_players as $player) { if($guild_leader_char->getId() == $player->getId()) { @@ -61,6 +61,7 @@ if(empty($errors)) { $rank->save(); } + //show errors or redirect if(empty($errors)) { header("Location: " . getLink('guilds') . "?action=manager&guild=".$guild->getName()); @@ -73,10 +74,10 @@ if(empty($errors)) { } else { - $errors[] = 'You are not logged. You can\'t manage guild.'; + $errors[] = "You are not logged. You can't manage guild."; } } if(!empty($errors)) { - $twig->display('error_box.html.twig', array('errors' => $errors)); + $twig->display('error_box.html.twig', ['errors' => $errors]); } diff --git a/system/pages/guilds/show.php b/system/pages/guilds/show.php index 33039ad3..6fd07a91 100644 --- a/system/pages/guilds/show.php +++ b/system/pages/guilds/show.php @@ -16,19 +16,18 @@ $title = 'Guilds'; require __DIR__ . '/base.php'; $guild_name = isset($_REQUEST['guild']) ? urldecode($_REQUEST['guild']) : null; -if(!Validator::guildName($guild_name)) +if(!Validator::guildName($guild_name)) { $errors[] = Validator::getLastError(); +} -if(empty($errors)) -{ +if(empty($errors)) { $guild = new OTS_Guild(); $guild->find($guild_name); if(!$guild->isLoaded()) $errors[] = 'Guild with name '.$guild_name.' doesn\'t exist.'; } -if(!empty($errors)) -{ +if(!empty($errors)) { $twig->display('error_box.html.twig', array('errors' => $errors)); $twig->display('guilds.back_button.html.twig'); return; @@ -47,9 +46,8 @@ $level_in_guild = 0; $players_from_account_in_guild = array(); $players_from_account_ids = array(); -if($logged) -{ - $account_players = $account_logged->getPlayers(); +if($logged) { + $account_players = $account_logged->getPlayersList(); foreach($account_players as $player) { $players_from_account_ids[] = $player->getId(); diff --git a/system/templates/forum.new_thread.html.twig b/system/templates/forum.new_thread.html.twig index 3b5e080d..e37bda08 100644 --- a/system/templates/forum.new_thread.html.twig +++ b/system/templates/forum.new_thread.html.twig @@ -1,4 +1,4 @@ -
    + {{ csrf() }} diff --git a/system/templates/forum.remove_post.html.twig b/system/templates/forum.remove_post.html.twig new file mode 100644 index 00000000..85684e41 --- /dev/null +++ b/system/templates/forum.remove_post.html.twig @@ -0,0 +1,12 @@ + + {{ csrf() }} + + + +
    diff --git a/system/templates/forum.show_thread.html.twig b/system/templates/forum.show_thread.html.twig index 2626c2de..71812be7 100644 --- a/system/templates/forum.show_thread.html.twig +++ b/system/templates/forum.show_thread.html.twig @@ -53,15 +53,16 @@ Page: {{ links_to_pages|raw }}
  • {% if is_moderator %} {% if post.first_post != post.id %} - + {{ include('forum.remove_post.html.twig') }} {% else %} - + {{ include('forum.remove_post.html.twig') }} {% endif %} {% endif %} {% if logged and (post.player.getAccount().getId() == account_logged.getId() or is_moderator) %} - + + {% endif %} {% if logged %} diff --git a/system/templates/guilds.accept_invite.html.twig b/system/templates/guilds.accept_invite.html.twig index 0c2d0dc3..7a3acff5 100644 --- a/system/templates/guilds.accept_invite.html.twig +++ b/system/templates/guilds.accept_invite.html.twig @@ -7,12 +7,15 @@
    -
    + {{ csrf() }} + + + {% set i = 0 %} {% for player in invited_players %} - - {% set i = i + 1 %} + + {% set i = i + 1 %} {% endfor %} {{ include('buttons.submit.html.twig') }}
    diff --git a/system/templates/guilds.change_logo.html.twig b/system/templates/guilds.change_logo.html.twig index 13813e9b..5cdc8eda 100644 --- a/system/templates/guilds.change_logo.html.twig +++ b/system/templates/guilds.change_logo.html.twig @@ -8,7 +8,7 @@
    {{ csrf() }} - + Select new logo:
    diff --git a/system/templates/guilds.change_rank.html.twig b/system/templates/guilds.change_rank.html.twig index 13ad7cf4..bbeb4602 100644 --- a/system/templates/guilds.change_rank.html.twig +++ b/system/templates/guilds.change_rank.html.twig @@ -1,5 +1,6 @@ -
    + {{ csrf() }} + diff --git a/system/templates/guilds.create.html.twig b/system/templates/guilds.create.html.twig index c2326416..1f016567 100644 --- a/system/templates/guilds.create.html.twig +++ b/system/templates/guilds.create.html.twig @@ -1,5 +1,6 @@ - + {{ csrf() }} +
    Change Rank
    diff --git a/system/templates/guilds.delete_invite.html.twig b/system/templates/guilds.delete_invite.html.twig index 012f7d46..7367ccf2 100644 --- a/system/templates/guilds.delete_invite.html.twig +++ b/system/templates/guilds.delete_invite.html.twig @@ -7,9 +7,10 @@
    Create a {{ config.lua.serverName }} Guild
    diff --git a/system/templates/guilds.invite.html.twig b/system/templates/guilds.invite.html.twig index b0a35ac7..ee6af769 100644 --- a/system/templates/guilds.invite.html.twig +++ b/system/templates/guilds.invite.html.twig @@ -1,5 +1,6 @@ - + {{ csrf() }} + Invite player with name:       {{ include('buttons.submit.html.twig') }} diff --git a/system/templates/guilds.kick_player.html.twig b/system/templates/guilds.kick_player.html.twig index ded31cc8..521631c2 100644 --- a/system/templates/guilds.kick_player.html.twig +++ b/system/templates/guilds.kick_player.html.twig @@ -7,8 +7,9 @@
    - - {{ csrf() }} - {{ include('buttons.submit.html.twig') }} + + {{ csrf() }} + + {{ include('buttons.submit.html.twig') }}
    diff --git a/system/templates/guilds.leave_guild.html.twig b/system/templates/guilds.leave_guild.html.twig index 86642156..4d865cef 100644 --- a/system/templates/guilds.leave_guild.html.twig +++ b/system/templates/guilds.leave_guild.html.twig @@ -1,5 +1,6 @@ - + {{ csrf() }} +
    -
    + {{ csrf() }} + {{ include('buttons.submit.html.twig') }}
    diff --git a/system/templates/guilds.manager.html.twig b/system/templates/guilds.manager.html.twig index c932ce2b..adebdff2 100644 --- a/system/templates/guilds.manager.html.twig +++ b/system/templates/guilds.manager.html.twig @@ -101,7 +101,12 @@ Here you can change names of ranks, delete and add ranks, pass leadership to oth {% set i = 0 %} {% for rank in rank_list %} - + {% if setting('core.highscores_skills_box') or setting('core.highscores_vocation_box') %} - {% if setting('core.online_record') %} + {% if setting('core.online_record') and record|length > 0 %} From 2f26748112d412ba8106eb0cdbabeb8c69c98e87 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 17 Aug 2025 18:19:07 +0200 Subject: [PATCH 144/222] =?UTF-8?q?=E2=9D=A4=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- system/settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/settings.php b/system/settings.php index 5befa9ca..71cbc34e 100644 --- a/system/settings.php +++ b/system/settings.php @@ -1295,7 +1295,7 @@ Sent by MyAAC,
    'name' => 'Data Center', 'type' => 'text', 'desc' => 'Server Location, will be shown on online page', - 'default' => 'Frankfurt - Germany', + 'default' => 'Poland - Warsaw', ], [ 'type' => 'section', From 482f4067b2a2e7513d9ba214274a361ffaf123d8 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 17 Aug 2025 18:45:49 +0200 Subject: [PATCH 145/222] Menus should be saved for each template separately Trying to fix some weird bug --- system/template.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/template.php b/system/template.php index c97c8416..30cb5535 100644 --- a/system/template.php +++ b/system/template.php @@ -148,7 +148,7 @@ function get_template_menus(): array { global $template_name; - $result = Cache::remember('template_menus', 10 * 60, function () use ($template_name) { + $result = Cache::remember('template_menus_' . $template_name, 10 * 60, function () use ($template_name) { $result = Menu::select(['name', 'link', 'blank', 'color', 'category']) ->where('template', $template_name) ->orderBy('category') From 4701461b1f27ee23f660014c3c14fedeb6a98964 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 21 Aug 2025 20:54:58 +0200 Subject: [PATCH 146/222] Add some comment about optional sorting, into migrate:run command --- system/src/Commands/MigrateRunCommand.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/system/src/Commands/MigrateRunCommand.php b/system/src/Commands/MigrateRunCommand.php index 3bdb1452..0c8aa325 100644 --- a/system/src/Commands/MigrateRunCommand.php +++ b/system/src/Commands/MigrateRunCommand.php @@ -45,6 +45,22 @@ class MigrateRunCommand extends Command $down = $input->getOption('down') ?? false; + /** + * Sort according to $down option. + * Do we really want it? + * Or should we use order provided by user, + * even when it's not sorted correctly? + * Leaving it for consideration. + */ + /* + if ($down) { + rsort($ids); + } + else { + sort($ids); + } + */ + foreach ($ids as $id) { $this->executeMigration($id, $io, !$down); } From d85681880ee53164749fec1544b17205924960b8 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 21 Aug 2025 21:12:55 +0200 Subject: [PATCH 147/222] Rename file name to PluginSetupCommand --- .../{PluginInstallInstallCommand.php => PluginSetupCommand.php} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename system/src/Commands/{PluginInstallInstallCommand.php => PluginSetupCommand.php} (95%) diff --git a/system/src/Commands/PluginInstallInstallCommand.php b/system/src/Commands/PluginSetupCommand.php similarity index 95% rename from system/src/Commands/PluginInstallInstallCommand.php rename to system/src/Commands/PluginSetupCommand.php index 116eeb13..8923360c 100644 --- a/system/src/Commands/PluginInstallInstallCommand.php +++ b/system/src/Commands/PluginSetupCommand.php @@ -8,7 +8,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -class PluginInstallInstallCommand extends Command +class PluginSetupCommand extends Command { protected function configure(): void { From 3451715e96c4826989f4708cc9924adb41e7de67 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 22 Aug 2025 15:30:19 +0200 Subject: [PATCH 148/222] Settings class: Add type hints --- system/src/Settings.php | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/system/src/Settings.php b/system/src/Settings.php index ef3da830..fe16b2e7 100644 --- a/system/src/Settings.php +++ b/system/src/Settings.php @@ -7,16 +7,13 @@ use MyAAC\Models\Settings as ModelsSettings; class Settings implements \ArrayAccess { - static private $instance; - private $settingsFile = []; - private $settingsDatabase = []; - private $cache = []; - private $valuesAsked = []; - private $errors = []; + static private ?Settings $instance = null; + private array $settingsFile = []; + private array $settingsDatabase = []; + private array $cache = []; + private array $valuesAsked = []; + private array $errors = []; - /** - * @return Settings - */ public static function getInstance(): Settings { if (!self::$instance) { @@ -26,7 +23,7 @@ class Settings implements \ArrayAccess return self::$instance; } - public function load() + public function load(): void { $cache = Cache::getInstance(); if ($cache->enabled()) { @@ -47,7 +44,7 @@ class Settings implements \ArrayAccess } } - public function save($pluginName, $values) + public function save($pluginName, $values): bool { $this->loadPlugin($pluginName); @@ -104,7 +101,7 @@ class Settings implements \ArrayAccess return true; } - public function updateInDatabase($pluginName, $key, $value) + public function updateInDatabase($pluginName, $key, $value): void { if (ModelsSettings::where(['name' => $pluginName, 'key' => $key])->exists()) { ModelsSettings::where(['name' => $pluginName, 'key' => $key])->update(['value' => $value]); @@ -117,7 +114,7 @@ class Settings implements \ArrayAccess $this->clearCache(); } - public function deleteFromDatabase($pluginName, $key = null) + public function deleteFromDatabase($pluginName, $key = null): void { if (!isset($key)) { ModelsSettings::where('name', $pluginName)->delete(); @@ -383,7 +380,7 @@ class Settings implements \ArrayAccess } #[\ReturnTypeWillChange] - public function offsetSet($offset, $value) + public function offsetSet($offset, $value): void { if (is_null($offset)) { throw new \RuntimeException("Settings: You cannot set empty offset with value: $value!"); @@ -423,7 +420,7 @@ class Settings implements \ArrayAccess } #[\ReturnTypeWillChange] - public function offsetUnset($offset) + public function offsetUnset($offset): void { $this->loadPlugin($offset); @@ -455,7 +452,7 @@ class Settings implements \ArrayAccess * @return array|mixed */ #[\ReturnTypeWillChange] - public function offsetGet($offset) + public function offsetGet($offset): mixed { // try cache hit if(isset($this->cache[$offset])) { @@ -521,7 +518,7 @@ class Settings implements \ArrayAccess return $ret; } - private function updateValuesAsked($offset) + private function updateValuesAsked($offset): void { $pluginKeyName = $offset; if (strpos($offset, '.')) { @@ -537,7 +534,7 @@ class Settings implements \ArrayAccess } } - private function loadPlugin($offset) + private function loadPlugin($offset): void { $this->updateValuesAsked($offset); @@ -566,7 +563,7 @@ class Settings implements \ArrayAccess } } - public static function saveConfig($config, $filename, &$content = '') + public static function saveConfig($config, $filename, &$content = ''): bool|int { $content = " Date: Fri, 22 Aug 2025 16:04:52 +0200 Subject: [PATCH 149/222] Refactor code to use Cache::remember --- system/src/Settings.php | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/system/src/Settings.php b/system/src/Settings.php index fe16b2e7..17dc11f4 100644 --- a/system/src/Settings.php +++ b/system/src/Settings.php @@ -25,23 +25,16 @@ class Settings implements \ArrayAccess public function load(): void { - $cache = Cache::getInstance(); - if ($cache->enabled()) { - $tmp = ''; - if ($cache->fetch('settings', $tmp)) { - $this->settingsDatabase = unserialize($tmp); - return; + $this->settingsDatabase = Cache::remember('settings', 10 * 60, function () { + $settingsDatabase = []; + + $settings = ModelsSettings::all(); + foreach ($settings as $setting) { + $settingsDatabase[$setting->name][$setting->key] = $setting->value; } - } - $settings = ModelsSettings::all(); - foreach ($settings as $setting) { - $this->settingsDatabase[$setting->name][$setting->key] = $setting->value; - } - - if ($cache->enabled()) { - $cache->set('settings', serialize($this->settingsDatabase), 600); - } + return $settingsDatabase; + }); } public function save($pluginName, $values): bool From f8c4332e03e838d285ea0afb4b72b7c23e324d45 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 22 Aug 2025 17:27:53 +0200 Subject: [PATCH 150/222] Option to reset plugin settings by plugin name --- system/src/Commands/SettingsResetCommand.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/system/src/Commands/SettingsResetCommand.php b/system/src/Commands/SettingsResetCommand.php index 78748b00..3e4d793c 100644 --- a/system/src/Commands/SettingsResetCommand.php +++ b/system/src/Commands/SettingsResetCommand.php @@ -3,6 +3,7 @@ namespace MyAAC\Commands; use MyAAC\Models\Settings as SettingsModel; +use MyAAC\Plugins; use MyAAC\Settings; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -34,7 +35,14 @@ class SettingsResetCommand extends Command return Command::FAILURE; } - if (!$name) { + // find by plugin name + foreach (Plugins::getAllPluginsSettings() as $key => $setting) { + if ($setting['pluginFilename'] === $name) { + $name = $key; + } + } + + if (empty($name)) { SettingsModel::truncate(); } else { From bcc4b48eb05c4a9a61c7451ff7dfafa2266f530c Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 22 Aug 2025 17:39:14 +0200 Subject: [PATCH 151/222] Settings: Option to set boolean values as "yes" --- system/src/Settings.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/system/src/Settings.php b/system/src/Settings.php index 17dc11f4..bd4fb488 100644 --- a/system/src/Settings.php +++ b/system/src/Settings.php @@ -220,12 +220,7 @@ class Settings implements \ArrayAccess } else if ($setting['type'] === 'boolean') { if(isset($settingsDb[$key])) { - if($settingsDb[$key] === 'true') { - $value = true; - } - else { - $value = false; - } + $value = getBoolean($settingsDb[$key]); } else { $value = ($setting['default'] ?? false); From 17ca93d02020f18c3db86e72934d92b4e2e7b546 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 22 Aug 2025 17:51:19 +0200 Subject: [PATCH 152/222] Same with default --- system/src/Settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Settings.php b/system/src/Settings.php index bd4fb488..ec4a83fa 100644 --- a/system/src/Settings.php +++ b/system/src/Settings.php @@ -207,7 +207,7 @@ class Settings implements \ArrayAccess if (isset($setting['hidden']) && $setting['hidden']) { $value = ''; if ($setting['type'] === 'boolean') { - $value = ($setting['default'] ? 'true' : 'false'); + $value = (getBoolean($setting['default']) ? 'true' : 'false'); } else if (in_array($setting['type'], ['text', 'number', 'float', 'double', 'email', 'password', 'textarea'])) { $value = $setting['default']; From 4b948e9510f7ba69d00f84d7fdaea8b3bf05b630 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 22 Aug 2025 18:20:37 +0200 Subject: [PATCH 153/222] Option to change/set plugin settings by plugin name --- system/src/Commands/SettingsSetCommand.php | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/system/src/Commands/SettingsSetCommand.php b/system/src/Commands/SettingsSetCommand.php index 4ad33227..eac0ecc5 100644 --- a/system/src/Commands/SettingsSetCommand.php +++ b/system/src/Commands/SettingsSetCommand.php @@ -3,6 +3,7 @@ namespace MyAAC\Commands; use MyAAC\Models\Settings as SettingsModel; +use MyAAC\Plugins; use MyAAC\Settings; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -17,7 +18,7 @@ class SettingsSetCommand extends Command ->setDescription('Updates the setting specified by argument in database') ->addArgument('key', InputArgument::REQUIRED, - 'Setting name/key' + 'Setting key in format name.key' ) ->addArgument('value', InputArgument::REQUIRED, @@ -34,6 +35,18 @@ class SettingsSetCommand extends Command $key = $input->getArgument('key'); $value = $input->getArgument('value'); + // format settings_name.key + // example: core.template + $explode = explode('.', $key); + + // find by plugin name + foreach (Plugins::getAllPluginsSettings() as $_key => $setting) { + if ($setting['pluginFilename'] === $explode[0]) { + $explode[0] = $_key; + $key = implode('.', $explode); + } + } + $settings = Settings::getInstance(); $settings->clearCache(); $settings->load(); @@ -44,10 +57,6 @@ class SettingsSetCommand extends Command return Command::FAILURE; } - // format plugin_name.key - // example: core.template - $explode = explode('.', $key); - $settings->updateInDatabase($explode[0], $explode[1], $value); $settings->clearCache(); From 7a08f91d3fc0897c1ff76089ef3c649a2c6d2003 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 25 Aug 2025 09:31:50 +0200 Subject: [PATCH 154/222] plugin:unistall command --- .../src/Commands/PluginUninstallCommand.php | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 system/src/Commands/PluginUninstallCommand.php diff --git a/system/src/Commands/PluginUninstallCommand.php b/system/src/Commands/PluginUninstallCommand.php new file mode 100644 index 00000000..f1a14138 --- /dev/null +++ b/system/src/Commands/PluginUninstallCommand.php @@ -0,0 +1,40 @@ +setName('plugin:uninstall') + ->setDescription('This command uninstalls plugin') + ->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to uninstall'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + require SYSTEM . 'init.php'; + + $io = new SymfonyStyle($input, $output); + + $pluginName = $input->getArgument('plugin-name'); + + if (!Plugins::uninstall($pluginName)) { + $io->error('Error while uninstalling plugin ' . $pluginName . ': ' . Plugins::getError()); + return 2; + } + + foreach(Plugins::getWarnings() as $warning) { + $io->warning($warning); + } + + $io->success($pluginName . ' plugin has been successfully installed.'); + return Command::SUCCESS; + } +} From 1b9f68c9ec92365fde317de3d7820d8a416d71ca Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 25 Aug 2025 10:58:54 +0200 Subject: [PATCH 155/222] Update PluginUninstallCommand.php --- system/src/Commands/PluginUninstallCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Commands/PluginUninstallCommand.php b/system/src/Commands/PluginUninstallCommand.php index f1a14138..a5cc00f5 100644 --- a/system/src/Commands/PluginUninstallCommand.php +++ b/system/src/Commands/PluginUninstallCommand.php @@ -34,7 +34,7 @@ class PluginUninstallCommand extends Command $io->warning($warning); } - $io->success($pluginName . ' plugin has been successfully installed.'); + $io->success('Successfully uninstalled plugin ' . $pluginName); return Command::SUCCESS; } } From fec773ba4b740f35c0a3ef92ca8444a4c7d02082 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 25 Aug 2025 11:35:56 +0200 Subject: [PATCH 156/222] plugin:enable/disable commands --- system/src/Commands/PluginDisableCommand.php | 36 ++++++++++++++++++++ system/src/Commands/PluginEnableCommand.php | 36 ++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 system/src/Commands/PluginDisableCommand.php create mode 100644 system/src/Commands/PluginEnableCommand.php diff --git a/system/src/Commands/PluginDisableCommand.php b/system/src/Commands/PluginDisableCommand.php new file mode 100644 index 00000000..baa268dd --- /dev/null +++ b/system/src/Commands/PluginDisableCommand.php @@ -0,0 +1,36 @@ +setName('plugin:disable') + ->setDescription('This command disables plugin') + ->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to disable'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + require SYSTEM . 'init.php'; + + $io = new SymfonyStyle($input, $output); + + $pluginName = $input->getArgument('plugin-name'); + + if (!Plugins::disable($pluginName)) { + $io->error('Error while disabling plugin ' . $pluginName . ': ' . Plugins::getError()); + return 2; + } + + $io->success('Successfully disabled plugin ' . $pluginName); + return Command::SUCCESS; + } +} diff --git a/system/src/Commands/PluginEnableCommand.php b/system/src/Commands/PluginEnableCommand.php new file mode 100644 index 00000000..ae1acea0 --- /dev/null +++ b/system/src/Commands/PluginEnableCommand.php @@ -0,0 +1,36 @@ +setName('plugin:enable') + ->setDescription('This command enables plugin') + ->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to enable'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + require SYSTEM . 'init.php'; + + $io = new SymfonyStyle($input, $output); + + $pluginName = $input->getArgument('plugin-name'); + + if (!Plugins::enable($pluginName)) { + $io->error('Error while enabling plugin ' . $pluginName . ': ' . Plugins::getError()); + return 2; + } + + $io->success('Successfully enabled plugin ' . $pluginName); + return Command::SUCCESS; + } +} From 42671c5c199dd9e91c774d8c9d30da9e12f1b695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Morais?= Date: Wed, 27 Aug 2025 06:26:46 -0300 Subject: [PATCH 157/222] Update settings.php (#321) * Update settings.php added Transferable Coins to the store dropdown menu in the admin area * Adjust code a bit --------- Co-authored-by: slawkens --- system/settings.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/system/settings.php b/system/settings.php index 71cbc34e..904c46f5 100644 --- a/system/settings.php +++ b/system/settings.php @@ -28,6 +28,15 @@ if (!IS_CLI) { $siteURL = $serverUrl . $baseDir; } +$donateColumnOptions = [ + 'premium_points' => 'Premium Points', + 'coins' => 'Coins', +]; + +if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) { + $donateColumnOptions[ACCOUNT_COINS_TRANSFERABLE_COLUMN] = 'Coins Transferable'; +} + return [ 'name' => 'MyAAC', 'settings' => [ @@ -1598,7 +1607,7 @@ Sent by MyAAC,
    'name' => 'Donate Column', 'type' => 'options', 'desc' => 'What to give to player after donation - what column in accounts table to use.', - 'options' => ['premium_points' => 'Premium Points', 'coins' => 'Coins'], + 'options' => $donateColumnOptions, 'default' => 'premium_points', 'callbacks' => [ 'beforeSave' => function($key, $value, &$errorMessage) { From 2465bb6f9a284596024491eecd1e4c1223996d37 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 27 Aug 2025 11:40:54 +0200 Subject: [PATCH 158/222] Update settings.php --- system/settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/settings.php b/system/settings.php index 904c46f5..8f69dd48 100644 --- a/system/settings.php +++ b/system/settings.php @@ -33,7 +33,7 @@ $donateColumnOptions = [ 'coins' => 'Coins', ]; -if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) { +if (defined('HAS_ACCOUNT_COINS_TRANSFERABLE') && (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS)) { $donateColumnOptions[ACCOUNT_COINS_TRANSFERABLE_COLUMN] = 'Coins Transferable'; } From e4b66f34ac1751c3e3c2559c631cf8ec58c3cb3c Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 27 Aug 2025 12:15:52 +0200 Subject: [PATCH 159/222] Fix check for donate column --- system/settings.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/system/settings.php b/system/settings.php index 8f69dd48..5c703494 100644 --- a/system/settings.php +++ b/system/settings.php @@ -1612,8 +1612,9 @@ Sent by MyAAC,
    'callbacks' => [ 'beforeSave' => function($key, $value, &$errorMessage) { global $db; - if ($value == 'coins' && !HAS_ACCOUNT_COINS) { - $errorMessage = "Shop: Donate Column: Cannot set column to coins, because it doesn't exist in database."; + + if (!$db->hasColumn('accounts', $value)) { + $errorMessage = "Shop: Donate Column: Cannot set column to $value, because it doesn't exist in database."; return false; } return true; From 46adeefce3368835a876acca712310a4398a0410 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 27 Aug 2025 15:30:52 +0200 Subject: [PATCH 160/222] Update settings.php --- system/settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/settings.php b/system/settings.php index 5c703494..73605530 100644 --- a/system/settings.php +++ b/system/settings.php @@ -1612,7 +1612,7 @@ Sent by MyAAC,
    'callbacks' => [ 'beforeSave' => function($key, $value, &$errorMessage) { global $db; - + if (!$db->hasColumn('accounts', $value)) { $errorMessage = "Shop: Donate Column: Cannot set column to $value, because it doesn't exist in database."; return false; From 9725a3c2bdb7003f5cb48febb77604c31a9b805b Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 3 Sep 2025 23:47:27 +0200 Subject: [PATCH 161/222] Some servers don't have guild_invites table --- system/pages/guilds/invite.php | 10 ++++++++- system/pages/guilds/show.php | 29 ++++++++++++++------------ system/templates/guilds.view.html.twig | 18 +++++++++------- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/system/pages/guilds/invite.php b/system/pages/guilds/invite.php index 9d6c9c06..0984fd0a 100644 --- a/system/pages/guilds/invite.php +++ b/system/pages/guilds/invite.php @@ -23,6 +23,12 @@ if(!Validator::guildName($guild_name)) { $errors[] = Validator::getLastError(); } +if (!$db->hasTableAndColumns('guild_invites', ['player_id'])) { + $errors[] = "Guild invite is not possible on this website."; + $twig->display('error_box.html.twig', ['errors' => $errors]); + return; +} + if(empty($errors)) { $guild = new OTS_Guild(); $guild->find($guild_name); @@ -58,7 +64,7 @@ if(empty($errors)) { } } -if(!$guild_vice) { +if(empty($errors) && !$guild_vice) { $errors[] = 'You are not a leader or vice leader of guild '.$guild_name.'.'.$level_in_guild; } @@ -84,6 +90,7 @@ if(isset($_POST['todo']) && $_POST['todo'] == 'save') { } } } + if(empty($errors)) { include(SYSTEM . 'libs/pot/InvitesDriver.php'); new InvitesDriver($guild); @@ -104,6 +111,7 @@ if(!empty($errors)) { else { if(isset($_POST['todo']) && $_POST['todo'] == 'save') { $guild->invite($player); + $twig->display('success.html.twig', array( 'title' => 'Invite player', 'description' => 'Player with name ' . $player->getName() . ' has been invited to your guild.', diff --git a/system/pages/guilds/show.php b/system/pages/guilds/show.php index 6fd07a91..99ac6599 100644 --- a/system/pages/guilds/show.php +++ b/system/pages/guilds/show.php @@ -121,25 +121,28 @@ foreach($rank_list as $rank) } } -include(SYSTEM . 'libs/pot/InvitesDriver.php'); -new InvitesDriver($guild); -$invited_list = $guild->listInvites(); +$invited_list = []; $show_accept_invite = 0; -if($logged && count($invited_list) > 0) -{ - foreach($invited_list as $invited_player) - { - if(count($account_players) > 0) - { - foreach($account_players as $player_from_acc) - { - if($player_from_acc->isLoaded() && $invited_player->isLoaded() && $player_from_acc->getName() == $invited_player->getName()) - $show_accept_invite++; + +if ($db->hasTableAndColumns('guild_invites', ['player_id'])) { + include(SYSTEM . 'libs/pot/InvitesDriver.php'); + new InvitesDriver($guild); + $invited_list = $guild->listInvites(); + + if($logged && count($invited_list) > 0) { + foreach($invited_list as $invited_player) { + if(count($account_players) > 0) { + foreach($account_players as $player_from_acc) { + if($player_from_acc->isLoaded() && $invited_player->isLoaded() && $player_from_acc->getName() == $invited_player->getName()) { + $show_accept_invite++; + } + } } } } } + $useGuildNick = $db->hasTable('guild_members') || $db->hasTable('guild_membership') || $db->hasColumn('players', 'guildnick'); $twig->display('guilds.view.html.twig', array( diff --git a/system/templates/guilds.view.html.twig b/system/templates/guilds.view.html.twig index b8c0d0be..33dc1d3d 100644 --- a/system/templates/guilds.view.html.twig +++ b/system/templates/guilds.view.html.twig @@ -235,14 +235,16 @@ {% endif %} {% if isVice %} - - {{ csrf() }} -
    - + {% if db.hasTableAndColumns('guild_invites', ['player_id']) %} + + {{ csrf() }} + + + {% endif %} {{ csrf() }} From 7a9b11434e29a4c6345251b6f3e522143b3e6234 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 5 Sep 2025 13:25:25 +0200 Subject: [PATCH 162/222] Release v1.8.1 --- CHANGELOG-1.x.md | 16 ++++++++++++++++ common.php | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index b513cebf..8602a0c6 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,21 @@ # Changelog +## [1.8.1 - 05.09.2025] + +### Added +* New Commands: plugin:enable/disable/uninstall {plugin-name} (https://github.com/slawkens/myaac/commit/7a08f91d3fc0897c1ff76089ef3c649a2c6d2003, https://github.com/slawkens/myaac/commit/fec773ba4b740f35c0a3ef92ca8444a4c7d02082) +* Gifts: Added Transferable Coins to the store dropdown menu in the admin area (by @andreoam, #321) (https://github.com/slawkens/myaac/commit/42671c5c199dd9e91c774d8c9d30da9e12f1b695) + +### Changed +* Commands: Allow settings to be changed/reset by plugin name (https://github.com/slawkens/myaac/commit/f8c4332e03e838d285ea0afb4b72b7c23e324d45, https://github.com/slawkens/myaac/commit/4b948e9510f7ba69d00f84d7fdaea8b3bf05b630) +* Templates: Menus should be saved for each template separately (https://github.com/slawkens/myaac/commit/482f4067b2a2e7513d9ba214274a361ffaf123d8) + +### Fixed +* Online: Fix skulls display (#320) (https://github.com/slawkens/myaac/commit/98073a110ae13f9592ec9d2c4d1d1aace87587a9) +* Online: Fix if there is no world_id in the server_record table (https://github.com/slawkens/myaac/commit/b6e1620f14c20eecfc9001a7d86dfb67942985c6) (Reported by @gesior in #318) +* tibiacom: some fixes to menus (https://github.com/slawkens/myaac/commit/20f99903ae80c74ad66c1cf5a5ea8d0b0fc2fd70, https://github.com/slawkens/myaac/commit/11dae90fa94fbbf47447017db5e5847c33d6aadf) +* Guilds: Fix for some servers that don't have guild_invites table (https://github.com/slawkens/myaac/commit/9725a3c2bdb7003f5cb48febb77604c31a9b805b) + ## [1.8 - 02.08.2025] ### Added diff --git a/common.php b/common.php index 3e6a9291..2e80ad4b 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.8.1-dev'; +const MYAAC_VERSION = '1.8.1'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 0b8645994092d53f69fa4253be4f348f78025ff1 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 7 Sep 2025 09:33:18 +0200 Subject: [PATCH 163/222] Start v1.8.2-dev --- common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.php b/common.php index 2e80ad4b..3c0f7890 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.8.1'; +const MYAAC_VERSION = '1.8.2-dev'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 3f24f961b1cdeff5c60387e837ae454448bc5e1b Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 9 Sep 2025 15:17:06 +0200 Subject: [PATCH 164/222] Possibility to override routes with plugins pages, like characters.php No need to define routes in plugin.json anymore --- system/router.php | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/system/router.php b/system/router.php index a6da5f4b..9c9ce4ad 100644 --- a/system/router.php +++ b/system/router.php @@ -94,19 +94,30 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) $routesFinal[] = ['*', $page, '__database__/' . $page, 100]; } + $routes = require SYSTEM . 'routes.php'; Plugins::clearWarnings(); - foreach (Plugins::getRoutes() as $route) { - $routesFinal[] = [$route[0], $route[1], $route[2], $route[3] ?? 1000]; + + foreach (Plugins::getRoutes() as $pluginRoute) { + + $routesFinal[] = [$pluginRoute[0], $pluginRoute[1], $pluginRoute[2], $pluginRoute[3] ?? 1000]; + + // Possibility to override routes with plugins pages, like characters.php + foreach ($routes as &$route) { + if (str_contains($pluginRoute[2], 'pages/' . $route[2])) { + $route[2] = $pluginRoute[2]; + } + } /* echo '
    ';
    -		var_dump($route[1], $route[3], $route[2]);
    +		var_dump($pluginRoute[1], $pluginRoute[3], $pluginRoute[2]);
     		echo '/
    ';
     */
     	}
     
    -	$routes = require SYSTEM . 'routes.php';
     	foreach ($routes as $route) {
    -		if (!str_contains($route[2], '__redirect__') && !str_contains($route[2], '__database__')) {
    +		if (!str_contains($route[2], '__redirect__') && !str_contains($route[2], '__database__')
    +			&& !str_contains($route[2], 'plugins/')
    +		) {
     			if (!is_file(BASE . 'system/pages/' . $route[2])) {
     				continue;
     			}
    
    From 4eab805d26d8c5562b29ed699769919d77dabced Mon Sep 17 00:00:00 2001
    From: slawkens 
    Date: Tue, 9 Sep 2025 17:49:05 +0200
    Subject: [PATCH 165/222] Fix when config.local.php cannot be saved
    
    ---
     install/steps/5-database.php | 61 ++++++++++++++++++------------------
     1 file changed, 30 insertions(+), 31 deletions(-)
    
    diff --git a/install/steps/5-database.php b/install/steps/5-database.php
    index cb4f14a3..ecf7f150 100644
    --- a/install/steps/5-database.php
    +++ b/install/steps/5-database.php
    @@ -42,45 +42,44 @@ if(!$error) {
     	$configToSave['cache_prefix'] = 'myaac_' . generateRandomString(8, true, false, true);
     	$configToSave['database_auto_migrate'] = true;
     
    -	if(!$error) {
    -		$content = '';
    -		$saved = Settings::saveConfig($configToSave, BASE . 'config.local.php', $content);
    -		if ($saved) {
    -			success($locale['step_database_config_saved']);
    -			$_SESSION['saved'] = true;
    +	$content = '';
    +	$saved = Settings::saveConfig($configToSave, BASE . 'config.local.php', $content);
    +	if ($saved || file_exists(BASE . 'config.local.php')) {
    +		success($locale['step_database_config_saved']);
    +		$_SESSION['saved'] = true;
     
    -			require BASE . 'config.local.php';
    -			require BASE . 'install/includes/config.php';
    +		require BASE . 'config.local.php';
    +		require BASE . 'install/includes/config.php';
     
    -			if (!$error) {
    -				require BASE . 'install/includes/database.php';
    +		if (!$error) {
    +			require BASE . 'install/includes/database.php';
     
    -				if (isset($database_error)) { // we failed connect to the database
    -					error($database_error);
    +			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;
     				}
    -				else {
    -					if (!$db->hasTable('accounts')) {
    -						$tmp = str_replace('$TABLE$', 'accounts', $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']
    -						));
    -					}
    +				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$', '' . BASE . 'config.php', $locale['step_database_error_file']);
    -			error($locale['step_database_error_file'] . '
    - '); } + } else { + $error = true; + $_SESSION['config_content'] = $content; + unset($_SESSION['saved']); + + $locale['step_database_error_file'] = str_replace('$FILE$', '' . BASE . 'config.local.php', $locale['step_database_error_file']); + error($locale['step_database_error_file'] . '
    + '); } } ?> From a6032093b21e5bb3f0e75d2704da87d6dea6469d Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 14 Sep 2025 19:35:12 +0200 Subject: [PATCH 166/222] Better look for myaac-table --- system/templates/tables.style.html.twig | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/system/templates/tables.style.html.twig b/system/templates/tables.style.html.twig index 479db426..d4c2e91a 100644 --- a/system/templates/tables.style.html.twig +++ b/system/templates/tables.style.html.twig @@ -1,6 +1,9 @@ From 5aa9bbf1c8e580d973ec82ac012489f8e7bc437e Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 14 Sep 2025 20:50:00 +0200 Subject: [PATCH 167/222] Ignore child tables of myaac-table class --- system/templates/tables.style.html.twig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/system/templates/tables.style.html.twig b/system/templates/tables.style.html.twig index d4c2e91a..8aa6305b 100644 --- a/system/templates/tables.style.html.twig +++ b/system/templates/tables.style.html.twig @@ -1,9 +1,9 @@ From ed9beaf2b6ca069e304e569c52e5b9188b58f05c Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 14 Sep 2025 21:02:01 +0200 Subject: [PATCH 168/222] Fix account lost routes in tibiacom template --- templates/tibiacom/index.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/templates/tibiacom/index.php b/templates/tibiacom/index.php index 9746e8d8..bd00cf02 100644 --- a/templates/tibiacom/index.php +++ b/templates/tibiacom/index.php @@ -37,7 +37,9 @@ if(isset($config['boxes'])) $tmp = str_replace('/', '_', PAGE); $exp = explode('/', PAGE); if(PAGE !== 'account/create' && PAGE !== 'account/lost' && isset($exp[1])) { - if ($exp[0] === 'account') { + if ($exp[0] === 'account' && $exp[1] === 'lost') { + $tmp = 'account_lost'; + } elseif ($exp[0] === 'account') { $tmp = 'account_manage'; } else if ($exp[0] === 'news' && $exp[1] === 'archive') { $tmp = 'news_archive'; From d0112d1a67e8b854b65ad131f0375b79305df8d3 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 23 Sep 2025 21:45:32 +0200 Subject: [PATCH 169/222] Fix exception when email cannot be send on create account --- system/pages/account/create.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/system/pages/account/create.php b/system/pages/account/create.php index 15f2b8b5..7a0d3c56 100644 --- a/system/pages/account/create.php +++ b/system/pages/account/create.php @@ -268,8 +268,10 @@ if($save) } else { - error('An error occorred while sending email! Account not created. Try again. For Admin: More info can be found in system/logs/mailer-error.log'); + error('An error occurred while sending email! Account not created. Try again. For Admin: More info can be found in system/logs/mailer-error.log'); $new_account->delete(); + + return; } } else From 3c0cb53e17dd0b85394cfa0fdc9cf9ad8d4551df Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 23 Sep 2025 21:45:49 +0200 Subject: [PATCH 170/222] Add missing csrf() - fix create account buton --- templates/tibiacom/account.login.html.twig | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/tibiacom/account.login.html.twig b/templates/tibiacom/account.login.html.twig index 505cb38a..2125bee9 100644 --- a/templates/tibiacom/account.login.html.twig +++ b/templates/tibiacom/account.login.html.twig @@ -130,6 +130,7 @@
    {% apply spaceless %} + {{ csrf() }}
    From 85e7005fd3f0be51466151a3c122b96085fdfe68 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 24 Sep 2025 15:39:47 +0200 Subject: [PATCH 171/222] Fix Menu div wrong tag/closing (#329) --- templates/tibiacom/index.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/tibiacom/index.php b/templates/tibiacom/index.php index bd00cf02..4fd5a72a 100644 --- a/templates/tibiacom/index.php +++ b/templates/tibiacom/index.php @@ -338,7 +338,7 @@ if(isset($config['boxes']))
    - + From e0cc19ad86408ea27d2e5bbe8acfc3dc1bcb28c0 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 26 Sep 2025 07:54:40 +0200 Subject: [PATCH 172/222] Release v1.8.2 --- CHANGELOG-1.x.md | 15 +++++++++++++++ common.php | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index 8602a0c6..98a7b537 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,20 @@ # Changelog +## [1.8.2 - 26.09.2025] + +### Added +* Routes: Possibility to override routes with plugins pages, like characters.php - No need to define routes in plugin.json anymore (https://github.com/slawkens/myaac/commit/3f24f961b1cdeff5c60387e837ae454448bc5e1b) + +### Changed +* Style: Better look for myaac-table (https://github.com/slawkens/myaac/commit/a6032093b21e5bb3f0e75d2704da87d6dea6469d, https://github.com/slawkens/myaac/commit/5aa9bbf1c8e580d973ec82ac012489f8e7bc437e) + +### Fixed +* Install: Fix when config.local.php cannot be saved (https://github.com/slawkens/myaac/commit/4eab805d26d8c5562b29ed699769919d77dabced) +* Create Account: Fix an exception when email cannot be sent (https://github.com/slawkens/myaac/commit/d0112d1a67e8b854b65ad131f0375b79305df8d3) +* Login Page: Add missing csrf() - fix create account button (https://github.com/slawkens/myaac/commit/3c0cb53e17dd0b85394cfa0fdc9cf9ad8d4551df) +* tibiacom template: Fix account lost menu (https://github.com/slawkens/myaac/commit/ed9beaf2b6ca069e304e569c52e5b9188b58f05c) +* tibiacom template: Fix Menu div wrong tag/closing (#329) (https://github.com/slawkens/myaac/commit/85e7005fd3f0be51466151a3c122b96085fdfe68) + ## [1.8.1 - 05.09.2025] ### Added diff --git a/common.php b/common.php index 3c0f7890..868754d2 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.8.2-dev'; +const MYAAC_VERSION = '1.8.2'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From df7b6e29fb8875da97f431468c81ee99116271d9 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 26 Sep 2025 08:56:15 +0200 Subject: [PATCH 173/222] Replace firstChild with firstElementChild (Thanks to @un000000) --- templates/tibiacom/index.php | 12 ++++++------ tools/basic.js | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/templates/tibiacom/index.php b/templates/tibiacom/index.php index 4fd5a72a..5812b1cf 100644 --- a/templates/tibiacom/index.php +++ b/templates/tibiacom/index.php @@ -92,13 +92,13 @@ if(isset($config['boxes'])) // mouse-over and click events of the loginbox function MouseOverLoginBoxText(source) { - source.lastChild.style.visibility = "visible"; - source.firstChild.style.visibility = "hidden"; + source.lastElementChild.style.visibility = "visible"; + source.firstElementChild.style.visibility = "hidden"; } function MouseOutLoginBoxText(source) { - source.firstChild.style.visibility = "visible"; - source.lastChild.style.visibility = "hidden"; + source.firstElementChild.style.visibility = "visible"; + source.lastElementChild.style.visibility = "hidden"; } function LoginButtonAction() { @@ -228,11 +228,11 @@ if(isset($config['boxes'])) // mouse-over effects of menubuttons and submenuitems function MouseOverMenuItem(source) { - source.firstChild.style.visibility = "visible"; + source.firstElementChild.style.visibility = "visible"; } function MouseOutMenuItem(source) { - source.firstChild.style.visibility = "hidden"; + source.firstElementChild.style.visibility = "hidden"; } function MouseOverSubmenuItem(source) { diff --git a/tools/basic.js b/tools/basic.js index 8fa21fa9..c5f84618 100644 --- a/tools/basic.js +++ b/tools/basic.js @@ -1,11 +1,11 @@ function MouseOverBigButton(source) { - if (source?.firstChild?.style) { - source.firstChild.style.visibility = "visible"; + if (source?.firstElementChild?.style) { + source.firstElementChild.style.visibility = "visible"; } } function MouseOutBigButton(source) { - if (source?.firstChild?.style) { - source.firstChild.style.visibility = "hidden"; + if (source?.firstElementChild?.style) { + source.firstElementChild.style.visibility = "hidden"; } } function BigButtonAction(path) { From ac41b82579cbe231b33fdc13f93d7f284965cf0c Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 26 Sep 2025 10:14:38 +0200 Subject: [PATCH 174/222] Update index.php --- templates/tibiacom/index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/tibiacom/index.php b/templates/tibiacom/index.php index 5812b1cf..1bfe6164 100644 --- a/templates/tibiacom/index.php +++ b/templates/tibiacom/index.php @@ -102,14 +102,14 @@ if(isset($config['boxes'])) } function LoginButtonAction() { - if(loginStatus == "false") { + if(loginStatus === "false") { window.location = ""; } else { window.location = ""; } } function LoginstatusTextAction(source) { - if(loginStatus == "false") { + if(loginStatus === "false") { window.location = ""; } else { window.location = ""; From 8bc328d6fbc1d74eb243a946ba1204771f057a02 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 26 Sep 2025 10:14:48 +0200 Subject: [PATCH 175/222] Now v1.8.2 real --- CHANGELOG-1.x.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index 98a7b537..17e2a06e 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -14,6 +14,7 @@ * Login Page: Add missing csrf() - fix create account button (https://github.com/slawkens/myaac/commit/3c0cb53e17dd0b85394cfa0fdc9cf9ad8d4551df) * tibiacom template: Fix account lost menu (https://github.com/slawkens/myaac/commit/ed9beaf2b6ca069e304e569c52e5b9188b58f05c) * tibiacom template: Fix Menu div wrong tag/closing (#329) (https://github.com/slawkens/myaac/commit/85e7005fd3f0be51466151a3c122b96085fdfe68) +* tibiacom template: Replace firstChild with firstElementChild (Thanks to @un000000) (https://github.com/slawkens/myaac/commit/df7b6e29fb8875da97f431468c81ee99116271d9) ## [1.8.1 - 05.09.2025] From 4e9999cc0d3ae351645b3e7962d4c34d41d527b5 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 28 Sep 2025 14:13:51 +0200 Subject: [PATCH 176/222] Do not use constant on twig hooks So it can be displayed which hook is used --- system/templates/characters.html.twig | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/system/templates/characters.html.twig b/system/templates/characters.html.twig index 2e09bd26..75e15b68 100644 --- a/system/templates/characters.html.twig +++ b/system/templates/characters.html.twig @@ -9,7 +9,7 @@
    Leave guild
    {{ rank.getId() }} // Delete Rank + {{ rank.getId() }} // + + {{ csrf() }} + + + diff --git a/templates/tibiacom/account.login.html.twig b/templates/tibiacom/account.login.html.twig index f406d0c1..505cb38a 100644 --- a/templates/tibiacom/account.login.html.twig +++ b/templates/tibiacom/account.login.html.twig @@ -1,8 +1,11 @@ {{ hook('HOOK_ACCOUNT_LOGIN_BEFORE_PAGE') }} -
    + + {{ csrf() }} + {% if redirect is not null %} {% endif %} +
    From 45ef390829f8c8ecf8719190f42da85c60c21ec2 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 24 May 2025 11:42:59 +0200 Subject: [PATCH 034/222] Nothing important --- system/templates/account.change-password.html.twig | 2 +- system/templates/account.characters.change-name.html.twig | 4 ++-- system/templates/account.generate_recovery_key.html.twig | 2 +- system/templates/account.login.html.twig | 6 ++++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/system/templates/account.change-password.html.twig b/system/templates/account.change-password.html.twig index 318d393f..df101323 100644 --- a/system/templates/account.change-password.html.twig +++ b/system/templates/account.change-password.html.twig @@ -37,7 +37,7 @@ Please enter your current password and a new password. For your security, please
    - @@ -204,13 +210,14 @@ {% if recovery_key is empty %} {% endif %} @@ -258,13 +265,14 @@ @@ -398,8 +406,9 @@ From 29faa4f6957dcbbcc16fb4468be4871e7d787ace Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 15 Jun 2025 19:03:03 +0200 Subject: [PATCH 084/222] Add missing csrf() in success.html.twig --- system/templates/success.html.twig | 1 + 1 file changed, 1 insertion(+) diff --git a/system/templates/success.html.twig b/system/templates/success.html.twig index 5d9a9b8b..eaee1fb1 100644 --- a/system/templates/success.html.twig +++ b/system/templates/success.html.twig @@ -19,6 +19,7 @@
    + {{ csrf() }} {{ include('buttons.submit.html.twig') }} diff --git a/system/templates/account.characters.change-name.html.twig b/system/templates/account.characters.change-name.html.twig index 7c0d18f3..7a0cfe22 100644 --- a/system/templates/account.characters.change-name.html.twig +++ b/system/templates/account.characters.change-name.html.twig @@ -35,7 +35,7 @@ To change a name of character select player and choose a new name.
    -
    + {{ csrf() }} @@ -48,7 +48,7 @@ To change a name of character select player and choose a new name.
    - - diff --git a/system/templates/account.login.html.twig b/system/templates/account.login.html.twig index fe52d7f9..a264e488 100644 --- a/system/templates/account.login.html.twig +++ b/system/templates/account.login.html.twig @@ -2,9 +2,11 @@ Please enter your account {{ account|lower }} and your password.
    Create an account if you do not have one yet.

    {{ csrf() }} + {% if redirect is not null %} {% endif %} +
    + {{ csrf() }} {{ include('buttons.back.html.twig') }} diff --git a/system/templates/account.generate_recovery_key.html.twig b/system/templates/account.generate_recovery_key.html.twig index 29ed1ec5..c34132f0 100644 --- a/system/templates/account.generate_recovery_key.html.twig +++ b/system/templates/account.generate_recovery_key.html.twig @@ -35,7 +35,7 @@ To generate recovery key for your account please enter your password.

    {{ csrf() }}
    + {{ include('buttons.back.html.twig') }}
    @@ -64,7 +66,7 @@ Please enter your account {{ account|lower }} and your password.
    - @@ -73,7 +75,7 @@ Please enter your account {{ account|lower }} and your password.
    - - + {% endfor %} From 064b92984172e0e5ece25b36902f1026b49aa43c Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 16:39:02 +0200 Subject: [PATCH 049/222] Allow [] in character name (for :string) --- system/router.php | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/system/router.php b/system/router.php index 40b45861..516c4286 100644 --- a/system/router.php +++ b/system/router.php @@ -129,14 +129,14 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) return ($a[3] < $b[3]) ? -1 : 1; }); + $aliases = [ + [':int', ':string', ':alphanum'], + [':\d+', ':[A-Za-z0-9-_%+\' \[\]]+', ':[A-Za-z0-9]+'], + ]; + // remove duplicates // if same route pattern, but different priority - $routesFinal = array_filter($routesFinal, function ($a) { - $aliases = [ - [':int', ':string', ':alphanum'], - [':\d+', ':[A-Za-z0-9-_%+\' ]+', ':[A-Za-z0-9]+'], - ]; - + $routesFinal = array_filter($routesFinal, function ($a) use ($aliases) { // apply aliases $a[1] = str_replace($aliases[0], $aliases[1], $a[1]); @@ -171,11 +171,6 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) $route[0] = array_map($toUpperCase, $route[0]); } - $aliases = [ - [':int', ':string', ':alphanum'], - [':\d+', ':[A-Za-z0-9-_%+\' ]+', ':[A-Za-z0-9]+'], - ]; - // apply aliases $route[1] = str_replace($aliases[0], $aliases[1], $route[1]); From dd731fd49be9d0f33e8c582b4445a254160e1855 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 16:43:43 +0200 Subject: [PATCH 050/222] Revert previous commit partially --- system/router.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/router.php b/system/router.php index 516c4286..1102ef0e 100644 --- a/system/router.php +++ b/system/router.php @@ -131,7 +131,7 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) $aliases = [ [':int', ':string', ':alphanum'], - [':\d+', ':[A-Za-z0-9-_%+\' \[\]]+', ':[A-Za-z0-9]+'], + [':\d+', ':[A-Za-z0-9-_%+\' ]+', ':[A-Za-z0-9]+'], ]; // remove duplicates From de6603a51347b9e656c58637ed9971fffdd7cedd Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 16:49:45 +0200 Subject: [PATCH 051/222] Allow [] in character name (again), example: [God] Test --- system/routes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/routes.php b/system/routes.php index 13cee37f..c804ec8c 100644 --- a/system/routes.php +++ b/system/routes.php @@ -22,7 +22,7 @@ return [ ['GET', 'account/confirm-email/{hash:alphanum}', 'account/confirm-email.php'], ['GET', 'bans/{page:int}', 'bans.php'], - [['GET', 'POST'], 'characters[/{name:string}]', 'characters.php'], + [['GET', 'POST'], 'characters[/{name:[A-Za-z0-9-_%+\' \[\]]+}]', 'characters.php'], ['GET', 'changelog[/{page:int}]', 'changelog.php'], [['GET', 'POST'], 'monsters[/{name:string}]', 'monsters.php'], From 01d49692ede5a3cc426f0711c642d66d5d0e2d70 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 16:59:20 +0200 Subject: [PATCH 052/222] Update CHANGELOG-1.x.md --- CHANGELOG-1.x.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index 291b5441..9c68b895 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,26 @@ # Changelog +## [1.6 - 03.06.2025] + +### Added +* Add new setting/configurable: site_url, prevents domain spoofing (https://github.com/slawkens/myaac/commit/d8a6090be382c35c19117cfef964b594ed02b8d4) +* Add new account coins setting (https://github.com/slawkens/myaac/commit/28886551e86fe562172c4c7f2afb89a2e7672c2e) +* autoload: settings/install/init.php (https://github.com/slawkens/myaac/commit/e5749437074c3b3556628a2aeb5bad2edf97bde0, https://github.com/slawkens/myaac/commit/7d213f479a7e40c6254069b5fc4e578dc32bf8d9) +* Protect against csrf in more places (accounts & guilds & forums pages) (https://github.com/slawkens/myaac/commit/6eda38603c8ed7e99b92a78a4600b1245377f74d, https://github.com/slawkens/myaac/commit/e776bd52beb3064a9e694efd1b9021ec972ee2f6, https://github.com/slawkens/myaac/commit/84d502bf105f2a789481fba1acc820d236b4de66) +* Added two new hooks for pages loaded from database (custom pages): HOOK_BEFORE_PAGE_CUSTOM, HOOK_AFTER_PAGE_CUSTOM (https://github.com/slawkens/myaac/commit/c961a1ebf837f2ab1734a825ff2c57b4937610c9) +* Add global variables into $hooks->executeFilter (https://github.com/slawkens/myaac/commit/8fdea943768b20193eede99d60313ee84511a0be) +* Add getNPCsCount() to OTS_InfoRespond (https://github.com/slawkens/myaac/commit/7d435ff6433ef1fb2295ee79ed043ee10dc725e9) + +### Fixed +* Allow [] in character name (https://github.com/slawkens/myaac/commit/064b92984172e0e5ece25b36902f1026b49aa43c) +* Do not allow access to tools/ folder after install (https://github.com/slawkens/myaac/commit/6e0f5913831f8dba69fd2d1505be3e2a303c6324) +* Fix CHANGELOG-1.x.md loading in admin panel (https://github.com/slawkens/myaac/commit/4a30fb495dbfbe1d434e8d52419eaf44fe517aee) +* Fix links not working in admin dashboard modules (https://github.com/slawkens/myaac/commit/be7b27c31aa3bbd6c0289c34d1e61139a3fe015c) +* Fix twig variables: logged + account_logged being not set directly after login (https://github.com/slawkens/myaac/commit/1e9b10d6489c488cadf7f6ed17b42f1ea6c767a8) + +### Changed +* OTS_ServerInfo -> move setTimeout out of class - Possibility to use the class without MyAAC (https://github.com/slawkens/myaac/commit/40d65a6613149fda51bdceb82c807e5301a3388b) + ## [1.5 - 14.05.2025] ### Added From dc839abfbbb826cd0674c30ab623422eb24efdff Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 16:59:55 +0200 Subject: [PATCH 053/222] Release v1.6 --- common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.php b/common.php index cec3a3c2..35af07af 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.5.1-dev'; +const MYAAC_VERSION = '1.6'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From ce2af2bb7afe5f5e203d1695622550e4d5c01f74 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 17:33:17 +0200 Subject: [PATCH 054/222] Update CHANGELOG-1.x.md --- CHANGELOG-1.x.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index 9c68b895..d3d81a56 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -5,14 +5,14 @@ ### Added * Add new setting/configurable: site_url, prevents domain spoofing (https://github.com/slawkens/myaac/commit/d8a6090be382c35c19117cfef964b594ed02b8d4) * Add new account coins setting (https://github.com/slawkens/myaac/commit/28886551e86fe562172c4c7f2afb89a2e7672c2e) -* autoload: settings/install/init.php (https://github.com/slawkens/myaac/commit/e5749437074c3b3556628a2aeb5bad2edf97bde0, https://github.com/slawkens/myaac/commit/7d213f479a7e40c6254069b5fc4e578dc32bf8d9) +* autoload: settings/install/init.php (https://github.com/slawkens/myaac/commit/e5749437074c3b3556628a2aeb5bad2edf97bde0, https://github.com/slawkens/myaac/commit/7d213f479a7e40c6254069b5fc4e578dc32bf8d9, https://github.com/slawkens/myaac/commit/207d6bc69120aba1af2b51808f17e0059b571fed) * Protect against csrf in more places (accounts & guilds & forums pages) (https://github.com/slawkens/myaac/commit/6eda38603c8ed7e99b92a78a4600b1245377f74d, https://github.com/slawkens/myaac/commit/e776bd52beb3064a9e694efd1b9021ec972ee2f6, https://github.com/slawkens/myaac/commit/84d502bf105f2a789481fba1acc820d236b4de66) * Added two new hooks for pages loaded from database (custom pages): HOOK_BEFORE_PAGE_CUSTOM, HOOK_AFTER_PAGE_CUSTOM (https://github.com/slawkens/myaac/commit/c961a1ebf837f2ab1734a825ff2c57b4937610c9) * Add global variables into $hooks->executeFilter (https://github.com/slawkens/myaac/commit/8fdea943768b20193eede99d60313ee84511a0be) * Add getNPCsCount() to OTS_InfoRespond (https://github.com/slawkens/myaac/commit/7d435ff6433ef1fb2295ee79ed043ee10dc725e9) ### Fixed -* Allow [] in character name (https://github.com/slawkens/myaac/commit/064b92984172e0e5ece25b36902f1026b49aa43c) +* Allow [] in character name (https://github.com/slawkens/myaac/commit/de6603a51347b9e656c58637ed9971fffdd7cedd) * Do not allow access to tools/ folder after install (https://github.com/slawkens/myaac/commit/6e0f5913831f8dba69fd2d1505be3e2a303c6324) * Fix CHANGELOG-1.x.md loading in admin panel (https://github.com/slawkens/myaac/commit/4a30fb495dbfbe1d434e8d52419eaf44fe517aee) * Fix links not working in admin dashboard modules (https://github.com/slawkens/myaac/commit/be7b27c31aa3bbd6c0289c34d1e61139a3fe015c) From 2dba778167d349a5230c1dcd4f9e19c2728562fa Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 18:38:02 +0200 Subject: [PATCH 055/222] Update example.json --- plugins/example.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/example.json b/plugins/example.json index 395db41d..fd5e183b 100644 --- a/plugins/example.json +++ b/plugins/example.json @@ -51,5 +51,8 @@ "themes": true, "admin-pages": true, "admin-pages-sub-folders": true, + "settings": true, + "install": true, + "init": false } } From db09980de10ee2b9f45a37ef839ca0c712edbaf1 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 22:57:33 +0200 Subject: [PATCH 056/222] Start v1.6.1-dev --- common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.php b/common.php index 35af07af..2af620c9 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.6'; +const MYAAC_VERSION = '1.6.1-dev'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 9d8e9d27bd87167d8d4005942a6af62bfe4c0892 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 5 Jun 2025 18:11:31 +0200 Subject: [PATCH 057/222] Ignore duplicated route exception --- system/router.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/system/router.php b/system/router.php index 1102ef0e..20f3f07a 100644 --- a/system/router.php +++ b/system/router.php @@ -174,7 +174,12 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) // apply aliases $route[1] = str_replace($aliases[0], $aliases[1], $route[1]); - $r->addRoute($route[0], $route[1], $route[2]); + try { + $r->addRoute($route[0], $route[1], $route[2]); + } + catch (\Exception $e) { + // duplicated route, just ignore + } } if (config('env') === 'dev') { From dcc703b1eb432586935fad5f05ce4a2561a0f020 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 5 Jun 2025 18:11:44 +0200 Subject: [PATCH 058/222] Remove optional param, make it required for few routes --- system/routes.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/system/routes.php b/system/routes.php index c804ec8c..b4af29f0 100644 --- a/system/routes.php +++ b/system/routes.php @@ -22,11 +22,11 @@ return [ ['GET', 'account/confirm-email/{hash:alphanum}', 'account/confirm-email.php'], ['GET', 'bans/{page:int}', 'bans.php'], - [['GET', 'POST'], 'characters[/{name:[A-Za-z0-9-_%+\' \[\]]+}]', 'characters.php'], - ['GET', 'changelog[/{page:int}]', 'changelog.php'], - [['GET', 'POST'], 'monsters[/{name:string}]', 'monsters.php'], + [['GET', 'POST'], 'characters/{name:[A-Za-z0-9-_%+\' \[\]]+}', 'characters.php'], + ['GET', 'changelog/{page:int}', 'changelog.php'], + [['GET', 'POST'], 'monsters/{name:string}', 'monsters.php'], - [['GET', 'POST'], 'faq[/{action:string}]', 'faq.php'], + [['GET', 'POST'], 'faq/{action:string}', 'faq.php'], [['GET', 'POST'], 'forum/{action:string}', 'forum.php'], ['GET', 'forum/board/{id:int}', 'forum/show_board.php'], From 835dda9659cb6b419baf25807ecf9f5cd5ca8b04 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 5 Jun 2025 19:08:53 +0200 Subject: [PATCH 059/222] Remove duplicated code - account redirect, already in account/manage --- system/pages/account/redirect.php | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 system/pages/account/redirect.php diff --git a/system/pages/account/redirect.php b/system/pages/account/redirect.php deleted file mode 100644 index 78bc54d9..00000000 --- a/system/pages/account/redirect.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @author Slawkens - * @copyright 2019 MyAAC - * @link https://my-aac.org - */ -defined('MYAAC') or die('Direct access not allowed!'); - -$redirect = urldecode($_REQUEST['redirect']); - -// should never happen, unless hacker modify the URL -if (!str_contains($redirect, BASE_URL)) { - error('Fatal error: Cannot redirect outside the website.'); - return; -} - -$twig->display('account.redirect.html.twig', array( - 'redirect' => $redirect -)); From f78285030708ad3c74ab048711f73bbf3ee5281e Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 6 Jun 2025 22:10:13 +0200 Subject: [PATCH 060/222] Move counter & visitors code before router In case someone wants to include that info on page --- index.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/index.php b/index.php index bc8a3663..87204e01 100644 --- a/index.php +++ b/index.php @@ -117,6 +117,14 @@ if(setting('core.backward_support')) { $config['status']['serverStatus_' . $key] = $value; } +if(setting('core.views_counter')) { + require_once SYSTEM . 'counter.php'; +} + +if(setting('core.visitors_counter')) { + $visitors = new Visitors(setting('core.visitors_counter_ttl')); +} + require_once SYSTEM . 'router.php'; // anonymous usage statistics @@ -153,13 +161,6 @@ if(setting('core.anonymous_usage_statistics')) { } } -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 */ From 8d29fdb98b92dbc3d2853ef88a185c67036b4a77 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 9 Jun 2025 14:24:22 +0200 Subject: [PATCH 061/222] Set TinyMCE license key to gpl (Avoid warning message in browser console) --- system/templates/tinymce.html.twig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/templates/tinymce.html.twig b/system/templates/tinymce.html.twig index effea162..7f065477 100644 --- a/system/templates/tinymce.html.twig +++ b/system/templates/tinymce.html.twig @@ -23,6 +23,8 @@ {title: 'Colored Table', value: 'myaac-table'}, ], + license_key: 'gpl', + setup: function (ed) { ed.on('NodeChange', function (e) { if (ed.getContent() !== lastContent) { From 309c1fb715b882e67cb673b1544a03befbf64a22 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 9 Jun 2025 14:24:36 +0200 Subject: [PATCH 062/222] Remove deprecated TinyMCE plugin - template --- system/templates/tinymce.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/templates/tinymce.html.twig b/system/templates/tinymce.html.twig index 7f065477..00f1638a 100644 --- a/system/templates/tinymce.html.twig +++ b/system/templates/tinymce.html.twig @@ -8,7 +8,7 @@ selector: "#editor", content_css: '{{ constant('ADMIN_URL') }}template/style.css', theme: "silver", - plugins: 'preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount help code emoticons', + plugins: 'preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount help code emoticons', toolbar1: 'formatselect | bold italic strikethrough forecolor backcolor | emoticons link | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat code', resize: 'both', image_advtab: true, From 0812fe025d3bd13ddc9b40ebc851b5f2185123e6 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 9 Jun 2025 21:14:44 +0200 Subject: [PATCH 063/222] Update settings_save.php --- admin/tools/settings_save.php | 1 - 1 file changed, 1 deletion(-) diff --git a/admin/tools/settings_save.php b/admin/tools/settings_save.php index dffea976..b161838c 100644 --- a/admin/tools/settings_save.php +++ b/admin/tools/settings_save.php @@ -1,6 +1,5 @@ Date: Mon, 9 Jun 2025 21:18:42 +0200 Subject: [PATCH 064/222] Add missing csrf() into account manage actions --- .../tibiacom/account.management.html.twig | 104 ++++++++++-------- 1 file changed, 58 insertions(+), 46 deletions(-) diff --git a/templates/tibiacom/account.management.html.twig b/templates/tibiacom/account.management.html.twig index 5125f3ed..7d8cf37c 100644 --- a/templates/tibiacom/account.management.html.twig +++ b/templates/tibiacom/account.management.html.twig @@ -11,13 +11,14 @@ @@ -59,13 +60,14 @@
    + {{ include('buttons.submit.html.twig') }}
    + {{ include('buttons.account_lost.html.twig') }} From ae847ff9a6c3b60aeacd317422a63a50181971e0 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 24 May 2025 11:51:06 +0200 Subject: [PATCH 035/222] Nothing important: tabs --- system/libs/pot/OTS_InfoRespond.php | 348 +++++++++++----------- system/libs/pot/OTS_ServerStatus.php | 416 +++++++++++++-------------- 2 files changed, 382 insertions(+), 382 deletions(-) diff --git a/system/libs/pot/OTS_InfoRespond.php b/system/libs/pot/OTS_InfoRespond.php index 6e452371..baea69e0 100644 --- a/system/libs/pot/OTS_InfoRespond.php +++ b/system/libs/pot/OTS_InfoRespond.php @@ -15,11 +15,11 @@ /** * Wrapper for 'info' respond's DOMDocument. - * + * *

    * Note: as this class extends DOMDocument class and contains exacly respond XML tree you can work on it as on normal DOM tree. *

    - * + * * @package POT * @version 0.1.0 * @property-read string $tspqVersion Root element version. @@ -48,252 +48,252 @@ class OTS_InfoRespond extends DOMDocument { /** * Returns version of root element. - * + * * @return string TSPQ version. * @throws DOMException On DOM operation error. */ - public function getTSPQVersion() - { - return $this->documentElement->getAttribute('version'); - } + public function getTSPQVersion() + { + return $this->documentElement->getAttribute('version'); + } /** * Returns server uptime. - * + * * @return int Uptime. * @throws DOMException On DOM operation error. */ - public function getUptime() - { - return (int) $this->documentElement->getElementsByTagName('serverinfo')->item(0)->getAttribute('uptime'); - } + public function getUptime() + { + return (int) $this->documentElement->getElementsByTagName('serverinfo')->item(0)->getAttribute('uptime'); + } /** * Returns server IP. - * + * * @return string IP. * @throws DOMException On DOM operation error. */ - public function getIP() - { - return $this->documentElement->getElementsByTagName('serverinfo')->item(0)->getAttribute('ip'); - } + public function getIP() + { + return $this->documentElement->getElementsByTagName('serverinfo')->item(0)->getAttribute('ip'); + } /** * Returns server name. - * + * * @return string Name. * @throws DOMException On DOM operation error. */ - public function getName() - { - return $this->documentElement->getElementsByTagName('serverinfo')->item(0)->getAttribute('servername'); - } + public function getName() + { + return $this->documentElement->getElementsByTagName('serverinfo')->item(0)->getAttribute('servername'); + } /** * Returns server port. - * + * * @return int Port. * @throws DOMException On DOM operation error. */ - public function getPort() - { - return (int) $this->documentElement->getElementsByTagName('serverinfo')->item(0)->getAttribute('port'); - } + public function getPort() + { + return (int) $this->documentElement->getElementsByTagName('serverinfo')->item(0)->getAttribute('port'); + } /** * Returns server location. - * + * * @return string Location. * @throws DOMException On DOM operation error. */ - public function getLocation() - { - return $this->documentElement->getElementsByTagName('serverinfo')->item(0)->getAttribute('location'); - } + public function getLocation() + { + return $this->documentElement->getElementsByTagName('serverinfo')->item(0)->getAttribute('location'); + } /** * Returns server website. - * + * * @return string Website URL. * @throws DOMException On DOM operation error. */ - public function getURL() - { - return $this->documentElement->getElementsByTagName('serverinfo')->item(0)->getAttribute('url'); - } + public function getURL() + { + return $this->documentElement->getElementsByTagName('serverinfo')->item(0)->getAttribute('url'); + } /** * Returns server attribute. - * + * * I have no idea what the hell is it representing :P. - * + * * @return string Attribute value. * @throws DOMException On DOM operation error. */ - public function getServer() - { - return $this->documentElement->getElementsByTagName('serverinfo')->item(0)->getAttribute('server'); - } + public function getServer() + { + return $this->documentElement->getElementsByTagName('serverinfo')->item(0)->getAttribute('server'); + } /** * Returns server version. - * + * * @return string Version. * @throws DOMException On DOM operation error. */ - public function getServerVersion() - { - return $this->documentElement->getElementsByTagName('serverinfo')->item(0)->getAttribute('version'); - } + public function getServerVersion() + { + return $this->documentElement->getElementsByTagName('serverinfo')->item(0)->getAttribute('version'); + } /** * Returns dedicated version of client. - * + * * @return string Version. * @throws DOMException On DOM operation error. */ - public function getClientVersion() - { - return $this->documentElement->getElementsByTagName('serverinfo')->item(0)->getAttribute('client'); - } + public function getClientVersion() + { + return $this->documentElement->getElementsByTagName('serverinfo')->item(0)->getAttribute('client'); + } /** * Returns owner name. - * + * * @return string Owner name. * @throws DOMException On DOM operation error. */ - public function getOwner() - { - return $this->documentElement->getElementsByTagName('owner')->item(0)->getAttribute('name'); - } + public function getOwner() + { + return $this->documentElement->getElementsByTagName('owner')->item(0)->getAttribute('name'); + } /** * Returns owner e-mail. - * + * * @return string Owner e-mail. * @throws DOMException On DOM operation error. */ - public function getEMail() - { - return $this->documentElement->getElementsByTagName('owner')->item(0)->getAttribute('email'); - } + public function getEMail() + { + return $this->documentElement->getElementsByTagName('owner')->item(0)->getAttribute('email'); + } /** * Returns current amount of players online. - * + * * @return int Count of players. * @throws DOMException On DOM operation error. */ - public function getOnlinePlayers() - { - return (int) $this->documentElement->getElementsByTagName('players')->item(0)->getAttribute('online'); - } + public function getOnlinePlayers() + { + return (int) $this->documentElement->getElementsByTagName('players')->item(0)->getAttribute('online'); + } /** * Returns maximum amount of players online. - * + * * @return int Maximum allowed count of players. * @throws DOMException On DOM operation error. */ - public function getMaxPlayers() - { - return (int) $this->documentElement->getElementsByTagName('players')->item(0)->getAttribute('max'); - } + public function getMaxPlayers() + { + return (int) $this->documentElement->getElementsByTagName('players')->item(0)->getAttribute('max'); + } /** * Returns record of online players. - * + * * @return int Players online record. * @throws DOMException On DOM operation error. */ - public function getPlayersPeak() - { - return (int) $this->documentElement->getElementsByTagName('players')->item(0)->getAttribute('peak'); - } + public function getPlayersPeak() + { + return (int) $this->documentElement->getElementsByTagName('players')->item(0)->getAttribute('peak'); + } /** * Returns number of all monsters on map. - * + * * @return int Count of monsters. * @throws DOMException On DOM operation error. */ - public function getMonstersCount() - { - return (int) $this->documentElement->getElementsByTagName('monsters')->item(0)->getAttribute('total'); - } + public function getMonstersCount() + { + return (int) $this->documentElement->getElementsByTagName('monsters')->item(0)->getAttribute('total'); + } /** * Returns map name. - * + * * @return string Map name. * @throws DOMException On DOM operation error. */ - public function getMapName() - { - return $this->documentElement->getElementsByTagName('map')->item(0)->getAttribute('name'); - } + public function getMapName() + { + return $this->documentElement->getElementsByTagName('map')->item(0)->getAttribute('name'); + } /** * Returns map author. - * + * * @return string Mapper name. * @throws DOMException On DOM operation error. */ - public function getMapAuthor() - { - return $this->documentElement->getElementsByTagName('map')->item(0)->getAttribute('author'); - } + public function getMapAuthor() + { + return $this->documentElement->getElementsByTagName('map')->item(0)->getAttribute('author'); + } /** * Returns map width. - * + * * @return int Map width. * @throws DOMException On DOM operation error. */ - public function getMapWidth() - { - return (int) $this->documentElement->getElementsByTagName('map')->item(0)->getAttribute('width'); - } + public function getMapWidth() + { + return (int) $this->documentElement->getElementsByTagName('map')->item(0)->getAttribute('width'); + } /** * Returns map height. - * + * * @return int Map height. * @throws DOMException On DOM operation error. */ - public function getMapHeight() - { - return (int) $this->documentElement->getElementsByTagName('map')->item(0)->getAttribute('height'); - } + public function getMapHeight() + { + return (int) $this->documentElement->getElementsByTagName('map')->item(0)->getAttribute('height'); + } /** * Returns server's Message Of The Day - * + * * @version 0.1.0 * @return string Server MOTD. * @throws DOMException On DOM operation error. */ - public function getMOTD() - { - // look for text node child - foreach( $this->documentElement->getElementsByTagName('motd')->item(0)->childNodes as $child) - { - if($child->nodeType == XML_TEXT_NODE) - { - // found - return $child->nodeValue; - } - } + public function getMOTD() + { + // look for text node child + foreach( $this->documentElement->getElementsByTagName('motd')->item(0)->childNodes as $child) + { + if($child->nodeType == XML_TEXT_NODE) + { + // found + return $child->nodeValue; + } + } - // strange... - return ''; - } + // strange... + return ''; + } /** * Magic PHP5 method. - * + * * @version 0.1.0 * @since 0.1.0 * @param string $name Property name. @@ -301,89 +301,89 @@ class OTS_InfoRespond extends DOMDocument * @throws OutOfBoundsException For non-supported properties. * @throws DOMException On DOM operation error. */ - public function __get($name) - { - switch($name) - { - case 'tspqVersion': - return $this->getTSPQVersion(); + public function __get($name) + { + switch($name) + { + case 'tspqVersion': + return $this->getTSPQVersion(); - case 'uptime': - return $this->getUptime(); + case 'uptime': + return $this->getUptime(); - case 'ip': - return $this->getIP(); + case 'ip': + return $this->getIP(); - case 'name': - return $this->getName(); + case 'name': + return $this->getName(); - case 'port': - return $this->getPort(); + case 'port': + return $this->getPort(); - case 'location': - return $this->getLocation(); + case 'location': + return $this->getLocation(); - case 'url': - return $this->getURL(); + case 'url': + return $this->getURL(); - case 'server': - return $this->getServer(); + case 'server': + return $this->getServer(); - case 'serverVersion': - return $this->getServerVersion(); + case 'serverVersion': + return $this->getServerVersion(); - case 'clientVersion': - return $this->getClientVersion(); + case 'clientVersion': + return $this->getClientVersion(); - case 'owner': - return $this->getOwner(); + case 'owner': + return $this->getOwner(); - case 'eMail': - return $this->getEMail(); + case 'eMail': + return $this->getEMail(); - case 'onlinePlayers': - return $this->getOnlinePlayers(); + case 'onlinePlayers': + return $this->getOnlinePlayers(); - case 'maxPlayers': - return $this->getMaxPlayers(); + case 'maxPlayers': + return $this->getMaxPlayers(); - case 'playersPeak': - return $this->getPlayersPeak(); + case 'playersPeak': + return $this->getPlayersPeak(); - case 'monstersCount': - return $this->getMonstersCount(); + case 'monstersCount': + return $this->getMonstersCount(); - case 'mapName': - return $this->getMapName(); + case 'mapName': + return $this->getMapName(); - case 'mapAuthor': - return $this->getMapAuthor(); + case 'mapAuthor': + return $this->getMapAuthor(); - case 'mapWidth': - return $this->getMapWidth(); + case 'mapWidth': + return $this->getMapWidth(); - case 'mapHeight': - return $this->getMapHeight(); + case 'mapHeight': + return $this->getMapHeight(); - case 'motd': - return $this->getMOTD(); + case 'motd': + return $this->getMOTD(); - default: - throw new OutOfBoundsException(); - } - } + default: + throw new OutOfBoundsException(); + } + } /** * Returns string representation of XML. - * + * * @version 0.1.0 * @since 0.1.0 * @return string String representation of object. */ - public function __toString() - { - return $this->saveXML(); - } + public function __toString() + { + return $this->saveXML(); + } } /**#@-*/ diff --git a/system/libs/pot/OTS_ServerStatus.php b/system/libs/pot/OTS_ServerStatus.php index e13a0f5b..4ba0035c 100644 --- a/system/libs/pot/OTS_ServerStatus.php +++ b/system/libs/pot/OTS_ServerStatus.php @@ -40,175 +40,175 @@ class OTS_ServerStatus /** * Basic server info. */ - const REQUEST_BASIC_SERVER_INFO = 1; + const REQUEST_BASIC_SERVER_INFO = 1; /** * Server owner info. */ - const REQUEST_OWNER_SERVER_INFO = 2; + const REQUEST_OWNER_SERVER_INFO = 2; /** * Server extra info. */ - const REQUEST_MISC_SERVER_INFO = 4; + const REQUEST_MISC_SERVER_INFO = 4; /** * Players stats info. */ - const REQUEST_PLAYERS_INFO = 8; + const REQUEST_PLAYERS_INFO = 8; /** * Map info. */ - const REQUEST_MAP_INFO = 16; + const REQUEST_MAP_INFO = 16; /** * Extended players info. */ - const REQUEST_EXT_PLAYERS_INFO = 32; + const REQUEST_EXT_PLAYERS_INFO = 32; /** * Player status info. */ - const REQUEST_PLAYER_STATUS_INFO = 64; + const REQUEST_PLAYER_STATUS_INFO = 64; /** * Server software info. */ - const REQUEST_SERVER_SOFTWARE_INFO = 128; + const REQUEST_SERVER_SOFTWARE_INFO = 128; /** * Basic server respond. */ - const RESPOND_BASIC_SERVER_INFO = 0x10; + const RESPOND_BASIC_SERVER_INFO = 0x10; /** * Server owner respond. */ - const RESPOND_OWNER_SERVER_INFO = 0x11; + const RESPOND_OWNER_SERVER_INFO = 0x11; /** * Server extra respond. */ - const RESPOND_MISC_SERVER_INFO = 0x12; + const RESPOND_MISC_SERVER_INFO = 0x12; /** * Players stats respond. */ - const RESPOND_PLAYERS_INFO = 0x20; + const RESPOND_PLAYERS_INFO = 0x20; /** * Map respond. */ - const RESPOND_MAP_INFO = 0x30; + const RESPOND_MAP_INFO = 0x30; /** * Extended players info. */ - const RESPOND_EXT_PLAYERS_INFO = 0x21; + const RESPOND_EXT_PLAYERS_INFO = 0x21; /** * Player status info. */ - const RESPOND_PLAYER_STATUS_INFO = 0x22; + const RESPOND_PLAYER_STATUS_INFO = 0x22; /** * Server software info. */ - const RESPOND_SERVER_SOFTWARE_INFO = 0x23; + const RESPOND_SERVER_SOFTWARE_INFO = 0x23; /** * Server name. * * @var string */ - private $name; + private $name; /** * Server IP. * * @var string */ - private $ip; + private $ip; /** * Server port. * * @var string */ - private $port; + private $port; /** * Owner name. * * @var string */ - private $owner; + private $owner; /** * Owner's e-mail. * * @var string */ - private $eMail; + private $eMail; /** * Message of the day. * * @var string */ - private $motd; + private $motd; /** * Server location. * * @var string */ - private $location; + private $location; /** * Website URL. * * @var string */ - private $url; + private $url; /** * Uptime. * * @var int */ - private $uptime; + private $uptime; /** * Status version. * * @var string */ - private $version; + private $version; /** * Players online. * * @var int */ - private $online; + private $online; /** * Maximum players. * * @var int */ - private $max; + private $max; /** * Players peak. * * @var int */ - private $peak; + private $peak; /** * Map name. * * @var string */ - private $map; + private $map; /** * Map author. * * @var string */ - private $author; + private $author; /** * Map width. * * @var int */ - private $width; + private $width; /** * Map height. * * @var int */ - private $height; + private $height; /** * Players online list. * * @var array */ - private $players = array(); + private $players = array(); /** * Server software. @@ -224,277 +224,277 @@ class OTS_ServerStatus * * @param OTS_Buffer $info Information packet. */ - public function __construct(OTS_Buffer $info) - { - // skips packet length - $info->getShort(); + public function __construct(OTS_Buffer $info) + { + // skips packet length + $info->getShort(); - while( $info->isValid() ) - { - switch( $info->getChar() ) - { - case self::RESPOND_BASIC_SERVER_INFO: - $this->name = $info->getString(); - $this->ip = $info->getString(); - $this->port = (int) $info->getString(); - break; + while( $info->isValid() ) + { + switch( $info->getChar() ) + { + case self::RESPOND_BASIC_SERVER_INFO: + $this->name = $info->getString(); + $this->ip = $info->getString(); + $this->port = (int) $info->getString(); + break; - case self::RESPOND_OWNER_SERVER_INFO: - $this->owner = $info->getString(); - $this->eMail = $info->getString(); - break; + case self::RESPOND_OWNER_SERVER_INFO: + $this->owner = $info->getString(); + $this->eMail = $info->getString(); + break; - case self::RESPOND_MISC_SERVER_INFO: - $this->motd = $info->getString(); - $this->location = $info->getString(); - $this->url = $info->getString(); + case self::RESPOND_MISC_SERVER_INFO: + $this->motd = $info->getString(); + $this->location = $info->getString(); + $this->url = $info->getString(); - $uptime = $info->getLong() << 32; + $uptime = $info->getLong() << 32; - $this->uptime += $info->getLong() + $uptime; - $this->version = $info->getString(); - break; + $this->uptime += $info->getLong() + $uptime; + $this->version = $info->getString(); + break; - case self::RESPOND_PLAYERS_INFO: - $this->online = $info->getLong(); - $this->max = $info->getLong(); - $this->peak = $info->getLong(); - break; + case self::RESPOND_PLAYERS_INFO: + $this->online = $info->getLong(); + $this->max = $info->getLong(); + $this->peak = $info->getLong(); + break; - case self::RESPOND_MAP_INFO: - $this->map = $info->getString(); - $this->author = $info->getString(); - $this->width = $info->getShort(); - $this->height = $info->getShort(); - break; + case self::RESPOND_MAP_INFO: + $this->map = $info->getString(); + $this->author = $info->getString(); + $this->width = $info->getShort(); + $this->height = $info->getShort(); + break; - case self::RESPOND_EXT_PLAYERS_INFO: - $count = $info->getLong(); + case self::RESPOND_EXT_PLAYERS_INFO: + $count = $info->getLong(); - for($i = 0; $i < $count; $i++) - { - $name = $info->getString(); - $this->players[$name] = $info->getLong(); - } - break; + for($i = 0; $i < $count; $i++) + { + $name = $info->getString(); + $this->players[$name] = $info->getLong(); + } + break; case self::RESPOND_SERVER_SOFTWARE_INFO: $this->softwareName = $info->getString(); $this->softwareVersion = $info->getString(); $this->softwareProtocol = $info->getString(); break; - } - } - } + } + } + } /** * Returns server uptime. * * @return int Uptime. */ - public function getUptime() - { - return $this->uptime; - } + public function getUptime() + { + return $this->uptime; + } /** * Returns server IP. * * @return string IP. */ - public function getIP() - { - return $this->ip; - } + public function getIP() + { + return $this->ip; + } /** * Returns server name. * * @return string Name. */ - public function getName() - { - return $this->name; - } + public function getName() + { + return $this->name; + } /** * Returns server port. * * @return int Port. */ - public function getPort() - { - return $this->port; - } + public function getPort() + { + return $this->port; + } /** * Returns server location. * * @return string Location. */ - public function getLocation() - { - return $this->location; - } + public function getLocation() + { + return $this->location; + } /** * Returns server website. * * @return string Website URL. */ - public function getURL() - { - return $this->url; - } + public function getURL() + { + return $this->url; + } /** * Returns server version. * * @return string Version. */ - public function getServerVersion() - { - return $this->version; - } + public function getServerVersion() + { + return $this->version; + } /** * Returns owner name. * * @return string Owner name. */ - public function getOwner() - { - return $this->owner; - } + public function getOwner() + { + return $this->owner; + } /** * Returns owner e-mail. * * @return string Owner e-mail. */ - public function getEMail() - { - return $this->eMail; - } + public function getEMail() + { + return $this->eMail; + } /** * Returns current amount of players online. * * @return int Count of players. */ - public function getOnlinePlayers() - { - return $this->online; - } + public function getOnlinePlayers() + { + return $this->online; + } /** * Returns maximum amount of players online. * * @return int Maximum allowed count of players. */ - public function getMaxPlayers() - { - return $this->max; - } + public function getMaxPlayers() + { + return $this->max; + } /** * Returns record of online players. * * @return int Players online record. */ - public function getPlayersPeak() - { - return $this->peak; - } + public function getPlayersPeak() + { + return $this->peak; + } /** * Returns map name. * * @return string Map name. */ - public function getMapName() - { - return $this->map; - } + public function getMapName() + { + return $this->map; + } /** * Returns map author. * * @return string Mapper name. */ - public function getMapAuthor() - { - return $this->author; - } + public function getMapAuthor() + { + return $this->author; + } /** * Returns map width. * * @return int Map width. */ - public function getMapWidth() - { - return $this->width; - } + public function getMapWidth() + { + return $this->width; + } /** * Returns map height. * * @return int Map height. */ - public function getMapHeight() - { - return $this->height; - } + public function getMapHeight() + { + return $this->height; + } /** * Returns server's Message Of The Day * * @return string Server MOTD. */ - public function getMOTD() - { - return $this->motd; - } + public function getMOTD() + { + return $this->motd; + } /** * Returns list of players currently online. * * @return array List of players in format 'name' => level. */ - public function getPlayers() - { - } + public function getPlayers() + { + } /** * Returns software name. * * @return string Software name. */ - public function getSoftwareName() - { - return $this->softwareName; - } + public function getSoftwareName() + { + return $this->softwareName; + } /** * Returns software version. * * @return string Software version. */ - public function getSoftwareVersion() - { - return $this->softwareVersion; - } + public function getSoftwareVersion() + { + return $this->softwareVersion; + } /** * Returns software protocol. * * @return string Software protocol. */ - public function getSoftwareProtocol() - { - return $this->softwareProtocol; - } + public function getSoftwareProtocol() + { + return $this->softwareProtocol; + } /** * Magic PHP5 method. @@ -503,68 +503,68 @@ class OTS_ServerStatus * @return mixed Property value. * @throws OutOfBoundsException For non-supported properties. */ - public function __get($name) - { - switch($name) - { - case 'uptime': - return $this->getUptime(); + public function __get($name) + { + switch($name) + { + case 'uptime': + return $this->getUptime(); - case 'ip': - return $this->getIP(); + case 'ip': + return $this->getIP(); - case 'name': - return $this->getName(); + case 'name': + return $this->getName(); - case 'port': - return $this->getPort(); + case 'port': + return $this->getPort(); - case 'location': - return $this->getLocation(); + case 'location': + return $this->getLocation(); - case 'url': - return $this->getURL(); + case 'url': + return $this->getURL(); - case 'serverVersion': - return $this->getServerVersion(); + case 'serverVersion': + return $this->getServerVersion(); - case 'owner': - return $this->getOwner(); + case 'owner': + return $this->getOwner(); - case 'eMail': - return $this->getEMail(); + case 'eMail': + return $this->getEMail(); - case 'onlinePlayers': - return $this->getOnlinePlayers(); + case 'onlinePlayers': + return $this->getOnlinePlayers(); - case 'maxPlayers': - return $this->getMaxPlayers(); + case 'maxPlayers': + return $this->getMaxPlayers(); - case 'playersPeak': - return $this->getPlayersPeak(); + case 'playersPeak': + return $this->getPlayersPeak(); - case 'mapName': - return $this->getMapName(); + case 'mapName': + return $this->getMapName(); - case 'mapAuthor': - return $this->getMapAuthor(); + case 'mapAuthor': + return $this->getMapAuthor(); - case 'mapWidth': - return $this->getMapWidth(); + case 'mapWidth': + return $this->getMapWidth(); - case 'mapHeight': - return $this->getMapHeight(); + case 'mapHeight': + return $this->getMapHeight(); - case 'motd': - return $this->getMOTD(); + case 'motd': + return $this->getMOTD(); - case 'players': - return $this->getPlayers(); + case 'players': + return $this->getPlayers(); - default: - throw new OutOfBoundsException(); - } - } + default: + throw new OutOfBoundsException(); + } + } } /**#@-*/ From 7d435ff6433ef1fb2295ee79ed043ee10dc725e9 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 24 May 2025 11:54:00 +0200 Subject: [PATCH 036/222] Add getNPCsCount --- system/libs/pot/OTS_InfoRespond.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/system/libs/pot/OTS_InfoRespond.php b/system/libs/pot/OTS_InfoRespond.php index baea69e0..3b345497 100644 --- a/system/libs/pot/OTS_InfoRespond.php +++ b/system/libs/pot/OTS_InfoRespond.php @@ -219,11 +219,16 @@ class OTS_InfoRespond extends DOMDocument * @return int Count of monsters. * @throws DOMException On DOM operation error. */ - public function getMonstersCount() + public function getMonstersCount(): int { return (int) $this->documentElement->getElementsByTagName('monsters')->item(0)->getAttribute('total'); } + public function getNPCsCount(): int + { + return (int) $this->documentElement->getElementsByTagName('npcs')->item(0)->getAttribute('total'); + } + /** * Returns map name. * From 28886551e86fe562172c4c7f2afb89a2e7672c2e Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 28 May 2025 13:33:36 +0200 Subject: [PATCH 037/222] feat: Add new account coins setting --- system/pages/account/create.php | 10 ++++++++-- system/settings.php | 9 +++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/system/pages/account/create.php b/system/pages/account/create.php index 0befa362..947ad0ad 100644 --- a/system/pages/account/create.php +++ b/system/pages/account/create.php @@ -221,8 +221,14 @@ if($save) } } - if(setting('core.account_premium_points') && setting('core.account_premium_points') > 0) { - $new_account->setCustomField('premium_points', setting('core.account_premium_points')); + $accountDefaultPremiumPoints = setting('core.account_premium_points'); + if($accountDefaultPremiumPoints > 0) { + $new_account->setCustomField('premium_points', $accountDefaultPremiumPoints); + } + + $accountDefaultCoins = setting('core.account_coins'); + if($db->hasColumn('accounts', 'coins') && $accountDefaultCoins > 0) { + $new_account->setCustomField('coins', $accountDefaultCoins); } $tmp_account = $email; diff --git a/system/settings.php b/system/settings.php index d0a705a0..c212587d 100644 --- a/system/settings.php +++ b/system/settings.php @@ -19,6 +19,8 @@ $templates = Cache::remember('templates', 5 * 60, function () { }); $defaultTemplate = in_array('kathrine', $templates) ? 'kathrine' : $templates[0]; +global $db; + return [ 'name' => 'MyAAC', 'settings' => [ @@ -674,6 +676,13 @@ Sent by MyAAC,
    'desc' => 'Default premium points on new account', 'default' => 0, ], + 'account_coins' => [ + 'name' => 'Default Account Coins', + 'type' => 'number', + 'desc' => 'Default coins on new account', + 'hidden' => !$db->hasColumn('accounts', 'coins'), + 'default' => 0, + ], 'account_mail_change' => [ 'name' => 'Account Mail Change Days', 'type' => 'number', From 4b7b121550a60d0b7395b75f5e1190e27145bcf1 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 28 May 2025 14:08:50 +0200 Subject: [PATCH 038/222] Try fix workflow --- system/src/Validator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Validator.php b/system/src/Validator.php index ad9e3e50..6c189b29 100644 --- a/system/src/Validator.php +++ b/system/src/Validator.php @@ -121,7 +121,7 @@ class Validator return false; } - if(setting('core.account_mail_block_plus_sign')) { + if(!defined('MYAAC_INSTALL') && setting('core.account_mail_block_plus_sign')) { $explode = explode('@', $email); if(isset($explode[0]) && (strpos($explode[0],'+') !== false)) { self::$lastError = 'Please do not use plus (+) sign in your e-mail.'; From 52109f5cca448349040de02f796648d6066b4347 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 28 May 2025 14:13:04 +0200 Subject: [PATCH 039/222] Another solution --- system/settings.php | 2 +- system/src/Validator.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/system/settings.php b/system/settings.php index c212587d..a7a5ee0a 100644 --- a/system/settings.php +++ b/system/settings.php @@ -680,7 +680,7 @@ Sent by MyAAC,
    'name' => 'Default Account Coins', 'type' => 'number', 'desc' => 'Default coins on new account', - 'hidden' => !$db->hasColumn('accounts', 'coins'), + 'hidden' => ($db && !$db->hasColumn('accounts', 'coins')), 'default' => 0, ], 'account_mail_change' => [ diff --git a/system/src/Validator.php b/system/src/Validator.php index 6c189b29..ad9e3e50 100644 --- a/system/src/Validator.php +++ b/system/src/Validator.php @@ -121,7 +121,7 @@ class Validator return false; } - if(!defined('MYAAC_INSTALL') && setting('core.account_mail_block_plus_sign')) { + if(setting('core.account_mail_block_plus_sign')) { $explode = explode('@', $email); if(isset($explode[0]) && (strpos($explode[0],'+') !== false)) { self::$lastError = 'Please do not use plus (+) sign in your e-mail.'; From d8a6090be382c35c19117cfef964b594ed02b8d4 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 29 May 2025 09:27:29 +0200 Subject: [PATCH 040/222] Add new setting/configurable: site_url, prevents domain spoofing --- common.php | 49 ++++++++++------------- install/steps/4-config.php | 8 ++++ system/base.php | 19 +++++++++ system/locale/de/install.php | 2 + system/locale/en/install.php | 2 + system/locale/pl/install.php | 2 + system/settings.php | 12 ++++++ system/templates/install.config.html.twig | 2 +- 8 files changed, 67 insertions(+), 29 deletions(-) create mode 100644 system/base.php diff --git a/common.php b/common.php index 7fc7f95f..14d4a5db 100644 --- a/common.php +++ b/common.php @@ -122,38 +122,31 @@ if (!IS_CLI) { session_start(); } -// basedir -$basedir = ''; -$tmp = explode('/', $_SERVER['SCRIPT_NAME']); -$size = count($tmp) - 1; -for($i = 1; $i < $size; $i++) - $basedir .= '/' . $tmp[$i]; - -$basedir = str_replace(['/' . ADMIN_PANEL_FOLDER, '/install', '/tools'], '', $basedir); -define('BASE_DIR', $basedir); - -if(!IS_CLI) { - if (isset($_SERVER['HTTP_HOST'][0])) { - $baseHost = $_SERVER['HTTP_HOST']; - } else { - if (isset($_SERVER['SERVER_NAME'][0])) { - $baseHost = $_SERVER['SERVER_NAME']; - } else { - $baseHost = $_SERVER['SERVER_ADDR']; - } - } - - define('SERVER_URL', 'http' . (isHttps() ? 's' : '') . '://' . $baseHost); - define('BASE_URL', SERVER_URL . BASE_DIR . '/'); - define('ADMIN_URL', SERVER_URL . BASE_DIR . '/' . ADMIN_PANEL_FOLDER . '/'); - - //define('CURRENT_URL', BASE_URL . $_SERVER['REQUEST_URI']); -} - if (file_exists(BASE . 'config.local.php')) { require BASE . 'config.local.php'; } +if(!IS_CLI) { + require SYSTEM . 'base.php'; + define('BASE_DIR', $baseDir); + + if (isset($config['site_url'])) { + $hasSlashAtEnd = ($config['site_url'][strlen($config['site_url']) - 1] == '/'); + + define('SERVER_URL', $config['site_url']); + define('BASE_URL', SERVER_URL . ($hasSlashAtEnd ? '' : '/')); + define('ADMIN_URL', SERVER_URL . ($hasSlashAtEnd ? '' : '/') . ADMIN_PANEL_FOLDER . '/'); + } + else { + define('SERVER_URL', 'http' . (isHttps() ? 's' : '') . '://' . $baseHost); + define('BASE_URL', SERVER_URL . BASE_DIR . '/'); + define('ADMIN_URL', SERVER_URL . BASE_DIR . '/' . ADMIN_PANEL_FOLDER . '/'); + + //define('CURRENT_URL', BASE_URL . $_SERVER['REQUEST_URI']); + } + +} + /** @var array $config */ ini_set('log_errors', 1); if(@$config['env'] === 'dev' || defined('MYAAC_INSTALL')) { diff --git a/install/steps/4-config.php b/install/steps/4-config.php index 325b97f1..342edd06 100644 --- a/install/steps/4-config.php +++ b/install/steps/4-config.php @@ -10,6 +10,14 @@ foreach($config['clients'] as $client) { $clients[$client] = $client_version; } +if (empty($_SESSION['var_site_url'])) { + //require SYSTEM . 'base.php'; + $serverUrl = 'http' . (isHttps() ? 's' : '') . '://' . $baseHost; + $siteURL = $serverUrl . $baseDir; + + $_SESSION['var_site_url'] = $siteURL; +} + $twig->display('install.config.html.twig', array( 'clients' => $clients, 'timezones' => DateTimeZone::listIdentifiers(), diff --git a/system/base.php b/system/base.php new file mode 100644 index 00000000..a0ba4e6b --- /dev/null +++ b/system/base.php @@ -0,0 +1,19 @@ + 'MyAAC', 'settings' => [ @@ -32,6 +37,13 @@ return [ 'type' => 'section', 'title' => 'General' ], + 'site_url' => [ + 'name' => 'Website URL', + 'type' => 'text', + 'desc' => 'Website address of this MyAAC instance', + 'default' => $siteURL, + 'is_config' => true, + ], 'env' => [ 'name' => 'App Environment', 'type' => 'options', diff --git a/system/templates/install.config.html.twig b/system/templates/install.config.html.twig index ab4fc361..8c0aa50a 100644 --- a/system/templates/install.config.html.twig +++ b/system/templates/install.config.html.twig @@ -9,7 +9,7 @@ - {% for value in ['server_path'] %} + {% for value in ['site_url', 'server_path'] %}
    From fb91281140cc81cb0837a46b896959473cff9f51 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 29 May 2025 09:35:20 +0200 Subject: [PATCH 041/222] Fix phpstan workflow --- common.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common.php b/common.php index 14d4a5db..cec3a3c2 100644 --- a/common.php +++ b/common.php @@ -126,10 +126,10 @@ if (file_exists(BASE . 'config.local.php')) { require BASE . 'config.local.php'; } -if(!IS_CLI) { - require SYSTEM . 'base.php'; - define('BASE_DIR', $baseDir); +require SYSTEM . 'base.php'; +define('BASE_DIR', $baseDir); +if(!IS_CLI) { if (isset($config['site_url'])) { $hasSlashAtEnd = ($config['site_url'][strlen($config['site_url']) - 1] == '/'); @@ -144,7 +144,6 @@ if(!IS_CLI) { //define('CURRENT_URL', BASE_URL . $_SERVER['REQUEST_URI']); } - } /** @var array $config */ From 6e0f5913831f8dba69fd2d1505be3e2a303c6324 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 29 May 2025 12:22:16 +0200 Subject: [PATCH 042/222] Do not allow access to tools/ folder after install --- install/steps/7-finish.php | 9 --------- install/tools/5-database.php | 5 +++++ install/tools/7-finish.php | 15 +++++++++++++-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/install/steps/7-finish.php b/install/steps/7-finish.php index 0ae302ea..afe63603 100644 --- a/install/steps/7-finish.php +++ b/install/steps/7-finish.php @@ -195,13 +195,4 @@ if(!isset($_SESSION['installed'])) { $_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); diff --git a/install/tools/5-database.php b/install/tools/5-database.php index 395492ee..b9ff587f 100644 --- a/install/tools/5-database.php +++ b/install/tools/5-database.php @@ -7,6 +7,11 @@ require SYSTEM . 'functions.php'; require BASE . 'install/includes/functions.php'; require BASE . 'install/includes/locale.php'; +if(isset($config['installed']) && $config['installed'] && !isset($_SESSION['saved'])) { + warning($locale['already_installed']); + return; +} + $error = false; require BASE . 'install/includes/config.php'; diff --git a/install/tools/7-finish.php b/install/tools/7-finish.php index c1ab5c1d..9c64382b 100644 --- a/install/tools/7-finish.php +++ b/install/tools/7-finish.php @@ -17,11 +17,11 @@ ini_set('max_execution_time', 300); ob_implicit_flush(); header('X-Accel-Buffering: no'); -/* + if(isset($config['installed']) && $config['installed'] && !isset($_SESSION['saved'])) { warning($locale['already_installed']); return; -}*/ +} require SYSTEM . 'init.php'; @@ -94,6 +94,17 @@ $hooks->trigger(HOOK_INSTALL_FINISH); $db->setClearCacheAfter(true); +// cleanup +foreach($_SESSION as $key => $value) { + if(str_contains($key, 'var_')) { + unset($_SESSION[$key]); + } +} +unset($_SESSION['saved']); +if(file_exists(CACHE . 'install.txt')) { + unlink(CACHE . 'install.txt'); +} + $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']); From 756d94bb3e746f0ea81bcd8b3bc825222508c771 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 29 May 2025 16:08:23 +0200 Subject: [PATCH 043/222] Fix warning from CLI --- system/base.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/system/base.php b/system/base.php index a0ba4e6b..9cab2925 100644 --- a/system/base.php +++ b/system/base.php @@ -8,12 +8,14 @@ for($i = 1; $i < $size; $i++) $baseDir = str_replace(['/' . ADMIN_PANEL_FOLDER, '/install', '/tools'], '', $baseDir); -if (isset($_SERVER['HTTP_HOST'][0])) { - $baseHost = $_SERVER['HTTP_HOST']; -} else { - if (isset($_SERVER['SERVER_NAME'][0])) { - $baseHost = $_SERVER['SERVER_NAME']; +if(!IS_CLI) { + if (isset($_SERVER['HTTP_HOST'][0])) { + $baseHost = $_SERVER['HTTP_HOST']; } else { - $baseHost = $_SERVER['SERVER_ADDR']; + if (isset($_SERVER['SERVER_NAME'][0])) { + $baseHost = $_SERVER['SERVER_NAME']; + } else { + $baseHost = $_SERVER['SERVER_ADDR']; + } } } From 770ffcfc528f35cb873d72ab71026d9a15b71297 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 29 May 2025 16:10:46 +0200 Subject: [PATCH 044/222] Fix warnings in CLI (part 2) --- system/settings.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/system/settings.php b/system/settings.php index 7a7a48a6..4cfe5c9f 100644 --- a/system/settings.php +++ b/system/settings.php @@ -21,10 +21,12 @@ $defaultTemplate = in_array('kathrine', $templates) ? 'kathrine' : $templates[0] global $db; -require SYSTEM . 'base.php'; +if (!IS_CLI) { + require SYSTEM . 'base.php'; -$serverUrl = 'http' . (isHttps() ? 's' : '') . '://' . $baseHost; -$siteURL = $serverUrl . $baseDir; + $serverUrl = 'http' . (isHttps() ? 's' : '') . '://' . $baseHost; + $siteURL = $serverUrl . $baseDir; +} return [ 'name' => 'MyAAC', @@ -41,7 +43,7 @@ return [ 'name' => 'Website URL', 'type' => 'text', 'desc' => 'Website address of this MyAAC instance', - 'default' => $siteURL, + 'default' => IS_CLI ? '' : $siteURL, 'is_config' => true, ], 'env' => [ From c961a1ebf837f2ab1734a825ff2c57b4937610c9 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 06:21:44 +0200 Subject: [PATCH 045/222] Two new hooks for pages loaded from database (custom pages) HOOK_BEFORE_PAGE_CUSTOM, HOOK_AFTER_PAGE_CUSTOM --- system/router.php | 4 +++- system/src/global.php | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/system/router.php b/system/router.php index b87a843d..40b45861 100644 --- a/system/router.php +++ b/system/router.php @@ -252,7 +252,7 @@ else { $success = false; $tmp_content = getCustomPage($pageName, $success); - if ($success) { + if ($success && $hooks->trigger(HOOK_BEFORE_PAGE_CUSTOM)) { $content .= $tmp_content; if (hasFlag(FLAG_CONTENT_PAGES) || superAdmin()) { $pageInfo = getCustomPageInfo($pageName); @@ -260,6 +260,8 @@ else { ) . $content; } + $hooks->trigger(HOOK_AFTER_PAGE_CUSTOM); + $page = $pageName; $file = false; } diff --git a/system/src/global.php b/system/src/global.php index 62366c1c..f374568d 100644 --- a/system/src/global.php +++ b/system/src/global.php @@ -8,7 +8,9 @@ $i = 0; define('HOOK_INIT', ++$i); define('HOOK_STARTUP', ++$i); define('HOOK_BEFORE_PAGE', ++$i); +define('HOOK_BEFORE_PAGE_CUSTOM', ++$i); define('HOOK_AFTER_PAGE', ++$i); +define('HOOK_AFTER_PAGE_CUSTOM', ++$i); define('HOOK_FINISH', ++$i); define('HOOK_TIBIACOM_ARTICLE', ++$i); define('HOOK_TIBIACOM_BORDER_3', ++$i); From 8fdea943768b20193eede99d60313ee84511a0be Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 08:39:48 +0200 Subject: [PATCH 046/222] Add globals into $hooks->executeFIlter --- system/src/Hook.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/src/Hook.php b/system/src/Hook.php index 161b2ffc..6acdf6ef 100644 --- a/system/src/Hook.php +++ b/system/src/Hook.php @@ -38,6 +38,8 @@ class Hook } public function executeFilter(&$args) { + global $db, $config, $template_path, $ots, $content, $twig; + return include BASE . $this->_file; } From 207d6bc69120aba1af2b51808f17e0059b571fed Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 08:52:33 +0200 Subject: [PATCH 047/222] feat: AutoLoad plugins init.php, by default disabled --- system/init.php | 6 ++++++ system/src/Plugins.php | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/system/init.php b/system/init.php index 44634265..821ac440 100644 --- a/system/init.php +++ b/system/init.php @@ -12,6 +12,7 @@ use DebugBar\StandardDebugBar; use MyAAC\Cache\Cache; use MyAAC\CsrfToken; use MyAAC\Hooks; +use MyAAC\Plugins; use MyAAC\Models\Town; use MyAAC\Settings; @@ -46,6 +47,11 @@ if(isset($config['gzip_output']) && $config['gzip_output'] && isset($_SERVER['HT global $cache; $cache = Cache::getInstance(); +// load plugins init.php +foreach (Plugins::getInits() as $init) { + require $init; +} + // event system global $hooks; $hooks = new Hooks(); diff --git a/system/src/Plugins.php b/system/src/Plugins.php index 438fe32e..85f0a2ba 100644 --- a/system/src/Plugins.php +++ b/system/src/Plugins.php @@ -11,6 +11,25 @@ class Plugins { private static $error = null; private static $plugin_json = []; + public static function getInits() + { + return Cache::remember('plugins_inits', 10 * 60, function () { + $inits = []; + foreach(self::getAllPluginsJson() as $plugin) { + if (!self::getAutoLoadOption($plugin, 'init', false)) { + continue; + } + + $pluginInits = glob(PLUGINS . $plugin['filename'] . '/init.php'); + foreach ($pluginInits as $path) { + $inits[] = $path; + } + } + + return $inits; + }); + } + public static function getAdminPages() { return Cache::remember('plugins_admin_pages', 10 * 60, function () { From c61747dc7589f7aa546bb6f8d3cd99a91fe1e535 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 10:17:08 +0200 Subject: [PATCH 048/222] Update coins.html.twig --- admin/pages/modules/templates/coins.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/pages/modules/templates/coins.html.twig b/admin/pages/modules/templates/coins.html.twig index 722064f8..ae586ee8 100644 --- a/admin/pages/modules/templates/coins.html.twig +++ b/admin/pages/modules/templates/coins.html.twig @@ -19,7 +19,7 @@ {% set i = i + 1 %}
    {{ i }}{{ result.name }}{{ result.name ?? result.id }} {{ result.coins }}
    - - - + - - + + +
    +
    + + {{ csrf() }} {{ include('buttons.logout.html.twig') }} -
    - - - + - - + + +
    +
    + + {{ csrf() }} {{ include('buttons.register_account.html.twig') }} -
    @@ -94,13 +96,14 @@
    - - - + - - + + +
    +
    + + {{ csrf() }} {{ include('buttons.edit.html.twig') }} -
    @@ -177,26 +180,29 @@
    - - - + - - + + +
    +
    + + {{ csrf() }} {{ include('buttons.change_password.html.twig') }} -
    - - - + - - + + +
    +
    + + {{ csrf() }} + {{ include('buttons.change_email.html.twig') }} -
    - - - + - - + + +
    +
    + + {{ csrf() }} {{ include('buttons.register_account.html.twig') }} -
    - - - + - - + + +
    +
    + + {{ csrf() }} {{ include('buttons.edit.html.twig') }} -
    - @@ -410,8 +419,9 @@ - - -
    +
    + {{ csrf() }} {{ include('buttons.create_character.html.twig') }}
    - @@ -423,8 +433,9 @@ From 4def6a6cae47d28451662a519334f43df509b956 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 10:39:45 +0200 Subject: [PATCH 077/222] Style --- system/templates/guilds.view.html.twig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/templates/guilds.view.html.twig b/system/templates/guilds.view.html.twig index 8f29dbf6..b8c0d0be 100644 --- a/system/templates/guilds.view.html.twig +++ b/system/templates/guilds.view.html.twig @@ -62,6 +62,7 @@ {{ hook('HOOK_GUILDS_AFTER_GUILD_INFORMATION') }} {% set title = 'Guild Members' %} + {% set background = config('lightborder') %} {% set content %}
    +
    + {{ csrf() }} {{ include('buttons.change_name.html.twig') }}
    - @@ -436,8 +447,9 @@
    +
    + {{ csrf() }} {{ include('buttons.change_sex.html.twig') }}
    - From fffb427eaed880b49a305a6351853c47eabe021a Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 9 Jun 2025 21:18:45 +0200 Subject: [PATCH 065/222] Update account.generate_recovery_key.html.twig --- .../account.generate_recovery_key.html.twig | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/system/templates/account.generate_recovery_key.html.twig b/system/templates/account.generate_recovery_key.html.twig index c34132f0..526d4659 100644 --- a/system/templates/account.generate_recovery_key.html.twig +++ b/system/templates/account.generate_recovery_key.html.twig @@ -32,14 +32,14 @@ To generate recovery key for your account please enter your password.

    From 524e982a0e343a3d36966ca8c01db4ef0e924175 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 11 Jun 2025 05:51:39 +0200 Subject: [PATCH 066/222] Release v1.6.1 --- CHANGELOG-1.x.md | 13 +++++++++++++ common.php | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index d3d81a56..ddee50e6 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,18 @@ # Changelog +## [1.6.1 - 11.06.2025] + +### Fixed +* Fixed "Request has been cancelled due to security reasons", cause of missing csrf() in twig files (https://github.com/slawkens/myaac/commit/10cd71a6630ffec91b43a26a6d685b66c5836a6a) +* Fix: Ignore duplicated route exception (https://github.com/slawkens/myaac/commit/9d8e9d27bd87167d8d4005942a6af62bfe4c0892) + +### Changed +* Move counter & visitors code before router (In case someone wants to include that info on page) (https://github.com/slawkens/myaac/commit/f78285030708ad3c74ab048711f73bbf3ee5281e) +* Set TinyMCE license key to gpl (Avoid warning message in browser console) (https://github.com/slawkens/myaac/commit/8d29fdb98b92dbc3d2853ef88a185c67036b4a77) + +### Removed +* Remove deprecated TinyMCE plugin - template (https://github.com/slawkens/myaac/commit/309c1fb715b882e67cb673b1544a03befbf64a22) + ## [1.6 - 03.06.2025] ### Added diff --git a/common.php b/common.php index 2af620c9..6df62349 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.6.1-dev'; +const MYAAC_VERSION = '1.6.1'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 0c95bcfd06b68b21512e477646ef7bd3a0d4912b Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 13 Jun 2025 21:03:09 +0200 Subject: [PATCH 067/222] Better $title inventing --- system/router.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/system/router.php b/system/router.php index 20f3f07a..a6da5f4b 100644 --- a/system/router.php +++ b/system/router.php @@ -326,7 +326,9 @@ if (isset($_REQUEST['_page_only'])) { if(!isset($title)) { $title = str_replace('index.php/', '', $page); - $title = ucfirst($title); + $title = str_replace(['_', '-', '/'], ' ', $page); + + $title = ucwords($title); } if(setting('core.backward_support')) { From 98b13c91a4efc06d78cbefa0a2b37ec86766a717 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 13 Jun 2025 21:24:52 +0200 Subject: [PATCH 068/222] Update notice about how to enable Visitors Counter --- admin/pages/visitors.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/admin/pages/visitors.php b/admin/pages/visitors.php index 9e83d339..f0ac731f 100644 --- a/admin/pages/visitors.php +++ b/admin/pages/visitors.php @@ -19,8 +19,7 @@ $use_datatable = true; if (!setting('core.visitors_counter')): ?> Visitors counter is disabled.
    - You can enable it by editing this configurable in config.local.php file:
    -

    $config['visitors_counter'] = true;

    + You can enable it Settings -> General -> Visitors Counter.
    Date: Fri, 13 Jun 2025 21:25:13 +0200 Subject: [PATCH 069/222] Ignore empty values --- admin/pages/visitors.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/pages/visitors.php b/admin/pages/visitors.php index f0ac731f..dfc92ff0 100644 --- a/admin/pages/visitors.php +++ b/admin/pages/visitors.php @@ -45,7 +45,7 @@ foreach ($tmp as &$visitor) { if ($dd->isBot()) { $bot = $dd->getBot(); $message = '(Bot) %s, %s'; - $browser = sprintf($message, $bot['category'], $bot['url'], $bot['name']); + $browser = sprintf($message, $bot['category'] ?? 'Unknown', $bot['url'] ?? '', $bot['name'] ?? 'Unknown name'); } else { $osFamily = OperatingSystem::getOsFamily($dd->getOs('name')); From 4d4f7759d32ebac6536c767b34f254a4a8bd55c3 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 13 Jun 2025 21:31:04 +0200 Subject: [PATCH 070/222] Update visitors.php --- admin/pages/visitors.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/pages/visitors.php b/admin/pages/visitors.php index dfc92ff0..9fae4d24 100644 --- a/admin/pages/visitors.php +++ b/admin/pages/visitors.php @@ -19,7 +19,7 @@ $use_datatable = true; if (!setting('core.visitors_counter')): ?> Visitors counter is disabled.
    - You can enable it Settings -> General -> Visitors Counter.
    + You can enable it in Settings -> General -> Visitors Counter.
    Date: Fri, 13 Jun 2025 22:14:20 +0200 Subject: [PATCH 071/222] Nothing important: convert to tabs --- system/libs/pot/OTS_Toolbox.php | 104 ++++++++++++++++---------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/system/libs/pot/OTS_Toolbox.php b/system/libs/pot/OTS_Toolbox.php index 980e5cb5..567f318d 100644 --- a/system/libs/pot/OTS_Toolbox.php +++ b/system/libs/pot/OTS_Toolbox.php @@ -15,7 +15,7 @@ /** * Toolbox for common operations. - * + * * @package POT * @version 0.1.5 */ @@ -23,41 +23,41 @@ class OTS_Toolbox { /** * Calculates experience points needed for given level. - * + * * @param int $level Level for which experience should be calculated. * @param int $experience Current experience points. * @return int Experience points for level. */ public static function experienceForLevel($level, $experience = 0) - { - //return 50 * ($level - 1) * ($level * $level - 5 * $level + 12) / 3 - $experience; + { + //return 50 * ($level - 1) * ($level * $level - 5 * $level + 12) / 3 - $experience; $level = $level - 1; return ((50 * $level * $level * $level) - (150 * $level * $level) + (400 * $level)) / 3; - } + } /** * Finds out which level user have basing on his/her experience. - * + * *

    * PHP doesn't support complex numbers natively so solving third-level polynomials would be quite hard. Rather then doing this, this method iterates calculating experience for next levels until it finds one which requires enought experience we have. Because of that, for high experience values this function can take relatively long time to be executed. *

    - * + * * @param int $experience Current experience points. * @return int Experience level. */ - public static function levelForExperience($experience) - { - // default level - $level = 1; + public static function levelForExperience($experience) + { + // default level + $level = 1; - // until we will find level which requires more experience then we have we will step to next - while( self::experienceForLevel($level + 1) <= $experience) - { - $level++; - } + // until we will find level which requires more experience then we have we will step to next + while( self::experienceForLevel($level + 1) <= $experience) + { + $level++; + } - return $level; - } + return $level; + } /** * @version 0.1.5 @@ -65,25 +65,25 @@ class OTS_Toolbox * @return OTS_Players_List Filtered list. * @deprecated 0.1.5 Use OTS_PlayerBans_List. */ - public static function bannedPlayers() - { - // creates filter - $filter = new OTS_SQLFilter(); - $filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_PLAYER); - $filter->addFilter( new OTS_SQLField('active', 'bans'), 1); - $filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'players') ); + public static function bannedPlayers() + { + // creates filter + $filter = new OTS_SQLFilter(); + $filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_PLAYER); + $filter->addFilter( new OTS_SQLField('active', 'bans'), 1); + $filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'players') ); - // selects only active bans - $actives = new OTS_SQLFilter(); - $actives->addFilter( new OTS_SQLField('expires', 'bans'), 0); - $actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR); - $filter->addFilter($actives); + // selects only active bans + $actives = new OTS_SQLFilter(); + $actives->addFilter( new OTS_SQLField('expires', 'bans'), 0); + $actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR); + $filter->addFilter($actives); - // creates list and aplies filter - $list = new OTS_Players_List(); - $list->setFilter($filter); - return $list; - } + // creates list and aplies filter + $list = new OTS_Players_List(); + $list->setFilter($filter); + return $list; + } /** * @version 0.1.5 @@ -91,25 +91,25 @@ class OTS_Toolbox * @return OTS_Accounts_List Filtered list. * @deprecated 0.1.5 Use OTS_AccountBans_List. */ - public static function bannedAccounts() - { - // creates filter - $filter = new OTS_SQLFilter(); - $filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_ACCOUNT); - $filter->addFilter( new OTS_SQLField('active', 'bans'), 1); - $filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'accounts') ); + public static function bannedAccounts() + { + // creates filter + $filter = new OTS_SQLFilter(); + $filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_ACCOUNT); + $filter->addFilter( new OTS_SQLField('active', 'bans'), 1); + $filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'accounts') ); - // selects only active bans - $actives = new OTS_SQLFilter(); - $actives->addFilter( new OTS_SQLField('expires', 'bans'), 0); - $actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR); - $filter->addFilter($actives); + // selects only active bans + $actives = new OTS_SQLFilter(); + $actives->addFilter( new OTS_SQLField('expires', 'bans'), 0); + $actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR); + $filter->addFilter($actives); - // creates list and aplies filter - $list = new OTS_Accounts_List(); - $list->setFilter($filter); - return $list; - } + // creates list and aplies filter + $list = new OTS_Accounts_List(); + $list->setFilter($filter); + return $list; + } } /**#@-*/ From e222957893c4a1de0dc8dbba55bce1a43418d275 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 13 Jun 2025 22:25:36 +0200 Subject: [PATCH 072/222] OTS_Toolbox::getVocationName($id, $promotion); --- system/libs/pot/OTS_Player.php | 11 ++--------- system/libs/pot/OTS_Toolbox.php | 9 +++++++++ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/system/libs/pot/OTS_Player.php b/system/libs/pot/OTS_Player.php index 7b688d1c..4b859dd9 100644 --- a/system/libs/pot/OTS_Player.php +++ b/system/libs/pot/OTS_Player.php @@ -2953,21 +2953,14 @@ class OTS_Player extends OTS_Row_DAO * @return string Player proffesion name. * @throws E_OTS_NotLoaded If player is not loaded or global vocations list is not loaded. */ - public function getVocationName() + public function getVocationName(): string { if( !isset($this->data['vocation']) ) { throw new E_OTS_NotLoaded(); } - global $config; - $voc = $this->getVocation(); - if(!isset($config['vocations'][$voc])) { - return 'Unknown'; - } - - return $config['vocations'][$voc]; - //return POT::getInstance()->getVocationsList()->getVocationName($this->data['vocation']); + return OTS_Toolbox::getVocationName($this->data['vocation'], $this->data['promotion'] ?? 0); } /** diff --git a/system/libs/pot/OTS_Toolbox.php b/system/libs/pot/OTS_Toolbox.php index 567f318d..575dba6f 100644 --- a/system/libs/pot/OTS_Toolbox.php +++ b/system/libs/pot/OTS_Toolbox.php @@ -110,6 +110,15 @@ class OTS_Toolbox $list->setFilter($filter); return $list; } + + public static function getVocationName($id, $promotion = 0): string + { + if($promotion > 0) { + $id = ($id + ($promotion * config('vocations_amount'))); + } + + return config('vocations')[$id] ?? 'Unknown'; + } } /**#@-*/ From c074a48f245df55646b6705737f667b6a84149b2 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 00:44:00 +0200 Subject: [PATCH 073/222] New hook: HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS --- system/src/global.php | 1 + system/templates/account.management.html.twig | 2 ++ templates/tibiacom/account.management.html.twig | 5 ++++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/system/src/global.php b/system/src/global.php index f374568d..37f507a0 100644 --- a/system/src/global.php +++ b/system/src/global.php @@ -54,6 +54,7 @@ define('HOOK_ACCOUNT_MANAGE_BEFORE_GENERAL_INFORMATION', ++$i); define('HOOK_ACCOUNT_MANAGE_BEFORE_PUBLIC_INFORMATION', ++$i); define('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS', ++$i); define('HOOK_ACCOUNT_MANAGE_BEFORE_CHARACTERS', ++$i); +define('HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS', ++$i); define('HOOK_ACCOUNT_LOGIN_BEFORE_PAGE', ++$i); define('HOOK_ACCOUNT_LOGIN_BEFORE_ACCOUNT', ++$i); define('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT', ++$i); diff --git a/system/templates/account.management.html.twig b/system/templates/account.management.html.twig index 2db1e57c..03e2c2a6 100644 --- a/system/templates/account.management.html.twig +++ b/system/templates/account.management.html.twig @@ -228,5 +228,7 @@
    +
    + {{ csrf() }} {{ include('buttons.delete_character.html.twig') }}
    - - {{ csrf() }} - - + - - + + +
    +
    + + {{ csrf() }} {{ include('buttons.back.html.twig') }} -
    +
    + {{ hook('HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS') }} diff --git a/templates/tibiacom/account.management.html.twig b/templates/tibiacom/account.management.html.twig index 7d8cf37c..649eba36 100644 --- a/templates/tibiacom/account.management.html.twig +++ b/templates/tibiacom/account.management.html.twig @@ -463,4 +463,7 @@
    {% endset %} {% include 'tables.headline.html.twig' %} -

    +
    +{{ hook('HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS') }} + +
    From 00c3635c5ff5800056432b29f2bd3a2f21417394 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 00:59:10 +0200 Subject: [PATCH 074/222] Add $config['site']['serverPath'] for better compatibility with Gesior --- index.php | 1 + 1 file changed, 1 insertion(+) diff --git a/index.php b/index.php index 87204e01..bf7069d4 100644 --- a/index.php +++ b/index.php @@ -93,6 +93,7 @@ if(setting('core.backward_support')) { if($logged && $account_logged) $group_id_of_acc_logged = $account_logged->getGroupId(); + $config['serverPath'] = $config['server_path']; $config['site'] = &$config; $config['server'] = &$config['lua']; $config['site']['shop_system'] = setting('core.gifts_system'); From 522f6c11d835afd36fd07a07074d96d7e219b488 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 08:26:43 +0200 Subject: [PATCH 075/222] Add OTS_Player->isNameLocked() --- system/libs/pot/OTS_Player.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/system/libs/pot/OTS_Player.php b/system/libs/pot/OTS_Player.php index 4b859dd9..099f5db1 100644 --- a/system/libs/pot/OTS_Player.php +++ b/system/libs/pot/OTS_Player.php @@ -2919,6 +2919,32 @@ class OTS_Player extends OTS_Row_DAO $this->data['banned'] = $ban['active']; $this->data['banned_time'] = $ban['expires']; } + + public function isNameLocked(): bool + { + // nothing can't be banned + if( !$this->isLoaded() ) { + throw new E_OTS_NotLoaded(); + } + + if($this->db->hasTable('player_namelocks')) { + $ban = $this->db->query('SELECT 1 FROM `player_namelocks` WHERE `player_id` = ' . $this->data['id'])->fetch(PDO::FETCH_ASSOC); + return (isset($ban['1'])); + } + else if($this->db->hasTable('bans')) { + if($this->db->hasColumn('bans', 'active')) { + $ban = $this->db->query('SELECT `active`, `expires` FROM `bans` WHERE `type` = 2 AND `active` = 1 AND `value` = ' . $this->data['id'] . ' AND (`expires` > ' . time() .' OR `expires` = -1) ORDER BY `expires` DESC')->fetch(); + return isset($ban['active']); + } + else { // tfs 0.2 + $ban = $this->db->query('SELECT `time` FROM `bans` WHERE `type` = 2 AND `account` = ' . $this->data['account_id'] . ' AND (`time` > ' . time() .' OR `time` = -1) ORDER BY `time` DESC')->fetch(); + + return isset($ban['time']) && ($ban['time'] == -1 || $ban['time'] > 0); + } + } + + return false; + } /** * Deletes player. * From e6100a1b72de8695bba1dae9ba4e28bfdce47b10 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 10:36:38 +0200 Subject: [PATCH 076/222] New hook: HOOK_GUILDS_AFTER_MANAGE_BUTTON --- system/src/global.php | 1 + system/templates/guilds.view.html.twig | 1 + 2 files changed, 2 insertions(+) diff --git a/system/src/global.php b/system/src/global.php index 37f507a0..8f1885f3 100644 --- a/system/src/global.php +++ b/system/src/global.php @@ -93,6 +93,7 @@ define('HOOK_EMAIL_CONFIRMED', ++$i); define('HOOK_GUILDS_BEFORE_GUILD_HEADER', ++$i); define('HOOK_GUILDS_AFTER_GUILD_HEADER', ++$i); define('HOOK_GUILDS_AFTER_GUILD_INFORMATION', ++$i); +define('HOOK_GUILDS_AFTER_MANAGE_BUTTON', ++$i); define('HOOK_GUILDS_AFTER_GUILD_MEMBERS', ++$i); define('HOOK_GUILDS_AFTER_INVITED_CHARACTERS', ++$i); define('HOOK_TWIG', ++$i); diff --git a/system/templates/guilds.view.html.twig b/system/templates/guilds.view.html.twig index a25d9570..8f29dbf6 100644 --- a/system/templates/guilds.view.html.twig +++ b/system/templates/guilds.view.html.twig @@ -49,6 +49,7 @@ {% include('buttons.base.html.twig') %} {% endif %} + {{ hook('HOOK_GUILDS_AFTER_MANAGE_BUTTON') }}
    @@ -152,6 +153,7 @@ {{ hook('HOOK_GUILDS_AFTER_GUILD_MEMBERS') }} {% set title = 'Invited Characters' %} + {% set background = config('lightborder') %} {% set content %}
    From b8abc11b96156da929122e9542994a3a7328fd26 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 11:33:47 +0200 Subject: [PATCH 078/222] Update list.php --- system/pages/guilds/list.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/system/pages/guilds/list.php b/system/pages/guilds/list.php index 26d77d3a..94c49854 100644 --- a/system/pages/guilds/list.php +++ b/system/pages/guilds/list.php @@ -36,10 +36,9 @@ if(count($guilds_list) > 0) { $guildName = $guild->getName(); $guilds[] = array('name' => $guildName, 'logo' => $guild_logo, 'link' => getGuildLink($guildName, false), 'description' => $description); } -}; +} $twig->display('guilds.list.html.twig', array( 'guilds' => $guilds, - 'logged' => $logged ?? false, 'isAdmin' => admin(), )); From 577037beccd740168d56b05124f95c2d28ab803a Mon Sep 17 00:00:00 2001 From: Goosey Date: Sat, 14 Jun 2025 17:58:08 +0400 Subject: [PATCH 079/222] fix: boostedcreatures for 13.40 (#307) * boostedcreatures fix for 13.40 Fixes the boosted boss/creature display on the login page for 13.40 running the default cipsoft client. * Adjust version --------- Co-authored-by: slawkens --- login.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/login.php b/login.php index 88d5d88a..d4d25529 100644 --- a/login.php +++ b/login.php @@ -88,8 +88,8 @@ switch ($action) { case 'boostedcreature': $clientVersion = (int)setting('core.client'); - // 14.00 and up - if ($clientVersion >= 1400) { + // 13.40 and up + if ($clientVersion >= 1340) { $creatureBoost = $db->query("SELECT * FROM " . $db->tableName('boosted_creature'))->fetchAll(); $bossBoost = $db->query("SELECT * FROM " . $db->tableName('boosted_boss'))->fetchAll(); die(json_encode([ From a7efacdbacdee40a470e010eb239147d378ecbdb Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 20:50:54 +0200 Subject: [PATCH 080/222] Delete online.form, use revamped characters.form --- system/pages/online.php | 2 +- system/templates/characters.form.html.twig | 40 +++++++++++++--------- system/templates/online.form.html.twig | 25 -------------- 3 files changed, 24 insertions(+), 43 deletions(-) delete mode 100644 system/templates/online.form.html.twig diff --git a/system/pages/online.php b/system/pages/online.php index 4f0baa7d..f292a4b1 100644 --- a/system/pages/online.php +++ b/system/pages/online.php @@ -127,5 +127,5 @@ $twig->display('online.html.twig', array( )); //search bar -$twig->display('online.form.html.twig'); +$twig->display('characters.form.html.twig'); ?> diff --git a/system/templates/characters.form.html.twig b/system/templates/characters.form.html.twig index d731b4e2..0fd85608 100644 --- a/system/templates/characters.form.html.twig +++ b/system/templates/characters.form.html.twig @@ -1,17 +1,23 @@ -
    -
    - - - - -
    Search Character
    - - - - - -
    Name: - {{ include('buttons.submit.html.twig') }} -
    -
    - \ No newline at end of file +
    +
    + {% set title = 'Search Character' %} + {% set tableClass = 'Table1' %} + {% set background = config('darkborder') %} + {% set content %} + + + + + + +
    + Character Name: + + + + {% set button_name = 'Submit' %} + {{ include('buttons.base.html.twig') }} +
    + {% endset %} + {{ include('tables.headline.html.twig') }} +
    diff --git a/system/templates/online.form.html.twig b/system/templates/online.form.html.twig deleted file mode 100644 index 82c6f7b2..00000000 --- a/system/templates/online.form.html.twig +++ /dev/null @@ -1,25 +0,0 @@ -
    -
    - - - - - - - -
    - Search Character -
    - - - - - - -
    Name: - - - {{ include('buttons.submit.html.twig') }} -
    -
    -
    \ No newline at end of file From ba4ed6a04b285bc179ca4db89409a6f0168524c1 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 20:52:38 +0200 Subject: [PATCH 081/222] Add LabelV120, LabelV150, LabelV200 --- templates/kathrine/style.css | 21 +++++++++++++++++++++ templates/tibiacom/basic.css | 21 +++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/templates/kathrine/style.css b/templates/kathrine/style.css index a021b1d9..45a1a9d4 100644 --- a/templates/kathrine/style.css +++ b/templates/kathrine/style.css @@ -453,6 +453,27 @@ a:hover white-space: nowrap; vertical-align: top; } +.LabelV120 { + font-weight: bold; + padding-right: 10px; + white-space: nowrap; + vertical-align: top; + width: 120px; +} +.LabelV150 { + font-weight: bold; + padding-right: 10px; + white-space: nowrap; + vertical-align: top; + width: 150px; +} +.LabelV200 { + font-weight: bold; + padding-right: 10px; + white-space: nowrap; + vertical-align: top; + width: 200px; +} .LabelH { font-weight: bold; padding-right: 10px; diff --git a/templates/tibiacom/basic.css b/templates/tibiacom/basic.css index 4633c5ed..a4f0fc24 100644 --- a/templates/tibiacom/basic.css +++ b/templates/tibiacom/basic.css @@ -1446,6 +1446,27 @@ img { white-space: nowrap; vertical-align: top; } +.LabelV120 { + font-weight: bold; + padding-right: 10px; + white-space: nowrap; + vertical-align: top; + width: 120px; +} +.LabelV150 { + font-weight: bold; + padding-right: 10px; + white-space: nowrap; + vertical-align: top; + width: 150px; +} +.LabelV200 { + font-weight: bold; + padding-right: 10px; + white-space: nowrap; + vertical-align: top; + width: 200px; +} .LabelH { font-weight: bold; padding-right: 10px; From 9a90e4aae280e607430511c6727d9a714b11f4c5 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 21:12:47 +0200 Subject: [PATCH 082/222] Revamped online page --- images/order_asc.gif | Bin 0 -> 56 bytes images/order_desc.gif | Bin 0 -> 56 bytes system/pages/online.php | 26 +++-- system/settings.php | 6 ++ system/templates/online.html.twig | 162 +++++++++++++++++++----------- 5 files changed, 127 insertions(+), 67 deletions(-) create mode 100644 images/order_asc.gif create mode 100644 images/order_desc.gif diff --git a/images/order_asc.gif b/images/order_asc.gif new file mode 100644 index 0000000000000000000000000000000000000000..c9698a5a02f81238b51b1d12bf85840fb7c1fdbe GIT binary patch literal 56 zcmZ?wbhEHbgRG IH3Ne+0CC0*ssI20 literal 0 HcmV?d00001 diff --git a/images/order_desc.gif b/images/order_desc.gif new file mode 100644 index 0000000000000000000000000000000000000000..4a764bd585acf65719cff63448779a4b584fdd09 GIT binary patch literal 56 zcmZ?wbhEHbhasColumn('players', 'promotion')) $promotion = '`promotion`,'; -$order = $_GET['order'] ?? 'name'; -if(!in_array($order, array('country', 'name', 'level', 'vocation'))) - $order = $db->fieldName('name'); -else if($order == 'country') - $order = $db->tableName('accounts') . '.' . $db->fieldName('country'); -else if($order == 'vocation') - $order = $promotion . 'vocation ASC'; +$order = $_GET['order'] ?? 'name_asc'; +if(!in_array($order, ['country_asc', 'country_desc', 'name_asc', 'name_desc', 'level_asc', 'level_desc', 'vocation_asc', 'vocation_desc'])) { + $order = 'name_asc'; +} +else if($order == 'vocation_asc' || $order == 'vocation_desc') { + $order = $promotion . 'vocation_' . (str_contains($order, 'asc') ? 'asc' : 'desc'); +} + +$orderExplode = explode('_', $order); +$orderSql = $orderExplode[0] . ' ' . $orderExplode[1]; $skull_type = 'skull'; if($db->hasColumn('players', 'skull_type')) { @@ -58,11 +61,11 @@ if (setting('core.online_vocations')) { } if($db->hasTable('players_online')) // tfs 1.0 - $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $order); + $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql); else - $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', ' . $promotion . ' `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players` WHERE `players`.`online` > 0 AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $order); + $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', ' . $promotion . ' `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players` WHERE `players`.`online` > 0 AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql); -$players_data = array(); +$players_data = []; $players = 0; $data = ''; foreach($playersOnline as $player) { @@ -115,7 +118,7 @@ if(count($players_data) > 0) { } if($result) { - $record = 'The maximum on this game world was ' . $result['record'] . ' players' . ($timestamp ? ' on ' . date("M d Y, H:i:s", $result['timestamp']) . '.' : '.'); + $record = $result['record'] . ' player' . ($result['record'] > 1 ? 's' : '') . ($timestamp ? ' (on ' . date("M d Y, H:i:s", $result['timestamp']) . ')' : ''); } } } @@ -124,6 +127,7 @@ $twig->display('online.html.twig', array( 'players' => $players_data, 'record' => $record, 'vocs' => $vocs, + 'order' => $order, )); //search bar diff --git a/system/settings.php b/system/settings.php index 4cfe5c9f..40c8be03 100644 --- a/system/settings.php +++ b/system/settings.php @@ -1264,6 +1264,12 @@ Sent by MyAAC,
    'desc' => '', 'default' => false, ], + 'online_datacenter' => [ + 'name' => 'Data Center', + 'type' => 'text', + 'desc' => 'Server Location, will be shown on online page', + 'default' => 'Frankfurt - Germany', + ], [ 'type' => 'section', 'title' => 'Team Page' diff --git a/system/templates/online.html.twig b/system/templates/online.html.twig index 0210d80f..2555873e 100644 --- a/system/templates/online.html.twig +++ b/system/templates/online.html.twig @@ -1,39 +1,7 @@ - - - - -{% if players|length == 0 %} -
    Server Status
    Currently no one is playing on {{ config.lua.serverName }}.
    -{% else %} -
    - {% if not status.online %} - Server is offline.
    - {% else %} - {% if setting('core.online_afk') %} - {% set players_count = players|length %} - {% set afk = players_count - status.players %} - {% if afk < 0 %} - {% set players_count = players_count + afk|abs %} - {% set afk = 0 %} - {% endif %} - Currently there are {{ status.players }} active and {{ afk }} AFK players.
    - Total number of players: {{ players_count }}.
    - {% else %} - Currently {{ players|length }} players are online.
    - {% endif %} - {% endif %} - {% if setting('core.online_record') %} - {{ record }} - {% endif %} -
    +{# vocation statistics #} +{% if setting('core.online_vocations') %}
    - {# vocation statistics #} - {% if setting('core.online_vocations') %} -
    - {% if setting('core.online_vocations_images') %} + {% if setting('core.online_vocations_images') %} @@ -69,11 +37,13 @@ {% endfor %}

    - {% endif %} {% endif %} +{% endif %} - {# show skulls #} - {% if setting('core.online_skulls') %} +
    + +{# show skulls #} +{% if setting('core.online_skulls') %}
    @@ -83,34 +53,114 @@
    +{% endif %} + +
    + +{% set title = 'World Information' %} +{% set tableClass = 'Table3' %} +{% set background = config('darkborder') %} +{% set content %} + + + + + + + + + + + {% if setting('core.online_record') %} + + + + {% endif %} -
    Status:{% if not status.online %}Offline{% else %}Online{% endif %}
    Players Online: + {% if setting('core.online_afk') %} + {% set players_count = players|length %} + {% set afk = players_count - status.players %} + {% if afk < 0 %} + {% set players_count = players_count + afk|abs %} + {% set afk = 0 %} + {% endif %} + Currently there are {{ status.players }} active and {{ afk }} AFK players.
    + Total number of players: {{ players_count }}.
    + {% else %} + {{ players|length }} Players Online. + {% endif %} +
    Online Record: + {{ record }} +
    - + + + + + + + + +
    Location Datacenter:{{ setting('core.online_datacenter') }} (Server date & time: - {{ "now"|date("d/m/Y H:i:s") }})
    PvP Type: + {% set worldType = config('lua')['worldType']|lower %} + {% if worldType in ['pvp','2','normal','open','openpvp'] %} + Open PvP + {% elseif worldType in ['no-pvp','nopvp','non-pvp','nonpvp','1','safe','optional','optionalpvp'] %} + Optional PvP + {% elseif worldType in ['pvp-enforced','pvpenforced','pvp-enfo','pvpenfo','pvpe','enforced','enfo','3','war','hardcore','hardcorepvp'] %} + Hardcore PvP + {% endif %} +
    +{% endset %} +{% include 'tables.headline.html.twig' %} +
    +
    + +{% set title = 'Players Online' %} +{% set tableClass = 'Table2' %} +{% set content %} + + {% if setting('core.account_country') %} - + {% endif %} {% if setting('core.online_outfit') %} - + {% endif %} - - - + + + + {% set i = 0 %} {% for player in players %} {% set i = i + 1 %} - - {% if setting('core.account_country') %} - - {% endif %} - {% if setting('core.online_outfit') %} - - {% endif %} - - - + + + {% if setting('core.account_country') %} + + {% endif %} + + {% if setting('core.online_outfit') %} + + {% endif %} + + + + {% endfor %}
    ##   + OutfitOutfitNameLevelVocationName   + [sort] + Level   + [sort] + + Vocation   + [sort] + +
    {{ player.country_image|raw }}player outfit{{ player.name|raw }}{{ player.skull }}{{ player.level }}{{ player.vocation }}
    {{ player.country_image|raw }}player outfit + {{ player.name|raw }}{{ player.skull }} + {{ player.level }}{{ player.vocation }}
    -{% endif %} +{% endset %} +{{ include('tables.headline.html.twig') }} From 4767120043b09141870383e249f3729638d53dc2 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 21:19:52 +0200 Subject: [PATCH 083/222] Update online.html.twig --- system/templates/online.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/templates/online.html.twig b/system/templates/online.html.twig index 2555873e..26a756ed 100644 --- a/system/templates/online.html.twig +++ b/system/templates/online.html.twig @@ -79,7 +79,7 @@ Currently there are {{ status.players }} active and {{ afk }} AFK players.
    Total number of players: {{ players_count }}.
    {% else %} - {{ players|length }} Players Online. + {{ players|length }} {% endif %}
    + {{ csrf() }} From 8dc42b654473ac4133effd7f26125619bbc64fb2 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 15 Jun 2025 19:05:47 +0200 Subject: [PATCH 086/222] Nothing important: just formatting --- .../templates/account.change-email.html.twig | 16 ++++++++-------- ...account.characters.change-comment.html.twig | 18 +++++++++--------- .../account.characters.delete.html.twig | 16 ++++++++-------- system/templates/success.html.twig | 14 +++++++------- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/system/templates/account.change-email.html.twig b/system/templates/account.change-email.html.twig index ea627cc7..ab2a8c06 100644 --- a/system/templates/account.change-email.html.twig +++ b/system/templates/account.change-email.html.twig @@ -28,7 +28,7 @@ Please enter your password and the new email address. Make sure that you enter a - + {% for plugin in plugins %} From 566c2a9151ab6392286f74e26853faa19a1b4f24 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 22 Jun 2025 08:48:24 +0200 Subject: [PATCH 091/222] Move out of $cache->enabled --- system/functions.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system/functions.php b/system/functions.php index 56cf378b..add481e5 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1263,10 +1263,10 @@ function clearCache() global $db; $db->setClearCacheAfter(true); + } - if (function_exists('apcu_clear_cache')) { - apcu_clear_cache(); - } + if (function_exists('apcu_clear_cache')) { + apcu_clear_cache(); } deleteDirectory(CACHE . 'signatures', ['index.html'], true); From bb830bce4425bec02c42e99e68e9e18fd3eea7dc Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 22 Jun 2025 08:55:29 +0200 Subject: [PATCH 092/222] Release v1.7 --- CHANGELOG-1.x.md | 16 ++++++++++++++++ common.php | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index ddee50e6..34439313 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,21 @@ # Changelog +## [1.7 - 22.06.2025] + +### Added +* Feature: plugins versions check (#310) +* New hooks: HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS, HOOK_GUILDS_AFTER_MANAGE_BUTTON (https://github.com/slawkens/myaac/commit/c074a48f245df55646b6705737f667b6a84149b2, https://github.com/slawkens/myaac/commit/e6100a1b72de8695bba1dae9ba4e28bfdce47b10) +* Add OTS_Toolbox::getVocationName(id, promotion) + OTS_Player->isNameLocked() (https://github.com/slawkens/myaac/commit/e222957893c4a1de0dc8dbba55bce1a43418d275, https://github.com/slawkens/myaac/commit/522f6c11d835afd36fd07a07074d96d7e219b488) +* Add missing csrf in more places, causing white page with error about Request (https://github.com/slawkens/myaac/commit/dca904e61d21d856bf809070e7652803a2df0f58, https://github.com/slawkens/myaac/commit/c720ccc451ff90ef40b2a1595468d061ffd7e1e4) + +### Changed +* Revamped online page (https://github.com/slawkens/myaac/commit/9a90e4aae280e607430511c6727d9a714b11f4c5, https://github.com/slawkens/myaac/commit/4767120043b09141870383e249f3729638d53dc2) +* Better $title inventing (https://github.com/slawkens/myaac/commit/0c95bcfd06b68b21512e477646ef7bd3a0d4912b) + +### Fixed +* Use apcu cache clear (https://github.com/slawkens/myaac/commit/b329da52aae9d0e21120a6444d3caf442420ce50, https://github.com/slawkens/myaac/commit/566c2a9151ab6392286f74e26853faa19a1b4f24) +* fix: boostedcreatures for 13.40 (by @GooseWithAKnife) (#307) + ## [1.6.1 - 11.06.2025] ### Fixed diff --git a/common.php b/common.php index 6df62349..1ed07a7f 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.6.1'; +const MYAAC_VERSION = '1.7'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 5cfa3a697f37f2a4e75497de68640f975223d5d2 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 22 Jun 2025 11:25:45 +0200 Subject: [PATCH 093/222] Start v1.7.1-dev --- common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.php b/common.php index 1ed07a7f..e07242b6 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.7'; +const MYAAC_VERSION = '1.7.1-dev'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 6cf4b9dac52dc9de565a9d23b088b776063858da Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 22 Jun 2025 18:51:20 +0200 Subject: [PATCH 094/222] Fix xdebug warnings in load_config_lua --- system/functions.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/functions.php b/system/functions.php index add481e5..3ef7a8a2 100644 --- a/system/functions.php +++ b/system/functions.php @@ -982,11 +982,12 @@ function load_config_lua($filename) foreach($lines as $ln => $line) { $line = trim($line); - if(@$line[0] === '{' || @$line[0] === '}') { + if(isset($line[0]) && ($line[0] === '{' || $line[0] === '}')) { // arrays are not supported yet // just ignore the error continue; } + $tmp_exp = explode('=', $line, 2); if(str_contains($line, 'dofile')) { $delimiter = '"'; From 0da524fefe93b3028392e9014550eea3324d3a22 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 23 Jun 2025 00:21:41 +0200 Subject: [PATCH 095/222] Fix plugin install:install command --- system/src/Plugins.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/system/src/Plugins.php b/system/src/Plugins.php index 85f0a2ba..37a1af3c 100644 --- a/system/src/Plugins.php +++ b/system/src/Plugins.php @@ -781,15 +781,15 @@ class Plugins { return false; } - if(!isset($plugin_json['install'])) { - self::$error = "Plugin doesn't have install options defined. Skipping..."; - return false; + $install = $plugin_json['install'] ?? ''; + if (self::getAutoLoadOption($plugin_json, 'install', true) && is_file(PLUGINS . $plugin_name . '/install.php')) { + $install = 'plugins/' . $plugin_name . '/install.php'; } global $db; - if (file_exists(BASE . $plugin_json['install'])) { + if (file_exists(BASE . $install)) { $db->revalidateCache(); - require BASE . $plugin_json['install']; + require BASE . $install; $db->revalidateCache(); } else { From 181131f7f3402b324747fdb2e7a32d1d9d9179ee Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 24 Jun 2025 12:44:34 +0200 Subject: [PATCH 096/222] Use __DIR__ instead of template path --- templates/tibiacom/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/tibiacom/index.php b/templates/tibiacom/index.php index 6d0d1e63..46ef0698 100644 --- a/templates/tibiacom/index.php +++ b/templates/tibiacom/index.php @@ -454,7 +454,7 @@ foreach($config['menu_categories'] as $id => $cat) { foreach($config['boxes'] as $box) { /** @var string $template_name */ - $file = TEMPLATES . $template_name . '/boxes/' . $box . '.php'; + $file = __DIR__ . '/boxes/' . $box . '.php'; if(file_exists($file)) { include($file); ?> Date: Tue, 24 Jun 2025 12:44:43 +0200 Subject: [PATCH 097/222] Fix polls link --- templates/tibiacom/boxes/templates/poll.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/tibiacom/boxes/templates/poll.html.twig b/templates/tibiacom/boxes/templates/poll.html.twig index 0b643ee5..25f10865 100644 --- a/templates/tibiacom/boxes/templates/poll.html.twig +++ b/templates/tibiacom/boxes/templates/poll.html.twig @@ -1,6 +1,6 @@
    {{ poll.question }}
    -
    +
    From f78ebad136c36ddeace2f90d714d1190af89262e Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 24 Jun 2025 14:57:01 +0200 Subject: [PATCH 098/222] Remove error number from 404 & 405 pages --- system/pages/404.php | 2 +- system/pages/405.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/system/pages/404.php b/system/pages/404.php index 90a8921a..60fb66aa 100644 --- a/system/pages/404.php +++ b/system/pages/404.php @@ -8,7 +8,7 @@ * @link https://my-aac.org */ defined('MYAAC') or die('Direct access not allowed!'); -$title = '404 Not Found'; +$title = 'Not Found'; header('HTTP/1.0 404 Not Found'); ?> diff --git a/system/pages/405.php b/system/pages/405.php index 3d585f59..d1eee43a 100644 --- a/system/pages/405.php +++ b/system/pages/405.php @@ -8,7 +8,7 @@ * @link https://my-aac.org */ defined('MYAAC') or die('Direct access not allowed!'); -$title = '405 Method Not Allowed'; +$title = 'Method Not Allowed'; header('HTTP/1.0 405 Method Not Allowed'); ?> From 13d33822b59df349199e885a78a3d6beb0863d0b Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 25 Jun 2025 17:36:02 +0200 Subject: [PATCH 099/222] Rename to plugin:setup, also add alias to previous command --- system/src/Commands/PluginInstallInstallCommand.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/src/Commands/PluginInstallInstallCommand.php b/system/src/Commands/PluginInstallInstallCommand.php index fe1b4f14..116eeb13 100644 --- a/system/src/Commands/PluginInstallInstallCommand.php +++ b/system/src/Commands/PluginInstallInstallCommand.php @@ -12,7 +12,8 @@ class PluginInstallInstallCommand extends Command { protected function configure(): void { - $this->setName('plugin:install:install') + $this->setName('plugin:setup') + ->setAliases(['plugin:install:install']) ->setDescription('This command executes the "install" part of the plugin') ->addArgument('plugin', InputArgument::REQUIRED, 'Plugin name'); } From 6d43fc181fce9a40a78954689a3d0f744a6eea3b Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 25 Jun 2025 17:36:43 +0200 Subject: [PATCH 100/222] In case the script don't have install option, inform the user --- system/src/Plugins.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/system/src/Plugins.php b/system/src/Plugins.php index 37a1af3c..c880dd90 100644 --- a/system/src/Plugins.php +++ b/system/src/Plugins.php @@ -786,6 +786,11 @@ class Plugins { $install = 'plugins/' . $plugin_name . '/install.php'; } + if (empty($install)) { + self::$error = "This plugin doesn't seem to have install script defined."; + return false; + } + global $db; if (file_exists(BASE . $install)) { $db->revalidateCache(); From 0bff910a056974d4698a02f5a9398d6a2be1f3be Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 25 Jun 2025 19:43:40 +0200 Subject: [PATCH 101/222] adjust command email:send + mail:send (alias) --- system/src/Commands/MailSendCommand.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/system/src/Commands/MailSendCommand.php b/system/src/Commands/MailSendCommand.php index ff1450e6..983e6fc5 100644 --- a/system/src/Commands/MailSendCommand.php +++ b/system/src/Commands/MailSendCommand.php @@ -12,9 +12,10 @@ class MailSendCommand extends Command { protected function configure(): void { - $this->setName('mail:send') + $this->setName('email:send') + ->setAliases(['mail:send']) ->setDescription('This command sends E-Mail to single user. Message can be provided as follows: ' . PHP_EOL - . ' echo "Hello World" | php sa email:send --subject="This is the subject" test@test.com') + . ' echo "Hello World" | php aac email:send --subject="This is the subject" test@test.com') ->addArgument('recipient', InputArgument::REQUIRED, 'Email, Account Name, Account id or Player Name') ->addOption('subject', 's', InputOption::VALUE_REQUIRED, 'Subject'); } From fe8281594e989f00280ba1adc734a9198c6b5cc1 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 27 Jun 2025 07:13:33 +0200 Subject: [PATCH 102/222] Fix cache:clear command (missing init) --- system/src/Commands/CacheClearCommand.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/system/src/Commands/CacheClearCommand.php b/system/src/Commands/CacheClearCommand.php index 3b052995..5b1715b5 100644 --- a/system/src/Commands/CacheClearCommand.php +++ b/system/src/Commands/CacheClearCommand.php @@ -17,10 +17,7 @@ class CacheClearCommand extends Command protected function execute(InputInterface $input, OutputInterface $output): int { - global $hooks; - $hooks = new Hooks(); - $hooks->load(); - $hooks->trigger(HOOK_INIT); + require SYSTEM . 'init.php'; $io = new SymfonyStyle($input, $output); From 047742848bf1a14282ceac2af7cc397ce5ae6725 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 27 Jun 2025 07:15:13 +0200 Subject: [PATCH 103/222] Delete clearRouteCache, was useless Directory is cleaned already --- system/functions.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/system/functions.php b/system/functions.php index 3ef7a8a2..a3c302c3 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1275,23 +1275,12 @@ function clearCache() deleteDirectory(CACHE . 'plugins', ['index.html'], true); 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); - } -} - function getCustomPageInfo($name) { global $logged_access; From b4b62442fe9470e94c94812c533cc132e165003f Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 27 Jun 2025 07:21:19 +0200 Subject: [PATCH 104/222] Release v1.7.1 --- CHANGELOG-1.x.md | 9 +++++++++ common.php | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index 34439313..28c946ec 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,14 @@ # Changelog +## [1.7.1 - 27.06.2025] + +### Changed +* Rename plugin:install:install to plugin:setup, also add alias to previous command (https://github.com/slawkens/myaac/commit/13d33822b59df349199e885a78a3d6beb0863d0b) + +### Fixed +* Fix commands: setup + cache:clear (https://github.com/slawkens/myaac/commit/0da524fefe93b3028392e9014550eea3324d3a22, https://github.com/slawkens/myaac/commit/fe8281594e989f00280ba1adc734a9198c6b5cc1) +* Fix polls link in tibiacom template (https://github.com/slawkens/myaac/commit/d90fa323d7c77d81768df60feeb1c374b1650a0c) + ## [1.7 - 22.06.2025] ### Added diff --git a/common.php b/common.php index e07242b6..94395409 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.7.1-dev'; +const MYAAC_VERSION = '1.7.1'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From c92148d467e9c19fdf68d0f77dacec9cfe2e34cf Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 27 Jun 2025 07:23:22 +0200 Subject: [PATCH 105/222] Revert delete clearRouteCache, is used somewhere else --- system/functions.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/system/functions.php b/system/functions.php index a3c302c3..540c9af3 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1281,6 +1281,14 @@ function clearCache() return true; } +function clearRouteCache(): void +{ + $routeCacheFile = CACHE . 'route.cache'; + if (file_exists($routeCacheFile)) { + unlink($routeCacheFile); + } +} + function getCustomPageInfo($name) { global $logged_access; From 45d6047031c9c3a0e7e512dc5d15c75629aec5a2 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 5 Jul 2025 14:22:58 +0200 Subject: [PATCH 106/222] Add Coins Transferable to accounts editor --- admin/pages/accounts.php | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/admin/pages/accounts.php b/admin/pages/accounts.php index c2154299..0358753b 100644 --- a/admin/pages/accounts.php +++ b/admin/pages/accounts.php @@ -27,6 +27,13 @@ $nameOrNumberColumn = getAccountIdentityColumn(); $hasSecretColumn = $db->hasColumn('accounts', 'secret'); $hasCoinsColumn = $db->hasColumn('accounts', 'coins'); + +$hasCoinsTransferableColumn = $db->hasColumn('accounts', 'coins_transferable'); +$hasTransferableCoinsColumn = $db->hasColumn('accounts', 'transferable_coins'); +$coinsTransferableColumn = + $hasTransferableCoinsColumn ? + 'transferable_coins' : 'coins_transferable'; + $hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); $hasTypeColumn = $db->hasColumn('accounts', 'type'); $hasGroupColumn = $db->hasColumn('accounts', 'group_id'); @@ -136,11 +143,18 @@ else if (isset($_REQUEST['search'])) { if (!Validator::email($email)) $errors['email'] = Validator::getLastError(); - //tibia coins + // tibia coins if ($hasCoinsColumn) { $t_coins = $_POST['t_coins']; verify_number($t_coins, 'Tibia coins', 12); } + + // transferable tibia coins + if ($hasCoinsTransferableColumn || $hasTransferableCoinsColumn) { + $t_coins_transferable = $_POST['t_coins_transferable']; + verify_number($t_coins_transferable, 'Transferable Tibia coins', 12); + } + // prem days $p_days = (int)$_POST['p_days']; verify_number($p_days, 'Prem days', 11); @@ -185,12 +199,18 @@ else if (isset($_REQUEST['search'])) { if ($hasSecretColumn) { $account->setCustomField('secret', $secret); } + $account->setCustomField('key', $key); $account->setEMail($email); + if ($hasCoinsColumn) { $account->setCustomField('coins', $t_coins); } + if ($hasCoinsTransferableColumn || $hasTransferableCoinsColumn) { + $account->setCustomField($coinsTransferableColumn, $t_coins_transferable); + } + $lastDay = 0; if($p_days != 0 && $p_days != OTS_Account::GRATIS_PREMIUM_DAYS) { $lastDay = time(); @@ -401,6 +421,12 @@ else if (isset($_REQUEST['search'])) { + +
    + + +
    +
    From a89f9a84847630eb75b4890fdcc8b7a7bfa6b8ac Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 8 Jul 2025 09:22:12 +0200 Subject: [PATCH 107/222] Set $process_sections to true --- system/template.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/template.php b/system/template.php index f051e640..c97c8416 100644 --- a/system/template.php +++ b/system/template.php @@ -91,7 +91,7 @@ else { $file = BASE . $template_path . '/layout_config.ini'; } - $template_ini = parse_ini_file($file); + $template_ini = parse_ini_file($file, true); unset($file); if ($cache->enabled()) { From dcb96f4ce1e0fe90bdbf66036ded51155959b51d Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 8 Jul 2025 13:48:33 +0200 Subject: [PATCH 108/222] Refactor code - early exit --- system/src/Plugins.php | 325 ++++++++++++++++++++--------------------- 1 file changed, 162 insertions(+), 163 deletions(-) diff --git a/system/src/Plugins.php b/system/src/Plugins.php index c880dd90..e1a58620 100644 --- a/system/src/Plugins.php +++ b/system/src/Plugins.php @@ -532,193 +532,192 @@ class Plugins { self::$plugin_json = $plugin_json; if ($plugin_json == null) { self::$warnings[] = 'Cannot load ' . $file_name . '. File might be not a valid json code.'; + return false; } - else { - $continue = true; - if(!isset($plugin_json['name']) || empty(trim($plugin_json['name']))) { - self::$error = 'Plugin "name" tag is not set.'; + $continue = true; + + if(!isset($plugin_json['name']) || empty(trim($plugin_json['name']))) { + self::$error = 'Plugin "name" tag is not set.'; + return false; + } + + if(!isset($plugin_json['version']) || empty(trim($plugin_json['version']))) { + self::$warnings[] = 'Plugin "version" tag is not set.'; + } + + if(isset($plugin_json['require'])) { + $require = $plugin_json['require']; + + $myaac_satified = true; + if(isset($require['myaac_'])) { + $require_myaac = $require['myaac_']; + if(!Semver::satisfies(MYAAC_VERSION, $require_myaac)) { + $myaac_satified = false; + } + } + else if(isset($require['myaac'])) { + $require_myaac = $require['myaac']; + if(version_compare(MYAAC_VERSION, $require_myaac, '<')) { + $myaac_satified = false; + } + } + + if(!$myaac_satified) { + self::$error = "Your AAC version doesn't meet the requirement of this plugin. Required version is: " . $require_myaac . ", and you're using version " . MYAAC_VERSION . "."; return false; } - if(!isset($plugin_json['version']) || empty(trim($plugin_json['version']))) { - self::$warnings[] = 'Plugin "version" tag is not set.'; + $php_satisfied = true; + if(isset($require['php_'])) { + $require_php = $require['php_']; + if(!Semver::satisfies(phpversion(), $require_php)) { + $php_satisfied = false; + } + } + else if(isset($require['php'])) { + $require_php = $require['php']; + if(version_compare(phpversion(), $require_php, '<')) { + $php_satisfied = false; + } } - if(isset($plugin_json['require'])) { - $require = $plugin_json['require']; + if(!$php_satisfied) { + self::$error = "Your PHP version doesn't meet the requirement of this plugin. Required version is: " . $require_php . ", and you're using version " . phpversion() . "."; + $continue = false; + } - $myaac_satified = true; - if(isset($require['myaac_'])) { - $require_myaac = $require['myaac_']; - if(!Semver::satisfies(MYAAC_VERSION, $require_myaac)) { - $myaac_satified = false; + $database_satisfied = true; + if(isset($require['database_'])) { + $require_database = $require['database_']; + if(!Semver::satisfies(DATABASE_VERSION, $require_database)) { + $database_satisfied = false; + } + } + else if(isset($require['database'])) { + $require_database = $require['database']; + if(version_compare(DATABASE_VERSION, $require_database, '<')) { + $database_satisfied = false; + } + } + + if(!$database_satisfied) { + self::$error = "Your database version doesn't meet the requirement of this plugin. Required version is: " . $require_database . ", and you're using version " . DATABASE_VERSION . "."; + $continue = false; + } + + if($continue) { + foreach($require as $req => $version) { + $req = strtolower(trim($req)); + $version = trim($version); + + if(in_array($req, array('myaac', 'myaac_', 'php', 'php_', 'database', 'database_'))) { + continue; } - } - else if(isset($require['myaac'])) { - $require_myaac = $require['myaac']; - if(version_compare(MYAAC_VERSION, $require_myaac, '<')) { - $myaac_satified = false; - } - } - if(!$myaac_satified) { - self::$error = "Your AAC version doesn't meet the requirement of this plugin. Required version is: " . $require_myaac . ", and you're using version " . MYAAC_VERSION . "."; - return false; - } + if(in_array($req, array('php-ext', 'php-extension'))) { // require php extension + $tmpDisplayError = false; + $explode = explode(',', $version); - $php_satisfied = true; - if(isset($require['php_'])) { - $require_php = $require['php_']; - if(!Semver::satisfies(phpversion(), $require_php)) { - $php_satisfied = false; - } - } - else if(isset($require['php'])) { - $require_php = $require['php']; - if(version_compare(phpversion(), $require_php, '<')) { - $php_satisfied = false; - } - } - - if(!$php_satisfied) { - self::$error = "Your PHP version doesn't meet the requirement of this plugin. Required version is: " . $require_php . ", and you're using version " . phpversion() . "."; - $continue = false; - } - - $database_satisfied = true; - if(isset($require['database_'])) { - $require_database = $require['database_']; - if(!Semver::satisfies(DATABASE_VERSION, $require_database)) { - $database_satisfied = false; - } - } - else if(isset($require['database'])) { - $require_database = $require['database']; - if(version_compare(DATABASE_VERSION, $require_database, '<')) { - $database_satisfied = false; - } - } - - if(!$database_satisfied) { - self::$error = "Your database version doesn't meet the requirement of this plugin. Required version is: " . $require_database . ", and you're using version " . DATABASE_VERSION . "."; - $continue = false; - } - - if($continue) { - foreach($require as $req => $version) { - $req = strtolower(trim($req)); - $version = trim($version); - - if(in_array($req, array('myaac', 'myaac_', 'php', 'php_', 'database', 'database_'))) { - continue; + foreach ($explode as $item) { + if(!extension_loaded($item)) { + $errors[] = "This plugin requires php extension: " . $item . " to be installed."; + $tmpDisplayError = true; + } } - if(in_array($req, array('php-ext', 'php-extension'))) { // require php extension - $tmpDisplayError = false; - $explode = explode(',', $version); - - foreach ($explode as $item) { - if(!extension_loaded($item)) { - $errors[] = "This plugin requires php extension: " . $item . " to be installed."; - $tmpDisplayError = true; - } - } - - if ($tmpDisplayError) { - self::$error = implode('
    ', $errors); - $continue = false; - break; - } - } - else if($req == 'table') { - $tmpDisplayError = false; - $explode = explode(',', $version); - foreach ($explode as $item) { - if(!$db->hasTable($item)) { - $errors[] = "This plugin requires table: " . $item . " to exist in the database."; - $tmpDisplayError = true; - } - } - - if ($tmpDisplayError) { - self::$error = implode('
    ', $errors); - $continue = false; - break; - } - } - else if($req == 'column') { - $tmpDisplayError = false; - $explode = explode(',', $version); - foreach ($explode as $item) { - $tmp = explode('.', $item); - - if(count($tmp) == 2) { - if(!$db->hasColumn($tmp[0], $tmp[1])) { - $errors[] = "This plugin requires database column: " . $tmp[0] . "." . $tmp[1] . " to exist in database."; - $tmpDisplayError = true; - } - } - else { - self::$warnings[] = "Invalid plugin require column: " . $item; - } - } - - if ($tmpDisplayError) { - self::$error = implode('
    ', $errors); - $continue = false; - break; - } - } - else if(strpos($req, 'ext-') !== false) { - $tmp = explode('-', $req); - if(count($tmp) == 2) { - if(!extension_loaded($tmp[1]) || !Semver::satisfies(phpversion($tmp[1]), $version)) { - self::$error = "This plugin requires php extension: " . $tmp[1] . ", version " . $version . " to be installed."; - $continue = false; - break; - } - } - } - else if(!self::is_installed($req, $version)) { - self::$error = "This plugin requires another plugin to run correctly. The another plugin is: " . $req . ", with version " . $version . "."; + if ($tmpDisplayError) { + self::$error = implode('
    ', $errors); $continue = false; break; } } - } - } + else if($req == 'table') { + $tmpDisplayError = false; + $explode = explode(',', $version); + foreach ($explode as $item) { + if(!$db->hasTable($item)) { + $errors[] = "This plugin requires table: " . $item . " to exist in the database."; + $tmpDisplayError = true; + } + } - if($continue) { - if(!$zip->extractTo(BASE)) { // "Real" Install - self::$error = 'There was a problem with extracting zip archive to base directory.'; - $zip->close(); - return false; - } - - $install = $plugin_json['install'] ?? ''; - if (self::getAutoLoadOption($plugin_json, 'install', true) && is_file(PLUGINS . $pluginFilename . '/install.php')) { - $install = 'plugins/' . $pluginFilename . '/install.php'; - } - - if (!empty($install)) { - if (file_exists(BASE . $install)) { - $db->revalidateCache(); - require BASE . $install; - $db->revalidateCache(); + if ($tmpDisplayError) { + self::$error = implode('
    ', $errors); + $continue = false; + break; + } } - else { - self::$warnings[] = 'Cannot load install script. Your plugin might be not working correctly.'; + else if($req == 'column') { + $tmpDisplayError = false; + $explode = explode(',', $version); + foreach ($explode as $item) { + $tmp = explode('.', $item); + + if(count($tmp) == 2) { + if(!$db->hasColumn($tmp[0], $tmp[1])) { + $errors[] = "This plugin requires database column: " . $tmp[0] . "." . $tmp[1] . " to exist in database."; + $tmpDisplayError = true; + } + } + else { + self::$warnings[] = "Invalid plugin require column: " . $item; + } + } + + if ($tmpDisplayError) { + self::$error = implode('
    ', $errors); + $continue = false; + break; + } + } + else if(strpos($req, 'ext-') !== false) { + $tmp = explode('-', $req); + if(count($tmp) == 2) { + if(!extension_loaded($tmp[1]) || !Semver::satisfies(phpversion($tmp[1]), $version)) { + self::$error = "This plugin requires php extension: " . $tmp[1] . ", version " . $version . " to be installed."; + $continue = false; + break; + } + } + } + else if(!self::is_installed($req, $version)) { + self::$error = "This plugin requires another plugin to run correctly. The another plugin is: " . $req . ", with version " . $version . "."; + $continue = false; + break; } } - - clearCache(); - - return true; } } - return false; + if(!$continue) { + return false; + } + + if(!$zip->extractTo(BASE)) { // "Real" Install + self::$error = 'There was a problem with extracting zip archive to base directory.'; + $zip->close(); + return false; + } + + $install = $plugin_json['install'] ?? ''; + if (self::getAutoLoadOption($plugin_json, 'install', true) && is_file(PLUGINS . $pluginFilename . '/install.php')) { + $install = 'plugins/' . $pluginFilename . '/install.php'; + } + + if (!empty($install)) { + if (file_exists(BASE . $install)) { + $db->revalidateCache(); + require BASE . $install; + $db->revalidateCache(); + } + else { + self::$warnings[] = 'Cannot load install script. Your plugin might be not working correctly.'; + } + } + + clearCache(); + return true; } public static function isEnabled($pluginFileName): bool From f17269e44ce9dd38447bd2e2a8e1bdb065d4161f Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 8 Jul 2025 14:22:51 +0200 Subject: [PATCH 109/222] Move admin bar code into body_start place_holder --- index.php | 9 --------- system/functions.php | 10 ++++++++++ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/index.php b/index.php index bf7069d4..ee8f7a87 100644 --- a/index.php +++ b/index.php @@ -162,15 +162,6 @@ if(setting('core.anonymous_usage_statistics')) { } } -/** - * @var OTS_Account $account_logged - */ -if ($logged && admin()) { - $content .= $twig->render('admin-bar.html.twig', [ - 'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId() - ]); -} - $title_full = (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName']; require $template_path . '/' . $template_index; diff --git a/system/functions.php b/system/functions.php index 540c9af3..7f54e69f 100644 --- a/system/functions.php +++ b/system/functions.php @@ -512,6 +512,16 @@ function template_place_holder($type): string } elseif ($type === 'body_start') { $ret .= $twig->render('browsehappy.html.twig'); + + /** + * @var OTS_Account $account_logged + */ + if (admin()) { + global $account_logged; + $ret .= $twig->render('admin-bar.html.twig', [ + 'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId() + ]); + } } elseif($type === 'body_end') { $ret .= template_ga_code(); From 36ca755243ef1c83f6ac87465b426d4d8d3b0bb9 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 8 Jul 2025 14:28:48 +0200 Subject: [PATCH 110/222] New setting: Display Skills Box on highscores Better space management --- system/settings.php | 6 ++++++ system/templates/highscores.html.twig | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/system/settings.php b/system/settings.php index 40c8be03..fb5c0301 100644 --- a/system/settings.php +++ b/system/settings.php @@ -1062,6 +1062,12 @@ Sent by MyAAC,
    'desc' => 'How often to update highscores from database in minutes. Too low may slow down your website.
    0 to disable.', 'default' => 15, ], + 'highscores_skills_box' => [ + 'name' => 'Display Skills Box', + 'type' => 'boolean', + 'desc' => 'show "Choose a skill" box on the highscores (allowing peoples to sort highscores by skill)?', + 'default' => true, + ], 'highscores_vocation_box' => [ 'name' => 'Display Vocation Box', 'type' => 'boolean', diff --git a/system/templates/highscores.html.twig b/system/templates/highscores.html.twig index 86599b90..3e85cf5d 100644 --- a/system/templates/highscores.html.twig +++ b/system/templates/highscores.html.twig @@ -94,8 +94,10 @@ {% endif %}
    {{ include('buttons.back.html.twig') }} From dca904e61d21d856bf809070e7652803a2df0f58 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 15 Jun 2025 19:05:19 +0200 Subject: [PATCH 085/222] Add missing csrf() --- templates/tibiacom/success.html.twig | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/tibiacom/success.html.twig b/templates/tibiacom/success.html.twig index 4aac4acb..c87a1971 100644 --- a/templates/tibiacom/success.html.twig +++ b/templates/tibiacom/success.html.twig @@ -35,6 +35,7 @@
    + {{ csrf() }} {{ include('buttons.back.html.twig') }} - diff --git a/system/templates/account.characters.change-comment.html.twig b/system/templates/account.characters.change-comment.html.twig index 8bb94c80..ab8fb384 100644 --- a/system/templates/account.characters.change-comment.html.twig +++ b/system/templates/account.characters.change-comment.html.twig @@ -88,7 +88,7 @@ If you do not want to specify a certain field, just leave it blank.

    +
    {{ csrf() }} @@ -40,14 +40,14 @@ Please enter your password and the new email address. Make sure that you enter a
    - - {{ csrf() }} - - + - - + + +
    +
    + + {{ csrf() }} {{ include('buttons.back.html.twig') }} -
    - + +
    + {{ include('buttons.submit.html.twig') }} @@ -99,15 +99,15 @@ If you do not want to specify a certain field, just leave it blank.

    - - {{ csrf() }} - - + - - -
    +
    + + {{ csrf() }} {{ include('buttons.back.html.twig') }} -
    + +
    diff --git a/system/templates/account.characters.delete.html.twig b/system/templates/account.characters.delete.html.twig index 8593f7ed..b946d221 100644 --- a/system/templates/account.characters.delete.html.twig +++ b/system/templates/account.characters.delete.html.twig @@ -24,7 +24,7 @@ To delete a character enter the name of the character and your password.

    - diff --git a/system/templates/success.html.twig b/system/templates/success.html.twig index eaee1fb1..3c69dad6 100644 --- a/system/templates/success.html.twig +++ b/system/templates/success.html.twig @@ -18,14 +18,14 @@ {% else %}
    +
    {{ csrf() }} @@ -36,14 +36,14 @@ To delete a character enter the name of the character and your password.

    - - {{ csrf() }} - - + - - + + +
    +
    + + {{ csrf() }} {{ include('buttons.back.html.twig') }} -
    - - {{ csrf() }} - - + - - + + +
    +
    + + {{ csrf() }} {{ include('buttons.back.html.twig') }} -
    {% endif %} From c720ccc451ff90ef40b2a1595468d061ffd7e1e4 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 15 Jun 2025 19:35:12 +0200 Subject: [PATCH 087/222] Add missing csrf() --- system/pages/account/change-email.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/pages/account/change-email.php b/system/pages/account/change-email.php index 857623f9..6dc8d388 100644 --- a/system/pages/account/change-email.php +++ b/system/pages/account/change-email.php @@ -166,7 +166,7 @@ if(isset($_POST['emailchangecancel']) && $_POST['emailchangecancel'] == 1) { $account_logged->setCustomField("email_new", ""); $account_logged->setCustomField("email_new_time", 0); - $custom_buttons = '
    ' . $twig->render('buttons.back.html.twig') . '
    '; + $custom_buttons = '
    ' . csrf(true) . '
    ' . $twig->render('buttons.back.html.twig') . '
    '; $twig->display('success.html.twig', array( 'title' => 'Email Address Change Cancelled', From b329da52aae9d0e21120a6444d3caf442420ce50 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 17 Jun 2025 17:52:23 +0200 Subject: [PATCH 088/222] Use apcu_clear_cache --- system/functions.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/system/functions.php b/system/functions.php index 6e58ca9d..56cf378b 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1263,6 +1263,10 @@ function clearCache() global $db; $db->setClearCacheAfter(true); + + if (function_exists('apcu_clear_cache')) { + apcu_clear_cache(); + } } deleteDirectory(CACHE . 'signatures', ['index.html'], true); From 0ea247ce7e8d28c4386f63411c2b928628e1daa0 Mon Sep 17 00:00:00 2001 From: Slawomir Boczek Date: Thu, 19 Jun 2025 16:46:22 +0200 Subject: [PATCH 089/222] Feature/plugins versions check (#310) * Check plugins versions from plugins.my-aac.org/api * Improve plugin update check messaging Updated the success message when checking for plugin updates to clarify the source. Added an informational message when outdated plugins are found to improve user feedback. * Use configurable API URI for plugin updates Replaces hardcoded plugin API URI with a configurable value from config, defaulting to the official API. Also fixes a typo in the success message. --- admin/pages/plugins.php | 50 ++ composer.json | 3 +- composer.lock | 537 +++++++++++++++++- system/src/Admin/Plugins.php | 49 ++ system/templates/admin.plugins.form.html.twig | 4 +- .../admin.plugins.outdated.html.twig | 18 + 6 files changed, 655 insertions(+), 6 deletions(-) create mode 100644 system/src/Admin/Plugins.php create mode 100644 system/templates/admin.plugins.outdated.html.twig diff --git a/admin/pages/plugins.php b/admin/pages/plugins.php index db886635..82f8309c 100644 --- a/admin/pages/plugins.php +++ b/admin/pages/plugins.php @@ -51,6 +51,56 @@ else { } else { error('Error while disabling plugin ' . $disable . ': ' . Plugins::getError()); } + } + else if (isset($_GET['check-updates'])) { + $repoUri = $config['admin_plugins_api_uri'] ?? 'https://plugins.my-aac.org/api/'; + success("Fetching latest info from $repoUri.."); + + $adminPlugins = new \MyAAC\Admin\Plugins(); + + $adminPlugins->setApiBaseUri($repoUri); + + try { + $plugins = $adminPlugins->getLatestVersions(); + } + catch (Exception $e) { + error($e->getMessage()); + } + + if (isset($plugins) && count($plugins) > 0) { + $outdated = []; + + foreach (get_plugins(true) as $plugin) { + $string = file_get_contents(BASE . 'plugins/' . $plugin . '.json'); + $plugin_info = json_decode($string, true); + + if (!$plugin_info) { + continue; + } + + $disabled = (str_contains($plugin, 'disabled.')); + $pluginOriginal = ($disabled ? str_replace('disabled.', '', $plugin) : $plugin); + + $info = $plugins[$pluginOriginal] ?? false; + if ($info && version_compare($info['version'], $plugin_info['version'], '>')) { + $outdated[] = [ + 'name' => $pluginOriginal, + 'yourVersion' => $plugin_info['version'], + 'latestVersion' => $info['version'], + 'link' => $info['link'] ?? 'Unknown', + 'download_link' => $info['download_link'] ?? 'Unknown', + ]; + } + } + + if (count($outdated) > 0) { + info('Following updates have been found for your plugins:'); + $twig->display('admin.plugins.outdated.html.twig', ['plugins' => $outdated]); + } + else { + success('All plugins up to date!'); + } + } } else if (isset($_FILES['plugin']['name'])) { $file = $_FILES['plugin']; $filename = $file['name']; diff --git a/composer.json b/composer.json index a150c7a3..fd7e5a44 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,8 @@ "symfony/string": "^6.4", "symfony/var-dumper": "^6.4", "filp/whoops": "^2.15", - "maximebf/debugbar": "1.*" + "maximebf/debugbar": "1.*", + "guzzlehttp/guzzle": "7.9.3" }, "require-dev": { "phpstan/phpstan": "^1.10" diff --git a/composer.lock b/composer.lock index 3a484492..9c831948 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "be4d1489a53a9cd8eec6bcaa7a096f30", + "content-hash": "5317e97a5025ebc2a977214bd3fa964c", "packages": [ { "name": "brick/math", @@ -493,6 +493,331 @@ ], "time": "2024-09-25T12:00:00+00:00" }, + { + "name": "guzzlehttp/guzzle", + "version": "7.9.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "guzzle/client-integration-tests": "3.0.2", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.9.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2025-03-27T13:37:11+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c", + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.2.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2025-03-27T13:27:01+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.7.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.7.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2025-03-27T12:30:47+00:00" + }, { "name": "illuminate/collections", "version": "v10.48.25", @@ -1472,6 +1797,166 @@ }, "time": "2021-11-05T16:47:00+00:00" }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, { "name": "psr/log", "version": "3.0.2", @@ -1573,6 +2058,50 @@ }, "time": "2021-10-29T13:26:27+00:00" }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, { "name": "symfony/console", "version": "v6.4.17", @@ -2910,7 +3439,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -2921,6 +3450,6 @@ "ext-xml": "*", "ext-dom": "*" }, - "platform-dev": [], - "plugin-api-version": "2.3.0" + "platform-dev": {}, + "plugin-api-version": "2.6.0" } diff --git a/system/src/Admin/Plugins.php b/system/src/Admin/Plugins.php new file mode 100644 index 00000000..f7b781f2 --- /dev/null +++ b/system/src/Admin/Plugins.php @@ -0,0 +1,49 @@ + $this->api_base_uri, + // You can set any number of default request options. + 'timeout' => 3.0, + ]); + + $plugins = get_plugins(true); + foreach ($plugins as &$plugin) { + if (str_contains($plugin, 'disabled.')) { + $plugin = str_replace('disabled.', '', $plugin); + } + } + + try { + $response = $client->get('get-latest-versions', [ + 'json' => ['plugins' => $plugins], + ]); + } + catch (\Exception $e) { + error('API Error. Please try again later.'); + return []; + } + + $statusCode = $response->getStatusCode(); + if ($statusCode != 200) { + throw new \Exception('Error getting info from plugins repository. Please try again later.'); + } + + $data = $response->getBody(); + return json_decode($data, true); + } + + public function setApiBaseUri(string $uri): void { + $this->api_base_uri = $uri; + } +} diff --git a/system/templates/admin.plugins.form.html.twig b/system/templates/admin.plugins.form.html.twig index aec82a8a..f8eddd41 100644 --- a/system/templates/admin.plugins.form.html.twig +++ b/system/templates/admin.plugins.form.html.twig @@ -1,7 +1,9 @@
    -
    Install plugin
    +
    Install plugin + Check for updates +
    {{ csrf() }} diff --git a/system/templates/admin.plugins.outdated.html.twig b/system/templates/admin.plugins.outdated.html.twig new file mode 100644 index 00000000..d587204e --- /dev/null +++ b/system/templates/admin.plugins.outdated.html.twig @@ -0,0 +1,18 @@ + + + + + + + + + + {% for plugin in plugins %} + + + + + + + {% endfor %} +
    Plugin NameYour VersionLatest VersionDownload link
    {{ plugin.name }}{{ plugin.yourVersion }}{{ plugin.latestVersion }}{{ plugin.download_link }}
    From 0f48f12e2e3112acab4bc2b6ab766ee6dbf7a9a5 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 19 Jun 2025 18:53:11 +0200 Subject: [PATCH 090/222] Update admin.plugins.outdated.html.twig --- system/templates/admin.plugins.outdated.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/templates/admin.plugins.outdated.html.twig b/system/templates/admin.plugins.outdated.html.twig index d587204e..95421edc 100644 --- a/system/templates/admin.plugins.outdated.html.twig +++ b/system/templates/admin.plugins.outdated.html.twig @@ -4,7 +4,7 @@
    Plugin Name Your Version Latest VersionDownload linkDownload Link
    + {% if setting('core.highscores_skills_box') %} @@ -109,7 +111,8 @@
    Choose a skill

    - {% if config.highscores_vocation_box %} + {% endif %} + {% if setting('core.highscores_vocation_box') %} @@ -126,5 +129,6 @@ {% endif %} + {% endif %}
    Choose a vocation
    From f0f2e3785f7b46d813f38cb6c1be3e1e6152c3e4 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 8 Jul 2025 15:44:45 +0200 Subject: [PATCH 111/222] Fix phpstan --- system/functions.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/system/functions.php b/system/functions.php index 7f54e69f..d1351f35 100644 --- a/system/functions.php +++ b/system/functions.php @@ -513,9 +513,6 @@ function template_place_holder($type): string elseif ($type === 'body_start') { $ret .= $twig->render('browsehappy.html.twig'); - /** - * @var OTS_Account $account_logged - */ if (admin()) { global $account_logged; $ret .= $twig->render('admin-bar.html.twig', [ From 2fe9924437c93b2363574af5e83e7192b6917ed5 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 8 Jul 2025 19:20:45 +0200 Subject: [PATCH 112/222] Start 1.7.2-dev --- common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.php b/common.php index 94395409..7d8a905d 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.7.1'; +const MYAAC_VERSION = '1.7.2-dev'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From ec11c1402417c25980582467546d1c1e9bb8267f Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 19 Jul 2025 07:48:01 +0200 Subject: [PATCH 113/222] kathrine: possibility to add custom menu categories --- templates/kathrine/config.php | 20 ++++++++++----- templates/kathrine/javascript.php | 38 +++++++++++++--------------- templates/kathrine/menu.js.html.twig | 8 +++--- templates/kathrine/style.css | 6 +++-- templates/kathrine/template.php | 21 ++++++++++++--- 5 files changed, 57 insertions(+), 36 deletions(-) diff --git a/templates/kathrine/config.php b/templates/kathrine/config.php index 63847317..52835ff4 100644 --- a/templates/kathrine/config.php +++ b/templates/kathrine/config.php @@ -1,12 +1,18 @@ array('id' => 'news', 'name' => 'Latest News'), - MENU_CATEGORY_ACCOUNT => array('id' => 'account', 'name' => 'Account'), - MENU_CATEGORY_COMMUNITY => array('id' => 'community', 'name' => 'Community'), - MENU_CATEGORY_LIBRARY => array('id' => 'library', 'name' => 'Library'), - MENU_CATEGORY_SHOP => array('id' => 'shops', 'name' => 'Shop') -); +// max 7 menus for kathrine +$config['menu_categories'] = [ + MENU_CATEGORY_NEWS => ['id' => 'news', 'name' => 'Latest News'], + // you can add custom menu by uncommenting this + // after doing it, go to admin panel -> Menus and add your entries for this category + // tip: you can move it up/down to show it on specific position + //7 => array('id' => 'testing', 'name' => 'Test Menu 1'), + //8 => array('id' => 'testing2', 'name' => 'Test Menu 2'), + MENU_CATEGORY_ACCOUNT => ['id' => 'account', 'name' => 'Account'], + MENU_CATEGORY_COMMUNITY => ['id' => 'community', 'name' => 'Community'], + MENU_CATEGORY_LIBRARY => ['id' => 'library', 'name' => 'Library'], + MENU_CATEGORY_SHOP => ['id' => 'shops', 'name' => 'Shop'] +]; $config['menus'] = require __DIR__ . '/menus.php'; diff --git a/templates/kathrine/javascript.php b/templates/kathrine/javascript.php index a092b7c2..32fcf53d 100644 --- a/templates/kathrine/javascript.php +++ b/templates/kathrine/javascript.php @@ -1,42 +1,40 @@ -var category = ' $info) { + $templatePages = get_template_pages($id); + + if ($id == MENU_CATEGORY_ACCOUNT) { + $templatePages = array_merge($templatePages, ['account']); + } + + if (in_array($tmp[0], $templatePages)) { + echo $info['id']; + break; + } } ?>'; diff --git a/templates/kathrine/menu.js.html.twig b/templates/kathrine/menu.js.html.twig index adf7ceb0..ae8ad3bf 100644 --- a/templates/kathrine/menu.js.html.twig +++ b/templates/kathrine/menu.js.html.twig @@ -1,10 +1,10 @@ var list = new Array(); {% set i = 0 %} -{% for cat in categories %} - {% if cat.id != 'shops' or setting('core.gifts_system') %} - list[{{ i }}] = '{{ cat.id }}'; +{% for id, cat in config('menu_categories') %} + {% if (cat.id != 'shops' or setting('core.gifts_system')) and menus[id]|length > 0 %} + list[{{ i }}] = '{{ cat.id }}'; + {% set i = i + 1 %} {% endif %} -{% set i = i + 1 %} {% endfor %} function initMenu() diff --git a/templates/kathrine/style.css b/templates/kathrine/style.css index 45a1a9d4..cc212685 100644 --- a/templates/kathrine/style.css +++ b/templates/kathrine/style.css @@ -27,11 +27,13 @@ body #tabs { - width: 580px; + width: 99%; height: 32px; background: url('images/tabs-bg.png') no-repeat; - float: left; padding-left: 200px; + position: relative; + display: inline-flex; + right: 0; } #tabs .tab diff --git a/templates/kathrine/template.php b/templates/kathrine/template.php index af03b3c9..ffa2195a 100644 --- a/templates/kathrine/template.php +++ b/templates/kathrine/template.php @@ -8,7 +8,9 @@ defined('MYAAC') or die('Direct access not allowed!'); @@ -28,11 +30,24 @@ defined('MYAAC') or die('Direct access not allowed!'); + + 6) { + $tabsStyle .= 'padding-left: 4px;'; + $tabsStyle .= 'padding-right: 12px;'; + } + elseif ($menusCount > 5) { + $tabsStyle .= 'padding-left: 90px;'; + } + ?> + -
    +
    $cat) { - if($id != MENU_CATEGORY_SHOP || $config['gifts_system']) { ?> + if (($id != MENU_CATEGORY_SHOP || $config['gifts_system']) && isset($menus[$id])) { ?> Date: Sat, 19 Jul 2025 10:05:25 +0200 Subject: [PATCH 114/222] Allow for timestamp as integer in the timeago twig function --- system/twig.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/system/twig.php b/system/twig.php index f59230e3..baeae276 100644 --- a/system/twig.php +++ b/system/twig.php @@ -36,7 +36,11 @@ $twig->addExtension(new MyAAC\Twig\Extension\TypeCastingExtension()); $filter = new TwigFilter('timeago', function ($datetime) { - $time = time() - strtotime($datetime); + if (!is_int($datetime)) { + $datetime = strtotime($datetime); + } + + $time = time() - $datetime; $units = array ( 31536000 => 'year', From 83f84172e02e8ea2ccb6dca29bc033e44c35aebc Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 19 Jul 2025 11:16:03 +0200 Subject: [PATCH 115/222] Add warning about APCu clear in CLI Adds a warning message if attempting to clear APCu cache from the CLI, as this is not supported. Users are advised to use the Admin Panel for clearing APCu cache outside of development environments. --- system/src/Commands/CacheClearCommand.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/system/src/Commands/CacheClearCommand.php b/system/src/Commands/CacheClearCommand.php index 5b1715b5..ac899655 100644 --- a/system/src/Commands/CacheClearCommand.php +++ b/system/src/Commands/CacheClearCommand.php @@ -2,6 +2,7 @@ namespace MyAAC\Commands; +use MyAAC\Cache\Cache; use MyAAC\Hooks; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -26,6 +27,15 @@ class CacheClearCommand extends Command return Command::FAILURE; } + $cache = Cache::getInstance(); + + $cacheEngine = config('cache_engine') == 'auto' ? + Cache::detect() : config('cache_engine'); + + if (config('env') !== 'dev' && $cacheEngine == 'apcu') { + $io->warning('APCu cache cannot be cleared in CLI. Please visit the Admin Panel and clear there.'); + } + $io->success('Cache cleared'); return Command::SUCCESS; } From ce5b1cf2a665a636bad51966b80527e2ca3381ca Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 19 Jul 2025 11:16:55 +0200 Subject: [PATCH 116/222] Update CacheClearCommand.php --- system/src/Commands/CacheClearCommand.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/system/src/Commands/CacheClearCommand.php b/system/src/Commands/CacheClearCommand.php index ac899655..5f9bae0b 100644 --- a/system/src/Commands/CacheClearCommand.php +++ b/system/src/Commands/CacheClearCommand.php @@ -27,8 +27,6 @@ class CacheClearCommand extends Command return Command::FAILURE; } - $cache = Cache::getInstance(); - $cacheEngine = config('cache_engine') == 'auto' ? Cache::detect() : config('cache_engine'); From 5271633bdbfbbfed0b1d59c403093ce6fc2b7d20 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 19 Jul 2025 15:00:17 +0200 Subject: [PATCH 117/222] Account -> isPremium -> ignore config.freePremium --- system/libs/pot/OTS_Account.php | 9 +++------ system/src/Models/Account.php | 9 +++------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/system/libs/pot/OTS_Account.php b/system/libs/pot/OTS_Account.php index 8528cf3f..20c7fe32 100644 --- a/system/libs/pot/OTS_Account.php +++ b/system/libs/pot/OTS_Account.php @@ -473,12 +473,9 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable public function isPremium() { - global $config; - if(isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium'])) return true; - - if(isset($this->data['premium_ends_at'])) { - return $this->data['premium_ends_at'] > time(); - } + if(isset($this->data['premium_ends_at'])) { + return $this->data['premium_ends_at'] > time(); + } if(isset($this->data['premend'])) { return $this->data['premend'] > time(); diff --git a/system/src/Models/Account.php b/system/src/Models/Account.php index b11c2a48..f0bd435f 100644 --- a/system/src/Models/Account.php +++ b/system/src/Models/Account.php @@ -53,12 +53,9 @@ class Account extends Model { public function getIsPremiumAttribute() { - global $config; - if(isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium'])) return true; - - if(isset($this->premium_ends_at)) { - return $this->premium_ends_at > time(); - } + if(isset($this->premium_ends_at)) { + return $this->premium_ends_at > time(); + } if(isset($this->premend)) { return $this->premend > time(); From 536b29be950a1108d0f7e4b16db9d096880eb6cd Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 19 Jul 2025 15:11:09 +0200 Subject: [PATCH 118/222] That is duplicated --- admin/pages/accounts.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/admin/pages/accounts.php b/admin/pages/accounts.php index 0358753b..c1b90eac 100644 --- a/admin/pages/accounts.php +++ b/admin/pages/accounts.php @@ -243,9 +243,6 @@ else if (isset($_REQUEST['search'])) { $password = encrypt($password); $account->setPassword($password); - - if (USE_ACCOUNT_SALT) - $account->setCustomField('salt', $salt); } $account->save(); From 1566deb84a082176b8c683fda205d828bc38fbcc Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 19 Jul 2025 15:46:51 +0200 Subject: [PATCH 119/222] Add getExperienceForLevel (level) --- system/functions.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/system/functions.php b/system/functions.php index d1351f35..8859d36f 100644 --- a/system/functions.php +++ b/system/functions.php @@ -774,6 +774,10 @@ function formatExperience($exp, $color = true) return $ret; } +function getExperienceForLevel($level): float|int { + return ( 50 / 3 ) * pow( $level, 3 ) - ( 100 * pow( $level, 2 ) ) + ( ( 850 / 3 ) * $level ) - 200; +} + function get_locales() { $ret = array(); From d8132d4d76e03d5aa0c042be426320655a601392 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 22 Jul 2025 18:18:29 +0200 Subject: [PATCH 120/222] Highscores revamp a bit * Show real rank, if 2 or more players have the same skill, show them with same rank * New setting: highscores_online_status * Additional fields passed to twig: updatedAt, totalResults, page, baseLink --- system/pages/highscores.php | 52 +++++++++++++++++++++------ system/settings.php | 6 ++++ system/templates/highscores.html.twig | 2 +- 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/system/pages/highscores.php b/system/pages/highscores.php index 6deb842c..15ce8ef8 100644 --- a/system/pages/highscores.php +++ b/system/pages/highscores.php @@ -146,17 +146,24 @@ $cache = Cache::getInstance(); if ($cache->enabled() && $highscoresTTL > 0) { $tmp = ''; if ($cache->fetch($cacheKey, $tmp)) { - $highscores = unserialize($tmp); + $data = unserialize($tmp); + $totalResults = $data['totalResults']; + $highscores = $data['highscores']; + $updatedAt = $data['updatedAt']; $needReCache = false; } } $offset = ($page - 1) * $configHighscoresPerPage; -$query->join('accounts', 'accounts.id', '=', 'players.account_id') - ->withOnlineStatus() +$query->withOnlineStatus() ->whereNotIn('players.id', setting('core.highscores_ids_hidden')) ->notDeleted() - ->where('players.group_id', '<', setting('core.highscores_groups_hidden')) + ->where('players.group_id', '<', setting('core.highscores_groups_hidden')); + +$totalResultsQuery = clone $query; + +$query + ->join('accounts', 'accounts.id', '=', 'players.account_id') ->limit($limit) ->offset($offset) ->selectRaw('accounts.country, players.id, players.name, players.account_id, players.level, players.vocation' . $outfit . $promotion) @@ -215,17 +222,24 @@ if (empty($highscores)) { return $tmp; })->toArray(); + + $updatedAt = time(); + $totalResults = $totalResultsQuery->count(); } if ($highscoresTTL > 0 && $cache->enabled() && $needReCache) { - $cache->set($cacheKey, serialize($highscores), $highscoresTTL * 60); + $cache->set($cacheKey, serialize( + [ + 'totalResults' => $totalResults, + 'highscores' => $highscores, + 'updatedAt' => $updatedAt, + ] + ), $highscoresTTL * 60); } $show_link_to_next_page = false; $i = 0; -$settingHighscoresVocation = setting('core.highscores_vocation'); - foreach($highscores as $id => &$player) { if(++$i <= $configHighscoresPerPage) @@ -239,10 +253,22 @@ foreach($highscores as $id => &$player) $player['link'] = getPlayerLink($player['name'], false); $player['flag'] = getFlagImage($player['country']); - if($settingHighscoresOutfit) { - $player['outfit'] = ''; + $player['outfit'] = ''; + + if ($skill != POT::SKILL__LEVEL) { + if (isset($lastValue) && $lastValue == $player['value']) { + $player['rank'] = $lastRank; + } + else { + $player['rank'] = $offset + $i; + } + + $lastRank = $player['rank'] ; + $lastValue = $player['value']; + } + else { + $player['rank'] = $offset + $i; } - $player['rank'] = $offset + $i; } else { unset($highscores[$id]); @@ -263,6 +289,8 @@ if($show_link_to_next_page) { $linkNextPage = getLink('highscores') . '/' . $list . ($vocation !== 'all' ? '/' . $vocation : '') . '/' . ($page + 1); } +$baseLink = getLink('highscores') . '/' . $list . ($vocation !== 'all' ? '/' . $vocation : '') . '/'; + $types = array( 'experience' => 'Experience', 'magic' => 'Magic', @@ -297,4 +325,8 @@ $twig->display('highscores.html.twig', [ 'types' => $types, 'linkPreviousPage' => $linkPreviousPage, 'linkNextPage' => $linkNextPage, + 'totalResults' => $totalResults, + 'page' => $page, + 'baseLink' => $baseLink, + 'updatedAt' => $updatedAt, ]); diff --git a/system/settings.php b/system/settings.php index fb5c0301..d7c124c2 100644 --- a/system/settings.php +++ b/system/settings.php @@ -1080,6 +1080,12 @@ Sent by MyAAC,
    'desc' => 'Show player vocation under his nickname?', 'default' => true, ], + 'highscores_online_status' => [ + 'name' => 'Display Online Status', + 'type' => 'boolean', + 'desc' => 'Show player status as red (offline) or green (online)', + 'default' => false, + ], 'highscores_frags' => [ 'name' => 'Display Top Frags', 'type' => 'boolean', diff --git a/system/templates/highscores.html.twig b/system/templates/highscores.html.twig index 3e85cf5d..88bf579b 100644 --- a/system/templates/highscores.html.twig +++ b/system/templates/highscores.html.twig @@ -66,7 +66,7 @@
    - {{ player.name }} + {{ player.name }} {% if setting('core.highscores_vocation') %}
    {{ player.vocation }} From c06b0017f1ad50383fae127e4ea86d00e20360d6 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 22 Jul 2025 19:07:58 +0200 Subject: [PATCH 121/222] Update phpstan.neon --- phpstan.neon | 1 + 1 file changed, 1 insertion(+) diff --git a/phpstan.neon b/phpstan.neon index 020fa3a6..cb5cd4d3 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -28,6 +28,7 @@ parameters: - '#Variable \$guild might not be defined#' - '#Variable \$[a-zA-Z0-9\\_]+ might not be defined#' # Eloquent models + - '#Call to an undefined method [a-zA-Z0-9\\_]+::[a-zA-Z0-9\\_]+\(\)#' - '#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 From 9b6f41045988f081cfc34b6bf202b5e099c1dba5 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 22 Jul 2025 19:11:42 +0200 Subject: [PATCH 122/222] Update phpstan.neon --- phpstan.neon | 2 -- 1 file changed, 2 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index cb5cd4d3..68e1aa6a 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -30,9 +30,7 @@ parameters: # Eloquent models - '#Call to an undefined method [a-zA-Z0-9\\_]+::[a-zA-Z0-9\\_]+\(\)#' - '#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#' - From 7d27e5a0bace31f0df79ae45afdd9a0cbc4e7ac9 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 22 Jul 2025 21:32:51 +0200 Subject: [PATCH 123/222] New setting: Default Account Transferable Coins --- system/init.php | 12 ++++++++---- system/pages/account/create.php | 5 +++++ system/settings.php | 7 +++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/system/init.php b/system/init.php index 821ac440..b0c36c48 100644 --- a/system/init.php +++ b/system/init.php @@ -144,6 +144,14 @@ $ots = POT::getInstance(); $eloquentConnection = null; require_once SYSTEM . 'database.php'; +define('USE_ACCOUNT_NAME', $db->hasColumn('accounts', 'name')); +define('USE_ACCOUNT_NUMBER', $db->hasColumn('accounts', 'number')); +define('USE_ACCOUNT_SALT', $db->hasColumn('accounts', 'salt')); + +define('HAS_ACCOUNT_COINS_TRANSFERABLE', $db->hasColumn('accounts', 'coins_transferable')); +define('HAS_ACCOUNT_TRANSFERABLE_COINS', $db->hasColumn('accounts', 'transferable_coins')); +const ACCOUNT_COINS_TRANSFERABLE_COLUMN = (HAS_ACCOUNT_COINS_TRANSFERABLE ? 'coins_transferable' : 'transferable_coins'); + $twig->addGlobal('logged', false); $twig->addGlobal('account_logged', new \OTS_Account()); @@ -188,10 +196,6 @@ if($settingsItemImagesURL[strlen($settingsItemImagesURL) - 1] !== '/') { setting(['core.item_images_url', $settingsItemImagesURL . '/']); } -define('USE_ACCOUNT_NAME', $db->hasColumn('accounts', 'name')); -define('USE_ACCOUNT_NUMBER', $db->hasColumn('accounts', 'number')); -define('USE_ACCOUNT_SALT', $db->hasColumn('accounts', 'salt')); - $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(); diff --git a/system/pages/account/create.php b/system/pages/account/create.php index 947ad0ad..8967c8e1 100644 --- a/system/pages/account/create.php +++ b/system/pages/account/create.php @@ -231,6 +231,11 @@ if($save) $new_account->setCustomField('coins', $accountDefaultCoins); } + $accountDefaultCoinsTransferable = setting('core.account_coins_transferable'); + if((HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) && $accountDefaultCoinsTransferable > 0) { + $new_account->setCustomField(ACCOUNT_COINS_TRANSFERABLE_COLUMN, $accountDefaultCoinsTransferable); + } + $tmp_account = $email; if (!config('account_login_by_email')) { $tmp_account = (USE_ACCOUNT_NAME ? $account_name : $account_id); diff --git a/system/settings.php b/system/settings.php index d7c124c2..e0f1fdb6 100644 --- a/system/settings.php +++ b/system/settings.php @@ -697,6 +697,13 @@ Sent by MyAAC,
    'hidden' => ($db && !$db->hasColumn('accounts', 'coins')), 'default' => 0, ], + 'account_coins_transferable' => [ + 'name' => 'Default Account Transferable Coins', + 'type' => 'number', + 'desc' => 'Default transferable coins on new account', + 'hidden' => (!HAS_ACCOUNT_COINS_TRANSFERABLE && !HAS_ACCOUNT_TRANSFERABLE_COINS), + 'default' => 0, + ], 'account_mail_change' => [ 'name' => 'Account Mail Change Days', 'type' => 'number', From bccf8e056df985bbe1bab5f7ab5492f714d6b62b Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 22 Jul 2025 21:33:45 +0200 Subject: [PATCH 124/222] Rewrite to use constants (account transferable coins) --- admin/pages/accounts.php | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/admin/pages/accounts.php b/admin/pages/accounts.php index c1b90eac..35543b0a 100644 --- a/admin/pages/accounts.php +++ b/admin/pages/accounts.php @@ -28,12 +28,6 @@ $nameOrNumberColumn = getAccountIdentityColumn(); $hasSecretColumn = $db->hasColumn('accounts', 'secret'); $hasCoinsColumn = $db->hasColumn('accounts', 'coins'); -$hasCoinsTransferableColumn = $db->hasColumn('accounts', 'coins_transferable'); -$hasTransferableCoinsColumn = $db->hasColumn('accounts', 'transferable_coins'); -$coinsTransferableColumn = - $hasTransferableCoinsColumn ? - 'transferable_coins' : 'coins_transferable'; - $hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); $hasTypeColumn = $db->hasColumn('accounts', 'type'); $hasGroupColumn = $db->hasColumn('accounts', 'group_id'); @@ -150,7 +144,7 @@ else if (isset($_REQUEST['search'])) { } // transferable tibia coins - if ($hasCoinsTransferableColumn || $hasTransferableCoinsColumn) { + if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) { $t_coins_transferable = $_POST['t_coins_transferable']; verify_number($t_coins_transferable, 'Transferable Tibia coins', 12); } @@ -207,8 +201,8 @@ else if (isset($_REQUEST['search'])) { $account->setCustomField('coins', $t_coins); } - if ($hasCoinsTransferableColumn || $hasTransferableCoinsColumn) { - $account->setCustomField($coinsTransferableColumn, $t_coins_transferable); + if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) { + $account->setCustomField(ACCOUNT_COINS_TRANSFERABLE_COLUMN, $t_coins_transferable); } $lastDay = 0; @@ -418,10 +412,10 @@ else if (isset($_REQUEST['search'])) { - +
    - +
    From caf326a6584a234775ebc6c8000ea02b3fecd160 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 22 Jul 2025 21:44:09 +0200 Subject: [PATCH 125/222] Refactor to use HAS_ACCOUNT_COINS $db->hasColumn('accounts', 'coins') -> HAS_ACCOUNT_COINS --- admin/pages/accounts.php | 8 +++----- admin/pages/mass_account.php | 11 ++++------- admin/pages/modules/coins.php | 2 +- system/init.php | 1 + system/pages/account/create.php | 2 +- system/settings.php | 4 ++-- 6 files changed, 12 insertions(+), 16 deletions(-) diff --git a/admin/pages/accounts.php b/admin/pages/accounts.php index 35543b0a..2d9c1bbd 100644 --- a/admin/pages/accounts.php +++ b/admin/pages/accounts.php @@ -26,8 +26,6 @@ if (setting('core.account_country')) $nameOrNumberColumn = getAccountIdentityColumn(); $hasSecretColumn = $db->hasColumn('accounts', 'secret'); -$hasCoinsColumn = $db->hasColumn('accounts', 'coins'); - $hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); $hasTypeColumn = $db->hasColumn('accounts', 'type'); $hasGroupColumn = $db->hasColumn('accounts', 'group_id'); @@ -138,7 +136,7 @@ else if (isset($_REQUEST['search'])) { $errors['email'] = Validator::getLastError(); // tibia coins - if ($hasCoinsColumn) { + if (HAS_ACCOUNT_COINS) { $t_coins = $_POST['t_coins']; verify_number($t_coins, 'Tibia coins', 12); } @@ -197,7 +195,7 @@ else if (isset($_REQUEST['search'])) { $account->setCustomField('key', $key); $account->setEMail($email); - if ($hasCoinsColumn) { + if (HAS_ACCOUNT_COINS) { $account->setCustomField('coins', $t_coins); } @@ -406,7 +404,7 @@ else if (isset($_REQUEST['search'])) { getEMail() . '">Send Mail)' : ''); ?>
    - +
    diff --git a/admin/pages/mass_account.php b/admin/pages/mass_account.php index 46c9bc9d..6b1ccb46 100644 --- a/admin/pages/mass_account.php +++ b/admin/pages/mass_account.php @@ -18,7 +18,6 @@ $title = 'Mass Account Actions'; csrfProtect(); -$hasCoinsColumn = $db->hasColumn('accounts', 'coins'); $hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); $freePremium = $config['lua']['freePremium']; @@ -40,9 +39,7 @@ function admin_give_points($points) function admin_give_coins($coins) { - global $hasCoinsColumn; - - if (!$hasCoinsColumn) { + if (!HAS_ACCOUNT_COINS) { displayMessage('Coins not supported.'); return; } @@ -167,19 +164,19 @@ if (!empty(ACTION) && isRequestMethod('post')) { } else { $twig->display('admin.tools.account.html.twig', array( - 'hasCoinsColumn' => $hasCoinsColumn, + 'hasCoinsColumn' => HAS_ACCOUNT_COINS, 'hasPointsColumn' => $hasPointsColumn, 'freePremium' => $freePremium, )); } function displayMessage($message, $success = false) { - global $twig, $hasCoinsColumn, $hasPointsColumn, $freePremium; + global $twig, $hasPointsColumn, $freePremium; $success ? success($message): error($message); $twig->display('admin.tools.account.html.twig', array( - 'hasCoinsColumn' => $hasCoinsColumn, + 'hasCoinsColumn' => HAS_ACCOUNT_COINS, 'hasPointsColumn' => $hasPointsColumn, 'freePremium' => $freePremium, )); diff --git a/admin/pages/modules/coins.php b/admin/pages/modules/coins.php index 939ee16c..66ce0186 100644 --- a/admin/pages/modules/coins.php +++ b/admin/pages/modules/coins.php @@ -6,7 +6,7 @@ defined('MYAAC') or die('Direct access not allowed!'); $coins = 0; -if ($db->hasColumn('accounts', 'coins')) { +if (HAS_ACCOUNT_COINS) { $whatToGet = ['id', 'coins']; if (USE_ACCOUNT_NAME) { $whatToGet[] = 'name'; diff --git a/system/init.php b/system/init.php index b0c36c48..57c299ba 100644 --- a/system/init.php +++ b/system/init.php @@ -148,6 +148,7 @@ define('USE_ACCOUNT_NAME', $db->hasColumn('accounts', 'name')); define('USE_ACCOUNT_NUMBER', $db->hasColumn('accounts', 'number')); define('USE_ACCOUNT_SALT', $db->hasColumn('accounts', 'salt')); +define('HAS_ACCOUNT_COINS', $db->hasColumn('accounts', 'coins')); define('HAS_ACCOUNT_COINS_TRANSFERABLE', $db->hasColumn('accounts', 'coins_transferable')); define('HAS_ACCOUNT_TRANSFERABLE_COINS', $db->hasColumn('accounts', 'transferable_coins')); const ACCOUNT_COINS_TRANSFERABLE_COLUMN = (HAS_ACCOUNT_COINS_TRANSFERABLE ? 'coins_transferable' : 'transferable_coins'); diff --git a/system/pages/account/create.php b/system/pages/account/create.php index 8967c8e1..15f2b8b5 100644 --- a/system/pages/account/create.php +++ b/system/pages/account/create.php @@ -227,7 +227,7 @@ if($save) } $accountDefaultCoins = setting('core.account_coins'); - if($db->hasColumn('accounts', 'coins') && $accountDefaultCoins > 0) { + if(HAS_ACCOUNT_COINS && $accountDefaultCoins > 0) { $new_account->setCustomField('coins', $accountDefaultCoins); } diff --git a/system/settings.php b/system/settings.php index e0f1fdb6..c39c706a 100644 --- a/system/settings.php +++ b/system/settings.php @@ -694,7 +694,7 @@ Sent by MyAAC,
    'name' => 'Default Account Coins', 'type' => 'number', 'desc' => 'Default coins on new account', - 'hidden' => ($db && !$db->hasColumn('accounts', 'coins')), + 'hidden' => ($db && !HAS_ACCOUNT_COINS), 'default' => 0, ], 'account_coins_transferable' => [ @@ -1595,7 +1595,7 @@ Sent by MyAAC,
    'callbacks' => [ 'beforeSave' => function($key, $value, &$errorMessage) { global $db; - if ($value == 'coins' && !$db->hasColumn('accounts', 'coins')) { + if ($value == 'coins' && !HAS_ACCOUNT_COINS) { $errorMessage = "Shop: Donate Column: Cannot set column to coins, because it doesn't exist in database."; return false; } From 6e5a4ff8c78ff5373aba091baa66cae029557643 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 22 Jul 2025 21:49:05 +0200 Subject: [PATCH 126/222] Fix if setting found in db, but not found in plugins --- system/src/Settings.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/system/src/Settings.php b/system/src/Settings.php index ca4192ad..ef3da830 100644 --- a/system/src/Settings.php +++ b/system/src/Settings.php @@ -472,24 +472,22 @@ class Settings implements \ArrayAccess if (!isset($this->settingsFile[$pluginKeyName]['settings'])) { throw new \RuntimeException('Unknown plugin settings: ' . $pluginKeyName); } + return $this->settingsFile[$pluginKeyName]['settings']; } - $ret = []; - if(isset($this->settingsFile[$pluginKeyName]['settings'][$key])) { - $ret = $this->settingsFile[$pluginKeyName]['settings'][$key]; + if (!isset($this->settingsFile[$pluginKeyName]['settings'][$key])) { + return null; } + $ret = $this->settingsFile[$pluginKeyName]['settings'][$key]; + if(isset($this->settingsDatabase[$pluginKeyName][$key])) { $value = $this->settingsDatabase[$pluginKeyName][$key]; $ret['value'] = $value; } else { - if (!isset($this->settingsFile[$pluginKeyName]['settings'][$key])) { - return null; - } - $ret['value'] = $this->settingsFile[$pluginKeyName]['settings'][$key]['default']; } From bb097b69ce106500a49686d6f4fe604348eaa310 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 22 Jul 2025 22:06:32 +0200 Subject: [PATCH 127/222] Update settings.php --- system/settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/settings.php b/system/settings.php index c39c706a..ae61fd52 100644 --- a/system/settings.php +++ b/system/settings.php @@ -701,7 +701,7 @@ Sent by MyAAC,
    'name' => 'Default Account Transferable Coins', 'type' => 'number', 'desc' => 'Default transferable coins on new account', - 'hidden' => (!HAS_ACCOUNT_COINS_TRANSFERABLE && !HAS_ACCOUNT_TRANSFERABLE_COINS), + 'hidden' => ($db && !HAS_ACCOUNT_COINS_TRANSFERABLE && !HAS_ACCOUNT_TRANSFERABLE_COINS), 'default' => 0, ], 'account_mail_change' => [ From 2d4be327b278c01d27a935fcb48825c1fc94e0cc Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 24 Jul 2025 23:07:49 +0200 Subject: [PATCH 128/222] Fix if highscores show outfit disabled --- system/pages/highscores.php | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/system/pages/highscores.php b/system/pages/highscores.php index 15ce8ef8..cec95d15 100644 --- a/system/pages/highscores.php +++ b/system/pages/highscores.php @@ -123,16 +123,10 @@ if($db->hasColumn('players', 'promotion')) $promotion = ',players.promotion'; $outfit_addons = false; -$outfit = ''; - -$settingHighscoresOutfit = setting('core.highscores_outfit'); - -if($settingHighscoresOutfit) { - $outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype'; - if($db->hasColumn('players', 'lookaddons')) { - $outfit .= ', lookaddons'; - $outfit_addons = true; - } +$outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype'; +if($db->hasColumn('players', 'lookaddons')) { + $outfit .= ', lookaddons'; + $outfit_addons = true; } $configHighscoresPerPage = setting('core.highscores_per_page'); From 20d69a641c0a933d14889a89da6d32f6a4bc6c7d Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 24 Jul 2025 23:30:28 +0200 Subject: [PATCH 129/222] Fix exception if setting not found --- system/functions.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/functions.php b/system/functions.php index 8859d36f..8c365391 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1228,7 +1228,8 @@ function setting($key) return $settings[$key[0]] = $key[1]; } - return $settings[$key]['value']; + $ret = $settings[$key]; + return isset($ret) ? $ret['value'] : null; } function clearCache() From 080cc2781f034c844af658229e495e9a47fd2298 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 31 Jul 2025 07:31:15 +0200 Subject: [PATCH 130/222] Fix mailer: send to email link from accounts page --- admin/pages/mailer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/pages/mailer.php b/admin/pages/mailer.php index 1f8d3188..f57be2d9 100644 --- a/admin/pages/mailer.php +++ b/admin/pages/mailer.php @@ -25,7 +25,7 @@ if (!setting('core.mail_enabled')) { return; } -$mail_to = isset($_POST['mail_to']) ? stripslashes(trim($_POST['mail_to'])) : null; +$mail_to = isset($_REQUEST['mail_to']) ? stripslashes(trim($_REQUEST['mail_to'])) : null; $mail_subject = isset($_POST['mail_subject']) ? stripslashes($_POST['mail_subject']) : null; $mail_content = isset($_POST['mail_content']) ? stripslashes($_POST['mail_content']) : null; From cf7fd20452e863980045bb5d6012ec86c6e8e01f Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 31 Jul 2025 09:19:49 +0200 Subject: [PATCH 131/222] Mailer: send only to verified accounts (option) --- admin/pages/mailer.php | 16 +++++++++------- system/templates/admin.mailer.html.twig | 7 +++++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/admin/pages/mailer.php b/admin/pages/mailer.php index f57be2d9..5ac8f58c 100644 --- a/admin/pages/mailer.php +++ b/admin/pages/mailer.php @@ -28,6 +28,7 @@ if (!setting('core.mail_enabled')) { $mail_to = isset($_REQUEST['mail_to']) ? stripslashes(trim($_REQUEST['mail_to'])) : null; $mail_subject = isset($_POST['mail_subject']) ? stripslashes($_POST['mail_subject']) : null; $mail_content = isset($_POST['mail_content']) ? stripslashes($_POST['mail_content']) : null; +$mail_verified_only = $_POST['mail_verified_only'] ?? false; if (isset($_POST['submit'])) { if (empty($mail_subject)) { @@ -58,14 +59,14 @@ if (!empty($mail_content) && !empty($mail_subject) && empty($mail_to)) { $success = 0; $failed = 0; - $add = ''; - if (setting('core.account_mail_verify')) { - note('Note: Sending only to users with verified E-Mail.'); - $add = ' AND `email_verified` = 1'; + $query = Account::where('email', '!=', ''); + + if ($mail_verified_only) { + info('Note: Sending only to users with verified E-Mail.'); + $query->where('email_verified', 1); } - $query = Account::where('email', '!=', '')->get(['email']); - foreach ($query as $email) { + foreach ($query->get(['email']) as $email) { if (_mail($email->email, $mail_subject, $mail_content)) { $success++; } @@ -84,5 +85,6 @@ if (!empty($mail_content) && !empty($mail_subject) && empty($mail_to)) { $twig->display('admin.mailer.html.twig', [ 'mail_to' => $mail_to, 'mail_subject' => $mail_subject, - 'mail_content' => $mail_content + 'mail_content' => $mail_content, + 'mail_verified_only' => $mail_verified_only, ]); diff --git a/system/templates/admin.mailer.html.twig b/system/templates/admin.mailer.html.twig index 0b77ccb3..1dd2eb30 100644 --- a/system/templates/admin.mailer.html.twig +++ b/system/templates/admin.mailer.html.twig @@ -16,6 +16,13 @@
    + {% if setting('core.account_mail_verify') %} +
    + + +
    + {% endif %} +
    From 43415cf35db1c1307f2684c1728693d65065ffff Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 31 Jul 2025 12:32:18 +0200 Subject: [PATCH 132/222] Add missing $fillable into PlayerOnline model --- system/src/Models/PlayerOnline.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/system/src/Models/PlayerOnline.php b/system/src/Models/PlayerOnline.php index e81b591e..6405d9c4 100644 --- a/system/src/Models/PlayerOnline.php +++ b/system/src/Models/PlayerOnline.php @@ -9,6 +9,10 @@ class PlayerOnline extends Model { public $timestamps = false; + protected $fillable = [ + 'player_id', + ]; + public function player() { return $this->belongsTo(Player::class); From 3b47e9df2f4051807c5ff87892f7fa3d348f9c55 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 31 Jul 2025 13:02:55 +0200 Subject: [PATCH 133/222] Cache::remember: $ttl = 0 means no cache --- system/src/Cache/Cache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Cache/Cache.php b/system/src/Cache/Cache.php index 0a369202..53a84530 100644 --- a/system/src/Cache/Cache.php +++ b/system/src/Cache/Cache.php @@ -106,7 +106,7 @@ class Cache public static function remember($key, $ttl, $callback) { $cache = self::getInstance(); - if (!$cache->enabled()) { + if (!$cache->enabled() || $ttl == 0) { return $callback(); } From 0efe47ce71c4b364a9e96bc5a55b1655326ae6da Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 31 Jul 2025 13:15:06 +0200 Subject: [PATCH 134/222] Twig: add cache variable --- system/twig.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/twig.php b/system/twig.php index baeae276..10f77cf3 100644 --- a/system/twig.php +++ b/system/twig.php @@ -156,3 +156,5 @@ $twig->addFilter($filter); unset($function, $filter); $hooks->trigger(HOOK_TWIG, ['twig' => $twig, 'twig_loader' => $twig_loader]); + +$twig->addGlobal('cache', $cache); From c8363086015cbb6e8786c398c7b9ac3959a26ec4 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 31 Jul 2025 13:28:46 +0200 Subject: [PATCH 135/222] pages/online: add cache, resulting in 20x performance boost (for an example server with 2k players) --- system/pages/online.php | 164 +++++++++++++++--------------- system/settings.php | 8 ++ system/templates/online.html.twig | 6 ++ 3 files changed, 98 insertions(+), 80 deletions(-) diff --git a/system/pages/online.php b/system/pages/online.php index e1bc25d4..3aa98c8f 100644 --- a/system/pages/online.php +++ b/system/pages/online.php @@ -9,18 +9,21 @@ * @link https://my-aac.org */ +use MyAAC\Cache\Cache; use MyAAC\Models\ServerConfig; use MyAAC\Models\ServerRecord; defined('MYAAC') or die('Direct access not allowed!'); $title = 'Who is online?'; -if (setting('core.account_country')) +if (setting('core.account_country')) { require SYSTEM . 'countries.conf.php'; +} $promotion = ''; -if($db->hasColumn('players', 'promotion')) +if($db->hasColumn('players', 'promotion')) { $promotion = '`promotion`,'; +} $order = $_GET['order'] ?? 'name_asc'; if(!in_array($order, ['country_asc', 'country_desc', 'name_asc', 'name_desc', 'level_asc', 'level_desc', 'vocation_asc', 'vocation_desc'])) { @@ -30,106 +33,107 @@ else if($order == 'vocation_asc' || $order == 'vocation_desc') { $order = $promotion . 'vocation_' . (str_contains($order, 'asc') ? 'asc' : 'desc'); } -$orderExplode = explode('_', $order); -$orderSql = $orderExplode[0] . ' ' . $orderExplode[1]; +$cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60, function() use($db, $promotion, $order) { + $orderExplode = explode('_', $order); + $orderSql = $orderExplode[0] . ' ' . $orderExplode[1]; -$skull_type = 'skull'; -if($db->hasColumn('players', 'skull_type')) { - $skull_type = 'skull_type'; -} + $skull_type = 'skull'; + if($db->hasColumn('players', 'skull_type')) { + $skull_type = 'skull_type'; + } -$skull_time = 'skulltime'; -if($db->hasColumn('players', 'skull_time')) { - $skull_time = 'skull_time'; -} + $skull_time = 'skulltime'; + if($db->hasColumn('players', 'skull_time')) { + $skull_time = 'skull_time'; + } -$outfit_addons = false; -$outfit = ''; -if (setting('core.online_outfit')) { + $outfit_addons = false; $outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype'; if($db->hasColumn('players', 'lookaddons')) { $outfit .= ', lookaddons'; $outfit_addons = true; } -} -$vocs = []; -if (setting('core.online_vocations')) { - foreach($config['vocations'] as $id => $name) { - $vocs[$id] = 0; - } -} + $vocations = array_map(function ($name) { + return 0; + }, setting('core.vocations')); -if($db->hasTable('players_online')) // tfs 1.0 - $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql); -else - $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', ' . $promotion . ' `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players` WHERE `players`.`online` > 0 AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql); + if($db->hasTable('players_online')) // tfs 1.0 + $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql); + else + $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', ' . $promotion . ' `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players` WHERE `players`.`online` > 0 AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql); -$players_data = []; -$players = 0; -$data = ''; -foreach($playersOnline as $player) { - $skull = ''; - if (setting('core.online_skulls')) - { - if($player['skulltime'] > 0) - { - if($player['skull'] == 3) + $settingVocations = setting('core.vocations'); + $settingVocationsAmount = setting('core.vocations_amount'); + + $players = []; + foreach($playersOnline as $player) { + $skull = ''; + if($player['skulltime'] > 0) { + if($player['skull'] == 3) { $skull = ' '; - elseif($player['skull'] == 4) + } + elseif($player['skull'] == 4) { $skull = ' '; - elseif($player['skull'] == 5) + } + elseif($player['skull'] == 5) { $skull = ' '; - } - } - - if(isset($player['promotion'])) { - if((int)$player['promotion'] > 0) - $player['vocation'] += ($player['promotion'] * $config['vocations_amount']); - } - - $players_data[] = array( - 'name' => getPlayerLink($player['name']), - 'player' => $player, - 'level' => $player['level'], - 'vocation' => $config['vocations'][$player['vocation']], - 'country_image' => setting('core.account_country') ? getFlagImage($player['country']) : null, - 'outfit' => setting('core.online_outfit') ? setting('core.outfit_images_url') . '?id=' . $player['looktype'] . ($outfit_addons ? '&addons=' . $player['lookaddons'] : '') . '&head=' . $player['lookhead'] . '&body=' . $player['lookbody'] . '&legs=' . $player['looklegs'] . '&feet=' . $player['lookfeet'] : null - ); - - if (setting('core.online_vocations')) { - $vocs[($player['vocation'] > $config['vocations_amount'] ? $player['vocation'] - $config['vocations_amount'] : $player['vocation'])]++; - } -} - -$record = ''; -if(count($players_data) > 0) { - if( setting('core.online_record')) { - $result = null; - $timestamp = false; - if($db->hasTable('server_record')) { - $timestamp = true; - $result = ServerRecord::where('world_id', $config['lua']['worldId'])->orderByDesc('record')->first()->toArray(); - } else if($db->hasTable('server_config')) { // tfs 1.0 - $row = ServerConfig::where('config', 'players_record')->first(); - if ($row) { - $result = ['record' => $row->value]; } } - if($result) { - $record = $result['record'] . ' player' . ($result['record'] > 1 ? 's' : '') . ($timestamp ? ' (on ' . date("M d Y, H:i:s", $result['timestamp']) . ')' : ''); + if(isset($player['promotion'])) { + if((int)$player['promotion'] > 0) + $player['vocation'] += ($player['promotion'] * $settingVocationsAmount); + } + + $players[] = array( + 'name' => getPlayerLink($player['name']), + 'player' => $player, + 'level' => $player['level'], + 'vocation' => $settingVocations[$player['vocation']], + 'skull' => $skull, + 'country_image' => getFlagImage($player['country']), + 'outfit' => setting('core.outfit_images_url') . '?id=' . $player['looktype'] . ($outfit_addons ? '&addons=' . $player['lookaddons'] : '') . '&head=' . $player['lookhead'] . '&body=' . $player['lookbody'] . '&legs=' . $player['looklegs'] . '&feet=' . $player['lookfeet'], + ); + + $vocations[($player['vocation'] > $settingVocationsAmount ? $player['vocation'] - $settingVocationsAmount : $player['vocation'])]++; + } + + $record = ''; + if(count($players) > 0) { + if( setting('core.online_record')) { + $result = null; + $timestamp = false; + if($db->hasTable('server_record')) { + $timestamp = true; + $result = ServerRecord::where('world_id', configLua('worldId'))->orderByDesc('record')->first()->toArray(); + } else if($db->hasTable('server_config')) { // tfs 1.0 + $row = ServerConfig::where('config', 'players_record')->first(); + if ($row) { + $result = ['record' => $row->value]; + } + } + + if($result) { + $record = $result['record'] . ' player' . ($result['record'] > 1 ? 's' : '') . ($timestamp ? ' (on ' . date("M d Y, H:i:s", $result['timestamp']) . ')' : ''); + } } } -} + + return [ + 'players' => $players, + 'record' => $record, + 'vocations' => $vocations, + ]; +}); $twig->display('online.html.twig', array( - 'players' => $players_data, - 'record' => $record, - 'vocs' => $vocs, + 'players' => $cached['players'], + 'record' => $cached['record'], + 'vocations' => $cached['vocations'], + 'vocs' => $cached['vocations'], // deprecated, to be removed 'order' => $order, )); -//search bar +// search bar $twig->display('characters.form.html.twig'); -?> diff --git a/system/settings.php b/system/settings.php index ae61fd52..5befa9ca 100644 --- a/system/settings.php +++ b/system/settings.php @@ -1247,6 +1247,14 @@ Sent by MyAAC,
    'type' => 'section', 'title' => 'Online Page' ], + 'online_cache_ttl' => [ + 'name' => 'Online Cache TTL (in minutes)', + 'type' => 'number', + 'min' => 0, + 'desc' => 'How often to update online list from database in minutes. Too low may slow down your website.' . PHP_EOL . + '0 to disable.', + 'default' => 15, + ], 'online_record' => [ 'name' => 'Display Players Record', 'type' => 'boolean', diff --git a/system/templates/online.html.twig b/system/templates/online.html.twig index 26a756ed..b5716858 100644 --- a/system/templates/online.html.twig +++ b/system/templates/online.html.twig @@ -1,3 +1,9 @@ +{% set onlineTTL = setting('core.online_cache_ttl') %} +{% if onlineTTL > 0 and cache.enabled() %} +*Note: Online List is updated every {{ onlineTTL > 1 ? ' ' ~ onlineTTL : '' }} minute{{ onlineTTL > 1 ? 's' : '' }}. +
    +{% endif %} + {# vocation statistics #} {% if setting('core.online_vocations') %}
    From e1c04ed28e0619a11f1636c18d81691284d78788 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 2 Aug 2025 12:28:13 +0200 Subject: [PATCH 136/222] Release v1.8 --- CHANGELOG-1.x.md | 36 ++++++++++++++++++++++++++++++++++++ common.php | 2 +- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index 28c946ec..716d11da 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,41 @@ # Changelog +## [1.8 - 01.08.2025] + +### Added +* Templates - Kathrine: Possibility to add custom menu categories (https://github.com/slawkens/myaac/commit/ec11c1402417c25980582467546d1c1e9bb8267f) +* Admin Panel - Accounts Editor: Add Coins Transferable (https://github.com/slawkens/myaac/commit/45d6047031c9c3a0e7e512dc5d15c75629aec5a2, https://github.com/slawkens/myaac/commit/bb097b69ce106500a49686d6f4fe604348eaa310) +* Highscores: + * Revamped: (https://github.com/slawkens/myaac/commit/d8132d4d76e03d5aa0c042be426320655a601392) + * Show real rank, if 2 or more players have the same skill, show them with same rank + * New setting: highscores_online_status + * Additional fields passed to twig: updatedAt, totalResults, page, baseLink + * Add new Setting: Display Skills Box (https://github.com/slawkens/myaac/commit/36ca755243ef1c83f6ac87465b426d4d8d3b0bb9) +* Functions: Add getExperienceForLevel (level) (https://github.com/slawkens/myaac/commit/1566deb84a082176b8c683fda205d828bc38fbcc) +* Commands - cache:clear : Add warning about APCu clear in CLI (https://github.com/slawkens/myaac/commit/83f84172e02e8ea2ccb6dca29bc033e44c35aebc) +* Models - PlayerOnline: Add missing $fillable into model (https://github.com/slawkens/myaac/commit/43415cf35db1c1307f2684c1728693d65065ffff) +* Twig: add cache variable (https://github.com/slawkens/myaac/commit/0efe47ce71c4b364a9e96bc5a55b1655326ae6da) + +### Changed +* pages/online: add cache, resulting in 20x performance boost + * (for an example server with 2k players) (https://github.com/slawkens/myaac/commit/c8363086015cbb6e8786c398c7b9ac3959a26ec4) +* Admin Bar: Move admin bar code into body_start place_holder (https://github.com/slawkens/myaac/commit/f17269e44ce9dd38447bd2e2a8e1bdb065d4161f) +* Cache::remember: $ttl = 0 means no cache (https://github.com/slawkens/myaac/commit/3b47e9df2f4051807c5ff87892f7fa3d348f9c55) +* Templates: Load config.ini with $process_sections set to true (https://github.com/slawkens/myaac/commit/a89f9a84847630eb75b4890fdcc8b7a7bfa6b8ac) +* Twig: Allow for timestamp as integer in the timeago twig function + (https://github.com/slawkens/myaac/commit/34fead906ea13b9f09d7a3c41ed88109d34d386c) + +### Fixed +* Settings: Fixed two exceptions (https://github.com/slawkens/myaac/commit/6e5a4ff8c78ff5373aba091baa66cae029557643, https://github.com/slawkens/myaac/commit/20d69a641c0a933d14889a89da6d32f6a4bc6c7d) +* Models\Account + OTS_Account -> isPremium -> ignore config.freePremium (https://github.com/slawkens/myaac/commit/5271633bdbfbbfed0b1d59c403093ce6fc2b7d20) +* Admin Panel - Mailer: + * Fix send to email link redirecting from accounts page (https://github.com/slawkens/myaac/commit/080cc2781f034c844af658229e495e9a47fd2298) + * Option to send only to verified accounts - only if setting('core.account_mail_verify') enabled (https://github.com/slawkens/myaac/commit/cf7fd20452e863980045bb5d6012ec86c6e8e01f) + +### Internal +* Rewrite to use constants (account transferable coins) (https://github.com/slawkens/myaac/commit/bccf8e056df985bbe1bab5f7ab5492f714d6b62b) +* Refactor to use HAS_ACCOUNT_COINS (https://github.com/slawkens/myaac/commit/caf326a6584a234775ebc6c8000ea02b3fecd160) + ## [1.7.1 - 27.06.2025] ### Changed diff --git a/common.php b/common.php index 7d8a905d..cf1909c3 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.7.2-dev'; +const MYAAC_VERSION = '1.8'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 785d38312b4673142089c1bfaa282f5841cd4531 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 2 Aug 2025 12:41:35 +0200 Subject: [PATCH 137/222] Start 1.8.1-dev --- CHANGELOG-1.x.md | 2 +- common.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index 716d11da..b513cebf 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,6 +1,6 @@ # Changelog -## [1.8 - 01.08.2025] +## [1.8 - 02.08.2025] ### Added * Templates - Kathrine: Possibility to add custom menu categories (https://github.com/slawkens/myaac/commit/ec11c1402417c25980582467546d1c1e9bb8267f) diff --git a/common.php b/common.php index cf1909c3..3e6a9291 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.8'; +const MYAAC_VERSION = '1.8.1-dev'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 0db908be181f66b0434b4aad0b69462aa6eee4a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 Aug 2025 14:15:13 +0200 Subject: [PATCH 138/222] Bump form-data from 4.0.2 to 4.0.4 (#315) Bumps [form-data](https://github.com/form-data/form-data) from 4.0.2 to 4.0.4. - [Release notes](https://github.com/form-data/form-data/releases) - [Changelog](https://github.com/form-data/form-data/blob/master/CHANGELOG.md) - [Commits](https://github.com/form-data/form-data/compare/v4.0.2...v4.0.4) --- updated-dependencies: - dependency-name: form-data dependency-version: 4.0.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7cdffe23..fb820852 100644 --- a/package-lock.json +++ b/package-lock.json @@ -976,15 +976,16 @@ } }, "node_modules/form-data": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", - "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { From 9cb7792623a856fa3a4d6c0523c12456c96df238 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Aug 2025 16:21:22 +0200 Subject: [PATCH 139/222] Bump tmp from 0.2.3 to 0.2.4 (#317) Bumps [tmp](https://github.com/raszi/node-tmp) from 0.2.3 to 0.2.4. - [Changelog](https://github.com/raszi/node-tmp/blob/master/CHANGELOG.md) - [Commits](https://github.com/raszi/node-tmp/compare/v0.2.3...v0.2.4) --- updated-dependencies: - dependency-name: tmp dependency-version: 0.2.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index fb820852..3ea74539 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2085,9 +2085,9 @@ "license": "MIT" }, "node_modules/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.4.tgz", + "integrity": "sha512-UdiSoX6ypifLmrfQ/XfiawN6hkjSBpCjhKxxZcWlUUmoXLaCKQU0bx4HF/tdDK2uzRuchf1txGvrWBzYREssoQ==", "dev": true, "license": "MIT", "engines": { From b6e1620f14c20eecfc9001a7d86dfb67942985c6 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 7 Aug 2025 21:17:25 +0200 Subject: [PATCH 140/222] Fix #318 (online.php throws error in one scenario) --- system/pages/online.php | 13 +++++++++++-- system/templates/online.html.twig | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/system/pages/online.php b/system/pages/online.php index 3aa98c8f..21f2ee0d 100644 --- a/system/pages/online.php +++ b/system/pages/online.php @@ -105,8 +105,17 @@ $cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60 $result = null; $timestamp = false; if($db->hasTable('server_record')) { - $timestamp = true; - $result = ServerRecord::where('world_id', configLua('worldId'))->orderByDesc('record')->first()->toArray(); + $timestamp = $db->hasColumn('server_record', 'timestamp'); + $serverRecordQuery = ServerRecord::query(); + + if ($db->hasColumn('server_record', 'world_id')) { + $serverRecordQuery->where('world_id', configLua('worldId')); + } + + $result = $serverRecordQuery->orderByDesc('record')->first(); + if ($result) { + $result = $result->toArray(); + } } else if($db->hasTable('server_config')) { // tfs 1.0 $row = ServerConfig::where('config', 'players_record')->first(); if ($row) { diff --git a/system/templates/online.html.twig b/system/templates/online.html.twig index b5716858..3a741aa1 100644 --- a/system/templates/online.html.twig +++ b/system/templates/online.html.twig @@ -90,7 +90,7 @@
    Online Record: From 20f99903ae80c74ad66c1cf5a5ea8d0b0fc2fd70 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 12 Aug 2025 12:46:39 +0200 Subject: [PATCH 141/222] Fix submenu initialization for missing elements Added a check in InitializeMenu to skip submenu items if their corresponding DOM element does not exist, preventing potential JavaScript errors. --- templates/tibiacom/index.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/templates/tibiacom/index.php b/templates/tibiacom/index.php index 46ef0698..cb482018 100644 --- a/templates/tibiacom/index.php +++ b/templates/tibiacom/index.php @@ -164,6 +164,10 @@ if(isset($config['boxes'])) function InitializeMenu() { for(menuItemName in menu[0]) { + if (!document.getElementById(menuItemName+"_Submenu")) { + continue; + } + if(menu[0][menuItemName] == "0") { document.getElementById(menuItemName+"_Submenu").style.visibility = "hidden"; document.getElementById(menuItemName+"_Submenu").style.display = "none"; From 11dae90fa94fbbf47447017db5e5847c33d6aadf Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 12 Aug 2025 17:42:06 +0200 Subject: [PATCH 142/222] Fix MenuBotton display if some elements are removed From menu_categories --- templates/tibiacom/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/tibiacom/index.php b/templates/tibiacom/index.php index cb482018..9746e8d8 100644 --- a/templates/tibiacom/index.php +++ b/templates/tibiacom/index.php @@ -391,7 +391,7 @@ foreach($config['menu_categories'] as $id => $cat) { ?> Date: Sun, 17 Aug 2025 17:50:16 +0200 Subject: [PATCH 143/222] Fix online skulls display (Fix #320) --- system/templates/online.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/templates/online.html.twig b/system/templates/online.html.twig index 3a741aa1..bb6c786c 100644 --- a/system/templates/online.html.twig +++ b/system/templates/online.html.twig @@ -161,7 +161,7 @@ {% endif %} - {{ player.name|raw }}{{ player.skull }} + {{ player.name|raw }}{{ player.skull|raw }} {{ player.level }} {{ player.vocation }} - {% set button_name = 'Invite Character' %} - {% set button_image = '_sbutton_invitecharacter' %} - {% include('buttons.base.html.twig') %} -
    + {% set button_name = 'Invite Character' %} + {% set button_image = '_sbutton_invitecharacter' %} + {% include('buttons.base.html.twig') %} +
    - {{ hook(constant('HOOK_CHARACTERS_BEFORE_INFORMATIONS')) }} + {{ hook('HOOK_CHARACTERS_BEFORE_INFORMATIONS') }} {% if canEdit %} Edit @@ -153,11 +153,11 @@ {% if account.isPremium() %}Premium Account{% else %}Free Account{% endif %}
    - {{ hook(constant('HOOK_CHARACTERS_AFTER_INFORMATIONS')) }} + {{ hook('HOOK_CHARACTERS_AFTER_INFORMATIONS') }}
    - {{ hook(constant('HOOK_CHARACTERS_BEFORE_SKILLS')) }} + {{ hook('HOOK_CHARACTERS_BEFORE_SKILLS') }} {% if config.characters.skills %} @@ -179,7 +179,7 @@ {% endif %} - {{ hook(constant('HOOK_CHARACTERS_AFTER_SKILLS')) }} + {{ hook('HOOK_CHARACTERS_AFTER_SKILLS') }} {% if quests_enabled %} @@ -201,7 +201,7 @@ {% endif %} - {{ hook(constant('HOOK_CHARACTERS_AFTER_QUESTS')) }} + {{ hook('HOOK_CHARACTERS_AFTER_QUESTS') }} {% if config.characters.equipment %} @@ -239,11 +239,11 @@ {% endif %} - {{ hook(constant('HOOK_CHARACTERS_AFTER_EQUIPMENT')) }} + {{ hook('HOOK_CHARACTERS_AFTER_EQUIPMENT') }}
    - {{ hook(constant('HOOK_CHARACTERS_BEFORE_DEATHS')) }} + {{ hook('HOOK_CHARACTERS_BEFORE_DEATHS') }} {% if deaths|length > 0 %} @@ -283,7 +283,7 @@ {% endif %} - {{ hook(constant('HOOK_CHARACTERS_BEFORE_SIGNATURE')) }} + {{ hook('HOOK_CHARACTERS_BEFORE_SIGNATURE') }} {% if setting('core.signature_enabled') %} @@ -327,7 +327,7 @@
    {% endif %} - {{ hook(constant('HOOK_CHARACTERS_AFTER_SIGNATURE')) }} + {{ hook('HOOK_CHARACTERS_AFTER_SIGNATURE') }} {% if not player.isHidden() %} {% set rows = 0 %} @@ -377,7 +377,7 @@ - {{ hook(constant('HOOK_CHARACTERS_AFTER_ACCOUNT')) }} + {{ hook('HOOK_CHARACTERS_AFTER_ACCOUNT') }}

    @@ -421,7 +421,7 @@
    {% endif %} - {{ hook(constant('HOOK_CHARACTERS_AFTER_CHARACTERS')) }} + {{ hook('HOOK_CHARACTERS_AFTER_CHARACTERS') }} {% if canEdit %} Edit From 228780f0ad8b6c5e16a93f3e946a74a6e9ad4cf8 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 28 Sep 2025 14:14:26 +0200 Subject: [PATCH 177/222] Just leaving it here, for future use (twig hook display) Maybe configurable in the future --- system/twig.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/twig.php b/system/twig.php index 10f77cf3..ecc7a957 100644 --- a/system/twig.php +++ b/system/twig.php @@ -101,6 +101,8 @@ $twig->addFunction($function); $function = new TwigFunction('hook', function ($context, $hook, array $params = []) { global $hooks; + //note($hook); + if(is_string($hook)) { if (defined($hook)) { $hook = constant($hook); From 4c6277c124e6244a63280e64fde7b5b0c9bada0d Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 28 Sep 2025 14:16:28 +0200 Subject: [PATCH 178/222] Start v1.8.3-dev --- common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.php b/common.php index 868754d2..6bb6be85 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.8.2'; +const MYAAC_VERSION = '1.8.3-dev'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 56bd7ec5ed904666074492f2e4f13e4fce226bee Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 28 Sep 2025 16:09:14 +0200 Subject: [PATCH 179/222] Prevent injection in $db->hasColumn --- system/libs/pot/OTS_DB_MySQL.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/libs/pot/OTS_DB_MySQL.php b/system/libs/pot/OTS_DB_MySQL.php index baa38c76..5b1e01cb 100644 --- a/system/libs/pot/OTS_DB_MySQL.php +++ b/system/libs/pot/OTS_DB_MySQL.php @@ -230,8 +230,8 @@ class OTS_DB_MySQL extends OTS_Base_DB return $this->hasColumnInternal($table, $column); } - private function hasColumnInternal($table, $column) { - return $this->hasTable($table) && ($this->has_column_cache[$table . '.' . $column] = count($this->query('SHOW COLUMNS FROM `' . $table . "` LIKE '" . $column . "'")->fetchAll()) > 0); + private function hasColumnInternal($table, $column): bool { + return $this->hasTable($table) && ($this->has_column_cache[$table . '.' . $column] = count($this->query('SHOW COLUMNS FROM `' . $table . "` LIKE " . $this->quote($column))->fetchAll()) > 0); } public function hasTableAndColumns(string $table, array $columns = []): bool From 73c07d470d90d943ce93c1e2f7c22bca90766901 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 28 Sep 2025 16:10:58 +0200 Subject: [PATCH 180/222] Add variable types, don't use $config --- system/libs/pot/OTS_DB_MySQL.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/system/libs/pot/OTS_DB_MySQL.php b/system/libs/pot/OTS_DB_MySQL.php index 5b1e01cb..7439adae 100644 --- a/system/libs/pot/OTS_DB_MySQL.php +++ b/system/libs/pot/OTS_DB_MySQL.php @@ -26,10 +26,10 @@ use MyAAC\Cache\Cache; */ class OTS_DB_MySQL extends OTS_Base_DB { - private $has_table_cache = array(); - private $has_column_cache = array(); + private array $has_table_cache = []; + private array $has_column_cache = []; - private $clearCacheAfter = false; + private bool $clearCacheAfter = false; /** * Creates database connection. * @@ -209,7 +209,8 @@ class OTS_DB_MySQL extends OTS_Base_DB return $sql; } - public function hasTable($name) { + public function hasTable($name): bool + { if(isset($this->has_table_cache[$name])) { return $this->has_table_cache[$name]; } @@ -217,12 +218,13 @@ class OTS_DB_MySQL extends OTS_Base_DB return $this->hasTableInternal($name); } - private function hasTableInternal($name) { - global $config; - return ($this->has_table_cache[$name] = $this->query('SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `TABLE_SCHEMA` = ' . $this->quote($config['database_name']) . ' AND `TABLE_NAME` = ' . $this->quote($name) . ' LIMIT 1;')->rowCount() > 0); + private function hasTableInternal($name): bool + { + return ($this->has_table_cache[$name] = $this->query('SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `TABLE_SCHEMA` = ' . $this->quote(config('database_name')) . ' AND `TABLE_NAME` = ' . $this->quote($name) . ' LIMIT 1;')->rowCount() > 0); } - public function hasColumn($table, $column) { + public function hasColumn($table, $column): bool + { if(isset($this->has_column_cache[$table . '.' . $column])) { return $this->has_column_cache[$table . '.' . $column]; } From c898fe25efff6793a01d11c26fc153cb23fcb858 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 28 Sep 2025 16:21:31 +0200 Subject: [PATCH 181/222] New function: getColumnInfo($table, $column) --- system/libs/pot/OTS_DB_MySQL.php | 46 ++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/system/libs/pot/OTS_DB_MySQL.php b/system/libs/pot/OTS_DB_MySQL.php index 7439adae..68f34787 100644 --- a/system/libs/pot/OTS_DB_MySQL.php +++ b/system/libs/pot/OTS_DB_MySQL.php @@ -28,6 +28,7 @@ class OTS_DB_MySQL extends OTS_Base_DB { private array $has_table_cache = []; private array $has_column_cache = []; + private array $get_column_info_cache = []; private bool $clearCacheAfter = false; /** @@ -249,6 +250,51 @@ class OTS_DB_MySQL extends OTS_Base_DB return true; } + public function getColumnInfo(string $table, string $column): bool|array + { + if(isset($this->get_column_info_cache[$table . '.' . $column])) { + return $this->get_column_info_cache[$table . '.' . $column]; + } + + return $this->getColumnInfoInternal($table, $column); + } + + private function getColumnInfoInternal(string $table, string $column): bool|array + { + if (!$this->hasTable($table) || !$this->hasColumn($table, $column)) { + return false; + } + + $formatResult = function ($result) { + return [ + 'field' => $result['Field'], + 'type' => $result['Type'], + 'null' => strtolower($result['Null']), + 'default' => $result['Default'], + 'extra' => $result['Extra'], + ]; + }; + + $query = $this->query('SHOW COLUMNS FROM `' . $table . "` LIKE " . $this->quote($column)); + $rowCount = $query->rowCount(); + if ($rowCount > 1) { + $tmp = []; + + $results = $query->fetchAll(PDO::FETCH_ASSOC); + foreach ($results as $result) { + $tmp[] = $formatResult($result); + } + + return ($this->get_column_info_cache[$table . '.' . $column] = $tmp); + } + else if ($rowCount == 1) { + $result = $query->fetch(PDO::FETCH_ASSOC); + return ($this->get_column_info_cache[$table . '.' . $column] = $formatResult($result)); + } + + return []; + } + public function revalidateCache() { foreach($this->has_table_cache as $key => $value) { $this->hasTableInternal($key); From f54b1bdd2af4c16c64ddff0e87a6c96bc4cf9eeb Mon Sep 17 00:00:00 2001 From: Slawomir Boczek Date: Sun, 28 Sep 2025 19:00:51 +0200 Subject: [PATCH 182/222] First attempt (#331) --- admin/pages/players.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/admin/pages/players.php b/admin/pages/players.php index c44bc012..bd3ab713 100644 --- a/admin/pages/players.php +++ b/admin/pages/players.php @@ -669,11 +669,17 @@ else if (isset($_REQUEST['search'])) {
    From 97f9d3d6f6c28aef6d824973058d7133f56e09c4 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 2 Oct 2025 15:06:57 +0200 Subject: [PATCH 183/222] Add option to use ?subtopic=x for plugins pages --- system/router.php | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/system/router.php b/system/router.php index 9c9ce4ad..0f1845f2 100644 --- a/system/router.php +++ b/system/router.php @@ -88,8 +88,10 @@ if($logged && $account_logged && $account_logged->isLoaded()) { /** * Routes loading */ +$routesFinal = []; $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) { - $routesFinal = []; + global $routesFinal; + foreach(getDatabasePages() as $page) { $routesFinal[] = ['*', $page, '__database__/' . $page, 100]; } @@ -165,7 +167,7 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) echo ''; die; */ - foreach ($routesFinal as $route) { + foreach ($routesFinal as &$route) { if ($route[0] === '*') { $route[0] = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD']; } @@ -212,7 +214,7 @@ $found = true; // old support for pages like /?subtopic=accountmanagement $page = $_REQUEST['p'] ?? ($_REQUEST['subtopic'] ?? ''); -if(!empty($page) && preg_match('/^[A-z0-9\-]+$/', $page)) { +if(!empty($page) && preg_match('/^[A-z0-9\/\-]+$/', $page)) { if (isset($_REQUEST['p'])) { // some plugins may require this $_REQUEST['subtopic'] = $_REQUEST['p']; } @@ -221,9 +223,20 @@ if(!empty($page) && preg_match('/^[A-z0-9\-]+$/', $page)) { require SYSTEM . 'compat/pages.php'; } - $file = loadPageFromFileSystem($page, $found); - if(!$found) { - $file = false; + $foundRoute = false; + foreach ($routesFinal as $route) { + if ($page === $route[1]) { + $file = $route[2]; + $foundRoute = true; + break; + } + } + + if (!$foundRoute) { + $file = loadPageFromFileSystem($page, $found); + if(!$found) { + $file = false; + } } } else { From 64acf70d3854182d88aaf0b67f77cea2a254f179 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 2 Oct 2025 22:13:15 +0200 Subject: [PATCH 184/222] Cache::remember -1 = infinite --- system/src/Cache/Cache.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/system/src/Cache/Cache.php b/system/src/Cache/Cache.php index 53a84530..1b7d284b 100644 --- a/system/src/Cache/Cache.php +++ b/system/src/Cache/Cache.php @@ -115,6 +115,11 @@ class Cache return unserialize($value); } + // -1 for infinite cache + if ($ttl == -1) { + $ttl = 10 * 365 * 24 * 60 * 60; // 10 years should be enough + } + $value = $callback(); $cache->set($key, serialize($value), $ttl); return $value; From 3bb272ebbbd2eb7769d174b7082061d14a17bd44 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 2 Oct 2025 22:13:33 +0200 Subject: [PATCH 185/222] Allow for img in online_datacenter --- system/templates/online.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/templates/online.html.twig b/system/templates/online.html.twig index bb6c786c..6f798740 100644 --- a/system/templates/online.html.twig +++ b/system/templates/online.html.twig @@ -101,7 +101,7 @@ Location Datacenter: - {{ setting('core.online_datacenter') }} (Server date & time: - {{ "now"|date("d/m/Y H:i:s") }}) + {{ setting('core.online_datacenter')|raw }} (Server date & time: - {{ "now"|date("d/m/Y H:i:s") }}) PvP Type: From d8b73f55a310704ee884f1338dead9ff2c48a2f2 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 2 Oct 2025 22:16:29 +0200 Subject: [PATCH 186/222] Fix routes_final for prod env --- system/router.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/system/router.php b/system/router.php index 0f1845f2..ec79f9b3 100644 --- a/system/router.php +++ b/system/router.php @@ -88,9 +88,9 @@ if($logged && $account_logged && $account_logged->isLoaded()) { /** * Routes loading */ -$routesFinal = []; $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) { - global $routesFinal; + global $cache; + $routesFinal = []; foreach(getDatabasePages() as $page) { $routesFinal[] = ['*', $page, '__database__/' . $page, 100]; @@ -200,6 +200,8 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) log_append('router.log', $warning); } } + + $cache->set('routes_final', serialize($routesFinal), 10 * 365 * 24 * 60 * 60); // 10 years / infinite }, [ 'cacheFile' => CACHE . 'route.cache', @@ -224,6 +226,13 @@ if(!empty($page) && preg_match('/^[A-z0-9\/\-]+$/', $page)) { } $foundRoute = false; + + $routesFinal = []; + $tmp = null; + if ($cache->fetch('routes_final', $tmp)) { + $routesFinal = unserialize($tmp); + } + foreach ($routesFinal as $route) { if ($page === $route[1]) { $file = $route[2]; From 0cb9d3a20801045d5553e303f1933ef82650923b Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 2 Oct 2025 22:31:02 +0200 Subject: [PATCH 187/222] Fix routes_final cache --- system/router.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/system/router.php b/system/router.php index ec79f9b3..f876a9b2 100644 --- a/system/router.php +++ b/system/router.php @@ -88,9 +88,9 @@ if($logged && $account_logged && $account_logged->isLoaded()) { /** * Routes loading */ +$routesFinal = []; $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) { - global $cache; - $routesFinal = []; + global $cache, $routesFinal; foreach(getDatabasePages() as $page) { $routesFinal[] = ['*', $page, '__database__/' . $page, 100]; @@ -201,7 +201,9 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) } } - $cache->set('routes_final', serialize($routesFinal), 10 * 365 * 24 * 60 * 60); // 10 years / infinite + if ($cache->enabled()) { + $cache->set('routes_final', serialize($routesFinal), 10 * 365 * 24 * 60 * 60); // 10 years / infinite + } }, [ 'cacheFile' => CACHE . 'route.cache', @@ -227,9 +229,8 @@ if(!empty($page) && preg_match('/^[A-z0-9\/\-]+$/', $page)) { $foundRoute = false; - $routesFinal = []; $tmp = null; - if ($cache->fetch('routes_final', $tmp)) { + if ($cache->enabled() && $cache->fetch('routes_final', $tmp)) { $routesFinal = unserialize($tmp); } From 0d8f68a48e0b5ce3071567ad955475263981879c Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 2 Oct 2025 22:31:16 +0200 Subject: [PATCH 188/222] Fix menus for ?subtopic= --- templates/tibiacom/index.php | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/templates/tibiacom/index.php b/templates/tibiacom/index.php index 1bfe6164..a6b57841 100644 --- a/templates/tibiacom/index.php +++ b/templates/tibiacom/index.php @@ -27,26 +27,18 @@ if(isset($config['boxes'])) var loginStatus=""; Date: Fri, 3 Oct 2025 00:25:41 +0200 Subject: [PATCH 189/222] Add lookmount into getTopPlayers --- system/functions.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/system/functions.php b/system/functions.php index 8c365391..b5141b2f 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1146,6 +1146,10 @@ function getTopPlayers($limit = 5, $skill = 'level') { $columns[] = 'lookaddons'; } + if ($db->hasColumn('players', 'lookmount')) { + $columns[] = 'lookmount'; + } + return Player::query() ->select($columns) ->withOnlineStatus() From 901df48d134079d648a18f9d82b60182e818ac02 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 3 Oct 2025 00:31:03 +0200 Subject: [PATCH 190/222] Add promotion into getTopPlayers --- system/functions.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/system/functions.php b/system/functions.php index b5141b2f..212a043e 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1142,6 +1142,10 @@ function getTopPlayers($limit = 5, $skill = 'level') { 'looktype', 'lookhead', 'lookbody', 'looklegs', 'lookfeet' ]; + if ($db->hasColumn('players', 'promotion')) { + $columns[] = 'promotion'; + } + if ($db->hasColumn('players', 'lookaddons')) { $columns[] = 'lookaddons'; } From 8272f1373c8592feebf2db5e092b294c4372ea75 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 3 Oct 2025 16:24:02 +0200 Subject: [PATCH 191/222] Fix database column info cache --- system/libs/pot/OTS_DB_MySQL.php | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/system/libs/pot/OTS_DB_MySQL.php b/system/libs/pot/OTS_DB_MySQL.php index 68f34787..8b9626d9 100644 --- a/system/libs/pot/OTS_DB_MySQL.php +++ b/system/libs/pot/OTS_DB_MySQL.php @@ -120,6 +120,11 @@ class OTS_DB_MySQL extends OTS_Base_DB if($cache->fetch('database_columns', $tmp) && $tmp) { $this->has_column_cache = unserialize($tmp); } + + $tmp = null; + if($cache->fetch('database_columns_info', $tmp) && $tmp) { + $this->get_column_info_cache = unserialize($tmp); + } } } @@ -156,11 +161,13 @@ class OTS_DB_MySQL extends OTS_Base_DB if ($this->clearCacheAfter) { $cache->delete('database_tables'); $cache->delete('database_columns'); + $cache->delete('database_columns_info'); $cache->delete('database_checksum'); } else { $cache->set('database_tables', serialize($this->has_table_cache), 3600); $cache->set('database_columns', serialize($this->has_column_cache), 3600); + $cache->set('database_columns_info', serialize($this->get_column_info_cache), 3600); $cache->set('database_checksum', serialize(sha1($config['database_host'] . '.' . $config['database_name'])), 3600); } } @@ -295,7 +302,8 @@ class OTS_DB_MySQL extends OTS_Base_DB return []; } - public function revalidateCache() { + public function revalidateCache(): void + { foreach($this->has_table_cache as $key => $value) { $this->hasTableInternal($key); } @@ -310,6 +318,21 @@ class OTS_DB_MySQL extends OTS_Base_DB $this->hasColumnInternal($explode[0], $explode[1]); } } + + foreach($this->get_column_info_cache as $key => $value) { + $explode = explode('.', $key); + if(!isset($this->has_table_cache[$explode[0]])) { // first check if table exist + $this->hasTableInternal($explode[0]); + } + + if($this->has_table_cache[$explode[0]]) { + $this->hasColumnInternal($explode[0], $explode[1]); + } + + if($this->has_table_cache[$explode[0]]) { + $this->getColumnInfoInternal($explode[0], $explode[1]); + } + } } public function setClearCacheAfter($clearCache) From 2eae44e0755e624a91be68b4d1ec26d01eb4d9a1 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 8 Oct 2025 14:39:23 +0200 Subject: [PATCH 192/222] Add missing compat config: email_lai_sec_interval --- system/compat/config.php | 1 + 1 file changed, 1 insertion(+) diff --git a/system/compat/config.php b/system/compat/config.php index 9d58f4d6..4fc3004a 100644 --- a/system/compat/config.php +++ b/system/compat/config.php @@ -81,6 +81,7 @@ $deprecatedConfig = [ 'account_change_character_name_points' => 'account_change_character_name_price', 'account_change_character_sex', 'account_change_character_sex_points' => 'account_change_character_name_price', + 'email_lai_sec_interval' => 'mail_lost_account_interval', ]; foreach ($deprecatedConfig as $key => $value) { From 8c3cb0e06f9709c1de3398b48221241e7cbdd310 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 11 Oct 2025 18:34:15 +0200 Subject: [PATCH 193/222] New configurable: hooks_debug To view where hooks are located in .twig files --- system/twig.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/system/twig.php b/system/twig.php index ecc7a957..89f25939 100644 --- a/system/twig.php +++ b/system/twig.php @@ -101,7 +101,9 @@ $twig->addFunction($function); $function = new TwigFunction('hook', function ($context, $hook, array $params = []) { global $hooks; - //note($hook); + if (config('hooks_debug')) { + note($hook); + } if(is_string($hook)) { if (defined($hook)) { From 9acad15451071639acf7a7d4e81619b0a9742b12 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 12 Oct 2025 00:15:04 +0200 Subject: [PATCH 194/222] Allow links in error_box --- system/templates/error_box.html.twig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/templates/error_box.html.twig b/system/templates/error_box.html.twig index e6ed4992..ba9a2263 100644 --- a/system/templates/error_box.html.twig +++ b/system/templates/error_box.html.twig @@ -9,7 +9,7 @@
    The Following Errors Have Occurred:
    {% for error in errors %} -
  • {{ error|striptags('')|raw }}
  • +
  • {{ error|striptags('')|raw }}
  • {% endfor %}
    @@ -17,4 +17,4 @@
    -
    \ No newline at end of file +
    From fe821c58085483e70491dcf76376ad5b96de3fdd Mon Sep 17 00:00:00 2001 From: Slawomir Boczek Date: Sun, 12 Oct 2025 11:19:30 +0200 Subject: [PATCH 195/222] Feature/resend email verify (#333) * feat: Resend Email Verify + rework the whole concept, based on new table for email hashes This make it possible that every email will work, not matter if first or last * Nothing important: change variable name * Change message --- common.php | 2 +- install/includes/schema.sql | 11 ++- install/tools/5-database.php | 9 +- .../migrations/46-account_emails_verify.sql | 8 ++ system/migrations/46.php | 24 +++++ system/pages/account/confirm-email.php | 13 ++- system/pages/account/create.php | 8 +- system/pages/account/login.php | 4 +- system/pages/account/resend-email-verify.php | 94 +++++++++++++++++++ system/src/Models/AccountEmailVerify.php | 15 +++ .../account.resend-email-verify.html.twig | 45 +++++++++ ...mail.account.resend-email-verify.html.twig | 7 ++ 12 files changed, 225 insertions(+), 15 deletions(-) create mode 100644 system/migrations/46-account_emails_verify.sql create mode 100644 system/migrations/46.php create mode 100644 system/pages/account/resend-email-verify.php create mode 100644 system/src/Models/AccountEmailVerify.php create mode 100644 system/templates/account.resend-email-verify.html.twig create mode 100644 system/templates/mail.account.resend-email-verify.html.twig diff --git a/common.php b/common.php index 6bb6be85..e26921c5 100644 --- a/common.php +++ b/common.php @@ -27,7 +27,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is const MYAAC = true; const MYAAC_VERSION = '1.8.3-dev'; -const DATABASE_VERSION = 45; +const DATABASE_VERSION = 46; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX')); diff --git a/install/includes/schema.sql b/install/includes/schema.sql index eccaee54..b53ffab2 100644 --- a/install/includes/schema.sql +++ b/install/includes/schema.sql @@ -1,4 +1,4 @@ -SET @myaac_database_version = 45; +SET @myaac_database_version = 46; CREATE TABLE `myaac_account_actions` ( @@ -10,6 +10,15 @@ CREATE TABLE `myaac_account_actions` KEY (`account_id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; +CREATE TABLE `myaac_account_emails_verify` +( + `id` int NOT NULL AUTO_INCREMENT, + `account_id` int NOT NULL, + `hash` varchar(32) NOT NULL, + `sent_at` int NOT NULL DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; + CREATE TABLE `myaac_admin_menu` ( `id` int NOT NULL AUTO_INCREMENT, diff --git a/install/tools/5-database.php b/install/tools/5-database.php index b9ff587f..f97eca11 100644 --- a/install/tools/5-database.php +++ b/install/tools/5-database.php @@ -102,18 +102,13 @@ if(!$db->hasColumn('accounts', 'web_flags')) { success($locale['step_database_adding_field'] . ' accounts.web_flags...'); } -if(!$db->hasColumn('accounts', 'email_hash')) { - if(query("ALTER TABLE `accounts` ADD `email_hash` VARCHAR(32) NOT NULL DEFAULT '' AFTER `web_flags`;")) - success($locale['step_database_adding_field'] . ' accounts.email_hash...'); -} - if(!$db->hasColumn('accounts', 'email_verified')) { - if(query("ALTER TABLE `accounts` ADD `email_verified` TINYINT(1) NOT NULL DEFAULT 0 AFTER `email_hash`;")) + if(query("ALTER TABLE `accounts` ADD `email_verified` TINYINT(1) NOT NULL DEFAULT 0 AFTER `web_flags`;")) success($locale['step_database_adding_field'] . ' accounts.email_verified...'); } if(!$db->hasColumn('accounts', 'email_new')) { - if(query("ALTER TABLE `accounts` ADD `email_new` VARCHAR(255) NOT NULL DEFAULT '' AFTER `email_hash`;")) + if(query("ALTER TABLE `accounts` ADD `email_new` VARCHAR(255) NOT NULL DEFAULT '' AFTER `email_verified`;")) success($locale['step_database_adding_field'] . ' accounts.email_new...'); } diff --git a/system/migrations/46-account_emails_verify.sql b/system/migrations/46-account_emails_verify.sql new file mode 100644 index 00000000..13d42b16 --- /dev/null +++ b/system/migrations/46-account_emails_verify.sql @@ -0,0 +1,8 @@ +CREATE TABLE `myaac_account_emails_verify` +( + `id` int NOT NULL AUTO_INCREMENT, + `account_id` int NOT NULL, + `hash` varchar(32) NOT NULL, + `sent_at` int NOT NULL DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; diff --git a/system/migrations/46.php b/system/migrations/46.php new file mode 100644 index 00000000..452527e5 --- /dev/null +++ b/system/migrations/46.php @@ -0,0 +1,24 @@ +hasColumn('accounts', 'email_hash')) { + $db->dropColumn('accounts', 'email_hash'); + } + + if (!$db->hasTable(TABLE_PREFIX . 'account_emails_verify')) { + $db->query(file_get_contents(__DIR__ . '/46-account_emails_verify.sql')); + } +}; + +$down = function () use ($db) { + if (!$db->hasColumn('accounts', 'email_hash')) { + $db->addColumn('accounts', 'email_hash', "varchar(32) NOT NULL DEFAULT ''"); + } + + if ($db->hasTable(TABLE_PREFIX . 'account_emails_verify')) { + $db->dropTable(TABLE_PREFIX . 'account_emails_verify'); + } +}; diff --git a/system/pages/account/confirm-email.php b/system/pages/account/confirm-email.php index 615dd942..87183a3c 100644 --- a/system/pages/account/confirm-email.php +++ b/system/pages/account/confirm-email.php @@ -9,6 +9,7 @@ */ use MyAAC\Models\Account; +use MyAAC\Models\AccountEmailVerify; defined('MYAAC') or die('Direct access not allowed!'); @@ -20,16 +21,20 @@ if(empty($hash)) { return; } -if(!Account::where('email_hash', $hash)->exists()) { - note("Your email couldn't be verified. Please contact staff to do it manually."); +// by default link is valid for 30 days +$accountEmailVerify = AccountEmailVerify::where('hash', $hash)->where('sent_at', '>', time() - 30 * 24 * 60 * 60)->first(); +if(!$accountEmailVerify) { + note("Wrong link or link has expired."); } else { - $accountModel = Account::where('email_hash', $hash)->where('email_verified', 0)->first(); + $accountModel = Account::where('id', $accountEmailVerify->account_id)->where('email_verified', 0)->first(); if ($accountModel) { $accountModel->email_verified = 1; $accountModel->save(); + AccountEmailVerify::where('account_id', $accountModel->id)->delete(); + success('You have now verified your e-mail, this will increase the security of your account. Thank you for doing this. You can now
    log in.'); $account = new OTS_Account(); @@ -39,6 +44,6 @@ else } } else { - error('Link has expired.'); + error('Your account is already verified.'); } } diff --git a/system/pages/account/create.php b/system/pages/account/create.php index 7a0d3c56..9ffdf6f7 100644 --- a/system/pages/account/create.php +++ b/system/pages/account/create.php @@ -10,6 +10,7 @@ */ use MyAAC\CreateCharacter; +use MyAAC\Models\AccountEmailVerify; defined('MYAAC') or die('Direct access not allowed!'); $title = 'Create Account'; @@ -244,7 +245,12 @@ if($save) if(setting('core.mail_enabled') && setting('core.account_mail_verify')) { $hash = md5(generateRandomString(16, true, true) . $email); - $new_account->setCustomField('email_hash', $hash); + + AccountEmailVerify::create([ + 'account_id' => $new_account->getId(), + 'hash' => $hash, + 'sent_at' => time(), + ]); $verify_url = getLink('account/confirm-email/' . $hash); $body_html = $twig->render('mail.account.verify.html.twig', array( diff --git a/system/pages/account/login.php b/system/pages/account/login.php index d6771c91..e18dacf4 100644 --- a/system/pages/account/login.php +++ b/system/pages/account/login.php @@ -48,7 +48,9 @@ if(!empty($login_account) && !empty($login_password)) ) { if (setting('core.account_mail_verify') && (int)$account_logged->getCustomField('email_verified') !== 1) { - $errors[] = 'Your account is not verified. Please verify your email address. If the message is not coming check the SPAM folder in your E-Mail client.'; + $link = getLink('account/resend-email-verify'); + $errors[] = 'Your account is not verified. Please verify your email address. If the message is not coming check the SPAM folder in your E-Mail client.
    ' . + 'You can resend the Email here: ' . $link . ''; } else { session_regenerate_id(); setSession('account', $account_logged->getId()); diff --git a/system/pages/account/resend-email-verify.php b/system/pages/account/resend-email-verify.php new file mode 100644 index 00000000..ffccb548 --- /dev/null +++ b/system/pages/account/resend-email-verify.php @@ -0,0 +1,94 @@ +display('error_box.html.twig', ['errors' => $errors]); + $twig->display('account.back_button.html.twig', [ + 'action' => getLink('account/resend-email-verify'), + ]); +}; + +if (!setting('core.mail_enabled') || !setting('core.account_mail_verify')) { + $errorWithBackButton('Resending email is not possible on this server.'); + return; +} + +$showForm = true; + +if (isset($_POST['submit']) && $_POST['submit'] == '1') { + $email = $_REQUEST['email']; + + if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) { + $errorWithBackButton('Please enter valid Email.'); + return; + } + + $account = new OTS_Account(); + $account->findByEMail($email); + if ($account->isLoaded()) { + if ($account->getCustomField('email_verified') == '1') { + $errorWithBackButton('This account is already verified! You can log in on the website.'); + return; + } + + $accountEmailVerify = AccountEmailVerify::where('account_id', $account->getId())->orderBy('sent_at', 'DESC')->first(); + if ($accountEmailVerify && time() - $accountEmailVerify->sent_at < 60) { + $errorWithBackButton('Only one Email per minute is allowed. Please try again later.'); + return; + } + + $tmp_account = $email; + if (!config('account_login_by_email')) { + $tmp_account = (USE_ACCOUNT_NAME ? $account->getName() : $account->getId()); + } + + $hash = md5(generateRandomString(16, true, true) . $email); + + AccountEmailVerify::create([ + 'account_id' => $account->getId(), + 'hash' => $hash, + 'sent_at' => time(), + ]); + + $verify_url = getLink('account/confirm-email/' . $hash); + $body_html = $twig->render('mail.account.resend-email-verify.html.twig', array( + 'account' => $tmp_account, + 'verify_url' => generateLink($verify_url, $verify_url, true) + )); + + if (_mail($account->getEMail(), configLua('serverName') . ' - Verify Account', $body_html)) { + $message = "If account with this email exists - you will become an email with verification link."; + $showForm = false; + } else { + $message = "

    An error occurred while sending email ({$email} )! Try again later. For Admin: More info can be found in system/logs/mailer-error.log

    "; + } + } + else { + $message = "
    If account with this email exists - you will become an email with verification link."; + $showForm = false; + } + + $twig->display('success.html.twig', array( + 'title' => 'Verify Email Sent', + 'description' => $message, + )); +} + +//show errors if not empty +if (!empty($errors)) { + $twig->display('error_box.html.twig', ['errors' => $errors]); + $twig->display('account.back_button.html.twig', [ + 'action' => getLink('account/resend-email-verify'), + ]); +} + +if ($showForm) { + $twig->display('account.resend-email-verify.html.twig'); +} diff --git a/system/src/Models/AccountEmailVerify.php b/system/src/Models/AccountEmailVerify.php new file mode 100644 index 00000000..8773750f --- /dev/null +++ b/system/src/Models/AccountEmailVerify.php @@ -0,0 +1,15 @@ +
    +{% set title = 'Resend Email' %} +{% set background = config('darkborder') %} +{% set content %} + + + + + +
    + + + +
    +{% endset %} +{% include 'tables.headline.html.twig' %} +
    + + + + + +
    + + + + +
    + + {{ csrf() }} + + {{ include('buttons.submit.html.twig') }} + +
    +
    + + + + +
    +
    + {{ include('buttons.back.html.twig') }} +
    +
    +
    diff --git a/system/templates/mail.account.resend-email-verify.html.twig b/system/templates/mail.account.resend-email-verify.html.twig new file mode 100644 index 00000000..75bdab8b --- /dev/null +++ b/system/templates/mail.account.resend-email-verify.html.twig @@ -0,0 +1,7 @@ +Hello {{ account }}!
    +
    +You requested to resend the verify Email on {{ config.lua.serverName }}!
    +
    + +To verify your email address please click the link below:
    +{{ verify_url|raw }} From c91bb5d4097647dca2196d3dea87bc90c89181d2 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 12 Oct 2025 21:53:01 +0200 Subject: [PATCH 196/222] Fix guild create with freePremium --- system/pages/guilds/create.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/system/pages/guilds/create.php b/system/pages/guilds/create.php index ef0117e8..ba348a36 100644 --- a/system/pages/guilds/create.php +++ b/system/pages/guilds/create.php @@ -21,6 +21,8 @@ if(!$logged) { $errors[] = 'You are not logged in. You can\'t create guild.'; } +$freePremium = getBoolean(configLua('freePremium')); + $array_of_player_nig = array(); if(empty($errors)) { @@ -31,7 +33,7 @@ if(empty($errors)) if(!$player_rank->isLoaded()) { if($player->getLevel() >= setting('core.guild_need_level')) { - if(!setting('core.guild_need_premium') || $account_logged->isPremium()) { + if(!setting('core.guild_need_premium') || $account_logged->isPremium() || $freePremium) { $array_of_player_nig[] = $player->getName(); } } @@ -95,7 +97,7 @@ if($todo == 'save') if($player->getLevel() < setting('core.guild_need_level')) { $errors[] = 'Character '.$name.' has too low level. To create guild you need character with level ' . setting('core.guild_need_level') . '.'; } - if(setting('core.guild_need_premium') && !$account_logged->isPremium()) { + if(setting('core.guild_need_premium') && !$account_logged->isPremium() && !$freePremium) { $errors[] = 'Character '.$name.' is on FREE account. To create guild you need PREMIUM account.'; } } From 90c846379751ab53b127ab7210efafbcd6353487 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 13 Oct 2025 17:52:39 +0200 Subject: [PATCH 197/222] Update create.php --- system/pages/guilds/create.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/pages/guilds/create.php b/system/pages/guilds/create.php index ba348a36..6921595f 100644 --- a/system/pages/guilds/create.php +++ b/system/pages/guilds/create.php @@ -21,7 +21,8 @@ if(!$logged) { $errors[] = 'You are not logged in. You can\'t create guild.'; } -$freePremium = getBoolean(configLua('freePremium')); +$configLuaFreePremium = configLua('freePremium'); +$freePremium = (isset($configLuaFreePremium) && getBoolean($configLuaFreePremium)) || $account_logged->getPremDays() == OTS_Account::GRATIS_PREMIUM_DAYS; $array_of_player_nig = array(); if(empty($errors)) From b797908e49fe66518f59d8854d939f9b9f8a2e5e Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 13 Oct 2025 17:53:26 +0200 Subject: [PATCH 198/222] Update create.php --- system/pages/guilds/create.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/pages/guilds/create.php b/system/pages/guilds/create.php index 6921595f..08bc8817 100644 --- a/system/pages/guilds/create.php +++ b/system/pages/guilds/create.php @@ -22,7 +22,7 @@ if(!$logged) { } $configLuaFreePremium = configLua('freePremium'); -$freePremium = (isset($configLuaFreePremium) && getBoolean($configLuaFreePremium)) || $account_logged->getPremDays() == OTS_Account::GRATIS_PREMIUM_DAYS; +$freePremium = (isset($configLuaFreePremium) && getBoolean($configLuaFreePremium)) || ($logged && $account_logged->getPremDays() == OTS_Account::GRATIS_PREMIUM_DAYS); $array_of_player_nig = array(); if(empty($errors)) From 82d417b5906c15580bd796fb54099151f3889260 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 13 Oct 2025 18:01:19 +0200 Subject: [PATCH 199/222] Change spaces to tabs --- system/libs/pot/OTS_Account.php | 824 ++++++++++++++++---------------- 1 file changed, 412 insertions(+), 412 deletions(-) diff --git a/system/libs/pot/OTS_Account.php b/system/libs/pot/OTS_Account.php index 20c7fe32..872d1c89 100644 --- a/system/libs/pot/OTS_Account.php +++ b/system/libs/pot/OTS_Account.php @@ -38,7 +38,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @var array * @version 0.1.5 */ - private $data = array('email' => '', 'rlname' => '','location' => '', 'country' => '','web_flags' => 0, 'lastday' => 0, 'premdays' => 0, 'created' => 0); + private $data = array('email' => '', 'rlname' => '','location' => '', 'country' => '','web_flags' => 0, 'lastday' => 0, 'premdays' => 0, 'created' => 0); public static $cache = array(); @@ -66,39 +66,39 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @example examples/create.php create.php * @tutorial POT/Accounts.pkg#create */ - public function createNamed($name = null) - { - // if name is not passed then it will be generated randomly - if( !isset($name) ) - { - // reads already existing names - foreach( $this->db->query('SELECT ' . $this->db->fieldName('name') . ' FROM ' . $this->db->tableName('accounts') )->fetchAll() as $account) - { - $exist[] = $account['name']; - } + public function createNamed($name = null) + { + // if name is not passed then it will be generated randomly + if( !isset($name) ) + { + // reads already existing names + foreach( $this->db->query('SELECT ' . $this->db->fieldName('name') . ' FROM ' . $this->db->tableName('accounts') )->fetchAll() as $account) + { + $exist[] = $account['name']; + } - // initial name - $name = uniqid(); + // initial name + $name = uniqid(); - // repeats until name is unique - while( in_array($name, $exist) ) - { - $name .= '_'; - } + // repeats until name is unique + while( in_array($name, $exist) ) + { + $name .= '_'; + } - // resets array for account numbers loop - $exist = array(); - } + // resets array for account numbers loop + $exist = array(); + } - // saves blank account info - $this->db->exec('INSERT INTO ' . $this->db->tableName('accounts') . ' (' . $this->db->fieldName('name') . ', ' . $this->db->fieldName('password') . ', ' . $this->db->fieldName('email') . ') VALUES (' . $this->db->quote($name) . ', \'\', \'\')'); + // saves blank account info + $this->db->exec('INSERT INTO ' . $this->db->tableName('accounts') . ' (' . $this->db->fieldName('name') . ', ' . $this->db->fieldName('password') . ', ' . $this->db->fieldName('email') . ') VALUES (' . $this->db->quote($name) . ', \'\', \'\')'); - // reads created account's ID - $this->data['id'] = $this->db->lastInsertId(); + // reads created account's ID + $this->data['id'] = $this->db->lastInsertId(); - // return name of newly created account - return $name; - } + // return name of newly created account + return $name; + } /** * @param $email @@ -166,8 +166,8 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws Exception ON lastInsertId error. * @deprecated 0.1.5 Use createNamed(). */ - public function create($name = NULL, $id = NULL) - { + public function create($name = NULL, $id = NULL) + { if(isset($name)) { $nameOrNumber = 'name'; $nameOrNumberValue = $name; @@ -183,8 +183,8 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable } } - // saves blank account info - $this->db->exec('INSERT INTO `accounts` (' . (isset($id) ? '`id`,' : '') . (isset($nameOrNumber) ? '`' . $nameOrNumber . '`,' : '') . '`password`, `email`, `created`) VALUES (' . (isset($id) ? $id . ',' : '') . (isset($nameOrNumber) ? $this->db->quote($nameOrNumberValue) . ',' : '') . ' \'\', \'\',' . time() . ')'); + // saves blank account info + $this->db->exec('INSERT INTO `accounts` (' . (isset($id) ? '`id`,' : '') . (isset($nameOrNumber) ? '`' . $nameOrNumber . '`,' : '') . '`password`, `email`, `created`) VALUES (' . (isset($id) ? $id . ',' : '') . (isset($nameOrNumber) ? $this->db->quote($nameOrNumberValue) . ',' : '') . ' \'\', \'\',' . time() . ')'); if(isset($name)) { $this->data['name'] = $name; @@ -206,8 +206,8 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable throw new Exception(__CLASS__ . ':' . __METHOD__ . ' unexpected error. Please report to MyAAC Developers.'); } - return $this->data['id']; - } + return $this->data['id']; + } /** * @version 0.0.6 @@ -218,10 +218,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @return int Created account number. * @deprecated 0.0.6 There is no more group_id field in database, use create(). */ - public function createEx(OTS_Group $group, $min = 1, $max = 9999999) - { - return $this->create($min, $max); - } + public function createEx(OTS_Group $group, $min = 1, $max = 9999999) + { + return $this->create($min, $max); + } /** * Loads account with given number. @@ -230,8 +230,8 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @param int $id Account number. * @throws PDOException On PDO operation error. */ - public function load($id, $fresh = false) - { + public function load($id, $fresh = false) + { if(!$fresh && isset(self::$cache[$id])) { $this->data = self::$cache[$id]; return; @@ -244,10 +244,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable $nameOrNumber = '`number`,'; } - // SELECT query on database + // SELECT query on database $this->data = $this->db->query('SELECT `id`, ' . $nameOrNumber . '`password`, `email`, `rlname`, `location`, `country`, `web_flags`, ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays`, ' : '') . ($this->db->hasColumn('accounts', 'lastday') ? '`lastday`, ' : ($this->db->hasColumn('accounts', 'premend') ? '`premend`,' : ($this->db->hasColumn('accounts', 'premium_ends_at') ? '`premium_ends_at`,' : ''))) . '`created` FROM `accounts` WHERE `id` = ' . (int) $id)->fetch(); self::$cache[$id] = $this->data; - } + } /** * Loads account by it's name. @@ -261,22 +261,22 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @param string $name Account's name. * @throws PDOException On PDO operation error. */ - public function find($name) - { + public function find($name) + { $nameOrNumberColumn = 'name'; if (USE_ACCOUNT_NUMBER) { $nameOrNumberColumn = 'number'; } - // finds player's ID - $id = $this->db->query('SELECT `id` FROM `accounts` WHERE `' . $nameOrNumberColumn . '` = ' . $this->db->quote($name) )->fetch(); + // finds player's ID + $id = $this->db->query('SELECT `id` FROM `accounts` WHERE `' . $nameOrNumberColumn . '` = ' . $this->db->quote($name) )->fetch(); - // if anything was found - if( isset($id['id']) ) - { - $this->load($id['id']); - } - } + // if anything was found + if( isset($id['id']) ) + { + $this->load($id['id']); + } + } /** * Loads account by it's e-mail address. @@ -286,27 +286,27 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @param string $email Account's e-mail address. * @throws PDOException On PDO operation error. */ - public function findByEMail($email) - { - // finds player's ID - $id = $this->db->query('SELECT `id` FROM `accounts` WHERE `email` = ' . $this->db->quote($email) )->fetch(); + public function findByEMail($email) + { + // finds player's ID + $id = $this->db->query('SELECT `id` FROM `accounts` WHERE `email` = ' . $this->db->quote($email) )->fetch(); - // if anything was found - if( isset($id['id']) ) - { - $this->load($id['id']); - } - } + // if anything was found + if( isset($id['id']) ) + { + $this->load($id['id']); + } + } /** * Checks if object is loaded. * * @return bool Load state. */ - public function isLoaded() - { - return isset($this->data['id']); - } + public function isLoaded() + { + return isset($this->data['id']); + } /** * Updates account in database. @@ -323,16 +323,16 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws E_OTS_NotLoaded If account doesn't have ID assigned. * @throws PDOException On PDO operation error. */ - public function save() - { - if( !isset($this->data['id']) ) - { - throw new E_OTS_NotLoaded(); - } + public function save() + { + if( !isset($this->data['id']) ) + { + throw new E_OTS_NotLoaded(); + } $field = 'lastday'; if($this->db->hasColumn('accounts', 'premend')) { // othire - $field = 'premend'; + $field = 'premend'; if(!isset($this->data['premend'])) { $this->data['premend'] = 0; } @@ -344,9 +344,9 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable } } - // UPDATE query on database - $this->db->exec('UPDATE `accounts` SET ' . ($this->db->hasColumn('accounts', 'name') ? '`name` = ' . $this->db->quote($this->data['name']) . ',' : '') . '`password` = ' . $this->db->quote($this->data['password']) . ', `email` = ' . $this->db->quote($this->data['email']) . ', `rlname` = ' . $this->db->quote($this->data['rlname']) . ', `location` = ' . $this->db->quote($this->data['location']) . ', `country` = ' . $this->db->quote($this->data['country']) . ', `web_flags` = ' . (int) $this->data['web_flags'] . ', ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays` = ' . (int) $this->data['premdays'] . ',' : '') . '`' . $field . '` = ' . (int) $this->data[$field] . ' WHERE `id` = ' . $this->data['id']); - } + // UPDATE query on database + $this->db->exec('UPDATE `accounts` SET ' . ($this->db->hasColumn('accounts', 'name') ? '`name` = ' . $this->db->quote($this->data['name']) . ',' : '') . '`password` = ' . $this->db->quote($this->data['password']) . ', `email` = ' . $this->db->quote($this->data['email']) . ', `rlname` = ' . $this->db->quote($this->data['rlname']) . ', `location` = ' . $this->db->quote($this->data['location']) . ', `country` = ' . $this->db->quote($this->data['country']) . ', `web_flags` = ' . (int) $this->data['web_flags'] . ', ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays` = ' . (int) $this->data['premdays'] . ',' : '') . '`' . $field . '` = ' . (int) $this->data[$field] . ' WHERE `id` = ' . $this->data['id']); + } /** * Account number. @@ -359,15 +359,15 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @return int Account number. * @throws E_OTS_NotLoaded If account is not loaded. */ - public function getId() - { - if( !isset($this->data['id']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getId() + { + if( !isset($this->data['id']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['id']; - } + return $this->data['id']; + } public function getNumber() { @@ -378,45 +378,45 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable return $this->data['id']; } - public function getRLName() - { - if( !isset($this->data['rlname']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getRLName() + { + if( !isset($this->data['rlname']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['rlname']; - } + return $this->data['rlname']; + } - public function getLocation() - { - if( !isset($this->data['location']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getLocation() + { + if( !isset($this->data['location']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['location']; - } + return $this->data['location']; + } - public function getCountry() - { - if( !isset($this->data['country']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getCountry() + { + if( !isset($this->data['country']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['country']; - } + return $this->data['country']; + } - public function getWebFlags() - { - if( !isset($this->data['web_flags']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getWebFlags() + { + if( !isset($this->data['web_flags']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['web_flags']; - } + return $this->data['web_flags']; + } public function hasFlag($flag) { @@ -462,17 +462,17 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable } public function getLastLogin() - { - if( !isset($this->data['lastday']) ) - { - throw new E_OTS_NotLoaded(); - } + { + if( !isset($this->data['lastday']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['lastday']; - } + return $this->data['lastday']; + } - public function isPremium() - { + public function isPremium() + { if(isset($this->data['premium_ends_at'])) { return $this->data['premium_ends_at'] > time(); } @@ -484,15 +484,15 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable return ($this->data['premdays'] - (date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->data['lastday']))) - date("z", $this->data['lastday'])) > 0); } - public function getCreated() - { - if( !isset($this->data['created']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getCreated() + { + if( !isset($this->data['created']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['created']; - } + return $this->data['created']; + } /** * Name. @@ -501,37 +501,37 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @since 0.7.5 * @throws E_OTS_NotLoaded If account is not loaded. */ - public function setPremDays($premdays) - { + public function setPremDays($premdays) + { $this->data['premdays'] = (int) $premdays; $this->data['premend'] = time() + ($premdays * 24 * 60 * 60); $this->data['premium_ends_at'] = time() + ($premdays * 24 * 60 * 60); - } + } - public function setRLName($name) - { - $this->data['rlname'] = (string) $name; - } + public function setRLName($name) + { + $this->data['rlname'] = (string) $name; + } - public function setLocation($location) - { - $this->data['location'] = (string) $location; - } + public function setLocation($location) + { + $this->data['location'] = (string) $location; + } - public function setCountry($country) - { - $this->data['country'] = (string) $country; - } + public function setCountry($country) + { + $this->data['country'] = (string) $country; + } public function setLastLogin($lastlogin) - { - $this->data['lastday'] = (int) $lastlogin; - } + { + $this->data['lastday'] = (int) $lastlogin; + } - public function setWebFlags($webflags) - { - $this->data['web_flags'] = (int) $webflags; - } + public function setWebFlags($webflags) + { + $this->data['web_flags'] = (int) $webflags; + } /** * Name. @@ -541,15 +541,15 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @return string Name. * @throws E_OTS_NotLoaded If account is not loaded. */ - public function getName() - { - if( !isset($this->data['name']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getName() + { + if( !isset($this->data['name']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['name']; - } + return $this->data['name']; + } /** * Sets account's name. @@ -562,10 +562,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @since 0.1.5 * @param string $name Account name. */ - public function setName($name) - { - $this->data['name'] = (string) $name; - } + public function setName($name) + { + $this->data['name'] = (string) $name; + } /** * Account's password. @@ -582,15 +582,15 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @return string Password. * @throws E_OTS_NotLoaded If account is not loaded. */ - public function getPassword() - { - if( !isset($this->data['password']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getPassword() + { + if( !isset($this->data['password']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['password']; - } + return $this->data['password']; + } /** * Sets account's password. @@ -605,10 +605,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * * @param string $password Password. */ - public function setPassword($password) - { - $this->data['password'] = (string) $password; - } + public function setPassword($password) + { + $this->data['password'] = (string) $password; + } /** * E-mail address. * @@ -620,15 +620,15 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @return string E-mail. * @throws E_OTS_NotLoaded If account is not loaded. */ - public function getEMail() - { - if( !isset($this->data['email']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getEMail() + { + if( !isset($this->data['email']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['email']; - } + return $this->data['email']; + } /** * Sets account's email. @@ -639,10 +639,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * * @param string $email E-mail address. */ - public function setEMail($email) - { - $this->data['email'] = (string) $email; - } + public function setEMail($email) + { + $this->data['email'] = (string) $email; + } /** * Reads custom field. @@ -662,16 +662,16 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws E_OTS_NotLoaded If account is not loaded. * @throws PDOException On PDO operation error. */ - public function getCustomField($field) - { - if( !isset($this->data['id']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getCustomField($field) + { + if( !isset($this->data['id']) ) + { + throw new E_OTS_NotLoaded(); + } - $value = $this->db->query('SELECT ' . $this->db->fieldName($field) . ' FROM ' . $this->db->tableName('accounts') . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id'])->fetch(); - return $value[$field]; - } + $value = $this->db->query('SELECT ' . $this->db->fieldName($field) . ' FROM ' . $this->db->tableName('accounts') . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id'])->fetch(); + return $value[$field]; + } /** * Writes custom field. @@ -695,20 +695,20 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws E_OTS_NotLoaded If account is not loaded. * @throws PDOException On PDO operation error. */ - public function setCustomField($field, $value) - { - if( !isset($this->data['id']) ) - { - throw new E_OTS_NotLoaded(); - } + public function setCustomField($field, $value) + { + if( !isset($this->data['id']) ) + { + throw new E_OTS_NotLoaded(); + } - // quotes value for SQL query - if(!( is_int($value) || is_float($value) )) - { - $value = $this->db->quote($value); - } - $this->db->exec('UPDATE ' . $this->db->tableName('accounts') . ' SET ' . $this->db->fieldName($field) . ' = ' . $value . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id']); - } + // quotes value for SQL query + if(!( is_int($value) || is_float($value) )) + { + $value = $this->db->quote($value); + } + $this->db->exec('UPDATE ' . $this->db->tableName('accounts') . ' SET ' . $this->db->fieldName($field) . ' = ' . $value . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id']); + } /** * @version 0.1.0 @@ -716,25 +716,25 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws E_OTS_NotLoaded If account is not loaded. * @deprecated 0.0.5 Use getPlayersList(). */ - public function getPlayers() - { - if( !isset($this->data['id']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getPlayers() + { + if( !isset($this->data['id']) ) + { + throw new E_OTS_NotLoaded(); + } - $players = array(); + $players = array(); - foreach( $this->db->query('SELECT ' . $this->db->fieldName('id') . ' FROM ' . $this->db->tableName('players') . ' WHERE ' . $this->db->fieldName('account_id') . ' = ' . $this->data['id'])->fetchAll() as $player) - { - // creates new object - $object = new OTS_Player(); - $object->load($player['id']); - $players[] = $object; - } + foreach( $this->db->query('SELECT ' . $this->db->fieldName('id') . ' FROM ' . $this->db->tableName('players') . ' WHERE ' . $this->db->fieldName('account_id') . ' = ' . $this->data['id'])->fetchAll() as $player) + { + // creates new object + $object = new OTS_Player(); + $object->load($player['id']); + $players[] = $object; + } - return $players; - } + return $players; + } /** * List of characters on account. @@ -752,16 +752,16 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @return OTS_Players_List List of players from current account. * @throws E_OTS_NotLoaded If account is not loaded. */ - public function getPlayersList($withDeleted = true) - { - if( !isset($this->data['id']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getPlayersList($withDeleted = true) + { + if( !isset($this->data['id']) ) + { + throw new E_OTS_NotLoaded(); + } - // creates filter - $filter = new OTS_SQLFilter(); - $filter->compareField('account_id', (int) $this->data['id']); + // creates filter + $filter = new OTS_SQLFilter(); + $filter->compareField('account_id', (int) $this->data['id']); if(!$withDeleted) { global $db; @@ -772,12 +772,12 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable } } - // creates list object - $list = new OTS_Players_List(); - $list->setFilter($filter); + // creates list object + $list = new OTS_Players_List(); + $list->setFilter($filter); - return $list; - } + return $list; + } /** * @version 0.1.5 @@ -786,22 +786,22 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws PDOException On PDO operation error. * @deprecated 0.1.5 Use OTS_AccountBan class. */ - public function ban($time = 0) - { - // can't ban nothing - if( !$this->isLoaded() ) - { - throw new E_OTS_NotLoaded(); - } + public function ban($time = 0) + { + // can't ban nothing + if( !$this->isLoaded() ) + { + throw new E_OTS_NotLoaded(); + } - // creates ban entry - $ban = new OTS_AccountBan(); - $ban->setValue($this->data['id']); - $ban->setExpires($time); - $ban->setAdded( time() ); - $ban->activate(); - $ban->save(); - } + // creates ban entry + $ban = new OTS_AccountBan(); + $ban->setValue($this->data['id']); + $ban->setExpires($time); + $ban->setAdded( time() ); + $ban->activate(); + $ban->save(); + } /** * @version 0.1.5 @@ -809,19 +809,19 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws PDOException On PDO operation error. * @deprecated 0.1.5 Use OTS_AccountBan class. */ - public function unban() - { - // can't unban nothing - if( !$this->isLoaded() ) - { - throw new E_OTS_NotLoaded(); - } + public function unban() + { + // can't unban nothing + if( !$this->isLoaded() ) + { + throw new E_OTS_NotLoaded(); + } - // deletes ban entry - $ban = new OTS_AccountBan(); - $ban->find($this->data['id']); - $ban->delete(); - } + // deletes ban entry + $ban = new OTS_AccountBan(); + $ban->find($this->data['id']); + $ban->delete(); + } /** * @version 0.1.5 @@ -830,37 +830,37 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws PDOException On PDO operation error. * @deprecated 0.1.5 Use OTS_AccountBan class. */ - public function isBanned() - { - // nothing can't be banned - if( !$this->isLoaded() ) - { - throw new E_OTS_NotLoaded(); - } + public function isBanned() + { + // nothing can't be banned + if( !$this->isLoaded() ) + { + throw new E_OTS_NotLoaded(); + } if( !isset($this->data['banned']) ) $this->loadBan(); - return ($this->data['banned'] === true); - } + return ($this->data['banned'] === true); + } - public function getBanTime() - { - // nothing can't be banned - if( !$this->isLoaded() ) - { - throw new E_OTS_NotLoaded(); - } + public function getBanTime() + { + // nothing can't be banned + if( !$this->isLoaded() ) + { + throw new E_OTS_NotLoaded(); + } if( !isset($this->data['banned_time']) ) $this->loadBan(); - return $this->data['banned_time']; - } + return $this->data['banned_time']; + } - public function loadBan() - { - // nothing can't be banned - if( !$this->isLoaded() ) - { - throw new E_OTS_NotLoaded(); - } + public function loadBan() + { + // nothing can't be banned + if( !$this->isLoaded() ) + { + throw new E_OTS_NotLoaded(); + } if($this->db->hasTable('account_bans')) { $ban = $this->db->query('SELECT `expires_at` FROM `account_bans` WHERE `account_id` = ' . $this->data['id'] . ' AND (`expires_at` > ' . time() .' OR `expires_at` = -1) ORDER BY `expires_at` DESC')->fetch(); @@ -883,7 +883,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable $this->data['banned'] = false; $this->data['banned_time'] = 0; } - } + } /** * Deletes account. @@ -897,19 +897,19 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws E_OTS_NotLoaded If account is not loaded. * @throws PDOException On PDO operation error. */ - public function delete() - { - if( !isset($this->data['id']) ) - { - throw new E_OTS_NotLoaded(); - } + public function delete() + { + if( !isset($this->data['id']) ) + { + throw new E_OTS_NotLoaded(); + } - // deletes row from database - $this->db->exec('DELETE FROM ' . $this->db->tableName('accounts') . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id']); + // deletes row from database + $this->db->exec('DELETE FROM ' . $this->db->tableName('accounts') . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id']); - // resets object handle - unset($this->data['id']); - } + // resets object handle + unset($this->data['id']); + } /** * Checks highest access level of account. @@ -917,10 +917,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @return int Access level (highest access level of all characters). * @throws PDOException On PDO operation error. */ - public function getAccess() - { + public function getAccess() + { return $this->getGroupId(); - } + } public function getGroupId() { @@ -982,25 +982,25 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @return int Access level (highest access level of all characters). * @throws PDOException On PDO operation error. */ - public function getGuildAccess(OTS_Guild $guild) - { - // by default - $access = 0; + public function getGuildAccess(OTS_Guild $guild) + { + // by default + $access = 0; - // finds ranks of all characters - foreach($this->getPlayersList(false) as $player) - { - $rank = $player->getRank(); + // finds ranks of all characters + foreach($this->getPlayersList(false) as $player) + { + $rank = $player->getRank(); - // checks if rank's access level is higher then previouls found highest - if( isset($rank) && $rank->isLoaded() && $rank->getGuild()->getId() == $guild->getId() && $rank->getLevel() > $access) - { - $access = $rank->getLevel(); - } - } + // checks if rank's access level is higher then previouls found highest + if( isset($rank) && $rank->isLoaded() && $rank->getGuild()->getId() == $guild->getId() && $rank->getLevel() > $access) + { + $access = $rank->getLevel(); + } + } - return $access; - } + return $access; + } public function logAction($action) { @@ -1039,10 +1039,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @return Iterator List of players. */ #[\ReturnTypeWillChange] - public function getIterator() - { - return $this->getPlayersList(); - } + public function getIterator() + { + return $this->getPlayersList(); + } /** * Returns number of player within. @@ -1053,10 +1053,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws PDOException On PDO operation error. * @return int Count of players. */ - public function count(): int - { - return $this->getPlayersList()->count(); - } + public function count(): int + { + return $this->getPlayersList()->count(); + } /** * Magic PHP5 method. @@ -1069,44 +1069,44 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws OutOfBoundsException For non-supported properties. * @throws PDOException On PDO operation error. */ - public function __get($name) - { - switch($name) - { - case 'id': - return $this->getId(); + public function __get($name) + { + switch($name) + { + case 'id': + return $this->getId(); - case 'name': - return $this->getName(); + case 'name': + return $this->getName(); - case 'password': - return $this->getPassword(); + case 'password': + return $this->getPassword(); - case 'eMail': - return $this->getEMail(); + case 'eMail': + return $this->getEMail(); - case 'premiumEnd': - return $this->getPremiumEnd(); + case 'premiumEnd': + return $this->getPremiumEnd(); - case 'loaded': - return $this->isLoaded(); + case 'loaded': + return $this->isLoaded(); - case 'playersList': - return $this->getPlayersList(); + case 'playersList': + return $this->getPlayersList(); - case 'deleted': - return $this->isDeleted(); + case 'deleted': + return $this->isDeleted(); - case 'banned': - return $this->isBanned(); + case 'banned': + return $this->isBanned(); - case 'access': - return $this->getAccess(); + case 'access': + return $this->getAccess(); - default: - throw new OutOfBoundsException(); - } - } + default: + throw new OutOfBoundsException(); + } + } /** * Magic PHP5 method. @@ -1119,52 +1119,52 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws OutOfBoundsException For non-supported properties. * @throws PDOException On PDO operation error. */ - public function __set($name, $value) - { - switch($name) - { - case 'name': - $this->setName($name); - break; + public function __set($name, $value) + { + switch($name) + { + case 'name': + $this->setName($name); + break; - case 'password': - $this->setPassword($value); - break; + case 'password': + $this->setPassword($value); + break; - case 'eMail': - $this->setEMail($value); - break; + case 'eMail': + $this->setEMail($value); + break; - case 'premiumEnd': - $this->setPremiumEnd($value); - break; + case 'premiumEnd': + $this->setPremiumEnd($value); + break; - case 'deleted': - if($value) - { - $this->setDeleted(); - } - else - { - $this->unsetDeleted(); - } - break; + case 'deleted': + if($value) + { + $this->setDeleted(); + } + else + { + $this->unsetDeleted(); + } + break; - case 'banned': - if($value) - { - $this->ban(); - } - else - { - $this->unban(); - } - break; + case 'banned': + if($value) + { + $this->ban(); + } + else + { + $this->unban(); + } + break; - default: - throw new OutOfBoundsException(); - } - } + default: + throw new OutOfBoundsException(); + } + } /** * Returns string representation of object. @@ -1177,18 +1177,18 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @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->isDisplayDriverLoaded() ) - { - return $ots->getDisplayDriver()->displayAccount($this); - } + // checks if display driver is loaded + if( $ots->isDisplayDriverLoaded() ) + { + return $ots->getDisplayDriver()->displayAccount($this); + } - return $this->getId(); - } + return $this->getId(); + } } /**#@-*/ From c88b08eb1ec1f560cbfdaaa16b24e3a0f26da7b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Morais?= Date: Wed, 15 Oct 2025 06:46:52 -0300 Subject: [PATCH 200/222] feature: show vip days in account management (#334) * feature: show vip days in account management This feature causes VIP days to be shown in account management when vipSystemEnabled is true in the canary config.lua * Some fixes & adjustments * If freePremium = true and vipEnabled = show gratis VIP * Revert to previous version --------- Co-authored-by: slawkens --- system/pages/account/manage.php | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/system/pages/account/manage.php b/system/pages/account/manage.php index 3776a732..b74f7bd8 100644 --- a/system/pages/account/manage.php +++ b/system/pages/account/manage.php @@ -38,15 +38,24 @@ csrfProtect(); $groups = new OTS_Groups_List(); -$freePremium = isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium']) || $account_logged->getPremDays() == OTS_Account::GRATIS_PREMIUM_DAYS; -$dayOrDays = $account_logged->getPremDays() == 1 ? 'day' : 'days'; /** * @var OTS_Account $account_logged */ -if(!$account_logged->isPremium()) +$premDays = $account_logged->getPremDays(); + +$freePremium = isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium']) || $premDays == OTS_Account::GRATIS_PREMIUM_DAYS; +$dayOrDays = ($premDays == 1 ? 'day' : 'days'); + +$vipSystemEnabled = isset($config['lua']['vipSystemEnabled']) && getBoolean($config['lua']['vipSystemEnabled']); +$premiumLabel = $vipSystemEnabled ? 'VIP' : 'Premium Account'; + +if ($freePremium && !$vipSystemEnabled) { + $account_status = 'Gratis Premium Account'; +} else if(!$account_logged->isPremium()) { $account_status = 'Free Account'; -else - $account_status = '' . ($freePremium ? 'Gratis Premium Account' : 'Premium Account, ' . $account_logged->getPremDays() . ' '.$dayOrDays.' left') . ''; +} else { + $account_status = '' . $premiumLabel . ', ' . $premDays . ' '.$dayOrDays.' left'; +} $recovery_key = $account_logged->getCustomField('key'); if(empty($recovery_key)) From 3e61692780d4add93b7b0e9f12f7a283bd8f4b7a Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 15 Oct 2025 15:49:58 +0200 Subject: [PATCH 201/222] Fix premDays count in canary --- system/functions.php | 6 ++++++ system/libs/pot/OTS_Account.php | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/system/functions.php b/system/functions.php index 212a043e..b3f1189f 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1704,6 +1704,12 @@ function getAccountIdentityColumn(): string return 'id'; } +function isCanary(): bool +{ + $vipSystemEnabled = configLua('vipSystemEnabled'); + return isset($vipSystemEnabled); +} + // validator functions require_once SYSTEM . 'compat/base.php'; diff --git a/system/libs/pot/OTS_Account.php b/system/libs/pot/OTS_Account.php index 872d1c89..5cee25a4 100644 --- a/system/libs/pot/OTS_Account.php +++ b/system/libs/pot/OTS_Account.php @@ -449,6 +449,11 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable return max($ret, 0); } + if (isCanary() && isset($this->data['lastday'])) { + $ret = ceil(($this->data['lastday'] - time()) / 86400); + return $ret > 0 ? $ret : 0; + } + if($this->data['premdays'] == 0) { return 0; } From 38902c30d114fdbce259467f5820f97037b393e9 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 15 Oct 2025 15:50:22 +0200 Subject: [PATCH 202/222] Comment code to update lastday --- login.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/login.php b/login.php index d4d25529..438754e2 100644 --- a/login.php +++ b/login.php @@ -220,6 +220,8 @@ switch ($action) { } } + /* + * not needed anymore? if (fieldExist('premdays', 'accounts') && fieldExist('lastday', 'accounts')) { $save = false; $timeNow = time(); @@ -256,6 +258,7 @@ switch ($action) { $account->save(); } } + */ $worlds = [$world]; $playdata = compact('worlds', 'characters'); From 12e40b2592ee4bb3a80a17158f5e2aa16142baac Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 15 Oct 2025 15:50:25 +0200 Subject: [PATCH 203/222] Update functions.php --- system/functions.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/system/functions.php b/system/functions.php index b3f1189f..582f9c30 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1640,13 +1640,14 @@ function camelCaseToUnderscore($input) return ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_'); } -function removeIfFirstSlash(&$text) { +function removeIfFirstSlash(&$text): void +{ if(strpos($text, '/') === 0) { $text = str_replace_first('/', '', $text); } }; -function escapeHtml($html) { +function escapeHtml($html): string { return htmlspecialchars($html); } @@ -1660,7 +1661,7 @@ function getGuildNameById($id) return false; } -function getGuildLogoById($id) +function getGuildLogoById($id): string { $logo = 'default.gif'; @@ -1676,7 +1677,8 @@ function getGuildLogoById($id) return BASE_URL . GUILD_IMAGES_DIR . $logo; } -function displayErrorBoxWithBackButton($errors, $action = null) { +function displayErrorBoxWithBackButton($errors, $action = null): void +{ global $twig; $twig->display('error_box.html.twig', ['errors' => $errors]); $twig->display('account.back_button.html.twig', [ From 7f60b3d31d53addb806631dd9edd5ac0e4c79d54 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 15 Oct 2025 15:59:49 +0200 Subject: [PATCH 204/222] Add same code in Models\Account + Optimize code --- system/libs/pot/OTS_Account.php | 11 ++++++----- system/src/Models/Account.php | 9 +++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/system/libs/pot/OTS_Account.php b/system/libs/pot/OTS_Account.php index 5cee25a4..a5007e3b 100644 --- a/system/libs/pot/OTS_Account.php +++ b/system/libs/pot/OTS_Account.php @@ -443,15 +443,16 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable throw new E_OTS_NotLoaded(); } - if(isset($this->data['premium_ends_at']) || isset($this->data['premend'])) { - $col = isset($this->data['premium_ends_at']) ? 'premium_ends_at' : 'premend'; - $ret = ceil(($this->data[$col] - time()) / (24 * 60 * 60)); - return max($ret, 0); + if(isset($this->data['premium_ends_at']) || isset($this->data['premend']) || + (isCanary() && isset($this->data['lastday']))) { + $col = (isset($this->premium_ends_at) ? 'premium_ends_at' : (isset($this->data['lastday']) ? 'lastday' : 'premend')); + $ret = ceil(($this->data[$col] - time()) / (24 * 60 * 60)); + return max($ret, 0); } if (isCanary() && isset($this->data['lastday'])) { $ret = ceil(($this->data['lastday'] - time()) / 86400); - return $ret > 0 ? $ret : 0; + return max($ret, 0); } if($this->data['premdays'] == 0) { diff --git a/system/src/Models/Account.php b/system/src/Models/Account.php index f0bd435f..fdd7d540 100644 --- a/system/src/Models/Account.php +++ b/system/src/Models/Account.php @@ -33,10 +33,11 @@ class Account extends Model { public function getPremiumDaysAttribute() { - if(isset($this->premium_ends_at) || isset($this->premend)) { - $col = isset($this->premium_ends_at) ? 'premium_ends_at' : 'premend'; - $ret = ceil(($this->{$col}- time()) / (24 * 60 * 60)); - return $ret > 0 ? $ret : 0; + if(isset($this->premium_ends_at) || isset($this->premend) || + (isCanary() && isset($this->data['lastday']))) { + $col = (isset($this->premium_ends_at) ? 'premium_ends_at' : (isset($this->data['lastday']) ? 'lastday' : 'premend')); + $ret = ceil(($this->{$col}- time()) / (24 * 60 * 60)); + return max($ret, 0); } if($this->premdays == 0) { From 470555f2687809a0c12491bbb27597e64b8929c1 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 16 Oct 2025 21:22:49 +0200 Subject: [PATCH 205/222] New hooks for account/change-password HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_OLD_PASSWORD + HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_NEW_PASSWORD --- system/src/global.php | 2 ++ system/templates/account.change-password.html.twig | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/system/src/global.php b/system/src/global.php index 8f1885f3..85f9476d 100644 --- a/system/src/global.php +++ b/system/src/global.php @@ -28,6 +28,8 @@ define('HOOK_CHARACTERS_AFTER_CHARACTERS', ++$i); define('HOOK_LOGIN', ++$i); define('HOOK_LOGIN_ATTEMPT', ++$i); define('HOOK_LOGOUT', ++$i); +define('HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_OLD_PASSWORD', ++$i); +define('HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_NEW_PASSWORD', ++$i); define('HOOK_ACCOUNT_CHANGE_PASSWORD_POST', ++$i); define('HOOK_ACCOUNT_CREATE_BEFORE_FORM', ++$i); define('HOOK_ACCOUNT_CREATE_BEFORE_BOXES', ++$i); diff --git a/system/templates/account.change-password.html.twig b/system/templates/account.change-password.html.twig index df101323..db2c1f74 100644 --- a/system/templates/account.change-password.html.twig +++ b/system/templates/account.change-password.html.twig @@ -12,6 +12,9 @@ Please enter your current password and a new password. For your security, please + + {{ hook('HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_OLD_PASSWORD') }} + New Password: @@ -20,6 +23,9 @@ Please enter your current password and a new password. For your security, please + + {{ hook('HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_NEW_PASSWORD') }} + New Password Again: From 16849e7578321c92bec12674e5bf46ad4d38140f Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 16 Oct 2025 21:36:14 +0200 Subject: [PATCH 206/222] account/change-password refactor a bit Add "The old password is same as the new password!" Better post variables names --- system/pages/account/change-password.php | 18 ++++++++++-------- .../account.change-password.html.twig | 6 +++--- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/system/pages/account/change-password.php b/system/pages/account/change-password.php index 35058d3d..157515b7 100644 --- a/system/pages/account/change-password.php +++ b/system/pages/account/change-password.php @@ -19,18 +19,17 @@ if(!$logged) { csrfProtect(); -$new_password = $_POST['newpassword'] ?? NULL; -$new_password_confirm = $_POST['newpassword_confirm'] ?? NULL; -$old_password = $_POST['oldpassword'] ?? NULL; +$new_password = $_POST['new_password'] ?? null; +$new_password_confirm = $_POST['new_password_confirm'] ?? null; +$old_password = $_POST['old_password'] ?? null; if(empty($new_password) && empty($new_password_confirm) && empty($old_password)) { $twig->display('account.change-password.html.twig'); } -else -{ +else { if(empty($new_password) || empty($new_password_confirm) || empty($old_password)){ $errors[] = 'Please fill in form.'; } - $password_strlen = strlen($new_password); + if($new_password != $new_password_confirm) { $errors[] = 'The new passwords do not match!'; } @@ -41,10 +40,13 @@ else } /** @var OTS_Account $account_logged */ - $old_password = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $old_password); - if($old_password != $account_logged->getPassword()) { + $old_password_hashed = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $old_password); + if($old_password_hashed != $account_logged->getPassword()) { $errors[] = 'Current password is incorrect!'; } + else if ($old_password == $new_password) { + $errors[] = 'The old password is same as the new password!'; + } $hooks->trigger(HOOK_ACCOUNT_CHANGE_PASSWORD_POST); } diff --git a/system/templates/account.change-password.html.twig b/system/templates/account.change-password.html.twig index db2c1f74..03f82d9b 100644 --- a/system/templates/account.change-password.html.twig +++ b/system/templates/account.change-password.html.twig @@ -9,7 +9,7 @@ Please enter your current password and a new password. For your security, please Current Password: - + @@ -20,7 +20,7 @@ Please enter your current password and a new password. For your security, please New Password: - + @@ -31,7 +31,7 @@ Please enter your current password and a new password. For your security, please New Password Again: - + From 89fae38caa7e4f645957fcf1a9330a36358ac04f Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 21 Oct 2025 12:18:56 +0200 Subject: [PATCH 207/222] Ignore set last visit for AJAX pages - Fixes template change redirect --- admin/tools/phpinfo.php | 3 ++- admin/tools/reload_data.php | 1 + admin/tools/settings_save.php | 1 + admin/tools/status.php | 3 ++- admin/tools/upload_image.php | 3 ++- system/login.php | 10 ++++++---- tools/generate_account_number.php | 2 ++ tools/status.php | 3 +++ tools/validate.php | 2 ++ 9 files changed, 21 insertions(+), 7 deletions(-) diff --git a/admin/tools/phpinfo.php b/admin/tools/phpinfo.php index cd043279..bd09fb5d 100644 --- a/admin/tools/phpinfo.php +++ b/admin/tools/phpinfo.php @@ -1,5 +1,6 @@ addGlobal('account_logged', $account_logged); } -setSession('last_visit', time()); -if(defined('PAGE')) { - setSession('last_page', PAGE); +if (!defined('IGNORE_SET_LAST_VISIT') || !IGNORE_SET_LAST_VISIT) { + setSession('last_visit', time()); + if(defined('PAGE')) { + setSession('last_page', PAGE); + } + setSession('last_uri', $_SERVER['REQUEST_URI']); } -setSession('last_uri', $_SERVER['REQUEST_URI']); diff --git a/tools/generate_account_number.php b/tools/generate_account_number.php index a53ba9a3..643bb2c2 100644 --- a/tools/generate_account_number.php +++ b/tools/generate_account_number.php @@ -9,6 +9,8 @@ * @link https://my-aac.org */ +const IGNORE_SET_LAST_VISIT = true; + // we need some functions require '../common.php'; require SYSTEM . 'functions.php'; diff --git a/tools/status.php b/tools/status.php index ae0ee49d..9e9c8a29 100644 --- a/tools/status.php +++ b/tools/status.php @@ -1,4 +1,7 @@ Date: Tue, 21 Oct 2025 17:18:07 +0200 Subject: [PATCH 208/222] Release v1.8.3 --- CHANGELOG-1.x.md | 25 +++++++++++++++++++++++++ common.php | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index 17e2a06e..8779d2c5 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,30 @@ # Changelog +## [1.8.3 - 21.10.2025] + +### Added +* Feature: resend email verify (https://github.com/slawkens/myaac/commit/fe821c58085483e70491dcf76376ad5b96de3fdd) +* New config: hooks_debug (To view where hooks are located in .twig files) (https://github.com/slawkens/myaac/commit/8c3cb0e06f9709c1de3398b48221241e7cbdd310) +* Functions: Add db->getColumnInfo(table, column) (https://github.com/slawkens/myaac/commit/c898fe25efff6793a01d11c26fc153cb23fcb858) +* Plugins: Add option to use ?subtopic=x for plugins pages (https://github.com/slawkens/myaac/commit/97f9d3d6f6c28aef6d824973058d7133f56e09c4) +* getTopPlayers() Function - Add lookmount & promotion (https://github.com/slawkens/myaac/commit/2da0024c68f1cedc38a16ebbc6f52ffa55e65f7a, https://github.com/slawkens/myaac/commit/901df48d134079d648a18f9d82b60182e818ac02) +* New hooks for account/change-password (https://github.com/slawkens/myaac/commit/470555f2687809a0c12491bbb27597e64b8929c1) + +### Changed +* Feature: show vip days in account management (https://github.com/slawkens/myaac/commit/c88b08eb1ec1f560cbfdaaa16b24e3a0f26da7b3, by @andreoam) +* Allow links in error_box.html.twig (https://github.com/slawkens/myaac/commit/9acad15451071639acf7a7d4e81619b0a9742b12) +* Canary - Comment code to update lastday in login.php (https://github.com/slawkens/myaac/commit/38902c30d114fdbce259467f5820f97037b393e9) +* Cache::remember $ttl = -1 = infinite (https://github.com/slawkens/myaac/commit/64acf70d3854182d88aaf0b67f77cea2a254f179) + +### Fixed +* Online - Allow for html code (example - img) in online_datacenter (https://github.com/slawkens/myaac/commit/3bb272ebbbd2eb7769d174b7082061d14a17bd44) +* Guilds - Fix guild create with freePremium enabled (https://github.com/slawkens/myaac/commit/c91bb5d4097647dca2196d3dea87bc90c89181d2) +* Canary - Fix premDays count (https://github.com/slawkens/myaac/commit/3e61692780d4add93b7b0e9f12f7a283bd8f4b7a) +* Template Change: Ignore set last visit for AJAX pages - Fixes template change redirect (https://github.com/slawkens/myaac/commit/89fae38caa7e4f645957fcf1a9330a36358ac04f) +* Admin Panel - Accounts: Fix lastip v6 (TFS master) (https://github.com/slawkens/myaac/commit/f54b1bdd2af4c16c64ddff0e87a6c96bc4cf9eeb) +* Functions - Prevent injection in $db->hasColumn (https://github.com/slawkens/myaac/commit/56bd7ec5ed904666074492f2e4f13e4fce226bee) +* Compat Config: Add missing config: email_lai_sec_interval (https://github.com/slawkens/myaac/commit/2eae44e0755e624a91be68b4d1ec26d01eb4d9a1) + ## [1.8.2 - 26.09.2025] ### Added diff --git a/common.php b/common.php index e26921c5..1cbd0dd8 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.8.3-dev'; +const MYAAC_VERSION = '1.8.3'; const DATABASE_VERSION = 46; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 13ea68cc0c9349380c8e4051d702a6c2c8256f44 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 24 Oct 2025 21:10:55 +0200 Subject: [PATCH 209/222] Use low level env init on migrate:run + migrate:to --- aac | 4 ++- system/src/Commands/Env.php | 33 +++++++++++++++++++++++ system/src/Commands/MigrateRunCommand.php | 6 +++-- system/src/Commands/MigrateToCommand.php | 29 +++----------------- 4 files changed, 43 insertions(+), 29 deletions(-) create mode 100644 system/src/Commands/Env.php diff --git a/aac b/aac index d4ce7b7d..8f213136 100644 --- a/aac +++ b/aac @@ -25,7 +25,9 @@ foreach ($commandsGlob as $item) { } $commandPre = '\\MyAAC\Commands\\'; - $application->add(new ($commandPre . $name)); + if (!trait_exists($class = $commandPre . $name)) { + $application->add(new $class); + } } $pluginCommands = Plugins::getCommands(); diff --git a/system/src/Commands/Env.php b/system/src/Commands/Env.php new file mode 100644 index 00000000..e3130806 --- /dev/null +++ b/system/src/Commands/Env.php @@ -0,0 +1,33 @@ +setName('migrate:run') @@ -23,12 +25,12 @@ class MigrateRunCommand extends Command protected function execute(InputInterface $input, OutputInterface $output): int { - require SYSTEM . 'init.php'; - $io = new SymfonyStyle($input, $output); $ids = $input->getArgument('id'); + $this->init(); + // pre-check // in case one of the migrations doesn't exist - we won't execute any of them foreach ($ids as $id) { diff --git a/system/src/Commands/MigrateToCommand.php b/system/src/Commands/MigrateToCommand.php index b82012ed..72be5730 100644 --- a/system/src/Commands/MigrateToCommand.php +++ b/system/src/Commands/MigrateToCommand.php @@ -11,6 +11,8 @@ use Symfony\Component\Console\Style\SymfonyStyle; class MigrateToCommand extends Command { + use Env; + protected function configure(): void { $this->setName('migrate:to') @@ -32,7 +34,7 @@ class MigrateToCommand extends Command return Command::FAILURE; } - $this->initEnv(); + $this->init(); $currentVersion = Config::where('name', 'database_version')->first()->value; if ($currentVersion > $versionDest) { @@ -80,29 +82,4 @@ class MigrateToCommand extends Command updateDatabaseConfig('database_version', ($_up ? $id : $id - 1)); } - - private function initEnv() - { - global $config; - if (!isset($config['installed']) || !$config['installed']) { - throw new \RuntimeException('MyAAC has not been installed yet or there was error during installation. Please install again.'); - } - - if(empty($config['server_path'])) { - throw new \RuntimeException('Server Path has been not set. Go to config.php and set it.'); - } - - // take care of trailing slash at the end - if($config['server_path'][strlen($config['server_path']) - 1] !== '/') - $config['server_path'] .= '/'; - - $config['lua'] = load_config_lua($config['server_path'] . 'config.lua'); - - // POT - require_once SYSTEM . 'libs/pot/OTS.php'; - $ots = POT::getInstance(); - $eloquentConnection = null; - - require_once SYSTEM . 'database.php'; - } } From 07fd034fe4cb0ffdb88667b1e400f414d0c6d06f Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 24 Oct 2025 21:12:40 +0200 Subject: [PATCH 210/222] Use low level env init on migrate command --- system/src/Commands/MigrateCommand.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/system/src/Commands/MigrateCommand.php b/system/src/Commands/MigrateCommand.php index a8a21016..73868ce3 100644 --- a/system/src/Commands/MigrateCommand.php +++ b/system/src/Commands/MigrateCommand.php @@ -9,6 +9,8 @@ use Symfony\Component\Console\Style\SymfonyStyle; class MigrateCommand extends Command { + use Env; + protected function configure(): void { $this->setName('migrate') @@ -17,7 +19,7 @@ class MigrateCommand extends Command protected function execute(InputInterface $input, OutputInterface $output): int { - require SYSTEM . 'init.php'; + $this->init(); $io = new SymfonyStyle($input, $output); require SYSTEM . 'migrate.php'; From 727f68a57594b7d98682024b6aac778804ad84a1 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 24 Oct 2025 21:14:49 +0200 Subject: [PATCH 211/222] migrate command: show "Already on latest version" --- system/migrate.php | 2 ++ system/src/Commands/MigrateCommand.php | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/system/migrate.php b/system/migrate.php index 2199fd73..2bbb3786 100644 --- a/system/migrate.php +++ b/system/migrate.php @@ -9,6 +9,8 @@ */ defined('MYAAC') or die('Direct access not allowed!'); +global $db; + // database migrations $tmp = ''; if(fetchDatabaseConfig('database_version', $tmp)) { // we got version diff --git a/system/src/Commands/MigrateCommand.php b/system/src/Commands/MigrateCommand.php index 73868ce3..fe110190 100644 --- a/system/src/Commands/MigrateCommand.php +++ b/system/src/Commands/MigrateCommand.php @@ -22,6 +22,16 @@ class MigrateCommand extends Command $this->init(); $io = new SymfonyStyle($input, $output); + + $tmp = ''; + if(fetchDatabaseConfig('database_version', $tmp)) { // we got version + $tmp = (int)$tmp; + if ($tmp >= DATABASE_VERSION) { + $io->success('Already on latest version.'); + return Command::SUCCESS; + } + } + require SYSTEM . 'migrate.php'; $io->success('Migrated to latest version (' . DATABASE_VERSION . ')'); From 44110a9496b4385e42c31b75de301037e711b6c3 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 25 Oct 2025 21:32:49 +0200 Subject: [PATCH 212/222] Show if there is mysql error on import schema Weird fix, don't know why it didn't worked with query() --- install/tools/5-database.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/tools/5-database.php b/install/tools/5-database.php index f97eca11..f377b809 100644 --- a/install/tools/5-database.php +++ b/install/tools/5-database.php @@ -40,7 +40,7 @@ else { $locale['step_database_importing'] = str_replace('$DATABASE_NAME$', config('database_name'), $locale['step_database_importing']); success($locale['step_database_importing']); - $db->query(file_get_contents(BASE . 'install/includes/schema.sql')); + $db->exec(file_get_contents(BASE . 'install/includes/schema.sql')); $locale['step_database_success_schema'] = str_replace('$PREFIX$', TABLE_PREFIX, $locale['step_database_success_schema']); success($locale['step_database_success_schema']); From 9d92a11fb7cb6d7a1619d79c12faaa0b1c01f980 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 27 Oct 2025 14:34:53 +0100 Subject: [PATCH 213/222] Fix the premium checks, introduced in v1.8.3 --- system/libs/pot/OTS_Account.php | 17 +++++++---------- system/src/Models/Account.php | 22 +++++++++++++--------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/system/libs/pot/OTS_Account.php b/system/libs/pot/OTS_Account.php index a5007e3b..f617bbfc 100644 --- a/system/libs/pot/OTS_Account.php +++ b/system/libs/pot/OTS_Account.php @@ -445,16 +445,11 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable if(isset($this->data['premium_ends_at']) || isset($this->data['premend']) || (isCanary() && isset($this->data['lastday']))) { - $col = (isset($this->premium_ends_at) ? 'premium_ends_at' : (isset($this->data['lastday']) ? 'lastday' : 'premend')); + $col = (isset($this->data['premium_ends_at']) ? 'premium_ends_at' : (isset($this->data['lastday']) ? 'lastday' : 'premend')); $ret = ceil(($this->data[$col] - time()) / (24 * 60 * 60)); return max($ret, 0); } - if (isCanary() && isset($this->data['lastday'])) { - $ret = ceil(($this->data['lastday'] - time()) / 86400); - return max($ret, 0); - } - if($this->data['premdays'] == 0) { return 0; } @@ -479,12 +474,14 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable public function isPremium() { - if(isset($this->data['premium_ends_at'])) { - return $this->data['premium_ends_at'] > time(); + if(isset($this->data['premium_ends_at']) || isset($this->data['premend']) || + (isCanary() && isset($this->data['lastday']))) { + $col = (isset($this->data['premium_ends_at']) ? 'premium_ends_at' : (isset($this->data['lastday']) ? 'lastday' : 'premend')); + return $this->data[$col] > time(); } - if(isset($this->data['premend'])) { - return $this->data['premend'] > time(); + if($this->data['premdays'] == self::GRATIS_PREMIUM_DAYS){ + return true; } return ($this->data['premdays'] - (date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->data['lastday']))) - date("z", $this->data['lastday'])) > 0); diff --git a/system/src/Models/Account.php b/system/src/Models/Account.php index fdd7d540..5f2de268 100644 --- a/system/src/Models/Account.php +++ b/system/src/Models/Account.php @@ -10,6 +10,8 @@ use Illuminate\Database\Eloquent\Model; */ class Account extends Model { + const GRATIS_PREMIUM_DAYS = 65535; + protected $table = 'accounts'; public $timestamps = false; @@ -34,9 +36,9 @@ class Account extends Model { public function getPremiumDaysAttribute() { if(isset($this->premium_ends_at) || isset($this->premend) || - (isCanary() && isset($this->data['lastday']))) { - $col = (isset($this->premium_ends_at) ? 'premium_ends_at' : (isset($this->data['lastday']) ? 'lastday' : 'premend')); - $ret = ceil(($this->{$col}- time()) / (24 * 60 * 60)); + (isCanary() && isset($this->lastday))) { + $col = (isset($this->premium_ends_at) ? 'premium_ends_at' : (isset($this->lastday) ? 'lastday' : 'premend')); + $ret = ceil(($this->{$col} - time()) / (24 * 60 * 60)); return max($ret, 0); } @@ -44,8 +46,8 @@ class Account extends Model { return 0; } - if($this->premdays == 65535){ - return 65535; + if($this->premdays == self::GRATIS_PREMIUM_DAYS){ + return self::GRATIS_PREMIUM_DAYS; } $ret = ceil($this->premdays - ((int)date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->lastday))) - date("z", $this->lastday))); @@ -54,12 +56,14 @@ class Account extends Model { public function getIsPremiumAttribute() { - if(isset($this->premium_ends_at)) { - return $this->premium_ends_at > time(); + if(isset($this->premium_ends_at) || isset($this->premend) || + (isCanary() && isset($this->lastday))) { + $col = (isset($this->premium_ends_at) ? 'premium_ends_at' : (isset($this->lastday) ? 'lastday' : 'premend')); + return $this->{$col} > time(); } - if(isset($this->premend)) { - return $this->premend > time(); + if($this->premdays == self::GRATIS_PREMIUM_DAYS){ + return true; } return ($this->premdays - (date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->lastday))) - date("z", $this->lastday)) > 0); From 6cd38ee1ecb519ec48d37d01e5fc5370f3e07b2a Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 27 Oct 2025 14:38:52 +0100 Subject: [PATCH 214/222] Fix php stan --- system/src/Models/Account.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/src/Models/Account.php b/system/src/Models/Account.php index 5f2de268..26a09f51 100644 --- a/system/src/Models/Account.php +++ b/system/src/Models/Account.php @@ -5,6 +5,8 @@ namespace MyAAC\Models; use Illuminate\Database\Eloquent\Model; /** + * @property integer $premium_ends_at + * @property integer $premend * @property integer $lastday * @property integer $premdays */ From 8f47b36dc88ad4d4c3176e4afda86b520394e8e8 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 27 Oct 2025 15:03:24 +0100 Subject: [PATCH 215/222] Add return type --- system/libs/pot/OTS_Account.php | 2 +- system/src/Models/Account.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/system/libs/pot/OTS_Account.php b/system/libs/pot/OTS_Account.php index f617bbfc..8505128e 100644 --- a/system/libs/pot/OTS_Account.php +++ b/system/libs/pot/OTS_Account.php @@ -472,7 +472,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable return $this->data['lastday']; } - public function isPremium() + public function isPremium(): bool { if(isset($this->data['premium_ends_at']) || isset($this->data['premend']) || (isCanary() && isset($this->data['lastday']))) { diff --git a/system/src/Models/Account.php b/system/src/Models/Account.php index 26a09f51..4b44b153 100644 --- a/system/src/Models/Account.php +++ b/system/src/Models/Account.php @@ -56,7 +56,7 @@ class Account extends Model { return max($ret, 0); } - public function getIsPremiumAttribute() + public function getIsPremiumAttribute(): bool { if(isset($this->premium_ends_at) || isset($this->premend) || (isCanary() && isset($this->lastday))) { From 2580edadf84779f09fd395c21f92019b2c762f83 Mon Sep 17 00:00:00 2001 From: Slawomir Boczek Date: Mon, 27 Oct 2025 16:27:22 +0100 Subject: [PATCH 216/222] Database import tables on every install with "IF NOT EXISTS" (#336) * Database import tables on every install with "IF NOT EXISTS" This fixed errors when one table is missing or is duplicated * Add success message on import data * Reorder --- install/includes/import_base_data.php | 69 +++++++++++++++++++++++++++ install/includes/schema.sql | 57 ++++++++-------------- install/tools/5-database.php | 30 +++++------- system/locale/de/install.php | 1 + system/locale/en/install.php | 1 + system/locale/pl/install.php | 3 +- system/src/Models/Changelog.php | 9 ++++ system/src/Models/ForumBoard.php | 16 +++++++ system/src/Models/Gallery.php | 5 ++ system/src/Models/NewsCategory.php | 15 ++++++ 10 files changed, 150 insertions(+), 56 deletions(-) create mode 100644 install/includes/import_base_data.php create mode 100644 system/src/Models/ForumBoard.php create mode 100644 system/src/Models/NewsCategory.php diff --git a/install/includes/import_base_data.php b/install/includes/import_base_data.php new file mode 100644 index 00000000..45c803ed --- /dev/null +++ b/install/includes/import_base_data.php @@ -0,0 +1,69 @@ + 3, + 'where' => 2, + 'date' => time(), + 'body' => 'MyAAC installed. (:', + 'hide' => 0, + ]); +} + +if (Config::where('name', 'database_version')->count() === 0) { + Config::create([ + 'name' => 'database_version', + 'value' => DATABASE_VERSION, + ]); +} + +if (ForumBoard::count() === 0) { + $forumBoards = [ + ['name' => 'News', 'description' => 'News commenting', 'closed' => 1], + ['name' => 'Trade', 'description' => 'Trade offers.', 'closed' => 0], + ['name' => 'Quests', 'description' => 'Quest making.', 'closed' => 0], + ['name' => 'Pictures', 'description' => 'Your pictures.', 'closed' => 0], + ['name' => 'Bug Report', 'description' => 'Report bugs there.', 'closed' => 0], + ]; + + $i = 0; + foreach ($forumBoards as $forumBoard) { + ForumBoard::create([ + 'name' => $forumBoard['name'], + 'description' => $forumBoard['description'], + 'ordering' => $i++, + 'closed' => $forumBoard['closed'], + ]); + } +} + +if (NewsCategory::count() === 0) { + $newsCategoriesIcons = [ + 0, 1, 2, 3, 4 + ]; + + foreach ($newsCategoriesIcons as $iconId) { + NewsCategory::create([ + 'icon_id' => $iconId, + ]); + } +} + +if (Gallery::count() === 0) { + Gallery::create([ + 'comment' => 'Demon', + 'image' => 'images/gallery/demon.jpg', + 'thumb' => 'images/gallery/demon_thumb.gif', + 'author' => 'MyAAC', + 'ordering' => 0, + ]); +} + +success($locale['step_database_success_import_data']); diff --git a/install/includes/schema.sql b/install/includes/schema.sql index b53ffab2..d4bc97d6 100644 --- a/install/includes/schema.sql +++ b/install/includes/schema.sql @@ -1,6 +1,4 @@ -SET @myaac_database_version = 46; - -CREATE TABLE `myaac_account_actions` +CREATE TABLE IF NOT EXISTS `myaac_account_actions` ( `account_id` int NOT NULL, `ip` int unsigned NOT NULL DEFAULT 0, @@ -10,7 +8,7 @@ CREATE TABLE `myaac_account_actions` KEY (`account_id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_account_emails_verify` +CREATE TABLE IF NOT EXISTS `myaac_account_emails_verify` ( `id` int NOT NULL AUTO_INCREMENT, `account_id` int NOT NULL, @@ -19,7 +17,7 @@ CREATE TABLE `myaac_account_emails_verify` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_admin_menu` +CREATE TABLE IF NOT EXISTS `myaac_admin_menu` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL DEFAULT '', @@ -30,7 +28,7 @@ CREATE TABLE `myaac_admin_menu` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_changelog` +CREATE TABLE IF NOT EXISTS `myaac_changelog` ( `id` int NOT NULL AUTO_INCREMENT, `body` varchar(500) NOT NULL DEFAULT '', @@ -42,9 +40,7 @@ CREATE TABLE `myaac_changelog` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -INSERT INTO `myaac_changelog` (`id`, `type`, `where`, `date`, `body`, `hide`) VALUES (1, 3, 2, UNIX_TIMESTAMP(), 'MyAAC installed. (:', 0); - -CREATE TABLE `myaac_config` +CREATE TABLE IF NOT EXISTS `myaac_config` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(30) NOT NULL, @@ -53,9 +49,7 @@ CREATE TABLE `myaac_config` UNIQUE (`name`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -INSERT INTO `myaac_config` (`name`, `value`) VALUES ('database_version', @myaac_database_version); - -CREATE TABLE `myaac_faq` +CREATE TABLE IF NOT EXISTS `myaac_faq` ( `id` int NOT NULL AUTO_INCREMENT, `question` varchar(255) NOT NULL DEFAULT '', @@ -65,7 +59,7 @@ CREATE TABLE `myaac_faq` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_forum_boards` +CREATE TABLE IF NOT EXISTS `myaac_forum_boards` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL, @@ -77,13 +71,8 @@ CREATE TABLE `myaac_forum_boards` `hide` tinyint NOT NULL DEFAULT 0, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`, `closed`) VALUES (NULL, 'News', 'News commenting', 0, 1); -INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Trade', 'Trade offers.', 1); -INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Quests', 'Quest making.', 2); -INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Pictures', 'Your pictures.', 3); -INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Bug Report', 'Report bugs there.', 4); -CREATE TABLE `myaac_forum` +CREATE TABLE IF NOT EXISTS `myaac_forum` ( `id` int NOT NULL AUTO_INCREMENT, `first_post` int NOT NULL DEFAULT 0, @@ -107,7 +96,7 @@ CREATE TABLE `myaac_forum` KEY `section` (`section`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_menu` +CREATE TABLE IF NOT EXISTS `myaac_menu` ( `id` int NOT NULL AUTO_INCREMENT, `template` varchar(255) NOT NULL, @@ -121,7 +110,7 @@ CREATE TABLE `myaac_menu` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_monsters` ( +CREATE TABLE IF NOT EXISTS `myaac_monsters` ( `id` int NOT NULL AUTO_INCREMENT, `hide` tinyint NOT NULL DEFAULT 0, `name` varchar(255) NOT NULL, @@ -154,7 +143,7 @@ CREATE TABLE `myaac_monsters` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_news` +CREATE TABLE IF NOT EXISTS `myaac_news` ( `id` int NOT NULL AUTO_INCREMENT, `title` varchar(100) NOT NULL, @@ -172,7 +161,7 @@ CREATE TABLE `myaac_news` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_news_categories` +CREATE TABLE IF NOT EXISTS `myaac_news_categories` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL DEFAULT "", @@ -182,13 +171,7 @@ CREATE TABLE `myaac_news_categories` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 0); -INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 1); -INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 2); -INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 3); -INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 4); - -CREATE TABLE `myaac_notepad` +CREATE TABLE IF NOT EXISTS `myaac_notepad` ( `id` int NOT NULL AUTO_INCREMENT, `account_id` int NOT NULL, @@ -198,7 +181,7 @@ CREATE TABLE `myaac_notepad` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_pages` +CREATE TABLE IF NOT EXISTS `myaac_pages` ( `id` INT NOT NULL AUTO_INCREMENT, `name` varchar(30) NOT NULL, @@ -214,7 +197,7 @@ CREATE TABLE `myaac_pages` UNIQUE (`name`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_gallery` +CREATE TABLE IF NOT EXISTS `myaac_gallery` ( `id` int NOT NULL AUTO_INCREMENT, `comment` varchar(255) NOT NULL DEFAULT '', @@ -226,9 +209,7 @@ CREATE TABLE `myaac_gallery` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -INSERT INTO `myaac_gallery` (`id`, `ordering`, `comment`, `image`, `thumb`, `author`) VALUES (NULL, 1, 'Demon', 'images/gallery/demon.jpg', 'images/gallery/demon_thumb.gif', 'MyAAC'); - -CREATE TABLE `myaac_settings` +CREATE TABLE IF NOT EXISTS `myaac_settings` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL DEFAULT '', @@ -238,7 +219,7 @@ CREATE TABLE `myaac_settings` KEY `key` (`key`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_spells` +CREATE TABLE IF NOT EXISTS `myaac_spells` ( `id` int NOT NULL AUTO_INCREMENT, `spell` varchar(255) NOT NULL DEFAULT '', @@ -261,7 +242,7 @@ CREATE TABLE `myaac_spells` UNIQUE (`name`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_visitors` +CREATE TABLE IF NOT EXISTS `myaac_visitors` ( `ip` varchar(45) NOT NULL, `lastvisit` int NOT NULL DEFAULT 0, @@ -270,7 +251,7 @@ CREATE TABLE `myaac_visitors` UNIQUE (`ip`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_weapons` +CREATE TABLE IF NOT EXISTS `myaac_weapons` ( `id` int NOT NULL, `level` int NOT NULL DEFAULT 0, diff --git a/install/tools/5-database.php b/install/tools/5-database.php index f377b809..6406ee48 100644 --- a/install/tools/5-database.php +++ b/install/tools/5-database.php @@ -30,26 +30,22 @@ if(!$error) { } } -if($db->hasTable(TABLE_PREFIX . 'account_actions')) { - $locale['step_database_error_table_exist'] = str_replace('$TABLE$', TABLE_PREFIX . 'account_actions', $locale['step_database_error_table_exist']); - warning($locale['step_database_error_table_exist']); -} -else { - // import schema - try { - $locale['step_database_importing'] = str_replace('$DATABASE_NAME$', config('database_name'), $locale['step_database_importing']); - success($locale['step_database_importing']); +// import schema +try { + $locale['step_database_importing'] = str_replace('$DATABASE_NAME$', config('database_name'), $locale['step_database_importing']); + success($locale['step_database_importing']); - $db->exec(file_get_contents(BASE . 'install/includes/schema.sql')); + $db->exec(file_get_contents(BASE . 'install/includes/schema.sql')); - $locale['step_database_success_schema'] = str_replace('$PREFIX$', TABLE_PREFIX, $locale['step_database_success_schema']); - success($locale['step_database_success_schema']); - } - catch(PDOException $error_) { - error($locale['step_database_error_schema'] . ' ' . $error_); - return; - } + $locale['step_database_success_schema'] = str_replace('$PREFIX$', TABLE_PREFIX, $locale['step_database_success_schema']); + success($locale['step_database_success_schema']); } +catch(PDOException $error_) { + error($locale['step_database_error_schema'] . ' ' . $error_); + return; +} + +require BASE . 'install/includes/import_base_data.php'; if(!$db->hasColumn('accounts', 'email')) { if(query("ALTER TABLE `accounts` ADD `email` varchar(255) NOT NULL DEFAULT '';")) diff --git a/system/locale/de/install.php b/system/locale/de/install.php index 927da34b..351f6009 100644 --- a/system/locale/de/install.php +++ b/system/locale/de/install.php @@ -78,6 +78,7 @@ $locale['step_database_error_mysql_connect_3'] = 'MySQL ist nicht richtig konfig $locale['step_database_error_mysql_connect_4'] = 'MySQL-Server läuft nicht.'; $locale['step_database_error_schema'] = 'Fehler beim Importieren des Schemas:'; $locale['step_database_success_schema'] = '$PREFIX$ Tabellen wurden erfolgreich installiert.'; +$locale['step_database_success_import_data'] = 'Import von Daten für Tabellen was erfolgreich.'; $locale['step_database_error_file'] = '$FILE$ konnte nicht geöffnet werden. Bitte kopieren Sie diesen Inhalt und fügen Sie ihn dort ein:'; $locale['step_database_adding_field'] = 'Folgendes Feld wurde hinzugefügt: '; $locale['step_database_modifying_field'] = 'Folgendes Feld wurde geändert: '; diff --git a/system/locale/en/install.php b/system/locale/en/install.php index 376e82c3..c623035c 100644 --- a/system/locale/en/install.php +++ b/system/locale/en/install.php @@ -83,6 +83,7 @@ $locale['step_database_error_mysql_connect_3'] = 'MySQL is not configured proper $locale['step_database_error_mysql_connect_4'] = 'MySQL server is not running.'; $locale['step_database_error_schema'] = 'Error while importing schema:'; $locale['step_database_success_schema'] = 'Successfully installed $PREFIX$ tables.'; +$locale['step_database_success_import_data'] = 'Successfully imported base data for tables.'; $locale['step_database_error_file'] = '$FILE$ couldn\'t be opened. Please copy this content and paste there:'; $locale['step_database_adding_field'] = 'Adding field'; $locale['step_database_modifying_field'] = 'Modifying field'; diff --git a/system/locale/pl/install.php b/system/locale/pl/install.php index 159a7d8f..a8ea0cf6 100644 --- a/system/locale/pl/install.php +++ b/system/locale/pl/install.php @@ -81,7 +81,8 @@ $locale['step_database_error_mysql_connect_2'] = 'Możliwe przyczyny:'; $locale['step_database_error_mysql_connect_3'] = 'MySQL nie jest poprawnie skonfigurowane w config.lua.'; $locale['step_database_error_mysql_connect_4'] = 'Serwer MySQL nie jest uruchomiony.'; $locale['step_database_error_schema'] = 'Błąd podczas importowania struktury bazy danych:'; -$locale['step_database_success_schema'] = 'Pomyślnie zainstalowano tabele $PREFIX$.'; +$locale['step_database_success_schema'] = 'Pomyślnie zaimportowano tabele $PREFIX$.'; +$locale['step_database_success_import_data'] = 'Pomyślnie załadowano bazowe dane dla tabel.'; $locale['step_database_error_file'] = '$FILE$ nie mógł zostać otwarty. Proszę skopiować zawartość pola tekstowego i wkleić do tego pliku:'; $locale['step_database_adding_field'] = 'Dodawanie pola'; $locale['step_database_modifying_field'] = 'Modyfikacja pola'; diff --git a/system/src/Models/Changelog.php b/system/src/Models/Changelog.php index b7356166..45f8cf59 100644 --- a/system/src/Models/Changelog.php +++ b/system/src/Models/Changelog.php @@ -18,7 +18,16 @@ class Changelog extends Model { public $timestamps = false; + protected $fillable = [ + 'body', 'type', 'where', + 'date', 'player_id', 'hide', + ]; + public function scopeIsPublic($query) { $query->where('hide', '!=', 1); } + + public function player() { + return $this->belongsTo(Player::class); + } } diff --git a/system/src/Models/ForumBoard.php b/system/src/Models/ForumBoard.php new file mode 100644 index 00000000..ee03fde9 --- /dev/null +++ b/system/src/Models/ForumBoard.php @@ -0,0 +1,16 @@ + Date: Mon, 27 Oct 2025 16:43:34 +0100 Subject: [PATCH 217/222] Release v1.8.4 --- CHANGELOG-1.x.md | 10 ++++++++++ common.php | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index 8779d2c5..bea711e1 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,15 @@ # Changelog +## [1.8.4 - 27.10.2025] + +### Changed +* Reimport myaac_ tables on every install, this fixes errors when one table is missing or is duplicated (https://github.com/slawkens/myaac/commit/2580edadf84779f09fd395c21f92019b2c762f83) +* Use custom env init on migrate, migrate:run and migrate:to (https://github.com/slawkens/myaac/commit/13ea68cc0c9349380c8e4051d702a6c2c8256f44, https://github.com/slawkens/myaac/commit/07fd034fe4cb0ffdb88667b1e400f414d0c6d06f) + +### Fixed +* Show if there is mysql error on import schema (https://github.com/slawkens/myaac/commit/44110a9496b4385e42c31b75de301037e711b6c3) +* Fix the premium checks (mostly TFS 1.6+), introduced in v1.8.3 (https://github.com/slawkens/myaac/commit/9d92a11fb7cb6d7a1619d79c12faaa0b1c01f980) + ## [1.8.3 - 21.10.2025] ### Added diff --git a/common.php b/common.php index 1cbd0dd8..4c9d9155 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.8.3'; +const MYAAC_VERSION = '1.8.4'; const DATABASE_VERSION = 46; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 4b8c3ffae253bbec5a503667d5aa94a5335f0c85 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 27 Oct 2025 16:55:29 +0100 Subject: [PATCH 218/222] Code smell --- admin/pages/mass_account.php | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/admin/pages/mass_account.php b/admin/pages/mass_account.php index 6b1ccb46..4ee9f63b 100644 --- a/admin/pages/mass_account.php +++ b/admin/pages/mass_account.php @@ -6,6 +6,7 @@ * @package MyAAC * @author Slawkens * @author Lee + * @author gpedro * @copyright 2020 MyAAC * @link https://my-aac.org */ @@ -19,9 +20,9 @@ $title = 'Mass Account Actions'; csrfProtect(); $hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); -$freePremium = $config['lua']['freePremium']; +$freePremium = getBoolean(configLua('freePremium')); -function admin_give_points($points) +function admin_give_points($points): void { global $hasPointsColumn; @@ -37,7 +38,7 @@ function admin_give_points($points) displayMessage($points . ' points added to all accounts.', true); } -function admin_give_coins($coins) +function admin_give_coins($coins): void { if (!HAS_ACCOUNT_COINS) { displayMessage('Coins not supported.'); @@ -52,7 +53,7 @@ function admin_give_coins($coins) displayMessage($coins . ' coins added to all accounts.', true); } -function admin_give_premdays($days) +function admin_give_premdays($days): void { global $db, $freePremium; @@ -63,6 +64,7 @@ function admin_give_premdays($days) $value = $days * 86400; $now = time(); + // othire if ($db->hasColumn('accounts', 'premend')) { // append premend @@ -70,14 +72,11 @@ function admin_give_premdays($days) // set premend if (Account::where('premend', '<=', $now)->update(['premend' => $now + $value])) { displayMessage($days . ' premium days added to all accounts.', true); - return; } else { displayMessage('Failed to execute set query.'); - return; } } else { displayMessage('Failed to execute append query.'); - return; } return; @@ -92,20 +91,14 @@ function admin_give_premdays($days) // set lastday if (Account::where('lastday', '<=', $now)->update(['lastday' => $now + $value])) { displayMessage($days . ' premium days added to all accounts.', true); - return; } else { displayMessage('Failed to execute set query.'); - return; } - - return; } else { displayMessage('Failed to execute append query.'); - return; } } else { displayMessage('Failed to execute set days query.'); - return; } return; @@ -118,14 +111,11 @@ function admin_give_premdays($days) // set premium_ends_at if (Account::where('premium_ends_at', '<=', $now)->update(['premium_ends_at' => $now + $value])) { displayMessage($days . ' premium days added to all accounts.', true); - return; } else { displayMessage('Failed to execute set query.'); - return; } } else { displayMessage('Failed to execute append query.'); - return; } return; @@ -170,7 +160,8 @@ else { )); } -function displayMessage($message, $success = false) { +function displayMessage($message, $success = false): void +{ global $twig, $hasPointsColumn, $freePremium; $success ? success($message): error($message); From a2f8759a5236112d4e360c69bb39c7bd3965e62d Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 27 Oct 2025 17:10:16 +0100 Subject: [PATCH 219/222] Update CHANGELOG-1.x.md --- CHANGELOG-1.x.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index bea711e1..b8c57ce7 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -8,7 +8,7 @@ ### Fixed * Show if there is mysql error on import schema (https://github.com/slawkens/myaac/commit/44110a9496b4385e42c31b75de301037e711b6c3) -* Fix the premium checks (mostly TFS 1.6+), introduced in v1.8.3 (https://github.com/slawkens/myaac/commit/9d92a11fb7cb6d7a1619d79c12faaa0b1c01f980) +* Fix the premium checks, introduced in v1.8.3 (https://github.com/slawkens/myaac/commit/9d92a11fb7cb6d7a1619d79c12faaa0b1c01f980) ## [1.8.3 - 21.10.2025] From d24bde2c1df2244388b63ce7fbf556b359f8c155 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 27 Oct 2025 21:45:34 +0100 Subject: [PATCH 220/222] Start v1.8.5-dev --- common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.php b/common.php index 4c9d9155..48945038 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.8.4'; +const MYAAC_VERSION = '1.8.5-dev'; const DATABASE_VERSION = 46; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From bc4107bd16965e3f4b5f5d7e4aa0846e91445f49 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 30 Oct 2025 18:54:11 +0100 Subject: [PATCH 221/222] Ignore only top-most Lua folder --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b198856f..15c069b1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ Thumbs.db # /.htaccess -lua +/lua # composer composer.phar From 26c5aa2e51c215f9a14db170a7591430ad7787d9 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 31 Oct 2025 06:52:56 +0100 Subject: [PATCH 222/222] Added more code into Items::getDescription Is not ready yet --- system/src/Items.php | 48 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/system/src/Items.php b/system/src/Items.php index 977aa602..0f92b005 100644 --- a/system/src/Items.php +++ b/system/src/Items.php @@ -76,10 +76,11 @@ class Items public static function get($id) { self::load(); - return isset(self::$items[$id]) ? self::$items[$id] : []; + return self::$items[$id] ?? []; } - public static function getDescription($id, $count = 1) { + public static function getDescription($id, $count = 1): string + { $item = self::get($id); $attr = $item['attributes']; @@ -112,15 +113,15 @@ class Items $s .= 'an item of type ' . $item['id']; if(isset($attr['type']) && strtolower($attr['type']) == 'rune') { - $item = Spell::where('item_id', $id)->first(); - if($item) { - if($item->level > 0 && $item->maglevel > 0) { - $s .= '. ' . ($count > 1 ? "They" : "It") . ' can only be used by '; + $spell = Spell::where('item_id', $id)->first(); + if($spell) { + if($spell->level > 0 && $spell->maglevel > 0) { + $s .= '. ' . ($count > 1 ? 'They' : 'It') . ' can only be used by '; } $configVocations = config('vocations'); - if(!empty(trim($item->vocations))) { - $vocations = json_decode($item->vocations); + if(!empty(trim($spell->vocations))) { + $vocations = json_decode($spell->vocations); if(count($vocations) > 0) { foreach($vocations as $voc => $show) { $vocations[$configVocations[$voc]] = $show; @@ -133,8 +134,39 @@ class Items $s .= ' with'; + if ($spell->level > 0) { + $s .= ' level ' . $spell->level; + } + + if ($spell->maglevel > 0) { + if ($spell->level > 0) { + $s .= ' and'; + } + + $s .= ' magic level ' . $spell->maglevel; + } + + $s .= ' or higher'; } } + + if (!empty($item['weaponType'])) { + if ($item['weaponType'] == 'distance' && isset($item['ammoType'])) { + $s .= ' (Range:' . $item['range']; + } + + if (isset($item['attack']) && $item['attack'] != 0) { + $s .= ', Atk ' . ($item['attack'] > 0 ? '+' . $item['attack'] : '-' . $item['attack']); + } + + if (isset($item['hitChance']) && $item['hitChance'] != -1) { + $s .= ', Hit% ' . ($item['hitChance'] > 0 ? '+' . $item['hitChance'] : '-' . $item['hitChance']); + } + elseif ($item['weaponType'] != 'ammo') { + + } + } + return $s; } }