summaryrefslogtreecommitdiff
path: root/includes/classes/BitBoard.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/classes/BitBoard.php')
-rw-r--r--includes/classes/BitBoard.php866
1 files changed, 866 insertions, 0 deletions
diff --git a/includes/classes/BitBoard.php b/includes/classes/BitBoard.php
new file mode 100644
index 0000000..1c62a35
--- /dev/null
+++ b/includes/classes/BitBoard.php
@@ -0,0 +1,866 @@
+<?php
+/**
+ * $Header$
+ * $Id$
+ *
+ * BitBoard class to illustrate best practices when creating a new bitweaver package that
+ * builds on core bitweaver functionality, such as the Liberty CMS engine
+ *
+ * @author spider <spider@steelsun.com>
+ * @version $Revision$
+ * @package boards
+ */
+
+/**
+ * required setup
+ */
+require_once( LIBERTY_PKG_PATH.'LibertyMime.php' );
+
+/**
+* This is used to uniquely identify the object
+*/
+define( 'BITBOARD_CONTENT_TYPE_GUID', 'bitboard' );
+
+/**
+ * @package boards
+ */
+class BitBoard extends LibertyMime {
+ /**
+ * Primary key for our mythical BitBoard class object & table
+ * @public
+ */
+ public $mBitBoardId;
+
+ /**
+ * During initialisation, be sure to call our base constructors
+ **/
+ function __construct( $pBitBoardId=NULL, $pContentId=NULL ) {
+ parent::__construct();
+ $this->mBitBoardId = (int)$pBitBoardId;
+ $this->mContentId = (int)$pContentId;
+ $this->mContentTypeGuid = BITBOARD_CONTENT_TYPE_GUID;
+ $this->registerContentType( BITBOARD_CONTENT_TYPE_GUID, array(
+ 'content_type_guid' => BITBOARD_CONTENT_TYPE_GUID,
+ 'content_name' => 'Message Board',
+ 'handler_class' => 'BitBoard',
+ 'handler_package' => 'boards',
+ 'handler_file' => 'BitBoard.php',
+ 'maintainer_url' => 'http://www.bitweaver.org'
+ ));
+
+ // Permission setup
+ $this->mViewContentPerm = 'p_boards_read';
+ $this->mCreateContentPerm = 'p_boards_create';
+ $this->mUpdateContentPerm = 'p_boards_update';
+ $this->mAdminContentPerm = 'p_boards_admin';
+ $this->mExpungeContentPerm = 'p_boards_remove';
+ }
+
+ /**
+ * Load the data from the database
+ * @param pParamHash be sure to pass by reference in case we need to make modifcations to the hash
+ **/
+ function load( $pContentId = NULL, $pPluginParams = NULL ) {
+ if( $this->verifyId( $this->mBitBoardId ) || $this->verifyId( $this->mContentId ) ) {
+ // LibertyContent::load()assumes you have joined already, and will not execute any sql!
+ // This is a significant performance optimization
+ $lookupColumn = $this->verifyId( $this->mBitBoardId ) ? 'board_id' : 'content_id';
+ $bindVars = array();
+ $selectSql = $joinSql = $whereSql = '';
+ array_push( $bindVars, (int)($lookupId = @BitBase::verifyId( $this->mBitBoardId ) ? $this->mBitBoardId : $this->mContentId) );
+ $this->getServicesSql( 'content_load_sql_function', $selectSql, $joinSql, $whereSql, $bindVars );
+
+ $query = "SELECT s.*, lc.*, " .
+ "uue.`login` AS modifier_user, uue.`real_name` AS modifier_real_name, " .
+ "uuc.`login` AS creator_user, uuc.`real_name` AS creator_real_name " .
+ "$selectSql " .
+ "FROM `".BIT_DB_PREFIX."boards` s " .
+ "INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON( lc.`content_id` = s.`content_id` ) $joinSql" .
+ "LEFT JOIN `".BIT_DB_PREFIX."users_users` uue ON( uue.`user_id` = lc.`modifier_user_id` )" .
+ "LEFT JOIN `".BIT_DB_PREFIX."users_users` uuc ON( uuc.`user_id` = lc.`user_id` )" .
+ "WHERE s.`$lookupColumn`=? $whereSql";
+ $result = $this->mDb->query( $query, $bindVars );
+
+ if( $result && $result->numRows() ) {
+ $this->mInfo = $result->fields;
+ $this->mContentId = $result->fields['content_id'];
+ $this->mBitBoardId = $result->fields['board_id'];
+
+ $this->mInfo['creator'] =( isset( $result->fields['creator_real_name'] )? $result->fields['creator_real_name'] : $result->fields['creator_user'] );
+ $this->mInfo['editor'] =( isset( $result->fields['modifier_real_name'] )? $result->fields['modifier_real_name'] : $result->fields['modifier_user'] );
+ $this->mInfo['display_url'] = $this->getDisplayUrl();
+ $this->parseData();
+
+ LibertyMime::load();
+ }
+ }
+ return( count( $this->mInfo ) );
+ }
+
+ function lookupByMigrateBoard( $pMigrateBoardId ) {
+ global $gBitDb;
+ $ret = NULL;
+ if( BitBase::verifyId( $pMigrateBoardId ) ) {
+ $ret = $gBitDb->getOne( "SELECT `board_id` FROM `".BIT_DB_PREFIX."boards` bb WHERE `migrate_board_id`=?", array( $pMigrateBoardId ) );
+ }
+ return $ret;
+ }
+
+ /**
+ * Any method named Store inherently implies data will be written to the database
+ * @param pParamHash be sure to pass by reference in case we need to make modifcations to the hash
+ * This is the ONLY method that should be called in order to store( create or update )an bitboard!
+ * It is very smart and will figure out what to do for you. It should be considered a black box.
+ *
+ * @param array pParams hash of values that will be used to store the page
+ *
+ * @return bool TRUE on success, FALSE if store could not occur. If FALSE, $this->mErrors will have reason why
+ *
+ * @access public
+ **/
+ function store( &$pParamHash ) {
+ if( $this->verify( $pParamHash )&& LibertyMime::store( $pParamHash ) ) {
+ $table = BIT_DB_PREFIX."boards";
+ $this->StartTrans();
+ if( $this->mBitBoardId ) {
+ $locId = array( "board_id" => $pParamHash['board_id'] );
+ $result = $this->mDb->associateUpdate( $table, $pParamHash['board_store'], $locId );
+ } else {
+ $pParamHash['board_store']['content_id'] = $pParamHash['content_id'];
+ if( @$this->verifyId( $pParamHash['board_id'] ) ) {
+ // if pParamHash['board_id'] is set, some is requesting a particular board_id. Use with caution!
+ $pParamHash['board_store']['board_id'] = $pParamHash['board_id'];
+ } else {
+ $pParamHash['board_store']['board_id'] = $this->mDb->GenID( 'boards_board_id_seq' );
+ }
+ $this->mBitBoardId = $pParamHash['board_store']['board_id'];
+
+ $result = $this->mDb->associateInsert( $table, $pParamHash['board_store'] );
+ $result = $this->mDb->associateInsert( BIT_DB_PREFIX."boards_map",array('board_content_id'=>$pParamHash['board_store']['content_id'],'topic_content_id'=>$pParamHash['board_store']['content_id']));
+ if( !empty( $pParamHash['boards_mailing_list'] ) ) {
+ global $gBitSystem, $gBitUser;
+ require_once( UTIL_PKG_INC.'mailman_lib.php' );
+ if( $gBitSystem->getConfig( 'boards_sync_mail_server' ) ) {
+ if( !($error = mailman_newlist( array( 'listname' => $pParamHash['boards_mailing_list'], 'listhost' => $gBitSystem->getConfig( 'boards_email_host', $gBitSystem->getConfig( 'kernel_server_name' ) ), 'admin-password'=>$pParamHash['boards_mailing_list_password'], 'listadmin-addr'=>$gBitUser->getField( 'email' ) ) )) ) {
+ $this->storePreference( 'boards_mailing_list', !empty( $pParamHash['boards_mailing_list'] ) ? $pParamHash['boards_mailing_list'] : NULL );
+ $this->storePreference( 'boards_mailing_list_password', $pParamHash['boards_mailing_list_password'] );
+ // Subscribe the owner
+ mailman_addmember( $this->getPreference( 'boards_mailing_list'), $gBitUser->getField('email') );
+ // If we have an inbox then subscribe it as a moderator
+ if( $this->getBoardSyncInbox() ) {
+ mailman_addmember( $this->getPreference( 'boards_mailing_list' ), $this->getBoardSyncInbox() );
+ mailman_setmoderator( $this->getPreference( 'boards_mailing_list' ), $this->getBoardSyncInbox() );
+ }
+ $this->storePreference( 'board_sync_list_address', $this->getBoardMailingList() );
+ } else {
+ $this->mErrors['mailing_list'] = $error;
+ }
+ }
+ }
+ }
+
+ if( count( $this->mErrors ) == 0 ) {
+ $this->CompleteTrans();
+ $this->load();
+ } else {
+ $this->mDb->RollbackTrans();
+ $this->mContentId = NULL;
+ $this->mBitBoardId = NULL;
+ }
+ }
+ return( count( $this->mErrors )== 0 );
+ }
+
+ /**
+ * Make sure the data is safe to store
+ * @param pParamHash be sure to pass by reference in case we need to make modifcations to the hash
+ * This function is responsible for data integrity and validation before any operations are performed with the $pParamHash
+ * NOTE: This is a PRIVATE METHOD!!!! do not call outside this class, under penalty of death!
+ *
+ * @param array pParams reference to hash of values that will be used to store the page, they will be modified where necessary
+ *
+ * @return bool TRUE on success, FALSE if verify failed. If FALSE, $this->mErrors will have reason why
+ *
+ * @access private
+ **/
+ function verify( &$pParamHash ) {
+ // make sure we're all loaded up of we have a mBitBoardId
+ if( $this->verifyId( $this->mBitBoardId ) && empty( $this->mInfo ) ) {
+ $this->load();
+ }
+
+ if( @$this->verifyId( $this->mInfo['content_id'] ) ) {
+ $pParamHash['content_id'] = $this->mInfo['content_id'];
+ }
+
+ // It is possible a derived class set this to something different
+ if( empty( $pParamHash['content_type_guid'] ) ) {
+ $pParamHash['content_type_guid'] = $this->mContentTypeGuid;
+ }
+
+ if( @$this->verifyId( $pParamHash['content_id'] ) ) {
+ $pParamHash['board_store']['content_id'] = $pParamHash['content_id'];
+ }
+
+ if( @$this->verifyId( $pParamHash['migrate_board_id'] ) ) {
+ $pParamHash['board_store']['migrate_board_id'] = $pParamHash['migrate_board_id'];
+ }
+/* board description seems to have been removed in favor of liberty_content data
+ // check some lengths, if too long, then truncate
+ if( $this->isValid() && !empty( $this->mInfo['description'] ) && empty( $pParamHash['description'] ) ) {
+ // someone has deleted the description, we need to null it out
+ $pParamHash['board_store']['description'] = '';
+ } else if( empty( $pParamHash['description'] ) ) {
+ unset( $pParamHash['description'] );
+ } else {
+ $pParamHash['board_store']['description'] = substr( $pParamHash['description'], 0, 200 );
+ }
+*/
+ if( !empty( $pParamHash['data'] ) ) {
+ $pParamHash['edit'] = $pParamHash['data'];
+ }
+
+ // check for name issues, first truncate length if too long
+ if( !empty( $pParamHash['title'] ) ) {
+ if( empty( $this->mBitBoardId ) ) {
+ if( empty( $pParamHash['title'] ) ) {
+ $this->mErrors['title'] = 'You must enter a name for this page.';
+ } else {
+ $pParamHash['content_store']['title'] = substr( $pParamHash['title'], 0, 160 );
+ }
+ } else {
+ $pParamHash['content_store']['title'] =( isset( $pParamHash['title'] ) )? substr( $pParamHash['title'], 0, 160 ): '';
+ }
+ } else if( empty( $pParamHash['title'] ) ) {
+ // no name specified
+ $this->mErrors['title'] = 'You must specify a name';
+ }
+
+ return( count( $this->mErrors )== 0 );
+ }
+
+
+ /**
+ * Prepare data for preview
+ */
+ function preparePreview( $pParamHash ) {
+ global $gBitSystem, $gBitUser;
+
+ if( empty( $pParamHash['user_id'] ) ) {
+ $pParamHash['user_id'] = $gBitUser->mUserId;
+ }
+
+ if( isset( $pParamHash["title"] ) ) {
+ $this->mInfo["title"] = $pParamHash["title"];
+ }
+
+ if( isset( $pParamHash["description"] ) ) {
+ $this->mInfo["description"] = $pParamHash["description"];
+ }
+
+ if( isset( $pParamHash["format_guid"] ) ) {
+ $this->mInfo['format_guid'] = $pParamHash["format_guid"];
+ }
+
+ if( isset( $pParamHash["edit"] ) ) {
+ $this->mInfo["data"] = $pParamHash["edit"];
+ $this->mInfo['parsed_data'] = $this->parseData();
+ }
+ }
+
+
+ /**
+ * This function removes a bitboard entry
+ **/
+ function expunge() {
+ $ret = FALSE;
+ if( $this->isValid() ) {
+ $this->StartTrans();
+ $mailingList = $this->getPreference( 'boards_mailing_list' );
+ $query = "DELETE FROM `".BIT_DB_PREFIX."boards_map` WHERE `board_content_id` = ?";
+ $result = $this->mDb->query( $query, array( $this->mContentId ) );
+ $query = "DELETE FROM `".BIT_DB_PREFIX."boards` WHERE `content_id` = ?";
+ $result = $this->mDb->query( $query, array( $this->mContentId ) );
+ if( LibertyMime::expunge() ) {
+ if( $mailingList ) {
+ require_once( UTIL_PKG_INC.'mailman_lib.php' );
+ if( $error = mailman_rmlist( $mailingList ) ) {
+ $this->mErrors['mailing_list'] = $error;
+ }
+ }
+ $ret = TRUE;
+ $this->CompleteTrans();
+ } else {
+ $this->mDb->RollbackTrans();
+ }
+ }
+ return $ret;
+ }
+
+ /**
+ * Make sure bitboard is loaded and valid
+ **/
+ function isValid() {
+ return( $this->verifyId( $this->mBitBoardId ) && $this->verifyId( $this->mContentId ) );
+ }
+
+ function getAllMap() {
+ $b = new BitBoard();
+ $listHash = array();
+ $l = $b->getList($listHash);
+ $ret = array();
+ foreach ($l as $k => $boardd) {
+ $board = new BitBoard($boardd['board_id']);
+ $board->mInfo=$boardd;
+ $ret['map'][$k]=$boardd;
+ $ret['map'][$k]['map'] = $board->getMap();
+ $ret['map'][$k]['integrity'] = $board->verifyIntegrity();
+ }
+ // reorganise unmapped content for better display
+ $umapped = $b->getUnMapped();
+ foreach( $umapped as $key => $content ) {
+ $umap[$content['content_name']][$key] = $content;
+ }
+ $ret['umap'] = $umap;
+ return $ret;
+ }
+
+ function getUnMapped() {
+ global $gBitSystem;
+ $ret = NULL;
+ $sql = "SELECT
+ lc.`title`,
+ lc.`content_id`,
+ lct.`content_name`, (
+ SELECT count(*)
+ FROM `".BIT_DB_PREFIX."liberty_comments` lcom
+ WHERE lcom.`root_id`=lcom.`parent_id` AND lcom.`root_id`=lc.`content_id`
+ ) AS thread_count
+ FROM `".BIT_DB_PREFIX."liberty_content` lc
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content_types` lct ON (lc.`content_type_guid`=lct.`content_type_guid`)
+ WHERE lc.`content_id` NOT IN (
+ SELECT lc.`content_id` AS content_id
+ FROM `".BIT_DB_PREFIX."boards` b
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` blc ON (blc.`content_id`=b.`content_id`)
+ INNER JOIN `".BIT_DB_PREFIX."boards_map` map ON (map.`board_content_id`= blc.`content_id`)
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (lc.`content_id`=map.`topic_content_id`)
+ )
+ AND lc.`content_type_guid` != 'pigeonholes'
+ AND lc.`content_type_guid` != 'bitboard'
+ AND lc.`content_type_guid` != 'bitcomment'
+ AND lc.`title` != ''
+ ORDER BY lc.`content_type_guid`, lc.`title`
+ ";
+ $rs = $this->mDb->query( $sql );
+ while( $row = $rs->fetchRow() ) {
+ $ret[$row['content_id']] = $row;
+ }
+ return $ret;
+ }
+
+ function addContent($content_id) {
+ if (@BitBase::verifyId($content_id)) {
+ $data = array(
+ 'board_content_id'=>$this->mContentId,
+ 'topic_content_id'=>$content_id,
+ );
+ $this->mDb->associateInsert( BIT_DB_PREFIX."boards_map",$data);
+ }
+ }
+
+ function removeContent($content_id) {
+ if (@BitBase::verifyId($content_id) && @BitBase::verifyId($this->mContentId)) {
+ $sql = "DELETE FROM `".BIT_DB_PREFIX."boards_map` WHERE `board_content_id` = ? AND `topic_content_id` = ?";
+ $result = $this->mDb->query( $sql, array( $this->mContentId,$content_id ) );
+ }
+ }
+
+ function verifyIntegrity() {
+ global $gBitSystem;
+ $ret = false;
+ if( $this->isValid() ) {
+ $sql = "SELECT
+ COUNT(*)
+ FROM `".BIT_DB_PREFIX."boards` b
+ INNER JOIN `".BIT_DB_PREFIX."boards_map` map ON (map.`board_content_id`= b.`content_id`)
+ WHERE b.`board_id`=? AND map.`board_content_id` = map.`topic_content_id`
+ ";
+ $count = $this->mDb->getOne( $sql, array( $this->mBitBoardId ));
+ return ($count==1);
+ }
+ return $ret;
+ }
+
+ function fixContentMap() {
+ if( $this->isValid() && @BitBase::verifyId($this->mContentId)) {
+ $this->removeContent($this->mContentId);
+ $this->addContent($this->mContentId);
+ }
+ }
+
+ function lookupMapRev($content_id) {
+ global $gBitDb;
+ $ret = NULL;
+ if (@BitBase::verifyId($content_id)) {
+ $sql = "SELECT `board_content_id` FROM `".BIT_DB_PREFIX."boards_map` map WHERE map.`topic_content_id`=?";
+ $ret = $gBitDb->getOne( $sql, array( $content_id ));
+ }
+ return $ret;
+ }
+
+ function getMap() {
+ global $gBitSystem;
+ $ret = NULL;
+ if( $this->isValid() ) {
+ $sql = "SELECT
+ lc.`title` AS t_title,
+ lc.`content_id` AS t_content_id,
+ lct.`content_name` AS t_content_name,
+ blc.`title` AS b_title,
+ blc.`content_id` AS b_content_id,
+ b.`board_id` AS b_board_id, (
+ SELECT count(*)
+ FROM `".BIT_DB_PREFIX."liberty_comments` lcom
+ WHERE lcom.`root_id`=lcom.`parent_id` AND lcom.`root_id`=lc.`content_id`
+ ) AS thread_count,
+ ((blc.`content_id`- lc.`content_id`)*(blc.`content_id`- lc.`content_id`)) AS order_key
+ FROM `".BIT_DB_PREFIX."boards` b
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` blc ON (blc.`content_id`=b.`content_id`)
+ INNER JOIN `".BIT_DB_PREFIX."boards_map` map ON (map.`board_content_id`= blc.`content_id`)
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON (lc.`content_id`=map.`topic_content_id`)
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content_types` lct ON (lc.`content_type_guid`=lct.`content_type_guid`)
+ WHERE b.`board_id`=? AND map.`board_content_id`!=map.`topic_content_id`
+ ORDER BY order_key
+ ";
+ $rs = $this->mDb->query( $sql, array( $this->mBitBoardId ));
+ while( $row = $rs->fetchRow() ) {
+ $ret[$row['t_content_id']] = $row;
+ }
+ }
+ return $ret;
+ }
+
+ public static function prepGetList( &$pParamHash ) {
+ if( empty( $pParamHash['sort_mode'] ) ) {
+ // default sort_mode for boards is alphabetical
+ $pParamHash['sort_mode'] = 'title_asc';
+ }
+ LibertyContent::prepGetList( $pParamHash );
+ }
+
+ /**
+ * This function generates a list of records from the liberty_content database for use in a list page
+ **/
+ function getList( &$pParamHash ) {
+ global $gBitSystem, $gBitUser;
+ // this makes sure parameters used later on are set
+ $this->prepGetList( $pParamHash );
+
+ $selectSql = $joinSql = $whereSql = '';
+ $bindVars = array();
+ array_push( $bindVars, $this->mContentTypeGuid );
+ $this->getServicesSql( 'content_list_sql_function', $selectSql, $joinSql, $whereSql, $bindVars );
+
+ // this will set $find, $sort_mode, $max_records and $offset
+ extract( $pParamHash );
+
+ if( is_array( $find ) ) {
+ // you can use an array of pages
+ $whereSql .= " AND lc.`title` IN( ".implode( ',',array_fill( 0,count( $find ),'?' ) )." )";
+ $bindVars = array_merge ( $bindVars, $find );
+ } elseif( is_string( $find ) ) {
+ // or a string
+ $whereSql .= " AND UPPER( lc.`title` )like ? ";
+ $bindVars[] = '%' . strtoupper( $find ). '%';
+ }
+
+ $pagination=true;
+ if (!empty($pParamHash['paginationOff'])) {
+ $pagination=false;
+ }
+
+ if (!empty($pParamHash['boards']) && is_array($pParamHash['boards'])) {
+ $whereSql .= " AND lc.`content_id` IN ( ".implode( ',',array_fill( 0,count( $pParamHash['boards'] ),'?' ) )." )";
+ $bindVars = array_merge ( $bindVars, $pParamHash['boards'] );
+ }
+ if (!empty($pParamHash['nboards']) && is_array($pParamHash['nboards'])) {
+ $whereSql .= " AND lc.`content_id` NOT IN ( ".implode( ',',array_fill( 0,count( $pParamHash['nboards'] ),'?' ) )." )";
+ $bindVars = array_merge ( $bindVars, $pParamHash['nboards'] );
+ }
+
+ $track = $gBitSystem->isFeatureActive('boards_thread_track');
+ $track = true;
+ if ($track) {
+ $selectSql .= ", (
+ SELECT COUNT(trk.`topic_id`)
+ FROM `".BIT_DB_PREFIX."boards_map` map
+ INNER JOIN `".BIT_DB_PREFIX."liberty_comments` lcom ON (map.`topic_content_id` = lcom.`root_id`)
+ INNER JOIN `".BIT_DB_PREFIX."boards_tracking` trk ON (trk.`topic_id` = lcom.`thread_forward_sequence`)
+ WHERE lcom.`root_id`=lcom.`parent_id` AND map.`board_content_id`=lc.`content_id` AND trk.`user_id`=".$gBitUser->mUserId."
+ ) AS track_count ";
+
+ }
+
+ if ($gBitSystem->isFeatureActive('boards_posts_anon_moderation') && !($gBitUser->hasPermission('p_boards_update') || $gBitUser->hasPermission('p_boards_post_update'))) {
+
+ }
+ if ($gBitSystem->isFeatureActive('boards_posts_anon_moderation') && ($gBitUser->hasPermission('p_boards_update') || $gBitUser->hasPermission('p_boards_post_update'))) {
+ $selectSql .= ", ( SELECT COUNT(*)
+ FROM `".BIT_DB_PREFIX."boards_map` map
+ INNER JOIN `".BIT_DB_PREFIX."liberty_comments` s_lcom ON (map.`topic_content_id` = s_lcom.`root_id`)
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` s_lc ON (s_lcom.`content_id` = s_lc.`content_id`)
+ LEFT JOIN `".BIT_DB_PREFIX."boards_posts` s ON( s_lcom.`comment_id` = s.`comment_id` )
+WHERE map.`board_content_id`=lc.`content_id` AND ((s_lc.`user_id` < 0) AND (s.`is_approved` = 0 OR s.`is_approved` IS NULL) )
+ ) AS unreg";
+ } else {
+ $selectSql .= ", 0 AS unreg";
+ }
+
+ // always show our own content
+ $whereSql .= " AND ( lc.`user_id`= ? ";
+ $bindVars[] = $gBitUser->mUserId;
+ if( !empty( $pParamHash['content_status_id'] ) ) {
+ // TODO needs safety checking! - spider
+ $whereSql .= " OR lc.`content_status_id` = ? ";
+ $bindVars[] = $pParamHash['content_status_id'];
+ } elseif( !empty( $pParamHash['min_content_status_id'] ) ) {
+ $whereSql .= " OR lc.`content_status_id` >= ? ";
+ $bindVars[] = $pParamHash['min_content_status_id'];
+ }
+ $whereSql .= " ) ";
+
+ $query = "SELECT ts.*, lc.`content_id`, lc.`title`, lc.`data`, lc.`format_guid`
+ $selectSql
+ FROM `".BIT_DB_PREFIX."boards` ts
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON( lc.`content_id` = ts.`content_id` ) $joinSql
+ WHERE lc.`content_type_guid` = ? $whereSql
+ ORDER BY ".$this->mDb->convertSortmode( $sort_mode );
+
+ $query_cant = "select count(*)
+ FROM `".BIT_DB_PREFIX."boards` ts INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON( lc.`content_id` = ts.`content_id` ) $joinSql
+ WHERE lc.`content_type_guid` = ? $whereSql";
+
+ $result = $this->mDb->query( $query, $bindVars );
+
+ $ret = array();
+ while( $res = $result->fetchRow() ) {
+ $res['url']= BOARDS_PKG_URL."index.php?b={$res['board_id']}";
+
+ $res['topic_count'] = $this->mDb->getOne( "SELECT count(*)
+ FROM `".BIT_DB_PREFIX."boards_map` map
+ INNER JOIN `".BIT_DB_PREFIX."liberty_comments` lcom ON (map.`topic_content_id` = lcom.`root_id`)
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` slc ON( slc.`content_id` = lcom.`content_id` )
+ LEFT JOIN `".BIT_DB_PREFIX."boards_posts` fp ON (fp.`comment_id` = lcom.`comment_id`)
+ WHERE lcom.`root_id`=lcom.`parent_id` AND map.`board_content_id`=? AND ((fp.`is_approved` = 1) OR (fp.`is_approved` IS NULL))", array( $res['content_id'] ) );
+
+ $res['post_count'] = $this->mDb->getOne( "SELECT count(*)
+ FROM `".BIT_DB_PREFIX."liberty_comments` lcom
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` slc ON( slc.`content_id` = lcom.`content_id` )
+ INNER JOIN `".BIT_DB_PREFIX."boards_map` map ON (lcom.`root_id`=map.`topic_content_id`)
+ LEFT JOIN `".BIT_DB_PREFIX."boards_posts` fp ON (fp.`comment_id` = lcom.`comment_id`)
+ WHERE map.`board_content_id`=? AND ((fp.`is_approved` = 1) OR (fp.`is_approved` IS NULL))", array( $res['content_id'] ) );
+ if($track) {
+ if ($gBitUser->isRegistered()) {
+ $res['track']['on'] = true;
+ $res['track']['count'] = $res['track_count'];
+ if ($res['post_count']>$res['track_count']) {
+ $res['track']['mod'] = true;
+ } else {
+ $res['track']['mod'] = false;
+ }
+ } else {
+ $res['track']['on'] = false;
+ }
+ unset($res['track_count']);
+ $res['parsed_data'] = LibertyContent::parseDataHash( $res );
+ $res['last'] = $this->getLastTopic($res);
+ }
+ $ret[] = $res;
+ }
+ $pParamHash["cant"] = $this->mDb->getOne( $query_cant, $bindVars );
+
+ // add all pagination info to pParamHash
+ LibertyContent::postGetList( $pParamHash );
+ return $ret;
+ }
+
+ function getLastTopic($data) {
+ global $gBitSystem;
+ $BIT_DB_PREFIX = BIT_DB_PREFIX;
+ $query="SELECT slc.`last_modified`, slc.`user_id`, lcom.`anon_name` AS l_anon_name, slc.`title`, lcom.comment_id AS topic_id
+ FROM `".BIT_DB_PREFIX."boards_map` map
+ INNER JOIN `".BIT_DB_PREFIX."liberty_comments` lcom ON (map.`topic_content_id` = lcom.`root_id`)
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` slc ON( slc.`content_id` = lcom.`content_id` )
+ LEFT JOIN `".BIT_DB_PREFIX."boards_posts` fp ON (fp.`comment_id` = lcom.`comment_id`)
+ WHERE lcom.`root_id`=lcom.`parent_id` AND map.`board_content_id`=? AND ((fp.`is_approved` IS NULL OR fp.`is_approved` = 1) OR (slc.`user_id` >= 0))
+ ORDER BY slc.`last_modified` DESC
+ ";
+ $result = $this->mDb->getRow( $query, array( $data['content_id'] ) );
+ if (!empty($result['topic_id'])) {
+ if (empty($result['l_anon_name'])) {
+ $result['l_anon_name'] = "Anonymous";
+ }
+ $result['topic_id']=intval($result['topic_id']);
+ $result['url'] = BitBoardTopic::getDisplayUrlFromHash( $result );
+ }
+ return $result;
+ }
+
+ /**
+ * Generates the URL to the bitboard page
+ * @return the link to display the page.
+ */
+ public static function getDisplayUrlFromHash( &$pParamHash ) {
+ global $gBitSystem;
+ $ret = NULL;
+
+ if( !empty( $pParamHash['comment'] ) && !empty( $pParamHash['comment']['thread_forward_sequence'] ) ){
+ // look up base of comment sequece which is BitBoardTopic
+ $seq = explode( ".", $pParamHash['comment']['thread_forward_sequence'] );
+ $topicRootId = (int)$seq[0];
+ if( BitBase::verifyId( $topicRootId )) {
+ require_once( BOARDS_PKG_CLASS_PATH.'BitBoardTopic.php' );
+ $hash = array( 'topic_id' => $topicRootId );
+ $ret = BitBoardTopic::getDisplayUrlFromHash( $hash );
+ // we're out of here with our topic url
+ return $ret;
+ }
+ }
+
+ if( BitBase::verifyId( $pParamHash['board_id'] )) {
+ if( $gBitSystem->isFeatureActive( 'pretty_urls' ) || $gBitSystem->isFeatureActive( 'pretty_urls_extended' ) ) {
+ $rewrite_tag = $gBitSystem->isFeatureActive( 'pretty_urls_extended' ) ? 'view/':'';
+ $ret = BOARDS_PKG_URL.$rewrite_tag.'board/'.$pParamHash['board_id'];
+ } else {
+ $ret = BOARDS_PKG_URL."index.php?b=".$pParamHash['board_id'];
+ }
+ } else {
+ $ret = parent::getDisplayUrlFromHash( $pParamHash );
+ }
+
+ return $ret;
+ }
+
+ function getBoardSelectList( $pBlankFirst=FALSE ) {
+ global $gBitSystem, $gBitUser;
+
+ // invoke list sql principly to enforce permission services
+ $selectSql = $joinSql = $whereSql = '';
+ $bindVars = array();
+
+ $this->getServicesSql( 'content_list_sql_function', $selectSql, $joinSql, $whereSql, $bindVars );
+
+ /* DEPRECATED - has some pointless stuff
+ $query = "SELECT lc.`content_id` as hash_key, lc.`title` AS `title`
+ FROM `".BIT_DB_PREFIX."boards` b
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON( lc.`content_id` = b.`content_id` )
+ LEFT JOIN `".BIT_DB_PREFIX."boards_map` bm ON( bm.`board_content_id`=b.`content_id` )
+ LEFT JOIN `".BIT_DB_PREFIX."liberty_comments` lcom ON (bm.`topic_content_id` = lcom.`root_id`)
+ GROUP BY lc.`content_id`, lc.`title`, lcom.`comment_id`
+ ORDER BY lc.`title` ASC";
+ */
+
+ // replacement query where we at least check that the board has been mapped to another board - a requirement for displaying comments
+ // if you hate it fix it or lets chat -wjames5
+ $query = "SELECT lc.`content_id` as hash_key, lc.`title` AS `title`
+ FROM `".BIT_DB_PREFIX."boards` b
+ INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON( lc.`content_id` = b.`content_id` )
+ INNER JOIN `".BIT_DB_PREFIX."boards_map` bm ON( bm.`topic_content_id`=b.`content_id` )
+ $joinSql
+ WHERE lc.`content_id` = b.`content_id` $whereSql
+ ORDER BY lc.`title` ASC";
+
+ $ret = array();
+
+ if( $rslt = $this->mDb->query( $query, $bindVars ) ){
+ if( $pBlankFirst ) {
+ $ret[''] = '---------';
+ }
+ while( $row = $rslt->fetchRow() ) {
+ $ret[$row['hash_key']] = $row['title'];
+ }
+ }
+
+ return $ret;
+ }
+
+ function getBoard( $contentId ) {
+ global $gBitDb;
+ global $gBitUser;
+ //var_dump($GLOBALS);
+ if( LibertyContent::verifyId( $contentId ) ) {
+ // LibertyContent::load()assumes you have joined already, and will not execute any sql!
+ // This is a significant performance optimization
+ $bindVars = array();
+ $selectSql = $joinSql = $whereSql = '';
+ array_push( $bindVars, $contentId );
+ $gBitUser->getServicesSql( 'content_load_sql_function', $selectSql, $joinSql, $whereSql, $bindVars );
+
+ $query = "SELECT lc.*, uue.`login` AS modifier_user, uue.`real_name` AS modifier_real_name, uuc.`login` AS creator_user, uuc.`real_name` AS creator_real_name $selectSql
+ FROM `".BIT_DB_PREFIX."liberty_content` lc $joinSql
+ LEFT JOIN `".BIT_DB_PREFIX."users_users` uue ON( uue.`user_id` = lc.`modifier_user_id` )
+ LEFT JOIN `".BIT_DB_PREFIX."users_users` uuc ON( uuc.`user_id` = lc.`user_id` )
+ WHERE lc.`content_id`=? $whereSql";
+ $result = $gBitDb->query( $query, $bindVars );
+
+ $ret = array();
+ if( $result && $result->numRows() ) {
+ $ret = $result->fields;
+
+ $ret['creator'] =( isset( $result->fields['creator_real_name'] )? $result->fields['creator_real_name'] : $result->fields['creator_user'] );
+ $ret['editor'] =( isset( $result->fields['modifier_real_name'] )? $result->fields['modifier_real_name'] : $result->fields['modifier_user'] );
+ $ret['display_url'] = BIT_ROOT_URL."index.php?content_id=$contentId";
+ }
+ }
+ return( $ret );
+ }
+
+ public static function getLinkedBoard( $pContentId ) {
+ global $gBitDb;
+ $ret = NULL;
+ if( BitBase::verifyId( $pContentId ) ) {
+ $sql = "SELECT b.`board_id`, b.`content_id` AS `board_content_id`, COUNT(lcom.`comment_id`) AS `post_count`
+ FROM `".BIT_DB_PREFIX."boards_map` bm
+ INNER JOIN `".BIT_DB_PREFIX."boards` b ON (bm.`board_content_id`=b.`content_id`)
+ LEFT JOIN `".BIT_DB_PREFIX."liberty_comments` lcom ON (lcom.`root_id`=bm.`topic_content_id`)
+ WHERE bm.`topic_content_id`=?
+ GROUP BY b.`board_id`, b.`content_id`";
+ $ret = $gBitDb->getRow( $sql, array( $pContentId ) );
+ }
+ return $ret;
+ }
+
+
+ // =-=-=-=-=-=-=-=-=-=-=-=-=-= Board Sync Methods =-=-=-=-=-=-=-=-=-=-=-=-=-=
+ function getBoardSyncInbox() {
+ global $gBitSystem;
+ $ret = '';
+ if( $gBitSystem->getConfig('boards_sync_user') ) {
+ $ret = $gBitSystem->getConfig('boards_sync_user').'@'.$gBitSystem->getConfig('boards_sync_mail_server');
+ }
+ return $ret;
+ }
+
+ function getBoardMailingList() {
+ global $gBitSystem;
+ $ret = NULL;
+ if( $this->isValid() && $gBitSystem->getConfig( 'boards_sync_mail_server' ) && $this->getPreference( 'boards_mailing_list' ) ) {
+ $ret = $this->getPreference( 'boards_mailing_list' ).'@'.$gBitSystem->getConfig( 'boards_email_host', $gBitSystem->getConfig( 'kernel_server_name' ) );
+ }
+ return $ret;
+ }
+}
+
+function boards_content_display ( $pContent ) {
+ global $gBitSmarty;
+ if( $pContent->isValid() && $pContent->getField('content_type_guid') != 'bitboard' ) {
+ $gBitSmarty->assign( 'boardInfo', BitBoard::getLinkedBoard( $pContent->mContentId ) );
+ }
+}
+
+function boards_content_edit ( $pContent, $pParamHash ) {
+ global $gBitSmarty;
+ // topic service
+ if( !$pContent->isContentType( BITBOARDTOPIC_CONTENT_TYPE_GUID ) ) {
+ if( $pContent->isValid() ) {
+ $gBitSmarty->assign( 'boardInfo', BitBoard::getLinkedBoard( $pContent->mContentId ) );
+ } else {
+ $boardInfo['board_content_id'] = $pParamHash['linked_board_cid'];
+ $gBitSmarty->assign( 'boardInfo', $boardInfo );
+ }
+ require_once( BOARDS_PKG_CLASS_PATH.'BitBoard.php' );
+ $board = new BitBoard();
+ $boardList = $board->getBoardSelectList( TRUE );
+ $gBitSmarty->assign( 'boardList', $boardList );
+ }
+}
+
+// store services for boads
+function boards_content_store( $pContent, $pParamHash ) {
+ global $gBitDb, $gBitSmarty, $gBitSystem;
+
+ require_once( BOARDS_PKG_CLASS_PATH.'BitBoardTopic.php' );
+ // do not allow unassigning topics. the UI should prevent this, but just to make sure...
+ if( $pContent->isValid() && !$pContent->isContentType( BITBOARDTOPIC_CONTENT_TYPE_GUID ) && !$pContent->isContentType( BITBOARD_CONTENT_TYPE_GUID ) ) {
+ // wipe out all previous assignments for good measure. Not the sanest thing to do, but edits are infrequent - at least for now
+ if ($gBitSystem->isFeatureActive('boards_link_by_pigeonholes') && $gBitSystem->isPackageActive('pigeonholes')) {
+ // Delete all old mappings
+ $pContent->mDb->query( "DELETE FROM `".BIT_DB_PREFIX."boards_map` WHERE `topic_content_id`=?", array( $pContent->mContentId ) );
+
+ // Get the pigeonholes this content is in
+ $p = null;
+ if ( ! empty( $pParamHash['pigoneholes'] ) ) {
+ foreach( $pParamHash['pigeonholes']['pigeonhole'] as $p_id ) {
+ require_once(PIGEONHOLES_PKG_PATH.'Pigeonholes.php');
+ if (empty($p)) {
+ $p = new Pigeonholes();
+ }
+
+ // What boards are in the same pigeonhole?
+ $params =
+ array('content_type_guid' => BITBOARD_CONTENT_TYPE_GUID,
+ 'content_id' => $p_id );
+ $boards = $p->getMemberList( $params );
+
+ // Insert into these boards
+ foreach ($boards as $board) {
+ if( @BitBase::verifyId( $board['content_id'] ) ) {
+ $pContent->mDb->query( "INSERT INTO `".BIT_DB_PREFIX."boards_map` (`board_content_id`,`topic_content_id`) VALUES (?,?)", array( $board['content_id'], $pContent->mContentId ) );
+ }
+ }
+ }
+ }
+ }
+ else {
+ $pContent->mDb->query( "DELETE FROM `".BIT_DB_PREFIX."boards_map` WHERE `topic_content_id`=?", array( $pContent->mContentId ) );
+ if( @BitBase::verifyId( $pParamHash['linked_board_cid'] ) ) {
+ $pContent->mDb->query( "INSERT INTO `".BIT_DB_PREFIX."boards_map` (`board_content_id`,`topic_content_id`) VALUES (?,?)", array( $pParamHash['linked_board_cid'], $pContent->mContentId ) );
+ }
+ }
+ $gBitSmarty->assign( 'boardInfo', BitBoard::getLinkedBoard( $pContent->mContentId ) );
+ } else {
+ if( @BitBase::verifyId( $pParamHash['content_id'] ) && @BitBase::verifyId( $pParamHash['linked_board_cid'] ) ) {
+ $pContent->mDb->query( "INSERT INTO `".BIT_DB_PREFIX."boards_map` (`board_content_id`,`topic_content_id`) VALUES (?,?)", array( $pParamHash['linked_board_cid'], $pParamHash['content_id'] ) );
+ }
+ }
+}
+
+// store services for topics and posts
+function boards_comment_store( &$pObject, &$pParamHash ) {
+ global $gBitSystem;
+ // board posts ( e.g. liberty comments ) service
+ // @TODO check that root object is a board -- otherwise all comments get fired
+ // @TODO probably should migrate sendNotification to Switchboard
+
+ if( $gBitSystem->isPackageActive( 'boards' ) && $pObject->isContentType( BITCOMMENT_CONTENT_TYPE_GUID ) && $gBitSystem->isFeatureActive( 'boards_thread_notification' )) {
+ if( isset( $pObject->mInfo['thread_forward_sequence'] ) ){
+ $topic_id = substr( $pObject->mInfo['thread_forward_sequence'], 0, 10 );
+ $data = BitBoardTopic::getNotificationData($topic_id);
+ foreach( $data['users'] as $login => $user ) {
+ if( $data['topic']->mInfo['llc_last_modified'] > $user['track_date'] && $data['topic']->mInfo['llc_last_modified'] > $user['track_notify_date'] ) {
+ $data['topic']->sendNotification( $user );
+ }
+ }
+ }
+ }
+}
+
+function boards_content_verify( &$pObject, &$pParamHash ){
+ // board posts ( e.g. liberty comments ) service
+ global $gBitSystem, $gBitUser;
+ // use is_a instead of isContentType( BITCOMMENT_CONTENT_TYPE_GUID ) as isContentType() checks isValid(), and this service method will not properly handle new object stores
+ if( $gBitSystem->isPackageActive( 'boards' ) && is_a( $pObject , 'LibertyComment' ) ) {
+ if( BitBoardTopic::isLockedMsg( $pParamHash['parent_id'] )) {
+ $pObject->mErrors['warning']=tra("The selected Topic is Locked posting is disabled");
+ }
+ }
+}
+
+function boards_content_expunge( $pContent ) {
+ global $gBitSmarty;
+ if( $pContent->isValid() ) {
+ $pContent->mDb->query( "DELETE FROM `".BIT_DB_PREFIX."boards_map` WHERE `topic_content_id`=?", array( $pContent->mContentId ) );
+ }
+}
+
+?>