r20160219
This commit is contained in:
parent
bbfd22d14d
commit
7c83d5c78d
29 changed files with 1103 additions and 1340 deletions
20
cron.php
20
cron.php
|
@ -24,23 +24,25 @@ define('SAKURA_CRON', true);
|
||||||
require_once 'sakura.php';
|
require_once 'sakura.php';
|
||||||
|
|
||||||
// Clean expired sessions
|
// Clean expired sessions
|
||||||
Database::delete('sessions', [
|
$cleanSessions = DB::prepare('DELETE FROM `{prefix}sessions` WHERE `session_expire` < :time AND `session_remember` != 1');
|
||||||
'session_expire' => [time(), '<'],
|
$cleanSessions->execute([
|
||||||
'session_remember' => ['1', '!='],
|
'time' => time(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Delete notifications that are older than a month but not unread
|
// Delete notifications that are older than a month but not unread
|
||||||
Database::delete('notifications', [
|
$cleanAlerts = DB::prepare('DELETE FROM `{prefix}notifications` WHERE `alert_timestamp` < :time AND `alert_read` = 1');
|
||||||
'alert_timestamp' => [(time() - 109500), '<'],
|
$cleanAlerts->execute([
|
||||||
'alert_read' => ['1', '='],
|
'time' => (time() - 109500),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Get expired premium accounts
|
// Get expired premium accounts
|
||||||
$expiredPremium = Database::fetch('premium', true, [
|
$expiredPremium = DB::prepare('SELECT * FROM `{prefix}premium` WHERE `premium_expire` < :time');
|
||||||
'premium_expire' => [time(), '<'],
|
$expiredPremium->execute([
|
||||||
|
'time' => time(),
|
||||||
]);
|
]);
|
||||||
|
$expiredPremium = $expiredPremium->fetchAll();
|
||||||
|
|
||||||
// Process expired premium accounts, make this not stupid in the future
|
// Process expired premium accounts, make this not stupid in the future
|
||||||
foreach ($expiredPremium as $expired) {
|
foreach ($expiredPremium as $expired) {
|
||||||
Users::updatePremiumMeta($expired['user_id']);
|
Users::updatePremiumMeta($expired->user_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,11 @@ class ActionCode
|
||||||
$code = uniqid();
|
$code = uniqid();
|
||||||
|
|
||||||
// Insert it
|
// Insert it
|
||||||
Database::insert('actioncodes', [
|
DB::prepare('INSERT INTO `{prefix}actioncodes` (`code_action`, `user_id`, `action_code`) VALUES (:action, :id, :code)')
|
||||||
'code_action' => $action,
|
->execute([
|
||||||
'user_id' => $user,
|
'action' => $action,
|
||||||
'action_code' => $code,
|
'id' => $user,
|
||||||
|
'code' => $code,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Return the code
|
// Return the code
|
||||||
|
@ -52,11 +53,13 @@ class ActionCode
|
||||||
public static function validate($action, $code, $user = 0, $invalidate = true)
|
public static function validate($action, $code, $user = 0, $invalidate = true)
|
||||||
{
|
{
|
||||||
// Fetch the code from the db
|
// Fetch the code from the db
|
||||||
$get = Database::count('actioncodes', [
|
$get = DB::prepare('SELECT * FROM `{prefix}actioncodes` WHERE `code_action` = :code AND `action_code` = :action AND `user_id` = :id');
|
||||||
'code_action' => [$action, '='],
|
$get->execute([
|
||||||
'action_code' => [$code, '='],
|
'code' => $action,
|
||||||
'user_id' => [$user, '='],
|
'action' => $code,
|
||||||
|
'id' => $user,
|
||||||
]);
|
]);
|
||||||
|
$get = $get->rowCount();
|
||||||
|
|
||||||
// Invalidate the code if requested
|
// Invalidate the code if requested
|
||||||
if ($invalidate) {
|
if ($invalidate) {
|
||||||
|
@ -64,7 +67,7 @@ class ActionCode
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the result
|
// Return the result
|
||||||
return $get[0] > 0;
|
return $get > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,8 +77,9 @@ class ActionCode
|
||||||
*/
|
*/
|
||||||
public static function invalidate($code)
|
public static function invalidate($code)
|
||||||
{
|
{
|
||||||
Database::delete('actioncodes', [
|
DB::prepare('DELETE FROM `{prefix}actioncodes` WHERE `code_action` = :code')
|
||||||
'code_action' => [$code, '='],
|
->execute([
|
||||||
|
'code' => $code,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,12 +48,14 @@ class BBcode
|
||||||
public static function parseEmoticons($text)
|
public static function parseEmoticons($text)
|
||||||
{
|
{
|
||||||
// Get emoticons from the database
|
// Get emoticons from the database
|
||||||
$emotes = Database::fetch('emoticons');
|
$emotes = DB::prepare('SELECT * FROM `{prefix}emoticons`');
|
||||||
|
$emotes->execute();
|
||||||
|
$emotes = $emotes->fetchAll();
|
||||||
|
|
||||||
// Parse all emoticons
|
// Parse all emoticons
|
||||||
foreach ($emotes as $emote) {
|
foreach ($emotes as $emote) {
|
||||||
$image = "<img src='{$emote['emote_path']}' alt='{$emote['emote_string']}' class='emoticon' />";
|
$image = "<img src='{$emote->emote_path}' alt='{$emote->emote_string}' class='emoticon' />";
|
||||||
$icon = preg_quote($emote['emote_string'], '#');
|
$icon = preg_quote($emote->emote_string, '#');
|
||||||
$text = preg_replace("#$icon#", $image, $text);
|
$text = preg_replace("#$icon#", $image, $text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,11 @@ class Bans
|
||||||
{
|
{
|
||||||
|
|
||||||
// Attempt to get a ban from this user
|
// Attempt to get a ban from this user
|
||||||
$bans = Database::fetch('bans', true, ['user_id' => [$uid, '=']]);
|
$bans = DB::prepare('SELECT * FROM `{prefix}bans` WHERE `user_id` = :id');
|
||||||
|
$bans->execute([
|
||||||
|
'id' => $uid,
|
||||||
|
]);
|
||||||
|
$bans = $bans->fetchAll();
|
||||||
|
|
||||||
// Reverse the array so new bans are listed first
|
// Reverse the array so new bans are listed first
|
||||||
$bans = array_reverse($bans);
|
$bans = array_reverse($bans);
|
||||||
|
@ -34,21 +38,22 @@ class Bans
|
||||||
// Go over each ban
|
// Go over each ban
|
||||||
foreach ($bans as $ban) {
|
foreach ($bans as $ban) {
|
||||||
// Check if it hasn't expired
|
// Check if it hasn't expired
|
||||||
if ($ban['ban_end'] != 0 && $ban['ban_end'] < time()) {
|
if ($ban->ban_end != 0 && $ban->ban_end < time()) {
|
||||||
// If it has delete the entry and continue
|
// If it has delete the entry and continue
|
||||||
Database::delete('bans', ['id' => [$ban['user_id'], '=']]);
|
DB::prepare('DELETE FROM `{prefix}bans` WHERE `ban_id` = :id')
|
||||||
|
->execute([
|
||||||
|
'id' => $ban->user_id,
|
||||||
|
]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the ban if all checks were passed
|
// Return the ban if all checks were passed
|
||||||
return [
|
return [
|
||||||
|
'user' => $ban->user_id,
|
||||||
'user' => $ban['user_id'],
|
'issuer' => $ban->ban_moderator,
|
||||||
'issuer' => $ban['ban_moderator'],
|
'issued' => $ban->ban_begin,
|
||||||
'issued' => $ban['ban_begin'],
|
'expires' => $ban->ban_end,
|
||||||
'expires' => $ban['ban_end'],
|
'reason' => $ban->ban_reason,
|
||||||
'reason' => $ban['ban_reason'],
|
|
||||||
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ namespace Sakura;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles and serves comments on pages.
|
* Handles and serves comments on pages.
|
||||||
|
* Needs a reimplementation.
|
||||||
*
|
*
|
||||||
* @package Sakura
|
* @package Sakura
|
||||||
* @author Julian van de Groep <me@flash.moe>
|
* @author Julian van de Groep <me@flash.moe>
|
||||||
|
@ -46,15 +47,11 @@ class Comments
|
||||||
$this->category = $category;
|
$this->category = $category;
|
||||||
|
|
||||||
// Get the comments and assign them to $comments
|
// Get the comments and assign them to $comments
|
||||||
$comments = Database::fetch(
|
$comments = DB::prepare('SELECT * FROM `{prefix}comments` WHERE `comment_category` = :category AND `comment_reply_to` = 0 ORDER BY `comment_id` DESC');
|
||||||
'comments',
|
$comments->execute([
|
||||||
true,
|
'category' => $this->category,
|
||||||
[
|
]);
|
||||||
'comment_category' => [$this->category, '='],
|
$comments = $comments->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
'comment_reply_to' => ['0', '='],
|
|
||||||
],
|
|
||||||
['comment_id', true]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Feed them into the sorter
|
// Feed them into the sorter
|
||||||
$this->comments = $this->sortComments($comments);
|
$this->comments = $this->sortComments($comments);
|
||||||
|
@ -99,10 +96,12 @@ class Comments
|
||||||
$this->count += 1;
|
$this->count += 1;
|
||||||
|
|
||||||
// Attempt to get replies from the database
|
// Attempt to get replies from the database
|
||||||
$replies = Database::fetch('comments', true, [
|
$replies = DB::prepare('SELECT * FROM `{prefix}comments` WHERE `comment_category` = :category AND `comment_reply_to` = :thread');
|
||||||
'comment_category' => [$this->category, '='],
|
$replies->execute([
|
||||||
'comment_reply_to' => [$comment['comment_id'], '='],
|
'category' => $this->category,
|
||||||
|
'thread' => $comment['comment_id'],
|
||||||
]);
|
]);
|
||||||
|
$replies = $replies->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// Check if this was a reply to something
|
// Check if this was a reply to something
|
||||||
if ($replies) {
|
if ($replies) {
|
||||||
|
@ -124,9 +123,11 @@ class Comments
|
||||||
public function getComment($cid)
|
public function getComment($cid)
|
||||||
{
|
{
|
||||||
// Get from database
|
// Get from database
|
||||||
return Database::fetch('comments', false, [
|
$comment = DB::prepare('SELECT * FROM `{prefix}comments` WHERE `comment_id` = :id');
|
||||||
'comment_id' => [$cid, '='],
|
$comment->execute([
|
||||||
|
'id' => $cid,
|
||||||
]);
|
]);
|
||||||
|
return $comment->fetch(\PDO::FETCH_ASSOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -139,9 +140,11 @@ class Comments
|
||||||
public function getVotes($cid)
|
public function getVotes($cid)
|
||||||
{
|
{
|
||||||
// Get from database
|
// Get from database
|
||||||
return Database::fetch('comment_votes', true, [
|
$comment = DB::prepare('SELECT * FROM `{prefix}comment_votes` WHERE `vote_comment` = :id');
|
||||||
'vote_comment' => [$cid, '='],
|
$comment->execute([
|
||||||
|
'id' => $cid,
|
||||||
]);
|
]);
|
||||||
|
return $comment->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -166,12 +169,13 @@ class Comments
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert into database
|
// Insert into database
|
||||||
Database::insert('comments', [
|
DB::prepare('INSERT INTO `{prefix}comments` (`comment_category`, `comment_timestamp`, `comment_poster`, `comment_reply_to`, `comment_text`) VALUES (:cat, :time, :user, :thread, :text)')
|
||||||
'comment_category' => $this->category,
|
->execute([
|
||||||
'comment_timestamp' => time(),
|
'cat' => $this->category,
|
||||||
'comment_poster' => $uid,
|
'time' => time(),
|
||||||
'comment_reply_to' => (int) $reply,
|
'user' => $uid,
|
||||||
'comment_text' => $content,
|
'thread' => (int) $reply,
|
||||||
|
'text' => $content,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Return success
|
// Return success
|
||||||
|
@ -190,38 +194,39 @@ class Comments
|
||||||
public function makeVote($uid, $cid, $mode)
|
public function makeVote($uid, $cid, $mode)
|
||||||
{
|
{
|
||||||
// Attempt to get previous vote
|
// Attempt to get previous vote
|
||||||
$vote = Database::fetch('comment_votes', false, [
|
$vote = DB::prepare('SELECT * FROM `{prefix}comment_votes` WHERE `vote_user` = :user AND `vote_comment` = :comment');
|
||||||
'vote_user' => [$uid, '='],
|
$vote->execute([
|
||||||
'vote_comment' => [$cid, '='],
|
'user' => $uid,
|
||||||
|
'comment' => $cid,
|
||||||
]);
|
]);
|
||||||
|
$vote = $vote->fetch(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// Check if anything was returned
|
// Check if anything was returned
|
||||||
if ($vote) {
|
if ($vote) {
|
||||||
// Check if the vote that's being casted is the same
|
// Check if the vote that's being casted is the same
|
||||||
if ($vote['vote_state'] == $mode) {
|
if ($vote['vote_state'] == $mode) {
|
||||||
// Delete the vote
|
// Delete the vote
|
||||||
Database::delete('comment_votes', [
|
DB::prepare('DELETE FROM `{prefix}comment_votes` WHERE `vote_user` = :user AND `vote_comment` = :comment')
|
||||||
'vote_user' => [$uid, '='],
|
->execute([
|
||||||
'vote_comment' => [$cid, '='],
|
'user' => $uid,
|
||||||
|
'comment' => $cid,
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
// Otherwise update the vote
|
// Otherwise update the vote
|
||||||
Database::update('comment_votes', [
|
DB::prepare('UPDATE `{prefix}comment_votes` SET `vote_state` = :state WHERE `vote_user` = :user AND `vote_comment` = :comment')
|
||||||
[
|
->execute([
|
||||||
'vote_state' => $mode,
|
'state' => $mode,
|
||||||
],
|
'user' => $uid,
|
||||||
[
|
'comment' => $cid,
|
||||||
'vote_user' => [$uid, '='],
|
|
||||||
'vote_comment' => [$cid, '='],
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Create a vote
|
// Create a vote
|
||||||
Database::insert('comment_votes', [
|
DB::prepare('INSERT INTO `{prefix}comment_votes` (`vote_user`, `vote_comment`, `vote_state`) VALUES (:user, :comment, :state)')
|
||||||
'vote_user' => $uid,
|
->execute([
|
||||||
'vote_comment' => $cid,
|
'user' => $uid,
|
||||||
'vote_state' => $mode,
|
'comment' => $cid,
|
||||||
|
'state' => $mode,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,14 +237,13 @@ class Comments
|
||||||
* Remove a comment
|
* Remove a comment
|
||||||
*
|
*
|
||||||
* @param int $cid ID of the comment to remove.
|
* @param int $cid ID of the comment to remove.
|
||||||
*
|
|
||||||
* @return mixed No idea what this returns but it doesn't really matter anyway, the comment is dead.
|
|
||||||
*/
|
*/
|
||||||
public function removeComment($cid)
|
public function removeComment($cid)
|
||||||
{
|
{
|
||||||
// Remove from database
|
// Remove from database
|
||||||
return Database::delete('comments', [
|
DB::prepare('DELETE FROM `{prefix}comments` WHERE `comment_id` = :id')
|
||||||
'comment_id' => [$cid, '='],
|
->execute([
|
||||||
|
'id' => $cid,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ class Config
|
||||||
* @param string $key Configuration section.
|
* @param string $key Configuration section.
|
||||||
* @param string $subkey Configuration key.
|
* @param string $subkey Configuration key.
|
||||||
*
|
*
|
||||||
* @return string Configuration value.
|
* @return array|string Configuration value.
|
||||||
*/
|
*/
|
||||||
public static function local($key, $subkey = null)
|
public static function local($key, $subkey = null)
|
||||||
{
|
{
|
||||||
|
@ -101,9 +101,13 @@ class Config
|
||||||
// Then return the value
|
// Then return the value
|
||||||
return self::$database[$key];
|
return self::$database[$key];
|
||||||
} else {
|
} else {
|
||||||
$value = Database::fetch('config', false, ['config_name' => [$key, '=']]);
|
$value = DB::prepare('SELECT * FROM `{prefix}config` WHERE `config_name` = :name');
|
||||||
|
$value->execute([
|
||||||
|
'name' => $key,
|
||||||
|
]);
|
||||||
|
$value = $value->fetch();
|
||||||
if ($value) {
|
if ($value) {
|
||||||
self::$database[$key] = $value['config_value'];
|
self::$database[$key] = $value->config_value;
|
||||||
return self::$database[$key];
|
return self::$database[$key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,4 +119,34 @@ class Config
|
||||||
);
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function set($key, $value)
|
||||||
|
{
|
||||||
|
// Unset the cached copy
|
||||||
|
if (array_key_exists($key, self::$database)) {
|
||||||
|
unset(self::$database[$key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the value already exists
|
||||||
|
$exists = DB::prepare('SELECT * FROM `{prefix}config` WHERE `config_name` = :name');
|
||||||
|
$exists->execute([
|
||||||
|
'name' => $key,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// If it exists run an update
|
||||||
|
if ($exists->rowCount()) {
|
||||||
|
$set = DB::prepare('UPDATE `{prefix}config` SET `config_value` = :value WHERE `config_name` = :name');
|
||||||
|
} else {
|
||||||
|
$set = DB::prepare('INSERT INTO `{prefix}config` (`config_name`, `config_value`) VALUES (:name, :value)');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the setter
|
||||||
|
$set->execute([
|
||||||
|
'name' => $key,
|
||||||
|
'value' => $value,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Return the value
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ namespace Sakura\Controllers;
|
||||||
|
|
||||||
use Sakura\Config;
|
use Sakura\Config;
|
||||||
use Sakura\Database;
|
use Sakura\Database;
|
||||||
|
use Sakura\DB;
|
||||||
use Sakura\Forum;
|
use Sakura\Forum;
|
||||||
use Sakura\Perms\Forum as ForumPerms;
|
use Sakura\Perms\Forum as ForumPerms;
|
||||||
use Sakura\Template;
|
use Sakura\Template;
|
||||||
|
@ -31,18 +32,25 @@ class Forums extends Controller
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
|
$userCount = DB::prepare("SELECT * FROM `{prefix}users` WHERE `password_algo` != 'disabled' AND `rank_main` != 1");
|
||||||
|
$userCount->execute();
|
||||||
|
$threadCount = DB::prepare('SELECT * FROM `{prefix}topics`');
|
||||||
|
$threadCount->execute();
|
||||||
|
$postCount = DB::prepare('SELECT * FROM `{prefix}posts`');
|
||||||
|
$postCount->execute();
|
||||||
|
|
||||||
// Merge index specific stuff with the global render data
|
// Merge index specific stuff with the global render data
|
||||||
Template::vars([
|
Template::vars([
|
||||||
'forum' => (new Forum\Forum()),
|
'forum' => (new Forum\Forum()),
|
||||||
'stats' => [
|
'stats' => [
|
||||||
'userCount' => Database::count('users', ['password_algo' => ['nologin', '!='], 'rank_main' => ['1', '!=']])[0],
|
'userCount' => $userCount->rowCount(),
|
||||||
'newestUser' => User::construct(Users::getNewestUserId()),
|
'newestUser' => User::construct(Users::getNewestUserId()),
|
||||||
'lastRegData' => date_diff(
|
'lastRegData' => date_diff(
|
||||||
date_create(date('Y-m-d', User::construct(Users::getNewestUserId())->registered)),
|
date_create(date('Y-m-d', User::construct(Users::getNewestUserId())->registered)),
|
||||||
date_create(date('Y-m-d'))
|
date_create(date('Y-m-d'))
|
||||||
)->format('%a'),
|
)->format('%a'),
|
||||||
'topicCount' => Database::count('topics')[0],
|
'topicCount' => $threadCount->rowCount(),
|
||||||
'postCount' => Database::count('posts')[0],
|
'postCount' => $postCount->rowCount(),
|
||||||
'onlineUsers' => Users::checkAllOnline(),
|
'onlineUsers' => Users::checkAllOnline(),
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -9,6 +9,7 @@ namespace Sakura\Controllers;
|
||||||
|
|
||||||
use Sakura\Config;
|
use Sakura\Config;
|
||||||
use Sakura\Database;
|
use Sakura\Database;
|
||||||
|
use Sakura\DB;
|
||||||
use Sakura\News;
|
use Sakura\News;
|
||||||
use Sakura\Template;
|
use Sakura\Template;
|
||||||
use Sakura\User;
|
use Sakura\User;
|
||||||
|
@ -30,19 +31,26 @@ class Meta extends Controller
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
|
$userCount = DB::prepare("SELECT * FROM `{prefix}users` WHERE `password_algo` != 'disabled' AND `rank_main` != 1");
|
||||||
|
$userCount->execute();
|
||||||
|
$threadCount = DB::prepare('SELECT * FROM `{prefix}topics`');
|
||||||
|
$threadCount->execute();
|
||||||
|
$postCount = DB::prepare('SELECT * FROM `{prefix}posts`');
|
||||||
|
$postCount->execute();
|
||||||
|
|
||||||
// Merge index specific stuff with the global render data
|
// Merge index specific stuff with the global render data
|
||||||
Template::vars([
|
Template::vars([
|
||||||
'news' => new News(Config::get('site_news_category')),
|
'news' => new News(Config::get('site_news_category')),
|
||||||
'newsCount' => Config::get('front_page_news_posts'),
|
'newsCount' => Config::get('front_page_news_posts'),
|
||||||
'stats' => [
|
'stats' => [
|
||||||
'userCount' => Database::count('users', ['password_algo' => ['nologin', '!='], 'rank_main' => ['1', '!=']])[0],
|
'userCount' => $userCount->rowCount(),
|
||||||
'newestUser' => User::construct(Users::getNewestUserId()),
|
'newestUser' => User::construct(Users::getNewestUserId()),
|
||||||
'lastRegDate' => date_diff(
|
'lastRegDate' => date_diff(
|
||||||
date_create(date('Y-m-d', User::construct(Users::getNewestUserId())->registered)),
|
date_create(date('Y-m-d', User::construct(Users::getNewestUserId())->registered)),
|
||||||
date_create(date('Y-m-d'))
|
date_create(date('Y-m-d'))
|
||||||
)->format('%a'),
|
)->format('%a'),
|
||||||
'topicCount' => Database::count('topics')[0],
|
'topicCount' => $threadCount->rowCount(),
|
||||||
'postCount' => Database::count('posts')[0],
|
'postCount' => $postCount->rowCount(),
|
||||||
'onlineUsers' => Users::checkAllOnline(),
|
'onlineUsers' => Users::checkAllOnline(),
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
@ -87,11 +95,16 @@ class Meta extends Controller
|
||||||
*/
|
*/
|
||||||
public function faq()
|
public function faq()
|
||||||
{
|
{
|
||||||
|
// Get faq entries
|
||||||
|
$faq = DB::prepare('SELECT * FROM `{prefix}faq` ORDER BY `faq_id`');
|
||||||
|
$faq->execute();
|
||||||
|
$faq = $faq->fetchAll();
|
||||||
|
|
||||||
// Set parse variables
|
// Set parse variables
|
||||||
Template::vars([
|
Template::vars([
|
||||||
'page' => [
|
'page' => [
|
||||||
'title' => 'Frequently Asked Questions',
|
'title' => 'Frequently Asked Questions',
|
||||||
'questions' => Database::fetch('faq', true, null, ['faq_id']),
|
'questions' => $faq,
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -109,25 +122,33 @@ class Meta extends Controller
|
||||||
public function infoPage($id = null)
|
public function infoPage($id = null)
|
||||||
{
|
{
|
||||||
// Set default variables
|
// Set default variables
|
||||||
$renderData['page'] = [
|
Template::vars([
|
||||||
|
'page' => [
|
||||||
'content' => '<h1>Unable to load the requested info page.</h1><p>Check the URL and try again.</p>',
|
'content' => '<h1>Unable to load the requested info page.</h1><p>Check the URL and try again.</p>',
|
||||||
];
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
// Set page id
|
// Set page id
|
||||||
$id = strtolower($id);
|
$id = strtolower($id);
|
||||||
|
|
||||||
// Get info page data from the database
|
// Get the page from the database
|
||||||
if ($ipData = Database::fetch('infopages', false, ['page_shorthand' => [$id, '=']])) {
|
$ipData = DB::prepare('SELECT * FROM `{prefix}infopages` WHERE `page_shorthand` = :id');
|
||||||
// Assign new proper variable
|
$ipData->execute([
|
||||||
$renderData['page'] = [
|
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
'title' => $ipData['page_title'],
|
]);
|
||||||
'content' => $ipData['page_content'],
|
$ipData = $ipData->fetch();
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set parse variables
|
// Get info page data from the database
|
||||||
Template::vars($renderData);
|
if ($ipData) {
|
||||||
|
// Assign new proper variable
|
||||||
|
Template::vars([
|
||||||
|
'page' => [
|
||||||
|
'id' => $id,
|
||||||
|
'title' => $ipData->page_title,
|
||||||
|
'content' => $ipData->page_content,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
// Return the compiled page
|
// Return the compiled page
|
||||||
return Template::render('main/infopage');
|
return Template::render('main/infopage');
|
||||||
|
|
|
@ -103,6 +103,7 @@ class Premium extends Controller
|
||||||
// Attempt to complete the transaction
|
// Attempt to complete the transaction
|
||||||
if ($finalise) {
|
if ($finalise) {
|
||||||
// Make the user premium
|
// Make the user premium
|
||||||
|
Users::addUserPremium($currentUser->id, (2628000 * $_SESSION['premiumMonths']));
|
||||||
Users::updatePremiumMeta($currentUser->id);
|
Users::updatePremiumMeta($currentUser->id);
|
||||||
Utils::updatePremiumTracker(
|
Utils::updatePremiumTracker(
|
||||||
$currentUser->id,
|
$currentUser->id,
|
||||||
|
|
|
@ -9,6 +9,7 @@ namespace Sakura\Controllers;
|
||||||
|
|
||||||
use Sakura\Config;
|
use Sakura\Config;
|
||||||
use Sakura\Database;
|
use Sakura\Database;
|
||||||
|
use Sakura\DB;
|
||||||
use Sakura\Rank;
|
use Sakura\Rank;
|
||||||
use Sakura\Template;
|
use Sakura\Template;
|
||||||
use Sakura\User as UserContext;
|
use Sakura\User as UserContext;
|
||||||
|
@ -39,13 +40,19 @@ class User extends Controller
|
||||||
// If the user id is zero check if there was a namechange
|
// If the user id is zero check if there was a namechange
|
||||||
if ($profile->id == 0) {
|
if ($profile->id == 0) {
|
||||||
// Fetch from username_history
|
// Fetch from username_history
|
||||||
$check = Database::fetch('username_history', false, ['username_old_clean' => [Utils::cleanString(isset($_GET['u']) ? $_GET['u'] : 0, true, true), '=']]);
|
$check = DB::prepare('SELECT `user_id` FROM `{prefix}username_history` WHERE `username_old_clean` = :uname ORDER BY `change_id` DESC');
|
||||||
|
$check->execute([
|
||||||
|
'uname' => Utils::cleanString($id, true, true),
|
||||||
|
]);
|
||||||
|
$check = $check->fetch();
|
||||||
|
|
||||||
// Redirect if so
|
// Redirect if so
|
||||||
if ($check) {
|
if ($check) {
|
||||||
Template::vars([
|
Template::vars([
|
||||||
|
'page' => [
|
||||||
'message' => 'The user this profile belongs to changed their username, you are being redirected.',
|
'message' => 'The user this profile belongs to changed their username, you are being redirected.',
|
||||||
'redirect' => (new \Sakura\Urls)->format('USER_PROFILE', [$check['user_id']]),
|
'redirect' => (new \Sakura\Urls)->format('USER_PROFILE', [$check->user_id]),
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Print page contents
|
// Print page contents
|
||||||
|
|
112
libraries/DB.php
Normal file
112
libraries/DB.php
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Holds the database wrapper (v2).
|
||||||
|
*
|
||||||
|
* @package Sakura
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Sakura;
|
||||||
|
|
||||||
|
use PDO;
|
||||||
|
use PDOException;
|
||||||
|
use PDOStatement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper to make the database communication experience smoother.
|
||||||
|
*
|
||||||
|
* @package Sakura
|
||||||
|
* @author Julian van de Groep <me@flash.moe>
|
||||||
|
*/
|
||||||
|
class DB
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The container for the PDO object.
|
||||||
|
*
|
||||||
|
* @var PDO
|
||||||
|
*/
|
||||||
|
public static $db = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The table prefix
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public static $prefix = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open the SQL connection and creates a PDO object.
|
||||||
|
*
|
||||||
|
* @param string $server A PDO driver.
|
||||||
|
* @param array $dsnParts An array consisting out of DSN string parts.
|
||||||
|
* @param string $username The username used to authenticate with the SQL server.
|
||||||
|
* @param string $password The password for the same purpose.
|
||||||
|
* @param array $options Additional PDO options.
|
||||||
|
*/
|
||||||
|
public static function open($server, $dsnParts, $username = null, $password = null, $prefix = '', $options = [])
|
||||||
|
{
|
||||||
|
// Check if the selected driver is available
|
||||||
|
if (!in_array($server, PDO::getAvailableDrivers())) {
|
||||||
|
trigger_error('A driver for the selected SQL server wasn\'t found!', E_USER_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the table prefix
|
||||||
|
self::$prefix = $prefix;
|
||||||
|
|
||||||
|
// Create start of the DSN
|
||||||
|
$dsn = "{$server}:";
|
||||||
|
|
||||||
|
// Append the parts
|
||||||
|
foreach ($dsnParts as $name => $value) {
|
||||||
|
$dsn .= "{$name}={$value};";
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Connect to SQL server using PDO
|
||||||
|
self::$db = new PDO($dsn, $username, $password, $options);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
// Catch connection errors
|
||||||
|
trigger_error($e->getMessage(), E_USER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
||||||
|
self::$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||||
|
self::$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the PDO object.
|
||||||
|
*/
|
||||||
|
public static function close()
|
||||||
|
{
|
||||||
|
self::$db = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the id of the item that was last inserted into the database.
|
||||||
|
*
|
||||||
|
* @param string $name Sequence of which the last id should be returned.
|
||||||
|
*
|
||||||
|
* @return string The last inserted id.
|
||||||
|
*/
|
||||||
|
public static function lastID($name = null)
|
||||||
|
{
|
||||||
|
return self::$db->lastInsertID($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares a statement for execution and returns a statement object.
|
||||||
|
*
|
||||||
|
* @param string $stmt The statement to prepare.
|
||||||
|
* @param array $opts Statement specific driver options.
|
||||||
|
*
|
||||||
|
* @return PDOStatement
|
||||||
|
*/
|
||||||
|
public static function prepare($stmt, $opts = [])
|
||||||
|
{
|
||||||
|
// Replace the table prefix
|
||||||
|
$stmt = str_replace('{prefix}', self::$prefix, $stmt);
|
||||||
|
|
||||||
|
return self::$db->prepare($stmt, $opts);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,478 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Holds the MySQL/PDO wrapper.
|
|
||||||
*
|
|
||||||
* @package Sakura
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Sakura\DBWrapper;
|
|
||||||
|
|
||||||
use PDO;
|
|
||||||
use PDOException;
|
|
||||||
use PDOStatement;
|
|
||||||
use \Sakura\Config;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sakura MySQL Wrapper.
|
|
||||||
*
|
|
||||||
* @package Sakura
|
|
||||||
* @author Julian van de Groep <me@flash.moe>
|
|
||||||
*/
|
|
||||||
class mysql
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Contains the PDO object.
|
|
||||||
*
|
|
||||||
* @var PDO
|
|
||||||
*/
|
|
||||||
protected $sql;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
if (!extension_loaded('PDO')) {
|
|
||||||
// Return error and die
|
|
||||||
trigger_error('PDO extension not loaded.', E_USER_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialise connection
|
|
||||||
$this->initConnect(
|
|
||||||
(
|
|
||||||
Config::local('database', 'unixsocket') ?
|
|
||||||
$this->prepareSock(
|
|
||||||
Config::local('database', 'host'),
|
|
||||||
Config::local('database', 'database')
|
|
||||||
) :
|
|
||||||
$this->prepareHost(
|
|
||||||
Config::local('database', 'host'),
|
|
||||||
Config::local('database', 'database'),
|
|
||||||
(
|
|
||||||
Config::local('database', 'port') !== null ?
|
|
||||||
Config::local('database', 'port') :
|
|
||||||
3306
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Config::local('database', 'username'),
|
|
||||||
Config::local('database', 'password')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a DSN for a regular hostname:port endpoint.
|
|
||||||
*
|
|
||||||
* @param string $dbHost Database hostname.
|
|
||||||
* @param string $dbName Database name.
|
|
||||||
* @param int $dbPort Database host port.
|
|
||||||
*
|
|
||||||
* @return string The PDO DSN.
|
|
||||||
*/
|
|
||||||
private function prepareHost($dbHost, $dbName, $dbPort = 3306)
|
|
||||||
{
|
|
||||||
$dsn = 'mysql:host=' . $dbHost . ';port=' . $dbPort . ';dbname=' . $dbName;
|
|
||||||
|
|
||||||
return $dsn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a DSN for a unix socket endpoint.
|
|
||||||
*
|
|
||||||
* @param string $dbHost Path to the Unix Socket.
|
|
||||||
* @param string $dbName Database name.
|
|
||||||
*
|
|
||||||
* @return string The PDO DSN.
|
|
||||||
*/
|
|
||||||
private function prepareSock($dbHost, $dbName)
|
|
||||||
{
|
|
||||||
$dsn = 'mysql:unix_socket=' . $dbHost . ';dbname=' . $dbName;
|
|
||||||
|
|
||||||
return $dsn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialise a the database connection.
|
|
||||||
*
|
|
||||||
* @param string $dsn The PDO DSN.
|
|
||||||
* @param string $dbUname The database username.
|
|
||||||
* @param string $dbPword The database password.
|
|
||||||
*
|
|
||||||
* @return bool Returns true if the connection was successful.
|
|
||||||
*/
|
|
||||||
private function initConnect($dsn, $dbUname, $dbPword)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// Connect to SQL server using PDO
|
|
||||||
$this->sql = new PDO($dsn, $dbUname, $dbPword, [
|
|
||||||
PDO::ATTR_EMULATE_PREPARES => false,
|
|
||||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING,
|
|
||||||
]);
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
// Catch connection errors
|
|
||||||
trigger_error('SQL Driver: ' . $e->getMessage(), E_USER_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Select table row(s).
|
|
||||||
*
|
|
||||||
* @param string $table The table to select data from.
|
|
||||||
* @param array $data The WHERE selectors.
|
|
||||||
* @param array $order The order in which the data is returned.
|
|
||||||
* @param array $limit The limit of what should be returned.
|
|
||||||
* @param array $group The way MySQL will group the data.
|
|
||||||
* @param bool $distinct Only return distinct values.
|
|
||||||
* @param string $column Only select from this column.
|
|
||||||
* @param string $prefix Use a different table prefix than the one from the configuration.
|
|
||||||
*
|
|
||||||
* @return PDOStatement The PDOStatement object for this action.
|
|
||||||
*/
|
|
||||||
public function select($table, $data = null, $order = null, $limit = null, $group = null, $distinct = false, $column = '*', $prefix = null)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Begin preparation of the statement
|
|
||||||
$prepare = 'SELECT ' . ($distinct ? 'DISTINCT ' : '') . ($column == '*' ? '' : '`') . $column . ($column == '*' ? '' : '`') . ' FROM `' . ($prefix ? $prefix : Config::local('database', 'prefix')) . $table . '`';
|
|
||||||
|
|
||||||
// If $data is set and is an array continue
|
|
||||||
if (is_array($data)) {
|
|
||||||
$prepare .= ' WHERE';
|
|
||||||
|
|
||||||
foreach ($data as $key => $value) {
|
|
||||||
// Check if there's multiple statements
|
|
||||||
if (!is_array($value[0])) {
|
|
||||||
$temp = $value;
|
|
||||||
unset($value);
|
|
||||||
$value[0] = $temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go over each data thing
|
|
||||||
foreach ($value as $sub => $val) {
|
|
||||||
$prepare .= ' `' . $key . '` ' . $val[1] . ' :' . $key . '_' . $sub . ($key == key(array_slice($data, -1, 1, true)) && $sub == key(array_slice($value, -1, 1, true)) ? '' : ' ' . (isset($val[2]) && $val[2] ? 'OR' : 'AND'));
|
|
||||||
|
|
||||||
unset($sub);
|
|
||||||
unset($val);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unset variables to be safe
|
|
||||||
unset($key);
|
|
||||||
unset($value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If $group is set and is an array continue
|
|
||||||
if (is_array($group)) {
|
|
||||||
$prepare .= ' GROUP BY';
|
|
||||||
|
|
||||||
foreach ($group as $key => $value) {
|
|
||||||
$prepare .= ' `' . $value . '`' . ($key == key(array_slice($group, -1, 1, true)) ? '' : ',');
|
|
||||||
|
|
||||||
// Unset variables to be safe
|
|
||||||
unset($key);
|
|
||||||
unset($value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If $order is set and is an array continue
|
|
||||||
if (is_array($order)) {
|
|
||||||
$prepare .= ' ORDER BY `' . $order[0] . '`' . (!empty($order[1]) && $order[1] ? ' DESC' : '');
|
|
||||||
}
|
|
||||||
|
|
||||||
// If $limit is set and is an array continue
|
|
||||||
if (is_array($limit)) {
|
|
||||||
$prepare .= ' LIMIT';
|
|
||||||
|
|
||||||
foreach ($limit as $key => $value) {
|
|
||||||
$prepare .= ' ' . $value . ($key == key(array_slice($limit, -1, 1, true)) ? '' : ',');
|
|
||||||
|
|
||||||
// Unset variables to be safe
|
|
||||||
unset($key);
|
|
||||||
unset($value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the finishing semicolon
|
|
||||||
$prepare .= ';';
|
|
||||||
|
|
||||||
// Actually prepare the preration
|
|
||||||
$query = $this->sql->prepare($prepare);
|
|
||||||
|
|
||||||
// Bind those parameters if $data is an array that is
|
|
||||||
if (is_array($data)) {
|
|
||||||
foreach ($data as $key => $value) {
|
|
||||||
// Check if there's multiple statements
|
|
||||||
if (!is_array($value[0])) {
|
|
||||||
$temp = $value;
|
|
||||||
unset($value);
|
|
||||||
$value[0] = $temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go over each data thing
|
|
||||||
foreach ($value as $sub => $val) {
|
|
||||||
$query->bindParam(':' . $key . '_' . $sub, $val[0]);
|
|
||||||
|
|
||||||
unset($sub);
|
|
||||||
unset($val);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unset variables to be safe
|
|
||||||
unset($key);
|
|
||||||
unset($value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute the prepared statements with parameters bound
|
|
||||||
$query->execute();
|
|
||||||
|
|
||||||
// Return the query
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Summary of fetch
|
|
||||||
*
|
|
||||||
* @param string $table The table to select data from.
|
|
||||||
* @param bool $fetchAll Whether all result will be returned or just the first one.
|
|
||||||
* @param array $data The WHERE selectors.
|
|
||||||
* @param array $order The order in which the data is returned.
|
|
||||||
* @param array $limit The limit of what should be returned.
|
|
||||||
* @param array $group The way MySQL will group the data.
|
|
||||||
* @param bool $distinct Only return distinct values.
|
|
||||||
* @param string $column Only select from this column.
|
|
||||||
* @param string $prefix Use a different table prefix than the one from the configuration.
|
|
||||||
*
|
|
||||||
* @return array The data the database returned.
|
|
||||||
*/
|
|
||||||
public function fetch($table, $fetchAll = true, $data = null, $order = null, $limit = null, $group = null, $distinct = false, $column = '*', $prefix = null)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Run a select statement
|
|
||||||
$query = $this->select($table, $data, $order, $limit, $group, $distinct, $column, $prefix);
|
|
||||||
|
|
||||||
// Return the output
|
|
||||||
return $fetchAll ? $query->fetchAll(PDO::FETCH_ASSOC) : $query->fetch(PDO::FETCH_ASSOC);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert data into the database.
|
|
||||||
*
|
|
||||||
* @param string $table The table that the data will be inserted into.
|
|
||||||
* @param array $data The data that should be stored.
|
|
||||||
* @param string $prefix Use a different table prefix than the one from the configuration.
|
|
||||||
*
|
|
||||||
* @return bool Successfulness.
|
|
||||||
*/
|
|
||||||
public function insert($table, $data, $prefix = null)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Begin preparation of the statement
|
|
||||||
$prepare = 'INSERT INTO `' . ($prefix ? $prefix : Config::local('database', 'prefix')) . $table . '` ';
|
|
||||||
|
|
||||||
// Run the foreach statement twice for (`stuff`) VALUES (:stuff)
|
|
||||||
for ($i = 0; $i < 2; $i++) {
|
|
||||||
$prepare .= '(';
|
|
||||||
// Do more shit, don't feel like describing this so yeah
|
|
||||||
foreach ($data as $key => $value) {
|
|
||||||
if (strlen($value)) {
|
|
||||||
$prepare .= ($i ? ':' : '`') . $key . ($i ? '' : '`') . ($key == key(array_slice($data, -1, 1, true)) ? '' : ', ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$prepare .= ')' . ($i ? ';' : ' VALUES ');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actually prepare the preration
|
|
||||||
$query = $this->sql->prepare($prepare);
|
|
||||||
|
|
||||||
// Bind those parameters
|
|
||||||
foreach ($data as $key => $value) {
|
|
||||||
if (strlen($value)) {
|
|
||||||
$query->bindParam(':' . $key, $value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unset variables to be safe
|
|
||||||
unset($key);
|
|
||||||
unset($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute the prepared statements with parameters bound
|
|
||||||
$result = $query->execute();
|
|
||||||
|
|
||||||
// Return whatever can be returned
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update existing database rows.
|
|
||||||
*
|
|
||||||
* @param string $table The table that the updated data will be inserted into.
|
|
||||||
* @param array $data The data that should be stored.
|
|
||||||
* @param string $prefix Use a different table prefix than the one from the configuration.
|
|
||||||
*
|
|
||||||
* @return bool Successfulness.
|
|
||||||
*/
|
|
||||||
public function update($table, $data, $prefix = null)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Begin preparation of the statement
|
|
||||||
$prepare = 'UPDATE `' . ($prefix ? $prefix : Config::local('database', 'prefix')) . $table . '`';
|
|
||||||
|
|
||||||
// Run a foreach on $data and complete the statement
|
|
||||||
foreach ($data as $key => $values) {
|
|
||||||
// Append WHERE or SET depending on where we are
|
|
||||||
$prepare .= ' ' . ($key ? 'WHERE' : 'SET');
|
|
||||||
|
|
||||||
// Do this complicated shit, I barely know what's going on anymore but it works
|
|
||||||
foreach ($values as $column => $column_data) {
|
|
||||||
$prepare .= ' `' . $column . '` ' . ($key ? $column_data[1] : '=') . ' :' . ($key ? 'w' : 's') . '_' . $column . ($column == key(array_slice($values, -1, 1, true)) ? ($key ? ';' : '') : ($key ? ' ' . (isset($value[2]) && $value[2] ? 'OR' : 'AND') : ','));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actually prepare the preration
|
|
||||||
$query = $this->sql->prepare($prepare);
|
|
||||||
|
|
||||||
// Seperate the foreaches for the SET and WHERE clauses because it's fucking it up for some odd reason
|
|
||||||
// Bind Set Clauses
|
|
||||||
foreach ($data[0] as $key => $value) {
|
|
||||||
// Do the binding
|
|
||||||
$query->bindParam(':s_' . $key, $value);
|
|
||||||
|
|
||||||
// Unset variables to be safe
|
|
||||||
unset($key);
|
|
||||||
unset($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind Where Clauses
|
|
||||||
foreach ($data[1] as $key => $values) {
|
|
||||||
// Assign the array entry to a variable because fuck strict standards
|
|
||||||
$value = $values[0];
|
|
||||||
|
|
||||||
// Binding two electrifying memes
|
|
||||||
$query->bindParam(':w_' . $key, $value);
|
|
||||||
|
|
||||||
// Unset variables to be safe
|
|
||||||
unset($key);
|
|
||||||
unset($value);
|
|
||||||
unset($values);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute the prepared statements with parameters bound
|
|
||||||
$result = $query->execute();
|
|
||||||
|
|
||||||
// Return whatever can be returned
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deleted data from the database.
|
|
||||||
*
|
|
||||||
* @param string $table The table that the data will be removed from.
|
|
||||||
* @param array $data The pointers to what should be deleted.
|
|
||||||
* @param string $prefix Use a different table prefix than the one from the configuration.
|
|
||||||
*
|
|
||||||
* @return bool Successfulness.
|
|
||||||
*/
|
|
||||||
public function delete($table, $data, $prefix = null)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Begin preparation of the statement
|
|
||||||
$prepare = 'DELETE FROM `' . ($prefix ? $prefix : Config::local('database', 'prefix')) . $table . '`';
|
|
||||||
|
|
||||||
// If $data is set and is an array continue
|
|
||||||
if (is_array($data)) {
|
|
||||||
$prepare .= ' WHERE';
|
|
||||||
|
|
||||||
foreach ($data as $key => $value) {
|
|
||||||
$prepare .= ' `' . $key . '` ' . $value[1] . ' :' . $key . ($key == key(array_slice($data, -1, 1, true)) ? '' : ' ' . (isset($value[2]) && $value[2] ? 'OR' : 'AND'));
|
|
||||||
|
|
||||||
// Unset variables to be safe
|
|
||||||
unset($key);
|
|
||||||
unset($value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actually prepare the preration
|
|
||||||
$query = $this->sql->prepare($prepare);
|
|
||||||
|
|
||||||
// Bind those parameters
|
|
||||||
foreach ($data as $key => $value) {
|
|
||||||
$query->bindParam(':' . $key, $value[0]);
|
|
||||||
|
|
||||||
// Unset variables to be safe
|
|
||||||
unset($key);
|
|
||||||
unset($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute the prepared statements with parameters bound
|
|
||||||
$result = $query->execute();
|
|
||||||
|
|
||||||
// Return whatever can be returned
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the amount of rows from a table.
|
|
||||||
*
|
|
||||||
* @param string $table Table to count in.
|
|
||||||
* @param array $data Data that should be matched.
|
|
||||||
* @param string $prefix Use a different table prefix than the one from the configuration.
|
|
||||||
*
|
|
||||||
* @return array Array containing the SQL result.
|
|
||||||
*/
|
|
||||||
public function count($table, $data = null, $prefix = null)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Begin preparation of the statement
|
|
||||||
$prepare = 'SELECT COUNT(*) FROM `' . ($prefix ? $prefix : Config::local('database', 'prefix')) . $table . '`';
|
|
||||||
|
|
||||||
// If $data is set and is an array continue
|
|
||||||
if (is_array($data)) {
|
|
||||||
$prepare .= ' WHERE';
|
|
||||||
|
|
||||||
foreach ($data as $key => $value) {
|
|
||||||
$prepare .= ' `' . $key . '` ' . $value[1] . ' :' . $key . ($key == key(array_slice($data, -1, 1, true)) ? '' : ' ' . (isset($value[2]) && $value[2] ? 'OR' : 'AND'));
|
|
||||||
|
|
||||||
// Unset variables to be safe
|
|
||||||
unset($key);
|
|
||||||
unset($value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the finishing semicolon
|
|
||||||
$prepare .= ';';
|
|
||||||
|
|
||||||
// Actually prepare the preration
|
|
||||||
$query = $this->sql->prepare($prepare);
|
|
||||||
|
|
||||||
// Bind those parameters if $data is an array that is
|
|
||||||
if (is_array($data)) {
|
|
||||||
foreach ($data as $key => $value) {
|
|
||||||
$query->bindParam(':' . $key, $value[0]);
|
|
||||||
|
|
||||||
// Unset variables to be safe
|
|
||||||
unset($key);
|
|
||||||
unset($value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute the prepared statements with parameters bound
|
|
||||||
$query->execute();
|
|
||||||
|
|
||||||
// Return the output
|
|
||||||
return $query->fetch(PDO::FETCH_BOTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the id of the item that was last inserted into the database.
|
|
||||||
*
|
|
||||||
* @param string $name Sequence of which the last id should be returned.
|
|
||||||
*
|
|
||||||
* @return string The last inserted id.
|
|
||||||
*/
|
|
||||||
public function lastInsertID($name = null)
|
|
||||||
{
|
|
||||||
return $this->sql->lastInsertID($name);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,151 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Holds the database wrapper interfacer.
|
|
||||||
*
|
|
||||||
* @package Sakura
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Sakura;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper to make the database communication experience smoother.
|
|
||||||
*
|
|
||||||
* @package Sakura
|
|
||||||
* @author Julian van de Groep <me@flash.moe>
|
|
||||||
*/
|
|
||||||
class Database
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The container for the wrapper.
|
|
||||||
*
|
|
||||||
* @var mixed
|
|
||||||
*/
|
|
||||||
public static $database;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialise the database wrapper.
|
|
||||||
*
|
|
||||||
* @param string $wrapper The wrapper to wrap.
|
|
||||||
*/
|
|
||||||
public static function init($wrapper)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Make the wrapper class name lowercase
|
|
||||||
$wrapper = __NAMESPACE__ . '\DBWrapper\\' . strtolower($wrapper);
|
|
||||||
|
|
||||||
// Check if the class exists
|
|
||||||
if (!class_exists($wrapper)) {
|
|
||||||
trigger_error('Failed to load database wrapper', E_USER_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialise SQL wrapper
|
|
||||||
self::$database = new $wrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Select table row(s).
|
|
||||||
*
|
|
||||||
* @param string $table The table to select data from.
|
|
||||||
* @param array $data The WHERE selectors.
|
|
||||||
* @param array $order The order in which the data is returned.
|
|
||||||
* @param array $limit The limit of what should be returned.
|
|
||||||
* @param array $group The way MySQL will group the data.
|
|
||||||
* @param bool $distinct Only return distinct values.
|
|
||||||
* @param string $column Only select from this column.
|
|
||||||
* @param string $prefix Use a different table prefix than the one from the configuration.
|
|
||||||
*
|
|
||||||
* @return \PDOStatement The PDOStatement object for this action.
|
|
||||||
*/
|
|
||||||
public static function select($table, $data = null, $order = null, $limit = null, $group = null, $distinct = false, $column = '*', $prefix = null)
|
|
||||||
{
|
|
||||||
return self::$database->select($table, $data, $order, $limit, $group, $distinct, $column, $prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Summary of fetch
|
|
||||||
*
|
|
||||||
* @param string $table The table to select data from.
|
|
||||||
* @param bool $fetchAll Whether all result will be returned or just the first one.
|
|
||||||
* @param array $data The WHERE selectors.
|
|
||||||
* @param array $order The order in which the data is returned.
|
|
||||||
* @param array $limit The limit of what should be returned.
|
|
||||||
* @param array $group The way MySQL will group the data.
|
|
||||||
* @param bool $distinct Only return distinct values.
|
|
||||||
* @param string $column Only select from this column.
|
|
||||||
* @param string $prefix Use a different table prefix than the one from the configuration.
|
|
||||||
*
|
|
||||||
* @return array The data the database returned.
|
|
||||||
*/
|
|
||||||
public static function fetch($table, $fetchAll = true, $data = null, $order = null, $limit = null, $group = null, $distinct = false, $column = '*', $prefix = null)
|
|
||||||
{
|
|
||||||
return self::$database->fetch($table, $fetchAll, $data, $order, $limit, $group, $distinct, $column, $prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert data into the database.
|
|
||||||
*
|
|
||||||
* @param string $table The table that the data will be inserted into.
|
|
||||||
* @param array $data The data that should be stored.
|
|
||||||
* @param string $prefix Use a different table prefix than the one from the configuration.
|
|
||||||
*
|
|
||||||
* @return bool Successfulness.
|
|
||||||
*/
|
|
||||||
public static function insert($table, $data, $prefix = null)
|
|
||||||
{
|
|
||||||
return self::$database->insert($table, $data, $prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update existing database rows.
|
|
||||||
*
|
|
||||||
* @param string $table The table that the updated data will be inserted into.
|
|
||||||
* @param array $data The data that should be stored.
|
|
||||||
* @param string $prefix Use a different table prefix than the one from the configuration.
|
|
||||||
*
|
|
||||||
* @return bool Successfulness.
|
|
||||||
*/
|
|
||||||
public static function update($table, $data, $prefix = null)
|
|
||||||
{
|
|
||||||
return self::$database->update($table, $data, $prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deleted data from the database.
|
|
||||||
*
|
|
||||||
* @param string $table The table that the data will be removed from.
|
|
||||||
* @param array $data The pointers to what should be deleted.
|
|
||||||
* @param string $prefix Use a different table prefix than the one from the configuration.
|
|
||||||
*
|
|
||||||
* @return bool Successfulness.
|
|
||||||
*/
|
|
||||||
public static function delete($table, $data, $prefix = null)
|
|
||||||
{
|
|
||||||
return self::$database->delete($table, $data, $prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the amount of rows from a table.
|
|
||||||
*
|
|
||||||
* @param string $table Table to count in.
|
|
||||||
* @param array $data Data that should be matched.
|
|
||||||
* @param string $prefix Use a different table prefix than the one from the configuration.
|
|
||||||
*
|
|
||||||
* @return array Array containing the SQL result.
|
|
||||||
*/
|
|
||||||
public static function count($table, $data = null, $prefix = null)
|
|
||||||
{
|
|
||||||
return self::$database->count($table, $data, $prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the id of the item that was last inserted into the database.
|
|
||||||
*
|
|
||||||
* @param string $name Sequence of which the last id should be returned.
|
|
||||||
*
|
|
||||||
* @return string The last inserted id.
|
|
||||||
*/
|
|
||||||
public static function lastInsertID($name = null)
|
|
||||||
{
|
|
||||||
return self::$database->lastInsertID($name);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -81,17 +81,18 @@ class File
|
||||||
$mime = (new finfo(FILEINFO_MIME_TYPE))->buffer($data);
|
$mime = (new finfo(FILEINFO_MIME_TYPE))->buffer($data);
|
||||||
|
|
||||||
// Insert it into the database
|
// Insert it into the database
|
||||||
Database::insert('uploads', [
|
DB::prepare('INSERT INTO `{prefix}uploads` (`user_id`, `file_data`, `file_name`, `file_mime`, `file_time`, `file_expire`) VALUES (:id, :data, :name, :mime, :time, :expire)')
|
||||||
'user_id' => $user->id,
|
->execute([
|
||||||
'file_data' => $data,
|
'id' => $user->id,
|
||||||
'file_name' => $name,
|
'data' => $data,
|
||||||
'file_mime' => $mime,
|
'name' => $name,
|
||||||
'file_time' => time(),
|
'mime' => $mime,
|
||||||
'file_expire' => $expire,
|
'time' => time(),
|
||||||
|
'expire' => $expire,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Get the last insert id
|
// Get the last insert id
|
||||||
$id = Database::lastInsertID();
|
$id = (int) DB::lastID();
|
||||||
|
|
||||||
// Return a new File object
|
// Return a new File object
|
||||||
return new File($id);
|
return new File($id);
|
||||||
|
@ -105,17 +106,21 @@ class File
|
||||||
public function __construct($fileId)
|
public function __construct($fileId)
|
||||||
{
|
{
|
||||||
// Attempt to get the database row
|
// Attempt to get the database row
|
||||||
$fileRow = Database::fetch('uploads', false, ['file_id' => [$fileId, '=']]);
|
$fr = DB::prepare('SELECT * FROM `{prefix}uploads` WHERE `file_id` = :id');
|
||||||
|
$fr->execute([
|
||||||
|
'id' => $fileId,
|
||||||
|
]);
|
||||||
|
$fileRow = $fr->fetch();
|
||||||
|
|
||||||
// If anything was returned populate the variables
|
// If anything was returned populate the variables
|
||||||
if ($fileRow) {
|
if ($fileRow) {
|
||||||
$this->id = $fileRow['file_id'];
|
$this->id = $fileRow->file_id;
|
||||||
$this->user = User::construct($fileRow['user_id']);
|
$this->user = User::construct($fileRow->user_id);
|
||||||
$this->data = $fileRow['file_data'];
|
$this->data = $fileRow->file_data;
|
||||||
$this->name = $fileRow['file_name'];
|
$this->name = $fileRow->file_name;
|
||||||
$this->mime = $fileRow['file_mime'];
|
$this->mime = $fileRow->file_mime;
|
||||||
$this->time = $fileRow['file_time'];
|
$this->time = $fileRow->file_time;
|
||||||
$this->expire = $fileRow['file_expire'];
|
$this->expire = $fileRow->file_expire;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,8 +129,9 @@ class File
|
||||||
*/
|
*/
|
||||||
public function delete()
|
public function delete()
|
||||||
{
|
{
|
||||||
Database::delete('uploads', [
|
DB::prepare('DELETE FROM `{prefix}uploads` WHERE `file_id` = :id')
|
||||||
'file_id' => [$this->id, '='],
|
->execute([
|
||||||
|
'id' => $this->id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
namespace Sakura\Forum;
|
namespace Sakura\Forum;
|
||||||
|
|
||||||
use Sakura\Database;
|
use Sakura\Database;
|
||||||
|
use Sakura\DB;
|
||||||
use Sakura\Users;
|
use Sakura\Users;
|
||||||
use Sakura\User;
|
use Sakura\User;
|
||||||
use Sakura\Perms;
|
use Sakura\Perms;
|
||||||
|
@ -118,21 +119,25 @@ class Forum
|
||||||
public function __construct($forumId = 0)
|
public function __construct($forumId = 0)
|
||||||
{
|
{
|
||||||
// Get the row from the database
|
// Get the row from the database
|
||||||
$forumRow = Database::fetch('forums', false, ['forum_id' => [$forumId, '=']]);
|
$forumRow = DB::prepare('SELECT * FROM `{prefix}forums` WHERE `forum_id` = :id');
|
||||||
|
$forumRow->execute([
|
||||||
|
'id' => $forumId,
|
||||||
|
]);
|
||||||
|
$forumRow = $forumRow->fetch();
|
||||||
|
|
||||||
// Create permissions object
|
// Create permissions object
|
||||||
$this->_permissions = new Perms(Perms::FORUM);
|
$this->_permissions = new Perms(Perms::FORUM);
|
||||||
|
|
||||||
// Populate the variables
|
// Populate the variables
|
||||||
if ($forumRow) {
|
if ($forumRow) {
|
||||||
$this->id = $forumRow['forum_id'];
|
$this->id = $forumRow->forum_id;
|
||||||
$this->order = $forumRow['forum_order'];
|
$this->order = $forumRow->forum_order;
|
||||||
$this->name = $forumRow['forum_name'];
|
$this->name = $forumRow->forum_name;
|
||||||
$this->description = $forumRow['forum_desc'];
|
$this->description = $forumRow->forum_desc;
|
||||||
$this->link = $forumRow['forum_link'];
|
$this->link = $forumRow->forum_link;
|
||||||
$this->category = $forumRow['forum_category'];
|
$this->category = $forumRow->forum_category;
|
||||||
$this->type = $forumRow['forum_type'];
|
$this->type = $forumRow->forum_type;
|
||||||
$this->icon = $forumRow['forum_icon'];
|
$this->icon = $forumRow->forum_icon;
|
||||||
} elseif ($forumId != 0) {
|
} elseif ($forumId != 0) {
|
||||||
$this->id = -1;
|
$this->id = -1;
|
||||||
}
|
}
|
||||||
|
@ -173,14 +178,18 @@ class Forum
|
||||||
// Check if _forums is populated
|
// Check if _forums is populated
|
||||||
if (!count($this->_forums)) {
|
if (!count($this->_forums)) {
|
||||||
// Get all rows with the category id set to the forum id
|
// Get all rows with the category id set to the forum id
|
||||||
$forumRows = Database::fetch('forums', true, ['forum_category' => [$this->id, '=']], ['forum_order']);
|
$forumRows = DB::prepare('SELECT `forum_id` FROM `{prefix}forums` WHERE `forum_category` = :cat ORDER BY forum_order');
|
||||||
|
$forumRows->execute([
|
||||||
|
'cat' => $this->id,
|
||||||
|
]);
|
||||||
|
$forumRows = $forumRows->fetchAll();
|
||||||
|
|
||||||
// Create a storage array
|
// Create a storage array
|
||||||
$forums = [];
|
$forums = [];
|
||||||
|
|
||||||
// Create new objects for each forum
|
// Create new objects for each forum
|
||||||
foreach ($forumRows as $forum) {
|
foreach ($forumRows as $forum) {
|
||||||
$forums[$forum['forum_id']] = new Forum($forum['forum_id']);
|
$forums[$forum->forum_id] = new Forum($forum->forum_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_forums = $forums;
|
$this->_forums = $forums;
|
||||||
|
@ -202,19 +211,18 @@ class Forum
|
||||||
// Check if _threads is populated
|
// Check if _threads is populated
|
||||||
if (!count($this->_threads)) {
|
if (!count($this->_threads)) {
|
||||||
// Get all rows with the forum id for this forum
|
// Get all rows with the forum id for this forum
|
||||||
$announcements = Database::fetch('topics', true, ['forum_id' => [$this->id, '='], 'topic_type' => ['2', '=']], ['topic_last_reply', true]);
|
$threadRows = DB::prepare('SELECT * FROM `{prefix}topics` WHERE `forum_id` = :forum ORDER BY `topic_type` DESC, `topic_last_reply` DESC');
|
||||||
$sticky = Database::fetch('topics', true, ['forum_id' => [$this->id, '='], 'topic_type' => ['1', '=']], ['topic_last_reply', true]);
|
$threadRows->execute([
|
||||||
$regular = Database::fetch('topics', true, ['forum_id' => [$this->id, '='], 'topic_type' => ['0', '=']], ['topic_last_reply', true]);
|
'forum' => $this->id,
|
||||||
|
]);
|
||||||
// Combine them into one array
|
$threadRows = $threadRows->fetchAll();
|
||||||
$threadRows = array_merge($announcements, $sticky, $regular);
|
|
||||||
|
|
||||||
// Create a storage array
|
// Create a storage array
|
||||||
$threads = [];
|
$threads = [];
|
||||||
|
|
||||||
// Create new objects for each thread
|
// Create new objects for each thread
|
||||||
foreach ($threadRows as $thread) {
|
foreach ($threadRows as $thread) {
|
||||||
$threads[$thread['topic_id']] = new Thread($thread['topic_id']);
|
$threads[$thread->topic_id] = new Thread($thread->topic_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_threads = $threads;
|
$this->_threads = $threads;
|
||||||
|
@ -236,10 +244,14 @@ class Forum
|
||||||
// Check if _firstPost is set
|
// Check if _firstPost is set
|
||||||
if ($this->_firstPost === null) {
|
if ($this->_firstPost === null) {
|
||||||
// Get the row
|
// Get the row
|
||||||
$firstPost = Database::fetch('posts', false, ['forum_id' => [$this->id, '=']], ['post_id'], [1]);
|
$firstPost = DB::prepare('SELECT `post_id` FROM `{prefix}posts` WHERE `forum_id` = :id ORDER BY `post_id` LIMIT 1');
|
||||||
|
$firstPost->execute([
|
||||||
|
'id' => $this->id,
|
||||||
|
]);
|
||||||
|
$firstPost = $firstPost->fetch();
|
||||||
|
|
||||||
// Create the post object
|
// Create the post object
|
||||||
$post = new Post(empty($firstPost) ? 0 : $firstPost['post_id']);
|
$post = new Post(empty($firstPost) ? 0 : $firstPost->post_id);
|
||||||
|
|
||||||
// Assign it to a "cache" variable
|
// Assign it to a "cache" variable
|
||||||
$this->_firstPost = $post;
|
$this->_firstPost = $post;
|
||||||
|
@ -261,10 +273,14 @@ class Forum
|
||||||
// Check if _lastPost is set
|
// Check if _lastPost is set
|
||||||
if ($this->_lastPost === null) {
|
if ($this->_lastPost === null) {
|
||||||
// Get the row
|
// Get the row
|
||||||
$lastPost = Database::fetch('posts', false, ['forum_id' => [$this->id, '=']], ['post_id', true], [1]);
|
$lastPost = DB::prepare('SELECT `post_id` FROM `{prefix}posts` WHERE `forum_id` = :id ORDER BY `post_id` DESC LIMIT 1');
|
||||||
|
$lastPost->execute([
|
||||||
|
'id' => $this->id,
|
||||||
|
]);
|
||||||
|
$lastPost = $lastPost->fetch();
|
||||||
|
|
||||||
// Create the post object
|
// Create the post object
|
||||||
$post = new Post(empty($lastPost) ? 0 : $lastPost['post_id']);
|
$post = new Post(empty($lastPost) ? 0 : $lastPost->post_id);
|
||||||
|
|
||||||
// Assign it to a "cache" variable
|
// Assign it to a "cache" variable
|
||||||
$this->_lastPost = $post;
|
$this->_lastPost = $post;
|
||||||
|
@ -283,7 +299,11 @@ class Forum
|
||||||
*/
|
*/
|
||||||
public function threadCount()
|
public function threadCount()
|
||||||
{
|
{
|
||||||
return Database::count('topics', ['forum_id' => [$this->id, '=']])[0];
|
$count = DB::prepare('SELECT * FROM `{prefix}topics` WHERE `forum_id` = :id');
|
||||||
|
$count->execute([
|
||||||
|
'id' => $this->id,
|
||||||
|
]);
|
||||||
|
return $count->rowCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -293,7 +313,11 @@ class Forum
|
||||||
*/
|
*/
|
||||||
public function postCount()
|
public function postCount()
|
||||||
{
|
{
|
||||||
return Database::count('posts', ['forum_id' => [$this->id, '=']])[0];
|
$count = DB::prepare('SELECT * FROM `{prefix}posts` WHERE `forum_id` = :id');
|
||||||
|
$count->execute([
|
||||||
|
'id' => $this->id,
|
||||||
|
]);
|
||||||
|
return $count->rowCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -9,6 +9,7 @@ namespace Sakura\Forum;
|
||||||
|
|
||||||
use Sakura\Utils;
|
use Sakura\Utils;
|
||||||
use Sakura\Database;
|
use Sakura\Database;
|
||||||
|
use Sakura\DB;
|
||||||
use Sakura\User;
|
use Sakura\User;
|
||||||
use Sakura\BBcode;
|
use Sakura\BBcode;
|
||||||
use Sakura\Config;
|
use Sakura\Config;
|
||||||
|
@ -114,21 +115,25 @@ class Post
|
||||||
public function __construct($postId)
|
public function __construct($postId)
|
||||||
{
|
{
|
||||||
// Attempt to get the database row
|
// Attempt to get the database row
|
||||||
$postRow = Database::fetch('posts', false, ['post_id' => [$postId, '=']]);
|
$postRow = DB::prepare('SELECT * FROM `{prefix}posts` WHERE `post_id` = :id');
|
||||||
|
$postRow->execute([
|
||||||
|
'id' => $postId,
|
||||||
|
]);
|
||||||
|
$postRow = $postRow->fetch();
|
||||||
|
|
||||||
// Assign data if a row was returned
|
// Assign data if a row was returned
|
||||||
if ($postRow) {
|
if ($postRow) {
|
||||||
$this->id = $postRow['post_id'];
|
$this->id = $postRow->post_id;
|
||||||
$this->thread = $postRow['topic_id'];
|
$this->thread = $postRow->topic_id;
|
||||||
$this->forum = $postRow['forum_id'];
|
$this->forum = $postRow->forum_id;
|
||||||
$this->poster = User::construct($postRow['poster_id']);
|
$this->poster = User::construct($postRow->poster_id);
|
||||||
$this->ip = $postRow['poster_ip'];
|
$this->ip = $postRow->poster_ip;
|
||||||
$this->time = $postRow['post_time'];
|
$this->time = $postRow->post_time;
|
||||||
$this->subject = $postRow['post_subject'];
|
$this->subject = $postRow->post_subject;
|
||||||
$this->text = $postRow['post_text'];
|
$this->text = $postRow->post_text;
|
||||||
$this->editTime = $postRow['post_edit_time'];
|
$this->editTime = $postRow->post_edit_time;
|
||||||
$this->editReason = $postRow['post_edit_reason'];
|
$this->editReason = $postRow->post_edit_reason;
|
||||||
$this->editUser = User::construct($postRow['post_edit_user']);
|
$this->editUser = User::construct($postRow->post_edit_user);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the markup
|
// Parse the markup
|
||||||
|
@ -144,7 +149,7 @@ class Post
|
||||||
* @param int $thread The ID of the thread this post is a reply to.
|
* @param int $thread The ID of the thread this post is a reply to.
|
||||||
* @param mixed $forum The forum this post is a reply in.
|
* @param mixed $forum The forum this post is a reply in.
|
||||||
*
|
*
|
||||||
* @return null|Post Either null, indicating a failure, or the Post object.
|
* @return null|self Either null, indicating a failure, or the Post object.
|
||||||
*/
|
*/
|
||||||
public static function create($subject, $text, User $poster, $thread = 0, $forum = 0)
|
public static function create($subject, $text, User $poster, $thread = 0, $forum = 0)
|
||||||
{
|
{
|
||||||
|
@ -169,18 +174,19 @@ class Post
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert the post
|
// Insert the post
|
||||||
Database::insert('posts', [
|
DB::prepare('INSERT INTO `{prefix}posts` (`topic_id`, `forum_id`, `poster_id`, `poster_ip`, `post_time`, `post_subject`, `post_text`) VALUES (:thread, :forum, :user, :ip, :time, :subject, :text)')
|
||||||
'topic_id' => $thread->id,
|
->execute([
|
||||||
'forum_id' => $thread->forum,
|
'thread' => $thread->id,
|
||||||
'poster_id' => $poster->id,
|
'forum' => $thread->forum,
|
||||||
'poster_ip' => Net::IP(),
|
'user' => $poster->id,
|
||||||
'post_time' => time(),
|
'ip' => Net::IP(),
|
||||||
'post_subject' => $subject,
|
'time' => time(),
|
||||||
'post_text' => $text,
|
'subject' => $subject,
|
||||||
|
'text' => $text,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Get post id
|
// Get post id
|
||||||
$id = Database::lastInsertID();
|
$id = (int) DB::lastID();
|
||||||
|
|
||||||
// Update the last post date
|
// Update the last post date
|
||||||
$thread->lastUpdate();
|
$thread->lastUpdate();
|
||||||
|
@ -208,22 +214,19 @@ class Post
|
||||||
$thread = new Thread($this->thread);
|
$thread = new Thread($this->thread);
|
||||||
|
|
||||||
// Update the post
|
// Update the post
|
||||||
Database::update('posts', [
|
DB::prepare('UPDATE `{prefix}posts` SET `topic_id` = :thread, `forum_id` = :forum, `poster_id` = :user, `poster_ip` = :ip, `post_time` = :time, `post_subject` = :subject, `post_text` = :text, `post_edit_time` = :edit_time, `post_edit_reason` = :edit_reason, `post_edit_user` = :edit_user WHERE `post_id` = :post')
|
||||||
[
|
->execute([
|
||||||
'topic_id' => $thread->id,
|
'post' => $this->id,
|
||||||
'forum_id' => $thread->forum,
|
'thread' => $thread->id,
|
||||||
'poster_id' => $this->poster->id,
|
'forum' => $thread->forum,
|
||||||
'poster_ip' => Net::pton(Net::IP()),
|
'user' => $this->poster->id,
|
||||||
'post_time' => $this->time,
|
'ip' => Net::pton(Net::IP()),
|
||||||
'post_subject' => $this->subject,
|
'time' => $this->time,
|
||||||
'post_text' => $this->text,
|
'subject' => $this->subject,
|
||||||
'post_edit_time' => $this->editTime,
|
'text' => $this->text,
|
||||||
'post_edit_reason' => $this->editReason,
|
'edit_time' => $this->editTime,
|
||||||
'post_edit_user' => $this->editUser->id,
|
'edit_reason' => $this->editReason,
|
||||||
],
|
'edit_user' => $this->editUser->id,
|
||||||
[
|
|
||||||
'post_id' => [$this->id, '='],
|
|
||||||
]
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Return a new post object
|
// Return a new post object
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
namespace Sakura\Forum;
|
namespace Sakura\Forum;
|
||||||
|
|
||||||
use Sakura\Database;
|
use Sakura\Database;
|
||||||
|
use Sakura\DB;
|
||||||
use Sakura\Utils;
|
use Sakura\Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -129,21 +130,25 @@ class Thread
|
||||||
public function __construct($threadId)
|
public function __construct($threadId)
|
||||||
{
|
{
|
||||||
// Attempt to get the database row
|
// Attempt to get the database row
|
||||||
$threadRow = Database::fetch('topics', false, ['topic_id' => [$threadId, '=']]);
|
$threadRow = DB::prepare('SELECT * FROM `{prefix}topics` WHERE `topic_id` = :id');
|
||||||
|
$threadRow->execute([
|
||||||
|
'id' => $threadId,
|
||||||
|
]);
|
||||||
|
$threadRow = $threadRow->fetch();
|
||||||
|
|
||||||
// Assign data if a row was returned
|
// Assign data if a row was returned
|
||||||
if ($threadRow) {
|
if ($threadRow) {
|
||||||
$this->id = $threadRow['topic_id'];
|
$this->id = $threadRow->topic_id;
|
||||||
$this->forum = $threadRow['forum_id'];
|
$this->forum = $threadRow->forum_id;
|
||||||
$this->hidden = (bool) $threadRow['topic_hidden'];
|
$this->hidden = (bool) $threadRow->topic_hidden;
|
||||||
$this->title = $threadRow['topic_title'];
|
$this->title = $threadRow->topic_title;
|
||||||
$this->time = $threadRow['topic_time'];
|
$this->time = $threadRow->topic_time;
|
||||||
$this->timeLimit = $threadRow['topic_time_limit'];
|
$this->timeLimit = $threadRow->topic_time_limit;
|
||||||
$this->views = $threadRow['topic_views'];
|
$this->views = $threadRow->topic_views;
|
||||||
$this->status = $threadRow['topic_status'];
|
$this->status = $threadRow->topic_status;
|
||||||
$this->statusChange = $threadRow['topic_status_change'];
|
$this->statusChange = $threadRow->topic_status_change;
|
||||||
$this->type = $threadRow['topic_type'];
|
$this->type = $threadRow->topic_type;
|
||||||
$this->oldForum = $threadRow['topic_old_forum'];
|
$this->oldForum = $threadRow->topic_old_forum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,21 +160,22 @@ class Thread
|
||||||
* @param mixed $status Status of the thread.
|
* @param mixed $status Status of the thread.
|
||||||
* @param mixed $type Type of thread.
|
* @param mixed $type Type of thread.
|
||||||
*
|
*
|
||||||
* @return Thread The new thread instance.
|
* @return self The new thread instance.
|
||||||
*/
|
*/
|
||||||
public static function create($forum, $title, $status = 0, $type = 0)
|
public static function create($forum, $title, $status = 0, $type = 0)
|
||||||
{
|
{
|
||||||
// Create the database entry
|
// Create the database entry
|
||||||
Database::insert('topics', [
|
DB::prepare('INSERT INTO `{prefix}topics` (`forum_id`, `topic_title`, `topic_time`, `topic_status`, `topic_type`) VALUES (:forum, :title, :time, :status, :type)')
|
||||||
'forum_id' => $forum,
|
->execute([
|
||||||
'topic_title' => $title,
|
'forum' => $forum,
|
||||||
'topic_time' => time(),
|
'title' => $title,
|
||||||
'topic_status' => $status,
|
'time' => time(),
|
||||||
'topic_type' => $type,
|
'status' => $status,
|
||||||
|
'type' => $type,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Return the thread object
|
// Return the thread object
|
||||||
return new Thread(Database::lastInsertID());
|
return new Thread(DB::lastID());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -178,13 +184,15 @@ class Thread
|
||||||
public function delete()
|
public function delete()
|
||||||
{
|
{
|
||||||
// Delete all posts
|
// Delete all posts
|
||||||
Database::delete('posts', [
|
DB::prepare('DELETE FROM `{prefix}posts` WHERE `topic_id` = :id')
|
||||||
'topic_id' => [$this->id, '='],
|
->execute([
|
||||||
|
'id' => $this->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Delete thread meta
|
// Delete thread meta
|
||||||
Database::delete('topics', [
|
DB::prepare('DELETE FROM `{prefix}topics` WHERE `topic_id` = :id')
|
||||||
'topic_id' => [$this->id, '='],
|
->execute([
|
||||||
|
'id' => $this->id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,48 +205,39 @@ class Thread
|
||||||
public function move($forum, $setOld = true)
|
public function move($forum, $setOld = true)
|
||||||
{
|
{
|
||||||
// Update all posts
|
// Update all posts
|
||||||
Database::update('posts', [
|
DB::prepare('UPDATE `{prefix}posts` SET `forum_id` = :forum WHERE `topic_id` = :thread')
|
||||||
[
|
->execute([
|
||||||
'forum_id' => $forum,
|
'forum' => $forum,
|
||||||
],
|
'thread' => $this->id,
|
||||||
[
|
|
||||||
'topic_id' => [$this->id, '='],
|
|
||||||
]
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Update thread meta
|
// Update thread meta
|
||||||
Database::update('topics', [
|
DB::prepare('UPDATE `{prefix}topics` SET `forum_id` = :forum, `topic_old_forum` = :old WHERE `topic_id` = :thread')
|
||||||
[
|
->execute([
|
||||||
'forum_id' => $forum,
|
'forum' => $forum,
|
||||||
'topic_old_forum' => ($setOld ? $this->forum : 0),
|
'old' => ($setOld ? $this->forum : 0),
|
||||||
],
|
'thread' => $this->id,
|
||||||
[
|
|
||||||
'topic_id' => [$this->id, '='],
|
|
||||||
]
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the thread data.
|
* Update the thread data.
|
||||||
*
|
*
|
||||||
* @return Thread The updated thread.
|
* @return self The updated thread.
|
||||||
*/
|
*/
|
||||||
public function update()
|
public function update()
|
||||||
{
|
{
|
||||||
// Update row
|
// Update row
|
||||||
Database::update('topics', [
|
DB::prepare('UPDATE `{prefix}topics` SET `topic_hidden` = :hidden, `topic_title` = :title, `topic_time_limit` = :limit, `topic_status` = :status, `topic_status_change` = :change, `topic_type` = :type, `topic_old_forum` = :old WHERE `topic_id` = :id')
|
||||||
[
|
->execute([
|
||||||
'topic_hidden' => $this->hidden,
|
'hidden' => $this->hidden,
|
||||||
'topic_title' => $this->title,
|
'title' => $this->title,
|
||||||
'topic_time_limit' => $this->timeLimit,
|
'limit' => $this->timeLimit,
|
||||||
'topic_status' => $this->status,
|
'status' => $this->status,
|
||||||
'topic_status_change' => $this->statusChange,
|
'change' => $this->statusChange,
|
||||||
'topic_type' => $this->type,
|
'type' => $this->type,
|
||||||
'topic_old_forum' => $this->oldForum,
|
'old' => $this->oldForum,
|
||||||
],
|
'id' => $this->id,
|
||||||
[
|
|
||||||
'topic_id' => [$this->id, '='],
|
|
||||||
]
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Return new object
|
// Return new object
|
||||||
|
@ -255,14 +254,18 @@ class Thread
|
||||||
// Check if _posts is something
|
// Check if _posts is something
|
||||||
if (!count($this->_posts)) {
|
if (!count($this->_posts)) {
|
||||||
// Get all rows with the thread id
|
// Get all rows with the thread id
|
||||||
$postRows = Database::fetch('posts', true, ['topic_id' => [$this->id, '=']]);
|
$postRows = DB::prepare('SELECT `post_id` FROM `{prefix}posts` WHERE `topic_id` = :thread');
|
||||||
|
$postRows->execute([
|
||||||
|
'thread' => $this->id,
|
||||||
|
]);
|
||||||
|
$postRows = $postRows->fetchAll();
|
||||||
|
|
||||||
// Create a storage array
|
// Create a storage array
|
||||||
$posts = [];
|
$posts = [];
|
||||||
|
|
||||||
// Create new post objects for each post
|
// Create new post objects for each post
|
||||||
foreach ($postRows as $post) {
|
foreach ($postRows as $post) {
|
||||||
$posts[$post['post_id']] = new Post($post['post_id']);
|
$posts[$post->post_id] = new Post($post->post_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_posts = $posts;
|
$this->_posts = $posts;
|
||||||
|
@ -287,10 +290,14 @@ class Thread
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the row from the database
|
// Get the row from the database
|
||||||
$post = Database::fetch('posts', false, ['topic_id' => [$this->id, '=']], ['post_id'], [1]);
|
$post = DB::prepare('SELECT `post_id` FROM `{prefix}posts` WHERE `topic_id` = :thread ORDER BY `post_id` LIMIT 1');
|
||||||
|
$post->execute([
|
||||||
|
'thread' => $this->id,
|
||||||
|
]);
|
||||||
|
$post = $post->fetch();
|
||||||
|
|
||||||
// Create the post class
|
// Create the post class
|
||||||
$post = new Post($post ? $post['post_id'] : 0);
|
$post = new Post($post ? $post->post_id : 0);
|
||||||
|
|
||||||
// Assign it to the cache var
|
// Assign it to the cache var
|
||||||
$this->_firstPost = $post;
|
$this->_firstPost = $post;
|
||||||
|
@ -312,10 +319,14 @@ class Thread
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the row from the database
|
// Get the row from the database
|
||||||
$post = Database::fetch('posts', false, ['topic_id' => [$this->id, '=']], ['post_id', true], [1]);
|
$post = DB::prepare('SELECT `post_id` FROM `{prefix}posts` WHERE `topic_id` = :thread ORDER BY `post_id` DESC LIMIT 1');
|
||||||
|
$post->execute([
|
||||||
|
'thread' => $this->id,
|
||||||
|
]);
|
||||||
|
$post = $post->fetch();
|
||||||
|
|
||||||
// Create the post class
|
// Create the post class
|
||||||
$post = new Post($post ? $post['post_id'] : 0);
|
$post = new Post($post ? $post->post_id : 0);
|
||||||
|
|
||||||
// Assign it to the cache var
|
// Assign it to the cache var
|
||||||
$this->_lastPost = $post;
|
$this->_lastPost = $post;
|
||||||
|
@ -331,7 +342,11 @@ class Thread
|
||||||
*/
|
*/
|
||||||
public function replyCount()
|
public function replyCount()
|
||||||
{
|
{
|
||||||
return Database::count('posts', ['topic_id' => [$this->id, '=']])[0];
|
$count = DB::prepare('SELECT * FROM `{prefix}posts` WHERE `topic_id` = :thread');
|
||||||
|
$count->execute([
|
||||||
|
'thread' => $this->id,
|
||||||
|
]);
|
||||||
|
return $count->rowCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -344,10 +359,15 @@ class Thread
|
||||||
public function unread($user)
|
public function unread($user)
|
||||||
{
|
{
|
||||||
// Attempt to get track row from the database
|
// Attempt to get track row from the database
|
||||||
$track = Database::fetch('topics_track', false, ['user_id' => [$user, '='], 'topic_id' => [$this->id, '='], 'mark_time' => [$this->lastPost()->time, '>']]);
|
$track = DB::prepare('SELECT * FROM `{prefix}topics_track` WHERE `user_id` = :user AND `topic_id` = :thread AND `mark_time` > :last');
|
||||||
|
$track->execute([
|
||||||
|
'user' => $user,
|
||||||
|
'thread' => $this->id,
|
||||||
|
'last' => $this->lastPost()->time,
|
||||||
|
]);
|
||||||
|
|
||||||
// If nothing was returned it's obvious that the status is unread
|
// If nothing was returned it's obvious that the status is unread
|
||||||
if (!$track) {
|
if (!$track->rowCount()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,26 +383,29 @@ class Thread
|
||||||
public function trackUpdate($user)
|
public function trackUpdate($user)
|
||||||
{
|
{
|
||||||
// Check if we already have a track record
|
// Check if we already have a track record
|
||||||
$track = Database::fetch('topics_track', false, ['user_id' => [$user, '='], 'topic_id' => [$this->id, '='], 'forum_id' => [$this->forum, '=']]);
|
$track = DB::prepare('SELECT * FROM `{prefix}topics_track` WHERE `user_id` = :user AND `topic_id` = :thread AND `forum_id` = :forum');
|
||||||
|
$track->execute([
|
||||||
|
'user' => $user,
|
||||||
|
'thread' => $this->id,
|
||||||
|
'forum' => $this->forum,
|
||||||
|
]);
|
||||||
|
|
||||||
// If so update it
|
// If so update it
|
||||||
if ($track) {
|
if ($track->rowCount()) {
|
||||||
Database::update('topics_track', [
|
DB::prepare('UPDATE `{prefix}topics_track` SET `mark_time` = :time WHERE `user_id` = :user AND `topic_id` = :thread')
|
||||||
[
|
->execute([
|
||||||
'mark_time' => time(),
|
'user' => $user,
|
||||||
],
|
'thread' => $this->id,
|
||||||
[
|
'time' => time(),
|
||||||
'user_id' => [$user, '='],
|
|
||||||
'topic_id' => [$this->id, '='],
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
// If not create a new record
|
// If not create a new record
|
||||||
Database::insert('topics_track', [
|
DB::prepare('INSERT INTO `{prefix}topics_track` (`user_id`, `topic_id`, `forum_id`, `mark_time`) VALUES (:user, :thread, :forum, :time)')
|
||||||
'user_id' => $user,
|
->execute([
|
||||||
'topic_id' => $this->id,
|
'user' => $user,
|
||||||
'forum_id' => $this->forum,
|
'thread' => $this->id,
|
||||||
'mark_time' => time(),
|
'forum' => $this->forum,
|
||||||
|
'time' => time(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -392,13 +415,10 @@ class Thread
|
||||||
*/
|
*/
|
||||||
public function viewsUpdate()
|
public function viewsUpdate()
|
||||||
{
|
{
|
||||||
Database::update('topics', [
|
DB::prepare('UPDATE `{prefix}topics` SET `topic_views` = :views WHERE `topic_id` = :thread')
|
||||||
[
|
->execute([
|
||||||
'topic_views' => $this->views + 1,
|
'views' => $this->views + 1,
|
||||||
],
|
'thread' => $this->id,
|
||||||
[
|
|
||||||
'topic_id' => [$this->id, '='],
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,13 +427,10 @@ class Thread
|
||||||
*/
|
*/
|
||||||
public function lastUpdate()
|
public function lastUpdate()
|
||||||
{
|
{
|
||||||
Database::update('topics', [
|
DB::prepare('UPDATE `{prefix}topics` SET `topic_last_reply` = :last WHERE `topic_id` = :thread')
|
||||||
[
|
->execute([
|
||||||
'topic_last_reply' => time(),
|
'last' => time(),
|
||||||
],
|
'thread' => $this->id,
|
||||||
[
|
|
||||||
'topic_id' => [$this->id, '='],
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,11 @@ class News
|
||||||
{
|
{
|
||||||
|
|
||||||
// Get the news posts and assign them to $posts
|
// Get the news posts and assign them to $posts
|
||||||
$posts = Database::fetch('news', true, ['news_category' => [$category, '=']], ['news_id', true]);
|
$posts = DB::prepare('SELECT * FROM `{prefix}news` WHERE `news_category` = :cat ORDER BY `news_id` DESC');
|
||||||
|
$posts->execute([
|
||||||
|
'cat' => $category,
|
||||||
|
]);
|
||||||
|
$posts = $posts->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// Attach poster data
|
// Attach poster data
|
||||||
foreach ($posts as $post) {
|
foreach ($posts as $post) {
|
||||||
|
|
|
@ -93,11 +93,30 @@ class Perms
|
||||||
*/
|
*/
|
||||||
public function rank($rid, $conditions = [], $perm = 0)
|
public function rank($rid, $conditions = [], $perm = 0)
|
||||||
{
|
{
|
||||||
// Merge rank id and additional conditions
|
// Build statement
|
||||||
$conditions = array_merge(['rank_id' => [$rid, '='], 'user_id' => [0, '=']], $conditions);
|
$stmt = "SELECT * FROM `{prefix}{$this->table}` WHERE `rank_id` = :rank AND `user_id` = 0";
|
||||||
|
|
||||||
|
// Append additional conditionals (DBWrapper v1 format, except OR is ignored)
|
||||||
|
foreach ($conditions as $column => $value) {
|
||||||
|
$stmt .= " AND `{$column}` {$value[1]} :_retarded_{$column}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare the statement
|
||||||
|
$get = DB::prepare($stmt);
|
||||||
|
|
||||||
|
// Bind rank
|
||||||
|
$get->bindParam('rank', $rid);
|
||||||
|
|
||||||
|
// Bind additionals
|
||||||
|
foreach ($conditions as $column => $value) {
|
||||||
|
$get->bindParam("_retarded_{$column}", $value[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute!
|
||||||
|
$get->execute();
|
||||||
|
|
||||||
// Fetch from the db
|
// Fetch from the db
|
||||||
$get = Database::fetch($this->table, false, $conditions);
|
$get = $get->fetch(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// Check if anything was returned
|
// Check if anything was returned
|
||||||
if ($get && array_key_exists($this->column, $get) && $get['rank_id']) {
|
if ($get && array_key_exists($this->column, $get) && $get['rank_id']) {
|
||||||
|
@ -128,11 +147,30 @@ class Perms
|
||||||
$perm = $perm | $this->rank($rank, $conditions, $perm);
|
$perm = $perm | $this->rank($rank, $conditions, $perm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge user id and additional conditions
|
// Build statement
|
||||||
$conditions = array_merge(['user_id' => [$uid, '='], 'rank_id' => [0, '=']], $conditions);
|
$stmt = "SELECT * FROM `{prefix}{$this->table}` WHERE `rank_id` = 0 AND `user_id` = :user";
|
||||||
|
|
||||||
|
// Append additional conditionals (DBWrapper v1 format, except OR is ignored)
|
||||||
|
foreach ($conditions as $column => $value) {
|
||||||
|
$stmt .= " AND `{$column}` {$value[1]} :_retarded_{$column}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare the statement
|
||||||
|
$get = DB::prepare($stmt);
|
||||||
|
|
||||||
|
// Bind rank
|
||||||
|
$get->bindParam('user', $uid);
|
||||||
|
|
||||||
|
// Bind additionals
|
||||||
|
foreach ($conditions as $column => $value) {
|
||||||
|
$get->bindParam("_retarded_{$column}", $value[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute!
|
||||||
|
$get->execute();
|
||||||
|
|
||||||
// Fetch from the db
|
// Fetch from the db
|
||||||
$get = Database::fetch($this->table, false, $conditions);
|
$get = $get->fetch(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// Check if anything was returned
|
// Check if anything was returned
|
||||||
if ($get && array_key_exists($this->column, $get) && $get['user_id']) {
|
if ($get && array_key_exists($this->column, $get) && $get['user_id']) {
|
||||||
|
|
|
@ -117,24 +117,22 @@ class Rank
|
||||||
{
|
{
|
||||||
|
|
||||||
// Get the rank database row
|
// Get the rank database row
|
||||||
$rankRow = Database::fetch(
|
$rankRow = DB::prepare('SELECT * FROM `{prefix}ranks` WHERE `rank_id` = :id');
|
||||||
'ranks',
|
$rankRow->execute([
|
||||||
false,
|
'id' => $rid,
|
||||||
[
|
]);
|
||||||
'rank_id' => [$rid, '=', true],
|
$rankRow = $rankRow->fetch();
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Check if the rank actually exists
|
// Check if the rank actually exists
|
||||||
if ($rankRow) {
|
if ($rankRow) {
|
||||||
$this->id = $rankRow['rank_id'];
|
$this->id = $rankRow->rank_id;
|
||||||
$this->name = $rankRow['rank_name'];
|
$this->name = $rankRow->rank_name;
|
||||||
$this->hierarchy = $rankRow['rank_hierarchy'];
|
$this->hierarchy = $rankRow->rank_hierarchy;
|
||||||
$this->multiple = $rankRow['rank_multiple'];
|
$this->multiple = $rankRow->rank_multiple;
|
||||||
$this->hidden = (bool) $rankRow['rank_hidden'];
|
$this->hidden = (bool) $rankRow->rank_hidden;
|
||||||
$this->colour = $rankRow['rank_colour'];
|
$this->colour = $rankRow->rank_colour;
|
||||||
$this->description = $rankRow['rank_description'];
|
$this->description = $rankRow->rank_description;
|
||||||
$this->title = $rankRow['rank_title'];
|
$this->title = $rankRow->rank_title;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init the permissions
|
// Init the permissions
|
||||||
|
@ -191,7 +189,11 @@ class Rank
|
||||||
public function users($justIds = false)
|
public function users($justIds = false)
|
||||||
{
|
{
|
||||||
// Fetch all users part of this rank
|
// Fetch all users part of this rank
|
||||||
$userIds = array_column(Database::fetch('user_ranks', true, ['rank_id' => [$this->id, '=']]), 'user_id');
|
$fetch = DB::prepare('SELECT `user_id` FROM `{prefix}user_ranks` WHERE `rank_id` = :id');
|
||||||
|
$fetch->execute([
|
||||||
|
'id' => $this->id,
|
||||||
|
]);
|
||||||
|
$userIds = array_column($fetch->fetchAll(\PDO::FETCH_ASSOC), 'user_id');
|
||||||
|
|
||||||
// Just return that if we were asked for just the ids
|
// Just return that if we were asked for just the ids
|
||||||
if ($justIds) {
|
if ($justIds) {
|
||||||
|
|
|
@ -53,9 +53,10 @@ class Session
|
||||||
public function destroy()
|
public function destroy()
|
||||||
{
|
{
|
||||||
// Invalidate the session key
|
// Invalidate the session key
|
||||||
Database::delete('sessions', [
|
DB::prepare('DELETE FROM `{prefix}sessions` WHERE `session_key` = :key AND `user_id` = :user')
|
||||||
'session_key' => [$this->sessionId, '='],
|
->execute([
|
||||||
'user_id' => [$this->userId, '='],
|
'key' => $this->sessionId,
|
||||||
|
'user' => $this->userId,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Unset userId and sessionId
|
// Unset userId and sessionId
|
||||||
|
@ -74,7 +75,10 @@ class Session
|
||||||
public function destroyAll()
|
public function destroyAll()
|
||||||
{
|
{
|
||||||
// Delete all database entries with this user in it
|
// Delete all database entries with this user in it
|
||||||
Database::delete('sessions', ['user_id' => [$this->userId, '=']]);
|
DB::prepare('DELETE FROM `{prefix}sessions` WHERE `user_id` = :user')
|
||||||
|
->execute([
|
||||||
|
'user' => $this->userId,
|
||||||
|
]);
|
||||||
|
|
||||||
// Destroy this session to finish it off
|
// Destroy this session to finish it off
|
||||||
$this->destroy();
|
$this->destroy();
|
||||||
|
@ -93,14 +97,15 @@ class Session
|
||||||
$session = hash('sha256', $this->userId . base64_encode('sakura' . mt_rand(0, 99999999)) . time());
|
$session = hash('sha256', $this->userId . base64_encode('sakura' . mt_rand(0, 99999999)) . time());
|
||||||
|
|
||||||
// Insert the session into the database
|
// Insert the session into the database
|
||||||
Database::insert('sessions', [
|
DB::prepare('INSERT INTO `{prefix}sessions` (`user_id`, `user_ip`, `user_agent`, `session_key`, `session_start`, `session_expire`, `session_remember`) VALUES (:id, :ip, :agent, :key, :start, :end, :remember)')
|
||||||
'user_id' => $this->userId,
|
->execute([
|
||||||
'user_ip' => Net::pton(Net::IP()),
|
'id' => $this->userId,
|
||||||
'user_agent' => Utils::cleanString(isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'No user agent header.'),
|
'ip' => Net::pton(Net::IP()),
|
||||||
'session_key' => $session,
|
'agent' => Utils::cleanString(isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'No user agent header.'),
|
||||||
'session_start' => time(),
|
'key' => $session,
|
||||||
'session_expire' => time() + 604800,
|
'start' => time(),
|
||||||
'session_remember' => $permanent ? '1' : '0',
|
'end' => time() + 604800,
|
||||||
|
'remember' => $permanent ? '1' : '0',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Return the session key
|
// Return the session key
|
||||||
|
@ -115,10 +120,12 @@ class Session
|
||||||
public function validate()
|
public function validate()
|
||||||
{
|
{
|
||||||
// Get session from database
|
// Get session from database
|
||||||
$session = Database::fetch('sessions', false, [
|
$session = DB::prepare('SELECT * FROM `{prefix}sessions` WHERE `user_id` = :user AND `session_key` = :key');
|
||||||
'user_id' => [$this->userId, '='],
|
$session->execute([
|
||||||
'session_key' => [$this->sessionId, '='],
|
'user' => $this->userId,
|
||||||
|
'key' => $this->sessionId,
|
||||||
]);
|
]);
|
||||||
|
$session = $session->fetch();
|
||||||
|
|
||||||
// Check if we actually got something in return
|
// Check if we actually got something in return
|
||||||
if (!$session) {
|
if (!$session) {
|
||||||
|
@ -126,13 +133,13 @@ class Session
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the session expired
|
// Check if the session expired
|
||||||
if ($session['session_expire'] < time()) {
|
if ($session->session_expire < time()) {
|
||||||
// ...and return false
|
// ...and return false
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// IP Check
|
// IP Check
|
||||||
$ipCheck = false;// Config::get('session_check');
|
$ipCheck = false; // Forced disabled due to incompatibility with the Net class. -- Config::get('session_check');
|
||||||
|
|
||||||
// Origin checking
|
// Origin checking
|
||||||
if ($ipCheck) {
|
if ($ipCheck) {
|
||||||
|
@ -178,18 +185,15 @@ class Session
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the remember flag is set extend the session time
|
// If the remember flag is set extend the session time
|
||||||
if ($session['session_remember']) {
|
if ($session->session_remember) {
|
||||||
Database::update('sessions', [
|
DB::prepare('UPDATE `{prefix}sessions` SET `session_expire` = :expire WHERE `session_id` = :id')
|
||||||
[
|
->execute([
|
||||||
'session_expire' => time() + 604800,
|
'expire' => time() + 604800,
|
||||||
],
|
'id' => $session->session_id,
|
||||||
[
|
|
||||||
'session_id' => [$session['session_id'], '='],
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return 2 if the remember flag is set and return 1 if not
|
// Return 2 if the remember flag is set and return 1 if not
|
||||||
return $session['session_remember'] ? 2 : 1;
|
return $session->session_remember ? 2 : 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,24 +258,25 @@ class User
|
||||||
$password = Hashing::createHash($password);
|
$password = Hashing::createHash($password);
|
||||||
|
|
||||||
// Insert the user into the database
|
// Insert the user into the database
|
||||||
Database::insert('users', [
|
DB::prepare('INSERT INTO `{prefix}users` (`username`, `username_clean`, `password_hash`, `password_salt`, `password_algo`, `password_iter`, `email`, `rank_main`, `register_ip`, `last_ip`, `user_registered`, `user_last_online`, `user_country`) VALUES (:uname, :uname_clean, :pw_hash, :pw_salt, :pw_algo, :pw_iter, :email, :rank, :r_ip, :l_ip, :registered, :l_online, :country)')
|
||||||
'username' => $username,
|
->execute([
|
||||||
'username_clean' => $usernameClean,
|
'uname' => $username,
|
||||||
'password_hash' => $password[3],
|
'uname_clean' => $usernameClean,
|
||||||
'password_salt' => $password[2],
|
'pw_hash' => $password[3],
|
||||||
'password_algo' => $password[0],
|
'pw_salt' => $password[2],
|
||||||
'password_iter' => $password[1],
|
'pw_algo' => $password[0],
|
||||||
|
'pw_iter' => $password[1],
|
||||||
'email' => $emailClean,
|
'email' => $emailClean,
|
||||||
'rank_main' => 0,
|
'rank' => 0,
|
||||||
'register_ip' => Net::pton(Net::IP()),
|
'r_ip' => Net::pton(Net::IP()),
|
||||||
'last_ip' => Net::pton(Net::IP()),
|
'l_ip' => Net::pton(Net::IP()),
|
||||||
'user_registered' => time(),
|
'registered' => time(),
|
||||||
'user_last_online' => 0,
|
'l_online' => 0,
|
||||||
'user_country' => Utils::getCountryCode(),
|
'country' => Utils::getCountryCode(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Get the last id
|
// Get the last id
|
||||||
$userId = Database::lastInsertID();
|
$userId = DB::lastID();
|
||||||
|
|
||||||
// Create a user object
|
// Create a user object
|
||||||
$user = self::construct($userId);
|
$user = self::construct($userId);
|
||||||
|
@ -298,49 +299,51 @@ class User
|
||||||
private function __construct($uid)
|
private function __construct($uid)
|
||||||
{
|
{
|
||||||
// Get the user database row
|
// Get the user database row
|
||||||
$userRow = Database::fetch(
|
$userRow = DB::prepare('SELECT * FROM `{prefix}users` WHERE `user_id` = :id OR `username_clean` = :clean');
|
||||||
'users',
|
$userRow->execute([
|
||||||
false,
|
'id' => $uid,
|
||||||
[
|
'clean' => Utils::cleanString($uid, true, true),
|
||||||
'user_id' => [$uid, '=', true],
|
]);
|
||||||
'username_clean' => [Utils::cleanString($uid, true), '=', true],
|
$userRow = $userRow->fetch();
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Populate the variables
|
// Populate the variables
|
||||||
if ($userRow) {
|
if ($userRow) {
|
||||||
$this->id = $userRow['user_id'];
|
$this->id = $userRow->user_id;
|
||||||
$this->username = $userRow['username'];
|
$this->username = $userRow->username;
|
||||||
$this->usernameClean = $userRow['username_clean'];
|
$this->usernameClean = $userRow->username_clean;
|
||||||
$this->passwordHash = $userRow['password_hash'];
|
$this->passwordHash = $userRow->password_hash;
|
||||||
$this->passwordSalt = $userRow['password_salt'];
|
$this->passwordSalt = $userRow->password_salt;
|
||||||
$this->passwordAlgo = $userRow['password_algo'];
|
$this->passwordAlgo = $userRow->password_algo;
|
||||||
$this->passwordIter = $userRow['password_iter'];
|
$this->passwordIter = $userRow->password_iter;
|
||||||
$this->passwordChan = $userRow['password_chan'];
|
$this->passwordChan = $userRow->password_chan;
|
||||||
$this->email = $userRow['email'];
|
$this->email = $userRow->email;
|
||||||
$this->mainRankId = $userRow['rank_main'];
|
$this->mainRankId = $userRow->rank_main;
|
||||||
$this->colour = $userRow['user_colour'];
|
$this->colour = $userRow->user_colour;
|
||||||
$this->registerIp = $userRow['register_ip'];
|
$this->registerIp = $userRow->register_ip;
|
||||||
$this->lastIp = $userRow['last_ip'];
|
$this->lastIp = $userRow->last_ip;
|
||||||
$this->title = $userRow['user_title'];
|
$this->title = $userRow->user_title;
|
||||||
$this->registered = $userRow['user_registered'];
|
$this->registered = $userRow->user_registered;
|
||||||
$this->lastOnline = $userRow['user_last_online'];
|
$this->lastOnline = $userRow->user_last_online;
|
||||||
$this->birthday = $userRow['user_birthday'];
|
$this->birthday = $userRow->user_birthday;
|
||||||
$this->country = $userRow['user_country'];
|
$this->country = $userRow->user_country;
|
||||||
$this->avatar = $userRow['user_avatar'];
|
$this->avatar = $userRow->user_avatar;
|
||||||
$this->background = $userRow['user_background'];
|
$this->background = $userRow->user_background;
|
||||||
$this->header = $userRow['user_header'];
|
$this->header = $userRow->user_header;
|
||||||
$this->page = $userRow['user_page'];
|
$this->page = $userRow->user_page;
|
||||||
$this->signature = $userRow['user_signature'];
|
$this->signature = $userRow->user_signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all ranks
|
// Get all ranks
|
||||||
$ranks = Database::fetch('user_ranks', true, ['user_id' => [$this->id, '=']]);
|
$ranks = DB::prepare('SELECT * FROM `{prefix}user_ranks` WHERE `user_id` = :id');
|
||||||
|
$ranks->execute([
|
||||||
|
'id' => $this->id,
|
||||||
|
]);
|
||||||
|
$ranks = $ranks->fetchAll();
|
||||||
|
|
||||||
// Get the rows for all the ranks
|
// Get the rows for all the ranks
|
||||||
foreach ($ranks as $rank) {
|
foreach ($ranks as $rank) {
|
||||||
// Store the database row in the array
|
// Store the database row in the array
|
||||||
$this->ranks[$rank['rank_id']] = Rank::construct($rank['rank_id']);
|
$this->ranks[$rank->rank_id] = Rank::construct($rank->rank_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if ranks were set
|
// Check if ranks were set
|
||||||
|
@ -423,10 +426,13 @@ class User
|
||||||
public function isOnline()
|
public function isOnline()
|
||||||
{
|
{
|
||||||
// Get all sessions
|
// Get all sessions
|
||||||
$sessions = Database::fetch('sessions', true, ['user_id' => [$this->id, '=']]);
|
$sessions = DB::prepare('SELECT `user_id` FROM `{prefix}sessions` WHERE `user_id` = :id');
|
||||||
|
$sessions->execute([
|
||||||
|
'id' => $this->id,
|
||||||
|
]);
|
||||||
|
|
||||||
// If there's no entries just straight up return false
|
// If there's no entries just straight up return false
|
||||||
if (!$sessions) {
|
if (!$sessions->rowCount()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,19 +447,19 @@ class User
|
||||||
*/
|
*/
|
||||||
public function forumStats()
|
public function forumStats()
|
||||||
{
|
{
|
||||||
|
$posts = DB::prepare('SELECT * FROM `{prefix}posts` WHERE `poster_id` = :id');
|
||||||
|
$posts->execute([
|
||||||
|
'id' => $this->id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$threads = DB::prepare('SELECT DISTINCT * FROM `{prefix}posts` WHERE `poster_id` = :id GROUP BY `topic_id` ORDER BY `post_time`');
|
||||||
|
$threads->execute([
|
||||||
|
'id' => $this->id,
|
||||||
|
]);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'posts' => Database::count(
|
'posts' => $posts->rowCount(),
|
||||||
'posts',
|
'topics' => $threads->rowCount(),
|
||||||
['poster_id' => [$this->id, '=']]
|
|
||||||
)[0],
|
|
||||||
'topics' => count(Database::fetch(
|
|
||||||
'posts',
|
|
||||||
true,
|
|
||||||
['poster_id' => [$this->id, '=']],
|
|
||||||
['post_time'],
|
|
||||||
null,
|
|
||||||
['topic_id']
|
|
||||||
)),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,9 +482,10 @@ class User
|
||||||
|
|
||||||
// Save to the database
|
// Save to the database
|
||||||
foreach ($ranks as $rank) {
|
foreach ($ranks as $rank) {
|
||||||
Database::insert('user_ranks', [
|
DB::prepare('INSERT INTO `{prefix}ranks` (`rank_id`, `user_id`) VALUES (:rank, :user)')
|
||||||
'rank_id' => $rank,
|
->execute([
|
||||||
'user_id' => $this->id,
|
'rank' => $rank,
|
||||||
|
'user' => $this->id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -495,7 +502,11 @@ class User
|
||||||
|
|
||||||
// Iterate over the ranks
|
// Iterate over the ranks
|
||||||
foreach ($remove as $rank) {
|
foreach ($remove as $rank) {
|
||||||
Database::delete('user_ranks', ['user_id' => [$this->id, '='], 'rank_id' => [$rank, '=']]);
|
DB::prepare('DELETE FROM `{prefix}user_ranks` WHERE `user_id` = :user AND `rank_id` = :rank')
|
||||||
|
->execute([
|
||||||
|
'user' => $this->id,
|
||||||
|
'rank' => $rank,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,13 +520,10 @@ class User
|
||||||
public function setMainRank($rank)
|
public function setMainRank($rank)
|
||||||
{
|
{
|
||||||
// If it does exist update their row
|
// If it does exist update their row
|
||||||
Database::update('users', [
|
DB::prepare('UPDATE `{prefix}users` SET `rank_main` = :rank WHERE `user_id` = :id')
|
||||||
[
|
->execute([
|
||||||
'rank_main' => $rank,
|
'rank' => $rank,
|
||||||
],
|
'id' => $this->id,
|
||||||
[
|
|
||||||
'user_id' => [$this->id, '='],
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Return true if everything was successful
|
// Return true if everything was successful
|
||||||
|
@ -571,10 +579,11 @@ class User
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add friend
|
// Add friend
|
||||||
Database::insert('friends', [
|
DB::prepare('INSERT INTO `{prefix}friends` (`user_id`, `friend_id`, `friend_timestamp`) VALUES (:user, :friend, :time)')
|
||||||
'user_id' => $this->id,
|
->execute([
|
||||||
'friend_id' => $uid,
|
'user' => $this->id,
|
||||||
'friend_timestamp' => time(),
|
'friend' => $uid,
|
||||||
|
'time' => time(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Return true because yay
|
// Return true because yay
|
||||||
|
@ -599,17 +608,20 @@ class User
|
||||||
return [0, 'USER_NOT_EXIST'];
|
return [0, 'USER_NOT_EXIST'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prepare the statement
|
||||||
|
$rem = DB::prepare('DELETE FROM `{prefix}friends` WHERE `user_id` = :user AND `friend_id` = :friend');
|
||||||
|
|
||||||
// Remove friend
|
// Remove friend
|
||||||
Database::delete('friends', [
|
$rem->execute([
|
||||||
'user_id' => [$this->id, '='],
|
'user' => $this->id,
|
||||||
'friend_id' => [$uid, '='],
|
'friend' => $uid,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Attempt to remove the request
|
// Attempt to remove the request
|
||||||
if ($deleteRequest) {
|
if ($deleteRequest) {
|
||||||
Database::delete('friends', [
|
$rem->execute([
|
||||||
'friend_id' => [$this->id, '='],
|
'user' => $uid,
|
||||||
'user_id' => [$uid, '='],
|
'friend' => $this->id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,16 +639,19 @@ class User
|
||||||
public function isFriends($with)
|
public function isFriends($with)
|
||||||
{
|
{
|
||||||
// Accepted from this user
|
// Accepted from this user
|
||||||
$user = Database::count('friends', [
|
$get = DB::prepare('SELECT * FROM `{prefix}friends` WHERE `user_id` = :user AND `friend_id` = :friend');
|
||||||
'user_id' => [$this->id, '='],
|
$get->execute([
|
||||||
'friend_id' => [$with, '='],
|
'user' => $this->id,
|
||||||
])[0];
|
'friend' => $with,
|
||||||
|
]);
|
||||||
|
$user = $get->rowCount();
|
||||||
|
|
||||||
// And the other user
|
// And the other user
|
||||||
$friend = Database::count('friends', [
|
$get->execute([
|
||||||
'user_id' => [$with, '='],
|
'user' => $with,
|
||||||
'friend_id' => [$this->id, '='],
|
'friend' => $this->id,
|
||||||
])[0];
|
]);
|
||||||
|
$friend = $get->rowCount();
|
||||||
|
|
||||||
if ($user && $friend) {
|
if ($user && $friend) {
|
||||||
return 2; // Mutual friends
|
return 2; // Mutual friends
|
||||||
|
@ -663,34 +678,72 @@ class User
|
||||||
|
|
||||||
// Select the correct level
|
// Select the correct level
|
||||||
switch ($level) {
|
switch ($level) {
|
||||||
|
// Mutual
|
||||||
case 2:
|
case 2:
|
||||||
// Get all the current user's friends
|
// Get all the current user's friends
|
||||||
$self = array_column(Database::fetch('friends', true, ['user_id' => [$this->id, '=']]), 'friend_id');
|
$self = DB::prepare('SELECT `friend_id` FROM `{prefix}friends` WHERE `user_id` = :user');
|
||||||
|
$self->execute([
|
||||||
|
'user' => $this->id,
|
||||||
|
]);
|
||||||
|
$self = array_column($self->fetchAll(\PDO::FETCH_ASSOC), 'friend_id');
|
||||||
|
|
||||||
// Get all the people that added this user as a friend
|
// Get all the people that added this user as a friend
|
||||||
$others = array_column(Database::fetch('friends', true, ['friend_id' => [$this->id, '=']]), 'user_id');
|
$others = DB::prepare('SELECT `user_id` FROM `{prefix}friends` WHERE `friend_id` = :user');
|
||||||
|
$others->execute([
|
||||||
|
'user' => $this->id,
|
||||||
|
]);
|
||||||
|
$others = array_column($others->fetchAll(\PDO::FETCH_ASSOC), 'user_id');
|
||||||
|
|
||||||
// Create a difference map
|
// Create a difference map
|
||||||
$users = array_intersect($self, $others);
|
$users = array_intersect($self, $others);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Non-mutual (from user perspective)
|
||||||
case 1:
|
case 1:
|
||||||
$users = array_column(Database::fetch('friends', true, ['user_id' => [$this->id, '=']]), 'friend_id');
|
$users = DB::prepare('SELECT `friend_id` FROM `{prefix}friends` WHERE `user_id` = :user');
|
||||||
|
$users->execute([
|
||||||
|
'user' => $this->id,
|
||||||
|
]);
|
||||||
|
$users = array_column($users->fetchAll(\PDO::FETCH_ASSOC), 'friend_id');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// All friend cases
|
||||||
case 0:
|
case 0:
|
||||||
default:
|
default:
|
||||||
// Get all the current user's friends
|
// Get all the current user's friends
|
||||||
$self = array_column(Database::fetch('friends', true, ['user_id' => [$this->id, '=']]), 'friend_id');
|
$self = DB::prepare('SELECT `friend_id` FROM `{prefix}friends` WHERE `user_id` = :user');
|
||||||
|
$self->execute([
|
||||||
|
'user' => $this->id,
|
||||||
|
]);
|
||||||
|
$self = array_column($self->fetchAll(\PDO::FETCH_ASSOC), 'friend_id');
|
||||||
|
|
||||||
// Get all the people that added this user as a friend
|
// Get all the people that added this user as a friend
|
||||||
$others = array_column(Database::fetch('friends', true, ['friend_id' => [$this->id, '=']]), 'user_id');
|
$others = DB::prepare('SELECT `user_id` FROM `{prefix}friends` WHERE `friend_id` = :user');
|
||||||
|
$others->execute([
|
||||||
|
'user' => $this->id,
|
||||||
|
]);
|
||||||
|
$others = array_column($others->fetchAll(\PDO::FETCH_ASSOC), 'user_id');
|
||||||
|
|
||||||
// Create a difference map
|
// Create a difference map
|
||||||
$users = array_merge($others, $self);
|
$users = array_merge($others, $self);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Open requests
|
||||||
case -1:
|
case -1:
|
||||||
// Get all the current user's friends
|
// Get all the current user's friends
|
||||||
$self = array_column(Database::fetch('friends', true, ['user_id' => [$this->id, '=']]), 'friend_id');
|
$self = DB::prepare('SELECT `friend_id` FROM `{prefix}friends` WHERE `user_id` = :user');
|
||||||
|
$self->execute([
|
||||||
|
'user' => $this->id,
|
||||||
|
]);
|
||||||
|
$self = array_column($self->fetchAll(\PDO::FETCH_ASSOC), 'friend_id');
|
||||||
|
|
||||||
// Get all the people that added this user as a friend
|
// Get all the people that added this user as a friend
|
||||||
$others = array_column(Database::fetch('friends', true, ['friend_id' => [$this->id, '=']]), 'user_id');
|
$others = DB::prepare('SELECT `user_id` FROM `{prefix}friends` WHERE `friend_id` = :user');
|
||||||
|
$others->execute([
|
||||||
|
'user' => $this->id,
|
||||||
|
]);
|
||||||
|
$others = array_column($others->fetchAll(\PDO::FETCH_ASSOC), 'user_id');
|
||||||
|
|
||||||
// Create a difference map
|
// Create a difference map
|
||||||
$users = array_diff($others, $self);
|
$users = array_diff($others, $self);
|
||||||
break;
|
break;
|
||||||
|
@ -770,8 +823,17 @@ class User
|
||||||
|
|
||||||
// Create array and get values
|
// Create array and get values
|
||||||
$profile = [];
|
$profile = [];
|
||||||
$profileFields = Database::fetch('profilefields');
|
|
||||||
$profileValuesRaw = Database::fetch('user_profilefields', true, ['user_id' => [$this->id, '=']]);
|
$profileFields = DB::prepare('SELECT * FROM `{prefix}profilefields`');
|
||||||
|
$profileFields->execute();
|
||||||
|
$profileFields = $profileFields->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
$profileValuesRaw = DB::prepare('SELECT * FROM `{prefix}user_profilefields` WHERE `user_id` = :user');
|
||||||
|
$profileValuesRaw->execute([
|
||||||
|
'user' => $this->id,
|
||||||
|
]);
|
||||||
|
$profileValuesRaw = $profileValuesRaw->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
$profileValueKeys = array_map(function ($a) {
|
$profileValueKeys = array_map(function ($a) {
|
||||||
return $a['field_name'];
|
return $a['field_name'];
|
||||||
}, $profileValuesRaw);
|
}, $profileValuesRaw);
|
||||||
|
@ -849,8 +911,17 @@ class User
|
||||||
|
|
||||||
// Create array and get values
|
// Create array and get values
|
||||||
$options = [];
|
$options = [];
|
||||||
$optionFields = Database::fetch('optionfields');
|
|
||||||
$optionValuesRaw = Database::fetch('user_optionfields', true, ['user_id' => [$this->id, '=']]);
|
$optionFields = DB::prepare('SELECT * FROM `{prefix}optionfields`');
|
||||||
|
$optionFields->execute();
|
||||||
|
$optionFields = $optionFields->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
$optionValuesRaw = DB::prepare('SELECT * FROM `{prefix}user_optionfields` WHERE `user_id` = :user');
|
||||||
|
$optionValuesRaw->execute([
|
||||||
|
'user' => $this->id,
|
||||||
|
]);
|
||||||
|
$optionValuesRaw = $optionValuesRaw->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
$optionValueKeys = array_map(function ($a) {
|
$optionValueKeys = array_map(function ($a) {
|
||||||
return $a['field_name'];
|
return $a['field_name'];
|
||||||
}, $optionValuesRaw);
|
}, $optionValuesRaw);
|
||||||
|
@ -901,9 +972,11 @@ class User
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to retrieve the premium record from the database
|
// Attempt to retrieve the premium record from the database
|
||||||
$getRecord = Database::fetch('premium', false, [
|
$getRecord = DB::prepare('SELECT * FROM `{prefix}premium` WHERE `user_id` = :user');
|
||||||
'user_id' => [$this->id, '='],
|
$getRecord->execute([
|
||||||
|
'user' => $this->id,
|
||||||
]);
|
]);
|
||||||
|
$getRecord = $getRecord->fetch();
|
||||||
|
|
||||||
// If nothing was returned just return false
|
// If nothing was returned just return false
|
||||||
if (empty($getRecord)) {
|
if (empty($getRecord)) {
|
||||||
|
@ -911,12 +984,12 @@ class User
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the Tenshi hasn't expired
|
// Check if the Tenshi hasn't expired
|
||||||
if ($getRecord['premium_expire'] < time()) {
|
if ($getRecord->premium_expire < time()) {
|
||||||
return [0, $getRecord['premium_start'], $getRecord['premium_expire']];
|
return [0, $getRecord->premium_start, $getRecord->premium_expire];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Else return the start and expiration date
|
// Else return the start and expiration date
|
||||||
return [1, $getRecord['premium_start'], $getRecord['premium_expire']];
|
return [1, $getRecord->premium_start, $getRecord->premium_expire];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -927,9 +1000,11 @@ class User
|
||||||
public function getWarnings()
|
public function getWarnings()
|
||||||
{
|
{
|
||||||
// Do the database query
|
// Do the database query
|
||||||
$getWarnings = Database::fetch('warnings', true, [
|
$getWarnings = DB::prepare('SELECT * FROM `{prefix}warnings` WHERE `user_id` = :user');
|
||||||
'user_id' => [$this->id, '='],
|
$getWarnings->execute([
|
||||||
|
'user' => $this->id,
|
||||||
]);
|
]);
|
||||||
|
$getWarnings = $getWarnings->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// Storage array
|
// Storage array
|
||||||
$warnings = [];
|
$warnings = [];
|
||||||
|
@ -938,7 +1013,10 @@ class User
|
||||||
foreach ($getWarnings as $warning) {
|
foreach ($getWarnings as $warning) {
|
||||||
// Check if it hasn't expired
|
// Check if it hasn't expired
|
||||||
if ($warning['warning_expires'] < time()) {
|
if ($warning['warning_expires'] < time()) {
|
||||||
Database::delete('warnings', ['warning_id' => [$warning['warning_id'], '=']]);
|
DB::prepare('DELETE FROM `{prefix}warnings` WHERE `warning_id` = :warn')
|
||||||
|
->execute([
|
||||||
|
'warn' => $warning['warning_id'],
|
||||||
|
]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1001,12 +1079,13 @@ class User
|
||||||
public function getUsernameHistory()
|
public function getUsernameHistory()
|
||||||
{
|
{
|
||||||
// Do the database query
|
// Do the database query
|
||||||
$changes = Database::fetch('username_history', true, [
|
$changes = DB::prepare('SELECT * FROM `{prefix}username_history` WHERE `user_id` = :user ORDER BY `change_id` DESC');
|
||||||
'user_id' => [$this->id, '='],
|
$changes->execute([
|
||||||
], ['change_id', true]);
|
'user' => $this->id,
|
||||||
|
]);
|
||||||
|
|
||||||
// Return all the warnings
|
// Return all the changes
|
||||||
return $changes;
|
return $changes->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1032,45 +1111,47 @@ class User
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this username hasn't been used in the last amount of days set in the config
|
// Check if this username hasn't been used in the last amount of days set in the config
|
||||||
$getOld = Database::fetch('username_history', false, [
|
$getOld = DB::prepare('SELECT * FROM `{prefix}username_history` WHERE `username_old_clean` = :clean AND `change_time` > :time ORDER BY `change_id` DESC');
|
||||||
'username_old_clean' => [$username_clean, '='],
|
$getOld->execute([
|
||||||
'change_time' => [(Config::get('old_username_reserve') * 24 * 60 * 60), '>'],
|
'clean' => $username_clean,
|
||||||
], ['change_id', true]);
|
'time' => (Config::get('old_username_reserve') * 24 * 60 * 60),
|
||||||
|
]);
|
||||||
|
$getOld = $getOld->fetch();
|
||||||
|
|
||||||
// Check if anything was returned
|
// Check if anything was returned
|
||||||
if ($getOld && $getOld['user_id'] != $this->id) {
|
if ($getOld && $getOld->user_id != $this->id) {
|
||||||
return [0, 'TOO_RECENT', $getOld['change_time']];
|
return [0, 'TOO_RECENT', $getOld['change_time']];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the username is already in use
|
// Check if the username is already in use
|
||||||
$getInUse = Database::fetch('users', false, [
|
$getInUse = DB::prepare('SELECT * FROM `{prefix}users` WHERE `username_clean` = :clean');
|
||||||
'username_clean' => [$username_clean, '='],
|
$getInUse->execute([
|
||||||
|
'clean' => $username_clean,
|
||||||
]);
|
]);
|
||||||
|
$getInUse = $getInUse->fetch();
|
||||||
|
|
||||||
// Check if anything was returned
|
// Check if anything was returned
|
||||||
if ($getInUse) {
|
if ($getInUse) {
|
||||||
return [0, 'IN_USE', $getInUse['user_id']];
|
return [0, 'IN_USE', $getInUse->user_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert into username_history table
|
// Insert into username_history table
|
||||||
Database::insert('username_history', [
|
DB::prepare('INSERT INTO `{prefix}username_history` (`change_time`, `user_id`, `username_new`, `username_new_clean`, `username_old`, `username_old_clean`) VALUES (:time, :user, :new, :new_clean, :old, :old_clean)')
|
||||||
'change_time' => time(),
|
->execute([
|
||||||
'user_id' => $this->id,
|
'time' => time(),
|
||||||
'username_new' => $username,
|
'user' => $this->id,
|
||||||
'username_new_clean' => $username_clean,
|
'new' => $username,
|
||||||
'username_old' => $this->username,
|
'new_clean' => $username_clean,
|
||||||
'username_old_clean' => $this->usernameClean,
|
'old' => $this->username,
|
||||||
|
'old_clean' => $this->usernameClean,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Update userrow
|
// Update userrow
|
||||||
Database::update('users', [
|
DB::prepare('UPDATE `{prefix}users` SET `username` = :username, `username_clean` = :clean WHERE `user_id` = :id')
|
||||||
[
|
->execute([
|
||||||
'username' => $username,
|
'username' => $username,
|
||||||
'username_clean' => $username_clean,
|
'clean' => $username_clean,
|
||||||
],
|
'id' => $this->id,
|
||||||
[
|
|
||||||
'user_id' => [$this->id, '='],
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Return success
|
// Return success
|
||||||
|
@ -1092,23 +1173,22 @@ class User
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the username is already in use
|
// Check if the username is already in use
|
||||||
$getInUse = Database::fetch('users', false, [
|
$getInUse = DB::prepare('SELECT * FROM `{prefix}users` WHERE `email` = :email');
|
||||||
'email' => [$email, '='],
|
$getInUse->execute([
|
||||||
|
'email' => $email,
|
||||||
]);
|
]);
|
||||||
|
$getInUse = $getInUse->fetch();
|
||||||
|
|
||||||
// Check if anything was returned
|
// Check if anything was returned
|
||||||
if ($getInUse) {
|
if ($getInUse) {
|
||||||
return [0, 'IN_USE', $getInUse['user_id']];
|
return [0, 'IN_USE', $getInUse->user_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update userrow
|
// Update userrow
|
||||||
Database::update('users', [
|
DB::prepare('UPDATE `{prefix}users` SET `email` = :email WHERE `user_id` = :id')
|
||||||
[
|
->execute([
|
||||||
'email' => $email,
|
'email' => $email,
|
||||||
],
|
'id' => $this->id,
|
||||||
[
|
|
||||||
'user_id' => [$this->id, '='],
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Return success
|
// Return success
|
||||||
|
@ -1159,17 +1239,14 @@ class User
|
||||||
$password = Hashing::createHash($new);
|
$password = Hashing::createHash($new);
|
||||||
|
|
||||||
// Update userrow
|
// Update userrow
|
||||||
Database::update('users', [
|
DB::prepare('UPDATE `{prefix}users` SET `password_hash` = :hash, `password_salt` = :salt, `password_algo` = :algo, `password_iter` = :iter, `password_chan` = :chan WHERE `user_id` = :id')
|
||||||
[
|
->execute([
|
||||||
'password_hash' => $password[3],
|
'hash' => $password[3],
|
||||||
'password_salt' => $password[2],
|
'salt' => $password[2],
|
||||||
'password_algo' => $password[0],
|
'algo' => $password[0],
|
||||||
'password_iter' => $password[1],
|
'iter' => $password[1],
|
||||||
'password_chan' => time(),
|
'chan' => time(),
|
||||||
],
|
'id' => $this->id,
|
||||||
[
|
|
||||||
'user_id' => [$this->id, '='],
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Return success
|
// Return success
|
||||||
|
|
|
@ -85,13 +85,10 @@ class Users
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update last online
|
// Update last online
|
||||||
Database::update('users', [
|
DB::prepare('UPDATE `{prefix}users` SET `user_last_online` = :lo WHERE `user_id` = :id')
|
||||||
[
|
->execute([
|
||||||
'user_last_online' => time(),
|
'lo' => time(),
|
||||||
],
|
'id' => $uid,
|
||||||
[
|
|
||||||
'user_id' => [$uid, '='],
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Update the premium meta
|
// Update the premium meta
|
||||||
|
@ -119,11 +116,12 @@ class Users
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we haven't hit the rate limit
|
// Check if we haven't hit the rate limit
|
||||||
$rates = Database::fetch('login_attempts', true, [
|
$rates = DB::prepare('SELECT * FROM `{prefix}login_attempts` WHERE `attempt_ip` = :ip AND `attempt_timestamp` > :time AND `attempt_success` = 0');
|
||||||
'attempt_ip' => [Net::pton(Net::IP()), '='],
|
$rates->execute([
|
||||||
'attempt_timestamp' => [time() - 1800, '>'],
|
'ip' => Net::pton(Net::IP()),
|
||||||
'attempt_success' => [0, '='],
|
'time' => time() - 1800,
|
||||||
]);
|
]);
|
||||||
|
$rates = $rates->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
if (count($rates) > 4) {
|
if (count($rates) > 4) {
|
||||||
return [0, 'RATE_LIMIT'];
|
return [0, 'RATE_LIMIT'];
|
||||||
|
@ -287,7 +285,11 @@ class Users
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the e-mail has already been used
|
// Check if the e-mail has already been used
|
||||||
if (Database::count('users', ['email' => [$email, '=']])[0] > 0) {
|
$emailCheck = DB::prepare('SELECT `user_id` FROM `{prefix}users` WHERE `email` = :email');
|
||||||
|
$emailCheck->execute([
|
||||||
|
'email' => $email,
|
||||||
|
]);
|
||||||
|
if ($emailCheck->rowCount() > 0) {
|
||||||
return [0, 'EMAIL_EXISTS'];
|
return [0, 'EMAIL_EXISTS'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,10 +340,12 @@ class Users
|
||||||
$emailClean = Utils::cleanString($email, true);
|
$emailClean = Utils::cleanString($email, true);
|
||||||
|
|
||||||
// Do database request
|
// Do database request
|
||||||
$user = Database::fetch('users', false, [
|
$user = DB::prepare('SELECT * FROM `{prefix}users` WHERE `username_clean` = :clean AND `email` = :email');
|
||||||
'username_clean' => [$usernameClean, '='],
|
$user->execute([
|
||||||
'email' => [$emailClean, '='],
|
'clean' => $usernameClean,
|
||||||
|
'email' => $emailClean,
|
||||||
]);
|
]);
|
||||||
|
$user = $user->fetch(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// Check if user exists
|
// Check if user exists
|
||||||
if (count($user) < 2) {
|
if (count($user) < 2) {
|
||||||
|
@ -417,20 +421,16 @@ class Users
|
||||||
|
|
||||||
// Hash the password
|
// Hash the password
|
||||||
$password = Hashing::createHash($newpass);
|
$password = Hashing::createHash($newpass);
|
||||||
$time = time();
|
|
||||||
|
|
||||||
// Update the user
|
// Update the user
|
||||||
Database::update('users', [
|
DB::prepare('UPDATE `{prefix}users` SET `password_hash` = :hash, `password_salt` = :salt, `password_algo` = :algo, `password_iter` = :iter, `password_chan` = :chan WHERE `user_id` = :id')
|
||||||
[
|
->execute([
|
||||||
'password_hash' => $password[3],
|
'hash' => $password[3],
|
||||||
'password_salt' => $password[2],
|
'salt' => $password[2],
|
||||||
'password_algo' => $password[0],
|
'algo' => $password[0],
|
||||||
'password_iter' => $password[1],
|
'iter' => $password[1],
|
||||||
'password_chan' => $time,
|
'chan' => time(),
|
||||||
],
|
'id' => $uid,
|
||||||
[
|
|
||||||
'user_id' => [$uid, '='],
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Return success
|
// Return success
|
||||||
|
@ -457,10 +457,12 @@ class Users
|
||||||
$emailClean = Utils::cleanString($email, true);
|
$emailClean = Utils::cleanString($email, true);
|
||||||
|
|
||||||
// Do database request
|
// Do database request
|
||||||
$user = Database::fetch('users', false, [
|
$user = DB::prepare('SELECT * FROM `{prefix}users` WHERE `username_clean` = :clean AND `email` = :email');
|
||||||
'username_clean' => [$usernameClean, '='],
|
$user->execute([
|
||||||
'email' => [$emailClean, '='],
|
'clean' => $usernameClean,
|
||||||
|
'email' => $emailClean,
|
||||||
]);
|
]);
|
||||||
|
$user = $user->fetch(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// Check if user exists
|
// Check if user exists
|
||||||
if (count($user) < 2) {
|
if (count($user) < 2) {
|
||||||
|
@ -580,21 +582,23 @@ class Users
|
||||||
/**
|
/**
|
||||||
* Check if a user exists.
|
* Check if a user exists.
|
||||||
*
|
*
|
||||||
* @param mixed $user The Username or ID.
|
* @param mixed $id The Username or ID.
|
||||||
* @param bool $id Use id instead.
|
* @param mixed $unused Unused variable.
|
||||||
*
|
*
|
||||||
* @return mixed Returns the ID if it exists, false otherwise.
|
* @return mixed Returns the ID if it exists, false otherwise.
|
||||||
*/
|
*/
|
||||||
public static function userExists($user, $id = true)
|
public static function userExists($id, $unused = null)
|
||||||
{
|
{
|
||||||
// Clean string
|
|
||||||
$user = Utils::cleanString($user, true);
|
|
||||||
|
|
||||||
// Do database request
|
// Do database request
|
||||||
$user = Database::fetch('users', true, [($id ? 'user_id' : 'username_clean') => [$user, '=']]);
|
$user = DB::prepare('SELECT * FROM `{prefix}users` WHERE `user_id` = :id OR `username_clean` = :clean');
|
||||||
|
$user->execute([
|
||||||
|
'id' => $id,
|
||||||
|
'clean' => Utils::cleanString($id, true, true),
|
||||||
|
]);
|
||||||
|
$user = $user->fetch();
|
||||||
|
|
||||||
// Return count (which would return 0, aka false, if nothing was found)
|
// Return count (which would return 0, aka false, if nothing was found)
|
||||||
return count($user) ? $user[0]['user_id'] : false;
|
return $user ? $user->user_id : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -605,7 +609,9 @@ class Users
|
||||||
public static function getProfileFields()
|
public static function getProfileFields()
|
||||||
{
|
{
|
||||||
// Get profile fields
|
// Get profile fields
|
||||||
$profileFields = Database::fetch('profilefields');
|
$profileFields = DB::prepare('SELECT * FROM `{prefix}profilefields`');
|
||||||
|
$profileFields->execute();
|
||||||
|
$profileFields = $profileFields->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// If there's nothing just return null
|
// If there's nothing just return null
|
||||||
if (!count($profileFields)) {
|
if (!count($profileFields)) {
|
||||||
|
@ -634,7 +640,9 @@ class Users
|
||||||
public static function getOptionFields()
|
public static function getOptionFields()
|
||||||
{
|
{
|
||||||
// Get option fields
|
// Get option fields
|
||||||
$optionFields = Database::fetch('optionfields');
|
$optionFields = DB::prepare('SELECT * FROM `{prefix}optionfields`');
|
||||||
|
$optionFields->execute();
|
||||||
|
$optionFields = $optionFields->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// If there's nothing just return null
|
// If there's nothing just return null
|
||||||
if (!count($optionFields)) {
|
if (!count($optionFields)) {
|
||||||
|
@ -672,10 +680,14 @@ class Users
|
||||||
$return = [];
|
$return = [];
|
||||||
|
|
||||||
// Get all online users in the past 5 minutes
|
// Get all online users in the past 5 minutes
|
||||||
$getAll = Database::fetch('users', true, ['user_last_online' => [$time, '>']]);
|
$getAll = DB::prepare('SELECT * FROM `{prefix}users` WHERE `user_last_online` > :lo');
|
||||||
|
$getAll->execute([
|
||||||
|
'lo' => $time,
|
||||||
|
]);
|
||||||
|
$getAll = $getAll->fetchAll();
|
||||||
|
|
||||||
foreach ($getAll as $user) {
|
foreach ($getAll as $user) {
|
||||||
$return[] = User::construct($user['user_id']);
|
$return[] = User::construct($user->user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return all the online users
|
// Return all the online users
|
||||||
|
@ -693,9 +705,11 @@ class Users
|
||||||
public static function addUserPremium($id, $seconds)
|
public static function addUserPremium($id, $seconds)
|
||||||
{
|
{
|
||||||
// Check if there's already a record of premium for this user in the database
|
// Check if there's already a record of premium for this user in the database
|
||||||
$getUser = Database::fetch('premium', false, [
|
$getUser = DB::prepare('SELECT * FROM `{prefix}premium` WHERE `user_id` = :user');
|
||||||
'user_id' => [$id, '='],
|
$getUser->execute([
|
||||||
|
'user' => $id,
|
||||||
]);
|
]);
|
||||||
|
$getUser = $getUser->fetch(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// Calculate the (new) start and expiration timestamp
|
// Calculate the (new) start and expiration timestamp
|
||||||
$start = isset($getUser['premium_start']) ? $getUser['premium_start'] : time();
|
$start = isset($getUser['premium_start']) ? $getUser['premium_start'] : time();
|
||||||
|
@ -703,19 +717,17 @@ class Users
|
||||||
|
|
||||||
// If the user already exists do an update call, otherwise an insert call
|
// If the user already exists do an update call, otherwise an insert call
|
||||||
if (empty($getUser)) {
|
if (empty($getUser)) {
|
||||||
Database::insert('premium', [
|
DB::prepare('INSERT INTO `{prefix}premium` (`user_id`, `premium_start`, `premium_expire`) VALUES (:user, :start, :expire)')
|
||||||
'user_id' => $id,
|
->execute([
|
||||||
'premium_start' => $start,
|
'user' => $id,
|
||||||
'premium_expire' => $expire,
|
'start' => $start,
|
||||||
|
'expire' => $expire,
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
Database::update('premium', [
|
DB::prepare('UPDATE `{prefix}premium` SET `premium_expire` = :expire WHERE `user_id` = :id')
|
||||||
[
|
->execute([
|
||||||
'premium_expire' => $expire,
|
'expire' => $expire,
|
||||||
],
|
'user_id' => $id,
|
||||||
[
|
|
||||||
'user_id' => [$id, '='],
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -751,8 +763,9 @@ class Users
|
||||||
}
|
}
|
||||||
} elseif (!$check[0]) {
|
} elseif (!$check[0]) {
|
||||||
// Remove the expired entry
|
// Remove the expired entry
|
||||||
Database::delete('premium', [
|
DB::prepare('DELETE FROM `{prefix}premium` WHERE `user_id` = :user')
|
||||||
'user_id' => [$user->id, '='],
|
->execute([
|
||||||
|
'user' => $user->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Else remove the rank from them
|
// Else remove the rank from them
|
||||||
|
@ -769,56 +782,18 @@ class Users
|
||||||
*/
|
*/
|
||||||
public static function getUsersByIP($ip)
|
public static function getUsersByIP($ip)
|
||||||
{
|
{
|
||||||
// Get users by registration IP
|
// Get the users
|
||||||
$registeredFrom = Database::fetch('users', true, ['register_ip' => [$ip, '=']]);
|
$users = DB::prepare('SELECT * FROM `{prefix}users` WHERE `register_ip` = :rip OR `last_ip` = :lip');
|
||||||
|
$users->execute([
|
||||||
// Get users by last IP
|
'rip' => $ip,
|
||||||
$lastFrom = Database::fetch('users', true, ['last_ip' => [$ip, '='], 'register_ip' => [$ip, '!=']]);
|
'lip' => $ip,
|
||||||
|
]);
|
||||||
// Merge the arrays
|
$users = $users->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
$users = array_merge($registeredFrom, $lastFrom);
|
|
||||||
|
|
||||||
// Return the array with users
|
// Return the array with users
|
||||||
return $users;
|
return $users;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all users.
|
|
||||||
*
|
|
||||||
* @param mixed $includeInactive include deactivated users.
|
|
||||||
* @param mixed $includeRestricted include restricted users.
|
|
||||||
*
|
|
||||||
* @return array The users.
|
|
||||||
*/
|
|
||||||
public static function getAllUsers($includeInactive = true, $includeRestricted = false)
|
|
||||||
{
|
|
||||||
// Execute query
|
|
||||||
$getUsers = Database::fetch('users', true);
|
|
||||||
|
|
||||||
// Define variable
|
|
||||||
$users = [];
|
|
||||||
|
|
||||||
// Reorder shit
|
|
||||||
foreach ($getUsers as $user) {
|
|
||||||
$user = User::construct($user['user_id']);
|
|
||||||
|
|
||||||
// Skip if inactive and not include deactivated users
|
|
||||||
if (!$includeInactive && $user->permission(Site::DEACTIVATED)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip if inactive and not include restricted users
|
|
||||||
if (!$includeRestricted && $user->permission(Site::RESTRICTED)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$users[$user->id] = $user;
|
|
||||||
}
|
|
||||||
|
|
||||||
// and return an array with the users
|
|
||||||
return $users;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all ranks.
|
* Get all ranks.
|
||||||
*
|
*
|
||||||
|
@ -827,14 +802,16 @@ class Users
|
||||||
public static function getAllRanks()
|
public static function getAllRanks()
|
||||||
{
|
{
|
||||||
// Execute query
|
// Execute query
|
||||||
$getRanks = Database::fetch('ranks', true);
|
$getRanks = DB::prepare('SELECT * FROM `{prefix}ranks`');
|
||||||
|
$getRanks->execute();
|
||||||
|
$getRanks = $getRanks->fetchAll();
|
||||||
|
|
||||||
// Define variable
|
// Define variable
|
||||||
$ranks = [];
|
$ranks = [];
|
||||||
|
|
||||||
// Reorder shit
|
// Reorder shit
|
||||||
foreach ($getRanks as $rank) {
|
foreach ($getRanks as $rank) {
|
||||||
$ranks[$rank['rank_id']] = Rank::construct($rank['rank_id']);
|
$ranks[$rank->rank_id] = Rank::construct($rank->rank_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// and return an array with the ranks
|
// and return an array with the ranks
|
||||||
|
@ -854,19 +831,18 @@ class Users
|
||||||
public static function getNotifications($uid = null, $timediff = 0, $excludeRead = true, $markRead = false)
|
public static function getNotifications($uid = null, $timediff = 0, $excludeRead = true, $markRead = false)
|
||||||
{
|
{
|
||||||
// Prepare conditions
|
// Prepare conditions
|
||||||
$conditions = [];
|
$uid = $uid ? $uid : self::checkLogin()[0];
|
||||||
$conditions['user_id'] = [($uid ? $uid : self::checkLogin()[0]), '='];
|
$time = $timediff ? time() - $timediff : '%';
|
||||||
|
$read = $excludeRead ? '0' : '%';
|
||||||
if ($timediff) {
|
|
||||||
$conditions['alert_timestamp'] = [time() - $timediff, '>'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($excludeRead) {
|
|
||||||
$conditions['alert_read'] = [0, '='];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get notifications for the database
|
// Get notifications for the database
|
||||||
$notifications = Database::fetch('notifications', true, $conditions);
|
$notifications = DB::prepare('SELECT * FROM `{prefix}notifications` WHERE `user_id` = :user AND `alert_timestamp` > :time AND `alert_read` = :read');
|
||||||
|
$notifications->execute([
|
||||||
|
'user' => $uid,
|
||||||
|
'time' => $time,
|
||||||
|
'read' => $read,
|
||||||
|
]);
|
||||||
|
$notifications = $notifications->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// Mark the notifications as read
|
// Mark the notifications as read
|
||||||
if ($markRead) {
|
if ($markRead) {
|
||||||
|
@ -895,13 +871,10 @@ class Users
|
||||||
public static function markNotificationRead($id, $mode = true)
|
public static function markNotificationRead($id, $mode = true)
|
||||||
{
|
{
|
||||||
// Execute an update statement
|
// Execute an update statement
|
||||||
Database::update('notifications', [
|
DB::prepare('UPDATE `{prefix}notifications` SET `alert_read` = :read WHERE `alert_id` = :id')
|
||||||
[
|
->execute([
|
||||||
'alert_read' => ($mode ? 1 : 0),
|
'read' => ($mode ? 1 : 0),
|
||||||
],
|
'id' => $id,
|
||||||
[
|
|
||||||
'alert_id' => [$id, '='],
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -918,20 +891,18 @@ class Users
|
||||||
*/
|
*/
|
||||||
public static function createNotification($user, $title, $text, $timeout = 60000, $img = 'FONT:fa-info-circle', $link = '', $sound = 0)
|
public static function createNotification($user, $title, $text, $timeout = 60000, $img = 'FONT:fa-info-circle', $link = '', $sound = 0)
|
||||||
{
|
{
|
||||||
// Get current timestamp
|
|
||||||
$time = time();
|
|
||||||
|
|
||||||
// Insert it into the database
|
// Insert it into the database
|
||||||
Database::insert('notifications', [
|
DB::prepare('INSERT INTO `{prefix}notifications` (`user_id`, `alert_timestamp`, `alert_read`, `alert_sound`, `alert_title`, `alert_text`, `alert_link`, `alert_img`, `alert_timeout`) VALUES (:user, :time, :read, :sound, :title, :text, :link, :img, :timeout)')
|
||||||
'user_id' => $user,
|
->execute([
|
||||||
'alert_timestamp' => $time,
|
'user' => $user,
|
||||||
'alert_read' => 0,
|
'time' => time(),
|
||||||
'alert_sound' => ($sound ? 1 : 0),
|
'read' => 0,
|
||||||
'alert_title' => $title,
|
'sound' => ($sound ? 1 : 0),
|
||||||
'alert_text' => $text,
|
'title' => $title,
|
||||||
'alert_link' => $link,
|
'text' => $text,
|
||||||
'alert_img' => $img,
|
'link' => $link,
|
||||||
'alert_timeout' => $timeout,
|
'img' => $img,
|
||||||
|
'timeout' => $timeout,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -942,6 +913,12 @@ class Users
|
||||||
*/
|
*/
|
||||||
public static function getNewestUserId()
|
public static function getNewestUserId()
|
||||||
{
|
{
|
||||||
return Database::fetch('users', false, ['rank_main' => [Config::get('restricted_rank_id'), '!=']], ['user_id', true], ['1'])['user_id'];
|
$get = DB::prepare('SELECT `user_id` FROM `{prefix}users` WHERE `rank_main` != :restricted ORDER BY `user_id` DESC LIMIT 1');
|
||||||
|
$get->execute([
|
||||||
|
'restricted' => Config::get('restricted_rank_id'),
|
||||||
|
]);
|
||||||
|
$get = $get->fetch();
|
||||||
|
|
||||||
|
return $get ? $get->user_id : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,31 +66,32 @@ class Utils
|
||||||
$backtrace = base64_encode(json_encode(debug_backtrace()));
|
$backtrace = base64_encode(json_encode(debug_backtrace()));
|
||||||
|
|
||||||
// Check if this error has already been logged in the past
|
// Check if this error has already been logged in the past
|
||||||
if ($past = Database::fetch(
|
$past = DB::prepare('SELECT * FROM `{prefix}error_log` WHERE `error_backtrace` = :bc OR (`error_string` = :str AND `error_line` = :li)');
|
||||||
'error_log',
|
$past->execute([
|
||||||
false,
|
'bc' => $backtrace,
|
||||||
[
|
'str' => $errstr,
|
||||||
'error_backtrace' => [$backtrace, '=', true],
|
'li' => $errline,
|
||||||
'error_string' => [$errstr, '='],
|
]);
|
||||||
'error_line' => [$errline, '='],
|
$past = $past->fetch();
|
||||||
]
|
|
||||||
)) {
|
if ($past) {
|
||||||
// If so assign the errid
|
// If so assign the errid
|
||||||
$errid = $past['error_id'];
|
$errid = $past->error_id;
|
||||||
} else {
|
} else {
|
||||||
// Create an error ID
|
// Create an error ID
|
||||||
$errid = substr(md5(microtime()), rand(0, 22), 10);
|
$errid = substr(md5(microtime()), rand(0, 22), 10);
|
||||||
|
|
||||||
// Log the error
|
// Log the error
|
||||||
Database::insert('error_log', [
|
DB::prepare('INSERT INTO `{prefix}error_log` (`error_id`, `error_timestamp`, `error_revision`, `error_type`, `error_line`, `error_string`, `error_file`, `error_backtrace`) VALUES (:id, :time, :rev, :type, :line, :string, :file, :bc)')
|
||||||
'error_id' => $errid,
|
->execute([
|
||||||
'error_timestamp' => date("r"),
|
'id' => $errid,
|
||||||
'error_revision' => SAKURA_VERSION,
|
'time' => date("r"),
|
||||||
'error_type' => $errno,
|
'rev' => SAKURA_VERSION,
|
||||||
'error_line' => $errline,
|
'type' => $errno,
|
||||||
'error_string' => $errstr,
|
'line' => $errline,
|
||||||
'error_file' => $errfile,
|
'string' => $errstr,
|
||||||
'error_backtrace' => $backtrace,
|
'file' => $errfile,
|
||||||
|
'bc' => $backtrace,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -430,7 +431,9 @@ class Utils
|
||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
// Get database stuff
|
// Get database stuff
|
||||||
$table = Database::fetch('premium_log', true, null, ['transaction_id', true]);
|
$table = DB::prepare('SELECT * FROM `{prefix}premium_log` ORDER BY `transaction_id` DESC');
|
||||||
|
$table->execute();
|
||||||
|
$table = $table->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// Add raw table data to data array
|
// Add raw table data to data array
|
||||||
$data['table'] = $table;
|
$data['table'] = $table;
|
||||||
|
@ -465,11 +468,12 @@ class Utils
|
||||||
*/
|
*/
|
||||||
public static function updatePremiumTracker($id, $amount, $comment)
|
public static function updatePremiumTracker($id, $amount, $comment)
|
||||||
{
|
{
|
||||||
Database::insert('premium_log', [
|
DB::prepare('INSERT INTO `{prefix}premium_log` (`user_id`, `transaction_amount`, `transaction_date`, `transaction_comment`) VALUES (:user, :amount, :date, :comment)')
|
||||||
'user_id' => $id,
|
->execute([
|
||||||
'transaction_amount' => $amount,
|
'user' => $id,
|
||||||
'transaction_date' => time(),
|
'amount' => $amount,
|
||||||
'transaction_comment' => $comment,
|
'date' => time(),
|
||||||
|
'comment' => $comment,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -184,11 +184,12 @@ if (isset($_REQUEST['mode'])) {
|
||||||
// Check if we're not RATE_LIMIT
|
// Check if we're not RATE_LIMIT
|
||||||
if ($login[1] != 'RATE_LIMIT') {
|
if ($login[1] != 'RATE_LIMIT') {
|
||||||
// Add to database
|
// Add to database
|
||||||
Database::insert('login_attempts', [
|
DB::prepare('INSERT INTO `{prefix}login_attempts` (`attempt_success`, `attempt_timestamp`, `attempt_ip`, `user_id`) VALUES (:succ, :time, :ip, :user)')
|
||||||
'attempt_success' => $login[0],
|
->execute([
|
||||||
'attempt_timestamp' => time(),
|
'succ' => $login[0],
|
||||||
'attempt_ip' => Net::pton(Net::IP()),
|
'time' => time(),
|
||||||
'user_id' => isset($login[2]) ? $login[2] : 0,
|
'ip' => Net::pton(Net::IP()),
|
||||||
|
'user' => isset($login[2]) ? $login[2] : 0,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,9 +67,12 @@ if (!isset($thread) && !$forum->permission(ForumPerms::CREATE_THREADS, $currentU
|
||||||
|
|
||||||
$mode = isset($_GET['f']) ? 'f' : (isset($_GET['t']) ? 't' : (isset($_GET['p']) ? 'p' : null));
|
$mode = isset($_GET['f']) ? 'f' : (isset($_GET['t']) ? 't' : (isset($_GET['p']) ? 'p' : null));
|
||||||
|
|
||||||
|
$emotes = DB::prepare('SELECT * FROM `{prefix}emoticons`');
|
||||||
|
$emotes->execute();
|
||||||
|
|
||||||
// Include emotes and bbcodes
|
// Include emotes and bbcodes
|
||||||
$posting = [
|
$posting = [
|
||||||
'emoticons' => Database::fetch('emoticons'),
|
'emoticons' => $emotes->fetchAll(),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Check if we're in reply mode
|
// Check if we're in reply mode
|
||||||
|
@ -198,8 +201,9 @@ if ($mode != 'f') {
|
||||||
// Post deletion code
|
// Post deletion code
|
||||||
if (isset($_POST['yes'])) {
|
if (isset($_POST['yes'])) {
|
||||||
// Delete the post
|
// Delete the post
|
||||||
Database::delete('posts', [
|
DB::prepare('DELETE FROM `{prefix}posts` WHERE `post_id` = :post')
|
||||||
'post_id' => [$_POST['post_id'], '='],
|
->execute([
|
||||||
|
'post' => $_POST['post_id'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Reload the topic
|
// Reload the topic
|
||||||
|
@ -207,8 +211,9 @@ if ($mode != 'f') {
|
||||||
|
|
||||||
// If there's no more posts left in the topic delete it as well
|
// If there's no more posts left in the topic delete it as well
|
||||||
if (!$thread->replyCount()) {
|
if (!$thread->replyCount()) {
|
||||||
Database::delete('topics', [
|
DB::prepare('DELETE FROM `{prefix}topics` WHERE `topic_id` = :thread')
|
||||||
'topic_id' => [$thread->id, '='],
|
->execute([
|
||||||
|
'thread' => $thread->id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -451,14 +451,14 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
// Assign the correct column and title to a variable
|
// Assign the correct column and title to a variable
|
||||||
switch ($mode) {
|
switch ($mode) {
|
||||||
case 'background':
|
case 'background':
|
||||||
$column = 'user_background';
|
$stmt = 'UPDATE `{prefix}users` SET `user_background` = :img WHERE `user_id` = :user';
|
||||||
$msgTitle = 'Background';
|
$msgTitle = 'Background';
|
||||||
$current = $currentUser->background;
|
$current = $currentUser->background;
|
||||||
$permission = $currentUser->permission(Site::CHANGE_BACKGROUND);
|
$permission = $currentUser->permission(Site::CHANGE_BACKGROUND);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'header':
|
case 'header':
|
||||||
$column = 'user_header';
|
$stmt = 'UPDATE `{prefix}users` SET `user_header` = :img WHERE `user_id` = :user';
|
||||||
$msgTitle = 'Header';
|
$msgTitle = 'Header';
|
||||||
$current = $currentUser->header;
|
$current = $currentUser->header;
|
||||||
$permission = $currentUser->permission(Site::CHANGE_HEADER);
|
$permission = $currentUser->permission(Site::CHANGE_HEADER);
|
||||||
|
@ -466,7 +466,7 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
|
|
||||||
case 'avatar':
|
case 'avatar':
|
||||||
default:
|
default:
|
||||||
$column = 'user_avatar';
|
$stmt = 'UPDATE `{prefix}users` SET `user_avatar` = :img WHERE `user_id` = :user';
|
||||||
$msgTitle = 'Avatar';
|
$msgTitle = 'Avatar';
|
||||||
$current = $currentUser->avatar;
|
$current = $currentUser->avatar;
|
||||||
$permission = $currentUser->permission(Site::CHANGE_AVATAR);
|
$permission = $currentUser->permission(Site::CHANGE_AVATAR);
|
||||||
|
@ -617,13 +617,10 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update table
|
// Update table
|
||||||
Database::update('users', [
|
DB::prepare($stmt)
|
||||||
[
|
->execute([
|
||||||
$column => $fileId,
|
'img' => $fileId,
|
||||||
],
|
'user' => $currentUser->id,
|
||||||
[
|
|
||||||
'user_id' => [$currentUser->id, '='],
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Set render data
|
// Set render data
|
||||||
|
@ -643,11 +640,16 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
foreach ($fields as $field) {
|
foreach ($fields as $field) {
|
||||||
// Add to the store array
|
// Add to the store array
|
||||||
if (isset($_POST['profile_' . $field['field_identity']]) && !empty($_POST['profile_' . $field['field_identity']])) {
|
if (isset($_POST['profile_' . $field['field_identity']]) && !empty($_POST['profile_' . $field['field_identity']])) {
|
||||||
Database::delete('user_profilefields', ['user_id' => [$currentUser->id, '='], 'field_name' => [$field['field_identity'], '=']]);
|
DB::prepare('DELETE FROM `{prefix}user_profilefields` WHERE `user_id` = :user AND `field_name` = :id')
|
||||||
Database::insert('user_profilefields', [
|
->execute([
|
||||||
'user_id' => $currentUser->id,
|
'user' => $currentUser->id,
|
||||||
'field_name' => $field['field_identity'],
|
'id' => $field['field_identity'],
|
||||||
'field_value' => $_POST['profile_' . $field['field_identity']],
|
]);
|
||||||
|
DB::prepare('INSERT INTO `{prefix}user_profilefields` (`user_id`, `field_name`, `field_value`) VALUES (:user, :name, :value)')
|
||||||
|
->execute([
|
||||||
|
'user' => $currentUser->id,
|
||||||
|
'name' => $field['field_identity'],
|
||||||
|
'value' => $_POST['profile_' . $field['field_identity']],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -657,11 +659,16 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
foreach ($field['field_additional'] as $addKey => $addVal) {
|
foreach ($field['field_additional'] as $addKey => $addVal) {
|
||||||
// Add to the array
|
// Add to the array
|
||||||
$store = (isset($_POST['profile_additional_' . $addKey]) || !empty($_POST['profile_additional_' . $addKey])) ? $_POST['profile_additional_' . $addKey] : false;
|
$store = (isset($_POST['profile_additional_' . $addKey]) || !empty($_POST['profile_additional_' . $addKey])) ? $_POST['profile_additional_' . $addKey] : false;
|
||||||
Database::delete('user_profilefields', ['user_id' => [$currentUser->id, '='], 'field_name' => [$addKey, '=']]);
|
DB::prepare('DELETE FROM `{prefix}user_profilefields` WHERE `user_id` = :user AND `field_name` = :id')
|
||||||
Database::insert('user_profilefields', [
|
->execute([
|
||||||
'user_id' => $currentUser->id,
|
'user' => $currentUser->id,
|
||||||
'field_name' => $addKey,
|
'id' => $addKey,
|
||||||
'field_value' => $store,
|
]);
|
||||||
|
DB::prepare('INSERT INTO `{prefix}user_profilefields` (`user_id`, `field_name`, `field_value`) VALUES (:user, :name, :value)')
|
||||||
|
->execute([
|
||||||
|
'user' => $currentUser->id,
|
||||||
|
'name' => $addKey,
|
||||||
|
'value' => $store,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -724,13 +731,10 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
[$_POST['birthday_year'], $_POST['birthday_month'], $_POST['birthday_day']]
|
[$_POST['birthday_year'], $_POST['birthday_month'], $_POST['birthday_day']]
|
||||||
);
|
);
|
||||||
|
|
||||||
Database::update('users', [
|
DB::prepare('UPDATE `{prefix}users` SET `user_birthday` = :bd WHERE `user_id` = :id')
|
||||||
[
|
->execute([
|
||||||
'user_birthday' => $birthdate,
|
'bd' => $birthdate,
|
||||||
],
|
'id' => $currentUser->id,
|
||||||
[
|
|
||||||
'user_id' => [$currentUser->id, '='],
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -742,7 +746,11 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
|
|
||||||
// Go over each field
|
// Go over each field
|
||||||
foreach ($fields as $field) {
|
foreach ($fields as $field) {
|
||||||
Database::delete('user_optionfields', ['user_id' => [$currentUser->id, '='], 'field_name' => [$field['option_id'], '=']]);
|
DB::prepare('DELETE FROM `{prefix}user_optionfields` WHERE `user_id` = :user AND `field_name` = :id')
|
||||||
|
->execute([
|
||||||
|
'user' => $currentUser->id,
|
||||||
|
'id' => $field['option_id'],
|
||||||
|
]);
|
||||||
|
|
||||||
// Make sure the user has sufficient permissions to complete this action
|
// Make sure the user has sufficient permissions to complete this action
|
||||||
if (!$currentUser->permission(constant('Sakura\Perms\Site::' . $field['option_permission']))) {
|
if (!$currentUser->permission(constant('Sakura\Perms\Site::' . $field['option_permission']))) {
|
||||||
|
@ -751,10 +759,11 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
|
|
||||||
if (isset($_POST['option_' . $field['option_id']])
|
if (isset($_POST['option_' . $field['option_id']])
|
||||||
&& !empty($_POST['option_' . $field['option_id']])) {
|
&& !empty($_POST['option_' . $field['option_id']])) {
|
||||||
Database::insert('user_optionfields', [
|
DB::prepare('INSERT INTO `{prefix}user_optionfields` (`user_id`, `field_name`, `field_value`) VALUES (:user, :name, :value)')
|
||||||
'user_id' => $currentUser->id,
|
->execute([
|
||||||
'field_name' => $field['option_id'],
|
'user' => $currentUser->id,
|
||||||
'field_value' => $_POST['option_' . $field['option_id']],
|
'name' => $field['option_id'],
|
||||||
|
'value' => $_POST['option_' . $field['option_id']],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -792,17 +801,11 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update database
|
// Update database
|
||||||
Database::update(
|
DB::prepare('UPDATE `{prefix}users` SET `user_title` = :title WHERE `user_id` = :id')
|
||||||
'users',
|
->execute([
|
||||||
[
|
'title' => (isset($_POST['usertitle']) ? $_POST['usertitle'] : null),
|
||||||
[
|
'id' => $currentUser->id,
|
||||||
'user_title' => (isset($_POST['usertitle']) ? $_POST['usertitle'] : null),
|
]);
|
||||||
],
|
|
||||||
[
|
|
||||||
'user_id' => [$currentUser->id, '='],
|
|
||||||
],
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set render data
|
// Set render data
|
||||||
$renderData['page'] = [
|
$renderData['page'] = [
|
||||||
|
@ -935,7 +938,11 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update database
|
// Update database
|
||||||
Database::update('users', [['user_page' => $_POST['userpage']], ['user_id' => [$currentUser->id, '=']]]);
|
DB::prepare('UPDATE `{prefix}users` SET `user_page` = :up WHERE `user_id` = :id')
|
||||||
|
->execute([
|
||||||
|
'up' => $_POST['userpage'],
|
||||||
|
'id' => $currentUser->id,
|
||||||
|
]);
|
||||||
|
|
||||||
// Set render data
|
// Set render data
|
||||||
$renderData['page'] = [
|
$renderData['page'] = [
|
||||||
|
@ -957,7 +964,11 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update database
|
// Update database
|
||||||
Database::update('users', [['user_signature' => $_POST['signature']], ['user_id' => [$currentUser->id, '=']]]);
|
DB::prepare('UPDATE `{prefix}users` SET `user_signature` = :us WHERE `user_id` = :id')
|
||||||
|
->execute([
|
||||||
|
'us' => $_POST['signature'],
|
||||||
|
'id' => $currentUser->id,
|
||||||
|
]);
|
||||||
|
|
||||||
// Set render data
|
// Set render data
|
||||||
$renderData['page'] = [
|
$renderData['page'] = [
|
||||||
|
@ -1038,8 +1049,9 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
// Check if sessionid is set to all
|
// Check if sessionid is set to all
|
||||||
if ($_POST['sessionid'] === 'all') {
|
if ($_POST['sessionid'] === 'all') {
|
||||||
// Delete all sessions assigned to the current user
|
// Delete all sessions assigned to the current user
|
||||||
Database::delete('sessions', [
|
DB::prepare('DELETE FROM `{prefix}sessions` WHERE `user_id` = :user')
|
||||||
'user_id' => [$currentUser->id, '='],
|
->execute([
|
||||||
|
'user' => $currentUser->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Set render data
|
// Set render data
|
||||||
|
@ -1052,7 +1064,12 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the session is owned by the current user
|
// Check if the session is owned by the current user
|
||||||
if (!Database::fetch('sessions', false, ['user_id' => [$currentUser->id, '='], 'session_id' => [$_POST['sessionid'], '=']])) {
|
$us = DB::prepare('SELECT * FROM `{prefix}sessions` WHERE `user_id` = :user AND `session_id` = :key');
|
||||||
|
$us->execute([
|
||||||
|
'user' => $currentUser->id,
|
||||||
|
'key' => $_POST['sessionid'],
|
||||||
|
]);
|
||||||
|
if (!$us->rowCount()) {
|
||||||
$renderData['page'] = [
|
$renderData['page'] = [
|
||||||
'redirect' => $redirect,
|
'redirect' => $redirect,
|
||||||
'message' => 'The session you tried to kill doesn\'t exist.',
|
'message' => 'The session you tried to kill doesn\'t exist.',
|
||||||
|
@ -1062,8 +1079,10 @@ if (isset($_REQUEST['request-notifications']) && $_REQUEST['request-notification
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete the session
|
// Delete the session
|
||||||
Database::delete('sessions', [
|
DB::prepare('DELETE FROM `{prefix}sessions` WHERE `user_id` = :user AND `session_id` = :session')
|
||||||
'session_id' => [$_POST['sessionid'], '='],
|
->execute([
|
||||||
|
'user' => $currentUser->id,
|
||||||
|
'session' => $_POST['sessionid'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Set render data
|
// Set render data
|
||||||
|
@ -1500,7 +1519,12 @@ if (Users::checkLogin()) {
|
||||||
|
|
||||||
// Sessions
|
// Sessions
|
||||||
case 'advanced.sessions':
|
case 'advanced.sessions':
|
||||||
$renderData['sessions'] = Database::fetch('sessions', true, ['user_id' => [$currentUser->id, '=']]);
|
$sessions = DB::prepare('SELECT * FROM `{prefix}sessions` WHERE `user_id` = :user');
|
||||||
|
$sessions->execute([
|
||||||
|
'user' => $currentUser->id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$renderData['sessions'] = $sessions->fetchAll();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
18
sakura.php
18
sakura.php
|
@ -8,7 +8,7 @@
|
||||||
namespace Sakura;
|
namespace Sakura;
|
||||||
|
|
||||||
// Define Sakura version
|
// Define Sakura version
|
||||||
define('SAKURA_VERSION', '20160215');
|
define('SAKURA_VERSION', '20160219');
|
||||||
define('SAKURA_VLABEL', 'Amethyst');
|
define('SAKURA_VLABEL', 'Amethyst');
|
||||||
define('SAKURA_COLOUR', '#9966CC');
|
define('SAKURA_COLOUR', '#9966CC');
|
||||||
|
|
||||||
|
@ -62,7 +62,13 @@ Config::init(ROOT . 'config/config.ini');
|
||||||
error_reporting(Config::local('dev', 'show_errors') ? -1 : 0);
|
error_reporting(Config::local('dev', 'show_errors') ? -1 : 0);
|
||||||
|
|
||||||
// Make the database connection
|
// Make the database connection
|
||||||
Database::init(Config::local('database', 'driver'));
|
DB::open(
|
||||||
|
Config::local('database', 'driver'),
|
||||||
|
Config::local('dsn'),
|
||||||
|
Config::local('database', 'username'),
|
||||||
|
Config::local('database', 'password'),
|
||||||
|
Config::local('database', 'prefix')
|
||||||
|
);
|
||||||
|
|
||||||
// Check if we're using console
|
// Check if we're using console
|
||||||
if (php_sapi_name() === 'cli' && !defined('SAKURA_CRON')) {
|
if (php_sapi_name() === 'cli' && !defined('SAKURA_CRON')) {
|
||||||
|
@ -83,7 +89,7 @@ if (Config::get('no_cron_service')) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update last execution time
|
// Update last execution time
|
||||||
Database::update('config', [['config_value' => time()], ['config_name' => ['no_cron_last', '=']]]);
|
Config::set('no_cron_last', time());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +123,7 @@ if (!defined('SAKURA_NO_TPL')) {
|
||||||
Template::set($templateName);
|
Template::set($templateName);
|
||||||
|
|
||||||
// Set base page rendering data
|
// Set base page rendering data
|
||||||
$renderData = [
|
Template::vars([
|
||||||
'sakura' => [
|
'sakura' => [
|
||||||
'versionInfo' => [
|
'versionInfo' => [
|
||||||
'version' => SAKURA_VERSION,
|
'version' => SAKURA_VERSION,
|
||||||
|
@ -176,10 +182,10 @@ if (!defined('SAKURA_NO_TPL')) {
|
||||||
|
|
||||||
'get' => $_GET,
|
'get' => $_GET,
|
||||||
'post' => $_POST,
|
'post' => $_POST,
|
||||||
];
|
]);
|
||||||
|
|
||||||
// Add the default render data
|
// Add the default render data
|
||||||
Template::vars($renderData);
|
$renderData = [];
|
||||||
|
|
||||||
// Site closing
|
// Site closing
|
||||||
if (Config::get('site_closed')) {
|
if (Config::get('site_closed')) {
|
||||||
|
|
|
@ -12,5 +12,5 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="clear"></div>
|
<div class="clear"></div>
|
||||||
<div class="news-post-time">
|
<div class="news-post-time">
|
||||||
Posted on <time>{{ post.news_timestamp|date(sakura.dateFormat) }}</time>{% if not (viewPost and postExists) %} <a class="default" href="{{ urls.format('SITE_NEWS_CAT_POST', [post.news_category, post.news_id]) }}#comments">{{ post.news_comments.count }} comment{% if post.news_comments.count != 1 %}s{% endif %}</a>{% endif %}
|
Posted <time>{{ post.news_timestamp|date(sakura.dateFormat) }}</time>{% if not (viewPost and postExists) %} <a class="default" href="{{ urls.format('SITE_NEWS_CAT_POST', [post.news_category, post.news_id]) }}#comments">{{ post.news_comments.count }} comment{% if post.news_comments.count != 1 %}s{% endif %}</a>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
Reference in a new issue