Version 5.0.0 beta 1

This commit is contained in:
Neo committed 2025-12-19 16:27:35 -08:00
1 parent 25ddeb65d6
commit 15c7beabc5
6736 files changed
+627902 -497943

No files matched your search

+78 -61
View File
@@ -12,16 +12,33 @@
namespace IPS\convert;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
use ErrorException;
use Exception;
use IPS\Db;
use IPS\Db\Select;
use IPS\forums\Topic\ArchivedPost;
use IPS\Log;
use IPS\Member;
use IPS\Output;
use UnderflowException;
use function count;
use function defined;
use function get_class;
use function in_array;
use function is_array;
use function is_null;
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Converter Library Class
*/
abstract class _Library
abstract class Library
{
/**
* @brief Flag to indicate that we are using a specific key, and should do WHERE static::$currentKeyName > static::$currentKeyValue rather than LIMIT 0,1000
@@ -74,10 +91,10 @@ abstract class _Library
/**
* Constructor
*
* @param \IPS\convert\Software $software Software Instance we are converting from
* @param Software $software Software Instance we are converting from
* @return void
*/
public function __construct( \IPS\convert\Software $software )
public function __construct(Software $software )
{
$this->software = $software;
}
@@ -135,13 +152,13 @@ abstract class _Library
*/
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 */
@@ -180,7 +197,7 @@ abstract class _Library
{
$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;
}
@@ -194,7 +211,7 @@ abstract class _Library
unset( $_SESSION['convertContinue'] );
$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 );
return array( 0, sprintf( Member::loggedIn()->language()->get( 'converted_x_of_x' ), $total, $total, Member::loggedIn()->language()->addToStack( '_' . $this->getMethodFromMenuRows( $method )['step_title'] ) ), $percentage );
}
else
{
@@ -222,23 +239,23 @@ abstract class _Library
/* Select our max foreign ID */
$type = $this->getMethodFromMenuRows( $method )['link_type'];
if( \is_array( $type ) )
if( is_array( $type ) )
{
$type = $type[0];
}
try
{
$lastId = \IPS\Db::i()->select( 'foreign_id', $table, array( "app=? AND type=?", $this->software->app->app_id, $type ), 'link_id DESC', 1 )->first();
$lastId = Db::i()->select( 'foreign_id', $table, array( "app=? AND type=?", $this->software->app->app_id, $type ), 'link_id DESC', 1 )->first();
}
catch( \UnderflowException $e )
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();
$data = Db::i()->select( 'COUNT(*)', $table, array( "app=? AND type=?", $this->software->app->app_id, $type ) )->first();
/* Set as last key value */
$this->setLastKeyValue( $lastId );
@@ -265,7 +282,7 @@ abstract class _Library
if( $_SESSION['convertSkipped'] > 5 AND $this->software->app->getRunningFlag( $method ) < ( time() - 60 ))
{
unset( $_SESSION['convertSkipped'] );
\IPS\Output::i()->error( 'converter_could_not_continue', '2V387/1', 403, '' );
Output::i()->error( 'converter_could_not_continue', '2V387/1', 403, '' );
}
/* Generate dots for UI to show that processing is still occurring */
@@ -273,7 +290,7 @@ abstract class _Library
/* 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 / static::getTotalCachedRows( $this->software->app->getMasterConversionId() ) ) * $this->_getConvertedCount( $total ) );
return array( $data, Member::loggedIn()->language()->get( 'waiting_previous_process' ) . $dots, ( 100 / static::getTotalCachedRows( $this->software->app->getMasterConversionId() ) ) * $this->_getConvertedCount( $total ) );
}
/* Set conversion as running */
@@ -289,7 +306,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;
}
@@ -303,27 +320,27 @@ abstract class _Library
unset( $_SESSION['convertContinue'] );
$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 );
return array( 0, sprintf( Member::loggedIn()->language()->get( 'converted_x_of_x' ), $total, $total, Member::loggedIn()->language()->addToStack( '_' . $this->getMethodFromMenuRows( $method )['step_title'] ) ), $percentage );
}
catch( \Exception $e )
catch( Exception $e )
{
\IPS\Log::log( $e, 'converters' );
Log::log( $e, 'converters' );
/* Clear the running flag */
$this->software->app->setRunningFlag( $method, FALSE );
$this->software->app->log( $e->getMessage(), __METHOD__, \IPS\convert\App::LOG_WARNING );
throw new \IPS\convert\Exception;
$this->software->app->log( $e->getMessage(), __METHOD__, App::LOG_WARNING );
throw new Exception;
}
catch( \ErrorException $e )
catch( ErrorException $e )
{
\IPS\Log::log( $e, 'converters' );
Log::log( $e, 'converters' );
/* Clear the running flag */
$this->software->app->setRunningFlag( $method, FALSE );
$this->software->app->log( $e->getMessage(), __METHOD__, \IPS\convert\App::LOG_WARNING );
throw new \IPS\convert\Exception;
$this->software->app->log( $e->getMessage(), __METHOD__, App::LOG_WARNING );
throw new Exception;
}
/* Manually set running flag to save write queries */
@@ -333,7 +350,7 @@ abstract class _Library
$this->software->app->_session = array_merge( $this->software->app->_session, array( 'working' => array( $method => $data + static::$perCycle ), 'running' => $running ) );
$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 array( $data + static::$perCycle, sprintf( Member::loggedIn()->language()->get( 'converted_x_of_x' ), ( $data + static::$perCycle ) < $total ? $data + static::$perCycle : $total, $total, Member::loggedIn()->language()->addToStack( '_' . $this->getMethodFromMenuRows( $method )['step_title'] ) ), $percentage );
}
}
@@ -370,7 +387,7 @@ abstract class _Library
$totalSoFar += array_sum(
array_filter( $_SESSION['convertCountRows'][ $masterAppId ][ $app->app_id ], function( $key ) use( $app ) {
return ( \in_array( $key, $app->_session['completed'] ) );
return ( in_array( $key, $app->_session['completed'] ) );
}, ARRAY_FILTER_USE_KEY )
);
}
@@ -387,7 +404,7 @@ abstract class _Library
* Empty Conversion Data
*
* @param integer $data Data from the previous step.
* @param \IPS\convert\App $method The conversion method to empty results for
* @param App $method The conversion method to empty results for
* @return array|NULL Data for the MultipleRedirect
*/
public function emptyData( $data, $method )
@@ -395,7 +412,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'] ) )
@@ -409,11 +426,11 @@ 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 )
{
$count += \IPS\Db::i()->select( 'COUNT(*)', $table, array( "type=? AND app=?", $type, $this->software->app->app_id ) )->first();
$count += Db::i()->select( 'COUNT(*)', $table, array( "type=? AND app=?", $type, $this->software->app->app_id ) )->first();
}
}
else
@@ -422,7 +439,7 @@ abstract class _Library
{
foreach( array( 'convert_link', 'convert_link_pms', 'convert_link_posts', 'convert_link_topics' ) as $table )
{
$count += \IPS\Db::i()->select( 'COUNT(*)', $table, array( "type=? AND app=?", $t, $this->software->app->app_id ) )->first();
$count += Db::i()->select( 'COUNT(*)', $table, array( "type=? AND app=?", $t, $this->software->app->app_id ) )->first();
}
}
}
@@ -441,7 +458,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 );
}
@@ -467,34 +484,34 @@ abstract class _Library
break;
}
$total = (int) \IPS\Db::i()->select( 'COUNT(*)', $table, array( "type=? AND app=?", $type, $this->software->app->app_id ) )->first();
$rows = iterator_to_array( \IPS\Db::i()->select( 'link_id, ipb_id', $table, array( "type=? AND app=?", $type, $this->software->app->app_id ), "link_id ASC", array( 0, $perCycle ) )->setKeyField( 'link_id' )->setValueField( 'ipb_id' ) );
$def = \IPS\Db::i()->getTableDefinition( $type );
$total = (int) Db::i()->select( 'COUNT(*)', $table, array( "type=? AND app=?", $type, $this->software->app->app_id ) )->first();
$rows = iterator_to_array( Db::i()->select( 'link_id, ipb_id', $table, array( "type=? AND app=?", $type, $this->software->app->app_id ), "link_id ASC", array( 0, $perCycle ) )->setKeyField( 'link_id' )->setValueField( 'ipb_id' ) );
$def = Db::i()->getTableDefinition( $type );
if ( isset( $def['indexes']['PRIMARY']['columns'] ) )
{
$id = array_pop( $def['indexes']['PRIMARY']['columns'] );
}
\IPS\Db::i()->delete( $type, array( \IPS\Db::i()->in( $id, array_values( $rows ) ) ) );
\IPS\Db::i()->delete( $table, array( \IPS\Db::i()->in( 'link_id', array_keys( $rows ) ) ) );
Db::i()->delete( $type, array( Db::i()->in( $id, array_values( $rows ) ) ) );
Db::i()->delete( $table, array( Db::i()->in( 'link_id', array_keys( $rows ) ) ) );
}
catch( \Exception $e )
catch( Exception $e )
{
\IPS\Log::log( $e, 'converters' );
Log::log( $e, 'converters' );
$this->software->app->log( $e->getMessage(), __METHOD__, \IPS\convert\App::LOG_WARNING );
throw new \IPS\convert\Exception;
$this->software->app->log( $e->getMessage(), __METHOD__, App::LOG_WARNING );
throw new Exception;
}
catch( \ErrorException $e )
catch( ErrorException $e )
{
\IPS\Log::log( $e, 'converters' );
Log::log( $e, 'converters' );
$this->software->app->log( $e->getMessage(), __METHOD__, \IPS\convert\App::LOG_ERROR );
throw new \IPS\convert\Exception;
$this->software->app->log( $e->getMessage(), __METHOD__, App::LOG_ERROR );
throw new Exception;
}
return array( $data + $perCycle, sprintf( \IPS\Member::loggedIn()->language()->get( 'removed_x_of_x' ), ( $data + $perCycle > $total ) ? $_SESSION['emptyConvertedDataCount'] : $data + $perCycle, \IPS\Member::loggedIn()->language()->addToStack( $method ), $_SESSION['emptyConvertedDataCount'] ), 100 / $_SESSION['emptyConvertedDataCount'] * ( $data + $perCycle ) );
return array( $data + $perCycle, sprintf( Member::loggedIn()->language()->get( 'removed_x_of_x' ), ( $data + $perCycle > $total ) ? $_SESSION['emptyConvertedDataCount'] : $data + $perCycle, Member::loggedIn()->language()->addToStack( $method ), $_SESSION['emptyConvertedDataCount'] ), 100 / $_SESSION['emptyConvertedDataCount'] * ( $data + $perCycle ) );
}
}
@@ -519,11 +536,11 @@ abstract class _Library
/* Kind of a hacky way to make sure we truncate the right forums archive table */
if ( $table === 'forums_archive_posts' )
{
\IPS\forums\Topic\ArchivedPost::db()->delete( $table, $where );
ArchivedPost::db()->delete( $table, $where );
}
else
{
\IPS\Db::i()->delete( $table, $where );
Db::i()->delete( $table, $where );
}
/* Do we have a specific link type? */
@@ -537,7 +554,7 @@ abstract class _Library
{
default:
$key = $linkType ?: $table;
if( \is_array( $key ) )
if( is_array( $key ) )
{
foreach( $key as $link )
{
@@ -565,28 +582,28 @@ abstract class _Library
foreach( $toDelete AS $table => $links )
{
if( !\count( $links ) )
if( !count( $links ) )
{
continue;
}
/* If posts or topics we may be able to truncate */
if( \in_array( $table, array( 'convert_link_topics', 'convert_link_posts' ) ) )
if( in_array( $table, array( 'convert_link_topics', 'convert_link_posts' ) ) )
{
try
{
/* Check for other app data in this table */
\IPS\Db::i()->select( 'link_id', $table, array('app<>?', $this->software->app->app_id ), NULL, 1 )->first();
Db::i()->select( 'link_id', $table, array('app<>?', $this->software->app->app_id ), NULL, 1 )->first();
}
catch ( \UnderflowException $e )
catch ( UnderflowException $e )
{
/* There isn't any other app data in this table, truncate */
\IPS\Db::i()->delete( $table );
Db::i()->delete( $table );
continue;
}
}
\IPS\Db::i()->delete( $table, array( \IPS\Db::i()->in( 'type', $links ) . " AND app=?", $this->software->app->app_id ) );
Db::i()->delete( $table, array( Db::i()->in( 'type', $links ) . " AND app=?", $this->software->app->app_id ) );
}
/* Clear the running flag */
@@ -610,7 +627,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 )
@@ -649,7 +666,7 @@ abstract class _Library
}
else
{
\IPS\Log::log( "Call to undefined method in " . \get_class( $this ) . "::{$name}", 'converters' );
Log::log( "Call to undefined method in " . get_class( $this ) . "::{$name}", 'converters' );
return NULL;
}
}
@@ -697,14 +714,14 @@ abstract class _Library
* @param bool $ips Count IPS rows
* @param bool $source Count source rows
* @return array
* @throws \UnderflowException
* @throws \IPS\convert\Exception
* @throws UnderflowException
* @throws Exception
*/
public function getDatabaseRowCounts( array $return, $ips=TRUE, $source=TRUE )
{
foreach( $return as $key => $value )
{
if( $ips AND isset( $value['ips_rows'] ) AND $value['ips_rows'] instanceof \IPS\Db\Select )
if( $ips AND isset( $value['ips_rows'] ) AND $value['ips_rows'] instanceof Select )
{
$return[ $key ]['ips_rows'] = (int) $value['ips_rows']->first();
}