612 lines
16 KiB
PHP
612 lines
16 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Invision Power Services
|
|
* IP.Board v3.0.5
|
|
* Threaded mode functions
|
|
* Last Updated: $Date: 2009-03-30 11:13:39 -0400 (Mon, 30 Mar 2009) $
|
|
*
|
|
* @author $Author: bfarber $
|
|
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
|
|
* @license http://www.iinvisionpower.com/community/board/license.html
|
|
* @package Invision Power Board
|
|
* @subpackage Forums
|
|
* @link http://www.iinvisionpower.com
|
|
* @version $Revision: 4354 $
|
|
*
|
|
*/
|
|
|
|
if ( ! defined( 'IN_IPB' ) )
|
|
{
|
|
print "<h1>Incorrect access</h1>You cannot access this file directly.";
|
|
exit();
|
|
}
|
|
|
|
class threadedModeLibrary
|
|
{
|
|
/**
|
|
* Topics library
|
|
*
|
|
* @access public
|
|
* @var object
|
|
*/
|
|
public $topics;
|
|
|
|
/**
|
|
* Structured post ids
|
|
*
|
|
* @access public
|
|
* @var array
|
|
*/
|
|
public $structured_pids = array();
|
|
|
|
/**
|
|
* Post cache
|
|
*
|
|
* @access public
|
|
* @var array
|
|
*/
|
|
public $post_cache = array();
|
|
|
|
/**
|
|
* Used post ids
|
|
*
|
|
* @access public
|
|
* @var array
|
|
*/
|
|
public $used_post_ids = array();
|
|
|
|
/**
|
|
* Threaded posts
|
|
*
|
|
* @access public
|
|
* @var array
|
|
*/
|
|
public $_threaded_posts = array();
|
|
|
|
/**
|
|
* Last id we've seen
|
|
*
|
|
* @access public
|
|
* @var int
|
|
*/
|
|
public $last_id = 0;
|
|
|
|
/**#@+
|
|
* Registry Object Shortcuts
|
|
*
|
|
* @access protected
|
|
* @var object
|
|
*/
|
|
protected $registry;
|
|
protected $DB;
|
|
protected $settings;
|
|
protected $request;
|
|
protected $lang;
|
|
protected $member;
|
|
protected $cache;
|
|
/**#@-*/
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @access public
|
|
* @param object Registry reference
|
|
* @param object Reference to topics lib
|
|
* @return void
|
|
*/
|
|
public function __construct( ipsRegistry $registry, $topics )
|
|
{
|
|
/* Make objects */
|
|
$this->registry = $registry;
|
|
$this->DB = $this->registry->DB();
|
|
$this->settings =& $this->registry->fetchSettings();
|
|
$this->request =& $this->registry->fetchRequest();
|
|
$this->lang = $this->registry->getClass('class_localization');
|
|
$this->member = $this->registry->member();
|
|
$this->memberData =& $this->registry->member()->fetchMemberData();
|
|
$this->cache = $this->registry->cache();
|
|
$this->caches =& $this->registry->cache()->fetchCaches();
|
|
|
|
$this->topics =& $topics;
|
|
}
|
|
|
|
/**
|
|
* Get Threaded Topic Data
|
|
*
|
|
* @access public
|
|
* @return array
|
|
**/
|
|
public function _getTopicDataThreaded()
|
|
{
|
|
//-----------------------------------------
|
|
// Grab the posts we'll need
|
|
//-----------------------------------------
|
|
|
|
$pc_join = array();
|
|
|
|
$first = intval( $this->request['start'] );
|
|
$last = $this->settings['threaded_per_page'] ? $this->settings['threaded_per_page'] : 250;
|
|
|
|
//-----------------------------------------
|
|
// GET meh pids
|
|
//-----------------------------------------
|
|
|
|
if ( $first > 0 )
|
|
{
|
|
// we're on a page, make sure init val is there
|
|
|
|
$this->topics->pids[0] = $this->topics->topic['topic_firstpost'];
|
|
$this->structured_pids[ 0 ][] = $this->topics->topic['topic_firstpost'];
|
|
}
|
|
|
|
$this->DB->build( array(
|
|
'select' => 'pid, post_parent',
|
|
'from' => 'posts',
|
|
'where' => 'topic_id=' . $this->topics->topic['tid'] . ' and queued != 1',
|
|
'order' => 'pid',
|
|
'limit' => array( $first, $last )
|
|
) );
|
|
|
|
$this->DB->execute();
|
|
|
|
while( $p = $this->DB->fetch() )
|
|
{
|
|
$this->topics->pids[] = $p['pid'];
|
|
|
|
// Force to be children of 'root' post
|
|
|
|
if ( ! $p['post_parent'] and $p['pid'] != $this->topics->topic['topic_firstpost'] )
|
|
{
|
|
$p['post_parent'] = $this->topics->topic['topic_firstpost'];
|
|
}
|
|
|
|
$this->structured_pids[ $p['post_parent'] ][] = $p['pid'];
|
|
}
|
|
|
|
/* Ignored Users */
|
|
$ignored_users = array();
|
|
|
|
foreach( $this->member->ignored_users as $_i )
|
|
{
|
|
if( $_i['ignore_topics'] )
|
|
{
|
|
$ignored_users[] = $_i['ignore_ignore_id'];
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Get post bodah
|
|
//-----------------------------------------
|
|
|
|
if ( count( $this->topics->pids ) )
|
|
{
|
|
$this->DB->build( array(
|
|
'select' => 'pid, post, author_id, author_name, post_date, post_title, post_parent, topic_id, icon_id',
|
|
'from' => 'posts',
|
|
'where' => 'pid IN(' . implode( ',', $this->topics->pids ) . ')',
|
|
'order' => 'pid',
|
|
) );
|
|
|
|
$this->DB->execute();
|
|
|
|
while( $p = $this->DB->fetch() )
|
|
{
|
|
if ( ! $p['post_parent'] and $p['pid'] != $this->topics->topic['topic_firstpost'] )
|
|
{
|
|
$p['post_parent'] = $this->topics->topic['topic_firstpost'];
|
|
}
|
|
|
|
$this->post_cache[ $p['pid'] ] = $p;
|
|
|
|
$this->last_id = $p['pid'];
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Force root in cache
|
|
//-----------------------------------------
|
|
|
|
$this->post_cache[0] = array( 'id' => 1 );
|
|
|
|
$this->post_cache[ $this->topics->topic['topic_firstpost'] ]['post_title'] = $this->topics->topic['title'];
|
|
|
|
//-----------------------------------------
|
|
// Are we viewing Posts?
|
|
//-----------------------------------------
|
|
|
|
$post_id = intval( $this->request['pid'] );
|
|
|
|
if ( $post_id && ! in_array( $post_id, $this->topics->pids ) )
|
|
{
|
|
$this->registry->output->showError( 'topics_post_not_in_topic', 10358, true );
|
|
}
|
|
|
|
$postid_array = array( 1 => $post_id );
|
|
|
|
if ( $post_id and $post_id != $this->topics->topic['topic_firstpost'] )
|
|
{
|
|
$parents = $this->_threadedPostGetParents( $post_id );
|
|
|
|
if ( count($parents) )
|
|
{
|
|
foreach( $parents as $pid )
|
|
{
|
|
if ( $pid != $this->topics->topic['topic_firstpost'] )
|
|
{
|
|
$postid_array[] = $pid;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Join Queries */
|
|
$_post_joins = array(
|
|
array(
|
|
'select' => 'm.member_id as mid,m.name,m.member_group_id,m.email,m.joined,m.posts, m.last_visit, m.last_activity,m.login_anonymous,m.title,m.hide_email, m.warn_level, m.warn_lastwarn, m.members_display_name, m.members_seo_name, m.has_gallery, m.has_blog, m.members_bitoptions',
|
|
'from' => array( 'members' => 'm' ),
|
|
'where' => 'm.member_id=p.author_id',
|
|
'type' => 'left'
|
|
),
|
|
array(
|
|
'select' => 'pp.*',
|
|
'from' => array( 'profile_portal' => 'pp' ),
|
|
'where' => 'm.member_id=pp.pp_member_id',
|
|
'type' => 'left'
|
|
)
|
|
);
|
|
|
|
|
|
/* Reputation system enabled? */
|
|
if( $this->settings['reputation_enabled'] )
|
|
{
|
|
/* Add the join to figure out if the user has already rated the post */
|
|
$_post_joins[] = $this->registry->repCache->getUserHasRatedJoin( 'pid', 'p.pid', 'forums' );
|
|
|
|
/* Add the join to figure out the total ratings for each post */
|
|
if( $this->settings['reputation_show_content'] )
|
|
{
|
|
$_post_joins[] = $this->registry->repCache->getTotalRatingJoin( 'pid', 'p.pid', 'forums' );
|
|
}
|
|
}
|
|
|
|
/* Cache? */
|
|
if ( IPSContentCache::isEnabled() )
|
|
{
|
|
if ( IPSContentCache::fetchSettingValue('post') )
|
|
{
|
|
$_post_joins[] = IPSContentCache::join( 'post', 'p.pid' );
|
|
}
|
|
|
|
if ( IPSContentCache::fetchSettingValue('sig') )
|
|
{
|
|
$_post_joins[] = IPSContentCache::join( 'sig' , 'm.member_id', 'ccb', 'left', 'ccb.cache_content as cache_content_sig, ccb.cache_updated as cache_updated_sig' );
|
|
}
|
|
}
|
|
|
|
if( $this->settings['custom_profile_topic'] == 1 )
|
|
{
|
|
$_post_joins[] = array(
|
|
'select' => 'pc.*',
|
|
'from' => array( 'pfields_content' => 'pc' ),
|
|
'where' => 'pc.member_id=p.author_id',
|
|
'type' => 'left'
|
|
);
|
|
}
|
|
|
|
if( count( $postid_array ) )
|
|
{
|
|
//-----------------------------------------
|
|
// Get root post and children of clicked
|
|
//-----------------------------------------
|
|
|
|
$this->used_post_ids = ',' . implode( ",", $postid_array ) . ',';
|
|
|
|
$postid_array[0] = $this->topics->topic['topic_firstpost'];
|
|
|
|
$this->DB->build( array(
|
|
'select' => 'p.*',
|
|
'from' => array( 'posts' => 'p' ),
|
|
'where' => "p.pid IN(" . implode( ',', $postid_array ) . ")",
|
|
'order' => 'pid asc',
|
|
'add_join' => $_post_joins
|
|
) );
|
|
}
|
|
else
|
|
{
|
|
//-----------------------------------------
|
|
// Just get root
|
|
//-----------------------------------------
|
|
|
|
$this->DB->build( array(
|
|
'select' => 'p.*',
|
|
'from' => array( 'posts' => 'p' ),
|
|
'where' => "p.pid=" . $this->topics->topic['topic_firstpost'],
|
|
'order' => 'pid asc',
|
|
'add_join' => $_post_joins
|
|
) );
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Attachment PIDS
|
|
//-----------------------------------------
|
|
|
|
$this->topics->attach_pids = $postid_array;
|
|
|
|
//-----------------------------------------
|
|
// Render the original post
|
|
//-----------------------------------------
|
|
|
|
$outer = $this->DB->execute();
|
|
|
|
//-----------------------------------------
|
|
// Format and print out the topic list
|
|
//-----------------------------------------
|
|
|
|
$post_data = array();
|
|
$num_rows = $this->DB->getTotalRows( $outer );
|
|
|
|
while ( $row = $this->DB->fetch( $outer ) )
|
|
{
|
|
$return = $this->topics->parsePostRow( $row );
|
|
|
|
$poster = $return['poster'];
|
|
$row = $return['row'];
|
|
|
|
/* Reputation */
|
|
if( $this->settings['reputation_enabled'] )
|
|
{
|
|
$row['pp_reputation_points'] = $row['pp_reputation_points'] ? $row['pp_reputation_points'] : 0;
|
|
$row['has_given_rep'] = $row['has_given_rep'] ? $row['has_given_rep'] : 0;
|
|
$row['rep_points'] = $row['rep_points'] ? $row['rep_points'] : 0;
|
|
}
|
|
|
|
$post_data[ $row['pid'] ] = array( 'post' => $row, 'author' => $poster );
|
|
|
|
//-----------------------------------------
|
|
// Are we giving this bloke a good ignoring?
|
|
//-----------------------------------------
|
|
if( isset( $ignored_users ) && is_array( $ignored_users ) && count( $ignored_users ) )
|
|
{
|
|
if( in_array( $poster['member_id'], $ignored_users ) )
|
|
{
|
|
if ( ! strstr( $this->settings['cannot_ignore_groups'], ','.$poster['member_group_id'].',' ) )
|
|
{
|
|
$post_data[ $row['pid'] ]['post']['_ignored'] = 1;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ! $this->printed and $num_rows > 1 )
|
|
{
|
|
$post_data[ $row['pid'] ]['post']['_end_first_post'] = 1;
|
|
$this->printed = 1;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Sort out pagination
|
|
//-----------------------------------------
|
|
|
|
$total_replies = $this->topics->topic['posts'];
|
|
$show_replies = count( $this->structured_pids ) - 1;
|
|
|
|
$this->topics->topic['SHOW_PAGES'] = '';
|
|
$this->topics->topic['threaded_pages'] = $this->registry->output->generatePagination( array(
|
|
'totalItems' => $total_replies,
|
|
'itemsPerPage' => $last,
|
|
'currentStartValue' => $this->request['start'],
|
|
'baseUrl' => "showtopic=" . $this->topics->topic['tid'],
|
|
'startValueKey' => 'start'
|
|
) );
|
|
|
|
//-----------------------------------------
|
|
// START GETTING THE OUTLINE LIST
|
|
//-----------------------------------------
|
|
|
|
$this->_threaded_posts[ 0 ]['child'] = $this->_threadedLoopGetChildren();
|
|
$this->topics->topic['_threaded_posts'] = $this->_buildThreadedOutput( $this->_threaded_posts[ 0 ] );
|
|
|
|
return $post_data;
|
|
}
|
|
|
|
/**
|
|
* Actually builds the HTML for threaded view
|
|
*
|
|
* @access public
|
|
* @param array $root The root we're iterating
|
|
* @param string $html The current HTML in this loop
|
|
* @return string HTML
|
|
*/
|
|
public function _buildThreadedOutput( $root, $html='' )
|
|
{
|
|
$child = '';
|
|
|
|
if( is_array( $root['child'] ) )
|
|
{
|
|
if( count( $root['child'] ) )
|
|
{
|
|
foreach( $root['child'] as $pid => $post )
|
|
{
|
|
$child .= $this->_buildThreadedOutput( $post );
|
|
}
|
|
}
|
|
}
|
|
|
|
$html .= $this->registry->output->getTemplate('topic')->build_threaded( $root, $child );
|
|
|
|
return $html;
|
|
}
|
|
|
|
/**
|
|
* Render kiddies
|
|
*
|
|
* @access public
|
|
* @param integer $root_id
|
|
* @param array $posts
|
|
* @param integer $dguide
|
|
* @return array
|
|
**/
|
|
public function _threadedLoopGetChildren($root_id=0, $posts=array() ,$dguide=-1)
|
|
{
|
|
$dguide++;
|
|
|
|
if ( isset( $this->structured_pids[ $root_id ] ) && is_array( $this->structured_pids[ $root_id ] ) )
|
|
{
|
|
if ( count( $this->structured_pids[ $root_id ] ) )
|
|
{
|
|
foreach( $this->structured_pids[ $root_id ] as $pid )
|
|
{
|
|
$posts[ $pid ] = $this->_threadedRenderListRow( $this->post_cache[ $pid ], $dguide );
|
|
$posts[$pid]['child'] = $this->_threadedLoopGetChildren( $pid, isset( $posts[ $root_id ] ) ? $posts[ $root_id ] : array(), $dguide );
|
|
}
|
|
}
|
|
}
|
|
|
|
return $posts;
|
|
}
|
|
|
|
/**
|
|
* Builds an array of output for used in threaded view
|
|
*
|
|
* @access public
|
|
* @param array $post
|
|
* @param integer $depth
|
|
* @return array
|
|
**/
|
|
public function _threadedRenderListRow( $post, $depth )
|
|
{
|
|
$post['depthguide'] = "";
|
|
|
|
$this->settings[ 'post_showtext_notitle'] = 1 ;
|
|
|
|
for( $i = 1 ; $i < $depth; $i++ )
|
|
{
|
|
$post['depthguide'] .= $this->depth_guide[ $i ];
|
|
}
|
|
|
|
// Last child?
|
|
|
|
if ( $depth > 0 )
|
|
{
|
|
$last_id = count($this->structured_pids[ $post['post_parent'] ]) - 1;
|
|
|
|
if ( $this->structured_pids[ $post['post_parent'] ][$last_id] == $post['pid'] )
|
|
{
|
|
$this->depth_guide[ $depth ] = '<img src="'.$this->settings['img_url'].'/spacer.gif" alt="" width="20" height="16">';
|
|
$post['depthguide'] .= "<img src='".$this->settings['img_url']."/to_post_no_children.gif' alt='-' />";
|
|
}
|
|
else
|
|
{
|
|
$this->depth_guide[ $depth ] = '<img src="'.$this->settings['img_url'].'/to_down_pipe.gif" alt="|" />';
|
|
$post['depthguide'] .= "<img src='".$this->settings['img_url']."/to_post_with_children.gif' alt='-' />";
|
|
}
|
|
}
|
|
|
|
if ( ! $post['post_title'] )
|
|
{
|
|
if ( $this->settings['post_showtext_notitle'] )
|
|
{
|
|
$post_text = IPSText::getTextClass( 'bbcode' )->stripAllTags( strip_tags( IPSText::br2nl( $post['post'] ) ) );
|
|
|
|
if ( IPSText::mbstrlen($post_text) > 50 )
|
|
{
|
|
$post['post_title'] = IPSText::truncate( $post_text, 50 ).'...';
|
|
}
|
|
else
|
|
{
|
|
$post['post_title'] = $post_text;
|
|
}
|
|
|
|
if ( ! trim($post['post_title']) )
|
|
{
|
|
$post['post_title'] = $this->lang->words['post_title_re'] . $this->topics->topic['title'];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$post['post_title'] = $this->lang->words['post_title_re'] . $this->topics->topic['title'];
|
|
}
|
|
}
|
|
|
|
$post['linked_name'] = IPSLib::makeProfileLink( $post['author_name'], $post['author_id'] );
|
|
|
|
$post['formatted_date'] = $this->registry->class_localization->getDate( $post['post_date'], 'LONG' );
|
|
|
|
$post['new_post'] = 't_threaded_read';
|
|
|
|
if ( $post['post_date'] > $this->topics->last_read_tid )
|
|
{
|
|
$post['new_post'] = 't_threaded_read';
|
|
}
|
|
|
|
if ( strstr( $this->used_post_ids, ','.$post['pid'].',' ) )
|
|
{
|
|
$post['_show_highlight'] = 1;
|
|
}
|
|
|
|
return $post;
|
|
}
|
|
|
|
/**
|
|
* Get parents
|
|
*
|
|
* @access private
|
|
* @param integer $root_id
|
|
* @param array $ids
|
|
* @return array
|
|
**/
|
|
private function _threadedPostGetParents($root_id, $ids=array())
|
|
{
|
|
if( in_array( $root_id, $ids ) )
|
|
{
|
|
$cnt = 0;
|
|
|
|
foreach( $ids as $id )
|
|
{
|
|
if( $id == $root_id )
|
|
{
|
|
$cnt++;
|
|
|
|
if( $cnt > 1 )
|
|
{
|
|
return $ids;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( $this->post_cache[ $root_id ]['post_parent'] )
|
|
{
|
|
$ids[] = $this->post_cache[ $root_id ]['post_parent'];
|
|
|
|
$ids = $this->_threadedPostGetParents( $this->post_cache[ $root_id ]['post_parent'], $ids );
|
|
}
|
|
|
|
return $ids;
|
|
}
|
|
|
|
/**
|
|
* Get children
|
|
*
|
|
* @access private
|
|
* @param integer $root_id
|
|
* @param array $ids
|
|
* @return array
|
|
**/
|
|
private function _threadedPostGetChildren($root_id, $ids=array())
|
|
{
|
|
if ( is_array($this->structured_pids[ $root_id ]) )
|
|
{
|
|
foreach( $this->structured_pids[ $root_id ] as $pid )
|
|
{
|
|
$ids[] = $pid;
|
|
|
|
$ids = $this->_threadedPostGetChildren( $pdaid, $ids );
|
|
}
|
|
}
|
|
|
|
return $ids;
|
|
}
|
|
} |