From 7beef3a1d5bea8fbdadbc7ea95b6933a4c757854 Mon Sep 17 00:00:00 2001 From: Riyyi Date: Thu, 10 Nov 2022 15:19:34 +0100 Subject: [PATCH] Everywhere: Add initial cut of the blogging functionality --- app/controllers/BlogController.php | 63 ++++++++++++++++++++++++++++++ app/model/BlogModel.php | 9 +++++ app/views/admin/cache.php | 3 +- app/views/blog.php | 17 ++++++++ app/views/partials/blog-posts.php | 38 ++++++++++++++++++ public/css/style.css | 5 +++ public/js/site.js | 33 ++++++++++++++++ route.php | 2 + 8 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 app/controllers/BlogController.php create mode 100644 app/model/BlogModel.php create mode 100644 app/views/blog.php create mode 100644 app/views/partials/blog-posts.php diff --git a/app/controllers/BlogController.php b/app/controllers/BlogController.php new file mode 100644 index 0000000..23f595e --- /dev/null +++ b/app/controllers/BlogController.php @@ -0,0 +1,63 @@ +router->request()->param('search', ''); + $posts = $this->search($query); + + $this->defineHelpers(); + + $this->router->service()->search = $query; + $this->router->service()->posts = $posts; + $this->router->service()->injectView = $this->views . '/partials/blog-posts.php'; + parent::view('blog', 'Hello'); + } + + public function searchAction(): void + { + $query = $this->router->request()->param('query', ''); + $posts = $this->search($query); + + $this->defineHelpers(); + + $this->router->service()->posts = $posts; + $this->router->service()->partial($this->views . '/partials/blog-posts.php', $posts); + } + + //-------------------------------------// + + private function search(string $query): ?array + { + return BlogModel::selectAll( + 'blog_post.*, media.filename, media.extension, page.page, section.section, log.created_at', ' + LEFT JOIN media ON blog_post.media_id = media.id + LEFT JOIN page ON blog_post.page_id = page.id + LEFT JOIN section ON page.section_id = section.id + LEFT JOIN log ON blog_post.log_id = log.id + WHERE blog_post.archived = 0 AND + (blog_post.title LIKE :query OR blog_post.tag LIKE :query) + ', [[':query', "%$query%", \PDO::PARAM_STR]]); + } + + private function defineHelpers(): void + { + $this->router->service()->prettyTimestamp = function (string $timestamp): string { + $date = date_create($timestamp); + $date = date_format($date, 'd M Y'); + return "{$date}"; + }; + + $this->router->service()->tags = function (string $tags): array { + // Remove empty elements via array_filter() + return array_filter(explode(':', $tags)); + }; + } + + +} diff --git a/app/model/BlogModel.php b/app/model/BlogModel.php new file mode 100644 index 0000000..f6fa299 --- /dev/null +++ b/app/model/BlogModel.php @@ -0,0 +1,9 @@ +

Cache

diff --git a/app/views/blog.php b/app/views/blog.php new file mode 100644 index 0000000..c09f342 --- /dev/null +++ b/app/views/blog.php @@ -0,0 +1,17 @@ +
+sideContent ? '8' : '12'; ?> +
+ +
+ +
+ +
+
+ +
+ partial($this->injectView); ?> +
+
+
diff --git a/app/views/partials/blog-posts.php b/app/views/partials/blog-posts.php new file mode 100644 index 0000000..9654423 --- /dev/null +++ b/app/views/partials/blog-posts.php @@ -0,0 +1,38 @@ + +posts as $post) { ?> + +
+
+
+
+

+ prettyTimestamp)($post['created_at']); ?> +
+

+ +

+ + + + tags: + tags)($post['tag']); ?> + $tag) { ?> + + + + +
+ +
+ +
+ +
+ +
+
+
+ diff --git a/public/css/style.css b/public/css/style.css index 0a8a1c7..3a2b4d9 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -57,6 +57,11 @@ nav.shadow { cursor: pointer; } +a.clear { + color: inherit; + text-decoration: none; +} + /* Anchor offset */ h3 { position: relative; diff --git a/public/js/site.js b/public/js/site.js index ef22a2c..13f8273 100644 --- a/public/js/site.js +++ b/public/js/site.js @@ -12,6 +12,39 @@ $(document).ready(function() { return elementBottom > viewportTop && elementTop < viewportBottom; } + //------------------------------------------// + // Blog search + + function blogSearch(input) + { + var url = input.data("url"); + var search = input.val(); + window.location.href = url + '?search=' + search; + } + + $("#js-blog-search").keydown(function(e) { + if (e.key == 'Enter') { + e.preventDefault(); + blogSearch($(this)); + } + }); + + $("#js-blog-search-button").click(function() { + blogSearch($("#js-blog-search")); + }); + + $("#js-blog-search").on("input", function() { + var url = $(this).data("url"); + var search = $(this).val(); + if (search.length == 0 || search.length >= 3) { + fetch(url + '/search?query=' + search) + .then(response => response.text()) + .then(data => { + $("#blog-posts").empty().append(data); + }); + } + }); + //------------------------------------------// // Image hover mouseenter diff --git a/route.php b/route.php index e12df84..8061f6c 100644 --- a/route.php +++ b/route.php @@ -17,6 +17,8 @@ return [ ['/img/captcha.jpg', 'IndexController', 'captcha'], ['/robots.txt', 'IndexController', 'robots'], ['/sitemap.xml', 'IndexController', 'sitemap'], + ['/blog', 'BlogController'], + ['/blog/search', 'BlogController', 'search'], ['/login', 'LoginController', 'login', ['', 'Sign in', '']], ['/reset-password', 'LoginController', 'reset', ['', 'Reset password', '']], ['/logout', 'LoginController', 'logout'],