* Invision Power Services * IP.Board v3.1.4 * Threaded mode functions * Last Updated: $Date: 2010-10-19 08:45:58 -0400 (Tue, 19 Oct 2010) $ * * * @author $Author: ips_terabyte $ * @copyright (c) 2001 - 2009 Invision Power Services, Inc. * @license http://www.invisionpower.com/community/board/license.html * @package IP.Board * @subpackage Forums * @link http://www.invisionpower.com * @version $Revision: 6994 $ */ if ( ! defined( 'IN_IPB' ) ) { print "

Incorrect access

You cannot access this file directly."; exit(); } class threadedModeLibrary { /** * Topics library * * @var object */ public $topics; /** * Structured post ids * * @var array */ public $structured_pids = array(); /** * Post cache * * @var array */ public $post_cache = array(); /** * Used post ids * * @var array */ public $used_post_ids = array(); /** * Threaded posts * * @var array */ public $_threaded_posts = array(); /** * Last id we've seen * * @var int */ public $last_id = 0; /**#@+ * Registry Object Shortcuts * * @var object */ protected $registry; protected $DB; protected $settings; protected $request; protected $lang; protected $member; protected $memberData; protected $cache; protected $caches; /**#@-*/ /** * Constructor * * @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 * * @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, null, 404 ); } $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; } } } } /* Data Hook Location */ $dataHook = array( 'members' => array(), 'postJoins' => array() ); IPSLib::doDataHooks( $dataHook , 'topicViewQuery' ); /* Join Queries */ $_extraMember = ( is_array($dataHook['members']) && count($dataHook['members']) ) ? ',m.'.implode(',m.', $dataHook['members']) : ''; $_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,m.mgroup_others'.$_extraMember, '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' ) ); /* Add data hook joins */ if ( is_array($dataHook['postJoins']) && count($dataHook['postJoins']) ) { $_post_joins = array_merge( $_post_joins, $dataHook['postJoins'] ); } /* 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 ) ) { /* That 1 line fix below took 1 hour, joy :D */ $row['member_id'] = $row['mid']; $row['g_access_cp'] = $this->caches['group_cache'][ $row['member_group_id'] ]['g_access_cp']; $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', 'seoTemplate' => 'showtopic', 'seoTitle' => $this->topics->topic['title_seo'] ) ); //----------------------------------------- // 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 * * @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, $this->topics->topic ); return $html; } /** * Render kiddies * * @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 * * @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 ] = ''; $post['depthguide'] .= "-"; } else { $this->depth_guide[ $depth ] = '|'; $post['depthguide'] .= "-"; } } 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 * * @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 * * @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( $pid, $ids ); } } return $ids; } }