1800 lines
52 KiB
PHP
1800 lines
52 KiB
PHP
<?php
|
|
/**
|
|
* Class to manage comments
|
|
*
|
|
* @author Matt Mecham
|
|
* @copyright (c) 2001 - 2010 Invision Power Services, Inc.
|
|
* @license http://www.invisionpower.com/company/standards.php#license
|
|
* @package Core
|
|
* @link http://www.invisionpower.com
|
|
* @version $Rev: 10914 $
|
|
*
|
|
*/
|
|
|
|
if ( ! defined( 'IN_IPB' ) )
|
|
{
|
|
print "<h1>Incorrect access</h1>You cannot access this file directly. If you have recently upgraded, make sure you upgraded all the relevant files.";
|
|
exit();
|
|
}
|
|
|
|
class classes_comments_bootstrap
|
|
{
|
|
static private $_app;
|
|
|
|
/**
|
|
* Construct
|
|
*
|
|
* @param string Comment class key (app-section)
|
|
* @param mixed Optional extra data to pass to init() method
|
|
*/
|
|
static public function controller( $app=null, $extraData=null )
|
|
{
|
|
if ( strstr( $app, '-' ) )
|
|
{
|
|
list( $app, $key ) = explode( '-', $app );
|
|
}
|
|
|
|
$_file = IPSLib::getAppDir( $app ) . '/extensions/comments/' . $key . '.php';
|
|
$_class = 'comments_' . $app . '_' . $key;
|
|
|
|
if ( is_file( $_file ) )
|
|
{
|
|
$classToLoad = IPSLib::loadLibrary( $_file, $_class, $app );
|
|
|
|
if ( class_exists( $classToLoad ) )
|
|
{
|
|
self::$_app = new $classToLoad();
|
|
self::$_app->init( $extraData );
|
|
}
|
|
else
|
|
{
|
|
throw new Exception( "No comment class available for $app" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new Exception( "No comment class available for $app" );
|
|
}
|
|
|
|
/* Load up language file */
|
|
$registry = ipsRegistry::instance();
|
|
$registry->getClass('class_localization')->loadLanguageFile( array( 'public_comments', 'public_editors' ), 'core' );
|
|
|
|
return self::$_app;
|
|
}
|
|
}
|
|
|
|
abstract class classes_comments_renderer
|
|
{
|
|
/**#@+
|
|
* Registry Object Shortcuts
|
|
*
|
|
* @var object
|
|
*/
|
|
protected $registry;
|
|
protected $DB;
|
|
protected $settings;
|
|
protected $request;
|
|
protected $lang;
|
|
protected $member;
|
|
protected $memberData;
|
|
protected $cache;
|
|
protected $caches;
|
|
/**#@-*/
|
|
|
|
protected $_cache = array();
|
|
/**
|
|
* App object
|
|
*
|
|
* @param object
|
|
*/
|
|
protected $_app;
|
|
|
|
/**
|
|
* Local settings object
|
|
*
|
|
* @param array
|
|
*/
|
|
protected $_settings;
|
|
|
|
/**
|
|
* CONSTRUCTOR
|
|
*
|
|
* @return @e void
|
|
*/
|
|
public function __construct()
|
|
{
|
|
/* Make registry objects */
|
|
$this->registry = ipsRegistry::instance();
|
|
$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();
|
|
}
|
|
|
|
/**
|
|
* Init method
|
|
*
|
|
* @param mixed Extra data (can be used by extending classes)
|
|
* @return @e void
|
|
*/
|
|
public function init( $extraData=null )
|
|
{
|
|
$this->lang->loadLanguageFile( array( 'public_topic' ), 'forums' );
|
|
|
|
/* Init some data */
|
|
$this->_settings = $this->settings();
|
|
$this->qpids = IPSCookie::get( 'comment_pids' );
|
|
$this->request['selectedpids'] = IPSCookie::get( 'commentmodpids' );
|
|
$this->request['selectedpidcount'] = intval( count( preg_split( "/,/", $this->request['commentmodpids'], -1, PREG_SPLIT_NO_EMPTY ) ) );
|
|
IPSCookie::set('commentmodpids', '', 0);
|
|
}
|
|
|
|
/**
|
|
* Get report center library
|
|
*
|
|
* @return @e object
|
|
*/
|
|
public function getReportLibrary()
|
|
{
|
|
static $reports = null;
|
|
|
|
if( !$reports )
|
|
{
|
|
$classToLoad = IPSLib::loadLibrary( IPSLib::getAppDir('core') . '/sources/classes/reportLibrary.php', 'reportLibrary' );
|
|
$reports = new $classToLoad( $this->registry );
|
|
}
|
|
|
|
return $reports;
|
|
}
|
|
|
|
/**
|
|
* Fetch setting
|
|
*
|
|
* @param string Setting key
|
|
* @return mixed Setting value OR null
|
|
*/
|
|
public function fetchSetting( $k, $parent=array() )
|
|
{
|
|
$setting = ( isset( $this->_settings[ $k ] ) ) ? $this->_settings[ $k ] : null;
|
|
|
|
if ( $setting !== null && is_array( $parent ) && count( $parent ) )
|
|
{
|
|
foreach( $parent as $_k => $_v )
|
|
{
|
|
$setting = str_replace( '#{' . $_k . '}', $_v, $setting );
|
|
}
|
|
}
|
|
|
|
return $setting;
|
|
}
|
|
|
|
/**
|
|
* Fetch formatted comments with HTML wrap
|
|
*
|
|
* @param mixed INT, parent ID, array, image data
|
|
* @param array Filters
|
|
* @return string
|
|
*/
|
|
public function fetchFormatted( $parent, $filters=array() )
|
|
{
|
|
/* Check parent */
|
|
if ( is_numeric( $parent ) )
|
|
{
|
|
$parent = $this->fetchParent( $parent );
|
|
}
|
|
|
|
/* Set filters */
|
|
$filters = $this->_setFilters( $filters );
|
|
$_remap = $this->remapKeys();
|
|
$parent = $this->remapFromLocal( $parent, 'parent' );
|
|
$preReply = '';
|
|
|
|
$data = array( 'counts' => array( 'commentTotal' => 0,
|
|
'thisPageCount' => 0,
|
|
'perPage' => $filters['limit'],
|
|
'curStart' => $filters['offset'] ) );
|
|
/* Fetch raw data */
|
|
$comments = $this->fetch( $parent, $filters );
|
|
|
|
list( $app, $_where ) = explode( '-', $this->whoAmI() );
|
|
|
|
if ( $comments === false )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/* Can comment */
|
|
$parent['_canComment'] = ( $this->can( 'add', array( 'comment_parent_id' => $parent['parent_id'] ) ) === true ) ? true : false;
|
|
|
|
/* Can moderate? */
|
|
$parent['_canModerate'] = ( $this->can( 'moderate', array( 'comment_parent_id' => $parent['parent_id'] ) ) === true ) ? true : false;
|
|
|
|
/* Got something? */
|
|
if ( is_array( $comments ) AND count( $comments ) )
|
|
{
|
|
$total = $this->count( $parent );
|
|
|
|
/* Add in addtional data */
|
|
if ( $total )
|
|
{
|
|
$data['counts']['commentTotal'] = $total;
|
|
$data['counts']['thisPageCount'] = count( $comments );
|
|
}
|
|
|
|
$pages = $this->registry->output->generatePagination( array( 'totalItems' => $total,
|
|
'itemsPerPage' => $filters['limit'],
|
|
'currentStartValue' => $filters['offset'],
|
|
'baseUrl' => sprintf( $this->fetchSetting('urls-showParent', $parent), $parent['parent_id'] ),
|
|
'anchor' => 'commentsStart',
|
|
'base' => 'public',
|
|
'seoTitle' => $parent['parent_seo_title'],
|
|
'seoTemplate' => $this->seoTemplate() ) );
|
|
|
|
}
|
|
|
|
|
|
$data['settings'] = $this->settings();
|
|
$data['canModerate'] = ( $parent['_canModerate'] ) ? true : false;
|
|
$data['fromApp'] = $this->whoAmI();
|
|
$data['thisApp'] = $app;
|
|
$data['repType'] = $_remap['comment_id'];
|
|
$data['enableRep'] = $this->reputationEnabled();
|
|
$data['autoSaveKey'] = 'comment-' . $this->table() . '-' . $parent['parent_id'];
|
|
$data['baseUrl'] = "app=core&module=global&section=comments&parentId={$parent['parent_id']}&fromApp={$data['fromApp']}";
|
|
$data['formUrl'] = $this->registry->output->buildSEOUrl( "" );
|
|
$data['formApp'] = 'core';
|
|
$data['formModule'] = 'global';
|
|
$data['formSection'] = 'comments';
|
|
|
|
$data['captcha'] = $this->getCaptcha();
|
|
|
|
/* Got a reply? */
|
|
if ( !empty( $this->request['_rcid'] ) )
|
|
{
|
|
$preReply = $this->fetchReply( $parent['parent_id'], $this->request['_rcid'], $this->memberData );
|
|
}
|
|
|
|
/* Give plugin a chance to adjust */
|
|
$adjusted = $this->preOutputAdjustment( 'commentsList', array( 'comments' => $comments, 'data' => $data, 'pages' => $pages, 'parent' => $parent, 'preReply' => $preReply ) );
|
|
|
|
return $this->registry->output->getTemplate( $this->skin() )->commentsList( $adjusted['comments'], $adjusted['data'], $adjusted['pages'], $adjusted['parent'], $adjusted['preReply'] );
|
|
}
|
|
|
|
/**
|
|
* Returns recaptcha data if we are a guest
|
|
*/
|
|
public function getCaptcha()
|
|
{
|
|
if ( ! $this->memberData['member_id'] AND $this->settings['guest_captcha'] AND $this->settings['bot_antispam_type'] != 'none' )
|
|
{
|
|
return $this->registry->getClass('class_captcha')->getTemplate();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetch a total count of comments we can see
|
|
*
|
|
* @param mixed parent Id or parent array
|
|
* @return int
|
|
*/
|
|
public function count( $parent )
|
|
{
|
|
/* Check parent */
|
|
if ( is_numeric( $parent ) )
|
|
{
|
|
$parent = $this->fetchParent( $parent );
|
|
}
|
|
|
|
$_remap = $this->remapKeys();
|
|
$parent = $this->remapFromLocal( $parent, 'parent' );
|
|
|
|
/* Check it out */
|
|
$q = ( $this->can( 'moderate', array( 'comment_parent_id' => $parent['parent_id'] ) ) ) ? '' : ' AND ' . $_remap['comment_approved'] . '=1';
|
|
|
|
/* Fetch a total */
|
|
$total = $this->DB->buildAndFetch( array( 'select' => 'count(*) as total',
|
|
'from' => $this->table(),
|
|
'where' => $_remap['comment_parent_id'] . '=' . $parent['parent_id'] . $q ) );
|
|
|
|
return $total['total'];
|
|
}
|
|
|
|
/**
|
|
* Fetch a single formatted comment. Useful for ajaxish functions.
|
|
*
|
|
* @param mixed INT, image ID, array, image data
|
|
* @param int Comment ID
|
|
* @return string
|
|
*/
|
|
public function fetchFormattedSingle( $parent, $commentId )
|
|
{
|
|
/* Got comment id? */
|
|
$filters['comment_id'] = intval( $commentId );
|
|
|
|
/* Check parent */
|
|
if ( is_numeric( $parent ) )
|
|
{
|
|
$parent = $this->fetchParent( $parent );
|
|
}
|
|
|
|
/* Set filters */
|
|
$filters = $this->_setFilters( $filters );
|
|
$parent = $this->remapFromLocal( $parent, 'parent' );
|
|
$_remap = $this->remapKeys();
|
|
|
|
list( $app, $_where ) = explode( '-', $this->whoAmI() );
|
|
|
|
/* Fetch raw data */
|
|
$comments = $this->fetch( $parent, $filters );
|
|
$comment = array_pop( $comments );
|
|
|
|
if ( $comment === null )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/* Can moderate? */
|
|
$parent['_canModerate'] = $this->can( 'moderate', array( 'comment_parent_id' => $parent['parent_id'] ) ) === true ? true: false;
|
|
|
|
$data['settings'] = $this->settings();
|
|
$data['fromApp'] = $this->whoAmI();
|
|
$data['thisApp'] = $app;
|
|
$data['repType'] = $_remap['comment_id'];
|
|
$data['enableRep'] = $this->reputationEnabled();
|
|
|
|
/* Give plugin a chance to adjust */
|
|
$adjusted = $this->preOutputAdjustment( 'commentSingle', array( 'comment' => $comment, 'data' => $data, 'parent' => $parent ) );
|
|
|
|
return $this->registry->output->getTemplate( $this->skin() )->comment( $adjusted['comment'], $adjusted['parent'], $adjusted['data'] );
|
|
}
|
|
|
|
/**
|
|
* Fetch a comment by ID (no perm checks)
|
|
*
|
|
* @param int Comment ID
|
|
*/
|
|
public function fetchById( $commentId )
|
|
{
|
|
$_remap = $this->remapKeys();
|
|
|
|
if ( ! isset( $this->_cache[ $commentId ] ) )
|
|
{
|
|
$comment = $this->DB->buildAndFetch( array( 'select' => '*',
|
|
'from' => $this->table(),
|
|
'where' => $_remap['comment_id'] . '=' . intval( $commentId ) ) );
|
|
|
|
$comment = $this->remapFromLocal( (array) $comment );
|
|
$this->_cache[ $comment['comment_id'] ] = $comment;
|
|
}
|
|
|
|
return $this->_cache[ $commentId ];
|
|
}
|
|
|
|
/**
|
|
* Fetch raw comments
|
|
*
|
|
* @param mixed parent ID
|
|
* @param array Filters
|
|
* @return array
|
|
*/
|
|
public function fetch( $parent, $filters=array() )
|
|
{
|
|
/* Check parent */
|
|
if ( is_numeric( $parent ) )
|
|
{
|
|
$parent = $this->fetchParent( $parent );
|
|
}
|
|
|
|
/* Set filters */
|
|
$filters = $this->_setFilters( $filters );
|
|
$parent = $this->remapFromLocal( $parent, 'parent' );
|
|
$comments = array();
|
|
$q = array();
|
|
$_remap = $this->remapKeys();
|
|
list( $app, $_where ) = explode( '-', $this->whoAmI() );
|
|
|
|
/* unpack cache */
|
|
$this->_unpackRepCache();
|
|
|
|
/* Joins */
|
|
$_post_joins = array( array( 'select' => 'm.*',
|
|
'where' => 'm.member_id=c.' . $_remap['comment_author_id'],
|
|
'from' => array( 'members' => 'm' ),
|
|
'type' => 'left', ),
|
|
array( 'select' => 'pc.*',
|
|
'where' => 'pc.member_id=m.member_id',
|
|
'from' => array( 'pfields_content' => 'pc' ),
|
|
'type' => 'left', ),
|
|
array( 'select' => 'pp.*',
|
|
'where' => 'pp.pp_member_id=m.member_id',
|
|
'from' => array( 'profile_portal' => 'pp' ),
|
|
'type' => 'left', ),
|
|
);
|
|
|
|
/* Reputation system enabled? */
|
|
if ( $this->reputationEnabled() && $this->settings['reputation_enabled'] )
|
|
{
|
|
/* Add the join to figure out if the user has already rated the post */
|
|
$_post_joins[] = $this->registry->repCache->getUserHasRatedJoin( $_remap['comment_id'], 'c.' . $_remap['comment_id'], $app );
|
|
|
|
/* Add the join to figure out the total ratings for each post */
|
|
if( $this->settings['reputation_show_content'] )
|
|
{
|
|
$_post_joins[] = $this->registry->repCache->getTotalRatingJoin( $_remap['comment_id'], 'c.' . $_remap['comment_id'], $app );
|
|
}
|
|
}
|
|
|
|
/* Start of query */
|
|
$q[] = "c." . $_remap['comment_parent_id'] . "=" . $parent['parent_id'];
|
|
|
|
/* Can moderate? */
|
|
if ( $this->can( 'moderate', array( 'comment_parent_id' => $parent['parent_id'] ) ) !== true )
|
|
{
|
|
$q[] = 'c.' . $_remap['comment_approved'] . '=1';
|
|
}
|
|
|
|
/* Fetching a single comment? */
|
|
if ( isset( $filters['comment_id'] ) )
|
|
{
|
|
if ( is_numeric( $filters['comment_id'] ) )
|
|
{
|
|
$q[] = 'c.' . $_remap['comment_id'] . '=' . intval( $filters['comment_id'] );
|
|
}
|
|
else if ( is_array( $filters['comment_id'] ) )
|
|
{
|
|
$q[] = 'c.' . $_remap['comment_id'] . ' IN(' . implode( ",", IPSLib::cleanIntArray( $filters['comment_id'] ) ) . ')';
|
|
}
|
|
}
|
|
|
|
/* Set up parser */
|
|
IPSText::getTextClass('bbcode')->parse_html = 0;
|
|
IPSText::getTextClass('bbcode')->parse_nl2br = 1;
|
|
IPSText::getTextClass('bbcode')->parse_bbcode = 1;
|
|
IPSText::getTextClass('bbcode')->parsing_section = $this->bbcodeSection();
|
|
|
|
/* Allow plugin to add additional where clauses, or modify existing ones */
|
|
$query = array( 'select' => 'c.*',
|
|
'from' => array( $this->table() => 'c' ),
|
|
'where' => implode( ' AND ', $q ),
|
|
'order' => 'c.' . $_remap[ $filters['sortKey'] ] . ' ' . $filters['sortOrder'],
|
|
'limit' => array( $filters['offset'], $filters['limit'] ),
|
|
'add_join' => $_post_joins );
|
|
|
|
$query = $this->alterFetchQuery( $query, $_remap, $parent, $filters );
|
|
|
|
/* Fetch the data */
|
|
$this->DB->build( $query );
|
|
|
|
$oq = $this->DB->execute();
|
|
|
|
/* Go get 'em bawss */
|
|
$hidden = array();
|
|
while( $row = $this->DB->fetch( $oq ) )
|
|
{
|
|
/* Reset member ID */
|
|
$row['member_id'] = $row[ $_remap['comment_author_id'] ];
|
|
|
|
/* Set up parser */
|
|
IPSText::getTextClass('bbcode')->parsing_mgroup = $row['member_group_id'];
|
|
IPSText::getTextClass('bbcode')->parsing_mgroup_others = $row['mgroup_others'];
|
|
|
|
/* Remap */
|
|
$row = $this->remapFromLocal( $row );
|
|
|
|
/* cache in generic state */
|
|
$this->_cache[ $row['comment_id'] ] = $row;
|
|
|
|
/* Preserve original DB formatting */
|
|
$row['_db_comment'] = $row['comment_text'];
|
|
|
|
/* Parse for display */
|
|
$row['comment_text'] = IPSText::getTextClass('bbcode')->preDisplayParse( $row['comment_text'] );
|
|
|
|
/* Can moderate? */
|
|
if ( $this->can( 'moderate', array( 'comment_parent_id' => $parent['parent_id'] ) ) )
|
|
{
|
|
if ( $this->request['selectedpids'] )
|
|
{
|
|
if ( strstr( ','.$this->request['selectedpids'].',', ','.$row['pid'].',' ) )
|
|
{
|
|
$row['_pidChecked'] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Ignored users */
|
|
foreach( $this->member->ignored_users as $_i )
|
|
{
|
|
if( $_i['ignore_topics'] AND $_i['ignore_ignore_id'] == $row['author_id'] )
|
|
{
|
|
if ( ! strstr( $this->settings['cannot_ignore_groups'], ','.$row['member_group_id'].',' ) )
|
|
{
|
|
$row['_ignored'] = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
|
|
/* Edit button */
|
|
$row['_canEdit'] = ( $this->can('edit', $row) === true ) ? 1 : 0;
|
|
|
|
/* Hide/Unhide buttons */
|
|
$row['_canHide'] = ( $this->can('hide', $row) === true ) ? 1 : 0;
|
|
$row['_canUnhide'] = ( $this->can('unhide', $row) === true ) ? 1 : 0;
|
|
$row['_canApprove'] = ( $this->can('visibility', $row) === true ) ? 1 : 0;
|
|
|
|
/* Delete button */
|
|
$row['_canDelete'] = ( $this->can('delete', $row) === true ) ? 1 : 0;
|
|
|
|
/* Reply button */
|
|
$row['_canReply'] = ( $this->can('add', $row) === true ) ? 1 : 0;
|
|
|
|
/* Report link */
|
|
if ( $this->fetchSetting('urls-report', $parent) )
|
|
{
|
|
$_parts = substr_count( $this->fetchSetting('urls-report', $parent), '%s' );
|
|
|
|
switch( $_parts )
|
|
{
|
|
case 1:
|
|
$row['urls-report'] = sprintf( $this->fetchSetting('urls-report', $parent), $row['comment_id'] );
|
|
break;
|
|
|
|
case 2:
|
|
$row['urls-report'] = sprintf( $this->fetchSetting('urls-report', $parent), $row['comment_id'], $parent['parent_id'] );
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Ensure parity */
|
|
$row['member_id'] = $row['comment_author_id'];
|
|
$row['members_display_name'] = $row['members_display_name'] ? $row['members_display_name'] : $this->lang->words['global_guestname'];
|
|
|
|
/* Reputation */
|
|
if ( $this->settings['reputation_enabled'] )
|
|
{
|
|
$row['like'] = $this->returnReputationFormatted( $app, $_remap, $row );
|
|
}
|
|
|
|
/* Hidden Information */
|
|
if ( $row['comment_approved'] == -1 )
|
|
{
|
|
$hidden[] = $row['comment_id'];
|
|
}
|
|
|
|
/* Done */
|
|
$comments[ $row['comment_id'] ] = array( 'author' => IPSMember::buildDisplayData( $row ), 'comment' => $row );
|
|
}
|
|
if ( !empty( $hidden ) )
|
|
{
|
|
foreach ( IPSDeleteLog::fetchEntries( $hidden, $this->whoAmI() ) as $k => $v )
|
|
{
|
|
$comments[ $k ]['sD'] = $v;
|
|
}
|
|
}
|
|
|
|
return is_array($comments) ? $comments : array();
|
|
}
|
|
|
|
/**
|
|
* Return the reputation data formatted. Abstracted so apps can override if needed.
|
|
*
|
|
* @param string Application
|
|
* @param array Remap data
|
|
* @param array Record data from database
|
|
* @return @string Reputation formatted
|
|
*/
|
|
public function returnReputationFormatted( $app, $_remap, $row )
|
|
{
|
|
return $this->registry->repCache->getLikeFormatted( array( 'app' => $app, 'type' => $_remap['comment_id'], 'id' => $row['comment_id'], 'rep_like_cache' => $row['rep_like_cache'] ) );
|
|
}
|
|
|
|
/**
|
|
* Updates a comment
|
|
*
|
|
* @param string Action (delete/approve/unapprove)
|
|
* @param int ID of parent
|
|
* @param int Comment IDs
|
|
* @param array Member Data of current member
|
|
* @reutrn html Does stuff to things.
|
|
* EXCEPTIONS
|
|
* MISSING_DATA Ids missing
|
|
* NO_PERMISSION No permission
|
|
*/
|
|
public function moderate( $action, $parentId, $commentIds, $memberData )
|
|
{
|
|
/* Init */
|
|
if ( is_numeric( $memberData ) )
|
|
{
|
|
$memberData = IPSMember::load( $memberData, 'all' );
|
|
}
|
|
|
|
/* Fetch and check image */
|
|
$parent = $this->fetchParent( $parentId );
|
|
$_remap = $this->remapKeys();
|
|
|
|
/* Parent */
|
|
$parent = $this->remapFromLocal( $parent, 'parent' );
|
|
|
|
/* Fetch comment */
|
|
$comments = $this->fetch( $parent, array( 'comment_id' => $commentIds ) );
|
|
|
|
if ( ! count( $comments ) )
|
|
{
|
|
throw new Exception( 'MISSING_DATA' );
|
|
}
|
|
|
|
/* Permission test */
|
|
$can = $this->can('moderate', array( 'comment_parent_id' => $parentId ) );
|
|
|
|
if ( $can !== true )
|
|
{
|
|
throw new Exception( $can );
|
|
}
|
|
|
|
/* WHAT ARE YOU DOING HERE? */
|
|
switch ( $action )
|
|
{
|
|
case 'delete':
|
|
try
|
|
{
|
|
return $this->delete( $parentId, $commentIds, $memberData );
|
|
}
|
|
catch (Exception $e)
|
|
{
|
|
throw new Exception('NO_PERMISSION');
|
|
}
|
|
break;
|
|
case 'approve':
|
|
try
|
|
{
|
|
return $this->visibility( 'on', $parentId, $commentIds, $memberData );
|
|
}
|
|
catch (Exception $e)
|
|
{
|
|
throw new Exception('NO_PERMISSION');
|
|
}
|
|
break;
|
|
case 'unapprove':
|
|
try
|
|
{
|
|
return $this->visibility( 'off', $parentId, $commentIds, $memberData );
|
|
}
|
|
catch (Exception $e)
|
|
{
|
|
throw new Exception('NO_PERMISSION' . $e->getMessage() . ' line: ' . $e->getFile() . '.' . $e->getLine());
|
|
}
|
|
break;
|
|
case 'hide':
|
|
$r = $this->hide( $parentId, $commentIds, NULL, $memberData );
|
|
if ( $r !== TRUE ) { throw new Exception( $r ); }
|
|
break;
|
|
case 'unhide':
|
|
$r = $this->unhide( $parentId, $commentIds, $memberData );
|
|
if ( $r !== TRUE ) { throw new Exception( $r ); }
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Hide a comment
|
|
*
|
|
* @param int Parent ID
|
|
* @param int|array Comment IDs
|
|
* @param string Reason
|
|
* @param int|array Member Data
|
|
* @return bool|string TRUE on sucess, error string on error
|
|
*/
|
|
public function hide( $parentId, $commentIds, $reason, $memberData )
|
|
{
|
|
/* Init */
|
|
if ( is_numeric( $memberData ) )
|
|
{
|
|
$memberData = IPSMember::load( $memberData, 'all' );
|
|
}
|
|
|
|
/* Check */
|
|
if ( !is_array( $commentIds ) )
|
|
{
|
|
$commentIds = array( $commentIds );
|
|
}
|
|
if ( ! $memberData['member_id'] OR ! $parentId )
|
|
{
|
|
return 'MISSING_DATA';
|
|
}
|
|
|
|
/* Permission Check */
|
|
foreach ( $commentIds as $k )
|
|
{
|
|
$permCheck = $this->can( 'hide', array( 'comment_id' => $k, 'comment_parent_id' => $parentId ) );
|
|
if ( $permCheck !== TRUE )
|
|
{
|
|
return $permCheck;
|
|
}
|
|
}
|
|
|
|
/* Do it */
|
|
$_remap = $this->remapKeys();
|
|
$array = array( 'comment_approved' => -1 );
|
|
$update = $this->preVisibility( -1, $commentIds, $parentId, $array );
|
|
$save = $this->remapToLocal( $update );
|
|
$this->DB->update( $this->table(), $save, $this->DB->buildWherePermission( $commentIds, $_remap['comment_id'], FALSE ) );
|
|
$this->postVisibility( -1, $commentIds, $parentId );
|
|
|
|
/* Log */
|
|
foreach ( $commentIds as $k )
|
|
{
|
|
IPSDeleteLog::addEntry( $k, $this->whoAmI(), $reason, $memberData );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Unhide a comment
|
|
*
|
|
* @param int Parent ID
|
|
* @param int|array Comment IDs
|
|
* @param int|array Member Data
|
|
* @return bool|string TRUE on sucess, error string on error
|
|
*/
|
|
public function unhide( $parentId, $commentIds, $memberData )
|
|
{
|
|
/* Init */
|
|
if ( is_numeric( $memberData ) )
|
|
{
|
|
$memberData = IPSMember::load( $memberData, 'all' );
|
|
}
|
|
|
|
/* Check */
|
|
if ( !is_array( $commentIds ) )
|
|
{
|
|
$commentIds = array( $commentIds );
|
|
}
|
|
if ( ! $memberData['member_id'] OR ! $parentId )
|
|
{
|
|
return 'MISSING_DATA';
|
|
}
|
|
|
|
/* Permission Check */
|
|
foreach ( $commentIds as $k )
|
|
{
|
|
$permCheck = $this->can( 'unhide', array( 'comment_id' => $k, 'comment_parent_id' => $parentId ) );
|
|
if ( $permCheck !== TRUE )
|
|
{
|
|
return $permCheck;
|
|
}
|
|
}
|
|
|
|
/* Do it */
|
|
$_remap = $this->remapKeys();
|
|
$array = array( 'comment_approved' => 1 );
|
|
$update = $this->preVisibility( 1, $commentIds, $parentId, $array );
|
|
$save = $this->remapToLocal( $update );
|
|
$this->DB->update( $this->table(), $save, $this->DB->buildWherePermission( $commentIds, $_remap['comment_id'], FALSE ) );
|
|
$this->postVisibility( 1, $commentIds, $parentId );
|
|
|
|
/* Log */
|
|
IPSDeleteLog::removeEntries( $commentIds, $this->whoAmI() );
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Add a comment
|
|
*
|
|
* @param Int Parent ID
|
|
* @param string Post content
|
|
* @param array Member ID of author (current member assumed if empty)
|
|
* @return exception or comment ID
|
|
*
|
|
* EXCEPTION CODES
|
|
* NO_PERMISSION Do not have permission to add comment
|
|
*/
|
|
public function add( $parentId, $post, $memberId=null )
|
|
{
|
|
/* Load member */
|
|
$memberData = IPSMember::load( ( ( $memberId === null ) ? $this->memberData['member_id'] : $memberId ), 'all' );
|
|
|
|
if( !$memberData['member_id'] )
|
|
{
|
|
if( !$this->request['comment_name'] )
|
|
{
|
|
throw new Exception( 'NO_NAME' );
|
|
}
|
|
|
|
$memberData['members_display_name'] = $this->request['comment_name'];
|
|
}
|
|
|
|
/* Permission test */
|
|
$can = $this->can('add', array( 'comment_parent_id' => $parentId ) );
|
|
|
|
if ( $can !== true )
|
|
{
|
|
throw new Exception( $can );
|
|
}
|
|
|
|
/* Mod queue? */
|
|
$modQ = IPSMember::isOnModQueue( $memberData );
|
|
if ( $modQ === NULL )
|
|
{
|
|
throw new Exception( 'NO_PERMISSION' );
|
|
}
|
|
|
|
/* Format comment */
|
|
IPSText::getTextClass( 'bbcode' )->parsing_section = $this->bbcodeSection();
|
|
|
|
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/editor/composite.php', 'classes_editor_composite' );
|
|
$editor = new $classToLoad();
|
|
|
|
$comment = $editor->process( $post );
|
|
if ( !trim( $comment ) )
|
|
{
|
|
throw new Exception( 'NO_COMMENT' );
|
|
}
|
|
|
|
$comment = IPSText::getTextClass( 'bbcode' )->preDbParse( $comment );
|
|
|
|
/* Build insert data */
|
|
$array = array( 'comment_author_id' => intval( $memberData['member_id'] ),
|
|
'comment_author_name' => $memberData['members_display_name'],
|
|
'comment_ip_address' => $this->member->ip_address,
|
|
'comment_date' => time(),
|
|
'comment_text' => $comment,
|
|
'comment_approved' => $modQ ? 0 : 1,
|
|
'comment_parent_id' => $parentId );
|
|
|
|
/* Pre save */
|
|
$insert = $this->preSave( 'add', $array, 0, $parentId );
|
|
|
|
/* Insert and fetch DB */
|
|
$save = $this->remapToLocal( $insert );
|
|
|
|
if( count($save) )
|
|
{
|
|
$this->DB->insert( $this->table(), $save );
|
|
|
|
$insert['comment_id'] = $this->DB->getInsertId();
|
|
}
|
|
|
|
/* Post save */
|
|
$insert = $this->postSave( 'add', $insert, $insert['comment_id'], $parentId );
|
|
|
|
/* remove saved content */
|
|
if ( $this->memberData['member_id'] )
|
|
{
|
|
$editor->removeAutoSavedContent( array( 'member_id' => $this->memberData['member_id'], 'autoSaveKey' => 'comment-' . $this->table() . '-' . $parentId ) );
|
|
}
|
|
|
|
/* Send notifications */
|
|
$this->sendNotifications( $this->remapFromLocal( $insert ), $comment );
|
|
|
|
return $insert;
|
|
}
|
|
|
|
/**
|
|
* Sends "like" notifications
|
|
*
|
|
* @param array Array of GENERIC data (comment_xxxx)
|
|
* @param string Comment Text
|
|
* @return nowt lad
|
|
*/
|
|
public function sendNotifications( array $array, $comment )
|
|
{
|
|
list( $_app, $_area ) = explode( '-', $this->whoAmI() );
|
|
|
|
/* Send them if they are approved */
|
|
if ( $array['comment_approved'] )
|
|
{
|
|
$this->lang->loadLanguageFile( array( 'public_comments' ), 'core' );
|
|
|
|
/* Fetch meta data */
|
|
$parent = $this->remapFromLocal( $this->fetchParent( $array['comment_parent_id'] ), 'parent' );
|
|
|
|
$_url = $this->fetchSetting( 'urls-showParent', $parent );
|
|
$url = $this->registry->output->buildSEOUrl( sprintf( $_url, $parent['parent_id'] ), 'public', $parent['parent_seo_title'], $this->seoTemplate() );
|
|
$commentUrl = $this->registry->output->buildSEOUrl( 'app=core&module=global&section=comments&do=findComment&fromApp=' . $_app . '-' . $_area . '&parentId=' . $parent['parent_id'] . '&commentId=' . $array['comment_id'], 'public', true, 'findcomment' );
|
|
|
|
/* Fetch like class */
|
|
try
|
|
{
|
|
require_once( IPS_ROOT_PATH . 'sources/classes/like/composite.php' );/*noLibHook*/
|
|
$_like = classes_like::bootstrap( $_app, $_area );
|
|
|
|
$_like->sendNotifications( $parent['parent_id'], array( 'immediate', 'offline' ), array( 'notification_key' => 'new_comment',
|
|
'notification_url' => $url,
|
|
'email_template' => 'comment_notifications',
|
|
'email_subject' => sprintf( $this->lang->words['comment_notice_subject'], $url, $parent['parent_title'] ),
|
|
'build_message_array' => array( 'NAME' => '-member:members_display_name-',
|
|
'AUTHOR' => $this->memberData['members_display_name'],
|
|
'TITLE' => $parent['parent_title'],
|
|
'URL' => $url,
|
|
'COMMENTURL' => $commentUrl,
|
|
'COMMENT' => $comment ) ) );
|
|
}
|
|
catch( Exception $e )
|
|
{
|
|
/* No like class for this comment class */
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Updates a comment
|
|
*
|
|
* @param int ID of parent
|
|
* @param int Comment ID
|
|
* @param array Member Data of current member
|
|
* @reutrn html Content of edited comment ready for printing to screen
|
|
* EXCEPTIONS
|
|
* MISSING_DATA Ids missing
|
|
* NO_PERMISSION No permission
|
|
*/
|
|
public function edit( $parentId, $commentId, $post, $memberData )
|
|
{
|
|
/* Init */
|
|
if ( is_numeric( $memberData ) )
|
|
{
|
|
$memberData = IPSMember::load( $memberData, 'all' );
|
|
}
|
|
|
|
/* Fetch and check image */
|
|
$parent = $this->fetchParent( $parentId );
|
|
$_remap = $this->remapKeys();
|
|
|
|
/* Parent */
|
|
$parent = $this->remapFromLocal( $parent, 'parent' );
|
|
|
|
/* Fetch comment */
|
|
$_c = $this->fetch( $parent, array( 'comment_id' => $commentId ) );
|
|
$comment = array_pop( $_c );
|
|
|
|
/* Permission test */
|
|
$can = $this->can('edit', array( 'comment_id' => $commentId, 'comment_parent_id' => $parentId ) );
|
|
|
|
if ( $can !== true )
|
|
{
|
|
throw new Exception( $can );
|
|
}
|
|
|
|
/* Format post */
|
|
IPSText::getTextClass('bbcode')->parse_html = 0;
|
|
IPSText::getTextClass('bbcode')->parse_nl2br = 1;
|
|
IPSText::getTextClass('bbcode')->parse_smilies = 1;
|
|
IPSText::getTextClass('bbcode')->parse_bbcode = 1;
|
|
IPSText::getTextClass('bbcode')->parsing_section = $this->bbcodeSection();
|
|
|
|
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/editor/composite.php', 'classes_editor_composite' );
|
|
$editor = new $classToLoad();
|
|
|
|
$comment = $editor->process( $post );
|
|
$comment = IPSText::getTextClass( 'bbcode' )->preDbParse( $comment );
|
|
|
|
/* Update array */
|
|
$array = array( 'comment_edit_date' => time(),
|
|
'comment_text' => $comment );
|
|
/* Pre save */
|
|
$update = $this->preSave( 'edit', $array, $commentId, $parentId );
|
|
|
|
/* Insert and fetch DB */
|
|
$save = $this->remapToLocal( $update );
|
|
|
|
/* Update */
|
|
if( count($save) )
|
|
{
|
|
$this->DB->update( $this->table(), $save, $_remap['comment_id'] . '=' . intval( $commentId ) );
|
|
}
|
|
|
|
/* Post save */
|
|
$this->postSave( 'edit', $update, $commentId, $parentId );
|
|
|
|
/* remove saved content */
|
|
if ( $this->memberData['member_id'] )
|
|
{
|
|
$editor->removeAutoSavedContent( array( 'member_id' => $this->memberData['member_id'], 'autoSaveKey' => 'comment-' . $this->table() . '-c' . $commentId ) );
|
|
}
|
|
|
|
/* Format and return */
|
|
IPSText::getTextClass('bbcode')->parse_html = 0;
|
|
IPSText::getTextClass('bbcode')->parse_nl2br = 1;
|
|
IPSText::getTextClass('bbcode')->parse_smilies = 1;
|
|
IPSText::getTextClass('bbcode')->parse_bbcode = 1;
|
|
IPSText::getTextClass('bbcode')->parsing_section = $this->bbcodeSection();
|
|
IPSText::getTextClass('bbcode')->parsing_mgroup = $this->memberData['member_group_id'];
|
|
IPSText::getTextClass('bbcode')->parsing_mgroup_others = $this->memberData['mgroup_others'];
|
|
|
|
return IPSText::getTextClass('bbcode')->preDisplayParse( $comment );
|
|
}
|
|
|
|
/**
|
|
* Deletes a comment
|
|
*
|
|
* @param int Image ID of parent
|
|
* @param mixed Comment ID or array of comment IDs
|
|
* @param array Member Data of current member
|
|
* @reutrn html
|
|
* EXCEPTIONS
|
|
* MISSING_DATA Ids missing
|
|
* NO_PERMISSION No permission
|
|
*/
|
|
public function delete( $parentId, $commentId, $memberData )
|
|
{
|
|
/* Init */
|
|
if ( is_numeric( $memberData ) )
|
|
{
|
|
$memberData = IPSMember::load( $memberData, 'all' );
|
|
}
|
|
|
|
/* Check */
|
|
if ( ! $memberData['member_id'] OR ! $parentId OR ! $commentId )
|
|
{
|
|
throw new Exception('MISSING_DATA');
|
|
}
|
|
|
|
/* Fetch and check image */
|
|
$parent = $this->fetchParent( $parentId );
|
|
$_remap = $this->remapKeys();
|
|
$cids = array();
|
|
|
|
/* Parent */
|
|
$parent = $this->remapFromLocal( $parent, 'parent' );
|
|
|
|
/* One or many? */
|
|
if ( is_numeric( $commentId ) )
|
|
{
|
|
/* Fetch comment */
|
|
$_c = $this->fetch( $parent, array( 'comment_id' => $commentId ) );
|
|
$comment = array_pop( $_c );
|
|
|
|
/* Permission test */
|
|
$can = $this->can('delete', array( 'comment_id' => $commentId, 'comment_parent_id' => $parentId ) );
|
|
|
|
if ( $can !== true )
|
|
{
|
|
throw new Exception( $can );
|
|
}
|
|
|
|
$cids = array( $commentId );
|
|
}
|
|
else if ( is_array( $commentId ) )
|
|
{
|
|
/* Permission test */
|
|
$can = $this->can('moderate', array( 'comment_parent_id' => $parentId ) );
|
|
|
|
if ( $can !== true )
|
|
{
|
|
throw new Exception( $can );
|
|
}
|
|
|
|
/* Finalize comment Ids */
|
|
$this->DB->build( array( 'select' => '*',
|
|
'from' => $this->table(),
|
|
'where' => $_remap['comment_id'] . ' IN (' . implode( ",", IPSLib::cleanIntArray( $commentId ) ) . ') AND ' . $_remap['comment_parent_id'] . '=' . $parent['parent_id'] ) );
|
|
|
|
$this->DB->execute();
|
|
|
|
while( $row = $this->DB->fetch() )
|
|
{
|
|
$cids[] = $row[ $_remap['comment_id'] ];
|
|
}
|
|
}
|
|
|
|
/* If we have anything.. */
|
|
if ( count( $cids ) )
|
|
{
|
|
/* Pre delete */
|
|
$this->preDelete( $cids, $parentId );
|
|
|
|
/* Delete */
|
|
$this->DB->delete( $this->table(), $_remap['comment_id'] . ' IN (' . implode( ",", $cids ) . ')' );
|
|
|
|
/* We also need to delete rep - Bug #37686 */
|
|
list( $app, $_where ) = explode( '-', $this->whoAmI() );
|
|
|
|
foreach( $cids as $cid )
|
|
{
|
|
$this->DB->delete( 'reputation_cache' , "app='" . $app . "' AND type='comment_id' AND type_id=" . $cid );
|
|
$this->DB->delete( 'reputation_index' , "app='" . $app . "' AND type='comment_id' AND type_id=" . $cid );
|
|
$this->DB->delete( 'reputation_totals', "rt_key=MD5('" . $app . ";comment_id;" . $cid . "') AND rt_type_id=" . $cid );
|
|
}
|
|
|
|
/* Post delete */
|
|
$this->postDelete( $cids, $parentId );
|
|
}
|
|
|
|
/* Return count deleted */
|
|
return count( $cids );
|
|
}
|
|
|
|
/**
|
|
* Toggles visbility a comment
|
|
*
|
|
* @param string on/off
|
|
* @param int Image ID of parent
|
|
* @param mixed Comment ID or array of comment IDs
|
|
* @param array Member Data of current member
|
|
* @reutrn html
|
|
* EXCEPTIONS
|
|
* MISSING_DATA Ids missing
|
|
* NO_PERMISSION No permission
|
|
*/
|
|
public function visibility( $toggle, $parentId, $commentId, $memberData )
|
|
{
|
|
/* Init */
|
|
if ( is_numeric( $memberData ) )
|
|
{
|
|
$memberData = IPSMember::load( $memberData, 'all' );
|
|
}
|
|
|
|
/* Check */
|
|
if ( ! $memberData['member_id'] OR ! $parentId OR ! $commentId )
|
|
{
|
|
throw new Exception('MISSING_DATA');
|
|
}
|
|
|
|
/* Fetch and check image */
|
|
$parent = $this->fetchParent( $parentId );
|
|
$_remap = $this->remapKeys();
|
|
$cids = array();
|
|
|
|
/* Parent */
|
|
$parent = $this->remapFromLocal( $parent, 'parent' );
|
|
|
|
/* One or many? */
|
|
if ( is_numeric( $commentId ) )
|
|
{
|
|
/* Fetch comment */
|
|
$_c = $this->fetch( $parent, array( 'comment_id' => $commentId ) );
|
|
$comment = array_pop( $_c );
|
|
|
|
/* Permission test */
|
|
$can = $this->can('visibility', array( 'comment_id' => $commentId, 'comment_parent_id' => $parentId ) );
|
|
|
|
if ( $can !== true )
|
|
{
|
|
throw new Exception( $can );
|
|
}
|
|
|
|
$cids = array( $commentId );
|
|
}
|
|
else if ( is_array( $commentId ) )
|
|
{
|
|
/* Permission test */
|
|
$can = $this->can('visibility', array( 'comment_parent_id' => $parentId ) );
|
|
|
|
if ( $can !== true )
|
|
{
|
|
throw new Exception( $can );
|
|
}
|
|
|
|
/* Finalize comment Ids */
|
|
$this->DB->build( array( 'select' => '*',
|
|
'from' => $this->table(),
|
|
'where' => $_remap['comment_id'] . ' IN (' . implode( ",", IPSLib::cleanIntArray( $commentId ) ) . ') AND ' . $_remap['comment_parent_id'] . '=' . $parent['parent_id'] ) );
|
|
|
|
$this->DB->execute();
|
|
|
|
while( $row = $this->DB->fetch() )
|
|
{
|
|
$cids[] = $row[ $_remap['comment_id'] ];
|
|
}
|
|
}
|
|
|
|
/* If we have anything.. */
|
|
if ( count( $cids ) )
|
|
{
|
|
/* Update array */
|
|
$array = array( 'comment_approved' => ( $toggle == 'on' ? 1 : 0 ) );
|
|
|
|
/* Pre save */
|
|
$update = $this->preVisibility( $toggle, $cids, $parentId, $array );
|
|
|
|
/* Insert and fetch DB */
|
|
$save = $this->remapToLocal( $update );
|
|
|
|
/* Update */
|
|
$this->DB->update( $this->table(), $save, $_remap['comment_id'] . ' IN (' . implode( ",", $cids ) . ')' );
|
|
|
|
/* Post delete */
|
|
$this->postVisibility( $toggle, $cids, $parentId );
|
|
}
|
|
|
|
/* Return count deleted */
|
|
return count( $cids );
|
|
}
|
|
|
|
/**
|
|
* Display a comment edit form suitable for ajax
|
|
*
|
|
* @param int Image ID of parent
|
|
* @param int Comment ID
|
|
* @param array Member Data of current member
|
|
* @reutrn html
|
|
* EXCEPTIONS
|
|
* MISSING_DATA Ids missing
|
|
* NO_PERMISSION No permission
|
|
*/
|
|
public function fetchReply( $parentId, $commentId, $memberData )
|
|
{
|
|
/* Init */
|
|
if ( is_numeric( $memberData ) )
|
|
{
|
|
$memberData = IPSMember::load( $memberData, 'all' );
|
|
}
|
|
|
|
/* Check */
|
|
if ( ! $parentId OR ! $commentId )
|
|
{
|
|
throw new Exception('MISSING_DATA');
|
|
}
|
|
|
|
/* Fetch and check image */
|
|
$parent = $this->fetchParent( $parentId );
|
|
|
|
/* Parent */
|
|
$parent = $this->remapFromLocal( $parent, 'parent' );
|
|
|
|
/* Fetch comment */
|
|
$_c = $this->fetch( $parent, array( 'comment_id' => $commentId ) );
|
|
$comment = array_pop( $_c );
|
|
|
|
/* Permission test */
|
|
$can = $this->can('view', array( 'comment_id' => $commentId, 'comment_parent_id' => $parentId ) );
|
|
|
|
if ( $can !== true )
|
|
{
|
|
throw new Exception( $can );
|
|
}
|
|
|
|
if ( $this->settings['strip_quotes'] )
|
|
{
|
|
$comment['comment']['comment_text'] = IPSText::getTextClass( 'bbcode' )->stripQuotes( $comment['comment']['_db_comment'] );
|
|
}
|
|
|
|
$reply = "[quote name='" . IPSText::getTextClass('bbcode')->makeQuoteSafe( $comment['author']['members_display_name'] ) . "' timestamp='" . $comment['comment']['comment_date'] . "']<br />{$comment['comment']['comment_text']}<br />[/quote]<br /><br />";
|
|
|
|
/* Throw, fetch and wag tail */
|
|
return $reply;
|
|
}
|
|
|
|
|
|
/**
|
|
* Display a comment edit form suitable for ajax
|
|
*
|
|
* @param int Image ID of parent
|
|
* @param int Comment ID
|
|
* @param array Member Data of current member
|
|
* @param string Type: html or ajax
|
|
* @reutrn html
|
|
* EXCEPTIONS
|
|
* MISSING_DATA Ids missing
|
|
* NO_PERMISSION No permission
|
|
*/
|
|
public function displayEditForm( $parentId, $commentId, $memberData, $type='html' )
|
|
{
|
|
/* Init */
|
|
if ( is_numeric( $memberData ) )
|
|
{
|
|
$memberData = IPSMember::load( $memberData, 'all' );
|
|
}
|
|
|
|
/* Check */
|
|
if ( ! $memberData['member_id'] OR ! $parentId OR ! $commentId )
|
|
{
|
|
throw new Exception('MISSING_DATA');
|
|
}
|
|
|
|
/* Fetch and check image */
|
|
$parent = $this->fetchParent( $parentId );
|
|
|
|
/* Parent */
|
|
$parent = $this->remapFromLocal( $parent, 'parent' );
|
|
|
|
/* Fetch comment */
|
|
$_c = $this->fetch( $parent, array( 'comment_id' => $commentId ) );
|
|
$comment = array_pop( $_c );
|
|
|
|
/* Permission test */
|
|
$can = $this->can('edit', array( 'comment_id' => $commentId, 'comment_parent_id' => $parentId ) );
|
|
|
|
if ( $can !== true )
|
|
{
|
|
throw new Exception( $can );
|
|
}
|
|
|
|
IPSText::getTextClass('bbcode')->parse_html = 0;
|
|
IPSText::getTextClass('bbcode')->parse_nl2br = 1;
|
|
IPSText::getTextClass('bbcode')->parse_smilies = 1;
|
|
IPSText::getTextClass('bbcode')->parse_bbcode = 1;
|
|
IPSText::getTextClass('bbcode')->parsing_section = $this->bbcodeSection();
|
|
|
|
/* Ayjacks? */
|
|
if ( $type == 'ajax' )
|
|
{
|
|
/* Throw, fetch and wag tail */
|
|
return $this->registry->getClass('output')->getTemplate('editors')->ajaxEditBox( $comment['comment']['_db_comment'], $commentId, array(), array( 'showEditOptions' => false, 'checkBoxes' => false, 'skipFullButton' => true, 'autoSaveKey' => 'comment-' . $this->table() . '-c' . $commentId ) );
|
|
}
|
|
else
|
|
{
|
|
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/editor/composite.php', 'classes_editor_composite' );
|
|
$editor = new $classToLoad();
|
|
|
|
$_editor = $editor->show( 'Post', array( 'type' => 'mini', 'autoSaveKey' => 'comment-' . $this->table() . '-c' . $commentId, 'warnInfo' => 'fastReply' ), $comment['comment']['_db_comment'] );
|
|
|
|
$settings = array( 'fromApp' => $this->whoAmI(),
|
|
'thisApp' => preg_replace( '#^(.+?)(?:-.*|$)#', '\\1', $this->whoAmI() ),
|
|
'baseUrl' => "app=core&module=global&section=comments&parentId={$parent['parent_id']}&fromApp=" . $this->whoAmI(),
|
|
'formAction' => $this->settings['base_url'],
|
|
'formApp' => 'core',
|
|
'formModule' => 'global',
|
|
'formSection' => 'comments' );
|
|
|
|
/* Give plugin a chance to adjust */
|
|
$adjusted = $this->preOutputAdjustment( 'form', array( 'comment' => $comment, 'parent' => $parent, '_editor' => $_editor, 'settings' => $settings, 'errors' => array(), 'do' => 'saveEdit' ) );
|
|
|
|
return $this->registry->getClass('output')->getTemplate( $this->skin() )->form( $adjusted['comment'], $adjusted['parent'], $adjusted['_editor'], $adjusted['settings'], $adjusted['errors'], $adjusted['do'] );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Display a comment edit form suitable for ajax
|
|
*
|
|
* @param int Image ID of parent
|
|
* @param int Comment ID
|
|
* @param array Member Data of current member
|
|
* @reutrn html
|
|
* EXCEPTIONS
|
|
* MISSING_DATA Ids missing
|
|
* NO_PERMISSION No permission
|
|
*/
|
|
public function displayAjaxEditForm( $parentId, $commentId, $memberData )
|
|
{
|
|
try
|
|
{
|
|
return $this->displayEditForm( $parentId, $commentId, $memberData, 'ajax' );
|
|
}
|
|
catch( Exception $e )
|
|
{
|
|
throw new Exception( $e->getMessage() );
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Redirects to the latest comment
|
|
*
|
|
* @param int Comment ID
|
|
* @param int Parent ID
|
|
* @param bool Did we just add a comment that requires approval?
|
|
* @return @e void [Redirects]
|
|
*/
|
|
public function redirectToComment( $commentId, $parentId, $showApprovalMessage=false )
|
|
{
|
|
/* Init */
|
|
$parentId = intval( $parentId );
|
|
|
|
if( !$parentId )
|
|
{
|
|
$this->registry->output->showError( 'nocomment_found', 110102.111 );
|
|
}
|
|
|
|
$parent = $this->fetchParent( $parentId );
|
|
$_remap = $this->remapKeys();
|
|
|
|
/* Parent */
|
|
$parent = $this->remapFromLocal( $parent, 'parent' );
|
|
|
|
/* fetch */
|
|
$q = ( $this->can( 'moderate', array( 'comment_parent_id' => $parent['parent_id'] ) ) === true ) ? '' : ' AND ' . $_remap['comment_approved'] . '=1';
|
|
|
|
/* Fetch comment */
|
|
if ( $commentId == 'last' )
|
|
{
|
|
$comment = $this->DB->buildAndFetch( array( 'select' => '*',
|
|
'from' => $this->table(),
|
|
'where' => $_remap['comment_parent_id'] . '='. $parentId . $q,
|
|
'order' => $_remap['comment_id'] . ' DESC',
|
|
'limit' => array( 0, 1 ) ) );
|
|
}
|
|
else
|
|
{
|
|
$comment = $this->DB->buildAndFetch( array( 'select' => '*',
|
|
'from' => $this->table(),
|
|
'where' => $_remap['comment_id'] . '='. intval( $commentId ) . $q,
|
|
'limit' => array( 0, 1 ) ) );
|
|
}
|
|
|
|
/* got a comment? */
|
|
if ( ! is_array( $comment ) )
|
|
{
|
|
$this->registry->output->silentRedirect( $this->settings['base_url'] . sprintf( $this->fetchSetting('urls-showParent', $parent), $parentId ) );
|
|
}
|
|
|
|
/* Permission test */
|
|
$can = $this->can('view', array( 'comment_id' => $comment['comment_id'], 'comment_parent_id' => $parentId ) );
|
|
|
|
if ( $can !== true )
|
|
{
|
|
throw new Exception( $can );
|
|
}
|
|
|
|
/* Fetch total */
|
|
$total = $this->DB->buildAndFetch( array( 'select' => 'count(*) as total',
|
|
'from' => $this->table(),
|
|
'where' => $_remap['comment_parent_id'] . '=' . $parentId . $q . ' AND ' . $_remap['comment_id'] . '<=' . intval( $comment[ $_remap['comment_id'] ] ) ) );
|
|
|
|
if ( $total['total'] > $this->perPage() )
|
|
{
|
|
if ( $total['total'] % $this->perPage() == 0 )
|
|
{
|
|
$pages = $total['total'] / $this->perPage();
|
|
}
|
|
else
|
|
{
|
|
$number = ( $total['total'] / $this->perPage() );
|
|
$pages = ceil( $number);
|
|
}
|
|
|
|
$st = ($pages - 1) * $this->perPage();
|
|
|
|
if( $showApprovalMessage )
|
|
{
|
|
$this->registry->output->redirectScreen( $this->lang->words['comment_approval_required'], $this->settings['base_url'] . sprintf( $this->fetchSetting('urls-showParent', $parent), $parentId ) . "&st=" . $st . '#comment_' . $comment[ $_remap['comment_id'] ], $parent['parent_seo_title'], $this->seoTemplate() );
|
|
}
|
|
else
|
|
{
|
|
$this->registry->output->silentRedirect( $this->settings['base_url'] . sprintf( $this->fetchSetting('urls-showParent', $parent), $parentId ) . "&st=" . $st . '#comment_' . $comment[ $_remap['comment_id'] ], $parent['parent_seo_title'], false, $this->seoTemplate() );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( $showApprovalMessage )
|
|
{
|
|
$this->registry->output->redirectScreen( $this->lang->words['comment_approval_required'], $this->settings['base_url'] . sprintf( $this->fetchSetting('urls-showParent', $parent), $parentId ) . "&st=0#comment_" . $comment[ $_remap['comment_id'] ], $parent['parent_seo_title'], $this->seoTemplate() );
|
|
}
|
|
else
|
|
{
|
|
$this->registry->output->silentRedirect( $this->settings['base_url'] . sprintf( $this->fetchSetting('urls-showParent', $parent), $parentId ) . "&st=0#comment_" . $comment[ $_remap['comment_id'] ], $parent['parent_seo_title'], false, $this->seoTemplate() );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remap for local
|
|
* Accepts a standard array of data
|
|
*
|
|
* @param array Array of GENERIC formatted data
|
|
* @return @e void
|
|
*/
|
|
public function remapToLocal( array $array, $type='comment' )
|
|
{
|
|
/* Return */
|
|
$return = array();
|
|
$_remap = $this->remapKeys( $type );
|
|
|
|
/* Please; continue */
|
|
foreach( $array as $k => $v )
|
|
{
|
|
if ( isset( $_remap[ $k ] ) )
|
|
{
|
|
$return[ $_remap[ $k ] ] = $v;
|
|
}
|
|
else
|
|
{
|
|
$return[ $k ] = $v;
|
|
}
|
|
}
|
|
|
|
return $return;
|
|
}
|
|
|
|
/**
|
|
* Remap for generic
|
|
* Accepts a standard array of data
|
|
*
|
|
* @param array Array of LOCAL data
|
|
* @return @e void
|
|
*/
|
|
public function remapFromLocal( array $array, $type='comment' )
|
|
{
|
|
/* Return */
|
|
$return = array();
|
|
$_remap = array_flip( $this->remapKeys( $type ) );
|
|
|
|
/* Please; continue */
|
|
foreach( $array as $k => $v )
|
|
{
|
|
if ( isset( $_remap[ $k ] ) )
|
|
{
|
|
$return[ $_remap[ $k ] ] = $v;
|
|
}
|
|
else
|
|
{
|
|
$return[ $k ] = $v;
|
|
}
|
|
}
|
|
|
|
return $return;
|
|
}
|
|
|
|
/**
|
|
* Parent SEO template
|
|
*
|
|
* @return string
|
|
*/
|
|
public function seoTemplate()
|
|
{
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* Section parsing for BBCode routines
|
|
*
|
|
* @return string
|
|
*/
|
|
public function bbcodeSection()
|
|
{
|
|
return 'global_comments';
|
|
}
|
|
|
|
/**
|
|
* Enable reputation?
|
|
*
|
|
* @return string
|
|
*/
|
|
public function reputationEnabled()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Number of items per page
|
|
*
|
|
* @return int
|
|
*/
|
|
public function perPage()
|
|
{
|
|
return 10;
|
|
}
|
|
|
|
/**
|
|
* Skin class
|
|
*
|
|
* @return string
|
|
*/
|
|
public function skin()
|
|
{
|
|
return 'global_comments';
|
|
}
|
|
|
|
/**
|
|
* Adjust parameters
|
|
*
|
|
* @param string Skin template being called
|
|
* @param array Array of parameters to be passed to skin template
|
|
* @return array Skin parameters to be passed to template (array keys MUST be preserved)
|
|
*/
|
|
public function preOutputAdjustment( $template, $params )
|
|
{
|
|
return $params;
|
|
}
|
|
|
|
/**
|
|
* Adjust where clause parameters for fetch query
|
|
*
|
|
* @param array Array of where clause parameters
|
|
* @param array Remapped columns used in the query
|
|
* @param array Parent data
|
|
* @param array Filters to use in the query
|
|
* @return array Array of where clause parameters
|
|
*/
|
|
public function alterFetchQuery( $q, $remap, $parent, $filters )
|
|
{
|
|
return $q;
|
|
}
|
|
|
|
/**
|
|
* Pre save
|
|
* Accepts an array of GENERIC data and allows manipulation before it's added to DB
|
|
*
|
|
* @param string $type Type of save (edit/add)
|
|
* @param array $array Array of GENERIC data (comment_xxxx)
|
|
* @param integer $commentId Comment ID (only for edits)
|
|
* @param integer $parentId Parent content ID
|
|
* @return @e array Array of GENERIC data
|
|
*/
|
|
public function preSave( $type, array $array )
|
|
{
|
|
return $array;
|
|
}
|
|
|
|
/**
|
|
* Post save
|
|
* Accepts an array of GENERIC data and allows manipulation after it's added to DB
|
|
*
|
|
* @param string Type of action (edit/add)
|
|
* @param array Array of GENERIC data (comment_xxxx)
|
|
* @return nowt lad
|
|
*/
|
|
public function postSave( $type, array $array )
|
|
{
|
|
return $array;
|
|
}
|
|
|
|
/**
|
|
* Pre Visibility
|
|
* Pre-DB-save function before visibility is toggled
|
|
*
|
|
* @param string on/off
|
|
* @param array Array of comment IDs to be deleted
|
|
* @param int Parent ID
|
|
* @param array Array of db fields => data to be updated
|
|
*/
|
|
public function preVisibility( $toggle, $commentIds, $parentId, array $update )
|
|
{
|
|
return $update;
|
|
}
|
|
|
|
/**
|
|
* Post Visibility
|
|
* Pre-DB-save function before visibility is toggled
|
|
*
|
|
* @param string on/off
|
|
* @param array Array of comment IDs to be deleted
|
|
* @param int Parent ID
|
|
*/
|
|
public function postVisibility( $toggle, $commentIds, $parentId )
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Pre delete. Can do stuff and that
|
|
*
|
|
* @param array Array of comment IDs to be deleted
|
|
* @param int Parent ID
|
|
* @return nowt lad
|
|
*/
|
|
public function preDelete( $commentIds, $parentId )
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Post delete. Can do stuff and that
|
|
*
|
|
* @param array Array of comment IDs to be deleted
|
|
* @param int Parent ID
|
|
* @return nowt lad
|
|
*/
|
|
public function postDelete( $commentIds, $parentId )
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Perform a permission check
|
|
*
|
|
* @param string Type of check (add/edit/delete/editall/deleteall/approve all)
|
|
* @param array Array of GENERIC data
|
|
* @return true or string to be used in exception
|
|
*/
|
|
public function can( $type, array $array )
|
|
{
|
|
/* Default, so return least permissive */
|
|
return 'NO_PERMISSION';
|
|
}
|
|
/**
|
|
* Unpack the repuation cache, yo.
|
|
*
|
|
* @return @e void
|
|
*/
|
|
protected function _unpackRepCache()
|
|
{
|
|
if ( $this->settings['reputation_enabled'] )
|
|
{
|
|
/* Load the class */
|
|
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/class_reputation_cache.php', 'classReputationCache' );
|
|
$this->registry->setClass( 'repCache', new $classToLoad() );
|
|
|
|
/* Update the filter? */
|
|
if( isset( $this->request['rep_filter'] ) && $this->request['rep_filter'] == 'update' )
|
|
{
|
|
$_mem_cache = IPSMember::unpackMemberCache( $this->memberData['members_cache'] );
|
|
|
|
if( $this->request['rep_filter_set'] == '*' )
|
|
{
|
|
$_mem_cache['rep_filter'] = '*';
|
|
}
|
|
else
|
|
{
|
|
$_mem_cache['rep_filter'] = intval( $this->request['rep_filter_set'] );
|
|
}
|
|
|
|
IPSMember::packMemberCache( $this->memberData['member_id'], $_mem_cache );
|
|
|
|
$this->memberData['_members_cache'] = $_mem_cache;
|
|
}
|
|
else
|
|
{
|
|
$this->memberData['_members_cache'] = IPSMember::unpackMemberCache( $this->memberData['members_cache'] );
|
|
}
|
|
|
|
$this->memberData['_members_cache']['rep_filter'] = isset( $this->memberData['_members_cache']['rep_filter'] ) ? $this->memberData['_members_cache']['rep_filter'] : '*';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set filters
|
|
* Takes user input and cleans it up a bit
|
|
*
|
|
* @param array Incoming filters
|
|
* @return array
|
|
*/
|
|
protected function _setFilters( $filters )
|
|
{
|
|
/* Do some set up */
|
|
switch( $filters['sortKey'] )
|
|
{
|
|
case 'post_date':
|
|
case 'date':
|
|
case 'time':
|
|
$filters['sortKey'] = 'comment_date';
|
|
break;
|
|
case 'author':
|
|
case 'author_id':
|
|
$filters['sortKey'] = 'comment_author_id';
|
|
break;
|
|
|
|
default:
|
|
if ( !$filters['sortKey'] )
|
|
{
|
|
$filters['sortKey'] = 'comment_date';
|
|
}
|
|
break;
|
|
}
|
|
|
|
switch( $filters['sortOrder'] )
|
|
{
|
|
case 'desc':
|
|
case 'descending':
|
|
case 'z-a':
|
|
$filters['sortOrder'] = 'desc';
|
|
break;
|
|
default:
|
|
case 'asc':
|
|
case 'ascending':
|
|
case 'a-z':
|
|
$filters['sortOrder'] = 'asc';
|
|
break;
|
|
}
|
|
|
|
/* Others */
|
|
$filters['offset'] = intval( $filters['offset'] );
|
|
$filters['limit'] = intval( $filters['limit'] );
|
|
$filters['unixCutOff'] = intval( $filters['unixCutOff'] );
|
|
|
|
/* Make sure we have a limit */
|
|
if ( ! $filters['limit'] )
|
|
{
|
|
$filters['limit'] = $this->perPage();
|
|
}
|
|
|
|
/* So we don't have to do this twice */
|
|
$filters['_cleaned'] = true;
|
|
|
|
return $filters;
|
|
}
|
|
} |