diff --git a/database/2018_04_13_140000_create_news_tables.php b/database/2018_04_13_140000_create_news_tables.php new file mode 100644 index 00000000..bd29c9fb --- /dev/null +++ b/database/2018_04_13_140000_create_news_tables.php @@ -0,0 +1,59 @@ +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'); + } +} diff --git a/public/news.php b/public/news.php new file mode 100644 index 00000000..443a2f7c --- /dev/null +++ b/public/news.php @@ -0,0 +1,41 @@ +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')); diff --git a/src/Application.php b/src/Application.php index 54d23811..035b853a 100644 --- a/src/Application.php +++ b/src/Application.php @@ -160,15 +160,19 @@ class Application extends ApplicationBase $this->addModule('templating', $twig = new TemplateEngine); $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('byte_symbol'); $twig->addFilter('country_name', 'get_country_name'); $twig->addFilter('flip', 'array_flip'); $twig->addFilter('create_pagination'); - - // avoid using config() in templates whenever possible - // in all honesty this shouldn't even be a thing - $twig->addFunction('config', [$this->config, 'get']); + $twig->addFilter('first_paragraph'); $twig->addFunction('git_hash', [Application::class, 'gitCommitHash']); $twig->addFunction('git_branch', [Application::class, 'gitBranch']); diff --git a/src/News/NewsCategory.php b/src/News/NewsCategory.php new file mode 100644 index 00000000..dae1a563 --- /dev/null +++ b/src/News/NewsCategory.php @@ -0,0 +1,15 @@ +hasMany(NewsPost::class, 'category_id'); + } +} diff --git a/src/News/NewsPost.php b/src/News/NewsPost.php new file mode 100644 index 00000000..f4a8612c --- /dev/null +++ b/src/News/NewsPost.php @@ -0,0 +1,24 @@ +belongsTo(User::class, 'user_id'); + } + + public function category() + { + return $this->belongsTo(NewsCategory::class, 'category_id'); + } +} diff --git a/utility.php b/utility.php index 38e87218..b7a8a95f 100644 --- a/utility.php +++ b/utility.php @@ -206,3 +206,9 @@ function running_on_windows(): bool { 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); +} diff --git a/views/mio/_layout/meta.twig b/views/mio/_layout/meta.twig index 8cec802e..7e48aa66 100644 --- a/views/mio/_layout/meta.twig +++ b/views/mio/_layout/meta.twig @@ -1,21 +1,59 @@ -{% set title = title|default('Flashii') %} -{% set description = description|default("Where the floor doesn't fall far from the carrot.") %} +{% spaceless %} + {% 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 }} - + + + {% if description|length > 0 %} + {% endif %} - + {% if site_twitter|length > 0 %} + + {% endif %} - + -{% if icon is defined %} - - -{% endif %} + {% if image is defined %} + {% if image|slice(0, 1) == '/' %} + {% if globals.site_url is not defined or globals.site_url|length < 1 %} + {% set image = '' %} + {% else %} + {% set image = globals.site_url|trim('/') ~ image %} + {% endif %} + {% endif %} + + {% if image|length > 0 %} + + + {% 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 %} + + + {% endif %} + {% endif %} +{% endspaceless %} diff --git a/views/mio/home/landing.twig b/views/mio/home/landing.twig index 734d1076..9109ed1d 100644 --- a/views/mio/home/landing.twig +++ b/views/mio/home/landing.twig @@ -1,6 +1,8 @@ {% extends '@mio/home/master.twig' %} {% from '@mio/macros.twig' import navigation, link %} +{% set canonical_url = '/' %} + {% block content %}
Welcome!
diff --git a/views/mio/master.twig b/views/mio/master.twig index cf4e1ec4..cd42eb9e 100644 --- a/views/mio/master.twig +++ b/views/mio/master.twig @@ -1,8 +1,9 @@ {% from '@mio/macros.twig' import link, navigation %} {% set mio_navigation = { - 'Home':'/', - 'Chat':'https://chat.flashii.net', + 'Home': '/', + 'News': '/news.php', + 'Chat': 'https://chat.flashii.net', } %} diff --git a/views/mio/news/category.twig b/views/mio/news/category.twig new file mode 100644 index 00000000..c076304f --- /dev/null +++ b/views/mio/news/category.twig @@ -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 %} +
+
News » {{ category.category_name }}
+
+
+ {% for post in posts %} +
+
+ {{ post.post_title }} +
+
+
+ {{ post.post_text|first_paragraph }} +
+
+ Posted on {{ post.created_at }} by {{ post.user.username }} +
+
+
+ {% endfor %} +
+
+
+ {% for featured_post in featured %} + {{ featured_post.post_title }} + {% endfor %} +
+
+ pagination here +
+
+
+
+{% endblock %} diff --git a/views/mio/news/index.twig b/views/mio/news/index.twig new file mode 100644 index 00000000..2ce0bc91 --- /dev/null +++ b/views/mio/news/index.twig @@ -0,0 +1,39 @@ +{% extends '@mio/news/master.twig' %} + +{% set title = 'News' %} +{% set canonical_url = '/news.php' %} + +{% block news_content %} +
+
News
+
+
+ {% for post in posts %} +
+
+ {{ post.post_title }} +
+
+
+ {{ post.post_text|first_paragraph }} +
+
+ Posted on {{ post.created_at }} by {{ post.user.username }} +
+
+
+ {% endfor %} +
+
+
+ {% for category in categories %} + {{ category.category_name }} + {% endfor %} +
+
+ pagination here +
+
+
+
+{% endblock %} diff --git a/views/mio/news/master.twig b/views/mio/news/master.twig new file mode 100644 index 00000000..193f7de4 --- /dev/null +++ b/views/mio/news/master.twig @@ -0,0 +1,15 @@ +{% extends '@mio/master.twig' %} +{% from '@mio/macros.twig' import navigation %} + +{% block content %} + {% block news_content %} +
+
News!
+
+

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!

+
+
+ {% endblock %} + + {{ navigation(mio_navigation, '/news.php') }} +{% endblock %} diff --git a/views/mio/news/post.twig b/views/mio/news/post.twig new file mode 100644 index 00000000..0c936452 --- /dev/null +++ b/views/mio/news/post.twig @@ -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 %} +
+
{{ post.category.category_name }} » {{ post.post_title }}
+
+
+ {{ post.post_text|raw }} +
+ +
+
+{% endblock %} diff --git a/views/mio/user/view.twig b/views/mio/user/view.twig index bc2426b1..164b3ed4 100644 --- a/views/mio/user/view.twig +++ b/views/mio/user/view.twig @@ -1,7 +1,8 @@ {% extends '@mio/user/master.twig' %} {% 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 youtube_is_channel_id = profile.user_youtube|slice(0, 2) == 'UC' and profile.user_youtube|length == 24 %} @@ -118,7 +119,7 @@ {% endspaceless %} {% endif %}
-
+