Source for file BitBoard.php
Documentation is available at BitBoard.php
* 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>
require_once( LIBERTY_PKG_PATH. 'LibertyMime.php' );
* This is used to uniquely identify the object
define( 'BITBOARD_CONTENT_TYPE_GUID', 'bitboard' );
* Primary key for our mythical BitBoard class object & table
* During initialisation, be sure to call our base constructors
function BitBoard( $pBitBoardId= NULL, $pContentId= NULL ) {
'content_name' => 'Message Board',
'handler_class' => 'BitBoard',
'handler_package' => 'boards',
'handler_file' => 'BitBoard.php',
'maintainer_url' => 'http://www.bitweaver.org'
* 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 ) {
// LibertyContent::load()assumes you have joined already, and will not execute any sql!
// This is a significant performance optimization
$selectSql = $joinSql = $whereSql = '';
$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 " .
"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->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'] );
if( BitBase::verifyId( $pMigrateBoardId ) ) {
$ret = $gBitDb->getOne( "SELECT `board_id` FROM `". BIT_DB_PREFIX. "boards` bb WHERE `migrate_board_id`=?", array( $pMigrateBoardId ) );
* 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
function store( &$pParamHash ) {
$this->mDb->StartTrans();
$locId = array( "board_id" => $pParamHash['board_id'] );
$result = $this->mDb->associateUpdate( $table, $pParamHash['board_store'], $locId );
$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'];
$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;
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'] );
mailman_addmember( $this->getPreference( 'boards_mailing_list'), $gBitUser->getField('email') );
// If we have an inbox then subscribe it as a moderator
$this->mErrors['mailing_list'] = $error;
$this->mDb->CompleteTrans();
$this->mDb->RollbackTrans();
* 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
function verify( &$pParamHash ) {
// make sure we're all loaded up of we have a mBitBoardId
$pParamHash['content_id'] = $this->mInfo['content_id'];
// It is possible a derived class set this to something different
if( empty( $pParamHash['content_type_guid'] ) ) {
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'] );
$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( $pParamHash['title'] ) ) {
$this->mErrors['title'] = 'You must enter a name for this page.';
$pParamHash['content_store']['title'] = substr( $pParamHash['title'], 0, 160 );
$pParamHash['content_store']['title'] = ( isset ( $pParamHash['title'] ) )? substr( $pParamHash['title'], 0, 160 ): '';
} else if( empty( $pParamHash['title'] ) ) {
$this->mErrors['title'] = 'You must specify a name';
* Prepare data for preview
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 function removes a bitboard entry
$this->mDb->StartTrans();
$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( $error = mailman_rmlist( $mailingList ) ) {
$this->mErrors['mailing_list'] = $error;
$this->mDb->CompleteTrans();
$this->mDb->RollbackTrans();
* Make sure bitboard is loaded and valid
$l = $b->getList($listHash);
foreach ($l as $k => $boardd) {
$board = new BitBoard($boardd['board_id']);
$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;
WHERE lcom.`root_id`=lcom.`parent_id` AND lcom.`root_id`=lc.`content_id`
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
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'
ORDER BY lc.`content_type_guid`, lc.`title`
$rs = $this->mDb->query( $sql );
while( $row = $rs->fetchRow() ) {
$ret[$row['content_id']] = $row;
if (@BitBase::verifyId($content_id)) {
'topic_content_id'=> $content_id,
$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 ) );
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`
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 ));
lc.`content_id` AS t_content_id,
lct.`content_name` AS t_content_name,
blc.`content_id` AS b_content_id,
b.`board_id` AS b_board_id, (
WHERE lcom.`root_id`=lcom.`parent_id` AND lcom.`root_id`=lc.`content_id`
((blc.`content_id`- lc.`content_id`)*(blc.`content_id`- lc.`content_id`)) AS order_key
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`
while( $row = $rs->fetchRow() ) {
$ret[$row['t_content_id']] = $row;
if( empty( $pParamHash['sort_mode'] ) ) {
// default sort_mode for boards is alphabetical
$pParamHash['sort_mode'] = 'title_asc';
* This function generates a list of records from the liberty_content database for use in a list page
global $gBitSystem, $gBitUser;
// this makes sure parameters used later on are set
$selectSql = $joinSql = $whereSql = '';
$this->getServicesSql( 'content_list_sql_function', $selectSql, $joinSql, $whereSql, $bindVars );
// this will set $find, $sort_mode, $max_records and $offset
// you can use an array of pages
$whereSql .= " AND UPPER( lc.`title` )like ? ";
if (!empty($pParamHash['paginationOff'])) {
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');
SELECT COUNT(trk.`topic_id`)
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. "
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(*)
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) )
$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'];
$query = "SELECT ts.*, lc.`content_id`, lc.`title`, lc.`data`, lc.`format_guid`
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 );
while( $res = $result->fetchRow() ) {
$res['url']= BOARDS_PKG_URL. "index.php?b={$res['board_id']}";
$res['topic_count'] = $this->mDb->getOne( "SELECT count(*)
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(*)
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 ($gBitUser->isRegistered()) {
$res['track']['on'] = true;
$res['track']['count'] = $res['track_count'];
if ($res['post_count']> $res['track_count']) {
$res['track']['mod'] = true;
$res['track']['mod'] = false;
$res['track']['on'] = false;
unset ($res['track_count']);
$pParamHash["cant"] = $this->mDb->getOne( $query_cant, $bindVars );
// add all pagination info to pParamHash
$query= "SELECT slc.`last_modified`, slc.`user_id`, lcom.`anon_name` AS l_anon_name, slc.`title`, lcom.comment_id AS topic_id
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']);
* Generates the URL to the bitboard page
* @return the link to display the page.
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_PATH. 'BitBoardTopic.php' );
$hash = array( 'topic_id' => $topicRootId );
// we're out of here with our topic url
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'];
$ret = BOARDS_PKG_URL. "index.php?b=". $pParamHash['board_id'];
$ret = parent::getDisplayUrlFromHash( $pParamHash );
global $gBitSystem, $gBitUser;
// invoke list sql principly to enforce permission services
$selectSql = $joinSql = $whereSql = '';
$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`
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` )
WHERE lc.`content_id` = b.`content_id` $whereSql
ORDER BY lc.`title` ASC";
if( $rslt = $this->mDb->query( $query, $bindVars ) ){
while( $row = $rslt->fetchRow() ) {
$ret[$row['hash_key']] = $row['title'];
// LibertyContent::load()assumes you have joined already, and will not execute any sql!
// This is a significant performance optimization
$selectSql = $joinSql = $whereSql = '';
$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
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 );
if( $result && $result->numRows() ) {
$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";
if( BitBase::verifyId( $pContentId ) ) {
$sql = "SELECT b.`board_id`, b.`content_id` AS `board_content_id`, COUNT(lcom.`comment_id`) AS `post_count`
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 ) );
// =-=-=-=-=-=-=-=-=-=-=-=-=-= Board Sync Methods =-=-=-=-=-=-=-=-=-=-=-=-=-=
if( $gBitSystem->getConfig('boards_sync_user') ) {
$ret = $gBitSystem->getConfig('boards_sync_user'). '@'. $gBitSystem->getConfig('boards_sync_mail_server');
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' ) );
if( $pContent->isValid() && $pContent->getField('content_type_guid') != 'bitboard' ) {
$boardInfo['board_content_id'] = $pParamHash['linked_board_cid'];
$gBitSmarty->assign( 'boardInfo', $boardInfo );
require_once( BOARDS_PKG_PATH. 'BitBoard.php' );
$gBitSmarty->assign( 'boardList', $boardList );
// store services for boads
global $gBitDb, $gBitSmarty, $gBitSystem;
require_once( BOARDS_PKG_PATH. 'BitBoardTopic.php' );
// do not allow unassigning topics. the UI should prevent this, but just to make sure...
// 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
// Get the pigeonholes this content is in
if ( ! empty( $pParamHash['pigoneholes'] ) ) {
foreach( $pParamHash['pigeonholes']['pigeonhole'] as $p_id ) {
require_once(PIGEONHOLES_PKG_PATH. 'Pigeonholes.php');
// What boards are in the same pigeonhole?
$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 ) );
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 ) );
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
// 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( isset ( $pObject->mInfo['thread_forward_sequence'] ) ){
$topic_id = substr( $pObject->mInfo['thread_forward_sequence'], 0, 10 );
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'] ) {
// 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' ) ) {
$pObject->mErrors['warning']= tra("The selected Topic is Locked posting is disabled");
|