]> git.bts.cx Git - cx.git/blob - cx/lib/posts.php
a7ebfa459bb6c5a67feb98fa14d7b1dd71ce5055
[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_metadata() {
49                 $data = [];
50
51                 $doc = new DOMDocument();
52                 $doc->loadHTML($this->html_content);
53
54                 $image_tag = $doc->getElementsByTagName('img')[0];
55
56                 if ($image_tag != null) {
57                         $data['post_hero_image'] = $image_tag->getAttribute('src');
58                         $data['post_hero_image_alt'] = htmlspecialchars($image_tag->getAttribute('alt'));
59                 }
60
61                 return new PostMetadata($data);
62         }
63 }
64
65 function cx_post_make_slug($title) {
66         $alnum_title = preg_replace('/[^A-Za-z0-9 ]?/', '', $title);
67         
68         $slug_components = explode(' ', $alnum_title, 10);
69         $slug_components = array_filter($slug_components);
70         $slug_components = array_values($slug_components); // re-index
71
72         $slug = join('-', $slug_components);
73         $slug = strtolower($slug);
74
75         return $slug;
76 }
77
78 function cx_posts_add_post($site_id, $title, $slug, $date, $page, $draft, $nav_index, $data) {
79         $creation_time = $update_time = time();
80         
81         if ($slug == null) {
82                 $slug = cx_post_make_slug($title);
83         }
84
85         if ($date == null) {
86                 $date = $update_time;
87         }
88
89         $sql = 'INSERT INTO posts (
90                         post_site_id,
91                         post_creation_time,
92                         post_update_time,
93                         post_slug,
94                         post_date,
95                         post_is_page,
96                         post_is_draft,
97                         post_navigation_index,
98                         post_title,
99                         post_data,
100                         post_data_version)
101                 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);';
102         $id = cx_db_exec($sql, $site_id, $creation_time, $update_time, $slug, $date, $page, $draft, $nav_index, $title, $data, 1);
103         return $id;
104 }
105
106 function cx_posts_update_post($post_id, $title, $slug, $date, $page, $draft, $nav_index, $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_page = ?,
122                 post_is_draft = ?,
123                 post_navigation_index = ?,
124                 post_title = ?,
125                 post_data = ?
126                 WHERE post_id == ?;';
127                 //LIMIT 1;';
128         cx_db_exec($sql, $update_time, $slug, $date, $page, $draft, $nav_index, $title, $data, $post_id);
129 }
130
131 function cx_posts_delete_post($post_id) {
132         $sql = 'DELETE FROM posts
133                 WHERE post_id == ?;';
134                 //LIMIT 1;';
135         cx_db_exec($sql, $post_id);
136 }
137
138 function cx_posts_get(int $limit = 0, int $offset = 0, bool $include_drafts = false) {
139         $sql = 'SELECT
140                 post_id,
141                 post_slug,
142                 post_date,
143                 post_is_page,
144                 post_is_draft,
145                 post_navigation_index,
146                 post_title,
147                 post_data
148                 FROM posts
149                 WHERE post_is_page == FALSE';
150         
151         if ($include_drafts == false) {
152                 $sql .= ' AND post_is_draft == FALSE';
153         }
154
155         $sql .= ' ORDER BY post_date DESC';
156         
157         if ($limit > 0) {
158                 $sql .= ' LIMIT ' . $limit;
159         }
160         
161         if ($offset > 0) {
162                 $sql .= ' OFFSET ' . $offset;
163         }
164
165         $sql .= ';';
166
167         foreach (cx_db_query($sql) as $post) {
168                 $p = new Post($post);
169                 yield $p;
170         }
171 }
172
173 function cx_posts_count(bool $include_drafts = false) {
174         $sql = 'SELECT
175                 COUNT(post_id) AS _count
176                 FROM posts
177                 WHERE post_is_page == FALSE';
178         
179         if ($include_drafts == false) {
180                 $sql .= ' AND post_is_draft == FALSE';
181         }
182
183         $sql .= ';';
184
185
186         foreach (cx_db_query($sql) as $count_details) {
187                 return $count_details['_count'];
188         }
189
190         return 0;
191 }
192
193 function cx_posts_find_post($post_id) {
194         $sql = 'SELECT
195                 post_id,
196                 post_slug,
197                 post_date,
198                 post_is_page,
199                 post_is_draft,
200                 post_navigation_index,
201                 post_title,
202                 post_data
203                 FROM posts
204                 WHERE post_id == ?
205                 LIMIT 1;';
206
207         foreach (cx_db_query($sql, $post_id) as $post) {
208                 $p = new Post($post);
209                 return $p;
210         }
211
212         return null;
213 }
214
215 function cx_posts_find_article_id($post_slug, bool $include_drafts = false) {
216         $sql = 'SELECT
217                 post_id
218                 FROM posts
219                 WHERE post_slug == ?
220                 AND post_is_page == FALSE';
221
222         if ($include_drafts == false) {
223                 $sql .= ' AND post_is_draft == FALSE';
224         }
225
226         $sql .= ' LIMIT 1';
227
228         $sql .= ';';
229
230         foreach (cx_db_query($sql, $post_slug) as $post) {
231                 return $post['post_id'];
232         }
233
234         return null;
235
236 }
237
238 function cx_posts_find_page_id($post_slug, bool $include_drafts = false) {
239         $sql = 'SELECT
240                 post_id
241                 FROM posts
242                 WHERE post_slug == ?
243                 AND post_is_page == TRUE';
244
245         if ($include_drafts == false) {
246                 $sql .= ' AND post_is_draft == FALSE';
247         }
248
249         $sql .= ' LIMIT 1';
250
251         $sql .= ';';
252
253         foreach (cx_db_query($sql, $post_slug) as $post) {
254                 return $post['post_id'];
255         }
256
257         return null;
258 }
259
260 function cx_pages_get(bool $navigation_only = true, bool $include_drafts = false) {
261         $sql = 'SELECT
262                 post_id,
263                 post_slug,
264                 post_date,
265                 post_is_page,
266                 post_is_draft,
267                 post_navigation_index,
268                 post_title,
269                 post_data
270                 FROM posts
271                 WHERE post_is_page == TRUE';
272
273         if ($navigation_only) {
274                 $sql .= ' AND post_navigation_index != ""';
275         }
276
277         if ($include_drafts == false) {
278                 $sql .= ' AND post_is_draft == FALSE';
279         }
280
281         $sql .= ' ORDER BY post_navigation_index ASC, post_date DESC';
282
283         $sql .= ';';
284
285         foreach (cx_db_query($sql) as $post) {
286                 $p = new Post($post);
287                 yield $p;
288         }
289 }
290
291 cx_setup_register(1, function() {
292         cx_db_exec('CREATE TABLE posts (
293                         post_id INTEGER PRIMARY KEY,
294                         post_site_id INTEGER,
295                         post_creation_time INTEGER,
296                         post_update_time INTEGER,
297                         post_slug STRING,
298                         post_date INTEGER,
299                         post_is_page BOOLEAN,
300                         post_is_draft BOOLEAN,
301                         post_navigation_index INTEGER,
302                         post_title STRING,
303                         post_data BLOB,
304                         post_data_version INTEGER,
305
306                         FOREIGN KEY(post_site_id) REFERENCES sites(site_id)
307                 );');
308 });