Version 3.3.4
This commit is contained in:
1 parent
78706903a2
commit
fb6b5baabc
2206 files changed
+409828
-382984
No files matched your search
@@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head><title>IP.Board - Bulletin Board System</title></head>
|
||||
<body>
|
||||
<h1>403: IP.Board -> Forbidden</h1>
|
||||
<hr>
|
||||
You have reached this page in error, please use your back button to return to the forum.
|
||||
<hr>
|
||||
<a href="http://www.invisionpower.com/">IP.Board</a>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* Archive: Reader
|
||||
* By Matt Mecham
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: ips_terabyte $
|
||||
* @copyright (c) 2010 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/company/standards.php#license
|
||||
* @package IP.Board
|
||||
* @link http://www.invisionpower.com
|
||||
* @since 18th November 2011
|
||||
* @version $Revision: 8644 $
|
||||
*/
|
||||
|
||||
class classes_archive_reader
|
||||
{
|
||||
/**#@+
|
||||
* Registry objects
|
||||
*
|
||||
* @access protected
|
||||
* @var object
|
||||
*/
|
||||
protected $registry;
|
||||
protected $DB;
|
||||
protected $settings;
|
||||
protected $request;
|
||||
protected $lang;
|
||||
protected $member;
|
||||
protected $memberData;
|
||||
protected $cache;
|
||||
protected $caches;
|
||||
/**#@-*/
|
||||
|
||||
/* Switch fields */
|
||||
protected $fields = array();
|
||||
/**
|
||||
* Set current app
|
||||
*/
|
||||
private $_app = '';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
*/
|
||||
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();
|
||||
|
||||
/* 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( $this->registry ) );
|
||||
$this->registry->class_forums->forumsInit();
|
||||
}
|
||||
|
||||
/* Load topic class */
|
||||
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 ) );
|
||||
}
|
||||
|
||||
/* Language class */
|
||||
$this->registry->getClass('class_localization')->loadLanguageFile( array( 'public_global' ), 'core' );
|
||||
|
||||
/* Fetch engine class */
|
||||
$this->settings['archive_engine'] = ( $this->settings['archive_engine'] ) ? $this->settings['archive_engine'] : 'sql';
|
||||
|
||||
/* Load up archive class */
|
||||
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/archive/reader/' . $this->settings['archive_engine'] . '.php', 'classes_archive_reader_' . $this->settings['archive_engine'] );
|
||||
$this->engine = new $classToLoad();
|
||||
|
||||
$this->fields = $this->registry->topics->getPostTableFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current application
|
||||
* @param string $app
|
||||
*/
|
||||
public function setApp( $app )
|
||||
{
|
||||
$this->_app = $app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the application
|
||||
* @return string
|
||||
*/
|
||||
public function getApp()
|
||||
{
|
||||
return $this->_app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a topic's post count
|
||||
* @param int Topic ID
|
||||
* @param array Masks [visible, hidden, sdelete]
|
||||
* @return int
|
||||
*/
|
||||
public function getPostCount( $tid, $masks )
|
||||
{
|
||||
$masks = ( is_array( $masks ) ) ? $masks : array( $masks );
|
||||
|
||||
return $this->engine->getPostCount( $tid, $masks );
|
||||
}
|
||||
|
||||
/**
|
||||
* getPosts
|
||||
* Fetches posts based on different critera
|
||||
* @param array Filters (see below for specifics)
|
||||
* @return array
|
||||
*
|
||||
* FILTERS:
|
||||
* topicId Get posts matching the (array) topic ids, (int) topic ID
|
||||
* forumId Get posts matching the (array) topic ids, (int) forum ID
|
||||
* postId Get posts matching the (array) post ids, (int) post id
|
||||
* memberData Set memberData (this->memberData is used otherwise)
|
||||
* onlyViewable Set whether this member can view them or not. (default is true ) NOTE: Will not check to see if parent topic is viewable!
|
||||
* onlyVisible Set whether to skip unapproved posts where permission allows (default is true)
|
||||
* postType array of 'sdelete', 'visible', 'hidden', 'pdeleted' (if you specify these, permission checks are NOT performed)
|
||||
* sortField Sort key (date, pid, etc)
|
||||
* sortOrder asc/desc
|
||||
* pidIsGreater Where PID is greater than x
|
||||
* dateIsGreater Where DATE is greater than UNIX
|
||||
* skipForumCheck Skips the forum ID IN list check to ensure you have access to view (good for when using perms elsewhere)
|
||||
* parse Parses post content
|
||||
* limit, offset Limit the amount of results in the returned query
|
||||
* getCount fetch count without limit
|
||||
*
|
||||
*/
|
||||
public function getPosts( $filters )
|
||||
{
|
||||
return $this->engine->getPosts( $filters );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fields
|
||||
* @return array
|
||||
*/
|
||||
public function getFields()
|
||||
{
|
||||
return $this->registry->topics->getPostTableFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches topic data
|
||||
* @param array $data
|
||||
*/
|
||||
public function get( $data )
|
||||
{
|
||||
/* Clean up a bit */
|
||||
$data['offset'] = intval( $data['offset'] );
|
||||
$data['limit'] = intval( $data['limit'] );
|
||||
|
||||
return $this->engine->getData( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Take an archive row and returned native friendly array
|
||||
* @param array $post
|
||||
* @return array
|
||||
*/
|
||||
public function archiveToNativeFields( $post )
|
||||
{
|
||||
return $this->registry->topics->archivePostToNativeFields( $post );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head><title>IP.Board - Bulletin Board System</title></head>
|
||||
<body>
|
||||
<h1>403: IP.Board -> Forbidden</h1>
|
||||
<hr>
|
||||
You have reached this page in error, please use your back button to return to the forum.
|
||||
<hr>
|
||||
<a href="http://www.invisionpower.com/">IP.Board</a>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,530 @@
|
||||
<?php
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* Archive: Writer
|
||||
* By Matt Mecham
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: ips_terabyte $
|
||||
* @copyright (c) 2010 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/company/standards.php#license
|
||||
* @package IP.Board
|
||||
* @link http://www.invisionpower.com
|
||||
* @since 17th February 2010
|
||||
* @version $Revision: 8644 $
|
||||
*/
|
||||
|
||||
class classes_archive_reader_sql extends classes_archive_reader
|
||||
{
|
||||
|
||||
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();
|
||||
|
||||
/* Do we have a remote DB? */
|
||||
if ( $this->settings['archive_remote_sql_database'] && $this->settings['archive_remote_sql_user'] )
|
||||
{
|
||||
if ( ! is_object( $this->registry->dbFunctions()->getDB('remoteArchive') ) )
|
||||
{
|
||||
|
||||
$this->registry->dbFunctions()->setDB( 'mysql', 'remoteArchive', array( 'sql_database' => $this->settings['archive_remote_sql_database'],
|
||||
'sql_user' => $this->settings['archive_remote_sql_user'],
|
||||
'sql_pass' => $this->settings['archive_remote_sql_pass'],
|
||||
'sql_host' => $this->settings['archive_remote_sql_host'],
|
||||
'sql_charset' => $this->settings['archive_remote_sql_charset'],
|
||||
'sql_tbl_prefix' => $this->settings['sql_tbl_prefix'],
|
||||
'catchConnectionError' => true ) );
|
||||
|
||||
|
||||
$this->remoteDB = $this->registry->dbFunctions()->getDB('remoteArchive');
|
||||
|
||||
/* Check for connection issue */
|
||||
if ( $this->remoteDB->error )
|
||||
{
|
||||
$this->connectError = $this->remoteDB->error;
|
||||
$this->remoteDB = null;
|
||||
|
||||
$this->registry->dbFunctions()->unsetDB('remoteArchive');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->remoteDB = $this->registry->dbFunctions()->getDB('remoteArchive');
|
||||
|
||||
/* Check for connection issue */
|
||||
if ( $this->remoteDB->error )
|
||||
{
|
||||
$this->connectError = $this->remoteDB->error;
|
||||
$this->remoteDB = null;
|
||||
|
||||
$this->registry->dbFunctions()->unsetDB('remoteArchive');
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->remoteDB = $this->DB;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a topic's post count
|
||||
* @param int Topic ID
|
||||
* @param array Masks [visible, hidden, sdelete]
|
||||
* @return int
|
||||
*/
|
||||
public function getPostCount( $tid, $masks )
|
||||
{
|
||||
/* Fetch replies */
|
||||
$_queued = $this->registry->class_forums->fetchPostHiddenQuery( $masks, 'archive_' );
|
||||
$posts = $this->remoteDB->buildAndFetch( array( 'select' => 'COUNT(*) as posts', 'from' => 'forums_archive_posts', 'where' => "archive_topic_id={$tid} and {$_queued}" ) );
|
||||
|
||||
return intval( $posts['posts'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* getPosts
|
||||
* Fetches posts based on different critera
|
||||
* @param array Filters (see below for specifics)
|
||||
* @return array
|
||||
*
|
||||
* FILTERS:
|
||||
* topicId Get posts matching the (array) topic ids, (int) topic ID
|
||||
* forumId Get posts matching the (array) forum ids, (int) forum ID
|
||||
* notForumId Get posts NOT matching the (array) forum ids, (int) forum ID
|
||||
* postId Get posts matching the (array) post ids, (int) post id
|
||||
* memberData Set memberData (this->memberData is used otherwise)
|
||||
* onlyViewable Set whether this member can view them or not. (default is true ) NOTE: Will not check to see if parent topic is viewable!
|
||||
* onlyVisible Set whether to skip unapproved posts where permission allows (default is true)
|
||||
* postType array of 'sdelete', 'visible', 'hidden', 'pdeleted' (if you specify these, permission checks are NOT performed)
|
||||
* sortField Sort key (date, pid, etc)
|
||||
* sortOrder asc/desc
|
||||
* pidIsGreater Where PID is greater than x
|
||||
* dateIsGreater Where DATE is greater than UNIX
|
||||
* skipForumCheck Skips the forum ID IN list check to ensure you have access to view (good for when using perms elsewhere)
|
||||
* parse Parses post content
|
||||
* limit, offset Limit the amount of results in the returned query
|
||||
* getCount fetch count without limit
|
||||
* getCountOnly fetch count and return only
|
||||
*
|
||||
*/
|
||||
public function getPosts( $filters )
|
||||
{
|
||||
/* init */
|
||||
$filters = $this->_setPostFilters( $filters );
|
||||
$limit = null;
|
||||
$posts = array();
|
||||
$where = array();
|
||||
$memberData = ( ! empty( $filters['memberData'] ) && is_array( $filters['memberData'] ) ) ? $filters['memberData'] : $this->memberData;
|
||||
|
||||
/* Posts */
|
||||
if ( ! empty( $filters['postId'] ) )
|
||||
{
|
||||
$filters['postId'] = ( ! is_array( $filters['postId'] ) ) ? array( $filters['postId'] ) : $filters['postId'];
|
||||
$where[] = "p.archive_id IN (" . implode( ',',$filters['postId'] ) . ")";
|
||||
}
|
||||
|
||||
/* Topics */
|
||||
if ( ! empty( $filters['topicId'] ) )
|
||||
{
|
||||
$filters['topicId'] = ( ! is_array( $filters['topicId'] ) ) ? array( $filters['topicId'] ) : $filters['topicId'];
|
||||
$where[] = "p.archive_topic_id IN (" . implode( ',',$filters['topicId'] ) . ")";
|
||||
}
|
||||
|
||||
/* Author Ids */
|
||||
if ( ! empty( $filters['authorId'] ) )
|
||||
{
|
||||
$filters['authorId'] = ( ! is_array( $filters['authorId'] ) ) ? array( $filters['authorId'] ) : $filters['authorId'];
|
||||
$where[] = "p.archive_author_id IN (" . implode( ',',$filters['authorId'] ) . ")";
|
||||
}
|
||||
|
||||
/* PID is greater */
|
||||
if ( ! empty( $filters['pidIsGreater'] ) )
|
||||
{
|
||||
$where[] = "p.archive_id > " . intval( $filters['pidIsGreater'] );
|
||||
}
|
||||
|
||||
/* PID is less */
|
||||
if ( ! empty( $filters['pidIsLess'] ) )
|
||||
{
|
||||
$where[] = "p.archive_id < " . intval( $filters['pidIsLess'] );
|
||||
}
|
||||
|
||||
/* Date is greater */
|
||||
if ( ! empty( $filters['dateIsGreater'] ) )
|
||||
{
|
||||
$where[] = "p.archive_content_date > " . intval( $filters['dateIsGreater'] );
|
||||
}
|
||||
|
||||
/* Forum Ids */
|
||||
if ( ! empty( $filters['forumId'] ) )
|
||||
{
|
||||
$filters['forumId'] = ( ! is_array( $filters['forumId'] ) ) ? array( $filters['forumId'] ) : $filters['forumId'];
|
||||
$where[] = "archive_forum_id IN (" . implode( ',', $filters['forumId'] ) . ")";
|
||||
}
|
||||
|
||||
/* Not Forum Ids */
|
||||
if ( ! empty( $filters['notForumId'] ) )
|
||||
{
|
||||
$filters['notForumId'] = ( ! is_array( $filters['notForumId'] ) ) ? array( $filters['notForumId'] ) : $filters['notForumId'];
|
||||
$where[] = "archive_forum_id NOT IN (" . implode( ',', $filters['notForumId'] ) . ")";
|
||||
}
|
||||
|
||||
/* Visible / specific filters */
|
||||
if ( ! empty( $filters['postType'] ) && is_array( $filters['postType'] ) )
|
||||
{
|
||||
$where[] = $this->registry->class_forums->fetchPostHiddenQuery( $filters['postType'], 'p.archive_' );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( isset( $filters['onlyViewable'] ) && $filters['onlyViewable'] === true && empty( $filters['onlyVisible'] ) )
|
||||
{
|
||||
$_perms = array( 'visible' );
|
||||
|
||||
if ( $this->registry->getClass('class_forums')->canSeeSoftDeletedPosts( false ) )
|
||||
{
|
||||
$_perms[] = 'sdelete';
|
||||
}
|
||||
|
||||
if ( $this->registry->getClass('class_forums')->canQueuePosts( false ) )
|
||||
{
|
||||
$_perms[] = 'hidden';
|
||||
}
|
||||
|
||||
$where[] = $this->registry->class_forums->fetchPostHiddenQuery( $_perms, 'p.archive_' );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Show visible only */
|
||||
$where[] = $this->registry->class_forums->fetchPostHiddenQuery( array( 'visible' ), 'p.archive_' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Forum ID check? */
|
||||
if ( ( isset( $filters['onlyViewable'] ) && $filters['onlyViewable'] === true ) && ( empty($filters['skipForumCheck']) OR $filters['skipForumCheck'] === false ) )
|
||||
{
|
||||
if ( empty( $filters['forumId'] ) && empty( $filters['notForumId'] ) )
|
||||
{
|
||||
$forumIds = $this->registry->class_forums->fetchSearchableForumIds( $memberData['member_id'] );
|
||||
|
||||
if ( ! count( $forumIds ) )
|
||||
{
|
||||
return $where;
|
||||
}
|
||||
|
||||
$where[] = "archive_forum_id IN (" . implode( ",", $forumIds ) . ")";
|
||||
}
|
||||
}
|
||||
|
||||
/* Did we want a count also? */
|
||||
if ( ! empty( $filters['getCount'] ) || ! empty( $filters['getCountOnly'] ) )
|
||||
{
|
||||
$count = $this->remoteDB->buildAndFetch( array( 'select' => 'COUNT(*) as posts',
|
||||
'from' => 'forums_archive_posts p',
|
||||
'where' => implode( ' AND ', $where ) ) );
|
||||
|
||||
$this->_countPosts = $count['posts'];
|
||||
|
||||
if ( $filters['getCountOnly'] )
|
||||
{
|
||||
return $this->_countPosts;
|
||||
}
|
||||
}
|
||||
|
||||
/* Offset, limit */
|
||||
if ( isset( $filters['offset'] ) OR isset( $filters['limit'] ) )
|
||||
{
|
||||
if ( $filters['offset'] > 0 || $filters['limit'] > 0 )
|
||||
{
|
||||
$limit = array( intval( $filters['offset'] ), intval( $filters['limit'] ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Order */
|
||||
if ( ! empty( $filters['sortField'] ) )
|
||||
{
|
||||
if ( strstr( $filters['sortField'], '.' ) )
|
||||
{
|
||||
$order = $filters['sortField'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$order = 'p.' . $filters['sortField'];
|
||||
}
|
||||
|
||||
if ( isset( $filters['sortOrder'] ) )
|
||||
{
|
||||
$order .= ' ' . $filters['sortOrder'];
|
||||
}
|
||||
}
|
||||
|
||||
/* Fetch them */
|
||||
$this->remoteDB->build( array( 'select' => 'p.*, p.archive_ip_address as post_ip',
|
||||
'from' => 'forums_archive_posts p',
|
||||
'where' => implode( ' AND ', $where ),
|
||||
'limit' => $limit ? $limit : '',
|
||||
'order' => $order ? $order : 'p.archive_id asc' ) );
|
||||
|
||||
$o = $this->remoteDB->execute();
|
||||
|
||||
while( $post = $this->remoteDB->fetch( $o ) )
|
||||
{
|
||||
/* Post IP overrides member */
|
||||
$post['ip_address'] = $post['post_ip'];
|
||||
|
||||
$post = $this->registry->topics->archivePostToNativeFields( $post );
|
||||
|
||||
$posts[ $post['pid'] ] = $post;
|
||||
}
|
||||
|
||||
return $posts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write single entry to DB
|
||||
* @param array INTS
|
||||
*/
|
||||
public function getData( $data=array() )
|
||||
{
|
||||
if ( ! $this->remoteDB )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Init */
|
||||
$topicData = $data['parentData'];
|
||||
$forumData = $this->registry->getClass('class_forums')->getForumById( $topicData['forum_id'] );
|
||||
$permissionData = $this->registry->getClass('topics')->getPermissionData();
|
||||
$first = $data['offset'];
|
||||
$end = $data['limit'];
|
||||
$fields = $this->getFields();
|
||||
|
||||
/* Default - just see all visible posts */
|
||||
$queued_query_bit = ' AND ' . $this->registry->class_forums->fetchPostHiddenQuery('visible', 'archive_');
|
||||
|
||||
/* Can we deal with hidden posts? */
|
||||
if ( $this->registry->class_forums->canQueuePosts( $topicData['forum_id'] ) )
|
||||
{
|
||||
if ( $permissionData['softDeleteSee'] )
|
||||
{
|
||||
/* See queued and soft deleted */
|
||||
$queued_query_bit = ' AND ' . $this->registry->class_forums->fetchPostHiddenQuery( array( 'visible', 'hidden', 'sdeleted' ), 'archive_' );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, see queued and approved */
|
||||
$queued_query_bit = ' AND ' . $this->registry->class_forums->fetchPostHiddenQuery( array( 'visible', 'hidden' ), 'archive_' );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We cannot see hidden posts */
|
||||
if ( $permissionData['softDeleteSee'] )
|
||||
{
|
||||
/* See queued and soft deleted */
|
||||
$queued_query_bit = ' AND ' . $this->registry->class_forums->fetchPostHiddenQuery( array('approved', 'sdeleted'), 'archive_' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up */
|
||||
/* Ignored Users */
|
||||
$ignored_users = array();
|
||||
|
||||
foreach( $this->member->ignored_users as $_i )
|
||||
{
|
||||
if ( $_i['ignore_topics'] )
|
||||
{
|
||||
$ignored_users[] = $_i['ignore_ignore_id'];
|
||||
}
|
||||
}
|
||||
|
||||
/* Format */
|
||||
$this->registry->getClass('topics')->setTopicData('adCodeSet' , false );
|
||||
$this->registry->getClass('topics')->setTopicData('ignoredUsers', $ignored_users );
|
||||
$posts = array();
|
||||
$cached = array();
|
||||
|
||||
/* Get posts separately */
|
||||
if ( IPSLib::isUsingRemoteArchiveDB() )
|
||||
{
|
||||
/* Get posts */
|
||||
$this->remoteDB->build( array( 'select' => '*',
|
||||
'from' => 'forums_archive_posts',
|
||||
'where' => 'archive_topic_id='.$topicData['tid'] . $queued_query_bit,
|
||||
'order' => $fields[ $data['sortKey'] ] . ' ' . $data['sortOrder'],
|
||||
'limit' => array( $first, $end ) ) );
|
||||
|
||||
$ab = $this->remoteDB->execute();
|
||||
|
||||
$mids = array();
|
||||
while( $p = $this->remoteDB->fetch( $ab ) )
|
||||
{
|
||||
$posts[ $p['archive_id'] ] = $p;
|
||||
$mids[ $p['archive_author_id'] ] = $p['archive_author_id'];
|
||||
}
|
||||
|
||||
if ( count( $posts ) )
|
||||
{
|
||||
/* Get cached posts */
|
||||
$this->DB->build( array( 'select' => 'cache_content_id, cache_content',
|
||||
'from' => 'content_cache_posts',
|
||||
'where' => 'cache_content_id IN ('. implode( ',', array_keys( $posts ) ) . ')' ) );
|
||||
|
||||
$this->DB->execute();
|
||||
|
||||
while( $row = $this->DB->fetch() )
|
||||
{
|
||||
$cached[ $row['cache_content_id'] ] = $row['cache_content'];
|
||||
}
|
||||
|
||||
/* Get members */
|
||||
$members = IPSMember::load( $mids, 'all' );
|
||||
|
||||
foreach( $posts as $pid => $pdata )
|
||||
{
|
||||
$pdata['member_id'] = $pdata['archive_author_id'];
|
||||
|
||||
if ( $data['goNative'] )
|
||||
{
|
||||
$pdata = $this->archiveToNativeFields( $pdata );
|
||||
}
|
||||
|
||||
if ( $pdata['author_id'] )
|
||||
{
|
||||
$members[ $pdata['author_id'] ]['cache_content_sig'] = $members[ $pdata['author_id'] ]['cache_content'];
|
||||
unset( $members[ $pdata['author_id'] ]['cache_content'] );
|
||||
$posts[ $pid ] = array_merge( $members[ $pdata['author_id'] ], $pdata );
|
||||
}
|
||||
else
|
||||
{
|
||||
$posts[ $pid ] = $pdata;
|
||||
}
|
||||
|
||||
/* Cached */
|
||||
if ( isset( $cached[ $pid ] ) )
|
||||
{
|
||||
$posts[ $pid ]['cache_content'] = $cached[ $pid ];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Joins */
|
||||
$_post_joins = array( array( 'select' => 'm.member_id as mid,m.name,m.member_group_id,m.email,m.joined,m.posts, m.last_visit, m.last_activity,m.login_anonymous,m.title as member_title, m.warn_level, m.warn_lastwarn, m.members_display_name, m.members_seo_name, m.has_gallery, m.has_blog, m.members_bitoptions,m.mgroup_others',
|
||||
'from' => array( 'members' => 'm' ),
|
||||
'where' => 'm.member_id=a.archive_author_id',
|
||||
'type' => 'left' ),
|
||||
array( 'select' => 'pp.*',
|
||||
'from' => array( 'profile_portal' => 'pp' ),
|
||||
'where' => 'm.member_id=pp.pp_member_id',
|
||||
'type' => 'left' ) );
|
||||
|
||||
/* Cache? */
|
||||
if ( IPSContentCache::isEnabled() )
|
||||
{
|
||||
if ( IPSContentCache::fetchSettingValue('post') )
|
||||
{
|
||||
$_post_joins[] = IPSContentCache::join( 'post', 'a.archive_id' );
|
||||
}
|
||||
|
||||
if ( IPSContentCache::fetchSettingValue('sig') )
|
||||
{
|
||||
$_post_joins[] = IPSContentCache::join( 'sig' , 'm.member_id', 'ccb', 'left', 'ccb.cache_content as cache_content_sig, ccb.cache_updated as cache_updated_sig' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Get posts */
|
||||
$this->remoteDB->build( array( 'select' => 'a.*',
|
||||
'from' => array( 'forums_archive_posts' => 'a' ),
|
||||
'where' => 'archive_topic_id='.$topicData['tid'] . $queued_query_bit,
|
||||
'order' => $fields[ $data['sortKey'] ] . ' ' . $data['sortOrder'],
|
||||
'limit' => array( $first, $end ),
|
||||
'add_join' => $_post_joins ) );
|
||||
|
||||
$oq = $this->remoteDB->execute();
|
||||
|
||||
while ( $row = $this->remoteDB->fetch( $oq ) )
|
||||
{
|
||||
$row['member_id'] = $row['archive_author_id'];
|
||||
|
||||
if ( $data['goNative'] )
|
||||
{
|
||||
$row = $this->archiveToNativeFields( $row );
|
||||
}
|
||||
|
||||
$posts[ $row['pid'] ] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return */
|
||||
return $posts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set post filters
|
||||
* Takes user input and cleans it up a bit
|
||||
*
|
||||
* @param array Incoming filters
|
||||
* @return array
|
||||
*/
|
||||
protected function _setPostFilters( $filters )
|
||||
{
|
||||
$filters['sortOrder'] = ( isset( $filters['sortOrder'] ) ) ? $filters['sortOrder'] : '';
|
||||
$filters['sortField'] = ( isset( $filters['sortField'] ) ) ? $filters['sortField'] : '';
|
||||
$filters['offset'] = ( isset( $filters['offset'] ) ) ? $filters['offset'] : '';
|
||||
$filters['limit'] = ( isset( $filters['limit'] ) ) ? $filters['limit'] : '';
|
||||
$filters['isVisible'] = ( isset( $filters['isVisible'] ) ) ? $filters['isVisible'] : '';
|
||||
|
||||
switch( $filters['sortOrder'] )
|
||||
{
|
||||
default:
|
||||
case 'desc':
|
||||
case 'descending':
|
||||
case 'z-a':
|
||||
$filters['sortOrder'] = 'desc';
|
||||
break;
|
||||
case 'asc':
|
||||
case 'ascending':
|
||||
case 'a-z':
|
||||
$filters['sortOrder'] = 'asc';
|
||||
break;
|
||||
}
|
||||
|
||||
/* Do some set up */
|
||||
switch( $filters['sortField'] )
|
||||
{
|
||||
case 'date':
|
||||
case 'time':
|
||||
case 'post_date':
|
||||
$filters['sortField'] = 'archive_content_date';
|
||||
break;
|
||||
case 'pid':
|
||||
case 'id':
|
||||
$filters['sortField'] = 'archive_id';
|
||||
break;
|
||||
}
|
||||
|
||||
/* Others */
|
||||
$filters['offset'] = intval( $filters['offset'] );
|
||||
$filters['limit'] = intval( $filters['limit'] );
|
||||
$filters['unixCutOff'] = ( ! empty( $filters['unixCutOff'] ) ) ? intval( $filters['unixCutOff'] ) : 0;
|
||||
|
||||
/* So we don't have to do this twice */
|
||||
$filters['_cleaned'] = true;
|
||||
|
||||
return $filters;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,416 @@
|
||||
<?php
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* Archive: Reader
|
||||
* By Matt Mecham
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: ips_terabyte $
|
||||
* @copyright (c) 2010 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/company/standards.php#license
|
||||
* @package IP.Board
|
||||
* @link http://www.invisionpower.com
|
||||
* @since 18th November 2011
|
||||
* @version $Revision: 8644 $
|
||||
*/
|
||||
|
||||
/**
|
||||
* Restores topics that are either manually flagged or via settings
|
||||
* from the Admin CP.
|
||||
*
|
||||
* Manually flagged topics are always restored first.
|
||||
* @author matt
|
||||
*
|
||||
*/
|
||||
class classes_archive_restore
|
||||
{
|
||||
/**#@+
|
||||
* Registry objects
|
||||
*
|
||||
* @access protected
|
||||
* @var object
|
||||
*/
|
||||
protected $registry;
|
||||
protected $DB;
|
||||
protected $settings;
|
||||
protected $request;
|
||||
protected $lang;
|
||||
protected $member;
|
||||
protected $memberData;
|
||||
protected $cache;
|
||||
protected $caches;
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* Set current app
|
||||
*/
|
||||
private $_app = '';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
*/
|
||||
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();
|
||||
|
||||
/* 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( $this->registry ) );
|
||||
$this->registry->class_forums->forumsInit();
|
||||
}
|
||||
|
||||
/* Language class */
|
||||
$this->registry->getClass('class_localization')->loadLanguageFile( array( 'public_global' ), 'core' );
|
||||
|
||||
/* Fetch engine class */
|
||||
$this->settings['archive_engine'] = ( $this->settings['archive_engine'] ) ? $this->settings['archive_engine'] : 'sql';
|
||||
|
||||
/* Load up archive class */
|
||||
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/archive/restore/' . $this->settings['archive_engine'] . '.php', 'classes_archive_restore_' . $this->settings['archive_engine'] );
|
||||
$this->engine = new $classToLoad();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current application
|
||||
* @param string $app
|
||||
*/
|
||||
public function setApp( $app )
|
||||
{
|
||||
$this->_app = $app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the application
|
||||
* @return string
|
||||
*/
|
||||
public function getApp()
|
||||
{
|
||||
return $this->_app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore posts to the topic
|
||||
* @param array INTS
|
||||
*/
|
||||
public function restore( $pids=array() )
|
||||
{
|
||||
if ( ! count( $pids ) )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
$topics = array();
|
||||
$forumIds = array();
|
||||
$completedTopics = array();
|
||||
$workingTopics = array();
|
||||
$maxes = array();
|
||||
|
||||
/* Load the attachments stuff */
|
||||
$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();
|
||||
|
||||
/* Load the attachments stuff */
|
||||
$classToLoad = IPSLib::loadLibrary( IPSLib::getAppDir( 'forums' ) . '/sources/classes/topics.php', 'app_forums_classes_topics' );
|
||||
$topicClass = new $classToLoad( $this->registry );
|
||||
|
||||
/* Fetch data based on PIDs */
|
||||
$posts = $topicClass->getPosts( array( 'postId' => $pids,
|
||||
'sortField' => 'pid',
|
||||
'sortOrder' => 'asc',
|
||||
'isArchivedTopic' => true ) );
|
||||
|
||||
foreach( $posts as $pid => $post )
|
||||
{
|
||||
/* Write it */
|
||||
$this->engine->set( $post );
|
||||
|
||||
/* Collect some data */
|
||||
if ( ! in_array( $post['tid'], $topics ) )
|
||||
{
|
||||
$post['_pids'] = 1;
|
||||
$post['_lowPid'] = $post['archive_id'];
|
||||
$post['_maxPid'] = $post['archive_id'];
|
||||
$post['_topicCount'] = ( intval( $post['posts'] ) + intval( $post['topic_deleted_posts'] ) + intval( $post['topic_queuedposts'] ) + 1 );
|
||||
$topics[ $post['tid'] ] = $post;
|
||||
}
|
||||
else
|
||||
{
|
||||
$topics[ $post['tid'] ]['_maxPid'] = $post['archive_id'];
|
||||
$topics[ $post['tid'] ]['_pids']++;
|
||||
}
|
||||
|
||||
/* Collect fids */
|
||||
$forums[ $post['forum_id'] ] = $post['forum_id'];
|
||||
}
|
||||
|
||||
/* Get the maxes */
|
||||
$this->DB->build( array( 'select' => 'topic_id, MAX(pid) as i',
|
||||
'from' => 'posts',
|
||||
'where' => 'topic_id IN (' . implode( ',', array_keys( $topics ) ) . ')',
|
||||
'group' => 'topic_id' ) );
|
||||
|
||||
$o = $this->DB->execute();
|
||||
|
||||
while( $t = $this->DB->fetch( $o ) )
|
||||
{
|
||||
$maxes[ $t['topic_id'] ] = intval( $t['i'] );
|
||||
}
|
||||
|
||||
/* Figure out how many topics have been completed */
|
||||
foreach( $topics as $tid => $data )
|
||||
{
|
||||
/* First pid matches topic first pid, so we have the first post in the topic
|
||||
* but have we got all the posts in this topic?
|
||||
*/
|
||||
if ( $maxes[ $tid ] == $data['_maxPid'] )
|
||||
{
|
||||
$completedTopics[] = $data['tid'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$workingTopics[] = $data['tid'];
|
||||
}
|
||||
}
|
||||
|
||||
/* Update completed */
|
||||
if ( count( $completedTopics ) )
|
||||
{
|
||||
$this->DB->update( 'topics', array( 'topic_archive_status' => $this->registry->class_forums->fetchTopicArchiveFlag( 'exclude' ) ), 'tid IN(' . implode( ',', $completedTopics ) . ')' );
|
||||
|
||||
/* Archive attachments */
|
||||
$class_attach->bulkUnarchive( $completedTopics, 'attach_parent_id' );
|
||||
|
||||
/* Remove posts */
|
||||
$this->engine->removePostsByTids( $completedTopics );
|
||||
}
|
||||
|
||||
/* Flag as archived */
|
||||
$this->engine->setAsRestoredByPids( $pids );
|
||||
|
||||
/* Do forums */
|
||||
foreach( $forums as $id )
|
||||
{
|
||||
$this->registry->class_forums->forumRebuild( $id );
|
||||
}
|
||||
|
||||
/* Log it */
|
||||
$this->log( $pids, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a batch. Genius.
|
||||
* $options is an array of keys and values:
|
||||
* process - INT - number of items to process in this batch
|
||||
* @return int count of topics archived
|
||||
*/
|
||||
public function processBatch( $options=array() )
|
||||
{
|
||||
$restoreData = $this->getRestoreData();
|
||||
$topics = array();
|
||||
$forums = array();
|
||||
$pids = array();
|
||||
|
||||
/* Fix up options */
|
||||
$options['process'] = ( is_numeric( $options['process'] ) && $options['process'] > 0 ) ? $options['process'] : 250;
|
||||
|
||||
if ( ! $restoreData['restore_min_tid'] && ! $restoreData['restore_max_tid'] && ! count( $restoreData['restore_manual_tids'] ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Any manually flagged? */
|
||||
if ( count( $restoreData['restore_manual_tids'] ) )
|
||||
{
|
||||
/* Select remaining Pids */
|
||||
$pids = $this->engine->getPidsInTids( IPSLib::cleanIntArray( array_keys( $restoreData['restore_manual_tids'] ) ), $options['process'] );
|
||||
|
||||
/* Did we complete topics? */
|
||||
foreach( $restoreData['restore_manual_tids'] as $tid => $maxPid )
|
||||
{
|
||||
if ( in_array( $maxPid, array_keys( $pids ) ) )
|
||||
{
|
||||
$this->deleteManualId( $tid );
|
||||
}
|
||||
}
|
||||
|
||||
/* All done? */
|
||||
if ( ! count( $pids ) )
|
||||
{
|
||||
$restoreData['restore_manual_tids'] = array();
|
||||
|
||||
$this->setRestoreData( $restoreData );
|
||||
}
|
||||
|
||||
/* Update process for below */
|
||||
$options['process'] -= count( $pids );
|
||||
}
|
||||
|
||||
/* Now fetch the max/min if archiver is on */
|
||||
if ( $this->settings['archive_on'] && $options['process'] > 0 && $restoreData['restore_min_tid'] && $restoreData['restore_max_tid'] )
|
||||
{
|
||||
$date = IPS_UNIX_TIME_NOW - ( 86400 * intval( $this->settings['archive_restore_days'] ) );
|
||||
|
||||
$pids = $this->engine->getPidsBetweenTidsAndDate( $restoreData['restore_min_tid'], $restoreData['restore_max_tid'], $date, $options['process'] );
|
||||
|
||||
/* All done? */
|
||||
if ( ! count( $pids ) )
|
||||
{
|
||||
$restoreData['restore_min_tid'] = 0;
|
||||
$restoreData['restore_max_tid'] = 0;
|
||||
|
||||
$this->setRestoreData( $restoreData );
|
||||
}
|
||||
}
|
||||
|
||||
/* Process */
|
||||
$this->restore( $pids );
|
||||
|
||||
return count( $pids );
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag an item for manual unarchive
|
||||
* @param int $id
|
||||
*/
|
||||
public function setManualUnarchive( $id )
|
||||
{
|
||||
/* Init */
|
||||
$classToLoad = IPSLib::loadLibrary( IPSLib::getAppDir( 'forums' ) . "/sources/classes/topics.php", 'app_forums_classes_topics', 'forums' );
|
||||
$topicClass = new $classToLoad( $this->registry );
|
||||
|
||||
$topic = $topicClass->getTopicById( $id );
|
||||
|
||||
if ( $topic['tid'] && $this->registry->class_forums->fetchArchiveTopicType( $topic ) == 'archived' )
|
||||
{
|
||||
$topicClass->updateTopic( $topic['tid'], array( 'topic_archive_status' => $this->registry->class_forums->fetchTopicArchiveFlag('restore') ) );
|
||||
|
||||
$this->insertManualId( $id );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an ID to the manual restore filter
|
||||
*/
|
||||
public function insertManualId( $id )
|
||||
{
|
||||
$data = $this->getRestoreData();
|
||||
$max = $this->engine->getMaxPidInTid( $id );
|
||||
|
||||
$data['restore_manual_tids'][ $id ] = $max;
|
||||
|
||||
$this->setRestoreData( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an ID from the manual restore filter
|
||||
*/
|
||||
public function deleteManualId( $id )
|
||||
{
|
||||
$data = $this->getRestoreData();
|
||||
|
||||
if ( in_array( $id, array_keys( $data['restore_manual_tids'] ) ) )
|
||||
{
|
||||
unset( $data['restore_manual_tids'][ $id ] );
|
||||
|
||||
$this->setRestoreData( $data );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get restore data
|
||||
*/
|
||||
public function getRestoreData()
|
||||
{
|
||||
$data = $this->DB->buildAndFetch( array( 'select' => '*',
|
||||
'from' => 'core_archive_restore' ) );
|
||||
|
||||
if ( IPSLib::isSerialized( $data['restore_manual_tids'] ) )
|
||||
{
|
||||
$data['restore_manual_tids'] = unserialize( $data['restore_manual_tids'] );
|
||||
}
|
||||
else
|
||||
{
|
||||
$data['restore_manual_tids'] = array();
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set restore data
|
||||
* @param array
|
||||
*/
|
||||
public function setRestoreData( $data )
|
||||
{
|
||||
if ( is_array( $data['restore_manual_tids'] ) )
|
||||
{
|
||||
$data['restore_manual_tids'] = serialize( $data['restore_manual_tids'] );
|
||||
}
|
||||
|
||||
$data['restore_min_tid'] = intval( $data['restore_min_tid'] );
|
||||
$data['restore_max_tid'] = intval( $data['restore_max_tid'] );
|
||||
|
||||
$this->DB->delete( 'core_archive_restore');
|
||||
$this->DB->insert( 'core_archive_restore', $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Take an archive row and returned native friendly array
|
||||
* @param array $post
|
||||
* @return array
|
||||
*/
|
||||
public function archiveToNativeFields( $post )
|
||||
{
|
||||
$native = array( 'pid' => intval( $post['archive_id'] ),
|
||||
'author_id' => intval( $post['archive_author_id'] ),
|
||||
'author_name' => $post['archive_author_name'],
|
||||
'ip_address' => $post['archive_ip_address'],
|
||||
'post_date' => intval( $post['archive_content_date'] ),
|
||||
'post' => $post['archive_content'],
|
||||
'queued' => $post['archive_queued'],
|
||||
'topic_id' => intval( $post['archive_topic_id'] ),
|
||||
'new_topic' => intval( $post['archive_is_first'] ),
|
||||
'post_bwoptions' => $post['archive_bwoptions'],
|
||||
'post_key' => $post['archive_attach_key'],
|
||||
'post_htmlstate' => $post['archive_html_mode'],
|
||||
'use_sig' => $post['archive_show_signature'],
|
||||
'use_emo' => $post['archive_show_emoticons'],
|
||||
'append_edit' => $post['archive_show_edited_by'],
|
||||
'edit_time' => $post['archive_edit_time'],
|
||||
'edit_name' => $post['archive_edit_name'],
|
||||
'post_edit_reason' => $post['archive_edit_reason'] );
|
||||
|
||||
return $native;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs archive action
|
||||
* @param array $ids
|
||||
*/
|
||||
public function log( $ids )
|
||||
{
|
||||
$this->DB->insert( 'core_archive_log', array( 'archlog_date' => IPS_UNIX_TIME_NOW,
|
||||
'archlog_app' => $this->getApp(),
|
||||
'archlog_ids' => serialize( $ids ),
|
||||
'archlog_is_restore' => 1,
|
||||
'archlog_count' => count( $ids ) ) );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head><title>IP.Board - Bulletin Board System</title></head>
|
||||
<body>
|
||||
<h1>403: IP.Board -> Forbidden</h1>
|
||||
<hr>
|
||||
You have reached this page in error, please use your back button to return to the forum.
|
||||
<hr>
|
||||
<a href="http://www.invisionpower.com/">IP.Board</a>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* Archive: Restore
|
||||
* By Matt Mecham
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: ips_terabyte $
|
||||
* @copyright (c) 2010 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/company/standards.php#license
|
||||
* @package IP.Board
|
||||
* @link http://www.invisionpower.com
|
||||
* @since 17th February 2010
|
||||
* @version $Revision: 8644 $
|
||||
*/
|
||||
|
||||
class classes_archive_restore_sql extends classes_archive_restore
|
||||
{
|
||||
|
||||
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();
|
||||
|
||||
/* Do we have a remote DB? */
|
||||
if ( $this->settings['archive_remote_sql_database'] && $this->settings['archive_remote_sql_user'] )
|
||||
{
|
||||
if ( ! is_object( $this->registry->dbFunctions()->getDB('remoteArchive') ) )
|
||||
{
|
||||
|
||||
$this->registry->dbFunctions()->setDB( 'mysql', 'remoteArchive', array( 'sql_database' => $this->settings['archive_remote_sql_database'],
|
||||
'sql_user' => $this->settings['archive_remote_sql_user'],
|
||||
'sql_pass' => $this->settings['archive_remote_sql_pass'],
|
||||
'sql_host' => $this->settings['archive_remote_sql_host'],
|
||||
'sql_charset' => $this->settings['archive_remote_sql_charset'],
|
||||
'sql_tbl_prefix' => $this->settings['sql_tbl_prefix'],
|
||||
'catchConnectionError' => true ) );
|
||||
|
||||
|
||||
$this->remoteDB = $this->registry->dbFunctions()->getDB('remoteArchive');
|
||||
|
||||
/* Check for connection issue */
|
||||
if ( $this->remoteDB->error )
|
||||
{
|
||||
$this->connectError = $this->remoteDB->error;
|
||||
$this->remoteDB = null;
|
||||
|
||||
$this->registry->dbFunctions()->unsetDB('remoteArchive');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->remoteDB = $this->registry->dbFunctions()->getDB('remoteArchive');
|
||||
|
||||
/* Check for connection issue */
|
||||
if ( $this->remoteDB->error )
|
||||
{
|
||||
$this->connectError = $this->remoteDB->error;
|
||||
$this->remoteDB = null;
|
||||
|
||||
$this->registry->dbFunctions()->unsetDB('remoteArchive');
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->remoteDB = $this->DB;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get max PID in a TID
|
||||
*/
|
||||
public function getMaxPidInTid( $tid )
|
||||
{
|
||||
$max = $this->remoteDB->buildAndFetch( array( 'select' => 'MAX(archive_id) as i', 'from' => 'forums_archive_posts', 'where' => 'archive_topic_id=' . intval( $tid ) ) );
|
||||
|
||||
return $max['i'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch by TIDS
|
||||
*/
|
||||
public function getPidsInTids( array $tids, $limit=50 )
|
||||
{
|
||||
$pids = array();
|
||||
|
||||
/* Select remaining Pids */
|
||||
$this->remoteDB->build( array( 'select' => 'archive_id',
|
||||
'from' => 'forums_archive_posts',
|
||||
'where' => 'archive_topic_id IN(' . implode( ',', $tids ) . ') AND archive_restored=0',
|
||||
'order' => 'archive_topic_id ASC, archive_id ASC',
|
||||
'limit' => array( 0, $limit ) ) );
|
||||
|
||||
$o = $this->remoteDB->execute();
|
||||
|
||||
while( $post = $this->remoteDB->fetch( $o ) )
|
||||
{
|
||||
$pids[ $post['archive_id'] ] = $post['archive_id'];
|
||||
}
|
||||
|
||||
return $pids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch between TIDS and date
|
||||
*
|
||||
*/
|
||||
public function getPidsBetweenTidsAndDate( $min, $max, $date=0, $limit=50 )
|
||||
{
|
||||
$this->remoteDB->build( array( 'select' => 'archive_id',
|
||||
'from' => 'forums_archive_posts',
|
||||
'where' => 'archive_content_date > ' . $date . ' AND archive_topic_id BETWEEN ' . intval( $min ) . ' AND ' . intval( $max ),
|
||||
'order' => 'archive_topic_id ASC, archive_id ASC',
|
||||
'limit' => array( 0, $limit ) ) );
|
||||
|
||||
$o = $this->remoteDB->execute();
|
||||
|
||||
while( $post = $this->remoteDB->fetch( $o ) )
|
||||
{
|
||||
$pids[ $post['archive_id'] ] = $post['archive_id'];
|
||||
}
|
||||
|
||||
return $pids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove posts by TIDs
|
||||
* @param array TIDS
|
||||
*/
|
||||
public function removePostsByTids( array $tids )
|
||||
{
|
||||
if ( count( $tids ) )
|
||||
{
|
||||
$this->remoteDB->delete( 'forums_archive_posts', 'archive_topic_id IN(' . implode( ',', $tids ) . ')' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove posts by PIDs
|
||||
* @param array PIDs
|
||||
*/
|
||||
public function setAsRestoredByPids( array $pids )
|
||||
{
|
||||
if ( count( $pids ) )
|
||||
{
|
||||
$this->DB->update( 'forums_archive_posts', array( 'archive_restored' => 1 ), 'archive_id IN (' . implode( ',', $pids ) .')' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write single entry to DB
|
||||
* @param array INTS
|
||||
*/
|
||||
public function set( $data=array() )
|
||||
{
|
||||
if ( ! count( $data ) )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->DB->replace( 'posts', $this->archiveToNativeFields( $data ), array( 'pid' ) );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,691 @@
|
||||
<?php
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* Archive: Writer
|
||||
* By Matt Mecham
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: ips_terabyte $
|
||||
* @copyright (c) 2010 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/company/standards.php#license
|
||||
* @package IP.Board
|
||||
* @link http://www.invisionpower.com
|
||||
* @since 17th February 2010
|
||||
* @version $Revision: 8644 $
|
||||
*/
|
||||
|
||||
class classes_archive_writer
|
||||
{
|
||||
/**#@+
|
||||
* Registry objects
|
||||
*
|
||||
* @access protected
|
||||
* @var object
|
||||
*/
|
||||
protected $registry;
|
||||
protected $DB;
|
||||
protected $settings;
|
||||
protected $request;
|
||||
protected $lang;
|
||||
protected $member;
|
||||
protected $memberData;
|
||||
protected $cache;
|
||||
protected $caches;
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* Set current app
|
||||
*/
|
||||
private $_app = '';
|
||||
|
||||
/**
|
||||
* Archive 'do' allowed fields
|
||||
*/
|
||||
private $_archiveOnFields = array( 'state' => 'state',
|
||||
'pinned' => 'pinned',
|
||||
'approved' => 'approved',
|
||||
'poll' => 'poll_state',
|
||||
'post' => 'posts',
|
||||
'view' => 'views',
|
||||
'rating' => 'topic_rating_total',
|
||||
'forum' => 'forum_id',
|
||||
'member' => 'starter_id',
|
||||
'lastpost' => 'last_post' );
|
||||
|
||||
/**
|
||||
* Archive 'skip' allowed fields
|
||||
*/
|
||||
private $_archiveSkipFields = array( 'post' => 'posts',
|
||||
'view' => 'views',
|
||||
'rating' => 'topic_rating_total',
|
||||
'forum' => 'forum_id',
|
||||
'member' => 'starter_id',
|
||||
'lastpost' => 'last_post');
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
*/
|
||||
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();
|
||||
|
||||
/* 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( $this->registry ) );
|
||||
$this->registry->class_forums->forumsInit();
|
||||
}
|
||||
|
||||
/* Language class */
|
||||
$this->registry->getClass('class_localization')->loadLanguageFile( array( 'public_global' ), 'core' );
|
||||
|
||||
/* Fetch engine class */
|
||||
$this->settings['archive_engine'] = ( $this->settings['archive_engine'] ) ? $this->settings['archive_engine'] : 'sql';
|
||||
|
||||
/* Load up archive class */
|
||||
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/archive/writer/' . $this->settings['archive_engine'] . '.php', 'classes_archive_writer_' . $this->settings['archive_engine'] );
|
||||
$this->engine = new $classToLoad();
|
||||
|
||||
if ( $this->engine->test() !== true )
|
||||
{
|
||||
$this->error( $this->lang->words['archive_fail_engine'] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It's magic!
|
||||
* @param string $method
|
||||
* @param array $arguments
|
||||
*/
|
||||
public function __call( $method, $arguments )
|
||||
{
|
||||
switch ( $method )
|
||||
{
|
||||
case 'testConnection':
|
||||
return $this->engine->test();
|
||||
break;
|
||||
case 'createTable':
|
||||
return $this->engine->createTable();
|
||||
break;
|
||||
case 'flush':
|
||||
return $this->engine->flush();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates posts
|
||||
*
|
||||
* @param $what Array of fields with vals to update
|
||||
* @param $where String of what to update
|
||||
*/
|
||||
public function update( array $what, $where )
|
||||
{
|
||||
return $this->engine->update( $what, $where );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current application
|
||||
* @param string $app
|
||||
*/
|
||||
public function setApp( $app )
|
||||
{
|
||||
$this->_app = $app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the application
|
||||
* @return string
|
||||
*/
|
||||
public function getApp()
|
||||
{
|
||||
return $this->_app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return archive on fields
|
||||
* @return array
|
||||
*/
|
||||
public function getArchiveOnFields()
|
||||
{
|
||||
return array_keys( $this->_archiveOnFields );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return archive skip fields
|
||||
* @return array
|
||||
*/
|
||||
public function getArchiveSkipFields()
|
||||
{
|
||||
return array_keys( $this->_archiveSkipFields );
|
||||
}
|
||||
|
||||
/**
|
||||
* Write topics to the archive
|
||||
* @param array INTS
|
||||
*/
|
||||
public function write( $pids=array() )
|
||||
{
|
||||
if ( ! count( $pids ) )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
$topics = array();
|
||||
$forumIds = array();
|
||||
$completedTopics = array();
|
||||
$workingTopics = array();
|
||||
$maxes = array();
|
||||
|
||||
/* Load the attachments stuff */
|
||||
$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();
|
||||
|
||||
/* Fetch data based on PIDs */
|
||||
$this->DB->build( array( 'select' => 'p.*',
|
||||
'from' => array( 'posts' => 'p' ),
|
||||
'where' => 'p.pid IN (' . implode( ',', $pids ) . ')',
|
||||
'order' => 'p.topic_id ASC, p.pid ASC',
|
||||
'add_join' => array( array( 'select' => 't.*',
|
||||
'from' => array( 'topics' => 't' ),
|
||||
'where' => 'p.topic_id=t.tid' ) ) ) );
|
||||
|
||||
$o = $this->DB->execute();
|
||||
|
||||
while( $post = $this->DB->fetch( $o ) )
|
||||
{
|
||||
/* Write it */
|
||||
$this->engine->set( $post );
|
||||
|
||||
/* Collect some data */
|
||||
if ( ! in_array( $post['tid'], $topics ) )
|
||||
{
|
||||
$post['_pids'] = 1;
|
||||
$post['_lowPid'] = $post['pid'];
|
||||
$post['_maxPid'] = $post['pid'];
|
||||
$post['_topicCount'] = ( intval( $post['posts'] ) + intval( $post['topic_deleted_posts'] ) + intval( $post['topic_queuedposts'] ) + 1 );
|
||||
$topics[ $post['tid'] ] = $post;
|
||||
}
|
||||
else
|
||||
{
|
||||
$topics[ $post['tid'] ]['_maxPid'] = $post['pid'];
|
||||
$topics[ $post['tid'] ]['_pids']++;
|
||||
}
|
||||
|
||||
/* Collect fids */
|
||||
$forums[ $post['forum_id'] ] = $post['forum_id'];
|
||||
}
|
||||
|
||||
/* Got any topics? */
|
||||
if ( ! count( $topics ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the maxes */
|
||||
$this->DB->build( array( 'select' => 'topic_id, MAX(pid) as i',
|
||||
'from' => 'posts',
|
||||
'where' => 'topic_id IN (' . implode( ',', array_keys( $topics ) ) . ')',
|
||||
'group' => 'topic_id' ) );
|
||||
|
||||
$o = $this->DB->execute();
|
||||
|
||||
while( $t = $this->DB->fetch( $o ) )
|
||||
{
|
||||
$maxes[ $t['topic_id'] ] = intval( $t['i'] );
|
||||
}
|
||||
|
||||
/* Figure out how many topics have been completed */
|
||||
foreach( $topics as $tid => $data )
|
||||
{
|
||||
/* First pid matches topic first pid, so we have the first post in the topic
|
||||
* but have we got all the posts in this topic?
|
||||
*/
|
||||
if ( $maxes[ $tid ] == $data['_maxPid'] )
|
||||
{
|
||||
$completedTopics[] = $data['tid'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$workingTopics[] = $data['tid'];
|
||||
}
|
||||
}
|
||||
|
||||
/* Update working */
|
||||
if ( count( $workingTopics ) )
|
||||
{
|
||||
$this->DB->update( 'topics', array( 'topic_archive_status' => $this->registry->class_forums->fetchTopicArchiveFlag( 'working' ) ),'tid IN(' . implode( ',', $workingTopics ) . ')' );
|
||||
}
|
||||
|
||||
/* Update completed */
|
||||
if ( count( $completedTopics ) )
|
||||
{
|
||||
$this->DB->update( 'topics', array( 'topic_archive_status' => $this->registry->class_forums->fetchTopicArchiveFlag( 'archived' ) ), 'tid IN(' . implode( ',', $completedTopics ) . ')' );
|
||||
|
||||
/* Archive attachments */
|
||||
$class_attach->bulkArchive( $completedTopics, 'attach_parent_id' );
|
||||
|
||||
/* Remove posts */
|
||||
$this->DB->delete( 'posts', 'topic_id IN(' . implode( ',', $completedTopics ) . ')' );
|
||||
}
|
||||
|
||||
/* Do forums */
|
||||
foreach( $forums as $id )
|
||||
{
|
||||
$this->registry->class_forums->forumRebuild( $id );
|
||||
}
|
||||
|
||||
/* Log it */
|
||||
$this->log( $pids );
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a batch. Genius.
|
||||
* $options is an array of keys and values:
|
||||
* process - INT - number of items to process in this batch
|
||||
* @return int count of topics archived
|
||||
*/
|
||||
public function processBatch( $options=array() )
|
||||
{
|
||||
/* Archiver running? */
|
||||
if ( ! $this->settings['archive_on'] )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Init vars */
|
||||
$query = $this->getArchiveWhereQuery();
|
||||
$topics = array();
|
||||
$forums = array();
|
||||
$pids = array();
|
||||
|
||||
/* Fix up options */
|
||||
$options['process'] = ( is_numeric( $options['process'] ) && $options['process'] > 0 ) ? $options['process'] : 250;
|
||||
|
||||
if ( $query === null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/* First see if we have a topic in progress */
|
||||
$working = $this->DB->buildAndFetch( array( 'select' => '*',
|
||||
'from' => 'topics',
|
||||
'where' => 'topic_archive_status=' . $this->registry->class_forums->fetchTopicArchiveFlag( 'working' ),
|
||||
'order' => 'tid ASC',
|
||||
'limit' => array( 0, 1 ) ) );
|
||||
|
||||
/* Got one? */
|
||||
if ( $working['tid'] )
|
||||
{
|
||||
$doneSoFar = $this->engine->getDoneSoFarByTid( $working['tid'] );
|
||||
|
||||
$postTable = $this->DB->buildAndFetch( array( 'select' => 'COUNT(*) as count, MAX(pid) as max',
|
||||
'from' => 'posts',
|
||||
'where' => 'pid > ' . intval( $doneSoFar['max'] ) . ' AND topic_id=' . $working['tid'] ) );
|
||||
|
||||
|
||||
/* Select remaining Pids */
|
||||
$this->DB->build( array( 'select' => 'pid',
|
||||
'from' => 'posts',
|
||||
'where' => 'pid > ' . intval( $doneSoFar['max'] ) . ' AND topic_id=' . $working['tid'],
|
||||
'order' => 'pid ASC',
|
||||
'limit' => array( 0, $options['process'] ) ) );
|
||||
|
||||
$o = $this->DB->execute();
|
||||
|
||||
while( $post = $this->DB->fetch( $o ) )
|
||||
{
|
||||
$pids[ $post['pid'] ] = $post['pid'];
|
||||
}
|
||||
|
||||
/* Update process for below */
|
||||
$options['process'] -= count( $pids );
|
||||
}
|
||||
|
||||
/* Carry on? */
|
||||
if ( $options['process'] > 0 )
|
||||
{
|
||||
/* Collect topic IDs first */
|
||||
$this->DB->build( array( 'select' => '*',
|
||||
'from' => 'topics',
|
||||
'where' => $query . ' AND (posts + topic_deleted_posts + topic_queuedposts ) >= 0',
|
||||
/**
|
||||
* We can't check for posts > 0 because if the topic has only the first post it will skip them
|
||||
*
|
||||
* @link http://community.invisionpower.com/tracker/issue-37131-archive-posts-missing-old-topics-with-post-count-0/
|
||||
*/
|
||||
//'where' => $query . ' AND (posts + topic_deleted_posts + topic_queuedposts ) > 0',
|
||||
'order' => 'tid ASC',
|
||||
'limit' => array( 0, 250 ) ) );
|
||||
|
||||
$o = $this->DB->execute();
|
||||
|
||||
$counter = 0;
|
||||
|
||||
while( $topic = $this->DB->fetch( $o ) )
|
||||
{
|
||||
$topics[] = $topic['tid'];
|
||||
|
||||
$counter += ( $topic['posts'] + $topic['topic_deleted_posts'] + $topic['topic_queuedposts'] ) + 1;
|
||||
|
||||
if ( $counter >= $options['process'] )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Got anything? */
|
||||
if ( ! count( $topics ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Now fetch the PIDS */
|
||||
$this->DB->build( array( 'select' => 'pid',
|
||||
'from' => 'posts',
|
||||
'where' => 'topic_id IN (' . implode( ',', $topics ) . ')',
|
||||
'order' => 'topic_id ASC, pid ASC',
|
||||
'limit' => array( 0, $options['process'] ) ) );
|
||||
|
||||
$o = $this->DB->execute();
|
||||
|
||||
while( $post = $this->DB->fetch( $o ) )
|
||||
{
|
||||
$pids[ $post['pid'] ] = $post['pid'];
|
||||
}
|
||||
}
|
||||
|
||||
/* Process */
|
||||
$this->write( $pids );
|
||||
|
||||
return count( $pids );
|
||||
}
|
||||
|
||||
/**
|
||||
* Give me a key and I'll give you a DB field you lucky beasts
|
||||
* @param string $key
|
||||
*/
|
||||
public function getDbFieldFromKey( $key )
|
||||
{
|
||||
return ( isset( $this->_archiveOnFields[ $key ] ) ) ? $this->_archiveOnFields[ $key ] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a count of how many topics the current settings would archive off
|
||||
* if performed in one go
|
||||
* @param array $rules [Optional]
|
||||
* @return array array( count, total, percentage )
|
||||
*/
|
||||
public function getArchivePossibleCount( $rules=array() )
|
||||
{
|
||||
$query = $this->getArchiveWhereQuery( $rules, false, true );
|
||||
|
||||
$return = array( 'count' => null, 'percentage' => 0, 'total' => 0 );
|
||||
|
||||
if ( $query !== null )
|
||||
{
|
||||
$total = $this->DB->buildAndFetch( array( 'select' => 'count(*) as count',
|
||||
'from' => 'topics',
|
||||
'where' => $query . ' AND state != \'link\'' ) );
|
||||
|
||||
$all = $this->DB->buildAndFetch( array( 'select' => 'count(*) as count',
|
||||
'from' => 'topics' ) );
|
||||
|
||||
$return['count'] = intval( $total['count'] );
|
||||
$return['total'] = intval( $all['count'] );
|
||||
|
||||
if ( $return['count'] && $return['total'] )
|
||||
{
|
||||
$return['percentage'] = round( ( $return['count'] / $return['total'] ) * 100, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the WHERE portion of a query string required to fetch topics to archive
|
||||
* @param array $rules [Optional]
|
||||
*/
|
||||
public function getArchiveWhereQuery( $rules=array(), $onlyGetUnarchived=true, $excludeExcluded=false )
|
||||
{
|
||||
$where = ( $onlyGetUnarchived ) ? array( 'topic_archive_status=' . $this->registry->class_forums->fetchTopicArchiveFlag( 'not' ) ) : array();
|
||||
$whereNot = ( $excludeExcluded ) ? array( 'topic_archive_status=' . $this->registry->class_forums->fetchTopicArchiveFlag( 'exclude' ) ) : array();
|
||||
|
||||
/* If no input, fetch from deebee */
|
||||
if ( ! count( $rules ) )
|
||||
{
|
||||
$rules = $this->getRulesFromDb();
|
||||
}
|
||||
|
||||
/* Hello mum! */
|
||||
if ( is_array( $rules ) && count( $rules ) )
|
||||
{
|
||||
if ( is_array( $rules['archive'] ) )
|
||||
{
|
||||
foreach( $rules['archive'] as $key => $data )
|
||||
{
|
||||
$result = $this->_buildQueryBit( $key, $data, true );
|
||||
|
||||
if ( $result !== null )
|
||||
{
|
||||
$where[] = $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( is_array( $rules['skip'] ) )
|
||||
{
|
||||
foreach( $rules['skip'] as $key => $data )
|
||||
{
|
||||
$result = $this->_buildQueryBit( $key, $data, false );
|
||||
|
||||
if ( $result !== null )
|
||||
{
|
||||
$where[] = $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( $whereNot as $w )
|
||||
{
|
||||
$where[] = "!({$w})";
|
||||
}
|
||||
|
||||
if ( count( $where ) )
|
||||
{
|
||||
/* Only fetch non-deleted topics */
|
||||
$where[] = $this->registry->class_forums->fetchTopicHiddenQuery( array( 'hidden', 'visible' ) );
|
||||
|
||||
return implode( ' AND ', $where );
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the rules form the database
|
||||
*/
|
||||
public function getRulesFromDb()
|
||||
{
|
||||
$rules = array();
|
||||
|
||||
$this->DB->build( array( 'select' => '*',
|
||||
'from' => 'core_archive_rules',
|
||||
'where' => 'archive_app=\'' . $this->DB->addSlashes( $this->getApp() ) . '\'' ) );
|
||||
|
||||
$this->DB->execute();
|
||||
|
||||
while( $row = $this->DB->fetch() )
|
||||
{
|
||||
$whut = ( $row['archive_skip'] ) ? 'skip' : 'archive';
|
||||
|
||||
$rules[ $whut ][ $row['archive_field'] ] = array( 'value' => $row['archive_value'],
|
||||
'text' => $row['archive_text'],
|
||||
'unit' => $row['archive_unit'] );
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a post and returned archive friendly array
|
||||
* @param array $post
|
||||
* @return array
|
||||
*/
|
||||
public function nativeToArchiveFields( $post )
|
||||
{
|
||||
$archive = array( 'archive_id' => intval( $post['pid'] ),
|
||||
'archive_author_id' => intval( $post['author_id'] ),
|
||||
'archive_author_name' => $post['author_name'],
|
||||
'archive_ip_address' => $post['ip_address'],
|
||||
'archive_content_date' => intval( $post['post_date'] ),
|
||||
'archive_content' => $post['post'],
|
||||
'archive_queued' => $post['queued'],
|
||||
'archive_topic_id' => intval( $post['topic_id'] ),
|
||||
'archive_is_first' => intval( $post['new_topic'] ),
|
||||
'archive_bwoptions' => $post['post_bwoptions'],
|
||||
'archive_added' => IPS_UNIX_TIME_NOW,
|
||||
'archive_attach_key' => $post['post_key'],
|
||||
'archive_html_mode' => $post['post_htmlstate'],
|
||||
'archive_show_signature' => $post['use_sig'],
|
||||
'archive_show_emoticons' => $post['use_emo'],
|
||||
'archive_show_edited_by' => $post['append_edit'],
|
||||
'archive_edit_time' => intval( $post['edit_time'] ),
|
||||
'archive_edit_name' => $post['edit_name'],
|
||||
'archive_edit_reason' => $post['post_edit_reason'],
|
||||
'archive_forum_id' => intval( $post['forum_id'] ) );
|
||||
|
||||
return $archive;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs archive action
|
||||
* @param array $ids
|
||||
*/
|
||||
public function log( $ids )
|
||||
{
|
||||
$this->DB->insert( 'core_archive_log', array( 'archlog_date' => IPS_UNIX_TIME_NOW,
|
||||
'archlog_app' => $this->getApp(),
|
||||
'archlog_ids' => serialize( $ids ),
|
||||
'archlog_is_restore' => 0,
|
||||
'archlog_count' => count( $ids ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs archive action
|
||||
* @param array $ids
|
||||
* @param boolean $isRestore
|
||||
*/
|
||||
public function error( $msg )
|
||||
{
|
||||
$this->DB->insert( 'core_archive_log', array( 'archlog_date' => IPS_UNIX_TIME_NOW,
|
||||
'archlog_app' => $this->getApp(),
|
||||
'archlog_msg' => $msg,
|
||||
'archlog_is_error' => 1 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a WHERE segment
|
||||
* @param string $key
|
||||
* @param data $data
|
||||
* @param boolean $archiveOn Archive = true, skip = false
|
||||
*/
|
||||
protected function _buildQueryBit( $key, $data, $archiveOn )
|
||||
{
|
||||
$strOp = ( $archiveOn ) ? '=' : '!=';
|
||||
$inOp = ( $archiveOn ) ? 'IN' : 'NOT IN';
|
||||
|
||||
switch( $key )
|
||||
{
|
||||
case 'state':
|
||||
if ( $data['value'] != '' && $data['value'] != '-' )
|
||||
{
|
||||
return $this->getDbFieldFromKey( $key ) . $strOp . "'" . $data['value'] . "'";
|
||||
}
|
||||
break;
|
||||
case 'pinned':
|
||||
case 'approved':
|
||||
case 'poll':
|
||||
if ( $data['value'] != '' && $data['value'] != '-' )
|
||||
{
|
||||
return $this->getDbFieldFromKey( $key ) . $strOp . intval( $data['value'] );
|
||||
}
|
||||
break;
|
||||
case 'post':
|
||||
case 'view':
|
||||
case 'rating':
|
||||
if ( is_numeric( $data['text'] ) && $data['text'] > 0 )
|
||||
{
|
||||
return $this->getDbFieldFromKey( $key ) . $data['value'] . intval( $data['text'] );
|
||||
}
|
||||
break;
|
||||
case 'lastpost':
|
||||
if ( is_numeric( $data['text'] ) && $data['text'] > 0 )
|
||||
{
|
||||
switch( $data['unit'] )
|
||||
{
|
||||
case 'd':
|
||||
$seconds = 86400;
|
||||
break;
|
||||
case 'm':
|
||||
$seconds = 2592000;
|
||||
break;
|
||||
case 'y':
|
||||
$seconds = 31536000;
|
||||
break;
|
||||
}
|
||||
|
||||
$time = IPS_UNIX_TIME_NOW - ( $seconds * intval( $data['text'] ) );
|
||||
|
||||
/* Switch around for skipping */
|
||||
$data['value'] = ( $archiveOn ) ? $data['value'] : ( $data['value'] == '>' ? '<' : '>' );
|
||||
|
||||
return $this->getDbFieldFromKey( $key ) . ' ' . $data['value'] . ' ' . $time;
|
||||
}
|
||||
break;
|
||||
case 'forum':
|
||||
case 'member':
|
||||
if ( $data['text'] )
|
||||
{
|
||||
if ( IPSLib::isSerialized( $data['text'] ) )
|
||||
{
|
||||
$ids = unserialize( $data['text'] );
|
||||
}
|
||||
else
|
||||
{
|
||||
$ids = array();
|
||||
}
|
||||
|
||||
$inOp = ( $data['value'] == '+' ) ? 'IN' : 'NOT IN';
|
||||
|
||||
if ( is_array( $ids ) && count( $ids ) )
|
||||
{
|
||||
return $this->getDbFieldFromKey( $key ) . ' ' . $inOp . '(' . implode(',', $ids ) . ')';
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head><title>IP.Board - Bulletin Board System</title></head>
|
||||
<body>
|
||||
<h1>403: IP.Board -> Forbidden</h1>
|
||||
<hr>
|
||||
You have reached this page in error, please use your back button to return to the forum.
|
||||
<hr>
|
||||
<a href="http://www.invisionpower.com/">IP.Board</a>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* Archive: Writer
|
||||
* By Matt Mecham
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: ips_terabyte $
|
||||
* @copyright (c) 2010 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/company/standards.php#license
|
||||
* @package IP.Board
|
||||
* @link http://www.invisionpower.com
|
||||
* @since 17th February 2010
|
||||
* @version $Revision: 8644 $
|
||||
*/
|
||||
|
||||
class classes_archive_writer_sql extends classes_archive_writer
|
||||
{
|
||||
protected $remoteDB = false;
|
||||
protected $connectError = false;
|
||||
|
||||
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();
|
||||
|
||||
/* Connect */
|
||||
$this->_connect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to DB
|
||||
*/
|
||||
protected function _connect( $forceNew=false )
|
||||
{
|
||||
/* Do we have a remote DB? */
|
||||
if ( $this->settings['archive_remote_sql_database'] && $this->settings['archive_remote_sql_user'] )
|
||||
{
|
||||
if ( $forceNew OR ! is_object( $this->registry->dbFunctions()->getDB('remoteArchive') ) )
|
||||
{
|
||||
$this->registry->dbFunctions()->setDB( 'mysql', 'remoteArchive', array( 'sql_database' => $this->settings['archive_remote_sql_database'],
|
||||
'sql_user' => $this->settings['archive_remote_sql_user'],
|
||||
'sql_pass' => $this->settings['archive_remote_sql_pass'],
|
||||
'sql_host' => $this->settings['archive_remote_sql_host'],
|
||||
'sql_charset' => $this->settings['archive_remote_sql_charset'],
|
||||
'sql_tbl_prefix' => $this->settings['sql_tbl_prefix'],
|
||||
'catchConnectionError' => true ) );
|
||||
|
||||
|
||||
$this->remoteDB = $this->registry->dbFunctions()->getDB('remoteArchive');
|
||||
|
||||
/* Check for connection issue */
|
||||
if ( $this->remoteDB->error )
|
||||
{
|
||||
$this->connectError = $this->remoteDB->error;
|
||||
$this->remoteDB = null;
|
||||
|
||||
$this->registry->dbFunctions()->unsetDB('remoteArchive');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->remoteDB = $this->registry->dbFunctions()->getDB('remoteArchive');
|
||||
|
||||
/* Check for connection issue */
|
||||
if ( $this->remoteDB->error )
|
||||
{
|
||||
$this->connectError = $this->remoteDB->error;
|
||||
$this->remoteDB = null;
|
||||
|
||||
$this->registry->dbFunctions()->unsetDB('remoteArchive');
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->remoteDB = $this->DB;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush and reconnect
|
||||
*/
|
||||
public function flush()
|
||||
{
|
||||
$this->registry->dbFunctions()->unsetDB('remoteArchive');
|
||||
$this->_connect( TRUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to ensure this works
|
||||
*/
|
||||
public function test()
|
||||
{
|
||||
if ( $this->connectError )
|
||||
{
|
||||
return $this->connectError;
|
||||
}
|
||||
|
||||
if ( ! $this->remoteDB )
|
||||
{
|
||||
return 'NO_CONNECTION';
|
||||
}
|
||||
|
||||
if ( ! $this->remoteDB->checkForTable( 'forums_archive_posts' ) )
|
||||
{
|
||||
return 'NO_TABLE';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the table
|
||||
*/
|
||||
public function createTable()
|
||||
{
|
||||
if ( ! $this->remoteDB->checkForTable( 'forums_archive_posts' ) )
|
||||
{
|
||||
/* Fetch correct file */
|
||||
$TABLE = array();
|
||||
$prefix = ( is_object( $this->registry->dbFunctions()->getDB('remoteArchive') ) ) ? $this->registry->dbFunctions()->getPrefix('remoteArchive') : $this->registry->dbFunctions()->getPrefix();
|
||||
|
||||
include( IPSLib::getAppDir('forums') . '/setup/versions/install/sql/forums_mysql_tables.php' );/*noLibHook*/
|
||||
|
||||
foreach( $TABLE as $t )
|
||||
{
|
||||
if ( stristr( $t, ' forums_archive_posts' ) )
|
||||
{
|
||||
$this->remoteDB->query( str_replace( ' forums_archive_posts', ' ' . $prefix . 'forums_archive_posts', $t ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update posts
|
||||
*
|
||||
* @param $what Array of fields with vals to update
|
||||
* @param $where String of what to update
|
||||
*/
|
||||
public function update( array $what, $where )
|
||||
{
|
||||
$this->remoteDB->update( 'forums_archive_posts', $what, $where );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get counts
|
||||
*
|
||||
*/
|
||||
public function getDoneSoFarByTid( $tid )
|
||||
{
|
||||
return $this->remoteDB->buildAndFetch( array( 'select' => 'COUNT(*) as count, MAX(archive_id) as max',
|
||||
'from' => 'forums_archive_posts',
|
||||
'where' => 'archive_topic_id=' . $tid ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Write single entry to DB
|
||||
* @param array INTS
|
||||
*/
|
||||
public function set( $data=array() )
|
||||
{
|
||||
if ( ! count( $data ) )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( ! $this->remoteDB )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->remoteDB->replace( 'forums_archive_posts', $this->nativeToArchiveFields( $data ), array( 'archive_id' ) );
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user