Version 4.5.0

This commit is contained in:
Neo committed 2025-12-19 05:51:58 -08:00
1 parent 1a0c7fd3c2
commit f79dcf067a
3791 files changed
+248032 -76372

No files matched your search

@@ -1,20 +1,33 @@
<?php
/**
* @brief Converter: Perform conversion
* @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 Invision Community
* @subpackage convert
* @since 21 Jan 2015
*/
namespace IPS\convert\modules\admin\manage;
/* 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;
}
/**
* convert
* Run conversion
*/
class _convert extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -22,6 +35,11 @@ class _convert extends \IPS\Dispatcher\Controller
*/
public function execute()
{
if ( \IPS\DEMO_MODE === TRUE )
{
\IPS\Output::i()->error( 'demo_mode_function_blocked', '2V368/2', 403, '' );
}
\IPS\Output::i()->responsive = FALSE;
\IPS\Dispatcher::i()->checkAcpPermission( 'convert_manage' );
parent::execute();
@@ -34,11 +52,13 @@ class _convert extends \IPS\Dispatcher\Controller
*/
protected function manage()
{
/* Do we have an id? */
if ( ! isset( \IPS\Request::i()->id ) )
{
\IPS\Output::i()->error( 'no_conversion_app', '2V101/1' );
}
/* Load the app */
try
{
$app = \IPS\convert\App::load( \IPS\Request::i()->id );
@@ -48,45 +68,57 @@ class _convert extends \IPS\Dispatcher\Controller
\IPS\Output::i()->error( 'conversion_app_not_found', '2V101/2', 404 );
}
if ( $app->finished )
{
\IPS\Output::i()->error( 'conversion_app_finished', '2V368/1', 403, '' );
}
$softwareClass = $app->getSource();
$libraryClass = $softwareClass->getLibrary();
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'converting_x_to_x', FALSE, array( 'sprintf' => array( $softwareClass::softwareName(), \IPS\Application::load( $app->sw )->_title ) ) );
/* Build our table. If I can do this using only the Table helper, I'll be impressed */
try
{
$menuRows = $libraryClass->menuRows( TRUE );
/* Do a quick parent storage check */
\IPS\convert\Application::checkConvParent( $app->getSource()->getLibrary()->app );
/* "Extra steps" should not show in the list of things to convert, but still need to be defined in menu rows */
$extraSteps = array();
/* Are we using the legacy UI? If not, then start converting as we already have everything we need. */
if( !\IPS\CONVERTERS_DEV_UI )
{
$configurationNeeded = FALSE;
foreach( $softwareClass::canConvert() as $row )
/* If we have not yet configured the app, go there first */
if( !\count( $app->_session['more_info'] ) )
{
if( isset( $row['extra_steps'] ) )
$configurationNeeded = TRUE;
}
/* Check child apps also have more_info */
foreach( $app->children() as $childApp )
{
if( !\count( $childApp->_session['more_info'] ) )
{
$extraSteps = array_merge( $extraSteps, $row['extra_steps'] );
$configurationNeeded = TRUE;
break;
}
}
$menuRows = array_filter( $menuRows, function( $row ) use ( $extraSteps ) {
if( in_array( $row['step_method'], $extraSteps ) )
{
return FALSE;
}
/* Do we need to configure? */
if( $configurationNeeded )
{
$url = \IPS\Http\Url::internal( "app=convert&module=manage&controller=create&_moveToStep=convert_start_conversion_details&id=" . ( $app->parent ?: $app->app_id ) );
}
/* Otherwise start converting! */
else
{
$url = \IPS\Http\Url::internal( "app=convert&module=manage&controller=convert&do=runStep&id=" . $app->app_id )->csrf();
return TRUE;
});
}
catch( \IPS\convert\Exception $e )
{
\IPS\Output::i()->error( $e->getMessage(), '1V101/3' );
if( isset( \IPS\Request::i()->continue ) )
{
$url = $url->setQueryString( 'continue', \IPS\Request::i()->continue );
}
}
\IPS\Output::i()->redirect( $url );
}
/* Get our details */
$softwareClass = $app->getSource();
$libraryClass = $softwareClass->getLibrary();
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'converting_x_to_x', FALSE, array( 'sprintf' => array( $softwareClass::softwareName(), \IPS\Application::load( $app->sw )->_title ), 'striptags' => true ) );
/* Build our table. If I can do this using only the Table helper, I'll be impressed */
$menuRows = static::getMenuRows( $softwareClass );
$table = new \IPS\Helpers\Table\Custom( $menuRows, \IPS\Http\Url::internal( "app=convert&module=manage&controller=convert" ) );
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'table' ), 'convertMenuRow' );
$table->extra = array( 'sessionData' => $app->_session, 'appClass' => $app, 'softwareClass' => $softwareClass, 'libraryClass' => $libraryClass, 'menuRows' => $menuRows );
@@ -115,6 +147,194 @@ class _convert extends \IPS\Dispatcher\Controller
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'table' )->postConversionInformation( $libraryClass->getPostConversionInformation() );
}
}
/**
* Get the appropriate menu rows for the library
*
* @param \IPS\convert\Software $softwareClass Library class
* @param bool $filter Filter out extra steps
* @param bool $return Let exception bubble instead of outputting it
* @param bool $count Count database rows
* @return array
*/
public static function getMenuRows( $softwareClass, $filter=TRUE, $return=FALSE, $count=TRUE )
{
$libraryClass = $softwareClass->getLibrary();
try
{
$menuRows = $libraryClass->menuRows( $count );
/* "Extra steps" should not show in the list of things to convert, but still need to be defined in menu rows */
$extraSteps = array();
foreach( $softwareClass::canConvert() as $row )
{
if( isset( $row['extra_steps'] ) )
{
$extraSteps = array_merge( $extraSteps, $row['extra_steps'] );
}
}
if( $filter === TRUE )
{
$menuRows = array_filter( $menuRows, function( $row ) use ( $extraSteps ) {
if( \in_array( $row['step_method'], $extraSteps ) )
{
return FALSE;
}
return TRUE;
});
}
}
catch( \IPS\convert\Exception $e )
{
if( $return )
{
throw $e;
}
\IPS\Output::i()->error( $e->getMessage(), '1V101/3', 500 );
}
return $menuRows;
}
/**
* Figure out the next steps for converting
*
* @param \IPS\convert\App $app Application we are converting
* @return array
*/
protected function _getNextStep( $app )
{
/* Set our variables */
$appId = $app->app_id;
$method = null;
if ( !isset( $_SESSION['convertCountRows'] ) )
{
$_SESSION['convertCountRows'] = array();
}
$applicationsToCheck = array();
if( $app->parent )
{
$masterAppId = $app->_parent->app_id;
$applicationsToCheck[] = $app->_parent;
$applicationsToCheck = array_merge( $applicationsToCheck, iterator_to_array( $app->_parent->children() ) );
}
else
{
$masterAppId = $app->app_id;
$applicationsToCheck[] = $app;
$applicationsToCheck = array_merge( $applicationsToCheck, iterator_to_array( $app->children() ) );
}
/* Set up cache array */
if( !isset( $_SESSION['convertCountRows'][ $masterAppId ] ) )
{
$_SESSION['convertCountRows'][ $masterAppId ] = array();
}
/* Loop over all applications */
if( \count( $applicationsToCheck ) )
{
foreach( $applicationsToCheck as $appToCheck )
{
/* If this is the parent app, and we can convert settings, and we elected to convert them, and no steps are done, go there first */
$softwareClass = $appToCheck->getSource();
/* Set up cache array */
if( !isset( $_SESSION['convertCountRows'][ $masterAppId ][ $appToCheck->sw ] ) )
{
$_SESSION['convertCountRows'][ $masterAppId ][ $appToCheck->sw ] = array();
}
if( !$appToCheck->parent AND $softwareClass::canConvertSettings() AND isset( $appToCheck->_session['more_info']['convertSettings'] ) AND $appToCheck->_session['more_info']['convertSettings']['convert_settings'] AND !\count( $appToCheck->_session['completed'] ) )
{
$method = 'convertSettings';
$_SESSION['convertCountRows'][ $masterAppId ][ $appToCheck->sw ][ $method ] = 1;
}
/* First, get all of the menu rows for this application to see if there are any (more) to run.
Do NOT filter out extra steps as we need to run those too. */
$menuRows = static::getMenuRows( $softwareClass, FALSE, FALSE, FALSE );
foreach( $menuRows as $row )
{
/* We need the total counts so we can show the progress bar on the multiredirect */
if ( !isset( $_SESSION['convertCountRows'][ $masterAppId ][ $appToCheck->sw ][ $row['step_method'] ] ) )
{
/* Only count the rows if the cache is missing */
$counts = $softwareClass->getLibrary()->getDatabaseRowCounts( array( $row ), FALSE, TRUE );
$_SESSION['convertCountRows'][ $masterAppId ][ $appToCheck->sw ][ $row['step_method'] ] = $counts[0]['source_rows'];
}
if( $method !== NULL )
{
continue;
}
$appId = $appToCheck->app_id;
/* If the row is marked working, this is the one we're on */
if( array_key_exists( $row['step_method'], $appToCheck->_session['working'] ) )
{
$method = $row['step_method'];
continue;
}
if( isset( \IPS\Request::i()->method ) AND $row['step_method'] == \IPS\Request::i()->method )
{
$method = $row['step_method'];
$session = $app->_session;
if( $key = array_search( $method, $session['completed'] ) )
{
unset( $session['completed'][ $key ] );
$app->_session = $session;
}
}
/* Check whether the dependency was set to be converted, or whether it actually converted (it may not have any source data) */
foreach( $row['dependencies'] as $k => $v )
{
if( empty( $menuRows[ $v ] ) OR empty( $appToCheck->_session['more_info'][ $v ][ $menuRows[ $v ]['step_title'] ] ) )
{
/* It wasn't, so we can continue without this dependency */
unset( $row['dependencies'][ $k ] );
}
}
/* If this step has any dependencies not yet converted, skip for now */
if( \count( array_filter( $row['dependencies'], array( $appToCheck, 'dependencies' ) ) ) )
{
continue;
}
/* If this step is already completed, also skip */
if( \in_array( $row['step_method'], $appToCheck->_session['completed'] ) )
{
continue;
}
/* If we don't want this converted, also skip */
if( empty( $appToCheck->_session['more_info'][ $row['step_method'] ][ $row['step_title'] ] ) AND !\in_array( $row['step_method'], array_keys( $softwareClass->extraMenuRows() ) ) )
{
continue;
}
/* Otherwise, this is our next step */
$method = $row['step_method'];
}
}
}
return array( 'id' => $appId, 'method' => $method );
}
/**
* Remove Converted Data
@@ -123,6 +343,8 @@ class _convert extends \IPS\Dispatcher\Controller
*/
protected function emptyData()
{
\IPS\Session::i()->csrfCheck();
if ( ! isset( \IPS\Request::i()->id ) )
{
\IPS\Output::i()->error( 'no_conversion_app', '2V101/4' );
@@ -163,11 +385,15 @@ class _convert extends \IPS\Dispatcher\Controller
*/
protected function runStep()
{
\IPS\Session::i()->csrfCheck();
/* Make sure we have our app id */
if ( ! isset( \IPS\Request::i()->id ) )
{
\IPS\Output::i()->error( 'no_conversion_app', '2V101/6' );
}
/* Load our app */
try
{
$app = \IPS\convert\App::load( \IPS\Request::i()->id );
@@ -178,7 +404,7 @@ class _convert extends \IPS\Dispatcher\Controller
}
/* If we decided to truncate, we need to do so before getMoreInfo() is generated */
if ( isset( \IPS\Request::i()->empty_local_data ) AND \IPS\Request::i()->empty_local_data == 1 )
if ( \IPS\CONVERTERS_DEV_UI AND isset( \IPS\Request::i()->empty_local_data ) AND \IPS\Request::i()->empty_local_data == 1 )
{
$app->getSource()->getLibrary()->emptyLocalData( \IPS\Request::i()->method );
@@ -187,7 +413,6 @@ class _convert extends \IPS\Dispatcher\Controller
$session = $app->_session;
if ( isset( $canConvert[ \IPS\Request::i()->method ]['extra_steps'] ) )
{
$next = NULL;
foreach( $canConvert[ \IPS\Request::i()->method ]['extra_steps'] as $next )
{
if( $key = array_search( $next, $session['completed'] ) )
@@ -220,47 +445,11 @@ class _convert extends \IPS\Dispatcher\Controller
}
/* Do we need more information? */
$softwareClass = $app->getSource();
if ( ! isset( $app->_session['more_info'][ \IPS\Request::i()->method ] ) OR ( isset( \IPS\Request::i()->reconfigure ) AND \IPS\Request::i()->reconfigure == 1 ) )
if ( \IPS\CONVERTERS_DEV_UI AND ! isset( $app->_session['more_info'][ \IPS\Request::i()->method ] ) OR ( isset( \IPS\Request::i()->reconfigure ) AND \IPS\Request::i()->reconfigure == 1 ) )
{
if ( in_array( \IPS\Request::i()->method, $softwareClass::checkConf() ) )
if( $this->_checkMethodConfiguration( $app ) )
{
$getMoreInfo = $softwareClass->getMoreInfo( \IPS\Request::i()->method );
if ( is_array( $getMoreInfo ) AND count( $getMoreInfo ) )
{
$form = new \IPS\Helpers\Form( \IPS\Request::i()->method . '_more_info', 'continue' );
$form->hiddenValues['per_cycle'] = \IPS\Request::i()->per_cycle;
if ( isset( \IPS\Request::i()->reconfigure ) )
{
$form->hiddenValues['reconfigure'] = 1;
}
/* Show the 'more info' fields */
foreach( $getMoreInfo as $key => $input )
{
$fieldClass = $input['field_class'];
$form->add( new $fieldClass( $key, $input['field_default'], $input['field_required'], $input['field_extra'], isset( $input['field_validation'] ) ? $input['field_validation'] : NULL ) );
if ( $input['field_hint'] !== NULL )
{
$form->addMessage( $input['field_hint'], 'ipsMessage ipsMessage_info' );
}
}
if ( $values = $form->values() )
{
$per_cycle = $values['per_cycle'];
unset( $values['per_cycle'] );
$app->saveMoreInfo( \IPS\Request::i()->method, $values );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=convert&module=manage&controller=convert&do=runStep&id={$app->app_id}&per_cycle={$per_cycle}&method=" . \IPS\Request::i()->method ) );
}
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'more_info_needed' );
\IPS\Output::i()->output = $form;
return;
}
return;
}
}
@@ -274,45 +463,154 @@ class _convert extends \IPS\Dispatcher\Controller
}
}
/* Generate our multiredirect URL */
$redirectUrl = \IPS\Http\Url::internal( "app=convert&module=manage&controller=convert&do=runStep&id={$app->app_id}" )->csrf();
/* Legacy URL parameters we won't need now, but will if using the developer UI */
if( isset( \IPS\Request::i()->per_cycle ) )
{
$redirectUrl = $redirectUrl->setQueryString( 'per_cycle', \IPS\Request::i()->per_cycle );
}
if( isset( \IPS\Request::i()->method ) )
{
$redirectUrl = $redirectUrl->setQueryString( 'method', \IPS\Request::i()->method );
}
/* Output multiredirector */
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'converting' );
\IPS\Output::i()->output = new \IPS\Helpers\MultipleRedirect( \IPS\Http\Url::internal( "app=convert&module=manage&controller=convert&do=runStep&id={$app->app_id}&per_cycle=" . \IPS\Request::i()->per_cycle . "&method=" . \IPS\Request::i()->method ),
function( $data ) use ( $app )
{
try
\IPS\Output::i()->output = new \IPS\Helpers\MultipleRedirect(
/* The multiredirect URL */
$redirectUrl,
/* The function we are running on each step */
function( $data ) use ( $app )
{
return $app->getSource()->getLibrary()->process( $data, \IPS\Request::i()->method, \IPS\Request::i()->per_cycle );
}
catch( \IPS\convert\Exception $e )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=convert&module=manage&controller=convert&do=error&id={$app->app_id}" ) );
}
},
function() use ( $app )
{
/* Do we have more steps to process? If so, go to those first. */
$canConvert = $app->getSource()->getLibrary()->getConvertableItems();
if ( isset( $canConvert[ \IPS\Request::i()->method ]['extra_steps'] ) )
{
/* See which one we need to run next. */
$next = NULL;
foreach( $canConvert[ \IPS\Request::i()->method ]['extra_steps'] as $next )
/* Determine which method we are converting */
$convertData = $this->_getNextStep( $app );
/* If there is no method returned, we are done */
if( $convertData['method'] === NULL )
{
if ( in_array( $next, $app->_session['completed'] ) )
return NULL;
}
/* If we are moving on to a different app, load it now */
if( $convertData['id'] != $app->app_id )
{
$app = \IPS\convert\App::load( $convertData['id'] );
}
/* Convert settings if that's what we're doing */
if( $convertData['method'] == 'convertSettings' )
{
$app->getSource()->convertSettings( $app->_session['more_info']['convertSettings'] );
\IPS\Settings::i()->clearCache();
/* A Software Exception indicates we are done */
$completed = $app->_session['completed'];
$more_info = $app->_session['more_info'];
if ( !\in_array( $convertData['method'], $completed ) )
{
$next = NULL;
continue;
$completed[] = $convertData['method'];
}
/* Manually set running flag to save write queries */
$running = (isset( $app->_session['running'] ) ) ? $app->_session['running'] : array();
$running[ $convertData['method'] ] = FALSE;
$app->_session = array( 'working' => array(), 'more_info' => $more_info, 'completed' => $completed, 'running' => $running );
$percentage = 100 / \IPS\convert\Library::getTotalCachedRows( $app->getMasterConversionId() );
if ( $percentage > 100 )
{
$percentage = 100;
}
return array( 0, sprintf( \IPS\Member::loggedIn()->language()->get( 'converted_x_of_x' ), 1, 1, \IPS\Member::loggedIn()->language()->addToStack( '_convert_settings' ) ), $percentage );
}
try
{
/* If the current method has been running for 45 seconds, set the flag to 'continue' */
if( $app->getRunningFlag( $convertData['method'] ) AND $app->getRunningFlag( $convertData['method'] ) < ( time() - 45 ) )
{
$_SESSION['convertContinue'] = TRUE;
}
return $app->getSource()->getLibrary()->process( $data, $convertData['method'], $app->getSource()->getLibrary()->getMethodFromMenuRows( $convertData['method'] )['per_cycle'] );
}
catch( \IPS\convert\Exception $e )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=convert&module=manage&controller=convert&do=error&id={$app->app_id}" ) );
}
},
/* The final function to run */
function() use ( $app )
{
if( \IPS\CONVERTERS_DEV_UI AND isset( \IPS\Request::i()->method ) )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=convert&module=manage&controller=convert&do=manage&id=" . ( $app->parent ?: $app->app_id ) ) );
}
else
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=convert&module=manage&controller=convert&do=finish&wasConfirmed=1&id=" . ( $app->parent ?: $app->app_id ) )->csrf() );
}
}
);
}
/**
* Check if we need to configure this conversion step
*
* @param \IPS\convert\App $app App we are converting
* @return bool
*/
protected function _checkMethodConfiguration( $app )
{
$softwareClass = $app->getSource();
if ( \in_array( \IPS\Request::i()->method, $softwareClass::checkConf() ) )
{
$getMoreInfo = $softwareClass->getMoreInfo( \IPS\Request::i()->method );
if ( \is_array( $getMoreInfo ) AND \count( $getMoreInfo ) )
{
$form = new \IPS\Helpers\Form( \IPS\Request::i()->method . '_more_info', 'continue' );
$form->hiddenValues['per_cycle'] = \IPS\Request::i()->per_cycle;
if ( isset( \IPS\Request::i()->reconfigure ) )
{
$form->hiddenValues['reconfigure'] = 1;
}
/* Show the 'more info' fields */
foreach( $getMoreInfo as $key => $input )
{
$fieldClass = $input['field_class'];
$form->add( new $fieldClass( $key, $input['field_default'], $input['field_required'], $input['field_extra'], isset( $input['field_validation'] ) ? $input['field_validation'] : NULL ) );
if ( $input['field_hint'] !== NULL )
{
$form->addMessage( $input['field_hint'], 'ipsMessage ipsMessage_info' );
}
}
/* Found one? */
if ( !is_null( $next ) )
if ( $values = $form->values() )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=convert&module=manage&controller=convert&do=runStep&id={$app->app_id}&per_cycle=" . \IPS\Request::i()->per_cycle . "&method={$next}" ) );
$per_cycle = $values['per_cycle'];
unset( $values['per_cycle'] );
$app->saveMoreInfo( \IPS\Request::i()->method, $values );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=convert&module=manage&controller=convert&do=runStep&id={$app->app_id}&per_cycle={$per_cycle}&method=" . \IPS\Request::i()->method ) );
}
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'more_info_needed' );
\IPS\Output::i()->output = $form;
return TRUE;
}
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=convert&module=manage&controller=convert&id={$app->app_id}" ) );
} );
}
return FALSE;
}
/**
@@ -375,7 +673,7 @@ class _convert extends \IPS\Dispatcher\Controller
foreach( $softwareClass->settingsMapList() as $key => $setting )
{
$value = $setting['value'];
if ( is_bool( ( $setting['value'] ) ) )
if ( \is_bool( ( $setting['value'] ) ) )
{
$value = $setting['value'] === TRUE ? 'On' : 'Off';
}
@@ -437,7 +735,7 @@ class _convert extends \IPS\Dispatcher\Controller
$parent->finished = TRUE;
$parent->save();
if ( is_array( $return ) )
if ( \is_array( $return ) )
{
$messages = array_merge( $messages, $return );
}
@@ -457,7 +755,7 @@ class _convert extends \IPS\Dispatcher\Controller
$sibling->finished = TRUE;
$sibling->save();
if ( is_array( $return ) )
if ( \is_array( $return ) )
{
$messages = array_merge( $messages, $return );
}
@@ -477,7 +775,7 @@ class _convert extends \IPS\Dispatcher\Controller
catch( \OutOfRangeException $e )
{
/* This is a parent - run it's children */
foreach( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'convert_apps', array( "parent=?", $app->app_id ) ), 'IPS\convert\App' ) AS $child )
foreach( $app->children() AS $child )
{
$childSoftwareClass = $child->getSource();
@@ -488,7 +786,7 @@ class _convert extends \IPS\Dispatcher\Controller
$child->finished = TRUE;
$child->save();
if ( is_array( $return ) )
if ( \is_array( $return ) )
{
$messages = array_merge( $messages, $return );
}
@@ -508,7 +806,7 @@ class _convert extends \IPS\Dispatcher\Controller
$app->finished = TRUE;
$app->save();
if ( is_array( $return ) )
if ( \is_array( $return ) )
{
$messages = array_merge( $messages, $return );
}
@@ -519,13 +817,15 @@ class _convert extends \IPS\Dispatcher\Controller
}
/* Any Messages? */
if( !count( $messages ) )
if( !\count( $messages ) )
{
$messages = array( 'nothing_to_finish' );
}
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=convert&module=manage&controller=manage" ), implode( ', ', array_map( function( $key ) {
$messages = array_map( function( $key ) {
return \IPS\Member::loggedIn()->language()->addToStack( $key );
}, $messages ) ) );
}, $messages );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=convert&module=manage&controller=manage" ), \IPS\Member::loggedIn()->language()->formatList( $messages ) );
}
}