diff --git a/admin/includes/settings_menus.php b/admin/includes/settings_menus.php new file mode 100644 index 00000000..2ce784fc --- /dev/null +++ b/admin/includes/settings_menus.php @@ -0,0 +1,35 @@ + 'MyAAC', + 'link' => 'settings&plugin=core', + 'icon' => 'list', + 'order' => $order, +]; + +foreach (Plugins::getAllPluginsSettings() as $setting) { + $file = BASE . $setting['settingsFilename']; + if (!file_exists($file)) { + warning('Plugin setting: ' . $file . ' - cannot be loaded.'); + continue; + } + + $order += 10; + + $settings = require $file; + + $settingsMenu[] = [ + 'name' => $settings['name'], + 'link' => 'settings&plugin=' . $setting['pluginFilename'], + 'icon' => 'list', + 'order' => $order, + ]; +} + +unset($settings, $file, $order); + +return $settingsMenu; diff --git a/admin/index.php b/admin/index.php index 60d96d6a..3974f953 100644 --- a/admin/index.php +++ b/admin/index.php @@ -6,10 +6,6 @@ require '../common.php'; const ADMIN_PANEL = true; const MYAAC_ADMIN = true; -if(file_exists(BASE . 'config.local.php')) { - require_once BASE . 'config.local.php'; -} - if(file_exists(BASE . 'install') && (!isset($config['installed']) || !$config['installed'])) { header('Location: ' . BASE_URL . 'install/'); @@ -34,12 +30,6 @@ if(!$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 this url.'); } -if(config('env') === 'dev') { - ini_set('display_errors', 1); - ini_set('display_startup_errors', 1); - error_reporting(E_ALL); -} - // event system require_once SYSTEM . 'hooks.php'; $hooks = new Hooks(); @@ -47,7 +37,6 @@ $hooks->load(); require SYSTEM . 'status.php'; require SYSTEM . 'login.php'; -require SYSTEM . 'migrate.php'; require __DIR__ . '/includes/functions.php'; $twig->addGlobal('config', $config); diff --git a/admin/pages/accounts.php b/admin/pages/accounts.php index 550ea670..68dd7081 100644 --- a/admin/pages/accounts.php +++ b/admin/pages/accounts.php @@ -37,7 +37,7 @@ if ($config['account_country']) { $countries[$code] = $c; } $web_acc = ACCOUNT_WEB_FLAGS; -$acc_type = config('account_types'); +$acc_type = setting('core.account_types'); ?> @@ -361,7 +361,7 @@ else if (isset($_REQUEST['search'])) {
- getEMail() . '">Send Mail)' : ''); ?> + getEMail() . '">Send Mail)' : ''); ?>
diff --git a/admin/pages/dashboard.php b/admin/pages/dashboard.php index 53380503..e24b98ad 100644 --- a/admin/pages/dashboard.php +++ b/admin/pages/dashboard.php @@ -47,12 +47,11 @@ $tmp = ''; if (fetchDatabaseConfig('site_closed_message', $tmp)) $closed_message = $tmp; -$configAdminPanelModules = config('admin_panel_modules'); -if (isset($configAdminPanelModules)) { +$settingAdminPanelModules = setting('core.admin_panel_modules'); +if (count($settingAdminPanelModules) > 0) { echo '
'; - $configAdminPanelModules = explode(',', $configAdminPanelModules); $twig_loader->prependPath(__DIR__ . '/modules/templates'); - foreach ($configAdminPanelModules as $box) { + foreach ($settingAdminPanelModules as $box) { $file = __DIR__ . '/modules/' . $box . '.php'; if (file_exists($file)) { include($file); diff --git a/admin/pages/mailer.php b/admin/pages/mailer.php index ea45eeb0..7d12f14b 100644 --- a/admin/pages/mailer.php +++ b/admin/pages/mailer.php @@ -15,7 +15,7 @@ if (!hasFlag(FLAG_CONTENT_MAILER) && !superAdmin()) { return; } -if (!config('mail_enabled')) { +if (!setting('core.mail_enabled')) { echo 'Mail support disabled in config.'; return; } diff --git a/admin/pages/pages.php b/admin/pages/pages.php index 7f030e47..e2b7acf5 100644 --- a/admin/pages/pages.php +++ b/admin/pages/pages.php @@ -152,8 +152,8 @@ class Pages $errors[] = 'Enable PHP is wrong.'; return false; } - if ($php == 1 && !getBoolean(config('admin_pages_php_enable'))) { - $errors[] = 'PHP pages disabled on this server. To enable go to config.php and change admin_pages_php_enable to "yes".'; + if ($php == 1 && !getBoolean(setting('core.admin_pages_php_enable'))) { + $errors[] = 'PHP pages disabled on this server. To enable go to Settings in Admin Panel and enable Enable PHP Pages.'; return false; } if(!isset($enable_tinymce) || ($enable_tinymce != 0 && $enable_tinymce != 1)) { diff --git a/admin/pages/plugins.php b/admin/pages/plugins.php index f754edf4..be9df2b0 100644 --- a/admin/pages/plugins.php +++ b/admin/pages/plugins.php @@ -13,8 +13,8 @@ $use_datatable = true; require_once LIBS . 'plugins.php'; -if (!getBoolean(config('admin_plugins_manage_enable'))) { - warning('Plugin installation and management is disabled in config.
If you wish to enable, go to config.php and change admin_plugins_manage_enable to "yes".'); +if (!getBoolean(setting('core.admin_plugins_manage_enable'))) { + warning('Plugin installation and management is disabled in Settings.
If you wish to enable, go to Settings and enable Enable Plugins Manage.'); } else { $twig->display('admin.plugins.form.html.twig'); diff --git a/admin/pages/settings.php b/admin/pages/settings.php new file mode 100644 index 00000000..5b354c99 --- /dev/null +++ b/admin/pages/settings.php @@ -0,0 +1,56 @@ + + * @copyright 2019 MyAAC + * @link https://my-aac.org + */ +defined('MYAAC') or die('Direct access not allowed!'); +$title = 'Settings'; + +require_once SYSTEM . 'clients.conf.php'; +if (empty($_GET['plugin'])) { + error('Please select plugin from left Panel.'); + return; +} + +$plugin = $_GET['plugin']; + +if($plugin != 'core') { + $pluginSettings = Plugins::getPluginSettings($plugin); + if (!$pluginSettings) { + error('This plugin does not exist or does not have settings defined.'); + return; + } + + $settingsFilePath = BASE . $pluginSettings; +} +else { + $settingsFilePath = SYSTEM . 'settings.php'; +} + +if (!file_exists($settingsFilePath)) { + error("Plugin $plugin does not exist or does not have settings defined."); + return; +} + +$settingsFile = require $settingsFilePath; +if (!is_array($settingsFile)) { + error("Cannot load settings file for plugin $plugin"); + return; +} + +$settingsKeyName = ($plugin == 'core' ? $plugin : $settingsFile['key']); + +$title = ($plugin == 'core' ? 'Settings' : 'Plugin Settings - ' . $plugin); + +$settingsParsed = Settings::display($settingsKeyName, $settingsFile['settings']); + +$twig->display('admin.settings.html.twig', [ + 'settingsParsed' => $settingsParsed['content'], + 'settings' => $settingsFile['settings'], + 'script' => $settingsParsed['script'], + 'settingsKeyName' => $settingsKeyName, +]); diff --git a/admin/pages/visitors.php b/admin/pages/visitors.php index 77626eb0..8ab78521 100644 --- a/admin/pages/visitors.php +++ b/admin/pages/visitors.php @@ -16,7 +16,7 @@ use DeviceDetector\Parser\OperatingSystem; $title = 'Visitors'; $use_datatable = true; -if (!$config['visitors_counter']): ?> +if (!setting('core.visitors_counter')): ?> Visitors counter is disabled.
You can enable it by editing this configurable in config.local.php file:

$config['visitors_counter'] = true;

@@ -25,10 +25,9 @@ if (!$config['visitors_counter']): ?> endif; require SYSTEM . 'libs/visitors.php'; -$visitors = new Visitors($config['visitors_counter_ttl']); +$visitors = new Visitors(setting('core.visitors_counter_ttl')); -function compare($a, $b) -{ +function compare($a, $b): int { return $a['lastvisit'] > $b['lastvisit'] ? -1 : 1; } @@ -61,7 +60,7 @@ foreach ($tmp as &$visitor) { } $twig->display('admin.visitors.html.twig', array( - 'config_visitors_counter_ttl' => $config['visitors_counter_ttl'], + 'config_visitors_counter_ttl' => setting('core.visitors_counter_ttl'), 'visitors' => $tmp )); ?> diff --git a/admin/template/menus.php b/admin/template/menus.php index 460c03dd..ff67a21e 100644 --- a/admin/template/menus.php +++ b/admin/template/menus.php @@ -1,8 +1,11 @@ 'Dashboard', 'icon' => 'tachometer-alt', 'order' => 10, 'link' => 'dashboard'], - ['name' => 'News', 'icon' => 'newspaper', 'order' => 20, 'link' => + ['name' => 'Settings', 'icon' => 'edit', 'order' => 19, 'link' => + require ADMIN . 'includes/settings_menus.php' + ], + ['name' => 'News', 'icon' => 'newspaper', 'order' => 20, 'link' => [ ['name' => 'View', 'link' => 'news', 'icon' => 'list', 'order' => 10], ['name' => 'Add news', 'link' => 'news&action=new&type=1', 'icon' => 'plus', 'order' => 20], @@ -16,7 +19,7 @@ $menus = [ ['name' => 'Add', 'link' => 'changelog&action=new', 'icon' => 'plus', 'order' => 20], ], ], - ['name' => 'Mailer', 'icon' => 'envelope', 'order' => 40, 'link' => 'mailer', 'disabled' => !config('mail_enabled')], + ['name' => 'Mailer', 'icon' => 'envelope', 'order' => 40, 'link' => 'mailer', 'disabled' => !setting('core.mail_enabled')], ['name' => 'Pages', 'icon' => 'book', 'order' => 50, 'link' => [ ['name' => 'View', 'link' => 'pages', 'icon' => 'list', 'order' => 10], diff --git a/admin/tools/settings_save.php b/admin/tools/settings_save.php new file mode 100644 index 00000000..83be1de3 --- /dev/null +++ b/admin/tools/settings_save.php @@ -0,0 +1,34 @@ +save($_REQUEST['plugin'], $_POST['settings']); + +$errors = $settings->getErrors(); +if (count($errors) > 0) { + http_response_code(500); + die(implode('
', $errors)); +} + +echo 'Saved at ' . date('H:i'); diff --git a/common.php b/common.php index 0c56f0ac..c1a89bbd 100644 --- a/common.php +++ b/common.php @@ -27,7 +27,7 @@ if (version_compare(phpversion(), '7.2.5', '<')) die('PHP version 7.2.5 or highe const MYAAC = true; const MYAAC_VERSION = '0.10.0-dev'; -const DATABASE_VERSION = 35; +const DATABASE_VERSION = 36; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX')); @@ -143,6 +143,22 @@ if(!IS_CLI) { //define('CURRENT_URL', BASE_URL . $_SERVER['REQUEST_URI']); } +if (file_exists(BASE . 'config.local.php')) { + require BASE . 'config.local.php'; +} + +ini_set('log_errors', 1); +if(@$config['env'] === 'dev') { + ini_set('display_errors', 1); + ini_set('display_startup_errors', 1); + error_reporting(E_ALL); +} +else { + ini_set('display_errors', 0); + ini_set('display_startup_errors', 0); + error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT); +} + $autoloadFile = VENDOR . 'autoload.php'; if (!is_file($autoloadFile)) { throw new RuntimeException('The vendor folder is missing. Please download Composer: https://getcomposer.org/download, install it and execute in the main MyAAC directory this command: composer install. Or download MyAAC from GitHub releases, which includes Vendor folder.'); diff --git a/config.php b/config.php deleted file mode 100644 index 49e8f128..00000000 --- a/config.php +++ /dev/null @@ -1,326 +0,0 @@ - - * @copyright 2019 MyAAC - * @link https://my-aac.org - */ - -$config = array( - // directories & files - 'server_path' => '', // path to the server directory (same directory where config file is located) - - /** - * Environment Setting - * - * if you use this script on your live server - set to 'prod' (production) - * if you want to test and debug the script locally, or develop plugins, set to 'dev' (development) - * WARNING: on 'dev' cache is disabled, so site will be significantly slower !!! - * WARNING2: on 'dev' all PHP errors/warnings are displayed - * Recommended: 'prod' cause of speed (page load time is better) - */ - 'env' => 'prod', // 'prod' for production and 'dev' for development - - 'template' => 'kathrine', // template used by website (kathrine, tibiacom) - 'template_allow_change' => true, // allow users to choose their own template while browsing website? - - 'vocations_amount' => 4, // how much basic vocations your server got (without promotion) - - // what client version are you using on this OT? - // used for the Downloads page and some templates aswell - 'client' => 1098, // 954 = client 9.54 - - 'session_prefix' => 'myaac_', // must be unique for every site on your server - 'friendly_urls' => false, // mod_rewrite is required for this, it makes links looks more elegant to eye, and also are SEO friendly (example: https://my-aac.org/guilds/Testing instead of https://my-aac.org/?subtopic=guilds&name=Testing). Remember to rename .htaccess.dist to .htaccess - 'gzip_output' => false, // gzip page content before sending it to the browser, uses less bandwidth but more cpu cycles - - // gesior backward support (templates & pages) - // allows using gesior templates and pages with myaac - // might bring some performance when disabled - 'backward_support' => true, - - // head options (html) - 'meta_description' => 'Tibia is a free massive multiplayer online role playing game (MMORPG).', // description of the site - 'meta_keywords' => 'free online game, free multiplayer game, ots, open tibia server', // keywords list separated by commas - - // footer - 'footer' => ''/*'
Your Server © 2016. All rights reserved.'*/, - - 'language' => 'en', // default language (currently only 'en' available) - 'language_allow_change' => false, - - 'visitors_counter' => true, - 'visitors_counter_ttl' => 10, // how long visitor will be marked as online (in minutes) - 'views_counter' => true, - - // cache system. by default file cache is used - 'cache_engine' => 'auto', // apc, apcu, eaccelerator, xcache, file, auto, or blank to disable. - 'cache_prefix' => 'myaac_', // have to be unique if running more MyAAC instances on the same server (except file system cache) - - // database details (leave blank for auto detect from config.lua) - 'database_host' => '', - 'database_port' => '', // leave blank to default 3306 - 'database_user' => '', - 'database_password' => '', - 'database_name' => '', - 'database_log' => false, // should database queries be logged and saved into system/logs/database.log? - 'database_socket' => '', // set if you want to connect to database through socket (example: /var/run/mysqld/mysqld.sock) - 'database_persistent' => false, // use database permanent connection (like server), may speed up your site - - // multiworld system (only TFS 0.3) - 'multiworld' => false, // use multiworld system? - 'worlds' => array( // list of worlds - //'1' => 'Your World Name', - //'2' => 'Your Second World Name' - ), - - // images - 'outfit_images_url' => 'https://outfit-images.ots.me/outfit.php', // set to animoutfit.php for animated outfit - 'outfit_images_wrong_looktypes' => [75, 126, 127, 266, 302], // this looktypes needs to have different margin-top and margin-left because they are wrong positioned - 'item_images_url' => 'https://item-images.ots.me/1092/', // set to images/items if you host your own items in images folder - 'item_images_extension' => '.gif', - - // creatures - 'creatures_images_url' => 'images/monsters/', // set to images/monsters if you host your own creatures in images folder - 'creatures_images_extension' => '.gif', - 'creatures_images_preview' => false, // set to true to allow picture previews for creatures - 'creatures_items_url' => 'https://tibia.fandom.com/wiki/', // set to website which shows details about items. - 'creatures_loot_percentage' => true, // set to true to show the loot tooltip percent - - // account - 'account_management' => true, // disable if you're using other method to manage users (fe. tfs account manager) - 'account_login_by_email' => false, // use email instead of Account Name like in latest Tibia - 'account_login_by_email_fallback' => false, // allow also additionally login by Account Name/Number (for users that might forget their email) - 'account_create_auto_login' => false, // auto login after creating account? - 'account_create_character_create' => true, // allow directly to create character on create account page? - 'account_mail_verify' => false, // force users to confirm their email addresses when registering - 'account_mail_confirmed_reward' => [ // reward users for confirming their E-Mails - // account_mail_verify needs to be enabled too - 'premium_days' => 0, - 'premium_points' => 0, - 'coins' => 0, - 'message' => 'You received %d %s for confirming your E-Mail address.' // example: You received 20 premium points for confirming your E-Mail address. - ], - 'account_mail_unique' => true, // email addresses cannot be duplicated? (one account = one email) - 'account_mail_block_plus_sign' => true, // block email with '+' signs like test+box@gmail.com (help protect against spamming accounts) - 'account_premium_days' => 0, // default premium days on new account - 'account_premium_points' => 0, // default premium points on new account - 'account_welcome_mail' => true, // send welcome email when user registers - 'account_mail_change' => 2, // how many days user need to change email to account - block hackers - 'account_country' => true, // user will be able to set country of origin when registering account, this information will be viewable in others places aswell - 'account_country_recognize' => true, // should country of user be automatically recognized by his IP? This makes an external API call to http://ipinfo.io - 'account_change_character_name' => false, // can user change their character name for premium points? - 'account_change_character_name_points' => 30, // cost of name change - 'account_change_character_sex' => false, // can user change their character sex for premium points? - 'account_change_character_sex_points' => 30, // cost of sex change - 'characters_per_account' => 10, // max. number of characters per account - - // mail - 'mail_enabled' => false, // is aac maker configured to send e-mails? - 'mail_address' => 'no-reply@your-server.org', // server e-mail address (from:) - 'mail_admin' => 'your-address@your-server.org', // admin email address, where mails from contact form will be sent - 'mail_signature' => array( // signature that will be included at the end of every message sent using _mail function - 'plain' => ""/*"--\nMy Server,\nhttp://www.myserver.com"*/, - 'html' => ''/*'
My Server,\nmyserver.com'*/ - ), - 'smtp_enabled' => false, // send by smtp or mail function (set false if use mail function, set to true if you use GMail or Microsoft Outlook) - 'smtp_host' => '', // mail host. smtp.gmail.com for GMail / smtp-mail.outlook.com for Microsoft Outlook - 'smtp_port' => 25, // 25 (default) / 465 (ssl, GMail) / 587 (tls, Microsoft Outlook) - 'smtp_auth' => true, // need authorization? - 'smtp_user' => 'admin@example.org', // here your email username - 'smtp_pass' => '', - 'smtp_secure' => '', // What kind of encryption to use on the SMTP connection. Options: '', 'ssl' (GMail) or 'tls' (Microsoft Outlook) - 'smtp_debug' => false, // set true to debug (you will see more info in error.log) - - // - 'generate_new_reckey' => true, // let player generate new recovery key, he will receive e-mail with new rec key (not display on page, hacker can't generate rec key) - 'generate_new_reckey_price' => 20, // price for new recovery key - 'send_mail_when_change_password' => true, // send e-mail with new password when change password to account - 'send_mail_when_generate_reckey' => true, // send e-mail with rec key (key is displayed on page anyway when generate) - - // you may need to adjust this for older tfs versions - // by removing Community Manager - 'account_types' => [ - 'None', - 'Normal', - 'Tutor', - 'Senior Tutor', - 'Gamemaster', - 'Community Manager', - 'God', - ], - - // genders (aka sex) - 'genders' => array( - 0 => 'Female', - 1 => 'Male' - ), - - // new character config - 'character_samples' => array( // vocations, format: ID_of_vocation => 'Name of Character to copy' - //0 => 'Rook Sample', - 1 => 'Sorcerer Sample', - 2 => 'Druid Sample', - 3 => 'Paladin Sample', - 4 => 'Knight Sample' - ), - - 'use_character_sample_skills' => false, - - // it must show limited number of players after using search in character page - 'characters_search_limit' => 15, - - // town list used when creating character - // won't be displayed if there is only one item (rookgaard for example) - 'character_towns' => array(1), - - // characters length - // This is the minimum and the maximum length that a player can create a character. It is highly recommend the maximum length to be 21. - 'character_name_min_length' => 4, - 'character_name_max_length' => 21, - 'character_name_npc_check' => true, - - // list of towns - // if you use TFS 1.3 with support for 'towns' table in database, then you can ignore this - it will be configured automatically (from MySQL database - Table - towns) - // otherwise it will try to load from your .OTBM map file - // if you don't see towns on website, then you need to fill this out - 'towns' => array( - 0 => 'No town', - 1 => 'Sample town' - ), - - // guilds - 'guild_management' => true, // enable guild management system on the site? - 'guild_need_level' => 1, // min. level to form a guild - 'guild_need_premium' => true, // require premium account to form a guild? - 'guild_image_size_kb' => 80, // maximum size of the guild logo image in KB (kilobytes) - 'guild_description_default' => 'New guild. Leader must edit this text :)', - 'guild_description_chars_limit' => 1000, // limit of guild description - 'guild_description_lines_limit' => 6, // limit of lines, if description has more lines it will be showed as long text, without 'enters' - 'guild_motd_chars_limit' => 150, // limit of MOTD (message of the day) that is shown later in the game on the guild channel - - // online page - 'online_record' => true, // display players record? - 'online_vocations' => false, // display vocation statistics? - 'online_vocations_images' => false, // display vocation images? - 'online_skulls' => false, // display skull images - 'online_outfit' => true, - 'online_afk' => false, - - // support list page - 'team_style' => 2, // 1/2 (1 - normal table, 2 - in boxes, grouped by group id) - 'team_display_status' => true, - 'team_display_lastlogin' => true, - 'team_display_world' => false, - 'team_display_outfit' => true, - - // bans page - 'bans_per_page' => 20, - - // highscores page - 'highscores_vocation_box' => true, // show 'Choose a vocation' box on the highscores (allowing peoples to sort highscores by vocation)? - 'highscores_vocation' => true, // show player vocation under his nickname? - 'highscores_frags' => false, // show 'Frags' tab (best fraggers on the server)? - 'highscores_balance' => false, // show 'Balance' tab (richest players on the server) - 'highscores_outfit' => true, // show player outfit? - 'highscores_country_box' => false, // doesnt work yet! (not implemented) - 'highscores_groups_hidden' => 3, // this group id and higher won't be shown on the highscores - 'highscores_ids_hidden' => array(0), // this ids of players will be hidden on the highscores (should be ids of samples) - 'highscores_per_page' => 100, // how many records per page on highscores - 'highscores_cache_ttl' => 15, // how often to update highscores from database in minutes (default 15 minutes) - - // characters page - 'characters' => array( // what things to display on character view page (true/false in each option) - 'level' => true, - 'experience' => false, - 'magic_level' => false, - 'balance' => false, - 'marriage_info' => true, // only 0.3 - 'outfit' => true, - 'creation_date' => true, - 'quests' => true, - 'skills' => true, - 'equipment' => true, - 'frags' => false, - 'deleted' => false, // should deleted characters from same account be still listed on the list of characters? When enabled it will show that character is "[DELETED]" - ), - 'quests' => array( - //'Some Quest' => 123, - //'Some Quest Two' => 456, - ), // quests list (displayed in character view), name => storage - 'signature_enabled' => true, - 'signature_type' => 'tibian', // signature engine to use: tibian, mango, gesior - 'signature_cache_time' => 5, // how long to store cached file (in minutes), default 5 minutes - 'signature_browser_cache' => 60, // how long to cache by browser (in minutes), default 1 hour - - // news page - 'news_limit' => 5, // limit of news on the latest news page - 'news_ticker_limit' => 5, // limit of news in tickers (mini news) (0 to disable) - 'news_date_format' => 'j.n.Y', // check php manual date() function for more info about this - 'news_author' => true, // show author of the news - - // gifts/shop system - 'gifts_system' => false, - - // support/system - 'bug_report' => true, // this configurable has no effect, its always enabled - - // forum - 'forum' => 'site', // link to the server forum, set to "site" if you want to use build in forum system, otherwise leave empty if you aren't going to use any forum - 'forum_level_required' => 0, // level required to post, 0 to disable - 'forum_post_interval' => 30, // in seconds - 'forum_posts_per_page' => 20, - 'forum_threads_per_page' => 20, - // uncomment to force use table for forum - //'forum_table_prefix' => 'z_', // what forum mysql table to use, z_ (for gesior old forum) or myaac_ (for myaac) - - // last kills - 'last_kills_limit' => 50, // max. number of deaths shown on the last kills page - - // status, took automatically from config file if empty - 'status_enabled' => true, // you can disable status checking by settings this to "false" - 'status_ip' => '', - 'status_port' => '', - 'status_timeout' => 2.0, // how long to wait for the initial response from the server (default: 2 seconds) - - // how often to connect to server and update status (default: every minute) - // if your status timeout in config.lua is bigger, that it will be used instead - // when server is offline, it will be checked every time web refreshes, ignoring this variable - 'status_interval' => 60, - - // admin panel - 'admin_plugins_manage_enable' => 'yes', // you can disable possibility to upload and uninstall plugins, for security - // enable support for plain php pages in admin panel, for security - // existing pages still will be working, so you need to delete them manually - 'admin_pages_php_enable' => 'no', - 'admin_panel_modules' => 'statistics,web_status,server_status,lastlogin,created,points,coins,balance', // default - statistics,web_status,server_status,lastlogin,created,points,coins,balance - - // other - 'anonymous_usage_statistics' => true, - 'email_lai_sec_interval' => 60, // time in seconds between e-mails to one account from lost account interface, block spam - 'google_analytics_id' => '', // e.g.: UA-XXXXXXX-X - 'experiencetable_columns' => 3, // how many columns to display in experience table page. * experiencetable_rows, 5 = 500 (will show up to 500 level) - 'experiencetable_rows' => 200, // till how many levels in one column - 'date_timezone' => 'Europe/Berlin', // more info at http://php.net/manual/en/timezones.php - 'footer_show_load_time' => true, // display load time of the page in the footer - - 'npc' => array(), - - // character name blocked - 'character_name_blocked' => array( - 'prefix' => array(), - 'names' => array(), - 'words' => array(), - ), - -); diff --git a/index.php b/index.php index a093b9bd..5ead45b9 100644 --- a/index.php +++ b/index.php @@ -56,22 +56,6 @@ if(preg_match("/^(.*)\.(gif|jpg|png|jpeg|tiff|bmp|css|js|less|map|html|zip|rar|g exit; } -if(file_exists(BASE . 'config.local.php')) { - require_once BASE . 'config.local.php'; -} - -ini_set('log_errors', 1); -if(config('env') === 'dev') { - ini_set('display_errors', 1); - ini_set('display_startup_errors', 1); - error_reporting(E_ALL); -} -else { - ini_set('display_errors', 0); - ini_set('display_startup_errors', 0); - error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT); -} - if((!isset($config['installed']) || !$config['installed']) && file_exists(BASE . 'install')) { header('Location: ' . BASE_URL . 'install/'); @@ -100,13 +84,11 @@ $twig->addGlobal('status', $status); require_once SYSTEM . 'router.php'; -require SYSTEM . 'migrate.php'; - $hooks->trigger(HOOK_STARTUP); // anonymous usage statistics // sent only when user agrees -if(isset($config['anonymous_usage_statistics']) && $config['anonymous_usage_statistics']) { +if(setting('core.anonymous_usage_statistics')) { $report_time = 30 * 24 * 60 * 60; // report one time per 30 days $should_report = true; @@ -139,17 +121,16 @@ if(isset($config['anonymous_usage_statistics']) && $config['anonymous_usage_stat } } -if($config['views_counter']) +if(setting('core.views_counter')) require_once SYSTEM . 'counter.php'; -if($config['visitors_counter']) -{ +if(setting('core.visitors_counter')) { require_once SYSTEM . 'libs/visitors.php'; - $visitors = new Visitors($config['visitors_counter_ttl']); + $visitors = new Visitors(setting('core.visitors_counter_ttl')); } // backward support for gesior -if($config['backward_support']) { +if(setting('core.backward_support')) { define('INITIALIZED', true); $SQL = $db; $layout_header = template_header(); @@ -165,7 +146,7 @@ if($config['backward_support']) { $config['site'] = &$config; $config['server'] = &$config['lua']; - $config['site']['shop_system'] = $config['gifts_system']; + $config['site']['shop_system'] = setting('core.gifts_system'); $config['site']['gallery_page'] = true; if(!isset($config['vdarkborder'])) @@ -179,8 +160,9 @@ if($config['backward_support']) { $config['site']['serverinfo_page'] = true; $config['site']['screenshot_page'] = true; - if($config['forum'] != '') - $config['forum_link'] = (strtolower($config['forum']) === 'site' ? getLink('forum') : $config['forum']); + $forumSetting = setting('core.forum'); + if($forumSetting != '') + $config['forum_link'] = (strtolower($forumSetting) === 'site' ? getLink('forum') : $forumSetting); foreach($status as $key => $value) $config['status']['serverStatus_' . $key] = $value; diff --git a/install/includes/schema.sql b/install/includes/schema.sql index 83f4c051..21776dc8 100644 --- a/install/includes/schema.sql +++ b/install/includes/schema.sql @@ -1,4 +1,4 @@ -SET @myaac_database_version = 35; +SET @myaac_database_version = 36; CREATE TABLE `myaac_account_actions` ( @@ -303,6 +303,16 @@ CREATE TABLE `myaac_gallery` INSERT INTO `myaac_gallery` (`id`, `ordering`, `comment`, `image`, `thumb`, `author`) VALUES (NULL, 1, 'Demon', 'images/gallery/demon.jpg', 'images/gallery/demon_thumb.gif', 'MyAAC'); +CREATE TABLE `myaac_settings` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` VARCHAR(255) NOT NULL DEFAULT '', + `key` VARCHAR(255) NOT NULL DEFAULT '', + `value` TEXT NOT NULL, + PRIMARY KEY (`id`), + KEY `key` (`key`) +) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8; + CREATE TABLE `myaac_spells` ( `id` INT(11) NOT NULL AUTO_INCREMENT, diff --git a/install/index.php b/install/index.php index 021bd184..22440101 100644 --- a/install/index.php +++ b/install/index.php @@ -12,9 +12,7 @@ require SYSTEM . 'functions.php'; require BASE . 'install/includes/functions.php'; require BASE . 'install/includes/locale.php'; require SYSTEM . 'clients.conf.php'; - -if(file_exists(BASE . 'config.local.php')) - require BASE . 'config.local.php'; +require LIBS . 'settings.php'; // ignore undefined index from Twig autoloader $config['env'] = 'prod'; @@ -91,10 +89,6 @@ if($step == 'database') { break; } } - else if($key == 'mail_admin' && !Validator::email($value)) { - $errors[] = $locale['step_config_mail_admin_error']; - break; - } else if($key == 'timezone' && !in_array($value, DateTimeZone::listIdentifiers())) { $errors[] = $locale['step_config_timezone_error']; break; diff --git a/install/steps/5-database.php b/install/steps/5-database.php index a133f236..5ebe18d9 100644 --- a/install/steps/5-database.php +++ b/install/steps/5-database.php @@ -11,16 +11,12 @@ if(!isset($_SESSION['var_server_path'])) { } if(!$error) { - $content = " 'prod', + ]; + foreach($_SESSION as $key => $value) { if(strpos($key, 'var_') !== false) @@ -32,17 +28,14 @@ if(!$error) { $value .= '/'; } - if($key === 'var_usage') { - $content .= '$config[\'anonymous_usage_statistics\'] = ' . ((int)$value == 1 ? 'true' : 'false') . ';'; - $content .= PHP_EOL; - } - else if(!in_array($key, array('var_account', 'var_account_id', 'var_password', 'var_step', 'var_email', 'var_player_name'), true)) { - $content .= '$config[\'' . str_replace('var_', '', $key) . '\'] = \'' . $value . '\';'; - $content .= PHP_EOL; + if(!in_array($key, ['var_usage', 'var_date_timezone', 'var_client', 'var_account', 'var_account_id', 'var_password', 'var_password_confirm', 'var_step', 'var_email', 'var_player_name'], true)) { + $configToSave[str_replace('var_', '', $key)] = $value; } } } + $configToSave['cache_prefix'] = 'myaac_' . generateRandomString(8, true, false, true); + require BASE . 'install/includes/config.php'; if(!$error) { @@ -79,31 +72,17 @@ if(!$error) { 'message' => $locale['loading_spinner'] )); - if(!Validator::email($_SESSION['var_mail_admin'])) { - error($locale['step_config_mail_admin_error']); - $error = true; - } - - $content .= '$config[\'session_prefix\'] = \'myaac_' . generateRandomString(8, true, false, true, false) . '_\';'; - $content .= PHP_EOL; - $content .= '$config[\'cache_prefix\'] = \'myaac_' . generateRandomString(8, true, false, true, false) . '_\';'; - - $saved = true; - if(!$error) { - $saved = file_put_contents(BASE . 'config.local.php', $content); - } - + $content = ''; + $saved = Settings::saveConfig($configToSave, BASE . 'config.local.php', $content); if($saved) { success($locale['step_database_config_saved']); - if(!$error) { - $_SESSION['saved'] = true; - } + $_SESSION['saved'] = true; } 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']); + $locale['step_database_error_file'] = str_replace('$FILE$', '' . BASE . 'config.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 f6e1f6c2..7ab77185 100644 --- a/install/steps/7-finish.php +++ b/install/steps/7-finish.php @@ -116,6 +116,23 @@ else { } } + $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'] diff --git a/install/tools/7-finish.php b/install/tools/7-finish.php index 3d98b570..22772714 100644 --- a/install/tools/7-finish.php +++ b/install/tools/7-finish.php @@ -11,11 +11,11 @@ ini_set('max_execution_time', 300); ob_implicit_flush(); ob_end_flush(); header('X-Accel-Buffering: no'); - +/* if(isset($config['installed']) && $config['installed'] && !isset($_SESSION['saved'])) { warning($locale['already_installed']); return; -} +}*/ require SYSTEM . 'init.php'; @@ -51,13 +51,6 @@ DataLoader::load(); // update config.highscores_ids_hidden require_once SYSTEM . 'migrations/20.php'; -$database_migration_20 = true; -$content = ''; -if(!databaseMigration20($content)) { - $locale['step_database_error_file'] = str_replace('$FILE$', '' . BASE . 'config.local.php', $locale['step_database_error_file']); - warning($locale['step_database_error_file'] . '
- '); -} // add z_polls tables require_once SYSTEM . 'migrations/22.php'; diff --git a/login.php b/login.php index 3ab0b5e9..6fb43f38 100644 --- a/login.php +++ b/login.php @@ -1,7 +1,5 @@ 'database_hash', + //'language', + 'visitors_counter', + 'visitors_counter_ttl', + 'views_counter', + 'outfit_images_url', + 'outfit_images_wrong_looktypes', + 'item_images_url', + 'account_country', + 'towns', + 'quests', + 'character_samples', + 'character_towns', + 'characters_per_account', + 'characters_search_limit', + 'news_author', + 'news_limit', + 'news_ticker_limit', + 'news_date_format', + 'highscores_groups_hidden', + 'highscores_ids_hidden', + 'online_record', + 'online_vocations', + 'online_vocations_images', + 'online_skulls', + 'online_outfit', + 'online_afk', + 'team_display_outfit' => 'team_outfit', + 'team_display_status' => 'team_status', + 'team_display_world' => 'team_world', + 'team_display_lastlogin' => 'team_lastlogin', + 'last_kills_limit', + 'multiworld', + 'forum', + 'signature_enabled', + 'signature_type', + 'signature_cache_time', + 'signature_browser_cache', + 'gifts_system', + 'status_enabled', + 'status_ip', + 'status_port', + 'mail_enabled', + 'account_login_by_email', + 'account_login_by_email_fallback', + 'account_mail_verify', + 'account_create_character_create', + 'account_change_character_name', + 'account_change_character_name_points' => 'account_change_character_name_price', + 'account_change_character_sex', + 'account_change_character_sex_points' => 'account_change_character_name_price', +]; + +foreach ($deprecatedConfig as $key => $value) { + config( + [ + (is_string($key) ? $key : $value), + setting('core.'.$value) + ] + ); + + //var_dump($settings['core.'.$value]['value']); +} + +$deprecatedConfigCharacters = [ + 'level', + 'experience', + 'magic_level', + 'balance', + 'marriage_info' => 'marriage', + 'outfit', + 'creation_date', + 'quests', + 'skills', + 'equipment', + 'frags', + 'deleted', +]; + +$tmp = []; +foreach ($deprecatedConfigCharacters as $key => $value) { + $tmp[(is_string($key) ? $key : $value)] = setting('core.characters_'.$value); +} + +config(['characters', $tmp]); +unset($tmp); diff --git a/system/database.php b/system/database.php index 41be6c87..e50e8568 100644 --- a/system/database.php +++ b/system/database.php @@ -9,7 +9,11 @@ */ defined('MYAAC') or die('Direct access not allowed!'); -if(!isset($config['database_user'][0], $config['database_password'][0], $config['database_name'][0])) +if (!isset($config['database_overwrite'])) { + $config['database_overwrite'] = false; +} + +if(!$config['database_overwrite'] && !isset($config['database_user'][0], $config['database_password'][0], $config['database_name'][0])) { if(isset($config['lua']['sqlType'])) {// tfs 0.3 if(isset($config['lua']['mysqlHost'])) {// tfs 0.2 @@ -116,4 +120,4 @@ catch(PDOException $error) { '
  • MySQL is not configured propertly in config.lua.
  • ' . '
  • MySQL server is not running.
  • ' . '' . $error->getMessage()); -} \ No newline at end of file +} diff --git a/system/functions.php b/system/functions.php index feb24360..11803c69 100644 --- a/system/functions.php +++ b/system/functions.php @@ -32,55 +32,49 @@ function message($message, $type, $return) return true; } function success($message, $return = false) { - return message($message, 'success', $return); + return message($message, 'success', $return); } function warning($message, $return = false) { - return message($message, 'warning', $return); + return message($message, 'warning', $return); } function note($message, $return = false) { - return message($message, 'note', $return); + return message($message, 'note', $return); } function error($message, $return = false) { - return message($message, ((defined('MYAAC_INSTALL') || defined('MYAAC_ADMIN')) ? 'danger' : 'error'), $return); + return message($message, ((defined('MYAAC_INSTALL') || defined('MYAAC_ADMIN')) ? 'danger' : 'error'), $return); } -function longToIp($ip) +function longToIp($ip): string { $exp = explode(".", long2ip($ip)); return $exp[3].".".$exp[2].".".$exp[1].".".$exp[0]; } -function generateLink($url, $name, $blank = false) { +function generateLink($url, $name, $blank = false): string { return '' . $name . ''; } -function getFullLink($page, $name, $blank = false) { +function getFullLink($page, $name, $blank = false): string { return generateLink(getLink($page), $name, $blank); } -function getLink($page, $action = null) -{ - global $config; - return BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . $page . ($action ? '/' . $action : ''); +function getLink($page, $action = null): string { + return BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . $page . ($action ? '/' . $action : ''); } -function internalLayoutLink($page, $action = null) {return getLink($page, $action);} - -function getForumThreadLink($thread_id, $page = NULL) -{ - global $config; - return BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . 'forum/thread/' . (int)$thread_id . (isset($page) ? '/' . $page : ''); +function internalLayoutLink($page, $action = null): string { + return getLink($page, $action); } -function getForumBoardLink($board_id, $page = NULL) -{ - global $config; - return BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . 'forum/board/' . (int)$board_id . (isset($page) ? '/' . $page : ''); +function getForumThreadLink($thread_id, $page = NULL): string { + return BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'forum/thread/' . (int)$thread_id . (isset($page) ? '/' . $page : ''); } -function getPlayerLink($name, $generate = true) -{ - global $config; +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 +{ if(is_numeric($name)) { $player = new OTS_Player(); @@ -89,25 +83,23 @@ function getPlayerLink($name, $generate = true) $name = $player->getName(); } - $url = BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . 'characters/' . urlencode($name); + $url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'characters/' . urlencode($name); if(!$generate) return $url; return generateLink($url, $name); } -function getMonsterLink($name, $generate = true) +function getMonsterLink($name, $generate = true): string { - global $config; - - $url = BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . 'creatures/' . urlencode($name); + $url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'creatures/' . urlencode($name); if(!$generate) return $url; return generateLink($url, $name); } -function getHouseLink($name, $generate = true) +function getHouseLink($name, $generate = true): string { - global $db, $config; + global $db; if(is_numeric($name)) { @@ -117,16 +109,14 @@ function getHouseLink($name, $generate = true) $name = $house->fetchColumn(); } - $url = BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . 'houses/' . urlencode($name); + $url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'houses/' . urlencode($name); if(!$generate) return $url; return generateLink($url, $name); } -function getGuildLink($name, $generate = true) +function getGuildLink($name, $generate = true): string { - global $config; - if(is_numeric($name)) { $name = getGuildNameById($name); if ($name === false) { @@ -134,7 +124,7 @@ function getGuildLink($name, $generate = true) } } - $url = BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . 'guilds/' . urlencode($name); + $url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'guilds/' . urlencode($name); if(!$generate) return $url; return generateLink($url, $name); @@ -180,7 +170,7 @@ function getItemRarity($chance) { return ''; } -function getFlagImage($country) +function getFlagImage($country): string { if(!isset($country[0])) return ''; @@ -202,7 +192,7 @@ function getFlagImage($country) * @param mixed $v Variable to check. * @return bool Value boolean status. */ -function getBoolean($v) +function getBoolean($v): bool { if(is_bool($v)) { return $v; @@ -225,7 +215,7 @@ function getBoolean($v) * @param bool $special Should special characters by used? * @return string Generated string. */ -function generateRandomString($length, $lowCase = true, $upCase = false, $numeric = false, $special = false) +function generateRandomString($length, $lowCase = true, $upCase = false, $numeric = false, $special = false): string { $characters = ''; if($lowCase) @@ -465,7 +455,7 @@ function tickers() * Types: head_start, head_end, body_start, body_end, center_top * */ -function template_place_holder($type) +function template_place_holder($type): string { global $twig, $template_place_holders; $ret = ''; @@ -489,7 +479,7 @@ function template_place_holder($type) /** * Returns content to be used by templates. */ -function template_header($is_admin = false) +function template_header($is_admin = false): string { global $title_full, $config, $twig; $charset = isset($config['charset']) ? $config['charset'] : 'utf-8'; @@ -506,29 +496,32 @@ function template_header($is_admin = false) /** * Returns footer content to be used by templates. */ -function template_footer() +function template_footer(): string { - global $config, $views_counter; + global $views_counter; $ret = ''; - if(admin()) + if(admin()) { $ret .= generateLink(ADMIN_URL, 'Admin Panel', true); + } - if($config['visitors_counter']) - { + if(setting('core.visitors_counter')) { global $visitors; $amount = $visitors->getAmountVisitors(); $ret .= '
    Currently there ' . ($amount > 1 ? 'are' : 'is') . ' ' . $amount . ' visitor' . ($amount > 1 ? 's' : '') . '.'; } - if($config['views_counter']) + if(setting('core.views_counter')) { $ret .= '
    Page has been viewed ' . $views_counter . ' times.'; + } - if(config('footer_show_load_time')) { + if(setting('core.footer_load_time')) { $ret .= '
    Load time: ' . round(microtime(true) - START_TIME, 4) . ' seconds.'; } - if(isset($config['footer'][0])) - $ret .= '
    ' . $config['footer']; + $settingFooter = setting('core.footer'); + if(isset($settingFooter[0])) { + $ret .= '
    ' . $settingFooter; + } // please respect my work and help spreading the word, thanks! return $ret . '
    ' . base64_decode('UG93ZXJlZCBieSA8YSBocmVmPSJodHRwOi8vbXktYWFjLm9yZyIgdGFyZ2V0PSJfYmxhbmsiPk15QUFDLjwvYT4='); @@ -536,8 +529,8 @@ function template_footer() function template_ga_code() { - global $config, $twig; - if(!isset($config['google_analytics_id'][0])) + global $twig; + if(!isset(setting('core.google_analytics_id')[0])) return ''; return $twig->render('google_analytics.html.twig'); @@ -822,7 +815,7 @@ function getWorldName($id) /** * Mailing users. - * $config['mail_enabled'] have to be enabled. + * Mailing has to be enabled in settings (in Admin Panel). * * @param string $to Recipient email address. * @param string $subject Subject of the message. @@ -834,8 +827,9 @@ function _mail($to, $subject, $body, $altBody = '', $add_html_tags = true) { global $mailer, $config; - if (!config('mail_enabled')) { - log_append('mailer-error.log', '_mail() function has been used, but config.mail_enabled is disabled.'); + if (!setting('core.mail_enabled')) { + log_append('mailer-error.log', '_mail() function has been used, but Mail Support is disabled.'); + return false; } if(!$mailer) @@ -847,47 +841,60 @@ function _mail($to, $subject, $body, $altBody = '', $add_html_tags = true) $mailer->clearAllRecipients(); } - $signature_html = ''; - if(isset($config['mail_signature']['html'])) - $signature_html = $config['mail_signature']['html']; - + $signature_html = setting('core.mail_signature_html'); if($add_html_tags && isset($body[0])) $tmp_body = '' . $body . '

    ' . $signature_html . ''; else $tmp_body = $body . '

    ' . $signature_html; - if($config['smtp_enabled']) + define('MAIL_MAIL', 0); + define('MAIL_SMTP', 1); + + $mailOption = setting('core.mail_option'); + if($mailOption == MAIL_SMTP) { $mailer->isSMTP(); - $mailer->Host = $config['smtp_host']; - $mailer->Port = (int)$config['smtp_port']; - $mailer->SMTPAuth = $config['smtp_auth']; - $mailer->Username = $config['smtp_user']; - $mailer->Password = $config['smtp_pass']; - $mailer->SMTPSecure = isset($config['smtp_secure']) ? $config['smtp_secure'] : ''; + $mailer->Host = setting('core.smtp_host'); + $mailer->Port = setting('core.smtp_port'); + $mailer->SMTPAuth = setting('core.smtp_auth'); + $mailer->Username = setting('core.smtp_user'); + $mailer->Password = setting('core.smtp_pass'); + + define('SMTP_SECURITY_NONE', 0); + define('SMTP_SECURITY_SSL', 1); + define('SMTP_SECURITY_TLS', 2); + + $security = setting('core.smtp_security'); + + $tmp = ''; + if ($security === SMTP_SECURITY_SSL) { + $tmp = 'ssl'; + } + else if ($security == SMTP_SECURITY_TLS) { + $tmp = 'tls'; + } + + $mailer->SMTPSecure = $tmp; } else { $mailer->isMail(); } $mailer->isHTML(isset($body[0]) > 0); - $mailer->From = $config['mail_address']; - $mailer->Sender = $config['mail_address']; + $mailer->From = setting('core.mail_address'); + $mailer->Sender = setting('core.mail_address'); $mailer->CharSet = 'utf-8'; $mailer->FromName = $config['lua']['serverName']; $mailer->Subject = $subject; $mailer->addAddress($to); $mailer->Body = $tmp_body; - if(config('smtp_debug')) { + if(setting('core.smtp_debug')) { $mailer->SMTPDebug = 2; $mailer->Debugoutput = 'echo'; } - $signature_plain = ''; - if(isset($config['mail_signature']['plain'])) - $signature_plain = $config['mail_signature']['plain']; - + $signature_plain = setting('core.mail_signature_plain'); if(isset($altBody[0])) { $mailer->AltBody = $altBody . $signature_plain; } @@ -1047,7 +1054,7 @@ function getTopPlayers($limit = 5) { $deleted = 'deletion'; $is_tfs10 = $db->hasTable('players_online'); - $players = $db->query('SELECT `id`, `name`, `level`, `vocation`, `experience`, `looktype`' . ($db->hasColumn('players', 'lookaddons') ? ', `lookaddons`' : '') . ', `lookhead`, `lookbody`, `looklegs`, `lookfeet`' . ($is_tfs10 ? '' : ', `online`') . ' FROM `players` WHERE `group_id` < ' . config('highscores_groups_hidden') . ' AND `id` NOT IN (' . implode(', ', config('highscores_ids_hidden')) . ') AND `' . $deleted . '` = 0 AND `account_id` != 1 ORDER BY `experience` DESC LIMIT ' . (int)$limit)->fetchAll(); + $players = $db->query('SELECT `id`, `name`, `level`, `vocation`, `experience`, `looktype`' . ($db->hasColumn('players', 'lookaddons') ? ', `lookaddons`' : '') . ', `lookhead`, `lookbody`, `looklegs`, `lookfeet`' . ($is_tfs10 ? '' : ', `online`') . ' FROM `players` WHERE `group_id` < ' . setting('core.highscores_groups_hidden') . ' AND `id` NOT IN (' . implode(', ', setting('core.highscores_ids_hidden')) . ') AND `' . $deleted . '` = 0 AND `account_id` != 1 ORDER BY `experience` DESC LIMIT ' . (int)$limit)->fetchAll(); if($is_tfs10) { foreach($players as &$player) { @@ -1100,6 +1107,9 @@ function deleteDirectory($dir, $ignore = array(), $contentOnly = false) { function config($key) { global $config; if (is_array($key)) { + if (is_null($key[1])) { + unset($config[$key[0]]); + } return $config[$key[0]] = $key[1]; } @@ -1115,6 +1125,21 @@ function configLua($key) { return @$config['lua'][$key]; } +function setting($key) +{ + $settings = Settings::getInstance(); + + if (is_array($key)) { + if (is_null($key[1])) { + unset($settings[$key[0]]); + } + + return $settings[$key[0]] = $key[1]; + } + + return $settings[$key]['value']; +} + function clearCache() { require_once LIBS . 'news.php'; @@ -1483,8 +1508,8 @@ function right($str, $length) { } function getCreatureImgPath($creature){ - $creature_path = config('creatures_images_url'); - $creature_gfx_name = trim(strtolower($creature)) . config('creatures_images_extension'); + $creature_path = config('monsters_images_url'); + $creature_gfx_name = trim(strtolower($creature)) . config('monsters_images_extension'); if (!file_exists($creature_path . $creature_gfx_name)) { $creature_gfx_name = str_replace(" ", "", $creature_gfx_name); if (file_exists($creature_path . $creature_gfx_name)) { diff --git a/system/init.php b/system/init.php index 2815f791..c941f4d4 100644 --- a/system/init.php +++ b/system/init.php @@ -9,11 +9,6 @@ */ defined('MYAAC') or die('Direct access not allowed!'); -// load configuration -require_once BASE . 'config.php'; -if(file_exists(BASE . 'config.local.php')) // user customizations - require BASE . 'config.local.php'; - if(!isset($config['installed']) || !$config['installed']) { throw new RuntimeException('MyAAC has not been installed yet or there was error during installation. Please install again.'); } @@ -22,13 +17,16 @@ if(config('env') === 'dev') { require SYSTEM . 'exception.php'; } -date_default_timezone_set($config['date_timezone']); +if(empty($config['server_path'])) { + throw new RuntimeException('Server Path has been not set. Go to config.php and set it.'); +} + // take care of trailing slash at the end if($config['server_path'][strlen($config['server_path']) - 1] !== '/') $config['server_path'] .= '/'; // enable gzip compression if supported by the browser -if($config['gzip_output'] && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false && function_exists('ob_gzhandler')) +if(isset($config['gzip_output']) && $config['gzip_output'] && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false && function_exists('ob_gzhandler')) ob_start('ob_gzhandler'); // cache @@ -96,9 +94,6 @@ if(isset($config['lua']['servername'])) if(isset($config['lua']['houserentperiod'])) $config['lua']['houseRentPeriod'] = $config['lua']['houserentperiod']; -if($config['item_images_url'][strlen($config['item_images_url']) - 1] !== '/') - $config['item_images_url'] .= '/'; - // localize data/ directory based on data directory set in config.lua foreach(array('dataDirectory', 'data_directory', 'datadir') as $key) { if(!isset($config['lua'][$key][0])) { @@ -122,51 +117,34 @@ if(!isset($foundValue)) { $config['data_path'] = $foundValue; unset($foundValue); -// new config values for compatibility -if(!isset($config['highscores_ids_hidden']) || count($config['highscores_ids_hidden']) == 0) { - $config['highscores_ids_hidden'] = array(0); -} - -$config['account_create_character_create'] = config('account_create_character_create') && (!config('mail_enabled') || !config('account_mail_verify')); - // POT require_once SYSTEM . 'libs/pot/OTS.php'; $ots = POT::getInstance(); require_once SYSTEM . 'database.php'; +// execute migrations +require SYSTEM . 'migrate.php'; + +// settings +require_once LIBS . 'Settings.php'; +$settings = Settings::getInstance(); +$settings->load(); + +// deprecated config values +require_once SYSTEM . 'compat/config.php'; + +date_default_timezone_set(setting('core.date_timezone')); + +$config['account_create_character_create'] = config('account_create_character_create') && (!setting('core.mail_enabled') || !config('account_mail_verify')); + +$settingsItemImagesURL = setting('core.item_images_url'); +if($settingsItemImagesURL[strlen($settingsItemImagesURL) - 1] !== '/') { + setting(['core.item_images_url', $settingsItemImagesURL . '/']); +} + define('USE_ACCOUNT_NAME', $db->hasColumn('accounts', 'name')); define('USE_ACCOUNT_NUMBER', $db->hasColumn('accounts', 'number')); define('USE_ACCOUNT_SALT', $db->hasColumn('accounts', 'salt')); -// load vocation names -$tmp = ''; -if($cache->enabled() && $cache->fetch('vocations', $tmp)) { - $config['vocations'] = unserialize($tmp); -} -else { - if(!class_exists('DOMDocument')) { - throw new RuntimeException('Please install PHP xml extension. MyAAC will not work without it.'); - } - - $vocations = new DOMDocument(); - $file = $config['data_path'] . 'XML/vocations.xml'; - if(!@file_exists($file)) - $file = $config['data_path'] . 'vocations.xml'; - - if(!$vocations->load($file)) - throw new RuntimeException('ERROR: Cannot load vocations.xml - the file is malformed. Check the file with xml syntax validator.'); - - $config['vocations'] = array(); - foreach($vocations->getElementsByTagName('vocation') as $vocation) { - $id = $vocation->getAttribute('id'); - $config['vocations'][$id] = $vocation->getAttribute('name'); - } - - if($cache->enabled()) { - $cache->set('vocations', serialize($config['vocations']), 120); - } -} -unset($tmp, $id, $vocation); - require LIBS . 'Towns.php'; Towns::load(); diff --git a/system/libs/CreateCharacter.php b/system/libs/CreateCharacter.php index 60909c0f..8ec6993a 100644 --- a/system/libs/CreateCharacter.php +++ b/system/libs/CreateCharacter.php @@ -18,8 +18,8 @@ class CreateCharacter */ public function checkName($name, &$errors) { - $minLength = config('character_name_min_length'); - $maxLength = config('character_name_max_length'); + $minLength = setting('core.create_character_name_min_length'); + $maxLength = setting('core.create_character_name_max_length'); if(empty($name)) { $errors['name'] = 'Please enter a name for your character!'; @@ -149,7 +149,7 @@ class CreateCharacter $char_to_copy = new OTS_Player(); $char_to_copy->find($char_to_copy_name); if(!$char_to_copy->isLoaded()) - $errors[] = 'Wrong characters configuration. Try again or contact with admin. ADMIN: Edit file config.php and set valid characters to copy names. Character to copy: '.$char_to_copy_name.' doesn\'t exist.'; + $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.'; } if(!empty($errors)) { @@ -195,7 +195,7 @@ class CreateCharacter for($skill = POT::SKILL_FIRST; $skill <= POT::SKILL_LAST; $skill++) { $value = 10; - if (config('use_character_sample_skills')) { + if (setting('core.use_character_sample_skills')) { $value = $char_to_copy->getSkill($skill); } @@ -239,14 +239,14 @@ class CreateCharacter } if($db->hasTable('player_skills')) { - for($i=0; $i<7; $i++) { + for($skill = POT::SKILL_FIRST; $skill <= POT::SKILL_LAST; $skill++) { $value = 10; - if (config('use_character_sample_skills')) { - $value = $char_to_copy->getSkill($i); + if (setting('core.use_character_sample_skills')) { + $value = $char_to_copy->getSkill($skill); } - $skillExists = $db->query('SELECT `skillid` FROM `player_skills` WHERE `player_id` = ' . $player->getId() . ' AND `skillid` = ' . $i); + $skillExists = $db->query('SELECT `skillid` FROM `player_skills` WHERE `player_id` = ' . $player->getId() . ' AND `skillid` = ' . $skill); if($skillExists->rowCount() <= 0) { - $db->query('INSERT INTO `player_skills` (`player_id`, `skillid`, `value`, `count`) VALUES ('.$player->getId().', '.$i.', ' . $value . ', 0)'); + $db->query('INSERT INTO `player_skills` (`player_id`, `skillid`, `value`, `count`) VALUES ('.$player->getId().', '.$skill.', ' . $value . ', 0)'); } } } diff --git a/system/libs/Settings.php b/system/libs/Settings.php new file mode 100644 index 00000000..7e1d07f5 --- /dev/null +++ b/system/libs/Settings.php @@ -0,0 +1,598 @@ + + * @copyright 2020 MyAAC + * @link https://my-aac.org + */ + +class Settings implements ArrayAccess +{ + static private $instance; + private $settingsFile = []; + private $settingsDatabase = []; + private $cache = []; + private $valuesAsked = []; + private $errors = []; + + /** + * @return Settings + */ + public static function getInstance(): Settings + { + if (!self::$instance) { + self::$instance = new self(); + } + + return self::$instance; + } + + public function load() + { + $cache = Cache::getInstance(); + if ($cache->enabled()) { + $tmp = ''; + if ($cache->fetch('settings', $tmp)) { + $this->settingsDatabase = unserialize($tmp); + return; + } + } + + global $db; + $settings = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'settings`'); + + if($settings->rowCount() > 0) { + foreach ($settings->fetchAll(PDO::FETCH_ASSOC) as $setting) { + $this->settingsDatabase[$setting['name']][$setting['key']] = $setting['value']; + } + } + + if ($cache->enabled()) { + $cache->set('settings', serialize($this->settingsDatabase), 600); + } + } + + public function save($pluginName, $values) { + global $db; + + if (!isset($this->settingsFile[$pluginName])) { + throw new RuntimeException('Error on save settings: plugin does not exist'); + } + + $settings = $this->settingsFile[$pluginName]; + if (isset($settings['callbacks']['beforeSave'])) { + if (!$settings['callbacks']['beforeSave']($settings, $values)) { + return false; + } + } + + $this->errors = []; + $db->query('DELETE FROM `' . TABLE_PREFIX . 'settings` WHERE `name` = ' . $db->quote($pluginName) . ';'); + foreach ($values as $key => $value) { + $errorMessage = ''; + if (isset($settings['settings'][$key]['callbacks']['beforeSave']) && !$settings['settings'][$key]['callbacks']['beforeSave']($key, $value, $errorMessage)) { + $this->errors[] = $errorMessage; + continue; + } + + try { + $db->insert(TABLE_PREFIX . 'settings', ['name' => $pluginName, 'key' => $key, 'value' => $value]); + } catch (PDOException $error) { + $this->errors[] = 'Error while saving setting (' . $pluginName . ' - ' . $key . '): ' . $error->getMessage(); + } + } + + $cache = Cache::getInstance(); + if ($cache->enabled()) { + $cache->delete('settings'); + } + + return true; + } + + public function updateInDatabase($pluginName, $key, $value) + { + global $db; + $db->update(TABLE_PREFIX . 'settings', ['value' => $value], ['name' => $pluginName, 'key' => $key]); + } + + public function deleteFromDatabase($pluginName, $key = null) + { + global $db; + + if (!isset($key)) { + $db->delete(TABLE_PREFIX . 'settings', ['name' => $pluginName], -1); + } + else { + $db->delete(TABLE_PREFIX . 'settings', ['name' => $pluginName, 'key' => $key]); + } + } + + public static function display($plugin, $settings): array + { + global $db; + + $query = 'SELECT `key`, `value` FROM `' . TABLE_PREFIX . 'settings` WHERE `name` = ' . $db->quote($plugin) . ';'; + $query = $db->query($query); + + $settingsDb = []; + if($query->rowCount() > 0) { + foreach($query->fetchAll(PDO::FETCH_ASSOC) as $value) { + $settingsDb[$value['key']] = $value['value']; + } + } + + $config = []; + require BASE . 'config.local.php'; + + foreach ($config as $key => $value) { + if (is_bool($value)) { + $settingsDb[$key] = $value ? 'true' : 'false'; + } + else { + $settingsDb[$key] = (string)$value; + } + } + + $javascript = ''; + ob_start(); + ?> + +
    + ' . ($type ? 'Yes' : 'No') . ' '; + }; + + $i = 0; + $j = 0; + foreach($settings as $key => $setting) { + if ($setting['type'] === 'category') { + if ($j++ !== 0) { // close previous category + echo '
    '; + } + ?> +
    + '; + } + ?> +

    + + + + + + + + + + + + + + + + + +
    NameValueDescription
    + '; + } + + else if($setting['type'] === 'textarea') { + $value = ($settingsDb[$key] ?? ($setting['default'] ?? '')); + $valueWithSpaces = array_map('trim', preg_split('/\r\n|\r|\n/', trim($value))); + $rows = count($valueWithSpaces); + if ($rows < 2) { + $rows = 2; // always min 2 rows for textarea + } + echo ''; + } + + else if ($setting['type'] === 'options') { + if ($setting['options'] === '$templates') { + $templates = []; + foreach (get_templates() as $value) { + $templates[$value] = $value; + } + + $setting['options'] = $templates; + } + + else if($setting['options'] === '$clients') { + $clients = []; + foreach((array)config('clients') as $client) { + + $client_version = (string)($client / 100); + if(strpos($client_version, '.') === false) + $client_version .= '.0'; + + $clients[$client] = $client_version; + } + + $setting['options'] = $clients; + } + else if ($setting['options'] == '$timezones') { + $timezones = []; + foreach (DateTimeZone::listIdentifiers() as $value) { + $timezones[$value] = $value; + } + + $setting['options'] = $timezones; + } + + else { + if (is_string($setting['options'])) { + $setting['options'] = explode(',', $setting['options']); + foreach ($setting['options'] as &$option) { + $option = trim($option); + } + } + } + + echo ''; + } + + if (!isset($setting['hidden']) || !$setting['hidden']) { + ?> + +
    '; + echo 'Default: '; + + if ($setting['type'] === 'boolean') { + echo ($setting['default'] ? 'Yes' : 'No'); + } + else if (in_array($setting['type'], ['text', 'number', 'email', 'password', 'textarea'])) { + echo $setting['default']; + } + else if ($setting['type'] === 'options') { + if (!empty($setting['default'])) { + echo $setting['options'][$setting['default']]; + } + } + ?>
    +
    +
    +
    + + ob_get_clean(), 'script' => $javascript]; + } + + #[\ReturnTypeWillChange] + public function offsetSet($offset, $value) + { + if (is_null($offset)) { + throw new \RuntimeException("Settings: You cannot set empty offset with value: $value!"); + } + + $this->loadPlugin($offset); + + $pluginKeyName = $this->valuesAsked['pluginKeyName']; + $key = $this->valuesAsked['key']; + + // remove whole plugin settings + if (!isset($value)) { + $this->offsetUnset($offset); + $this->deleteFromDatabase($pluginKeyName, $key); + return; + } + + $this->settingsDatabase[$pluginKeyName][$key] = $value; + $this->updateInDatabase($pluginKeyName, $key, $value); + } + + #[\ReturnTypeWillChange] + public function offsetExists($offset): bool + { + $this->loadPlugin($offset); + + $pluginKeyName = $this->valuesAsked['pluginKeyName']; + $key = $this->valuesAsked['key']; + + // remove specified plugin settings (all) + if(is_null($key)) { + return isset($this->settingsDatabase[$offset]); + } + + return isset($this->settingsDatabase[$pluginKeyName][$key]); + } + + #[\ReturnTypeWillChange] + public function offsetUnset($offset) + { + $this->loadPlugin($offset); + + $pluginKeyName = $this->valuesAsked['pluginKeyName']; + $key = $this->valuesAsked['key']; + + if (isset($this->cache[$offset])) { + unset($this->cache[$offset]); + } + + // remove specified plugin settings (all) + if(!isset($key)) { + unset($this->settingsFile[$pluginKeyName]); + unset($this->settingsDatabase[$pluginKeyName]); + $this->deleteFromDatabase($pluginKeyName); + return; + } + + unset($this->settingsFile[$pluginKeyName]['settings'][$key]); + unset($this->settingsDatabase[$pluginKeyName][$key]); + $this->deleteFromDatabase($pluginKeyName, $key); + } + + /** + * Get settings + * Usage: $setting['plugin_name.key'] + * Example: $settings['shop_system.paypal_email'] + * + * @param mixed $offset + * @return array|mixed + */ + #[\ReturnTypeWillChange] + public function offsetGet($offset) + { + // try cache hit + if(isset($this->cache[$offset])) { + return $this->cache[$offset]; + } + + $this->loadPlugin($offset); + + $pluginKeyName = $this->valuesAsked['pluginKeyName']; + $key = $this->valuesAsked['key']; + + // return specified plugin settings (all) + if(!isset($key)) { + if (!isset($this->settingsFile[$pluginKeyName]['settings'])) { + throw new RuntimeException('Unknown plugin settings: ' . $pluginKeyName); + } + return $this->settingsFile[$pluginKeyName]['settings']; + } + + $ret = []; + if(isset($this->settingsFile[$pluginKeyName]['settings'][$key])) { + $ret = $this->settingsFile[$pluginKeyName]['settings'][$key]; + } + + if(isset($this->settingsDatabase[$pluginKeyName][$key])) { + $value = $this->settingsDatabase[$pluginKeyName][$key]; + + $ret['value'] = $value; + } + else { + $ret['value'] = $this->settingsFile[$pluginKeyName]['settings'][$key]['default']; + } + + if(isset($ret['type'])) { + switch($ret['type']) { + case 'boolean': + $ret['value'] = getBoolean($ret['value']); + break; + + case 'number': + if (!isset($ret['step']) || (int)$ret['step'] == 1) { + $ret['value'] = (int)$ret['value']; + } + break; + + default: + break; + } + } + + if (isset($ret['callbacks']['get'])) { + $ret['value'] = $ret['callbacks']['get']($ret['value']); + } + + $this->cache[$offset] = $ret; + return $ret; + } + + private function updateValuesAsked($offset) + { + $pluginKeyName = $offset; + if (strpos($offset, '.')) { + $explode = explode('.', $offset, 2); + + $pluginKeyName = $explode[0]; + $key = $explode[1]; + + $this->valuesAsked = ['pluginKeyName' => $pluginKeyName, 'key' => $key]; + } + else { + $this->valuesAsked = ['pluginKeyName' => $pluginKeyName, 'key' => null]; + } + } + + private function loadPlugin($offset) + { + $this->updateValuesAsked($offset); + + $pluginKeyName = $this->valuesAsked['pluginKeyName']; + $key = $this->valuesAsked['key']; + + if (!isset($this->settingsFile[$pluginKeyName])) { + if ($pluginKeyName === 'core') { + $settingsFilePath = SYSTEM . 'settings.php'; + } else { + //$pluginSettings = Plugins::getPluginSettings($pluginKeyName); + $settings = Plugins::getAllPluginsSettings(); + if (!isset($settings[$pluginKeyName])) { + warning("Setting $pluginKeyName does not exist or does not have settings defined."); + return; + } + + $settingsFilePath = BASE . $settings[$pluginKeyName]['settingsFilename']; + } + + if (!file_exists($settingsFilePath)) { + throw new \RuntimeException('Failed to load settings file for plugin: ' . $pluginKeyName); + } + + $this->settingsFile[$pluginKeyName] = require $settingsFilePath; + } + } + + public static function saveConfig($config, $filename, &$content = '') + { + $content = " $value) { + $content .= "\$config['$key'] = "; + $content .= var_export($value, true); + $content .= ';' . PHP_EOL; + } + + $success = file_put_contents($filename, $content); + + // we saved new config.php, need to revalidate cache (only if opcache is enabled) + if (function_exists('opcache_invalidate')) { + opcache_invalidate($filename); + } + + return $success; + } + + public static function testDatabaseConnection($config): bool + { + $user = null; + $password = null; + $dns = []; + + if( isset($config['database_name']) ) { + $dns[] = 'dbname=' . $config['database_name']; + } + + if( isset($config['database_user']) ) { + $user = $config['database_user']; + } + + if( isset($config['database_password']) ) { + $password = $config['database_password']; + } + + if( isset($config['database_host']) ) { + $dns[] = 'host=' . $config['database_host']; + } + + if( isset($config['database_port']) ) { + $dns[] = 'port=' . $config['database_port']; + } + + try { + $connectionTest = new PDO('mysql:' . implode(';', $dns), $user, $password); + $connectionTest->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + } + catch(PDOException $error) { + error('MySQL connection failed. Settings has been reverted.'); + error($error->getMessage()); + return false; + } + + return true; + } + + public function getErrors() { + return $this->errors; + } +} diff --git a/system/libs/forum.php b/system/libs/forum.php index 4922a9c3..c7f303f7 100644 --- a/system/libs/forum.php +++ b/system/libs/forum.php @@ -10,7 +10,7 @@ */ defined('MYAAC') or die('Direct access not allowed!'); -$configForumTablePrefix = config('forum_table_prefix'); +$configForumTablePrefix = setting('core.forum_table_prefix'); if(null !== $configForumTablePrefix && !empty(trim($configForumTablePrefix))) { if(!in_array($configForumTablePrefix, array('myaac_', 'z_'))) { throw new RuntimeException('Invalid value for forum_table_prefix in config.php. Can be only: "myaac_" or "z_".'); @@ -47,7 +47,7 @@ class Forum return $db->query( 'SELECT `id` FROM `players` WHERE `account_id` = ' . $db->quote($account->getId()) . - ' AND `level` >= ' . $db->quote($config['forum_level_required']) . + ' AND `level` >= ' . $db->quote(setting('core.forum_level_required')) . ' LIMIT 1')->rowCount() > 0; } diff --git a/system/libs/plugins.php b/system/libs/plugins.php index c3b548dc..c2b8f594 100644 --- a/system/libs/plugins.php +++ b/system/libs/plugins.php @@ -168,6 +168,36 @@ class Plugins { return $hooks; } + public static function getAllPluginsSettings() + { + $cache = Cache::getInstance(); + if ($cache->enabled()) { + $tmp = ''; + if ($cache->fetch('plugins_settings', $tmp)) { + return unserialize($tmp); + } + } + + $settings = []; + foreach (self::getAllPluginsJson() as $plugin) { + if (isset($plugin['settings'])) { + $settingsFile = require BASE . $plugin['settings']; + if (!isset($settingsFile['key'])) { + warning("Settings file for plugin - {$plugin['name']} does not contain 'key' field"); + continue; + } + + $settings[$settingsFile['key']] = ['pluginFilename' => $plugin['filename'], 'settingsFilename' => $plugin['settings']]; + } + } + + if ($cache->enabled()) { + $cache->set('plugins_settings', serialize($settings), 600); // cache for 10 minutes + } + + return $settings; + } + public static function getAllPluginsJson($disabled = false) { $cache = Cache::getInstance(); @@ -180,30 +210,66 @@ class Plugins { $plugins = []; foreach (get_plugins($disabled) as $filename) { - $string = file_get_contents(PLUGINS . $filename . '.json'); - $plugin = json_decode($string, true); - self::$plugin_json = $plugin; - if ($plugin == null) { - self::$warnings[] = 'Cannot load ' . $filename . '.json. File might be not a valid json code.'; - continue; - } - - if (isset($plugin['enabled']) && !getBoolean($plugin['enabled'])) { - self::$warnings[] = 'Skipping ' . $filename . '... The plugin is disabled.'; + $plugin = self::getPluginJson($filename); + + if (!$plugin) { continue; } + $plugin['filename'] = $filename; $plugins[] = $plugin; } if ($cache->enabled()) { - $cache->set('plugins', serialize($plugins), 600); + $cache->set('plugins', serialize($plugins), 600); // cache for 10 minutes } return $plugins; } - public static function install($file) { + public static function getPluginSettings($filename) + { + $plugin_json = self::getPluginJson($filename); + if (!$plugin_json) { + return false; + } + + if (!isset($plugin_json['settings']) || !file_exists(BASE . $plugin_json['settings'])) { + return false; + } + + return $plugin_json['settings']; + } + + public static function getPluginJson($filename = null) + { + if(!isset($filename)) { + return self::$plugin_json; + } + + $pathToPlugin = PLUGINS . $filename . '.json'; + if (!file_exists($pathToPlugin)) { + self::$warnings[] = "Cannot load $filename.json. File doesn't exist."; + return false; + } + + $string = file_get_contents($pathToPlugin); + $plugin_json = json_decode($string, true); + if ($plugin_json == null) { + self::$warnings[] = "Cannot load $filename.json. File might be not a valid json code."; + return false; + } + + if (isset($plugin_json['enabled']) && !getBoolean($plugin_json['enabled'])) { + self::$warnings[] = 'Skipping ' . $filename . '... The plugin is disabled.'; + return false; + } + + return $plugin_json; + } + + public static function install($file): bool + { global $db; if(!\class_exists('ZipArchive')) { @@ -242,6 +308,12 @@ class Plugins { return false; } + $pluginFilename = str_replace('.json', '', basename($json_file)); + if (self::existDisabled($pluginFilename)) { + success('The plugin already existed, but was disabled. It has been enabled again and will be now reinstalled.'); + self::enable($pluginFilename); + } + $string = file_get_contents($file_name); $plugin_json = json_decode($string, true); self::$plugin_json = $plugin_json; @@ -442,13 +514,23 @@ class Plugins { return false; } - public static function enable($pluginFileName): bool + public static function isEnabled($pluginFileName): bool { + $filenameJson = $pluginFileName . '.json'; + return !is_file(PLUGINS . 'disabled.' . $filenameJson) && is_file(PLUGINS . $filenameJson); + } + + public static function existDisabled($pluginFileName): bool + { + $filenameJson = $pluginFileName . '.json'; + return is_file(PLUGINS . 'disabled.' . $filenameJson); + } + + public static function enable($pluginFileName): bool { return self::enableDisable($pluginFileName, true); } - public static function disable($pluginFileName): bool - { + public static function disable($pluginFileName): bool { return self::enableDisable($pluginFileName, false); } @@ -526,7 +608,8 @@ class Plugins { return false; } - public static function is_installed($plugin_name, $version) { + public static function is_installed($plugin_name, $version): bool + { $filename = BASE . 'plugins/' . $plugin_name . '.json'; if(!file_exists($filename)) { return false; @@ -534,7 +617,7 @@ class Plugins { $string = file_get_contents($filename); $plugin_info = json_decode($string, true); - if($plugin_info == false) { + if(!$plugin_info) { return false; } @@ -557,10 +640,6 @@ class Plugins { return self::$error; } - public static function getPluginJson() { - return self::$plugin_json; - } - /** * Install menus * Helper function for plugins diff --git a/system/libs/pot/OTS_ServerInfo.php b/system/libs/pot/OTS_ServerInfo.php index 30a81f7b..eebe0d2e 100644 --- a/system/libs/pot/OTS_ServerInfo.php +++ b/system/libs/pot/OTS_ServerInfo.php @@ -14,7 +14,7 @@ /** * Various server status querying methods. - * + * * @package POT * @property-read OTS_InfoRespond|bool $status status() method wrapper. * @property-read OTS_ServerStatus|bool $info Full info() method wrapper. @@ -23,21 +23,21 @@ class OTS_ServerInfo { /** * Server address. - * + * * @var string */ private $server; /** * Connection port. - * + * * @var int */ private $port; /** * Creates handler for new server. - * + * * @param string $server Server IP/domain. * @param int $port OTServ port. */ @@ -49,7 +49,7 @@ class OTS_ServerInfo /** * Sends packet to server. - * + * * @param OTS_Buffer|string $packet Buffer to send. * @return OTS_Buffer|null Respond buffer (null if server is offline). * @throws E_OTS_OutOfBuffer When there is read attemp after end of packet stream. @@ -57,7 +57,7 @@ class OTS_ServerInfo private function send(OTS_Buffer $packet) { // connects to server - $socket = @fsockopen($this->server, $this->port, $error, $message, config('status_timeout')); + $socket = @fsockopen($this->server, $this->port, $error, $message, setting('core.status_timeout')); // if connected then checking statistics if($socket) @@ -75,7 +75,7 @@ class OTS_ServerInfo // reads respond //$data = stream_get_contents($socket); - $data = ''; + $data = ''; while (!feof($socket)) $data .= fgets($socket, 1024); @@ -97,11 +97,11 @@ class OTS_ServerInfo /** * Queries server status. - * + * *

    * Sends 'info' packet to OTS server and return output. Returns {@link OTS_InfoRespond OTS_InfoRespond} (wrapper for XML data) with results or false if server is online. *

    - * + * * @return OTS_InfoRespond|bool Respond content document (false when server is offline). * @throws DOMException On DOM operation error. * @throws E_OTS_OutOfBuffer When there is read attemp after end of packet stream. @@ -135,11 +135,11 @@ class OTS_ServerInfo /** * Queries server information. - * + * *

    * This method uses binary info protocol. It provides more infromation then {@link OTS_Toolbox::serverStatus() XML way}. *

    - * + * * @param int $flags Requested info flags. * @return OTS_ServerStatus|bool Respond content document (false when server is offline). * @throws E_OTS_OutOfBuffer When there is read attemp after end of packet stream. @@ -169,11 +169,11 @@ class OTS_ServerInfo /** * Checks player online status. - * + * *

    * This method uses binary info protocol. *

    - * + * * @param string $name Player name. * @return bool True if player is online, false if player or server is online. * @throws E_OTS_OutOfBuffer When there is read attemp after end of packet stream. @@ -204,7 +204,7 @@ class OTS_ServerInfo /** * Magic PHP5 method. - * + * * @param string $name Property name. * @param mixed $value Property value. * @throws OutOfBoundsException For non-supported properties. diff --git a/system/libs/validator.php b/system/libs/validator.php index eb958583..e7bffd6a 100644 --- a/system/libs/validator.php +++ b/system/libs/validator.php @@ -117,7 +117,7 @@ class Validator return false; } - if(config('account_mail_block_plus_sign')) { + if(setting('core.account_mail_block_plus_sign')) { $explode = explode('@', $email); if(isset($explode[0]) && (strpos($explode[0],'+') !== false)) { self::$lastError = 'Please do not use plus (+) sign in your e-mail.'; @@ -180,15 +180,16 @@ class Validator return false; } - $minLength = config('character_name_min_length'); - $maxLength = config('character_name_max_length'); - // installer doesn't know config.php yet // that's why we need to ignore the nulls - if(is_null($minLength) || is_null($maxLength)) { + if(defined('MYAAC_INSTALL')) { $minLength = 4; $maxLength = 21; } + else { + $minLength = setting('core.create_character_name_min_length'); + $maxLength = setting('core.create_character_name_max_length'); + } $length = strlen($name); if($length < $minLength) @@ -221,16 +222,6 @@ class Validator return false; } - $npcCheck = config('character_name_npc_check'); - if ($npcCheck) { - require_once LIBS . 'npc.php'; - NPCS::load(); - if(NPCS::$npcs && in_array(strtolower($name), NPCS::$npcs)) { - self::$lastError = "Invalid name format. Do not use NPC Names"; - return false; - } - } - return true; } @@ -246,14 +237,9 @@ class Validator global $db, $config; $name_lower = strtolower($name); - $custom_first_words_blocked = []; - if (isset($config['character_name_blocked']['prefix']) && $config['character_name_blocked']['prefix']) { - $custom_first_words_blocked = $config['character_name_blocked']['prefix']; - } - $first_words_blocked = array_merge($custom_first_words_blocked, array('admin ', 'administrator ', 'gm ', 'cm ', 'god ','tutor ', "'", '-')); - foreach($first_words_blocked as $word) - { + $first_words_blocked = array_merge(["'", '-'], setting('core.create_character_name_blocked_prefix')); + foreach($first_words_blocked as $word) { if($word == substr($name_lower, 0, strlen($word))) { self::$lastError = 'Your name contains blocked words.'; return false; @@ -275,8 +261,7 @@ class Validator return false; } - if(preg_match('/ {2,}/', $name)) - { + if(preg_match('/ {2,}/', $name)) { self::$lastError = 'Invalid character name format. Use only A-Z and numbers 0-9 and no double spaces.'; return false; } @@ -286,26 +271,16 @@ class Validator return false; } - $custom_names_blocked = []; - if (isset($config['character_name_blocked']['names']) && $config['character_name_blocked']['names']) { - $custom_names_blocked = $config['character_name_blocked']['names']; - } - $names_blocked = array_merge($custom_names_blocked, array('admin', 'administrator', 'gm', 'cm', 'god', 'tutor')); - foreach($names_blocked as $word) - { + $names_blocked = setting('core.create_character_name_blocked_names'); + foreach($names_blocked as $word) { if($word == $name_lower) { self::$lastError = 'Your name contains blocked words.'; return false; } } - $custom_words_blocked = []; - if (isset($config['character_name_blocked']['words']) && $config['character_name_blocked']['words']) { - $custom_words_blocked = $config['character_name_blocked']['words']; - } - $words_blocked = array_merge($custom_words_blocked, array('admin', 'administrator', 'gamemaster', 'game master', 'game-master', "game'master", '--', "''","' ", " '", '- ', ' -', "-'", "'-", 'fuck', 'sux', 'suck', 'noob', 'tutor')); - foreach($words_blocked as $word) - { + $words_blocked = array_merge(['--', "''","' ", " '", '- ', ' -', "-'", "'-"], setting('core.create_character_name_blocked_words')); + foreach($words_blocked as $word) { if(!(strpos($name_lower, $word) === false)) { self::$lastError = 'Your name contains illegal words.'; return false; @@ -321,7 +296,7 @@ class Validator } } - //check if was namelocked previously + // check if was namelocked previously if($db->hasTable('player_namelocks') && $db->hasColumn('player_namelocks', 'name')) { $namelock = $db->query('SELECT `player_id` FROM `player_namelocks` WHERE `name` = ' . $db->quote($name)); if($namelock->rowCount() > 0) { @@ -330,39 +305,41 @@ class Validator } } - $monsters = $db->query('SELECT `name` FROM `' . TABLE_PREFIX . 'monsters` WHERE `name` LIKE ' . $db->quote($name_lower)); - if($monsters->rowCount() > 0) { - self::$lastError = 'Your name cannot contains monster name.'; - return false; - } - - $spells_name = $db->query('SELECT `name` FROM `' . TABLE_PREFIX . 'spells` WHERE `name` LIKE ' . $db->quote($name_lower)); - if($spells_name->rowCount() > 0) { - self::$lastError = 'Your name cannot contains spell name.'; - return false; - } - - $spells_words = $db->query('SELECT `words` FROM `' . TABLE_PREFIX . 'spells` WHERE `words` = ' . $db->quote($name_lower)); - if($spells_words->rowCount() > 0) { - self::$lastError = 'Your name cannot contains spell name.'; - return false; - } - - if(isset($config['npc'])) - { - if(in_array($name_lower, $config['npc'])) { - self::$lastError = 'Your name cannot contains NPC name.'; + $monstersCheck = setting('core.create_character_name_monsters_check'); + if ($monstersCheck) { + $monsters = $db->query('SELECT `name` FROM `' . TABLE_PREFIX . 'monsters` WHERE `name` LIKE ' . $db->quote($name_lower)); + if ($monsters->rowCount() > 0) { + self::$lastError = 'Your name cannot contains monster name.'; return false; } } - $npcCheck = config('character_name_npc_check'); + $spellsCheck = setting('core.create_character_name_spells_check'); + if ($spellsCheck) { + $spells_name = $db->query('SELECT `name` FROM `' . TABLE_PREFIX . 'spells` WHERE `name` LIKE ' . $db->quote($name_lower)); + if ($spells_name->rowCount() > 0) { + self::$lastError = 'Your name cannot contains spell name.'; + return false; + } + + $spells_words = $db->query('SELECT `words` FROM `' . TABLE_PREFIX . 'spells` WHERE `words` = ' . $db->quote($name_lower)); + if ($spells_words->rowCount() > 0) { + self::$lastError = 'Your name cannot contains spell name.'; + return false; + } + } + + $npcCheck = setting('core.create_character_name_npc_check'); if ($npcCheck) { require_once LIBS . 'npc.php'; NPCS::load(); - if(NPCS::$npcs && in_array($name_lower, NPCS::$npcs)) { - self::$lastError = "Invalid name format. Do not use NPC Names"; - return false; + if(NPCS::$npcs) { + foreach (NPCs::$npcs as $npc) { + if(strpos($name_lower, $npc) !== false) { + self::$lastError = 'Your name cannot contains NPC name.'; + return false; + } + } } } diff --git a/system/migrations/20.php b/system/migrations/20.php index d0012fde..b0e09471 100644 --- a/system/migrations/20.php +++ b/system/migrations/20.php @@ -1,47 +1,15 @@ query("SELECT `id` FROM `players` WHERE (`name` = " . $db->quote("Rook Sample") . " OR `name` = " . $db->quote("Sorcerer Sample") . " OR `name` = " . $db->quote("Druid Sample") . " OR `name` = " . $db->quote("Paladin Sample") . " OR `name` = " . $db->quote("Knight Sample") . " OR `name` = " . $db->quote("Account Manager") . ") ORDER BY `id`;"); + +$highscores_ignored_ids = array(); +if($query->rowCount() > 0) { + foreach($query->fetchAll() as $result) + $highscores_ignored_ids[] = $result['id']; +} +else { + $highscores_ignored_ids[] = 0; } -function databaseMigration20(&$content = '') { - global $db; - - $config_file = BASE . 'config.local.php'; - if(!is_writable($config_file)) { // we can't do anything, just ignore - return false; - } - - $content_of_file = trim(file_get_contents($config_file)); - if(strpos($content_of_file, 'highscores_ids_hidden') !== false) { // already present - return true; - } - - $query = $db->query("SELECT `id` FROM `players` WHERE (`name` = " . $db->quote("Rook Sample") . " OR `name` = " . $db->quote("Sorcerer Sample") . " OR `name` = " . $db->quote("Druid Sample") . " OR `name` = " . $db->quote("Paladin Sample") . " OR `name` = " . $db->quote("Knight Sample") . " OR `name` = " . $db->quote("Account Manager") . ") ORDER BY `id`;"); - - $highscores_ignored_ids = array(); - if($query->rowCount() > 0) { - foreach($query->fetchAll() as $result) - $highscores_ignored_ids[] = $result['id']; - } - else { - $highscores_ignored_ids[] = 0; - } - - $php_on_end = substr($content_of_file, -2, 2) == '?>'; - $content = PHP_EOL; - if($php_on_end) { - $content .= ''; - } - - file_put_contents($config_file, $content, FILE_APPEND); - return true; -} +$settings = Settings::getInstance(); +$settings->updateInDatabase('core', 'highscores_ids_hidden', implode(', ', $highscores_ignored_ids)); diff --git a/system/migrations/36.php b/system/migrations/36.php new file mode 100644 index 00000000..d88e9d28 --- /dev/null +++ b/system/migrations/36.php @@ -0,0 +1,14 @@ +hasTable(TABLE_PREFIX . 'settings')) { + $db->exec("CREATE TABLE `" . TABLE_PREFIX . "settings` + ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` VARCHAR(255) NOT NULL DEFAULT '', + `key` VARCHAR(255) NOT NULL DEFAULT '', + `value` TEXT NOT NULL, + PRIMARY KEY (`id`), + KEY `key` (`key`) + ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;"); +} diff --git a/system/pages/account/change_name.php b/system/pages/account/change_name.php index 48b6bb4d..ef82b9ad 100644 --- a/system/pages/account/change_name.php +++ b/system/pages/account/change_name.php @@ -19,17 +19,17 @@ if(!$logged) { $player_id = isset($_POST['player_id']) ? (int)$_POST['player_id'] : NULL; $name = isset($_POST['name']) ? stripslashes(ucwords(strtolower($_POST['name']))) : NULL; -if((!$config['account_change_character_name'])) +if((!setting('core.account_change_character_name'))) echo 'Changing character name for premium points is disabled on this server.'; else { - $points = $account_logged->getCustomField('premium_points'); + $points = $account_logged->getCustomField(setting('core.donate_column')); if(isset($_POST['changenamesave']) && $_POST['changenamesave'] == 1) { - if($points < $config['account_change_character_name_points']) - $errors[] = 'You need ' . $config['account_change_character_name_points'] . ' premium points to change name. You have '.$points.' premium points.'; + if($points < setting('core.account_change_character_name_price')) + $errors[] = 'You need ' . setting('core.account_change_character_name_price') . ' premium points to change name. You have '.$points.' premium points.'; - $minLength = config('character_name_min_length'); - $maxLength = config('character_name_max_length'); + $minLength = setting('core.create_character_name_min_length'); + $maxLength = setting('core.create_character_name_max_length'); if(empty($errors) && empty($name)) $errors[] = 'Please enter a new name for your character!'; @@ -86,7 +86,7 @@ else } } - $account_logged->setCustomField("premium_points", $points - $config['account_change_character_name_points']); + $account_logged->setCustomField(setting('core.donate_column'), $points - setting('core.account_change_character_name_price')); $account_logged->logAction('Changed name from ' . $old_name . ' to ' . $player->getName() . '.'); $twig->display('success.html.twig', array( 'title' => 'Character Name Changed', diff --git a/system/pages/account/change_password.php b/system/pages/account/change_password.php index deef3602..95e15159 100644 --- a/system/pages/account/change_password.php +++ b/system/pages/account/change_password.php @@ -69,7 +69,7 @@ else $account_logged->logAction('Account password changed.'); $message = ''; - if($config['mail_enabled'] && $config['send_mail_when_change_password']) { + if(setting('core.mail_enabled') && setting('core.mail_send_when_change_password')) { $mailBody = $twig->render('mail.password_changed.html.twig', array( 'new_password' => $org_pass, 'ip' => get_browser_real_ip(), @@ -89,4 +89,4 @@ else )); setSession('password', $new_password); } -} \ No newline at end of file +} diff --git a/system/pages/account/change_sex.php b/system/pages/account/change_sex.php index 2f944564..7e43b6ff 100644 --- a/system/pages/account/change_sex.php +++ b/system/pages/account/change_sex.php @@ -20,14 +20,14 @@ if(!$logged) { $sex_changed = false; $player_id = isset($_POST['player_id']) ? (int)$_POST['player_id'] : NULL; $new_sex = isset($_POST['new_sex']) ? (int)$_POST['new_sex'] : NULL; -if((!$config['account_change_character_sex'])) +if((!setting('core.account_change_character_sex'))) echo 'You cant change your character sex'; else { - $points = $account_logged->getCustomField('premium_points'); + $points = $account_logged->getCustomField(setting('core.donate_column')); if(isset($_POST['changesexsave']) && $_POST['changesexsave'] == 1) { - if($points < $config['account_change_character_sex_points']) - $errors[] = 'You need ' . $config['account_change_character_sex_points'] . ' premium points to change sex. You have '.$points.' premium points.'; + if($points < setting('core.account_change_character_sex_price')) + $errors[] = 'You need ' . setting('core.account_change_character_sex_price') . ' premium points to change sex. You have '.$points.' premium points.'; if(empty($errors) && !isset($config['genders'][$new_sex])) { $errors[] = 'This sex is invalid.'; @@ -66,7 +66,7 @@ else $new_sex_str = $config['genders'][$new_sex]; $player->save(); - $account_logged->setCustomField("premium_points", $points - $config['account_change_character_name_points']); + $account_logged->setCustomField(setting('core.donate_column'), $points - setting('core.account_change_character_name_price')); $account_logged->logAction('Changed sex on character ' . $player->getName() . ' from ' . $old_sex_str . ' to ' . $new_sex_str . '.'); $twig->display('success.html.twig', array( 'title' => 'Character Sex Changed', diff --git a/system/pages/account/create.php b/system/pages/account/create.php index dd7c7713..2aa7c544 100644 --- a/system/pages/account/create.php +++ b/system/pages/account/create.php @@ -219,7 +219,7 @@ if($save) $tmp_account = (USE_ACCOUNT_NAME ? $account_name : $account_id); } - if($config['mail_enabled'] && $config['account_mail_verify']) + if(setting('core.mail_enabled') && $config['account_mail_verify']) { $hash = md5(generateRandomString(16, true, true) . $email); $new_account->setCustomField('email_hash', $hash); @@ -294,7 +294,7 @@ if($save) 'custom_buttons' => config('account_create_character_create') ? '' : null )); - if($config['mail_enabled'] && $config['account_welcome_mail']) + if(setting('core.mail_enabled') && $config['account_welcome_mail']) { $mailBody = $twig->render('account.welcome_mail.html.twig', array( 'account' => $tmp_account @@ -313,7 +313,7 @@ if($save) } $country_recognized = null; -if($config['account_country_recognize']) { +if(setting('core.account_country_recognize')) { $country_session = getSession('country'); if($country_session !== false) { // get from session $country_recognized = $country_session; diff --git a/system/pages/account/lost.php b/system/pages/account/lost.php index 3ea0957e..664cee9c 100644 --- a/system/pages/account/lost.php +++ b/system/pages/account/lost.php @@ -11,7 +11,7 @@ defined('MYAAC') or die('Direct access not allowed!'); $title = 'Lost Account Interface'; -if(!$config['mail_enabled']) +if(!setting('core.mail_enabled')) { echo 'Account maker is not configured to send e-mails, you can\'t use Lost Account Interface. Contact with admin to get help.'; return; @@ -59,7 +59,7 @@ elseif($action == 'step1' && $action_type == 'email') $minutesleft = floor($insec / 60); $secondsleft = $insec - ($minutesleft * 60); $timeleft = $minutesleft.' minutes '.$secondsleft.' seconds'; - echo 'Account of selected character ('.$nick.') received e-mail in last '.ceil($config['email_lai_sec_interval'] / 60).' minutes. You must wait '.$timeleft.' before you can use Lost Account Interface again.'; + echo 'Account of selected character ('.$nick.') received e-mail in last '.ceil(setting('core.mail_lost_account_interval') / 60).' minutes. You must wait '.$timeleft.' before you can use Lost Account Interface again.'; } } else @@ -104,7 +104,7 @@ elseif($action == 'sendcode') if(_mail($account_mail, $config['lua']['serverName'].' - Recover your account', $mailBody)) { $account->setCustomField('email_code', $newcode); - $account->setCustomField('email_next', (time() + $config['email_lai_sec_interval'])); + $account->setCustomField('email_next', (time() + setting('core.mail_lost_account_interval'))); echo '
    Details about steps required to recover your account has been sent to ' . $account_mail . '. You should receive this email within 15 minutes. Please check your inbox/spam directory.'; } else @@ -122,7 +122,7 @@ elseif($action == 'sendcode') $minutesleft = floor($insec / 60); $secondsleft = $insec - ($minutesleft * 60); $timeleft = $minutesleft.' minutes '.$secondsleft.' seconds'; - echo 'Account of selected character ('.$nick.') received e-mail in last '.ceil($config['email_lai_sec_interval'] / 60).' minutes. You must wait '.$timeleft.' before you can use Lost Account Interface again.'; + echo 'Account of selected character ('.$nick.') received e-mail in last '.ceil(setting('core.mail_lost_account_interval') / 60).' minutes. You must wait '.$timeleft.' before you can use Lost Account Interface again.'; } } else diff --git a/system/pages/account/manage.php b/system/pages/account/manage.php index b2af3cee..c4a8402a 100644 --- a/system/pages/account/manage.php +++ b/system/pages/account/manage.php @@ -35,7 +35,7 @@ if(empty($recovery_key)) $account_registered = 'No'; else { - if($config['generate_new_reckey'] && $config['mail_enabled']) + if(setting('core.account_generate_new_reckey') && setting('core.mail_enabled')) $account_registered = 'Yes ( Buy new Recovery Key )'; else $account_registered = 'Yes'; diff --git a/system/pages/account/register.php b/system/pages/account/register.php index 1d16d905..f33f0b17 100644 --- a/system/pages/account/register.php +++ b/system/pages/account/register.php @@ -31,7 +31,7 @@ if(isset($_POST['registeraccountsave']) && $_POST['registeraccountsave'] == "1") $account_logged->logAction('Generated recovery key.'); $message = ''; - if($config['mail_enabled'] && $config['send_mail_when_generate_reckey']) + if(setting('core.mail_enabled') && setting('core.mail_send_when_generate_reckey')) { $mailBody = $twig->render('mail.account.register.html.twig', array( 'recovery_key' => $new_rec_key diff --git a/system/pages/account/register_new.php b/system/pages/account/register_new.php index fb2e8ea3..04e8bf33 100644 --- a/system/pages/account/register_new.php +++ b/system/pages/account/register_new.php @@ -21,18 +21,18 @@ if(isset($_POST['reg_password'])) $reg_password = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $_POST['reg_password']); $reckey = $account_logged->getCustomField('key'); -if((!$config['generate_new_reckey'] || !$config['mail_enabled']) || empty($reckey)) { +if((!setting('core.account_generate_new_reckey') || !setting('core.mail_enabled')) || empty($reckey)) { $errors[] = 'You cant get new recovery key.'; $twig->display('error_box.html.twig', array('errors' => $errors)); } else { - $points = $account_logged->getCustomField('premium_points'); + $points = $account_logged->getCustomField(setting('core.donate_column')); if(isset($_POST['registeraccountsave']) && $_POST['registeraccountsave'] == '1') { if($reg_password == $account_logged->getPassword()) { - if($points >= $config['generate_new_reckey_price']) + if($points >= setting('core.account_generate_new_reckey_price')) { $show_form = false; $new_rec_key = generateRandomString(10, false, true, true); @@ -43,10 +43,10 @@ else if(_mail($account_logged->getEMail(), $config['lua']['serverName']." - new recovery key", $mailBody)) { - $account_logged->setCustomField("key", $new_rec_key); - $account_logged->setCustomField("premium_points", $account_logged->getCustomField("premium_points") - $config['generate_new_reckey_price']); - $account_logged->logAction('Generated new recovery key for ' . $config['generate_new_reckey_price'] . ' premium points.'); - $message = '
    Your recovery key were send on email address '.$account_logged->getEMail().' for '.$config['generate_new_reckey_price'].' premium points.'; + $account_logged->setCustomField('key', $new_rec_key); + $account_logged->setCustomField(setting('core.donate_column'), $account_logged->getCustomField(setting('core.donate_column')) - setting('core.account_generate_new_reckey_price')); + $account_logged->logAction('Generated new recovery key for ' . setting('core.account_generate_new_reckey_price') . ' premium points.'); + $message = '
    Your recovery key were send on email address '.$account_logged->getEMail().' for '.setting('core.account_generate_new_reckey_price').' premium points.'; } else $message = '

    An error occurred while sending email ( '.$account_logged->getEMail().' ) with recovery key! Recovery key not changed. Try again later. For Admin: More info can be found in system/logs/mailer-error.log

    '; @@ -57,7 +57,7 @@ else )); } else - $errors[] = 'You need '.$config['generate_new_reckey_price'].' premium points to generate new recovery key. You have '.$points.' premium points.'; + $errors[] = 'You need ' . setting('core.account_generate_new_reckey_price') . ' premium points to generate new recovery key. You have '.$points.' premium points.'; } else $errors[] = 'Wrong password to account.'; diff --git a/system/pages/characters.php b/system/pages/characters.php index 13f88f05..62cb2759 100644 --- a/system/pages/characters.php +++ b/system/pages/characters.php @@ -340,8 +340,8 @@ WHERE killers.death_id = '".$death['id']."' ORDER BY killers.final_hit DESC, kil } // signature - if($config['signature_enabled']) { - $signature_url = BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . urlencode($player->getName()) . '.png'; + if(setting('core.signature_enabled')) { + $signature_url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . urlencode($player->getName()) . '.png'; } $hidden = $player->isHidden(); diff --git a/system/pages/creatures.php b/system/pages/creatures.php index f87b6f28..9e472738 100644 --- a/system/pages/creatures.php +++ b/system/pages/creatures.php @@ -14,7 +14,7 @@ $title = 'Creatures'; if (empty($_REQUEST['name'])) { // display list of monsters - $preview = config('creatures_images_preview'); + $preview = config('monsters_images_preview'); $creatures = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'monsters` WHERE `hidden` != 1 '.(empty($_REQUEST['boss']) ? '': 'AND `rewardboss` = 1').' ORDER BY name asc')->fetchAll(); if ($preview) { @@ -62,7 +62,7 @@ if (isset($creature['name'])) { $item['name'] = getItemNameById($item['id']); $item['rarity_chance'] = round($item['chance'] / 1000, 2); $item['rarity'] = getItemRarity($item['chance']); - $item['tooltip'] = ucfirst($item['name']) . '
    Chance: ' . $item['rarity'] . (config('creatures_loot_percentage') ? ' ('. $item['rarity_chance'] .'%)' : '') . '
    Max count: ' . $item['count']; + $item['tooltip'] = ucfirst($item['name']) . '
    Chance: ' . $item['rarity'] . (config('monsters_loot_percentage') ? ' ('. $item['rarity_chance'] .'%)' : '') . '
    Max count: ' . $item['count']; } $creature['loot'] = isset($loot) ? $loot : null; diff --git a/system/pages/experience_table.php b/system/pages/experience_table.php index d8ed39dc..e45b7714 100644 --- a/system/pages/experience_table.php +++ b/system/pages/experience_table.php @@ -11,9 +11,9 @@ defined('MYAAC') or die('Direct access not allowed!'); $title = 'Experience Table'; $experience = array(); -$columns = $config['experiencetable_columns']; +$columns = setting('core.experience_table_columns'); for($i = 0; $i < $columns; $i++) { - for($level = $i * $config['experiencetable_rows'] + 1; $level < $i * $config['experiencetable_rows'] + ($config['experiencetable_rows'] + 1); $level++) { + for($level = $i * setting('core.experience_table_rows') + 1; $level < $i * setting('core.experience_table_rows') + (setting('core.experience_table_rows') + 1); $level++) { $experience[$level] = OTS_Toolbox::experienceForLevel($level); } } diff --git a/system/pages/forum.php b/system/pages/forum.php index 5c9688a6..e5b68ed0 100644 --- a/system/pages/forum.php +++ b/system/pages/forum.php @@ -10,7 +10,11 @@ */ defined('MYAAC') or exit; -require __DIR__ . '/forum/base.php'; +$ret = require __DIR__ . '/forum/base.php'; +if ($ret === false) { + return; +} + require __DIR__ . '/forum/admin.php'; $errors = []; diff --git a/system/pages/forum/base.php b/system/pages/forum/base.php index 57ae6d17..de449692 100644 --- a/system/pages/forum/base.php +++ b/system/pages/forum/base.php @@ -11,22 +11,24 @@ defined('MYAAC') or die('Direct access not allowed!'); $title = 'Forum'; -if(strtolower($config['forum']) != 'site') { - if($config['forum'] != '') { - header('Location: ' . $config['forum']); +require_once LIBS . 'forum.php'; + +$forumSetting = setting('core.forum'); +if(strtolower($forumSetting) != 'site') { + if($forumSetting != '') { + header('Location: ' . $forumSetting); exit; } echo 'Forum is disabled on this site.'; - return; + return false; } if(!$logged) { echo 'You are not logged in. Log in to post on the forum.

    '; + return false; } -require_once LIBS . 'forum.php'; - $sections = array(); foreach(getForumBoards() as $section) { $sections[$section['id']] = array( diff --git a/system/pages/forum/edit_post.php b/system/pages/forum/edit_post.php index 2df443a0..539ca7e0 100644 --- a/system/pages/forum/edit_post.php +++ b/system/pages/forum/edit_post.php @@ -10,7 +10,10 @@ */ defined('MYAAC') or die('Direct access not allowed!'); -require __DIR__ . '/base.php'; +$ret = require __DIR__ . '/base.php'; +if ($ret === false) { + return; +} if(Forum::canPost($account_logged)) { @@ -75,7 +78,7 @@ if(Forum::canPost($account_logged)) $char_id = $thread['author_guid']; $db->query("UPDATE `" . FORUM_TABLE_PREFIX . "forum` SET `author_guid` = ".(int) $char_id.", `post_text` = ".$db->quote($text).", `post_topic` = ".$db->quote($post_topic).", `post_smile` = ".$smile.", `post_html` = ".$html.", `last_edit_aid` = ".(int) $account_logged->getId().",`edit_date` = ".time()." WHERE `id` = ".(int) $thread['id']); $post_page = $db->query("SELECT COUNT(`" . FORUM_TABLE_PREFIX . "forum`.`id`) AS posts_count FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`post_date` <= ".$thread['post_date']." AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".(int) $thread['first_post'])->fetch(); - $_page = (int) ceil($post_page['posts_count'] / $config['forum_threads_per_page']) - 1; + $_page = (int) ceil($post_page['posts_count'] / setting('core.forum_threads_per_page')) - 1; header('Location: ' . getForumThreadLink($thread['first_post'], $_page)); echo '
    Thank you for editing post.
    GO BACK TO LAST THREAD'; } @@ -117,6 +120,6 @@ if(Forum::canPost($account_logged)) } } else { - $errors[] = "Your account is banned, deleted or you don't have any player with level " . $config['forum_level_required'] . " on your account. You can't post."; + $errors[] = "Your account is banned, deleted or you don't have any player with level " . setting('core.forum_level_required') . " on your account. You can't post."; displayErrorBoxWithBackButton($errors, getLink('forum')); } diff --git a/system/pages/forum/move_thread.php b/system/pages/forum/move_thread.php index 3c01a13e..45d14683 100644 --- a/system/pages/forum/move_thread.php +++ b/system/pages/forum/move_thread.php @@ -10,7 +10,10 @@ */ defined('MYAAC') or die('Direct access not allowed!'); -require __DIR__ . '/base.php'; +$ret = require __DIR__ . '/base.php'; +if ($ret === false) { + return; +} if(!Forum::isModerator()) { echo 'You are not logged in or you are not moderator.'; diff --git a/system/pages/forum/new_post.php b/system/pages/forum/new_post.php index d4b605c6..dd027984 100644 --- a/system/pages/forum/new_post.php +++ b/system/pages/forum/new_post.php @@ -10,7 +10,10 @@ */ defined('MYAAC') or die('Direct access not allowed!'); -require __DIR__ . '/base.php'; +$ret = require __DIR__ . '/base.php'; +if ($ret === false) { + return; +} if(!$logged) { $extra_url = ''; @@ -81,8 +84,8 @@ if(Forum::canPost($account_logged)) { $query = $query->fetch(); $last_post = $query['post_date']; } - if($last_post+$config['forum_post_interval']-time() > 0 && !Forum::isModerator()) - $errors[] = 'You can post one time per '.$config['forum_post_interval'].' seconds. Next post after '.($last_post+$config['forum_post_interval']-time()).' second(s).'; + if($last_post+setting('core.forum_post_interval')-time() > 0 && !Forum::isModerator()) + $errors[] = 'You can post one time per ' . setting('core.forum_post_interval') . ' seconds. Next post after '.($last_post + setting('core.forum_post_interval')-time()).' second(s).'; } if(count($errors) == 0) { @@ -90,7 +93,7 @@ if(Forum::canPost($account_logged)) { Forum::add_post($thread['id'], $thread['section'], $account_logged->getId(), $char_id, $text, $post_topic, $smile, $html); $db->query("UPDATE `" . FORUM_TABLE_PREFIX . "forum` SET `replies`=`replies`+1, `last_post`=".time()." WHERE `id` = ".$thread_id); $post_page = $db->query("SELECT COUNT(`" . FORUM_TABLE_PREFIX . "forum`.`id`) AS posts_count FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`post_date` <= ".time()." AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".(int) $thread['id'])->fetch(); - $_page = (int) ceil($post_page['posts_count'] / $config['forum_threads_per_page']) - 1; + $_page = (int) ceil($post_page['posts_count'] / setting('core.forum_threads_per_page')) - 1; header('Location: ' . getForumThreadLink($thread_id, $_page)); echo '
    Thank you for posting.
    GO BACK TO LAST THREAD'; } @@ -131,7 +134,7 @@ if(Forum::canPost($account_logged)) { } } else { - $errors[] = "Your account is banned, deleted or you don't have any player with level " . config('forum_level_required') . " on your account. You can't post."; + $errors[] = "Your account is banned, deleted or you don't have any player with level " . setting('core.forum_level_required') . " on your account. You can't post."; displayErrorBoxWithBackButton($errors, getLink('forum')); } diff --git a/system/pages/forum/new_thread.php b/system/pages/forum/new_thread.php index b864c448..9dfe82a1 100644 --- a/system/pages/forum/new_thread.php +++ b/system/pages/forum/new_thread.php @@ -10,7 +10,10 @@ */ defined('MYAAC') or die('Direct access not allowed!'); -require __DIR__ . '/base.php'; +$ret = require __DIR__ . '/base.php'; +if ($ret === false) { + return; +} if(Forum::canPost($account_logged)) { $players_from_account = $db->query('SELECT `players`.`name`, `players`.`id` FROM `players` WHERE `players`.`account_id` = '.(int) $account_logged->getId())->fetchAll(); @@ -67,8 +70,8 @@ if(Forum::canPost($account_logged)) { $last_post = $query['post_date']; } - if ($last_post + config('forum_post_interval') - time() > 0 && !Forum::isModerator()) - $errors[] = 'You can post one time per ' . config('forum_post_interval') . ' seconds. Next post after ' . ($last_post + config('forum_post_interval') - time()) . ' second(s).'; + if ($last_post + setting('core.forum_post_interval') - time() > 0 && !Forum::isModerator()) + $errors[] = 'You can post one time per ' . setting('core.forum_post_interval') . ' seconds. Next post after ' . ($last_post + setting('core.forum_post_interval') - time()) . ' second(s).'; } if (count($errors) == 0) { @@ -113,6 +116,6 @@ if(Forum::canPost($account_logged)) { } } else { - $errors[] = 'Your account is banned, deleted or you don\'t have any player with level '.$config['forum_level_required'].' on your account. You can\'t post.'; + $errors[] = 'Your account is banned, deleted or you don\'t have any player with level '.setting('core.forum_level_required').' on your account. You can\'t post.'; displayErrorBoxWithBackButton($errors, getLink('forum')); } diff --git a/system/pages/forum/remove_post.php b/system/pages/forum/remove_post.php index a1e13338..c3f2d46f 100644 --- a/system/pages/forum/remove_post.php +++ b/system/pages/forum/remove_post.php @@ -10,7 +10,10 @@ */ defined('MYAAC') or die('Direct access not allowed!'); -require __DIR__ . '/base.php'; +$ret = require __DIR__ . '/base.php'; +if ($ret === false) { + return; +} if(Forum::isModerator()) { $id = (int) $_REQUEST['id']; @@ -23,7 +26,7 @@ if(Forum::isModerator()) { } else { $post_page = $db->query("SELECT COUNT(`" . FORUM_TABLE_PREFIX . "forum`.`id`) AS posts_count FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`id` < ".$id." AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".(int) $post['first_post'])->fetch(); - $_page = (int) ceil($post_page['posts_count'] / $config['forum_threads_per_page']) - 1; + $_page = (int) ceil($post_page['posts_count'] / setting('core.forum_threads_per_page')) - 1; $db->query("DELETE FROM `" . FORUM_TABLE_PREFIX . "forum` WHERE `id` = ".$post['id']); header('Location: ' . getForumThreadLink($post['first_post'], (int) $_page)); } diff --git a/system/pages/forum/show_board.php b/system/pages/forum/show_board.php index d3dcd0d5..4e37984c 100644 --- a/system/pages/forum/show_board.php +++ b/system/pages/forum/show_board.php @@ -10,7 +10,10 @@ */ defined('MYAAC') or die('Direct access not allowed!'); -require __DIR__ . '/base.php'; +$ret = require __DIR__ . '/base.php'; +if ($ret === false) { + return; +} $links_to_pages = ''; $section_id = isset($_REQUEST['id']) ? (int) $_REQUEST['id'] : null; @@ -29,7 +32,7 @@ if(!Forum::hasAccess($section_id)) { $_page = (int) (isset($_REQUEST['page']) ? $_REQUEST['page'] : 0); $threads_count = $db->query("SELECT COUNT(`" . FORUM_TABLE_PREFIX . "forum`.`id`) AS threads_count FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`section` = ".(int) $section_id." AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = `" . FORUM_TABLE_PREFIX . "forum`.`id`")->fetch(); -for($i = 0; $i < $threads_count['threads_count'] / $config['forum_threads_per_page']; $i++) { +for($i = 0; $i < $threads_count['threads_count'] / setting('core.forum_threads_per_page'); $i++) { if($i != $_page) $links_to_pages .= ''.($i + 1).' '; else @@ -44,7 +47,7 @@ if(!$sections[$section_id]['closed'] || Forum::isModerator()) { } echo '

    Page: '.$links_to_pages.'
    '; -$last_threads = $db->query("SELECT `players`.`id` as `player_id`, `players`.`name`, `" . FORUM_TABLE_PREFIX . "forum`.`post_text`, `" . FORUM_TABLE_PREFIX . "forum`.`post_topic`, `" . FORUM_TABLE_PREFIX . "forum`.`id`, `" . FORUM_TABLE_PREFIX . "forum`.`last_post`, `" . FORUM_TABLE_PREFIX . "forum`.`replies`, `" . FORUM_TABLE_PREFIX . "forum`.`views`, `" . FORUM_TABLE_PREFIX . "forum`.`post_date` FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`section` = ".$section_id." AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = `" . FORUM_TABLE_PREFIX . "forum`.`id` ORDER BY `" . FORUM_TABLE_PREFIX . "forum`.`last_post` DESC LIMIT ".$config['forum_threads_per_page']." OFFSET ".($_page * $config['forum_threads_per_page']))->fetchAll(); +$last_threads = $db->query("SELECT `players`.`id` as `player_id`, `players`.`name`, `" . FORUM_TABLE_PREFIX . "forum`.`post_text`, `" . FORUM_TABLE_PREFIX . "forum`.`post_topic`, `" . FORUM_TABLE_PREFIX . "forum`.`id`, `" . FORUM_TABLE_PREFIX . "forum`.`last_post`, `" . FORUM_TABLE_PREFIX . "forum`.`replies`, `" . FORUM_TABLE_PREFIX . "forum`.`views`, `" . FORUM_TABLE_PREFIX . "forum`.`post_date` FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`section` = ".$section_id." AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = `" . FORUM_TABLE_PREFIX . "forum`.`id` ORDER BY `" . FORUM_TABLE_PREFIX . "forum`.`last_post` DESC LIMIT ".setting('core.forum_threads_per_page')." OFFSET ".($_page * setting('core.forum_threads_per_page')))->fetchAll(); if(isset($last_threads[0])) { echo ' diff --git a/system/pages/forum/show_thread.php b/system/pages/forum/show_thread.php index dc252560..263683ee 100644 --- a/system/pages/forum/show_thread.php +++ b/system/pages/forum/show_thread.php @@ -10,7 +10,10 @@ */ defined('MYAAC') or die('Direct access not allowed!'); -require __DIR__ . '/base.php'; +$ret = require __DIR__ . '/base.php'; +if ($ret === false) { + return; +} $links_to_pages = ''; $thread_id = (int) $_REQUEST['id']; @@ -30,14 +33,14 @@ if(!Forum::hasAccess($thread_starter['section'])) { } $posts_count = $db->query("SELECT COUNT(`" . FORUM_TABLE_PREFIX . "forum`.`id`) AS posts_count FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".(int) $thread_id)->fetch(); -for($i = 0; $i < $posts_count['posts_count'] / $config['forum_threads_per_page']; $i++) { +for($i = 0; $i < $posts_count['posts_count'] / setting('core.forum_threads_per_page'); $i++) { if($i != $_page) $links_to_pages .= ''.($i + 1).' '; else $links_to_pages .= ''.($i + 1).' '; } -$posts = $db->query("SELECT `players`.`id` as `player_id`, `" . FORUM_TABLE_PREFIX . "forum`.`id`,`" . FORUM_TABLE_PREFIX . "forum`.`first_post`, `" . FORUM_TABLE_PREFIX . "forum`.`section`,`" . FORUM_TABLE_PREFIX . "forum`.`post_text`, `" . FORUM_TABLE_PREFIX . "forum`.`post_topic`, `" . FORUM_TABLE_PREFIX . "forum`.`post_date` AS `date`, `" . FORUM_TABLE_PREFIX . "forum`.`post_smile`, `" . FORUM_TABLE_PREFIX . "forum`.`post_html`, `" . FORUM_TABLE_PREFIX . "forum`.`author_aid`, `" . FORUM_TABLE_PREFIX . "forum`.`author_guid`, `" . FORUM_TABLE_PREFIX . "forum`.`last_edit_aid`, `" . FORUM_TABLE_PREFIX . "forum`.`edit_date` FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".$thread_id." ORDER BY `" . FORUM_TABLE_PREFIX . "forum`.`post_date` LIMIT ".$config['forum_posts_per_page']." OFFSET ".($_page * $config['forum_posts_per_page']))->fetchAll(); +$posts = $db->query("SELECT `players`.`id` as `player_id`, `" . FORUM_TABLE_PREFIX . "forum`.`id`,`" . FORUM_TABLE_PREFIX . "forum`.`first_post`, `" . FORUM_TABLE_PREFIX . "forum`.`section`,`" . FORUM_TABLE_PREFIX . "forum`.`post_text`, `" . FORUM_TABLE_PREFIX . "forum`.`post_topic`, `" . FORUM_TABLE_PREFIX . "forum`.`post_date` AS `date`, `" . FORUM_TABLE_PREFIX . "forum`.`post_smile`, `" . FORUM_TABLE_PREFIX . "forum`.`post_html`, `" . FORUM_TABLE_PREFIX . "forum`.`author_aid`, `" . FORUM_TABLE_PREFIX . "forum`.`author_guid`, `" . FORUM_TABLE_PREFIX . "forum`.`last_edit_aid`, `" . FORUM_TABLE_PREFIX . "forum`.`edit_date` FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = ".$thread_id." ORDER BY `" . FORUM_TABLE_PREFIX . "forum`.`post_date` LIMIT " . setting('core.forum_posts_per_page') . " OFFSET ".($_page * setting('core.forum_posts_per_page')))->fetchAll(); if(isset($posts[0]['player_id'])) { $db->query("UPDATE `" . FORUM_TABLE_PREFIX . "forum` SET `views`=`views`+1 WHERE `id` = ".(int) $thread_id); diff --git a/system/pages/highscores.php b/system/pages/highscores.php index dd2efa7b..fe8533c7 100644 --- a/system/pages/highscores.php +++ b/system/pages/highscores.php @@ -11,8 +11,8 @@ defined('MYAAC') or die('Direct access not allowed!'); $title = 'Highscores'; -$configHighscoresCountryBox = config('highscores_country_box'); -if(config('account_country') && $configHighscoresCountryBox) +$settingHighscoresCountryBox = setting('core.highscores_country_box'); +if(config('account_country') && $settingHighscoresCountryBox) require SYSTEM . 'countries.conf.php'; $list = $_GET['list'] ?? 'experience'; @@ -25,11 +25,11 @@ if(!is_numeric($page) || $page < 1 || $page > PHP_INT_MAX) { $add_sql = ''; -$configHighscoresVocationBox = config('highscores_vocation_box'); +$settingHighscoresVocationBox = setting('core.highscores_vocation_box'); $configVocations = config('vocations'); $configVocationsAmount = config('vocations_amount'); -if($configHighscoresVocationBox && $vocation !== 'all') +if($settingHighscoresVocationBox && $vocation !== 'all') { foreach($configVocations as $id => $name) { if(strtolower($name) == $vocation) { @@ -99,12 +99,12 @@ else break; case 'frags': - if(config('highscores_frags')) + if(setting('core.highscores_frags')) $skill = SKILL_FRAGS; break; case 'balance': - if(config('highscores_balance')) + if(setting('core.highscores_balance')) $skill = SKILL_BALANCE; break; } @@ -125,9 +125,9 @@ if($db->hasColumn('players', 'deletion')) $outfit_addons = false; $outfit = ''; -$configHighscoresOutfit = config('highscores_outfit'); +$settingHighscoresOutfit = setting('core.highscores_outfit'); -if($configHighscoresOutfit) { +if($settingHighscoresOutfit) { $outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype'; if($db->hasColumn('players', 'lookaddons')) { $outfit .= ', lookaddons'; @@ -135,7 +135,7 @@ if($configHighscoresOutfit) { } } -$configHighscoresPerPage = config('highscores_per_page'); +$configHighscoresPerPage = setting('core.highscores_per_page'); $limit = $configHighscoresPerPage + 1; $needReCache = true; @@ -164,15 +164,15 @@ if (!isset($highscores) || empty($highscores)) { POT::SKILL_FISH => 'skill_fishing', ); - $highscores = $db->query('SELECT accounts.country, players.id,players.name' . $online . ',level,vocation' . $promotion . $outfit . ', ' . $skill_ids[$skill] . ' as value FROM accounts,players WHERE players.id NOT IN (' . implode(', ', config('highscores_ids_hidden')) . ') AND players.' . $deleted . ' = 0 AND players.group_id < ' . config('highscores_groups_hidden') . ' ' . $add_sql . ' AND accounts.id = players.account_id ORDER BY ' . $skill_ids[$skill] . ' DESC LIMIT ' . $limit . ' OFFSET ' . $offset)->fetchAll(); + $highscores = $db->query('SELECT accounts.country, players.id,players.name' . $online . ',level,vocation' . $promotion . $outfit . ', ' . $skill_ids[$skill] . ' as value FROM accounts,players WHERE players.id NOT IN (' . implode(', ', setting('core.highscores_ids_hidden')) . ') AND players.' . $deleted . ' = 0 AND players.group_id < ' . setting('core.highscores_groups_hidden') . ' ' . $add_sql . ' AND accounts.id = players.account_id ORDER BY ' . $skill_ids[$skill] . ' DESC LIMIT ' . $limit . ' OFFSET ' . $offset)->fetchAll(); } else - $highscores = $db->query('SELECT accounts.country, players.id,players.name' . $online . ',value,level,vocation' . $promotion . $outfit . ' FROM accounts,players,player_skills WHERE players.id NOT IN (' . implode(', ', config('highscores_ids_hidden')) . ') AND players.' . $deleted . ' = 0 AND players.group_id < ' . config('highscores_groups_hidden') . ' ' . $add_sql . ' AND players.id = player_skills.player_id AND player_skills.skillid = ' . $skill . ' AND accounts.id = players.account_id ORDER BY value DESC, count DESC LIMIT ' . $limit . ' OFFSET ' . $offset)->fetchAll(); + $highscores = $db->query('SELECT accounts.country, players.id,players.name' . $online . ',value,level,vocation' . $promotion . $outfit . ' FROM accounts,players,player_skills WHERE players.id NOT IN (' . implode(', ', setting('core.highscores_ids_hidden')) . ') AND players.' . $deleted . ' = 0 AND players.group_id < ' . setting('core.highscores_groups_hidden') . ' ' . $add_sql . ' AND players.id = player_skills.player_id AND player_skills.skillid = ' . $skill . ' AND accounts.id = players.account_id ORDER BY value DESC, count DESC LIMIT ' . $limit . ' OFFSET ' . $offset)->fetchAll(); } else if ($skill == SKILL_FRAGS) // frags { if ($db->hasTable('player_killers')) { $highscores = $db->query('SELECT accounts.country, players.id, players.name' . $online . ',level, vocation' . $promotion . $outfit . ', COUNT(`player_killers`.`player_id`) as value' . ' FROM `accounts`, `players`, `player_killers` ' . - ' WHERE players.id NOT IN (' . implode(', ', config('highscores_ids_hidden')) . ') AND players.' . $deleted . ' = 0 AND players.group_id < ' . config('highscores_groups_hidden') . ' ' . $add_sql . ' AND players.id = player_killers.player_id AND accounts.id = players.account_id' . + ' WHERE players.id NOT IN (' . implode(', ', setting('core.highscores_ids_hidden')) . ') AND players.' . $deleted . ' = 0 AND players.group_id < ' . setting('core.highscores_groups_hidden') . ' ' . $add_sql . ' AND players.id = player_killers.player_id AND accounts.id = players.account_id' . ' GROUP BY `player_id`' . ' ORDER BY value DESC' . ' LIMIT ' . $limit . ' OFFSET ' . $offset)->fetchAll(); @@ -183,9 +183,9 @@ if (!isset($highscores) || empty($highscores)) { FROM `players` p LEFT JOIN `accounts` a ON `a`.`id` = `p`.`account_id` LEFT JOIN `player_deaths` pd ON `pd`.`killed_by` = `p`.`name` - WHERE `p`.id NOT IN (' . implode(', ', config('highscores_ids_hidden')) . ') + WHERE `p`.id NOT IN (' . implode(', ', setting('core.highscores_ids_hidden')) . ') AND `p`.' . $deleted . ' = 0 - AND `p`.group_id < ' . config('highscores_groups_hidden') . ' ' . $add_sql . ' + AND `p`.group_id < ' . setting('core.highscores_groups_hidden') . ' ' . $add_sql . ' AND `pd`.`unjustified` = 1 GROUP BY `killed_by` ORDER BY value DESC @@ -193,19 +193,19 @@ if (!isset($highscores) || empty($highscores)) { } } else if ($skill == SKILL_BALANCE) // balance { - $highscores = $db->query('SELECT accounts.country, players.id,players.name' . $online . ',level,balance as value,vocation' . $promotion . $outfit . ' FROM accounts,players WHERE players.id NOT IN (' . implode(', ', config('highscores_ids_hidden')) . ') AND players.' . $deleted . ' = 0 AND players.group_id < ' . config('highscores_groups_hidden') . ' ' . $add_sql . ' AND accounts.id = players.account_id ORDER BY value DESC LIMIT ' . $limit . ' OFFSET ' . $offset)->fetchAll(); + $highscores = $db->query('SELECT accounts.country, players.id,players.name' . $online . ',level,balance as value,vocation' . $promotion . $outfit . ' FROM accounts,players WHERE players.id NOT IN (' . implode(', ', setting('core.highscores_ids_hidden')) . ') AND players.' . $deleted . ' = 0 AND players.group_id < ' . setting('core.highscores_groups_hidden') . ' ' . $add_sql . ' AND accounts.id = players.account_id ORDER BY value DESC LIMIT ' . $limit . ' OFFSET ' . $offset)->fetchAll(); } else { if ($skill == POT::SKILL__MAGLEVEL) { - $highscores = $db->query('SELECT accounts.country, players.id,players.name' . $online . ',maglevel,level,vocation' . $promotion . $outfit . ' FROM accounts, players WHERE players.id NOT IN (' . implode(', ', config('highscores_ids_hidden')) . ') AND players.' . $deleted . ' = 0 ' . $add_sql . ' AND players.group_id < ' . config('highscores_groups_hidden') . ' AND accounts.id = players.account_id ORDER BY maglevel DESC, manaspent DESC LIMIT ' . $limit . ' OFFSET ' . $offset)->fetchAll(); + $highscores = $db->query('SELECT accounts.country, players.id,players.name' . $online . ',maglevel,level,vocation' . $promotion . $outfit . ' FROM accounts, players WHERE players.id NOT IN (' . implode(', ', setting('core.highscores_ids_hidden')) . ') AND players.' . $deleted . ' = 0 ' . $add_sql . ' AND players.group_id < ' . setting('core.highscores_groups_hidden') . ' AND accounts.id = players.account_id ORDER BY maglevel DESC, manaspent DESC LIMIT ' . $limit . ' OFFSET ' . $offset)->fetchAll(); } else { // level - $highscores = $db->query('SELECT accounts.country, players.id,players.name' . $online . ',level,experience,vocation' . $promotion . $outfit . ' FROM accounts, players WHERE players.id NOT IN (' . implode(', ', config('highscores_ids_hidden')) . ') AND players.' . $deleted . ' = 0 ' . $add_sql . ' AND players.group_id < ' . config('highscores_groups_hidden') . ' AND accounts.id = players.account_id ORDER BY level DESC, experience DESC LIMIT ' . $limit . ' OFFSET ' . $offset)->fetchAll(); + $highscores = $db->query('SELECT accounts.country, players.id,players.name' . $online . ',level,experience,vocation' . $promotion . $outfit . ' FROM accounts, players WHERE players.id NOT IN (' . implode(', ', setting('core.highscores_ids_hidden')) . ') AND players.' . $deleted . ' = 0 ' . $add_sql . ' AND players.group_id < ' . setting('core.highscores_groups_hidden') . ' AND accounts.id = players.account_id ORDER BY level DESC, experience DESC LIMIT ' . $limit . ' OFFSET ' . $offset)->fetchAll(); $list = 'experience'; } } } if ($cache->enabled() && $needReCache) { - $cache->set($cacheKey, serialize($highscores), config('highscores_cache_ttl') * 60); + $cache->set($cacheKey, serialize($highscores), setting('core.highscores_cache_ttl') * 60); } $online_exist = false; @@ -227,7 +227,7 @@ if($db->hasTable('players_online') && count($players) > 0) { $show_link_to_next_page = false; $i = 0; -$configHighscoresVocation = config('highscores_vocation'); +$settingHighscoresVocation = setting('core.highscores_vocation'); foreach($highscores as $id => &$player) { @@ -248,7 +248,7 @@ foreach($highscores as $id => &$player) $player['experience'] = number_format($player['experience']); } - if($configHighscoresVocation) { + if($settingHighscoresVocation) { if(isset($player['promotion'])) { if((int)$player['promotion'] > 0) { $player['vocation'] += ($player['promotion'] * $configVocationsAmount); @@ -266,7 +266,7 @@ foreach($highscores as $id => &$player) $player['link'] = getPlayerLink($player['name'], false); $player['flag'] = getFlagImage($player['country']); - if($configHighscoresOutfit) { + if($settingHighscoresOutfit) { $player['outfit'] = ''; } $player['rank'] = $offset + $i; @@ -302,10 +302,10 @@ $types = array( 'fishing' => 'Fishing', ); -if(config('highscores_frags')) { +if(setting('core.highscores_frags')) { $types['frags'] = 'Frags'; } -if(config('highscores_balance')) +if(setting('core.highscores_balance')) $types['balance'] = 'Balance'; /** @var Twig\Environment $twig */ diff --git a/system/pages/team.php b/system/pages/team.php index fbc0df99..b1fd15dc 100644 --- a/system/pages/team.php +++ b/system/pages/team.php @@ -23,7 +23,7 @@ if(!$groups->count()) $outfit_addons = false; $outfit = ''; -if($config['team_display_outfit']) { +if(setting('core.team_outfit')) { $outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype'; if($db->hasColumn('players', 'lookaddons')) { $outfit .= ', lookaddons'; @@ -56,12 +56,12 @@ foreach($groupList as $id => $group) $members[] = array( 'group_name' => $group->getName(), 'player' => $member, - 'outfit' => $config['team_display_outfit'] ? $config['outfit_images_url'] . '?id=' . $member->getLookType() . ($outfit_addons ? '&addons=' . $member->getLookAddons() : '') . '&head=' . $member->getLookHead() . '&body=' . $member->getLookBody() . '&legs=' . $member->getLookLegs() . '&feet=' . $member->getLookFeet() : null, - 'status' => $config['team_display_status'] ? $member->isOnline() : null, + 'outfit' => setting('core.team_outfit') ? setting('core.outfit_images_url') . '?id=' . $member->getLookType() . ($outfit_addons ? '&addons=' . $member->getLookAddons() : '') . '&head=' . $member->getLookHead() . '&body=' . $member->getLookBody() . '&legs=' . $member->getLookLegs() . '&feet=' . $member->getLookFeet() : null, + 'status' => setting('core.team_status') ? $member->isOnline() : null, 'link' => getPlayerLink($member->getName()), - 'flag_image' => $config['account_country'] ? getFlagImage($member->getAccount()->getCountry()) : null, - 'world_name' => ($config['multiworld'] || $config['team_display_world']) ? getWorldName($member->getWorldId()) : null, - 'last_login' => $config['team_display_lastlogin'] ? $lastLogin : null + 'flag_image' => setting('core.account_country') ? getFlagImage($member->getAccount()->getCountry()) : null, + 'world_name' => (setting('core.multiworld') || setting('core.team_world')) ? getWorldName($member->getWorldId()) : null, + 'last_login' => setting('core.team_lastlogin') ? $lastLogin : null ); } diff --git a/system/settings.php b/system/settings.php new file mode 100644 index 00000000..83a1d85e --- /dev/null +++ b/system/settings.php @@ -0,0 +1,1638 @@ + 'MyAAC', + 'settings' => + [ + [ + 'type' => 'category', + 'title' => 'General' + ], + [ + 'type' => 'section', + 'title' => 'General' + ], + 'env' => [ + 'name' => 'App Environment', + 'type' => 'options', + 'options' => ['prod' => 'Production', 'dev' => 'Development'], + 'desc' => 'if you use this script on your live server - set production
    ' . + '* if you want to test and debug the script locally, or develop plugins, set to development
    ' . + '* WARNING: on "development" cache is disabled, so site will be significantly slower !!!
    ' . + '* WARNING2: on "development" all PHP errors/warnings are displayed
    ' . + '* Recommended: "production" cause of speed (page load time is better)', + 'default' => 'prod', + 'is_config' => true, + ], + 'server_path' => [ + 'name' => 'Server Path', + 'type' => 'text', + 'desc' => 'Path to the server directory (same directory where config file is located)', + 'default' => '', + 'is_config' => true, + ], + 'date_timezone' => [ + 'name' => 'Date Timezone', + 'type' => 'options', + 'options' => '$timezones', + 'desc' => 'Timezone of the server, more info at http://php.net/manual/en/timezones.php', + 'default' => 'Europe/Warsaw', + ], + 'friendly_urls' => [ + 'name' => 'Friendly URLs', + 'type' => 'boolean', + 'desc' => 'It makes links looks more elegant to eye, and also are SEO friendly

    ' . + 'yes: http://example.net/guilds/Testing
    ' . + 'no: http://example.net/index.php/guilds/Testing

    ' . + 'apache2: mod_rewrite is required for this + remember to rename .htaccess.dist to .htaccess
    ' . + 'nginx: check included nginx-sample.conf', + 'default' => false, + ], + 'gzip_output' => [ + 'name' => 'gzip Output', + 'type' => 'boolean', + 'desc' => 'gzip page content before sending it to the browser, uses less bandwidth but more cpu cycles', + 'default' => false, + 'is_config' => true, + ], + 'google_analytics_id' => [ + 'name' => 'Google Analytics ID', + 'type' => 'text', + 'desc' => 'Format: UA-XXXXXXX-X', + 'default' => '', + ], + [ + 'type' => 'section', + 'title' => 'Template' + ], + 'template' => [ + 'name' => 'Template Name', + 'type' => 'options', + 'options' => '$templates', + 'desc' => 'Name of the template used by website', + 'default' => 'kathrine', + ], + 'template_allow_change' => [ + 'name' => 'Template Allow Change', + 'type' => 'boolean', + 'desc' => 'Allow changing template of the website by showing a special select in the part of website', + 'default' => true, + ], + [ + 'type' => 'section', + 'title' => escapeHtml('') . ' - Header' + ], + 'charset' => [ + 'name' => 'Meta Charset', + 'type' => 'text', + 'desc' => 'Charset used in ' . escapeHtml(''), + 'default' => 'utf-8', + ], + 'meta_description' => [ + 'name' => 'Meta Description', + 'type' => 'textarea', + 'desc' => 'description of the site in ' . escapeHtml(''), + 'default' => 'Tibia is a free massive multiplayer online role playing game (MMORPG).', + ], + 'meta_keywords' => [ + 'name' => 'Meta Keywords', + 'type' => 'textarea', + 'desc' => 'keywords list separated by commas', + 'default' => 'free online game, free multiplayer game, ots, open tibia server', + ], + [ + 'type' => 'section', + 'title' => 'Footer' + ], + 'footer' => [ + 'name' => 'Custom Text', + 'type' => 'textarea', + 'desc' => 'Text displayed in the footer.
    For example: ' . escapeHtml('
    ') . 'Your Server © 2023. All rights reserved.
    ', + 'default' => '', + ], + 'footer_load_time' => [ + 'name' => 'Load Time', + 'type' => 'boolean', + 'desc' => 'Display load time of the page in the footer', + 'default' => true, + ], + // do we really want this? I'm leaving it for consideration + /* + 'footer_powered_by' => [ + 'name' => 'Display Powered by MyAAC', + 'type' => 'boolean', + 'desc' => 'Do you want to show Powered by MyAAC slogan in the footer?', + 'default' => true, + ], + */ + /*'language' => [ + 'name' => 'Language', + 'type' => 'options', + 'options' => ['en' => 'English'], + 'desc' => 'default language (currently only English available)', + 'default' => 'en', + ],*/ + /*'language_allow_change' => [ + 'name' => 'Language Allow Change', + 'type' => 'boolean', + 'default' => false, + 'desc' => 'default language (currently only English available)' + ],*/ + [ + 'type' => 'section', + 'title' => 'Counters' + ], + 'visitors_counter' => [ + 'name' => 'Visitors Counter', + 'type' => 'boolean', + 'desc' => 'Enable Visitors Counter? It will show list of online members on the website in Admin Panel', + 'default' => true, + ], + 'visitors_counter_ttl' => [ + 'name' => 'Visitors Counter TTL', + 'type' => 'number', + 'desc' => 'Time To Live for Visitors Counter. In other words - how long user will be marked as online. In Minutes', + 'default' => 10, + 'show_if' => [ + 'visitors_counter', '=', 'true' + ] + ], + 'views_counter' => [ + 'name' => 'Views Counter', + 'type' => 'boolean', + 'desc' => 'Enable Views Counter? It will show how many times the website has been viewed by users', + 'default' => true, + ], + [ + 'type' => 'section', + 'title' => 'Misc' + ], + 'cache_engine' => [ + 'name' => 'Cache Engine', + 'type' => 'options', + 'options' => ['auto' => 'Auto', 'file' => 'Files', 'apc' => 'APC', 'apcu' => 'APCu', 'eaccelerator' => 'eAccelerator', 'disable' => 'Disable'], + 'desc' => 'Auto is most reasonable. It will detect the best cache engine', + 'default' => 'auto', + 'is_config' => true, + ], + 'cache_prefix' => [ + 'name' => 'Cache Prefix', + 'type' => 'text', + 'desc' => 'Have to be unique if running more MyAAC instances on the same server (except file system cache)', + 'default' => 'myaac_' . generateRandomString(8, true, false, true), + 'is_config' => true, + ], + 'session_prefix' => [ + 'name' => 'Session Prefix', + 'type' => 'text', + 'desc' => 'must be unique for every site on your server', + 'default' => 'myaac_', + ], + 'backward_support' => [ + 'name' => 'Gesior Backward Support', + 'type' => 'boolean', + 'desc' => 'gesior backward support (templates & pages)
    ' . + 'allows using gesior templates and pages with myaac
    ' . + 'might bring some performance when disabled', + 'default' => true, + ], + 'anonymous_usage_statistics' => [ + 'name' => 'Anonymous Usage Statistics', + 'type' => 'boolean', + 'desc' => 'Allow MyAAC to report anonymous usage statistics to developers? The data is sent only once per 30 days and is fully confidential. It won\'t affect the performance of your website', + 'default' => true, + ], + [ + 'type' => 'category', + 'title' => 'Game', + ], + [ + 'type' => 'section', + 'title' => 'Game' + ], + 'client' => [ + 'name' => 'Client Version', + 'type' => 'options', + 'options' => '$clients', + 'desc' => 'what client version are you using on this OT?
    used for the Downloads page and some templates aswell', + 'default' => 710 + ], + 'towns' => [ + 'name' => 'Towns', + 'type' => 'textarea', + 'desc' => "if you use TFS 1.3 with support for 'towns' table in database, then you can ignore this - it will be configured automatically (from MySQL database - Table - towns)
    " . + "otherwise it will try to load from your .OTBM map file
    " . + "if you don't see towns on website, then you need to fill this out", + 'default' => "0=No Town\n1=Sample Town", + 'callbacks' => [ + 'get' => function ($value) { + $ret = []; + $towns = array_map('trim', preg_split('/\r\n|\r|\n/', trim($value))); + + foreach ($towns as $town) { + if (empty($town)) { + continue; + } + + $explode = explode('=', $town); + $ret[$explode[0]] = $explode[1]; + } + + return $ret; + }, + ], + ], + 'genders' => [ + 'name' => 'Genders (aka sex)', + 'type' => 'textarea', + 'desc' => 'Separated with comma', + 'default' => 'Female, Male', + 'callbacks' => [ + 'get' => function ($value) { + return array_map('trim', explode(',', $value)); + }, + ], + ], + 'account_types' => [ + 'name' => 'Account Types', + 'type' => 'textarea', + 'desc' => 'Separated with comma, you may need to adjust this for older tfs versions by removing Community Manager', + 'default' => 'None, Normal, Tutor, Senior Tutor, Gamemaster, Community Manager, God', + 'callbacks' => [ + 'get' => function ($value) { + return array_map('trim', explode(',', $value)); + }, + ], + ], + 'vocations_amount' => [ + 'name' => 'Vocations Amount', + 'type' => 'number', + 'desc' => 'How much basic vocations your server got (without promotion)', + 'default' => 4, + ], + 'vocations' => [ + 'name' => 'Vocation Names', + 'type' => 'textarea', + 'desc' => 'Separated by comma ,', + 'default' => 'None, Sorcerer, Druid, Paladin, Knight, Master Sorcerer, Elder Druid,Royal Paladin, Elite Knight', + 'callbacks' => [ + 'get' => function ($value) { + return array_map('trim', explode(',', $value)); + }, + ], + ], + [ + 'type' => 'category', + 'title' => 'Database', + ], + [ + 'type' => 'section', + 'title' => 'Database', + ], + 'database_overwrite' => [ + 'name' => 'Database Manual', + 'type' => 'boolean', + 'desc' => 'Manual database configuration. Enable if you want to manually enter database details. If set to no - it will get from config.lua', + 'default' => false, + 'is_config' => true, + ], + 'database_host' => [ + 'name' => 'Database Host', + 'type' => 'text', + 'default' => '127.0.0.1', + 'show_if' => [ + 'database_overwrite', '=', 'true' + ], + 'is_config' => true, + ], + 'database_port' => [ + 'name' => 'Database Port', + 'type' => 'number', + 'default' => 3306, + 'show_if' => [ + 'database_overwrite', '=', 'true' + ], + 'is_config' => true, + ], + 'database_user' => [ + 'name' => 'Database User', + 'type' => 'text', + 'default' => '', + 'show_if' => [ + 'database_overwrite', '=', 'true' + ], + 'is_config' => true, + ], + 'database_password' => [ + 'name' => 'Database Password', + 'type' => 'text', + 'default' => '', + 'show_if' => [ + 'database_overwrite', '=', 'true' + ], + 'is_config' => true, + ], + 'database_name' => [ + 'name' => 'Database Name', + 'type' => 'text', + 'default' => '', + 'show_if' => [ + 'database_overwrite', '=', 'true' + ], + 'is_config' => true, + ], + 'database_socket' => [ + 'name' => 'Database Socket', + 'desc' => 'Set if you want to connect to database through socket (example: /var/run/mysqld/mysqld.sock)', + 'type' => 'text', + 'default' => '', + 'show_if' => [ + 'database_overwrite', '=', 'true' + ], + 'is_config' => true, + ], + 'database_hash' => [ + 'name' => 'Database Hashing Algorithm', + 'desc' => 'Hashing algorithm: sha1 or md5 are most common', + 'type' => 'text', + 'default' => 'sha1', + 'show_if' => [ + 'database_overwrite', '=', 'true' + ], + 'is_config' => true, + ], + 'database_log' => [ + 'name' => 'Database Log', + 'desc' => 'Should database queries be logged and saved into system/logs/database.log?', + 'type' => 'boolean', + 'default' => false, + 'is_config' => true, + ], + 'database_persistent' => [ + 'name' => 'Database Persistent Connection', + 'desc' => 'Use database permanent connection (like server), may speed up your site', + 'type' => 'boolean', + 'default' => false, + 'is_config' => true, + ], + [ + 'type' => 'category', + 'title' => 'Mailing', + ], + [ + 'type' => 'section', + 'title' => 'Mailing' + ], + 'mail_enabled' => [ + 'name' => 'Mailing enabled', + 'type' => 'boolean', + 'desc' => 'Is AAC configured to send e-mails?', + 'default' => false, + /*'script' => <<<'SCRIPT' + +SCRIPT,*/ + ], + 'mail_address' => [ + 'name' => 'Mail Address', + 'type' => 'email', + 'desc' => 'Server e-mail address (from:)', + 'default' => 'no-reply@your-server.org', + 'show_if' => [ + 'mail_enabled', '=', 'true' + ], + ], + /*'mail_admin' => [ + 'name' => 'Mail Admin Address', + 'type' => 'email', + 'desc' => 'Admin email address, where mails from contact form will be sent', + 'default' => 'your-address@your-server.org', + ],*/ + 'mail_signature_plain' => [ + 'name' => 'Mail Signature (Plain)', + 'type' => 'textarea', + 'desc' => 'Signature that will be included at the end of every message sent.
    In Normal Format!', + 'default' => '-- +Sent by MyAAC, +https://my-aac.org', + 'show_if' => [ + 'mail_enabled', '=', 'true' + ] + ], + 'mail_signature_html' => [ + 'name' => 'Mail Signature (HTML)', + 'type' => 'textarea', + 'desc' => 'Signature that will be included at the end of every message sent.
    In HTML Format!', + 'default' => escapeHtml('
    +Sent by MyAAC,
    +my-aac.org'), + 'show_if' => [ + 'mail_enabled', '=', 'true' + ] + ], + 'section_smtp' => [ + 'type' => 'section', + 'title' => 'SMTP (Mail Server)', + 'show_if' => [ + 'mail_enabled', '=', 'true' + ] + ], + 'mail_option' => [ + 'name' => 'Mail Option', + 'type' => 'options', + 'options' => [0 => 'Mail (PHP Built-in)', 1 => 'SMTP (Gmail or Microsoft Outlook)'], + 'desc' => 'Mail sender. Set to SMTP if using Gmail or Microsoft Outlook, or any other provider', + 'default' => 0, + 'show_if' => [ + 'mail_enabled', '=', 'true' + ] + ], + 'smtp_host' => [ + 'name' => 'SMTP Host', + 'type' => 'text', + 'desc' => 'SMTP mail host. smtp.gmail.com for GMail / smtp-mail.outlook.com for Microsoft Outlook', + 'default' => '', + 'show_if' => [ + 'mail_enabled', '=', 'true' + ] + ], + 'smtp_port' => [ + 'name' => 'SMTP Host', + 'type' => 'number', + 'desc' => '25 (default) / 465 (ssl, GMail) / 587 (tls, Microsoft Outlook)', + 'default' => 25, + 'show_if' => [ + 'mail_enabled', '=', 'true' + ] + ], + 'smtp_auth' => [ + 'name' => 'SMTP Auth', + 'type' => 'boolean', + 'desc' => 'Need authorization for Server? In normal situation, almost always Yes.', + 'default' => true, + 'show_if' => [ + 'mail_enabled', '=', 'true' + ] + ], + 'smtp_user' => [ + 'name' => 'SMTP Username', + 'type' => 'text', + 'desc' => 'Here your email username to authenticate with SMTP', + 'default' => 'admin@example.org', + 'show_if' => [ + 'mail_enabled', '=', 'true' + ] + ], + 'smtp_pass' => [ + 'name' => 'SMTP Password', + 'type' => 'password', + 'desc' => 'Here your email password to authenticate with SMTP', + 'default' => '', + 'show_if' => [ + 'mail_enabled', '=', 'true' + ] + ], + 'smtp_security' => [ + 'name' => 'SMTP Security', + 'type' => 'options', + 'options' => ['None', 'SSL', 'TLS'], + 'desc' => 'What kind of encryption to use on the SMTP connection', + 'default' => 0, + 'show_if' => [ + 'mail_enabled', '=', 'true' + ] + ], + 'smtp_debug' => [ + 'name' => 'SMTP Debug', + 'type' => 'boolean', + 'desc' => 'Activate to see more logs about mailing errors in error.log', + 'default' => false, + 'show_if' => [ + 'mail_enabled', '=', 'true' + ] + ], + 'mail_other' => [ + 'type' => 'section', + 'title' => 'Account E-Mails', + 'show_if' => [ + 'mail_enabled', '=', 'true' + ], + ], + 'account_welcome_mail' => [ + 'name' => 'Account Welcome E-Mail', + 'type' => 'boolean', + 'desc' => 'Send welcome e-mail when user registers', + 'default' => true, + 'show_if' => [ + 'mail_enabled', '=', 'true' + ], + ], + 'account_mail_verify' => [ + 'name' => 'Account E-Mail Verify', + 'type' => 'boolean', + 'desc' => 'Force users to confirm their e-mail addresses when registering account', + 'default' => false, + 'show_if' => [ + 'mail_enabled', '=', 'true' + ], + ], + 'mail_send_when_change_password' => [ + 'name' => 'Change Password E-Mail', + 'type' => 'boolean', + 'desc' => 'Send e-mail with new password when change password to account', + 'default' => true, + 'show_if' => [ + 'mail_enabled', '=', 'true', + ], + ], + 'mail_send_when_generate_reckey' => [ + 'name' => 'Generate Recovery Key E-Mail', + 'type' => 'boolean', + 'desc' => 'Send e-mail with recovery key (key is displayed on page anyway when generate)', + 'default' => true, + 'show_if' => [ + 'mail_enabled', '=', 'true', + ], + ], + 'mail_lost_account_interval' => [ + 'name' => 'Mail Lost Interface Interval', + 'type' => 'number', + 'desc' => 'Time in seconds between e-mails to one account from lost account interface, block spam', + 'default' => 60, + 'show_if' => [ + 'mail_enabled', '=', 'true', + ], + ], + [ + 'type' => 'category', + 'title' => 'Accounts', + ], + [ + 'type' => 'section', + 'title' => 'Accounts Settings' + ], + 'account_management' => [ + 'name' => 'Enable Account Management', + 'type' => 'boolean', + 'desc' => "disable if you're using other method to manage users (fe. tfs account manager)", + 'default' => true, + ], + 'account_login_by_email' => [ + 'name' => 'Account Login By E-Mail', + 'type' => 'boolean', + 'desc' => "use email instead of Account Name like in latest Tibia", + 'default' => true, + ], + 'account_login_by_email_fallback' => [ + 'name' => 'Account Login By E-Mail Fallback', + 'type' => 'boolean', + 'desc' => "allow also additionally login by Account Name/Number (for users that might forget their email). Works only if Account Login By E-Mail is also enabled", + 'default' => false, + 'show_if' => [ + 'account_login_by_email', '=', 'true' + ], + ], + 'account_create_auto_login' => [ + 'name' => 'Account Create Auto Login', + 'type' => 'boolean', + 'desc' => 'Auto login after creating account?', + 'default' => false, + ], + 'account_create_character_create' => [ + 'name' => 'Account Create Character Create', + 'type' => 'boolean', + 'desc' => 'Allow to create character directly on create account page?', + 'default' => true, + ], + 'account_mail_unique' => [ + 'name' => 'Account Mail Unique', + 'type' => 'boolean', + 'desc' => 'Email addresses cannot be duplicated? (one account = one email)', + 'default' => true, + ], + 'account_premium_days' => [ + 'name' => 'Default Account Premium Days', + 'type' => 'number', + 'desc' => 'Default premium days on new account', + 'default' => 0, + ], + 'account_premium_points' => [ + 'name' => 'Default Account Premium Points', + 'type' => 'number', + 'desc' => 'Default premium points on new account', + 'default' => 0, + ], + 'account_mail_change' => [ + 'name' => 'Account Mail Change Days', + 'type' => 'number', + 'desc' => 'How many days user need to change email to account - block hackers', + 'default' => 2, + ], + 'account_mail_block_plus_sign' => [ + 'name' => 'Account Mail Block Plus Sign (+)', + 'type' => 'boolean', + 'desc' => "Block E-Mails with '+' signs like test+box@gmail.com (help protect against spamming accounts)", + 'default' => true, + ], + 'account_country' => [ + 'name' => 'Account Country', + 'type' => 'boolean', + 'desc' => 'User will be able to set country of origin when registering account, this information will be viewable in others places as well', + 'default' => true, + ], + 'account_country_recognize' => [ + 'name' => 'Auto Recognize Account Country', + 'type' => 'boolean', + 'desc' => 'should country of user be automatically recognized by his IP? This makes an external API call to http://ipinfo.io', + 'default' => true, + ], + 'characters_per_account' => [ + 'name' => 'Characters per Account', + 'type' => 'number', + 'desc' => 'Max. number of characters per account', + 'default' => 10, + ], + 'create_character' => [ + 'type' => 'section', + 'title' => 'Create Character', + ], + 'character_samples' => [ + 'name' => 'Character Samples', + 'type' => 'textarea', + 'desc' => "Character Samples used when creating character.
    " . + "Format: ID_of_vocation =Name of Character to copy
    " . + "For Rook use - 0=Rook Sample", + 'default' => "1=Sorcerer Sample\n2=Druid Sample\n3=Paladin Sample\n4=Knight Sample", + 'callbacks' => [ + 'get' => function ($value) { + $ret = []; + $vocs = array_map('trim', preg_split('/\r\n|\r|\n/', trim($value))); + + foreach ($vocs as $voc) { + if (empty($voc)) { + continue; + } + + $explode = explode('=', $voc); + $ret[$explode[0]] = $explode[1]; + } + + return $ret; + }, + ], + ], + 'character_towns' => [ + 'name' => 'Towns List', + 'type' => 'text', + 'desc' => "Towns List used when creating character separated by comma (,). Won't be displayed if there is only one item (rookgaard for example)", + 'default' => '1,2', + 'callbacks' => [ + 'get' => function ($value) { + return array_map('trim', explode(',', $value)); + }, + ], + ], + 'create_character_name_min_length' => [ + 'name' => 'Name Min Length', + 'type' => 'number', + 'desc' => '', + 'default' => 4, + ], + 'create_character_name_max_length' => [ + 'name' => 'Name Max Length', + 'type' => 'number', + 'desc' => 'It is highly recommend the maximum length to be 21', + 'default' => 21, + ], + 'create_character_name_blocked_prefix' => [ + 'name' => 'Create Character Name Blocked Prefix', + 'type' => 'textarea', + 'desc' => 'Space after is important!', + 'default' => 'admin ,administrator ,gm ,cm ,god ,tutor', + 'callbacks' => [ + 'get' => function ($value) { + return explode(',', $value); + }, + ], + ], + 'create_character_name_blocked_names' => [ + 'name' => 'Create Character Name Blocked Names', + 'type' => 'textarea', + 'desc' => 'Separated by comma (,)', + 'default' => 'admin,administrator,gm,cm,god,tutor', + 'callbacks' => [ + 'get' => function ($value) { + return array_map('trim', explode(',', $value)); + }, + ], + ], + 'create_character_name_blocked_words' => [ + 'name' => 'Create Character Name Blocked Words', + 'type' => 'textarea', + 'desc' => 'Separated by comma (,)', + 'default' => "admin,administrator,gamemaster,game master,game-master,game'master,fuck,sux,suck,noob,tutor", + 'callbacks' => [ + 'get' => function ($value) { + return array_map('trim', explode(',', $value)); + }, + ], + ], + 'create_character_name_monsters_check' => [ + 'name' => 'Block Monsters Names', + 'type' => 'boolean', + 'desc' => 'Should monsters names be blocked when creating character?', + 'default' => true, + ], + 'create_character_name_npc_check' => [ + 'name' => 'Block NPC Names', + 'type' => 'boolean', + 'desc' => 'Should NPC names be blocked when creating character?', + 'default' => true, + ], + 'create_character_name_spells_check' => [ + 'name' => 'Block Spells Names', + 'type' => 'boolean', + 'desc' => 'Should spells names and words be blocked when creating character?', + 'default' => true, + ], + 'use_character_sample_skills' => [ + 'name' => 'Use Character Sample Skills', + 'type' => 'boolean', + 'desc' => 'No = default skill = 10, yes - use sample skills', + 'default' => false, + ], + 'account_mail_confirmed_reward' => [ + 'type' => 'section', + 'title' => 'Reward Users for confirming their E-Mails. Works only with Account Mail Verify enabled', + 'show_if' => [ + 'account_mail_verify', '=', 'true' + ], + ], + 'account_mail_confirmed_reward_premium_days' => [ + 'name' => 'Reward Premium Days', + 'type' => 'number', + 'desc' => '0 to disable', + 'default' => 0, + 'show_if' => [ + 'account_mail_verify', '=', 'true' + ], + ], + 'account_mail_confirmed_reward_premium_points' => [ + 'name' => 'Reward Premium Points', + 'type' => 'number', + 'desc' => '0 to disable', + 'default' => 0, + 'show_if' => [ + 'account_mail_verify', '=', 'true' + ], + ], + 'account_mail_confirmed_reward_coins' => [ + 'name' => 'Reward Coins', + 'type' => 'number', + 'desc' => '0 to disable. Works only with servers that supports coins', + 'default' => 0, + 'show_if' => [ + 'account_mail_verify', '=', 'true' + ], + ], + [ + 'type' => 'category', + 'title' => 'Guilds', + ], + [ + 'type' => 'section', + 'title' => 'Guilds' + ], + 'guild_management' => [ + 'name' => 'Enable Guilds Management', + 'type' => 'boolean', + 'desc' => 'Enable guild management system on the site', + 'default' => true, + ], + 'guild_need_level' => [ + 'name' => 'Guild Need Level', + 'type' => 'number', + 'desc' => 'Min. level to form a guild', + 'default' => 1, + 'show_if' => [ + 'guild_management', '=', 'true', + ], + ], + 'guild_need_premium' => [ + 'name' => 'Guild Need Premium', + 'type' => 'boolean', + 'desc' => 'Require premium account to form a guild?', + 'default' => true, + 'show_if' => [ + 'guild_management', '=', 'true', + ], + ], + 'guild_image_size_kb' => [ + 'name' => 'Guild Image Size', + 'type' => 'number', + 'desc' => 'Maximum size of the guild logo image in KB (kilobytes)', + 'default' => 80, + 'show_if' => [ + 'guild_management', '=', 'true', + ], + ], + 'guild_description_default' => [ + 'name' => 'Default Guild Description', + 'type' => 'text', + 'desc' => 'Default description set on new guild', + 'default' => 'New guild. Leader must edit this text :)', + 'show_if' => [ + 'guild_management', '=', 'true', + ], + ], + 'guild_description_chars_limit' => [ + 'name' => 'Guild Description Characters Limit', + 'type' => 'number', + 'desc' => 'How many characters can be in guild description', + 'default' => 1000, + 'show_if' => [ + 'guild_management', '=', 'true', + ], + ], + 'guild_description_lines_limit' => [ + 'name' => 'Guild Description Lines Limit', + 'type' => 'number', + 'desc' => "Limit of lines, if description has more lines it will be showed as long text, without 'enters'", + 'default' => 6, + 'show_if' => [ + 'guild_management', '=', 'true', + ], + ], + 'guild_motd_chars_limit' => [ + 'name' => 'Guild MOTD Characters Limit', + 'type' => 'number', + 'desc' => 'Limit of MOTD (message of the day) that is shown later in the game on the guild channel', + 'default' => 150, + 'show_if' => [ + 'guild_management', '=', 'true', + ], + ], + [ + 'type' => 'category', + 'title' => 'Pages', + ], + [ + 'type' => 'section', + 'title' => 'News Page', + ], + 'news_author' => [ + 'name' => 'News Author', + 'type' => 'boolean', + 'desc' => 'Show author of the news', + 'default' => true, + ], + 'news_limit' => [ + 'name' => 'News Limit', + 'type' => 'number', + 'min' => 0, + 'desc' => 'Limit of news on the latest news page (0 to disable)', + 'default' => 5, + ], + 'news_ticker_limit' => [ + 'name' => 'News Ticker Limit', + 'type' => 'number', + 'min' => 0, + 'desc' => 'Limit of news in tickers (mini news) (0 to disable)', + 'default' => 5, + ], + 'news_date_format' => [ + 'name' => 'News Date Format', + 'type' => 'text', + 'desc' => 'Check php manual date() function for more info about this', + 'default' => 'j.n.Y', + ], + [ + 'type' => 'section', + 'title' => 'Forum' + ], + 'forum' => [ + 'name' => 'Forum', + 'type' => 'text', + 'desc' => 'Do you want to use built-in forum feature? Enter "site" if you want to use built-in forum feature, if you want use custom forum - enter URL here, otherwise leave empty (to disable)', + 'default' => 'site', + ], + 'forum_level_required' => [ + 'name' => 'Forum Level Required', + 'type' => 'number', + 'desc' => 'Level required to post on forum. 0 to disable', + 'min' => 0, + 'max' => 99999999999, + 'default' => 0, + 'show_if' => [ + 'forum', '=', 'site', + ], + ], + 'forum_post_interval' => [ + 'name' => 'Forum Post Interval', + 'type' => 'number', + 'desc' => 'How often user can post on forum, in seconds', + 'min' => 0, + 'max' => 99999999999, + 'default' => 30, + 'show_if' => [ + 'forum', '=', 'site', + ], + ], + 'forum_posts_per_page' => [ + 'name' => 'Forum Posts per Page', + 'type' => 'number', + 'desc' => 'How many posts per page', + 'min' => 0, + 'max' => 99999999999, + 'default' => 20, + 'show_if' => [ + 'forum', '=', 'site', + ], + ], + 'forum_threads_per_page' => [ + 'name' => 'Forum Threads per Page', + 'type' => 'number', + 'desc' => 'How many threads per page', + 'min' => 0, + 'max' => 99999999999, + 'default' => 20, + 'show_if' => [ + 'forum', '=', 'site', + ], + ], + 'forum_table_prefix' => [ + 'name' => 'Forum Table Prefix', + 'type' => 'text', + 'desc' => 'What forum mysql table to use, z_ (for gesior old forum) or myaac_ (for myaac)', + 'default' => 'myaac_', + 'show_if' => [ + 'forum', '=', 'site', + ], + ], + [ + 'type' => 'section', + 'title' => 'Highscores Page', + ], + 'highscores_per_page' => [ + 'name' => 'Highscores per Page', + 'type' => 'number', + 'min' => 1, + 'desc' => 'How many records per page on highscores', + 'default' => 100, + ], + 'highscores_cache_ttl' => [ + 'name' => 'Highscores Cache TTL (in minutes)', + 'type' => 'number', + 'min' => 1, + 'desc' => 'How often to update highscores from database in minutes (default 15 minutes). Too low may cause lags on website.', + 'default' => 15, + ], + 'highscores_vocation_box' => [ + 'name' => 'Display Vocation Box', + 'type' => 'boolean', + 'desc' => 'show "Choose a vocation" box on the highscores (allowing peoples to sort highscores by vocation)?', + 'default' => true, + ], + 'highscores_vocation' => [ + 'name' => 'Display Vocation', + 'type' => 'boolean', + 'desc' => 'Show player vocation under his nickname?', + 'default' => true, + ], + 'highscores_frags' => [ + 'name' => 'Display Top Frags', + 'type' => 'boolean', + 'desc' => 'Show "Frags" tab (best fraggers on the server)?', + 'default' => false, + ], + 'highscores_balance' => [ + 'name' => 'Display Balance', + 'type' => 'boolean', + 'desc' => 'Show "Balance" tab (richest players on the server)?', + 'default' => false, + ], + 'highscores_outfit' => [ + 'name' => 'Display Player Outfit', + 'type' => 'boolean', + 'desc' => 'Show player outfit?', + 'default' => true, + ], + 'highscores_country_box' => [ // not implemented yet + 'name' => 'Display Country Box', + 'type' => 'hidden', + 'desc' => 'Show player outfit?', + 'default' => false, + ], + 'highscores_groups_hidden' => [ + 'name' => 'Hidden Groups', + 'type' => 'number', + 'desc' => "This group id and higher won't be shown on highscores", + 'default' => 3, + ], + 'highscores_ids_hidden' => [ + 'name' => 'Hidden IDs of players', + 'type' => 'textarea', + 'desc' => "this ids of players will be hidden on the highscores (should be ids of samples)", + 'default' => '0', + 'callbacks' => [ + 'get' => function ($value) { + return array_map('trim', explode(',', $value)); + }, + ], + ], + [ + 'type' => 'section', + 'title' => 'Characters Page', + ], + 'characters_search_limit' => [ + 'name' => 'Characters Search Limit', + 'type' => 'number', + 'desc' => "How many characters (players) to show when using search function", + 'default' => 15, + ], + 'characters_level' => [ + 'name' => 'Display Level', + 'type' => 'boolean', + 'desc' => 'Show characters level', + 'default' => true, + ], + 'characters_experience' => [ + 'name' => 'Display Experience', + 'type' => 'boolean', + 'desc' => 'Show characters experience points', + 'default' => false, + ], + 'characters_magic_level' => [ + 'name' => 'Display Magic Level', + 'type' => 'boolean', + 'desc' => 'Show characters magic level', + 'default' => false, + ], + 'characters_balance' => [ + 'name' => 'Display Balance', + 'type' => 'boolean', + 'desc' => 'Show characters bank balance', + 'default' => false, + ], + 'characters_marriage' => [ + 'name' => 'Display Marriage', + 'type' => 'boolean', + 'desc' => 'Show characters marriage info. Works only in TFS 0.3', + 'default' => true, + ], + 'characters_outfit' => [ + 'name' => 'Display Outfit', + 'type' => 'boolean', + 'desc' => 'Show characters outfit', + 'default' => true, + ], + 'characters_creation_date' => [ + 'name' => 'Display Creation Date', + 'type' => 'boolean', + 'desc' => 'Show characters date of creation', + 'default' => true, + ], + 'characters_quests' => [ + 'name' => 'Display Quests', + 'type' => 'boolean', + 'desc' => 'Show characters quests. Can be configured below', + 'default' => true, + ], + 'quests' => [ + 'name' => 'Quests List', + 'type' => 'textarea', + 'desc' => 'Character Quests List. Format: NameOfQuest=StorageValue', + 'default' => "Some Quest=123\nSome Quest Two=456", + 'show_if' => [ + 'characters_quests', '=', 'true' + ], + 'callbacks' => [ + 'get' => function ($value) { + $ret = []; + $quests = array_map('trim', preg_split('/\r\n|\r|\n/', trim($value))); + + foreach ($quests as $quest) { + if (empty($quest)) { + continue; + } + + $explode = explode('=', $quest); + $ret[$explode[0]] = $explode[1]; + } + + return $ret; + }, + ], + ], + 'characters_skills' => [ + 'name' => 'Display Skills', + 'type' => 'boolean', + 'desc' => 'Show characters skills', + 'default' => true, + ], + 'characters_equipment' => [ + 'name' => 'Display Equipment', + 'type' => 'boolean', + 'desc' => 'Show characters equipment', + 'default' => true, + ], + 'characters_frags' => [ + 'name' => 'Display Frags', + 'type' => 'boolean', + 'desc' => 'Show characters frags', + 'default' => false, + ], + 'characters_deleted' => [ + 'name' => 'Display Deleted', + 'type' => 'boolean', + 'desc' => 'Should deleted characters from same account be still listed on the list of characters? When enabled it will show that character is "[DELETED]', + 'default' => false, + ], + [ + 'type' => 'section', + 'title' => 'Online Page' + ], + 'online_record' => [ + 'name' => 'Display Players Record', + 'type' => 'boolean', + 'desc' => '', + 'default' => true, + ], + 'online_vocations' => [ + 'name' => 'Display Vocation Statistics', + 'type' => 'boolean', + 'desc' => '', + 'default' => false, + ], + 'online_vocations_images' => [ + 'name' => 'Display Vocation Images', + 'type' => 'boolean', + 'desc' => 'Only if Display Vocation Statistics enabled', + 'default' => true, + ], + 'online_skulls' => [ + 'name' => 'Display Skull Images', + 'type' => 'boolean', + 'desc' => '', + 'default' => true, + ], + 'online_outfit' => [ + 'name' => 'Display Player Outfit', + 'type' => 'boolean', + 'desc' => '', + 'default' => true, + ], + 'online_afk' => [ + 'name' => 'Display AFK Players', + 'type' => 'boolean', + 'desc' => '', + 'default' => false, + ], + [ + 'type' => 'section', + 'title' => 'Team Page' + ], + 'team_style' => [ + 'name' => 'Style', + 'type' => 'options', + 'desc' => '', + 'options' => ['normal table', 'in boxes, grouped by group id'], + 'default' => 1, + ], + 'team_status' => [ + 'name' => 'Display Online Status', + 'type' => 'boolean', + 'desc' => '', + 'default' => true, + ], + 'team_lastlogin' => [ + 'name' => 'Display Last Login', + 'type' => 'boolean', + 'desc' => '', + 'default' => true, + ], + 'team_world' => [ + 'name' => 'Display World', + 'type' => 'boolean', + 'desc' => '', + 'default' => false, + ], + 'team_outfit' => [ + 'name' => 'Display Outfit', + 'type' => 'boolean', + 'desc' => '', + 'default' => true, + ], + [ + 'type' => 'section', + 'title' => 'Bans Page' + ], + 'bans_per_page' => [ + 'name' => 'Bans per Page', + 'type' => 'number', + 'min' => 1, + 'default' => 20, + 'desc' => '', + ], + [ + 'type' => 'section', + 'title' => 'Last Kills Page' + ], + 'last_kills_limit' => [ + 'name' => 'Last Kills Limit', + 'type' => 'number', + 'desc' => 'Max. number of kills shown on the last kills page', + 'default' => 50, + ], + [ + 'type' => 'section', + 'title' => 'Experience Table Page' + ], + 'experience_table_columns' => [ + 'name' => 'Columns', + 'type' => 'number', + 'desc' => 'How many columns to display in experience table page, * rows, 5 = 500 (will show up to 500 level)', + 'default' => 3, + ], + 'experience_table_rows' => [ + 'name' => 'Rows', + 'type' => 'number', + 'desc' => 'Till how many levels in one column', + 'default' => 200, + ], + [ + 'type' => 'category', + 'title' => 'Images', + ], + [ + 'type' => 'section', + 'title' => 'Signatures' + ], + 'signature_enabled' => [ + 'name' => 'Enable Signatures', + 'type' => 'boolean', + 'desc' => 'Signature is a small picture with character info and server to paste on forums etc. It can be viewed on characters page, when enabled.', + 'default' => true, + ], + 'signature_type' => [ + 'name' => 'Signature Type', + 'type' => 'options', + 'options' => ['tibian' => 'tibian', 'mango' => 'mango', 'gesior' => 'gesior'], + 'desc' => 'Signature engine to use', + 'default' => 'tibian', + 'show_if' => [ + 'signature_enabled', '=', 'true' + ], + ], + 'signature_cache_time' => [ + 'name' => 'Signature Cache Time', + 'type' => 'number', + 'min' => 1, + 'desc' => 'How long to store cached file (in minutes)', + 'default' => 5, + 'show_if' => [ + 'signature_enabled', '=', 'true', + ], + ], + 'signature_browser_cache' => [ + 'name' => 'Signature Browser Cache Time', + 'type' => 'number', + 'min' => 1, + 'desc' => 'How long to cache by browser (in minutes)', + 'default' => 60, + 'show_if' => [ + 'signature_enabled', '=', 'true', + ], + ], + [ + 'type' => 'section', + 'title' => 'Item Images' + ], + 'item_images_url' => [ + 'name' => 'Item Images URL', + 'type' => 'text', + 'desc' => 'Set to images/items if you host your own items in images folder', + 'default' => 'http://item-images.ots.me/1092/', + ], + 'item_images_extension' => [ + 'name' => 'Item Images File Extension', + 'type' => 'text', + 'desc' => '', + 'default' => '.gif', + ], + [ + 'type' => 'section', + 'title' => 'Outfit Images' + ], + 'outfit_images_url' => [ + 'name' => 'Outfit Images URL', + 'type' => 'text', + 'desc' => 'Set to animoutfit.php for animated outfit', + 'default' => 'http://outfit-images.ots.me/outfit.php', + ], + 'outfit_images_wrong_looktypes' => [ + 'name' => 'Outfit Images Wrong Looktypes', + 'type' => 'text', + 'desc' => 'This looktypes needs to have different margin-top and margin-left because they are wrong positioned', + 'default' => '75, 126, 127, 266, 302', + 'callbacks' => [ + 'get' => function ($value) { + return array_map('trim', explode(',', $value)); + }, + ], + ], + [ + 'type' => 'section', + 'title' => 'Monster Images' + ], + 'monsters_images_url' => [ + 'name' => 'Monsters Images URL', + 'type' => 'text', + 'desc' => 'Set to images/monsters/ if you host your own creatures in images folder', + 'default' => 'images/monsters/', + ], + 'monsters_images_extension' => [ + 'name' => 'Monsters Images File Extension', + 'type' => 'text', + 'desc' => '', + 'default' => '.gif', + ], + 'monsters_images_preview' => [ + 'name' => 'Monsters Images Preview', + 'type' => 'boolean', + 'desc' => 'Set to yes to allow picture previews for creatures', + 'default' => false, + ], + 'monsters_items_url' => [ + 'name' => 'Monsters Items URL', + 'type' => 'text', + 'desc' => 'Set to website which shows details about items', + 'default' => 'https://tibia.fandom.com/wiki/', + ], + 'monsters_loot_percentage' => [ + 'name' => 'Monsters Items URL', + 'type' => 'boolean', + 'desc' => 'Set to yes to show the loot tooltip percent', + 'default' => true, + ], + // this is hidden, because no implemented yet + 'multiworld' => [ + 'hidden' => true, + 'type' => 'boolean', + 'default' => false, + ], + [ + 'type' => 'category', + 'title' => 'Status', + ], + [ + 'type' => 'section', + 'title' => 'Server Status' + ], + 'status_enabled' => [ + 'name' => 'Enable Server Status', + 'type' => 'boolean', + 'desc' => 'You can disable status checking here', + 'default' => true, + ], + 'status_ip' => [ + 'name' => 'Status IP', + 'type' => 'text', + 'desc' => 'Leave empty to get automatically from config', + 'default' => '127.0.0.1', + 'show_if' => [ + 'status_enabled', '=', 'true', + ] + ], + 'status_port' => [ + 'name' => 'Status Port', + 'type' => 'number', + 'min' => 0, + 'desc' => 'Leave empty to get automatically from config', + 'default' => 7171, + 'show_if' => [ + 'status_enabled', '=', 'true', + ] + ], + 'status_timeout' => [ + 'name' => 'Status Timeout', + 'type' => 'number', + 'min' => 0, + 'max' => 10, // more than 10 seconds waiting makes no sense + 'step' => 0.1, + 'desc' => 'How long to wait for the initial response from the server', + 'default' => 2.0, + 'show_if' => [ + 'status_enabled', '=', 'true', + ] + ], + 'status_interval' => [ + 'name' => 'Status Interval', + 'type' => 'number', + 'min' => 0, + 'desc' => 'How often to connect to server and update status.
    If your status timeout in config.lua is bigger, that it will be used instead. When server is offline, it will be checked every time web refreshes, ignoring this variable', + 'default' => 60, + 'show_if' => [ + 'status_enabled', '=', 'true', + ] + ], + [ + 'type' => 'category', + 'title' => 'Admin', + ], + [ + 'type' => 'section', + 'title' => 'Admin Panel' + ], + 'admin_plugins_manage_enable' => [ + 'name' => 'Enable Plugins Manage', + 'type' => 'boolean', + 'desc' => 'You can disable possibility to upload, enable/disable and uninstall plugins, for security', + 'default' => true, + ], + 'admin_pages_php_enable' => [ + 'name' => 'Enable PHP Pages', + 'type' => 'boolean', + 'desc' => 'You can disable support for plain php pages in admin panel, for security.
    Existing pages still will be working, so you need to delete them manually', + 'default' => false, + ], + 'admin_panel_modules' => [ + 'name' => 'Modules Enabled', + 'type' => 'textarea', + 'desc' => 'What modules will be shown on Admin Panel Dashboard page', + 'default' => 'statistics,web_status,server_status,lastlogin,created,points,coins,balance', + 'callbacks' => [ + 'get' => function ($value) { + return array_map('trim', explode(',', $value)); + }, + ], + ], + [ + 'type' => 'category', + 'title' => 'Shop', + ], + [ + 'type' => 'section', + 'title' => 'Gifts/shop system' + ], + 'gifts_system' => [ + 'name' => 'Enable gifts system', + 'desc' => 'Plugin needs to be installed', + 'type' => 'boolean', + 'default' => false, + ], + 'donate_column' => [ + 'name' => 'Donate Column', + 'type' => 'options', + 'desc' => 'What to give to player after donation - what column in accounts table to use.', + 'options' => ['premium_points' => 'Premium Points', 'coins' => 'Coins'], + 'default' => 'premium_points', + 'callbacks' => [ + 'beforeSave' => function($key, $value, &$errorMessage) { + global $db; + if ($value == 'coins' && !$db->hasColumn('accounts', 'coins')) { + $errorMessage = "Shop: Donate Column: Cannot set column to coins, because it doesn't exist in database."; + return false; + } + return true; + } + ] + ], + 'account_generate_new_reckey' => [ + 'name' => 'Allow Generate New Key', + 'desc' => "Allow to generate new key for premium points. The player will receive e-mail with new rec key (not display on page, hacker can't generate rec key)", + 'type' => 'boolean', + 'default' => false, + ], + 'account_generate_new_reckey_price' => [ + 'name' => 'Generate New Key Price', + 'type' => 'number', + 'min' => 0, + 'desc' => 'Price for new recovery key', + 'default' => 20, + 'show_if' => [ + 'account_generate_new_reckey', '=', 'true', + ], + ], + 'account_change_character_name' => [ + 'name' => 'Allow Change Name', + 'desc' => 'Can user change their character name for premium points?', + 'type' => 'boolean', + 'default' => false, + ], + 'account_change_character_name_price' => [ + 'name' => 'Change Name Price', + 'type' => 'number', + 'min' => 0, + 'desc' => 'Cost of name change', + 'default' => 30, + 'show_if' => [ + 'account_change_character_name', '=', 'true', + ], + ], + 'account_change_character_sex' => [ + 'name' => 'Allow Change Sex', + 'desc' => 'Can user change their character sex for premium points?', + 'type' => 'boolean', + 'default' => false, + ], + 'account_change_character_sex_price' => [ + 'name' => 'Change Sex Price', + 'type' => 'number', + 'min' => 0, + 'desc' => 'Cost of change sex', + 'default' => 30, + 'show_if' => [ + 'account_change_character_sex', '=', 'true', + ], + ], + ], + 'callbacks' => [ + 'beforeSave' => function(&$settings, &$values) { + global $config; + + $configToSave = []; + + $server_path = ''; + $database = []; + foreach ($settings['settings'] as $key => $value) { + if (isset($value['is_config']) && getBoolean($value['is_config'])) { + if ($value['type'] === 'boolean') { + $values[$key] = ($values[$key] === 'true'); + } + elseif ($value['type'] === 'number') { + $values[$key] = (int)$values[$key]; + } + //elseif ($value['type'] === 'options') { + // + //} + + $configToSave[$key] = $values[$key]; + + if ($key == 'server_path') { + $server_path = $values[$key]; + } + elseif (strpos($key, 'database_') !== false) { + $database[$key] = $values[$key]; + } + + unset($settings[$key]); + unset($values[$key]); + } + } + + if($server_path[strlen($server_path) - 1] != '/') + $server_path .= '/'; + + // test config.lua existence + // if fail - revert the setting and inform the user + if (!file_exists($server_path . 'config.lua')) { + error('Server Path is invalid - cannot find config.lua in the directory. Setting have been reverted.'); + $configToSave['server_path'] = $config['server_path']; + } + + // test database connection + // if fail - revert the setting and inform the user + if ($database['database_overwrite'] && !Settings::testDatabaseConnection($database)) { + foreach ($database as $key => $value) { + if (!in_array($key, ['database_log', 'database_persistent'])) { // ignore these two + $configToSave[$key] = $config[$key]; + } + } + } + + return Settings::saveConfig($configToSave, BASE . 'config.local.php'); + }, + ], +]; + diff --git a/system/status.php b/system/status.php index 86cba2ed..310e4127 100644 --- a/system/status.php +++ b/system/status.php @@ -17,7 +17,7 @@ $status['lastCheck'] = 0; $status['uptime'] = '0h 0m'; $status['monsters'] = 0; -if(config('status_enabled') === false) { +if(setting('core.status_enabled') === false) { return; } @@ -37,9 +37,10 @@ else if(isset($config['lua']['status_port'])) { } // ip check -if(isset($config['status_ip'][0])) +$settingIP = setting('core.status_ip'); +if(isset($settingIP[0])) { - $status_ip = $config['status_ip']; + $status_ip = $settingIP; } elseif(!isset($status_ip[0])) // try localhost if no ip specified { @@ -48,10 +49,11 @@ elseif(!isset($status_ip[0])) // try localhost if no ip specified // port check $status_port = $config['lua']['statusPort']; -if(isset($config['status_port'][0])) { - $status_port = $config['status_port']; +$settingPort = setting('core.status_port'); +if(isset($settingPort[0])) { + $status_port = $settingPort; } -elseif(!isset($status_port[0])) // try 7171 if no ip specified +elseif(!isset($status_port[0])) // try 7171 if no port specified { $status_port = 7171; } @@ -94,9 +96,9 @@ if(isset($config['lua']['statustimeout'])) // get status timeout from server config $status_timeout = eval('return ' . $config['lua']['statusTimeout'] . ';') / 1000 + 1; -$status_interval = @$config['status_interval']; -if($status_interval && $status_timeout < $config['status_interval']) { - $status_timeout = $config['status_interval']; +$status_interval = setting('core.status_interval'); +if($status_interval && $status_timeout < $status_interval) { + $status_timeout = $status_interval; } if($status['lastCheck'] + $status_timeout < time()) { diff --git a/system/template.php b/system/template.php index 72ae3792..a01939a4 100644 --- a/system/template.php +++ b/system/template.php @@ -10,8 +10,8 @@ defined('MYAAC') or die('Direct access not allowed!'); // template -$template_name = $config['template']; -if($config['template_allow_change']) +$template_name = setting('core.template'); +if(setting('core.template_allow_change')) { if(isset($_GET['template'])) { @@ -111,12 +111,13 @@ $template['link_screenshots'] = getLink('gallery'); $template['link_movies'] = getLink('videos'); $template['link_gifts_history'] = getLink('gifts', 'history'); -if($config['forum'] != '') +$forumSetting = setting('core.forum'); +if($forumSetting != '') { - if(strtolower($config['forum']) == 'site') + if(strtolower($forumSetting) == 'site') $template['link_forum'] = ""; else - $template['link_forum'] = ""; + $template['link_forum'] = ""; } $twig->addGlobal('template_path', $template_path); diff --git a/system/templates/account.change_name.html.twig b/system/templates/account.change_name.html.twig index bd1fa8f0..76c038d4 100644 --- a/system/templates/account.change_name.html.twig +++ b/system/templates/account.change_name.html.twig @@ -1,5 +1,5 @@ To change a name of character select player and choose a new name.
    -Change name cost {{ config.account_change_character_name_points }} premium points. You have {{ points }} premium points.

    +Change name cost {{ setting('core.account_change_character_name_price') }} premium points. You have {{ points }} premium points.

    diff --git a/system/templates/account.change_sex.html.twig b/system/templates/account.change_sex.html.twig index 07ea83e9..24141f61 100644 --- a/system/templates/account.change_sex.html.twig +++ b/system/templates/account.change_sex.html.twig @@ -1,5 +1,5 @@ To change a sex of character select player and choose a new sex.
    -Change sex cost {{ config.account_change_character_sex_points }} premium points. You have {{ points }} premium points.

    +Change sex cost {{ setting('core.account_change_character_sex_price') }} premium points. You have {{ points }} premium points.

    @@ -73,4 +73,4 @@ To change a sex of character select player and choose a new sex.
    - \ No newline at end of file + diff --git a/system/templates/account.create.html.twig b/system/templates/account.create.html.twig index 38907c74..a43d6e7d 100644 --- a/system/templates/account.create.html.twig +++ b/system/templates/account.create.html.twig @@ -59,7 +59,7 @@ {% if errors.email is defined %}{{ errors.email }}{% endif %} - {% if config.mail_enabled and config.account_mail_verify %} + {% if setting('core.mail_enabled') and config.account_mail_verify %} Please use real address!
    We will send a link to validate your Email.
    {% endif %} @@ -122,7 +122,7 @@ {{ hook('HOOK_ACCOUNT_CREATE_BETWEEN_BOXES_1') }} - {% if (not config.mail_enabled or not config.account_mail_verify) and config.account_create_character_create %} + {% if (not setting('core.mail_enabled') or not config.account_mail_verify) and config.account_create_character_create %}
    @@ -140,7 +140,7 @@ Character Name: - +
    diff --git a/system/templates/account.create_character.html.twig b/system/templates/account.create_character.html.twig index 045c749c..acb57f5c 100644 --- a/system/templates/account.create_character.html.twig +++ b/system/templates/account.create_character.html.twig @@ -45,7 +45,7 @@ In any case the name must not violate the naming conventions stated in the
    - +
    @@ -145,4 +145,4 @@ In any case the name must not violate the naming conventions stated in the
    - \ No newline at end of file + diff --git a/system/templates/account.generate_new_recovery_key.html.twig b/system/templates/account.generate_new_recovery_key.html.twig index f1ec611b..6f3e5c50 100644 --- a/system/templates/account.generate_new_recovery_key.html.twig +++ b/system/templates/account.generate_new_recovery_key.html.twig @@ -1,5 +1,5 @@ To generate new recovery key for your account please enter your password.
    -New recovery key cost {{ config.generate_new_reckey_price }} Premium Points. You have {{ points }} premium points. You will receive e-mail with this recovery key.
    +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.
    @@ -56,4 +56,4 @@ To generate new recovery key for your account please enter your password.
    - \ No newline at end of file + diff --git a/system/templates/account.management.html.twig b/system/templates/account.management.html.twig index 510c90a1..95fc0975 100644 --- a/system/templates/account.management.html.twig +++ b/system/templates/account.management.html.twig @@ -39,10 +39,10 @@ {% for name, link in menus %}
    {{ name }} {% endfor %} - {% if config.account_change_character_name %} + {% if setting('core.account_change_character_name') %} Change Name {% endif %} - {% if config.account_change_character_sex %} + {% if setting('core.account_change_character_sex') %} Change Sex {% endif %} Logout @@ -192,7 +192,7 @@ {% include('buttons.base.html.twig') %} - {% if config.account_change_character_name %} + {% if setting('core.account_change_character_name') %}
    {% set button_name = 'Change Name' %} @@ -200,7 +200,7 @@
    {% endif %} - {% if config.account_change_character_sex %} + {% if setting('core.account_change_character_sex') %}
    {% set button_name = 'Change Sex' %} diff --git a/system/templates/admin.settings.html.twig b/system/templates/admin.settings.html.twig new file mode 100644 index 00000000..e5d3ef9b --- /dev/null +++ b/system/templates/admin.settings.html.twig @@ -0,0 +1,105 @@ +
    +
    +
    Settings
    +
    +
    + +
    +
    +
    +
    + +
    +
    + {{ settingsParsed|raw }} +
    +
    +
    + +
    +
    + + +{{ script|raw }} + + + + diff --git a/system/templates/characters.html.twig b/system/templates/characters.html.twig index 4234f2ab..9553d20c 100644 --- a/system/templates/characters.html.twig +++ b/system/templates/characters.html.twig @@ -284,7 +284,7 @@ {{ hook(constant('HOOK_CHARACTERS_BEFORE_SIGNATURE')) }} - {% if config.signature_enabled %} + {% if setting('core.signature_enabled') %} \ No newline at end of file + diff --git a/system/templates/install.config.html.twig b/system/templates/install.config.html.twig index 0776d540..ab4fc361 100644 --- a/system/templates/install.config.html.twig +++ b/system/templates/install.config.html.twig @@ -9,7 +9,7 @@
    - {% for value in ['server_path', 'mail_admin'] %} + {% for value in ['server_path'] %}
    diff --git a/system/templates/mail.password_changed.html.twig b/system/templates/mail.password_changed.html.twig index d87601f0..a43af3a2 100644 --- a/system/templates/mail.password_changed.html.twig +++ b/system/templates/mail.password_changed.html.twig @@ -4,4 +4,4 @@ The request was made on {{ "now"|date("F j, Y, g:i a") }} by a user with the IP:

    The new password is: {{ new_password }}

    -If this was you, please ignore this email. If it was not you, please contact our support department at {{ config.mail_admin }}. \ No newline at end of file +If this was you, please ignore this email. If it was not you, please contact our support department. diff --git a/system/templates/team.html.twig b/system/templates/team.html.twig index bbbe35cd..a979e670 100644 --- a/system/templates/team.html.twig +++ b/system/templates/team.html.twig @@ -25,7 +25,7 @@ Group - {% if config.team_display_outfit %} + {% if setting('core.team_outfit') %} Outfit @@ -35,19 +35,19 @@ Name - {% if config.team_display_status %} + {% if setting('core.team_status') %} Status {% endif %} - {% if (config.multiworld or config.team_display_world) %} + {% if (setting('core.multiworld') or setting('core.team_world')) %} World {% endif %} - {% if config.team_display_lastlogin %} + {% if setting('core.team_lastlogin') %} Last login @@ -61,7 +61,7 @@ {{ group.group_name|capitalize }} - {% if config.team_display_outfit %} + {% if setting('core.team_outfit') %} player outfit @@ -74,7 +74,7 @@ {{ member.link|raw }} - {% if config.team_display_status %} + {% if setting('core.team_status') %} {% if member.status %} Online @@ -84,13 +84,13 @@ {% endif %} - {% if (config.multiworld or config.team_display_world) %} + {% if (setting('core.multiworld') or setting('core.team_world')) %} {{ member.world_name }} {% endif %} - {% if config.team_display_lastlogin %} + {% if setting('core.team_lastlogin') %} {{ member.last_login }} @@ -107,7 +107,7 @@ - {% if config.team_display_outfit %} + {% if setting('core.team_outfit') %} @@ -117,19 +117,19 @@ Name - {% if config.team_display_status %} + {% if setting('core.team_status') %} {% endif %} - {% if (config.multiworld or config.team_display_world) %} + {% if (setting('core.multiworld') or setting('core.team_world')) %} {% endif %} - {% if config.team_display_lastlogin %} + {% if setting('core.team_lastlogin') %} @@ -139,7 +139,7 @@ {% for member in group.members %} {% set i = i + 1 %} - {% if config.team_display_outfit %} + {% if setting('core.team_outfit') %} @@ -152,7 +152,7 @@ {{ member.link|raw }} - {% if config.team_display_status %} + {% if setting('core.team_status') %} {% endif %} - {% if (config.multiworld or config.team_display_world) %} + {% if (setting('core.multiworld') or setting('core.team_world')) %} {% endif %} - {% if config.team_display_lastlogin %} + {% if setting('core.team_lastlogin') %} diff --git a/system/twig.php b/system/twig.php index 4fc7c5ec..5eb35c68 100644 --- a/system/twig.php +++ b/system/twig.php @@ -107,6 +107,11 @@ $function = new TwigFunction('config', function ($key) { }); $twig->addFunction($function); +$function = new TwigFunction('setting', function ($key) { + return setting($key); +}); +$twig->addFunction($function); + $function = new TwigFunction('getCustomPage', function ($name) { $success = false; return getCustomPage($name, $success); diff --git a/templates/tibiacom/account.management.html.twig b/templates/tibiacom/account.management.html.twig index 7c387c36..e1106e8c 100644 --- a/templates/tibiacom/account.management.html.twig +++ b/templates/tibiacom/account.management.html.twig @@ -470,7 +470,7 @@
    Outfit Status World Last login
    player outfit {% if member.status %} Online @@ -162,13 +162,13 @@ {{ member.world_name }} {{ member.last_login }}
    - {% if config.account_change_character_name %} + {% if setting('core.account_change_character_name') %} @@ -483,7 +483,7 @@
    {% endif %} - {% if config.account_change_character_sex %} + {% if setting('core.account_change_character_sex') %} diff --git a/templates/tibiacom/index.php b/templates/tibiacom/index.php index 539453c9..6bb5f445 100644 --- a/templates/tibiacom/index.php +++ b/templates/tibiacom/index.php @@ -289,7 +289,7 @@ if(isset($config['boxes'])) logoartworklogoartworklogoartwork - logoartwork + logoartwork
    diff --git a/tools/css/toastify.min.css b/tools/css/toastify.min.css new file mode 100644 index 00000000..427c25bc --- /dev/null +++ b/tools/css/toastify.min.css @@ -0,0 +1,15 @@ +/** + * Minified by jsDelivr using clean-css v5.3.0. + * Original file: /npm/toastify-js@1.12.0/src/toastify.css + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +/*! + * Toastify js 1.12.0 + * https://github.com/apvarun/toastify-js + * @license MIT licensed + * + * Copyright (C) 2018 Varun A P + */ +.toastify{padding:12px 20px;color:#fff;display:inline-block;box-shadow:0 3px 6px -1px rgba(0,0,0,.12),0 10px 36px -4px rgba(77,96,232,.3);background:-webkit-linear-gradient(315deg,#73a5ff,#5477f5);background:linear-gradient(135deg,#73a5ff,#5477f5);position:fixed;opacity:0;transition:all .4s cubic-bezier(.215, .61, .355, 1);border-radius:2px;cursor:pointer;text-decoration:none;max-width:calc(50% - 20px);z-index:2147483647}.toastify.on{opacity:1}.toast-close{background:0 0;border:0;color:#fff;cursor:pointer;font-family:inherit;font-size:1em;opacity:.4;padding:0 5px}.toastify-right{right:15px}.toastify-left{left:15px}.toastify-top{top:-150px}.toastify-bottom{bottom:-150px}.toastify-rounded{border-radius:25px}.toastify-avatar{width:1.5em;height:1.5em;margin:-7px 5px;border-radius:2px}.toastify-center{margin-left:auto;margin-right:auto;left:0;right:0;max-width:fit-content;max-width:-moz-fit-content}@media only screen and (max-width:360px){.toastify-left,.toastify-right{margin-left:auto;margin-right:auto;left:0;right:0;max-width:fit-content}} +/*# sourceMappingURL=/sm/cb4335d1b03e933ed85cb59fffa60cf51f07567ed09831438c60f59afd166464.map */ \ No newline at end of file diff --git a/tools/js/toastify.min.js b/tools/js/toastify.min.js new file mode 100644 index 00000000..29af3859 --- /dev/null +++ b/tools/js/toastify.min.js @@ -0,0 +1,15 @@ +/** + * Minified by jsDelivr using Terser v5.14.1. + * Original file: /npm/toastify-js@1.12.0/src/toastify.js + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +/*! + * Toastify js 1.12.0 + * https://github.com/apvarun/toastify-js + * @license MIT licensed + * + * Copyright (C) 2018 Varun A P + */ +!function(t,o){"object"==typeof module&&module.exports?module.exports=o():t.Toastify=o()}(this,(function(t){var o=function(t){return new o.lib.init(t)};function i(t,o){return o.offset[t]?isNaN(o.offset[t])?o.offset[t]:o.offset[t]+"px":"0px"}function s(t,o){return!(!t||"string"!=typeof o)&&!!(t.className&&t.className.trim().split(/\s+/gi).indexOf(o)>-1)}return o.defaults={oldestFirst:!0,text:"Toastify is awesome!",node:void 0,duration:3e3,selector:void 0,callback:function(){},destination:void 0,newWindow:!1,close:!1,gravity:"toastify-top",positionLeft:!1,position:"",backgroundColor:"",avatar:"",className:"",stopOnFocus:!0,onClick:function(){},offset:{x:0,y:0},escapeMarkup:!0,ariaLive:"polite",style:{background:""}},o.lib=o.prototype={toastify:"1.12.0",constructor:o,init:function(t){return t||(t={}),this.options={},this.toastElement=null,this.options.text=t.text||o.defaults.text,this.options.node=t.node||o.defaults.node,this.options.duration=0===t.duration?0:t.duration||o.defaults.duration,this.options.selector=t.selector||o.defaults.selector,this.options.callback=t.callback||o.defaults.callback,this.options.destination=t.destination||o.defaults.destination,this.options.newWindow=t.newWindow||o.defaults.newWindow,this.options.close=t.close||o.defaults.close,this.options.gravity="bottom"===t.gravity?"toastify-bottom":o.defaults.gravity,this.options.positionLeft=t.positionLeft||o.defaults.positionLeft,this.options.position=t.position||o.defaults.position,this.options.backgroundColor=t.backgroundColor||o.defaults.backgroundColor,this.options.avatar=t.avatar||o.defaults.avatar,this.options.className=t.className||o.defaults.className,this.options.stopOnFocus=void 0===t.stopOnFocus?o.defaults.stopOnFocus:t.stopOnFocus,this.options.onClick=t.onClick||o.defaults.onClick,this.options.offset=t.offset||o.defaults.offset,this.options.escapeMarkup=void 0!==t.escapeMarkup?t.escapeMarkup:o.defaults.escapeMarkup,this.options.ariaLive=t.ariaLive||o.defaults.ariaLive,this.options.style=t.style||o.defaults.style,t.backgroundColor&&(this.options.style.background=t.backgroundColor),this},buildToast:function(){if(!this.options)throw"Toastify is not initialized";var t=document.createElement("div");for(var o in t.className="toastify on "+this.options.className,this.options.position?t.className+=" toastify-"+this.options.position:!0===this.options.positionLeft?(t.className+=" toastify-left",console.warn("Property `positionLeft` will be depreciated in further versions. Please use `position` instead.")):t.className+=" toastify-right",t.className+=" "+this.options.gravity,this.options.backgroundColor&&console.warn('DEPRECATION NOTICE: "backgroundColor" is being deprecated. Please use the "style.background" property.'),this.options.style)t.style[o]=this.options.style[o];if(this.options.ariaLive&&t.setAttribute("aria-live",this.options.ariaLive),this.options.node&&this.options.node.nodeType===Node.ELEMENT_NODE)t.appendChild(this.options.node);else if(this.options.escapeMarkup?t.innerText=this.options.text:t.innerHTML=this.options.text,""!==this.options.avatar){var s=document.createElement("img");s.src=this.options.avatar,s.className="toastify-avatar","left"==this.options.position||!0===this.options.positionLeft?t.appendChild(s):t.insertAdjacentElement("afterbegin",s)}if(!0===this.options.close){var e=document.createElement("button");e.type="button",e.setAttribute("aria-label","Close"),e.className="toast-close",e.innerHTML="✖",e.addEventListener("click",function(t){t.stopPropagation(),this.removeElement(this.toastElement),window.clearTimeout(this.toastElement.timeOutValue)}.bind(this));var n=window.innerWidth>0?window.innerWidth:screen.width;("left"==this.options.position||!0===this.options.positionLeft)&&n>360?t.insertAdjacentElement("afterbegin",e):t.appendChild(e)}if(this.options.stopOnFocus&&this.options.duration>0){var a=this;t.addEventListener("mouseover",(function(o){window.clearTimeout(t.timeOutValue)})),t.addEventListener("mouseleave",(function(){t.timeOutValue=window.setTimeout((function(){a.removeElement(t)}),a.options.duration)}))}if(void 0!==this.options.destination&&t.addEventListener("click",function(t){t.stopPropagation(),!0===this.options.newWindow?window.open(this.options.destination,"_blank"):window.location=this.options.destination}.bind(this)),"function"==typeof this.options.onClick&&void 0===this.options.destination&&t.addEventListener("click",function(t){t.stopPropagation(),this.options.onClick()}.bind(this)),"object"==typeof this.options.offset){var l=i("x",this.options),r=i("y",this.options),p="left"==this.options.position?l:"-"+l,d="toastify-top"==this.options.gravity?r:"-"+r;t.style.transform="translate("+p+","+d+")"}return t},showToast:function(){var t;if(this.toastElement=this.buildToast(),!(t="string"==typeof this.options.selector?document.getElementById(this.options.selector):this.options.selector instanceof HTMLElement||"undefined"!=typeof ShadowRoot&&this.options.selector instanceof ShadowRoot?this.options.selector:document.body))throw"Root element is not defined";var i=o.defaults.oldestFirst?t.firstChild:t.lastChild;return t.insertBefore(this.toastElement,i),o.reposition(),this.options.duration>0&&(this.toastElement.timeOutValue=window.setTimeout(function(){this.removeElement(this.toastElement)}.bind(this),this.options.duration)),this},hideToast:function(){this.toastElement.timeOutValue&&clearTimeout(this.toastElement.timeOutValue),this.removeElement(this.toastElement)},removeElement:function(t){t.className=t.className.replace(" on",""),window.setTimeout(function(){this.options.node&&this.options.node.parentNode&&this.options.node.parentNode.removeChild(this.options.node),t.parentNode&&t.parentNode.removeChild(t),this.options.callback.call(t),o.reposition()}.bind(this),400)}},o.reposition=function(){for(var t,o={top:15,bottom:15},i={top:15,bottom:15},e={top:15,bottom:15},n=document.getElementsByClassName("toastify"),a=0;a0?window.innerWidth:screen.width)<=360?(n[a].style[t]=e[t]+"px",e[t]+=l+15):!0===s(n[a],"toastify-left")?(n[a].style[t]=o[t]+"px",o[t]+=l+15):(n[a].style[t]=i[t]+"px",i[t]+=l+15)}return this},o.lib.init.prototype=o.lib,o})); +//# sourceMappingURL=/sm/e1ebbfe1bf0b0061f0726ebc83434e1c2f8308e6354c415fd05ecccdaad47617.map \ No newline at end of file diff --git a/tools/signature/index.php b/tools/signature/index.php index e3e33303..f196781e 100644 --- a/tools/signature/index.php +++ b/tools/signature/index.php @@ -21,12 +21,14 @@ define('SIGNATURES_IMAGES', SIGNATURES . 'images/'); define('SIGNATURES_ITEMS', BASE . 'images/items/'); - if(!$config['signature_enabled']) + if(!setting('core.signature_enabled')) { die('Signatures are disabled on this server.'); + } - $file = trim(strtolower($config['signature_type'])) . '.php'; - if(!file_exists($file)) - die('ERROR: Wrong signature_type in config.'); + $file = trim(strtolower(setting('core.signature_type'))) . '.php'; + if(!file_exists($file)) { + die('ERROR: Wrong signature_type in Settings.'); + } putenv('GDFONTPATH=' . SIGNATURES_FONTS); @@ -52,7 +54,7 @@ } $cached = SIGNATURES_CACHE.$player->getId() . '.png'; - if(file_exists($cached) && (time() < (filemtime($cached) + (60 * $config['signature_cache_time'])))) + if(file_exists($cached) && (time() < (filemtime($cached) + (60 * setting('core.signature_cache_time'))))) { header( 'Content-type: image/png' ); readfile( SIGNATURES_CACHE.$player->getId().'.png' ); @@ -61,7 +63,7 @@ require $file; header('Content-type: image/png'); - $seconds_to_cache = $config['signature_browser_cache'] * 60; + $seconds_to_cache = setting('core.signature_browser_cache') * 60; $ts = gmdate("D, d M Y H:i:s", time() + $seconds_to_cache) . " GMT"; header('Expires: ' . $ts); header('Pragma: cache');