source: trunk/libs/Post.php @ 1375

Revision 1375, 18.2 KB checked in by nick_ramsay, 3 years ago (diff)

[Trunk] Hotaru 1.1.3 [Run upgrade script]

Line 
1<?php
2/**
3 * Post functions
4 *
5 * PHP version 5
6 *
7 * LICENSE: Hotaru CMS is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * Hotaru CMS is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with Hotaru CMS. If not, see http://www.gnu.org/licenses/.
18 *
19 * @category  Content Management System
20 * @package   HotaruCMS
21 * @author    Nick Ramsay <admin@hotarucms.org>
22 * @copyright Copyright (c) 2009, Hotaru CMS
23 * @license   http://www.gnu.org/copyleft/gpl.html GNU General Public License
24 * @link      http://www.hotarucms.org/
25 */
26class Post
27{
28    // individual posts
29    protected $id = 0;
30    protected $archived         = 'N';            // archived Yes or No (Y/N)
31    protected $author           = 0;            // post author
32    protected $date             = '';           // post submission date
33    protected $status           = 'unsaved';    // initial status before database entry
34    protected $type             = '';           // post type, e.g. news, blog, forum
35    protected $category         = 1;            // default category 'all'
36    protected $tags             = '';           // tags
37    protected $title            = '';           // post title
38    protected $origUrl          = '';           // original url for the submitted post
39    protected $domain           = '';           // the domain of the submitted url
40    protected $url              = '';           // post slug (needs BASEURL and category attached)
41    protected $content          = '';           // post description
42    protected $contentLength    = 50;           // default min characters for content
43    protected $summary          = '';           // truncated post description
44    protected $summaryLength    = 200;          // default max characters for summary
45    protected $comments         ='open';        // is the comment form open or closed?
46    protected $subscribe        = 0;            // is the post author subscribed to comments?
47
48    public $vars                = array();      // for additional fields
49
50    /**
51     * Access modifier to set protected properties
52     */
53    public function __set($var, $val)
54    {
55        $this->$var = $val; 
56    }
57   
58   
59    /**
60     * Access modifier to get protected properties
61     */
62    public function &__get($var)
63    {
64        return $this->$var;
65    }
66   
67   
68    /**
69     * Get all the settings for the current post
70     *
71     * @param int $post_id - Optional row from the posts table in the database
72     * @param array $post_row - a post already fetched from the db, just needs reading
73     * @return bool
74     */   
75    public function readPost($h, $post_id = 0, $post_row = NULL)
76    {
77        $h->vars['post_error'] = false;
78       
79        if (!$post_id && !$post_row) {
80            $post_id = $this->id;   // use the id already assigned to $h->post
81        }
82       
83        if ($post_id != 0) {
84            $post_row = $h->getPost($post_id);
85            if (!$post_row) { $h->vars['post_error'] = true; return false; }
86        }
87       
88        if ($post_row) {
89            $this->id = $post_row->post_id;
90            $this->archived = $post_row->post_archived;
91            $this->author = $post_row->post_author;
92            $this->date = $post_row->post_date;
93            $this->status = $post_row->post_status;
94            $this->type = urldecode($post_row->post_type);
95            $this->category = urldecode($post_row->post_category);
96            $this->tags = stripslashes(urldecode($post_row->post_tags));
97            $this->title = stripslashes(urldecode($post_row->post_title));
98            $this->origUrl = urldecode($post_row->post_orig_url);
99            $this->domain = urldecode($post_row->post_domain);
100            $this->url = urldecode($post_row->post_url);
101            $this->content = stripslashes(urldecode($post_row->post_content));
102            $this->comments = $post_row->post_comments;
103            $this->subscribe = $post_row->post_subscribe;
104           
105            $this->vars['post_row'] = $post_row;    // make available to plugins
106           
107            $h->pluginHook('post_read_post');
108                       
109            return true;
110        } else {
111            return false;
112        }
113       
114    }
115   
116   
117    /**
118     * Gets a single post from the database
119     *
120     * @param int $post_id - post id of the post to get
121     * @return array|false
122     */   
123    public function getPost($h, $post_id = 0)
124    {
125        // Build SQL
126        $query = "SELECT * FROM " . TABLE_POSTS . " WHERE post_id = %d ORDER BY post_date DESC";
127        $sql = $h->db->prepare($query, $post_id);
128       
129        // Create temp cache array
130        if (!isset($h->vars['tempPostCache'])) { $h->vars['tempPostCache'] = array(); }
131
132        // If this query has already been read once this page load, we should have it in memory...
133        if (array_key_exists($sql, $h->vars['tempPostCache'])) {
134            // Fetch from memory
135            $post = $h->vars['tempPostCache'][$sql];
136        } else {
137            // Fetch from database
138            $post = $h->db->get_row($sql);
139            $h->vars['tempPostCache'][$sql] = $post;
140        }
141
142        if ($post) { return $post; } else { return false; }
143    }
144   
145   
146    /**
147     * Add a post to the database
148     *
149     * @return true
150     */   
151    public function addPost($h)
152    {
153        $sql = "INSERT INTO " . TABLE_POSTS . " SET post_author = %d, post_date = CURRENT_TIMESTAMP, post_status = %s, post_type = %s, post_category = %d, post_tags = %s, post_title = %s, post_orig_url = %s, post_domain = %s, post_url = %s, post_content = %s, post_subscribe = %d, post_updateby = %d";
154       
155        $h->db->query($h->db->prepare($sql, $this->author, $this->status, urlencode($this->type), $this->category, urlencode(trim($this->tags)), urlencode(trim($this->title)), urlencode($this->origUrl), urlencode($this->domain), urlencode(trim($this->url)), urlencode(trim($this->content)), $this->subscribe, $h->currentUser->id));
156       
157        $last_insert_id = $h->db->get_var($h->db->prepare("SELECT LAST_INSERT_ID()"));
158       
159        $this->id = $last_insert_id;
160        $this->vars['last_insert_id'] = $last_insert_id;    // make it available outside this class
161       
162        // Update post_date field if $this->date has been declared
163        // Normally used when scheduling or auto-submitting posts
164        if ($this->date) {
165           $date = date('YmdHis', $this->date);
166           $sql = "UPDATE " . TABLE_POSTS . " SET post_date = %s WHERE post_id = %d";
167           $h->db->query($h->db->prepare($sql, $date, $last_insert_id));
168        }
169
170        // Add tags to the Tags table:
171        require_once(LIBS . 'Tags.php');
172        $tags = new TagFunctions();
173        $tags->addTags($h, $this->id, $this->tags);
174       
175        $h->pluginHook('post_add_post');
176       
177        return true;
178    }
179   
180   
181    /**
182     * Update a post in the database
183     *
184     * @return true
185     */   
186    public function updatePost($h)
187    {
188        if (strstr($this->origUrl, BASEURL)) {
189            // original url contains our base url, so it must be an "editorial" post.
190            // Therefore, it's essential we rebuild this source url to match the updated post title to avoid errors:
191            $this->origUrl = $h->url(array('page'=>$this->id)); // update the url with the real one
192        }
193       
194        $parsed = parse_url($this->origUrl);
195        if (isset($parsed['scheme'])){ $this->domain = $parsed['scheme'] . "://" . $parsed['host']; }
196       
197        $sql = "UPDATE " . TABLE_POSTS . " SET post_author = %d, post_status = %s, post_type = %s, post_category = %d, post_tags = %s, post_title = %s, post_orig_url = %s, post_domain = %s, post_url = %s, post_content = %s, post_subscribe = %d, post_comments = %s, post_updateby = %d WHERE post_id = %d";
198       
199        $h->db->query($h->db->prepare($sql, $this->author, $this->status, urlencode($this->type), $this->category, urlencode(trim($this->tags)), urlencode(trim($this->title)), urlencode($this->origUrl), urlencode($this->domain), urlencode(trim($this->url)), urlencode(trim($this->content)), $this->subscribe, $this->comments, $h->currentUser->id, $this->id));
200       
201        $h->post->id = $this->id; // a small hack to get the id for use in plugins.
202       
203        // Update tags in the Tags table:
204        require_once(LIBS . 'Tags.php');
205        $tags = new TagFunctions();
206        $tags->deleteTags($h, $this->id); // delete existing tags
207        $tags->addTags($h, $this->id, $this->tags); // insert new or updated tags
208       
209        $h->pluginHook('post_update_post');
210       
211        return true;
212    }
213   
214   
215    /**
216     * Physically delete a post from the database
217     *
218     * There's a plugin hook in here to delete their parts, e.g. votes, coments, tags, etc.
219     */   
220    public function deletePost($h)
221    {
222        if (!$this->id) { return false; }
223       
224        $sql = "DELETE FROM " . TABLE_POSTS . " WHERE post_id = %d";
225        $h->db->query($h->db->prepare($sql, $this->id));
226       
227        $h->post->id = $this->id; // a small hack to get the id for use in plugins.
228       
229        // Delete tags from the Tags table:
230        require_once(LIBS . 'Tags.php');
231        $tags = new TagFunctions();
232        $tags->deleteTags($h, $this->id); // delete existing tags
233       
234        $h->pluginHook('post_delete_post');
235       
236        // Need to clear both these cache to be sure the post is removed from widgets:
237        $h->clearCache('html_cache', false);
238        $h->clearCache('db_cache', false);
239    }
240   
241   
242    /**
243     * Physically delete all posts by a specified user
244     *
245     * @param array $user_id
246     * @return bool
247     */
248    public function deletePosts($h, $user_id = 0)
249    {
250        if (!$user_id) { return false; }
251       
252        $sql = "SELECT post_id FROM " . TABLE_POSTS. " WHERE post_author = %d";
253        $results = $h->db->get_results($h->db->prepare($sql, $user_id));
254       
255        if ($results) {
256            foreach ($results as $r) {
257                $h->post->id = $r->post_id; // used by other plugins in "post_delete_post" function/hook
258                $this->deletePost($h);
259            }
260        }
261       
262        return true;
263    }
264   
265   
266    /**
267     * Update a post's status
268     *
269     * @param string $status
270     * @param int $post_id (optional)
271     * @return true
272     */   
273    public function changePostStatus($h, $status = "processing", $post_id = 0)
274    {
275        $this->status = $status;
276        if (!$post_id) { $post_id = $this->id; }
277           
278        $sql = "UPDATE " . TABLE_POSTS . " SET post_status = %s WHERE post_id = %d";
279        $h->db->query($h->db->prepare($sql, $this->status, $post_id));
280       
281        // hacks for plugins:
282        $h->post->id = $post_id;
283         
284        $h->pluginHook('post_change_status');
285               
286        return true;
287    }
288   
289   
290    /**
291     * Checks for existence of a url
292     *
293     * @return array|false - array of posts
294     */   
295    public function urlExists($h, $url = '')
296    {
297        $sql = "SELECT post_id, post_status FROM " . TABLE_POSTS . " WHERE post_orig_url = %s";
298        $posts = $h->db->get_results($h->db->prepare($sql, urlencode($url)));
299
300        if (!$posts) { return false; }
301       
302        // we know there's at least one post with the same url, so if it's processing, let's delete it:
303        foreach ($posts as $post) {
304            if ($post->post_status == 'processing') {
305                $h->post->id = $post->post_id;
306                $h->deletePost($h);
307            }
308        }
309
310        // One last check to see if a post is present:
311        $sql = "SELECT count(post_id) FROM " . TABLE_POSTS . " WHERE post_orig_url = %s";
312        $posts = $h->db->get_var($h->db->prepare($sql, urlencode($url)));
313       
314        if ($posts > 0) { return $posts; } else { return false; }
315    }
316   
317   
318    /**
319     * Checks for existence of a post title
320     *
321     * @param str $title
322     * @return int - id of post with matching title
323     */
324    public function titleExists($h, $title = '')
325    {
326        $title = trim($title);
327        $sql = "SELECT post_id, post_status FROM " . TABLE_POSTS . " WHERE post_title = %s";
328        $posts = $h->db->get_results($h->db->prepare($sql, urlencode($title)));
329       
330        if (!$posts) { return false; }
331       
332        // we know there's at least one post with the same title, so if it's processing, let's delete it:
333        foreach ($posts as $post) {
334            if ($post->post_status == 'processing') {
335                $h->post->id = $post->post_id;
336                $h->deletePost($h);
337            }
338        }
339       
340        // One last check to see if a post is present:
341        $sql = "SELECT post_id FROM " . TABLE_POSTS . " WHERE post_title = %s";
342        $post_id = $h->db->get_var($h->db->prepare($sql, urlencode($title)));
343       
344        if ($post_id) { return $post_id; } else { return false; }
345    }
346   
347   
348    /**
349     * Checks for existence of a post with given post_url
350     *
351     * @param str $post_url (slug)
352     * @return int - id of post with matching url
353     */
354    public function isPostUrl($h, $post_url = '')
355    {
356        $sql = "SELECT post_id FROM " . TABLE_POSTS . " WHERE post_url = %s";
357        $post_id = $h->db->get_var($h->db->prepare($sql, urlencode($post_url)));
358        if ($post_id) { return $post_id; } else { return false; }
359    }
360   
361   
362    /**
363     * Count how many approved posts a user has had
364     *
365     * @param int $userid (optional)
366     * @return int
367     */
368    public function postsApproved($h, $user_id = 0)
369    {
370        if (!$user_id) { $user_id = $h->currentUser->id; }
371       
372        $sql = "SELECT COUNT(*) FROM " . TABLE_POSTS . " WHERE (post_status = %s || post_status = %s) AND post_author = %d";
373        $count = $h->db->get_var($h->db->prepare($sql, 'top', 'new', $user_id));
374       
375        return $count;
376       
377    }
378   
379   
380    /**
381     * Delete posts with "processing" status that are older than 30 minutes
382     */
383    public function deleteProcessingPosts($h)
384    {
385        $exp = date('YmdHis', strtotime("-30 mins"));
386        $sql = "DELETE FROM " . TABLE_POSTS . " WHERE post_status = %s AND post_date < %s";
387        $h->db->query($h->db->prepare($sql, 'processing', $exp));
388    }
389   
390
391    /**
392     * Count posts in the last X hours/minutes for this user
393     *
394     * @param int $hours
395     * @param int $minutes
396     * @param int $user_id (optional)
397     * @return int
398     */
399    public function countPosts($h, $hours = 0, $minutes = 0, $user_id = 0)
400    {
401        if (!$user_id) { $user_id = $h->currentUser->id; }
402        if ($hours) {
403            $time_ago = "-" . $hours . " Hours";
404        } else {
405            $time_ago = "-" . $minutes . " minutes";
406        }
407       
408        $start = date('YmdHis', strtotime("now"));
409        $end = date('YmdHis', strtotime($time_ago));
410        $sql = "SELECT COUNT(post_id) FROM " . TABLE_POSTS . " WHERE post_archived = %s AND post_author = %d AND (post_date >= %s AND post_date <= %s)";
411        $count = $h->db->get_var($h->db->prepare($sql, 'N', $user_id, $end, $start));
412       
413        return $count;
414    }
415   
416   
417    /**
418     * Get Unique Post Statuses
419     *
420     * @return array|false
421     */
422    public function getUniqueStatuses($h)
423    {
424        /* This function pulls all the different statuses from current links,
425        or adds some defaults if not present.*/
426
427        $unique_statuses = array();
428       
429        // Some essentials:
430        array_push($unique_statuses, 'new');
431        array_push($unique_statuses, 'top');
432        array_push($unique_statuses, 'pending');
433        array_push($unique_statuses, 'buried');
434        array_push($unique_statuses, 'processing');
435       
436        // Add any other statuses already in use:
437        $sql = "SELECT DISTINCT post_status FROM " . TABLE_POSTS;
438        $statuses = $h->db->get_results($h->db->prepare($sql));
439        if ($statuses) {
440            foreach ($statuses as $status) {
441                if ($status->post_status && !in_array($status->post_status, $unique_statuses)) {
442                    array_push($unique_statuses, $status->post_status);
443                }
444            }
445        }
446       
447        if ($unique_statuses) { return $unique_statuses; } else { return false; }
448    }
449   
450   
451    /**
452     * Post stats
453     *
454     * @param string $stat_type
455     * @return int
456     */
457    public function stats($h, $stat_type = '')
458    {
459        switch ($stat_type) {
460            case 'total_posts':
461                $sql = "SELECT count(post_id) FROM " . TABLE_POSTS;
462                $posts = $h->db->get_var($sql);
463                break;
464            case 'approved_posts':
465                $sql = "SELECT count(post_id) FROM " . TABLE_POSTS . " WHERE post_status = %s OR post_status = %s";
466                $posts = $h->db->get_var($h->db->prepare($sql, 'top', 'new'));
467                break;
468            case 'pending_posts':
469                $sql = "SELECT count(post_id) FROM " . TABLE_POSTS . " WHERE post_status = %s";
470                $posts = $h->db->get_var($h->db->prepare($sql, 'pending'));
471                break;
472            case 'buried_posts':
473                $sql = "SELECT count(post_id) FROM " . TABLE_POSTS . " WHERE post_status = %s";
474                $posts = $h->db->get_var($h->db->prepare($sql, 'buried'));
475                break;
476            case 'archived_posts':
477                $sql = "SELECT count(post_id) FROM " . TABLE_POSTS . " WHERE post_archived = %s";
478                $posts = $h->db->get_var($h->db->prepare($sql, 'Y'));
479                break;
480            default:
481                $posts = 0;
482        }
483       
484        return $posts;
485    }
486}
487?>
Note: See TracBrowser for help on using the repository browser.