News, part 1 at least.
This commit is contained in:
parent
9cf45fe036
commit
aea66a62fb
14 changed files with 330 additions and 17 deletions
59
database/2018_04_13_140000_create_news_tables.php
Normal file
59
database/2018_04_13_140000_create_news_tables.php
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Misuzu\Database;
|
||||||
|
|
||||||
|
// phpcs:disable
|
||||||
|
class CreateNewsTables extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @SuppressWarnings(PHPMD)
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
$schema = Database::connection()->getSchemaBuilder();
|
||||||
|
|
||||||
|
$schema->create('news_categories', function (Blueprint $table) {
|
||||||
|
$table->increments('category_id');
|
||||||
|
$table->string('category_name');
|
||||||
|
$table->text('category_description');
|
||||||
|
$table->boolean('is_hidden')->default(false);
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
|
||||||
|
$schema->create('news_posts', function (Blueprint $table) {
|
||||||
|
$table->increments('post_id');
|
||||||
|
$table->integer('category_id')->unsigned();
|
||||||
|
$table->boolean('is_featured')->default(false);
|
||||||
|
$table->integer('user_id')->unsigned()->nullable();
|
||||||
|
$table->string('post_title');
|
||||||
|
$table->text('post_text');
|
||||||
|
$table->timestamp('scheduled_for')->useCurrent();
|
||||||
|
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
|
||||||
|
$table->foreign('category_id')
|
||||||
|
->references('category_id')
|
||||||
|
->on('news_categories')
|
||||||
|
->onUpdate('cascade')
|
||||||
|
->onDelete('cascade');
|
||||||
|
|
||||||
|
$table->foreign('user_id')
|
||||||
|
->references('user_id')
|
||||||
|
->on('users')
|
||||||
|
->onUpdate('cascade')
|
||||||
|
->onDelete('set null');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @SuppressWarnings(PHPMD)
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
$schema = Database::connection()->getSchemaBuilder();
|
||||||
|
$schema->drop('news_posts');
|
||||||
|
$schema->drop('news_categories');
|
||||||
|
}
|
||||||
|
}
|
41
public/news.php
Normal file
41
public/news.php
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
use Misuzu\News\NewsCategory;
|
||||||
|
use Misuzu\News\NewsPost;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../misuzu.php';
|
||||||
|
|
||||||
|
$category_id = empty($_GET['c']) ? null : (int)$_GET['c'];
|
||||||
|
$post_id = empty($_GET['n']) ? null : (int)$_GET['n'];
|
||||||
|
|
||||||
|
if ($post_id !== null) {
|
||||||
|
$post = NewsPost::find($post_id);
|
||||||
|
|
||||||
|
if ($post === null) {
|
||||||
|
http_response_code(404);
|
||||||
|
echo $app->templating->render('errors.404');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo $app->templating->render('news.post', compact('post'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($category_id !== null) {
|
||||||
|
$category = NewsCategory::find($category_id);
|
||||||
|
|
||||||
|
if ($category === null) {
|
||||||
|
http_response_code(404);
|
||||||
|
echo $app->templating->render('errors.404');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$posts = $category->posts()->orderBy('created_at', 'desc')->paginate(5);
|
||||||
|
$featured = $category->where('is_featured', 1)->orderBy('created_at', 'desc')->take(10);
|
||||||
|
echo $app->templating->render('news.category', compact('category', 'posts', 'featured'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$categories = NewsCategory::where('is_hidden', false)->get();
|
||||||
|
$posts = NewsPost::where('is_featured', true)->paginate(5);
|
||||||
|
|
||||||
|
echo $app->templating->render('news.index', compact('categories', 'posts'));
|
|
@ -160,15 +160,19 @@ class Application extends ApplicationBase
|
||||||
$this->addModule('templating', $twig = new TemplateEngine);
|
$this->addModule('templating', $twig = new TemplateEngine);
|
||||||
$twig->debug($this->debugMode);
|
$twig->debug($this->debugMode);
|
||||||
|
|
||||||
|
$twig->var('globals', [
|
||||||
|
'site_name' => $this->config->get('Site', 'name', 'string', 'Flashii'),
|
||||||
|
'site_description' => $this->config->get('Site', 'description'),
|
||||||
|
'site_twitter' => $this->config->get('Site', 'twitter'),
|
||||||
|
'site_url' => $this->config->get('Site', 'url'),
|
||||||
|
]);
|
||||||
|
|
||||||
$twig->addFilter('json_decode');
|
$twig->addFilter('json_decode');
|
||||||
$twig->addFilter('byte_symbol');
|
$twig->addFilter('byte_symbol');
|
||||||
$twig->addFilter('country_name', 'get_country_name');
|
$twig->addFilter('country_name', 'get_country_name');
|
||||||
$twig->addFilter('flip', 'array_flip');
|
$twig->addFilter('flip', 'array_flip');
|
||||||
$twig->addFilter('create_pagination');
|
$twig->addFilter('create_pagination');
|
||||||
|
$twig->addFilter('first_paragraph');
|
||||||
// avoid using config() in templates whenever possible
|
|
||||||
// in all honesty this shouldn't even be a thing
|
|
||||||
$twig->addFunction('config', [$this->config, 'get']);
|
|
||||||
|
|
||||||
$twig->addFunction('git_hash', [Application::class, 'gitCommitHash']);
|
$twig->addFunction('git_hash', [Application::class, 'gitCommitHash']);
|
||||||
$twig->addFunction('git_branch', [Application::class, 'gitBranch']);
|
$twig->addFunction('git_branch', [Application::class, 'gitBranch']);
|
||||||
|
|
15
src/News/NewsCategory.php
Normal file
15
src/News/NewsCategory.php
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<?php
|
||||||
|
namespace Misuzu\News;
|
||||||
|
|
||||||
|
use Misuzu\Model;
|
||||||
|
|
||||||
|
final class NewsCategory extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'news_categories';
|
||||||
|
protected $primaryKey = 'category_id';
|
||||||
|
|
||||||
|
public function posts()
|
||||||
|
{
|
||||||
|
return $this->hasMany(NewsPost::class, 'category_id');
|
||||||
|
}
|
||||||
|
}
|
24
src/News/NewsPost.php
Normal file
24
src/News/NewsPost.php
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
namespace Misuzu\News;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
use Misuzu\Users\User;
|
||||||
|
use Misuzu\Model;
|
||||||
|
|
||||||
|
final class NewsPost extends Model
|
||||||
|
{
|
||||||
|
use SoftDeletes;
|
||||||
|
|
||||||
|
protected $table = 'news_posts';
|
||||||
|
protected $primaryKey = 'post_id';
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'user_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function category()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(NewsCategory::class, 'category_id');
|
||||||
|
}
|
||||||
|
}
|
|
@ -206,3 +206,9 @@ function running_on_windows(): bool
|
||||||
{
|
{
|
||||||
return starts_with(strtolower(PHP_OS), 'win');
|
return starts_with(strtolower(PHP_OS), 'win');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function first_paragraph(string $text, string $delimiter = "\n"): string
|
||||||
|
{
|
||||||
|
$index = mb_strpos($text, $delimiter);
|
||||||
|
return $index === false ? $text : mb_substr($text, 0, $index);
|
||||||
|
}
|
||||||
|
|
|
@ -1,21 +1,59 @@
|
||||||
{% set title = title|default('Flashii') %}
|
{% spaceless %}
|
||||||
{% set description = description|default("Where the floor doesn't fall far from the carrot.") %}
|
{% set description = description|default(globals.site_description) %}
|
||||||
|
{% set site_twitter = site_twitter|default(globals.site_twitter) %}
|
||||||
|
|
||||||
|
{% if title is defined %}
|
||||||
|
{% set title = title ~ ' :: ' ~ globals.site_name %}
|
||||||
|
{% else %}
|
||||||
|
{% set title = globals.site_name %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<title>{{ title }}</title>
|
<title>{{ title }}</title>
|
||||||
|
|
||||||
<meta name="twitter:title" content="{{ title }}">
|
<meta name="twitter:title" content="{{ title|slice(0, 70) }}">
|
||||||
<meta property="og:title" content="{{ title }}">
|
<meta property="og:title" content="{{ title }}">
|
||||||
|
<meta property="og:site_name" content="{{ globals.site_name }}">
|
||||||
|
|
||||||
|
{% if description|length > 0 %}
|
||||||
<meta name="description" content="{{ description }}">
|
<meta name="description" content="{{ description }}">
|
||||||
<meta name="twitter:description" content="{{ description }}">
|
<meta name="twitter:description" content="{{ description }}">
|
||||||
<meta property="og:description" content="{{ description }}">
|
<meta property="og:description" content="{{ description }}">
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<meta name="twitter:card" content="summary">
|
{% if site_twitter|length > 0 %}
|
||||||
|
<meta name="twitter:site" content="{{ site_twitter }}">
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<meta property="og:type" content="object">
|
<meta property="og:type" content="object">
|
||||||
<meta property="og:site_name" content="Flashii">
|
<meta name="twitter:card" content="summary">
|
||||||
|
|
||||||
{% if icon is defined %}
|
{% if image is defined %}
|
||||||
<meta name="twitter:image:src" content="{{ icon }}">
|
{% if image|slice(0, 1) == '/' %}
|
||||||
<meta property="og:image" content="{{ icon }}">
|
{% if globals.site_url is not defined or globals.site_url|length < 1 %}
|
||||||
{% endif %}
|
{% set image = '' %}
|
||||||
|
{% else %}
|
||||||
|
{% set image = globals.site_url|trim('/') ~ image %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if image|length > 0 %}
|
||||||
|
<meta name="twitter:image:src" content="{{ image }}">
|
||||||
|
<meta property="og:image" content="{{ image }}">
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if canonical_url is defined %}
|
||||||
|
{% if canonical_url|slice(0, 1) == '/' %}
|
||||||
|
{% if globals.site_url is not defined or globals.site_url|length < 1 %}
|
||||||
|
{% set canonical_url = '' %}
|
||||||
|
{% else %}
|
||||||
|
{% set canonical_url = globals.site_url|trim('/') ~ canonical_url %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if canonical_url|length > 0 %}
|
||||||
|
<link rel="canonical" href="{{ canonical_url }}">
|
||||||
|
<link rel="og:url" href="{{ canonical_url }}">
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endspaceless %}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
{% extends '@mio/home/master.twig' %}
|
{% extends '@mio/home/master.twig' %}
|
||||||
{% from '@mio/macros.twig' import navigation, link %}
|
{% from '@mio/macros.twig' import navigation, link %}
|
||||||
|
|
||||||
|
{% set canonical_url = '/' %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="mio__container">
|
<div class="mio__container">
|
||||||
<div class="mio__container__title">Welcome!</div>
|
<div class="mio__container__title">Welcome!</div>
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
{% from '@mio/macros.twig' import link, navigation %}
|
{% from '@mio/macros.twig' import link, navigation %}
|
||||||
|
|
||||||
{% set mio_navigation = {
|
{% set mio_navigation = {
|
||||||
'Home':'/',
|
'Home': '/',
|
||||||
'Chat':'https://chat.flashii.net',
|
'News': '/news.php',
|
||||||
|
'Chat': 'https://chat.flashii.net',
|
||||||
} %}
|
} %}
|
||||||
|
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
|
|
39
views/mio/news/category.twig
Normal file
39
views/mio/news/category.twig
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{% extends '@mio/news/master.twig' %}
|
||||||
|
|
||||||
|
{% set title = category.category_name ~ ' :: News' %}
|
||||||
|
{% set canonical_url = '/news.php?c=' ~ category.category_id %}
|
||||||
|
|
||||||
|
{% block news_content %}
|
||||||
|
<div class="mio__container">
|
||||||
|
<div class="mio__container__title">News » {{ category.category_name }}</div>
|
||||||
|
<div class="mio__container__content">
|
||||||
|
<div class="mio__news__category__posts">
|
||||||
|
{% for post in posts %}
|
||||||
|
<div class="mio__container mio__news__preview">
|
||||||
|
<div class="mio__container__title mio__news__preview__title">
|
||||||
|
{{ post.post_title }}
|
||||||
|
</div>
|
||||||
|
<div class="mio__container__content mio__news__preview__content">
|
||||||
|
<div class="mio__news__preview__text">
|
||||||
|
{{ post.post_text|first_paragraph }}
|
||||||
|
</div>
|
||||||
|
<div class="mio__news__preview__info">
|
||||||
|
Posted on {{ post.created_at }} by {{ post.user.username }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div class="mio__news__category__menu">
|
||||||
|
<div class="mio__news__category__listing">
|
||||||
|
{% for featured_post in featured %}
|
||||||
|
<a href="/news.php?n={{ featured_post.post_id }}">{{ featured_post.post_title }}</a>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div class="mio__news__category__pagination">
|
||||||
|
pagination here
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
39
views/mio/news/index.twig
Normal file
39
views/mio/news/index.twig
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{% extends '@mio/news/master.twig' %}
|
||||||
|
|
||||||
|
{% set title = 'News' %}
|
||||||
|
{% set canonical_url = '/news.php' %}
|
||||||
|
|
||||||
|
{% block news_content %}
|
||||||
|
<div class="mio__container">
|
||||||
|
<div class="mio__container__title">News</div>
|
||||||
|
<div class="mio__container__content">
|
||||||
|
<div class="mio__news__category__posts">
|
||||||
|
{% for post in posts %}
|
||||||
|
<div class="mio__container mio__news__preview">
|
||||||
|
<div class="mio__container__title mio__news__preview__title">
|
||||||
|
{{ post.post_title }}
|
||||||
|
</div>
|
||||||
|
<div class="mio__container__content mio__news__preview__content">
|
||||||
|
<div class="mio__news__preview__text">
|
||||||
|
{{ post.post_text|first_paragraph }}
|
||||||
|
</div>
|
||||||
|
<div class="mio__news__preview__info">
|
||||||
|
Posted on {{ post.created_at }} by {{ post.user.username }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div class="mio__news__category__menu">
|
||||||
|
<div class="mio__news__category__listing">
|
||||||
|
{% for category in categories %}
|
||||||
|
<a href="/news.php?c={{ category.category_id }}">{{ category.category_name }}</a>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div class="mio__news__category__pagination">
|
||||||
|
pagination here
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
15
views/mio/news/master.twig
Normal file
15
views/mio/news/master.twig
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{% extends '@mio/master.twig' %}
|
||||||
|
{% from '@mio/macros.twig' import navigation %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% block news_content %}
|
||||||
|
<div class="mio__container">
|
||||||
|
<div class="mio__container__title">News!</div>
|
||||||
|
<div class="mio__container__content">
|
||||||
|
<p>Welcome to News, the news is still heavily in development. You can follow us on News where we'll post news every so often, we'll also announce when the news is ready for public use there!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{{ navigation(mio_navigation, '/news.php') }}
|
||||||
|
{% endblock %}
|
29
views/mio/news/post.twig
Normal file
29
views/mio/news/post.twig
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
{% extends '@mio/news/master.twig' %}
|
||||||
|
|
||||||
|
{% set title = post.post_title ~ ' :: News' %}
|
||||||
|
{% set canonical_url = '/news.php?n=' ~ post.post_id %}
|
||||||
|
|
||||||
|
{% block news_content %}
|
||||||
|
<div class="mio__container">
|
||||||
|
<div class="mio__container__title">{{ post.category.category_name }} » {{ post.post_title }}</div>
|
||||||
|
<div class="mio__container__content">
|
||||||
|
<div class="mio__news__post__text">
|
||||||
|
{{ post.post_text|raw }}
|
||||||
|
</div>
|
||||||
|
<div class="mio__news__post__info">
|
||||||
|
<div class="mio__news__post__user">
|
||||||
|
<div class="mio__news__post__username">
|
||||||
|
{{ post.user.username }}
|
||||||
|
</div>
|
||||||
|
<div class="mio__news__post__avatar" style="background-image:url('/profile.php?u={{ post.user.user_id }}&m=avatar');"></div>
|
||||||
|
</div>
|
||||||
|
<div class="mio__news__post__info">
|
||||||
|
Category: <a href="/news.php?c={{ post.category.category_id }}">{{ post.category.category_name }}</a>
|
||||||
|
</div>
|
||||||
|
<div class="mio__news__post__info">
|
||||||
|
Posted: {{ post.created_at }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -1,7 +1,8 @@
|
||||||
{% extends '@mio/user/master.twig' %}
|
{% extends '@mio/user/master.twig' %}
|
||||||
{% from '@mio/macros.twig' import navigation, link %}
|
{% from '@mio/macros.twig' import navigation, link %}
|
||||||
|
|
||||||
{% set icon = '/profile.php?u=' ~ profile.user_id ~ '&m=avatar' %}
|
{% set image = '/profile.php?u=' ~ profile.user_id ~ '&m=avatar' %}
|
||||||
|
{% set canonical_url = '/profile.php?u=' ~ profile.user_id %}
|
||||||
{% set title = 'Profile of ' ~ profile.username %}
|
{% set title = 'Profile of ' ~ profile.username %}
|
||||||
|
|
||||||
{% set youtube_is_channel_id = profile.user_youtube|slice(0, 2) == 'UC' and profile.user_youtube|length == 24 %}
|
{% set youtube_is_channel_id = profile.user_youtube|slice(0, 2) == 'UC' and profile.user_youtube|length == 24 %}
|
||||||
|
@ -118,7 +119,7 @@
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="mio__avatar mio__profile__avatar" style="background-image:url('{{ icon }}');"></div>
|
<div class="mio__avatar mio__profile__avatar" style="background-image:url('{{ image }}');"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Reference in a new issue