wip news and pagination stuff

This commit is contained in:
flash 2016-12-12 23:22:09 +01:00
parent c393368c4e
commit 028de7b576
16 changed files with 273 additions and 113 deletions

View file

@ -58,12 +58,10 @@ class MetaController extends Controller
$onlineUsers[$user->id] = $user;
}
// Get news
$news = new Category(config('general.news'));
//$news = new Category(config('general.news'));
// Merge index specific stuff with the global render data
Template::vars([
'news' => $news->posts(3),
'news' => [],
'stats' => [
'userCount' => DB::table('users')
->where('rank_main', '!=', config('rank.banned'))

View file

@ -7,6 +7,7 @@
namespace Sakura\Controllers;
use Phroute\Phroute\Exception\HttpRouteNotFoundException;
use Sakura\DB;
use Sakura\Config;
use Sakura\News\Category;
use Sakura\News\Post;
@ -18,24 +19,29 @@ use Sakura\News\Post;
*/
class NewsController extends Controller
{
/**
* Shows all news posts in any category.
* @return string
*/
public function index(): string
{
$categories = DB::table('news_categories')->get();
$news = new Category;
return view('news/index', compact('categories', 'news'));
}
/**
* Shows all posts in a specific category.
* @param string $category
* @param int $catId
* @throws HttpRouteNotFoundException
* @return string
*/
public function category(string $category = ''): string
public function category(int $catId = 1): string
{
// Check if the category is set
if ($category === '') {
// Fetch the default category from the config
$category = config('general.news');
}
$category = new Category($catId);
// Create the category object
$category = new Category($category);
if (!$category->posts()) {
if ($category->id === 0) {
throw new HttpRouteNotFoundException;
}

View file

@ -6,6 +6,7 @@
namespace Sakura\News;
use Carbon\Carbon;
use Sakura\DB;
/**
@ -16,42 +17,84 @@ use Sakura\DB;
class Category
{
/**
* The name over this news category.
* Id of this category.
* @var int
*/
public $id = 0;
/**
* Name of this category.
* @var string
*/
public $name = "";
/**
* Constructor.
* @param string $name
* Description of this news category.
* @var string
*/
public function __construct(string $name)
public $description = null;
/**
* Whether this category should be hidden.
* @var bool
*/
public $hidden = false;
/**
* Holds instances of Post.
* @var array
*/
private $postsCache = [];
/**
* @param int $id
*/
public function __construct(int $id = 0)
{
$this->name = $name;
if ($id !== 0) {
$data = DB::table('news_categories')
->where('category_id', $id)
->first();
if ($data) {
$this->id = intval($data->category_id);
$this->name = $data->category_name;
$this->category = $data->category_description;
$this->hidden = boolval($data->category_hidden);
}
}
}
/**
* Gets the news posts in this category.
* @param int $limit
* @param bool $excludeFuture
* @param bool $excludeDeleted
* @return array
*/
public function posts(int $limit = 0): array
public function posts(int $limit = 0, bool $excludeDeleted = true): array
{
$postIds = DB::table('news')
->where('news_category', $this->name)
->orderBy('news_id', 'desc');
if ($limit) {
$postIds->limit($limit);
}
$postIds = $postIds->get(['news_id']);
$postIds = array_column($postIds, 'news_id');
if (!$this->postsCache) {
$posts = DB::table('news_posts')
->orderBy('post_id', 'desc');
$posts = [];
if ($this->id !== 0) {
$posts->where('category_id', $this->id);
}
foreach ($postIds as $post) {
$posts[$post] = new Post($post);
if ($excludeDeleted) {
$posts->whereNull('deleted_at');
}
if ($limit) {
$posts->limit($limit);
}
$this->postsCache = array_map(function ($post) {
return new Post($post->post_id);
}, $posts->get(['post_id']));
}
return $posts;
return $this->postsCache;
}
}

View file

@ -6,6 +6,7 @@
namespace Sakura\News;
use Carbon\Carbon;
use Sakura\Comment;
use Sakura\DB;
use Sakura\User;
@ -30,9 +31,9 @@ class Post
/**
* The category this post is part of.
* @var string
* @var int
*/
public $category = "";
public $category = 0;
/**
* The user who made this post.
@ -40,12 +41,6 @@ class Post
*/
public $user = 0;
/**
* The timestamp when this post was made.
* @var int
*/
public $time = 0;
/**
* The title of this news post.
* @var string
@ -58,6 +53,24 @@ class Post
*/
public $text = "";
/**
* When the post was created.
* @var Carbon
*/
public $created = null;
/**
* When the post was last updated.
* @var Carbon
*/
public $updated = null;
/**
* When the post was deleted.
* @var Carbon
*/
public $deleted = null;
/**
* A cache of the amount of comments this post has.
* @var int
@ -76,19 +89,19 @@ class Post
*/
public function __construct(int $id = 0)
{
// Get comment data from the database
$data = DB::table('news')
->where('news_id', $id)
$data = DB::table('news_posts')
->where('post_id', $id)
->first();
// Check if anything was returned and assign data
if ($data) {
$this->id = $data->news_id;
$this->category = $data->news_category;
$this->user = $data->user_id;
$this->time = $data->news_timestamp;
$this->title = $data->news_title;
$this->text = $data->news_content;
$this->id = intval($data->post_id);
$this->category = intval($data->category_id);
$this->user = intval($data->user_id);
$this->title = $data->post_title;
$this->text = $data->post_text;
$this->created = new Carbon($data->created_at);
$this->updated = new Carbon($data->updated_at);
$this->deleted = new Carbon($data->deleted_at);
}
}
@ -97,24 +110,24 @@ class Post
*/
public function save(): void
{
// Create submission data, insert and update take the same format
$data = [
'news_category' => $this->category,
'user_id' => $this->user,
'news_timestamp' => $this->time,
'news_title' => $this->title,
'news_content' => $this->text,
];
// // Create submission data, insert and update take the same format
// $data = [
// 'news_category' => $this->category,
// 'user_id' => $this->user,
// 'news_timestamp' => $this->time,
// 'news_title' => $this->title,
// 'news_content' => $this->text,
// ];
// Update if id isn't 0
if ($this->id) {
DB::table('news')
->where('news_id', $this->id)
->update($data);
} else {
$this->id = DB::table('news')
->insertGetId($data);
}
// // Update if id isn't 0
// if ($this->id) {
// DB::table('news')
// ->where('news_id', $this->id)
// ->update($data);
// } else {
// $this->id = DB::table('news')
// ->insertGetId($data);
// }
}
/**
@ -122,11 +135,11 @@ class Post
*/
public function delete(): void
{
DB::table('news')
->where('news_id', $this->id)
->delete();
// DB::table('news')
// ->where('news_id', $this->id)
// ->delete();
$this->id = 0;
// $this->id = 0;
}
/**

View file

@ -0,0 +1,57 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Sakura\DB;
class NewsRefactor extends Migration
{
/**
* Run the migrations.
* @return void
*/
public function up()
{
$schema = DB::getSchemaBuilder();
$schema->drop('news');
$schema->create('news_posts', function (Blueprint $table) {
$table->increments('post_id');
$table->integer('category_id')->unsigned();
$table->integer('user_id')->unsigned();
$table->string('post_title');
$table->text('post_text');
$table->timestampTz('created_at')->useCurrent = true;
$table->timestampTz('updated_at')->useCurrent = true;
$table->timestampTz('deleted_at')->nullable()->default(null);
});
$schema->create('news_categories', function (Blueprint $table) {
$table->increments('category_id');
$table->string('category_name');
$table->string('category_description')->nullable();
$table->boolean('category_hidden')->default(false);
});
}
/**
* Reverse the migrations.
* @return void
*/
public function down()
{
$schema = DB::getSchemaBuilder();
$schema->drop('news_posts');
$schema->drop('news_categories');
$schema->create('news', function (Blueprint $table) {
$table->increments('news_id');
$table->string('news_category', 255);
$table->integer('user_id')->unsigned();
$table->integer('news_timestamp')->unsigned();
$table->string('news_title', 255);
$table->text('news_content');
});
}
}

View file

@ -1,17 +0,0 @@
{% if newsHideTitle is not defined %}<a href="{{ route('news.post', post.id) }}" class="news__head" id="p{{ post.id }}">{{ post.title }}</a>{% endif %}
<div class="news__body">
<a class="news__poster" href="{{ route('user.profile', post.userData.id) }}">
<div class="avatar avatar--border news__avatar" style="background-image: url('{{ route('user.avatar', post.userData.id) }}')"></div>
<div class="news__username" style="color: {{ post.userData.colour }}; text-shadow: 0 0 7px {% if post.userData.colour != 'inherit' %}{{ post.userData.colour }}{% else %}#222{% endif %}">
{{ post.userData.username }}
</div>
</a>
<div class="bbcode">
{{ post.text|raw }}
</div>
</div>
<div class="clear"></div>
<div class="news__date">
Posted <time class="time-ago" datetime="{{ post.time|date('r') }}">{{ post.time|date(config('general.date_format')) }}</time>
{% if newsHideCommentCount is not defined %}<a href="{{ route('news.post', post.id) }}#comments">{{ post.commentCount }} comment{% if post.commentCount != 1 %}s{% endif %}</a>{% endif %}
</div>

View file

@ -24,8 +24,8 @@
{% if not forum.type and forum.id > 0 %}
{% set topics = forum.topics|batch(25) %}
{% set paginationPages = topics %}
{% set paginationUrl %}{{ route('forums.forum', forum.id) }}{% endset %}
{% set pagination_pages = topics %}
{% set pagination_url %}{{ route('forums.forum', forum.id) }}{% endset %}
{% include 'forum/elements/forumBtns.twig' %}

View file

@ -1,4 +1,4 @@
{% set paginationClass = 'rightSide' %}
{% from 'macros.twig' import pagination %}
<div class="forum-list__buttons">
<div>
@ -18,5 +18,7 @@
{% include 'forum/elements/forumMod.twig' %}
{% endif %}
</div>
{% include 'elements/pagination.twig' %}
{% if pagination_url is defined %}
{{ pagination(pagination_url, pagination_pages, 'rightSide') }}
{% endif %}
</div>

View file

@ -48,8 +48,8 @@
{% set posts = topic.posts|batch(10) %}
{% set paginationPages = posts %}
{% set paginationUrl = route('forums.topic', topic.id) %}
{% set pagination_pages = posts %}
{% set pagination_url = route('forums.topic', topic.id) %}
{% endif %}
{% block js %}

View file

@ -6,3 +6,53 @@
<button class="uploader__button uploader__button--delete fa fa-trash" onclick="handleImageDelete('{{ url }}', '{{ query }}')"></button>
</div>
{% endmacro %}
{% macro news_post(id, text, created, user, title, comments) %}
{% if title is defined and title %}
<a href="{{ route('news.post', id) }}" class="news__head" id="p{{ id }}">{{ title }}</a>
{% endif %}
<div class="news__body">
<a class="news__poster" href="{{ route('user.profile', user.id) }}">
<div class="avatar avatar--border news__avatar" style="background-image: url('{{ route('user.avatar', user.id) }}')"></div>
<div class="news__username" style="color: {{ user.colour }}; text-shadow: 0 0 7px {% if user.colour != 'inherit' %}{{ user.colour }}{% else %}#222{% endif %}">
{{ user.username }}
</div>
</a>
<div class="bbcode">
{{ text|raw }}
</div>
</div>
<div class="clear"></div>
<div class="news__date">
Posted <time class="time-ago" datetime="{{ created.format('c') }}">{{ created.format(config('general.date_format')) }}</time>
{% if comments is defined and comments %}<a href="{{ route('news.post', id) }}#comments">{{ comments }} comment{% if comments != 1 %}s{% endif %}</a>{% endif %}
</div>
{% endmacro %}
{% macro pagination(url, pages, class, name) %}
{% set separator %}{% if '%3F' in url|default('')|url_encode %}&amp;{% else %}?{% endif %}{% endset %}
{% set current_page = get[name|default('page')]|default(1) %}
{% set url = url ~ separator ~ name|default('page') ~ "=" %}
<div class="pagination {{ class }}">
{% if pages is defined and pages|length > 1 %}
{% if current_page > 1 %}
{% if pages|length > 2 %}
<a class="input__button" href="{{ url ~ 1 }}" title="Jump to first page"><span class="fa fa-fast-backward"></span></a>
{% endif %}
<a class="input__button" href="{{ url ~ (current_page - 1) }}" title="Previous page"><span class="fa fa-step-backward"></span></a>
{% endif %}
{% for id,page in pages %}
{% if (id + 1) > (current_page - 3) and (id + 1) < (current_page + 3) %}
<a class="input__button{% if id == current_page - 1 %} input__button--current{% endif %}" href="{{ url ~ (id + 1) }}" title="Page {{ id + 1 }}">{{ id + 1 }}</a>
{% endif %}
{% endfor %}
{% if current_page < pages|length %}
<a class="input__button" href="{{ url ~ (current_page + 1) }}" title="Next page"><span class="fa fa-step-forward"></span></a>
{% if pages|length > 2 %}
<a class="input__button" href="{{ url ~ pages|length }}" title="Jump to last page"><span class="fa fa-fast-forward"></span></a>
{% endif %}
{% endif %}
{% endif %}
</div>
{% endmacro %}

View file

@ -39,7 +39,7 @@
<div class="header__menu">
<div class="header__menu--left" id="navMenuSite">
<a class="header__menu-item fa fa-home" href="{{ route('main.index') }}" title="Home"></a>
<a class="header__menu-item fa fa-newspaper-o" href="{{ route('news.category') }}" title="News"></a>
<a class="header__menu-item fa fa-newspaper-o" href="{{ route('news.index') }}" title="News"></a>
<a class="header__menu-item fa fa-commenting" href="#" title="Chat"></a>
<a class="header__menu-item fa fa-list" href="{{ route('forums.index') }}" title="Forums"></a>
<a class="header__menu-item fa fa-search" href="{{ route('main.search') }}" title="Search"></a>
@ -174,7 +174,7 @@
<ul class="footer__section">
<li class="footer__item footer__item--head">General</li>
<li class="footer__item"><a class="footer__link" href="{{ route('main.index') }}">Home</a></li>
<li class="footer__item"><a class="footer__link" href="{{ route('news.category') }}">News</a></li>
<li class="footer__item"><a class="footer__link" href="{{ route('news.index') }}">News</a></li>
<li class="footer__item"><a class="footer__link" href="{{ route('main.search') }}">Search</a></li>
<li class="footer__item"><a class="footer__link" href="https://sakura.flash.moe">Changelog</a></li>
<li class="footer__item"><a class="footer__link" href="{{ route('premium.index') }}">Support us</a></li>

View file

@ -1,4 +1,5 @@
{% extends 'master.twig' %}
{% from 'macros.twig' import news_post %}
{% block content %}
<div class="content homepage">
@ -49,7 +50,7 @@
<div class="content--left">
<div class="content__header">News</div>
{% for post in news %}
{% include 'elements/newsPost.twig' %}
{{ news_post(post.id, post.text, post.created, post.userData, post.title, post.commentCount) }}
{% endfor %}
</div>
<div class="clear"></div>

View file

@ -1,15 +1,7 @@
{% extends 'master.twig' %}
{% from 'macros.twig' import news_post %}
{% set title = 'News' %}
{% block css %}
<style type="text/css">
.pagination {
float: right;
}
</style>
{% endblock %}
{% set posts = category.posts|batch(3) %}
{% set paginationPages = posts|keys %}
@ -19,7 +11,7 @@
<div class="content news">
<div class="content__header">News</div>
{% for post in posts[get.page|default(1) - 1] %}
{% include 'elements/newsPost.twig' %}
{{ news_post(post.id, post.text, post.created, post.userData, post.title, post.commentCount) }}
{% endfor %}
{% if posts|length > 1 %}
<div>

View file

@ -0,0 +1,16 @@
{% extends 'master.twig' %}
{% block content %}
<div class="content">
<div class="content--right">
<div class="content__header content__header--alt">Categories</div>
{% for category in categories %}
<a href="{{ route('news.category', category.category_id) }}">{{ category.category_name }}</a>
{% endfor %}
</div>
<div class="content--left">
<div class="content__header">News</div>
</div>
<div class="clear"></div>
</div>
{% endblock %}

View file

@ -1,17 +1,15 @@
{% extends 'master.twig' %}
{% from 'macros.twig' import news_post %}
{% set title = post.title %}
{% set commentsCategory = 'news-' ~ post.category ~ '-' ~ post.id %}
{% set comments = post.comments %}
{% set newsHideTitle = true %}
{% set newsHideCommentCount = true %}
{% block content %}
<div class="content news">
<div class="content__header">{{ post.title }}</div>
{% include 'elements/newsPost.twig' %}
{{ news_post(post.id, post.text, post.created, post.userData) }}
{% include 'elements/comments.twig' %}
</div>
{% endblock %}

View file

@ -82,7 +82,8 @@ Router::group(['before' => 'maintenance'], function () {
// News
Router::group(['prefix' => 'news'], function () {
Router::get('/{category:c}?', 'NewsController@category', 'news.category');
Router::get('/', 'NewsController@index', 'news.index');
Router::get('/{category:i}', 'NewsController@category', 'news.category');
Router::get('/post/{id:i}', 'NewsController@post', 'news.post');
});