r20150916

This commit is contained in:
flash 2015-09-16 22:34:36 +02:00
parent c7670d2816
commit 430e8ffa82
21 changed files with 519 additions and 190 deletions

View file

@ -2764,6 +2764,62 @@
"user": "Flashwave"
}
],
"20150916": [
"eminence",
{
"type": "ADD",
"change": "Begin implementation of new comment system.",
"user": "Flashwave"
},
{
"type": "UPD",
"change": "Made ajaxPost async.",
"user": "Flashwave"
},
{
"type": "FIX",
"change": "Fix AJAX submitted forms using a strange behaviour.",
"user": "Flashwave"
},
{
"type": "REM",
"change": "Removed CORS from the notification system since we're not using subdomains anymore.",
"user": "Flashwave"
},
{
"type": "FIX",
"change": "Fixed usertitle page having Username as the title.",
"user": "Flashwave"
},
{
"type": "ADD",
"change": "Added usertitle changing.",
"user": "Flashwave"
},
{
"type": "ADD",
"change": "Added site closing.",
"user": "Flashwave"
},
{
"type": "FIX",
"change": "Fixed user class related issues in the forum.",
"user": "Flashwave"
},
{
"type": "FIX",
"change": "Fixed reference to users class in permissions class.",
"user": "Flashwave"
},
{
"type": "ADD",
"change": "Added more templates for the settings page.",
"user": "Flashwave"
}
]
}

View file

@ -61,12 +61,13 @@ class Forum
], ['post_id', true]);
// Add last poster data and the details about the post as well
$return[$forum['forum_category']]['forums'][$forum['forum_id']]['last_poster'] = [
'post' => $lastPost,
'user' => ($_LAST_POSTER = Users::getUser($lastPost['poster_id'])),
'rank' => Users::getRank($_LAST_POSTER['rank_main']),
'elap' => Main::timeElapsed($lastPost['post_time']),
];
$return[$forum['forum_category']]['forums'][$forum['forum_id']]['last_poster'] = new User($lastPost['poster_id']);
// Add last poster data and the details about the post as well
$return[$forum['forum_category']]['forums'][$forum['forum_id']]['last_post'] = array_merge(
empty($lastPost) ? [] : $lastPost,
['elapsed' => Main::timeElapsed($lastPost['post_time'])]
);
}
}
@ -120,11 +121,11 @@ class Forum
'forum_id' => [$sub['forum_id'], '='],
], ['post_id', true]);
$forum['forums'][$key]['last_poster'] = [
'post' => $lastPost,
'user' => ($lastPoster = Users::getUser($lastPost['poster_id'])),
'rank' => Users::getRank($lastPoster['rank_main']),
];
$forum['forums'][$key]['last_poster'] = new User($lastPost['poster_id']);
$forum['forums'][$key]['last_post'] = array_merge(
empty($lastPost) ? [] : $lastPost,
['elapsed' => Main::timeElapsed($lastPost['post_time'])]
);
}
// Lastly grab the topics for this forum
@ -156,24 +157,24 @@ class Forum
'topic_id' => [$topic['topic_id'], '='],
]);
$topics[$key]['first_poster'] = [
'post' => $firstPost,
'user' => ($_FIRST_POSTER = Users::getUser($firstPost['poster_id'])),
'rank' => Users::getRank($_FIRST_POSTER['rank_main']),
'elap' => Main::timeElapsed($firstPost['post_time']),
];
$topics[$key]['first_poster'] = new User($firstPost['poster_id']);
$topics[$key]['first_post'] = array_merge(
empty($firstPost) ? [] : $firstPost,
['elapsed' => Main::timeElapsed($firstPost['post_time'])]
);
// Get last post in topics
$lastPost = Database::fetch('posts', false, [
'topic_id' => [$topic['topic_id'], '='],
], ['post_id', true]);
$topics[$key]['last_poster'] = [
'post' => $lastPost,
'user' => ($_LAST_POSTER = Users::getUser($lastPost['poster_id'])),
'rank' => Users::getRank($_LAST_POSTER['rank_main']),
'elap' => Main::timeElapsed($lastPost['post_time']),
];
$topics[$key]['last_poster'] = new User($lastPost['poster_id']);
$topics[$key]['last_post'] = array_merge(
empty($lastPost) ? [] : $lastPost,
['elapsed' => Main::timeElapsed($lastPost['post_time'])]
);
}
return $topics;
@ -229,26 +230,24 @@ class Forum
'topic_id' => [$topic['topic']['topic_id'], '='],
]);
// Get the data of the first poster
$topic['topic']['first_poster'] = [
'post' => $firstPost,
'user' => ($_FIRST_POSTER = Users::getUser($firstPost['poster_id'])),
'rank' => Users::getRank($_FIRST_POSTER['rank_main']),
'elap' => Main::timeElapsed($firstPost['post_time']),
];
$topic['topic']['first_poster'] = new User($firstPost['poster_id']);
$topic['topic']['first_post'] = array_merge(
empty($firstPost) ? [] : $firstPost,
['elapsed' => Main::timeElapsed($firstPost['post_time'])]
);
// Get last post in topics
$lastPost = Database::fetch('posts', false, [
'topic_id' => [$topic['topic']['topic_id'], '='],
], ['post_id', true]);
// Get the data of the last poster
$topic['topic']['last_poster'] = [
'post' => $lastPost,
'user' => ($_LAST_POSTER = Users::getUser($lastPost['poster_id'])),
'rank' => Users::getRank($_LAST_POSTER['rank_main']),
'elap' => Main::timeElapsed($lastPost['post_time']),
];
$topic['topic']['last_poster'] = new User($lastPost['poster_id']);
$topic['topic']['last_post'] = array_merge(
empty($lastPost) ? [] : $lastPost,
['elapsed' => Main::timeElapsed($lastPost['post_time'])]
);
// Create space for posts
$topic['posts'] = [];
@ -257,14 +256,9 @@ class Forum
foreach ($rawPosts as $post) {
// Add post and metadata to the global storage array
$topic['posts'][$post['post_id']] = array_merge($post, [
'user' => (new User($post['poster_id'])),
'elapsed' => Main::timeElapsed($post['post_time']),
'is_op' => ($post['poster_id'] == $firstPost['poster_id'] ? '1' : '0'),
'user' => ($_POSTER = Users::getUser($post['poster_id'])),
'rank' => Users::getRank($_POSTER['rank_main']),
'time_elapsed' => Main::timeElapsed($post['post_time']),
'country' => Main::getCountryName($_POSTER['country']),
'is_premium' => Users::checkUserPremium($_POSTER['id'])[0],
'is_online' => Users::checkUserOnline($_POSTER['id']),
'is_friend' => Users::checkFriend($_POSTER['id']),
'parsed_post' => self::parseMarkUp($post['post_text'], $post['parse_mode'], $post['enable_emotes']),
'signature' => empty($_POSTER['userData']['signature']) ?
'' :

View file

@ -150,13 +150,13 @@ class Permissions
{
// Get user data
$user = Users::getUser($uid);
$user = new User($uid);
// Attempt to get the permission row of a user
$userPerms = Database::fetch('permissions', false, ['rid' => [0, '='], 'uid' => [$user['id'], '=']]);
$userPerms = Database::fetch('permissions', false, ['rid' => [0, '='], 'uid' => [$user->data['id'], '=']]);
// Get their rank permissions
$rankPerms = self::getRankPermissions(json_decode($user['ranks'], true));
$rankPerms = self::getRankPermissions(json_decode($user->data['ranks'], true));
// Just return the rank permissions if no special ones are set
if (empty($userPerms)) {

View file

@ -1508,7 +1508,7 @@ class Users
]);
// Return true because yay
return [1, Users::checkFriend($uid) == 2 ? 'FRIENDS' : 'NOT_MUTUAL'];
return [1, self::checkFriend($uid) == 2 ? 'FRIENDS' : 'NOT_MUTUAL'];
}

View file

@ -8,7 +8,7 @@
namespace Sakura;
// Define Sakura version
define('SAKURA_VERSION', '20150915');
define('SAKURA_VERSION', '20150916');
define('SAKURA_VLABEL', 'Eminence');
define('SAKURA_COLOUR', '#6C3082');
define('SAKURA_STABLE', false);
@ -157,8 +157,6 @@ if (!defined('SAKURA_NO_TPL')) {
'recaptchaEnabled' => Configuration::getConfig('recaptcha'),
'disableRegistration' => Configuration::getConfig('disable_registration'),
'lockSite' => Configuration::getConfig('lock_site'),
'lockSiteReason' => Configuration::getConfig('lock_site_reason'),
'lockAuth' => Configuration::getConfig('lock_authentication'),
'requireRegCodes' => Configuration::getConfig('require_registration_code'),
'requireActivation' => Configuration::getConfig('require_activation'),
@ -189,6 +187,21 @@ if (!defined('SAKURA_NO_TPL')) {
];
// Site closing
if (Configuration::getConfig('site_closed')) {
// Additional render data
$renderData = array_merge($renderData, [
'page' => [
'message' => Configuration::getConfig('site_closed_reason'),
],
]);
print Templates::render('global/information.tpl', $renderData);
exit;
}
// Ban checking
if (Users::checkLogin() && $ban = Bans::checkBan(Session::$userId)) {
// Additional render data

View file

@ -1,19 +1,19 @@
<div class="comments">
<div class="comment-input-section">
{% if session.checkLogin %}
<form action="" method="post">
<form action="" method="post" id="commentsForm">
<input type="hidden" name="sessid" value="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" />
<input type="hidden" name="mode" value="comment" />
<div class="comment">
<div class="comment-avatar" style="background-image: url('{{ urls.format('IMAGE_AVATAR', [user.data.id]) }}');"></div>
<div class="comment-pointer"></div>
<textarea class="comment-text" class="comment" placeholder="Join the conversation..."></textarea>
<textarea class="comment-content" class="comment" placeholder="Join the conversation..."></textarea>
<input class="comment-submit" name="submit" type="submit" value="&#xf1d8;" />
</div>
</form>
{% else %}
<h1 class="stylised" style="text-align: center;">Log in to comment!</h1>
<h1 class="stylised" style="text-align: center; padding: 10px 0">Log in to comment!</h1>
{% endif %}
</div>
<div class="comments-discussion">
@ -22,8 +22,20 @@
<div class="comment">
<div class="comment-avatar" style="background-image: url('{{ urls.format('IMAGE_AVATAR', [user.data.id]) }}');"></div>
<div class="comment-pointer"></div>
<div class="comment-text">
aaaaaaaaaa
<div class="comment-content">
<div class="comment-controls">
<ul>
<li>Report</li>
<li>Delete</li>
<li>Reply</li>
<li class="shown"><span class="fa fa-plus-circle"></span> 1</li>
<li class="shown"><span class="fa fa-minus-circle"></span> 1</li>
</ul>
<div class="clear"></div>
</div>
<div class="comment-text">
aaaaaaaaaa
</div>
</div>
</div>
<ul>
@ -31,8 +43,19 @@
<div class="comment">
<div class="comment-avatar" style="background-image: url('{{ urls.format('IMAGE_AVATAR', [1]) }}');"></div>
<div class="comment-pointer"></div>
<div class="comment-text">
aaaaaaaaaa
<div class="comment-content">
<div class="comment-controls">
<ul>
<li>Report</li>
<li>Delete</li>
<li>Reply</li>
<li class="shown"><span class="fa fa-plus-circle"></span> 1</li>
<li class="shown"><span class="fa fa-minus-circle"></span> 1</li>
</ul>
</div>
<div class="comment-text">
aaaaaaaaaa
</div>
</div>
</div>
<ul>
@ -40,8 +63,19 @@
<div class="comment">
<div class="comment-avatar" style="background-image: url('{{ urls.format('IMAGE_AVATAR', [user.data.id]) }}');"></div>
<div class="comment-pointer"></div>
<div class="comment-text">
aaaaaaaaaa
<div class="comment-content">
<div class="comment-controls">
<ul>
<li>Report</li>
<li>Delete</li>
<li>Reply</li>
<li class="shown"><span class="fa fa-plus-circle"></span> 1</li>
<li class="shown"><span class="fa fa-minus-circle"></span> 1</li>
</ul>
</div>
<div class="comment-text">
aaaaaaaaaa
</div>
</div>
</div>
<ul>
@ -49,8 +83,19 @@
<div class="comment">
<div class="comment-avatar" style="background-image: url('{{ urls.format('IMAGE_AVATAR', [3]) }}');"></div>
<div class="comment-pointer"></div>
<div class="comment-text">
aaaaaaaaaa
<div class="comment-content">
<div class="comment-controls">
<ul>
<li>Report</li>
<li>Delete</li>
<li>Reply</li>
<li class="shown"><span class="fa fa-plus-circle"></span> 1</li>
<li class="shown"><span class="fa fa-minus-circle"></span> 1</li>
</ul>
</div>
<div class="comment-text">
aaaaaaaaaa
</div>
</div>
</div>
</li>
@ -60,8 +105,19 @@
<div class="comment">
<div class="comment-avatar" style="background-image: url('{{ urls.format('IMAGE_AVATAR', [1]) }}');"></div>
<div class="comment-pointer"></div>
<div class="comment-text">
aaaaaaaaaa
<div class="comment-content">
<div class="comment-controls">
<ul>
<li>Report</li>
<li>Delete</li>
<li>Reply</li>
<li class="shown"><span class="fa fa-plus-circle"></span> 1</li>
<li class="shown"><span class="fa fa-minus-circle"></span> 1</li>
</ul>
</div>
<div class="comment-text">
aaaaaaaaaa
</div>
</div>
</div>
</li>
@ -71,8 +127,19 @@
<div class="comment">
<div class="comment-avatar" style="background-image: url('{{ urls.format('IMAGE_AVATAR', [2]) }}');"></div>
<div class="comment-pointer"></div>
<div class="comment-text">
aaaaaaaaaa
<div class="comment-content">
<div class="comment-controls">
<ul>
<li>Report</li>
<li>Delete</li>
<li>Reply</li>
<li class="shown"><span class="fa fa-plus-circle"></span> 1</li>
<li class="shown"><span class="fa fa-minus-circle"></span> 1</li>
</ul>
</div>
<div class="comment-text">
aaaaaaaaaa
</div>
</div>
</div>
</li>
@ -81,3 +148,10 @@
</ul>
</div>
</div>
<script type="text/javascript">
window.addEventListener("load", function() {
prepareAjaxForm('commentsForm', 'Posting comment...');
});
</script>

View file

@ -28,8 +28,8 @@
</td>
<td class="forumLastColumn">
<div>
{% if forum.last_poster.user.id %}
<a href="{{ urls.format('FORUM_THREAD', [forum.last_poster.post.topic_id]) }}" class="default">{{ forum.last_poster.post.post_subject }}</a><br /><span title="{{ forum.last_poster.post.post_time|date(sakura.dateFormat) }}">{{ forum.last_poster.elap }}</span> by {% if forum.last_poster.user.id %}<a href="{{ urls.format('USER_PROFILE', [forum.last_poster.user.id]) }}" class="default" style="color: {% if forum.last_poster.user.name_colour %}{{ forum.last_poster.user.name_colour }}{% else %}{{ forum.last_poster.rank.colour }}{% endif %};">{{ forum.last_poster.user.username }}</a>{% else %}[deleted user]{% endif %} <a href="{{ urls.format('FORUM_POST', [forum.last_poster.post.post_id]) }}#p{{ forum.last_poster.post.post_id }}" class="default fa fa-tag"></a>
{% if forum.last_post.post_id %}
<a href="{{ urls.format('FORUM_THREAD', [forum.last_post.topic_id]) }}" class="default">{{ forum.last_post.post_subject }}</a><br /><span title="{{ forum.last_post.post_time|date(sakura.dateFormat) }}">{{ forum.last_post.elapsed }}</span> by {% if forum.last_poster.data.id %}<a href="{{ urls.format('USER_PROFILE', [forum.last_poster.data.id]) }}" class="default" style="color: {{ forum.last_poster.colour }}; text-shadow: 0 0 5px {% if forum.last_poster.colour != 'inherit' %}{{ forum.last_poster.colour }}{% else %}#222{% endif %};">{{ forum.last_poster.data.username }}</a>{% else %}[deleted user]{% endif %} <a href="{{ urls.format('FORUM_POST', [forum.last_poster.post.post_id]) }}#p{{ forum.last_poster.post.post_id }}" class="default fa fa-tag"></a>
{% else %}
There are no posts in this forum.<br />&nbsp;
{% endif %}

View file

@ -6,8 +6,8 @@
<a href="{{ urls.format('FORUM_THREAD', [topic.topic_id]) }}" class="default">{{ topic.topic_title }}</a>
</td>
<td class="topicAuthor">
{% if topic.first_poster.user.id %}
<a href="{{ urls.format('USER_PROFILE', [topic.first_poster.user.id]) }}" class="default" style="color: {% if topic.first_poster.user.name_colour %}{{ topic.first_poster.user.name_colour }}{% else %}{{ topic.first_poster.rank.colour }}{% endif %};">{{ topic.first_poster.user.username }}</a>
{% if topic.first_poster.data.id %}
<a href="{{ urls.format('USER_PROFILE', [topic.first_poster.data.id]) }}" class="default" style="color: {{ topic.first_poster.colour }}; text-shadow: 0 0 5px {% if topic.first_poster.colour != 'inherit' %}{{ topic.first_poster.colour }}{% else %}#222{% endif %};">{{ topic.first_poster.data.username }}</a>
{% else %}
[deleted user]
{% endif %}
@ -17,11 +17,11 @@
<div class="views" title="Amount of times this topic has been viewed.">{{ topic.topic_views }}</div>
</td>
<td class="topicLast">
{% if topic.last_poster.user.id %}
<a href="{{ urls.format('USER_PROFILE', [topic.last_poster.user.id]) }}" class="default" style="color: {% if topic.last_poster.user.name_colour %}{{ topic.last_poster.user.name_colour }}{% else %}{{ topic.last_poster.rank.colour }}{% endif %};">{{ topic.last_poster.user.username }}</a>
{% if topic.last_poster.data.id %}
<a href="{{ urls.format('USER_PROFILE', [topic.last_poster.data.id]) }}" class="default" style="color: {{ topic.last_poster.colour }}; text-shadow: 0 0 5px {% if topic.last_poster.colour != 'inherit' %}{{ topic.last_poster.colour }}{% else %}#222{% endif %};">{{ topic.last_poster.data.username }}</a>
{% else %}
[deleted user]
{% endif %} <a href="{{ urls.format('FORUM_POST', [topic.last_poster.post.post_id]) }}#p{{ topic.last_poster.post.post_id }}" class="default fa fa-tag"></a><br />
<span title="{{ topic.last_poster.post.post_time|date(sakura.dateFormat) }}">{{ topic.last_poster.elap }}</span>
{% endif %} <a href="{{ urls.format('FORUM_POST', [topic.last_post.post.post_id]) }}#p{{ topic.last_post.post.post_id }}" class="default fa fa-tag"></a><br />
<span title="{{ topic.last_post.post.post_time|date(sakura.dateFormat) }}">{{ topic.last_post.elapsed }}</span>
</td>
</tr>

View file

@ -11,23 +11,25 @@
{% for post in posts %}
<tr class="post" id="p{{ post.post_id }}">
<td class="userpanel">
{% if post.user.rank_main > 1 %}<a href="{{ urls.format('USER_PROFILE', [post.user.id]) }}" class="default username" style="color: {% if post.user.name_colour %}{{ post.user.name_colour }}{% else %}{{ post.rank.colour }}{% endif %};" title="Go to {{ post.user.username }}'s profile">{{ post.user.username }}</a>
<img src="{{ urls.format('IMAGE_AVATAR', [post.user.id]) }}" alt="{{ post.user.username }}" class="avatar" style="box-shadow: 0 3px 7px #{% if post.is_online %}484{% else %}844{% endif %};" />
{% if not post.user.checkPermission('SITE', 'DEACTIVATED') or post.user.checkPermission('SITE', 'RESTRICTED') %}<a href="{{ urls.format('USER_PROFILE', [post.user.data.id]) }}" class="default username" style="color: {{ post.user.colour }}; text-shadow: 0 0 5px {% if post.user.colour != 'inherit' %}{{ post.user.colour }}{% else %}#222{% endif %};" title="Go to {{ post.user.data.username }}'s profile">{{ post.user.data.username }}</a>
<img src="{{ urls.format('IMAGE_AVATAR', [post.user.data.id]) }}" alt="{{ post.user.data.username }}" class="avatar" style="box-shadow: 0 3px 7px #{% if post.is_online %}484{% else %}844{% endif %};" />
{% else %}
<a class="username">[deleted user]</a>
{% endif %}
<div class="userdata">
<div class="usertitle">{% if not post.user.usertitle %}{{ post.rank.title }}{% else %}{{ post.user.usertitle }}{% endif %}</div>
<img src="{{ sakura.contentPath }}/images/tenshi.png" alt="Tenshi"{% if not post.is_premium %} style="opacity: 0;"{% endif %} /> <img src="{{ sakura.contentPath }}/images/flags/{% if post.user.country|lower == 'eu' %}europeanunion{% else %}{{ post.user.country|lower }}{% endif %}.png" alt="{{ post.country }}" />
<img src="{{ sakura.contentPath }}/images/tenshi.png" alt="Tenshi"{% if not post.user.checkPremium[0] %} style="opacity: 0;"{% endif %} /> <img src="{{ sakura.contentPath }}/images/flags/{{ post.user.country.short|lower }}.png" alt="{{ post.user.country.long }}" />
{% if session.checkLogin %}
<div class="actions">
{% if user.data.id == post.user.id %}
<a class="fa fa-pencil-square-o" title="Edit this post" href="{{ urls.format('FORUM_EDIT_POST', [post.post_id]) }}"></a>
<a class="fa fa-trash" title="Delete this post" href="{{ urls.format('FORUM_DELETE_POST', [post.post_id]) }}"></a>
{% elseif post.user.rank_main > 1 %}
{% if post.is_friend != 0 %}<a class="fa fa-{% if post.is_friend == 2 %}heart{% else %}star{% endif %}" title="You are friends"></a>{% endif %}
<a class="fa fa-user-{% if post.is_friend == 0 %}plus{% else %}times{% endif %} forum-friend-toggle" title="{% if post.is_friend == 0 %}Add {{ post.user.username }} as a friend{% else %}Remove friend{% endif %}" href="{% if post.is_friend == 0 %}{{ urls.format('FRIEND_ADD', [post.user.id, php.sessionid, php.time, sakura.currentPage]) }}{% else %}{{ urls.format('FRIEND_REMOVE', [post.user.id, php.sessionid, php.time, sakura.currentPage]) }}{% endif %}"></a>
<a class="fa fa-flag" title="Report {{ post.user.username }}" href="{{ urls.format('USER_REPORT', [post.user.id]) }}"></a>
{% if user.data.id == post.user.data.id %}
<a class="fa fa-pencil-square-o" title="Edit this post" href="{{ urls.format('FORUM_EDIT_POST', [post.post_id]) }}"></a>
<a class="fa fa-trash" title="Delete this post" href="{{ urls.format('FORUM_DELETE_POST', [post.post_id]) }}"></a>
{% elseif not post.user.checkPermission('SITE', 'DEACTIVATED') or post.user.checkPermission('SITE', 'RESTRICTED') %}
{% if post.user.checkFriends(user.data.id) != 0 %}
<a class="fa fa-{% if post.user.checkFriends(user.data.id) == 2 %}heart{% else %}star{% endif %}" title="You are friends"></a>
{% endif %}
<a class="fa fa-user-{% if post.user.checkFriends(user.data.id) == 0 %}plus{% else %}times{% endif %} forum-friend-toggle" title="{% if post.user.checkFriends(user.data.id) == 0 %}Add {{ post.user.data.username }} as a friend{% else %}Remove friend{% endif %}" href="{% if post.user.checkFriends(user.data.id) == 0 %}{{ urls.format('FRIEND_ADD', [post.user.data.id, php.sessionid, php.time, sakura.currentPage]) }}{% else %}{{ urls.format('FRIEND_REMOVE', [post.user.data.id, php.sessionid, php.time, sakura.currentPage]) }}{% endif %}"></a>
<a class="fa fa-flag" title="Report {{ post.user.data.username }}" href="{{ urls.format('USER_REPORT', [post.user.data.id]) }}"></a>
{% endif %}
<a class="fa fa-reply" title="Quote this post" href="{{ urls.format('FORUM_QUOTE_POST', [post.post_id]) }}"></a>
</div>
@ -40,7 +42,7 @@
<a href="#p{{ post.post_id }}" class="clean">{{ post.post_subject }}</a>
</div>
<div class="date">
<a href="{{ urls.format('FORUM_POST', [post.post_id]) }}#p{{ post.post_id }}" class="clean" title="{{ post.post_time|date(sakura.dateFormat) }}">{{ post.time_elapsed }}</a>
<a href="{{ urls.format('FORUM_POST', [post.post_id]) }}#p{{ post.post_id }}" class="clean" title="{{ post.post_time|date(sakura.dateFormat) }}">{{ post.elapsed }}</a>
</div>
<div class="clear"></div>
</div>

View file

@ -72,17 +72,7 @@
prepareAjaxLink('headerLogoutLink', 'submitPost', ', true, "Logging out..."');
{% elseif not sakura.lockAuth and php.self != '/authenticate.php' %}
// Make the header login form dynamic
var headerLoginForm = document.getElementById('headerLoginForm');
var createInput = document.createElement('input');
var submit = headerLoginForm.querySelector('[type="submit"]');
createInput.setAttribute('name', 'ajax');
createInput.setAttribute('value', 'true');
createInput.setAttribute('type', 'hidden');
headerLoginForm.appendChild(createInput);
submit.setAttribute('type', 'button');
submit.setAttribute('onclick', 'submitPost(\''+ headerLoginForm.action +'\', formToObject(\'headerLoginForm\'), true, \'Logging in...\');');
prepareAjaxForm('headerLoginForm', 'Logging in...');
{% endif %}
{% if session.checkLogin %}
@ -127,20 +117,7 @@
};
for(var i in forms) {
var form = document.getElementById(i);
var submit = form.querySelector('[type="submit"]');
form.setAttribute('onkeydown', 'formEnterCatch(event, \''+ submit.id +'\');');
submit.setAttribute('href', 'javascript:void(0);');
submit.setAttribute('onclick', 'submitPost(\''+ form.action +'\', formToObject(\''+ i+ '\'), true, \''+ forms[i] +'\', '+ (i == 'registerForm' ? 'true' : 'false') +');');
submit.setAttribute('type', 'button');
var createInput = document.createElement('input');
createInput.setAttribute('name', 'ajax');
createInput.setAttribute('value', 'true');
createInput.setAttribute('type', 'hidden');
form.appendChild(createInput);
prepareAjaxForm(i, forms[i], (i == 'registerForm'));
}
{% endif %}
@ -210,7 +187,7 @@
<div id="userBackground" style="background-image: url('{{ urls.format('IMAGE_BACKGROUND', [(php.self == '/profile.php' ? profile : user).data.id]) }}');"></div>
{% endif %}
{% if not session.checkLogin and php.self != '/authenticate.php' %}
<form method="post" action="{{ urls.format('AUTH_ACTION') }}" id="headerLoginForm" onkeydown="formEnterCatch(event, 'headerLoginButton');">
<form method="post" action="{{ urls.format('AUTH_ACTION') }}" id="headerLoginForm">
<input type="hidden" name="redirect" value="{{ sakura.currentPage }}" />
<input type="hidden" name="session" value="{{ php.sessionid }}" />
<input type="hidden" name="time" value="{{ php.time }}" />

View file

@ -32,7 +32,9 @@
<div class="clear"></div>
</div>
{% endif %}
{% include 'elements/comments.tpl' %}
{% if viewPost and postExists %}
{% include 'elements/comments.tpl' %}
{% endif %}
{% else %}
<div style="padding: 20px;">
<h1>The requested news post does not exist!</h1>

View file

@ -0,0 +1,25 @@
<form enctype="multipart/form-data" method="post" action="{{ sakura.currentPage }}" id="emailAddressChangeForm">
<input type="hidden" name="sessid" value="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" />
<input type="hidden" name="mode" value="email" />
<h3 style="text-align: center;">Your e-mail address is currently set to <span style="font-weight: 700;">{{ user.data.email }}</span>.</h3>
<div class="profile-field">
<div><h2>E-mail address</h2></div>
<div><input type="text" name="emailnew" placeholder="Enter your new e-mail address" class="inputStyling" /></div>
</div>
<div class="profile-field">
<div><h2>Confirmation</h2></div>
<div><input type="text" name="emailver" placeholder="Just to make sure..." class="inputStyling" /></div>
</div>
<div class="profile-save">
<input type="submit" value="Save" name="submit" class="inputStyling" />
<input type="reset" value="Reset" name="reset" class="inputStyling" />
</div>
</form>
<script type="text/javascript">
window.addEventListener("load", function() {
prepareAjaxForm('emailAddressChangeForm', 'Changing E-mail address...');
});
</script>

View file

@ -0,0 +1,28 @@
<form enctype="multipart/form-data" method="post" action="{{ sakura.currentPage }}" id="changePasswordForm">
<input type="hidden" name="sessid" value="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" />
<input type="hidden" name="mode" value="password" />
<div class="profile-field">
<div><h2>Current Password</h2></div>
<div><input type="password" name="currentpw" placeholder="Enter your current password for verification." class="inputStyling" /></div>
</div>
<div class="profile-field">
<div><h2>New Password</h2></div>
<div><input type="password" name="newpw" placeholder="Enter your new password." class="inputStyling" /></div>
</div>
<div class="profile-field">
<div><h2>Confirmation</h2></div>
<div><input type="password" name="conpw" placeholder="Enter your new password again to make sure you didn't fuck up." class="inputStyling" /></div>
</div>
<div class="profile-save">
<input type="submit" value="Save" name="submit" class="inputStyling" />
<input type="reset" value="Reset" name="reset" class="inputStyling" />
</div>
</form>
<script type="text/javascript">
window.addEventListener("load", function() {
prepareAjaxForm('changePasswordForm', 'Changing password...');
});
</script>

View file

@ -0,0 +1,30 @@
{% set eligible = (php.time - user.data.lastunamechange) > 2592000 %}
<form enctype="multipart/form-data" method="post" action="{{ sakura.currentPage }}" id="changeUsernameForm">
<input type="hidden" name="sessid" value="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" />
<input type="hidden" name="mode" value="username" />
<h1 class="stylised" style="text-align: center; margin-top: 10px;{% if not eligible %} color: #c44;{% endif %}">You are {% if not eligible %}not {% endif %}eligible for a name change.</h1>
<h3 style="text-align: center;">Your last name change was {{ difference }}.</h3>
{% if eligible %}
<div class="profile-field">
<div><h2>Username</h2></div>
<div><input type="text" name="usernew" placeholder="Enter your new username (Max 20 characters)" class="inputStyling" /></div>
</div>
<div class="profile-field">
<div><h2>Confirmation</h2></div>
<div><input type="text" name="userver" placeholder="Just to make sure since you'll be stuck with it for 30 days..." class="inputStyling" /></div>
</div>
<div class="profile-save">
<input type="submit" value="Save" name="submit" class="inputStyling" />
<input type="reset" value="Reset" name="reset" class="inputStyling" />
</div>
{% endif %}
</form>
<script type="text/javascript">
window.addEventListener("load", function() {
prepareAjaxForm('changeUsernameForm', 'Changing username...');
});
</script>

View file

@ -0,0 +1,21 @@
<form enctype="multipart/form-data" method="post" action="{{ sakura.currentPage }}" id="changeUserTitleForm">
<input type="hidden" name="sessid" value="{{ php.sessionid }}" />
<input type="hidden" name="timestamp" value="{{ php.time }}" />
<input type="hidden" name="mode" value="usertitle" />
<h3 style="text-align: center;">Your current user title is:<br /><span style="font-weight: 700;">{{ user.userTitle }}</span></h3>
<div class="profile-field">
<div><h2>Usertitle</h2></div>
<div><input type="text" name="usertitle" placeholder="Enter your new user title (Max 64 characters)" class="inputStyling" value="{{ user.data.usertitle }}" /></div>
</div>
<div class="profile-save">
<input type="submit" value="Save" name="submit" class="inputStyling" />
<input type="reset" value="Reset" name="reset" class="inputStyling" />
</div>
</form>
<script type="text/javascript">
window.addEventListener("load", function() {
prepareAjaxForm('changeUserTitleForm', 'Updating Usertitle...');
});
</script>

View file

@ -23,17 +23,9 @@
</form>
<script type="text/javascript">
window.addEventListener("load", function() {
var optionsForm = document.getElementById('optionsForm');
var createInput = document.createElement('input');
var submit = optionsForm.querySelector('[type="submit"]');
createInput.setAttribute('name', 'ajax');
createInput.setAttribute('value', 'true');
createInput.setAttribute('type', 'hidden');
optionsForm.appendChild(createInput);
prepareAjaxForm('optionsForm', 'Changing Options...');
submit.setAttribute('type', 'button');
submit.setAttribute('onclick', 'submitPost(\''+ optionsForm.action +'\', formToObject(\'optionsForm\'), true, \'Changing Options...\');');
});
</script>
{% else %}

View file

@ -54,16 +54,8 @@
</form>
<script type="text/javascript">
window.addEventListener("load", function() {
var editProfileForm = document.getElementById('editProfileForm');
var createInput = document.createElement('input');
var submit = editProfileForm.querySelector('[type="submit"]');
createInput.setAttribute('name', 'ajax');
createInput.setAttribute('value', 'true');
createInput.setAttribute('type', 'hidden');
editProfileForm.appendChild(createInput);
prepareAjaxForm('editProfileForm', 'Updating Profile...');
submit.setAttribute('type', 'button');
submit.setAttribute('onclick', 'submitPost(\''+ editProfileForm.action +'\', formToObject(\'editProfileForm\'), true, \'Updating Profile...\');');
});
</script>

View file

@ -2109,17 +2109,17 @@ textarea.inputStyling {
.comments .comment {
display: flex;
align-items: stretch;
margin: 2px 0;
margin: 3px 0;
}
.comments .comment > .comment-avatar {
height: 58px;
width: 58px;
background: url("/content/pixel.png") no-repeat scroll left center / contain;
height: 60px;
width: 60px;
background: rgba(0, 0, 0, .2) url("/content/pixel.png") no-repeat scroll left center / contain;
flex-shrink: 0;
margin-right: 2px;
border-radius: 4px;
border: 1px solid #9475B2;
border: 0;
}
.comments .comment > .comment-pointer {
@ -2127,18 +2127,35 @@ textarea.inputStyling {
height: 0px;
border-style: solid;
border-width: 0px 15px 15px 0px;
border-color: transparent #FFF transparent transparent;
border-color: transparent #F6F6F6 transparent transparent;
margin-top: 10px;
}
.comments .comment > .comment-text {
border-radius: 0 5px 5px 5px;
.comments .comment > .comment-content {
border-radius: 5px;
border: 0;
min-height: 50px;
height: 50px;
flex-grow: 2;
padding: 5px;
font: 12px/20px "SegoeUI", "Segoe UI", sans-serif;
background: #FFF;
background: #F6F6F6;
}
.comments .comment > .comment-content > .comment-controls {
float: right;
}
.comments .comment > .comment-content > .comment-controls > ul > li {
float: left;
margin: 0 5px;
opacity: 0;
transition: .5s;
}
.comments .comment > .comment-content:hover > .comment-controls > ul > li,
.comments .comment > .comment-content > .comment-controls > ul > li.shown {
opacity: 1;
}
.comments .comment > .comment-submit {
@ -2148,10 +2165,19 @@ textarea.inputStyling {
width: 60px;
border-radius: 4px;
margin-left: 2px;
border: 0;
background: #9475B2;
color: #FFF;
font-size: 2em;
background: linear-gradient(0deg, #9475B2 10%, #C2AFFE 90%);
color: #306;
border: 1px solid #9475B2;
cursor: pointer;
}
.comments .comment > .comment-submit:hover {
background: linear-gradient(0deg, #9475B2 30%, #C2AFFE 70%);
}
.comments .comment > .comment-submit:active {
background: linear-gradient(180deg, #9475B2 30%, #C2AFFE 70%);
}
.comments ul {
@ -2163,11 +2189,11 @@ textarea.inputStyling {
}
.comments ul > li > ul .comment > .comment-avatar {
height: 48px;
width: 48px;
height: 50px;
width: 50px;
}
.comments ul > li > ul .comment > .comment-text {
.comments ul > li > ul .comment > .comment-content {
min-height: 40px;
height: 40px;
}

View file

@ -375,16 +375,7 @@ function ajaxBusyView(show, message, type) {
}
// Making a post request using AJAX
function ajaxPost(url, data) {
// Create a new XMLHttpRequest
var req = new XMLHttpRequest();
// Open a post request
req.open("POST", url, false);
// Set the request header to a form
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
function ajaxPost(url, data, callback) {
// Combine name and value with an = inbetween
var query = [];
@ -394,11 +385,50 @@ function ajaxPost(url, data) {
}
// Join the array and submit the request
req.send(query.join("&"));
// Join the array
query = query.join("&");
// If the HTTP resonse was 200 return the page
return (req.status === 200 ? req.responseText : null);
// Create XMLHttpRequest
var request = new XMLHttpRequest();
// Open a post request
request.open('POST', url, true);
// Wait for the readiness to change
request.onreadystatechange = function() {
// Wait for completion
if(request.readyState === 4) {
if(request.status === 200) {
callback.call(request.responseText);
} else {
ajaxBusyView(false);
notifyUI({
"title": "An internal server error occurred!",
"text": "If this problem persists please report this to the administrator.",
"img": "FONT:fa-chain-broken",
"timeout": 60000,
"sound": false
});
return null;
}
}
}
// Set headers
request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
// Submit the request
request.send(query);
}
@ -447,6 +477,26 @@ function prepareAjaxLink(linkId, callback, attrs) {
}
function prepareAjaxForm(formId, message, resetCaptchaOnFailure) {
// Get the form
var form = document.getElementById(formId);
// Create the AJAX form input
var createHidden = document.createElement('input');
// Set the attributes
createHidden.setAttribute('name', 'ajax');
createHidden.setAttribute('value', 'true');
createHidden.setAttribute('type', 'hidden');
form.appendChild(createHidden);
// Update form
form.setAttribute('onsubmit', 'submitPost(\''+ form.action +'\', formToObject(\''+ formId +'\'), true, \''+ (message ? message : 'Please wait...') +'\', '+ (resetCaptchaOnFailure ? 'true' : 'false') +');');
form.setAttribute('action', 'javascript:void(0);');
}
// Convert form to an object
function formToObject(formId) {
@ -517,25 +567,6 @@ function generateForm(formId, formAttr, formData, appendTo) {
}
// Enter substitute
function formEnterCatch(key, id) {
// 13 == Enter
if(key.which == 13) {
// Submit the form
document.getElementById(id).click();
// Return true if yeah
return true;
}
// Return false if not
return false;
}
// Submitting a form using an AJAX POST request
function submitPost(action, requestParts, busyView, msg, resetCaptchaOnFailure) {
@ -547,17 +578,29 @@ function submitPost(action, requestParts, busyView, msg, resetCaptchaOnFailure)
}
// Submit the AJAX request
var request = ajaxPost(action, requestParts).split('|');
var request = ajaxPost(action, requestParts, function() {
submitPostHandler(this, busyView, resetCaptchaOnFailure);
});
}
// Submitting a form using an AJAX POST request
function submitPostHandler(result, busyView, resetCaptchaOnFailure) {
// Split result
result = result.split('|');
// If using the busy view thing update the text displayed to the return of the request
if(busyView) {
ajaxBusyView(true, request[0], (request[1] == '1' ? 'ok' : 'fail'));
ajaxBusyView(true, result[0], (result[1] == '1' ? 'ok' : 'fail'));
}
// If request reset the recaptcha on failure
if(resetCaptchaOnFailure && request[1] != '1' && sakuraVars.recpatchaEnabled) {
if(resetCaptchaOnFailure && result[1] != '1' && sakuraVars.recaptchaEnabled) {
grecaptcha.reset();
@ -571,9 +614,9 @@ function submitPost(action, requestParts, busyView, msg, resetCaptchaOnFailure)
}
if(request[1] == '1') {
if(result[1] == '1') {
window.location = request[2];
window.location = result[2];
}

View file

@ -16,9 +16,6 @@ require_once str_replace(basename(__DIR__), '', dirname(__FILE__)) . '_sakura/sa
// Notifications
if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notifications']) {
// Set CORS header
header('Access-Control-Allow-Origin: *');
// Create the notification container array
$notifications = array();
@ -198,7 +195,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
];
break;
$continue = false;
}
// Check session variables
@ -215,7 +212,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
];
break;
$continue = false;
}
// Change settings
@ -541,7 +538,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
break;
// Profile
// Site Options
case 'options':
// Get profile fields and create storage var
$fields = Users::getOptionFields();
@ -575,6 +572,58 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
break;
// Usertitle
case 'usertitle':
// Check permissions
if (!$currentUser->checkPermission('SITE', 'CHANGE_USERTITLE')) {
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'You aren\'t allowed to change your usertitle.',
'success' => 0,
];
break;
}
// Check length
if (isset($_POST['usertitle']) ? (strlen($_POST['usertitle']) > 64) : false) {
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'Your usertitle is too long.',
'success' => 0,
];
break;
}
// Update database
Database::update(
'users',
[
[
'usertitle' => (isset($_POST['usertitle']) ? $_POST['usertitle'] : null),
],
[
'id' => [Session::$userId, '='],
],
]
);
// Set render data
$renderData['page'] = [
'redirect' => $redirect,
'message' => 'Updated your usertitle!',
'success' => 1,
];
break;
// Userpage
/*case 'userpage':
@ -892,7 +941,7 @@ if (Users::checkLogin()) {
],
'usertitle' => [
'title' => 'Username',
'title' => 'Usertitle',
'description' => [
'That little piece of text displayed under your username on your profile.',
@ -1103,6 +1152,11 @@ if (Users::checkLogin()) {
// Profile
case 'appearance.userpage':
break;
// Username changing
case 'account.username':
$renderData['difference'] = Main::timeElapsed($currentUser->data['lastunamechange']);
break;
}
// Print page contents