Version 4.5.0
This commit is contained in:
1 parent
1a0c7fd3c2
commit
f79dcf067a
3791 files changed
+248032
-76372
No files matched your search
@@ -5,19 +5,22 @@
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @package Invision Community
|
||||
* @subpackage Converter
|
||||
* @subpackage convert
|
||||
* @since 21 Jan 2015
|
||||
*/
|
||||
|
||||
namespace IPS\convert;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converter Library Class
|
||||
*/
|
||||
abstract class _Library
|
||||
{
|
||||
/**
|
||||
@@ -79,6 +82,25 @@ abstract class _Library
|
||||
$this->software = $software;
|
||||
}
|
||||
|
||||
/**
|
||||
* Libraries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function libraries()
|
||||
{
|
||||
return array(
|
||||
'core' => 'IPS\convert\Library\Core',
|
||||
'blog' => 'IPS\convert\Library\Blog',
|
||||
'calendar' => 'IPS\convert\Library\Calendar',
|
||||
'cms' => 'IPS\convert\Library\Cms',
|
||||
'downloads' => 'IPS\convert\Library\Downloads',
|
||||
'forums' => 'IPS\convert\Library\Forums',
|
||||
'gallery' => 'IPS\convert\Library\Gallery',
|
||||
'nexus' => 'IPS\convert\Library\Nexus',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* When called at the start of a conversion step, indicates that we are using a specific key for WHERE clauses which nets performance improvements
|
||||
*
|
||||
@@ -106,21 +128,23 @@ abstract class _Library
|
||||
/**
|
||||
* Processes a conversion cycle.
|
||||
*
|
||||
* @param integer $data Data from the previous step.
|
||||
* @param \IPS\convert\App $app Application Class for the current conversion
|
||||
* @param integer $data Data from the previous step.
|
||||
* @param string $method Conversion method we are processing
|
||||
* @param int|NULL $perCycle The number of results to process per cycle
|
||||
* @return array|NULL Data for the MultipleRedirect
|
||||
*/
|
||||
public function process( $data, $method, $perCycle=NULL )
|
||||
{
|
||||
if ( !is_null( $perCycle ) )
|
||||
if ( !\is_null( $perCycle ) )
|
||||
{
|
||||
static::$perCycle = $perCycle;
|
||||
}
|
||||
|
||||
/* temp */
|
||||
$classname = get_class( $this->software );
|
||||
$classname = \get_class( $this->software );
|
||||
$canConvert = $classname::canConvert();
|
||||
|
||||
/* If we hit something that can't be converted, there's a problem */
|
||||
if( $canConvert === NULL )
|
||||
{
|
||||
return NULL;
|
||||
@@ -128,24 +152,35 @@ abstract class _Library
|
||||
|
||||
static::$action = $canConvert[ $method ]['table'];
|
||||
static::$startValue = $data;
|
||||
$masterAppId = $this->software->app->getMasterConversionId();
|
||||
|
||||
if ( !isset( $_SESSION['convertCountRows'] ) )
|
||||
{
|
||||
$_SESSION['convertCountRows'] = array();
|
||||
}
|
||||
|
||||
if ( !isset( $_SESSION['convertCountRows'][ $method ] ) )
|
||||
|
||||
if ( !isset( $_SESSION['convertCountRows'][ $masterAppId ] ) )
|
||||
{
|
||||
$_SESSION['convertCountRows'][ $method ] = $this->software->countRows( static::$action, $canConvert[ $method ]['where'], true );
|
||||
$_SESSION['convertCountRows'][ $masterAppId ] = array();
|
||||
}
|
||||
|
||||
if ( !isset( $_SESSION['convertCountRows'][ $masterAppId ][ $this->software->app->sw ] ) )
|
||||
{
|
||||
$_SESSION['convertCountRows'][ $masterAppId ][ $this->software->app->sw ] = array();
|
||||
}
|
||||
|
||||
$total = $_SESSION['convertCountRows'][ $method ];
|
||||
if ( !isset( $_SESSION['convertCountRows'][ $masterAppId ][ $this->software->app->sw ][ $method ] ) )
|
||||
{
|
||||
$_SESSION['convertCountRows'][ $masterAppId ][ $this->software->app->sw ][ $method ] = $this->software->countRows( static::$action, $canConvert[ $method ]['where'], true );
|
||||
}
|
||||
|
||||
$total = $_SESSION['convertCountRows'][ $masterAppId ][ $this->software->app->sw ][ $method ];
|
||||
|
||||
if ( $data >= $total )
|
||||
{
|
||||
$completed = $this->software->app->_session['completed'];
|
||||
$more_info = $this->software->app->_session['more_info'];
|
||||
if ( !in_array( $method, $completed ) )
|
||||
if ( !\in_array( $method, $completed ) )
|
||||
{
|
||||
$completed[] = $method;
|
||||
}
|
||||
@@ -156,9 +191,10 @@ abstract class _Library
|
||||
|
||||
$this->software->app->_session = array( 'working' => array(), 'more_info' => $more_info, 'completed' => $completed, 'running' => $running );
|
||||
unset( $_SESSION['currentKeyValue'] );
|
||||
unset( $_SESSION['convertCountRows'][ $method ] );
|
||||
unset( $_SESSION['convertContinue'] );
|
||||
return NULL;
|
||||
|
||||
$percentage = ( 100 / static::getTotalCachedRows( $this->software->app->getMasterConversionId() ) ) * $this->_getConvertedCount();
|
||||
return array( 0, sprintf( \IPS\Member::loggedIn()->language()->get( 'converted_x_of_x' ), $total, $total, \IPS\Member::loggedIn()->language()->addToStack( '_' . $this->getMethodFromMenuRows( $method )['step_title'] ) ), $percentage );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -178,6 +214,7 @@ abstract class _Library
|
||||
break;
|
||||
|
||||
case 'convertPrivateMessages':
|
||||
case 'convertPrivateMessageReplies':
|
||||
$table = 'convert_link_pms';
|
||||
break;
|
||||
}
|
||||
@@ -185,13 +222,20 @@ abstract class _Library
|
||||
/* Select our max foreign ID */
|
||||
$type = $this->getMethodFromMenuRows( $method )['link_type'];
|
||||
|
||||
/* @todo If we ever support converting more than one CMS database, we'll need to change this */
|
||||
if( is_array( $type ) )
|
||||
if( \is_array( $type ) )
|
||||
{
|
||||
$type = $type[0];
|
||||
}
|
||||
|
||||
$lastId = \IPS\Db::i()->select( 'MAX(CAST( foreign_id AS UNSIGNED) )', $table, array( "app=? AND type=?", $this->software->app->app_id, $type ) )->first();
|
||||
try
|
||||
{
|
||||
$lastId = \IPS\Db::i()->select( 'foreign_id', $table, array( "app=? AND type=?", $this->software->app->app_id, $type ), 'link_id DESC', 1 )->first();
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
// Nothing has been ran yet
|
||||
$lastId = 0;
|
||||
}
|
||||
|
||||
/* Set the data count for MR */
|
||||
$data = \IPS\Db::i()->select( 'COUNT(*)', $table, array( "app=? AND type=?", $this->software->app->app_id, $type ) )->first();
|
||||
@@ -207,6 +251,7 @@ abstract class _Library
|
||||
}
|
||||
|
||||
/* Unset this so we don't do this again. */
|
||||
$_SESSION['convertContinue'] = false;
|
||||
unset( $_SESSION['convertContinue'] );
|
||||
}
|
||||
|
||||
@@ -223,12 +268,12 @@ abstract class _Library
|
||||
\IPS\Output::i()->error( 'converter_could_not_continue', '2V387/1', 403, '' );
|
||||
}
|
||||
|
||||
/* Generate dots for UI to show that processing is still occuring */
|
||||
/* Generate dots for UI to show that processing is still occurring */
|
||||
$dots = str_repeat( '.', $_SESSION['convertSkipped'] );
|
||||
|
||||
/* Sleep to allow the other process to complete without hammering the server */
|
||||
sleep(5);
|
||||
return array( $data, \IPS\Member::loggedIn()->language()->get( 'waiting_previous_process' ) . $dots, 100 / $total * ( $data ) );
|
||||
return array( $data, \IPS\Member::loggedIn()->language()->get( 'waiting_previous_process' ) . $dots, ( 100 / static::getTotalCachedRows( $this->software->app->getMasterConversionId() ) ) * $this->_getConvertedCount( $total ) );
|
||||
}
|
||||
|
||||
/* Set conversion as running */
|
||||
@@ -244,7 +289,7 @@ abstract class _Library
|
||||
/* A Software Exception indicates we are done */
|
||||
$completed = $this->software->app->_session['completed'];
|
||||
$more_info = $this->software->app->_session['more_info'];
|
||||
if ( !in_array( $method, $completed ) )
|
||||
if ( !\in_array( $method, $completed ) )
|
||||
{
|
||||
$completed[] = $method;
|
||||
}
|
||||
@@ -256,7 +301,9 @@ abstract class _Library
|
||||
$this->software->app->_session = array( 'working' => array(), 'more_info' => $more_info, 'completed' => $completed, 'running' => $running );
|
||||
unset( $_SESSION['currentKeyValue'] );
|
||||
unset( $_SESSION['convertContinue'] );
|
||||
return NULL;
|
||||
|
||||
$percentage = ( 100 / static::getTotalCachedRows( $this->software->app->getMasterConversionId() ) ) * $this->_getConvertedCount();
|
||||
return array( 0, sprintf( \IPS\Member::loggedIn()->language()->get( 'converted_x_of_x' ), $total, $total, \IPS\Member::loggedIn()->language()->addToStack( '_' . $this->getMethodFromMenuRows( $method )['step_title'] ) ), $percentage );
|
||||
}
|
||||
catch( \Exception $e )
|
||||
{
|
||||
@@ -284,15 +331,63 @@ abstract class _Library
|
||||
$running[ $method ] = FALSE;
|
||||
|
||||
$this->software->app->_session = array_merge( $this->software->app->_session, array( 'working' => array( $method => $data + static::$perCycle ), 'running' => $running ) );
|
||||
return array( $data + static::$perCycle, sprintf( \IPS\Member::loggedIn()->language()->get( 'converted_x_of_x' ), ( $data + static::$perCycle > $total ) ? $total : $data + static::$perCycle, \IPS\Member::loggedIn()->language()->addToStack( $this->getMethodFromMenuRows( $method )['step_title'] ), $total ), 100 / $total * ( $data + static::$perCycle ) );
|
||||
|
||||
$percentage = ( 100 / static::getTotalCachedRows( $this->software->app->getMasterConversionId() ) ) * $this->_getConvertedCount( ( $data + static::$perCycle > $total ) ? $total : $data + static::$perCycle );
|
||||
return array( $data + static::$perCycle, sprintf( \IPS\Member::loggedIn()->language()->get( 'converted_x_of_x' ), ( $data + static::$perCycle ) < $total ? $data + static::$perCycle : $total, $total, \IPS\Member::loggedIn()->language()->addToStack( '_' . $this->getMethodFromMenuRows( $method )['step_title'] ) ), $percentage );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of everything converted so far
|
||||
*
|
||||
* @param int $add Amount to add to completed count
|
||||
* @return int
|
||||
*/
|
||||
protected function _getConvertedCount( $add = 0 )
|
||||
{
|
||||
if( $this->software->app->parent )
|
||||
{
|
||||
$masterAppId = $this->software->app->_parent->app_id;
|
||||
$applicationsToCheck[] = $this->software->app->_parent;
|
||||
$applicationsToCheck = array_merge( $applicationsToCheck, iterator_to_array( $this->software->app->_parent->children() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$masterAppId = $this->software->app->app_id;
|
||||
$applicationsToCheck[] = $this->software->app;
|
||||
$applicationsToCheck = array_merge( $applicationsToCheck, iterator_to_array( $this->software->app->children() ) );
|
||||
}
|
||||
|
||||
$totalSoFar = 0;
|
||||
|
||||
foreach( $applicationsToCheck as $app )
|
||||
{
|
||||
/* Check app has cached data */
|
||||
if( !isset( $_SESSION['convertCountRows'][ $masterAppId ][ $app->sw ] ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$totalSoFar += array_sum(
|
||||
array_filter( $_SESSION['convertCountRows'][ $masterAppId ][ $app->sw ], function( $key ) use( $app ) {
|
||||
return ( \in_array( $key, $app->_session['completed'] ) );
|
||||
}, ARRAY_FILTER_USE_KEY )
|
||||
);
|
||||
}
|
||||
|
||||
if( $add )
|
||||
{
|
||||
$totalSoFar += $add;
|
||||
}
|
||||
|
||||
return $totalSoFar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty Conversion Data
|
||||
*
|
||||
* @param integer $data Data from the previous step.
|
||||
* @param \IPS\convert\App $app Application Class for the current conversion
|
||||
* @param integer $data Data from the previous step.
|
||||
* @param \IPS\convert\App $method The conversion method to empty results for
|
||||
* @return array|NULL Data for the MultipleRedirect
|
||||
*/
|
||||
public function emptyData( $data, $method )
|
||||
@@ -300,7 +395,7 @@ abstract class _Library
|
||||
$perCycle = 500;
|
||||
|
||||
/* temp */
|
||||
$classname = get_class( $this->software );
|
||||
$classname = \get_class( $this->software );
|
||||
$canConvert = $this->menuRows();
|
||||
|
||||
if ( !isset( $canConvert[ $method ]['link_type'] ) )
|
||||
@@ -314,7 +409,7 @@ abstract class _Library
|
||||
{
|
||||
$count = 0;
|
||||
/* Just one type? */
|
||||
if ( !is_array( $type ) )
|
||||
if ( !\is_array( $type ) )
|
||||
{
|
||||
foreach( array( 'convert_link', 'convert_link_pms', 'convert_link_posts', 'convert_link_topics' ) as $table )
|
||||
{
|
||||
@@ -346,7 +441,7 @@ abstract class _Library
|
||||
try
|
||||
{
|
||||
/* If we're dealing with more than one type, then we can just delete from any one at random until we're done */
|
||||
if ( is_array( $type ) )
|
||||
if ( \is_array( $type ) )
|
||||
{
|
||||
$type = array_rand( $type );
|
||||
}
|
||||
@@ -406,7 +501,7 @@ abstract class _Library
|
||||
/**
|
||||
* Truncates data from local database
|
||||
*
|
||||
* @param string Convert method to run truncate call for.
|
||||
* @param string $method Convert method to run truncate call for
|
||||
* @return void
|
||||
*/
|
||||
public function emptyLocalData( $method )
|
||||
@@ -442,7 +537,17 @@ abstract class _Library
|
||||
{
|
||||
default:
|
||||
$key = $linkType ?: $table;
|
||||
$toDelete['convert_link'][ $key ] = $key;
|
||||
if( \is_array( $key ) )
|
||||
{
|
||||
foreach( $key as $link )
|
||||
{
|
||||
$toDelete['convert_link'][ $link ] = $link;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$toDelete['convert_link'][ $key ] = $key;
|
||||
}
|
||||
break;
|
||||
case 'core_message_topics':
|
||||
case 'core_message_posts':
|
||||
@@ -505,7 +610,7 @@ abstract class _Library
|
||||
return $this->convertable;
|
||||
}
|
||||
|
||||
$classname = get_class( $this->software );
|
||||
$classname = \get_class( $this->software );
|
||||
$this->convertable = $classname::canConvert();
|
||||
|
||||
if( $this->convertable === NULL )
|
||||
@@ -528,22 +633,23 @@ abstract class _Library
|
||||
* Magic __call() method
|
||||
*
|
||||
* @param string $name The method to call without convert prefix.
|
||||
* @param mixed $arguements Arguments to pass to the method
|
||||
* @param mixed $arguments Arguments to pass to the method
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call( $name, $arguments )
|
||||
{
|
||||
if ( method_exists( $this, 'convert' . $name ) )
|
||||
{
|
||||
return call_user_func( array( $this, 'convert' . $name ), $arguments );
|
||||
$function = 'convert' . $name;
|
||||
return $this->$function( $arguments );
|
||||
}
|
||||
elseif ( method_exists( $this, $name ) )
|
||||
{
|
||||
return call_user_func( array( $this, $name ), $arguments );
|
||||
return $this->$name( $arguments );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Log::log( "Call to undefined method in " . get_class( $this ) . "::{$name}", 'converters' );
|
||||
\IPS\Log::log( "Call to undefined method in " . \get_class( $this ) . "::{$name}", 'converters' );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -555,11 +661,25 @@ abstract class _Library
|
||||
*/
|
||||
public function getPostConversionInformation()
|
||||
{
|
||||
$appId = $this->software->app->parent ?: $this->software->app->app_id;
|
||||
return \IPS\Member::loggedIn()->language()->addToStack( 'conversion_info_message', FALSE, array( 'sprintf' => array(
|
||||
(string) \IPS\Http\Url::internal( "app=convert&module=manage&controller=create&_new=1" ),
|
||||
(string) \IPS\Http\Url::internal( "app=convert&module=manage&controller=convert&do=finish&id={$appId}" )
|
||||
) ) );
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a count of cached convertable rows
|
||||
*
|
||||
* @param int $appId Parent conversion APP ID
|
||||
* @return int|null
|
||||
*/
|
||||
public static function getTotalCachedRows( int $appId ) :?int
|
||||
{
|
||||
if( empty( $_SESSION['convertCountRows'][ $appId ] ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return array_sum( array_map( function( $app ) {
|
||||
return array_sum( $app );
|
||||
}, $_SESSION['convertCountRows'][ $appId ] ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -574,20 +694,22 @@ abstract class _Library
|
||||
* Utility method to run queries for menuRows() data
|
||||
*
|
||||
* @param array $return menuRow() data
|
||||
* @param bool $ips Count IPS rows
|
||||
* @param bool $source Count source rows
|
||||
* @return array
|
||||
* @throws \UnderflowException
|
||||
* @throws \IPS\convert\Exception
|
||||
*/
|
||||
public function getDatabaseRowCounts( array $return )
|
||||
public function getDatabaseRowCounts( array $return, $ips=TRUE, $source=TRUE )
|
||||
{
|
||||
foreach( $return as $key => $value )
|
||||
{
|
||||
if( isset( $value['ips_rows'] ) AND $value['ips_rows'] instanceof \IPS\Db\Select )
|
||||
if( $ips AND isset( $value['ips_rows'] ) AND $value['ips_rows'] instanceof \IPS\Db\Select )
|
||||
{
|
||||
$return[ $key ]['ips_rows'] = (int) $value['ips_rows']->first();
|
||||
}
|
||||
|
||||
if( isset( $return[ $key ]['source_rows']['table'] ) )
|
||||
if( $source AND isset( $return[ $key ]['source_rows']['table'] ) )
|
||||
{
|
||||
$return[ $key ]['source_rows'] = $this->software->countRows( $value['source_rows']['table'], $value['source_rows']['where'] );
|
||||
}
|
||||
@@ -631,7 +753,7 @@ abstract class _Library
|
||||
/**
|
||||
* Returns an array of tables that need to be truncated when Empty Local Data is used
|
||||
*
|
||||
* @param string The method to truncate
|
||||
* @param string $method The method to truncate
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function truncate( $method );
|
||||
|
||||
Reference in new issue
Block a user