Progress!

This commit is contained in:
Pachira 2015-05-11 22:20:19 +00:00
parent 66a98d4c44
commit be33f3cb89
28 changed files with 396 additions and 169 deletions

View file

@ -9,7 +9,9 @@
"builds": [
"20150508",
"20150509"
"20150509",
"20150509.1",
"20150512"
]
@ -1003,6 +1005,40 @@
"change": "Fixed avatar border being depositioned."
}
],
"20150509.1": [
{
"type": "UPD",
"change": "Compactise (not a word but you get the meaning) array adding in the server-side notification system."
},
{
"type": "FIX",
"change": "Fixed some redundancy in the news viewer."
},
{
"type": "FIX",
"change": "Fixed CORS breaking notifications."
},
{
"type": "FIX",
"change": "Fix a wrong way of assigning notifications to a user (Session::$userId instead of $user)."
},
{
"type": "UPD",
"change": "Replace .cfg files and parser with the built in .ini parser."
}
],
"20150512": [
{
"type": "FIX",
"change": "Fix {{ sakura.currentpage }} redirecting to the php file that's being used without the right attributes."
}
]
}

View file

@ -56,7 +56,7 @@ class Configuration {
trigger_error('Unable to get local configuration value!', E_USER_ERROR);
}
// Dynamically set local configuration values, does not update the configuration file
public static function setLocalConfig($key, $subkey, $value) {

View file

@ -19,17 +19,17 @@ class Templates {
self::$_TPL = $template;
// Assign config path to a variable so we don't have to type it out twice
$confPath = ROOT .'_sakura/templates/'. self::$_TPL .'/template.cfg';
$confPath = ROOT .'_sakura/templates/'. self::$_TPL .'/template.ini';
// Check if the configuration file exists
if(!file_exists($confPath))
trigger_error('Template configuration does not exist', E_USER_ERROR);
// Parse and store the configuration
self::$_CFG = self::parseCfg(file_get_contents($confPath));
self::$_CFG = parse_ini_file($confPath, true);
// Make sure we're not using a manage template for the main site or the other way around
if((bool)self::$_CFG['MANAGE'] != (bool)Main::$_MANAGE_MODE)
if((bool)self::$_CFG['manage']['mode'] != (bool)Main::$_MANAGE_MODE)
trigger_error('Incorrect template type', E_USER_ERROR);
// Start Twig
@ -55,43 +55,6 @@ class Templates {
}
// Parse .cfg files
public static function parseCfg($data) {
// Create storage variable
$out = array();
// Remove comments and empty lines
$data = preg_replace('/#.*?\r\n/im', null, $data);
$data = preg_replace('/^\r\n/im', null, $data);
// Break line breaks up into array values
$data = str_replace("\r\n", "\n", $data);
$data = str_replace("\r", "\n", $data);
$data = explode("\n", $data);
foreach($data as $var) {
// Make sure no whitespaces escaped the check
if(empty($var))
continue;
// Remove whitespace between key, equals sign and value
$var = preg_replace('/[\s+]=[\s+]/i', '=', $var);
// Then break this up
$var = explode('=', $var);
// And assign the value with the key to the output variable
$out[$var[0]] = $var[1];
}
// Return the output variable
return $out;
}
// Render template
public static function render($file, $tags) {

View file

@ -991,7 +991,7 @@ class Users {
// Insert it into the database
Database::insert('notifications', [
'uid' => Session::$userId,
'uid' => $user,
'timestamp' => $time,
'notif_read' => 0,
'notif_sound' => ($sound ? 1 : 0),
@ -1004,4 +1004,34 @@ class Users {
}
// Getting a user's PMs
public static function getPrivateMessages($from = false) {
// Get all messages from the database
$messages = Database::fetch('messages', true, [
($from ? 'from_user' : 'to_user') => [Session::$userId, '=']
]);
// Prepare a storage array
$store = array();
// Go over each message and check if they are for the current user
foreach($messages as $message) {
// Store the message
$store[$message['id']] = $message;
// Store user data as well
$store[$message['id']]['data']['from']['user'] = ($_MSG_USR = self::getUser($message['from_user']));
$store[$message['id']]['data']['from']['rank'] = self::getRank($_MSG_USR['rank_main']);
$store[$message['id']]['data']['to']['user'] = ($_MSG_USR = self::getUser($message['to_user']));
$store[$message['id']]['data']['to']['rank'] = self::getRank($_MSG_USR['rank_main']);
}
// Return store array
return $store;
}
}

View file

@ -0,0 +1,74 @@
; Example Sakura configuration
; Rename this file to config.ini after you're done editing.
; Database configuration
[database]
; SQL Driver that should be used.
; This has to relate to a PHP file in the _sakura/components/database folder
; but must EXCLUDE the .php file extension. (I recommend sticking with the bundled mysql library)
driver = mysql
; Use a Unix system socket (if the library supports it), doesn't work on Windows servers.
unix_socket = 0
; URI to SQL server (usually localhost or 127.0.0.1) or in the case that you're using Unix sockets
; the path to the socket.
host = localhost
; Port for the SQL server, ignored if Unix sockets are used. Should be 3306.
port = 3306
; Username used to authenticate with the SQL server
username = sakura
; Password for the same purpose
password = password
; Database (not table) name used.
database = sakura
; Table prefix used.
prefix = sakura_
; Path configuration (DO NOT INCLUDE PROTOCOLS)
[urls]
; Main site location
main = yourdomain.com
; API location
api = api.yourdomain.com
; Content location
content = content.yourdomain.com
; Management panel location
manage = manage.yourdomain.com
; Forum location
forum = forum.yourdomain.com
; Chat location
chat = chat.yourdomain.com
; Data files relative to the _sakura directory
[data]
; File containing CloudFlare CIDRs
cfhosts = config/cloudflare.hosts
; JSON file containing WHOIS servers
whoisservers = config/whois.json
; JSON file containing ISO 3166 country codes
iso3166 = config/iso3166.json
; Sock Chat extensions configuration
; These only work properly if Sock Chat uses the same database as the rest of Sakura
[sockchat]
; Set whether the Sock Chat extensions should be used or not
enabled = 1
; The table prefix used for Sock Chat
prefix = sock_

View file

@ -8,7 +8,7 @@
namespace Sakura;
// Define Sakura version
define('SAKURA_VERSION', '20150509');
define('SAKURA_VERSION', '20150512');
define('SAKURA_VLABEL', 'Eminence');
define('SAKURA_VTYPE', 'Development');
define('SAKURA_COLOUR', '#6C3082');
@ -64,7 +64,7 @@ $renderData = array(
'vcolour' => SAKURA_COLOUR,
'urls' => Configuration::getLocalConfig('urls'),
'charset' => Configuration::getConfig('charset'),
'currentpage' => '//'. $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'],
'currentpage' => '//'. $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'],
'recaptcha_public' => Configuration::getConfig('recaptcha_public'),
'recaptcha_enable' => Configuration::getConfig('recaptcha'),
'resources' => '//'. Configuration::getLocalConfig('urls')['content'] .'/data/'. strtolower(Templates::$_TPL),

View file

@ -1,10 +0,0 @@
#
# Amu
# Design planned for 2016
#
# Sets name of this template
NAME = Amu
# Is this style intended for manage?
MANAGE = 0

View file

@ -0,0 +1,14 @@
; Sakura Template Configuration
[meta]
; Display name of the style, only used in the admin section of the management panel.
name = Amu
; Author of this template.
author = Flashwave
; If you set a URL below your name becomes a clickable link in the management panel.
author_url = https://flash.moe
[manage]
; This defines whether the template is intended for the management panel.
; When it's incorrect Sakura will halt execution of the script.
mode = 0

View file

@ -1,9 +0,0 @@
#
# Sakura Manage Panel
#
# Sets name of this template
NAME = Broomcloset
# Is this style intended for manage?
MANAGE = 1

View file

@ -0,0 +1,14 @@
; Sakura Template Configuration
[meta]
; Display name of the style, only used in the admin section of the management panel.
name = Broom Closet
; Author of this template.
author = Flashwave
; If you set a URL below your name becomes a clickable link in the management panel.
author_url = https://flash.moe
[manage]
; This defines whether the template is intended for the management panel.
; When it's incorrect Sakura will halt execution of the script.
mode = 1

View file

@ -1,10 +0,0 @@
#
# Mio
# 2014 Flashii Design
#
# Sets name of this template
NAME = Mio
# Is this style intended for manage?
MANAGE = 0

View file

@ -0,0 +1,14 @@
; Sakura Template Configuration
[meta]
; Display name of the style, only used in the admin section of the management panel.
name = Mio
; Author of this template.
author = Flashwave
; If you set a URL below your name becomes a clickable link in the management panel.
author_url = https://flash.moe
[manage]
; This defines whether the template is intended for the management panel.
; When it's incorrect Sakura will halt execution of the script.
mode = 0

View file

@ -1,4 +1,4 @@
{% if page.articleCount > 1 %}<a href="/news/{{ newsPost.id }}" class="news-head" id="{{ newsPost.id }}">{{ newsPost.title }}</a>{% endif %}
{% if newsPosts|length > 1 %}<a href="/news/{{ newsPost.id }}" class="news-head" id="{{ newsPost.id }}">{{ newsPost.title }}</a>{% endif %}
<div class="news-body">
<a class="no-underline" href="/u/{{ newsPost.uid }}">
<div class="news-poster">
@ -12,5 +12,5 @@
</div>
<div class="clear"></div>
<div class="news-post-time">
Posted on {{ newsPost.date|date("D Y-m-d H:i:s T") }}{% if page.articleCount > 1 %} <a class="default" href="/news/{{ newsPost.id }}#disqus_thread">View comments</a>{% endif %}
Posted on {{ newsPost.date|date("D Y-m-d H:i:s T") }}{% if newsPosts|length > 1 %} <a class="default" href="/news/{{ newsPost.id }}#disqus_thread">View comments</a>{% endif %}
</div>

View file

@ -0,0 +1,5 @@
<div class="content standalone" style="padding: 20px;">
<h1>Login to view this page!</h1>
If you actually are logged in something went wrong and you should report this to the administrator.<br />
If you aren't logged in please log in or create an account if you don't have one.
</div>

View file

@ -0,0 +1,28 @@
<div class="head">
Navigation
</div>
<div class="right-menu-nav">
<div>General</div>
<a href="/settings/">Home</a>
<a href="/settings/profile">Edit Profile</a>
<div>Messages</div>
<a href="/messages/inbox">Inbox</a>
<a href="/messages/sent">Sent</a>
<a href="/messages/compose">Compose</a>
<div>Notifications</div>
<a href="/settings/notifications">History</a>
<div>Aesthetics</div>
<a href="/settings/avatar">Avatar</a>
<a href="/settings/background">Background</a>
<a href="/settings/page">Profile Page</a>
<div>Account</div>
<a href="/settings/email">E-Mail Address</a>
<a href="/settings/username">Username</a>
<a href="/settings/usertitle">User Title</a>
<a href="/settings/password">Password</a>
<a href="/settings/ranks">Ranks</a>
<div>Danger zone</div>
<a href="/settings/sessions">Sessions</a>
<a href="/settings/regkeys">Registration Keys</a>
<a href="/settings/deactivate">Deactivate Account</a>
</div>

View file

@ -92,10 +92,6 @@
{% endif %}
</div>
{% else %}
<div class="content standalone" style="padding: 20px;">
<h1>Login to view this page!</h1>
If you actually are logged in something went wrong and you should report this to the administrator.<br />
If you aren't logged in please log in or create an account if you don't have one.
</div>
{% include 'elements/restricted.tpl' %}
{% endif %}
{% include 'global/footer.tpl' %}

View file

@ -0,0 +1,36 @@
{% include 'global/header.tpl' %}
<div class="content settings messages">
<div class="content-right content-column">
{% include 'elements/settingsNav.tpl' %}
</div>
<div class="content-left content-column">
<div class="head">
Messages / Inbox
</div>
{% if messages|length %}
<table class="msgTable">
<thead>
<tr>
<th>From</th>
<th>Subject</th>
<th>Sent on</th>
</tr>
</thead>
<tbody>
{% for message in messages %}
<tr>
<td><a href="//{{ sakura.urls.main }}/u/{{ message.data.from.user.id }}" class="default" style="font-weight: 700; color: {% if message.data.from.user.name_colour == null %}{{ message.data.from.rank.colour }}{% else %}{{ message.data.from.user.name_colour }}{% endif %};">{{ message.data.from.user.username }}</a></td>
<td><a href="//{{ sakura.urls.main }}/messages/read/{{ message.id }}" class="default">{{ message.subject }}</a></td>
<td>{{ message.time|date("l Y-m-d H:i T") }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<h1 class="stylised"style="line-height: 1.8em; text-align: center;">Nothing to view!</h1>
{% endif %}
<h3 style="text-align: center;">Click Compose in the menu on the right side to write a new message!</h3>
</div>
<div class="clear"></div>
</div>
{% include 'global/footer.tpl' %}

View file

@ -1,8 +1,8 @@
{% include 'global/header.tpl' %}
<div class="content">
<div class="content-column news">
<div class="head">{% if page.articleCount == 1 %}{{ newsPosts[0].title }}{% elseif page.articleCount < 1 %}Post does not exist!{% else %}News <a href="/news.xml" class="fa fa-rss news-rss default"></a>{% endif %}</div>
{% if page.articleCount >= 1 %}
<div class="head">{% if newsPosts|length == 1 %}{{ newsPosts[0].title }}{% elseif newsPosts|length < 1 %}Post does not exist!{% else %}News <a href="/news.xml" class="fa fa-rss news-rss default"></a>{% endif %}</div>
{% if newsPosts|length >= 1 %}
{% for newsPost in newsPosts %}
{% include 'elements/newsPost.tpl' %}
{% endfor %}
@ -17,7 +17,7 @@
</div>
{% endif %}
</div>
{% if page.articleCount > 1 %}
{% if newsPosts|length > 1 %}
<script type="text/javascript">
/* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
var disqus_shortname = 'flashii';
@ -30,7 +30,7 @@
(document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s);
}());
</script>
{% elseif page.articleCount == 1 %}
{% elseif newsPosts|length == 1 %}
<div id="disqus_thread">
</div>
<script type="text/javascript">

View file

@ -20,6 +20,16 @@
<h1 style="color: {{ profile.colour }}; text-shadow: 0 0 7px #888; padding: 0 0 2px;">{{ profile.user.username }}</h1>
{% if profile.user.rank_main > 1 %}
{% if profile.istenshi %}<img src="//{{ sakura.urls.content }}/images/tenshi.png" alt="Tenshi" /> {% endif %}<img src="//{{ sakura.urls.content }}/images/flags/{% if profile.user.country|lower == 'eu' %}europeanunion{% else %}{{ profile.user.country|lower }}{% endif %}.png" alt="{{ profile.user.country }}" /> <span style="font-size: .9em; line-height: 11px;">{{ profile.country }}</span>
{% if user.checklogin %}
<div class="user-actions">
{% if user.data.id == profile.user.id %}
<a class="fa fa-pencil-square" title="Edit your profile" href="//{{ sakura.urls.main }}/settings/profile"></a>
{% else %}
<a class="fa fa-user-plus" title="Add {{ profile.user.username }} as a friend" href="//{{ sakura.urls.main }}/friends?add={{ profile.user.id }}&session={{ php.sessionid }}&time={{ php.time }}&return={{ sakura.currentpage }}"></a>
<a class="fa fa-flag" title="Report {{ profile.user.username }}" href="//{{ sakura.urls.main }}/report/{{ profile.user.id }}"></a>
{% endif %}
</div>
{% endif %}
<hr class="default" />
<b>Joined</b> {{ profile.user.regdate|date("l Y-m-d H:i T") }}<br />
{% if profile.user.lastdate == 0 %}

View file

@ -0,0 +1,18 @@
{% include 'global/header.tpl' %}
<div class="content settings messages">
<div class="content-right content-column">
{% include 'elements/settingsNav.tpl' %}
</div>
<div class="content-left content-column">
<div class="head">
General / Home
</div>
<div class="settings-explanation">
Welcome to the Settings Panel. From here you can monitor, view and update your profile and preferences.
</div>
<h1 class="stylised" style="line-height: 1.8em; text-align: center;">Select an option from the menu on the right!</h1>
<h3 style="text-align: center;">Some parts may require you to click a confirmation code sent to you in an e-mail, this is to ensure the security of your identity on the site.</h3>
</div>
<div class="clear"></div>
</div>
{% include 'global/footer.tpl' %}

View file

@ -1,10 +0,0 @@
#
# Yuuno
# 2015 Flashii Design
#
# Sets name of this template
NAME = Yuuno
# Is this style intended for manage?
MANAGE = 0

View file

@ -0,0 +1,14 @@
; Sakura Template Configuration
[meta]
; Display name of the style, only used in the admin section of the management panel.
name = Yuuno
; Author of this template.
author = Flashwave
; If you set a URL below your name becomes a clickable link in the management panel.
author_url = https://flash.moe
[manage]
; This defines whether the template is intended for the management panel.
; When it's incorrect Sakura will halt execution of the script.
mode = 0

View file

@ -858,6 +858,23 @@ h1.stylised {
max-height: 800px;
overflow: auto;
}
.profile .user-actions {
font-size: 3em;
line-height: 1.4em;
}
.profile .user-actions a {
color: #8364A1;
text-decoration: none;
text-shadow: 0 0 2px #9475B2;
transition: all .2s;
}
.profile .user-actions a:hover {
text-shadow: 0 0 6px #9475B2;
}
.profile .user-actions a:active {
color: #725390;
text-shadow: 0 0 8px #8364A1;
}
@media (max-width: 1024px) {
.content {
width: auto;
@ -1134,65 +1151,6 @@ h1.stylised {
text-align: center;
}
/* Messages */
.messages > table {
width: 100%;
border-spacing: 0;
}
.messages > .msg-inbox > thead > tr > td {
font-weight: 700;
text-align: center;
}
.messages > .msg-inbox > tbody > tr > td {
border-bottom: 1px solid #B19EED;
border-top: 1px solid #B19EED;
}
.messages > .msg-inbox > * > tr > td {
padding: 0 4px;
}
.messages > .msg-inbox > * > tr > td:first-child {
width: 150px;
text-align: center;
}
.messages > .msg-inbox > tbody > tr > td:first-child {
border-left: 1px solid #B19EED;
}
.messages > .msg-inbox > * > tr > td:last-child {
width: 220px;
text-align: center;
}
.messages > .msg-inbox > tbody > tr > td:last-child {
border-right: 1px solid #B19EED;
}
.messageFoldersContainer {
text-align: center;
padding: 9px 0 0;
}
.messageFoldersContainer > .messagesFolder {
background: linear-gradient(180deg, #C2AFFE, #B19EED) no-repeat scroll left top / cover #C2AFFE;
margin: 7px;
border-radius: 5px;
text-align: center;
box-shadow: 0 0 .5em #000;
display: inline-block;
vertical-align: top;
transition: box-shadow .2s;
padding: 5px;
font-size: 15px;
min-width: 150px;
color: inherit;
text-decoration: none;
}
.messageFoldersContainer > .messagesFolder:hover {
box-shadow: 0 0 1em #000;
cursor: pointer;
}
.messageFoldersContainer > .messagesFolder:active {
box-shadow: 0 0 1.5em #609;
}
/* Input buttons styling */
input[type="submit"].inputStyling,
input[type="button"].inputStyling,
@ -1465,3 +1423,34 @@ textarea.inputStyling {
.forum .forumList .forumForum .forumTitleColumn div {
padding-left: 5px;
}
/* Messages */
.messages table {
width: 100%;
border-spacing: 0;
}
.messages table > tbody > tr.unread {
background: #C2AFFE;
font-weight: 700;
}
.messages table > tbody > tr > td {
border-bottom: 1px solid #B19EED;
border-top: 1px solid #B19EED;
}
.messages table > * > tr > td {
padding: 0 4px;
}
.messages table > * > tr > td:first-child {
width: 150px;
text-align: center;
}
.messages table > tbody > tr > td:first-child {
border-left: 1px solid #B19EED;
}
.messages table > * > tr > td:last-child {
width: 220px;
text-align: center;
}
.messages table > tbody > tr > td:last-child {
border-right: 1px solid #B19EED;
}

View file

@ -34,9 +34,11 @@ RewriteRule ^news.xml$ news.php?xml
## Settings
RewriteRule ^settings?/?$ settings.php
RewriteRule ^settings/([a-z]+)?/?$ settings.php?mode=$1
## Private Messages
RewriteRule ^messages?/?$ messages.php
RewriteRule ^messages/([a-z]+)?/?$ messages.php?mode=$1
## Members
RewriteRule ^members?/?$ members.php

View file

@ -12,8 +12,7 @@ require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sak
// Add page specific things
$renderData['newsPosts'] = Main::getNewsPosts(3);
$renderData['page'] = [
'title' => Configuration::getConfig('sitename'),
'articleCount' => count($renderData['newsPosts'])
'title' => Configuration::getConfig('sitename')
];
$renderData['stats'] = [
'userCount' => ($_INDEX_USER_COUNT = count($_INDEX_USERS = Users::getAllUsers(false))) .' user'. ($_INDEX_USER_COUNT == 1 ? '' : 's'),

View file

@ -11,8 +11,9 @@ require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sak
// Add page specific things
$renderData['page'] = [
'title' => 'Private Messages'
'title' => 'Inbox'
];
$renderData['messages'] = Users::getPrivateMessages();
// Print page contents
print Templates::render('main/messages.tpl', $renderData);

View file

@ -12,11 +12,10 @@ require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sak
// Add page specific things
$renderData['newsPosts'] = Main::getNewsPosts((isset($_GET['id']) && !isset($_GET['xml']) && is_numeric($_GET['id'])) ? $_GET['id'] : null, (isset($_GET['id']) && !isset($_GET['xml']) && is_numeric($_GET['id'])));
$renderData['page'] = [
'articleCount' => ($postCount = count($renderData['newsPosts'])),
'title' => (isset($_GET['id']) ? ($postCount ? $renderData['newsPosts'][0]['title'] : 'Post does not exist!') : 'Flashii News'),
'title' => (isset($_GET['id']) ? (count($renderData['newsPosts']) ? $renderData['newsPosts'][0]['title'] : 'Post does not exist!') : 'Flashii News'),
];
// News XML, don't really care so yeah
// News XML feed
if(isset($_GET['xml'])) {
print '<?xml version="1.0" encoding="UTF-8"?>';

View file

@ -12,6 +12,9 @@ require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) .'_sakura/sak
// Notifications
if(isset($_REQUEST['request-notifications']) && $_REQUEST['request-notifications']) {
// Set CORS header
header('Access-Control-Allow-Origin: *');
// Create the notification container array
$notifications = array();
@ -24,14 +27,16 @@ if(isset($_REQUEST['request-notifications']) && $_REQUEST['request-notifications
// Add the proper values to the array
foreach($userNotifs as $notif) {
$notifications[$notif['timestamp']] = array();
$notifications[$notif['timestamp']]['read'] = $notif['notif_read'];
$notifications[$notif['timestamp']]['title'] = $notif['notif_title'];
$notifications[$notif['timestamp']]['text'] = $notif['notif_text'];
$notifications[$notif['timestamp']]['link'] = $notif['notif_link'];
$notifications[$notif['timestamp']]['img'] = $notif['notif_img'];
$notifications[$notif['timestamp']]['timeout'] = $notif['notif_timeout'];
$notifications[$notif['timestamp']]['sound'] = $notif['notif_sound'];
// Add the notification to the display array
$notifications[$notif['timestamp']] = [
'read' => $notif['notif_read'],
'title' => $notif['notif_title'],
'text' => $notif['notif_text'],
'link' => $notif['notif_link'],
'img' => $notif['notif_img'],
'timeout' => $notif['notif_timeout'],
'sound' => $notif['notif_sound']
];
}
@ -43,5 +48,24 @@ if(isset($_REQUEST['request-notifications']) && $_REQUEST['request-notifications
}
// Settings page list
$pages = [
'home' => ['General', 'Home'],
'profile' => ['General', 'Edit Profile'],
'notifications' => ['Notifications', 'History'],
'avatar' => ['Aesthetics', 'Avatar'],
'background' => ['Aesthetics', 'Background'],
'page' => ['Aesthetics', 'Profile Page'],
'email' => ['Account', 'E-Mail Address'],
'username' => ['Account', 'Username'],
'usertitle' => ['Account', 'User Title'],
'password' => ['Account', 'Password'],
'ranks' => ['Account', 'Ranks'],
'sessions' => ['Danger zone', 'Sessions'],
'regkeys' => ['Danger zone', 'Registration Keys'],
'deactivate' => ['Danger zone', 'Deactivate Account']
];
$currentPage = isset($_GET['mode']) && array_key_exists($_GET['mode'], $pages) ? $_GET['mode'] : key($pages);
// Print page contents
print Templates::render('ucp/index.tpl', $renderData);
print Templates::render('settings/'. $currentPage .'.tpl', $renderData);