diff --git a/_sakura/changelog.json b/_sakura/changelog.json index 20f0202..3e4810d 100644 --- a/_sakura/changelog.json +++ b/_sakura/changelog.json @@ -30,7 +30,8 @@ "20150701", "20150702", "20150703", - "20150704" + "20150704", + "20150705" ] @@ -1445,6 +1446,35 @@ "change": "Removed ignore lines for Misaki files." } + ], + + "20150705": [ + + { + "type": "ADD", + "change": "Added count functionality to database wrapper." + }, + { + "type": "UPD", + "change": "Make forum index page fully functional." + }, + { + "type": "UPD", + "change": "Add user data and post linking to viewforum." + }, + { + "type": "ADD", + "change": "Add 'x time ago' generator function." + }, + { + "type": "FIX", + "change": "Fix bug while decoding the country name JSON with systems that don't default to UTF-8." + }, + { + "type": "REM", + "change": "Removed some columns and replaced them with live stats." + } + ] } diff --git a/_sakura/components/Database.php b/_sakura/components/Database.php index f707caa..704e3ac 100644 --- a/_sakura/components/Database.php +++ b/_sakura/components/Database.php @@ -1,6 +1,6 @@ count($table, $data, $prefix); + + } + } diff --git a/_sakura/components/Forum.php b/_sakura/components/Forum.php index 35b5e94..6da44fd 100644 --- a/_sakura/components/Forum.php +++ b/_sakura/components/Forum.php @@ -46,6 +46,16 @@ class Forum { // For link and reg. forum add it to the category $return[$forum['forum_category']]['forums'][$forum['forum_id']] = $forum; + // Get the topic count + $return[$forum['forum_category']]['forums'][$forum['forum_id']]['topic_count'] = Database::count('topics', [ + 'forum_id' => [$forum['forum_id'], '='] + ])[0]; + + // Get the post count + $return[$forum['forum_category']]['forums'][$forum['forum_id']]['post_count'] = Database::count('posts', [ + 'forum_id' => [$forum['forum_id'], '='] + ])[0]; + // Get last post in forum $lastPost = Database::fetch('posts', false, [ 'forum_id' => [$forum['forum_id'], '='] @@ -53,8 +63,10 @@ class Forum { // Add last poster data and the details about the post as well $return[$forum['forum_category']]['forums'][$forum['forum_id']]['last_poster'] = [ + 'post' => $lastPost, 'user' => ($_LAST_POSTER = Users::getUser($lastPost['poster_id'])), - 'rank' => Users::getRank($_LAST_POSTER['rank_main']) + 'rank' => Users::getRank($_LAST_POSTER['rank_main']), + 'elap' => Main::timeElapsed($lastPost['post_time']) ]; } @@ -114,6 +126,7 @@ class Forum { ], ['post_id', true]); $forum['forums'][$key]['last_poster'] = [ + 'post' => $lastPost, 'user' => ($_LAST_POSTER = Users::getUser($lastPost['poster_id'])), 'rank' => Users::getRank($_LAST_POSTER['rank_main']) ]; @@ -121,29 +134,7 @@ class Forum { } // Lastly grab the topics for this forum - $forum['topics'] = Database::fetch('topics', true, [ - 'forum_id' => [$id, '='] - ]); - - // Get the userdata related to first and last posts - foreach($forum['topics'] as $key => $topic) { - - // Get last post in forum - $firstPost = Database::fetch('posts', false, [ - 'topic_id' => [$topic['topic_id'], '='] - ]); - - $forum['topics'][$key]['first_poster'] = [ - 'user' => ($_FIRST_POSTER = Users::getUser($firstPost['topic_first_poster_id'])), - 'rank' => Users::getRank($_FIRST_POSTER['rank_main']) - ]; - - $forum['topics'][$key]['last_poster'] = [ - 'user' => ($_LAST_POSTER = Users::getUser($topic['topic_last_poster_id'])), - 'rank' => Users::getRank($_LAST_POSTER['rank_main']) - ]; - - } + $forum['topics'] = self::getTopics($forum['forum']['forum_id']); // Return the forum/category return $forum; @@ -161,14 +152,33 @@ class Forum { // Get the userdata related to last posts foreach($topics as $key => $topic) { + // Get the reply count + $topics[$key]['reply_count'] = Database::count('posts', [ + 'topic_id' => [$topic['topic_id'], '='] + ])[0]; + + // Get first post in topics + $firstPost = Database::fetch('posts', false, [ + 'topic_id' => [$topic['topic_id'], '='] + ]); + $topics[$key]['first_poster'] = [ - 'user' => ($_FIRST_POSTER = Users::getUser($topic['topic_first_poster_id'])), - 'rank' => Users::getRank($_FIRST_POSTER['rank_main']) + 'post' => $firstPost, + 'user' => ($_FIRST_POSTER = Users::getUser($firstPost['poster_id'])), + 'rank' => Users::getRank($_FIRST_POSTER['rank_main']), + 'elap' => Main::timeElapsed($firstPost['post_time']) ]; + // Get last post in topics + $lastPost = Database::fetch('posts', false, [ + 'topic_id' => [$topic['topic_id'], '='] + ], ['post_id', true]); + $topics[$key]['last_poster'] = [ - 'user' => ($_LAST_POSTER = Users::getUser($topic['topic_last_poster_id'])), - 'rank' => Users::getRank($_LAST_POSTER['rank_main']) + 'post' => $lastPost, + 'user' => ($_LAST_POSTER = Users::getUser($lastPost['poster_id'])), + 'rank' => Users::getRank($_LAST_POSTER['rank_main']), + 'elap' => Main::timeElapsed($lastPost['post_time']) ]; } @@ -203,15 +213,27 @@ class Forum { // Store the topic info $topic['topic'] = $topicInfo; + // Get first post in topics + $firstPost = Database::fetch('posts', false, [ + 'topic_id' => [$topic['topic']['topic_id'], '='] + ]); + // Get the data of the first poster $topic['topic']['first_poster'] = [ - 'user' => ($_FIRST_POSTER = Users::getUser($topic['topic']['topic_first_poster_id'])), + 'post' => $firstPost, + 'user' => ($_FIRST_POSTER = Users::getUser($firstPost['poster_id'])), 'rank' => Users::getRank($_FIRST_POSTER['rank_main']) ]; + // Get last post in topics + $lastPost = Database::fetch('posts', false, [ + 'topic_id' => [$topic['topic']['topic_id'], '='] + ], ['post_id', true]); + // Get the data of the last poster $topic['topic']['last_poster'] = [ - 'user' => ($_LAST_POSTER = Users::getUser($topic['topic']['topic_last_poster_id'])), + 'post' => $lastPost, + 'user' => ($_LAST_POSTER = Users::getUser($lastPost['poster_id'])), 'rank' => Users::getRank($_LAST_POSTER['rank_main']) ]; @@ -223,7 +245,7 @@ class Forum { // Add post and metadata to the global storage array $topic['posts'][$post['post_id']] = array_merge($post, [ - 'is_op' => ($post['poster_id'] == $topic['topic']['topic_first_poster_id'] ? '1' : '0'), + 'is_op' => ($post['poster_id'] == $firstPost['poster_id'] ? '1' : '0'), 'user' => ($_POSTER = Users::getUser($post['poster_id'])), 'rank' => Users::getRank($_POSTER['rank_main']), 'country' => Main::getCountryName($_POSTER['country']), diff --git a/_sakura/components/Main.php b/_sakura/components/Main.php index 7c66198..d59857e 100644 --- a/_sakura/components/Main.php +++ b/_sakura/components/Main.php @@ -518,7 +518,7 @@ class Main { public static function getCountryName($code) { // Parse JSON file - $iso3166 = json_decode(file_get_contents(ROOT .'_sakura/'. Configuration::getLocalConfig('data', 'iso3166')), true); + $iso3166 = json_decode(utf8_encode(file_get_contents(ROOT .'_sakura/'. Configuration::getLocalConfig('data', 'iso3166'))), true); // Check if key exists if(array_key_exists($code, $iso3166)) @@ -674,4 +674,43 @@ class Main { } + // Time elapsed + public static function timeElapsed($timestamp) { + + // Subtract the entered timestamp from the current timestamp + $time = time() - $timestamp; + + // If the new timestamp is below 1 return a standard string + if($time < 1) + return 'Just now'; + + // Array containing time "types" + $times = [ + 365 * 24 * 60 * 60 => 'year', + 30 * 24 * 60 * 60 => 'month', + 24 * 60 * 60 => 'day', + 60 * 60 => 'hour', + 60 => 'minute', + 1 => 'second' + ]; + + foreach($times as $secs => $str) { + + // Do a devision to check if the given timestamp fits in the current "type" + $calc = $time / $secs; + + if($calc >= 1) { + + // Round the number + $round = round($calc); + + // Return the string + return $round .' '. $times[$secs] . ($round == 1 ? '' : 's') .' ago'; + + } + + } + + } + } diff --git a/_sakura/components/database/mysql.php b/_sakura/components/database/mysql.php index 021d6fb..d1cc9fd 100644 --- a/_sakura/components/database/mysql.php +++ b/_sakura/components/database/mysql.php @@ -308,4 +308,52 @@ class MySQL { } + // Count data from the database + public function count($table, $data, $prefix = null) { + + // Begin preparation of the statement + $prepare = 'SELECT COUNT(*) FROM `' . ($prefix ? $prefix : Configuration::getLocalConfig('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)) ? '' : ' 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); + + } + } diff --git a/_sakura/sakura.php b/_sakura/sakura.php index 6bba562..4b915f6 100644 --- a/_sakura/sakura.php +++ b/_sakura/sakura.php @@ -8,7 +8,7 @@ namespace Sakura; // Define Sakura version -define('SAKURA_VERSION', '20150704'); +define('SAKURA_VERSION', '20150705'); define('SAKURA_VLABEL', 'Eminence'); define('SAKURA_STABLE', false); define('SAKURA_COLOUR', '#6C3082'); @@ -19,6 +19,9 @@ define('ROOT', str_replace(basename(__DIR__), '', dirname(__FILE__))); // Error Reporting: 0 for production and -1 for testing error_reporting(SAKURA_STABLE ? 0 : -1); +// Set internal encoding method +mb_internal_encoding('utf-8'); + // Include libraries require_once ROOT .'_sakura/vendor/autoload.php'; require_once ROOT .'_sakura/components/Main.php'; diff --git a/_sakura/templates/yuuno/forum/forumEntry.tpl b/_sakura/templates/yuuno/forum/forumEntry.tpl index 5c0bca5..5834056 100644 --- a/_sakura/templates/yuuno/forum/forumEntry.tpl +++ b/_sakura/templates/yuuno/forum/forumEntry.tpl @@ -23,13 +23,13 @@ {% if forum.forum_type != 2 %}