diff --git a/admin/pages/plugins.php b/admin/pages/plugins.php
index db886635..82f8309c 100644
--- a/admin/pages/plugins.php
+++ b/admin/pages/plugins.php
@@ -51,6 +51,56 @@ else {
} else {
error('Error while disabling plugin ' . $disable . ': ' . Plugins::getError());
}
+ }
+ else if (isset($_GET['check-updates'])) {
+ $repoUri = $config['admin_plugins_api_uri'] ?? 'https://plugins.my-aac.org/api/';
+ success("Fetching latest info from $repoUri..");
+
+ $adminPlugins = new \MyAAC\Admin\Plugins();
+
+ $adminPlugins->setApiBaseUri($repoUri);
+
+ try {
+ $plugins = $adminPlugins->getLatestVersions();
+ }
+ catch (Exception $e) {
+ error($e->getMessage());
+ }
+
+ if (isset($plugins) && count($plugins) > 0) {
+ $outdated = [];
+
+ foreach (get_plugins(true) as $plugin) {
+ $string = file_get_contents(BASE . 'plugins/' . $plugin . '.json');
+ $plugin_info = json_decode($string, true);
+
+ if (!$plugin_info) {
+ continue;
+ }
+
+ $disabled = (str_contains($plugin, 'disabled.'));
+ $pluginOriginal = ($disabled ? str_replace('disabled.', '', $plugin) : $plugin);
+
+ $info = $plugins[$pluginOriginal] ?? false;
+ if ($info && version_compare($info['version'], $plugin_info['version'], '>')) {
+ $outdated[] = [
+ 'name' => $pluginOriginal,
+ 'yourVersion' => $plugin_info['version'],
+ 'latestVersion' => $info['version'],
+ 'link' => $info['link'] ?? 'Unknown',
+ 'download_link' => $info['download_link'] ?? 'Unknown',
+ ];
+ }
+ }
+
+ if (count($outdated) > 0) {
+ info('Following updates have been found for your plugins:');
+ $twig->display('admin.plugins.outdated.html.twig', ['plugins' => $outdated]);
+ }
+ else {
+ success('All plugins up to date!');
+ }
+ }
} else if (isset($_FILES['plugin']['name'])) {
$file = $_FILES['plugin'];
$filename = $file['name'];
diff --git a/admin/pages/visitors.php b/admin/pages/visitors.php
index 9e83d339..9fae4d24 100644
--- a/admin/pages/visitors.php
+++ b/admin/pages/visitors.php
@@ -19,8 +19,7 @@ $use_datatable = true;
if (!setting('core.visitors_counter')): ?>
Visitors counter is disabled.
- You can enable it by editing this configurable in config.local.php file:
-
$config['visitors_counter'] = true;
+ You can enable it in Settings -> General -> Visitors Counter.
isBot()) {
$bot = $dd->getBot();
$message = '(Bot) %s, %s';
- $browser = sprintf($message, $bot['category'], $bot['url'], $bot['name']);
+ $browser = sprintf($message, $bot['category'] ?? 'Unknown', $bot['url'] ?? '', $bot['name'] ?? 'Unknown name');
}
else {
$osFamily = OperatingSystem::getOsFamily($dd->getOs('name'));
diff --git a/admin/template/menus.php b/admin/template/menus.php
index 0bcd7304..6df84745 100644
--- a/admin/template/menus.php
+++ b/admin/template/menus.php
@@ -60,7 +60,7 @@ usort($menus, function ($a, $b) {
foreach ($menus as $i => $menu) {
if (isset($menu['link']) && is_array($menu['link'])) {
- usort($menus[$i]['link'], function ($a, $b) {
+ usort($menu['link'], function ($a, $b) {
return $a['order'] - $b['order'];
});
}
diff --git a/admin/tools/phpinfo.php b/admin/tools/phpinfo.php
index cd043279..bd09fb5d 100644
--- a/admin/tools/phpinfo.php
+++ b/admin/tools/phpinfo.php
@@ -1,5 +1,6 @@
0) {
if ($success) {
echo 'Saved at ' . date('H:i');
}
+else {
+ echo 'Something unexpected happened - it was impossible to save the settings, please try again later. If problem persists - contact MyAAC developers.';
+}
diff --git a/admin/tools/status.php b/admin/tools/status.php
index e7a471e7..45597b6f 100644
--- a/admin/tools/status.php
+++ b/admin/tools/status.php
@@ -1,5 +1,6 @@
=7.1",
+ "psr/http-message": "^1.0 || ^2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
+ "keywords": [
+ "factory",
+ "http",
+ "message",
+ "psr",
+ "psr-17",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-factory"
+ },
+ "time": "2024-04-15T12:06:14+00:00"
+ },
+ {
+ "name": "psr/http-message",
+ "version": "2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-message.git",
+ "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+ "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP messages",
+ "homepage": "https://github.com/php-fig/http-message",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-message/tree/2.0"
+ },
+ "time": "2023-04-04T09:54:51+00:00"
+ },
{
"name": "psr/log",
"version": "3.0.2",
@@ -1573,6 +2058,50 @@
},
"time": "2021-10-29T13:26:27+00:00"
},
+ {
+ "name": "ralouphie/getallheaders",
+ "version": "3.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ralouphie/getallheaders.git",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6"
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "^2.1",
+ "phpunit/phpunit": "^5 || ^6.5"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/getallheaders.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ralph Khattar",
+ "email": "ralph.khattar@gmail.com"
+ }
+ ],
+ "description": "A polyfill for getallheaders.",
+ "support": {
+ "issues": "https://github.com/ralouphie/getallheaders/issues",
+ "source": "https://github.com/ralouphie/getallheaders/tree/develop"
+ },
+ "time": "2019-03-08T08:55:37+00:00"
+ },
{
"name": "symfony/console",
"version": "v6.4.17",
@@ -2910,7 +3439,7 @@
],
"aliases": [],
"minimum-stability": "stable",
- "stability-flags": [],
+ "stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
@@ -2921,6 +3450,6 @@
"ext-xml": "*",
"ext-dom": "*"
},
- "platform-dev": [],
- "plugin-api-version": "2.3.0"
+ "platform-dev": {},
+ "plugin-api-version": "2.6.0"
}
diff --git a/images/facebook_16x16.png b/images/facebook_16x16.png
new file mode 100644
index 00000000..d64c153a
Binary files /dev/null and b/images/facebook_16x16.png differ
diff --git a/images/instagram_16x16.png b/images/instagram_16x16.png
new file mode 100644
index 00000000..62b8ee18
Binary files /dev/null and b/images/instagram_16x16.png differ
diff --git a/images/order_asc.gif b/images/order_asc.gif
new file mode 100644
index 00000000..c9698a5a
Binary files /dev/null and b/images/order_asc.gif differ
diff --git a/images/order_desc.gif b/images/order_desc.gif
new file mode 100644
index 00000000..4a764bd5
Binary files /dev/null and b/images/order_desc.gif differ
diff --git a/images/whatsapp_16x16.png b/images/whatsapp_16x16.png
new file mode 100644
index 00000000..a13d2faf
Binary files /dev/null and b/images/whatsapp_16x16.png differ
diff --git a/index.php b/index.php
index bc8a3663..ee8f7a87 100644
--- a/index.php
+++ b/index.php
@@ -93,6 +93,7 @@ if(setting('core.backward_support')) {
if($logged && $account_logged)
$group_id_of_acc_logged = $account_logged->getGroupId();
+ $config['serverPath'] = $config['server_path'];
$config['site'] = &$config;
$config['server'] = &$config['lua'];
$config['site']['shop_system'] = setting('core.gifts_system');
@@ -117,6 +118,14 @@ if(setting('core.backward_support')) {
$config['status']['serverStatus_' . $key] = $value;
}
+if(setting('core.views_counter')) {
+ require_once SYSTEM . 'counter.php';
+}
+
+if(setting('core.visitors_counter')) {
+ $visitors = new Visitors(setting('core.visitors_counter_ttl'));
+}
+
require_once SYSTEM . 'router.php';
// anonymous usage statistics
@@ -153,22 +162,6 @@ if(setting('core.anonymous_usage_statistics')) {
}
}
-if(setting('core.views_counter'))
- require_once SYSTEM . 'counter.php';
-
-if(setting('core.visitors_counter')) {
- $visitors = new Visitors(setting('core.visitors_counter_ttl'));
-}
-
-/**
- * @var OTS_Account $account_logged
- */
-if ($logged && admin()) {
- $content .= $twig->render('admin-bar.html.twig', [
- 'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId()
- ]);
-}
-
$title_full = (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName'];
require $template_path . '/' . $template_index;
diff --git a/install/includes/import_base_data.php b/install/includes/import_base_data.php
new file mode 100644
index 00000000..45c803ed
--- /dev/null
+++ b/install/includes/import_base_data.php
@@ -0,0 +1,69 @@
+ 3,
+ 'where' => 2,
+ 'date' => time(),
+ 'body' => 'MyAAC installed. (:',
+ 'hide' => 0,
+ ]);
+}
+
+if (Config::where('name', 'database_version')->count() === 0) {
+ Config::create([
+ 'name' => 'database_version',
+ 'value' => DATABASE_VERSION,
+ ]);
+}
+
+if (ForumBoard::count() === 0) {
+ $forumBoards = [
+ ['name' => 'News', 'description' => 'News commenting', 'closed' => 1],
+ ['name' => 'Trade', 'description' => 'Trade offers.', 'closed' => 0],
+ ['name' => 'Quests', 'description' => 'Quest making.', 'closed' => 0],
+ ['name' => 'Pictures', 'description' => 'Your pictures.', 'closed' => 0],
+ ['name' => 'Bug Report', 'description' => 'Report bugs there.', 'closed' => 0],
+ ];
+
+ $i = 0;
+ foreach ($forumBoards as $forumBoard) {
+ ForumBoard::create([
+ 'name' => $forumBoard['name'],
+ 'description' => $forumBoard['description'],
+ 'ordering' => $i++,
+ 'closed' => $forumBoard['closed'],
+ ]);
+ }
+}
+
+if (NewsCategory::count() === 0) {
+ $newsCategoriesIcons = [
+ 0, 1, 2, 3, 4
+ ];
+
+ foreach ($newsCategoriesIcons as $iconId) {
+ NewsCategory::create([
+ 'icon_id' => $iconId,
+ ]);
+ }
+}
+
+if (Gallery::count() === 0) {
+ Gallery::create([
+ 'comment' => 'Demon',
+ 'image' => 'images/gallery/demon.jpg',
+ 'thumb' => 'images/gallery/demon_thumb.gif',
+ 'author' => 'MyAAC',
+ 'ordering' => 0,
+ ]);
+}
+
+success($locale['step_database_success_import_data']);
diff --git a/install/includes/schema.sql b/install/includes/schema.sql
index eccaee54..d4bc97d6 100644
--- a/install/includes/schema.sql
+++ b/install/includes/schema.sql
@@ -1,6 +1,4 @@
-SET @myaac_database_version = 45;
-
-CREATE TABLE `myaac_account_actions`
+CREATE TABLE IF NOT EXISTS `myaac_account_actions`
(
`account_id` int NOT NULL,
`ip` int unsigned NOT NULL DEFAULT 0,
@@ -10,7 +8,16 @@ CREATE TABLE `myaac_account_actions`
KEY (`account_id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
-CREATE TABLE `myaac_admin_menu`
+CREATE TABLE IF NOT EXISTS `myaac_account_emails_verify`
+(
+ `id` int NOT NULL AUTO_INCREMENT,
+ `account_id` int NOT NULL,
+ `hash` varchar(32) NOT NULL,
+ `sent_at` int NOT NULL DEFAULT 0,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
+
+CREATE TABLE IF NOT EXISTS `myaac_admin_menu`
(
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '',
@@ -21,7 +28,7 @@ CREATE TABLE `myaac_admin_menu`
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
-CREATE TABLE `myaac_changelog`
+CREATE TABLE IF NOT EXISTS `myaac_changelog`
(
`id` int NOT NULL AUTO_INCREMENT,
`body` varchar(500) NOT NULL DEFAULT '',
@@ -33,9 +40,7 @@ CREATE TABLE `myaac_changelog`
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
-INSERT INTO `myaac_changelog` (`id`, `type`, `where`, `date`, `body`, `hide`) VALUES (1, 3, 2, UNIX_TIMESTAMP(), 'MyAAC installed. (:', 0);
-
-CREATE TABLE `myaac_config`
+CREATE TABLE IF NOT EXISTS `myaac_config`
(
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL,
@@ -44,9 +49,7 @@ CREATE TABLE `myaac_config`
UNIQUE (`name`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
-INSERT INTO `myaac_config` (`name`, `value`) VALUES ('database_version', @myaac_database_version);
-
-CREATE TABLE `myaac_faq`
+CREATE TABLE IF NOT EXISTS `myaac_faq`
(
`id` int NOT NULL AUTO_INCREMENT,
`question` varchar(255) NOT NULL DEFAULT '',
@@ -56,7 +59,7 @@ CREATE TABLE `myaac_faq`
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
-CREATE TABLE `myaac_forum_boards`
+CREATE TABLE IF NOT EXISTS `myaac_forum_boards`
(
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL,
@@ -68,13 +71,8 @@ CREATE TABLE `myaac_forum_boards`
`hide` tinyint NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
-INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`, `closed`) VALUES (NULL, 'News', 'News commenting', 0, 1);
-INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Trade', 'Trade offers.', 1);
-INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Quests', 'Quest making.', 2);
-INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Pictures', 'Your pictures.', 3);
-INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Bug Report', 'Report bugs there.', 4);
-CREATE TABLE `myaac_forum`
+CREATE TABLE IF NOT EXISTS `myaac_forum`
(
`id` int NOT NULL AUTO_INCREMENT,
`first_post` int NOT NULL DEFAULT 0,
@@ -98,7 +96,7 @@ CREATE TABLE `myaac_forum`
KEY `section` (`section`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
-CREATE TABLE `myaac_menu`
+CREATE TABLE IF NOT EXISTS `myaac_menu`
(
`id` int NOT NULL AUTO_INCREMENT,
`template` varchar(255) NOT NULL,
@@ -112,7 +110,7 @@ CREATE TABLE `myaac_menu`
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
-CREATE TABLE `myaac_monsters` (
+CREATE TABLE IF NOT EXISTS `myaac_monsters` (
`id` int NOT NULL AUTO_INCREMENT,
`hide` tinyint NOT NULL DEFAULT 0,
`name` varchar(255) NOT NULL,
@@ -145,7 +143,7 @@ CREATE TABLE `myaac_monsters` (
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
-CREATE TABLE `myaac_news`
+CREATE TABLE IF NOT EXISTS `myaac_news`
(
`id` int NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL,
@@ -163,7 +161,7 @@ CREATE TABLE `myaac_news`
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
-CREATE TABLE `myaac_news_categories`
+CREATE TABLE IF NOT EXISTS `myaac_news_categories`
(
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL DEFAULT "",
@@ -173,13 +171,7 @@ CREATE TABLE `myaac_news_categories`
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
-INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 0);
-INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 1);
-INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 2);
-INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 3);
-INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 4);
-
-CREATE TABLE `myaac_notepad`
+CREATE TABLE IF NOT EXISTS `myaac_notepad`
(
`id` int NOT NULL AUTO_INCREMENT,
`account_id` int NOT NULL,
@@ -189,7 +181,7 @@ CREATE TABLE `myaac_notepad`
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
-CREATE TABLE `myaac_pages`
+CREATE TABLE IF NOT EXISTS `myaac_pages`
(
`id` INT NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL,
@@ -205,7 +197,7 @@ CREATE TABLE `myaac_pages`
UNIQUE (`name`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
-CREATE TABLE `myaac_gallery`
+CREATE TABLE IF NOT EXISTS `myaac_gallery`
(
`id` int NOT NULL AUTO_INCREMENT,
`comment` varchar(255) NOT NULL DEFAULT '',
@@ -217,9 +209,7 @@ CREATE TABLE `myaac_gallery`
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
-INSERT INTO `myaac_gallery` (`id`, `ordering`, `comment`, `image`, `thumb`, `author`) VALUES (NULL, 1, 'Demon', 'images/gallery/demon.jpg', 'images/gallery/demon_thumb.gif', 'MyAAC');
-
-CREATE TABLE `myaac_settings`
+CREATE TABLE IF NOT EXISTS `myaac_settings`
(
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '',
@@ -229,7 +219,7 @@ CREATE TABLE `myaac_settings`
KEY `key` (`key`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
-CREATE TABLE `myaac_spells`
+CREATE TABLE IF NOT EXISTS `myaac_spells`
(
`id` int NOT NULL AUTO_INCREMENT,
`spell` varchar(255) NOT NULL DEFAULT '',
@@ -252,7 +242,7 @@ CREATE TABLE `myaac_spells`
UNIQUE (`name`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
-CREATE TABLE `myaac_visitors`
+CREATE TABLE IF NOT EXISTS `myaac_visitors`
(
`ip` varchar(45) NOT NULL,
`lastvisit` int NOT NULL DEFAULT 0,
@@ -261,7 +251,7 @@ CREATE TABLE `myaac_visitors`
UNIQUE (`ip`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
-CREATE TABLE `myaac_weapons`
+CREATE TABLE IF NOT EXISTS `myaac_weapons`
(
`id` int NOT NULL,
`level` int NOT NULL DEFAULT 0,
diff --git a/install/steps/4-config.php b/install/steps/4-config.php
index 325b97f1..342edd06 100644
--- a/install/steps/4-config.php
+++ b/install/steps/4-config.php
@@ -10,6 +10,14 @@ foreach($config['clients'] as $client) {
$clients[$client] = $client_version;
}
+if (empty($_SESSION['var_site_url'])) {
+ //require SYSTEM . 'base.php';
+ $serverUrl = 'http' . (isHttps() ? 's' : '') . '://' . $baseHost;
+ $siteURL = $serverUrl . $baseDir;
+
+ $_SESSION['var_site_url'] = $siteURL;
+}
+
$twig->display('install.config.html.twig', array(
'clients' => $clients,
'timezones' => DateTimeZone::listIdentifiers(),
diff --git a/install/steps/5-database.php b/install/steps/5-database.php
index cb4f14a3..ecf7f150 100644
--- a/install/steps/5-database.php
+++ b/install/steps/5-database.php
@@ -42,45 +42,44 @@ if(!$error) {
$configToSave['cache_prefix'] = 'myaac_' . generateRandomString(8, true, false, true);
$configToSave['database_auto_migrate'] = true;
- if(!$error) {
- $content = '';
- $saved = Settings::saveConfig($configToSave, BASE . 'config.local.php', $content);
- if ($saved) {
- success($locale['step_database_config_saved']);
- $_SESSION['saved'] = true;
+ $content = '';
+ $saved = Settings::saveConfig($configToSave, BASE . 'config.local.php', $content);
+ if ($saved || file_exists(BASE . 'config.local.php')) {
+ success($locale['step_database_config_saved']);
+ $_SESSION['saved'] = true;
- require BASE . 'config.local.php';
- require BASE . 'install/includes/config.php';
+ require BASE . 'config.local.php';
+ require BASE . 'install/includes/config.php';
- if (!$error) {
- require BASE . 'install/includes/database.php';
+ if (!$error) {
+ require BASE . 'install/includes/database.php';
- if (isset($database_error)) { // we failed connect to the database
- error($database_error);
+ if (isset($database_error)) { // we failed connect to the database
+ error($database_error);
+ }
+ else {
+ if (!$db->hasTable('accounts')) {
+ $tmp = str_replace('$TABLE$', 'accounts', $locale['step_database_error_table']);
+ error($tmp);
+ $error = true;
}
- else {
- if (!$db->hasTable('accounts')) {
- $tmp = str_replace('$TABLE$', 'accounts', $locale['step_database_error_table']);
- error($tmp);
- $error = true;
- }
- if (!$error) {
- $twig->display('install.installer.html.twig', array(
- 'url' => 'tools/5-database.php',
- 'message' => $locale['loading_spinner']
- ));
- }
+ if (!$error) {
+ $twig->display('install.installer.html.twig', array(
+ 'url' => 'tools/5-database.php',
+ 'message' => $locale['loading_spinner']
+ ));
}
}
- } else {
- $_SESSION['config_content'] = $content;
- unset($_SESSION['saved']);
-
- $locale['step_database_error_file'] = str_replace('$FILE$', '' . BASE . 'config.php', $locale['step_database_error_file']);
- error($locale['step_database_error_file'] . '
- ');
}
+ } else {
+ $error = true;
+ $_SESSION['config_content'] = $content;
+ unset($_SESSION['saved']);
+
+ $locale['step_database_error_file'] = str_replace('$FILE$', '' . BASE . 'config.local.php', $locale['step_database_error_file']);
+ error($locale['step_database_error_file'] . '
+ ');
}
}
?>
diff --git a/install/steps/7-finish.php b/install/steps/7-finish.php
index 0ae302ea..afe63603 100644
--- a/install/steps/7-finish.php
+++ b/install/steps/7-finish.php
@@ -195,13 +195,4 @@ if(!isset($_SESSION['installed'])) {
$_SESSION['installed'] = true;
}
-foreach($_SESSION as $key => $value) {
- if(strpos($key, 'var_') !== false)
- unset($_SESSION[$key]);
-}
-unset($_SESSION['saved']);
-if(file_exists(CACHE . 'install.txt')) {
- unlink(CACHE . 'install.txt');
-}
-
$hooks->trigger(HOOK_INSTALL_FINISH_END);
diff --git a/install/tools/5-database.php b/install/tools/5-database.php
index 395492ee..6406ee48 100644
--- a/install/tools/5-database.php
+++ b/install/tools/5-database.php
@@ -7,6 +7,11 @@ require SYSTEM . 'functions.php';
require BASE . 'install/includes/functions.php';
require BASE . 'install/includes/locale.php';
+if(isset($config['installed']) && $config['installed'] && !isset($_SESSION['saved'])) {
+ warning($locale['already_installed']);
+ return;
+}
+
$error = false;
require BASE . 'install/includes/config.php';
@@ -25,26 +30,22 @@ if(!$error) {
}
}
-if($db->hasTable(TABLE_PREFIX . 'account_actions')) {
- $locale['step_database_error_table_exist'] = str_replace('$TABLE$', TABLE_PREFIX . 'account_actions', $locale['step_database_error_table_exist']);
- warning($locale['step_database_error_table_exist']);
-}
-else {
- // import schema
- try {
- $locale['step_database_importing'] = str_replace('$DATABASE_NAME$', config('database_name'), $locale['step_database_importing']);
- success($locale['step_database_importing']);
+// import schema
+try {
+ $locale['step_database_importing'] = str_replace('$DATABASE_NAME$', config('database_name'), $locale['step_database_importing']);
+ success($locale['step_database_importing']);
- $db->query(file_get_contents(BASE . 'install/includes/schema.sql'));
+ $db->exec(file_get_contents(BASE . 'install/includes/schema.sql'));
- $locale['step_database_success_schema'] = str_replace('$PREFIX$', TABLE_PREFIX, $locale['step_database_success_schema']);
- success($locale['step_database_success_schema']);
- }
- catch(PDOException $error_) {
- error($locale['step_database_error_schema'] . ' ' . $error_);
- return;
- }
+ $locale['step_database_success_schema'] = str_replace('$PREFIX$', TABLE_PREFIX, $locale['step_database_success_schema']);
+ success($locale['step_database_success_schema']);
}
+catch(PDOException $error_) {
+ error($locale['step_database_error_schema'] . ' ' . $error_);
+ return;
+}
+
+require BASE . 'install/includes/import_base_data.php';
if(!$db->hasColumn('accounts', 'email')) {
if(query("ALTER TABLE `accounts` ADD `email` varchar(255) NOT NULL DEFAULT '';"))
@@ -97,18 +98,13 @@ if(!$db->hasColumn('accounts', 'web_flags')) {
success($locale['step_database_adding_field'] . ' accounts.web_flags...');
}
-if(!$db->hasColumn('accounts', 'email_hash')) {
- if(query("ALTER TABLE `accounts` ADD `email_hash` VARCHAR(32) NOT NULL DEFAULT '' AFTER `web_flags`;"))
- success($locale['step_database_adding_field'] . ' accounts.email_hash...');
-}
-
if(!$db->hasColumn('accounts', 'email_verified')) {
- if(query("ALTER TABLE `accounts` ADD `email_verified` TINYINT(1) NOT NULL DEFAULT 0 AFTER `email_hash`;"))
+ if(query("ALTER TABLE `accounts` ADD `email_verified` TINYINT(1) NOT NULL DEFAULT 0 AFTER `web_flags`;"))
success($locale['step_database_adding_field'] . ' accounts.email_verified...');
}
if(!$db->hasColumn('accounts', 'email_new')) {
- if(query("ALTER TABLE `accounts` ADD `email_new` VARCHAR(255) NOT NULL DEFAULT '' AFTER `email_hash`;"))
+ if(query("ALTER TABLE `accounts` ADD `email_new` VARCHAR(255) NOT NULL DEFAULT '' AFTER `email_verified`;"))
success($locale['step_database_adding_field'] . ' accounts.email_new...');
}
diff --git a/install/tools/7-finish.php b/install/tools/7-finish.php
index c1ab5c1d..9c64382b 100644
--- a/install/tools/7-finish.php
+++ b/install/tools/7-finish.php
@@ -17,11 +17,11 @@ ini_set('max_execution_time', 300);
ob_implicit_flush();
header('X-Accel-Buffering: no');
-/*
+
if(isset($config['installed']) && $config['installed'] && !isset($_SESSION['saved'])) {
warning($locale['already_installed']);
return;
-}*/
+}
require SYSTEM . 'init.php';
@@ -94,6 +94,17 @@ $hooks->trigger(HOOK_INSTALL_FINISH);
$db->setClearCacheAfter(true);
+// cleanup
+foreach($_SESSION as $key => $value) {
+ if(str_contains($key, 'var_')) {
+ unset($_SESSION[$key]);
+ }
+}
+unset($_SESSION['saved']);
+if(file_exists(CACHE . 'install.txt')) {
+ unlink(CACHE . 'install.txt');
+}
+
$locale['step_finish_desc'] = str_replace('$ADMIN_PANEL$', generateLink(str_replace('tools/', '',ADMIN_URL), $locale['step_finish_admin_panel'], true), $locale['step_finish_desc']);
$locale['step_finish_desc'] = str_replace('$HOMEPAGE$', generateLink(str_replace('tools/', '', BASE_URL), $locale['step_finish_homepage'], true), $locale['step_finish_desc']);
$locale['step_finish_desc'] = str_replace('$LINK$', generateLink('https://my-aac.org', 'https://my-aac.org', true), $locale['step_finish_desc']);
diff --git a/login.php b/login.php
index 88d5d88a..438754e2 100644
--- a/login.php
+++ b/login.php
@@ -88,8 +88,8 @@ switch ($action) {
case 'boostedcreature':
$clientVersion = (int)setting('core.client');
- // 14.00 and up
- if ($clientVersion >= 1400) {
+ // 13.40 and up
+ if ($clientVersion >= 1340) {
$creatureBoost = $db->query("SELECT * FROM " . $db->tableName('boosted_creature'))->fetchAll();
$bossBoost = $db->query("SELECT * FROM " . $db->tableName('boosted_boss'))->fetchAll();
die(json_encode([
@@ -220,6 +220,8 @@ switch ($action) {
}
}
+ /*
+ * not needed anymore?
if (fieldExist('premdays', 'accounts') && fieldExist('lastday', 'accounts')) {
$save = false;
$timeNow = time();
@@ -256,6 +258,7 @@ switch ($action) {
$account->save();
}
}
+ */
$worlds = [$world];
$playdata = compact('worlds', 'characters');
diff --git a/package-lock.json b/package-lock.json
index 7cdffe23..3ea74539 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -976,15 +976,16 @@
}
},
"node_modules/form-data": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
- "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
+ "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"dev": true,
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
"mime-types": "^2.1.12"
},
"engines": {
@@ -2084,9 +2085,9 @@
"license": "MIT"
},
"node_modules/tmp": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
- "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==",
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.4.tgz",
+ "integrity": "sha512-UdiSoX6ypifLmrfQ/XfiawN6hkjSBpCjhKxxZcWlUUmoXLaCKQU0bx4HF/tdDK2uzRuchf1txGvrWBzYREssoQ==",
"dev": true,
"license": "MIT",
"engines": {
diff --git a/phpstan.neon b/phpstan.neon
index 020fa3a6..68e1aa6a 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -28,10 +28,9 @@ parameters:
- '#Variable \$guild might not be defined#'
- '#Variable \$[a-zA-Z0-9\\_]+ might not be defined#'
# Eloquent models
+ - '#Call to an undefined method [a-zA-Z0-9\\_]+::[a-zA-Z0-9\\_]+\(\)#'
- '#Call to an undefined static method [a-zA-Z0-9\\_]+::[a-zA-Z0-9\\_]+\(\)#'
- - '#Call to an undefined method object::toArray\(\)#'
# system/pages/highscores.php
- - '#Call to an undefined method Illuminate\\Database\\Query\\Builder::withOnlineStatus\(\)#'
- '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::\$online_status#'
- '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::\$vocation_name#'
-
diff --git a/plugins/example.json b/plugins/example.json
index 395db41d..fd5e183b 100644
--- a/plugins/example.json
+++ b/plugins/example.json
@@ -51,5 +51,8 @@
"themes": true,
"admin-pages": true,
"admin-pages-sub-folders": true,
+ "settings": true,
+ "install": true,
+ "init": false
}
}
diff --git a/system/base.php b/system/base.php
new file mode 100644
index 00000000..9cab2925
--- /dev/null
+++ b/system/base.php
@@ -0,0 +1,21 @@
+ 'account_change_character_name_price',
'account_change_character_sex',
'account_change_character_sex_points' => 'account_change_character_name_price',
+ 'email_lai_sec_interval' => 'mail_lost_account_interval',
];
foreach ($deprecatedConfig as $key => $value) {
diff --git a/system/functions.php b/system/functions.php
index 6e58ca9d..f11fa382 100644
--- a/system/functions.php
+++ b/system/functions.php
@@ -433,16 +433,22 @@ function delete_guild($id)
$rank_list->orderBy('level');
global $db;
+
+ $deletedColumn = 'deleted';
+ if ($db->hasColumn('players', 'deletion')) {
+ $deletedColumn = 'deletion';
+ }
+
/**
* @var OTS_GuildRank $rank_in_guild
*/
foreach($rank_list as $rank_in_guild) {
if($db->hasTable('guild_members'))
- $players_with_rank = $db->query('SELECT `players`.`id` as `id`, `guild_members`.`rank_id` as `rank_id` FROM `players`, `guild_members` WHERE `guild_members`.`rank_id` = ' . $rank_in_guild->getId() . ' AND `players`.`id` = `guild_members`.`player_id` ORDER BY `name`;');
+ $players_with_rank = $db->query('SELECT `players`.`id` as `id`, `guild_members`.`rank_id` as `rank_id` FROM `players`, `guild_members` WHERE `guild_members`.`rank_id` = ' . $rank_in_guild->getId() . ' AND `players`.`id` = `guild_members`.`player_id` AND `' . $deletedColumn . '` = 0 ORDER BY `name`;');
else if($db->hasTable('guild_membership'))
- $players_with_rank = $db->query('SELECT `players`.`id` as `id`, `guild_membership`.`rank_id` as `rank_id` FROM `players`, `guild_membership` WHERE `guild_membership`.`rank_id` = ' . $rank_in_guild->getId() . ' AND `players`.`id` = `guild_membership`.`player_id` ORDER BY `name`;');
+ $players_with_rank = $db->query('SELECT `players`.`id` as `id`, `guild_membership`.`rank_id` as `rank_id` FROM `players`, `guild_membership` WHERE `guild_membership`.`rank_id` = ' . $rank_in_guild->getId() . ' AND `players`.`id` = `guild_membership`.`player_id` AND `' . $deletedColumn . '` = 0 ORDER BY `name`;');
else
- $players_with_rank = $db->query('SELECT `id`, `rank_id` FROM `players` WHERE `rank_id` = ' . $rank_in_guild->getId() . ' AND `deleted` = 0;');
+ $players_with_rank = $db->query('SELECT `id`, `rank_id` FROM `players` WHERE `rank_id` = ' . $rank_in_guild->getId() . ' AND `' . $deletedColumn . '` = 0;');
$players_with_rank_number = $players_with_rank->rowCount();
if($players_with_rank_number > 0) {
@@ -512,6 +518,13 @@ function template_place_holder($type): string
}
elseif ($type === 'body_start') {
$ret .= $twig->render('browsehappy.html.twig');
+
+ if (admin()) {
+ global $account_logged;
+ $ret .= $twig->render('admin-bar.html.twig', [
+ 'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId()
+ ]);
+ }
}
elseif($type === 'body_end') {
$ret .= template_ga_code();
@@ -767,6 +780,10 @@ function formatExperience($exp, $color = true)
return $ret;
}
+function getExperienceForLevel($level): float|int {
+ return ( 50 / 3 ) * pow( $level, 3 ) - ( 100 * pow( $level, 2 ) ) + ( ( 850 / 3 ) * $level ) - 200;
+}
+
function get_locales()
{
$ret = array();
@@ -982,11 +999,12 @@ function load_config_lua($filename)
foreach($lines as $ln => $line)
{
$line = trim($line);
- if(@$line[0] === '{' || @$line[0] === '}') {
+ if(isset($line[0]) && ($line[0] === '{' || $line[0] === '}')) {
// arrays are not supported yet
// just ignore the error
continue;
}
+
$tmp_exp = explode('=', $line, 2);
if(str_contains($line, 'dofile')) {
$delimiter = '"';
@@ -1130,10 +1148,18 @@ function getTopPlayers($limit = 5, $skill = 'level') {
'looktype', 'lookhead', 'lookbody', 'looklegs', 'lookfeet'
];
+ if ($db->hasColumn('players', 'promotion')) {
+ $columns[] = 'promotion';
+ }
+
if ($db->hasColumn('players', 'lookaddons')) {
$columns[] = 'lookaddons';
}
+ if ($db->hasColumn('players', 'lookmount')) {
+ $columns[] = 'lookmount';
+ }
+
return Player::query()
->select($columns)
->withOnlineStatus()
@@ -1157,7 +1183,8 @@ function getTopPlayers($limit = 5, $skill = 'level') {
});
}
-function deleteDirectory($dir, $ignore = array(), $contentOnly = false) {
+function deleteDirectory($dir, $ignore = array(), $contentOnly = false): bool
+{
if(!file_exists($dir)) {
return true;
}
@@ -1183,6 +1210,21 @@ function deleteDirectory($dir, $ignore = array(), $contentOnly = false) {
return rmdir($dir);
}
+function ensureFolderExists($dir): void
+{
+ if (!file_exists($dir)) {
+ mkdir($dir, 0777, true);
+ }
+}
+
+function ensureIndexExists($dir): void
+{
+ $dir = rtrim($dir, '/');
+ if (!file_exists($file = $dir . '/index.html')) {
+ touch($file);
+ }
+}
+
function config($key) {
global $config;
if (is_array($key)) {
@@ -1216,7 +1258,8 @@ function setting($key)
return $settings[$key[0]] = $key[1];
}
- return $settings[$key]['value'];
+ $ret = $settings[$key];
+ return isset($ret) ? $ret['value'] : null;
}
function clearCache()
@@ -1265,14 +1308,15 @@ function clearCache()
$db->setClearCacheAfter(true);
}
+ if (function_exists('apcu_clear_cache')) {
+ apcu_clear_cache();
+ }
+
deleteDirectory(CACHE . 'signatures', ['index.html'], true);
deleteDirectory(CACHE . 'twig', ['index.html'], true);
deleteDirectory(CACHE . 'plugins', ['index.html'], true);
deleteDirectory(CACHE, ['signatures', 'twig', 'plugins', 'index.html', 'persistent'], true);
- // routes cache
- clearRouteCache();
-
global $hooks;
$hooks->trigger(HOOK_CACHE_CLEAR, ['cache' => Cache::getInstance()]);
@@ -1618,13 +1662,14 @@ function camelCaseToUnderscore($input)
return ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_');
}
-function removeIfFirstSlash(&$text) {
+function removeIfFirstSlash(&$text): void
+{
if(strpos($text, '/') === 0) {
$text = str_replace_first('/', '', $text);
}
};
-function escapeHtml($html) {
+function escapeHtml($html): string {
return htmlspecialchars($html);
}
@@ -1638,7 +1683,7 @@ function getGuildNameById($id)
return false;
}
-function getGuildLogoById($id)
+function getGuildLogoById($id): string
{
$logo = 'default.gif';
@@ -1654,7 +1699,8 @@ function getGuildLogoById($id)
return BASE_URL . GUILD_IMAGES_DIR . $logo;
}
-function displayErrorBoxWithBackButton($errors, $action = null) {
+function displayErrorBoxWithBackButton($errors, $action = null): void
+{
global $twig;
$twig->display('error_box.html.twig', ['errors' => $errors]);
$twig->display('account.back_button.html.twig', [
@@ -1682,6 +1728,49 @@ function getAccountIdentityColumn(): string
return 'id';
}
+function isCanary(): bool
+{
+ $vipSystemEnabled = configLua('vipSystemEnabled');
+ return isset($vipSystemEnabled);
+}
+
+function getStatusUptimeReadable(int $uptime): string
+{
+ $fullMinute = 60;
+ $fullHour = (60 * $fullMinute);
+ $fullDay = (24 * $fullHour);
+ $fullMonth = (30 * $fullDay);
+ $fullYear = (365 * $fullDay);
+
+ // years
+ $years = floor($uptime / $fullYear);
+ $y = ($years > 1 ? "$years years, " : ($years == 1 ? 'year, ' : ''));
+
+ $uptime -= $years * $fullYear;
+
+ // months
+ $months = floor($uptime / $fullMonth);
+ $m = ($months > 1 ? "$months months, " : ($months == 1 ? 'month, ' : ''));
+
+ $uptime -= $months * $fullMonth;
+
+ // days
+ $days = floor($uptime / $fullDay);
+ $d = ($days > 1 ? "$days days, " : ($days == 1 ? 'day, ' : ''));
+
+ $uptime -= $days * $fullDay;
+
+ // hours
+ $hours = floor($uptime / $fullHour);
+
+ $uptime -= $hours * $fullHour;
+
+ // minutes
+ $min = floor($uptime / $fullMinute);
+
+ return "{$y}{$m}{$d}{$hours}h {$min}m";
+}
+
// validator functions
require_once SYSTEM . 'compat/base.php';
diff --git a/system/init.php b/system/init.php
index 44634265..862b5370 100644
--- a/system/init.php
+++ b/system/init.php
@@ -12,11 +12,15 @@ use DebugBar\StandardDebugBar;
use MyAAC\Cache\Cache;
use MyAAC\CsrfToken;
use MyAAC\Hooks;
+use MyAAC\Plugins;
use MyAAC\Models\Town;
use MyAAC\Settings;
defined('MYAAC') or die('Direct access not allowed!');
+ensureIndexExists(CACHE);
+ensureIndexExists(CACHE . 'twig/');
+
global $config;
if(!isset($config['installed']) || !$config['installed']) {
throw new RuntimeException('MyAAC has not been installed yet or there was error during installation. Please install again.');
@@ -46,6 +50,11 @@ if(isset($config['gzip_output']) && $config['gzip_output'] && isset($_SERVER['HT
global $cache;
$cache = Cache::getInstance();
+// load plugins init.php
+foreach (Plugins::getInits() as $init) {
+ require $init;
+}
+
// event system
global $hooks;
$hooks = new Hooks();
@@ -138,6 +147,15 @@ $ots = POT::getInstance();
$eloquentConnection = null;
require_once SYSTEM . 'database.php';
+define('USE_ACCOUNT_NAME', $db->hasColumn('accounts', 'name'));
+define('USE_ACCOUNT_NUMBER', $db->hasColumn('accounts', 'number'));
+define('USE_ACCOUNT_SALT', $db->hasColumn('accounts', 'salt'));
+
+define('HAS_ACCOUNT_COINS', $db->hasColumn('accounts', 'coins'));
+define('HAS_ACCOUNT_COINS_TRANSFERABLE', $db->hasColumn('accounts', 'coins_transferable'));
+define('HAS_ACCOUNT_TRANSFERABLE_COINS', $db->hasColumn('accounts', 'transferable_coins'));
+const ACCOUNT_COINS_TRANSFERABLE_COLUMN = (HAS_ACCOUNT_COINS_TRANSFERABLE ? 'coins_transferable' : 'transferable_coins');
+
$twig->addGlobal('logged', false);
$twig->addGlobal('account_logged', new \OTS_Account());
@@ -182,10 +200,6 @@ if($settingsItemImagesURL[strlen($settingsItemImagesURL) - 1] !== '/') {
setting(['core.item_images_url', $settingsItemImagesURL . '/']);
}
-define('USE_ACCOUNT_NAME', $db->hasColumn('accounts', 'name'));
-define('USE_ACCOUNT_NUMBER', $db->hasColumn('accounts', 'number'));
-define('USE_ACCOUNT_SALT', $db->hasColumn('accounts', 'salt'));
-
$towns = Cache::remember('towns', 10 * 60, function () use ($db) {
if ($db->hasTable('towns') && Town::count() > 0) {
return Town::orderBy('id', 'ASC')->pluck('name', 'id')->toArray();
diff --git a/system/libs/pot/OTS_Account.php b/system/libs/pot/OTS_Account.php
index 8528cf3f..8505128e 100644
--- a/system/libs/pot/OTS_Account.php
+++ b/system/libs/pot/OTS_Account.php
@@ -38,7 +38,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @var array
* @version 0.1.5
*/
- private $data = array('email' => '', 'rlname' => '','location' => '', 'country' => '','web_flags' => 0, 'lastday' => 0, 'premdays' => 0, 'created' => 0);
+ private $data = array('email' => '', 'rlname' => '','location' => '', 'country' => '','web_flags' => 0, 'lastday' => 0, 'premdays' => 0, 'created' => 0);
public static $cache = array();
@@ -66,39 +66,39 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @example examples/create.php create.php
* @tutorial POT/Accounts.pkg#create
*/
- public function createNamed($name = null)
- {
- // if name is not passed then it will be generated randomly
- if( !isset($name) )
- {
- // reads already existing names
- foreach( $this->db->query('SELECT ' . $this->db->fieldName('name') . ' FROM ' . $this->db->tableName('accounts') )->fetchAll() as $account)
- {
- $exist[] = $account['name'];
- }
+ public function createNamed($name = null)
+ {
+ // if name is not passed then it will be generated randomly
+ if( !isset($name) )
+ {
+ // reads already existing names
+ foreach( $this->db->query('SELECT ' . $this->db->fieldName('name') . ' FROM ' . $this->db->tableName('accounts') )->fetchAll() as $account)
+ {
+ $exist[] = $account['name'];
+ }
- // initial name
- $name = uniqid();
+ // initial name
+ $name = uniqid();
- // repeats until name is unique
- while( in_array($name, $exist) )
- {
- $name .= '_';
- }
+ // repeats until name is unique
+ while( in_array($name, $exist) )
+ {
+ $name .= '_';
+ }
- // resets array for account numbers loop
- $exist = array();
- }
+ // resets array for account numbers loop
+ $exist = array();
+ }
- // saves blank account info
- $this->db->exec('INSERT INTO ' . $this->db->tableName('accounts') . ' (' . $this->db->fieldName('name') . ', ' . $this->db->fieldName('password') . ', ' . $this->db->fieldName('email') . ') VALUES (' . $this->db->quote($name) . ', \'\', \'\')');
+ // saves blank account info
+ $this->db->exec('INSERT INTO ' . $this->db->tableName('accounts') . ' (' . $this->db->fieldName('name') . ', ' . $this->db->fieldName('password') . ', ' . $this->db->fieldName('email') . ') VALUES (' . $this->db->quote($name) . ', \'\', \'\')');
- // reads created account's ID
- $this->data['id'] = $this->db->lastInsertId();
+ // reads created account's ID
+ $this->data['id'] = $this->db->lastInsertId();
- // return name of newly created account
- return $name;
- }
+ // return name of newly created account
+ return $name;
+ }
/**
* @param $email
@@ -166,8 +166,8 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws Exception ON lastInsertId error.
* @deprecated 0.1.5 Use createNamed().
*/
- public function create($name = NULL, $id = NULL)
- {
+ public function create($name = NULL, $id = NULL)
+ {
if(isset($name)) {
$nameOrNumber = 'name';
$nameOrNumberValue = $name;
@@ -183,8 +183,8 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
}
}
- // saves blank account info
- $this->db->exec('INSERT INTO `accounts` (' . (isset($id) ? '`id`,' : '') . (isset($nameOrNumber) ? '`' . $nameOrNumber . '`,' : '') . '`password`, `email`, `created`) VALUES (' . (isset($id) ? $id . ',' : '') . (isset($nameOrNumber) ? $this->db->quote($nameOrNumberValue) . ',' : '') . ' \'\', \'\',' . time() . ')');
+ // saves blank account info
+ $this->db->exec('INSERT INTO `accounts` (' . (isset($id) ? '`id`,' : '') . (isset($nameOrNumber) ? '`' . $nameOrNumber . '`,' : '') . '`password`, `email`, `created`) VALUES (' . (isset($id) ? $id . ',' : '') . (isset($nameOrNumber) ? $this->db->quote($nameOrNumberValue) . ',' : '') . ' \'\', \'\',' . time() . ')');
if(isset($name)) {
$this->data['name'] = $name;
@@ -206,8 +206,8 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
throw new Exception(__CLASS__ . ':' . __METHOD__ . ' unexpected error. Please report to MyAAC Developers.');
}
- return $this->data['id'];
- }
+ return $this->data['id'];
+ }
/**
* @version 0.0.6
@@ -218,10 +218,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @return int Created account number.
* @deprecated 0.0.6 There is no more group_id field in database, use create().
*/
- public function createEx(OTS_Group $group, $min = 1, $max = 9999999)
- {
- return $this->create($min, $max);
- }
+ public function createEx(OTS_Group $group, $min = 1, $max = 9999999)
+ {
+ return $this->create($min, $max);
+ }
/**
* Loads account with given number.
@@ -230,8 +230,8 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @param int $id Account number.
* @throws PDOException On PDO operation error.
*/
- public function load($id, $fresh = false)
- {
+ public function load($id, $fresh = false)
+ {
if(!$fresh && isset(self::$cache[$id])) {
$this->data = self::$cache[$id];
return;
@@ -244,10 +244,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
$nameOrNumber = '`number`,';
}
- // SELECT query on database
+ // SELECT query on database
$this->data = $this->db->query('SELECT `id`, ' . $nameOrNumber . '`password`, `email`, `rlname`, `location`, `country`, `web_flags`, ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays`, ' : '') . ($this->db->hasColumn('accounts', 'lastday') ? '`lastday`, ' : ($this->db->hasColumn('accounts', 'premend') ? '`premend`,' : ($this->db->hasColumn('accounts', 'premium_ends_at') ? '`premium_ends_at`,' : ''))) . '`created` FROM `accounts` WHERE `id` = ' . (int) $id)->fetch();
self::$cache[$id] = $this->data;
- }
+ }
/**
* Loads account by it's name.
@@ -261,22 +261,22 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @param string $name Account's name.
* @throws PDOException On PDO operation error.
*/
- public function find($name)
- {
+ public function find($name)
+ {
$nameOrNumberColumn = 'name';
if (USE_ACCOUNT_NUMBER) {
$nameOrNumberColumn = 'number';
}
- // finds player's ID
- $id = $this->db->query('SELECT `id` FROM `accounts` WHERE `' . $nameOrNumberColumn . '` = ' . $this->db->quote($name) )->fetch();
+ // finds player's ID
+ $id = $this->db->query('SELECT `id` FROM `accounts` WHERE `' . $nameOrNumberColumn . '` = ' . $this->db->quote($name) )->fetch();
- // if anything was found
- if( isset($id['id']) )
- {
- $this->load($id['id']);
- }
- }
+ // if anything was found
+ if( isset($id['id']) )
+ {
+ $this->load($id['id']);
+ }
+ }
/**
* Loads account by it's e-mail address.
@@ -286,27 +286,27 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @param string $email Account's e-mail address.
* @throws PDOException On PDO operation error.
*/
- public function findByEMail($email)
- {
- // finds player's ID
- $id = $this->db->query('SELECT `id` FROM `accounts` WHERE `email` = ' . $this->db->quote($email) )->fetch();
+ public function findByEMail($email)
+ {
+ // finds player's ID
+ $id = $this->db->query('SELECT `id` FROM `accounts` WHERE `email` = ' . $this->db->quote($email) )->fetch();
- // if anything was found
- if( isset($id['id']) )
- {
- $this->load($id['id']);
- }
- }
+ // if anything was found
+ if( isset($id['id']) )
+ {
+ $this->load($id['id']);
+ }
+ }
/**
* Checks if object is loaded.
*
* @return bool Load state.
*/
- public function isLoaded()
- {
- return isset($this->data['id']);
- }
+ public function isLoaded()
+ {
+ return isset($this->data['id']);
+ }
/**
* Updates account in database.
@@ -323,16 +323,16 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws E_OTS_NotLoaded If account doesn't have ID assigned.
* @throws PDOException On PDO operation error.
*/
- public function save()
- {
- if( !isset($this->data['id']) )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function save()
+ {
+ if( !isset($this->data['id']) )
+ {
+ throw new E_OTS_NotLoaded();
+ }
$field = 'lastday';
if($this->db->hasColumn('accounts', 'premend')) { // othire
- $field = 'premend';
+ $field = 'premend';
if(!isset($this->data['premend'])) {
$this->data['premend'] = 0;
}
@@ -344,9 +344,9 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
}
}
- // UPDATE query on database
- $this->db->exec('UPDATE `accounts` SET ' . ($this->db->hasColumn('accounts', 'name') ? '`name` = ' . $this->db->quote($this->data['name']) . ',' : '') . '`password` = ' . $this->db->quote($this->data['password']) . ', `email` = ' . $this->db->quote($this->data['email']) . ', `rlname` = ' . $this->db->quote($this->data['rlname']) . ', `location` = ' . $this->db->quote($this->data['location']) . ', `country` = ' . $this->db->quote($this->data['country']) . ', `web_flags` = ' . (int) $this->data['web_flags'] . ', ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays` = ' . (int) $this->data['premdays'] . ',' : '') . '`' . $field . '` = ' . (int) $this->data[$field] . ' WHERE `id` = ' . $this->data['id']);
- }
+ // UPDATE query on database
+ $this->db->exec('UPDATE `accounts` SET ' . ($this->db->hasColumn('accounts', 'name') ? '`name` = ' . $this->db->quote($this->data['name']) . ',' : '') . '`password` = ' . $this->db->quote($this->data['password']) . ', `email` = ' . $this->db->quote($this->data['email']) . ', `rlname` = ' . $this->db->quote($this->data['rlname']) . ', `location` = ' . $this->db->quote($this->data['location']) . ', `country` = ' . $this->db->quote($this->data['country']) . ', `web_flags` = ' . (int) $this->data['web_flags'] . ', ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays` = ' . (int) $this->data['premdays'] . ',' : '') . '`' . $field . '` = ' . (int) $this->data[$field] . ' WHERE `id` = ' . $this->data['id']);
+ }
/**
* Account number.
@@ -359,15 +359,15 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @return int Account number.
* @throws E_OTS_NotLoaded If account is not loaded.
*/
- public function getId()
- {
- if( !isset($this->data['id']) )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function getId()
+ {
+ if( !isset($this->data['id']) )
+ {
+ throw new E_OTS_NotLoaded();
+ }
- return $this->data['id'];
- }
+ return $this->data['id'];
+ }
public function getNumber()
{
@@ -378,45 +378,45 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
return $this->data['id'];
}
- public function getRLName()
- {
- if( !isset($this->data['rlname']) )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function getRLName()
+ {
+ if( !isset($this->data['rlname']) )
+ {
+ throw new E_OTS_NotLoaded();
+ }
- return $this->data['rlname'];
- }
+ return $this->data['rlname'];
+ }
- public function getLocation()
- {
- if( !isset($this->data['location']) )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function getLocation()
+ {
+ if( !isset($this->data['location']) )
+ {
+ throw new E_OTS_NotLoaded();
+ }
- return $this->data['location'];
- }
+ return $this->data['location'];
+ }
- public function getCountry()
- {
- if( !isset($this->data['country']) )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function getCountry()
+ {
+ if( !isset($this->data['country']) )
+ {
+ throw new E_OTS_NotLoaded();
+ }
- return $this->data['country'];
- }
+ return $this->data['country'];
+ }
- public function getWebFlags()
- {
- if( !isset($this->data['web_flags']) )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function getWebFlags()
+ {
+ if( !isset($this->data['web_flags']) )
+ {
+ throw new E_OTS_NotLoaded();
+ }
- return $this->data['web_flags'];
- }
+ return $this->data['web_flags'];
+ }
public function hasFlag($flag)
{
@@ -443,10 +443,11 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
throw new E_OTS_NotLoaded();
}
- if(isset($this->data['premium_ends_at']) || isset($this->data['premend'])) {
- $col = isset($this->data['premium_ends_at']) ? 'premium_ends_at' : 'premend';
- $ret = ceil(($this->data[$col] - time()) / (24 * 60 * 60));
- return max($ret, 0);
+ if(isset($this->data['premium_ends_at']) || isset($this->data['premend']) ||
+ (isCanary() && isset($this->data['lastday']))) {
+ $col = (isset($this->data['premium_ends_at']) ? 'premium_ends_at' : (isset($this->data['lastday']) ? 'lastday' : 'premend'));
+ $ret = ceil(($this->data[$col] - time()) / (24 * 60 * 60));
+ return max($ret, 0);
}
if($this->data['premdays'] == 0) {
@@ -462,40 +463,39 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
}
public function getLastLogin()
- {
- if( !isset($this->data['lastday']) )
- {
- throw new E_OTS_NotLoaded();
- }
+ {
+ if( !isset($this->data['lastday']) )
+ {
+ throw new E_OTS_NotLoaded();
+ }
- return $this->data['lastday'];
- }
+ return $this->data['lastday'];
+ }
- public function isPremium()
- {
- global $config;
- if(isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium'])) return true;
+ public function isPremium(): bool
+ {
+ if(isset($this->data['premium_ends_at']) || isset($this->data['premend']) ||
+ (isCanary() && isset($this->data['lastday']))) {
+ $col = (isset($this->data['premium_ends_at']) ? 'premium_ends_at' : (isset($this->data['lastday']) ? 'lastday' : 'premend'));
+ return $this->data[$col] > time();
+ }
- if(isset($this->data['premium_ends_at'])) {
- return $this->data['premium_ends_at'] > time();
- }
-
- if(isset($this->data['premend'])) {
- return $this->data['premend'] > time();
+ if($this->data['premdays'] == self::GRATIS_PREMIUM_DAYS){
+ return true;
}
return ($this->data['premdays'] - (date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->data['lastday']))) - date("z", $this->data['lastday'])) > 0);
}
- public function getCreated()
- {
- if( !isset($this->data['created']) )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function getCreated()
+ {
+ if( !isset($this->data['created']) )
+ {
+ throw new E_OTS_NotLoaded();
+ }
- return $this->data['created'];
- }
+ return $this->data['created'];
+ }
/**
* Name.
@@ -504,37 +504,37 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @since 0.7.5
* @throws E_OTS_NotLoaded If account is not loaded.
*/
- public function setPremDays($premdays)
- {
+ public function setPremDays($premdays)
+ {
$this->data['premdays'] = (int) $premdays;
$this->data['premend'] = time() + ($premdays * 24 * 60 * 60);
$this->data['premium_ends_at'] = time() + ($premdays * 24 * 60 * 60);
- }
+ }
- public function setRLName($name)
- {
- $this->data['rlname'] = (string) $name;
- }
+ public function setRLName($name)
+ {
+ $this->data['rlname'] = (string) $name;
+ }
- public function setLocation($location)
- {
- $this->data['location'] = (string) $location;
- }
+ public function setLocation($location)
+ {
+ $this->data['location'] = (string) $location;
+ }
- public function setCountry($country)
- {
- $this->data['country'] = (string) $country;
- }
+ public function setCountry($country)
+ {
+ $this->data['country'] = (string) $country;
+ }
public function setLastLogin($lastlogin)
- {
- $this->data['lastday'] = (int) $lastlogin;
- }
+ {
+ $this->data['lastday'] = (int) $lastlogin;
+ }
- public function setWebFlags($webflags)
- {
- $this->data['web_flags'] = (int) $webflags;
- }
+ public function setWebFlags($webflags)
+ {
+ $this->data['web_flags'] = (int) $webflags;
+ }
/**
* Name.
@@ -544,15 +544,15 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @return string Name.
* @throws E_OTS_NotLoaded If account is not loaded.
*/
- public function getName()
- {
- if( !isset($this->data['name']) )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function getName()
+ {
+ if( !isset($this->data['name']) )
+ {
+ throw new E_OTS_NotLoaded();
+ }
- return $this->data['name'];
- }
+ return $this->data['name'];
+ }
/**
* Sets account's name.
@@ -565,10 +565,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @since 0.1.5
* @param string $name Account name.
*/
- public function setName($name)
- {
- $this->data['name'] = (string) $name;
- }
+ public function setName($name)
+ {
+ $this->data['name'] = (string) $name;
+ }
/**
* Account's password.
@@ -585,15 +585,15 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @return string Password.
* @throws E_OTS_NotLoaded If account is not loaded.
*/
- public function getPassword()
- {
- if( !isset($this->data['password']) )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function getPassword()
+ {
+ if( !isset($this->data['password']) )
+ {
+ throw new E_OTS_NotLoaded();
+ }
- return $this->data['password'];
- }
+ return $this->data['password'];
+ }
/**
* Sets account's password.
@@ -608,10 +608,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
*
* @param string $password Password.
*/
- public function setPassword($password)
- {
- $this->data['password'] = (string) $password;
- }
+ public function setPassword($password)
+ {
+ $this->data['password'] = (string) $password;
+ }
/**
* E-mail address.
*
@@ -623,15 +623,15 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @return string E-mail.
* @throws E_OTS_NotLoaded If account is not loaded.
*/
- public function getEMail()
- {
- if( !isset($this->data['email']) )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function getEMail()
+ {
+ if( !isset($this->data['email']) )
+ {
+ throw new E_OTS_NotLoaded();
+ }
- return $this->data['email'];
- }
+ return $this->data['email'];
+ }
/**
* Sets account's email.
@@ -642,10 +642,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
*
* @param string $email E-mail address.
*/
- public function setEMail($email)
- {
- $this->data['email'] = (string) $email;
- }
+ public function setEMail($email)
+ {
+ $this->data['email'] = (string) $email;
+ }
/**
* Reads custom field.
@@ -665,16 +665,16 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws E_OTS_NotLoaded If account is not loaded.
* @throws PDOException On PDO operation error.
*/
- public function getCustomField($field)
- {
- if( !isset($this->data['id']) )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function getCustomField($field)
+ {
+ if( !isset($this->data['id']) )
+ {
+ throw new E_OTS_NotLoaded();
+ }
- $value = $this->db->query('SELECT ' . $this->db->fieldName($field) . ' FROM ' . $this->db->tableName('accounts') . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id'])->fetch();
- return $value[$field];
- }
+ $value = $this->db->query('SELECT ' . $this->db->fieldName($field) . ' FROM ' . $this->db->tableName('accounts') . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id'])->fetch();
+ return $value[$field];
+ }
/**
* Writes custom field.
@@ -698,20 +698,20 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws E_OTS_NotLoaded If account is not loaded.
* @throws PDOException On PDO operation error.
*/
- public function setCustomField($field, $value)
- {
- if( !isset($this->data['id']) )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function setCustomField($field, $value)
+ {
+ if( !isset($this->data['id']) )
+ {
+ throw new E_OTS_NotLoaded();
+ }
- // quotes value for SQL query
- if(!( is_int($value) || is_float($value) ))
- {
- $value = $this->db->quote($value);
- }
- $this->db->exec('UPDATE ' . $this->db->tableName('accounts') . ' SET ' . $this->db->fieldName($field) . ' = ' . $value . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id']);
- }
+ // quotes value for SQL query
+ if(!( is_int($value) || is_float($value) ))
+ {
+ $value = $this->db->quote($value);
+ }
+ $this->db->exec('UPDATE ' . $this->db->tableName('accounts') . ' SET ' . $this->db->fieldName($field) . ' = ' . $value . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id']);
+ }
/**
* @version 0.1.0
@@ -719,25 +719,25 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws E_OTS_NotLoaded If account is not loaded.
* @deprecated 0.0.5 Use getPlayersList().
*/
- public function getPlayers()
- {
- if( !isset($this->data['id']) )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function getPlayers()
+ {
+ if( !isset($this->data['id']) )
+ {
+ throw new E_OTS_NotLoaded();
+ }
- $players = array();
+ $players = array();
- foreach( $this->db->query('SELECT ' . $this->db->fieldName('id') . ' FROM ' . $this->db->tableName('players') . ' WHERE ' . $this->db->fieldName('account_id') . ' = ' . $this->data['id'])->fetchAll() as $player)
- {
- // creates new object
- $object = new OTS_Player();
- $object->load($player['id']);
- $players[] = $object;
- }
+ foreach( $this->db->query('SELECT ' . $this->db->fieldName('id') . ' FROM ' . $this->db->tableName('players') . ' WHERE ' . $this->db->fieldName('account_id') . ' = ' . $this->data['id'])->fetchAll() as $player)
+ {
+ // creates new object
+ $object = new OTS_Player();
+ $object->load($player['id']);
+ $players[] = $object;
+ }
- return $players;
- }
+ return $players;
+ }
/**
* List of characters on account.
@@ -755,16 +755,16 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @return OTS_Players_List List of players from current account.
* @throws E_OTS_NotLoaded If account is not loaded.
*/
- public function getPlayersList($withDeleted = true)
- {
- if( !isset($this->data['id']) )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function getPlayersList($withDeleted = true)
+ {
+ if( !isset($this->data['id']) )
+ {
+ throw new E_OTS_NotLoaded();
+ }
- // creates filter
- $filter = new OTS_SQLFilter();
- $filter->compareField('account_id', (int) $this->data['id']);
+ // creates filter
+ $filter = new OTS_SQLFilter();
+ $filter->compareField('account_id', (int) $this->data['id']);
if(!$withDeleted) {
global $db;
@@ -775,12 +775,12 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
}
}
- // creates list object
- $list = new OTS_Players_List();
- $list->setFilter($filter);
+ // creates list object
+ $list = new OTS_Players_List();
+ $list->setFilter($filter);
- return $list;
- }
+ return $list;
+ }
/**
* @version 0.1.5
@@ -789,22 +789,22 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws PDOException On PDO operation error.
* @deprecated 0.1.5 Use OTS_AccountBan class.
*/
- public function ban($time = 0)
- {
- // can't ban nothing
- if( !$this->isLoaded() )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function ban($time = 0)
+ {
+ // can't ban nothing
+ if( !$this->isLoaded() )
+ {
+ throw new E_OTS_NotLoaded();
+ }
- // creates ban entry
- $ban = new OTS_AccountBan();
- $ban->setValue($this->data['id']);
- $ban->setExpires($time);
- $ban->setAdded( time() );
- $ban->activate();
- $ban->save();
- }
+ // creates ban entry
+ $ban = new OTS_AccountBan();
+ $ban->setValue($this->data['id']);
+ $ban->setExpires($time);
+ $ban->setAdded( time() );
+ $ban->activate();
+ $ban->save();
+ }
/**
* @version 0.1.5
@@ -812,19 +812,19 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws PDOException On PDO operation error.
* @deprecated 0.1.5 Use OTS_AccountBan class.
*/
- public function unban()
- {
- // can't unban nothing
- if( !$this->isLoaded() )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function unban()
+ {
+ // can't unban nothing
+ if( !$this->isLoaded() )
+ {
+ throw new E_OTS_NotLoaded();
+ }
- // deletes ban entry
- $ban = new OTS_AccountBan();
- $ban->find($this->data['id']);
- $ban->delete();
- }
+ // deletes ban entry
+ $ban = new OTS_AccountBan();
+ $ban->find($this->data['id']);
+ $ban->delete();
+ }
/**
* @version 0.1.5
@@ -833,37 +833,37 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws PDOException On PDO operation error.
* @deprecated 0.1.5 Use OTS_AccountBan class.
*/
- public function isBanned()
- {
- // nothing can't be banned
- if( !$this->isLoaded() )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function isBanned()
+ {
+ // nothing can't be banned
+ if( !$this->isLoaded() )
+ {
+ throw new E_OTS_NotLoaded();
+ }
if( !isset($this->data['banned']) )
$this->loadBan();
- return ($this->data['banned'] === true);
- }
+ return ($this->data['banned'] === true);
+ }
- public function getBanTime()
- {
- // nothing can't be banned
- if( !$this->isLoaded() )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function getBanTime()
+ {
+ // nothing can't be banned
+ if( !$this->isLoaded() )
+ {
+ throw new E_OTS_NotLoaded();
+ }
if( !isset($this->data['banned_time']) )
$this->loadBan();
- return $this->data['banned_time'];
- }
+ return $this->data['banned_time'];
+ }
- public function loadBan()
- {
- // nothing can't be banned
- if( !$this->isLoaded() )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function loadBan()
+ {
+ // nothing can't be banned
+ if( !$this->isLoaded() )
+ {
+ throw new E_OTS_NotLoaded();
+ }
if($this->db->hasTable('account_bans')) {
$ban = $this->db->query('SELECT `expires_at` FROM `account_bans` WHERE `account_id` = ' . $this->data['id'] . ' AND (`expires_at` > ' . time() .' OR `expires_at` = -1) ORDER BY `expires_at` DESC')->fetch();
@@ -886,7 +886,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
$this->data['banned'] = false;
$this->data['banned_time'] = 0;
}
- }
+ }
/**
* Deletes account.
@@ -900,19 +900,19 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws E_OTS_NotLoaded If account is not loaded.
* @throws PDOException On PDO operation error.
*/
- public function delete()
- {
- if( !isset($this->data['id']) )
- {
- throw new E_OTS_NotLoaded();
- }
+ public function delete()
+ {
+ if( !isset($this->data['id']) )
+ {
+ throw new E_OTS_NotLoaded();
+ }
- // deletes row from database
- $this->db->exec('DELETE FROM ' . $this->db->tableName('accounts') . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id']);
+ // deletes row from database
+ $this->db->exec('DELETE FROM ' . $this->db->tableName('accounts') . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id']);
- // resets object handle
- unset($this->data['id']);
- }
+ // resets object handle
+ unset($this->data['id']);
+ }
/**
* Checks highest access level of account.
@@ -920,10 +920,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @return int Access level (highest access level of all characters).
* @throws PDOException On PDO operation error.
*/
- public function getAccess()
- {
+ public function getAccess()
+ {
return $this->getGroupId();
- }
+ }
public function getGroupId()
{
@@ -985,25 +985,25 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @return int Access level (highest access level of all characters).
* @throws PDOException On PDO operation error.
*/
- public function getGuildAccess(OTS_Guild $guild)
- {
- // by default
- $access = 0;
+ public function getGuildAccess(OTS_Guild $guild)
+ {
+ // by default
+ $access = 0;
- // finds ranks of all characters
- foreach($this->getPlayersList(false) as $player)
- {
- $rank = $player->getRank();
+ // finds ranks of all characters
+ foreach($this->getPlayersList(false) as $player)
+ {
+ $rank = $player->getRank();
- // checks if rank's access level is higher then previouls found highest
- if( isset($rank) && $rank->isLoaded() && $rank->getGuild()->getId() == $guild->getId() && $rank->getLevel() > $access)
- {
- $access = $rank->getLevel();
- }
- }
+ // checks if rank's access level is higher then previouls found highest
+ if( isset($rank) && $rank->isLoaded() && $rank->getGuild()->getId() == $guild->getId() && $rank->getLevel() > $access)
+ {
+ $access = $rank->getLevel();
+ }
+ }
- return $access;
- }
+ return $access;
+ }
public function logAction($action)
{
@@ -1042,10 +1042,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @return Iterator List of players.
*/
#[\ReturnTypeWillChange]
- public function getIterator()
- {
- return $this->getPlayersList();
- }
+ public function getIterator()
+ {
+ return $this->getPlayersList();
+ }
/**
* Returns number of player within.
@@ -1056,10 +1056,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws PDOException On PDO operation error.
* @return int Count of players.
*/
- public function count(): int
- {
- return $this->getPlayersList()->count();
- }
+ public function count(): int
+ {
+ return $this->getPlayersList()->count();
+ }
/**
* Magic PHP5 method.
@@ -1072,44 +1072,44 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws OutOfBoundsException For non-supported properties.
* @throws PDOException On PDO operation error.
*/
- public function __get($name)
- {
- switch($name)
- {
- case 'id':
- return $this->getId();
+ public function __get($name)
+ {
+ switch($name)
+ {
+ case 'id':
+ return $this->getId();
- case 'name':
- return $this->getName();
+ case 'name':
+ return $this->getName();
- case 'password':
- return $this->getPassword();
+ case 'password':
+ return $this->getPassword();
- case 'eMail':
- return $this->getEMail();
+ case 'eMail':
+ return $this->getEMail();
- case 'premiumEnd':
- return $this->getPremiumEnd();
+ case 'premiumEnd':
+ return $this->getPremiumEnd();
- case 'loaded':
- return $this->isLoaded();
+ case 'loaded':
+ return $this->isLoaded();
- case 'playersList':
- return $this->getPlayersList();
+ case 'playersList':
+ return $this->getPlayersList();
- case 'deleted':
- return $this->isDeleted();
+ case 'deleted':
+ return $this->isDeleted();
- case 'banned':
- return $this->isBanned();
+ case 'banned':
+ return $this->isBanned();
- case 'access':
- return $this->getAccess();
+ case 'access':
+ return $this->getAccess();
- default:
- throw new OutOfBoundsException();
- }
- }
+ default:
+ throw new OutOfBoundsException();
+ }
+ }
/**
* Magic PHP5 method.
@@ -1122,52 +1122,52 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @throws OutOfBoundsException For non-supported properties.
* @throws PDOException On PDO operation error.
*/
- public function __set($name, $value)
- {
- switch($name)
- {
- case 'name':
- $this->setName($name);
- break;
+ public function __set($name, $value)
+ {
+ switch($name)
+ {
+ case 'name':
+ $this->setName($name);
+ break;
- case 'password':
- $this->setPassword($value);
- break;
+ case 'password':
+ $this->setPassword($value);
+ break;
- case 'eMail':
- $this->setEMail($value);
- break;
+ case 'eMail':
+ $this->setEMail($value);
+ break;
- case 'premiumEnd':
- $this->setPremiumEnd($value);
- break;
+ case 'premiumEnd':
+ $this->setPremiumEnd($value);
+ break;
- case 'deleted':
- if($value)
- {
- $this->setDeleted();
- }
- else
- {
- $this->unsetDeleted();
- }
- break;
+ case 'deleted':
+ if($value)
+ {
+ $this->setDeleted();
+ }
+ else
+ {
+ $this->unsetDeleted();
+ }
+ break;
- case 'banned':
- if($value)
- {
- $this->ban();
- }
- else
- {
- $this->unban();
- }
- break;
+ case 'banned':
+ if($value)
+ {
+ $this->ban();
+ }
+ else
+ {
+ $this->unban();
+ }
+ break;
- default:
- throw new OutOfBoundsException();
- }
- }
+ default:
+ throw new OutOfBoundsException();
+ }
+ }
/**
* Returns string representation of object.
@@ -1180,18 +1180,18 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @since 0.1.0
* @return string String representation of object.
*/
- public function __toString()
- {
- $ots = POT::getInstance();
+ public function __toString()
+ {
+ $ots = POT::getInstance();
- // checks if display driver is loaded
- if( $ots->isDisplayDriverLoaded() )
- {
- return $ots->getDisplayDriver()->displayAccount($this);
- }
+ // checks if display driver is loaded
+ if( $ots->isDisplayDriverLoaded() )
+ {
+ return $ots->getDisplayDriver()->displayAccount($this);
+ }
- return $this->getId();
- }
+ return $this->getId();
+ }
}
/**#@-*/
diff --git a/system/libs/pot/OTS_DB_MySQL.php b/system/libs/pot/OTS_DB_MySQL.php
index baa38c76..8b9626d9 100644
--- a/system/libs/pot/OTS_DB_MySQL.php
+++ b/system/libs/pot/OTS_DB_MySQL.php
@@ -26,10 +26,11 @@ use MyAAC\Cache\Cache;
*/
class OTS_DB_MySQL extends OTS_Base_DB
{
- private $has_table_cache = array();
- private $has_column_cache = array();
+ private array $has_table_cache = [];
+ private array $has_column_cache = [];
+ private array $get_column_info_cache = [];
- private $clearCacheAfter = false;
+ private bool $clearCacheAfter = false;
/**
* Creates database connection.
*
@@ -119,6 +120,11 @@ class OTS_DB_MySQL extends OTS_Base_DB
if($cache->fetch('database_columns', $tmp) && $tmp) {
$this->has_column_cache = unserialize($tmp);
}
+
+ $tmp = null;
+ if($cache->fetch('database_columns_info', $tmp) && $tmp) {
+ $this->get_column_info_cache = unserialize($tmp);
+ }
}
}
@@ -155,11 +161,13 @@ class OTS_DB_MySQL extends OTS_Base_DB
if ($this->clearCacheAfter) {
$cache->delete('database_tables');
$cache->delete('database_columns');
+ $cache->delete('database_columns_info');
$cache->delete('database_checksum');
}
else {
$cache->set('database_tables', serialize($this->has_table_cache), 3600);
$cache->set('database_columns', serialize($this->has_column_cache), 3600);
+ $cache->set('database_columns_info', serialize($this->get_column_info_cache), 3600);
$cache->set('database_checksum', serialize(sha1($config['database_host'] . '.' . $config['database_name'])), 3600);
}
}
@@ -209,7 +217,8 @@ class OTS_DB_MySQL extends OTS_Base_DB
return $sql;
}
- public function hasTable($name) {
+ public function hasTable($name): bool
+ {
if(isset($this->has_table_cache[$name])) {
return $this->has_table_cache[$name];
}
@@ -217,12 +226,13 @@ class OTS_DB_MySQL extends OTS_Base_DB
return $this->hasTableInternal($name);
}
- private function hasTableInternal($name) {
- global $config;
- return ($this->has_table_cache[$name] = $this->query('SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `TABLE_SCHEMA` = ' . $this->quote($config['database_name']) . ' AND `TABLE_NAME` = ' . $this->quote($name) . ' LIMIT 1;')->rowCount() > 0);
+ private function hasTableInternal($name): bool
+ {
+ return ($this->has_table_cache[$name] = $this->query('SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `TABLE_SCHEMA` = ' . $this->quote(config('database_name')) . ' AND `TABLE_NAME` = ' . $this->quote($name) . ' LIMIT 1;')->rowCount() > 0);
}
- public function hasColumn($table, $column) {
+ public function hasColumn($table, $column): bool
+ {
if(isset($this->has_column_cache[$table . '.' . $column])) {
return $this->has_column_cache[$table . '.' . $column];
}
@@ -230,8 +240,8 @@ class OTS_DB_MySQL extends OTS_Base_DB
return $this->hasColumnInternal($table, $column);
}
- private function hasColumnInternal($table, $column) {
- return $this->hasTable($table) && ($this->has_column_cache[$table . '.' . $column] = count($this->query('SHOW COLUMNS FROM `' . $table . "` LIKE '" . $column . "'")->fetchAll()) > 0);
+ private function hasColumnInternal($table, $column): bool {
+ return $this->hasTable($table) && ($this->has_column_cache[$table . '.' . $column] = count($this->query('SHOW COLUMNS FROM `' . $table . "` LIKE " . $this->quote($column))->fetchAll()) > 0);
}
public function hasTableAndColumns(string $table, array $columns = []): bool
@@ -247,7 +257,53 @@ class OTS_DB_MySQL extends OTS_Base_DB
return true;
}
- public function revalidateCache() {
+ public function getColumnInfo(string $table, string $column): bool|array
+ {
+ if(isset($this->get_column_info_cache[$table . '.' . $column])) {
+ return $this->get_column_info_cache[$table . '.' . $column];
+ }
+
+ return $this->getColumnInfoInternal($table, $column);
+ }
+
+ private function getColumnInfoInternal(string $table, string $column): bool|array
+ {
+ if (!$this->hasTable($table) || !$this->hasColumn($table, $column)) {
+ return false;
+ }
+
+ $formatResult = function ($result) {
+ return [
+ 'field' => $result['Field'],
+ 'type' => $result['Type'],
+ 'null' => strtolower($result['Null']),
+ 'default' => $result['Default'],
+ 'extra' => $result['Extra'],
+ ];
+ };
+
+ $query = $this->query('SHOW COLUMNS FROM `' . $table . "` LIKE " . $this->quote($column));
+ $rowCount = $query->rowCount();
+ if ($rowCount > 1) {
+ $tmp = [];
+
+ $results = $query->fetchAll(PDO::FETCH_ASSOC);
+ foreach ($results as $result) {
+ $tmp[] = $formatResult($result);
+ }
+
+ return ($this->get_column_info_cache[$table . '.' . $column] = $tmp);
+ }
+ else if ($rowCount == 1) {
+ $result = $query->fetch(PDO::FETCH_ASSOC);
+ return ($this->get_column_info_cache[$table . '.' . $column] = $formatResult($result));
+ }
+
+ return [];
+ }
+
+ public function revalidateCache(): void
+ {
foreach($this->has_table_cache as $key => $value) {
$this->hasTableInternal($key);
}
@@ -262,6 +318,21 @@ class OTS_DB_MySQL extends OTS_Base_DB
$this->hasColumnInternal($explode[0], $explode[1]);
}
}
+
+ foreach($this->get_column_info_cache as $key => $value) {
+ $explode = explode('.', $key);
+ if(!isset($this->has_table_cache[$explode[0]])) { // first check if table exist
+ $this->hasTableInternal($explode[0]);
+ }
+
+ if($this->has_table_cache[$explode[0]]) {
+ $this->hasColumnInternal($explode[0], $explode[1]);
+ }
+
+ if($this->has_table_cache[$explode[0]]) {
+ $this->getColumnInfoInternal($explode[0], $explode[1]);
+ }
+ }
}
public function setClearCacheAfter($clearCache)
diff --git a/system/libs/pot/OTS_Player.php b/system/libs/pot/OTS_Player.php
index 7b688d1c..099f5db1 100644
--- a/system/libs/pot/OTS_Player.php
+++ b/system/libs/pot/OTS_Player.php
@@ -2919,6 +2919,32 @@ class OTS_Player extends OTS_Row_DAO
$this->data['banned'] = $ban['active'];
$this->data['banned_time'] = $ban['expires'];
}
+
+ public function isNameLocked(): bool
+ {
+ // nothing can't be banned
+ if( !$this->isLoaded() ) {
+ throw new E_OTS_NotLoaded();
+ }
+
+ if($this->db->hasTable('player_namelocks')) {
+ $ban = $this->db->query('SELECT 1 FROM `player_namelocks` WHERE `player_id` = ' . $this->data['id'])->fetch(PDO::FETCH_ASSOC);
+ return (isset($ban['1']));
+ }
+ else if($this->db->hasTable('bans')) {
+ if($this->db->hasColumn('bans', 'active')) {
+ $ban = $this->db->query('SELECT `active`, `expires` FROM `bans` WHERE `type` = 2 AND `active` = 1 AND `value` = ' . $this->data['id'] . ' AND (`expires` > ' . time() .' OR `expires` = -1) ORDER BY `expires` DESC')->fetch();
+ return isset($ban['active']);
+ }
+ else { // tfs 0.2
+ $ban = $this->db->query('SELECT `time` FROM `bans` WHERE `type` = 2 AND `account` = ' . $this->data['account_id'] . ' AND (`time` > ' . time() .' OR `time` = -1) ORDER BY `time` DESC')->fetch();
+
+ return isset($ban['time']) && ($ban['time'] == -1 || $ban['time'] > 0);
+ }
+ }
+
+ return false;
+ }
/**
* Deletes player.
*
@@ -2953,21 +2979,14 @@ class OTS_Player extends OTS_Row_DAO
* @return string Player proffesion name.
* @throws E_OTS_NotLoaded If player is not loaded or global vocations list is not loaded.
*/
- public function getVocationName()
+ public function getVocationName(): string
{
if( !isset($this->data['vocation']) )
{
throw new E_OTS_NotLoaded();
}
- global $config;
- $voc = $this->getVocation();
- if(!isset($config['vocations'][$voc])) {
- return 'Unknown';
- }
-
- return $config['vocations'][$voc];
- //return POT::getInstance()->getVocationsList()->getVocationName($this->data['vocation']);
+ return OTS_Toolbox::getVocationName($this->data['vocation'], $this->data['promotion'] ?? 0);
}
/**
diff --git a/system/libs/pot/OTS_ServerInfo.php b/system/libs/pot/OTS_ServerInfo.php
index 76ebcaf7..a0ee464f 100644
--- a/system/libs/pot/OTS_ServerInfo.php
+++ b/system/libs/pot/OTS_ServerInfo.php
@@ -97,6 +97,8 @@ class OTS_ServerInfo
return new OTS_Buffer($data);
}
+ log_append('status-error.log', "Cannot connect to {$this->server}:{$this->port} - Error code: $error, message: $message");
+
return false;
}
diff --git a/system/libs/pot/OTS_Toolbox.php b/system/libs/pot/OTS_Toolbox.php
index 980e5cb5..575dba6f 100644
--- a/system/libs/pot/OTS_Toolbox.php
+++ b/system/libs/pot/OTS_Toolbox.php
@@ -15,7 +15,7 @@
/**
* Toolbox for common operations.
- *
+ *
* @package POT
* @version 0.1.5
*/
@@ -23,41 +23,41 @@ class OTS_Toolbox
{
/**
* Calculates experience points needed for given level.
- *
+ *
* @param int $level Level for which experience should be calculated.
* @param int $experience Current experience points.
* @return int Experience points for level.
*/
public static function experienceForLevel($level, $experience = 0)
- {
- //return 50 * ($level - 1) * ($level * $level - 5 * $level + 12) / 3 - $experience;
+ {
+ //return 50 * ($level - 1) * ($level * $level - 5 * $level + 12) / 3 - $experience;
$level = $level - 1;
return ((50 * $level * $level * $level) - (150 * $level * $level) + (400 * $level)) / 3;
- }
+ }
/**
* Finds out which level user have basing on his/her experience.
- *
+ *
*
* PHP doesn't support complex numbers natively so solving third-level polynomials would be quite hard. Rather then doing this, this method iterates calculating experience for next levels until it finds one which requires enought experience we have. Because of that, for high experience values this function can take relatively long time to be executed.
*
- *
+ *
* @param int $experience Current experience points.
* @return int Experience level.
*/
- public static function levelForExperience($experience)
- {
- // default level
- $level = 1;
+ public static function levelForExperience($experience)
+ {
+ // default level
+ $level = 1;
- // until we will find level which requires more experience then we have we will step to next
- while( self::experienceForLevel($level + 1) <= $experience)
- {
- $level++;
- }
+ // until we will find level which requires more experience then we have we will step to next
+ while( self::experienceForLevel($level + 1) <= $experience)
+ {
+ $level++;
+ }
- return $level;
- }
+ return $level;
+ }
/**
* @version 0.1.5
@@ -65,25 +65,25 @@ class OTS_Toolbox
* @return OTS_Players_List Filtered list.
* @deprecated 0.1.5 Use OTS_PlayerBans_List.
*/
- public static function bannedPlayers()
- {
- // creates filter
- $filter = new OTS_SQLFilter();
- $filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_PLAYER);
- $filter->addFilter( new OTS_SQLField('active', 'bans'), 1);
- $filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'players') );
+ public static function bannedPlayers()
+ {
+ // creates filter
+ $filter = new OTS_SQLFilter();
+ $filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_PLAYER);
+ $filter->addFilter( new OTS_SQLField('active', 'bans'), 1);
+ $filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'players') );
- // selects only active bans
- $actives = new OTS_SQLFilter();
- $actives->addFilter( new OTS_SQLField('expires', 'bans'), 0);
- $actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR);
- $filter->addFilter($actives);
+ // selects only active bans
+ $actives = new OTS_SQLFilter();
+ $actives->addFilter( new OTS_SQLField('expires', 'bans'), 0);
+ $actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR);
+ $filter->addFilter($actives);
- // creates list and aplies filter
- $list = new OTS_Players_List();
- $list->setFilter($filter);
- return $list;
- }
+ // creates list and aplies filter
+ $list = new OTS_Players_List();
+ $list->setFilter($filter);
+ return $list;
+ }
/**
* @version 0.1.5
@@ -91,25 +91,34 @@ class OTS_Toolbox
* @return OTS_Accounts_List Filtered list.
* @deprecated 0.1.5 Use OTS_AccountBans_List.
*/
- public static function bannedAccounts()
- {
- // creates filter
- $filter = new OTS_SQLFilter();
- $filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_ACCOUNT);
- $filter->addFilter( new OTS_SQLField('active', 'bans'), 1);
- $filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'accounts') );
+ public static function bannedAccounts()
+ {
+ // creates filter
+ $filter = new OTS_SQLFilter();
+ $filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_ACCOUNT);
+ $filter->addFilter( new OTS_SQLField('active', 'bans'), 1);
+ $filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'accounts') );
- // selects only active bans
- $actives = new OTS_SQLFilter();
- $actives->addFilter( new OTS_SQLField('expires', 'bans'), 0);
- $actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR);
- $filter->addFilter($actives);
+ // selects only active bans
+ $actives = new OTS_SQLFilter();
+ $actives->addFilter( new OTS_SQLField('expires', 'bans'), 0);
+ $actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR);
+ $filter->addFilter($actives);
- // creates list and aplies filter
- $list = new OTS_Accounts_List();
- $list->setFilter($filter);
- return $list;
- }
+ // creates list and aplies filter
+ $list = new OTS_Accounts_List();
+ $list->setFilter($filter);
+ return $list;
+ }
+
+ public static function getVocationName($id, $promotion = 0): string
+ {
+ if($promotion > 0) {
+ $id = ($id + ($promotion * config('vocations_amount')));
+ }
+
+ return config('vocations')[$id] ?? 'Unknown';
+ }
}
/**#@-*/
diff --git a/system/locale/de/install.php b/system/locale/de/install.php
index ad354609..351f6009 100644
--- a/system/locale/de/install.php
+++ b/system/locale/de/install.php
@@ -48,6 +48,8 @@ $locale['step_config'] = 'Konfiguration';
$locale['step_config_title'] = 'Grundkonfiguration';
$locale['step_config_server_path'] = 'Serverpfad';
$locale['step_config_server_path_desc'] = 'Pfad zu Ihrem TFS-Hauptverzeichnis, in dem sich die config.lua befinden.';
+$locale['step_config_site_url'] = 'Website URL';
+$locale['step_config_site_url_desc'] = 'Ihre Website-Adresse.';
$locale['step_config_mail_admin'] = 'Admin E-Mail';
$locale['step_config_mail_admin_desc'] = 'Adresse, an die E-Mails aus dem Kontaktformular gesendet werden, z. B. admin@gmail.com';
$locale['step_config_mail_admin_error'] = 'Admin E-Mail ist nicht korrekt.';
@@ -76,6 +78,7 @@ $locale['step_database_error_mysql_connect_3'] = 'MySQL ist nicht richtig konfig
$locale['step_database_error_mysql_connect_4'] = 'MySQL-Server läuft nicht.';
$locale['step_database_error_schema'] = 'Fehler beim Importieren des Schemas:';
$locale['step_database_success_schema'] = '$PREFIX$ Tabellen wurden erfolgreich installiert.';
+$locale['step_database_success_import_data'] = 'Import von Daten für Tabellen was erfolgreich.';
$locale['step_database_error_file'] = '$FILE$ konnte nicht geöffnet werden. Bitte kopieren Sie diesen Inhalt und fügen Sie ihn dort ein:';
$locale['step_database_adding_field'] = 'Folgendes Feld wurde hinzugefügt: ';
$locale['step_database_modifying_field'] = 'Folgendes Feld wurde geändert: ';
diff --git a/system/locale/en/install.php b/system/locale/en/install.php
index 0cbd29ad..c623035c 100644
--- a/system/locale/en/install.php
+++ b/system/locale/en/install.php
@@ -52,6 +52,8 @@ $locale['step_config'] = 'Configuration';
$locale['step_config_title'] = 'Basic configuration';
$locale['step_config_server_path'] = 'Server path';
$locale['step_config_server_path_desc'] = 'Path to your TFS main directory, where you have config.lua located.';
+$locale['step_config_site_url'] = 'Website URL';
+$locale['step_config_site_url_desc'] = 'Your website address.';
$locale['step_config_mail_admin'] = 'Admin Email';
$locale['step_config_mail_admin_desc'] = 'Address where emails from contact form will be delivered, for example admin@gmail.com';
$locale['step_config_mail_admin_error'] = 'Admin Email is not correct.';
@@ -81,6 +83,7 @@ $locale['step_database_error_mysql_connect_3'] = 'MySQL is not configured proper
$locale['step_database_error_mysql_connect_4'] = 'MySQL server is not running.';
$locale['step_database_error_schema'] = 'Error while importing schema:';
$locale['step_database_success_schema'] = 'Successfully installed $PREFIX$ tables.';
+$locale['step_database_success_import_data'] = 'Successfully imported base data for tables.';
$locale['step_database_error_file'] = '$FILE$ couldn\'t be opened. Please copy this content and paste there:';
$locale['step_database_adding_field'] = 'Adding field';
$locale['step_database_modifying_field'] = 'Modifying field';
diff --git a/system/locale/pl/install.php b/system/locale/pl/install.php
index 5b6725cf..a8ea0cf6 100644
--- a/system/locale/pl/install.php
+++ b/system/locale/pl/install.php
@@ -52,6 +52,8 @@ $locale['step_config'] = 'Konfiguracja';
$locale['step_config_title'] = 'Podstawowa konfiguracja';
$locale['step_config_server_path'] = 'Ścieżka do serwera';
$locale['step_config_server_path_desc'] = 'Ścieżka do Twojego folderu z TFS, gdzie znajduje się plik config.lua.';
+$locale['step_config_server_url'] = 'Adres strony';
+$locale['step_config_server_url_desc'] = 'Adres tej strony www.';
$locale['step_config_mail_admin'] = 'E-Mail admina';
$locale['step_config_mail_admin_desc'] = 'Na ten adres będą dostarczane E-Maile z formularza kontaktowego, przykładowo admin@gmail.com';
$locale['step_config_mail_admin_error'] = 'E-Mail admina jest niepoprawny.';
@@ -79,7 +81,8 @@ $locale['step_database_error_mysql_connect_2'] = 'Możliwe przyczyny:';
$locale['step_database_error_mysql_connect_3'] = 'MySQL nie jest poprawnie skonfigurowane w config.lua.';
$locale['step_database_error_mysql_connect_4'] = 'Serwer MySQL nie jest uruchomiony.';
$locale['step_database_error_schema'] = 'Błąd podczas importowania struktury bazy danych:';
-$locale['step_database_success_schema'] = 'Pomyślnie zainstalowano tabele $PREFIX$.';
+$locale['step_database_success_schema'] = 'Pomyślnie zaimportowano tabele $PREFIX$.';
+$locale['step_database_success_import_data'] = 'Pomyślnie załadowano bazowe dane dla tabel.';
$locale['step_database_error_file'] = '$FILE$ nie mógł zostać otwarty. Proszę skopiować zawartość pola tekstowego i wkleić do tego pliku:';
$locale['step_database_adding_field'] = 'Dodawanie pola';
$locale['step_database_modifying_field'] = 'Modyfikacja pola';
diff --git a/system/login.php b/system/login.php
index 42a96111..335177e7 100644
--- a/system/login.php
+++ b/system/login.php
@@ -34,8 +34,10 @@ if($logged) {
$twig->addGlobal('account_logged', $account_logged);
}
-setSession('last_visit', time());
-if(defined('PAGE')) {
- setSession('last_page', PAGE);
+if (!defined('IGNORE_SET_LAST_VISIT') || !IGNORE_SET_LAST_VISIT) {
+ setSession('last_visit', time());
+ if(defined('PAGE')) {
+ setSession('last_page', PAGE);
+ }
+ setSession('last_uri', $_SERVER['REQUEST_URI']);
}
-setSession('last_uri', $_SERVER['REQUEST_URI']);
diff --git a/system/migrate.php b/system/migrate.php
index 2199fd73..2bbb3786 100644
--- a/system/migrate.php
+++ b/system/migrate.php
@@ -9,6 +9,8 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
+global $db;
+
// database migrations
$tmp = '';
if(fetchDatabaseConfig('database_version', $tmp)) { // we got version
diff --git a/system/migrations/46-account_emails_verify.sql b/system/migrations/46-account_emails_verify.sql
new file mode 100644
index 00000000..13d42b16
--- /dev/null
+++ b/system/migrations/46-account_emails_verify.sql
@@ -0,0 +1,8 @@
+CREATE TABLE `myaac_account_emails_verify`
+(
+ `id` int NOT NULL AUTO_INCREMENT,
+ `account_id` int NOT NULL,
+ `hash` varchar(32) NOT NULL,
+ `sent_at` int NOT NULL DEFAULT 0,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
diff --git a/system/migrations/46.php b/system/migrations/46.php
new file mode 100644
index 00000000..452527e5
--- /dev/null
+++ b/system/migrations/46.php
@@ -0,0 +1,24 @@
+hasColumn('accounts', 'email_hash')) {
+ $db->dropColumn('accounts', 'email_hash');
+ }
+
+ if (!$db->hasTable(TABLE_PREFIX . 'account_emails_verify')) {
+ $db->query(file_get_contents(__DIR__ . '/46-account_emails_verify.sql'));
+ }
+};
+
+$down = function () use ($db) {
+ if (!$db->hasColumn('accounts', 'email_hash')) {
+ $db->addColumn('accounts', 'email_hash', "varchar(32) NOT NULL DEFAULT ''");
+ }
+
+ if ($db->hasTable(TABLE_PREFIX . 'account_emails_verify')) {
+ $db->dropTable(TABLE_PREFIX . 'account_emails_verify');
+ }
+};
diff --git a/system/migrations/7.php b/system/migrations/7.php
index a96ed7c9..5a6a7925 100644
--- a/system/migrations/7.php
+++ b/system/migrations/7.php
@@ -9,7 +9,7 @@ $up = function () use ($db) {
}
};
-$up = function () use ($db) {
+$down = function () use ($db) {
if (!$db->hasColumn(TABLE_PREFIX . 'screenshots', 'name')) {
$db->addColumn(TABLE_PREFIX . 'screenshots', 'name', 'VARCHAR(30) NOT NULL');
}
diff --git a/system/pages/404.php b/system/pages/404.php
index 90a8921a..60fb66aa 100644
--- a/system/pages/404.php
+++ b/system/pages/404.php
@@ -8,7 +8,7 @@
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
-$title = '404 Not Found';
+$title = 'Not Found';
header('HTTP/1.0 404 Not Found');
?>
diff --git a/system/pages/405.php b/system/pages/405.php
index 3d585f59..d1eee43a 100644
--- a/system/pages/405.php
+++ b/system/pages/405.php
@@ -8,7 +8,7 @@
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
-$title = '405 Method Not Allowed';
+$title = 'Method Not Allowed';
header('HTTP/1.0 405 Method Not Allowed');
?>
diff --git a/system/pages/account/change-email.php b/system/pages/account/change-email.php
index 857623f9..6dc8d388 100644
--- a/system/pages/account/change-email.php
+++ b/system/pages/account/change-email.php
@@ -166,7 +166,7 @@ if(isset($_POST['emailchangecancel']) && $_POST['emailchangecancel'] == 1) {
$account_logged->setCustomField("email_new", "");
$account_logged->setCustomField("email_new_time", 0);
- $custom_buttons = '
';
+ $custom_buttons = '
';
$twig->display('success.html.twig', array(
'title' => 'Email Address Change Cancelled',
diff --git a/system/pages/account/change-password.php b/system/pages/account/change-password.php
index 35058d3d..157515b7 100644
--- a/system/pages/account/change-password.php
+++ b/system/pages/account/change-password.php
@@ -19,18 +19,17 @@ if(!$logged) {
csrfProtect();
-$new_password = $_POST['newpassword'] ?? NULL;
-$new_password_confirm = $_POST['newpassword_confirm'] ?? NULL;
-$old_password = $_POST['oldpassword'] ?? NULL;
+$new_password = $_POST['new_password'] ?? null;
+$new_password_confirm = $_POST['new_password_confirm'] ?? null;
+$old_password = $_POST['old_password'] ?? null;
if(empty($new_password) && empty($new_password_confirm) && empty($old_password)) {
$twig->display('account.change-password.html.twig');
}
-else
-{
+else {
if(empty($new_password) || empty($new_password_confirm) || empty($old_password)){
$errors[] = 'Please fill in form.';
}
- $password_strlen = strlen($new_password);
+
if($new_password != $new_password_confirm) {
$errors[] = 'The new passwords do not match!';
}
@@ -41,10 +40,13 @@ else
}
/** @var OTS_Account $account_logged */
- $old_password = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $old_password);
- if($old_password != $account_logged->getPassword()) {
+ $old_password_hashed = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $old_password);
+ if($old_password_hashed != $account_logged->getPassword()) {
$errors[] = 'Current password is incorrect!';
}
+ else if ($old_password == $new_password) {
+ $errors[] = 'The old password is same as the new password!';
+ }
$hooks->trigger(HOOK_ACCOUNT_CHANGE_PASSWORD_POST);
}
diff --git a/system/pages/account/confirm-email.php b/system/pages/account/confirm-email.php
index 615dd942..87183a3c 100644
--- a/system/pages/account/confirm-email.php
+++ b/system/pages/account/confirm-email.php
@@ -9,6 +9,7 @@
*/
use MyAAC\Models\Account;
+use MyAAC\Models\AccountEmailVerify;
defined('MYAAC') or die('Direct access not allowed!');
@@ -20,16 +21,20 @@ if(empty($hash)) {
return;
}
-if(!Account::where('email_hash', $hash)->exists()) {
- note("Your email couldn't be verified. Please contact staff to do it manually.");
+// by default link is valid for 30 days
+$accountEmailVerify = AccountEmailVerify::where('hash', $hash)->where('sent_at', '>', time() - 30 * 24 * 60 * 60)->first();
+if(!$accountEmailVerify) {
+ note("Wrong link or link has expired.");
}
else
{
- $accountModel = Account::where('email_hash', $hash)->where('email_verified', 0)->first();
+ $accountModel = Account::where('id', $accountEmailVerify->account_id)->where('email_verified', 0)->first();
if ($accountModel) {
$accountModel->email_verified = 1;
$accountModel->save();
+ AccountEmailVerify::where('account_id', $accountModel->id)->delete();
+
success('You have now verified your e-mail, this will increase the security of your account. Thank you for doing this. You can now log in.');
$account = new OTS_Account();
@@ -39,6 +44,6 @@ else
}
}
else {
- error('Link has expired.');
+ error('Your account is already verified.');
}
}
diff --git a/system/pages/account/create.php b/system/pages/account/create.php
index 0befa362..731771b7 100644
--- a/system/pages/account/create.php
+++ b/system/pages/account/create.php
@@ -10,6 +10,7 @@
*/
use MyAAC\CreateCharacter;
+use MyAAC\Models\AccountEmailVerify;
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Create Account';
@@ -221,8 +222,19 @@ if($save)
}
}
- if(setting('core.account_premium_points') && setting('core.account_premium_points') > 0) {
- $new_account->setCustomField('premium_points', setting('core.account_premium_points'));
+ $accountDefaultPremiumPoints = setting('core.account_premium_points');
+ if($accountDefaultPremiumPoints > 0) {
+ $new_account->setCustomField('premium_points', $accountDefaultPremiumPoints);
+ }
+
+ $accountDefaultCoins = setting('core.account_coins');
+ if(HAS_ACCOUNT_COINS && $accountDefaultCoins > 0) {
+ $new_account->setCustomField('coins', $accountDefaultCoins);
+ }
+
+ $accountDefaultCoinsTransferable = setting('core.account_coins_transferable');
+ if((HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) && $accountDefaultCoinsTransferable > 0) {
+ $new_account->setCustomField(ACCOUNT_COINS_TRANSFERABLE_COLUMN, $accountDefaultCoinsTransferable);
}
$tmp_account = $email;
@@ -233,7 +245,12 @@ if($save)
if(setting('core.mail_enabled') && setting('core.account_mail_verify'))
{
$hash = md5(generateRandomString(16, true, true) . $email);
- $new_account->setCustomField('email_hash', $hash);
+
+ AccountEmailVerify::create([
+ 'account_id' => $new_account->getId(),
+ 'hash' => $hash,
+ 'sent_at' => time(),
+ ]);
$verify_url = getLink('account/confirm-email/' . $hash);
$body_html = $twig->render('mail.account.verify.html.twig', array(
@@ -257,8 +274,10 @@ if($save)
}
else
{
- error('An error occorred while sending email! Account not created. Try again. For Admin: More info can be found in system/logs/mailer-error.log');
+ error('An error occurred while sending email! Account not created. Try again. For Admin: More info can be found in system/logs/mailer-error.log');
$new_account->delete();
+
+ return;
}
}
else
@@ -348,7 +367,7 @@ if(!empty($errors))
if (setting('core.account_country')) {
$countries = array();
- foreach (array('pl', 'se', 'br', 'us', 'gb') as $c)
+ foreach (setting('core.account_countries_most_popular') ?? [] as $c)
$countries[$c] = $config['countries'][$c];
$countries['--'] = '----------';
diff --git a/system/pages/account/login.php b/system/pages/account/login.php
index d6771c91..e18dacf4 100644
--- a/system/pages/account/login.php
+++ b/system/pages/account/login.php
@@ -48,7 +48,9 @@ if(!empty($login_account) && !empty($login_password))
)
{
if (setting('core.account_mail_verify') && (int)$account_logged->getCustomField('email_verified') !== 1) {
- $errors[] = 'Your account is not verified. Please verify your email address. If the message is not coming check the SPAM folder in your E-Mail client.';
+ $link = getLink('account/resend-email-verify');
+ $errors[] = 'Your account is not verified. Please verify your email address. If the message is not coming check the SPAM folder in your E-Mail client. ' .
+ 'You can resend the Email here: ' . $link . '';
} else {
session_regenerate_id();
setSession('account', $account_logged->getId());
diff --git a/system/pages/account/manage.php b/system/pages/account/manage.php
index 3776a732..b74f7bd8 100644
--- a/system/pages/account/manage.php
+++ b/system/pages/account/manage.php
@@ -38,15 +38,24 @@ csrfProtect();
$groups = new OTS_Groups_List();
-$freePremium = isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium']) || $account_logged->getPremDays() == OTS_Account::GRATIS_PREMIUM_DAYS;
-$dayOrDays = $account_logged->getPremDays() == 1 ? 'day' : 'days';
/**
* @var OTS_Account $account_logged
*/
-if(!$account_logged->isPremium())
+$premDays = $account_logged->getPremDays();
+
+$freePremium = isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium']) || $premDays == OTS_Account::GRATIS_PREMIUM_DAYS;
+$dayOrDays = ($premDays == 1 ? 'day' : 'days');
+
+$vipSystemEnabled = isset($config['lua']['vipSystemEnabled']) && getBoolean($config['lua']['vipSystemEnabled']);
+$premiumLabel = $vipSystemEnabled ? 'VIP' : 'Premium Account';
+
+if ($freePremium && !$vipSystemEnabled) {
+ $account_status = 'Gratis Premium Account';
+} else if(!$account_logged->isPremium()) {
$account_status = 'Free Account';
-else
- $account_status = '' . ($freePremium ? 'Gratis Premium Account' : 'Premium Account, ' . $account_logged->getPremDays() . ' '.$dayOrDays.' left') . '';
+} else {
+ $account_status = '' . $premiumLabel . ', ' . $premDays . ' '.$dayOrDays.' left';
+}
$recovery_key = $account_logged->getCustomField('key');
if(empty($recovery_key))
diff --git a/system/pages/account/redirect.php b/system/pages/account/redirect.php
deleted file mode 100644
index 78bc54d9..00000000
--- a/system/pages/account/redirect.php
+++ /dev/null
@@ -1,23 +0,0 @@
-
- * @author Slawkens
- * @copyright 2019 MyAAC
- * @link https://my-aac.org
- */
-defined('MYAAC') or die('Direct access not allowed!');
-
-$redirect = urldecode($_REQUEST['redirect']);
-
-// should never happen, unless hacker modify the URL
-if (!str_contains($redirect, BASE_URL)) {
- error('Fatal error: Cannot redirect outside the website.');
- return;
-}
-
-$twig->display('account.redirect.html.twig', array(
- 'redirect' => $redirect
-));
diff --git a/system/pages/account/resend-email-verify.php b/system/pages/account/resend-email-verify.php
new file mode 100644
index 00000000..ffccb548
--- /dev/null
+++ b/system/pages/account/resend-email-verify.php
@@ -0,0 +1,94 @@
+display('error_box.html.twig', ['errors' => $errors]);
+ $twig->display('account.back_button.html.twig', [
+ 'action' => getLink('account/resend-email-verify'),
+ ]);
+};
+
+if (!setting('core.mail_enabled') || !setting('core.account_mail_verify')) {
+ $errorWithBackButton('Resending email is not possible on this server.');
+ return;
+}
+
+$showForm = true;
+
+if (isset($_POST['submit']) && $_POST['submit'] == '1') {
+ $email = $_REQUEST['email'];
+
+ if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
+ $errorWithBackButton('Please enter valid Email.');
+ return;
+ }
+
+ $account = new OTS_Account();
+ $account->findByEMail($email);
+ if ($account->isLoaded()) {
+ if ($account->getCustomField('email_verified') == '1') {
+ $errorWithBackButton('This account is already verified! You can log in on the website.');
+ return;
+ }
+
+ $accountEmailVerify = AccountEmailVerify::where('account_id', $account->getId())->orderBy('sent_at', 'DESC')->first();
+ if ($accountEmailVerify && time() - $accountEmailVerify->sent_at < 60) {
+ $errorWithBackButton('Only one Email per minute is allowed. Please try again later.');
+ return;
+ }
+
+ $tmp_account = $email;
+ if (!config('account_login_by_email')) {
+ $tmp_account = (USE_ACCOUNT_NAME ? $account->getName() : $account->getId());
+ }
+
+ $hash = md5(generateRandomString(16, true, true) . $email);
+
+ AccountEmailVerify::create([
+ 'account_id' => $account->getId(),
+ 'hash' => $hash,
+ 'sent_at' => time(),
+ ]);
+
+ $verify_url = getLink('account/confirm-email/' . $hash);
+ $body_html = $twig->render('mail.account.resend-email-verify.html.twig', array(
+ 'account' => $tmp_account,
+ 'verify_url' => generateLink($verify_url, $verify_url, true)
+ ));
+
+ if (_mail($account->getEMail(), configLua('serverName') . ' - Verify Account', $body_html)) {
+ $message = "If account with this email exists - you will become an email with verification link.";
+ $showForm = false;
+ } else {
+ $message = "
An error occurred while sending email ({$email} )! Try again later. For Admin: More info can be found in system/logs/mailer-error.log
';
@@ -281,7 +266,7 @@ class Settings implements \ArrayAccess
if ($rows < 2) {
$rows = 2; // always min 2 rows for textarea
}
- echo '';
+ echo '';
}
else if ($setting['type'] === 'options') {
@@ -383,7 +368,7 @@ class Settings implements \ArrayAccess
}
#[\ReturnTypeWillChange]
- public function offsetSet($offset, $value)
+ public function offsetSet($offset, $value): void
{
if (is_null($offset)) {
throw new \RuntimeException("Settings: You cannot set empty offset with value: $value!");
@@ -423,7 +408,7 @@ class Settings implements \ArrayAccess
}
#[\ReturnTypeWillChange]
- public function offsetUnset($offset)
+ public function offsetUnset($offset): void
{
$this->loadPlugin($offset);
@@ -455,7 +440,7 @@ class Settings implements \ArrayAccess
* @return array|mixed
*/
#[\ReturnTypeWillChange]
- public function offsetGet($offset)
+ public function offsetGet($offset): mixed
{
// try cache hit
if(isset($this->cache[$offset])) {
@@ -472,24 +457,22 @@ class Settings implements \ArrayAccess
if (!isset($this->settingsFile[$pluginKeyName]['settings'])) {
throw new \RuntimeException('Unknown plugin settings: ' . $pluginKeyName);
}
+
return $this->settingsFile[$pluginKeyName]['settings'];
}
- $ret = [];
- if(isset($this->settingsFile[$pluginKeyName]['settings'][$key])) {
- $ret = $this->settingsFile[$pluginKeyName]['settings'][$key];
+ if (!isset($this->settingsFile[$pluginKeyName]['settings'][$key])) {
+ return null;
}
+ $ret = $this->settingsFile[$pluginKeyName]['settings'][$key];
+
if(isset($this->settingsDatabase[$pluginKeyName][$key])) {
$value = $this->settingsDatabase[$pluginKeyName][$key];
$ret['value'] = $value;
}
else {
- if (!isset($this->settingsFile[$pluginKeyName]['settings'][$key])) {
- return null;
- }
-
$ret['value'] = $this->settingsFile[$pluginKeyName]['settings'][$key]['default'];
}
@@ -523,7 +506,7 @@ class Settings implements \ArrayAccess
return $ret;
}
- private function updateValuesAsked($offset)
+ private function updateValuesAsked($offset): void
{
$pluginKeyName = $offset;
if (strpos($offset, '.')) {
@@ -539,7 +522,7 @@ class Settings implements \ArrayAccess
}
}
- private function loadPlugin($offset)
+ private function loadPlugin($offset): void
{
$this->updateValuesAsked($offset);
@@ -568,7 +551,7 @@ class Settings implements \ArrayAccess
}
}
- public static function saveConfig($config, $filename, &$content = '')
+ public static function saveConfig($config, $filename, &$content = ''): bool|int
{
$content = " $name, 'error' => ''];
+ $hooks->triggerFilter(HOOK_FILTER_VALIDATE_CHARACTER_NEW_NAME, $params);
+
+ if (!empty($params['error'])) {
+ self::$lastError = $params['error'];
+ return false;
+ }
+
return true;
}
diff --git a/system/src/global.php b/system/src/global.php
index e4dfec58..03a977b3 100644
--- a/system/src/global.php
+++ b/system/src/global.php
@@ -8,7 +8,9 @@ $i = 0;
define('HOOK_INIT', ++$i);
define('HOOK_STARTUP', ++$i);
define('HOOK_BEFORE_PAGE', ++$i);
+define('HOOK_BEFORE_PAGE_CUSTOM', ++$i);
define('HOOK_AFTER_PAGE', ++$i);
+define('HOOK_AFTER_PAGE_CUSTOM', ++$i);
define('HOOK_FINISH', ++$i);
define('HOOK_TIBIACOM_ARTICLE', ++$i);
define('HOOK_TIBIACOM_BORDER_3', ++$i);
@@ -26,6 +28,8 @@ define('HOOK_CHARACTERS_AFTER_CHARACTERS', ++$i);
define('HOOK_LOGIN', ++$i);
define('HOOK_LOGIN_ATTEMPT', ++$i);
define('HOOK_LOGOUT', ++$i);
+define('HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_OLD_PASSWORD', ++$i);
+define('HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_NEW_PASSWORD', ++$i);
define('HOOK_ACCOUNT_CHANGE_PASSWORD_POST', ++$i);
define('HOOK_ACCOUNT_CREATE_BEFORE_FORM', ++$i);
define('HOOK_ACCOUNT_CREATE_BEFORE_BOXES', ++$i);
@@ -52,6 +56,7 @@ define('HOOK_ACCOUNT_MANAGE_BEFORE_GENERAL_INFORMATION', ++$i);
define('HOOK_ACCOUNT_MANAGE_BEFORE_PUBLIC_INFORMATION', ++$i);
define('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS', ++$i);
define('HOOK_ACCOUNT_MANAGE_BEFORE_CHARACTERS', ++$i);
+define('HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS', ++$i);
define('HOOK_ACCOUNT_LOGIN_BEFORE_PAGE', ++$i);
define('HOOK_ACCOUNT_LOGIN_BEFORE_ACCOUNT', ++$i);
define('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT', ++$i);
@@ -90,6 +95,7 @@ define('HOOK_EMAIL_CONFIRMED', ++$i);
define('HOOK_GUILDS_BEFORE_GUILD_HEADER', ++$i);
define('HOOK_GUILDS_AFTER_GUILD_HEADER', ++$i);
define('HOOK_GUILDS_AFTER_GUILD_INFORMATION', ++$i);
+define('HOOK_GUILDS_AFTER_MANAGE_BUTTON', ++$i);
define('HOOK_GUILDS_AFTER_GUILD_MEMBERS', ++$i);
define('HOOK_GUILDS_AFTER_INVITED_CHARACTERS', ++$i);
define('HOOK_TWIG', ++$i);
@@ -103,6 +109,7 @@ define('HOOK_FILTER_TWIG_DISPLAY', ++$i);
define('HOOK_FILTER_TWIG_RENDER', ++$i);
define('HOOK_FILTER_THEME_FOOTER', ++$i);
define('HOOK_FILTER_POT', ++$i);
+define('HOOK_FILTER_VALIDATE_CHARACTER_NEW_NAME', ++$i);
const HOOK_FIRST = HOOK_INIT;
define('HOOK_LAST', $i);
diff --git a/system/status.php b/system/status.php
index 8e8225dd..b69e7acc 100644
--- a/system/status.php
+++ b/system/status.php
@@ -145,13 +145,7 @@ function updateStatus() {
}
$uptime = $status['uptime'] = $serverStatus->getUptime();
- $m = date('m', $uptime);
- $m = $m > 1 ? "$m months, " : ($m == 1 ? 'month, ' : '');
- $d = date('d', $uptime);
- $d = $d > 1 ? "$d days, " : ($d == 1 ? 'day, ' : '');
- $h = date('H', $uptime);
- $min = date('i', $uptime);
- $status['uptimeReadable'] = "{$m}{$d}{$h}h {$min}m";
+ $status['uptimeReadable'] = getStatusUptimeReadable($uptime);
$status['monsters'] = $serverStatus->getMonstersCount();
$status['motd'] = $serverStatus->getMOTD();
diff --git a/system/template.php b/system/template.php
index f051e640..30cb5535 100644
--- a/system/template.php
+++ b/system/template.php
@@ -91,7 +91,7 @@ else {
$file = BASE . $template_path . '/layout_config.ini';
}
- $template_ini = parse_ini_file($file);
+ $template_ini = parse_ini_file($file, true);
unset($file);
if ($cache->enabled()) {
@@ -148,7 +148,7 @@ function get_template_menus(): array
{
global $template_name;
- $result = Cache::remember('template_menus', 10 * 60, function () use ($template_name) {
+ $result = Cache::remember('template_menus_' . $template_name, 10 * 60, function () use ($template_name) {
$result = Menu::select(['name', 'link', 'blank', 'color', 'category'])
->where('template', $template_name)
->orderBy('category')
diff --git a/system/templates/account.change-email.html.twig b/system/templates/account.change-email.html.twig
index ea627cc7..ab2a8c06 100644
--- a/system/templates/account.change-email.html.twig
+++ b/system/templates/account.change-email.html.twig
@@ -28,7 +28,7 @@ Please enter your password and the new email address. Make sure that you enter a
-
+
-
+
+
+
diff --git a/system/templates/account.change-password.html.twig b/system/templates/account.change-password.html.twig
index df101323..03f82d9b 100644
--- a/system/templates/account.change-password.html.twig
+++ b/system/templates/account.change-password.html.twig
@@ -9,23 +9,29 @@ Please enter your current password and a new password. For your security, please
Current Password:
diff --git a/system/templates/account.characters.change-comment.html.twig b/system/templates/account.characters.change-comment.html.twig
index 8bb94c80..ab8fb384 100644
--- a/system/templates/account.characters.change-comment.html.twig
+++ b/system/templates/account.characters.change-comment.html.twig
@@ -88,7 +88,7 @@ If you do not want to specify a certain field, just leave it blank.
-
+
{{ include('buttons.submit.html.twig') }}
@@ -99,15 +99,15 @@ If you do not want to specify a certain field, just leave it blank.
diff --git a/system/templates/account.characters.delete.html.twig b/system/templates/account.characters.delete.html.twig
index 8593f7ed..b946d221 100644
--- a/system/templates/account.characters.delete.html.twig
+++ b/system/templates/account.characters.delete.html.twig
@@ -24,7 +24,7 @@ To delete a character enter the name of the character and your password.
-
+
{{ csrf() }}
@@ -36,14 +36,14 @@ To delete a character enter the name of the character and your password.
diff --git a/system/templates/account.generate_recovery_key.html.twig b/system/templates/account.generate_recovery_key.html.twig
index c34132f0..526d4659 100644
--- a/system/templates/account.generate_recovery_key.html.twig
+++ b/system/templates/account.generate_recovery_key.html.twig
@@ -32,14 +32,14 @@ To generate recovery key for your account please enter your password.
- {% for value in ['server_path'] %}
+ {% for value in ['site_url', 'server_path'] %}
diff --git a/system/templates/mail.account.resend-email-verify.html.twig b/system/templates/mail.account.resend-email-verify.html.twig
new file mode 100644
index 00000000..75bdab8b
--- /dev/null
+++ b/system/templates/mail.account.resend-email-verify.html.twig
@@ -0,0 +1,7 @@
+Hello {{ account }}!
+
+You requested to resend the verify Email on {{ config.lua.serverName }}!
+
+
+To verify your email address please click the link below:
+{{ verify_url|raw }}
diff --git a/system/templates/online.form.html.twig b/system/templates/online.form.html.twig
deleted file mode 100644
index 82c6f7b2..00000000
--- a/system/templates/online.form.html.twig
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
- Search Character
-
-
-
-
-
-
-
Name:
-
-
-
-
- {{ include('buttons.submit.html.twig') }}
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/system/templates/online.html.twig b/system/templates/online.html.twig
index 0210d80f..6f798740 100644
--- a/system/templates/online.html.twig
+++ b/system/templates/online.html.twig
@@ -1,39 +1,13 @@
-
-
-
Server Status
-
-{% if players|length == 0 %}
-
Currently no one is playing on {{ config.lua.serverName }}.
-{% else %}
-
-
- {% if not status.online %}
- Server is offline.
- {% else %}
- {% if setting('core.online_afk') %}
- {% set players_count = players|length %}
- {% set afk = players_count - status.players %}
- {% if afk < 0 %}
- {% set players_count = players_count + afk|abs %}
- {% set afk = 0 %}
- {% endif %}
- Currently there are {{ status.players }} active and {{ afk }} AFK players.
- Total number of players: {{ players_count }}.
- {% else %}
- Currently {{ players|length }} players are online.
- {% endif %}
- {% endif %}
- {% if setting('core.online_record') %}
- {{ record }}
- {% endif %}
-
-
-
+{% set onlineTTL = setting('core.online_cache_ttl') %}
+{% if onlineTTL > 0 and cache.enabled() %}
+*Note: Online List is updated every {{ onlineTTL > 1 ? ' ' ~ onlineTTL : '' }} minute{{ onlineTTL > 1 ? 's' : '' }}.
- {# vocation statistics #}
- {% if setting('core.online_vocations') %}
+{% endif %}
+
+{# vocation statistics #}
+{% if setting('core.online_vocations') %}
- {% if setting('core.online_vocations_images') %}
+ {% if setting('core.online_vocations_images') %}
@@ -69,11 +43,13 @@
{% endfor %}
- {% endif %}
{% endif %}
+{% endif %}
- {# show skulls #}
- {% if setting('core.online_skulls') %}
+
+
+{# show skulls #}
+{% if setting('core.online_skulls') %}
@@ -83,34 +59,114 @@
+{% endif %}
+
+
+
+{% set title = 'World Information' %}
+{% set tableClass = 'Table3' %}
+{% set background = config('darkborder') %}
+{% set content %}
+
+
+
Status:
+
{% if not status.online %}Offline{% else %}Online{% endif %}
+
+
+
Players Online:
+
+ {% if setting('core.online_afk') %}
+ {% set players_count = players|length %}
+ {% set afk = players_count - status.players %}
+ {% if afk < 0 %}
+ {% set players_count = players_count + afk|abs %}
+ {% set afk = 0 %}
+ {% endif %}
+ Currently there are {{ status.players }} active and {{ afk }} AFK players.
+ Total number of players: {{ players_count }}.
+ {% else %}
+ {{ players|length }}
+ {% endif %}
+
+
+
+ {% if setting('core.online_record') and record|length > 0 %}
+