* Invision Power Services * IP.Board v3.3.4 * Moderator actions * Last Updated: $Date: 2012-06-27 12:46:44 -0400 (Wed, 27 Jun 2012) $ * * * @author $Author: AndyMillne $ * @copyright (c) 2001 - 2009 Invision Power Services, Inc. * @license http://www.invisionpower.com/company/standards.php#license * @package IP.Board * @subpackage Forums * @link http://www.invisionpower.com * @version $Revision: 10995 $ * */ if ( ! defined( 'IN_IPB' ) ) { print "

Incorrect access

You cannot access this file directly. If you have recently upgraded, make sure you upgraded all the relevant files."; exit(); } class moderatorLibrary { /** * Moderator information * * @var array Array of moderator details */ public $moderator = array(); /** * Forum information * * @var array Array of forum details */ public $forum = array(); /** * Topic information * * @var array Array of topic details */ public $topic = array(); /** * Error code encountered * * @var string Error code */ public $error = ""; /** * Stored statement * * @var string Stored multi-mod statement */ public $stm = ""; /**#@+ * Registry Object Shortcuts * * @var object */ protected $registry; protected $DB; protected $settings; protected $request; protected $lang; protected $member; protected $memberData; protected $cache; protected $caches; /**#@-*/ /** * Class entry point * * @param object Registry reference * @return @e void */ public function __construct( ipsRegistry $registry ) { /* 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(); /* Check for class_forums */ if ( ipsRegistry::isClassLoaded('class_forums') !== TRUE ) { $classToLoad = IPSLib::loadLibrary( IPSLib::getAppDir( 'forums' ) . "/sources/classes/forums/class_forums.php", 'class_forums', 'forums' ); $this->registry->setClass( 'class_forums', new $classToLoad( $registry ) ); $this->registry->class_forums->forumsInit(); } /* Init */ if ( ! $this->registry->isClassLoaded('topics') ) { $classToLoad = IPSLib::loadLibrary( IPSLib::getAppDir( 'forums' ) . "/sources/classes/topics.php", 'app_forums_classes_topics', 'forums' ); $this->registry->setClass( 'topics', new $classToLoad( $this->registry ) ); } /* Load tagging stuff */ if ( ! $this->registry->isClassLoaded('tags') ) { require_once( IPS_ROOT_PATH . 'sources/classes/tags/bootstrap.php' );/*noLibHook*/ $this->registry->setClass( 'tags', classes_tags_bootstrap::run( 'forums', 'topics' ) ); } } /** * Initialization * * @param array Forum array * @param array [Optional] Topic array * @param array [Optional] Moderator array * @return boolean True */ public function init($forum="", $topic="", $moderator="") { $this->forum = $forum; if ( is_array($topic) ) { $this->topic = $topic; } if ( is_array($moderator) ) { $this->moderator = $moderator; } return true; } /** * Toggle approve status of content by a member * WARNING: This is a utility function. No permission checks are performed. * * @param int Member ID (topic starter / post author) * @param boolean TRUE = approve, FALSE = unapprove * @param string Option [ topics / replies / all ] * @param int [ Optional: last X hours worth of data ] * @return boolean */ public function toggleApproveMemberContent( $memberID, $approve=FALSE, $option, $date=0 ) { $memberID = intval( $memberID ); $date = intval( $date ); $timeCut = ( $date ) ? ( time() - ( $date * 3600 ) ) : 0; $topicFind = ''; $postFind = ''; $forumIDs = array(); $topicIDs = array(); $followTids = array(); if ( ! $memberID ) { return FALSE; } switch ( $option ) { default: case 'all': case 'both': case 'topics': $postFind = 'author_id=' . $memberID . ' AND new_topic=0'; $postFind .= ( $timeCut ) ? ' AND post_date > ' . $timeCut : ''; $topicFind = 'starter_id=' . $memberID; $topicFind .= ( $timeCut ) ? ' AND start_date > ' . $timeCut : ''; break; case 'replies': case 'posts': $postFind = 'author_id=' . $memberID . ' AND new_topic=0'; $postFind .= ( $timeCut ) ? ' AND post_date > ' . $timeCut : ''; break; } //----------------------------------------- // Find forums.. //----------------------------------------- if ( $topicFind ) { $this->DB->build( array( 'select' => $this->DB->buildDistinct( 'forum_id' ) . ',tid', 'from' => 'topics', 'where' => $topicFind ) ); $this->DB->execute(); while( $row = $this->DB->fetch() ) { $forumIDs[ $row['forum_id'] ] = $row['forum_id']; $topicIDs[ $row['tid'] ] = $row['tid']; $followTids[ $row['tid'] ] = $row['tid']; } } if ( $postFind ) { $this->DB->build( array( 'select' => $this->DB->buildDistinct( 't.forum_id' ) . ',t.tid', 'from' => array( 'posts' => 'p' ), 'where' => $postFind, 'add_join' => array( array( 'select' => '', 'from' => array( 'topics' => 't' ), 'where' => 'p.topic_id=t.tid' ) ) ) ); $this->DB->execute(); while( $row = $this->DB->fetch() ) { $forumIDs[ $row['forum_id'] ] = $row['forum_id']; $topicIDs[ $row['tid'] ] = $row['tid']; } } //----------------------------------------- // Run... //----------------------------------------- if ( $topicFind AND count($topicIDs) ) { $this->DB->update( 'topics', array( 'approved' => ( $approve === TRUE ) ? 1 : 0 ), $topicFind ); /* Tagging */ $this->registry->tags->updateVisibilityByMetaId( $topicIDs, ( $approve === TRUE ? 1 : 0 ) ); /* Likes */ if ( count( $followTids ) ) { require_once( IPS_ROOT_PATH . 'sources/classes/like/composite.php' );/*noLibHook*/ $_like = classes_like::bootstrap( 'forums', 'topics' ); $_like->toggleVisibility( $followTids, $approve ); } } if ( $postFind ) { $this->DB->update( 'posts', array( 'queued' => ( $approve === TRUE ) ? 0 : 1 ), $postFind ); } if ( count( $topicIDs ) ) { foreach( $topicIDs as $id ) { $this->rebuildTopic( $id ); } } if ( count( $forumIDs ) ) { foreach( $forumIDs as $id ) { $this->forumRecount( $id ); } } $this->cache->rebuildCache( 'stats', 'global' ); return TRUE; } /** * Delete content by a member * WARNING: This is a utility function. No permission checks are performed. * * @param int Member ID (topic starter / post author) * @param string Option [ topics / replies / all ] * @param int [ Optional: last X hours worth of data ] * @return boolean */ public function deleteMemberContent( $memberID, $option, $date=0 ) { $memberID = intval( $memberID ); $date = intval( $date ); $timeCut = ( $date ) ? ( time() - ( $date * 3600 ) ) : 0; $topicFind = ''; $postFind = ''; $topicIDs = array(); $postIDs = array(); $forumIDs = array(); if ( ! $memberID ) { return FALSE; } switch ( $option ) { default: case 'all': case 'both': case 'topics': $postFind = 'author_id=' . $memberID . ' AND new_topic=0'; $postFind .= ( $timeCut ) ? ' AND post_date > ' . $timeCut : ''; $topicFind = 'starter_id=' . $memberID; $topicFind .= ( $timeCut ) ? ' AND start_date > ' . $timeCut : ''; break; case 'replies': case 'posts': $postFind = 'author_id=' . $memberID . ' AND new_topic=0'; $postFind .= ( $timeCut ) ? ' AND post_date > ' . $timeCut : ''; break; } //----------------------------------------- // Run... //----------------------------------------- if ( $topicFind ) { /* Update the posts to delete */ $this->DB->update( 'topics', array( 'approved' => $this->registry->class_forums->fetchTopicHiddenFlag('pdelete') ), $topicFind ); $this->DB->build( array( 'select' => $this->DB->buildDistinct( 'forum_id' ), 'from' => 'topics', 'where' => $topicFind ) ); $this->DB->execute(); while( $row = $this->DB->fetch() ) { $forumIDs[ $row['forum_id'] ] = $row['forum_id']; } /* Fetch unique topic IDs */ $this->DB->build( array( 'select' => 'tid', 'from' => 'topics', 'where' => $topicFind, 'order' => 'tid DESC', 'limit' => array( 0, 2000 ) ) ); $this->DB->execute(); while( $row = $this->DB->fetch() ) { $tagTopicIDs[] = $row['tid']; } if ( count( $tagTopicIDs ) ) { /* Tagging */ try { $this->registry->tags->updateVisibilityByMetaId( $tagTopicIDs, 0 ); } catch ( Exception $e ) { } /* Likes */ require_once( IPS_ROOT_PATH . 'sources/classes/like/composite.php' );/*noLibHook*/ $_like = classes_like::bootstrap( 'forums', 'topics' ); $_like->toggleVisibility( $tagTopicIDs, false ); } } if ( $postFind ) { /* Update the posts to delete */ $this->DB->update( 'posts', array( 'queued' => $this->registry->class_forums->fetchPostHiddenFlag('pdelete'), 'pdelete_time' => IPS_UNIX_TIME_NOW ), $postFind ); /* Fetch unique forum IDs */ $this->DB->build( array( 'select' => $this->DB->buildDistinct( 't.forum_id' ), 'from' => array( 'topics' => 't' ), 'where' => 'p.author_id=' . $memberID . ' AND p.new_topic=0 AND p.topic_id=t.tid', 'add_join' => array( array( 'select' => '', 'from' => array( 'posts' => 'p' ), 'type' => 'inner' ) ) ) ); $this->DB->execute(); while( $row = $this->DB->fetch() ) { $forumIDs[ $row['forum_id'] ] = $row['forum_id']; } /* Fetch unique topic IDs */ $this->DB->build( array( 'select' => $this->DB->buildDistinct( 'topic_id' ), 'from' => 'posts', 'where' => $postFind, 'order' => 'topic_id DESC', 'limit' => array( 0, 2000 ) ) ); $this->DB->execute(); while( $row = $this->DB->fetch() ) { $topicIDs[ $row['topic_id'] ] = $row['topic_id']; } } //----------------------------------------- // Delete topics... //----------------------------------------- if ( is_array( $topicIDs ) AND count( $topicIDs ) ) { foreach( $topicIDs as $id ) { $this->rebuildTopic( $id, 0 ); } } if ( count( $forumIDs ) ) { foreach( $forumIDs as $id ) { $this->registry->class_forums->allForums[ $id ]['_update_deletion'] = 1; $this->forumRecount( $id ); } } $this->cache->rebuildCache( 'stats', 'global' ); return TRUE; } /** * Delete / undelete posts * * @param array Array of Post IDs * @param boolean Approve (TRUE) / Unapprove (FALSE) * @param int Fix so posts can only come from a specific topic ID * @return boolean */ public function postToggleSoftDelete( $postIDs, $delete=FALSE, $reason='', $topicIDFix=0 ) { //----------------------------------------- // INIT //----------------------------------------- $_restoreTopic = 1; $_deletedPost = 0; $_pdeleteTs = 0; if ( $delete === TRUE ) { $_restoreTopic = -1; $_deletedPost = 2; $_pdeleteTs = IPS_UNIX_TIME_NOW; } $_topics = array(); $_forumIDs = array(); $_pids = IPSLib::cleanIntArray( $postIDs ); $_tids = array(); //----------------------------------------- // Fetch distinct topic IDs //----------------------------------------- $this->DB->build( array( 'select' => $this->DB->buildDistinct( 'p.topic_id' ), 'from' => array( 'posts' => 'p' ), 'where' => 'p.pid IN (' . implode( ',', $postIDs ) . ')', 'add_join' => array( array( 'select' => 't.*', 'from' => array( 'topics' => 't' ), 'where' => 'p.topic_id=t.tid', 'type' => 'inner' ) ) ) ); $this->DB->execute(); while( $row = $this->DB->fetch() ) { $_topics[ $row['topic_id'] ] = $row; } //----------------------------------------- // Did we get the first post too? //----------------------------------------- foreach( $_topics as $tid => $topicData ) { /* Fix to a topic? */ if ( $topicIDFix AND ( $topicIDFix != $tid ) ) { continue; } if ( $this->registry->getClass('topics')->isArchived( $topicData ) ) { continue; } $_forumIDs[] = $topicData['forum_id']; if ( in_array( $topicData['topic_firstpost'], $_pids ) ) { $this->DB->update( 'topics', array( 'approved' => $_restoreTopic ), 'tid=' . $tid ); $tmp = $_pids; $_pids = array(); foreach( $tmp as $t ) { if ( $t != $topicData['topic_firstpost'] ) { $_pids[] = $t; } else { $_tids[ $topicData['tid'] ] = $topicData['tid']; } } } } if ( count( $_pids ) ) { $this->DB->update( 'posts', array( 'queued' => $_deletedPost, 'pdelete_time' => $_pdeleteTs ), 'pid IN (' . implode( ",", $_pids ) . ')' ); if ( $_deletedPost ) { foreach( $_pids as $_p ) { /* Add entry to delete log innit */ IPSDeleteLog::addEntry( $_p, 'post', $reason, $this->memberData ); } } else { /* Un-deleting, so delete */ IPSDeleteLog::removeEntries( $_pids, 'post' ); } } if ( count( $_tids ) ) { if ( $_deletedPost ) { foreach( $_tids as $_t ) { IPSDeleteLog::addEntry( $_t, 'topic', $reason, $this->memberData ); } } else { /* Un-deleting, so delete */ IPSDeleteLog::removeEntries( $_tids, 'topic' ); } } if ( $delete ) { /* Delete from recent posts */ $this->registry->topics->deleteRecentPost( array( 'post_id' => $_pids ) ); foreach( $_topics as $tid => $topicData ) { $this->addModerateLog( $topicData['forum_id'], $tid, 0, $topicData['title'], sprintf( $this->lang->words['acp_softdeleted_posts'], count( $_pids ), $topicData['title'] ) ); } /* Run moderation sync */ $this->runModSync( 'postHide', $_pids ); } else { /* Restore from recent posts */ $this->registry->topics->restoreRecentPost( array( 'post_id' => $_pids ) ); foreach( $_topics as $tid => $topicData ) { $this->addModerateLog( $topicData['forum_id'], $tid, 0, $topicData['title'], sprintf( $this->lang->words['acp_unsoftdeleted_posts'], count( $_pids ), $topicData['title'] ) ); } /* Run moderation sync */ $this->runModSync( 'postUnhide', $_pids ); } foreach( $_topics as $tid => $topicData ) { $this->rebuildTopic( $tid ); } if ( count( $_forumIDs ) ) { foreach( $_forumIDs as $_fid ) { $this->forumRecount( $_fid ); } } $this->cache->rebuildCache( 'stats', 'global' ); return TRUE; } /** * Approve / unapprove posts * * @param array Array of Post IDs * @param boolean Approve (TRUE) / Unapprove (FALSE) * @param int Fix so posts can only come from a specific topic ID * @return boolean */ public function postToggleApprove( $postIDs, $approve=FALSE, $topicIDFix=0 ) { //----------------------------------------- // INIT //----------------------------------------- $_approveTopic = 1; $_queuedPost = 0; if ( $approve === FALSE ) { $_approveTopic = 0; $_queuedPost = 1; } $_topics = array(); $_forumIDs = array(); $_pids = IPSLib::cleanIntArray( $postIDs ); $_tids = array(); //----------------------------------------- // Fetch distinct topic IDs //----------------------------------------- $this->DB->build( array( 'select' => $this->DB->buildDistinct( 'p.topic_id' ) . ', p.author_id, p.author_name, p.post', 'from' => array( 'posts' => 'p' ), 'where' => 'p.pid IN (' . implode( ',', $postIDs ) . ')', 'add_join' => array( array( 'select' => 't.*', 'from' => array( 'topics' => 't' ), 'where' => 'p.topic_id=t.tid', 'type' => 'inner' ) ) ) ); $this->DB->execute(); while( $row = $this->DB->fetch() ) { $_topics[ $row['topic_id'] ] = $row; } //----------------------------------------- // Did we get the first post too? //----------------------------------------- foreach( $_topics as $tid => $topicData ) { /* Fix to a topic? */ if ( $topicIDFix AND ( $topicIDFix != $tid ) ) { continue; } if ( $this->registry->getClass('topics')->isArchived( $topicData ) ) { continue; } $_forumIDs[] = $topicData['forum_id']; if ( in_array( $topicData['topic_firstpost'], $_pids ) ) { $this->DB->update( 'topics', array( 'approved' => $_approveTopic ), 'tid=' . $tid ); /* Need to hide/show tags too */ $this->registry->tags->updateVisibilityByMetaId( $tid, $_approveTopic ); /* Unapprove the topic, but not the first post? */ //if ( $_queuedPost ) //{ $tmp = $_pids; $_pids = array(); foreach( $tmp as $t ) { if ( $t != $topicData['topic_firstpost'] ) { $_pids[] = $t; } else { /* @link http://community.invisionpower.com/tracker/issue-33622-approveunapprove-and-old-posts */ $_pids[] = $t; $_tids[ $topicData['tid'] ] = $topicData['tid']; } } //} } } if ( count( $_pids ) ) { $this->DB->update( 'posts', array( 'queued' => $_queuedPost ), 'pid IN (' . implode( ",", $_pids ) . ')' ); } if ( $approve ) { $this->registry->getClass( 'class_localization')->loadLanguageFile( array( 'public_email_content' ), 'core' ); /* Delete from recent posts */ $this->registry->topics->restoreRecentPost( array( 'post_id' => $_pids ) ); foreach( $_topics as $tid => $topicData ) { $this->addModerateLog( $topicData['forum_id'], $tid, 0, $topicData['title'], sprintf( $this->lang->words['acp_approved_posts'], count( $_pids ), $topicData['title'] ) ); /* Notifications are sent in clearModQueueTable now */ } if( count($_pids) ) { $this->clearModQueueTable( 'post', $_pids, true ); } if( count($_tids) ) { $this->clearModQueueTable( 'topic', $_tids, true ); } } else { /* Delete from recent posts */ $this->registry->topics->deleteRecentPost( array( 'post_id' => $_pids ) ); foreach( $_topics as $tid => $topicData ) { $this->addModerateLog( $topicData['forum_id'], $tid, 0, $topicData['title'], sprintf( $this->lang->words['acp_unapproved_posts'], count( $_pids ), $topicData['title'] ) ); } } foreach( $_topics as $tid => $topicData ) { $this->rebuildTopic( $tid ); } if ( count( $_forumIDs ) ) { foreach( $_forumIDs as $_fid ) { $this->forumRecount( $_fid ); } } $this->cache->rebuildCache( 'stats', 'global' ); return TRUE; } /** * Clear out the mod-queue table appropriately * * @param string [topic|post] Type of item moved * @param mixed ID of topic or post, or array of ids * @param boolean Was content approved? * @return @e void */ public function clearModQueueTable( $type, $typeId, $approved=false ) { //----------------------------------------- // Are we operating on one id, or an array //----------------------------------------- if( is_array($typeId) ) { $where = "type_id IN(" . implode( ',', IPSLib::cleanIntArray($typeId) ) . ")"; } else { $where = "type_id=" . intval($typeId); } //----------------------------------------- // Was content deleted //----------------------------------------- if( ! $approved ) { $this->DB->delete( 'mod_queued_items', "type='{$type}' AND {$where}" ); } //----------------------------------------- // No, then we are approving content //----------------------------------------- else { //----------------------------------------- // Get post class.. //----------------------------------------- require_once( IPSLib::getAppDir( 'forums' ) . '/sources/classes/post/classPost.php' );/*noLibHook*/ $classToLoad = IPSLib::loadLibrary( IPSLib::getAppDir( 'forums' ) . '/sources/classes/post/classPostForms.php', 'classPostForms', 'forums' ); $_postClass = new $classToLoad( $this->registry ); //----------------------------------------- // Working with posts? //----------------------------------------- if( $type == 'post' ) { IPSDebug::fireBug( 'info', array( 'type is post' ) ); $this->DB->build( array( 'select' => 'm.id', 'from' => array( 'mod_queued_items' => 'm' ), 'where' => "m.type='{$type}' AND m.{$where}", 'add_join' => array( array( 'select' => 'p.pid, p.post, p.author_id, p.post_date, p.topic_id', 'from' => array( 'posts' => 'p' ), 'where' => 'p.pid=m.type_id', 'type' => 'left', ), array( 'select' => 't.*', 'from' => array( 'topics' => 't' ), 'where' => 't.tid=p.topic_id', 'type' => 'left', ), ) ) ); $outer = $this->DB->execute(); while( $r = $this->DB->fetch($outer) ) { $member = IPSMember::load( $r['author_id'], 'extendedProfile,groups' ); $_postClass->setPublished( true ); $_postClass->setAuthor( $member ); $_postClass->setForumData( $this->registry->class_forums->allForums[ $r['forum_id'] ] ); $_postClass->incrementUsersPostCount(); $_postClass->sendOutTrackedTopicEmails( $r, $r['post'] ); $this->DB->delete( 'mod_queued_items', 'id=' . $r['id'] ); } } else { IPSDebug::fireBug( 'info', array( 'type is topic' ) ); $this->DB->build( array( 'select' => 'm.id', 'from' => array( 'mod_queued_items' => 'm' ), 'where' => "m.type='{$type}' AND m.{$where}", 'add_join' => array( array( 'select' => 't.*', 'from' => array( 'topics' => 't' ), 'where' => 't.tid=m.type_id', 'type' => 'left', ), array( 'select' => 'p.pid, p.post, p.post_date', 'from' => array( 'posts' => 'p' ), 'where' => 'p.pid=t.topic_firstpost', 'type' => 'left', ), ) ) ); $outer = $this->DB->execute(); while( $r = $this->DB->fetch($outer) ) { $member = IPSMember::load( $r['starter_id'], 'extendedProfile,groups' ); $_postClass->setPublished( true ); $_postClass->setAuthor( $member ); $_postClass->setForumData( $this->registry->class_forums->allForums[ $r['forum_id'] ] ); $_postClass->incrementUsersPostCount(); $_postClass->sendOutTrackedForumEmails( $this->registry->class_forums->getForumById( $r['forum_id'] ), $r, $r['post'] ); $this->DB->delete( 'mod_queued_items', 'id=' . $r['id'] ); } } } } /** * Delete a post * * @param mixed Post id | Array of post ids * @return array Topic IDs */ public function postDelete($id) { $posts = array(); $attach_tid = array(); $attach_ids = array(); $topics = array(); $fids = array(); $this->error = ""; if ( is_array( $id ) ) { $id = IPSLib::cleanIntArray( $id ); if ( count($id) > 0 ) { $pid = " IN(" . implode( ",", $id ) . ")"; } else { return false; } } else { if ( intval($id) ) { $pid = "={$id}"; } else { return false; } } /* Set ids */ $_ids = ( is_array( $id ) ) ? $id : array( $id ); /* Get data */ $this->DB->build( array( 'select' => 'p.pid, p.topic_id, p.new_topic', 'from' => array( 'posts' => 'p' ), 'where' => 'p.pid' . $pid, 'add_join' => array( array( 'select' => 't.*', 'from' => array('topics' => 't' ), 'where' => 'p.topic_id=t.tid' ) ) ) ); $q = $this->DB->execute(); while ( $r = $this->DB->fetch( $q ) ) { if ( ! $this->registry->getClass('topics')->isArchived( $r ) ) { $posts[ $r['pid'] ] = $r['topic_id']; $topics[ $r['topic_id'] ] = 1; } } /* Reset keys */ $pid = " IN(" . implode( ",", array_keys( $posts ) ) . ")"; /* Update the posts to delete */ $this->DB->update( 'posts', array( 'queued' => $this->registry->class_forums->fetchPostHiddenFlag('pdelete'), 'pdelete_time' => IPS_UNIX_TIME_NOW ), 'pid' . $pid ); /* Delete from recent posts */ $this->registry->topics->deleteRecentPost( array( 'post_id' => $_ids ) ); //----------------------------------------- // Update the stats //----------------------------------------- $this->cache->rebuildCache( 'stats', 'global' ); //----------------------------------------- // Update all relevant topics //----------------------------------------- foreach( array_keys($topics) as $tid ) { $this->rebuildTopic( $tid ); } if ( count( $topics ) ) { $this->DB->build( array( 'select' => 'forum_id', 'from' => 'topics', 'where' => 'tid IN (' . implode( ',', array_keys( $topics ) ) . ')' ) ); $i = $this->DB->execute(); while( $row = $this->DB->fetch( $i ) ) { $fids[ $row['forum_id'] ] = $row['forum_id']; } } if ( count( $fids ) ) { foreach( $fids as $f ) { $this->forumRecount( $f ); } } /* Run moderation sync */ $this->runModSync( 'postDelete', array_keys( $posts ) ); //----------------------------------------- // Log and return //----------------------------------------- $pid = str_replace( array( 'IN', '(', ')', '=' ), '', $pid ); $this->addModerateLog( "", "", "", $this->lang->words['mod_from_id'] . ' ' . implode( ',', array_keys($topics) ), sprintf( $this->lang->words['multi_post_delete'], implode( ', ', $_ids ) ) ); return array_keys($topics); } /** * Delete a post * * @param mixed Post id | Array of post ids * @param bool Skip rebuilding stats/forums * @param bool Quick mode (will skip loading data and rebuild - only use if you are processing many posts and will rebuild manually later) * @return array Topic IDs */ public function postDeleteFromDb( $id, $nostats=false, $quick=false ) { $posts = array(); $attach_tid = array(); $attach_ids = array(); $topics = array(); $fids = array(); $this->error = ""; if ( is_array( $id ) ) { $id = IPSLib::cleanIntArray( $id ); if ( count($id) > 0 ) { $pid = " IN(" . implode( ",", $id ) . ")"; } else { return false; } } else { if ( intval($id) ) { $pid = "={$id}"; } else { return false; } } /* Remove from deletion log */ $_ids = ( is_array( $id ) ) ? $id : array( $id ); IPSDeleteLog::removeEntries( $_ids, 'post', TRUE ); //----------------------------------------- // Get Stuff //----------------------------------------- /* Get IDs */ if ( $quick ) { $posts = array_flip( $_ids ); } else { $this->DB->build( array( 'select' => 'p.pid, p.topic_id, p.new_topic', 'from' => array( 'posts' => 'p' ), 'where' => 'p.pid' . $pid, 'add_join' => array( array( 'select' => 't.*', 'from' => array('topics' => 't' ), 'where' => 'p.topic_id=t.tid' ) ) ) ); $q = $this->DB->execute(); while ( $r = $this->DB->fetch( $q ) ) { if ( ! $this->registry->getClass('topics')->isArchived( $r ) ) { $posts[ $r['pid'] ] = $r['topic_id']; $topics[ $r['topic_id'] ] = 1; } } } /* Reset keys */ $pid = " IN(" . implode( ",", array_keys( $posts ) ) . ")"; /* Delete from rep cache */ $this->DB->delete( 'reputation_cache' , "app='forums' AND type='pid' AND type_id" . $pid ); $this->DB->delete( 'reputation_index' , "app='forums' AND type='pid' AND type_id" . $pid ); /* And totals */ foreach( array_keys($posts) as $post ) { $this->DB->delete( 'reputation_totals', "rt_key=MD5('forums;pid;" . $post . "') AND rt_type_id=" . $post ); } /* Delete from recent posts */ $this->registry->topics->deleteRecentPost( array( 'post_id' => array_keys( $posts ) ) ); //----------------------------------------- // Is there an attachment to this post? //----------------------------------------- $classToLoad = IPSLib::loadLibrary( IPSLib::getAppDir( 'core' ) . '/sources/classes/attach/class_attach.php', 'class_attach' ); $class_attach = new $classToLoad( $this->registry ); $class_attach->type = 'post'; $class_attach->init(); $class_attach->bulkRemoveAttachment( array_keys( $posts ) ); //----------------------------------------- // delete the post //----------------------------------------- $this->DB->delete( 'posts', "pid" . $pid ); /* Remove cache content */ IPSContentCache::drop( 'post', array_keys( $posts ) ); //----------------------------------------- // Update all relevant topics //----------------------------------------- if ( !$quick ) { foreach( array_keys($topics) as $tid ) { $this->rebuildTopic( $tid ); } } //----------------------------------------- // Update the stats //----------------------------------------- if( !$nostats and !$quick ) { if ( count( $topics ) ) { $this->DB->build( array( 'select' => 'forum_id', 'from' => 'topics', 'where' => 'tid IN (' . implode( ',', array_keys( $topics ) ) . ')' ) ); $i = $this->DB->execute(); while( $row = $this->DB->fetch( $i ) ) { $fids[ $row['forum_id'] ] = $row['forum_id']; } } if ( count( $fids ) ) { foreach( $fids as $f ) { $this->forumRecount( $f ); } } $this->cache->rebuildCache( 'stats', 'global' ); } /* Run moderation sync */ $this->runModSync( 'postDelete', array_keys( $posts ) ); //----------------------------------------- // Log and return //----------------------------------------- if ( $quick ) { return TRUE; } else { $pid = str_replace( array( 'IN', '(', ')', '=' ), '', $pid ); $this->addModerateLog( "", "", "", $this->lang->words['mod_from_id'] . ' ' . implode( ',', array_keys($topics) ), sprintf( $this->lang->words['multi_post_delete'], implode( ',', $_ids ) ) ); return array_keys($topics); } } /** * Rebuild a topic * * @param integer Topic id * @return boolean Rebuild complete */ public function rebuildTopic( $tid ) { /* Init */ if ( ! $this->registry->isClassLoaded('topics') ) { $classToLoad = IPSLib::loadLibrary( IPSLib::getAppDir( 'forums' ) . "/sources/classes/topics.php", 'app_forums_classes_topics', 'forums' ); $this->registry->setClass( 'topics', new $classToLoad( $this->registry ) ); } $this->registry->topics->rebuildTopic( $tid ); return true; } /** * Add a reply to a topic * * @param string Post contnet * @param array Array of topic ids to apply this reply to * @param boolean Increment post count? * @return boolean Reply added * @deprecated */ public function topicAddReply( $post="", $tids=array(), $incpost=false ) { require_once( IPSLib::getAppDir( 'forums' ) . '/sources/classes/post/classPost.php' );/*noLibHook*/ $classToLoad = IPSLib::loadLibrary( IPSLib::getAppDir( 'forums' ) . '/sources/classes/post/classPostForms.php', 'classPostForms', 'forums' ); $r = TRUE; foreach ( $tids as $row ) { try { $_postClass = new $classToLoad( $this->registry ); $_postClass->setBypassPermissionCheck( true ); $_postClass->setForumId( $row[1] ); $_postClass->setTopicId( $row[0] ); $_postClass->setAuthor( $this->memberData ); $_postClass->setPostContent( $post ); $_postClass->setSettings( array( 'enableSignature' => TRUE, 'enableEmoticons' => TRUE, ) ); $_postClass->setIncrementPostCountFlag( $incpost ? true : false ); $_postClass->addReply(); } catch ( Exception $e ) { $r = FALSE; } } return $r; } /** * Close a topic * * @param integer Topic id * @return boolean */ public function topicClose( $id ) { $this->stmInit(); $this->stmAddClose(); $this->stmExec($id); return TRUE; } /** * Open a topic * * @param integer Topic id * @return boolean */ public function topicOpen($id) { $this->stmInit(); $this->stmAddOpen(); $this->stmExec($id); return TRUE; } /** * Pin a topic * * @param integer Topic id * @return boolean */ public function topicPin($id) { $this->stmInit(); $this->stmAddPin(); $this->stmExec($id); return TRUE; } /** * Unpin a topic * * @param integer Topic id * @return boolean */ public function topicUnpin($id) { $this->stmInit(); $this->stmAddUnpin(); $this->stmExec($id); return TRUE; } /** * Delete a topic * * @param mixed Topic id | Array of topic ids * @param boolean Skip updating the stats * @return boolean */ public function topicDelete( $id, $nostats=0 ) { $posts = array(); $attach = array(); $this->error = ""; $ids = array(); if ( is_array( $id ) ) { $id = IPSLib::cleanIntArray( $id ); if ( count($id) > 0 ) { $ids = $id; $tid = " IN(" . implode( ",", $id ) . ")"; } else { return false; } } else { if ( intval($id) ) { $tid = "={$id}"; $ids = array( $id ); } else { return false; } } /* Set ids */ $_ids = ( is_array( $id ) ) ? $id : array( $id ); /* GET AND EXAMINE */ $topics = $this->registry->topics->getTopics( array( 'topicId' => $_ids, 'archiveState' => array( 'not', 'exclude' ), 'topicType' => array( 'all' ) ) ); if ( ! count( $topics ) ) { return false; } else { $ids = array_keys( $topics ); $tid = " IN(" . implode( ",", $ids ) . ")"; } /* Update the posts to delete */ $this->DB->update( 'topics', array( 'approved' => $this->registry->class_forums->fetchTopicHiddenFlag('pdelete'), 'tdelete_time' => IPS_UNIX_TIME_NOW ), 'tid' . $tid ); /* Delete from recent posts */ $this->registry->topics->deleteRecentPost( array( 'post_topic_id' => $ids ) ); /* Tagging */ $this->registry->tags->updateVisibilityByMetaId( $ids, 0 ); /* Likes */ require_once( IPS_ROOT_PATH . 'sources/classes/like/composite.php' );/*noLibHook*/ $_like = classes_like::bootstrap( 'forums', 'topics' ); $_like->toggleVisibility( $ids, false ); //----------------------------------------- // Recount forum... //----------------------------------------- if ( !$nostats ) { if ( $this->forum['id'] ) { $this->registry->class_forums->allForums[ $this->forum['id'] ]['_update_deletion'] = 1; $this->forumRecount( $this->forum['id'] ); } $this->cache->rebuildCache( 'stats', 'global' ); } /* Run moderation sync */ $this->runModSync( 'topicDelete', $_ids ); return TRUE; } /** * Delete a topic * * @param mixed Topic id | Array of topic ids * @param boolean Skip updating the stats * @return boolean */ public function topicDeleteFromDB( $id, $nostats=0 ) { $posts = array(); $attach = array(); $this->error = ""; $ids = array(); if ( is_array( $id ) ) { $id = IPSLib::cleanIntArray( $id ); if ( count($id) > 0 ) { $ids = $id; $tid = " IN(" . implode( ",", $id ) . ")"; } else { return false; } } else { if ( intval($id) ) { $ids = array( $id ); $tid = "={$id}"; } else { return false; } } /* GET AND EXAMINE */ $topics = $this->registry->topics->getTopics( array( 'topicId' => $ids, 'archiveState' => array( 'not', 'exclude' ), 'topicType' => array( 'all' ) ) ); if ( ! count( $topics ) ) { return false; } else { $ids = array_keys( $topics ); $tid = " IN(" . implode( ",", $ids ) . ")"; } /* Remove from deletion log */ IPSDeleteLog::removeEntries( $ids, 'topic', TRUE ); /* Tagging */ $this->registry->tags->deleteByMetaId( $ids ); /* Delete from recent posts */ $this->registry->topics->deleteRecentPost( array( 'post_topic_id' => $ids ) ); //----------------------------------------- // Remove polls assigned to this topic //----------------------------------------- $this->DB->delete( 'polls', "tid" . $tid ); $this->DB->delete( 'voters', "tid" . $tid ); $this->DB->delete( 'topic_ratings', "rating_tid" . $tid ); $this->DB->delete( 'topic_views', "views_tid" . $tid ); $this->DB->delete( 'topics', "tid" . $tid ); //----------------------------------------- // Like class //----------------------------------------- require_once( IPS_ROOT_PATH . 'sources/classes/like/composite.php' );/*noLibHook*/ $_like = classes_like::bootstrap( 'forums', 'topics' ); $_like->remove( $ids ); //----------------------------------------- // Get PIDS for attachment deletion //----------------------------------------- $this->DB->build( array( 'select' => 'pid', 'from' => 'posts', 'where' => "topic_id" . $tid ) ); $this->DB->execute(); while ( $r = $this->DB->fetch() ) { $posts[] = $r['pid']; } /* Remove cache content */ IPSContentCache::drop( 'post', $posts ); //----------------------------------------- // Remove the attachments //----------------------------------------- $classToLoad = IPSLib::loadLibrary( IPSLib::getAppDir( 'core' ) . '/sources/classes/attach/class_attach.php', 'class_attach' ); $class_attach = new $classToLoad( $this->registry ); $class_attach->type = 'post'; $class_attach->init(); $class_attach->bulkRemoveAttachment( $posts ); //----------------------------------------- // Remove the posts //----------------------------------------- $this->DB->delete( 'posts', "topic_id" . $tid ); if ( count( $posts ) ) { $this->DB->delete( 'reputation_cache' , "app='forums' AND type='pid' AND type_id IN (" . implode( ',', $posts ) . ")"); $this->DB->delete( 'reputation_index' , "app='forums' AND type='pid' AND type_id IN (" . implode( ',', $posts ) . ")" ); $this->DB->delete( 'reputation_totals', "rt_key=MD5('forums;pid') AND rt_type_id IN (" . implode( ',', $posts ) . ")" ); } //----------------------------------------- // Recount forum... //----------------------------------------- if ( !$nostats ) { if ( $this->forum['id'] ) { $this->registry->class_forums->allForums[ $this->forum['id'] ]['_update_deletion'] = 1; $this->forumRecount( $this->forum['id'] ); } $this->cache->rebuildCache( 'stats', 'global' ); } /* Run moderation sync */ $this->runModSync( 'topicDelete', $ids ); return TRUE; } /** * Move a topic * * @param mixed Topic id | Array of topic ids * @param integer Source forum * @param integer Move to forum * @param boolean Leave the 'link' * @return boolean */ public function topicMove($topics, $source=0, $moveto=0, $leavelink=0) { $this->error = ""; $source = intval($source); $moveto = intval($moveto); $forumIDSQL = ( $source ) ? " forum_id={$source} AND " : ''; $ids = array(); if ( is_array( $topics ) ) { $topics = IPSLib::cleanIntArray( $topics ); if ( count($topics) > 0 ) { $tid = " IN(" . implode( ",", $topics ) . ")"; $ids = $topics; } else { return false; } //----------------------------------------- // Mark as read in new forum //----------------------------------------- foreach( $topics as $_tid ) { $this->registry->classItemMarking->markRead( array( 'forumID' => $moveto, 'itemID' => $_tid ), 'forums' ); } } else { if ( intval($topics) ) { $tid = "={$topics}"; $ids = array( $topics ); } else { return false; } //----------------------------------------- // Mark as read in new forum //----------------------------------------- $this->registry->classItemMarking->markRead( array( 'forumID' => $moveto, 'itemID' => $topics ), 'forums' ); } /* GET AND EXAMINE */ $_topics = $this->registry->topics->getTopics( array( 'topicId' => $ids, 'archiveState' => array( 'not', 'exclude' ), 'topicType' => array( 'all' ) ) ); if ( ! count( $_topics ) ) { return false; } else { $ids = array_keys( $_topics ); $tid = " IN(" . implode( ",", $ids ) . ")"; } /* Update recent posts */ $this->registry->topics->updateRecentPost( array( 'post_forum_id' => $moveto ), array( 'post_topic_id' => $ids ) ); //----------------------------------------- // Update the topic //----------------------------------------- $this->DB->update( 'topics', array( 'forum_id' => $moveto ), $forumIDSQL . "tid" . $tid ); //----------------------------------------- // Update the polls //----------------------------------------- $this->DB->update( 'polls', array( 'forum_id' => $moveto ), $forumIDSQL . "tid" . $tid ); //----------------------------------------- // Update the voters //----------------------------------------- $this->DB->update( 'voters', array( 'forum_id' => $moveto ), $forumIDSQL . "tid" . $tid ); //----------------------------------------- // Are we leaving a stink er link? //----------------------------------------- if ( $leavelink AND $source ) { $this->DB->build( array( 'select' => '*', 'from' => 'topics', 'where' => "tid" . $tid ) ); $oq = $this->DB->execute(); while ( $row = $this->DB->fetch($oq) ) { $this->DB->setDataType( array( 'title', 'starter_name', 'last_poster_name', 'seo_last_name' ), 'string' ); $this->DB->insert( 'topics', array ( 'title' => $row['title'], 'state' => 'link', 'posts' => 0, 'views' => 0, 'starter_id' => $row['starter_id'], 'start_date' => $row['start_date'], 'starter_name' => $row['starter_name'], 'seo_first_name' => IPSText::makeSeoTitle( $row['starter_name'] ), 'last_post' => $row['last_post'], 'forum_id' => $source, 'approved' => 1, 'pinned' => 0, 'moved_to' => $row['tid'] . '&' . $moveto, 'moved_on' => time(), 'last_poster_id' => $row['last_poster_id'], 'last_poster_name' => $row['last_poster_name'], 'seo_last_name' => IPSText::makeSeoTitle( $row['starter_name'] ), ) ); } } /* Tagging */ $this->registry->tags->moveTagsToParentId( $ids, $moveto ); //----------------------------------------- // Sort out subscriptions //----------------------------------------- $trid_to_delete = array(); //----------------------------------------- // Like class - remove if you don't have access //----------------------------------------- require_once( IPS_ROOT_PATH . 'sources/classes/like/composite.php' );/*noLibHook*/ $_like = classes_like::bootstrap( 'forums', 'topics' ); $topics = $_like->getDataByRelationshipId( $tid ); if( count($topics) ) { foreach( $topics as $r ) { $perm_id = $r['org_perm_id'] ? $r['org_perm_id'] : $r['g_perm_id']; if ( $this->registry->permissions->check( 'read', $this->registry->class_forums->allForums[ $moveto ], explode( ',', IPSText::cleanPermString( $perm_id ) ) ) !== TRUE ) { $trid_to_delete[] = $r['like_id']; } } } if ( count($trid_to_delete) > 0 ) { $this->DB->delete( 'core_like', "like_id IN('" . implode( "','", $trid_to_delete ) . "')" ); } return true; } /** * Delete / undelete posts * * @param array Array of Post IDs * @param boolean Approve (TRUE) / Unapprove (FALSE) * @return boolean */ public function topicToggleSoftDelete( $topicIds, $delete=FALSE, $reason='' ) { //----------------------------------------- // INIT //----------------------------------------- $_restoreTopic = 1; if ( $delete === TRUE ) { $_restoreTopic = -1; } $_topics = array(); $_forumIDs = array(); $_tids = IPSLib::cleanIntArray( $topicIds ); //----------------------------------------- // Fetch distinct topic IDs //----------------------------------------- $this->DB->build( array( 'select' => '*', 'from' => 'topics', 'where' => 'tid IN (' . implode( ',', $_tids ) . ')' ) ); $this->DB->execute(); while( $row = $this->DB->fetch() ) { if ( ! $this->registry->getClass('topics')->isArchived( $row ) ) { $_topics[ $row['tid'] ] = $row; $_forumIDs[ $row['forum_id'] ] = $row['forum_id']; } } //----------------------------------------- // Did we get the first post too? //----------------------------------------- foreach( $_topics as $tid => $topicData ) { $this->DB->update( 'topics', array( 'approved' => $_restoreTopic ), 'tid=' . $tid ); if ( $delete ) { IPSDeleteLog::addEntry( $tid, 'topic', $reason, $this->memberData ); } /* Rebuild topic */ $this->rebuildTopic( $tid ); /* Mod log */ $this->addModerateLog( $topicData['forum_id'], $tid, 0, $topicData['title'], sprintf( $this->lang->words['acp_altered_topics'], "approved={$_restoreTopic}", $topicData['title'] ) ); } /* Restoring */ if ( ! $delete ) { /* Un-deleting, so delete */ IPSDeleteLog::removeEntries( $_tids, 'post' ); /* Delete from recent posts */ $this->registry->topics->restoreRecentPost( array( 'post_topic_id' => $_tids ) ); /* Run moderation sync */ $this->runModSync( 'topicUnhide', $_tids ); } else { /* Delete from recent posts */ $this->registry->topics->deleteRecentPost( array( 'post_topic_id' => $_tids ) ); /* Run moderation sync */ $this->runModSync( 'topicHide', $_tids ); } if ( count( $_forumIDs ) ) { foreach( $_forumIDs as $_fid ) { $this->forumRecount( $_fid ); } } /* Tagging */ $this->registry->tags->updateVisibilityByMetaId( $_tids, ( $delete ? 0 : 1 ) ); /* Likes */ require_once( IPS_ROOT_PATH . 'sources/classes/like/composite.php' );/*noLibHook*/ $_like = classes_like::bootstrap( 'forums', 'topics' ); $_like->toggleVisibility( $_tids, ( $delete ) ? 0 : 1 ); $this->cache->rebuildCache( 'stats', 'global' ); return TRUE; } /** * Recount a forum * * @return boolean */ public function forumRecount( $fid="" ) { $fid = $fid ? intval($fid) : $this->forum['id']; $this->registry->class_forums->forumRebuild( $fid ); return true; } /** * Multi-statement init * * @return boolean */ public function stmInit() { $this->stm = array(); return true; } /** * Multi-statement execute * * @param mixed Id | Array of ids * @return boolean */ public function stmExec($id) { if ( count($this->stm) < 1 ) { return false; } $final_array = array(); foreach( $this->stm as $real_array ) { foreach( $real_array as $k => $v ) { $final_array[ $k ] = $v; } } if ( isset( $final_array['approved'] ) and $final_array['approved'] == -1 ) { $this->_addToSoftDeleteLog( $id ); } if ( is_array($id) ) { $id = IPSLib::cleanIntArray( $id ); if ( count($id) > 0 ) { /* Ensure we don't moderate topics in archives */ $this->DB->update( 'topics', $final_array, $this->registry->class_forums->fetchTopicArchiveQuery( array('not', 'exclude' ) ) . " AND tid IN(" . implode( ",", $id ) . ")" ); } else { return false; } } else if ( intval($id) != "" ) { $this->DB->update( 'topics', $final_array, $this->registry->class_forums->fetchTopicArchiveQuery( array('not', 'exclude' ) ) . " AND tid=" . intval($id) ); } else { return false; } return true; } /** * Add record to soft delete log * * @param int|array Topic ID(s) */ private function _addToSoftDeleteLog( $topicIds ) { if ( !is_array( $topicIds ) ) { $topicIds = array( $topicIds ); } foreach ( $topicIds as $i ) { $this->lang->loadLanguageFile( array( 'public_topic' ), 'forums' ); $this->DB->replace( 'core_soft_delete_log', array( 'sdl_obj_id' => $i, 'sdl_obj_key' => 'topic', 'sdl_obj_member_id' => $this->memberData['member_id'], 'sdl_obj_date' => time(), 'sdl_obj_reason' => $this->lang->words['mm_title'], 'sdl_locked' => 0, ), array( 'sdl_obj_id', 'sdl_obj_key' ) ); } } /** * Multi-statement pin topic * * @return boolean */ public function stmAddPin() { $this->stm[] = array( 'pinned' => 1 ); return TRUE; } /** * Multi-statement unpin topic * * @return boolean */ public function stmAddUnpin() { $this->stm[] = array( 'pinned' => 0 ); return TRUE; } /** * Multi-statement close topic * * @return boolean */ public function stmAddClose() { $this->stm[] = array( 'state' => 'closed' ); $this->stm[] = array( 'topic_open_time' => 0 ); $this->stm[] = array( 'topic_close_time' => 0 ); return TRUE; } /** * Multi-statement open topic * * @return boolean */ public function stmAddOpen() { $this->stm[] = array( 'state' => 'open' ); $this->stm[] = array( 'topic_open_time' => 0 ); $this->stm[] = array( 'topic_close_time' => 0 ); return TRUE; } /** * Multi-statement update topic title * * @return boolean */ public function stmAddTitle($new_title='') { if ( $new_title == "" ) { return FALSE; } $this->stm[] = array( 'title' => $new_title ); return TRUE; } /** * Multi-statement approve topic * * @return boolean */ public function stmAddApprove() { $this->stm[] = array( 'approved' => 1 ); return TRUE; } /** * Multi-statement unapprove topic * * @return boolean */ public function stmAddUnapprove() { $this->stm[] = array( 'approved' => -1 ); return TRUE; } /** * Create 'where' clause for SQL forum pruning * * @return boolean */ public function sqlPruneCreate( $forum_id, $starter_id="", $topic_state="", $post_min="", $date_exp="", $ignore_pin="" ) { $sql = 'forum_id=' . intval($forum_id) . ' AND approved < 2'; if ( intval($date_exp) ) { $sql .= " AND last_post < " . intval( $date_exp ); } if ( intval($starter_id) ) { $sql .= " AND starter_id=" . intval( $starter_id ); } if ( intval($post_min) ) { $sql .= " AND posts < " . intval( $post_min ); } if ($topic_state != 'all') { if ($topic_state) { $sql .= " AND state='{$topic_state}'"; } } if ( $ignore_pin != "" ) { $sql .= " AND pinned=0"; } /* Archived */ $sql .= ' AND ' . $this->registry->class_forums->fetchTopicArchiveQuery( array('not', 'exclude' ) ); return $sql; } /** * Determines if current member is authorized to use multi-mod * * @return boolean */ public function mmAuthorize() { $pass_go = FALSE; if ( $this->memberData['member_id'] ) { if ( $this->memberData['g_is_supmod'] ) { $pass_go = TRUE; } else if ( $this->moderator['can_mm'] == 1 ) { $pass_go = TRUE; } } return $pass_go; } /** * Checks if multi-mod is allowed in a specified forum * * @return boolean */ public function mmCheckIdInForum( $fid, $mm_data) { $retval = FALSE; if ( $mm_data['mm_forums'] == '*' OR strstr( "," . $mm_data['mm_forums'] . ",", "," . $fid . "," ) ) { $retval = TRUE; } return $retval; } /** * Add an entry to the moderator log * * @param integer Forum id * @param integer Topic id * @param string Topic title * @param string Title to add to moderator log * @return boolean */ public function addModerateLog($fid, $tid, $pid, $t_title, $mod_title='Unknown') { $this->DB->setDataType( 'member_name', 'string' ); $this->DB->insert( 'moderator_logs', array ( 'forum_id' => intval($fid), 'topic_id' => intval($tid), 'post_id' => intval($pid), 'member_id' => $this->memberData['member_id'], 'member_name' => $this->memberData['members_display_name'], 'ip_address' => $this->member->ip_address, 'http_referer' => htmlspecialchars( my_getenv('HTTP_REFERER') ), 'ctime' => time(), 'topic_title' => $t_title, 'action' => $mod_title, 'query_string' => htmlspecialchars( my_getenv('QUERY_STRING') ), ) ); return TRUE; } /** * Run the forum mod sync system * * @param string Function to call * @return bool */ public function runModSync( $func ) { /* ipsRegistry::$applications only contains apps with a public title #15785 */ $app_cache = $this->registry->cache()->getCache('app_cache'); /* Params */ $params = func_get_args(); array_shift( $params ); /* Loop through applications */ foreach( $app_cache as $app_dir => $app ) { if( IPSLib::appIsInstalled( $app_dir ) ) { /* Setup */ $_file = IPSLib::getAppDir( $app['app_directory'] ) . '/extensions/forumDataSync.php'; /* Check for the file */ if( is_file( $_file ) ) { /* Get the file */ $classToLoad = IPSLib::loadLibrary( $_file, $app['app_directory'] . '_forumDataSync', $app['app_directory'] ); /* Check for the class */ if( class_exists( $classToLoad ) ) { /* Create an object */ $_obj = new $classToLoad( $this->registry ); /* Check for the module */ if( method_exists( $_obj, $func ) ) { /* Call it */ call_user_func_array( array( $_obj, $func ), $params ); } } } } } } }