diff --git a/www/mysql_adapter.php b/www/mysql_adapter.php index 3d845b6..23904a7 100644 --- a/www/mysql_adapter.php +++ b/www/mysql_adapter.php @@ -268,7 +268,7 @@ class MySQLAdapter { ]; $qry = " - SELECT post_path, post_metadata + SELECT * FROM posts WHERE MATCH(post_tags) AGAINST (? IN BOOLEAN MODE) "; diff --git a/www/post.php b/www/post.php new file mode 100644 index 0000000..94c0da2 --- /dev/null +++ b/www/post.php @@ -0,0 +1,166 @@ + + -1, + 'post_path' => '/404.md', + 'post_title' => '404 Page', + 'post_metadata' => [ + 'type' => '404' + ] + ]; + } + + public static function _deduce_type($path) { + $ext = pathinfo($path, PATHINFO_EXTENSION); + + if(preg_match("/\.(\w+)\.md$/", $path, $ext_match)) { + $ext = $ext_match[1]; + } + + $ext_mapping = [ + '' => 'directory', + 'md' => 'text/markdown', + 'png' => 'image', + 'jpg' => 'image', + 'jpeg' => 'image' + ]; + + return $ext_mapping[$ext] ?? '?'; + } + + public static function _deduce_icon($type) { + $icon_mapping = [ + '' => 'question', + 'text/markdown' => 'markdown', + 'directory' => 'folder', + 'gallery' => 'images', + 'image' => 'image' + ]; + + return $icon_mapping[$type] ?? 'unknown'; + } + + function __construct($post_handler, $sql_row) { + $this->post_handler = $post_handler; + + $this->content_html = null; + + $sql_meta = null; + if(!isset($sql_row) or !$sql_row['found']) { + $sql_row = $this->_generate_404($sql_row); + $sql_meta = $sql_row['post_metadata']; + } + + + $sql_meta = $sql_row['post_metadata']; + if(is_string($sql_meta)) { + $sql_meta = json_decode($sql_meta, true); + } + + unset($sql_meta['settings']); + + $this->sql_row = $sql_row; + $this->sql_meta = $sql_meta ?? []; + $sql_settings = json_decode($sql_row['post_settings_cache'], true) ?? []; + + $data = [ + 'id' => $sql_row['post_id'], + 'path' => $sql_row['post_path'], + 'url' => 'https://' . $sql_row['host'] . $sql_row['post_path'], + 'created_at' => $sql_row['post_create_time'] ?? '', + 'updated_at' => $sql_row['post_update_time'] ?? '', + 'view_count' => $sql_row['post_access_count'] ?? 0 + ]; + + $data['title'] = $sql_meta['title'] ?? $sql_row['title']; + unset($sql_meta['title']); + + $data['tags'] = $sql_meta['tags'] ?? []; + unset($sql_meta['tags']); + + $data['type'] = $sql_meta['type'] + ?? self::_deduce_type($sql_row['post_path']); + unset($sql_meta['type']); + + $data['icon'] = $sql_meta['icon'] + ?? self::_deduce_icon($data['type']); + unset($sql_meta['icon']); + + if(isset($sql_meta['media_url'])) { + $data['media_url'] = $sql_meta['media_url']; + $data['thumb_url'] = $sql_meta['thumb_url'] ?? $data['media_url']; + + unset($sql_meta['media_url']); + unset($sql_meta['thumb_url']); + } + + $data['banners'] = $sql_meta['banners'] + ?? $sql_settings['banners'] + ?? self::$default_banners; + + unset($sql_meta['banners']); + unset($sql_settings['banners']); + + $data['preview_image'] = $sql_meta['preview_image'] ?? $data['banners'][0]['src'] ?? null; + unset($sql_meta['preview_image']); + + $data['brief'] = $sql_meta['brief'] + ?? $data['title']; + unset($sql_meta['brief']); + + $data['excerpt'] = $sql_meta['excerpt'] + ?? substr($sql_row['post_content'], 0, 256); + + $data['metadata'] = $sql_meta; + $data['settings'] = $sql_settings; + + $this->data = $data; + } + + public function __get($name) { + if($name == 'html') { + return $this->get_html(); + } + if($name == 'markdown') { + return $this->sql_row['post_content']; + } + if($name == 'json') { + return $this->to_json(); + } + + return $this->data[$name]; + } + + public function get_html() { + $fn = self::$markdown_engine; + $this->content_html ??= $fn($this); + + return $this->content_html; + } + + public function to_json($with_markdown = false, $with_html = false) { + $out_data = $this->data; + + if($with_markdown) { + $out_data['markdown'] = $this->sql_row['post_content']; + } + if($with_html) { + $out_data['html'] = $this->get_html(); + } + + return json_encode($out_data); + } +} + +?> \ No newline at end of file diff --git a/www/post_adapter.php b/www/post_adapter.php index 09027cf..314f0d7 100644 --- a/www/post_adapter.php +++ b/www/post_adapter.php @@ -118,12 +118,14 @@ class PostHandler extends MySQLAdapter { } function handle_upload($post_path, $file_path) { + $post_path = $this->_sanitize_path($post_path); $ext = pathinfo($post_path, PATHINFO_EXTENSION); switch($ext) { case "md": $this->save_markdown_post($post_path, file_get_contents($file_path)); + $this->make_post_directory(dirname($post_path)); move_uploaded_file($file_path, $this->data_directory . $post_path); break; default: diff --git a/www/router.php b/www/router.php index 18c4641..7994645 100644 --- a/www/router.php +++ b/www/router.php @@ -5,6 +5,9 @@ $data_time_start = microtime(true); require_once 'vendor/autoload.php'; require_once 'post_adapter.php'; + +require_once 'post.php'; + require_once 'fontawesome.php'; require_once 'dergdown.php'; @@ -40,6 +43,10 @@ function dergdown_to_html($text) { return $Parsedown->text($text); } +function post_to_html($post) { + return dergdown_to_html($post->markdown); +} +PostData::$markdown_engine = "post_to_html"; function deduce_user_agent() { $real_agent=$_SERVER['HTTP_USER_AGENT']; @@ -160,6 +167,7 @@ function try_render_post($SURI) { break; + case 'blog': case 'text/markdown': echo render_twig('post_types/markdown.html', [ "post" => $post @@ -185,6 +193,30 @@ function try_render_post($SURI) { ]); break; + case 'blog_list': + if(preg_match('/^(.*[^\/])((?:#.*)?)$/', $SURI, $match)) { + header('Location: ' . $match[1] . '/' . $match[2]); + + die(); + } + + $search_query = $post['post_metadata']['search_tags'] ?? + ('+type:blog +path:' . $post['post_path'] . '/*'); + + $search_result = $adapter->perform_post_search($search_query); + + $search_result = array_map(function($key) { + $post = new PostData(null, $key); + return $post->data; + }, $search_result['results']); + + echo render_twig('post_types/blog_list.html', [ + "post" => $post, + "subposts" => $adapter->get_subposts_by_path($SURI), + "blog_posts" => $search_result + ]); + break; + case 'image': echo render_twig('post_types/image.html', [ "post" => $post, @@ -233,7 +265,9 @@ function generate_website($SURI) { } elseif(preg_match('/^\/api\/posts(.*)$/', $SURI, $match)) { header('Content-Type: application/json'); - echo json_encode($adapter->get_post_by_path($match[1])); + + $post = new PostData(null, $adapter->get_post_by_path($match[1])); + echo $post->to_json(with_markdown: true, with_html: true); } elseif(preg_match('/^\/api\/subposts(.*)$/', $SURI, $match)) { diff --git a/www/static/article_blop.css b/www/static/article_blop.css new file mode 100644 index 0000000..1c46c37 --- /dev/null +++ b/www/static/article_blop.css @@ -0,0 +1,81 @@ + + +.article_blop { + position: relative; + overflow: clip; + z-index: 0; + + background: var(--bg_2); + + margin: 2rem; + padding: 0; + + border-radius: 1rem; + + box-shadow: 0px 5px 5px 0px #00000040; + transition: 0.3s; + + min-height: 10rem; +} + +.article_blop_bg { + position: absolute; + left: 0px; + right: 0; + top: 0; + bottom: 0; + + background-repeat: no-repeat; + background-position: center; + background-size: cover; + + opacity: 0.2; + + z-index: -1; +} + +.article_blop:hover { + box-shadow: 0px 8px 8px 0px #00000040; +} + +.article_blop_content { + padding: 1rem; + padding-top: 5rem; +} + +.article_blop_tags { + position: absolute; + top: 0.5rem; + right: 0.2rem; + + width: 40%; + height: auto; + + list-style: none; + display: flex; + flex-direction: row; + flex-flow: row wrap; + + justify-content: right; +} +.article_blop_tags :first-child { + margin-left: auto; +} +.article_blop_tags li { + margin-right: 0.4rem; + margin-bottom: 0.4rem; + + padding-left: 0.2rem; + padding-right: 0.2rem; + + font-size: 0.8rem; + + font-style: normal; + font-weight: bold; + + background-color: var(--highlight_1); + border-radius: 0.3rem; + color: var(--bg_2); + + +} \ No newline at end of file diff --git a/www/static/dergstyle.css b/www/static/dergstyle.css index ccde5fa..8ee91c8 100644 --- a/www/static/dergstyle.css +++ b/www/static/dergstyle.css @@ -16,6 +16,7 @@ body { --bg_2: #2c2943; --bg_3: #3f4148; + --highlight_0: #ee9015b1; --highlight_1: #ee9015; --highlight_2: #edd29e; @@ -185,6 +186,7 @@ a:hover { z-index: 5; } + #post_file_titles { display: flex; flex-direction: row; @@ -194,13 +196,35 @@ a:hover { padding: 0px; } -#post_file_titles * { - padding: 0.5rem; +#post_file_titles li { + padding: 0.2rem 0.8rem; + font-style: bold; font-size: 1.3rem; background: var(--highlight_1); } +#post_file_titles li:hover { + background: var(--highlight_0) !important; +} + +#post_file_bar_dirbtn { + margin-left: 0.15rem; + background: var(--bg_2) !important; +} +#post_file_bar #dir_collapse { + display: none; +} +#post_file_bar #dir_collapse:checked + #post_file_bar_dirbtn { + background: var(--highlight_1) !important; +} + +.directory { + display: none; +} +#dir_collapse:checked ~ .directory { + display: block; +} #post_file_path { width: 100%; @@ -223,7 +247,7 @@ a:hover { padding-right: 0.2rem; } -#main_content_wrapper article { +article { background: var(--bg_3); border-radius: 0rem 0rem 0.8rem 0.8rem; @@ -232,7 +256,7 @@ a:hover { padding: 0.75rem; } -#main_content_wrapper article img { +article img { display: block; max-width: 100%; diff --git a/www/templates/fragments/article_blop.html b/www/templates/fragments/article_blop.html new file mode 100644 index 0000000..0000271 --- /dev/null +++ b/www/templates/fragments/article_blop.html @@ -0,0 +1,23 @@ + + + +
+
+ +
+

+ {{post.title}} +

+ +
    + {% for tag in post.tags %} +
  • {{ tag }}
  • + {% endfor %} +
+ + + {{post.excerpt}} + +
+
+
\ No newline at end of file diff --git a/www/templates/post_types/blog_list.html b/www/templates/post_types/blog_list.html new file mode 100644 index 0000000..9fe2add --- /dev/null +++ b/www/templates/post_types/blog_list.html @@ -0,0 +1,48 @@ + + +{% extends "pathed_content.html" %} + +{% block extra_head %} + + +{%endblock%} + +{%block content_article%} + {% if subposts|length > 0 %} + +

Art Subfolders:

+ + + + + + + {% for subpost in subposts %} + + + + + + + {% endfor %} +
NameTitleModified
+ {{ fa[subpost.post_metadata.icon] | raw }} + + {{subpost.post_basename}} + + {{ subpost.post_metadata.title }} + + {{ subpost.post_update_time }} +
+ {% endif %} + + {{ content_html|raw }} + + {% if blog_posts|length > 0 %} + {% for post in blog_posts %} + {% include('fragments/article_blop.html') %} + {% endfor %} + {%else%} +

How sad. There are no blog posts yet... What a real shame :c

+ {% endif %} +{%endblock%}