<?php
/**
* @brief Archive table conversion module
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package IPS Tools
* @since 4 Sept 2013
*/
namespace IPSUtf8\Convert;
/**
* Conversion class
*/
class Archive extends \IPSUtf8\Convert
{
/**
* @brief Instance
*/
protected static $instance = NULL;
/**
* @brief Tables we need to convert
*/
protected static $nonUtf8Tables = NULL;
/**
* @brief Tables we need to convert
*/
protected static $nonUtf8Collations = NULL;
/**
* @brief Number of rows we need to convert
*/
protected static $rowsToConvert = NULL;
/**
* @brief Table definition
*/
protected static $tableDefinition = NULL;
/**
* @brief Post archive table name
*/
const ARCHIVE_TABLE = 'forums_archive_posts';
/**
* @brief Native Database object
*/
protected static $db = NULL;
/**
* @brief UTF-8 Database object
*/
protected static $utf = NULL;
/**
* Get instance
*
* @return Output
*/
public static function i()
{
if ( self::$instance === NULL )
{
self::$instance = new self();
require( ROOT_PATH . '/conf_global.php' );
if ( $INFO['archive_remote_sql_database'] )
{
/* Set up two new database connections */
static::$db = \IPSUtf8\Db::i('archive', array(
'sql_host' => $INFO['archive_remote_sql_host'],
'sql_user' => $INFO['archive_remote_sql_user'],
'sql_pass' => $INFO['archive_remote_sql_pass'],
'sql_database' => $INFO['archive_remote_sql_database'],
'sql_tbl_prefix' => $INFO['sql_tbl_prefix']
) );
$sessionData = \IPSUtf8\Session::i()->json;
static::$utf = \IPSUtf8\Db::i('utf8-archive', array(
'sql_host' => $INFO['archive_remote_sql_host'],
'sql_user' => $INFO['archive_remote_sql_user'],
'sql_pass' => $INFO['archive_remote_sql_pass'],
'sql_database' => $INFO['archive_remote_sql_database'],
'sql_tbl_prefix' => $INFO['sql_tbl_prefix'],
'sql_utf8mb4' => ( isset( $sessionData['use_utf8mb4'] ) AND ! empty( $sessionData['use_utf8mb4'] ) )
) );
static::$tableDefinition = \IPSUtf8\Db::i('archive')->getTableDefinition( self::ARCHIVE_TABLE );
if ( preg_match( '#\scharset=([a-z0-9]+?)(\s|$)#i', $row['Create Table'], $matches ) )
{
static::$tableDefinition['charset'] = mb_strtolower( $matches[1] );
}
static::$tableDefinition['definition'] = static::$tableDefinition;
}
self::$instance->init();
}
return static::$instance;
}
/**
* Set the current work table
*
* @return void
*/
public function getTable()
{
$table = self::$tableDefinition;
\IPSUtf8\Session::i()->current_table = self::ARCHIVE_TABLE;
\IPSUtf8\Session::i()->current_pkey = 'archive_id';
\IPSUtf8\Session::i()->save();
if ( in_array( self::ARCHIVE_TABLE, array_keys( \IPSUtf8\Session::i()->completed_json ) ) )
{
return null;
}
static::log( "Continuing with " . $table['name'] . ' (PKEY: ' . \IPSUtf8\Session::i()->current_pkey . ')' );
if ( ! \IPSUtf8\Db::i('utf8-archive')->checkForTable( $table['name'] ) )
{
if ( \IPSUtf8\Db::i('utf8-archive')->createTable( $this->checkTable( $table['definition'] ) ) === false )
{
throw new \RuntimeException( \IPSUtf8\Db::i('utf8-archive')->error . "\n" . var_export( $table['definition'], true ) );
}
}
return $table;
}
/**
* Return tables that need converting
*
* @param boolean $force Force a recount
* @return array
*/
public function getNonUtf8Tables( $force=false )
{
if ( static::$nonUtf8Tables === NULL or $force === TRUE )
{
$row = static::$db->query( "SHOW CREATE TABLE `" . \IPSUtf8\Db::i('archive')->prefix . self::ARCHIVE_TABLE . "`" )->fetch_assoc();
$tblCharset = null;
if ( preg_match( '#\scharset=([a-z0-9]+?)(\s|$)#i', $row['Create Table'], $matches ) )
{
$tblCharset = mb_strtolower( $matches[1] );
}
if ( $tblCharset !== 'utf8' )
{
static::$nonUtf8Tables = array( self::ARCHIVE_TABLE );
}
}
return static::$nonUtf8Tables;
}
/**
* Returns total rows to convert
*
* @return array
*/
public function getTotalRowsToConvert()
{
if ( static::$rowsToConvert === NULL )
{
static::$rowsToConvert = static::$db->select('COUNT(*) as count', self::ARCHIVE_TABLE )->setKeyField('count')->first();
}
return static::$rowsToConvert;
}
/**
* Returns whether the DB has the correct collation
*
* @return bool
*/
public function getNonUtf8CollationTables()
{
if ( static::$nonUtf8Collations === null )
{
static::$nonUtf8Collations = array();
/* Best check the tables, then */
foreach( self::$tableDefinition['definition']['columns'] as $name => $column )
{
if ( $column['collation'] and ! in_array( $column['collation'], array( 'utf8_unicode_ci', 'utf8mb4_unicode_ci' ) ) )
{
static::$nonUtf8Collations[] = self::$tableDefinition['name'];
break;
}
}
}
return static::$nonUtf8Collations;
}
/**
* Return a list of numeric columns that need checking
*
* @param string $name Table
* @return array Array of columns that need checking as they can contain INT
*/
public static function getNumericColumns( $name )
{
if ( ! is_string( $name ) )
{
return false;
}
$return = array();
foreach( self::$tableDefinition['definition']['columns'] as $col => $val )
{
if ( in_array( mb_strtolower( $val['type'] ), static::$numericCols ) )
{
$return[] = $val['name'];
}
}
return $return;
}
/**
* Return a list of columns that need converting
*
* @param string $name Table
* @return array Array of columns that need converting as they can contain text
*/
public static function getConvertableColumns( $name )
{
if ( ! is_string( $name ) )
{
return false;
}
$return = array();
foreach( self::$tableDefinition['definition']['columns'] as $col => $val )
{
if ( in_array( mb_strtolower( $val['type'] ), static::$convertCols ) )
{
$return[] = $val['name'];
}
}
return $return;
}
/**
* Rename the tables
*
* @return null
*/
public function renameTables()
{
/* No need to bother with fancy stuffs to find the tables - we already know what they are */
\IPSUtf8\Db::i('archive')->query( "RENAME TABLE `" . \IPSUtf8\Db::i('archive')->prefix . self::ARCHIVE_TABLE . "` TO `orig_" . \IPSUtf8\Db::i('archive')->prefix . self::ARCHIVE_TABLE . "`" );
/* Sleep for a second to avoid a race condition */
sleep(1);
\IPSUtf8\Db::i('utf8-archive')->query( "RENAME TABLE `" . \IPSUtf8\Db::i('utf8-archive')->prefix . self::ARCHIVE_TABLE . "` TO `" . \IPSUtf8\Db::i('archive')->prefix . self::ARCHIVE_TABLE . "`" );
}
}