Invision Power Services, Inc. * @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 . "`" ); } }