diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index 610cafed..8c581d8a 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -36,9 +36,8 @@ jobs: with: path: ${{ steps.composer-cache.outputs.dir }} # Use composer.json for key, if composer.lock is not committed. - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - #key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - name: "Install composer dependencies" run: "composer install" diff --git a/.gitignore b/.gitignore index cc9460c2..a7b02182 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,6 @@ Thumbs.db # composer composer.phar -composer.lock vendor # npm diff --git a/CHANGELOG.md b/CHANGELOG.md index 7327c8ff..66117c5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## [1.0-beta - 02.02.2024] +## [1.0-beta - 18.05.2024] Minimum PHP version for this release is 8.1. @@ -22,7 +22,7 @@ Minimum PHP version for this release is 8.1. * list of open source libraries used in project page * auto-loading of themes, commands & pages from plugins/ folder. You need just to place them in correct folder and they will be loaded automatically - this allows better customization, without interfering with core AAC folders. This will allow in the future automatic updates for plugins as well the AAC as whole. * config.php moved to Admin Panel -> Settings page -* new console script: aac (comes from MyAAC) - using symfony/console +* new console script: aac - using symfony/console * usage: `php aac` (will list all commands by default) * example: `php aac cache:clear` * example: `php aac plugin:install theme-example.zip` @@ -46,7 +46,7 @@ Minimum PHP version for this release is 8.1. * phpdebug bar (http://phpdebugbar.com/). Activated if env == 'dev', can be also activated in production by enabling "enable_debugbar" in local config ### Changed -* Composer is now used for external libraries like: Twig, PHPMailer, fast-route etc. +* Composer and NPM is now used for external libraries like: Twig, PHPMailer, fast-route, jQuery, Bootstrap etc. * mail support is disabled on fresh install, can be manually enabled by user * disable add php pages in admin panel for security. Option to disable plugins upload * visitors counter shows now user browser, and also if its bot diff --git a/admin/pages/accounts.php b/admin/pages/accounts.php index 34b3941b..d42a2ee6 100644 --- a/admin/pages/accounts.php +++ b/admin/pages/accounts.php @@ -404,6 +404,7 @@ else if (isset($_REQUEST['search'])) { autocomplete="off" maxlength="20" value="getLocation(); ?>"/> +
+
diff --git a/admin/pages/players.php b/admin/pages/players.php index 4febcdb5..e8084afd 100644 --- a/admin/pages/players.php +++ b/admin/pages/players.php @@ -202,7 +202,7 @@ else if (isset($_REQUEST['search'])) { if ($hasBlessingsColumn) { $blessings = $_POST['blessings']; - verify_number($blessings, 'Blessings', 2); + verify_number($blessings, 'Blessings', 3); } $balance = $_POST['balance']; @@ -274,7 +274,7 @@ else if (isset($_REQUEST['search'])) { $player->setLossContainers($loss_containers); $player->setLossItems($loss_items); } - if ($db->hasColumn('players', 'blessings')) + if ($hasBlessingsColumn) $player->setBlessings($blessings); if ($hasBlessingColumn) { diff --git a/admin/pages/settings.php b/admin/pages/settings.php index 4533b33b..2c4979e1 100644 --- a/admin/pages/settings.php +++ b/admin/pages/settings.php @@ -48,7 +48,7 @@ if (!is_array($settingsFile)) { $settingsKeyName = ($plugin == 'core' ? $plugin : $settingsFile['key']); -$title = ($plugin == 'core' ? 'Settings' : 'Plugin Settings - ' . $plugin); +$title = ($plugin == 'core' ? 'Settings' : 'Plugin Settings - ' . $settingsFile['name']); $settingsParsed = Settings::display($settingsKeyName, $settingsFile['settings']); diff --git a/common.php b/common.php index 5a19fdb3..2057e972 100644 --- a/common.php +++ b/common.php @@ -20,13 +20,13 @@ * * @package MyAAC * @author Slawkens - * @copyright 2019 MyAAC + * @copyright 2024 MyAAC * @link https://my-aac.org */ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.0-beta'; +const MYAAC_VERSION = '1.0-beta.2'; const DATABASE_VERSION = 40; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); @@ -156,7 +156,7 @@ if (file_exists(BASE . 'config.local.php')) { /** @var array $config */ ini_set('log_errors', 1); -if(@$config['env'] === 'dev') { +if(@$config['env'] === 'dev' || defined('MYAAC_INSTALL')) { ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); diff --git a/composer.json b/composer.json index 384add29..47d68dbe 100644 --- a/composer.json +++ b/composer.json @@ -15,11 +15,12 @@ "illuminate/database": "^10.18", "peppeocchi/php-cron-scheduler": "4.*", "symfony/console": "^6.4", - "symfony/string": "^6.4" + "symfony/string": "^6.4", + "symfony/var-dumper": "^6.4", + "filp/whoops": "^2.15", + "maximebf/debugbar": "dev-master" }, "require-dev": { - "filp/whoops": "^2.15", - "maximebf/debugbar": "dev-master", "phpstan/phpstan": "^1.10" }, "autoload": { diff --git a/composer.lock b/composer.lock new file mode 100644 index 00000000..ea12d783 --- /dev/null +++ b/composer.lock @@ -0,0 +1,2922 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "230e3acec441b5af61be78d2d3b0b364", + "packages": [ + { + "name": "brick/math", + "version": "0.12.1", + "source": { + "type": "git", + "url": "https://github.com/brick/math.git", + "reference": "f510c0a40911935b77b86859eb5223d58d660df1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/brick/math/zipball/f510c0a40911935b77b86859eb5223d58d660df1", + "reference": "f510c0a40911935b77b86859eb5223d58d660df1", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.2", + "phpunit/phpunit": "^10.1", + "vimeo/psalm": "5.16.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Brick\\Math\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Arbitrary-precision arithmetic library", + "keywords": [ + "Arbitrary-precision", + "BigInteger", + "BigRational", + "arithmetic", + "bigdecimal", + "bignum", + "bignumber", + "brick", + "decimal", + "integer", + "math", + "mathematics", + "rational" + ], + "support": { + "issues": "https://github.com/brick/math/issues", + "source": "https://github.com/brick/math/tree/0.12.1" + }, + "funding": [ + { + "url": "https://github.com/BenMorel", + "type": "github" + } + ], + "time": "2023-11-29T23:19:16+00:00" + }, + { + "name": "carbonphp/carbon-doctrine-types", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/CarbonPHP/carbon-doctrine-types.git", + "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/99f76ffa36cce3b70a4a6abce41dba15ca2e84cb", + "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "doctrine/dbal": "<3.7.0 || >=4.0.0" + }, + "require-dev": { + "doctrine/dbal": "^3.7.0", + "nesbot/carbon": "^2.71.0 || ^3.0.0", + "phpunit/phpunit": "^10.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Carbon\\Doctrine\\": "src/Carbon/Doctrine/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "KyleKatarn", + "email": "kylekatarnls@gmail.com" + } + ], + "description": "Types to use Carbon in Doctrine", + "keywords": [ + "carbon", + "date", + "datetime", + "doctrine", + "time" + ], + "support": { + "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/2.1.0" + }, + "funding": [ + { + "url": "https://github.com/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "type": "tidelift" + } + ], + "time": "2023-12-11T17:09:12+00:00" + }, + { + "name": "composer/semver", + "version": "3.4.0", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.0" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2023-08-31T09:50:34+00:00" + }, + { + "name": "doctrine/inflector", + "version": "2.0.10", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^11.0", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^8.5 || ^9.5", + "vimeo/psalm": "^4.25 || ^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "keywords": [ + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.0.10" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2024-02-18T20:23:39+00:00" + }, + { + "name": "dragonmantank/cron-expression", + "version": "v3.3.3", + "source": { + "type": "git", + "url": "https://github.com/dragonmantank/cron-expression.git", + "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", + "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0", + "webmozart/assert": "^1.0" + }, + "replace": { + "mtdowling/cron-expression": "^1.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-webmozart-assert": "^1.0", + "phpunit/phpunit": "^7.0|^8.0|^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Cron\\": "src/Cron/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Tankersley", + "email": "chris@ctankersley.com", + "homepage": "https://github.com/dragonmantank" + } + ], + "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "keywords": [ + "cron", + "schedule" + ], + "support": { + "issues": "https://github.com/dragonmantank/cron-expression/issues", + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.3" + }, + "funding": [ + { + "url": "https://github.com/dragonmantank", + "type": "github" + } + ], + "time": "2023-08-10T19:36:49+00:00" + }, + { + "name": "erusev/parsedown", + "version": "1.7.4", + "source": { + "type": "git", + "url": "https://github.com/erusev/parsedown.git", + "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/erusev/parsedown/zipball/cb17b6477dfff935958ba01325f2e8a2bfa6dab3", + "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35" + }, + "type": "library", + "autoload": { + "psr-0": { + "Parsedown": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Emanuil Rusev", + "email": "hello@erusev.com", + "homepage": "http://erusev.com" + } + ], + "description": "Parser for Markdown.", + "homepage": "http://parsedown.org", + "keywords": [ + "markdown", + "parser" + ], + "support": { + "issues": "https://github.com/erusev/parsedown/issues", + "source": "https://github.com/erusev/parsedown/tree/1.7.x" + }, + "time": "2019-12-30T22:54:17+00:00" + }, + { + "name": "filp/whoops", + "version": "2.15.4", + "source": { + "type": "git", + "url": "https://github.com/filp/whoops.git", + "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filp/whoops/zipball/a139776fa3f5985a50b509f2a02ff0f709d2a546", + "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546", + "shasum": "" + }, + "require": { + "php": "^5.5.9 || ^7.0 || ^8.0", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "require-dev": { + "mockery/mockery": "^0.9 || ^1.0", + "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.3", + "symfony/var-dumper": "^2.6 || ^3.0 || ^4.0 || ^5.0" + }, + "suggest": { + "symfony/var-dumper": "Pretty print complex values better with var-dumper available", + "whoops/soap": "Formats errors as SOAP responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Whoops\\": "src/Whoops/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" + } + ], + "description": "php error handling for cool kids", + "homepage": "https://filp.github.io/whoops/", + "keywords": [ + "error", + "exception", + "handling", + "library", + "throwable", + "whoops" + ], + "support": { + "issues": "https://github.com/filp/whoops/issues", + "source": "https://github.com/filp/whoops/tree/2.15.4" + }, + "funding": [ + { + "url": "https://github.com/denis-sokolov", + "type": "github" + } + ], + "time": "2023-11-03T12:00:00+00:00" + }, + { + "name": "illuminate/collections", + "version": "v10.48.10", + "source": { + "type": "git", + "url": "https://github.com/illuminate/collections.git", + "reference": "f9589f1063a449111dcaa1d68285b507d9483a95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/collections/zipball/f9589f1063a449111dcaa1d68285b507d9483a95", + "reference": "f9589f1063a449111dcaa1d68285b507d9483a95", + "shasum": "" + }, + "require": { + "illuminate/conditionable": "^10.0", + "illuminate/contracts": "^10.0", + "illuminate/macroable": "^10.0", + "php": "^8.1" + }, + "suggest": { + "symfony/var-dumper": "Required to use the dump method (^6.2)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "10.x-dev" + } + }, + "autoload": { + "files": [ + "helpers.php" + ], + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Collections package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2024-03-20T20:09:13+00:00" + }, + { + "name": "illuminate/conditionable", + "version": "v10.48.10", + "source": { + "type": "git", + "url": "https://github.com/illuminate/conditionable.git", + "reference": "d0958e4741fc9d6f516a552060fd1b829a85e009" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/conditionable/zipball/d0958e4741fc9d6f516a552060fd1b829a85e009", + "reference": "d0958e4741fc9d6f516a552060fd1b829a85e009", + "shasum": "" + }, + "require": { + "php": "^8.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "10.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Conditionable package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-02-03T08:06:17+00:00" + }, + { + "name": "illuminate/container", + "version": "v10.48.10", + "source": { + "type": "git", + "url": "https://github.com/illuminate/container.git", + "reference": "ddc26273085fad3c471b2602ad820e0097ff7939" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/container/zipball/ddc26273085fad3c471b2602ad820e0097ff7939", + "reference": "ddc26273085fad3c471b2602ad820e0097ff7939", + "shasum": "" + }, + "require": { + "illuminate/contracts": "^10.0", + "php": "^8.1", + "psr/container": "^1.1.1|^2.0.1" + }, + "provide": { + "psr/container-implementation": "1.1|2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "10.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Container\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Container package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-06-18T09:12:03+00:00" + }, + { + "name": "illuminate/contracts", + "version": "v10.48.10", + "source": { + "type": "git", + "url": "https://github.com/illuminate/contracts.git", + "reference": "8d7152c4a1f5d9cf7da3e8b71f23e4556f6138ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/contracts/zipball/8d7152c4a1f5d9cf7da3e8b71f23e4556f6138ac", + "reference": "8d7152c4a1f5d9cf7da3e8b71f23e4556f6138ac", + "shasum": "" + }, + "require": { + "php": "^8.1", + "psr/container": "^1.1.1|^2.0.1", + "psr/simple-cache": "^1.0|^2.0|^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "10.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Contracts\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Contracts package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2024-01-15T18:52:32+00:00" + }, + { + "name": "illuminate/database", + "version": "v10.48.10", + "source": { + "type": "git", + "url": "https://github.com/illuminate/database.git", + "reference": "eb8edf206d3a6eea8894bc6e21f53469e27dd5c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/database/zipball/eb8edf206d3a6eea8894bc6e21f53469e27dd5c9", + "reference": "eb8edf206d3a6eea8894bc6e21f53469e27dd5c9", + "shasum": "" + }, + "require": { + "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12", + "ext-pdo": "*", + "illuminate/collections": "^10.0", + "illuminate/container": "^10.0", + "illuminate/contracts": "^10.0", + "illuminate/macroable": "^10.0", + "illuminate/support": "^10.0", + "php": "^8.1" + }, + "conflict": { + "carbonphp/carbon-doctrine-types": ">=3.0", + "doctrine/dbal": ">=4.0" + }, + "suggest": { + "doctrine/dbal": "Required to rename columns and drop SQLite columns (^3.5.1).", + "ext-filter": "Required to use the Postgres database driver.", + "fakerphp/faker": "Required to use the eloquent factory builder (^1.21).", + "illuminate/console": "Required to use the database commands (^10.0).", + "illuminate/events": "Required to use the observers with Eloquent (^10.0).", + "illuminate/filesystem": "Required to use the migrations (^10.0).", + "illuminate/pagination": "Required to paginate the result set (^10.0).", + "symfony/finder": "Required to use Eloquent model factories (^6.2)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "10.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Database\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Database package.", + "homepage": "https://laravel.com", + "keywords": [ + "database", + "laravel", + "orm", + "sql" + ], + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2024-04-29T13:23:17+00:00" + }, + { + "name": "illuminate/macroable", + "version": "v10.48.10", + "source": { + "type": "git", + "url": "https://github.com/illuminate/macroable.git", + "reference": "dff667a46ac37b634dcf68909d9d41e94dc97c27" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/macroable/zipball/dff667a46ac37b634dcf68909d9d41e94dc97c27", + "reference": "dff667a46ac37b634dcf68909d9d41e94dc97c27", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "10.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Macroable package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-06-05T12:46:42+00:00" + }, + { + "name": "illuminate/support", + "version": "v10.48.10", + "source": { + "type": "git", + "url": "https://github.com/illuminate/support.git", + "reference": "ee3a1aaed36d916654ce0ae09dfbd38644a4f582" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/support/zipball/ee3a1aaed36d916654ce0ae09dfbd38644a4f582", + "reference": "ee3a1aaed36d916654ce0ae09dfbd38644a4f582", + "shasum": "" + }, + "require": { + "doctrine/inflector": "^2.0", + "ext-ctype": "*", + "ext-filter": "*", + "ext-mbstring": "*", + "illuminate/collections": "^10.0", + "illuminate/conditionable": "^10.0", + "illuminate/contracts": "^10.0", + "illuminate/macroable": "^10.0", + "nesbot/carbon": "^2.67", + "php": "^8.1", + "voku/portable-ascii": "^2.0" + }, + "conflict": { + "tightenco/collect": "<5.5.33" + }, + "suggest": { + "illuminate/filesystem": "Required to use the composer class (^10.0).", + "league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.0.2).", + "ramsey/uuid": "Required to use Str::uuid() (^4.7).", + "symfony/process": "Required to use the composer class (^6.2).", + "symfony/uid": "Required to use Str::ulid() (^6.2).", + "symfony/var-dumper": "Required to use the dd function (^6.2).", + "vlucas/phpdotenv": "Required to use the Env class and env helper (^5.4.1)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "10.x-dev" + } + }, + "autoload": { + "files": [ + "helpers.php" + ], + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Support package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2024-04-07T17:47:33+00:00" + }, + { + "name": "matomo/device-detector", + "version": "6.3.1", + "source": { + "type": "git", + "url": "https://github.com/matomo-org/device-detector.git", + "reference": "8096093346917ee2477d802ab3b00c4c091c5cee" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/matomo-org/device-detector/zipball/8096093346917ee2477d802ab3b00c4c091c5cee", + "reference": "8096093346917ee2477d802ab3b00c4c091c5cee", + "shasum": "" + }, + "require": { + "mustangostang/spyc": "*", + "php": "^7.2|^8.0" + }, + "replace": { + "piwik/device-detector": "self.version" + }, + "require-dev": { + "matthiasmullie/scrapbook": "^1.4.7", + "mayflower/mo4-coding-standard": "^v9.0.0", + "phpstan/phpstan": "^1.10.44", + "phpunit/phpunit": "^8.5.8", + "psr/cache": "^1.0.1", + "psr/simple-cache": "^1.0.1", + "symfony/yaml": "^5.1.7" + }, + "suggest": { + "doctrine/cache": "Can directly be used for caching purpose", + "ext-yaml": "Necessary for using the Pecl YAML parser" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeviceDetector\\": "" + }, + "exclude-from-classmap": [ + "Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "The Matomo Team", + "email": "hello@matomo.org", + "homepage": "https://matomo.org/team/" + } + ], + "description": "The Universal Device Detection library, that parses User Agents and detects devices (desktop, tablet, mobile, tv, cars, console, etc.), clients (browsers, media players, mobile apps, feed readers, libraries, etc), operating systems, devices, brands and models.", + "homepage": "https://matomo.org", + "keywords": [ + "devicedetection", + "parser", + "useragent" + ], + "support": { + "forum": "https://forum.matomo.org/", + "issues": "https://github.com/matomo-org/device-detector/issues", + "source": "https://github.com/matomo-org/matomo", + "wiki": "https://dev.matomo.org/" + }, + "time": "2024-04-12T12:16:21+00:00" + }, + { + "name": "maximebf/debugbar", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/maximebf/php-debugbar.git", + "reference": "40d2d7e986082287b47bb6f675541ba43db09398" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/40d2d7e986082287b47bb6f675541ba43db09398", + "reference": "40d2d7e986082287b47bb6f675541ba43db09398", + "shasum": "" + }, + "require": { + "php": "^7.2|^8", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^4|^5|^6|^7" + }, + "require-dev": { + "dbrekelmans/bdi": "^1", + "phpunit/phpunit": "^8|^9", + "symfony/panther": "^1|^2.1", + "twig/twig": "^1.38|^2.7|^3.0" + }, + "suggest": { + "kriswallsmith/assetic": "The best way to manage assets", + "monolog/monolog": "Log using Monolog", + "predis/predis": "Redis storage" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.22-dev" + } + }, + "autoload": { + "psr-4": { + "DebugBar\\": "src/DebugBar/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maxime Bouroumeau-Fuseau", + "email": "maxime.bouroumeau@gmail.com", + "homepage": "http://maximebf.com" + }, + { + "name": "Barry vd. Heuvel", + "email": "barryvdh@gmail.com" + } + ], + "description": "Debug bar in the browser for php application", + "homepage": "https://github.com/maximebf/php-debugbar", + "keywords": [ + "debug", + "debugbar" + ], + "support": { + "issues": "https://github.com/maximebf/php-debugbar/issues", + "source": "https://github.com/maximebf/php-debugbar/tree/master" + }, + "time": "2024-04-15T10:55:03+00:00" + }, + { + "name": "mustangostang/spyc", + "version": "0.6.3", + "source": { + "type": "git", + "url": "https://github.com/mustangostang/spyc.git", + "reference": "4627c838b16550b666d15aeae1e5289dd5b77da0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mustangostang/spyc/zipball/4627c838b16550b666d15aeae1e5289dd5b77da0", + "reference": "4627c838b16550b666d15aeae1e5289dd5b77da0", + "shasum": "" + }, + "require": { + "php": ">=5.3.1" + }, + "require-dev": { + "phpunit/phpunit": "4.3.*@dev" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.5.x-dev" + } + }, + "autoload": { + "files": [ + "Spyc.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "mustangostang", + "email": "vlad.andersen@gmail.com" + } + ], + "description": "A simple YAML loader/dumper class for PHP", + "homepage": "https://github.com/mustangostang/spyc/", + "keywords": [ + "spyc", + "yaml", + "yml" + ], + "support": { + "issues": "https://github.com/mustangostang/spyc/issues", + "source": "https://github.com/mustangostang/spyc/tree/0.6.3" + }, + "time": "2019-09-10T13:16:29+00:00" + }, + { + "name": "nesbot/carbon", + "version": "2.72.3", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "0c6fd108360c562f6e4fd1dedb8233b423e91c83" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/0c6fd108360c562f6e4fd1dedb8233b423e91c83", + "reference": "0c6fd108360c562f6e4fd1dedb8233b423e91c83", + "shasum": "" + }, + "require": { + "carbonphp/carbon-doctrine-types": "*", + "ext-json": "*", + "php": "^7.1.8 || ^8.0", + "psr/clock": "^1.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/polyfill-php80": "^1.16", + "symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "require-dev": { + "doctrine/dbal": "^2.0 || ^3.1.4 || ^4.0", + "doctrine/orm": "^2.7 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.0", + "kylekatarnls/multi-tester": "^2.0", + "ondrejmirtes/better-reflection": "*", + "phpmd/phpmd": "^2.9", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12.99 || ^1.7.14", + "phpunit/php-file-iterator": "^2.0.5 || ^3.0.6", + "phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20", + "squizlabs/php_codesniffer": "^3.4" + }, + "bin": [ + "bin/carbon" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-3.x": "3.x-dev", + "dev-master": "2.x-dev" + }, + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "https://markido.com" + }, + { + "name": "kylekatarnls", + "homepage": "https://github.com/kylekatarnls" + } + ], + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "https://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "support": { + "docs": "https://carbon.nesbot.com/docs", + "issues": "https://github.com/briannesbitt/Carbon/issues", + "source": "https://github.com/briannesbitt/Carbon" + }, + "funding": [ + { + "url": "https://github.com/sponsors/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon#sponsor", + "type": "opencollective" + }, + { + "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme", + "type": "tidelift" + } + ], + "time": "2024-01-25T10:35:09+00:00" + }, + { + "name": "nikic/fast-route", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/FastRoute.git", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35|~5.7" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "FastRoute\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "description": "Fast request router for PHP", + "keywords": [ + "router", + "routing" + ], + "support": { + "issues": "https://github.com/nikic/FastRoute/issues", + "source": "https://github.com/nikic/FastRoute/tree/master" + }, + "time": "2018-02-13T20:26:39+00:00" + }, + { + "name": "peppeocchi/php-cron-scheduler", + "version": "v4.0", + "source": { + "type": "git", + "url": "https://github.com/peppeocchi/php-cron-scheduler.git", + "reference": "0acfa032e60f0ea22a27b96a6b15a673a31d3448" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/peppeocchi/php-cron-scheduler/zipball/0acfa032e60f0ea22a27b96a6b15a673a31d3448", + "reference": "0acfa032e60f0ea22a27b96a6b15a673a31d3448", + "shasum": "" + }, + "require": { + "dragonmantank/cron-expression": "^3.0", + "php": "^7.3 || ^8.0" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.4", + "phpunit/phpunit": "~9.5", + "swiftmailer/swiftmailer": "~5.4 || ^6.0" + }, + "suggest": { + "swiftmailer/swiftmailer": "Required to send the output of a job to email address/es (~5.4 || ^6.0)." + }, + "type": "library", + "autoload": { + "psr-4": { + "GO\\": "src/GO/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Giuseppe Occhipinti", + "email": "peppeocchi@gmail.com" + }, + { + "name": "Carsten Windler", + "email": "carsten@carstenwindler.de", + "homepage": "http://carstenwindler.de", + "role": "Contributor" + } + ], + "description": "PHP Cron Job Scheduler", + "keywords": [ + "cron job", + "scheduler" + ], + "support": { + "issues": "https://github.com/peppeocchi/php-cron-scheduler/issues", + "source": "https://github.com/peppeocchi/php-cron-scheduler/tree/v4.0" + }, + "time": "2021-04-22T21:32:03+00:00" + }, + { + "name": "phpmailer/phpmailer", + "version": "v6.9.1", + "source": { + "type": "git", + "url": "https://github.com/PHPMailer/PHPMailer.git", + "reference": "039de174cd9c17a8389754d3b877a2ed22743e18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/039de174cd9c17a8389754d3b877a2ed22743e18", + "reference": "039de174cd9c17a8389754d3b877a2ed22743e18", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-filter": "*", + "ext-hash": "*", + "php": ">=5.5.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "doctrine/annotations": "^1.2.6 || ^1.13.3", + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.3.2", + "phpcompatibility/php-compatibility": "^9.3.5", + "roave/security-advisories": "dev-latest", + "squizlabs/php_codesniffer": "^3.7.2", + "yoast/phpunit-polyfills": "^1.0.4" + }, + "suggest": { + "decomplexity/SendOauth2": "Adapter for using XOAUTH2 authentication", + "ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses", + "ext-openssl": "Needed for secure SMTP sending and DKIM signing", + "greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication", + "hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication", + "league/oauth2-google": "Needed for Google XOAUTH2 authentication", + "psr/log": "For optional PSR-3 debug logging", + "symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)", + "thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPMailer\\PHPMailer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-only" + ], + "authors": [ + { + "name": "Marcus Bointon", + "email": "phpmailer@synchromedia.co.uk" + }, + { + "name": "Jim Jagielski", + "email": "jimjag@gmail.com" + }, + { + "name": "Andy Prevost", + "email": "codeworxtech@users.sourceforge.net" + }, + { + "name": "Brent R. Matzelle" + } + ], + "description": "PHPMailer is a full-featured email creation and transfer class for PHP", + "support": { + "issues": "https://github.com/PHPMailer/PHPMailer/issues", + "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.9.1" + }, + "funding": [ + { + "url": "https://github.com/Synchro", + "type": "github" + } + ], + "time": "2023-11-25T22:23:28+00:00" + }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/log", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.0" + }, + "time": "2021-07-14T16:46:02+00:00" + }, + { + "name": "psr/simple-cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + }, + "time": "2021-10-29T13:26:27+00:00" + }, + { + "name": "symfony/console", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "a170e64ae10d00ba89e2acbb590dc2e54da8ad8f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/a170e64ae10d00ba89e2acbb590dc2e54da8ad8f", + "reference": "a170e64ae10d00ba89e2acbb590dc2e54da8ad8f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^5.4|^6.0|^7.0" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:22:46+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", + "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", + "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/861391a8da9a04cbad2d232ddd9e4893220d6e25", + "reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php72/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.29.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-29T20:11:03+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/string", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "ffeb9591c61f65a68d47f77d12b83fa530227a69" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/ffeb9591c61f65a68d47f77d12b83fa530227a69", + "reference": "ffeb9591c61f65a68d47f77d12b83fa530227a69", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/intl": "^6.2|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:22:46+00:00" + }, + { + "name": "symfony/translation", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "7495687c58bfd88b7883823747b0656d90679123" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/7495687c58bfd88b7883823747b0656d90679123", + "reference": "7495687c58bfd88b7883823747b0656d90679123", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.5|^3.0" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<5.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<5.4", + "symfony/yaml": "<5.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, + "require-dev": { + "nikic/php-parser": "^4.18|^5.0", + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:22:46+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", + "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v6.4.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "7a9cd977cd1c5fed3694bee52990866432af07d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7a9cd977cd1c5fed3694bee52990866432af07d7", + "reference": "7a9cd977cd1c5fed3694bee52990866432af07d7", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/console": "<5.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^6.3|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/uid": "^5.4|^6.0|^7.0", + "twig/twig": "^2.13|^3.0.4" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v6.4.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:22:46+00:00" + }, + { + "name": "twig/twig", + "version": "v2.16.0", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "0c9cc7ef2e0ec6d20c5af1200522a89ba101f623" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/0c9cc7ef2e0ec6d20c5af1200522a89ba101f623", + "reference": "0c9cc7ef2e0ec6d20c5af1200522a89ba101f623", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php72": "^1.8" + }, + "require-dev": { + "psr/container": "^1.0", + "symfony/phpunit-bridge": "^5.4.9|^6.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.16-dev" + } + }, + "autoload": { + "psr-0": { + "Twig_": "lib/" + }, + "psr-4": { + "Twig\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Twig Team", + "role": "Contributors" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "https://twig.symfony.com", + "keywords": [ + "templating" + ], + "support": { + "issues": "https://github.com/twigphp/Twig/issues", + "source": "https://github.com/twigphp/Twig/tree/v2.16.0" + }, + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/twig/twig", + "type": "tidelift" + } + ], + "time": "2023-12-22T07:22:15+00:00" + }, + { + "name": "voku/portable-ascii", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/voku/portable-ascii.git", + "reference": "b56450eed252f6801410d810c8e1727224ae0743" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b56450eed252f6801410d810c8e1727224ae0743", + "reference": "b56450eed252f6801410d810c8e1727224ae0743", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + }, + "suggest": { + "ext-intl": "Use Intl for transliterator_transliterate() support" + }, + "type": "library", + "autoload": { + "psr-4": { + "voku\\": "src/voku/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Moelleken", + "homepage": "http://www.moelleken.org/" + } + ], + "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", + "homepage": "https://github.com/voku/portable-ascii", + "keywords": [ + "ascii", + "clean", + "php" + ], + "support": { + "issues": "https://github.com/voku/portable-ascii/issues", + "source": "https://github.com/voku/portable-ascii/tree/2.0.1" + }, + "funding": [ + { + "url": "https://www.paypal.me/moelleken", + "type": "custom" + }, + { + "url": "https://github.com/voku", + "type": "github" + }, + { + "url": "https://opencollective.com/portable-ascii", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/voku", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", + "type": "tidelift" + } + ], + "time": "2022-03-08T17:03:00+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + } + ], + "packages-dev": [ + { + "name": "phpstan/phpstan", + "version": "1.11.1", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "e524358f930e41a2b4cca1320e3b04fc26b39e0b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e524358f930e41a2b4cca1320e3b04fc26b39e0b", + "reference": "e524358f930e41a2b4cca1320e3b04fc26b39e0b", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2024-05-15T08:00:59+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "maximebf/debugbar": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^8.0", + "ext-pdo": "*", + "ext-pdo_mysql": "*", + "ext-json": "*", + "ext-xml": "*", + "ext-dom": "*" + }, + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/cypress/e2e/1-install.cy.js b/cypress/e2e/1-install.cy.js index 1d294cbc..7e46f430 100644 --- a/cypress/e2e/1-install.cy.js +++ b/cypress/e2e/1-install.cy.js @@ -67,7 +67,7 @@ describe('Install MyAAC', () => { cy.get('form').submit() - cy.contains('[class="alert alert-success"]', 'Congratulations', { timeout: 30000 }).should('be.visible') + cy.contains('[class="alert alert-success"]', 'Congratulations', { timeout: 60000 }).should('be.visible') cy.wait(2000); diff --git a/install/index.php b/install/index.php index 8418b994..91c8a7ef 100644 --- a/install/index.php +++ b/install/index.php @@ -3,9 +3,9 @@ use Twig\Environment as Twig_Environment; use Twig\Loader\FilesystemLoader as Twig_FilesystemLoader; -require '../common.php'; +const MYAAC_INSTALL = true; -define('MYAAC_INSTALL', true); +require '../common.php'; // includes require SYSTEM . 'functions.php'; diff --git a/install/steps/3-requirements.php b/install/steps/3-requirements.php index 659e3036..65281248 100644 --- a/install/steps/3-requirements.php +++ b/install/steps/3-requirements.php @@ -2,10 +2,15 @@ defined('MYAAC') or die('Direct access not allowed!'); // configuration -$dirs_required = [ +$dirs_required_writable = [ 'system/logs', 'system/cache', ]; + +$dirs_required = [ + 'tools/ext' => $locale['step_requirements_folder_not_exists_tools_ext'], +]; + $dirs_optional = [ GUILD_IMAGES_DIR => $locale['step_requirements_warning_images_guilds'], GALLERY_DIR => $locale['step_requirements_warning_images_gallery'], @@ -18,6 +23,7 @@ $extensions_optional = [ 'gd' => $locale['step_requirements_warning_player_signatures'], 'zip' => $locale['step_requirements_warning_install_plugins'], ]; + /* * * @param string $name @@ -41,7 +47,7 @@ $failed = false; // start validating version_check($locale['step_requirements_php_version'], (PHP_VERSION_ID >= 50500), PHP_VERSION); -foreach ($dirs_required as $value) +foreach ($dirs_required_writable as $value) { $is_writable = is_writable(BASE . $value) && (MYAAC_OS != 'WINDOWS' || win_is_writable(BASE . $value)); version_check($locale['step_requirements_write_perms'] . ': ' . $value, $is_writable); @@ -52,6 +58,12 @@ foreach ($dirs_optional as $dir => $errorMsg) { version_check($locale['step_requirements_write_perms'] . ': ' . $dir, $is_writable, $is_writable ? '' : $errorMsg, true); } +foreach ($dirs_required as $dir => $errorMsg) +{ + $exists = is_dir(BASE . $dir); + version_check($locale['step_requirements_folder_exists'] . ': ' . $dir, $exists, $exists ? '' : $errorMsg); +} + $ini_register_globals = ini_get_bool('register_globals'); version_check('register_long_arrays', !$ini_register_globals, $ini_register_globals ? $locale['on'] : $locale['off']); @@ -78,4 +90,3 @@ if($failed) { } echo '
'; -?> diff --git a/install/steps/5-database.php b/install/steps/5-database.php index 18d244bb..881953d6 100644 --- a/install/steps/5-database.php +++ b/install/steps/5-database.php @@ -44,57 +44,56 @@ if(!$error) { $configToSave['install_ignore_ip_check'] = $config['install_ignore_ip_check']; } - require BASE . 'install/includes/config.php'; - if(!$error) { - require BASE . 'install/includes/database.php'; + $content = ''; + $saved = Settings::saveConfig($configToSave, BASE . 'config.local.php', $content); + if ($saved) { + success($locale['step_database_config_saved']); + $_SESSION['saved'] = true; - $locale['step_database_importing'] = str_replace('$DATABASE_NAME$', config('database_name'), $locale['step_database_importing']); - success($locale['step_database_importing']); + require BASE . 'config.local.php'; + require BASE . 'install/includes/config.php'; - if(isset($database_error)) { // we failed connect to the database - error($database_error); - } - else { - if(!$db->hasTable('accounts')) { - $tmp = str_replace('$TABLE$', 'accounts', $locale['step_database_error_table']); - error($tmp); - $error = true; - } + if (!$error) { + require BASE . 'install/includes/database.php'; - if(!$db->hasTable('players')) { - $tmp = str_replace('$TABLE$', 'players', $locale['step_database_error_table']); - error($tmp); - $error = true; - } - - if(!$db->hasTable('guilds')) { - $tmp = str_replace('$TABLE$', 'guilds', $locale['step_database_error_table']); - error($tmp); - $error = true; - } - - if(!$error) { - $twig->display('install.installer.html.twig', array( - 'url' => 'tools/5-database.php', - 'message' => $locale['loading_spinner'] - )); - - $content = ''; - $saved = Settings::saveConfig($configToSave, BASE . 'config.local.php', $content); - if($saved) { - success($locale['step_database_config_saved']); - $_SESSION['saved'] = true; + if (isset($database_error)) { // we failed connect to the database + error($database_error); } else { - $_SESSION['config_content'] = $content; - unset($_SESSION['saved']); + if (!$db->hasTable('accounts')) { + $tmp = str_replace('$TABLE$', 'accounts', $locale['step_database_error_table']); + error($tmp); + $error = true; + } - $locale['step_database_error_file'] = str_replace('$FILE$', '' . BASE . 'config.local.php', $locale['step_database_error_file']); - error($locale['step_database_error_file'] . '
- '); + if (!$db->hasTable('players')) { + $tmp = str_replace('$TABLE$', 'players', $locale['step_database_error_table']); + error($tmp); + $error = true; + } + + if (!$db->hasTable('guilds')) { + $tmp = str_replace('$TABLE$', 'guilds', $locale['step_database_error_table']); + error($tmp); + $error = true; + } + + if (!$error) { + $twig->display('install.installer.html.twig', array( + 'url' => 'tools/5-database.php', + 'message' => $locale['loading_spinner'] + )); + } } } + } else { + $_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'] . '
+ '); } } } diff --git a/install/steps/7-finish.php b/install/steps/7-finish.php index 3c4094dc..84c2cce4 100644 --- a/install/steps/7-finish.php +++ b/install/steps/7-finish.php @@ -1,5 +1,7 @@ enabled()) { + // clear plugin_hooks to have fresh hooks + $cache->delete('plugins_hooks'); +} + +require SYSTEM . 'init.php'; +if($error) { + return; +} + +if(USE_ACCOUNT_NAME || USE_ACCOUNT_NUMBER) + $account = $_SESSION['var_account'] ?? null; +else + $account_id = $_SESSION['var_account_id'] ?? null; + +$password = $_SESSION['var_password']; + +if(USE_ACCOUNT_SALT) +{ + $salt = generateRandomString(10, false, true, true); + $password = $salt . $password; +} + +$account_db = new OTS_Account(); +if(isset($account)) + $account_db->find($account); +else + $account_db->load($account_id); + +$player_name = $_SESSION['var_player_name']; +$player_db = new OTS_Player(); +$player_db->find($player_name); + +if(!$player_db->isLoaded()) +{ + $player = new OTS_Player(); + $player->setName($player_name); + + $player_used = &$player; } else { - require SYSTEM . 'init.php'; - if(!$error) { - if(USE_ACCOUNT_NAME || USE_ACCOUNT_NUMBER) - $account = isset($_SESSION['var_account']) ? $_SESSION['var_account'] : null; - else - $account_id = isset($_SESSION['var_account_id']) ? $_SESSION['var_account_id'] : null; + $player_used = &$player_db; +} - $password = $_SESSION['var_password']; +$groups = new OTS_Groups_List(); +$player_used->setGroupId($groups->getHighestId()); - if(USE_ACCOUNT_SALT) - { - $salt = generateRandomString(10, false, true, true); - $password = $salt . $password; +$email = $_SESSION['var_email']; +if($account_db->isLoaded()) { + $account_db->setPassword(encrypt($password)); + $account_db->setEMail($email); + $account_db->save(); + + $account_used = &$account_db; +} +else { + $new_account = new OTS_Account(); + if(USE_ACCOUNT_NAME) { + $new_account->create($account); + } + else { + $new_account->create(null, $account_id); + } + + $new_account->setPassword(encrypt($password)); + $new_account->setEMail($email); + + $new_account->save(); + + $new_account->setCustomField('created', time()); + $new_account->logAction('Account created.'); + + $account_used = &$new_account; +} + +if(USE_ACCOUNT_SALT) + $account_used->setCustomField('salt', $salt); + +$account_used->setCustomField('web_flags', FLAG_ADMIN + FLAG_SUPER_ADMIN); +$account_used->setCustomField('country', 'us'); +$account_used->setCustomField('email_verified', 1); + +if($db->hasColumn('accounts', 'group_id')) + $account_used->setCustomField('group_id', $groups->getHighestId()); +if($db->hasColumn('accounts', 'type')) + $account_used->setCustomField('type', 6); + +if(!$player_db->isLoaded()) + $player->setAccountId($account_used->getId()); +else + $player_db->setAccountId($account_used->getId()); + +success($locale['step_database_created_account']); + +setSession('account', $account_used->getId()); +setSession('password', encrypt($password)); +setSession('remember_me', true); + +if($player_db->isLoaded()) { + $player_db->save(); +} +else { + $player->save(); +} + +if(!News::all()->count()) { + $player_id = 0; + $tmpNewsPlayer = \MyAAC\Models\Player::where('name', $player_name)->first(); + if($tmpNewsPlayer) { + $player_id = $tmpNewsPlayer->id; + } + + News::create([ + 'type' => 1, + 'date' => time(), + 'category' => 2, + 'title' => 'Hello!', + 'body' => 'MyAAC is just READY to use!', + 'player_id' => $player_id, + 'comments' => 'https://my-aac.org', + 'hide' => 0, + ]); + + News::create([ + 'type' => 2, + 'date' => time(), + 'category' => 4, + 'title' => 'Hello tickers!', + 'body' => 'https://my-aac.org', + 'player_id' => $player_id, + 'comments' => '', + 'hide' => 0, + ]); + + success($locale['step_database_created_news']); +} + +$settings = Settings::getInstance(); +foreach($_SESSION as $key => $value) { + if (in_array($key, ['var_usage', 'var_date_timezone', 'var_client'])) { + if ($key == 'var_usage') { + $key = 'anonymous_usage_statistics'; + $value = ((int)$value == 1 ? 'true' : 'false'); + } elseif ($key == 'var_date_timezone') { + $key = 'date_timezone'; + } elseif ($key == 'var_client') { + $key = 'client'; } - $account_db = new OTS_Account(); - if(isset($account)) - $account_db->find($account); - else - $account_db->load($account_id); - - $player_name = $_SESSION['var_player_name']; - $player_db = new OTS_Player(); - $player_db->find($player_name); - - if(!$player_db->isLoaded()) - { - $player = new OTS_Player(); - $player->setName($player_name); - - $player_used = &$player; - } - else { - $player_used = &$player_db; - } - - $groups = new OTS_Groups_List(); - $player_used->setGroupId($groups->getHighestId()); - - $email = $_SESSION['var_email']; - if($account_db->isLoaded()) { - $account_db->setPassword(encrypt($password)); - $account_db->setEMail($email); - $account_db->save(); - - $account_used = &$account_db; - } - else { - $new_account = new OTS_Account(); - if(USE_ACCOUNT_NAME) { - $new_account->create($account); - } - else { - $new_account->create(null, $account_id); - } - - $new_account->setPassword(encrypt($password)); - $new_account->setEMail($email); - - $new_account->save(); - - $new_account->setCustomField('created', time()); - $new_account->logAction('Account created.'); - - $account_used = &$new_account; - } - - if(USE_ACCOUNT_SALT) - $account_used->setCustomField('salt', $salt); - - $account_used->setCustomField('web_flags', FLAG_ADMIN + FLAG_SUPER_ADMIN); - $account_used->setCustomField('country', 'us'); - if($db->hasColumn('accounts', 'group_id')) - $account_used->setCustomField('group_id', $groups->getHighestId()); - if($db->hasColumn('accounts', 'type')) - $account_used->setCustomField('type', 6); - - if(!$player_db->isLoaded()) - $player->setAccountId($account_used->getId()); - else - $player_db->setAccountId($account_used->getId()); - - success($locale['step_database_created_account']); - - setSession('account', $account_used->getId()); - setSession('password', encrypt($password)); - setSession('remember_me', true); - - if($player_db->isLoaded()) { - $player_db->save(); - } - else { - $player->save(); - } - - $player_id = 0; - $query = $db->query("SELECT `id` FROM `players` WHERE `name` = " . $db->quote($player_name) . ";"); - if($query->rowCount() == 1) { - $query = $query->fetch(); - $player_id = $query['id']; - } - - $query = $db->query("SELECT `id` FROM `" . TABLE_PREFIX ."news` WHERE `title` LIKE 'Hello!';"); - if($query->rowCount() == 0) { - if(query("INSERT INTO `" . TABLE_PREFIX ."news` (`id`, `type`, `date`, `category`, `title`, `body`, `player_id`, `comments`, `hide`) VALUES (NULL, '1', UNIX_TIMESTAMP(), '2', 'Hello!', 'MyAAC is just READY to use!', " . $player_id . ", 'https://my-aac.org', '0'); - INSERT INTO `myaac_news` (`id`, `type`, `date`, `category`, `title`, `body`, `player_id`, `comments`, `hide`) VALUES (NULL, '2', UNIX_TIMESTAMP(), '4', 'Hello tickets!', 'https://my-aac.org', " . $player_id . ", '', '0');")) { - success($locale['step_database_created_news']); - } - } - - $settings = Settings::getInstance(); - foreach($_SESSION as $key => $value) { - if (in_array($key, ['var_usage', 'var_date_timezone', 'var_client'])) { - if ($key == 'var_usage') { - $key = 'anonymous_usage_statistics'; - $value = ((int)$value == 1 ? 'true' : 'false'); - } elseif ($key == 'var_date_timezone') { - $key = 'date_timezone'; - } elseif ($key == 'var_client') { - $key = 'client'; - } - - $settings->updateInDatabase('core', $key, $value); - } - } - success('Settings saved.'); - - $twig->display('install.installer.html.twig', array( - 'url' => 'tools/7-finish.php', - 'message' => $locale['importing_spinner'] - )); - - if(!isset($_SESSION['installed'])) { - if (!array_key_exists('CI', getenv())) { - $report_url = 'https://my-aac.org/report_install.php?v=' . MYAAC_VERSION . '&b=' . urlencode(BASE_URL); - if (function_exists('curl_version')) - { - $curl = curl_init(); - curl_setopt($curl, CURLOPT_URL, $report_url); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); - curl_exec($curl); - curl_close($curl); - } - else if (ini_get('allow_url_fopen') ) { - file_get_contents($report_url); - } - } - - $_SESSION['installed'] = true; - } - - foreach($_SESSION as $key => $value) { - if(strpos($key, 'var_') !== false) - unset($_SESSION[$key]); - } - unset($_SESSION['saved']); - if(file_exists(CACHE . 'install.txt')) { - unlink(CACHE . 'install.txt'); - } + $settings->updateInDatabase('core', $key, $value); } } +success('Settings saved.'); + +$twig->display('install.installer.html.twig', array( + 'url' => 'tools/7-finish.php', + 'message' => $locale['importing_spinner'] +)); + +if(!isset($_SESSION['installed'])) { + if (!array_key_exists('CI', getenv())) { + $report_url = 'https://my-aac.org/report_install.php?v=' . MYAAC_VERSION . '&b=' . urlencode(BASE_URL); + if (function_exists('curl_version')) + { + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $report_url); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_exec($curl); + curl_close($curl); + } + else if (ini_get('allow_url_fopen') ) { + file_get_contents($report_url); + } + } + + $_SESSION['installed'] = true; +} + +foreach($_SESSION as $key => $value) { + if(strpos($key, 'var_') !== false) + unset($_SESSION[$key]); +} +unset($_SESSION['saved']); +if(file_exists(CACHE . 'install.txt')) { + unlink(CACHE . 'install.txt'); +} + +$hooks->trigger(HOOK_INSTALL_FINISH_END); diff --git a/install/tools/5-database.php b/install/tools/5-database.php index 12e02b90..ff0bcbbb 100644 --- a/install/tools/5-database.php +++ b/install/tools/5-database.php @@ -32,6 +32,9 @@ if($db->hasTable(TABLE_PREFIX . 'account_actions')) { else { // import schema try { + $locale['step_database_importing'] = str_replace('$DATABASE_NAME$', config('database_name'), $locale['step_database_importing']); + success($locale['step_database_importing']); + $db->query(file_get_contents(BASE . 'install/includes/schema.sql')); $locale['step_database_success_schema'] = str_replace('$PREFIX$', TABLE_PREFIX, $locale['step_database_success_schema']); @@ -138,73 +141,74 @@ if(!$db->hasColumn('accounts', 'premium_points')) { success($locale['step_database_adding_field'] . ' accounts.premium_points...'); } -if($db->hasColumn('guilds', 'checkdata')) { - if(query("ALTER TABLE `guilds` MODIFY `checkdata` INT NOT NULL DEFAULT 0;")) - success($locale['step_database_modifying_field'] . ' guilds.checkdata...'); -} - -if(!$db->hasColumn('guilds', 'motd')) { - if(query("ALTER TABLE `guilds` ADD `motd` VARCHAR(255) NOT NULL DEFAULT '';")) - success($locale['step_database_adding_field'] . ' guilds.motd...'); -} -else { - if(query("ALTER TABLE `guilds` MODIFY `motd` VARCHAR(255) NOT NULL DEFAULT '';")) - success($locale['step_database_modifying_field'] . ' guilds.motd...'); -} - -if(!$db->hasColumn('guilds', 'description')) { - if(query("ALTER TABLE `guilds` ADD `description` TEXT NOT NULL;")) - success($locale['step_database_adding_field'] . ' guilds.description...'); -} - -if($db->hasColumn('guilds', 'logo_gfx_name')) { - if(query("ALTER TABLE `guilds` CHANGE `logo_gfx_name` `logo_name` VARCHAR( 255 ) NOT NULL DEFAULT 'default.gif';")) { - $tmp = str_replace('$FIELD$', 'guilds.logo_gfx_name', $locale['step_database_changing_field']); - $tmp = str_replace('$FIELD_NEW$', 'guilds.logo_name', $tmp); - success($tmp); +if ($db->hasTable('guilds')) { + if ($db->hasColumn('guilds', 'checkdata')) { + if (query("ALTER TABLE `guilds` MODIFY `checkdata` INT NOT NULL DEFAULT 0;")) + success($locale['step_database_modifying_field'] . ' guilds.checkdata...'); } -} -else if(!$db->hasColumn('guilds', 'logo_name')) { - if(query("ALTER TABLE `guilds` ADD `logo_name` VARCHAR( 255 ) NOT NULL DEFAULT 'default.gif';")) - success($locale['step_database_adding_field'] . ' guilds.logo_name...'); -} -if(!$db->hasColumn('players', 'created')) { - if(query("ALTER TABLE `players` ADD `created` INT(11) NOT NULL DEFAULT 0;")) - success($locale['step_database_adding_field'] . ' players.created...'); -} + if (!$db->hasColumn('guilds', 'motd')) { + if (query("ALTER TABLE `guilds` ADD `motd` VARCHAR(255) NOT NULL DEFAULT '';")) + success($locale['step_database_adding_field'] . ' guilds.motd...'); + } else { + if (query("ALTER TABLE `guilds` MODIFY `motd` VARCHAR(255) NOT NULL DEFAULT '';")) + success($locale['step_database_modifying_field'] . ' guilds.motd...'); + } -if(!$db->hasColumn('players', 'deleted') && !$db->hasColumn('players', 'deletion')) { - if(query("ALTER TABLE `players` ADD `deleted` TINYINT(1) NOT NULL DEFAULT 0;")) - success($locale['step_database_adding_field'] . ' players.deleted...'); -} + if (!$db->hasColumn('guilds', 'description')) { + if (query("ALTER TABLE `guilds` ADD `description` TEXT NOT NULL;")) + success($locale['step_database_adding_field'] . ' guilds.description...'); + } -if($db->hasColumn('players', 'hide_char')) { - if(!$db->hasColumn('players', 'hide')) { - if(query("ALTER TABLE `players` CHANGE `hide_char` `hide` TINYINT(1) NOT NULL DEFAULT 0;")) { - $tmp = str_replace('$FIELD$', 'players.hide_char', $locale['step_database_changing_field']); - $tmp = str_replace('$FIELD_NEW$', 'players.hide', $tmp); + if ($db->hasColumn('guilds', 'logo_gfx_name')) { + if (query("ALTER TABLE `guilds` CHANGE `logo_gfx_name` `logo_name` VARCHAR( 255 ) NOT NULL DEFAULT 'default.gif';")) { + $tmp = str_replace('$FIELD$', 'guilds.logo_gfx_name', $locale['step_database_changing_field']); + $tmp = str_replace('$FIELD_NEW$', 'guilds.logo_name', $tmp); success($tmp); } + } else if (!$db->hasColumn('guilds', 'logo_name')) { + if (query("ALTER TABLE `guilds` ADD `logo_name` VARCHAR( 255 ) NOT NULL DEFAULT 'default.gif';")) + success($locale['step_database_adding_field'] . ' guilds.logo_name...'); } } -else if(!$db->hasColumn('players', 'hide')) { - if(query("ALTER TABLE `players` ADD `hide` TINYINT(1) NOT NULL DEFAULT 0;")) - success($locale['step_database_adding_field'] . ' players.hide...'); -} -if(!$db->hasColumn('players', 'comment')) { - if(query("ALTER TABLE `players` ADD `comment` TEXT NOT NULL;")) - success($locale['step_database_adding_field'] . ' players.comment...'); -} +if ($db->hasTable('players')) { + if (!$db->hasColumn('players', 'created')) { + if (query("ALTER TABLE `players` ADD `created` INT(11) NOT NULL DEFAULT 0;")) + success($locale['step_database_adding_field'] . ' players.created...'); + } -if($db->hasColumn('players', 'rank_id')) { - if(query("ALTER TABLE players MODIFY `rank_id` INT(11) NOT NULL DEFAULT 0;")) - success($locale['step_database_modifying_field'] . ' players.rank_id...'); + if (!$db->hasColumn('players', 'deleted') && !$db->hasColumn('players', 'deletion')) { + if (query("ALTER TABLE `players` ADD `deleted` TINYINT(1) NOT NULL DEFAULT 0;")) + success($locale['step_database_adding_field'] . ' players.deleted...'); + } - if($db->hasColumn('players', 'guildnick')) { - if(query("ALTER TABLE players MODIFY `guildnick` VARCHAR(255) NOT NULL DEFAULT '';")) { - success($locale['step_database_modifying_field'] . ' players.guildnick...'); + if ($db->hasColumn('players', 'hide_char')) { + if (!$db->hasColumn('players', 'hide')) { + if (query("ALTER TABLE `players` CHANGE `hide_char` `hide` TINYINT(1) NOT NULL DEFAULT 0;")) { + $tmp = str_replace('$FIELD$', 'players.hide_char', $locale['step_database_changing_field']); + $tmp = str_replace('$FIELD_NEW$', 'players.hide', $tmp); + success($tmp); + } + } + } else if (!$db->hasColumn('players', 'hide')) { + if (query("ALTER TABLE `players` ADD `hide` TINYINT(1) NOT NULL DEFAULT 0;")) + success($locale['step_database_adding_field'] . ' players.hide...'); + } + + if (!$db->hasColumn('players', 'comment')) { + if (query("ALTER TABLE `players` ADD `comment` TEXT NOT NULL;")) + success($locale['step_database_adding_field'] . ' players.comment...'); + } + + if ($db->hasColumn('players', 'rank_id')) { + if (query("ALTER TABLE players MODIFY `rank_id` INT(11) NOT NULL DEFAULT 0;")) + success($locale['step_database_modifying_field'] . ' players.rank_id...'); + + if ($db->hasColumn('players', 'guildnick')) { + if (query("ALTER TABLE players MODIFY `guildnick` VARCHAR(255) NOT NULL DEFAULT '';")) { + success($locale['step_database_modifying_field'] . ' players.guildnick...'); + } } } } diff --git a/install/tools/7-finish.php b/install/tools/7-finish.php index 0715ce01..37914a5f 100644 --- a/install/tools/7-finish.php +++ b/install/tools/7-finish.php @@ -77,6 +77,8 @@ if(ModelsFAQ::count() == 0) { ]); } +$hooks->trigger(HOOK_INSTALL_FINISH); + $db->setClearCacheAfter(true); $locale['step_finish_desc'] = str_replace('$ADMIN_PANEL$', generateLink(str_replace('tools/', '',ADMIN_URL), $locale['step_finish_admin_panel'], true), $locale['step_finish_desc']); diff --git a/nginx-sample.conf b/nginx-sample.conf index e601abcb..40d85fb4 100644 --- a/nginx-sample.conf +++ b/nginx-sample.conf @@ -10,17 +10,20 @@ server { # this is very important, be sure its in your nginx conf - it prevents access to logs etc. location ~ /system { deny all; - return 404; } - # block .htaccess - location ~ /\.ht { + location /vendor { + deny all; + } + + # block .htaccess, CHANGELOG.md, composer.json etc. + # this is to prevent finding software versions + location ~\.(ht|md|json|dist)$ { deny all; } # block git files and folders location ~ /\.git { - return 404; deny all; } diff --git a/phpstan.neon b/phpstan.neon index b77bc1d2..fda6a07c 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -29,6 +29,7 @@ parameters: - '#Variable \$[a-zA-Z0-9\\_]+ might not be defined#' # Eloquent models - '#Call to an undefined static method [a-zA-Z0-9\\_]+::[a-zA-Z0-9\\_]+()#' + - '#Call to an undefined method object::toArray\(\)#' # system/pages/highscores.php - '#Call to an undefined method Illuminate\\Database\\Query\\Builder::withOnlineStatus\(\)#' - '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::\$online_status#' diff --git a/plugins/email-confirmed-reward/reward.php b/plugins/email-confirmed-reward/reward.php index 11af5b34..e485dcf0 100644 --- a/plugins/email-confirmed-reward/reward.php +++ b/plugins/email-confirmed-reward/reward.php @@ -1,8 +1,6 @@ hasColumn('accounts', 'coins'); $rewardCoins = setting('core.account_mail_confirmed_reward_coins'); if ($rewardCoins > 0 && !$hasCoinsColumn) { diff --git a/plugins/example.json b/plugins/example.json index 20415897..68805cb9 100644 --- a/plugins/example.json +++ b/plugins/example.json @@ -25,7 +25,8 @@ "hooks": { "Example Hook": { "type": "BEFORE_PAGE", - "file": "plugins/example/before.php" + "file": "plugins/example/before.php", + "priority": 1000 } }, "routes": { @@ -33,12 +34,20 @@ "pattern": "/YourAwesomePage/{name:string}/{page:int}", "file": "plugins/your-plugin/your-awesome-page.php", "method": "GET", - "priority": "130" + "priority": 130 }, "Redirect Example": { "redirect_from": "/redirectExample", "redirect_to": "account/manage" } }, - "settings": "plugins/your-plugin-folder/settings.php" + "routes-default-priority": 1000, + "pages-default-priority": 1000, + "settings": "plugins/your-plugin-folder/settings.php", + "autoload": { + "pages": true, + "pagesSubFolders": false, + "commands": true, + "themes": true + } } diff --git a/release.sh b/release.sh index f2fa9c30..855db72f 100644 --- a/release.sh +++ b/release.sh @@ -38,7 +38,11 @@ if [ $1 = "prepare" ]; then cd $dir || exit # dependencies - composer install --prefer-dist --optimize-autoloader + composer install --no-dev --prefer-dist --optimize-autoloader + npm install + + # node_modules is useless, we already have copy in tools/ext + rm -R node_modules echo "Now you can make changes to $dir. When you are ready, type 'release.sh pack'" exit diff --git a/system/database.php b/system/database.php index f20ca720..34b4574a 100644 --- a/system/database.php +++ b/system/database.php @@ -127,6 +127,7 @@ try { } if(defined('MYAAC_INSTALL')) { + $error = $e->getMessage(); return; // installer will take care of this } diff --git a/system/functions.php b/system/functions.php index c0fb7f2a..70c0b93e 100644 --- a/system/functions.php +++ b/system/functions.php @@ -87,18 +87,29 @@ function getForumBoardLink($board_id, $page = NULL): string { return BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'forum/board/' . (int)$board_id . (isset($page) ? '/' . $page : ''); } -function getPlayerLink($name, $generate = true): string +function getPlayerLink($name, $generate = true, bool $colored = false): string { - if(is_numeric($name)) - { - $player = new OTS_Player(); + $player = new OTS_Player(); + + if(is_numeric($name)) { $player->load((int)$name); - if($player->isLoaded()) - $name = $player->getName(); + } + else { + $player->find($name); } + if (!$player->isLoaded()) { + return '(error)'; + } + + $name = $player->getName(); + $url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'characters/' . urlencode($name); + if ($colored) { + $name = '' . $name . ''; + } + if(!$generate) return $url; return generateLink($url, $name); } @@ -1623,7 +1634,7 @@ function removeIfFirstSlash(&$text) { }; function escapeHtml($html) { - return htmlentities($html, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); + return htmlspecialchars($html); } function getGuildNameById($id) diff --git a/system/init.php b/system/init.php index 10379b19..9bc14514 100644 --- a/system/init.php +++ b/system/init.php @@ -134,10 +134,6 @@ $ots = POT::getInstance(); $eloquentConnection = null; require_once SYSTEM . 'database.php'; -if ($config_lua_reload) { - clearCache(); -} - // verify myaac tables exists in database if(!defined('MYAAC_INSTALL') && !$db->hasTable('myaac_account_actions')) { throw new RuntimeException('Seems that the table myaac_account_actions of MyAAC doesn\'t exist in the database. This is a fatal error. You can try to reinstall MyAAC by visiting ' . BASE_URL . 'install'); @@ -163,8 +159,8 @@ date_default_timezone_set(setting('core.date_timezone')); setting( [ - 'core.account_create_character_create', - setting('core.account_create_character_create') && (!setting('core.mail_enabled') || !setting('core.account_mail_verify')) + 'core.account_mail_verify', + setting('core.account_mail_verify') && setting('core.mail_enabled') ] ); diff --git a/system/libs/pot/OTS_Base_DAO.php b/system/libs/pot/OTS_Base_DAO.php index 1ab75e6f..48b1ff35 100644 --- a/system/libs/pot/OTS_Base_DAO.php +++ b/system/libs/pot/OTS_Base_DAO.php @@ -15,15 +15,15 @@ /** * Basic data access object routines. - * + * *

* This class defines basic mechanisms for all classes that will represent database accessors. However no coding logic is defined here - only connection handling and PHP core-related stuff to enable variouse operations with objects. *

- * + * *

* This class is mostly usefull when you create own extensions for POT code. *

- * + * * @package POT * @version 0.1.0 */ @@ -31,14 +31,14 @@ abstract class OTS_Base_DAO implements IOTS_DAO { /** * Database connection. - * + * * @var PDO */ protected $db; /** * Sets database connection handler. - * + * * @version 0.1.0 */ public function __construct() @@ -48,11 +48,11 @@ abstract class OTS_Base_DAO implements IOTS_DAO /** * Magic PHP5 method. - * + * *

* Allows object serialisation. *

- * + * * @return array List of properties that should be saved. */ public function __sleep() @@ -62,7 +62,7 @@ abstract class OTS_Base_DAO implements IOTS_DAO /** * Magic PHP5 method. - * + * *

* Allows object unserialisation. *

@@ -74,7 +74,7 @@ abstract class OTS_Base_DAO implements IOTS_DAO /** * Creates clone of object. - * + * *

* Copy of object needs to have different ID. *

@@ -83,38 +83,4 @@ abstract class OTS_Base_DAO implements IOTS_DAO { unset($this->data['id']); } - -/** - * Magic PHP5 method. - * - *

- * Allows object importing from {@link http://www.php.net/manual/en/function.var-export.php var_export()}. - *

- * - * @version 0.1.0 - * @param array $properties List of object properties. - */ - public static function __set_state($properties) - { - // deletes database handle - if( isset($properties['db']) ) - { - unset($properties['db']); - } - - // initializes new object with current database connection - $object = new self(); - - // loads properties - foreach($properties as $name => $value) - { - $object->$name = $value; - } - - return $object; - } } - -/**#@-*/ - -?> diff --git a/system/libs/pot/OTS_Buffer.php b/system/libs/pot/OTS_Buffer.php index c10ee942..69cfea18 100644 --- a/system/libs/pot/OTS_Buffer.php +++ b/system/libs/pot/OTS_Buffer.php @@ -15,15 +15,15 @@ /** * Binary buffer container. - * + * *

* This is generic class for classes that uses buffer-baser read-write operations (it can also emulate C-like pointers). *

- * + * *

* Note that unlike NetworkMessage class from OTServ C++ source code, in this one reading and writing positions are separated so you can pararelly read and write it's content like for example using object of this class as stack. *

- * + * * @package POT * @version 0.1.3 * @property string $buffer Properties binary string. @@ -39,381 +39,391 @@ class OTS_Buffer { /** * Node properties stream. - * + * * @var string */ - protected $buffer; + protected $buffer; /** * Properties stream pointer. - * + * * @var int */ - protected $pos; + protected $pos; /** * Initializes new buffered reader. - * + * * @param string $buffer Buffer content. */ - public function __construct($buffer = '') - { - $this->buffer = $buffer; - $this->pos = 0; - } + public function __construct($buffer = '') + { + $this->buffer = $buffer; + $this->pos = 0; + } /** * Magic PHP5 method. - * + * *

* Allows object importing from {@link http://www.php.net/manual/en/function.var-export.php var_export()}. *

- * + * * @param array $properties List of object properties. */ - public static function __set_state($properties) - { - $object = new self(); + public static function __set_state($properties) + { + $object = new self(); - // loads properties - foreach($properties as $name => $value) - { - $object->$name = $value; - } + // loads properties + foreach($properties as $name => $value) + { + $object->$name = $value; + } - return $object; - } + return $object; + } /** * Returs properties stream. - * + * * @return string Properties stream. */ - public function getBuffer() - { - return $this->buffer; - } + public function getBuffer() + { + return $this->buffer; + } /** * Sets properties stream. - * + * * @param string Properties stream. */ - public function setBuffer($buffer) - { - $this->buffer = $buffer; - $this->pos = 0; - } + public function setBuffer($buffer) + { + $this->buffer = $buffer; + $this->pos = 0; + } /** * Checks if there is anything left in stream. - * + * * @return bool False if pointer is at the end of stream. */ - public function isValid() - { - return $this->pos < strlen($this->buffer); - } + public function isValid() + { + return $this->pos < strlen($this->buffer); + } /** * Checks stream end state. - * + * * @param int $size Amount of bytes that are going to be read. * @throws E_OTS_OutOfBuffer When there is read attemp after end of stream. */ - protected function check($size = 1) - { - if( strlen($this->buffer) < $this->pos + $size) - { - throw new E_OTS_OutOfBuffer(); - } - } + protected function check($size = 1) + { + if( strlen($this->buffer) < $this->pos + $size) + { + throw new E_OTS_OutOfBuffer(); + } + } /** * Returns single byte. - * + * * @return int Byte (char) value. * @throws E_OTS_OutOfBuffer When there is read attemp after end of stream. */ - public function getChar() - { - // checks buffer size - $this->check(); + public function getChar() + { + // checks buffer size + $this->check(); - $value = ord($this->buffer[$this->pos]); - $this->pos++; - return $value; - } + $value = ord($this->buffer[$this->pos]); + $this->pos++; + return $value; + } /** * Appends single byte to buffer. - * + * * @param int $char Byte (char) value. */ - public function putChar($char) - { - $this->buffer .= chr($char); - } + public function putChar($char) + { + $this->buffer .= chr($char); + } /** * Returns double byte. - * + * * @return int Word (short) value. * @throws E_OTS_OutOfBuffer When there is read attemp after end of stream. */ - public function getShort() - { - // checks buffer size - $this->check(2); + public function getShort() + { + // checks buffer size + $this->check(2); - $value = unpack('v', substr($this->buffer, $this->pos, 2) ); - $this->pos += 2; - return $value[1]; - } + $value = unpack('v', substr($this->buffer, $this->pos, 2) ); + $this->pos += 2; + return $value[1]; + } /** * Appends double byte to buffer. - * + * * @param int $short Word (short) value. */ - public function putShort($short) - { - $this->buffer .= pack('v', $short); - } + public function putShort($short) + { + $this->buffer .= pack('v', $short); + } /** * Returns quater byte. - * + * * @return int Double word (long) value. * @throws E_OTS_OutOfBuffer When there is read attemp after end of stream. */ - public function getLong() - { - // checks buffer size - $this->check(4); + public function getLong() + { + // checks buffer size + $this->check(4); - $value = unpack('V', substr($this->buffer, $this->pos, 4) ); - $this->pos += 4; - return $value[1]; - } + $value = unpack('V', substr($this->buffer, $this->pos, 4) ); + $this->pos += 4; + return $value[1]; + } + + public function getLongLong() + { + // checks buffer size + $this->check(8); + + $value = unpack('P', substr($this->buffer, $this->pos, 8) ); + $this->pos += 8; + return $value[1]; + } /** * Appends quater byte to buffer. - * + * * @param int $long Double word (long) value. */ - public function putLong($long) - { - $this->buffer .= pack('V', $long); - } + public function putLong($long) + { + $this->buffer .= pack('V', $long); + } /** * Returns string from buffer. - * + * *

* If length is not given then treats first short value from current buffer as string length. *

- * + * * @param int|bool $length String length. * @return string First substring. * @throws E_OTS_OutOfBuffer When there is read attemp after end of stream. */ - public function getString($length = false) - { - // reads string length if not given - if($length === false) - { - $length = $this->getShort(); - } + public function getString($length = false) + { + // reads string length if not given + if($length === false) + { + $length = $this->getShort(); + } - // checks buffer size - $this->check($length); + // checks buffer size + $this->check($length); - // copies substring - $value = substr($this->buffer, $this->pos, $length); - $this->pos += $length; - return $value; - } + // copies substring + $value = substr($this->buffer, $this->pos, $length); + $this->pos += $length; + return $value; + } /** * Appends string to buffer. - * + * * @param string $string Binary length. * @param bool $dynamic Whether if string length is fixed or not (if it is dynamic then length will be inserted as short before string chunk). */ - public function putString($string, $dynamic = true) - { - // appends string length if requires - if($dynamic) - { - $this->putShort( strlen($string) ); - } + public function putString($string, $dynamic = true) + { + // appends string length if requires + if($dynamic) + { + $this->putShort( strlen($string) ); + } - $this->buffer .= $string; - } + $this->buffer .= $string; + } /** * Empties buffer. */ - public function reset() - { - $this->__construct(); - } + public function reset() + { + $this->__construct(); + } /** * Returns current read position. - * + * * @return int Read position. */ - public function getPos() - { - return $this->pos; - } + public function getPos() + { + return $this->pos; + } /** * Seeks current reading position. - * + * * @param int $pos Read position. */ - public function setPos($pos) - { - $this->pos = $pos; - } + public function setPos($pos) + { + $this->pos = $pos; + } /** * Returns buffer size. - * + * * @return int Buffer length. */ - public function getSize() - { - return strlen($this->buffer); - } + public function getSize() + { + return strlen($this->buffer); + } /** * Skips given amount of bytes. - * + * * @param int $n Bytes to skip. * @throws E_OTS_OutOfBuffer When there is read attemp after end of stream. */ - public function skip($n) - { - $this->check($n); - $this->pos += $n; - } + public function skip($n) + { + $this->check($n); + $this->pos += $n; + } /** * Magic PHP5 method. - * + * * @param string $name Property name. * @return mixed Property value. * @throws OutOfBoundsException For non-supported properties. * @throws E_OTS_OutOfBuffer When there is read attemp after end of stream. */ - public function __get($name) - { - switch($name) - { - // simple properties - case 'buffer': - return $this->buffer; + public function __get($name) + { + switch($name) + { + // simple properties + case 'buffer': + return $this->buffer; - // isValid() wrapper - case 'valid': - return $this->isValid(); + // isValid() wrapper + case 'valid': + return $this->isValid(); - // getChar() wrapper - case 'char': - return $this->getChar(); + // getChar() wrapper + case 'char': + return $this->getChar(); - // getShort() wrapper - case 'short': - return $this->getShort(); + // getShort() wrapper + case 'short': + return $this->getShort(); - // getLong() wrapper - case 'long': - return $this->getLong(); + // getLong() wrapper + case 'long': + return $this->getLong(); - // getString() wrapper - case 'string': - return $this->getString(); + // getString() wrapper + case 'string': + return $this->getString(); - // getPos() wrapper - case 'pos': - return $this->getPos(); + // getPos() wrapper + case 'pos': + return $this->getPos(); - // getSize() wrapper - case 'size': - return $this->getSize(); + // getSize() wrapper + case 'size': + return $this->getSize(); - default: - throw new OutOfBoundsException(); - } - } + default: + throw new OutOfBoundsException(); + } + } /** * Magic PHP5 method. - * + * * @version 0.1.3 * @param string $name Property name. * @param mixed $value Property value. * @throws OutOfBoundsException For non-supported properties. */ - public function __set($name, $value) - { - switch($name) - { - // buffer needs to be reset - case 'buffer': - $this->setBuffer($value); - break; + public function __set($name, $value) + { + switch($name) + { + // buffer needs to be reset + case 'buffer': + $this->setBuffer($value); + break; - // putChar() wrapper - case 'char': - $this->putChar($value); - break; + // putChar() wrapper + case 'char': + $this->putChar($value); + break; - // putShort() wrapper - case 'short': - $this->putShort($value); - break; + // putShort() wrapper + case 'short': + $this->putShort($value); + break; - // putLong() wrapper - case 'long': - $this->putLong($value); - break; + // putLong() wrapper + case 'long': + $this->putLong($value); + break; - // putString() wrapper - case 'string': - $this->putString($value); - break; + // putString() wrapper + case 'string': + $this->putString($value); + break; - // setPos() wrapper - case 'pos': - $this->setPos($value); - break; + // setPos() wrapper + case 'pos': + $this->setPos($value); + break; - default: - throw new OutOfBoundsException(); - } - } + default: + throw new OutOfBoundsException(); + } + } /** * Returns string representation of buffer object. - * + * * @return string Object's buffer. */ - public function __toString() - { - return $this->buffer; - } + public function __toString() + { + return $this->buffer; + } /** * Resets pointer of cloned object. */ - public function __clone() - { - $this->pos = 0; - } + public function __clone() + { + $this->pos = 0; + } } /**#@-*/ diff --git a/system/libs/pot/OTS_Monster.php b/system/libs/pot/OTS_Monster.php index 19482dce..759375f5 100644 --- a/system/libs/pot/OTS_Monster.php +++ b/system/libs/pot/OTS_Monster.php @@ -57,10 +57,10 @@ class OTS_Monster extends DOMDocument * @return string Name. * @throws DOMException On DOM operation error. */ - public function getName() - { - return $this->documentElement->getAttribute('name'); - } + public function getName() + { + return $this->documentElement->getAttribute('name'); + } /** * Returns monster race. @@ -68,10 +68,10 @@ class OTS_Monster extends DOMDocument * @return string Race. * @throws DOMException On DOM operation error. */ - public function getRace() - { - return $this->documentElement->getAttribute('race'); - } + public function getRace() + { + return $this->documentElement->getAttribute('race'); + } /** * Returns amount of experience for killing this monster. @@ -79,10 +79,10 @@ class OTS_Monster extends DOMDocument * @return int Experience points. * @throws DOMException On DOM operation error. */ - public function getExperience() - { - return (int) $this->documentElement->getAttribute('experience'); - } + public function getExperience() + { + return (int) $this->documentElement->getAttribute('experience'); + } /** * Returns monster speed. @@ -90,10 +90,10 @@ class OTS_Monster extends DOMDocument * @return int Speed. * @throws DOMException On DOM operation error. */ - public function getSpeed() - { - return (int) $this->documentElement->getAttribute('speed'); - } + public function getSpeed() + { + return (int) $this->documentElement->getAttribute('speed'); + } /** * Returns amount of mana required to summon this monster. @@ -101,18 +101,18 @@ class OTS_Monster extends DOMDocument * @return int|bool Mana required (false if not possible). * @throws DOMException On DOM operation error. */ - public function getManaCost() - { - // check if it is possible to summon this monster - if( $this->documentElement->hasAttribute('manacost') ) - { - return (int) $this->documentElement->getAttribute('manacost'); - } - else - { - return false; - } - } + public function getManaCost() + { + // check if it is possible to summon this monster + if( $this->documentElement->hasAttribute('manacost') ) + { + return (int) $this->documentElement->getAttribute('manacost'); + } + else + { + return false; + } + } /** * Returns monster HP. @@ -120,10 +120,10 @@ class OTS_Monster extends DOMDocument * @return int Hit points. * @throws DOMException On DOM operation error. */ - public function getHealth() - { - return (int) $this->documentElement->getElementsByTagName('health')->item(0)->getAttribute('max'); - } + public function getHealth() + { + return (int) $this->documentElement->getElementsByTagName('health')->item(0)->getAttribute('max'); + } /** * Returns all monster flags (in format flagname => value). @@ -131,20 +131,21 @@ class OTS_Monster extends DOMDocument * @return array Flags. * @throws DOMException On DOM operation error. */ - public function getFlags() - { - $flags = array(); + public function getFlags() + { + $flags = array(); - // read all flags - foreach( $this->documentElement->getElementsByTagName('flags')->item(0)->getElementsByTagName('flag') as $flag) - { - $flag = $flag->attributes->item(0); + if ($this->documentElement->getElementsByTagName('flags')->item(0)) { + foreach( $this->documentElement->getElementsByTagName('flags')->item(0)->getElementsByTagName('flag') as $flag) + { + $flag = $flag->attributes->item(0); - $flags[$flag->nodeName] = (int) $flag->nodeValue; - } + $flags[$flag->nodeName] = (int) $flag->nodeValue; + } + } - return $flags; - } + return $flags; + } /** * Returns specified flag value. @@ -153,21 +154,21 @@ class OTS_Monster extends DOMDocument * @return int|bool Flag value (false if not set). * @throws DOMException On DOM operation error. */ - public function getFlag($flag) - { - // searches for flag - foreach( $this->documentElement->getElementsByTagName('flags')->item(0)->getElementsByTagName('flag') as $flag) - { - // found - if( $flag->hasAttribute($flag) ) - { - return (int) $flag->getAttribute($flag); - } - } + public function getFlag($flag) + { + // searches for flag + foreach( $this->documentElement->getElementsByTagName('flags')->item(0)->getElementsByTagName('flag') as $flag) + { + // found + if( $flag->hasAttribute($flag) ) + { + return (int) $flag->getAttribute($flag); + } + } - // not found - return false; - } + // not found + return false; + } /** * Returns voices that monster can sound. @@ -175,64 +176,64 @@ class OTS_Monster extends DOMDocument * @return array List of voices. * @throws DOMException On DOM operation error. */ - public function getVoices() - { - $voices = array(); + public function getVoices() + { + $voices = array(); - $element = $this->documentElement->getElementsByTagName('voices')->item(0); + $element = $this->documentElement->getElementsByTagName('voices')->item(0); - // checks if it has any voices - if( isset($element) ) - { - // loads all voices - foreach( $element->getElementsByTagName('voice') as $voice) - { - $voices[] = $voice->getAttribute('sentence'); - } - } + // checks if it has any voices + if( isset($element) ) + { + // loads all voices + foreach( $element->getElementsByTagName('voice') as $voice) + { + $voices[] = $voice->getAttribute('sentence'); + } + } - return $voices; - } + return $voices; + } /** * @return array List of item IDs. */ - public function getLoot() - { - $loot = array(); + public function getLoot() + { + $loot = array(); - $element = $this->documentElement->getElementsByTagName('loot')->item(0); + $element = $this->documentElement->getElementsByTagName('loot')->item(0); - // checks if it has any loot - if( isset($element) ) - { - // adds all items - foreach( $element->getElementsByTagName('item') as $item) - { - $chance = $item->getAttribute('chance'); - if(empty($chance)) { - $chance = $item->getAttribute('chance1'); - if(empty($chance)) { - $chance = 100000; - } - } + // checks if it has any loot + if( isset($element) ) + { + // adds all items + foreach( $element->getElementsByTagName('item') as $item) + { + $chance = $item->getAttribute('chance'); + if(empty($chance)) { + $chance = $item->getAttribute('chance1'); + if(empty($chance)) { + $chance = 100000; + } + } - $count = $item->getAttribute('countmax'); - if(empty($count)) { - $count = 1; - } + $count = $item->getAttribute('countmax'); + if(empty($count)) { + $count = 1; + } - $id = $item->getAttribute('id'); - if(empty($id)) { - $id = $item->getAttribute('name'); - } + $id = $item->getAttribute('id'); + if(empty($id)) { + $id = $item->getAttribute('name'); + } - $loot[] = array('id' => $id, 'count' => $count, 'chance' => $chance); - } - } + $loot[] = array('id' => $id, 'count' => $count, 'chance' => $chance); + } + } - return $loot; - } + return $loot; + } /** * Returns all possible loot. @@ -247,33 +248,33 @@ class OTS_Monster extends DOMDocument * @throws E_OTS_NotLoaded When there is no items list available in global POT instance. * @throws DOMException On DOM operation error. */ - public function getItems() - { - $loot = array(); - $keys = array(); - $items = POT::getInstance()->getItemsList(); + public function getItems() + { + $loot = array(); + $keys = array(); + $items = POT::getInstance()->getItemsList(); - $element = $this->documentElement->getElementsByTagName('loot')->item(0); + $element = $this->documentElement->getElementsByTagName('loot')->item(0); - // checks if it has any loot - if( isset($element) ) - { - // adds all items - foreach( $element->getElementsByTagName('item') as $item) - { - $id = $item->getAttribute('id'); + // checks if it has any loot + if( isset($element) ) + { + // adds all items + foreach( $element->getElementsByTagName('item') as $item) + { + $id = $item->getAttribute('id'); - // avoid redundancy - if( !in_array($id, $keys) ) - { - $keys[] = $id; - $loot[] = $items->getItemType($id); - } - } - } + // avoid redundancy + if( !in_array($id, $keys) ) + { + $keys[] = $id; + $loot[] = $items->getItemType($id); + } + } + } - return $loot; - } + return $loot; + } /** * Returns look of the monster. @@ -281,27 +282,27 @@ class OTS_Monster extends DOMDocument * @return array Look with all the attributes of the look. * @throws DOMException On DOM operation error. */ - public function getLook() - { - $look = array(); + public function getLook() + { + $look = array(); - $element = $this->documentElement->getElementsByTagName('look')->item(0); + $element = $this->documentElement->getElementsByTagName('look')->item(0); - if (!$element) { - return $look; - } + if (!$element) { + return $look; + } - $look['type'] = $element->getAttribute('type'); - $look['typeex'] = $element->getAttribute('typeex'); - $look['head'] = $element->getAttribute('head'); - $look['body'] = $element->getAttribute('body'); - $look['legs'] = $element->getAttribute('legs'); - $look['feet'] = $element->getAttribute('feet'); - $look['addons'] = $element->getAttribute('addons'); - $look['corpse'] = $element->getAttribute('corpse'); + $look['type'] = $element->getAttribute('type'); + $look['typeex'] = $element->getAttribute('typeex'); + $look['head'] = $element->getAttribute('head'); + $look['body'] = $element->getAttribute('body'); + $look['legs'] = $element->getAttribute('legs'); + $look['feet'] = $element->getAttribute('feet'); + $look['addons'] = $element->getAttribute('addons'); + $look['corpse'] = $element->getAttribute('corpse'); - return $look; - } + return $look; + } /** * Returns all monster summons. @@ -311,24 +312,24 @@ class OTS_Monster extends DOMDocument */ public function getSummons() - { - $summons = array(); + { + $summons = array(); - $element = $this->documentElement->getElementsByTagName('summons')->item(0); + $element = $this->documentElement->getElementsByTagName('summons')->item(0); - // checks if it has any Summons - if( isset($element) ) - { - // adds all summons - foreach( $element->getElementsByTagName('summon') as $item) - { - $chance = $item->getAttribute('chance'); - $id = $item->getAttribute('name'); - $summons[] = array('name' => $id, 'chance' => $chance); - } - } - return $summons; - } + // checks if it has any Summons + if( isset($element) ) + { + // adds all summons + foreach( $element->getElementsByTagName('summon') as $item) + { + $chance = $item->getAttribute('chance'); + $id = $item->getAttribute('name'); + $summons[] = array('name' => $id, 'chance' => $chance); + } + } + return $summons; + } /** * Returns all monster elements. @@ -336,30 +337,30 @@ class OTS_Monster extends DOMDocument * @return array elements. * @throws DOMException On DOM operation error. */ - public function getElements() - { - $elements = array(); + public function getElements() + { + $elements = array(); - $element = $this->documentElement->getElementsByTagName('elements')->item(0); + $element = $this->documentElement->getElementsByTagName('elements')->item(0); - // checks if it has any elements - if( isset($element) ) - { - // read all elements - foreach( $element->getElementsByTagName('element') as $elementv) - { - $elementv = $elementv->attributes->item(0); + // checks if it has any elements + if( isset($element) ) + { + // read all elements + foreach( $element->getElementsByTagName('element') as $elementv) + { + $elementv = $elementv->attributes->item(0); - // checks if element is set - if($elementv->nodeValue > 0) - { + // checks if element is set + if($elementv->nodeValue > 0) + { $elements[] = array('name' => ucfirst(str_replace('Percent', '', $elementv->nodeName)), 'percent' => $elementv->nodeValue); - } - } - } + } + } + } - return $elements; - } + return $elements; + } /** * Checks if monster has given element. @@ -368,26 +369,26 @@ class OTS_Monster extends DOMDocument * @return bool element state. * @throws DOMException On DOM operation error. */ - public function hasElement($name) - { - $element = $this->documentElement->getElementsByTagName('elements')->item(0); + public function hasElement($name) + { + $element = $this->documentElement->getElementsByTagName('elements')->item(0); - // if doesn't have any elements obviously doesn't have this one too - if( isset($element) ) - { - // read all elements - foreach( $element->getElementsByTagName('element') as $element) - { - // checks if this is what we are searching for - if( $element->hasAttribute($name) ) - { - return $element->getAttribute($name) > 0; - } - } - } + // if doesn't have any elements obviously doesn't have this one too + if( isset($element) ) + { + // read all elements + foreach( $element->getElementsByTagName('element') as $element) + { + // checks if this is what we are searching for + if( $element->hasAttribute($name) ) + { + return $element->getAttribute($name) > 0; + } + } + } - return false; - } + return false; + } /** * Returns all monster immunities. @@ -395,30 +396,30 @@ class OTS_Monster extends DOMDocument * @return array Immunities. * @throws DOMException On DOM operation error. */ - public function getImmunities() - { - $immunities = array(); + public function getImmunities() + { + $immunities = array(); - $element = $this->documentElement->getElementsByTagName('immunities')->item(0); + $element = $this->documentElement->getElementsByTagName('immunities')->item(0); - // checks if it has any immunities - if( isset($element) ) - { - // read all immunities - foreach( $element->getElementsByTagName('immunity') as $immunity) - { - $immunity = $immunity->attributes->item(0); + // checks if it has any immunities + if( isset($element) ) + { + // read all immunities + foreach( $element->getElementsByTagName('immunity') as $immunity) + { + $immunity = $immunity->attributes->item(0); - // checks if immunity is set - if($immunity->nodeValue > 0) - { - $immunities[] = $immunity->nodeName; - } - } - } + // checks if immunity is set + if($immunity->nodeValue > 0) + { + $immunities[] = $immunity->nodeName; + } + } + } - return $immunities; - } + return $immunities; + } /** * Checks if monster has given immunity. @@ -427,26 +428,26 @@ class OTS_Monster extends DOMDocument * @return bool Immunity state. * @throws DOMException On DOM operation error. */ - public function hasImmunity($name) - { - $element = $this->documentElement->getElementsByTagName('immunities')->item(0); + public function hasImmunity($name) + { + $element = $this->documentElement->getElementsByTagName('immunities')->item(0); - // if doesn't have any immunities obviously doesn't have this one too - if( isset($element) ) - { - // read all immunities - foreach( $element->getElementsByTagName('immunity') as $immunity) - { - // checks if this is what we are searching for - if( $immunity->hasAttribute($name) ) - { - return $immunity->getAttribute($name) > 0; - } - } - } + // if doesn't have any immunities obviously doesn't have this one too + if( isset($element) ) + { + // read all immunities + foreach( $element->getElementsByTagName('immunity') as $immunity) + { + // checks if this is what we are searching for + if( $immunity->hasAttribute($name) ) + { + return $immunity->getAttribute($name) > 0; + } + } + } - return false; - } + return false; + } /** * Returns monster defense rate. @@ -454,18 +455,18 @@ class OTS_Monster extends DOMDocument * @return int Defense rate. * @throws DOMException On DOM operation error. */ - public function getDefense() - { - $element = $this->documentElement->getElementsByTagName('defenses')->item(0); + public function getDefense() + { + $element = $this->documentElement->getElementsByTagName('defenses')->item(0); - // checks if defenses element is set - if( isset($element) ) - { - return (int) $element->getAttribute('defense'); - } + // checks if defenses element is set + if( isset($element) ) + { + return (int) $element->getAttribute('defense'); + } - return 0; - } + return 0; + } /** * Returns monster armor. @@ -473,18 +474,18 @@ class OTS_Monster extends DOMDocument * @return int Armor rate. * @throws DOMException On DOM operation error. */ - public function getArmor() - { - $element = $this->documentElement->getElementsByTagName('defenses')->item(0); + public function getArmor() + { + $element = $this->documentElement->getElementsByTagName('defenses')->item(0); - // checks if defenses element is set - if( isset($element) ) - { - return (int) $element->getAttribute('armor'); - } + // checks if defenses element is set + if( isset($element) ) + { + return (int) $element->getAttribute('armor'); + } - return 0; - } + return 0; + } /** * Returns list of special defenses. @@ -492,23 +493,23 @@ class OTS_Monster extends DOMDocument * @return array List of defense effects. * @throws DOMException On DOM operation error. */ - public function getDefenses() - { - $defenses = array(); + public function getDefenses() + { + $defenses = array(); - $element = $this->documentElement->getElementsByTagName('defenses')->item(0); + $element = $this->documentElement->getElementsByTagName('defenses')->item(0); - // checks if it has any defenses - if( isset($element) ) - { - foreach( $element->getElementsByTagName('defense') as $defense) - { - $defenses[] = $defense->getAttribute('name'); - } - } + // checks if it has any defenses + if( isset($element) ) + { + foreach( $element->getElementsByTagName('defense') as $defense) + { + $defenses[] = $defense->getAttribute('name'); + } + } - return $defenses; - } + return $defenses; + } /** * Returns list of monster attacks. @@ -516,23 +517,23 @@ class OTS_Monster extends DOMDocument * @return array List of attafck effects. * @throws DOMException On DOM operation error. */ - public function getAttacks() - { - $attacks = array(); + public function getAttacks() + { + $attacks = array(); - $element = $this->documentElement->getElementsByTagName('attacks')->item(0); + $element = $this->documentElement->getElementsByTagName('attacks')->item(0); - // checks if it has any defenses - if( isset($element) ) - { - foreach( $element->getElementsByTagName('attack') as $attack) - { - $attacks[] = $attack->getAttribute('name'); - } - } + // checks if it has any defenses + if( isset($element) ) + { + foreach( $element->getElementsByTagName('attack') as $attack) + { + $attacks[] = $attack->getAttribute('name'); + } + } - return $attacks; - } + return $attacks; + } /** * Magic PHP5 method. @@ -544,59 +545,59 @@ class OTS_Monster extends DOMDocument * @throws OutOfBoundsException For non-supported properties. * @throws DOMException On DOM operation error. */ - public function __get($name) - { - switch($name) - { - case 'name': - return $this->getName(); + public function __get($name) + { + switch($name) + { + case 'name': + return $this->getName(); - case 'race': - return $this->getRace(); + case 'race': + return $this->getRace(); - case 'experience': - return $this->getExperience(); + case 'experience': + return $this->getExperience(); - case 'speed': - return $this->getSpeed(); + case 'speed': + return $this->getSpeed(); - case 'manaCost': - return $this->getManaCost(); + case 'manaCost': + return $this->getManaCost(); - case 'health': - return $this->getHealth(); + case 'health': + return $this->getHealth(); - case 'flags': - return $this->getFlags(); + case 'flags': + return $this->getFlags(); - case 'voices': - return $this->getVoices(); + case 'voices': + return $this->getVoices(); - case 'items': - return $this->getItems(); + case 'items': + return $this->getItems(); - case 'immunities': - return $this->getImmunities(); + case 'immunities': + return $this->getImmunities(); - case 'defense': - return $this->getDefense(); + case 'defense': + return $this->getDefense(); - case 'armor': - return $this->getArmor(); + case 'armor': + return $this->getArmor(); - case 'defenses': - return $this->getDefenses(); + case 'defenses': + return $this->getDefenses(); - case 'attacks': - return $this->getAttacks(); + case 'attacks': + return $this->getAttacks(); - case 'look': - return $this->getLook(); + case 'look': + return $this->getLook(); - default: - throw new OutOfBoundsException(); - } - } + default: + throw new OutOfBoundsException(); + } + } /** * Returns string representation of XML. @@ -609,18 +610,18 @@ class OTS_Monster extends DOMDocument * @since 0.1.0 * @return string String representation of object. */ - public function __toString() - { - $ots = POT::getInstance(); + public function __toString() + { + $ots = POT::getInstance(); - // checks if display driver is loaded - if( $ots->isDataDisplayDriverLoaded() ) - { - return $ots->getDataDisplayDriver()->displayMonster($this); - } + // checks if display driver is loaded + if( $ots->isDataDisplayDriverLoaded() ) + { + return $ots->getDataDisplayDriver()->displayMonster($this); + } - return $this->saveXML(); - } + return $this->saveXML(); + } } /**#@-*/ diff --git a/system/libs/pot/OTS_Player.php b/system/libs/pot/OTS_Player.php index 491a6303..1cc1a7cd 100644 --- a/system/libs/pot/OTS_Player.php +++ b/system/libs/pot/OTS_Player.php @@ -90,7 +90,7 @@ class OTS_Player extends OTS_Row_DAO * @version 0.1.2 * @var array */ - private $data = array('sex' => 0, 'vocation' => 0, 'experience' => 0, 'level' => 1, 'maglevel' => 0, 'health' => 100, 'healthmax' => 100, 'mana' => 100, 'manamax' => 100, 'manaspent' => 0, 'soul' => 0, 'lookbody' => 10, 'lookfeet' => 10, 'lookhead' => 10, 'looklegs' => 10, 'looktype' => 136, 'lookaddons' => 0, 'posx' => 0, 'posy' => 0, 'posz' => 0, 'cap' => 0, 'lastlogin' => 0, 'lastip' => 0, 'save' => true, 'skulltime' => 0, 'skull' => 0, 'balance' => 0, 'lastlogout' => 0, 'blessings' => 0, 'stamina' => 0, 'online' => 0, 'comment' => '', 'created' => 0, 'hide' => 0); + private $data = array('group_id' => 1, 'sex' => 0, 'vocation' => 0, 'experience' => 0, 'level' => 1, 'maglevel' => 0, 'health' => 100, 'healthmax' => 100, 'mana' => 100, 'manamax' => 100, 'manaspent' => 0, 'soul' => 0, 'lookbody' => 10, 'lookfeet' => 10, 'lookhead' => 10, 'looklegs' => 10, 'looktype' => 136, 'lookaddons' => 0, 'posx' => 0, 'posy' => 0, 'posz' => 0, 'cap' => 0, 'lastlogin' => 0, 'lastip' => 0, 'save' => true, 'skulltime' => 0, 'skull' => 0, 'balance' => 0, 'lastlogout' => 0, 'blessings' => 0, 'stamina' => 0, 'online' => 0, 'comment' => '', 'created' => 0, 'hide' => 0); /** * Player skills. @@ -1229,6 +1229,13 @@ class OTS_Player extends OTS_Row_DAO $this->data['direction'] = (int) $direction; } + public function getOutfit(): string + { + $hasLookAddons = $this->db->hasColumn('players', 'lookaddons'); + + return setting('core.outfit_images_url') . '?id=' . $this->getLookType() . ($hasLookAddons ? '&addons=' . $this->getLookAddons() : '') . '&head=' . $this->getLookHead() . '&body=' . $this->getLookBody() . '&legs=' . $this->getLookLegs() . '&feet=' . $this->getLookFeet(); + } + /** * Body color. * diff --git a/system/locale/de/install.php b/system/locale/de/install.php index 85be3b16..ad354609 100644 --- a/system/locale/de/install.php +++ b/system/locale/de/install.php @@ -36,6 +36,10 @@ $locale['step_requirements'] = 'Anforderungen'; $locale['step_requirements_title'] = 'Anforderungen überprüfen'; $locale['step_requirements_php_version'] = 'PHP Version'; $locale['step_requirements_write_perms'] = 'Schreibberechtigungen'; +$locale['step_requirements_folder_exists'] = 'Ordner ist vorhanden'; +$locale['step_requirements_folder_not_exists_tools_ext'] = 'NPM Package Manager wird verwendet für externe JavaScript/CSS Bibliotheken.' + . ' Es sollte via Command Line installiert werden: https://docs.npmjs.com/downloading-and-installing-node-js-and-npm' + . ' Nachdem das Tool installiert wurde, folgende Befehl sollte ausgeführt in dem Hauptordner des MyAACs: "npm install".'; $locale['step_requirements_failed'] = 'Die Installation wird deaktiviert, bis diese Anforderungen erfüllt sind.
Für weitere Informationen siehe README Datei.'; $locale['step_requirements_extension'] = '$EXTENSION$ PHP Erweiterung'; diff --git a/system/locale/en/install.php b/system/locale/en/install.php index 3de85896..e25537c9 100644 --- a/system/locale/en/install.php +++ b/system/locale/en/install.php @@ -36,6 +36,10 @@ $locale['step_requirements'] = 'Requirements'; $locale['step_requirements_title'] = 'Requirements check'; $locale['step_requirements_php_version'] = 'PHP Version'; $locale['step_requirements_write_perms'] = 'Write permissions'; +$locale['step_requirements_folder_exists'] = 'Directory exists'; +$locale['step_requirements_folder_not_exists_tools_ext'] = 'NPM Package Manager is used for external JavaScript/CSS libraries.' + . ' You need to install it through Command Line: https://docs.npmjs.com/downloading-and-installing-node-js-and-npm' + . ' When you done with installing that tool, execute: "npm install" in the main MyAAC folder.'; $locale['step_requirements_failed'] = 'Installation will be disabled until these requirements will be passed.
For more informations see README file.'; $locale['step_requirements_extension'] = '$EXTENSION$ PHP extension'; $locale['step_requirements_warning_images_guilds'] = 'Guild logo upload will not work'; diff --git a/system/locale/pl/install.php b/system/locale/pl/install.php index 1afb2ddd..22204adf 100644 --- a/system/locale/pl/install.php +++ b/system/locale/pl/install.php @@ -36,6 +36,10 @@ $locale['step_requirements'] = 'Wymagania'; $locale['step_requirements_title'] = 'Sprawdzanie wymagań'; $locale['step_requirements_php_version'] = 'Wersja PHP'; $locale['step_requirements_write_perms'] = 'Uprawnienia do zapisu'; +$locale['step_requirements_folder_exists'] = 'Folder istnieje'; +$locale['step_requirements_folder_not_exists_tools_ext'] = 'Manadżer Pakietów NPM jest używany do zewnętrznych bibliotek JavaScript/CSS.' + . ' Trzeba go zainstalować poprzez wiersz poleceń: https://docs.npmjs.com/downloading-and-installing-node-js-and-npm' + . ' Po instalacji narzędzia, wywołaj następujące polecenie w głownym katalogu MyAAC: "npm install".'; $locale['step_requirements_failed'] = 'Instalacja zostanie zablokowana dopóki te wymagania nie zostaną spełnione.
Po więcej informacji zasięgnij do pliku README.'; $locale['step_requirements_extension'] = 'Rozszerzenie PHP - $EXTENSION$'; $locale['step_requirements_warning_images_guilds'] = 'Nie będzie możliwości uploadu obrazków gildii'; diff --git a/system/logout.php b/system/logout.php index 4f653ecb..dd72a455 100644 --- a/system/logout.php +++ b/system/logout.php @@ -22,11 +22,5 @@ if(isset($account_logged) && $account_logged->isLoaded()) { $logged = false; unset($account_logged); - - if(isset($_REQUEST['redirect'])) - { - header('Location: ' . urldecode($_REQUEST['redirect'])); - exit; - } } } diff --git a/system/pages/account/base.php b/system/pages/account/base.php index 75b1cc77..e644b610 100644 --- a/system/pages/account/base.php +++ b/system/pages/account/base.php @@ -12,6 +12,8 @@ defined('MYAAC') or die('Direct access not allowed!'); if(!$logged) { + $title = 'Login'; + if(!empty($errors)) $twig->display('error_box.html.twig', array('errors' => $errors)); @@ -19,7 +21,8 @@ if(!$logged) 'redirect' => $_REQUEST['redirect'] ?? null, 'account' => USE_ACCOUNT_NAME ? 'Name' : 'Number', 'account_login_by' => getAccountLoginByLabel(), - 'error' => $errors[0] ?? null + 'error' => $errors[0] ?? null, + 'errors' => $errors ?? [], )); return; diff --git a/system/pages/account/change_email.php b/system/pages/account/change-email.php similarity index 97% rename from system/pages/account/change_email.php rename to system/pages/account/change-email.php index 954d596b..c97b5541 100644 --- a/system/pages/account/change_email.php +++ b/system/pages/account/change-email.php @@ -57,14 +57,14 @@ if($email_new_time < 10) { $twig->display('error_box.html.twig', array('errors' => $errors)); //show form - $twig->display('account.change_mail.html.twig', array( + $twig->display('account.change-email.html.twig', array( 'new_email' => isset($_POST['new_email']) ? $_POST['new_email'] : null )); } } else { - $twig->display('account.change_mail.html.twig', array( + $twig->display('account.change-email.html.twig', array( 'new_email' => isset($_POST['new_email']) ? $_POST['new_email'] : null )); } diff --git a/system/pages/account/change_info.php b/system/pages/account/change-info.php similarity index 77% rename from system/pages/account/change_info.php rename to system/pages/account/change-info.php index 2a8d4a07..709dce27 100644 --- a/system/pages/account/change_info.php +++ b/system/pages/account/change-info.php @@ -26,12 +26,13 @@ if(setting('core.account_country')) $account = Account::find($account_logged->getId()); $show_form = true; -$new_rlname = isset($_POST['info_rlname']) ? htmlspecialchars(stripslashes($_POST['info_rlname'])) : NULL; -$new_location = isset($_POST['info_location']) ? htmlspecialchars(stripslashes($_POST['info_location'])) : NULL; -$new_country = isset($_POST['info_country']) ? htmlspecialchars(stripslashes($_POST['info_country'])) : NULL; +$new_rlname = isset($_POST['info_rlname']) ? htmlspecialchars(stripslashes($_POST['info_rlname'])) : ''; +$new_location = isset($_POST['info_location']) ? htmlspecialchars(stripslashes($_POST['info_location'])) : ''; +$new_country = isset($_POST['info_country']) ? htmlspecialchars(stripslashes($_POST['info_country'])) : ''; if(isset($_POST['changeinfosave']) && $_POST['changeinfosave'] == 1) { - if(!isset($config['countries'][$new_country])) + if(setting('core.account_country') && !isset($config['countries'][$new_country])) { $errors[] = 'Country is not correct.'; + } if(empty($errors)) { //save data from form @@ -39,7 +40,14 @@ if(isset($_POST['changeinfosave']) && $_POST['changeinfosave'] == 1) { $account->location = $new_location; $account->country = $new_country; $account->save(); - $account_logged->logAction('Changed Real Name to ' . $new_rlname . ', Location to ' . $new_location . ' and Country to ' . $config['countries'][$new_country] . '.'); + + $log = 'Changed Real Name to ' . $new_rlname . ', Location to ' . $new_location . ''; + if(setting('core.account_country')) { + $log .= ' and Country to ' . $config['countries'][$new_country] . ''; + } + $log .= '.'; + + $account_logged->logAction($log); $twig->display('success.html.twig', array( 'title' => 'Public Information Changed', 'description' => 'Your public information has been changed.' @@ -68,7 +76,7 @@ if($show_form) { $countries[$code] = $country; } - $twig->display('account.change_info.html.twig', array( + $twig->display('account.change-info.html.twig', array( 'countries' => $countries ?? [], 'account_rlname' => $account_rlname, 'account_location' => $account_location, diff --git a/system/pages/account/change_password.php b/system/pages/account/change-password.php similarity index 96% rename from system/pages/account/change_password.php rename to system/pages/account/change-password.php index 309c8dee..bf172455 100644 --- a/system/pages/account/change_password.php +++ b/system/pages/account/change-password.php @@ -21,7 +21,7 @@ $new_password = $_POST['newpassword'] ?? NULL; $new_password_confirm = $_POST['newpassword_confirm'] ?? NULL; $old_password = $_POST['oldpassword'] ?? NULL; if(empty($new_password) && empty($new_password_confirm) && empty($old_password)) { - $twig->display('account.change_password.html.twig'); + $twig->display('account.change-password.html.twig'); } else { @@ -52,7 +52,7 @@ else $twig->display('error_box.html.twig', array('errors' => $errors)); //show form - $twig->display('account.change_password.html.twig'); + $twig->display('account.change-password.html.twig'); } else { $org_pass = $new_password; diff --git a/system/pages/account/change_comment.php b/system/pages/account/characters/change-comment.php similarity index 94% rename from system/pages/account/change_comment.php rename to system/pages/account/characters/change-comment.php index e4fb6e42..7fa10c69 100644 --- a/system/pages/account/change_comment.php +++ b/system/pages/account/characters/change-comment.php @@ -14,7 +14,7 @@ use MyAAC\Models\Player; defined('MYAAC') or die('Direct access not allowed!'); $title = 'Change Comment'; -require __DIR__ . '/base.php'; +require PAGES . 'account/base.php'; if(!$logged) { return; @@ -68,7 +68,7 @@ if($show_form) { } if(isset($player) && $player) { - $twig->display('account.change_comment.html.twig', array( + $twig->display('account.characters.change-comment.html.twig', array( 'player' => $player->toArray() )); } diff --git a/system/pages/account/change_name.php b/system/pages/account/characters/change-name.php similarity index 97% rename from system/pages/account/change_name.php rename to system/pages/account/characters/change-name.php index ef82b9ad..4a23131d 100644 --- a/system/pages/account/change_name.php +++ b/system/pages/account/characters/change-name.php @@ -11,7 +11,7 @@ defined('MYAAC') or die('Direct access not allowed!'); $title = 'Change Name'; -require __DIR__ . '/base.php'; +require PAGES . 'account/base.php'; if(!$logged) { return; @@ -109,7 +109,7 @@ else $twig->display('error_box.html.twig', array('errors' => $errors)); } - $twig->display('account.change_name.html.twig', array( + $twig->display('account.characters.change-name.html.twig', array( 'points' => $points, 'errors' => $errors //'account_players' => $account_logged->getPlayersList() diff --git a/system/pages/account/change_sex.php b/system/pages/account/characters/change-sex.php similarity index 96% rename from system/pages/account/change_sex.php rename to system/pages/account/characters/change-sex.php index 7e43b6ff..6c95a6e7 100644 --- a/system/pages/account/change_sex.php +++ b/system/pages/account/characters/change-sex.php @@ -11,7 +11,7 @@ defined('MYAAC') or die('Direct access not allowed!'); $title = 'Change Sex'; -require __DIR__ . '/base.php'; +require PAGES . 'account/base.php'; if(!$logged) { return; @@ -88,7 +88,7 @@ else if(!empty($errors)) { $twig->display('error_box.html.twig', array('errors' => $errors)); } - $twig->display('account.change_sex.html.twig', array( + $twig->display('account.characters.change-sex.html.twig', array( 'players' => $account_logged->getPlayersList(false), 'player_sex' => isset($player) ? $player->getSex() : -1, 'points' => $points diff --git a/system/pages/account/create_character.php b/system/pages/account/characters/create.php similarity index 93% rename from system/pages/account/create_character.php rename to system/pages/account/characters/create.php index e68c8773..5ad21dab 100644 --- a/system/pages/account/create_character.php +++ b/system/pages/account/characters/create.php @@ -14,7 +14,7 @@ use MyAAC\CreateCharacter; defined('MYAAC') or die('Direct access not allowed!'); $title = 'Create Character'; -require __DIR__ . '/base.php'; +require PAGES . 'account/base.php'; if(!$logged) { return; @@ -43,7 +43,7 @@ if(count($errors) > 0) { } if(!$character_created) { - $twig->display('account.create_character.html.twig', array( + $twig->display('account.characters.create.html.twig', array( 'name' => $character_name, 'sex' => $character_sex, 'vocation' => $character_vocation, diff --git a/system/pages/account/delete_character.php b/system/pages/account/characters/delete.php similarity index 96% rename from system/pages/account/delete_character.php rename to system/pages/account/characters/delete.php index 7804f01d..af32070b 100644 --- a/system/pages/account/delete_character.php +++ b/system/pages/account/characters/delete.php @@ -11,7 +11,7 @@ defined('MYAAC') or die('Direct access not allowed!'); $title = 'Delete Character'; -require __DIR__ . '/base.php'; +require PAGES . 'account/base.php'; if(!$logged) { return; @@ -93,5 +93,5 @@ if($show_form) { $twig->display('error_box.html.twig', array('errors' => $errors)); } - $twig->display('account.delete_character.html.twig'); + $twig->display('account.characters.delete.html.twig'); } diff --git a/system/pages/account/confirm_email.php b/system/pages/account/confirm-email.php similarity index 61% rename from system/pages/account/confirm_email.php rename to system/pages/account/confirm-email.php index 925aef5e..615dd942 100644 --- a/system/pages/account/confirm_email.php +++ b/system/pages/account/confirm-email.php @@ -25,16 +25,20 @@ if(!Account::where('email_hash', $hash)->exists()) { } else { - if (Account::where('email_hash', $hash)->where('email_verified', 0)->exists()) { - $query = $query->fetch(PDO::FETCH_ASSOC); + $accountModel = Account::where('email_hash', $hash)->where('email_verified', 0)->first(); + if ($accountModel) { + $accountModel->email_verified = 1; + $accountModel->save(); + + 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(); - $account->load($query['id']); + $account->load($accountModel->id); if ($account->isLoaded()) { $hooks->trigger(HOOK_EMAIL_CONFIRMED, ['account' => $account]); } } - - Account::where('email_hash', $hash)->update('email_verified', 1); - success('You have now verified your e-mail, this will increase the security of your account. Thank you for doing this.'); + else { + error('Link has expired.'); + } } -?> diff --git a/system/pages/account/create.php b/system/pages/account/create.php index 58e72356..0074f9e3 100644 --- a/system/pages/account/create.php +++ b/system/pages/account/create.php @@ -227,7 +227,7 @@ if($save) $hash = md5(generateRandomString(16, true, true) . $email); $new_account->setCustomField('email_hash', $hash); - $verify_url = getLink('account/confirm_email/' . $hash); + $verify_url = getLink('account/confirm-email/' . $hash); $body_html = $twig->render('mail.account.verify.html.twig', array( 'account' => $tmp_account, 'verify_url' => generateLink($verify_url, $verify_url, true) @@ -236,6 +236,9 @@ if($save) if(_mail($email, 'New account on ' . $config['lua']['serverName'], $body_html)) { echo 'Your account has been created.

'; + + warning("Before you can login - you need to verify your E-Mail. The verification link has been sent to $email. If the message is not coming - remember to check the SPAM folder."); + $twig->display('success.html.twig', array( 'title' => 'Account Created', 'description' => 'Your account ' . $account_type . ' is ' . $tmp_account . '
You will need the account ' . $account_type . ' and your password to play on ' . configLua('serverName') . '. @@ -252,15 +255,6 @@ if($save) } else { - if(setting('core.account_create_character_create')) { - // character creation - $character_created = $createCharacter->doCreate($character_name, $character_sex, $character_vocation, $character_town, $new_account, $errors); - if (!$character_created) { - error('There was an error creating your character. Please create your character later in account management page.'); - error(implode(' ', $errors)); - } - } - if(setting('core.account_create_auto_login')) { if ($hasBeenCreatedByEMail) { $_POST['account_login'] = $email; @@ -311,6 +305,15 @@ if($save) } } + if(setting('core.account_create_character_create')) { + // character creation + $character_created = $createCharacter->doCreate($character_name, $character_sex, $character_vocation, $character_town, $new_account, $errors); + if (!$character_created) { + error('There was an error creating your character. Please create your character later in account management page.'); + error(implode(' ', $errors)); + } + } + return; } } diff --git a/system/pages/account/login.php b/system/pages/account/login.php index c063c28e..0fce795d 100644 --- a/system/pages/account/login.php +++ b/system/pages/account/login.php @@ -9,56 +9,61 @@ * @link https://my-aac.org */ defined('MYAAC') or die('Direct access not allowed!'); -$title = 'Login'; // new login with data from form -if(!$logged && isset($_POST['account_login'], $_POST['password_login'])) +if($logged || !isset($_POST['account_login']) || !isset($_POST['password_login'])) { + return; +} + +$login_account = $_POST['account_login']; +$login_password = $_POST['password_login']; +$remember_me = isset($_POST['remember_me']); +if(!empty($login_account) && !empty($login_password)) { - $login_account = $_POST['account_login']; - $login_password = $_POST['password_login']; - $remember_me = isset($_POST['remember_me']); - if(!empty($login_account) && !empty($login_password)) + if($cache->enabled()) { - if($cache->enabled()) + $tmp = ''; + if($cache->fetch('failed_logins', $tmp)) { - $tmp = ''; - if($cache->fetch('failed_logins', $tmp)) + $tmp = unserialize($tmp); + $to_remove = array(); + foreach($tmp as $ip => $t) { - $tmp = unserialize($tmp); - $to_remove = array(); - foreach($tmp as $ip => $t) - { - if(time() - $t['last'] >= 5 * 60) - $to_remove[] = $ip; - } - - foreach($to_remove as $ip) - unset($tmp[$ip]); + if(time() - $t['last'] >= 5 * 60) + $to_remove[] = $ip; } - else - $tmp = array(); - $ip = $_SERVER['REMOTE_ADDR']; - $t = $tmp[$ip] ?? null; + foreach($to_remove as $ip) + unset($tmp[$ip]); } + else + $tmp = array(); - $account_logged = new OTS_Account(); - if (config('account_login_by_email')) { - $account_logged->findByEMail($login_account); + $ip = $_SERVER['REMOTE_ADDR']; + $t = $tmp[$ip] ?? null; + } + + $account_logged = new OTS_Account(); + if (config('account_login_by_email')) { + $account_logged->findByEMail($login_account); + } + + if (!config('account_login_by_email') || config('account_login_by_email_fallback')) { + if(USE_ACCOUNT_NAME || USE_ACCOUNT_NUMBER) { + $account_logged->find($login_account); + } else { + $account_logged->load($login_account, true); } + } - if (!config('account_login_by_email') || config('account_login_by_email_fallback')) { - if(USE_ACCOUNT_NAME || USE_ACCOUNT_NUMBER) { - $account_logged->find($login_account); - } else { - $account_logged->load($login_account, true); - } + if($account_logged->isLoaded() && encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $login_password) == $account_logged->getPassword() + && (!isset($t) || $t['attempts'] < 5) + ) + { + 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.'; } - - if($account_logged->isLoaded() && encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $login_password) == $account_logged->getPassword() - && (!isset($t) || $t['attempts'] < 5) - ) - { + else { session_regenerate_id(); setSession('account', $account_logged->getId()); setSession('password', encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $login_password)); @@ -82,44 +87,44 @@ if(!$logged && isset($_POST['account_login'], $_POST['password_login'])) $hooks->trigger(HOOK_LOGIN, array('account' => $account_logged, 'password' => $login_password, 'remember_me' => $remember_me)); } - else + } + else + { + $hooks->trigger(HOOK_LOGIN_ATTEMPT, array('account' => $login_account, 'password' => $login_password, 'remember_me' => $remember_me)); + + $errorMessage = getAccountLoginByLabel() . ' or password is not correct.'; + + // temporary solution for blocking failed login attempts + if($cache->enabled()) { - $hooks->trigger(HOOK_LOGIN_ATTEMPT, array('account' => $login_account, 'password' => $login_password, 'remember_me' => $remember_me)); - - $errorMessage = getAccountLoginByLabel() . ' or password is not correct.'; - - // temporary solution for blocking failed login attempts - if($cache->enabled()) + if(isset($t)) { - if(isset($t)) - { - $t['attempts']++; - $t['last'] = time(); + $t['attempts']++; + $t['last'] = time(); - if($t['attempts'] >= 5) - $errors[] = 'A wrong password has been entered 5 times in a row. You are unable to log into your account for the next 5 minutes. Please wait.'; - else - $errors[] = $errorMessage; - } + if($t['attempts'] >= 5) + $errors[] = 'A wrong password has been entered 5 times in a row. You are unable to log into your account for the next 5 minutes. Please wait.'; else - { - $t = array('attempts' => 1, 'last' => time()); $errors[] = $errorMessage; - } - - $tmp[$ip] = $t; - $cache->set('failed_logins', serialize($tmp), 60 * 60); // save for 1 hour } - else { + else + { + $t = array('attempts' => 1, 'last' => time()); $errors[] = $errorMessage; } + + $tmp[$ip] = $t; + $cache->set('failed_logins', serialize($tmp), 60 * 60); // save for 1 hour + } + else { + $errors[] = $errorMessage; } } - else { - $errors[] = 'Please enter your ' . getAccountLoginByLabel() . ' and password.'; - - $hooks->trigger(HOOK_LOGIN_ATTEMPT, array('account' => $login_account, 'password' => $login_password, 'remember_me' => $remember_me)); - } - - $hooks->trigger(HOOK_ACCOUNT_LOGIN_POST); } +else { + $errors[] = 'Please enter your ' . getAccountLoginByLabel() . ' and password.'; + + $hooks->trigger(HOOK_LOGIN_ATTEMPT, array('account' => $login_account, 'password' => $login_password, 'remember_me' => $remember_me)); +} + +$hooks->trigger(HOOK_ACCOUNT_LOGIN_POST); diff --git a/system/pages/account/manage.php b/system/pages/account/manage.php index 615ffdc7..eff71c78 100644 --- a/system/pages/account/manage.php +++ b/system/pages/account/manage.php @@ -22,6 +22,12 @@ if(isset($_REQUEST['redirect'])) { $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 )); @@ -46,7 +52,7 @@ if(empty($recovery_key)) else { if(setting('core.account_generate_new_reckey') && setting('core.mail_enabled')) - $account_registered = 'Yes ( Buy new Recovery Key )'; + $account_registered = 'Yes ( Buy new Recovery Key )'; else $account_registered = 'Yes'; } diff --git a/system/pages/account/redirect.php b/system/pages/account/redirect.php index 8abff630..78bc54d9 100644 --- a/system/pages/account/redirect.php +++ b/system/pages/account/redirect.php @@ -12,6 +12,12 @@ 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 )); diff --git a/system/pages/account/register_new.php b/system/pages/account/register-new.php similarity index 100% rename from system/pages/account/register_new.php rename to system/pages/account/register-new.php diff --git a/system/pages/characters.php b/system/pages/characters.php index b2286db6..89f98cf0 100644 --- a/system/pages/characters.php +++ b/system/pages/characters.php @@ -8,6 +8,9 @@ * @copyright 2019 MyAAC * @link https://my-aac.org */ + +use MyAAC\Models\PlayerDeath; + defined('MYAAC') or die('Direct access not allowed!'); $title = 'Characters'; @@ -199,7 +202,7 @@ if($player->isLoaded() && !$player->isDeleted()) unset($storage); } - if($config['characters']['equipment'] && $db->hasTable('player_items') && $db->hasColumn('player_items', 'pid') && $db->hasColumn('player_items', 'sid') && $db->hasColumn('player_items', 'itemtype')) { + if($db->hasTable('player_items') && $db->hasColumn('player_items', 'pid') && $db->hasColumn('player_items', 'sid') && $db->hasColumn('player_items', 'itemtype')) { $eq_sql = $db->query('SELECT `pid`, `itemtype` FROM player_items WHERE player_id = '.$player->getId().' AND (`pid` >= 1 and `pid` <= 10)'); $equipment = array(); foreach($eq_sql as $eq) @@ -322,17 +325,36 @@ WHERE killers.death_id = '".$death['id']."' ORDER BY killers.final_hit DESC, kil $frags = array(); $frag_add_content = ''; - if($config['characters']['frags'] && $db->hasTable('killers')) { - //frags list by Xampy - $i = 0; + if ($config['characters']['frags']) { $frags_limit = 10; // frags limit to show? // default: 10 - $player_frags = $db->query('SELECT `player_deaths`.*, `players`.`name`, `killers`.`unjustified` FROM `player_deaths` LEFT JOIN `killers` ON `killers`.`death_id` = `player_deaths`.`id` LEFT JOIN `player_killers` ON `player_killers`.`kill_id` = `killers`.`id` LEFT JOIN `players` ON `players`.`id` = `player_deaths`.`player_id` WHERE `player_killers`.`player_id` = '.$player->getId().' ORDER BY `date` DESC LIMIT 0,'.$frags_limit.';')->fetchAll(); - if(count($player_frags)) { - $row_count = 0; - foreach($player_frags as $frag) - { - $description = 'Fragged ' . $frag['name'] . ' at level ' . $frag['level']; - $frags[] = array('time' => $frag['date'], 'description' => $description, 'unjustified' => $frag['unjustified'] != 0); + + if ($db->hasTable('killers')) { + //frags list by Xampy + $i = 0; + $player_frags = $db->query('SELECT `player_deaths`.*, `players`.`name`, `killers`.`unjustified` FROM `player_deaths` LEFT JOIN `killers` ON `killers`.`death_id` = `player_deaths`.`id` LEFT JOIN `player_killers` ON `player_killers`.`kill_id` = `killers`.`id` LEFT JOIN `players` ON `players`.`id` = `player_deaths`.`player_id` WHERE `player_killers`.`player_id` = ' . $player->getId() . ' ORDER BY `date` DESC LIMIT 0,' . $frags_limit . ';')->fetchAll(); + if (count($player_frags)) { + $row_count = 0; + foreach ($player_frags as $frag) { + $description = 'Fragged ' . $frag['name'] . ' at level ' . $frag['level']; + $frags[] = array('time' => $frag['date'], 'description' => $description, 'unjustified' => $frag['unjustified'] != 0); + } + } + } + else if($db->hasTable('player_deaths') && $db->hasColumn('player_deaths', 'killed_by')) { + $i = 0; + $player_frags = PlayerDeath::where('player_deaths.killed_by', $player->getName()) + ->join('players', 'players.id', '=', 'player_deaths.player_id') + ->limit($frags_limit) + ->selectRaw('players.name, player_deaths.*') + ->orderBy('player_deaths.time', 'DESC') + ->get(); + + if ($player_frags->count()) { + $row_count = 0; + foreach ($player_frags as $frag) { + $description = 'Fragged ' . $frag->name . ' at level ' . $frag->level; + $frags[] = array('time' => $frag->time, 'description' => $description, 'unjustified' => $frag->unjustified != 0); + } } } } diff --git a/system/pages/forum/edit_post.php b/system/pages/forum/edit_post.php index f42b743f..29ac1bec 100644 --- a/system/pages/forum/edit_post.php +++ b/system/pages/forum/edit_post.php @@ -19,7 +19,7 @@ if ($ret === false) { } if(!$logged) { - echo 'You are not logged in. Log in to post on the forum.

'; + 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 86305b4d..cdae005a 100644 --- a/system/pages/forum/move_thread.php +++ b/system/pages/forum/move_thread.php @@ -19,7 +19,7 @@ if ($ret === false) { } if(!$logged) { - echo 'You are not logged in. Log in to post on the forum.

'; + 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 659b4037..c47302b6 100644 --- a/system/pages/forum/new_post.php +++ b/system/pages/forum/new_post.php @@ -24,7 +24,7 @@ if(!$logged) { $extra_url = '?action=new_post&thread_id=' . $_GET['thread_id']; } - echo 'You are not logged in. Log in to post on the forum.

'; + echo 'You are not logged in. Log in to post on the forum.

'; return; } diff --git a/system/pages/forum/new_thread.php b/system/pages/forum/new_thread.php index 7b97f30e..7a66ac27 100644 --- a/system/pages/forum/new_thread.php +++ b/system/pages/forum/new_thread.php @@ -24,7 +24,7 @@ if(!$logged) { $extra_url = '?action=new_thread§ion_id=' . $_GET['section_id']; } - echo 'You are not logged in. Log in to post on the forum.

'; + echo 'You are not logged in. Log in to post on the forum.

'; return; } diff --git a/system/pages/forum/remove_post.php b/system/pages/forum/remove_post.php index 3e234e6f..690b3f75 100644 --- a/system/pages/forum/remove_post.php +++ b/system/pages/forum/remove_post.php @@ -19,7 +19,7 @@ if ($ret === false) { } if(!$logged) { - echo 'You are not logged in. Log in to post on the forum.

'; + echo 'You are not logged in. Log in to post on the forum.

'; return; } diff --git a/system/pages/forum/show_thread.php b/system/pages/forum/show_thread.php index 51dcd096..e4c53f16 100644 --- a/system/pages/forum/show_thread.php +++ b/system/pages/forum/show_thread.php @@ -60,7 +60,7 @@ foreach($posts as &$post) { } if($config['characters']['outfit']) { - $post['outfit'] = setting('core.outfit_images_url') . '?id=' . $player->getLookType() . ($lookaddons ? '&addons=' . $player->getLookAddons() : '') . '&head=' . $player->getLookHead() . '&body=' . $player->getLookBody() . '&legs=' . $player->getLookLegs() . '&feet=' . $player->getLookFeet(); + $post['outfit'] = $player->getOutfit(); } $groupName = ''; diff --git a/system/pages/guilds/cleanup_players.php b/system/pages/guilds/cleanup_players.php index 61b1ce49..7e02fbeb 100644 --- a/system/pages/guilds/cleanup_players.php +++ b/system/pages/guilds/cleanup_players.php @@ -40,7 +40,7 @@ if(count($players_list) > 0) if(!$rank_guild->isLoaded()) { $player->setRank(); - $player->setGuildNick(); + $player->setGuildNick(''); $changed_ranks_of[] = $player->getName(); $deleted_ranks[] = 'ID: '.$player_rank->getId().' - '.$player_rank->getName(); $player_rank->delete(); diff --git a/system/pages/guilds/create.php b/system/pages/guilds/create.php index 97de0699..b404c494 100644 --- a/system/pages/guilds/create.php +++ b/system/pages/guilds/create.php @@ -10,6 +10,8 @@ */ defined('MYAAC') or die('Direct access not allowed!'); +use MyAAC\Models\GuildRank; + require __DIR__ . '/base.php'; $guild_name = isset($_REQUEST['guild']) ? urldecode($_REQUEST['guild']) : NULL; @@ -113,7 +115,25 @@ if(isset($todo) && $todo == 'save') $new_guild->setOwner($player); $new_guild->save(); $new_guild->setCustomField('description', setting('core.guild_description_default')); - //$new_guild->setCustomField('creationdata', time()); + + if ($db->hasTable('guild_ranks')) { + if (!GuildRank::where('guild_id', $new_guild->getId())->first()) { + $ranks = [ + ['level' => 3, 'name' => 'the Leader'], + ['level' => 2, 'name' => 'a Vice-Leader'], + ['level' => 1, 'name' => 'a Member'], + ]; + + foreach ($ranks as $rank) { + GuildRank::create([ + 'guild_id' => $new_guild->getId(), + 'name' => $rank['name'], + 'level' => $rank['level'], + ]); + } + } + } + $ranks = $new_guild->getGuildRanksList(); $ranks->orderBy('level', POT::ORDER_DESC); foreach($ranks as $rank) { @@ -124,14 +144,11 @@ if(isset($todo) && $todo == 'save') $player->setRank($rank); } } + $twig->display('guilds.create.success.html.twig', array( 'guild_name' => $guild_name, 'leader_name' => $player->getName() )); - - /*$db->exec('INSERT INTO `guild_ranks` (`id`, `guild_id`, `name`, `level`) VALUES (null, '.$new_guild->getId().', "the Leader", 3)'); - $db->exec('INSERT INTO `guild_ranks` (`id`, `guild_id`, `name`, `level`) VALUES (null, '.$new_guild->getId().', "a Vice-Leader", 2)'); - $db->exec('INSERT INTO `guild_ranks` (`id`, `guild_id`, `name`, `level`) VALUES (null, '.$new_guild->getId().', "a Member", 1)');*/ } else { sort($array_of_player_nig); diff --git a/system/pages/guilds/show.php b/system/pages/guilds/show.php index 58a4b45f..33039ad3 100644 --- a/system/pages/guilds/show.php +++ b/system/pages/guilds/show.php @@ -142,9 +142,7 @@ if($logged && count($invited_list) > 0) } } -$useGuildNick = false; -if($db->hasColumn('players', 'guildnick')) - $useGuildNick = true; +$useGuildNick = $db->hasTable('guild_members') || $db->hasTable('guild_membership') || $db->hasColumn('players', 'guildnick'); $twig->display('guilds.view.html.twig', array( 'logo' => $guild_logo, @@ -160,7 +158,6 @@ $twig->display('guilds.view.html.twig', array( 'level_in_guild' => $level_in_guild, 'isLeader' => $guild_leader, 'isVice' => $guild_vice, - 'logged' => $logged, 'invited_list' => $invited_list, 'show_accept_invite' => $show_accept_invite, 'useGuildNick' => $useGuildNick diff --git a/system/pages/highscores.php b/system/pages/highscores.php index 1229dca3..0e5662e1 100644 --- a/system/pages/highscores.php +++ b/system/pages/highscores.php @@ -182,7 +182,7 @@ if (empty($highscores)) { if ($db->hasTable('player_killers')) { $query->addSelect(['value' => PlayerKillers::where('player_killers.player_id', 'players.id')->selectRaw('COUNT(*)')]); } else { - $query->addSelect(['value' => PlayerDeath::unjustified()->where('player_deaths.killed_by', 'players.name')->selectRaw('COUNT(*)')]); + $query->addSelect(['value' => PlayerDeath::unjustified()->whereColumn('player_deaths.killed_by', 'players.name')->selectRaw('COUNT(*)')]); } } else if ($skill == SKILL_BALANCE) // balance { diff --git a/system/pages/monsters.php b/system/pages/monsters.php index 17252438..988d15b5 100644 --- a/system/pages/monsters.php +++ b/system/pages/monsters.php @@ -39,9 +39,12 @@ if (empty($_REQUEST['name'])) { // display monster $monster_name = urldecode(stripslashes(ucwords(strtolower($_REQUEST['name'])))); -$monster = Monster::where('hide', '!=', 1)->where('name', $monster_name)->first()->toArray(); +$monsterModel = Monster::where('hide', '!=', 1)->where('name', $monster_name)->first(); + +if ($monsterModel && isset($monsterModel->name)) { + /** @var array $monster */ + $monster = $monsterModel->toArray(); -if (isset($monster['name'])) { function sort_by_chance($a, $b) { if ($a['chance'] == $b['chance']) { @@ -79,7 +82,7 @@ if (isset($monster['name'])) { )); } else { - echo "Monster with name " . $monster_name . " doesn't exist."; + echo "Monster with name " . htmlspecialchars($monster_name) . " doesn't exist."; } // back button diff --git a/system/pages/polls.php b/system/pages/polls.php index 21549891..37372f25 100644 --- a/system/pages/polls.php +++ b/system/pages/polls.php @@ -51,7 +51,7 @@ function getColorByPercent($percent) if($logged) echo $link.'?id='.$poll['id']; else - echo getLink('account/manage') . '?redirect=' . BASE_URL . urlencode($link.'?id='.$poll['id']); + echo getLink('account/manage') . '?redirect=' . urlencode($link.'?id='.$poll['id']); echo '">'.$poll['question'] . ' @@ -80,7 +80,7 @@ function getColorByPercent($percent) if($logged) echo $link.'?id='.$poll['id']; else - echo getLink('account/manage') . '?redirect=' . BASE_URL . urlencode($link.'?id='.$poll['id']); + echo getLink('account/manage') . '?redirect=' . urlencode($link.'?id='.$poll['id']); echo '">'.$poll['question'] . ' diff --git a/system/router.php b/system/router.php index bbdb7aa2..0a5ed7f8 100644 --- a/system/router.php +++ b/system/router.php @@ -91,35 +91,67 @@ if($logged && $account_logged && $account_logged->isLoaded()) { $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) { $routes = require SYSTEM . 'routes.php'; - $isAlreadyDefined = []; - - $routesTmp = []; + $routesFinal = []; foreach(getDatabasePages() as $page) { - $isAlreadyDefined[$page] = true; - $routesTmp[] = ['*', $page, '__database__/' . $page, true]; + $routesFinal[] = ['*', $page, '__database__/' . $page, 100]; } Plugins::clearWarnings(); foreach (Plugins::getRoutes() as $route) { - if(!isset($isAlreadyDefined[$route[1]])) { - $isAlreadyDefined[$route[1]] = true; - $routesTmp[] = [$route[0], $route[1], $route[2]]; - } + $routesFinal[] = [$route[0], $route[1], $route[2], $route[3] ?? 1000]; +/* + echo '
';
+		var_dump($route[1], $route[3], $route[2]);
+		echo '/
';
+*/
 	}
 
 	foreach ($routes as $route) {
-		if(!isset($isAlreadyDefined[$route[1]])) {
-			if (strpos($route[2], '__redirect__') === false && strpos($route[2], '__database__') === false) {
-				$routesTmp[] = [$route[0], $route[1], 'system/pages/' . $route[2]];
-			}
-			else {
-				$routesTmp[] = [$route[0], $route[1], $route[2]];
-			}
+		if (!str_contains($route[2], '__redirect__') && !str_contains($route[2], '__database__')) {
+			$routesFinal[] = [$route[0], $route[1], 'system/pages/' . $route[2], $route[3] ?? 10000];
+		}
+		else {
+			$routesFinal[] = [$route[0], $route[1], $route[2], $route[3] ?? 10000];
 		}
 	}
 
-	//var_dump($routesTmp);
-	foreach ($routesTmp as $route) {
+	// sort required for the next step (filter)
+	usort($routesFinal, function ($a, $b)
+	{
+		// key 3 is priority
+		if ($a[3] == $b[3]) {
+			return 0;
+		}
+
+		return ($a[3] < $b[3]) ? -1 : 1;
+	});
+
+	// 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]+'],
+		];
+
+		// apply aliases
+		$a[1] = str_replace($aliases[0], $aliases[1], $a[1]);
+
+		static $duplicates = [];
+		if (isset($duplicates[$a[1]])) {
+			return false;
+		}
+
+		$duplicates[$a[1]] = true;
+		return true;
+	});
+/*
+	echo '
';
+	var_dump($routesFinal);
+	echo '
'; + die; +*/ + foreach ($routesFinal as $route) { if ($route[0] === '*') { $route[0] = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD']; } diff --git a/system/routes.php b/system/routes.php index 35516b3e..c49b16b1 100644 --- a/system/routes.php +++ b/system/routes.php @@ -11,50 +11,56 @@ defined('MYAAC') or die('Direct access not allowed!'); return [ ['GET', '', 'news.php'], // empty URL = show news - ['GET', 'news/archive/{id:int}[/]', 'news/archive.php'], - ['GET', 'news/{id:int}[/]', 'news/archive.php'], + ['GET', 'news/archive/{id:int}', 'news/archive.php'], + ['GET', 'news/{id:int}', 'news/archive.php'], // block access to some files - ['*', 'account/base[/]', '404.php'], // this is to block account/base.php - ['*', 'forum/base[/]', '404.php'], - ['*', 'guilds/base[/]', '404.php'], + ['*', 'account/base', '404.php', 10], // this is to block account/base.php + ['*', 'forum/base', '404.php', 10], + ['*', 'guilds/base', '404.php', 10], - [['GET', 'POST'], 'account/password[/]', 'account/change_password.php'], - [['GET', 'POST'], 'account/register/new[/]', 'account/register_new.php'], - [['GET', 'POST'], 'account/email[/]', 'account/change_email.php'], - [['GET', 'POST'], 'account/info[/]', 'account/change_info.php'], - [['GET', 'POST'], 'account/character/create[/]', 'account/create_character.php'], - [['GET', 'POST'], 'account/character/name[/]', 'account/change_name.php'], - [['GET', 'POST'], 'account/character/sex[/]', 'account/change_sex.php'], - [['GET', 'POST'], 'account/character/delete[/]', 'account/delete_character.php'], - [['GET', 'POST'], 'account/character/comment[/{name:[A-Za-z0-9-_%+\']+}]', 'account/change_comment.php'], - ['GET', 'account/confirm_email/{hash:alphanum}[/]', 'account/confirm_email.php'], + ['GET', 'account/confirm-email/{hash:alphanum}', 'account/confirm-email.php'], - ['GET', 'bans/{page:int}[/]', 'bans.php'], + ['GET', 'bans/{page:int}', 'bans.php'], [['GET', 'POST'], 'characters[/{name:string}]', 'characters.php'], ['GET', 'changelog[/{page:int}]', 'changelog.php'], [['GET', 'POST'], 'monsters[/{name:string}]', 'monsters.php'], [['GET', 'POST'], 'faq[/{action:string}]', 'faq.php'], - [['GET', 'POST'], 'forum/{action:string}[/]', 'forum.php'], - ['GET', 'forum/board/{id:int}[/]', 'forum/show_board.php'], - ['GET', 'forum/board/{id:int}/{page:[0-9]+}[/]', 'forum/show_board.php'], - ['GET', 'forum/thread/{id:int}[/]', 'forum/show_thread.php'], - ['GET', 'forum/thread/{id:int}/{page:int}[/]', 'forum/show_thread.php'], + [['GET', 'POST'], 'forum/{action:string}', 'forum.php'], + ['GET', 'forum/board/{id:int}', 'forum/show_board.php'], + ['GET', 'forum/board/{id:int}/{page:[0-9]+}', 'forum/show_board.php'], + ['GET', 'forum/thread/{id:int}', 'forum/show_thread.php'], + ['GET', 'forum/thread/{id:int}/{page:int}', 'forum/show_thread.php'], - ['GET', 'gallery/{image:int}[/]', 'gallery.php'], - [['GET', 'POST'], 'gallery/{action:string}[/]', 'gallery.php'], + ['GET', 'gallery/{image:int}', 'gallery.php'], + [['GET', 'POST'], 'gallery/{action:string}', 'gallery.php'], - [['GET', 'POST'], 'guilds/{guild:string}[/]', 'guilds/show.php'], + [['GET', 'POST'], 'guilds/{guild:string}', 'guilds/show.php'], - ['GET', 'highscores/{list:alphanum}/{vocation:alphanum}/{page:int}[/]', 'highscores.php'], - ['GET', 'highscores/{list:alphanum}/{page:int}[/]', 'highscores.php'], - ['GET', 'highscores/{list:alphanum}/{vocation:alphanum}[/]', 'highscores.php'], - ['GET', 'highscores/{list:alphanum}[/]', 'highscores.php'], + ['GET', 'highscores/{list:alphanum}/{vocation:alphanum}/{page:int}', 'highscores.php'], + ['GET', 'highscores/{list:alphanum}/{page:int}', 'highscores.php'], + ['GET', 'highscores/{list:alphanum}/{vocation:alphanum}', 'highscores.php'], + ['GET', 'highscores/{list:alphanum}', 'highscores.php'], /* - '/^gifts\/history\/?$/' => array('subtopic' => 'gifts', 'action' => 'show_history'), '/^polls\/[0-9]+\/?$/' => array('subtopic' => 'polls', 'id' => '$1'), '/^spells\/[A-Za-z0-9-_%]+\/[A-Za-z0-9-_]+\/?$/' => array('subtopic' => 'spells', 'vocation' => '$1', 'order' => '$2'), '/^houses\/view\/?$/' => array('subtopic' => 'houses', 'page' => 'view')*/ + + /** + * Deprecated + * To be removed in next versions + * Kept just for compatibility + */ + [['GET', 'POST'], 'account/password', 'account/change-password.php'], + [['GET', 'POST'], 'account/register/new', 'account/register-new.php'], + [['GET', 'POST'], 'account/email', 'account/change-email.php'], + [['GET', 'POST'], 'account/info', 'account/change-info.php'], + [['GET', 'POST'], 'account/character/create', 'account/characters/create.php'], + [['GET', 'POST'], 'account/character/name', 'account/characters/change-name.php'], + [['GET', 'POST'], 'account/character/sex', 'account/characters/change-sex.php'], + [['GET', 'POST'], 'account/character/delete', 'account/characters/delete.php'], + [['GET', 'POST'], 'account/character/comment[/{name:string}]', 'account/characters/change-comment.php'], + ['GET', 'account/confirm_email/{hash:alphanum}', 'account/confirm-email.php'], ]; diff --git a/system/settings.php b/system/settings.php index a5d0c00e..a7f1b53c 100644 --- a/system/settings.php +++ b/system/settings.php @@ -735,7 +735,7 @@ Sent by MyAAC,
'name' => 'Name Min Length', 'type' => 'number', 'desc' => '', - 'default' => 4, + 'default' => 3, ], 'create_character_name_max_length' => [ 'name' => 'Name Max Length', diff --git a/system/src/CreateCharacter.php b/system/src/CreateCharacter.php index 446ed160..ea0d2c6c 100644 --- a/system/src/CreateCharacter.php +++ b/system/src/CreateCharacter.php @@ -149,9 +149,9 @@ class CreateCharacter if(empty($errors)) { $char_to_copy_name = config('character_samples')[$vocation]; - $char_to_copy = new \OTS_Player(); - $char_to_copy->find($char_to_copy_name); - if(!$char_to_copy->isLoaded()) + $playerSample = new \OTS_Player(); + $playerSample->find($char_to_copy_name); + if(!$playerSample->isLoaded()) $errors[] = 'Wrong characters configuration. Try again or contact with admin. ADMIN: Go to Admin Panel -> Settings -> Create Character and set valid characters to copy names. Character to copy: '.$char_to_copy_name.' doesn\'t exist.'; } @@ -162,72 +162,72 @@ class CreateCharacter global $db; if($sex == "0") - $char_to_copy->setLookType(136); + $playerSample->setLookType(136); $player = new \OTS_Player(); $player->setName($name); $player->setAccount($account); $player->setGroupId(1); $player->setSex($sex); - $player->setVocation($char_to_copy->getVocation()); + $player->setVocation($playerSample->getVocation()); if($db->hasColumn('players', 'promotion')) - $player->setPromotion($char_to_copy->getPromotion()); + $player->setPromotion($playerSample->getPromotion()); if($db->hasColumn('players', 'direction')) - $player->setDirection($char_to_copy->getDirection()); + $player->setDirection($playerSample->getDirection()); - $player->setConditions($char_to_copy->getConditions()); - $rank = $char_to_copy->getRank(); + $player->setConditions($playerSample->getConditions()); + $rank = $playerSample->getRank(); if($rank->isLoaded()) { - $player->setRank($char_to_copy->getRank()); + $player->setRank($playerSample->getRank()); } if($db->hasColumn('players', 'lookaddons')) - $player->setLookAddons($char_to_copy->getLookAddons()); + $player->setLookAddons($playerSample->getLookAddons()); $player->setTownId($town); - $player->setExperience($char_to_copy->getExperience()); - $player->setLevel($char_to_copy->getLevel()); - $player->setMagLevel($char_to_copy->getMagLevel()); - $player->setHealth($char_to_copy->getHealth()); - $player->setHealthMax($char_to_copy->getHealthMax()); - $player->setMana($char_to_copy->getMana()); - $player->setManaMax($char_to_copy->getManaMax()); - $player->setManaSpent($char_to_copy->getManaSpent()); - $player->setSoul($char_to_copy->getSoul()); + $player->setExperience($playerSample->getExperience()); + $player->setLevel($playerSample->getLevel()); + $player->setMagLevel($playerSample->getMagLevel()); + $player->setHealth($playerSample->getHealth()); + $player->setHealthMax($playerSample->getHealthMax()); + $player->setMana($playerSample->getMana()); + $player->setManaMax($playerSample->getManaMax()); + $player->setManaSpent($playerSample->getManaSpent()); + $player->setSoul($playerSample->getSoul()); for($skill = \POT::SKILL_FIRST; $skill <= \POT::SKILL_LAST; $skill++) { $value = 10; if (setting('core.use_character_sample_skills')) { - $value = $char_to_copy->getSkill($skill); + $value = $playerSample->getSkill($skill); } $player->setSkill($skill, $value); } - $player->setLookBody($char_to_copy->getLookBody()); - $player->setLookFeet($char_to_copy->getLookFeet()); - $player->setLookHead($char_to_copy->getLookHead()); - $player->setLookLegs($char_to_copy->getLookLegs()); - $player->setLookType($char_to_copy->getLookType()); - $player->setCap($char_to_copy->getCap()); + $player->setLookBody($playerSample->getLookBody()); + $player->setLookFeet($playerSample->getLookFeet()); + $player->setLookHead($playerSample->getLookHead()); + $player->setLookLegs($playerSample->getLookLegs()); + $player->setLookType($playerSample->getLookType()); + $player->setCap($playerSample->getCap()); $player->setBalance(0); $player->setPosX(0); $player->setPosY(0); $player->setPosZ(0); if($db->hasColumn('players', 'stamina')) { - $player->setStamina($char_to_copy->getStamina()); + $player->setStamina($playerSample->getStamina()); } if($db->hasColumn('players', 'loss_experience')) { - $player->setLossExperience($char_to_copy->getLossExperience()); - $player->setLossMana($char_to_copy->getLossMana()); - $player->setLossSkills($char_to_copy->getLossSkills()); + $player->setLossExperience($playerSample->getLossExperience()); + $player->setLossMana($playerSample->getLossMana()); + $player->setLossSkills($playerSample->getLossSkills()); } if($db->hasColumn('players', 'loss_items')) { - $player->setLossItems($char_to_copy->getLossItems()); - $player->setLossContainers($char_to_copy->getLossContainers()); + $player->setLossItems($playerSample->getLossItems()); + $player->setLossContainers($playerSample->getLossContainers()); } $player->save(); @@ -245,7 +245,7 @@ class CreateCharacter for($skill = \POT::SKILL_FIRST; $skill <= \POT::SKILL_LAST; $skill++) { $value = 10; if (setting('core.use_character_sample_skills')) { - $value = $char_to_copy->getSkill($skill); + $value = $playerSample->getSkill($skill); } $skillExists = $db->query('SELECT `skillid` FROM `player_skills` WHERE `player_id` = ' . $player->getId() . ' AND `skillid` = ' . $skill); if($skillExists->rowCount() <= 0) { @@ -255,7 +255,7 @@ class CreateCharacter } if ($db->hasTable('player_items') && $db->hasColumn('player_items', 'pid') && $db->hasColumn('player_items', 'sid') && $db->hasColumn('player_items', 'itemtype')) { - $loaded_items_to_copy = $db->query("SELECT * FROM player_items WHERE player_id = ".$char_to_copy->getId().""); + $loaded_items_to_copy = $db->query("SELECT * FROM player_items WHERE player_id = ".$playerSample->getId().""); foreach($loaded_items_to_copy as $save_item) { $blob = $db->quote($save_item['attributes']); $db->query("INSERT INTO `player_items` (`player_id` ,`pid` ,`sid` ,`itemtype`, `count`, `attributes`) VALUES ('".$player->getId()."', '".$save_item['pid']."', '".$save_item['sid']."', '".$save_item['itemtype']."', '".$save_item['count']."', $blob);"); @@ -267,6 +267,7 @@ class CreateCharacter [ 'account' => $account, 'player' => $player, + 'samplePlayer' => $playerSample, 'name' => $name, 'sex' => $sex, 'vocation' => $vocation, diff --git a/system/src/Models/GuildRank.php b/system/src/Models/GuildRank.php index 3abce8e8..59ea9f56 100644 --- a/system/src/Models/GuildRank.php +++ b/system/src/Models/GuildRank.php @@ -9,6 +9,8 @@ class GuildRank extends Model { public $timestamps = false; + protected $fillable = ['guild_id', 'name', 'level']; + public function guild() { return $this->belongsTo(Guild::class); diff --git a/system/src/Plugins.php b/system/src/Plugins.php index d30a2497..fbaa5e40 100644 --- a/system/src/Plugins.php +++ b/system/src/Plugins.php @@ -23,18 +23,15 @@ class Plugins { $routes = []; foreach(self::getAllPluginsJson() as $plugin) { - $pluginPages = glob(PLUGINS . $plugin['filename'] . '/pages/*.php'); - foreach ($pluginPages as $file) { - $file = str_replace(PLUGINS, 'plugins/', $file); - $name = pathinfo($file, PATHINFO_FILENAME); - - $routes[] = [['get', 'post'], $name, $file, 1000]; + $routesDefaultPriority = 1000; + if (isset($plugin['routes-default-priority'])) { + $routesDefaultPriority = $plugin['routes-default-priority']; } $warningPreTitle = 'Plugin: ' . $plugin['name'] . ' - '; if (isset($plugin['routes'])) { - foreach ($plugin['routes'] as $_name => $info) { + foreach ($plugin['routes'] as $info) { // default method: get $method = $info['method'] ?? ['GET']; if ($method !== '*') { @@ -51,7 +48,7 @@ class Plugins { } if (!isset($info['priority'])) { - $info['priority'] = 100; // default priority + $info['priority'] = $routesDefaultPriority; // default priority taken from plugin.json } if (isset($info['redirect_from'])) { @@ -70,39 +67,75 @@ class Plugins { // replace first occurrence of / in pattern if found (will be auto-added later) removeIfFirstSlash($info['pattern']); - foreach ($routes as $id => &$route) { - if($route[1] == $info['pattern']) { - if($info['priority'] < $route[3]) { - self::$warnings[] = $warningPreTitle . "Duplicated route with lower priority: {$info['pattern']}. Disabling this route..."; - continue 2; - } - else { - self::$warnings[] = $warningPreTitle . "Duplicated route with lower priority: {$route[1]} ({$route[3]}). Disabling this route..."; - unset($routes[$id]); - } - } - } - $routes[] = [$methods, $info['pattern'], $info['file'], $info['priority']]; } } - } - /* - usort($routes, function ($a, $b) - { - // key 3 is priority - if ($a[3] == $b[3]) { - return 0; + + $pagesDefaultPriority = 1000; + if (isset($plugin['pages-default-priority'])) { + $pagesDefaultPriority = $plugin['pages-default-priority']; + } + + if (self::getAutoLoadOption($plugin, 'pages', true)) { + // + // Get all plugins/*/pages/*.php pages + // + $pluginPages = glob(PLUGINS . $plugin['filename'] . '/pages/*.php'); + foreach ($pluginPages as $file) { + $file = str_replace(PLUGINS, 'plugins/', $file); + $name = pathinfo($file, PATHINFO_FILENAME); + + $routes[] = [['get', 'post'], $name, $file, $pagesDefaultPriority]; + } + } + + if (self::getAutoLoadOption($plugin, 'pagesSubFolders', true)) { + // + // Get all plugins/*/pages/subFolder/*.php pages + // + $pluginPagesSubFolders = glob(PLUGINS . $plugin['filename'] . '/pages/*', GLOB_ONLYDIR); + foreach ($pluginPagesSubFolders as $folder) { + $folderName = pathinfo($folder, PATHINFO_FILENAME); + + $subFiles = glob(PLUGINS . $plugin['filename'] . '/pages/' . $folderName . '/*.php'); + foreach ($subFiles as $file) { + $file = str_replace(PLUGINS, 'plugins/', $file); + $name = $folderName . '/' . pathinfo($file, PATHINFO_FILENAME); + + $routes[] = [['get', 'post'], $name, $file, $pagesDefaultPriority]; } - return ($a[3] > $b[3]) ? -1 : 1; - }); - */ + $subFolders = glob(PLUGINS . $plugin['filename'] . '/pages/' . $folderName . '/*', GLOB_ONLYDIR); + foreach ($subFolders as $subFolder) { + $subFolderName = pathinfo($subFolder, PATHINFO_FILENAME); + $subSubFiles = glob(PLUGINS . $plugin['filename'] . '/pages/' . $folderName . '/' . $subFolderName . '/*.php'); + + foreach ($subSubFiles as $subSubFile) { + $subSubFile = str_replace(PLUGINS, 'plugins/', $subSubFile); + $name = $folderName . '/' . $subFolderName . '/' . pathinfo($subSubFile, PATHINFO_FILENAME); + + $routes[] = [['get', 'post'], $name, $subSubFile, $pagesDefaultPriority]; + } + } + } + } + } + + usort($routes, function ($a, $b) + { + // key 3 is priority + if ($a[3] == $b[3]) { + return 0; + } + + return ($a[3] < $b[3]) ? -1 : 1; + }); + // cleanup before passing back // priority is not needed anymore - foreach ($routes as &$route) { - unset($route[3]); - } + //foreach ($routes as &$route) { + // unset($route[3]); + //} if ($cache->enabled()) { $cache->set('plugins_routes', serialize($routes), 600); @@ -123,6 +156,10 @@ class Plugins { $themes = []; foreach(self::getAllPluginsJson() as $plugin) { + if (!self::getAutoLoadOption($plugin, 'themes', true)) { + continue; + } + $pluginThemes = glob(PLUGINS . $plugin['filename'] . '/themes/*', GLOB_ONLYDIR); foreach ($pluginThemes as $path) { $path = str_replace(PLUGINS, 'plugins/', $path); @@ -151,6 +188,10 @@ class Plugins { $commands = []; foreach(self::getAllPluginsJson() as $plugin) { + if (!self::getAutoLoadOption($plugin, 'commands', true)) { + continue; + } + $pluginCommands = glob(PLUGINS . $plugin['filename'] . '/commands/*.php'); foreach ($pluginCommands as $path) { $commands[] = $path; @@ -178,13 +219,19 @@ class Plugins { foreach(self::getAllPluginsJson() as $plugin) { if (isset($plugin['hooks'])) { foreach ($plugin['hooks'] as $_name => $info) { + $priority = 1000; + if (str_contains($info['type'], 'HOOK_')) { $info['type'] = str_replace('HOOK_', '', $info['type']); } + if (isset($info['priority'])) { + $priority = (int)$info['priority']; + } + if (defined('HOOK_'. $info['type'])) { $hook = constant('HOOK_'. $info['type']); - $hooks[] = ['name' => $_name, 'type' => $hook, 'file' => $info['file']]; + $hooks[] = ['name' => $_name, 'type' => $hook, 'file' => $info['file'], 'priority' => $priority]; } else { self::$warnings[] = 'Plugin: ' . $plugin['name'] . '. Unknown event type: ' . $info['type']; } @@ -192,6 +239,15 @@ class Plugins { } } + usort($hooks, function ($a, $b) + { + if ($a['priority'] == $b['priority']) { + return 0; + } + + return ($a['priority'] < $b['priority']) ? -1 : 1; + }); + if ($cache->enabled()) { $cache->set('plugins_hooks', serialize($hooks), 600); } @@ -757,4 +813,21 @@ class Plugins { } } } + + private static function getAutoLoadOption(array $plugin, string $optionName, bool $default = true) + { + if (isset($plugin['autoload'])) { + $autoload = $plugin['autoload']; + if (is_array($autoload)) { + if (isset($autoload[$optionName])) { + return getBoolean($autoload[$optionName]); + } + } + else if (is_bool($autoload)) { + return $autoload; + } + } + + return $default; + } } diff --git a/system/src/Settings.php b/system/src/Settings.php index 6c122237..0749396a 100644 --- a/system/src/Settings.php +++ b/system/src/Settings.php @@ -382,6 +382,8 @@ class Settings implements \ArrayAccess } $this->settingsDatabase[$pluginKeyName][$key] = $value; + // invalidate cache + unset($this->cache[$offset]); } #[\ReturnTypeWillChange] diff --git a/system/src/Towns.php b/system/src/Towns.php index e8a24359..6b02d41b 100644 --- a/system/src/Towns.php +++ b/system/src/Towns.php @@ -124,6 +124,6 @@ class Towns */ public static function getFromDatabase() { - return Town::pluck('name', 'id')->toArray(); + return Town::orderBy('id', 'ASC')->pluck('name', 'id')->toArray(); } } diff --git a/system/src/Twig/Extension/TypeCastingExtension.php b/system/src/Twig/Extension/TypeCastingExtension.php new file mode 100644 index 00000000..cb15c0ad --- /dev/null +++ b/system/src/Twig/Extension/TypeCastingExtension.php @@ -0,0 +1,36 @@ + */ + public function getFilters(): array + { + return [ + new TwigFilter('int', function ($value) { + return (int)$value; + }), + new TwigFilter('float', function ($value) { + return (float)$value; + }), + new TwigFilter('string', function ($value) { + return (string)$value; + }), + new TwigFilter('bool', function ($value) { + return (bool)$value; + }), + new TwigFilter('array', function (object $value) { + return (array)$value; + }), + new TwigFilter('object', function (array $value) { + return (object)$value; + }), + ]; + } +} diff --git a/system/src/global.php b/system/src/global.php index 3700dee6..d4bd0cc4 100644 --- a/system/src/global.php +++ b/system/src/global.php @@ -54,6 +54,11 @@ define('HOOK_ACCOUNT_LOGIN_AFTER_REMEMBER_ME', ++$i); define('HOOK_ACCOUNT_LOGIN_AFTER_PAGE', ++$i); define('HOOK_ACCOUNT_LOGIN_POST', ++$i); define('HOOK_ACCOUNT_CREATE_CHARACTER_AFTER', ++$i); +define('HOOK_ACCOUNT_CREATE_CHARACTER_BEFORE_FIRST_TABLE', ++$i); +define('HOOK_ACCOUNT_CREATE_CHARACTER_BEFORE_VOCATIONS', ++$i); +define('HOOK_ACCOUNT_CREATE_CHARACTER_BEFORE_TOWNS', ++$i); +define('HOOK_ACCOUNT_CREATE_CHARACTER_AFTER_TOWNS', ++$i); +define('HOOK_ACCOUNT_CREATE_CHARACTER_AFTER_SECOND_TABLE', ++$i); define('HOOK_ADMIN_HEAD_END', ++$i); define('HOOK_ADMIN_HEAD_START', ++$i); define('HOOK_ADMIN_BODY_START', ++$i); @@ -74,6 +79,8 @@ define('HOOK_GUILDS_AFTER_GUILD_MEMBERS', ++$i); define('HOOK_GUILDS_AFTER_INVITED_CHARACTERS', ++$i); define('HOOK_TWIG', ++$i); define('HOOK_CACHE_CLEAR', ++$i); +define('HOOK_INSTALL_FINISH', ++$i); +define('HOOK_INSTALL_FINISH_END', ++$i); const HOOK_FIRST = HOOK_STARTUP; define('HOOK_LAST', $i); diff --git a/system/templates/account.change-email.html.twig b/system/templates/account.change-email.html.twig new file mode 100644 index 00000000..ea627cc7 --- /dev/null +++ b/system/templates/account.change-email.html.twig @@ -0,0 +1,54 @@ +Please enter your password and the new email address. Make sure that you enter a valid email address which you have access to.
For security reasons, the actual change will be finalised after a waiting period of {{ setting('core.account_mail_change') }} days.

+{% set title = 'Change Email Address' %} +{% set background = config('darkborder') %} +{% set content %} + + + + + + + + + +
+ New Email Address: + + +
+ Password: + + +
+{% endset %} +{% include 'tables.headline.html.twig' %} +
+ + + + + +
+ + + + +
+
+ {{ csrf() }} + + {{ include('buttons.submit.html.twig') }} +
+
+
+ + + {{ csrf() }} + + + + +
+ {{ include('buttons.back.html.twig') }} +
+
diff --git a/system/templates/account.change-info.html.twig b/system/templates/account.change-info.html.twig new file mode 100644 index 00000000..e3481472 --- /dev/null +++ b/system/templates/account.change-info.html.twig @@ -0,0 +1,84 @@ +Here you can tell other players about yourself. This information will be displayed alongside the data of your characters. If you do not want to fill in a certain field, just leave it blank.

+{% set title = 'Change Public Information' %} +{% set background = config('darkborder') %} +{% set content %} + + + + + + + + + + {% if setting('core.account_country') %} + + + + + {% endif %} +
Real Name: + +
Location: + +
Country: + + + +
+{% endset %} +{% include 'tables.headline.html.twig' %} +
+ + + + + +
+ + + + +
+
+ {{ csrf() }} + + {{ include('buttons.submit.html.twig') }} +
+
+
+ + + + +
+
+ {{ csrf() }} + {{ include('buttons.back.html.twig') }} +
+
+
diff --git a/system/templates/account.change-password.html.twig b/system/templates/account.change-password.html.twig new file mode 100644 index 00000000..56e52c08 --- /dev/null +++ b/system/templates/account.change-password.html.twig @@ -0,0 +1,62 @@ +Please enter your current password and a new password. For your security, please enter the new password twice.
+
+{% set title = 'Change Password' %} +{% set background = config('darkborder') %} +{% set content %} + + + + + + + + + + + + + +
+ New Password: + + +
+ New Password Again: + + +
+ Current Password: + + +
+{% endset %} +{% include 'tables.headline.html.twig' %} +
+ + + + + +
+ + + + +
+
+ {{ csrf() }} + {{ include('buttons.submit.html.twig') }} +
+
+
+ + + + +
+
+ {{ csrf() }} + {{ include('buttons.back.html.twig') }} +
+
+
diff --git a/system/templates/account.change_info.html.twig b/system/templates/account.change_info.html.twig deleted file mode 100644 index 067eabc5..00000000 --- a/system/templates/account.change_info.html.twig +++ /dev/null @@ -1,102 +0,0 @@ -Here you can tell other players about yourself. This information will be displayed alongside the data of your characters. If you do not want to fill in a certain field, just leave it blank.

-
- {{ csrf() }} -
- -
-
- - - - -
Change Public Information
- - - - -
-
- - - -
-
- - - - - - - - - - {% if setting('core.account_country') %} - - - - - {% endif %} -
Real Name: - -
Location: - -
Country: - - - -
-
-
-
-
- - - - - -
- - - - -
- - {{ include('buttons.submit.html.twig') }} -
-
- - - - {{ csrf() }} - - - - -
- {{ include('buttons.back.html.twig') }} -
-
diff --git a/system/templates/account.change_mail.html.twig b/system/templates/account.change_mail.html.twig deleted file mode 100644 index f093fbff..00000000 --- a/system/templates/account.change_mail.html.twig +++ /dev/null @@ -1,72 +0,0 @@ -Please enter your password and the new email address. Make sure that you enter a valid email address which you have access to.
For security reasons, the actual change will be finalised after a waiting period of {{ setting('core.account_mail_change') }} days.

-
- {{ csrf() }} -
- -
-
- - - - -
Change Email Address
- - - - -
-
- - - -
-
- - - - - - - - - -
- New Email Address: - - -
- Password: - - -
-
-
-
-
- - - - - - -
- - - - -
- - {{ include('buttons.submit.html.twig') }} -
-
- - - {{ csrf() }} - - - - -
- {{ include('buttons.back.html.twig') }} -
-
diff --git a/system/templates/account.change_name.html.twig b/system/templates/account.change_name.html.twig deleted file mode 100644 index 1fd10609..00000000 --- a/system/templates/account.change_name.html.twig +++ /dev/null @@ -1,79 +0,0 @@ -To change a name of character select player and choose a new name.
-Change name cost {{ setting('core.account_change_character_name_price') }} {{ setting('core.donate_column') == 'coins' ? 'coins' : 'premium points' }}. You have {{ points }} {{ setting('core.donate_column') == 'coins' ? 'coins' : 'premium points' }}.

-
- {{ csrf() }} - -
- -
-
- - - - -
Change Name
- - - - -
-
- - - -
-
- - - - - - - - - -
Character: - -
New Name: - - -
- -
Please enter your character name.
-
-
-
-
-
-
- - - - - -
- - - - - -
- {{ include('buttons.submit.html.twig') }} -
-
- - - {{ csrf() }} - - - - -
- {{ include('buttons.back.html.twig') }} -
-
- diff --git a/system/templates/account.change_password.html.twig b/system/templates/account.change_password.html.twig deleted file mode 100644 index 89ccf592..00000000 --- a/system/templates/account.change_password.html.twig +++ /dev/null @@ -1,80 +0,0 @@ -Please enter your current password and a new password. For your security, please enter the new password twice.
-
-
- {{ csrf() }} -
- -
-
- - - - -
Change Password
- - - - -
-
- - - -
-
- - - - - - - - - - - - - -
- New Password: - - -
- New Password Again: - - -
- Current Password: - - -
-
-
-
-
- - - - - - -
- - - - -
- {{ include('buttons.submit.html.twig') }} -
-
- - - {{ csrf() }} - - - - -
- {{ include('buttons.back.html.twig') }} -
-
diff --git a/system/templates/account.change_sex.html.twig b/system/templates/account.change_sex.html.twig deleted file mode 100644 index fe0ef6e7..00000000 --- a/system/templates/account.change_sex.html.twig +++ /dev/null @@ -1,78 +0,0 @@ -To change a sex of character select player and choose a new sex.
-Change sex cost {{ setting('core.account_change_character_sex_price') }} {{ setting('core.donate_column') == 'coins' ? 'coins' : 'premium points' }}. You have {{ points }} {{ setting('core.donate_column') == 'coins' ? 'coins' : 'premium points' }}.

-
- {{ csrf() }} - -
- -
-
- - - - -
Change sex
- - - - -
-
- - - -
-
- - - - - - - - - -
Character: - -
New Sex: - -
-
-
-
-
- - - - - -
- - - - - - -
- {{ include('buttons.submit.html.twig') }} -
-
- - - {{ csrf() }} - - - - -
- {{ include('buttons.back.html.twig') }} -
-
diff --git a/system/templates/account.change_comment.html.twig b/system/templates/account.characters.change-comment.html.twig similarity index 98% rename from system/templates/account.change_comment.html.twig rename to system/templates/account.characters.change-comment.html.twig index 04e20c0b..8bb94c80 100644 --- a/system/templates/account.change_comment.html.twig +++ b/system/templates/account.characters.change-comment.html.twig @@ -1,6 +1,6 @@ Here you can see and edit the information about your character.
If you do not want to specify a certain field, just leave it blank.

-
+ {{ csrf() }}
diff --git a/system/templates/account.characters.change-name.html.twig b/system/templates/account.characters.change-name.html.twig new file mode 100644 index 00000000..7c0d18f3 --- /dev/null +++ b/system/templates/account.characters.change-name.html.twig @@ -0,0 +1,62 @@ +To change a name of character select player and choose a new name.
+Change name cost {{ setting('core.account_change_character_name_price') }} {{ setting('core.donate_column') == 'coins' ? 'coins' : 'premium points' }}. You have {{ points }} {{ setting('core.donate_column') == 'coins' ? 'coins' : 'premium points' }}.

+ +{% set title = 'Change Name' %} +{% set background = config('darkborder') %} +{% set content %} +
+ + + + + + + + +
Character: + +
New Name: + + +
+ +
Please enter your character name.
+
+
+{% endset %} +{% include 'tables.headline.html.twig' %} +
+ + + + + +
+ + + + +
+ + {{ csrf() }} + + {{ include('buttons.submit.html.twig') }} + +
+
+ + + + +
+
+ {{ csrf() }} + {{ include('buttons.back.html.twig') }} +
+
+
+ diff --git a/system/templates/account.characters.change-sex.html.twig b/system/templates/account.characters.change-sex.html.twig new file mode 100644 index 00000000..440fed9f --- /dev/null +++ b/system/templates/account.characters.change-sex.html.twig @@ -0,0 +1,61 @@ +To change a sex of character select player and choose a new sex.
+Change sex cost {{ setting('core.account_change_character_sex_price') }} {{ setting('core.donate_column') == 'coins' ? 'coins' : 'premium points' }}. You have {{ points }} {{ setting('core.donate_column') == 'coins' ? 'coins' : 'premium points' }}. +

+{% set title = 'Change sex' %} +{% set background = config('darkborder') %} +{% set content %} + + + + + + + + + +
Character: + +
New Sex: + +
+{% endset %} +{% include 'tables.headline.html.twig' %} + +
+ + + + + +
+ + + + +
+
+ {{ csrf() }} + + {{ include('buttons.submit.html.twig') }} +
+
+
+ + + + +
+
+ {{ csrf() }} + {{ include('buttons.back.html.twig') }} +
+
+
diff --git a/system/templates/account.characters.create.html.twig b/system/templates/account.characters.create.html.twig new file mode 100644 index 00000000..6e2b613d --- /dev/null +++ b/system/templates/account.characters.create.html.twig @@ -0,0 +1,168 @@ +Please choose a name{% if config.character_samples|length > 1 %}, vocation{% endif %} +{% if config.character_towns|length > 1 %}, town{% endif %} + and sex for your character.
+In any case the name must not violate the naming conventions stated in the {{ config.lua.serverName }} Rules, or your character might get deleted or name locked. +{% if account_logged.getPlayersList(true)|length >= setting('core.characters_per_account') %} + You have maximum number of characters per account on your account. Delete one before you make new. +{% endif %} +

+
+ +
+
+ + + + +
Create Character
+ + + + +
+
+ + + +
+ + {{ hook('HOOK_ACCOUNT_CREATE_CHARACTER_BEFORE_FIRST_TABLE') }} + +
+ + + + +
+
+
+
+
+
+ + + + + + + + + +
+ Name + + Sex +
+ + +
+ +
{% if not save or errors.name is defined %}Please enter your character name.{% endif %}
+
+
+ {% set i = 0 %} + {% for id, gender in config.genders|reverse(true) %} + {% set i = i + 1 %} +
+ {% endfor %} +
+
+
+
+
+ + {{ hook('HOOK_ACCOUNT_CREATE_CHARACTER_BEFORE_VOCATION') }} + +
+ + + {% if config.character_samples|length > 1 %} + + {% endif %} + + {{ hook('HOOK_ACCOUNT_CREATE_CHARACTER_BEFORE_TOWNS') }} + + {% if config.character_towns|length > 1 %} + + {% endif %} + + {{ hook('HOOK_ACCOUNT_CREATE_CHARACTER_AFTER_TOWNS') }} + + +
+ + + + + +

Select your vocation:
+ + {% for key, sample_char in config.character_samples %} + + + + {% endfor %} +
+ + +
+
+
+ + + + + +

Select your city:
+ + {% for town_id in config.character_towns %} + + + + {% endfor %} +
+ + +
+
+
+
+ + {{ hook('HOOK_ACCOUNT_CREATE_CHARACTER_AFTER_SECOND_TABLE') }} + +
+
+
+ + + + + +
+ + + + +
+
+ {{ csrf() }} + + {{ include('buttons.submit.html.twig') }} +
+
+
+ + + + +
+
+ {{ csrf() }} + {{ include('buttons.back.html.twig') }} +
+
+
+ diff --git a/system/templates/account.characters.delete.html.twig b/system/templates/account.characters.delete.html.twig new file mode 100644 index 00000000..8593f7ed --- /dev/null +++ b/system/templates/account.characters.delete.html.twig @@ -0,0 +1,50 @@ +To delete a character enter the name of the character and your password.

+{% set title = 'Delete Character' %} +{% set background = config('darkborder') %} +{% set content %} + + + + + + + + + +
Character Name: + +
Password: + +
+{% endset %} +{% include 'tables.headline.html.twig' %} +
+ + + + + +
+ + + + +
+
+ {{ csrf() }} + + {{ include('buttons.submit.html.twig') }} +
+
+
+ + + {{ csrf() }} + + + + +
+ {{ include('buttons.back.html.twig') }} +
+
diff --git a/system/templates/account.create.html.twig b/system/templates/account.create.html.twig index 7611a0c2..2e5267e2 100644 --- a/system/templates/account.create.html.twig +++ b/system/templates/account.create.html.twig @@ -1,313 +1,298 @@ {{ hook('HOOK_ACCOUNT_CREATE_BEFORE_FORM') }}
{{ csrf() }} -
- -
-
- - - - -
Create {{ config.lua.serverName }} Account
- - - - -
-
+ + {% set title = 'Create ' ~ config.lua.serverName ~ ' Account' %} + {% set background = config('darkborder') %} + {% set tableClass = 'Table5' %} + {% set content %} +
+ {{ hook('HOOK_ACCOUNT_CREATE_BEFORE_BOXES') }} + - {{ hook('HOOK_ACCOUNT_CREATE_BETWEEN_BOXES_1') }} + {{ hook('HOOK_ACCOUNT_CREATE_BETWEEN_BOXES_1') }} - {% if (not setting('core.mail_enabled') or not setting('core.account_mail_verify')) and setting('core.account_create_character_create') %} - - +
-
- - {{ hook('HOOK_ACCOUNT_CREATE_BEFORE_BOXES') }} - - - + {{ hook('HOOK_ACCOUNT_CREATE_AFTER_PASSWORDS') }} + +
-
-
-
- - +
+
+
+
+ - {{ hook('HOOK_ACCOUNT_CREATE_BEFORE_ACCOUNT') }} + {{ hook('HOOK_ACCOUNT_CREATE_BEFORE_ACCOUNT') }} - {% if not config.account_login_by_email %} - - - - - {% endif %} - - {{ hook('HOOK_ACCOUNT_CREATE_AFTER_ACCOUNT') }} - - - - - - - + {% if not config.account_login_by_email %} + + + + + {% endif %} + + {{ hook('HOOK_ACCOUNT_CREATE_AFTER_ACCOUNT') }} + + + + + + + - {% if setting('core.mail_enabled') and setting('core.account_mail_verify') %} - - {% endif %} + {% if setting('core.mail_enabled') and setting('core.account_mail_verify') %} + + {% endif %} - {{ hook('HOOK_ACCOUNT_CREATE_AFTER_EMAIL') }} + {{ hook('HOOK_ACCOUNT_CREATE_AFTER_EMAIL') }} - {% if setting('core.account_country') %} - - - - - {% if errors.country is defined %} - - {% endif %} - {% endif %} + {% if setting('core.account_country') %} + + + + + {% if errors.country is defined %} + + {% endif %} + {% endif %} - {{ hook('HOOK_ACCOUNT_CREATE_AFTER_COUNTRY') }} + {{ hook('HOOK_ACCOUNT_CREATE_AFTER_COUNTRY') }} - - - - - + + + + + - {{ hook('HOOK_ACCOUNT_CREATE_AFTER_PASSWORD') }} + {{ hook('HOOK_ACCOUNT_CREATE_AFTER_PASSWORD') }} - - - - - + + + + + - {{ hook('HOOK_ACCOUNT_CREATE_AFTER_PASSWORDS') }} - -
- Account {% if constant('USE_ACCOUNT_NAME') %}Name{% else %}Number{% endif %}: - {% if not constant('USE_ACCOUNT_NAME') %} - - {% endif %} - - - -
{% if errors.account is defined %}{{ errors.account }}{% endif %}
- Email Address: - - - -
{% if errors.email is defined %}{{ errors.email }}{% endif %}
+ Account {% if constant('USE_ACCOUNT_NAME') %}Name{% else %}Number{% endif %}: + {% if not constant('USE_ACCOUNT_NAME') %} + + {% endif %} + + + +
{% if errors.account is defined %}{{ errors.account }}{% endif %}
+ Email Address: + + + +
{% if errors.email is defined %}{{ errors.email }}{% endif %}
Please use real address!
We will send a link to validate your Email.
Please use real address!
We will send a link to validate your Email.
- Country: - - - -
{{ errors.country }}
+ Country: + + + +
{{ errors.country }}
- Password: - - - -
{% if errors.password is defined %}{{ errors.password }}{% endif %}
+ Password: + + + +
{% if errors.password is defined %}{{ errors.password }}{% endif %}
- Repeat password: - - - -
{% if errors.password is defined %}{{ errors.password }}{% endif %}
+ Repeat password: + + + +
{% if errors.password is defined %}{{ errors.password }}{% endif %}
-
-
-
-
-
+
+ +
+
+
-
-
-
-
-
- - + {% if setting('core.account_create_character_create') %} + + - - {% endif %} - - {{ hook('HOOK_ACCOUNT_CREATE_BETWEEN_BOXES_2') }} - - - - - - {{ hook('HOOK_ACCOUNT_CREATE_AFTER_BOXES') }} - -
+
+
+
+
+
+ + - {{ hook('HOOK_ACCOUNT_CREATE_BEFORE_CHARACTER_NAME') }} + {{ hook('HOOK_ACCOUNT_CREATE_BEFORE_CHARACTER_NAME') }} - - - - - - - - + + + + + + + + - {{ hook('HOOK_ACCOUNT_CREATE_AFTER_CHARACTER_NAME') }} + {{ hook('HOOK_ACCOUNT_CREATE_AFTER_CHARACTER_NAME') }} - - - - - - - - + + + + + + + + - {{ hook('HOOK_ACCOUNT_CREATE_AFTER_SEX') }} + {{ hook('HOOK_ACCOUNT_CREATE_AFTER_SEX') }} - {% if config.character_samples|length > 1 %} - - - - - - - - - {% endif %} + {% if config.character_samples|length > 1 %} + + + + + + + + + {% endif %} - {{ hook('HOOK_ACCOUNT_CREATE_AFTER_VOCATION') }} + {{ hook('HOOK_ACCOUNT_CREATE_AFTER_VOCATION') }} - {% if config.character_towns|length > 1 %} - - - - - {% endif %} + {% if config.character_towns|length > 1 %} + + + + + {% endif %} - {{ hook('HOOK_ACCOUNT_CREATE_AFTER_TOWNS') }} + {{ hook('HOOK_ACCOUNT_CREATE_AFTER_TOWNS') }} - -
- Character Name: - - - -
-
- {% if errors.name is defined %}{{ errors.name }}{% endif %} -
+ Character Name: + + + +
+
+ {% if errors.name is defined %}{{ errors.name }}{% endif %} +
- Sex: - - - - - - - - -
- {% set i = 0 %} - {% for id, gender in config.genders|reverse(true) %} - {% set i = i + 1 %} - - - - - {% endfor %} - -
-
- {% if errors.sex is defined %}{{ errors.sex }}{% endif %} -
+ Sex: + + + + + + + + +
+ {% set i = 0 %} + {% for id, gender in config.genders|reverse(true) %} + {% set i = i + 1 %} + + + + + {% endfor %} + +
+
+ {% if errors.sex is defined %}{{ errors.sex }}{% endif %} +
- Vocation: - - - - - - - -
- {% for key, sample_char in config.character_samples %} - - - - - {% endfor %} -
-
- {% if errors.vocation is defined %}{{ errors.vocation }}{% endif %} -
+ Vocation: + + + + + + + +
+ {% for key, sample_char in config.character_samples %} + + + + + {% endfor %} +
+
+ {% if errors.vocation is defined %}{{ errors.vocation }}{% endif %} +
- Select your town: - - - - - - - -
- {% for town_id in config.character_towns %} - - - - - {% endfor %} -
-
+ Select your town: + + + + + + + +
+ {% for town_id in config.character_towns %} + + + + + {% endfor %} +
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - - - - - - - - {% if errors.accept_rules is defined %} - - - - {% endif %} - -
Please select the following check box:
- -
- {{ errors.accept_rules }} -
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ {% endif %} + + {{ hook('HOOK_ACCOUNT_CREATE_BETWEEN_BOXES_2') }} + + + +
+
+
+
+
+ + + + + + + + + {% if errors.accept_rules is defined %} + + + + {% endif %} + +
Please select the following check box:
+ +
+ {{ errors.accept_rules }} +
+
+
+
+
+
+
+ + + + {{ hook('HOOK_ACCOUNT_CREATE_AFTER_BOXES') }} + -
+ {% endset %} + {% include 'tables.headline.html.twig' %} +
{{ hook('HOOK_ACCOUNT_CREATE_BEFORE_SUBMIT_BUTTON') }} diff --git a/system/templates/account.create.js.html.twig b/system/templates/account.create.js.html.twig index 61300039..8c3534ca 100644 --- a/system/templates/account.create.js.html.twig +++ b/system/templates/account.create.js.html.twig @@ -3,10 +3,12 @@ var lastSend = 0; $(function() { - updateFlag(); - $('#account_country').change(function() { + {% if setting('core.account_country') %} updateFlag(); - }); + $('#account_country').change(function() { + updateFlag(); + }); + {% endif %} $('#account_input').blur(function() { checkAccount(); diff --git a/system/templates/account.create_character.html.twig b/system/templates/account.create_character.html.twig deleted file mode 100644 index a860a8b1..00000000 --- a/system/templates/account.create_character.html.twig +++ /dev/null @@ -1,150 +0,0 @@ -Please choose a name{% if config.character_samples|length > 1 %}, vocation{% endif %} -{% if config.character_towns|length > 1 %}, town{% endif %} - and sex for your character.
-In any case the name must not violate the naming conventions stated in the {{ config.lua.serverName }} Rules, or your character might get deleted or name locked. -{% if account_logged.getPlayersList(true)|length >= setting('core.characters_per_account') %} - You have maximum number of characters per account on your account. Delete one before you make new. -{% endif %} -

- - {{ csrf() }} - -
-
-
-
- - - - -
Create Character
- - - - -
-
- - - -
-
- - -
-
-
-
-
-
- - - - - - - - - -
- Name - - Sex -
- - -
- -
{% if not save or errors.name is defined %}Please enter your character name.{% endif %}
-
-
- {% set i = 0 %} - {% for id, gender in config.genders|reverse(true) %} - {% set i = i + 1 %} -
- {% endfor %} -
-
-
-
-
-
- - - {% if config.character_samples|length > 1 %} - - {% endif %} - -
- - - - - -

Select your vocation:
- - {% for key, sample_char in config.character_samples %} - - - - {% endfor %} -
- - -
-
- {% endif %} - {% if config.character_towns|length > 1 %} -
- - - - - -

Select your city:
- - {% for town_id in config.character_towns %} - - - - {% endfor %} -
- - -
-
-
-
-
- -
- - - - - -
- - - - - -
- {{ include('buttons.submit.html.twig') }} -
-
- - - {{ csrf() }} - - - - -
- {{ include('buttons.back.html.twig') }} -
-
- diff --git a/system/templates/account.delete_character.html.twig b/system/templates/account.delete_character.html.twig deleted file mode 100644 index c5953cc7..00000000 --- a/system/templates/account.delete_character.html.twig +++ /dev/null @@ -1,68 +0,0 @@ -To delete a character enter the name of the character and your password.

-
- {{ csrf() }} - -
- -
-
- - - - -
Delete Character
- - - - -
-
- - - -
-
- - - - - - - - - -
Character Name: - -
Password: - -
-
-
-
-
- - - - - -
- - - - - -
- {{ include('buttons.submit.html.twig') }} -
-
- - - {{ csrf() }} - - - - -
- {{ include('buttons.back.html.twig') }} -
-
diff --git a/system/templates/account.generate_new_recovery_key.html.twig b/system/templates/account.generate_new_recovery_key.html.twig index 9b28cebc..fc48d3a9 100644 --- a/system/templates/account.generate_new_recovery_key.html.twig +++ b/system/templates/account.generate_new_recovery_key.html.twig @@ -1,61 +1,44 @@ To generate new recovery key for your account please enter your password.
-New recovery key cost {{ setting('core.account_generate_new_reckey_price') }} Premium Points. You have {{ points }} premium points. You will receive e-mail with this recovery key.
-
- {{ csrf() }} - -
- -
-
- - - - -
Generate recovery key
- - - - -
-
- - - -
-
- - - - - -
Password:
-
-
-
-
- - - + + +
- - - + +
+New recovery key cost {{ setting('core.account_generate_new_reckey_price') }} Premium Points. You have {{ points }} premium points. You will receive e-mail with this recovery key. +
+{% set title = 'Generate recovery key' %} +{% set background = config('darkborder') %} +{% set content %} + + + + + +
Password:
+{% endset %} +{% include 'tables.headline.html.twig' %} +
+ + + - - -
+ + + - - -
+ + {{ csrf() }} + {{ include('buttons.submit.html.twig') }} -
-
- - - {{ csrf() }} - - - - -
- {{ include('buttons.back.html.twig') }} -
-
+ +
+
+ + + + +
+
+ {{ 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 cb69476c..29ed1ec5 100644 --- a/system/templates/account.generate_recovery_key.html.twig +++ b/system/templates/account.generate_recovery_key.html.twig @@ -1,40 +1,19 @@ To generate recovery key for your account please enter your password.

-
- {{ csrf() }} - -
- -
-
- - - - -
Generate recovery key
- - - - -
-
- - - -
-
- - - - - -
- Password: - - -
-
-
-
+{% set title = 'Generate recovery key' %} +{% set background = config('darkborder') %} +{% set content %} + + + + + +
+ Password: + + +
+{% endset %} +{% include 'tables.headline.html.twig' %}
@@ -42,12 +21,15 @@ To generate recovery key for your account please enter your password.

- {{ include('buttons.submit.html.twig') }} + + {{ csrf() }} + + {{ include('buttons.submit.html.twig') }} +
- diff --git a/system/templates/account.login.html.twig b/system/templates/account.login.html.twig index 6ab08df9..c1b4afcc 100644 --- a/system/templates/account.login.html.twig +++ b/system/templates/account.login.html.twig @@ -61,20 +61,19 @@ Please enter your account {{ account|lower }} and your password.
- - {{ csrf() }} - - + - - + + +
+
+ {{ include('buttons.account_lost.html.twig') }} -
+ diff --git a/system/templates/account.logout.html.twig b/system/templates/account.logout.html.twig index f74c9ffd..d71c4130 100644 --- a/system/templates/account.logout.html.twig +++ b/system/templates/account.logout.html.twig @@ -1,28 +1,10 @@ -
- -
-
- - - - -
Logout Successful
- - - - -
-
- - - -
-
- - - - -
You have logged out of your {{ config.serverName }} account. In order to view your account you need to log in again.
-
-
-
\ No newline at end of file +{% set title = 'Logout Successful' %} +{% set background = config('darkborder') %} +{% set content %} + + + + +
You have logged out of your {{ config.serverName }} account. In order to view your account you need to log in again.
+{% endset %} +{% include 'tables.headline.html.twig' %} diff --git a/system/templates/account.management.html.twig b/system/templates/account.management.html.twig index a648f28e..db8c766f 100644 --- a/system/templates/account.management.html.twig +++ b/system/templates/account.management.html.twig @@ -26,8 +26,8 @@ } {% set menus = { - 'Create Character': 'account/character/create','Delete Character': 'account/character/delete', - 'Change Info': 'account/info', 'Change Password': 'account/password', 'Change Email': 'account/email' + 'Create Character': 'account/characters/create','Delete Character': 'account/characters/delete', + 'Change Info': 'account/change-info', 'Change Password': 'account/change-password', 'Change Email': 'account/change-email' } %}
@@ -40,10 +40,10 @@ {{ name }} {% endfor %} {% if setting('core.account_change_character_name') %} - Change Name + Change Name {% endif %} {% if setting('core.account_change_character_sex') %} - Change Sex + Change Sex {% endif %} Logout
@@ -80,7 +80,7 @@
A request has been submitted to change the email address of this account to {{ email_new }}. After {{ email_new_time|date("j F Y, G:i:s") }} you can accept the new email address and finish the process. Please cancel the request if you do not want your email address to be changed! Also cancel the request if you have no access to the new email address! -
+ {{ csrf() }} {% set button_name = 'Edit' %} {% include('buttons.base.html.twig') %} @@ -99,8 +99,8 @@ {% endif %} Email Address: - {{ account_email ~ email_change }} - + {{ account_email }}{{ email_change|raw }} + {{ csrf() }} {% set button_name = 'Change Email' %} {% include('buttons.base.html.twig') %} @@ -139,7 +139,7 @@ {{ account_location }} - + {{ csrf() }} {% set button_name = 'Change Info' %} {% include('buttons.base.html.twig') %} @@ -183,7 +183,7 @@ {% if player.getLastLogin() > 0 %}{{ player.getLastLogin|date('d F Y (H:i)') }}{% else %}Never.{% endif %} {% if player.isOnline() %}ONLINE{% else %}Offline{% endif %} {% if player.isHidden() %}Hidden{% else %}Visible{% endif %} - {% if not player.isDeleted() %}[Edit]{% endif %} + {% if not player.isDeleted() %}[Edit]{% endif %} {% endfor %} @@ -191,7 +191,7 @@ {% if setting('core.account_change_character_name') %} {% endif %} - + {% set i = i + 1 %} {% endfor %} diff --git a/system/templates/forum.add_board.html.twig b/system/templates/forum.add_board.html.twig index 39f39688..2c150076 100644 --- a/system/templates/forum.add_board.html.twig +++ b/system/templates/forum.add_board.html.twig @@ -39,7 +39,9 @@ -
- + {{ csrf() }} {% set button_name = 'Create Character' %} {% include('buttons.base.html.twig') %} @@ -199,7 +199,7 @@ - + {{ csrf() }} {% set button_name = 'Change Name' %} {% include('buttons.base.html.twig') %} @@ -208,7 +208,7 @@ {% endif %} {% if setting('core.account_change_character_sex') %} - + {{ csrf() }} {% set button_name = 'Change Sex' %} {% include('buttons.base.html.twig') %} @@ -216,7 +216,7 @@ - + {{ csrf() }} {% set button_name = 'Delete Character' %} {% include('buttons.base.html.twig') %} diff --git a/system/templates/account.redirect.html.twig b/system/templates/account.redirect.html.twig index 16b8d7ba..18028e56 100644 --- a/system/templates/account.redirect.html.twig +++ b/system/templates/account.redirect.html.twig @@ -1,31 +1,13 @@ -
- -
-
- - - - -
Login Successful
- - - - -
-
- - - -
-
- - - - -
You have logged in.
Press here if you are not returned automatically.
-
-
-
+{% set title = 'Login Successful' %} +{% set background = config('darkborder') %} +{% set content %} + + + + +
You have logged in.
Press here if you are not returned automatically.
+{% endset %} +{% include 'tables.headline.html.twig' %} \ No newline at end of file + diff --git a/system/templates/characters.html.twig b/system/templates/characters.html.twig index ec00758e..2e09bd26 100644 --- a/system/templates/characters.html.twig +++ b/system/templates/characters.html.twig @@ -275,7 +275,7 @@ {% for frag in frags %}
{{ frag.time|date("j M Y, H:i") }}{{ frag.description|raw }}({% if frag.unjustified %}Unjustified{% else %}Justified{% endif %}){{ frag.description|raw }} ({% if frag.unjustified %}Unjustified{% else %}Justified{% endif %})
+ + {{ include('buttons.submit.html.twig') }} +
diff --git a/system/templates/forum.boards.html.twig b/system/templates/forum.boards.html.twig index 82da2320..5ac3e88b 100644 --- a/system/templates/forum.boards.html.twig +++ b/system/templates/forum.boards.html.twig @@ -1,24 +1,26 @@ Boards + - {% if canEdit %} - {% endif %} + {% set i = 0 %} {% for board in boards %} {% set i = i + 1 %} diff --git a/system/templates/guilds.change_description.html.twig b/system/templates/guilds.change_description.html.twig index 4576ae0a..9c656920 100644 --- a/system/templates/guilds.change_description.html.twig +++ b/system/templates/guilds.change_description.html.twig @@ -1,14 +1,24 @@ -

Change guild description

-Here you can change description of your guild.
- - {{ csrf() }} - -
- (max. {{ setting('core.guild_description_lines_limit') }} lines, max. {{ setting('core.guild_description_chars_limit') }} chars)
-
-
-
- {{ csrf() }} - {{ include('buttons.back.html.twig') }} - -
+{% set title = 'Change guild description' %} +{% set background = config('darkborder') %} +{% set content %} +
+ Board - - + + Posts - - + + Threads - - + + Last Post - + + Options - +
+ + + +
+ Here you can change description of your guild.
+
+ {{ csrf() }} + +
+ (max. {{ setting('core.guild_description_lines_limit') }} lines, max. {{ setting('core.guild_description_chars_limit') }} chars)

+
+
+
+ {{ csrf() }} + {{ include('buttons.back.html.twig') }} +
+
+
+{% endset %} +{% include 'tables.headline.html.twig' %} diff --git a/system/templates/guilds.change_logo.html.twig b/system/templates/guilds.change_logo.html.twig index 016c13c9..13813e9b 100644 --- a/system/templates/guilds.change_logo.html.twig +++ b/system/templates/guilds.change_logo.html.twig @@ -1,20 +1,32 @@ -

Change guild logo

-Here you can change logo of your guild.
Actuall logo:

-
- {{ csrf() }} - - - Select new logo: - -
-Only jpg, gif, png, bmp pictures. Max. size: {{ setting('core.guild_image_size_kb') }} KB
-
+{% set title = 'Change guild logo' %} +{% set background = config('darkborder') %} +{% set content %} + + + + +
+ Here you can change logo of your guild.
Actuall logo:

+
+ {{ csrf() }} + + + Select new logo: + +
+ Only jpg, gif, png, bmp pictures. Max. size: {{ setting('core.guild_image_size_kb') }} KB
+
+
+{% endset %} +{% include 'tables.headline.html.twig' %} +
{{ csrf() }} {{ include('buttons.back.html.twig') }}
+