]> git.bts.cx Git - cx.git/blob - cx/lib/posts.php
326d81c470585f90848e59d57b2ab2ffcbd339d8
[cx.git] / cx / lib / posts.php
1 <?php
2
3 cx_require('lib', 'db.php');
4 cx_require('lib', 'setup.php');
5 cx_require('lib', 'markdown.php');
6
7 class PostMetadata {
8         public $hero_image;
9         public $hero_image_alt;
10
11         public function __construct($dict) {
12                 $this->hero_image = isset($dict['post_hero_image']) ? $dict['post_hero_image'] : null;
13                 $this->hero_image_alt = isset($dict['post_hero_image_alt']) ? $dict['post_hero_image_alt'] : null;
14         }
15 }
16
17 class Post {
18         public $id;
19         public $title;
20         public $slug;
21         public $date;
22         public $is_page;
23         public $is_draft;
24         public $nav_index;
25         public $data;
26         public $html_content;
27         public $html_excerpt;
28
29         public function __construct($dict) {
30                 $this->id = $dict['post_id']; // FIXME, hide when not used?
31                 $this->title = $dict['post_title'];
32                 $this->slug = $dict['post_slug'];
33                 $this->date = $dict['post_date'];
34                 $this->is_page = $dict['post_is_page'];
35                 $this->is_draft = $dict['post_is_draft'];
36                 $this->nav_index = $dict['post_navigation_index'];
37                 $this->data = $dict['post_data'];
38                 $this->html_content = cx_markdown_generate_html($this->data);
39                 $this->html_excerpt = null;
40
41                 // Read more...
42                 $segments = explode('---', $this->data, 2);
43                 if (count($segments) > 1) {
44                         $this->html_excerpt = cx_markdown_generate_html($segments[0]);
45                 }
46         }
47
48         public function get_permalink_path() {
49                 $post_permalink = $this->is_page ? '/' . $this->slug : '/' . date('Y', $this->date) . '/' . date('m', $this->date) . '/' . $this->slug;
50                 return $post_permalink;
51         }
52
53         public function get_metadata() {
54                 $data = [];
55
56                 $doc = new DOMDocument();
57                 $doc->loadHTML($this->html_content);
58
59                 $image_tag = $doc->getElementsByTagName('img')[0];
60
61                 if ($image_tag != null) {
62                         $data['post_hero_image'] = $image_tag->getAttribute('src');
63                         $data['post_hero_image_alt'] = htmlspecialchars($image_tag->getAttribute('alt'));
64                 }
65
66                 return new PostMetadata($data);
67         }
68 }
69
70 function cx_post_make_slug($title) {
71         $alnum_title = preg_replace('/[^A-Za-z0-9 ]?/', '', $title);
72         
73         $slug_components = explode(' ', $alnum_title, 10);
74         $slug_components = array_filter($slug_components);
75         $slug_components = array_values($slug_components); // re-index
76
77         $slug = join('-', $slug_components);
78         $slug = strtolower($slug);
79
80         return $slug;
81 }
82
83 function cx_posts_add_post($site_id, $title, $slug, $date, $page, $draft, $nav_index, $data) {
84         $creation_time = $update_time = time();
85         
86         if ($slug == null) {
87                 $slug = cx_post_make_slug($title);
88         }
89
90         if ($date == null) {
91                 $date = $update_time;
92         }
93
94         $sql = 'INSERT INTO posts (
95                         post_site_id,
96                         post_creation_time,
97                         post_update_time,
98                         post_slug,
99                         post_date,
100                         post_is_page,
101                         post_is_draft,
102                         post_navigation_index,
103                         post_title,
104                         post_data,
105                         post_data_version)
106                 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);';
107         $id = cx_db_exec($sql, $site_id, $creation_time, $update_time, $slug, $date, $page, $draft, $nav_index, $title, $data, 1);
108         return $id;
109 }
110
111 function cx_posts_update_post($post_id, $title, $slug, $date, $page, $draft, $nav_index, $data) {
112         $update_time = time();
113         
114         if ($slug == null) {
115                 $slug = cx_post_make_slug($title);
116         }
117
118         if ($date == null) {
119                 $date = $update_time;
120         }
121
122         $sql = 'UPDATE posts
123                 SET post_update_time = ?,
124                 post_slug = ?,
125                 post_date = ?,
126                 post_is_page = ?,
127                 post_is_draft = ?,
128                 post_navigation_index = ?,
129                 post_title = ?,
130                 post_data = ?
131                 WHERE post_id == ?;';
132                 //LIMIT 1;';
133         cx_db_exec($sql, $update_time, $slug, $date, $page, $draft, $nav_index, $title, $data, $post_id);
134 }
135
136 function cx_posts_delete_post($post_id) {
137         $sql = 'DELETE FROM posts
138                 WHERE post_id == ?;';
139                 //LIMIT 1;';
140         cx_db_exec($sql, $post_id);
141 }
142
143 function cx_posts_get(int $limit = 0, int $offset = 0, bool $include_drafts = false) {
144         $sql = 'SELECT
145                 post_id,
146                 post_slug,
147                 post_date,
148                 post_is_page,
149                 post_is_draft,
150                 post_navigation_index,
151                 post_title,
152                 post_data
153                 FROM posts
154                 WHERE post_is_page == FALSE';
155         
156         if ($include_drafts == false) {
157                 $sql .= ' AND post_is_draft == FALSE';
158         }
159
160         $sql .= ' ORDER BY post_date DESC';
161         
162         if ($limit > 0) {
163                 $sql .= ' LIMIT ' . $limit;
164         }
165         
166         if ($offset > 0) {
167                 $sql .= ' OFFSET ' . $offset;
168         }
169
170         $sql .= ';';
171
172         foreach (cx_db_query($sql) as $post) {
173                 $p = new Post($post);
174                 yield $p;
175         }
176 }
177
178 function cx_posts_count(bool $include_drafts = false) {
179         $sql = 'SELECT
180                 COUNT(post_id) AS _count
181                 FROM posts
182                 WHERE post_is_page == FALSE';
183         
184         if ($include_drafts == false) {
185                 $sql .= ' AND post_is_draft == FALSE';
186         }
187
188         $sql .= ';';
189
190
191         foreach (cx_db_query($sql) as $count_details) {
192                 return $count_details['_count'];
193         }
194
195         return 0;
196 }
197
198 function cx_posts_find_post($post_id) {
199         $sql = 'SELECT
200                 post_id,
201                 post_slug,
202                 post_date,
203                 post_is_page,
204                 post_is_draft,
205                 post_navigation_index,
206                 post_title,
207                 post_data
208                 FROM posts
209                 WHERE post_id == ?
210                 LIMIT 1;';
211
212         foreach (cx_db_query($sql, $post_id) as $post) {
213                 $p = new Post($post);
214                 return $p;
215         }
216
217         return null;
218 }
219
220 function cx_posts_find_article_id($post_slug, bool $include_drafts = false) {
221         $sql = 'SELECT
222                 post_id
223                 FROM posts
224                 WHERE post_slug == ?
225                 AND post_is_page == FALSE';
226
227         if ($include_drafts == false) {
228                 $sql .= ' AND post_is_draft == FALSE';
229         }
230
231         $sql .= ' LIMIT 1';
232
233         $sql .= ';';
234
235         foreach (cx_db_query($sql, $post_slug) as $post) {
236                 return $post['post_id'];
237         }
238
239         return null;
240
241 }
242
243 function cx_posts_find_page_id($post_slug, bool $include_drafts = false) {
244         $sql = 'SELECT
245                 post_id
246                 FROM posts
247                 WHERE post_slug == ?
248                 AND post_is_page == TRUE';
249
250         if ($include_drafts == false) {
251                 $sql .= ' AND post_is_draft == FALSE';
252         }
253
254         $sql .= ' LIMIT 1';
255
256         $sql .= ';';
257
258         foreach (cx_db_query($sql, $post_slug) as $post) {
259                 return $post['post_id'];
260         }
261
262         return null;
263 }
264
265 function cx_pages_get(bool $navigation_only = true, bool $include_drafts = false) {
266         $sql = 'SELECT
267                 post_id,
268                 post_slug,
269                 post_date,
270                 post_is_page,
271                 post_is_draft,
272                 post_navigation_index,
273                 post_title,
274                 post_data
275                 FROM posts
276                 WHERE post_is_page == TRUE';
277
278         if ($navigation_only) {
279                 $sql .= ' AND post_navigation_index != ""';
280         }
281
282         if ($include_drafts == false) {
283                 $sql .= ' AND post_is_draft == FALSE';
284         }
285
286         $sql .= ' ORDER BY post_navigation_index ASC, post_date DESC';
287
288         $sql .= ';';
289
290         foreach (cx_db_query($sql) as $post) {
291                 $p = new Post($post);
292                 yield $p;
293         }
294 }
295
296 cx_setup_register(1, function() {
297         cx_db_exec('CREATE TABLE posts (
298                         post_id INTEGER PRIMARY KEY,
299                         post_site_id INTEGER,
300                         post_creation_time INTEGER,
301                         post_update_time INTEGER,
302                         post_slug STRING,
303                         post_date INTEGER,
304                         post_is_page BOOLEAN,
305                         post_is_draft BOOLEAN,
306                         post_navigation_index INTEGER,
307                         post_title STRING,
308                         post_data BLOB,
309                         post_data_version INTEGER,
310
311                         FOREIGN KEY(post_site_id) REFERENCES sites(site_id)
312                 );');
313 });