r20151101
Signed-off-by: Flashwave <me@flash.moe>
This commit is contained in:
parent
82ba292600
commit
d4063a994f
32 changed files with 225 additions and 253 deletions
|
@ -20,18 +20,12 @@ class Template
|
|||
private $template;
|
||||
private $templateName;
|
||||
private $templateOptions;
|
||||
private $fallback;
|
||||
private $fallbackName;
|
||||
private $fallbackOptions;
|
||||
|
||||
// Initialise templating engine and data
|
||||
public function __construct()
|
||||
{
|
||||
// Set template to default
|
||||
$this->setTemplate(Configuration::getConfig('site_style'));
|
||||
|
||||
// Set a fallback
|
||||
$this->setFallback(Configuration::getConfig('site_style'));
|
||||
}
|
||||
|
||||
// Set a template name
|
||||
|
@ -81,53 +75,6 @@ class Template
|
|||
$this->template->addExtension(new Twig_Extension_StringLoader());
|
||||
}
|
||||
|
||||
// Set a fallback
|
||||
private function setFallback($name)
|
||||
{
|
||||
// Assign config path to a variable so we don't have to type it out twice
|
||||
$confPath = ROOT . '_sakura/templates/' . $name . '/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
|
||||
$this->fallbackOptions = parse_ini_file($confPath, true);
|
||||
|
||||
// Make sure we're not using a manage template for the main site or the other way around
|
||||
if (defined('SAKURA_MANAGE') && (bool) $this->fallbackOptions['manage']['mode'] != (bool) SAKURA_MANAGE) {
|
||||
trigger_error('Incorrect template type', E_USER_ERROR);
|
||||
}
|
||||
|
||||
// Set variables
|
||||
$this->fallbackName = $name;
|
||||
|
||||
// Reinitialise
|
||||
$this->initFallback();
|
||||
}
|
||||
|
||||
// Initialise main fallback engine
|
||||
public function initFallback()
|
||||
{
|
||||
// Initialise Twig Filesystem Loader
|
||||
$twigLoader = new Twig_Loader_Filesystem(ROOT . '_sakura/templates/' . $this->fallbackName);
|
||||
|
||||
// Environment variable
|
||||
$twigEnv = [];
|
||||
|
||||
// Enable caching
|
||||
if (Configuration::getConfig('enable_tpl_cache')) {
|
||||
$twigEnv['cache'] = ROOT . 'cache';
|
||||
}
|
||||
|
||||
// And now actually initialise the templating engine
|
||||
$this->fallback = new Twig_Environment($twigLoader, $twigEnv);
|
||||
|
||||
// Load String template loader
|
||||
$this->fallback->addExtension(new Twig_Extension_StringLoader());
|
||||
}
|
||||
|
||||
// Set variables
|
||||
public function setVariables($vars)
|
||||
{
|
||||
|
@ -140,11 +87,7 @@ class Template
|
|||
try {
|
||||
return $this->template->render($file, $this->vars);
|
||||
} catch (\Exception $e) {
|
||||
try {
|
||||
return $this->fallback->render($file, $this->vars);
|
||||
} catch (\Exception $e) {
|
||||
trigger_error($e->getMessage(), E_USER_ERROR);
|
||||
}
|
||||
trigger_error($e->getMessage(), E_USER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
namespace Sakura;
|
||||
|
||||
// Define Sakura version
|
||||
define('SAKURA_VERSION', '20151031');
|
||||
define('SAKURA_VERSION', '20151101');
|
||||
define('SAKURA_VLABEL', 'Eminence');
|
||||
define('SAKURA_COLOUR', '#6C3082');
|
||||
define('SAKURA_STABLE', false);
|
||||
|
|
5
_sakura/templates/misaki/forum/forum.tpl
Normal file
5
_sakura/templates/misaki/forum/forum.tpl
Normal file
|
@ -0,0 +1,5 @@
|
|||
<div class="forumListing">
|
||||
{% for category in board.forums %}
|
||||
{% include 'forum/forumEntry.tpl' %}
|
||||
{% endfor %}
|
||||
</div>
|
45
_sakura/templates/misaki/forum/forumEntry.tpl
Normal file
45
_sakura/templates/misaki/forum/forumEntry.tpl
Normal file
|
@ -0,0 +1,45 @@
|
|||
{% if category.forums|length and category.forum|length %}
|
||||
<div class="forumCategory">
|
||||
<div class="forumCategoryHead">
|
||||
<div class="forumCategoryTitle">{% if category.forum.forum_type != 1 %}Subforums{% else %}<a href="{{ urls.format('FORUM_SUB', [category.forum.forum_id]) }}">{{ category.forum.forum_name }}</a>{% endif %}</div>
|
||||
<div class="forumCategoryDescription">{{ category.forum.forum_desc }}</div>
|
||||
</div>
|
||||
{% for forum in category.forums %}
|
||||
<div class="forumSubEntry">
|
||||
<a href="{% if forum.forum_type == 2 %}{{ forum.forum_link }}{% else %}{{ urls.format('FORUM_SUB', [forum.forum_id]) }}{% endif %}" class="forumSubIcon">
|
||||
<div class="forumIcon fa fa-3x {% if forum.forum_icon %}{{ forum.forum_icon }}{% else %}{% if forum.forum_type == 2 %}fa-chevron-circle-right{% elseif forum.forum_type == 1 %}fa-folder{% else %}fa-comments{% endif %}{% endif %}"></div>
|
||||
</a>
|
||||
<div class="forumSubTitle">
|
||||
<a href="{% if forum.forum_type == 2 %}{{ forum.forum_link }}{% else %}{{ urls.format('FORUM_SUB', [forum.forum_id]) }}{% endif %}" class="forumSubName">{{ forum.forum_name }}</a>
|
||||
<div class="forumSubDesc">
|
||||
{{ forum.forum_desc }}
|
||||
{% if board.forums[forum.forum_id]|length %}
|
||||
<ul class="forumSubSubforums">
|
||||
{% for forum in board.forums[forum.forum_id].forums %}
|
||||
<li><a href="{% if forum.forum_type == 2 %}{{ forum.forum_link }}{% else %}{{ urls.format('FORUM_SUB', [forum.forum_id]) }}{% endif %}" class="default">{{ forum.forum_name }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if forum.forum_type != 2 %}
|
||||
<div class="forumSubStats">
|
||||
<div class="forumSubTopics" title="Amount of topics in this forum.">{{ forum.topic_count }}</div>
|
||||
<div class="forumSubStatsSeperator">/</div>
|
||||
<div class="forumSubPosts" title="Amount of posts in this forum.">{{ forum.post_count }}</div>
|
||||
</div>
|
||||
<div class="forumSubReplies">
|
||||
<div>
|
||||
{% 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.user_id %}<a href="{{ urls.format('USER_PROFILE', [forum.last_poster.data.user_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_post.post_id]) }}#p{{ forum.last_post.post_id }}" class="default fa fa-tag"></a>
|
||||
{% else %}
|
||||
There are no posts in this forum.
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
10
_sakura/templates/misaki/forum/index.tpl
Normal file
10
_sakura/templates/misaki/forum/index.tpl
Normal file
|
@ -0,0 +1,10 @@
|
|||
{% extends 'global/master.tpl' %}
|
||||
|
||||
{% block title %}Forum Listing{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="homepage forums">
|
||||
{% include 'elements/statsHeader.tpl' %}
|
||||
{% include 'forum/forum.tpl' %}
|
||||
</div>
|
||||
{% endblock %}
|
1
_sakura/templates/misaki/forum/posting.tpl
Normal file
1
_sakura/templates/misaki/forum/posting.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
{% extends 'global/master.tpl' %}
|
0
_sakura/templates/misaki/forum/topicEntry.tpl
Normal file
0
_sakura/templates/misaki/forum/topicEntry.tpl
Normal file
1
_sakura/templates/misaki/forum/viewforum.tpl
Normal file
1
_sakura/templates/misaki/forum/viewforum.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
{% extends 'global/master.tpl' %}
|
1
_sakura/templates/misaki/forum/viewtopic.tpl
Normal file
1
_sakura/templates/misaki/forum/viewtopic.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
{% extends 'global/master.tpl' %}
|
|
@ -85,8 +85,6 @@
|
|||
<li><a target="_blank" title="Flashii on Twitter" class="fa fa-twitter" href="https://twitter.com/_flashii"></a></li>
|
||||
<li><a target="_blank" title="Flashii on YouTube" class="fa fa-youtube-play" href="https://youtube.com/user/flashiinet"></a></li>
|
||||
<li><a target="_blank" title="Flashii on Steam" class="fa fa-steam" href="https://steamcommunity.com/groups/flashiinet"></a></li>
|
||||
<li><a target="_blank" title="Circlestorm on BitBucket" class="fa fa-bitbucket" href="https://bitbucket.org/circlestorm"></a></li>
|
||||
<li><a target="_blank" title="Flashii on osu!" class="fa fa-dot-circle-o" href="https://osu.ppy.sh/#"></a></li>
|
||||
<li><a title="Subscribe to the news page feed" class="fa fa-rss" href="/news.xml"></a></li>
|
||||
</ul>
|
||||
<div class="clear"></div>
|
||||
|
@ -126,7 +124,7 @@
|
|||
</ul>
|
||||
</div>
|
||||
{% block content %}
|
||||
<h1>{{ php.self }} is now printing!</h1>
|
||||
<div style="text-align: center; font-family: 'Exo2-0-LightItalic', sans-serif; font-size: 3em; line-height: 1.5em; margin: 10px auto">This template doesn't exist (yet)!<br />Switch back to Yuuno via the User Settings to view this page!</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -135,7 +133,7 @@
|
|||
<div class="ft-logo"></div>
|
||||
<div class="ft-text">
|
||||
<div>Copyright © 2013-2015 <a href="http://flash.moe/" target="_blank">Flashwave</a>, <a href="http://circlestorm.net/" target="_blank">et al</a>.</div>
|
||||
<div><a href="{{ urls.format('INFO_PAGE', ['terms']) }}">Terms of Service</a> | <a href="{{ urls.format('INFO_PAGE', ['contact']) }}">Contact</a> | <a href="{{ urls.format('SITE_FAQ') }}">FAQ</a> | <a href="{{ urls.format('INFO_PAGE', ['rules']) }}">Rules</a> | <a href="{{ urls.format('CHANGELOG') }}">Changelog</a> | <a href="https://fiistat.us/">Status</a></div>
|
||||
<div><a href="{{ urls.format('INFO_PAGE', ['terms']) }}">Terms of Service</a> | <a href="{{ urls.format('INFO_PAGE', ['contact']) }}">Contact</a> | <a href="{{ urls.format('SITE_FAQ') }}">FAQ</a> | <a href="{{ urls.format('INFO_PAGE', ['rules']) }}">Rules</a> | <a href="https://sakura.flash.moe/">Changelog</a> | <a href="https://fiistat.us/">Status</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
1
_sakura/templates/misaki/group/index.tpl
Normal file
1
_sakura/templates/misaki/group/index.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
{% extends 'global/master.tpl' %}
|
1
_sakura/templates/misaki/main/authenticate.tpl
Normal file
1
_sakura/templates/misaki/main/authenticate.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
{% extends 'global/master.tpl' %}
|
1
_sakura/templates/misaki/main/banned.tpl
Normal file
1
_sakura/templates/misaki/main/banned.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
{% extends 'global/master.tpl' %}
|
1
_sakura/templates/misaki/main/faq.tpl
Normal file
1
_sakura/templates/misaki/main/faq.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
{% extends 'global/master.tpl' %}
|
1
_sakura/templates/misaki/main/forgotpassword.tpl
Normal file
1
_sakura/templates/misaki/main/forgotpassword.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
{% extends 'global/master.tpl' %}
|
1
_sakura/templates/misaki/main/memberlist.tpl
Normal file
1
_sakura/templates/misaki/main/memberlist.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
{% extends 'global/master.tpl' %}
|
|
@ -0,0 +1 @@
|
|||
{% extends 'global/master.tpl' %}
|
1
_sakura/templates/misaki/main/premiumcomplete.tpl
Normal file
1
_sakura/templates/misaki/main/premiumcomplete.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
{% extends 'global/master.tpl' %}
|
1
_sakura/templates/misaki/main/report.tpl
Normal file
1
_sakura/templates/misaki/main/report.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
{% extends 'global/master.tpl' %}
|
1
_sakura/templates/misaki/main/support.tpl
Normal file
1
_sakura/templates/misaki/main/support.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
{% extends 'global/master.tpl' %}
|
1
_sakura/templates/misaki/main/supporttracker.tpl
Normal file
1
_sakura/templates/misaki/main/supporttracker.tpl
Normal file
|
@ -0,0 +1 @@
|
|||
{% extends 'global/master.tpl' %}
|
0
_sakura/templates/misaki/profile/friends.tpl
Normal file
0
_sakura/templates/misaki/profile/friends.tpl
Normal file
0
_sakura/templates/misaki/profile/groups.tpl
Normal file
0
_sakura/templates/misaki/profile/groups.tpl
Normal file
0
_sakura/templates/misaki/profile/posts.tpl
Normal file
0
_sakura/templates/misaki/profile/posts.tpl
Normal file
0
_sakura/templates/misaki/profile/threads.tpl
Normal file
0
_sakura/templates/misaki/profile/threads.tpl
Normal file
|
@ -29,7 +29,7 @@
|
|||
</tr>
|
||||
</tfoot>
|
||||
<tbody>
|
||||
{% for topic in board.topics %}
|
||||
{% for topic in board.topics[currentPage] %}
|
||||
{% include 'forum/topicEntry.tpl' %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<div class="head">{{ forum.forum.forum_name }} / {{ topic.topic_title }}</div>
|
||||
{% include 'forum/forumBtns.tpl' %}
|
||||
<table class="posts">
|
||||
{% for post in posts %}
|
||||
{% for post in posts[currentPage] %}
|
||||
<tr class="post" id="p{{ post.post_id }}">
|
||||
<td class="userpanel">
|
||||
{% if not post.user.checkPermission('SITE', 'DEACTIVATED') or post.user.checkPermission('SITE', 'RESTRICTED') %}<a href="{{ urls.format('USER_PROFILE', [post.user.data.user_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>
|
||||
|
|
0
_sakura/templates/yuuno/profile/groups.tpl
Normal file
0
_sakura/templates/yuuno/profile/groups.tpl
Normal file
|
@ -189,6 +189,10 @@ a:active {
|
|||
text-align: right;
|
||||
}
|
||||
|
||||
#footer > .inner a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Site header
|
||||
*/
|
||||
|
@ -660,7 +664,7 @@ a:active {
|
|||
flex-shrink: 1;
|
||||
background: rgba(148, 117, 178, .2);
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, .75);
|
||||
margin: 5px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.homepage .frontStats > div > div {
|
||||
|
@ -711,3 +715,126 @@ a:active {
|
|||
.news-post > .news-content > .news-text {
|
||||
padding: 3px 4px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Forums
|
||||
*/
|
||||
.forums .forumListing .forumCategory {
|
||||
margin: 10px;
|
||||
padding: 5px;
|
||||
background: #3A2E44;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, .75);
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumCategoryHead {
|
||||
color: #FFF;
|
||||
padding: 5px;
|
||||
text-shadow: 1px 1px 2px rgba(0, 0, 0, .75);
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumCategoryHead .forumCategoryTitle {
|
||||
font-size: 2em;
|
||||
line-height: .8em;
|
||||
padding-bottom: 5px;
|
||||
font-family: "Exo2-0-LightItalic", sans-serif;
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumCategoryHead .forumCategoryDescription {
|
||||
font-size: .8em;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumCategoryHead a {
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumSubEntry {
|
||||
border-top: 1px solid #231C29;
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
transition: .2s;
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumSubEntry:hover {
|
||||
background: #231C29;
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumSubEntry .forumSubIcon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumSubEntry .forumSubIcon .forumIcon {
|
||||
transition: .1s;
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumSubEntry:hover .forumSubIcon .forumIcon {
|
||||
font-size: 3.5em;
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumSubEntry a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumSubTitle {
|
||||
flex-grow: 2;
|
||||
border-right: 1px solid #231C29;
|
||||
text-shadow: 1px 1px 2px rgba(0, 0, 0, .75);
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumSubEntry:hover .forumSubTitle {
|
||||
border-right: 1px solid #3A2E44;
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumSubTitle .forumSubName {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumSubStats {
|
||||
flex-shrink: 0;
|
||||
font-family: "Exo2-0-LightItalic", sans-serif;
|
||||
padding: 0 10px;
|
||||
min-width: 70px;
|
||||
text-shadow: 1px 1px 2px rgba(0, 0, 0, .75);
|
||||
line-height: .5em;
|
||||
border-right: 1px solid #231C29;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumSubEntry:hover .forumSubStats {
|
||||
border-right: 1px solid #3A2E44;
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumSubStats div {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumSubStats .forumSubTopics {
|
||||
font-size: 1.5em;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumSubStats .forumSubStatsSeperator {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumSubStats .forumSubPosts {
|
||||
font-size: .8em;
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
.forums .forumListing .forumCategory .forumSubReplies {
|
||||
padding: 0 5px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
line-height: 1.2em;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
|
||||
// Get or set cookies
|
||||
function cookieData(action, name, data) {
|
||||
|
||||
switch(action) {
|
||||
|
||||
case 'get':
|
||||
return (result = new RegExp('(^|; )' + encodeURIComponent(name) + '=([^;]*)').exec(document.cookie)) ? result[2] : '';
|
||||
|
||||
|
@ -16,21 +14,16 @@ function cookieData(action, name, data) {
|
|||
|
||||
default:
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Get the current unix/epoch timestamp
|
||||
function epochTime() {
|
||||
|
||||
return Math.floor(Date.now() / 1000);
|
||||
|
||||
}
|
||||
|
||||
// Create a notification box
|
||||
function notifyUI(content) {
|
||||
|
||||
// Grab the container and create an ID
|
||||
var container = document.getElementById('notifications');
|
||||
var identifier = 'sakura-notification-' + Date.now();
|
||||
|
@ -100,7 +93,6 @@ function notifyUI(content) {
|
|||
|
||||
// Play sound if requested
|
||||
if(content.sound > 0) {
|
||||
|
||||
// Create sound element and mp3 and ogg sources
|
||||
var sound = document.createElement('audio');
|
||||
var soundMP3 = document.createElement('source');
|
||||
|
@ -118,27 +110,20 @@ function notifyUI(content) {
|
|||
|
||||
// Play the sound
|
||||
sound.play();
|
||||
|
||||
}
|
||||
|
||||
// If keepalive is 0 keep the notification open "forever" (until the user closes it or changes the page)
|
||||
if(content.timeout > 0) {
|
||||
|
||||
// Set set a timeout and execute notifyClose() after amount of milliseconds specified
|
||||
setTimeout(function() {
|
||||
|
||||
// Use the later defined notifyClose function
|
||||
notifyClose(identifier);
|
||||
|
||||
}, content.timeout);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Closing a notification box
|
||||
function notifyClose(id) {
|
||||
|
||||
// Get the element and assign it to a variable
|
||||
var element = document.getElementById(id);
|
||||
|
||||
|
@ -147,35 +132,25 @@ function notifyClose(id) {
|
|||
|
||||
// Remove the element after 500 milliseconds (animation takes 400)
|
||||
setTimeout(function() {
|
||||
|
||||
// Use the later defined removeId function
|
||||
removeId(id);
|
||||
|
||||
}, 410);
|
||||
|
||||
}
|
||||
|
||||
// Opening a link to a notifcated thing (what even)
|
||||
function notifyOpen(id) {
|
||||
|
||||
var sakuraHref = document.getElementById(id).getAttribute('sakurahref');
|
||||
|
||||
if(typeof sakuraHref !== 'undefined') {
|
||||
|
||||
window.location = sakuraHref;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Request notifications
|
||||
function notifyRequest(session) {
|
||||
|
||||
// Check if the document isn't hidden
|
||||
if(document.hidden) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Create XMLHttpRequest and notifyURL
|
||||
|
@ -184,19 +159,15 @@ function notifyRequest(session) {
|
|||
|
||||
// Wait for the ready state to change
|
||||
notificationWatcher.onreadystatechange = function() {
|
||||
|
||||
// Wait for it to reach the "complete" stage
|
||||
if(notificationWatcher.readyState === 4) {
|
||||
|
||||
// Continue if the HTTP return was 200
|
||||
if(notificationWatcher.status === 200) {
|
||||
|
||||
// Assign the JSON parsed content to a variable
|
||||
var notifyGet = JSON.parse(notificationWatcher.responseText);
|
||||
|
||||
// If nothing was set stop
|
||||
if(typeof notifyGet == 'undefined') {
|
||||
|
||||
// Tell the user something went wrong...
|
||||
notifyUI({
|
||||
"title": "An error occurred!",
|
||||
|
@ -208,18 +179,13 @@ function notifyRequest(session) {
|
|||
|
||||
// ...then prevent the function from contiuing
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Go over every return notification and pass the object to it
|
||||
for(var notifyID in notifyGet) {
|
||||
|
||||
notifyUI(notifyGet[notifyID]);
|
||||
|
||||
}
|
||||
|
||||
} else if((notificationWatcher.status + '').substring(0, 1) == '5') {
|
||||
|
||||
// ELse tell the user there was an internal server error...
|
||||
notifyUI({
|
||||
"title": "An internal server error occurred!",
|
||||
|
@ -228,52 +194,39 @@ function notifyRequest(session) {
|
|||
"timeout": 60000,
|
||||
"sound": false
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Make the request
|
||||
notificationWatcher.open('GET', notifyURL, true);
|
||||
notificationWatcher.send();
|
||||
|
||||
}
|
||||
|
||||
// Removing all elements with a certain class
|
||||
function removeClass(className) {
|
||||
|
||||
// Get the elements
|
||||
var objectCont = document.getElementsByClassName(className);
|
||||
|
||||
// Use a while loop instead of a for loop (Array keys change) to remove each element
|
||||
while(objectCont.length > 0) {
|
||||
|
||||
objectCont[0].parentNode.removeChild(objectCont[0]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Removing an element by ID
|
||||
function removeId(id) {
|
||||
|
||||
// Get the element
|
||||
var objectCont = document.getElementById(id);
|
||||
|
||||
// If the element exists use the parent node to remove it
|
||||
if(typeof(objectCont) != "undefined" && objectCont !== null) {
|
||||
|
||||
objectCont.parentNode.removeChild(objectCont);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Show the full-page busy window
|
||||
function ajaxBusyView(show, message, type) {
|
||||
|
||||
// Get elements
|
||||
var busyCont = document.getElementById('ajaxBusy');
|
||||
var busyStat = document.getElementById('ajaxStatus');
|
||||
|
@ -283,7 +236,6 @@ function ajaxBusyView(show, message, type) {
|
|||
|
||||
// Select the proper icon
|
||||
switch(type) {
|
||||
|
||||
case 'ok':
|
||||
busyAnimIco = 'fa fa-check fa-4x';
|
||||
break;
|
||||
|
@ -294,15 +246,12 @@ function ajaxBusyView(show, message, type) {
|
|||
default:
|
||||
busyAnimIco = 'fa fa-refresh fa-spin fa-4x';
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// If requested to show the window build it
|
||||
if(show) {
|
||||
|
||||
// Make sure it doesn't exist already
|
||||
if(busyCont === null) {
|
||||
|
||||
// Container
|
||||
var createBusyCont = document.createElement('div');
|
||||
createBusyCont.className = 'ajax-busy';
|
||||
|
@ -330,7 +279,6 @@ function ajaxBusyView(show, message, type) {
|
|||
busyCont = document.getElementById('ajaxBusy');
|
||||
busyStat = document.getElementById('ajaxStatus');
|
||||
busyAnim = document.getElementById('ajaxAnimate');
|
||||
|
||||
} // If the container already exists just continue and update the elements
|
||||
|
||||
// Alter the icon
|
||||
|
@ -338,51 +286,34 @@ function ajaxBusyView(show, message, type) {
|
|||
|
||||
// Change the message
|
||||
busyStat.innerHTML = (message === null ? 'Unknown' : message);
|
||||
|
||||
} else { // If show is false remove the element...
|
||||
|
||||
// ...but just do nothing if the container doesn't exist
|
||||
if(busyCont !== null) {
|
||||
|
||||
// Create the fadeout with a 10ms interval
|
||||
var fadeOut = setInterval(function() {
|
||||
|
||||
// Set an opacity if it doesn't exist yet
|
||||
if(busyCont.style.opacity === null || busyCont.style.opacity === "") {
|
||||
|
||||
busyCont.style.opacity = 1;
|
||||
|
||||
}
|
||||
|
||||
// If the value isn't 0 yet start subtract .1 from the opacity
|
||||
if(busyCont.style.opacity > 0) {
|
||||
|
||||
busyCont.style.opacity = busyCont.style.opacity - 0.1;
|
||||
|
||||
} else { // When we've reached 0 remove the container element and clear the fadeout interval
|
||||
|
||||
removeId('ajaxBusy');
|
||||
clearInterval(fadeOut);
|
||||
|
||||
}
|
||||
|
||||
}, 10);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Making a post request using AJAX
|
||||
function ajaxPost(url, data, callback) {
|
||||
|
||||
// Combine name and value with an = inbetween
|
||||
var query = [];
|
||||
for(var i in data) {
|
||||
|
||||
query.push(encodeURIComponent(i) +"="+ encodeURIComponent(data[i]));
|
||||
|
||||
}
|
||||
|
||||
// Join the array
|
||||
|
@ -396,16 +327,11 @@ function ajaxPost(url, data, callback) {
|
|||
|
||||
// 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({
|
||||
|
@ -417,11 +343,8 @@ function ajaxPost(url, data, callback) {
|
|||
});
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Set headers
|
||||
|
@ -429,20 +352,16 @@ function ajaxPost(url, data, callback) {
|
|||
|
||||
// Submit the request
|
||||
request.send(query);
|
||||
|
||||
}
|
||||
|
||||
// Convert href attribute to an object
|
||||
function prepareAjaxLink(linkId, callback, attrs) {
|
||||
|
||||
// Get the elements
|
||||
var link = typeof linkId === 'object' ? linkId : document.getElementById(linkId);
|
||||
|
||||
// Catch null
|
||||
if(link == null) {
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Get the href value
|
||||
|
@ -459,13 +378,11 @@ function prepareAjaxLink(linkId, callback, attrs) {
|
|||
|
||||
// Split the name and values of the variables
|
||||
for(var key in variablesNotSplit) {
|
||||
|
||||
// Split name and value
|
||||
var newVar = variablesNotSplit[key].split('=');
|
||||
|
||||
// Push it into the object
|
||||
variables[newVar[0]] = newVar[1];
|
||||
|
||||
}
|
||||
|
||||
// Add ajax=true
|
||||
|
@ -474,11 +391,9 @@ function prepareAjaxLink(linkId, callback, attrs) {
|
|||
// Update link attributes
|
||||
link.setAttribute('href', 'javascript:void(0);');
|
||||
link.setAttribute('onclick', callback +'(\''+ action +'\', JSON.parse(\''+ JSON.stringify(variables) +'\')'+ (typeof attrs != 'undefined' ? attrs : '') +');');
|
||||
|
||||
}
|
||||
|
||||
function prepareAjaxForm(formId, message, resetCaptchaOnFailure) {
|
||||
|
||||
// Get the form
|
||||
var form = document.getElementById(formId);
|
||||
|
||||
|
@ -494,12 +409,10 @@ function prepareAjaxForm(formId, message, resetCaptchaOnFailure) {
|
|||
// 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) {
|
||||
|
||||
// Get form data
|
||||
var form = document.getElementById(formId);
|
||||
|
||||
|
@ -511,23 +424,17 @@ function formToObject(formId) {
|
|||
|
||||
// Sort children and make them ready for submission
|
||||
for(var i in children) {
|
||||
|
||||
if(typeof children[i] == 'object') {
|
||||
|
||||
requestParts[children[i].name] = ((typeof children[i].type !== "undefined" && children[i].type.toLowerCase() == "checkbox") ? (children[i].checked ? 1 : 0) : children[i].value);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Return the object
|
||||
return requestParts;
|
||||
|
||||
}
|
||||
|
||||
// Quickly building a form for god knows what reason
|
||||
function generateForm(formId, formAttr, formData, appendTo) {
|
||||
|
||||
// Create form elements and assign ID
|
||||
var i;
|
||||
var form = document.createElement('form');
|
||||
|
@ -535,53 +442,39 @@ function generateForm(formId, formAttr, formData, appendTo) {
|
|||
|
||||
// Set additional attributes
|
||||
if(formAttr !== null) {
|
||||
|
||||
for(i in formAttr) {
|
||||
|
||||
form.setAttribute(i, formAttr[i]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Generate input elements
|
||||
for(i in formData) {
|
||||
|
||||
var disposableVar = document.createElement('input');
|
||||
disposableVar.setAttribute('type', 'hidden');
|
||||
disposableVar.setAttribute('name', i);
|
||||
disposableVar.setAttribute('value', formData[i]);
|
||||
form.appendChild(disposableVar);
|
||||
|
||||
}
|
||||
|
||||
// Append to another element if requested
|
||||
if(appendTo !== null) {
|
||||
|
||||
document.getElementById(appendTo).appendChild(form);
|
||||
|
||||
}
|
||||
|
||||
// Return the completed form
|
||||
return form;
|
||||
|
||||
}
|
||||
|
||||
// Submitting a form using an AJAX POST request
|
||||
function submitPost(action, requestParts, busyView, msg, resetCaptchaOnFailure) {
|
||||
|
||||
// If requested display the busy thing
|
||||
if(busyView) {
|
||||
|
||||
ajaxBusyView(true, msg, 'busy');
|
||||
|
||||
}
|
||||
|
||||
// Submit the AJAX request
|
||||
var request = ajaxPost(action, requestParts, function() {
|
||||
|
||||
submitPostHandler(this, busyView, resetCaptchaOnFailure);
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
@ -594,144 +487,114 @@ function submitPostHandler(result, busyView, resetCaptchaOnFailure) {
|
|||
|
||||
// If using the busy view thing update the text displayed to the return of the request
|
||||
if(busyView) {
|
||||
|
||||
ajaxBusyView(true, result[0], (result[1] == '1' ? 'ok' : 'fail'));
|
||||
|
||||
}
|
||||
|
||||
// If request reset the recaptcha on failure
|
||||
if(resetCaptchaOnFailure && result[1] != '1' && sakuraVars.recaptchaEnabled != '0') {
|
||||
|
||||
grecaptcha.reset();
|
||||
|
||||
}
|
||||
|
||||
setTimeout(function(){
|
||||
|
||||
if(busyView) {
|
||||
|
||||
ajaxBusyView(false);
|
||||
|
||||
}
|
||||
|
||||
if(result[1] == '1') {
|
||||
|
||||
window.location = result[2];
|
||||
|
||||
}
|
||||
|
||||
}, 2000);
|
||||
|
||||
}
|
||||
|
||||
// Encode UTF-8
|
||||
function utf8_encode(str) {
|
||||
|
||||
return unescape(encodeURIComponent(str));
|
||||
|
||||
}
|
||||
|
||||
// Decode UTF-8
|
||||
function utf8_decode(str) {
|
||||
|
||||
return decodeURIComponent(escape(str));
|
||||
|
||||
}
|
||||
|
||||
// Calculate the amount of unique characters in a string
|
||||
function uniqueChars(str) {
|
||||
|
||||
// Create storage array and count var
|
||||
var usedChars = [];
|
||||
var count = 0;
|
||||
|
||||
// Count the amount of unique characters
|
||||
for(var i = 0; i < str.length; i++) {
|
||||
|
||||
// Check if we already counted this character
|
||||
if(usedChars.indexOf(str[i]) == -1) {
|
||||
|
||||
// Push the character into the used array
|
||||
usedChars.push(str[i]);
|
||||
|
||||
// Up the count
|
||||
count++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Return the count
|
||||
return count;
|
||||
|
||||
}
|
||||
|
||||
// Alternative for Math.log2() since it's still experimental
|
||||
function log2(num) {
|
||||
|
||||
return Math.log(num) / Math.log(2);
|
||||
|
||||
}
|
||||
|
||||
// Calculate password entropy
|
||||
function pwdEntropy(pwd) {
|
||||
|
||||
// Decode utf-8 chars
|
||||
pwd = utf8_decode(pwd);
|
||||
|
||||
// Count the amount of unique characters in the password and calculate the entropy
|
||||
return uniqueChars(pwd) * log2(256);
|
||||
|
||||
}
|
||||
|
||||
// Check if password is within the minimum entropy value
|
||||
function checkPwdEntropy(pwd) {
|
||||
|
||||
return (pwdEntropy(pwd) >= sakuraVars.minPwdEntropy);
|
||||
|
||||
}
|
||||
|
||||
// Check the length of a string
|
||||
function checkStringLength(str, min, max) {
|
||||
|
||||
// Get length of string
|
||||
var len = str.length;
|
||||
|
||||
// Check if it meets the minimum
|
||||
if(len < min)
|
||||
if(len < min) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if it meets the maximum
|
||||
if(len > max)
|
||||
if(len > max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If it passes both return true
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// Validate email address formats
|
||||
function validateEmail(email) {
|
||||
|
||||
// The regex
|
||||
var re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,48})+$/;
|
||||
// is of fix
|
||||
|
||||
// Test it (which returns true or false)
|
||||
return re.test(email);
|
||||
|
||||
}
|
||||
|
||||
// Check registration variables
|
||||
function registerVarCheck(id, mode, option) {
|
||||
|
||||
// Get the element we're working with
|
||||
var input = document.getElementById(id);
|
||||
var check = null;
|
||||
|
||||
// Use the proper mode
|
||||
switch(mode) {
|
||||
|
||||
case 'confirmpw':
|
||||
option = document.getElementById(option);
|
||||
check = input.value === option.value;
|
||||
|
@ -749,26 +612,19 @@ function registerVarCheck(id, mode, option) {
|
|||
default:
|
||||
check = checkStringLength(input.value, sakuraVars.minUserLen, sakuraVars.maxUserLen);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if(input.className.indexOf(check ? 'green' : 'red') < 0) {
|
||||
|
||||
input.className = input.className + ' ' + (check ? 'green' : 'red');
|
||||
|
||||
}
|
||||
|
||||
if(input.className.indexOf(check ? 'red' : 'green') > 0) {
|
||||
|
||||
input.className = input.className.replace(check ? 'red' : 'green', '');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Initialising the element parallax functionality
|
||||
function initialiseParallax(id) {
|
||||
|
||||
// Assign the element to a variable
|
||||
var parallax = document.getElementById(id);
|
||||
|
||||
|
@ -788,12 +644,10 @@ function initialiseParallax(id) {
|
|||
parallax.style.right = convertParallaxPositionValue(e.clientX, false, true) + 'px';
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Converting the position value of the mouseover to a pixel value
|
||||
function convertParallaxPositionValue(pos, dir, neg) {
|
||||
|
||||
// Get the body element
|
||||
var body = document.getElementsByTagName('body')[0];
|
||||
|
||||
|
@ -802,9 +656,7 @@ function convertParallaxPositionValue(pos, dir, neg) {
|
|||
|
||||
// If someone decided to fuck with the inputs reset it to 0%
|
||||
if(position < 0 || position > 100) {
|
||||
|
||||
position = 0;
|
||||
|
||||
}
|
||||
|
||||
// Do the first maths
|
||||
|
@ -812,9 +664,7 @@ function convertParallaxPositionValue(pos, dir, neg) {
|
|||
|
||||
// If the negative flag is set inverse the number
|
||||
if(neg) {
|
||||
|
||||
position = -position;
|
||||
|
||||
}
|
||||
|
||||
// Subtract another 2.5 to make the element not go all over the place
|
||||
|
@ -822,12 +672,10 @@ function convertParallaxPositionValue(pos, dir, neg) {
|
|||
|
||||
// Return the proper position value
|
||||
return position;
|
||||
|
||||
}
|
||||
|
||||
// Smooth scrolling
|
||||
function scrollToTop() {
|
||||
|
||||
// Get the current position
|
||||
var windowY = window.pageYOffset - 100;
|
||||
|
||||
|
@ -836,11 +684,8 @@ function scrollToTop() {
|
|||
|
||||
// Keep executing this function till we're at the top
|
||||
if(windowY + 1 > 0) {
|
||||
|
||||
setTimeout(function(){scrollToTop();}, 10);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function replaceTag(tag) {
|
||||
|
@ -852,7 +697,6 @@ function safeTagsReplace(str) {
|
|||
}
|
||||
|
||||
function commentReply(id, session, category, action, avatar) {
|
||||
|
||||
// Find subject post
|
||||
var replyingTo = document.getElementById('comment-' + id);
|
||||
|
||||
|
@ -952,20 +796,17 @@ function commentReply(id, session, category, action, avatar) {
|
|||
|
||||
// Prepare AJAX submission
|
||||
prepareAjaxForm(replyForm.id, 'Replying...');
|
||||
|
||||
}
|
||||
|
||||
// Formatting money
|
||||
Number.prototype.formatMoney = function(c, d, t) {
|
||||
|
||||
var n = this,
|
||||
c = isNaN(c = Math.abs(c)) ? 2 : c,
|
||||
d = d == undefined ? "." : d,
|
||||
t = t == undefined ? "," : t,
|
||||
s = n < 0 ? "-" : "",
|
||||
i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "",
|
||||
j = (j = i.length) > 3 ? j % 3 : 0;
|
||||
|
||||
return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
|
||||
Number.prototype.formatMoney = function(u, c, k) {
|
||||
var f = this,
|
||||
u = isNaN(u = Math.abs(u)) ? 2 : u,
|
||||
c = c == undefined ? "." : c,
|
||||
k = k == undefined ? "," : k,
|
||||
i = f < 0 ? "-" : "",
|
||||
n = parseInt(f = Math.abs(+f || 0).toFixed(u)) + "",
|
||||
g = (g = n.length) > 3 ? g % 3 : 0;
|
||||
|
||||
return i + (g ? n.substr(0, g) + k : "") + n.substr(g).replace(/(\c{3})(?=\c)/g, "$1" + k) + (u ? c + Math.abs(f - n).toFixed(u).slice(2) : "");
|
||||
};
|
||||
|
|
|
@ -16,10 +16,8 @@ $forum = Forum::getForum(isset($_GET['f']) ? $_GET['f'] : 0);
|
|||
if (!$forum) {
|
||||
// Set render data
|
||||
$renderData['page'] = [
|
||||
|
||||
'title' => 'Information',
|
||||
'message' => 'The subforum you tried to access does not exist.',
|
||||
|
||||
];
|
||||
|
||||
// Print template
|
||||
|
@ -31,11 +29,9 @@ if (!$forum) {
|
|||
if ($forum['forum']['forum_type'] === 2) {
|
||||
// Set render data
|
||||
$renderData['page'] = [
|
||||
|
||||
'title' => 'Information',
|
||||
'message' => 'The forum you tried to access is a link. You\'re being redirected.',
|
||||
'redirect' => $forum['forum']['forum_link'],
|
||||
|
||||
];
|
||||
|
||||
// Print template
|
||||
|
@ -44,17 +40,14 @@ if ($forum['forum']['forum_type'] === 2) {
|
|||
}
|
||||
|
||||
$renderData['board'] = [
|
||||
|
||||
'forums' => [
|
||||
|
||||
$forum,
|
||||
|
||||
],
|
||||
'topics' => Forum::getTopics($forum['forum']['forum_id']),
|
||||
'topics' => array_chunk($forum['topics'], 25, true),
|
||||
'viewforum' => true,
|
||||
'viewtopic' => false,
|
||||
|
||||
];
|
||||
$renderData['currentPage'] = isset($_GET['page']) && ($_GET['page'] - 1) >= 0 ? $_GET['page'] - 1 : 0;
|
||||
|
||||
// Print page contents
|
||||
print Templates::render('forum/viewforum.tpl', $renderData);
|
||||
|
|
|
@ -20,9 +20,7 @@ $topic = Forum::getTopic(
|
|||
if (!$topic) {
|
||||
// Set render data
|
||||
$renderData['page'] = [
|
||||
|
||||
'message' => 'The topic you tried to access does not exist.',
|
||||
|
||||
];
|
||||
|
||||
// Print template
|
||||
|
@ -32,14 +30,12 @@ if (!$topic) {
|
|||
|
||||
// Set additional render data
|
||||
$renderData = array_merge($renderData, $topic, [
|
||||
|
||||
'board' => [
|
||||
|
||||
'viewforum' => false,
|
||||
'viewtopic' => true,
|
||||
|
||||
],
|
||||
|
||||
'posts' => array_chunk($topic['posts'], 10, true),
|
||||
'currentPage' => isset($_GET['page']) && ($_GET['page'] - 1) >= 0 ? $_GET['page'] - 1 : 0,
|
||||
]);
|
||||
|
||||
// Print page contents
|
||||
|
|
Reference in a new issue