4 * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
5 * Copyright (C) 2002-2009 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 // ID of currently selected category
33 // After creating an object of the blog class, contains true if the BLOG object is
34 // valid (the blog exists)
37 // associative array, containing all blogsettings (use the get/set functions instead)
41 * Creates a new BLOG object for the given blog
46 $this->blogid = intval($id);
47 $this->readSettings();
50 // (the parse functions in SKIN.php will override this, so it's mainly useless)
52 $this->setSelectedCategory($catid);
56 * Shows the given amount of items for this blog
59 * String representing the template _NAME_ (!)
60 * @param $amountEntries
61 * amount of entries to show
63 * offset from where items should be shown (e.g. 5 = start at fifth item)
65 * amount of items shown
67 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
81 function showArchive($templatename, $year, $month=0, $day=0)
83 // create extra where clause for select query
84 if ( $day == 0 && $month != 0 )
86 $timestamp_start = mktime(0,0,0,$month,1,$year);
87 // also works when $month==12
88 $timestamp_end = mktime(0,0,0,$month+1,1,$year);
90 elseif ( $month == 0 )
92 $timestamp_start = mktime(0,0,0,1,1,$year);
93 // also works when $month==12
94 $timestamp_end = mktime(0,0,0,12,31,$year);
98 $timestamp_start = mktime(0,0,0,$month,$day,$year);
99 $timestamp_end = mktime(0,0,0,$month,$day+1,$year);
101 $extra_query = " and i.itime>='%s' and i.itime<'%s'";
102 $extra_query = sprintf($extra_query, i18n::formatted_datetime('mysql', $timestamp_start), i18n::formatted_datetime('mysql', $timestamp_end));
104 $this->readLogAmount($templatename,0,$extra_query,'',1,1);
109 * Sets the selected category by id (only when category exists)
111 function setSelectedCategory($catid) {
112 if ($this->isValidCategory($catid) || (intval($catid) == 0))
113 $this->selectedcatid = intval($catid);
117 * Sets the selected category by name
119 function setSelectedCategoryByName($catname) {
120 $this->setSelectedCategory($this->getCategoryIdFromName($catname));
124 * Returns the selected category
126 function getSelectedCategory() {
127 return $this->selectedcatid;
131 * Shows the given amount of items for this blog
134 * String representing the template _NAME_ (!)
135 * @param $amountEntries
136 * amount of entries to show (0 = no limit)
138 * extra conditions to be added to the query
140 * contains a query that should be highlighted
142 * 1=show comments 0=don't show comments
144 * 1=show dateheads 0=don't show dateheads
148 * amount of items shown
150 function readLogAmount($template, $amountEntries, $extraQuery, $highlight, $comments, $dateheads, $offset = 0, $startpos = 0) {
152 $query = $this->getSqlBlog($extraQuery);
154 if ($amountEntries > 0) {
155 // $offset zou moeten worden:
156 // (($startpos / $amountentries) + 1) * $offset ... later testen ...
157 $query .= ' LIMIT ' . intval($startpos + $offset).',' . intval($amountEntries);
159 return $this->showUsingQuery($template, $query, $highlight, $comments, $dateheads);
163 * BLOG::showUsingQuery()
164 * Do the job for readLogAmmount
166 * @param string $templateName template name
167 * @param string $query string for query
168 * @param string $highlight string to be highlighted
169 * @param integer $comments the number of comments
170 * @param boolean $dateheads date header is needed or not
171 * @return integer the number of rows as a result of mysql query
174 function showUsingQuery($templateName, $query, $highlight = '', $comments = 0, $dateheads = 1)
176 global $CONF, $manager, $currentTemplateName;
178 $lastVisit = cookieVar($CONF['CookiePrefix'] .'lastVisit');
179 if ( $lastVisit != 0 )
181 $lastVisit = $this->getCorrectTime($lastVisit);
184 // set templatename as global variable (so plugins can access it)
185 $currentTemplateName = $templateName;
186 $template =& $manager->getTemplate($templateName);
188 // create parser object & action handler
189 $actions = new ITEMACTIONS($this);
190 $parser = new PARSER($actions->getDefinedActions(),$actions);
191 $actions->setTemplate($template);
192 $actions->setHighlight($highlight);
193 $actions->setLastVisit($lastVisit);
194 $actions->setParser($parser);
195 $actions->setShowComments($comments);
198 $items = sql_query($query);
200 // loop over all items
202 while ( $item = sql_fetch_object($items) )
204 $item->timestamp = strtotime($item->itime); // string timestamp -> unix timestamp
206 // action handler needs to know the item we're handling
207 $actions->setCurrentItem($item);
209 // add date header if needed
212 $new_date = date('dFY',$item->timestamp);
213 if ( $new_date != $old_date )
215 // unless this is the first time, write date footer
216 $timestamp = $item->timestamp;
217 if ( $old_date != 0 )
219 $oldTS = strtotime($old_date);
220 $manager->notify('PreDateFoot',array('blog' => &$this, 'timestamp' => $oldTS));
221 $tmp_footer = i18n::strftime(isset($template['DATE_FOOTER'])?$template['DATE_FOOTER']:'', $oldTS);
222 $parser->parse($tmp_footer);
223 $manager->notify('PostDateFoot',array('blog' => &$this, 'timestamp' => $oldTS));
225 $manager->notify('PreDateHead',array('blog' => &$this, 'timestamp' => $timestamp));
226 // note, to use templatvars in the dateheader, the %-characters need to be doubled in
227 // order to be preserved by strftime
228 $tmp_header = i18n::strftime((isset($template['DATE_HEADER']) ? $template['DATE_HEADER'] : null), $timestamp);
229 $parser->parse($tmp_header);
230 $manager->notify('PostDateHead',array('blog' => &$this, 'timestamp' => $timestamp));
232 $old_date = $new_date;
236 $parser->parse($template['ITEM_HEADER']);
237 $manager->notify('PreItem', array('blog' => &$this, 'item' => &$item));
238 $parser->parse($template['ITEM']);
239 $manager->notify('PostItem', array('blog' => &$this, 'item' => &$item));
240 $parser->parse($template['ITEM_FOOTER']);
243 $numrows = sql_num_rows($items);
245 // add another date footer if there was at least one item
246 if ( ($numrows > 0) && $dateheads )
248 $manager->notify('PreDateFoot',array('blog' => &$this, 'timestamp' => strtotime($old_date)));
249 $parser->parse($template['DATE_FOOTER']);
250 $manager->notify('PostDateFoot',array('blog' => &$this, 'timestamp' => strtotime($old_date)));
253 sql_free_result($items);
258 * Simplified function for showing only one item
260 function showOneitem($itemid, $template, $highlight) {
261 $extraQuery = ' and inumber=' . intval($itemid);
263 return $this->readLogAmount($template, 1, $extraQuery, $highlight, 0, 0);
269 * Adds an item to this blog
271 * @param Integer $catid ID for category
272 * @param String $title ID for
273 * @param String $body text for body
274 * @param String $more text for more
275 * @param Integer $blogid ID for blog
276 * @param Integer $authorid ID for author
277 * @param Timestamp $timestamp UNIX timestamp for post
278 * @param Boolean $closed opened or closed
279 * @param Boolean $draft draft or not
280 * @param Boolean $posted posted or not
283 function additem($catid, $title, $body, $more, $blogid, $authorid, $timestamp, $closed, $draft, $posted='1')
287 $blogid = intval($blogid);
288 $authorid = intval($authorid);
292 $catid = intval($catid);
294 // convert newlines to <br />
295 if ( $this->convertBreaks() )
297 $body = addBreaks($body);
298 $more = addBreaks($more);
301 if ( $closed != '1' )
310 if ( !$this->isValidCategory($catid) )
312 $catid = $this->getDefaultCategory();
315 if ( $timestamp > $this->getCorrectTime() )
320 $timestamp = date('Y-m-d H:i:s',$timestamp);
322 $manager->notify('PreAddItem',array('title' => &$title, 'body' => &$body, 'more' => &$more, 'blog' => &$this, 'authorid' => &$authorid, 'timestamp' => &$timestamp, 'closed' => &$closed, 'draft' => &$draft, 'catid' => &$catid));
324 $ititle = sql_real_escape_string($title);
325 $ibody = sql_real_escape_string($body);
326 $imore = sql_real_escape_string($more);
328 $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)";
329 $query = sprintf($query, sql_table('item'), $ititle, $ibody, $imore, $blogid, $authorid, $timestamp, $closed, $draft, $catid, $posted);
331 $itemid = sql_insert_id();
333 $manager->notify('PostAddItem',array('itemid' => $itemid));
337 $this->updateUpdateFile();
339 // send notification mail
340 if ( !$draft && !$isFuture && $this->getNotifyAddress() && $this->notifyOnNewItem() )
342 $this->sendNewItemNotification($itemid, $title, $body);
348 * BLOG::sendNewItemNotification()
349 * Send a new item notification to the notification list
351 * @param String $itemid ID of the item
352 * @param String $title title of the item
353 * @param String $body body of the item
356 function sendNewItemNotification($itemid, $title, $body)
358 global $CONF, $member;
360 $ascii = ENTITY::anchor_footnoting($body);
362 $message = _NOTIFY_NI_MSG . " \n";
363 $temp = parse_url($CONF['Self']);
364 if ( $temp['scheme'] )
366 $message .= LINK::create_item_link($itemid) . "\n\n";
370 $tempurl = $this->getURL();
371 if ( i18n::substr($tempurl, -1) == '/' || i18n::substr($tempurl, -4) == '.php' )
373 $message .= $tempurl . '?itemid=' . $itemid . "\n\n";
377 $message .= $tempurl . '/?itemid=' . $itemid . "\n\n";
380 $message .= _NOTIFY_TITLE . ' ' . strip_tags($title) . "\n";
381 $message .= _NOTIFY_CONTENTS . "\n " . $ascii . "\n";
382 $message .= NOTIFICATION::get_mail_footer();
384 $subject = $this->getName() . ': ' . _NOTIFY_NI_TITLE;
386 $from = $member->getNotifyFromMailAddress();
388 NOTIFICATION::mail($this->getNotifyAddress(), $subject, $message, $from, i18n::get_current_charset());
393 * BLOG::createNewCategory()
394 * Creates a new category for this blog
396 * @param String $catName name of the new category. When empty, a name is generated automatically (starting with newcat)
397 * @param String $catDescription description of the new category. Defaults to 'New Category'
398 * @returns Integer the new category-id in case of success. 0 on failure
400 function createNewCategory($catName = '', $catDescription = _CREATED_NEW_CATEGORY_DESC)
402 global $member, $manager;
404 if ( $member->blogAdminRights($this->getID()) )
407 if ( $catName == '' )
409 $catName = _CREATED_NEW_CATEGORY_NAME;
412 $res = sql_query('SELECT * FROM '.sql_table('category')." WHERE cname='".$catName.$i."' and cblog=".$this->getID());
413 while ( sql_num_rows($res) > 0 )
416 $res = sql_query('SELECT * FROM '.sql_table('category')." WHERE cname='".$catName.$i."' and cblog=".$this->getID());
419 $catName = $catName . $i;
427 'description' => $catDescription
431 $query = "INSERT INTO %s (cblog, cname, cdesc) VALUES (%d, '%s', '%s')";
432 $query = sprintf($query, sql_table('category'), (integer) $this->getID(), sql_real_escape_string($catName), sql_real_escape_string($catDescription));
434 $catid = sql_insert_id();
441 'description' => $catDescription,
452 * Searches all months of this blog for the given query
457 * template to be used (__NAME__ of the template)
458 * @param $amountMonths
459 * max amount of months to be search (0 = all)
461 * max number of results to show
465 * amount of hits found
467 function search($query, $template, $amountMonths, $maxresults, $startpos) {
468 global $CONF, $manager;
471 $sqlquery = $this->getSqlSearch($query, $amountMonths, $highlight);
475 // no query -> show everything
477 $amountfound = $this->readLogAmount($template, $maxresults, $extraQuery, $query, 1, 1);
480 // add LIMIT to query (to split search results into pages)
481 if (intval($maxresults > 0))
482 $sqlquery .= ' LIMIT ' . intval($startpos).',' . intval($maxresults);
485 $amountfound = $this->showUsingQuery($template, $sqlquery, $highlight, 1, 1);
487 // when no results were found, show a message
488 if ($amountfound == 0)
490 $template =& $manager->getTemplate($template);
492 'query' => ENTITY::hsc($query),
493 'blogid' => $this->getID()
495 echo TEMPLATE::fill($template['SEARCH_NOTHINGFOUND'],$vars);
503 * BLOG::getSqlSearch()
504 * Returns an SQL query to use for a search query
505 * No LIMIT clause is added. (caller should add this if multiple pages are requested)
507 * @param string $query search query
508 * @param integer $amountMonths amount of months to search back. Default = 0 = unlimited
509 * @param string $mode either empty, or 'count'. In this case, the query will be a SELECT COUNT(*) query
510 * @return string $highlight words to highlight (out parameter)
511 * @return string either a full SQL query, or an empty string (if querystring empty)
513 function getSqlSearch($query, $amountMonths = 0, &$highlight, $mode = '')
515 $searchclass = new SEARCH($query);
517 $highlight = $searchclass->inclusive;
519 // if querystring is empty, return empty string
520 if ( $searchclass->inclusive == '' )
525 $where = $searchclass->boolean_sql_where('ititle, ibody, imore');
526 $select = $searchclass->boolean_sql_select('ititle, ibody, imore');
528 // get list of blogs to search
529 $blogs = $searchclass->blogs; // array containing blogs that always need to be included
530 $blogs[] = $this->getID(); // also search current blog (duh)
531 $blogs = array_unique($blogs); // remove duplicates
534 if ( count($blogs) > 0 )
536 $selectblogs = ' and i.iblog in (' . implode(',', $blogs) . ')';
541 $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,
542 m.mname as author, m.mrealname as authorname, m.mnumber as authorid, m.memail as authormail, m.murl as authorurl,
543 c.cname as category';
547 $query .= ', '.$select. ' as score ';
552 $query = 'SELECT COUNT(*) as result ';
555 $query .= ' FROM '.sql_table('item').' as i, '.sql_table('member').' as m, '.sql_table('category').' as c'
556 . ' WHERE i.iauthor=m.mnumber'
557 . ' and i.icat=c.catid'
561 // don't show future items
562 . ' and i.itime<="' . i18n::formatted_datetime('mysql', $this->getCorrectTime()) . '"'
565 // take into account amount of months to search
566 if ( $amountMonths > 0 )
568 $localtime = getdate($this->getCorrectTime());
569 $timestamp_start = mktime(0,0,0,$localtime['mon'] - $amountMonths,1,$localtime['year']);
570 $query .= ' and i.itime>"' . i18n::formatted_datetime('mysql', $timestamp_start) . '"';
577 $query .= ' ORDER BY score DESC';
581 $query .= ' ORDER BY i.itime DESC ';
589 * Returns the SQL query that's normally used to display the blog items on the index type skins
590 * No LIMIT clause is added. (caller should add this if multiple pages are requested)
592 * @param string $extraQuery extra query string
593 * @param string $mode either empty, or 'count'. In this case, the query will be a SELECT COUNT(*) query
594 * @return string either a full SQL query, or an empty string
596 function getSqlBlog($extraQuery, $mode = '')
600 $query = 'SELECT i.inumber as itemid, i.ititle as title, i.ibody as body, m.mname as author,
601 m.mrealname as authorname, i.itime, i.imore as more, m.mnumber as authorid, m.memail as authormail,
602 m.murl as authorurl, c.cname as category, i.icat as catid, i.iclosed as closed';
606 $query = 'SELECT COUNT(*) as result ';
609 $query .= ' FROM '.sql_table('item').' as i, '.sql_table('member').' as m, '.sql_table('category').' as c'
610 . ' WHERE i.iblog='.$this->blogid
611 . ' and i.iauthor=m.mnumber'
612 . ' and i.icat=c.catid'
615 // don't show future items
616 . ' and i.itime<="' . i18n::formatted_datetime('mysql', $this->getCorrectTime()) . '"';
618 if ( $this->getSelectedCategory() )
620 $query .= ' and i.icat=' . $this->getSelectedCategory() . ' ';
623 $query .= $extraQuery;
627 $query .= ' ORDER BY i.itime DESC';
633 * BLOG::showArchiveList()
634 * Shows the archivelist using the given template
636 * @param String $template template name
637 * @param String $mode year/month/day
638 * @param Integer $limit limit of record count
641 function showArchiveList($template, $mode = 'month', $limit = 0)
643 global $CONF, $catid, $manager;
645 if ( !isset ($linkparams) )
647 $linkparams = array();
652 $linkparams = array('catid' => $catid);
655 $template =& $manager->getTemplate($template);
656 $data['blogid'] = $this->getID();
658 if ( !array_key_exists('ARCHIVELIST_HEADER', $template) || !$template['ARCHIVELIST_HEADER'] )
664 $tplt = $template['ARCHIVELIST_HEADER'];
667 echo TEMPLATE::fill($tplt, $data);
669 $query = 'SELECT itime, SUBSTRING(itime,1,4) AS Year, SUBSTRING(itime,6,2) AS Month, SUBSTRING(itime,9,2) AS Day'
670 . ' FROM '.sql_table('item')
671 . ' WHERE iblog=' . $this->getID()
672 // don't show future items!
673 . ' AND itime <="' . i18n::formatted_datetime('mysql', $this->getCorrectTime()) . '"'
674 // don't show draft items
679 $query .= ' and icat=' . intval($catid);
682 $query .= ' GROUP BY Year';
683 if ( $mode == 'month' || $mode == 'day' )
687 if ( $mode == 'day' )
692 $query .= ' ORDER BY itime DESC';
696 $query .= ' LIMIT ' . intval($limit);
699 $res = sql_query($query);
700 while ( $current = sql_fetch_object($res) )
702 /* string time -> unix timestamp */
703 $current->itime = strtotime($current->itime);
705 if ( $mode == 'day' )
707 $archivedate = date('Y-m-d',$current->itime);
708 $archive['day'] = date('d',$current->itime);
709 $data['day'] = date('d',$current->itime);
710 $data['month'] = date('m',$current->itime);
711 $archive['month'] = $data['month'];
713 elseif ( $mode == 'year' )
715 $archivedate = date('Y',$current->itime);
718 $archive['day'] = '';
719 $archive['month'] = '';
723 $archivedate = date('Y-m',$current->itime);
724 $data['month'] = date('m',$current->itime);
725 $archive['month'] = $data['month'];
727 $archive['day'] = '';
730 $data['year'] = date('Y',$current->itime);
731 $archive['year'] = $data['year'];
732 $data['archivelink'] = LINK::create_archive_link($this->getID(),$archivedate,$linkparams);
735 'PreArchiveListItem',
741 $temp = TEMPLATE::fill($template['ARCHIVELIST_LISTITEM'],$data);
742 echo i18n::strftime($temp,$current->itime);
746 sql_free_result($res);
748 if ( !array_key_exists('ARCHIVELIST_FOOTER', $template) || !$template['ARCHIVELIST_FOOTER'] )
754 $tplt = $template['ARCHIVELIST_FOOTER'];
757 echo TEMPLATE::fill($tplt, $data);
762 * BLOG::showCategoryList()
763 * Shows the list of categories using a given template
765 * @param String $template Template Name
768 function showCategoryList($template)
770 global $CONF, $manager;
773 * determine arguments next to catids
774 * I guess this can be done in a better way, but it works
776 global $archive, $archivelist;
778 $linkparams = array();
781 $blogurl = LINK::create_archive_link($this->getID(), $archive, '');
782 $linkparams['blogid'] = $this->getID();
783 $linkparams['archive'] = $archive;
785 else if ( $archivelist )
787 $blogurl = LINK::create_archivelist_link($this->getID(), '');
788 $linkparams['archivelist'] = $archivelist;
792 $blogurl = LINK::create_blogid_link($this->getID(), '');
793 $linkparams['blogid'] = $this->getID();
796 $template =& $manager->getTemplate($template);
798 //: Change: Set nocatselected variable
799 if ( $this->getSelectedCategory() )
801 $nocatselected = 'no';
805 $nocatselected = 'yes';
808 echo TEMPLATE::fill((isset($template['CATLIST_HEADER']) ? $template['CATLIST_HEADER'] : null),
810 'blogid' => $this->getID(),
811 'blogurl' => $blogurl,
812 'self' => $CONF['Self'],
813 //: Change: Set catiscurrent template variable for header
814 'catiscurrent' => $nocatselected,
815 'currentcat' => $nocatselected
818 $query = 'SELECT catid, cdesc as catdesc, cname as catname FROM '.sql_table('category').' WHERE cblog=' . $this->getID() . ' ORDER BY cname ASC';
819 $res = sql_query($query);
821 while ( $data = sql_fetch_assoc($res) )
823 $data['blogid'] = $this->getID();
824 $data['blogurl'] = $blogurl;
825 $data['catlink'] = LINK::create_link(
828 'catid' => $data['catid'],
829 'name' => $data['catname'],
830 'extra' => $linkparams
832 $data['self'] = $CONF['Self'];
835 //: Change: Bugfix for catiscurrent logic so it gives catiscurrent = no when no category is selected.
836 $data['catiscurrent'] = 'no';
837 $data['currentcat'] = 'no';
838 if ( $this->getSelectedCategory() )
840 if ( $this->getSelectedCategory() == $data['catid'] )
842 $data['catiscurrent'] = 'yes';
843 $data['currentcat'] = 'yes';
849 if ( intval($itemid) && $manager->existsItem(intval($itemid),0,0) )
851 $iobj =& $manager->getItem(intval($itemid),0,0);
852 $cid = $iobj['catid'];
853 if ( $cid == $data['catid'] )
855 $data['catiscurrent'] = 'yes';
856 $data['currentcat'] = 'yes';
862 'PreCategoryListItem',
868 echo TEMPLATE::fill((isset($template['CATLIST_LISTITEM']) ? $template['CATLIST_LISTITEM'] : null), $data);
871 sql_free_result($res);
873 echo TEMPLATE::fill((isset($template['CATLIST_FOOTER']) ? $template['CATLIST_FOOTER'] : null),
875 'blogid' => $this->getID(),
876 'blogurl' => $blogurl,
877 'self' => $CONF['Self'],
878 //: Change: Set catiscurrent template variable for footer
879 'catiscurrent' => $nocatselected,
880 'currentcat' => $nocatselected
886 * BLOG::showBlogList()
887 * Shows a list of all blogs in the system using a given template
888 * ordered by number, name, shortname or description
889 * in ascending or descending order
891 * @param String $template tempalte name
892 * @param String $bnametype bname/bshortname
893 * @param String $orderby string for 'ORDER BY' SQL
894 * @param String $direction ASC/DESC
897 function showBlogList($template, $bnametype, $orderby, $direction)
899 global $CONF, $manager;
910 $orderby='bshortname';
920 $direction=strtolower($direction);
921 switch ( $direction )
934 $template =& $manager->getTemplate($template);
936 echo TEMPLATE::fill((isset($template['BLOGLIST_HEADER']) ? $template['BLOGLIST_HEADER'] : null),
938 'sitename' => $CONF['SiteName'],
939 'siteurl' => $CONF['IndexURL']
943 $query = 'SELECT bnumber, bname, bshortname, bdesc, burl FROM '.sql_table('blog').' ORDER BY '.$orderby.' '.$direction;
944 $res = sql_query($query);
946 while ( $data = sql_fetch_assoc($res) )
949 $list['bloglink'] = LINK::create_blogid_link($data['bnumber']);
950 $list['blogdesc'] = $data['bdesc'];
951 $list['blogurl'] = $data['burl'];
953 if ( $bnametype == 'shortname' )
955 $list['blogname'] = $data['bshortname'];
959 /* all other cases */
960 $list['blogname'] = $data['bname'];
970 echo TEMPLATE::fill((isset($template['BLOGLIST_LISTITEM']) ? $template['BLOGLIST_LISTITEM'] : null), $list);
973 sql_free_result($res);
975 echo TEMPLATE::fill((isset($template['BLOGLIST_FOOTER']) ? $template['BLOGLIST_FOOTER'] : null),
977 'sitename' => $CONF['SiteName'],
978 'siteurl' => $CONF['IndexURL']
985 * Read the blog settings
987 function readSettings() {
989 . ' FROM '.sql_table('blog')
990 . ' WHERE bnumber=' . $this->blogid;
991 $res = sql_query($query);
993 $this->isValid = (sql_num_rows($res) > 0);
997 $this->settings = sql_fetch_assoc($res);
1001 * Write the blog settings
1003 function writeSettings() {
1005 // (can't use floatval since not available prior to PHP 4.2)
1006 $offset = $this->getTimeOffset();
1007 if (!is_float($offset))
1008 $offset = intval($offset);
1010 $query = 'UPDATE '.sql_table('blog')
1011 . " SET bname='" . sql_real_escape_string($this->getName()) . "',"
1012 . " bshortname='". sql_real_escape_string($this->getShortName()) . "',"
1013 . " bcomments=". intval($this->commentsEnabled()) . ","
1014 . " bmaxcomments=" . intval($this->getMaxComments()) . ","
1015 . " btimeoffset=" . $offset . ","
1016 . " bpublic=" . intval($this->isPublic()) . ","
1017 . " breqemail=" . intval($this->emailRequired()) . ","
1018 . " bconvertbreaks=" . intval($this->convertBreaks()) . ","
1019 . " ballowpast=" . intval($this->allowPastPosting()) . ","
1020 . " bnotify='" . sql_real_escape_string($this->getNotifyAddress()) . "',"
1021 . " bnotifytype=" . intval($this->getNotifyType()) . ","
1022 . " burl='" . sql_real_escape_string($this->getURL()) . "',"
1023 . " bupdate='" . sql_real_escape_string($this->getUpdateFile()) . "',"
1024 . " bdesc='" . sql_real_escape_string($this->getDescription()) . "',"
1025 . " bdefcat=" . intval($this->getDefaultCategory()) . ","
1026 . " bdefskin=" . intval($this->getDefaultSkin()) . ","
1027 . " bincludesearch=" . intval($this->getSearchable())
1028 . " WHERE bnumber=" . intval($this->getID());
1034 * Update the update file if requested
1036 function updateUpdatefile() {
1037 if ($this->getUpdateFile()) {
1038 $f_update = fopen($this->getUpdateFile(),'w');
1039 fputs($f_update,$this->getCorrectTime());
1046 * Check if a category with a given catid is valid
1051 function isValidCategory($catid) {
1052 $query = 'SELECT * FROM '.sql_table('category').' WHERE cblog=' . $this->getID() . ' and catid=' . intval($catid);
1053 $res = sql_query($query);
1054 return (sql_num_rows($res) != 0);
1058 * Get the category name for a given catid
1063 function getCategoryName($catid) {
1064 $res = sql_query('SELECT cname FROM '.sql_table('category').' WHERE cblog='.$this->getID().' and catid=' . intval($catid));
1065 $o = sql_fetch_object($res);
1070 * Get the category description for a given catid
1075 function getCategoryDesc($catid) {
1076 $res = sql_query('SELECT cdesc FROM '.sql_table('category').' WHERE cblog='.$this->getID().' and catid=' . intval($catid));
1077 $o = sql_fetch_object($res);
1082 * Get the category id for a given category name
1087 function getCategoryIdFromName($name) {
1088 $res = sql_query('SELECT catid FROM '.sql_table('category').' WHERE cblog='.$this->getID().' and cname="' . sql_real_escape_string($name) . '"');
1089 if (sql_num_rows($res) > 0) {
1090 $o = sql_fetch_object($res);
1093 return $this->getDefaultCategory();
1098 * Get the the setting for the line break handling
1099 * [should be named as getConvertBreaks()]
1101 function convertBreaks() {
1102 return $this->getSetting('bconvertbreaks');
1106 * Set the the setting for the line break handling
1109 * new value for bconvertbreaks
1111 function setConvertBreaks($val) {
1112 $this->setSetting('bconvertbreaks',$val);
1116 * Insert a javascript that includes information about the settings
1117 * of an author: ConvertBreaks, MediaUrl and AuthorId
1122 function insertJavaScriptInfo($authorid = '') {
1123 global $member, $CONF;
1125 if ($authorid == '')
1126 $authorid = $member->getID();
1129 <script type="text/javascript">
1130 setConvertBreaks(<?php echo $this->convertBreaks() ? 'true' : 'false' ?>);
1131 setMediaUrl("<?php echo $CONF['MediaURL']?>");
1132 setAuthorId(<?php echo $authorid?>);
1137 * Set the the setting for allowing to publish postings in the past
1140 * new value for ballowpast
1142 function setAllowPastPosting($val) {
1143 $this->setSetting('ballowpast',$val);
1147 * Get the the setting if it is allowed to publish postings in the past
1148 * [should be named as getAllowPastPosting()]
1150 function allowPastPosting() {
1151 return $this->getSetting('ballowpast');
1154 function getCorrectTime($t=0) {
1155 if ($t == 0) $t = time();
1156 return ($t + 3600 * $this->getTimeOffset());
1159 function getName() {
1160 return $this->getSetting('bname');
1163 function getShortName() {
1164 return $this->getSetting('bshortname');
1167 function getMaxComments() {
1168 return $this->getSetting('bmaxcomments');
1171 function getNotifyAddress() {
1172 return $this->getSetting('bnotify');
1175 function getNotifyType() {
1176 return $this->getSetting('bnotifytype');
1179 function notifyOnComment() {
1180 $n = $this->getNotifyType();
1181 return (($n != 0) && (($n % 3) == 0));
1184 function notifyOnVote() {
1185 $n = $this->getNotifyType();
1186 return (($n != 0) && (($n % 5) == 0));
1189 function notifyOnNewItem() {
1190 $n = $this->getNotifyType();
1191 return (($n != 0) && (($n % 7) == 0));
1194 function setNotifyType($val) {
1195 $this->setSetting('bnotifytype',$val);
1199 function getTimeOffset() {
1200 return $this->getSetting('btimeoffset');
1203 function commentsEnabled() {
1204 return $this->getSetting('bcomments');
1208 return $this->getSetting('burl');
1211 function getDefaultSkin() {
1212 return $this->getSetting('bdefskin');
1215 function getUpdateFile() {
1216 return $this->getSetting('bupdate');
1219 function getDescription() {
1220 return $this->getSetting('bdesc');
1223 function isPublic() {
1224 return $this->getSetting('bpublic');
1227 function emailRequired() {
1228 return $this->getSetting('breqemail');
1231 function getSearchable() {
1232 return $this->getSetting('bincludesearch');
1235 function getDefaultCategory() {
1236 return $this->getSetting('bdefcat');
1239 function setPublic($val) {
1240 $this->setSetting('bpublic',$val);
1243 function setSearchable($val) {
1244 $this->setSetting('bincludesearch',$val);
1247 function setDescription($val) {
1248 $this->setSetting('bdesc',$val);
1251 function setUpdateFile($val) {
1252 $this->setSetting('bupdate',$val);
1255 function setDefaultSkin($val) {
1256 $this->setSetting('bdefskin',$val);
1259 function setURL($val) {
1260 $this->setSetting('burl',$val);
1263 function setName($val) {
1264 $this->setSetting('bname',$val);
1267 function setShortName($val) {
1268 $this->setSetting('bshortname',$val);
1271 function setCommentsEnabled($val) {
1272 $this->setSetting('bcomments',$val);
1275 function setMaxComments($val) {
1276 $this->setSetting('bmaxcomments',$val);
1279 function setNotifyAddress($val) {
1280 $this->setSetting('bnotify',$val);
1283 function setEmailRequired($val) {
1284 $this->setSetting('breqemail',$val);
1287 function setTimeOffset($val) {
1288 // check validity of value
1289 // 1. replace , by . (common mistake)
1290 $val = str_replace(',','.',$val);
1291 // 2. cast to float or int
1292 if (is_numeric($val) && strstr($val,'.5')) {
1293 $val = (float) $val;
1295 $val = intval($val);
1298 $this->setSetting('btimeoffset',$val);
1301 function setDefaultCategory($val) {
1302 $this->setSetting('bdefcat',$val);
1305 function getSetting($key) {
1306 return $this->settings[$key];
1309 function setSetting($key,$value) {
1310 $this->settings[$key] = $value;
1314 * BLOG::addTeamMember()
1315 * Tries to add a member to the team.
1316 * Returns false if the member was already on the team
1318 * @param Integer $memberid id for member
1319 * @param Boolean $admin super-admin or not
1320 * @return Boolean Success/Fail
1322 function addTeamMember($memberid, $admin)
1326 $memberid = intval($memberid);
1327 $admin = intval($admin);
1329 // check if member is already a member
1330 $tmem = MEMBER::createFromID($memberid);
1332 if ( $tmem->isTeamMember($this->getID()) )
1347 $query = "INSERT INTO %s (TMEMBER, TBLOG, TADMIN) ' . 'VALUES (%d, %d, %d)";
1348 $query = sprintf($query, sql_table('team'), $memberid, $this->getID(), $admin);
1352 'PostAddTeamMember',
1360 $logMsg = sprintf(_TEAM_ADD_NEWTEAMMEMBER, $tmem->getDisplayName(), $memberid, $this->getName());
1361 ACTIONLOG::add(INFO, $logMsg);
1367 return (integer) $this->blogid;
1371 * Checks if a blog with a given shortname exists
1372 * Returns true if there is a blog with the given shortname (static)
1377 function exists($name) {
1378 $r = sql_query('select * FROM '.sql_table('blog').' WHERE bshortname="'.sql_real_escape_string($name).'"');
1379 return (sql_num_rows($r) != 0);
1383 * Checks if a blog with a given id exists
1384 * Returns true if there is a blog with the given ID (static)
1389 function existsID($id) {
1390 $r = sql_query('select * FROM '.sql_table('blog').' WHERE bnumber='.intval($id));
1391 return (sql_num_rows($r) != 0);
1395 * flag there is a future post pending
1397 function setFuturePost() {
1398 $query = 'UPDATE '.sql_table('blog')
1399 . " SET bfuturepost='1' WHERE bnumber=" . $this->getID();
1404 * clear there is a future post pending
1406 function clearFuturePost() {
1407 $query = 'UPDATE '.sql_table('blog')
1408 . " SET bfuturepost='0' WHERE bnumber=" . $this->getID();
1413 * check if we should throw justPosted event
1415 function checkJustPosted() {
1418 if ($this->settings['bfuturepost'] == 1) {
1419 $blogid = $this->getID();
1420 $result = sql_query("SELECT * FROM " . sql_table('item')
1421 . " WHERE iposted=0 AND iblog=" . $blogid . " AND itime<NOW()");
1422 if (sql_num_rows($result) > 0) {
1423 // This $pinged is allow a plugin to tell other hook to the event that a ping is sent already
1424 // Note that the plugins's calling order is subject to thri order in the plugin list
1428 array('blogid' => $blogid,
1429 'pinged' => &$pinged
1433 // clear all expired future posts
1434 sql_query("UPDATE " . sql_table('item') . " SET iposted='1' WHERE iblog=" . $blogid . " AND itime<NOW()");
1436 // check to see any pending future post, clear the flag is none
1437 $result = sql_query("SELECT * FROM " . sql_table('item')
1438 . " WHERE iposted=0 AND iblog=" . $blogid);
1439 if (sql_num_rows($result) == 0) {
1440 $this->clearFuturePost();
1447 * Shows the given list of items for this blog
1450 * array of item numbers to be displayed
1452 * String representing the template _NAME_ (!)
1454 * contains a query that should be highlighted
1456 * 1=show comments 0=don't show comments
1458 * 1=show dateheads 0=don't show dateheads
1459 * @param $showDrafts
1460 * 0=do not show drafts 1=show drafts
1461 * @param $showFuture
1462 * 0=do not show future posts 1=show future posts
1464 * amount of items shown
1466 function readLogFromList($itemarray, $template, $highlight = '', $comments = 1, $dateheads = 1,$showDrafts = 0, $showFuture = 0) {
1468 $query = $this->getSqlItemList($itemarray,$showDrafts,$showFuture);
1470 return $this->showUsingQuery($template, $query, $highlight, $comments, $dateheads);
1474 * BLOG::getSqlItemList()
1475 * Returns the SQL query used to fill out templates for a list of items
1476 * No LIMIT clause is added. (caller should add this if multiple pages are requested)
1478 * @param array $itemarray an array holding the item numbers of the items to be displayed
1479 * @param integer $showDrafts 0=do not show drafts 1=show drafts
1480 * @param integer $showFuture 0=do not show future posts 1=show future posts
1481 * @return string either a full SQL query, or an empty string
1484 function getSqlItemList($itemarray,$showDrafts = 0,$showFuture = 0)
1486 if ( !is_array($itemarray) )
1491 $showDrafts = intval($showDrafts);
1492 $showFuture = intval($showFuture);
1495 foreach ( $itemarray as $value )
1497 if ( intval($value) )
1499 $items[] = intval($value);
1502 if ( !count($items) )
1509 foreach ( $items as $value )
1513 . ' i.inumber as itemid,'
1514 . ' i.ititle as title,'
1515 . ' i.ibody as body,'
1516 . ' m.mname as author,'
1517 . ' m.mrealname as authorname,'
1519 . ' i.imore as more,'
1520 . ' m.mnumber as authorid,'
1521 . ' m.memail as authormail,'
1522 . ' m.murl as authorurl,'
1523 . ' c.cname as category,'
1524 . ' i.icat as catid,'
1525 . ' i.iclosed as closed';
1528 . sql_table('item') . ' as i, '
1529 . sql_table('member') . ' as m, '
1530 . sql_table('category') . ' as c'
1532 . ' i.iblog='.$this->blogid
1533 . ' and i.iauthor=m.mnumber'
1534 . ' and i.icat=c.catid';
1539 $query .= ' and i.idraft=0';
1543 // don't show future items
1544 $query .= ' and i.itime<="' . i18n::formatted_datetime('mysql', $this->getCorrectTime()) . '"';
1547 $query .= ' and i.inumber='.intval($value);
1550 if ($i) $query .= ' UNION ';