4 * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
5 * Copyright (C) 2002-2012 The Nucleus Group
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 * (see nucleus/documentation/index.html#license for more info)
14 * A class representing a blog and containing functions to get that blog shown
17 * @license http://nucleuscms.org/license.txt GNU General Public License
18 * @copyright Copyright (C) 2002-2009 The Nucleus Group
19 * @version $Id: BLOG.php 1624 2012-01-09 11:36:20Z sakamocchi $
22 if ( !function_exists('requestVar') ) exit;
23 require_once dirname(__FILE__) . '/ITEMACTIONS.php';
30 // After creating an object of the blog class, contains true if the BLOG object is
31 // valid (the blog exists)
34 // associative array, containing all blogsettings (use the get/set functions instead)
37 // ID of currently selected category
38 private $selectedcatid;
42 * Creates a new BLOG object for the given blog
44 * @param integer $id blogid
47 public function __construct($id)
51 $this->blogid = (integer) $id;
52 $this->readSettings();
53 $this->setSelectedCategory($catid);
59 * Shows the given amount of items for this blog
61 * @param string $template String representing the template _NAME_ (!)
62 * @param integer $amountEntries amount of entries to show
63 * @param integer $startpos offset from where items should be shown (e.g. 5 = start at fifth item)
64 * @return integer amount of items shown
66 public function readLog($template, $amountEntries, $offset = 0, $startpos = 0)
68 return $this->readLogAmount($template,$amountEntries,'','',1,1,$offset, $startpos);
73 * Shows an archive for a given month
75 * @param integer $year year
76 * @param integer $month month
77 * @param string $template String representing the template name to be used
80 public function showArchive($templatename, $year, $month=0, $day=0)
82 // create extra where clause for select query
83 if ( $day == 0 && $month != 0 )
85 $timestamp_start = mktime(0,0,0,$month,1,$year);
86 // also works when $month==12
87 $timestamp_end = mktime(0,0,0,$month+1,1,$year);
89 elseif ( $month == 0 )
91 $timestamp_start = mktime(0,0,0,1,1,$year);
92 // also works when $month==12
93 $timestamp_end = mktime(0,0,0,12,31,$year);
97 $timestamp_start = mktime(0,0,0,$month,$day,$year);
98 $timestamp_end = mktime(0,0,0,$month,$day+1,$year);
100 $extra_query = " and i.itime>=%s and i.itime<%s";
101 $extra_query = sprintf($extra_query, DB::formatDateTime($timestamp_start), DB::formatDateTime($timestamp_end));
103 $this->readLogAmount($templatename,0,$extra_query,'',1,1);
108 * Blog::setSelectedCategory()
109 * Sets the selected category by id (only when category exists)
111 * @param integer $catid ID for category
114 public function setSelectedCategory($catid)
116 if ( $this->isValidCategory($catid) || (intval($catid) == 0) )
118 $this->selectedcatid = intval($catid);
124 * Blog::setSelectedCategoryByName()
125 * Sets the selected category by name
127 * @param string $catname name of category
130 public function setSelectedCategoryByName($catname)
132 $this->setSelectedCategory($this->getCategoryIdFromName($catname));
137 * Blog::getSelectedCategory()
138 * Returns the selected category
143 public function getSelectedCategory()
145 return $this->selectedcatid;
149 * Shows the given amount of items for this blog
151 * @param string $template string representing the template _NAME_ (!)
152 * @param integer $amountEntries amount of entries to show (0 = no limit)
153 * @param string $extraQuery extra conditions to be added to the query
154 * @param string $highlight contains a query that should be highlighted
155 * @param integer $comments 1=show comments 0=don't show comments
156 * @param integer $dateheads 1=show dateheads 0=don't show dateheads
157 * @param integer $offset offset
158 * @return integer amount of items shown
160 private function readLogAmount($template, $amountEntries, $extraQuery, $highlight, $comments, $dateheads, $offset = 0, $startpos = 0)
162 $query = $this->getSqlBlog($extraQuery);
164 if ( $amountEntries > 0 )
166 // $offset zou moeten worden:
167 // (($startpos / $amountentries) + 1) * $offset ... later testen ...
168 $query .= ' LIMIT ' . intval($startpos + $offset).',' . intval($amountEntries);
170 return $this->showUsingQuery($template, $query, $highlight, $comments, $dateheads);
174 * Blog::showUsingQuery()
175 * Do the job for readLogAmmount
177 * @param string $templateName template name
178 * @param string $query string for query
179 * @param string $highlight string to be highlighted
180 * @param integer $comments the number of comments
181 * @param boolean $dateheads date header is needed or not
182 * @return integer the number of rows as a result of mysql query
184 private function showUsingQuery($templateName, $query, $highlight = '', $comments = 0, $dateheads = 1)
186 global $CONF, $manager, $currentTemplateName;
188 $lastVisit = cookieVar($CONF['CookiePrefix'] .'lastVisit');
189 if ( $lastVisit != 0 )
191 $lastVisit = $this->getCorrectTime($lastVisit);
194 // set templatename as global variable (so plugins can access it)
195 $currentTemplateName = $templateName;
196 $template =& $manager->getTemplate($templateName);
198 // create parser object & action handler
199 $handler = new ItemActions($this);
200 $handler->setTemplate($template);
201 $handler->setHighlight($highlight);
202 $handler->setLastVisit($lastVisit);
203 $handler->setShowComments($comments);
205 $parser = new Parser($handler);
208 $items = DB::getResult($query);
210 // loop over all items
212 foreach ( $items as $item )
214 // string timestamp -> unix timestamp
215 $item['timestamp'] = strtotime($item['itime']);
217 // action handler needs to know the item we're handling
218 $handler->setCurrentItem($item);
220 // add date header if needed
223 $new_date = date('dFY', $item['timestamp']);
224 if ( $new_date != $old_date )
226 // unless this is the first time, write date footer
227 $timestamp = $item['timestamp'];
228 if ( $old_date != 0 )
230 $oldTS = strtotime($old_date);
231 $data = array('blog' => &$this, 'timestamp' => $oldTS);
232 $manager->notify('PreDateFoot', $data);
234 if ( !in_array('DATE_FOOTER', $template) || empty($template['DATE_FOOTER']) )
240 $tmp_footer = i18n::formatted_datetime($template['DATE_FOOTER'], $oldTS);
242 $parser->parse($tmp_footer);
243 $manager->notify('PostDateFoot', $data);
246 $data = array('blog' => &$this, 'timestamp' => $timestamp);
247 $manager->notify('PreDateHead', $data);
249 // note, to use templatvars in the dateheader, the %-characters need to be doubled in
250 // order to be preserved by strftime
251 if ( !in_array('DATE_HEADER', $template) || empty($template['DATE_HEADER']) )
257 $tmp_header = i18n::formatted_datetime($template['DATE_HEADER'], $timestamp);
259 $parser->parse($tmp_header);
260 $manager->notify('PostDateHead', $data);
262 $old_date = $new_date;
266 $parser->parse($template['ITEM_HEADER']);
267 $data = array('blog' => &$this, 'item' => &$item);
268 $manager->notify('PreItem', $data);
269 $parser->parse($template['ITEM']);
270 $manager->notify('PostItem', $data);
271 $parser->parse($template['ITEM_FOOTER']);
274 $numrows = $items->rowCount();
276 // add another date footer if there was at least one item
277 if ( ($numrows > 0) && $dateheads )
279 $data = array('blog' => &$this, 'timestamp' => strtotime($old_date));
280 $manager->notify('PreDateFoot', $data);
281 $parser->parse($template['DATE_FOOTER']);
282 $manager->notify('PostDateFoot', $data);
285 $items->closeCursor();
290 * Blog::showOneitem()
291 * Simplified function for showing only one item
293 * @param integer $itemid ID for item
294 * @param array $template template for item
295 * @param string $highlight string for highlight
298 public function showOneitem($itemid, $template, $highlight)
300 $extraQuery = ' and inumber=' . intval($itemid);
302 return $this->readLogAmount($template, 1, $extraQuery, $highlight, 0, 0);
307 * Adds an item to this blog
309 * @param integer $catid ID for category
310 * @param string $title ID for
311 * @param string $body text for body
312 * @param string $more text for more
313 * @param integer $blogid ID for blog
314 * @param integer $authorid ID for author
315 * @param timestamp $timestamp UNIX timestamp for post
316 * @param boolean $closed opened or closed
317 * @param boolean $draft draft or not
318 * @param boolean $posted posted or not
319 * @return integer ID for added item
321 function additem($catid, $title, $body, $more, $blogid, $authorid, $timestamp, $closed, $draft, $posted='1')
325 $blogid = (integer) $blogid;
326 $authorid = (integer) $authorid;
330 $catid = intval($catid);
332 // convert newlines to <br />
333 if ( $this->convertBreaks() )
335 $body = addBreaks($body);
336 $more = addBreaks($more);
339 if ( $closed != '1' )
348 if ( !$this->isValidCategory($catid) )
350 $catid = $this->getDefaultCategory();
354 if ( $timestamp > $this->getCorrectTime() )
359 $timestamp = date('Y-m-d H:i:s',$timestamp);
361 $data = array('title' => &$title, 'body' => &$body, 'more' => &$more, 'blog' => $this, 'authorid' => &$authorid, 'timestamp' => &$timestamp, 'closed' => &$closed, 'draft' => &$draft, 'catid' => &$catid);
362 $manager->notify('PreAddItem', $data);
364 $ititle = DB::quoteValue($title);
365 $ibody = DB::quoteValue($body);
366 $imore = DB::quoteValue($more);
367 $timestamp = DB::formatDateTime(strtotime($timestamp));
369 $query = "INSERT INTO %s (ITITLE, IBODY, IMORE, IBLOG, IAUTHOR, ITIME, ICLOSED, IDRAFT, ICAT, IPOSTED) VALUES (%s, %s, %s, %d, %d, %s, %s, %s, %s, %s)";
370 $query = sprintf($query, sql_table('item'), $ititle, $ibody, $imore, $blogid, $authorid, $timestamp, $closed, $draft, $catid, $posted);
372 $itemid = DB::getInsertId();
374 $data = array('itemid' => $itemid);
375 $manager->notify('PostAddItem', $data);
379 $this->updateUpdateFile();
381 // send notification mail
382 if ( !$draft && !$isFuture && $this->getNotifyAddress() && $this->notifyOnNewItem() )
384 $this->sendNewItemNotification($itemid, $title, $body);
390 * Blog::sendNewItemNotification()
391 * Send a new item notification to the notification list
393 * @param string $itemid ID of the item
394 * @param string $title title of the item
395 * @param string $body body of the item
398 public function sendNewItemNotification($itemid, $title, $body)
400 global $CONF, $member;
402 $ascii = Entity::anchor_footnoting($body);
404 $message = _NOTIFY_NI_MSG . " \n";
405 $temp = parse_url($CONF['Self']);
406 if ( $temp['scheme'] )
408 $message .= Link::create_item_link($itemid) . "\n\n";
412 $tempurl = $this->getURL();
413 if ( i18n::substr($tempurl, -1) == '/' || i18n::substr($tempurl, -4) == '.php' )
415 $message .= $tempurl . '?itemid=' . $itemid . "\n\n";
419 $message .= $tempurl . '/?itemid=' . $itemid . "\n\n";
422 $message .= _NOTIFY_TITLE . ' ' . strip_tags($title) . "\n";
423 $message .= _NOTIFY_CONTENTS . "\n " . $ascii . "\n";
424 $message .= NOTIFICATION::get_mail_footer();
426 $subject = $this->getName() . ': ' . _NOTIFY_NI_TITLE;
428 $from = $member->getNotifyFromMailAddress();
430 NOTIFICATION::mail($this->getNotifyAddress(), $subject, $message, $from, i18n::get_current_charset());
435 * Blog::createNewCategory()
436 * Creates a new category for this blog
438 * @param string $catName name of the new category. When empty, a name is generated automatically (starting with newcat)
439 * @param string $catDescription description of the new category. Defaults to 'New Category'
440 * @return integer ID for new category on success. 0 on failure
442 public function createNewCategory($catName = '', $catDescription = _CREATED_NEW_CATEGORY_DESC)
444 global $member, $manager;
446 if ( !$member->blogAdminRights($this->blogid) )
452 if ( $catName == '' )
454 $catName = _CREATED_NEW_CATEGORY_NAME;
457 $res = DB::getResult('SELECT * FROM '.sql_table('category')." WHERE cname='".$catName.$i."' and cblog=".$this->blogid);
458 while ( $res->rowCount() > 0 )
461 $res = DB::getResult('SELECT * FROM '.sql_table('category')." WHERE cname='".$catName.$i."' and cblog=".$this->blogid);
464 $catName = $catName . $i;
470 'description' => $catDescription
472 $manager->notify('PreAddCategory', $data);
474 $query = "INSERT INTO %s (cblog, cname, cdesc) VALUES (%d, %s, %s)";
475 $query = sprintf($query, sql_table('category'), (integer) $this->blogid, DB::quoteValue($catName), DB::quoteValue($catDescription));
477 $catid = DB::getInsertId();
482 'description' => $catDescription,
485 $manager->notify('PostAddCategory', $data);
492 * Searches all months of this blog for the given query
494 * @param string $query search query
495 * @param array $template template to be used (__NAME__ of the template)
496 * @param integer $amountMonths max amount of months to be search (0 = all)
497 * @param integer $maxresults max number of results to show
498 * @param integer $startpos offset
499 * @return amount of hits found
501 public function search($query, $template, $amountMonths, $maxresults, $startpos) {
502 global $CONF, $manager;
505 $sqlquery = $this->getSqlSearch($query, $amountMonths, $highlight);
507 if ( $sqlquery == '' )
509 // no query -> show everything
511 $amountfound = $this->readLogAmount($template, $maxresults, $extraQuery, $query, 1, 1);
515 // add LIMIT to query (to split search results into pages)
516 if ( intval($maxresults > 0) )
518 $sqlquery .= ' LIMIT ' . intval($startpos) . ',' . intval($maxresults);
522 $amountfound = $this->showUsingQuery($template, $sqlquery, $highlight, 1, 1);
524 // when no results were found, show a message
525 if ( $amountfound == 0 )
527 $template =& $manager->getTemplate($template);
529 'query' => Entity::hsc($query),
530 'blogid' => $this->blogid
532 echo Template::fill($template['SEARCH_NOTHINGFOUND'], $vars);
539 * Blog::getSqlSearch()
540 * Returns an SQL query to use for a search query
541 * No LIMIT clause is added. (caller should add this if multiple pages are requested)
543 * @param string $query search query
544 * @param integer $amountMonths amount of months to search back. Default = 0 = unlimited
545 * @param string $mode either empty, or 'count'. In this case, the query will be a SELECT COUNT(*) query
546 * @return string $highlight words to highlight (out parameter)
547 * @return string either a full SQL query, or an empty string (if querystring empty)
549 public function getSqlSearch($query, $amountMonths = 0, &$highlight, $mode = '')
551 $searchclass = new Search($query);
553 $highlight = $searchclass->inclusive;
555 // if querystring is empty, return empty string
556 if ( $searchclass->inclusive == '' )
561 $where = $searchclass->boolean_sql_where('ititle,ibody,imore');
562 $select = $searchclass->boolean_sql_select('ititle,ibody,imore');
564 // get list of blogs to search
565 $blogs = $searchclass->blogs; // array containing blogs that always need to be included
566 $blogs[] = $this->blogid; // also search current blog (duh)
567 $blogs = array_unique($blogs); // remove duplicates
569 if ( count($blogs) > 0 )
571 $selectblogs = ' and i.iblog in (' . implode(',', $blogs) . ')';
576 $query = 'SELECT i.inumber as itemid, i.ititle as title, i.ibody as body, i.itime, i.imore as more, i.icat as catid, i.iclosed as closed,
577 m.mname as author, m.mrealname as authorname, m.mnumber as authorid, m.memail as authormail, m.murl as authorurl,
578 c.cname as category';
582 $query .= ', '.$select. ' as score ';
587 $query = 'SELECT COUNT(*) as result ';
590 $query .= ' FROM '.sql_table('item').' as i, '.sql_table('member').' as m, '.sql_table('category').' as c'
591 . ' WHERE i.iauthor=m.mnumber'
592 . ' and i.icat=c.catid'
596 // don't show future items
597 . ' and i.itime<=' . DB::formatDateTime($this->getCorrectTime())
600 // take into account amount of months to search
601 if ( $amountMonths > 0 )
603 $localtime = getdate($this->getCorrectTime());
604 $timestamp_start = mktime(0,0,0,$localtime['mon'] - $amountMonths,1,$localtime['year']);
605 $query .= ' and i.itime>' . DB::formatDateTime($timestamp_start);
612 $query .= ' ORDER BY score DESC';
616 $query .= ' ORDER BY i.itime DESC ';
625 * Returns the SQL query that's normally used to display the blog items on the index type skins
626 * No LIMIT clause is added. (caller should add this if multiple pages are requested)
628 * @param string $extraQuery extra query string
629 * @param string $mode either empty, or 'count'. In this case, the query will be a SELECT COUNT(*) query
630 * @return string either a full SQL query, or an empty string
632 public function getSqlBlog($extraQuery, $mode = '')
636 $query = 'SELECT i.inumber as itemid, i.ititle as title, i.ibody as body, m.mname as author,
637 m.mrealname as authorname, i.itime, i.imore as more, m.mnumber as authorid, m.memail as authormail,
638 m.murl as authorurl, c.cname as category, i.icat as catid, i.iclosed as closed';
642 $query = 'SELECT COUNT(*) as result ';
645 $query .= ' FROM '.sql_table('item').' as i, '.sql_table('member').' as m, '.sql_table('category').' as c'
646 . ' WHERE i.iblog='.$this->blogid
647 . ' and i.iauthor=m.mnumber'
648 . ' and i.icat=c.catid'
649 . ' and i.idraft=0' // exclude drafts
650 . ' and i.itime<=' . DB::formatDateTime($this->getCorrectTime()); // don't show future items
652 if ( $this->selectedcatid )
654 $query .= ' and i.icat=' . $this->selectedcatid . ' ';
657 $query .= $extraQuery;
661 $query .= ' ORDER BY i.itime DESC';
667 * Blog::showArchiveList()
668 * Shows the archivelist using the given template
670 * @param string $template template name
671 * @param string $mode year/month/day
672 * @param integer $limit limit of record count
675 public function showArchiveList($template, $mode = 'month', $limit = 0)
677 global $CONF, $catid, $manager;
679 if ( !isset ($linkparams) )
681 $linkparams = array();
686 $linkparams = array('catid' => $catid);
689 $template =& $manager->getTemplate($template);
690 $listitem['blogid'] = $this->blogid;
692 if ( !array_key_exists('ARCHIVELIST_HEADER', $template) || !$template['ARCHIVELIST_HEADER'] )
698 $tplt = $template['ARCHIVELIST_HEADER'];
701 echo Template::fill($tplt, $listitem);
703 $query = 'SELECT itime, SUBSTRING(itime,1,4) AS Year, SUBSTRING(itime,6,2) AS Month, SUBSTRING(itime,9,2) AS Day'
704 . ' FROM '.sql_table('item')
705 . ' WHERE iblog=' . $this->blogid
706 . ' AND itime <=' . DB::formatDateTime($this->getCorrectTime()) // don't show future items!
707 . ' AND idraft=0'; // don't show draft items
711 $query .= ' and icat=' . intval($catid);
714 $query .= ' GROUP BY Year';
715 if ( $mode == 'month' || $mode == 'day' )
719 if ( $mode == 'day' )
724 $query .= ' ORDER BY itime DESC';
728 $query .= ' LIMIT ' . intval($limit);
731 $res = DB::getResult($query);
732 foreach ( $res as $current )
734 /* string time -> unix timestamp */
735 $current['itime'] = strtotime($current['itime']);
737 if ( $mode == 'day' )
739 $archivedate = date('Y-m-d',$current['itime']);
740 $archive['day'] = date('d',$current['itime']);
741 $listitem['day'] = date('d',$current['itime']);
742 $listitem['month'] = date('m',$current['itime']);
743 $archive['month'] = $listitem['month'];
745 elseif ( $mode == 'year' )
747 $archivedate = date('Y',$current['itime']);
748 $listitem['day'] = '';
749 $listitem['month'] = '';
750 $archive['day'] = '';
751 $archive['month'] = '';
755 $archivedate = date('Y-m',$current['itime']);
756 $listitem['month'] = date('m',$current['itime']);
757 $archive['month'] = $listitem['month'];
758 $listitem['day'] = '';
759 $archive['day'] = '';
762 $listitem['year'] = date('Y',$current['itime']);
763 $archive['year'] = $listitem['year'];
764 $listitem['archivelink'] = Link::create_archive_link($this->blogid,$archivedate,$linkparams);
766 $data = array('listitem' => &$listitem);
767 $manager->notify('PreArchiveListItem', $data);
769 $temp = Template::fill($template['ARCHIVELIST_LISTITEM'],$listitem);
770 echo i18n::formatted_datetime($temp, $current['itime']);
776 if ( !array_key_exists('ARCHIVELIST_FOOTER', $template) || !$template['ARCHIVELIST_FOOTER'] )
782 $tplt = $template['ARCHIVELIST_FOOTER'];
785 echo Template::fill($tplt, $listitem);
790 * Blog::showCategoryList()
791 * Shows the list of categories using a given template
793 * @param string $template Template Name
796 public function showCategoryList($template)
798 global $CONF, $archive, $archivelist, $manager;
801 * determine arguments next to catids
802 * I guess this can be done in a better way, but it works
804 $linkparams = array();
807 $blogurl = Link::create_archive_link($this->blogid, $archive, '');
808 $linkparams['blogid'] = $this->blogid;
809 $linkparams['archive'] = $archive;
811 else if ( $archivelist )
813 $blogurl = Link::create_archivelist_link($this->blogid, '');
814 $linkparams['archivelist'] = $archivelist;
818 $blogurl = Link::create_blogid_link($this->blogid, '');
819 $linkparams['blogid'] = $this->blogid;
822 $template =& $manager->getTemplate($template);
824 //: Change: Set nocatselected variable
825 if ( $this->selectedcatid )
827 $nocatselected = 'no';
831 $nocatselected = 'yes';
835 'blogid' => $this->blogid,
836 'blogurl' => $blogurl,
837 'self' => $CONF['Self'],
838 'catiscurrent' => $nocatselected, // Change: Set catiscurrent template variable for header
839 'currentcat' => $nocatselected
842 /* output header of category list item */
843 if ( !array_key_exists('CATLIST_HEADER', $template) || empty($template['CATLIST_HEADER']) )
845 echo Template::fill(NULL, $args);
849 echo Template::fill($template['CATLIST_HEADER'], $args);
852 $query = "SELECT catid, cdesc as catdesc, cname as catname FROM %s WHERE cblog=%d ORDER BY cname ASC;";
853 $query = sprintf($query, sql_table('category'), (integer) $this->blogid);
854 $res = DB::getResult($query);
856 foreach ( $res as $row )
859 'catid' => $row['catid'],
860 'name' => $row['catname'],
861 'extra' => $linkparams
864 $row['blogid'] = $this->blogid;
865 $row['blogurl'] = $blogurl;
866 $row['catlink'] = Link::create_link('category', $args);
867 $row['self'] = $CONF['Self'];
869 // this gives catiscurrent = no when no category is selected.
870 $row['catiscurrent'] = 'no';
871 $row['currentcat'] = 'no';
873 if ( $this->selectedcatid )
875 if ( $this->selectedcatid == $row['catid'] )
877 $row['catiscurrent'] = 'yes';
878 $row['currentcat'] = 'yes';
884 if ( (integer) $itemid && $manager->existsItem((integer) $itemid, 0, 0) )
886 $iobj =& $manager->getItem($itemid, 0, 0);
887 $cid = $iobj['catid'];
889 if ( $cid == $row['catid'] )
891 $row['catiscurrent'] = 'yes';
892 $row['currentcat'] = 'yes';
897 $data = array('listitem' => &$row);
898 $manager->notify('PreCategoryListItem', $data);
900 if ( !array_key_exists('CATLIST_LISTITEM', $template) || empty($template['CATLIST_LISTITEM']))
902 echo Template::fill(NULL, $row);
906 echo Template::fill($template['CATLIST_LISTITEM'], $row);
913 'blogid' => $this->blogid,
914 'blogurl' => $blogurl,
915 'self' => $CONF['Self'],
916 'catiscurrent' => $nocatselected, //: Change: Set catiscurrent template variable for footer
917 'currentcat' => $nocatselected
920 if ( !array_key_exists('CATLIST_FOOTER', $template) || empty($template['CATLIST_FOOTER']))
922 echo Template::fill(NULL, $args);
926 echo Template::fill($template['CATLIST_FOOTER'], $args);
933 * Blog::showBlogList()
934 * Shows a list of all blogs in the system using a given template
935 * ordered by number, name, shortname or description
936 * in ascending or descending order
938 * @param string $template tempalte name
939 * @param string $bnametype bname/bshortname
940 * @param string $orderby string for 'ORDER BY' SQL
941 * @param string $direction ASC/DESC
944 static public function showBlogList($template, $bnametype, $orderby, $direction)
946 global $CONF, $manager;
957 $orderby='bshortname';
967 $direction=strtolower($direction);
968 switch ( $direction )
981 $template =& $manager->getTemplate($template);
983 if ( array_key_exists('BLOGLIST_HEADER', $template) && !empty($template['BLOGLIST_HEADER']) )
986 'sitename' => $CONF['SiteName'],
987 'siteurl' => $CONF['IndexURL']
990 echo Template::fill($template['BLOGLIST_HEADER'], $vars);
993 if ( array_key_exists('BLOGLIST_LISTITEM', $template) && !empty($template['BLOGLIST_LISTITEM']) )
995 $query = 'SELECT bnumber, bname, bshortname, bdesc, burl FROM '.sql_table('blog').' ORDER BY '.$orderby.' '.$direction;
996 $res = DB::getResult($query);
998 foreach ( $res as $row )
1001 $list['bloglink'] = Link::create_blogid_link($row['bnumber']);
1002 $list['blogdesc'] = $row['bdesc'];
1003 $list['blogurl'] = $row['burl'];
1005 if ( $bnametype == 'shortname' )
1007 $list['blogname'] = $row['bshortname'];
1011 /* all other cases */
1012 $list['blogname'] = $row['bname'];
1015 $data = array('listitem' => &$list);
1016 $manager->notify('PreBlogListItem', $data);
1018 echo Template::fill($template['BLOGLIST_LISTITEM'], $list);
1021 $res->closeCursor();
1025 if ( array_key_exists('BLOGLIST_FOOTER', $template) && !empty($template['BLOGLIST_FOOTER']) )
1028 'sitename' => $CONF['SiteName'],
1029 'siteurl' => $CONF['IndexURL']
1031 echo Template::fill($template['BLOGLIST_FOOTER']);
1037 * Blog::readSettings()
1038 * Read the blog settings
1043 public function readSettings()
1045 $query = 'SELECT * FROM %s WHERE bnumber=%d;';
1046 $query = sprintf($query, sql_table('blog'), (integer) $this->blogid);
1047 $res = DB::getResult($query);
1049 $this->isValid = ($res->rowCount() > 0);
1050 if ( $this->isValid )
1052 $this->settings = $res->fetch(PDO::FETCH_ASSOC);
1058 * Blog::writeSettings()
1059 * Write the blog settings
1061 public function writeSettings()
1063 // (can't use floatval since not available prior to PHP 4.2)
1064 $offset = $this->getTimeOffset();
1065 if ( !is_float($offset) )
1067 $offset = (integer) $offset;
1070 $query = 'UPDATE '.sql_table('blog')
1071 . ' SET bname=' . DB::quoteValue($this->getName()) . ','
1072 . ' bshortname='. DB::quoteValue($this->getShortName()) . ','
1073 . ' bcomments='. intval($this->commentsEnabled()) . ','
1074 . ' bmaxcomments=' . intval($this->getMaxComments()) . ','
1075 . ' btimeoffset=' . $offset . ','
1076 . ' bpublic=' . intval($this->isPublic()) . ','
1077 . ' breqemail=' . intval($this->emailRequired()) . ','
1078 . ' bconvertbreaks=' . intval($this->convertBreaks()) . ','
1079 . ' ballowpast=' . intval($this->allowPastPosting()) . ','
1080 . ' bnotify=' . DB::quoteValue($this->getNotifyAddress()) . ','
1081 . ' bnotifytype=' . intval($this->getNotifyType()) . ','
1082 . ' burl=' . DB::quoteValue($this->getURL()) . ','
1083 . ' bupdate=' . DB::quoteValue($this->getUpdateFile()) . ','
1084 . ' bdesc=' . DB::quoteValue($this->getDescription()) . ','
1085 . ' bdefcat=' . intval($this->getDefaultCategory()) . ','
1086 . ' bdefskin=' . intval($this->getDefaultSkin()) . ','
1087 . ' bincludesearch=' . intval($this->getSearchable())
1088 . ' WHERE bnumber=' . intval($this->blogid);
1089 DB::execute($query);
1094 * Blog::updateUpdatefile()
1095 * Update the update file if requested
1100 public function updateUpdatefile()
1102 if ( $this->getUpdateFile() )
1104 $f_update = fopen($this->getUpdateFile(), 'w');
1105 fputs($f_update,$this->getCorrectTime());
1112 * Blog::isValidCategory()
1113 * Check if a category with a given catid is valid
1115 * @param integer $catid ID for category
1116 * @return boolean exists or not
1118 public function isValidCategory($catid)
1120 $query = 'SELECT * FROM %s WHERE cblog=%d and catid=%d;';
1121 $query = sprintf($query, sql_table('category'), (integer) $this->blogid, (integer) $catid);
1122 $res = DB::getResult($query);
1123 return ($res->rowCount() != 0);
1127 * Blog::getCategoryName()
1128 * Get the category name for a given catid
1130 * @param integer $catid ID for category
1131 * @return string name of category
1133 public function getCategoryName($catid)
1135 $query = 'SELECT cname FROM %s WHERE cblog=%d and catid=%d;';
1136 $query = sprintf($query, sql_table('category'), (integer) $this->blogid, (integer) $catid);
1137 $res = DB::getValue($query);
1142 * Blog::getCategoryDesc()
1143 * Get the category description for a given catid
1148 public function getCategoryDesc($catid)
1150 $query = 'SELECT cdesc FROM %s WHERE cblog=%d and catid=%d;';
1151 $query = sprintf($query, sql_table('category'), (integer) $this->blogid, (integer) $catid);
1152 $res = DB::getValue($query);
1157 * Blog::getCategoryIdFromName
1158 * Get the category id for a given category name
1160 * @param string $name category name
1161 * @return ID for category
1163 public function getCategoryIdFromName($name)
1165 $query = 'SELECT catid FROM %s WHERE cblog=%d and cname=%s;';
1166 $query = sprintf($query, sql_table('category'), (integer) $this->blogid, DB::quoteValue($name));
1168 $res = DB::getValue();
1171 return $this->getDefaultCategory();
1177 * Blog::insertJavaScriptInfo()
1178 * Insert a javascript that includes information about the settings
1179 * of an author: ConvertBreaks, MediaUrl and AuthorId
1181 * @param $authorid id of the author
1183 public function insertJavaScriptInfo($authorid = '')
1185 global $member, $CONF;
1187 if ( $authorid == '' )
1189 $authorid = $member->getID();
1192 echo "<script type=\"text/javascript\">\n";
1194 if ( !$this->convertBreaks() )
1196 echo "setConvertBreaks(false);\n";
1200 echo "setConvertBreaks(true);\n";
1202 echo "setMediaUrl('{$CONF['MediaURL']}');\n";
1203 echo "setAuthorId('{$authorid}');\n";
1209 * Blog::setAllowPastPosting()
1210 * Set the the setting for allowing to publish postings in the past
1212 * @param boolean $val new value for ballowpast
1215 public function setAllowPastPosting($val)
1217 $this->setSetting('ballowpast', $val);
1222 * Blog::allowPastPosting()
1223 * Get the the setting if it is allowed to publish postings in the past
1224 * [should be named as getAllowPastPosting()]
1229 public function allowPastPosting()
1231 return $this->getSetting('ballowpast');
1235 * Blog::getCorrectTime()
1240 public function getCorrectTime($t=0)
1246 return ($t + 3600 * $this->getTimeOffset());
1253 * @return string name of this weblog
1255 public function getName()
1257 return $this->getSetting('bname');
1261 * Blog::getShortName()
1264 * @return string short name of this weblog
1266 public function getShortName()
1268 return $this->getSetting('bshortname');
1272 * Blog::getMaxComments()
1275 * @return integer maximum number of comments
1277 public function getMaxComments()
1279 return $this->getSetting('bmaxcomments');
1283 * Blog::getNotifyAddress()
1286 * @return string mail address for notifying
1288 public function getNotifyAddress()
1290 return $this->getSetting('bnotify');
1294 * Blog::getNotifyType()
1297 * @return integer notifycation type
1299 public function getNotifyType()
1301 return $this->getSetting('bnotifytype');
1305 * Blog::notifyOnComment()
1310 public function notifyOnComment()
1312 $n = $this->getNotifyType();
1313 return (($n != 0) && (($n % 3) == 0));
1317 * Blog::notifyOnVote()
1322 public function notifyOnVote()
1324 $n = $this->getNotifyType();
1325 return (($n != 0) && (($n % 5) == 0));
1329 * Blog::notifyOnNewItem()
1334 public function notifyOnNewItem()
1336 $n = $this->getNotifyType();
1337 return (($n != 0) && (($n % 7) == 0));
1341 * Blog::setNotifyType()
1343 * @param integer $val
1346 public function setNotifyType($val)
1348 $this->setSetting('bnotifytype',$val);
1353 * Blog::getTimeOffset()
1357 public function getTimeOffset()
1359 return $this->getSetting('btimeoffset');
1363 * Blog::commentsEnabled()
1365 * @return integer enabled or not
1367 public function commentsEnabled()
1369 return $this->getSetting('bcomments');
1375 * @return string URI for this weblog
1377 public function getURL()
1379 return $this->getSetting('burl');
1383 * Blog::getDefaultSkin()
1385 * @return name of skin as default for this weblog
1387 public function getDefaultSkin()
1389 return $this->getSetting('bdefskin');
1393 * Blog::getUpdateFile()
1395 * @return string name of file to be updated when weblog is updated
1397 public function getUpdateFile()
1399 return $this->getSetting('bupdate');
1403 * Blog::getDescription()
1405 * @return string description for this weblog
1407 public function getDescription()
1409 return $this->getSetting('bdesc');
1415 * @return integer publlic or not
1417 public function isPublic()
1419 return $this->getSetting('bpublic');
1423 * Blog::emailRequired()
1425 * @return integer email is required when posting comment or not
1427 public function emailRequired()
1429 return $this->getSetting('breqemail');
1433 * Blog::getSearchable()
1435 * @return integer searchable or not
1437 public function getSearchable()
1439 return $this->getSetting('bincludesearch');
1443 * Blog::getDefaultCategory()
1445 * @return ID for category as a default
1447 public function getDefaultCategory()
1449 return $this->getSetting('bdefcat');
1454 * @param integer $val allow comments by non-registered members or not
1457 public function setPublic($val)
1459 $this->setSetting('bpublic', $val);
1464 * Blog::setSearchable()
1465 * @param integer $val searchable from the other blogs or not
1468 public function setSearchable($val)
1470 $this->setSetting('bincludesearch', $val);
1475 * Blog::setDescription
1476 * @param string $val description for this weblog
1479 public function setDescription($val)
1481 $this->setSetting('bdesc',$val);
1486 * Blog::setUpdateFile()
1487 * @param string $val name of file to beupdated when weblog is updated
1490 public function setUpdateFile($val)
1492 $this->setSetting('bupdate',$val);
1497 * Blog::setDefaultSkin()
1498 * @param integer $val ID for default skin to use when displaying this weblog
1501 public function setDefaultSkin($val)
1503 $this->setSetting('bdefskin', $val);
1509 * @param string $val URI for this weblog
1512 public function setURL($val)
1514 $this->setSetting('burl', $val);
1520 * @param string $val name of this weblog
1523 public function setName($val)
1525 $this->setSetting('bname', $val);
1530 * Blog::setShortName()
1531 * @param string $val short name for this weblog
1534 public function setShortName($val)
1536 $this->setSetting('bshortname', $val);
1541 * Blog::setCommentsEnabled()
1542 * @param integer $val enabling posting comment or not
1545 public function setCommentsEnabled($val)
1547 $this->setSetting('bcomments',$val);
1552 * Blog::setMaxComments()
1553 * @param integer $val maximum number of comments for this weblog
1556 public function setMaxComments($val)
1558 $this->setSetting('bmaxcomments', $val);
1563 * Blog::setNotifyAddress()
1564 * @param string $val email to be notified if weblog updated
1567 public function setNotifyAddress($val)
1569 $this->setSetting('bnotify', $val);
1574 * Blog::setEmailRequired()
1575 * @param string requiring comments with email or not from non member
1578 public function setEmailRequired($val)
1580 $this->setSetting('breqemail', $val);
1585 * Blog::setTimeOffset()
1586 * @param integer $val time offset
1589 public function setTimeOffset($val)
1591 // check validity of value
1592 // 1. replace , by . (common mistake)
1593 $val = str_replace(',','.',$val);
1595 // 2. cast to float or int
1596 if ( is_numeric($val) && (i18n::strpos($val, '.5') === (i18n::strlen($val) - 2)) )
1598 $val = (float) $val;
1602 $val = (integer) $val;
1605 $this->setSetting('btimeoffset',$val);
1610 * Blog::setDefaultCategory()
1611 * @param integer $val ID for default category for this weblog
1614 public function setDefaultCategory($val)
1616 $this->setSetting('bdefcat',$val);
1621 * Blog::getSetting()
1622 * @param string $key key for setting of this weblog
1623 * @return mixed value for the setting
1625 public function getSetting($key)
1627 return $this->settings[$key];
1631 * Blog::setSetting()
1632 * @param string $key key for setting of this weblog
1633 * @param mixed $value value for the key
1636 public function setSetting($key, $value)
1638 $this->settings[$key] = $value;
1643 * Blog::addTeamMember()
1644 * Tries to add a member to the team.
1645 * Returns false if the member was already on the team
1647 * @param integer $memberid id for member
1648 * @param boolean $admin super-admin or not
1649 * @return boolean Success/Fail
1651 public function addTeamMember($memberid, $admin)
1655 $memberid = intval($memberid);
1656 $admin = intval($admin);
1658 // check if member is already a member
1659 $tmem =& $manager->getMember($memberid);
1661 if ( $tmem->isTeamMember($this->blogid) )
1671 $manager->notify('PreAddTeamMember', $data);
1674 $query = "INSERT INTO %s (TMEMBER, TBLOG, TADMIN) VALUES (%d, %d, %d);";
1675 $query = sprintf($query, sql_table('team'), (integer) $memberid, (integer) $this->blogid, (integer) $admin);
1676 DB::execute($query);
1683 $manager->notify('PostAddTeamMember', $data);
1685 $logMsg = sprintf(_TEAM_ADD_NEWTEAMMEMBER, $tmem->getDisplayName(), $memberid, $this->getName());
1686 ActionLog::add(INFO, $logMsg);
1694 * @return integer ID for this weblog
1696 public function getID()
1698 return (integer) $this->blogid;
1702 * Checks if a blog with a given shortname exists
1703 * Returns true if there is a blog with the given shortname (static)
1705 * @param string $name blog shortname
1706 * @return boolean exists or not
1708 public function exists($name)
1710 $r = DB::getResult('SELECT * FROM '.sql_table('blog').' WHERE bshortname='. DB::quoteValue($name));
1711 return ($r->rowCount() != 0);
1715 * Checks if a blog with a given id exists
1716 * Returns true if there is a blog with the given ID (static)
1718 * @param integer $id ID for searched weblog
1719 * @return boolean exists or not
1721 public function existsID($id)
1723 $r = DB::getResult('SELECT * FROM '.sql_table('blog').' WHERE bnumber='.intval($id));
1724 return ($r->rowCount() != 0);
1728 * Blog::setFuturePost()
1729 * flag there is a future post pending
1734 public function setFuturePost()
1736 $query = "UPDATE %s SET bfuturepost='1' WHERE bnumber=%d;";
1737 $query = sprintf($query, sql_table('blog'), (integer) $this->blogid);
1738 DB::execute($query);
1743 * Blog::clearFuturePost()
1744 * clear there is a future post pending
1749 public function clearFuturePost()
1751 $query = "UPDATE %s SET bfuturepost='0' WHERE bnumber=%d;";
1752 $query = sprintf($query, sql_table('blog'), (integer) $this->blogid);
1753 DB::execute($query);
1758 * Blog::checkJustPosted()
1759 * check if we should throw justPosted event
1764 public function checkJustPosted()
1768 if ( $this->settings['bfuturepost'] == 1 )
1770 $query = "SELECT * FROM %s WHERE iposted=0 AND iblog=%d AND itime < NOW();";
1771 $query = sprintf($query, sql_table('item'), (integer) $this->blogid);
1773 $result = DB::getResult($query);
1774 if ( $result->rowCount() > 0 )
1776 // This $pinged is allow a plugin to tell other hook to the event that a ping is sent already
1777 // Note that the plugins's calling order is subject to thri order in the plugin list
1779 $data = array('blogid' => $this->blogid, 'pinged' => &$pinged);
1780 $manager->notify('JustPosted', $data);
1782 // clear all expired future posts
1783 $query = "UPDATE %s SET iposted='1' WHERE iblog=%d AND itime < NOW();";
1784 $query = spriintf($query, sql_table('item'), (integer) $this->blogid);
1785 DB::execute($query);
1787 // check to see any pending future post, clear the flag is none
1788 $query = "SELECT * FROM %s WHERE iposted=0 AND iblog=%d;";
1789 $query = sprintf($query, sql_table('item'), (integer) $this->blogid);
1791 $result = DB::getResult($query);
1792 if ( $result->rowCount() == 0 )
1794 $this->clearFuturePost();
1802 * Blog::readLogFromList()
1803 * Shows the given list of items for this blog
1805 * @param array $itemarray array of item numbers to be displayed
1806 * @param string $template string representing the template _NAME_ (!)
1807 * @param string $highlight contains a query that should be highlighted
1808 * @param boolean $comments 1=show comments 0=don't show comments
1809 * @param boolean $dateheads 1=show dateheads 0=don't show dateheads
1810 * @param boolean $showDrafts 0=do not show drafts 1=show drafts
1811 * @param boolean $showFuture 0=do not show future posts 1=show future posts
1812 * @return integer amount of items shown
1814 public function readLogFromList($itemarray, $template, $highlight = '', $comments = 1, $dateheads = 1,$showDrafts = 0, $showFuture = 0)
1816 $query = $this->getSqlItemList($itemarray,$showDrafts,$showFuture);
1817 return $this->showUsingQuery($template, $query, $highlight, $comments, $dateheads);
1821 * Blog::getSqlItemList()
1822 * Returns the SQL query used to fill out templates for a list of items
1823 * No LIMIT clause is added. (caller should add this if multiple pages are requested)
1825 * @param array $itemarray an array holding the item numbers of the items to be displayed
1826 * @param integer $showDrafts 0=do not show drafts 1=show drafts
1827 * @param integer $showFuture 0=do not show future posts 1=show future posts
1828 * @return string either a full SQL query, or an empty string
1830 public function getSqlItemList($itemarray,$showDrafts = 0,$showFuture = 0)
1832 if ( !is_array($itemarray) )
1837 $showDrafts = intval($showDrafts);
1838 $showFuture = intval($showFuture);
1841 foreach ( $itemarray as $value )
1843 if ( intval($value) )
1845 $items[] = intval($value);
1848 if ( !count($items) )
1855 foreach ( $items as $value )
1859 . ' i.inumber as itemid,'
1860 . ' i.ititle as title,'
1861 . ' i.ibody as body,'
1862 . ' m.mname as author,'
1863 . ' m.mrealname as authorname,'
1865 . ' i.imore as more,'
1866 . ' m.mnumber as authorid,'
1867 . ' m.memail as authormail,'
1868 . ' m.murl as authorurl,'
1869 . ' c.cname as category,'
1870 . ' i.icat as catid,'
1871 . ' i.iclosed as closed';
1874 . sql_table('item') . ' as i, '
1875 . sql_table('member') . ' as m, '
1876 . sql_table('category') . ' as c'
1878 . ' i.iblog='.$this->blogid
1879 . ' and i.iauthor=m.mnumber'
1880 . ' and i.icat=c.catid';
1885 $query .= ' and i.idraft=0';
1889 // don't show future items
1890 $query .= ' and i.itime<=' . DB::formatDateTime($this->getCorrectTime());
1893 $query .= ' and i.inumber='.intval($value);
1896 if ($i) $query .= ' UNION ';
1903 * Blog::convertBreaks()
1904 * Get the the setting for the line break handling
1905 * [should be named as getConvertBreaks()]
1911 public function convertBreaks()
1913 return $this->getSetting('bconvertbreaks');
1917 * Set the the setting for the line break handling
1920 * @param boolean $val new value for bconvertbreaks
1923 public function setConvertBreaks($val)
1925 $this->setSetting('bconvertbreaks', $val);