]> git.bts.cx Git - cx.git/blob - cx/lib/posts.php
post metadata support (not very good yet)
[cx.git] / cx / lib / posts.php
1 <?php
2
3 cx_require('lib', 'db.php');
4 cx_require('lib', 'setup.php');
5 cx_require('third_party', 'parsedown', 'Parsedown.php');
6
7 function mk_markdown($markdown) {
8         static $Parsedown = new Parsedown();
9
10         return $Parsedown->text($markdown);
11 }
12
13 class PostMetadata {
14         public $hero_image;
15         public $hero_image_alt;
16
17         public function __construct($dict) {
18                 $this->hero_image = $dict['post_hero_image'];
19                 $this->hero_image_alt = $dict['post_hero_image_alt'];
20         }
21 }
22
23 class Post {
24         public $id;
25         public $title;
26         public $slug;
27         public $date;
28         public $is_draft;
29         public $data;
30         public $html_content;
31         public $html_excerpt;
32
33         public function __construct($dict) {
34                 $this->id = $dict['post_id']; // FIXME, hide when not used?
35                 $this->title = $dict['post_title'];
36                 $this->slug = $dict['post_slug'];
37                 $this->date = $dict['post_date'];
38                 $this->is_draft = $dict['post_is_draft'];
39                 $this->data = $dict['post_data'];
40                 $this->html_content = mk_markdown($this->data);
41                 $this->html_excerpt = null;
42
43                 // Read more...
44                 $segments = explode('---', $this->data, 2);
45                 if (count($segments) > 1) {
46                         $this->html_excerpt = mk_markdown($segments[0]);
47                 }
48         }
49
50         public function get_metadata() {
51                 $data = [];
52
53                 $doc = new DOMDocument();
54                 $doc->loadHTML($this->html_content);
55
56                 $image_tag = $doc->getElementsByTagName('img')[0];
57
58                 if ($image_tag != null) {
59                         $data['post_hero_image'] = $image_tag->getAttribute('src');
60                         $data['post_hero_image_alt'] = htmlspecialchars($image_tag->getAttribute('alt'));
61                 }
62
63                 return new PostMetadata($data);
64         }
65 }
66
67 function cx_post_make_slug($title) {
68         $alnum_title = preg_replace('/[^A-Za-z0-9 ]?/', '', $title);
69         
70         $slug_components = explode(' ', $alnum_title, 10);
71         $slug_components = array_filter($slug_components);
72         $slug_components = array_values($slug_components); // re-index
73
74         $slug = join('-', $slug_components);
75         $slug = strtolower($slug);
76
77         return $slug;
78 }
79
80 function cx_posts_add_post($site_id, $title, $slug, $date, $draft, $data) {
81         $creation_time = $update_time = time();
82         
83         if ($slug == null) {
84                 $slug = cx_post_make_slug($title);
85         }
86
87         if ($date == null) {
88                 $date = $update_time;
89         }
90
91         $sql = 'INSERT INTO posts (
92                         post_site_id,
93                         post_creation_time,
94                         post_update_time,
95                         post_slug,
96                         post_date,
97                         post_is_page,
98                         post_is_draft,
99                         post_title,
100                         post_data,
101                         post_data_version)
102                 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);';
103         cx_db_exec($sql, $site_id, $creation_time, $update_time, $slug, $date, false, $draft, $title, $data, 1);
104 }
105
106 function cx_posts_update_post($post_id, $title, $slug, $date, $draft, $data) {
107         $update_time = time();
108         
109         if ($slug == null) {
110                 $slug = cx_post_make_slug($title);
111         }
112
113         if ($date == null) {
114                 $date = $update_time;
115         }
116
117         $sql = 'UPDATE posts
118                 SET post_update_time = ?,
119                 post_slug = ?,
120                 post_date = ?,
121                 post_is_draft = ?,
122                 post_title = ?,
123                 post_data = ?
124                 WHERE post_id == ?;';
125                 //LIMIT 1;';
126         cx_db_exec($sql, $update_time, $slug, $date, $draft, $title, $data, $post_id);
127 }
128
129 function cx_posts_delete_post($post_id) {
130         $sql = 'DELETE FROM posts
131                 WHERE post_id == ?;';
132                 //LIMIT 1;';
133         cx_db_exec($sql, $post_id);
134 }
135
136 function cx_posts_get(int $limit = 0, bool $include_drafts = false) {
137         $sql = 'SELECT
138                 post_id,
139                 post_slug,
140                 post_date,
141                 post_is_draft,
142                 post_title,
143                 post_data
144                 FROM posts
145                 WHERE post_is_page == FALSE';
146         
147         if ($include_drafts == false) {
148                 $sql .= ' AND post_is_draft == FALSE';
149         }
150
151         $sql .= ' ORDER BY post_date DESC';
152         
153         if ($limit > 0) {
154                 $sql .= ' LIMIT ' . $limit;
155         }
156
157         $sql .= ';';
158
159         foreach (cx_db_query($sql) as $post) {
160                 $p = new Post($post);
161                 yield $p;
162         }
163 }
164
165 function cx_posts_find_post($post_id) {
166         $sql = 'SELECT
167                 post_id,
168                 post_slug,
169                 post_date,
170                 post_is_draft,
171                 post_title,
172                 post_data
173                 FROM posts
174                 WHERE post_is_page == FALSE
175                 AND post_id == ?
176                 LIMIT 1;';
177
178         foreach (cx_db_query($sql, $post_id) as $post) {
179                 $p = new Post($post);
180                 return $p;
181         }
182
183         return null;
184 }
185
186 function cx_posts_find_post_id($post_slug) {
187         $sql = 'SELECT
188                 post_id
189                 FROM posts
190                 WHERE post_slug == ?
191                 LIMIT 1;';
192
193         foreach (cx_db_query($sql, $post_slug) as $post) {
194                 return $post['post_id'];
195         }
196
197         return null;
198 }
199
200 function cx_pages_get() {
201         $sql = 'SELECT
202                 post_id,
203                 post_slug,
204                 post_date,
205                 post_is_draft,
206                 post_title,
207                 post_data
208                 FROM posts
209                 WHERE post_is_page == TRUE
210                 AND post_is_draft == FALSE
211                 ORDER BY post_creation_time DESC;';
212
213         foreach (cx_db_query($sql) as $post) {
214                 $p = new Post($post);
215                 yield $p;
216         }
217 }
218
219 cx_setup_register(1, function() {
220         cx_db_exec('CREATE TABLE posts (
221                         post_id INTEGER PRIMARY KEY,
222                         post_site_id INTEGER,
223                         post_creation_time INTEGER,
224                         post_update_time INTEGER,
225                         post_slug STRING,
226                         post_date INTEGER,
227                         post_is_page BOOLEAN,
228                         post_is_draft BOOLEAN,
229                         post_title STRING,
230                         post_data BLOB,
231                         post_data_version INTEGER,
232
233                         FOREIGN KEY(post_site_id) REFERENCES sites(site_id)
234                 );');
235 });