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