blog (development code)
[moodle.git] / blog / class.BlogFilter.php
1 <?php // $Id$
2 /*******************************************************************
3  * This class represents a set of active filters to be applied 
4  * in searching for or presenting blog entries.
5  * Retrieve  filtered entries by calling get_filtered_entries 
6  * rather than directly accessing the array as
7  * the function will fetch the entries for you if needed.
8  *
9  * @copyright 2003/2004/2005, Daryl Hawes ({@link http://www.cocoaobjects.com})
10  * @author Daryl Hawes
11  * @version  $Id$
12  * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
13  * @package blog
14  ******************************************************************/
16 include_once($CFG->dirroot.'/blog/lib.php');
18 /*******************************************************************
19  * This class represents a set of active filters to be applied 
20  * in searching for or presenting blog entries. 
21  * Retrieve filtered entries by calling get_filtered_entries 
22  * rather than directly accessing the array as
23  * the function will fetch the entries for you if needed.
24  ******************************************************************/
25 class BlogFilter {
26     // member variables
27     // you can use variable names directly to access properties.
28     //ie. $blogFilter->month
29     
30     var $startmonth; 
31     var $startday;
32     var $startyear;
33     var $endmonth; 
34     var $endday;
35     var $endyear;
36     var $tstart; //start time, calculated from the values of startmonth, startday and startyear
37     var $tend; //end time, calculated from the values of endmonth, endday and endyear
38     var $fetchlimit; //max # of entries to read from database
39     var $fetchstart; //entry # to start reading from database at
40     var $max_entries; //maximum number of matching entries available in database
41     var $sort; 
42     var $courseid;
43     var $userid; // moodle userid to specify a specific user's blog
44     var $postid; //id of a single blog entry
45     var $categoryid;
46     var $groupid;
47     var $blogtitle;
48     var $blogtagline;
49     var $blogtheme;
50     var $blogInfo;
51     var $memberlist; //do not access directly - use getter get_member_list()
52     var $filtered_entries = array();
53     var $baseurl;
54     var $filtertype;
55     var $filterselect;
56     var $tag;
57     var $keywords = NULL; //array of $keywordtype = $keywordstring
59     /**
60      * BlogFilter 
61      * class constructor that will build a new instance of a BlogFilter object
62      *
63      * @param  int $userid = the blog that the entries are to be found in. If 0 then all blogs are searched.
64      * @param  int $courseid = if needed the entries can be restricted to those associated with a given course.
65      * @param  int $postid = a specific blog entry that is being sought
66      */
67     function BlogFilter($userid='', $postid='', $courseid='', $groupid='', $fetchlimit='', $fetchstart='', $startmonth='', $startday='', $startyear='', $endmonth='', $endday='', $endyear='', $filtertype='', $filterselect='', $tagid='', $tag ='', $sort='lastmodified DESC') {
69         global $CFG;    //filter settings to be pass in for baseurl
71         if (!empty($userid) && $userid != 0 && $userid != '') {
72 //            print "creating blogInfo object for user with id '$userid'<br />"; //debug
73             $this->blogInfo =& new BlogInfo($userid);
74         }
75         if ( empty($this->blogInfo) || empty($this->blogInfo->userid)) {
76             unset($this->blogInfo);
77             $this->blogtitle = '';
78             $this->blogtagline = '';
79             $this->blogtheme = '';
80         } else {
82             $this->blogtitle = &$this->blogInfo->blogtitle;
83             $this->blogtagline = &$this->blogInfo->blogtagline;
84             $this->blogtheme = $this->blogInfo->get_blog_theme();
85         }
86         
87         if (!is_numeric($courseid) || $courseid == 0 || $courseid == 1) {
88             $this->courseid = '';
89         } else {
90             $this->courseid = $courseid;        
91         }
92         if (! is_numeric($userid) ) {
93             $this->userid = 0;
94         } else {
95             $this->userid = $userid;
96         }
97         if (!is_numeric($fetchstart) ) {
98             $this->fetchstart = 0;
99         } else {
100             $this->fetchstart = $fetchstart;
101         }
102         if (!is_numeric($fetchlimit) ) {
103             $this->fetchlimit = $CFG->blog_default_fetch_num_entries;
104         } else {
105             $this->fetchlimit = $fetchlimit;
106         }
107         
108         $this->postid = $postid;
109         $this->groupid = $groupid;
110         
111         $this->startmonth = $startmonth;
112         $this->startday = $startday;
113         $this->startyear = $startyear;
114         $this->endmonth = $endmonth;
115         $this->endday = $endday;
116         $this->endyear = $endyear;
118         $this->tstart = blog_get_month_time($startyear, $startmonth, $startday);
119         $this->tend = blog_get_month_time($endyear, $endmonth, $endday);
121         $this->sort = $sort;
122         $this->filtertype = $filtertype;
123         $this->filterselect = $filterselect;
124         if ($tagid) {
125             $this->tag = $tagid;
126         } else if ($tag) {
127             $tagrec = get_record('tags', 'text', $tag);
128             $this->tag = $tagrec -> id;
129         }
130         // borrowed from Jon's table class
131         if(empty($this->baseurl)) {
133             $getcopy  = $_GET;
134             unset($getcopy['blogpage']);
135             
136             $strippedurl = strip_querystring(qualified_me());
137             if(!empty($getcopy)) {
138                 $first = false;
139                 $querystring = '';    
140                 foreach($getcopy as $var => $val) {
141                     if(!$first) {
142                         $first = true;
143                         if ($var != 'filterselect' && $var != 'filtertype') {
144                             $querystring .= '?'.$var.'='.$val;
145                             $hasparam = true;
146                         } else {
147                             $querystring .= '?';
148                         }
149                     } else {
150                         if ($var != 'filterselect' && $var != 'filtertype') {
151                             $querystring .= '&amp;'.$var.'='.$val;
152                             $hasparam = true;
153                         }
154                     }
155                 }
156                 if (isset($hasparam)) {
157                     $querystring .= '&amp;';
158                 } else {
159                     $querystring = '?';
160                 }
161             } else {
162                 $querystring = '?';
163             }
164             
165             $this->baseurl = strip_querystring(qualified_me()) . $querystring. 'filtertype='.$filtertype.'&amp;filterselect='.$filterselect.'&amp;';
167         }
168     }
170     /**
171      * borrowed from Jon's table class.
172      */
173     function define_baseurl($url) {
174         if(!strpos($url, '?')) {
175             $this->baseurl = $url.'?';
176         }
177         else {
178             $this->baseurl = $url.'&amp;';
179         }
180     }
181     
182     /**
183      *
184      */
185     function set_filtered_entries(&$blogentries) {
186         $this->filtered_entries = $blogentries;
187     }
188     
189     /**
190      * @return array Blog entries based on current filters
191      */
192     function get_filtered_entries() {
193         
194         if ( empty($this->filtered_entries) ) {
195             //no entries defined. try to fetch them.
196             $this->fetch_entries();
197         }
198         
199         if (!empty($this->filtered_entries)) {
200             //we have entries - return them
201             return $this->filtered_entries;
202         }
203         //still no entries - they must all be filtered away or there simply are none. return null.
204         return NULL;
205     }
206     
207     /**
208      *
209      */    
210     function get_bloginfo() {
211         //returns blog entries based on current filters as stored by but not created by this class
212         if (!empty($this->blogInfo) ) {
213             return $this->blogInfo;
214         }
215         return NULL;
216     }
217         
218     /**
219      * Using the member variables build a where clause and sql statment
220      * and fetch the correct blog entries from the database. The entries
221      * are then stored in the filtered_entries member variable.
222      *
223      * @uses $CFG
224      * @uses $USER
225      * @limit, if limit is false, then return all records
226      */
227     function fetch_entries($limit=true) {
228         global $CFG, $USER;
229 /*
230         echo "<br />filter trying to do its job";
231         echo "<br />filtertype = $this->filtertype";
232         echo "<br />filterselect = $this->filterselect";
233         */
234         if (!isset($USER->id)) {
235             $USER->id = 0;    //hack, for guests
236         }
237         
238         if ($this->tag) {
239             $tagtablesql = $CFG->prefix.'blog_tag_instance bt, ';
240             $tagquerysql = ' AND bt.entryid = p.id AND bt.tagid = '.$this->tag.' ';
241         } else {
242             $tagtablesql = '';
243             $tagquerysql = '';
244         }
245         
246         /****************************************
247          * depending on the type, there are 4   *
248          * different possible sqls              *
249          ****************************************/
250         switch ($this->filtertype) {
252             case 'site':
253             
254                 if (!isguest() && isloggedin()) {
256                     $SQL = 'SELECT p.* FROM '.$CFG->prefix.'post p, '.$tagtablesql
257                             .$CFG->prefix.'user u
258                             WHERE p.userid = u.id '.$tagquerysql.'
259                             AND (p.publishstate = \'site\' OR p.publishstate = \'public\' OR p.userid = '.$USER->id.')
260                             AND u.deleted = 0';
262                 } else {
264                     $SQL = 'SELECT p.* FROM '.$CFG->prefix.'post p, '.$tagtablesql
265                             .$CFG->prefix.'user u
266                             WHERE p.userid = u.id '.$tagquerysql.'
267                             AND p.publishstate = \'public\'
268                             AND u.deleted = 0';
269                 }
270             
271             break;
272             
273             case 'course':
274                 if ($this->filterselect != SITEID) {
275                     $SQL = '(SELECT p.* FROM '.$CFG->prefix.'post p, '.$tagtablesql
276                             .$CFG->prefix.'user_students u
277                             WHERE p.userid = u.userid '.$tagquerysql.'
278                             AND u.course = '.$this->filterselect.'
279                             AND (p.publishstate = \'site\' OR p.publishstate = \'public\' OR p.userid = '.$USER->id.'))
281                             UNION
283                             (SELECT p.* FROM '.$CFG->prefix.'post p, '.$tagtablesql
284                             .$CFG->prefix.'user_teachers u
285                             WHERE p.userid = u.userid '.$tagquerysql.'
286                             AND u.course = '.$this->filterselect.'
287                             AND (p.publishstate = \'site\' OR p.publishstate = \'public\' OR p.userid = '.$USER->id.'))';    //this will break for postgres, i think
288                 } else {
290                     if (isloggedin()) {
292                         $SQL = 'SELECT p.* FROM '.$CFG->prefix.'post p, '.$tagtablesql
293                                 .$CFG->prefix.'user u
294                                 WHERE p.userid = u.id '.$tagquerysql.'
295                                 AND (p.publishstate = \'site\' OR p.publishstate = \'public\' OR p.userid = '.$USER->id.')
296                                 AND u.deleted = 0';
298                     } else {
300                         $SQL = 'SELECT p.* FROM '.$CFG->prefix.'post p, '.$tagtablesql
301                                 .$CFG->prefix.'user u
302                                 WHERE p.userid = u.id '.$tagquerysql.'
303                                 AND p.publishstate = \'public\'
304                                 AND u.deleted = 0';
305                     }
307                 }
308             
309             break;
310             
311             case 'group':
313                 $SQL = 'SELECT p.* FROM '.$CFG->prefix.'post p, '.$tagtablesql
314                         .$CFG->prefix.'groups_members m
315                         WHERE p.userid = m.userid '.$tagquerysql.'
316                         AND m.groupid = '.$this->filterselect.'
317                         AND (p.publishstate = \'site\' OR p.publishstate = \'public\' OR p.userid = '.$USER->id.')';
318             
319             break;
320             
321             case 'user':
323                 $SQL = 'SELECT p.* FROM '.$CFG->prefix.'post p, '.$tagtablesql
324                         .$CFG->prefix.'user u
325                         WHERE p.userid = u.id '.$tagquerysql.'
326                         AND u.id = '.$this->filterselect.'
327                         AND (p.publishstate = \'site\' OR p.publishstate = \'public\' OR p.userid = '.$USER->id.')';
328             
329             break;
332         }
333         
334         if ($this->fetchstart !== '' && $limit) {    //this can be changed to use mysql_paging_limit
335             $limit = sql_paging_limit($this->fetchstart, $this->fetchlimit);
336         } else {
337             $limit = '';
338         }
339         
340         $orderby = ' ORDER BY '. $this->sort .' ';
342         //echo 'Debug: BlogFilter fetch_entries() sql="'. $SQL . $orderby . $limit .'"<br />'. $this->categoryid; //debug
344         $records = get_records_sql($SQL . $orderby . $limit);
346 //        print_object($records); //debug
347        
348         if (empty($records)) {
349             return array();
350         } else {
351             $blogEntries = array();
352             foreach($records as $record) {
353                 $blogEntry = new BlogEntry($record);
354                 $blogEntries[] = $blogEntry;
355             }
356         }
358 //        echo 'Debug: blog entries retrieved in fetch_entries function  of BlogFilter class:<br />'; //debug
359 //        print_object($blogEntries); //debug
361         $this->filtered_entries = $blogEntries;
363         return $this->filtered_entries;
364     }
366     /**
367      * get_where_clause
368      *
369      * This function will take all of this BlogFilter's instance variables and 
370      * calculate the proper sql string needed to fetch the appropriate entries.
371      * fields are referred to as e.* in the post table
372      * and c.* if they are in the blog_categories_entries table
373      *
374      * @return string The where clause for searching using this filter's settings
375      */
376     function get_where_clause() {
377         $hascats = false;
378         $where = '';
379         if ( !empty($this->categoryid) ) {
380             $hascats = true;
381         }
383         if ($this->is_userid_valid()) {
384             $where .= 'e.userid='. $this->userid;
385         }
386         if ($this->is_courseid_valid()) {
387             if ($where != '') {
388                 $where .= ' AND ';
389             }
390             $where .= 'e.courseid='. $this->courseid;
391         }
393         if ($this->is_userid_valid() && $this->is_postid_valid()) {
394             // a blog and a specific entry in that blog were specified. our mission is clear
395             if ($where != '') {
396                 $where .= ' AND ';
397             }
398             $where .= 'e.id='. $this->postid .' ';
399         } else {
400             // we do not have a specific post id, so get all posts that match additional criteria if present
401             if ($hascats) {
402                 if ($where != '') {
403                     $where .= ' AND ';
404                 }
405                 // where the discovered post id matches the categories_entries table entryid and the catid matches
406                 $where .= ' e.id = c.entryid AND c.categoryid='. $this->categoryid;
407                 
408             }
409         }
410         
411         if ( !empty($this->tstart) && !empty($this->tend) ) {
412             if ($where != '') {
413                 $where .= ' AND ';
414             }
415             $where .= 'e.lastmodified >= '. $this->tstart .' AND e.lastmodified <= '. $this->tend;
416         }
418         //http://www.techonthenet.com/sql/like.htm
419         $keywords = $this->keywords;
420         if (!empty($keywords) && count($keywords) > 0) {
421             if (!empty($keywords['body'])) {
422                 if ($where != '') {
423                     $where .= ' AND ';
424                 }
425                 $where .= "(e.body LIKE '%". $keywords['body'] ."%' OR e.extendedbody LIKE '%". $keywords['body'] ."%') ";
426             }
427             if (!empty($keywords['body'])) {
428                 if ($where != '') {
429                     $where .= ' AND ';
430                 }
431                 $where .= "(e.title LIKE '%". $keywords['title'] ."%') ";
432             }
433         }
434         return $where;
435     }
436     
437     /**
438      * get the count of entries in db without applying full filtering
439      */
440     function get_entry_count($where='', $hascats=false) {
441         global $CFG;
442         $sql = 'post e';
443         if ($hascats) {
444             $sql .= ', '. $CFG->prefix .'blog_categories_entries c ';
445         }
446         if (empty($where)) {
447             $where = $this->get_where_clause();
448         }
449         return count_records_select($sql, $where);
450     }
452     /**
453      * get the count of viewable entries, easiest way is to count fetch_entries
454      * this is used for print_paging_bar
455      */
456     function get_viewable_entry_count($where='', $hascats=false) {
457         $blogEntries = $this->fetch_entries(false);
458         return count($blogEntries);
459     }
461     /**
462      * get count of entries as they have been fetched from the fully filtered query
463      */
464     function get_filtered_entry_count() {
465         global $CFG;
467         $entries = $this->get_filtered_entries();
468         return count($entries);
469     }
470         
471     /**
472      * Use this function to retrieve a link to a blog page (typically not the one 
473      * you are currently processing) which contains the correct blog filter information
474      * to maintain the user's filtered view when progressing from page to page.
475      *
476      * The unused param is defined as either
477      * <code>
478      * $unused = array('userid', 'courseid', 'groupid');
479      * </code>
480      * or
481      * <code>
482      * $unused = 'startyear';
483      * </code>
484      * @param string $baseurl The url to be added to the full href before the getvars
485      * @param array|string $unused Can be an array of ivar names or a single variable name
486      * @return string A link to the specified baseurl along with the correct getvars for this filter.
487      */
488     function get_complete_link($baseurl, $linktext, $unused='') {
489         $getargs = $this->get_getvars($unused);
490         $link = '<a href="'. $baseurl;
491         $link .= $getargs . '">';
492         $link .= $linktext . '</a>';
493         return $link;
494     }
495     
496     /**
497     * The unused param is defined as either
498     * <code>
499     * $unused = array('userid', 'courseid', 'groupid');
500     * </code>
501     * or
502     * <code>
503     * $unused = 'startyear';
504     * </code>
505     * @param array|string $unused Can be an array of ivar names or a single variable name
506     */
507     function get_getvars($unused) {
508         $getargs = '?';
509         if(!is_array($unused)) {
510             $unused = array($unused);
511         }
512         if (!is_array($unused)) {
513             //argument is not an array, hopefully it's a string. wrap it in an array for comparisons below.
514             $unused = array($unused);
515         }
516         if (!in_array('startmonth', $unused)) {
517             $getargs .= '&amp;m=' . $this->startmonth; 
518         }
519         if (!in_array('startday', $unused)) {
520             $getargs .= '&amp;d=' . $this->startday;
521         }
522         if (!in_array('startyear', $unused)) {
523             $getargs .= '&amp;y=' . $this->startyear;
524         }
525         if (!in_array('limit', $unused)) {
526             $getargs .= '&amp;limit=' . $this->fetchlimit;
527         }
528         if (!in_array('formstart', $unused)) {
529             $getargs .= '&amp;formstart=' . $this->fetchstart;
530         }
531         if (!in_array('courseid', $unused)) {
532             $getargs .= '&amp;courseid=' . $this->courseid;
533         }
534         if (!in_array('userid', $unused)) {
535             $getargs .= '&amp;userid=' . $this->userid;
536         }
537         if (!in_array('categoryid', $unused)) {
538             $getargs .= '&amp;categoryid=' . $this->categoryid;
539         }
540         if (!in_array('groupid', $unused)) {
541             $getargs .= '&amp;groupid=' . $this->groupid;
542         }
543         return $getargs;
544     }
545     
546     function is_userid_valid() {
547         if (is_numeric($this->userid) && $this->userid != 0 && $this->userid != '') {
548             return true;
549         } 
550         return false;
551     }
553     function is_groupid_valid() {
554         if (is_numeric($this->groupid) && $this->groupid != 0 && $this->groupid != '') {
555             return true;
556         } 
557         return false;
558     }
560     function is_courseid_valid() {
561         if (is_numeric($this->courseid) && $this->courseid != 0 && $this->courseid != '') {
562             return true;
563         } 
564         return false;
565     }
567     function is_postid_valid() {
568         if (is_numeric($this->postid) && $this->postid != 0 && $this->postid != '') {
569             return true;
570         } 
571         return false;
572     }
574     /**
575      * get_member_list
576      *
577      * @param string $sort
578      * @param int $limitnum
579      * @return object containing records with ->id and ->title of member blogs
580      */
581     function get_member_list($sort='', $limitnum='') {
582         global $CFG;
583         if (!empty($this->memberlist)) {
584             return $this->memberlist;
585         }
587         //temporarily change $this->fetchstart to unlimit the entries from db and fetch
588         $oldstart = $this->fetchstart;
589         $this->fetchstart = '';
590         $entries = $this->fetch_entries();
591         $this->fetchstart = $oldstart;
593         $records = array();
594         $bids = array();
595         foreach ($entries as $entry) {
596             if (!in_array($entry->entryuserid, $bids)) {
597                 $bids[$entry->entryuserid] = $entry->entryuserid;
598             }
599         }
601         foreach ($bids as $bid) {
602             $thisrecord->id = $bid;
603             $thisrecord->title = get_user_preferences('blogtitle', $CFG->blog_default_title, $bid);
604             $records[] = $thisrecord;
605         }
606         $this->memberlist = $records;
607         return $records;
608     }
610 }    //end class BlogFilter
611 ?>