Files
IPB/applications/core/setup/upg_101100/upgrade.php
T
2025-12-19 05:44:59 -08:00

1162 lines
34 KiB
PHP

<?php
/**
* @brief 4.2.0 Beta 1 Upgrade Code
* @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
* @since 06 Feb 2017
*/
namespace IPS\core\setup\upg_101100;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* 4.2.0 Beta 1 Upgrade Code
*/
class _Upgrade
{
/**
* Step 1
* Enable/disable letter photos appropriately
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step1()
{
/* If the installation can't write text to images anyways, just return now and normal settings insert will insert with the normal default value */
if( !\IPS\Image::canWriteText() )
{
return true;
}
\IPS\Db::i()->insert( 'core_sys_conf_settings', array(
'conf_key' => 'letter_photos',
'conf_default' => 'letters',
'conf_value' => $_SESSION['upgrade_options']['core']['101100']['letter_photos'] ? 'letters' : 'default',
'conf_app' => 'core'
) );
unset( \IPS\Data\Store::i()->settings );
return true;
}
/**
* Custom title for this step
*
* @return string
*/
public function step1CustomTitle()
{
return "Setting letter photo preference";
}
/**
* Step 2
* Fix orphaned status updates
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step2()
{
$queries = array();
/* Orphaned status updates */
try
{
\IPS\Db::i()->select( 'status_id', 'core_member_status_updates', array( 'status_member_id NOT IN ( ' . \IPS\Db::i()->select( 'member_id', 'core_members' ) . ' )' ), NULL, 1 )->first();
/* Remove the offending entries */
\IPS\Db::i()->returnQuery = TRUE;
$queries[] = array(
'table' => 'core_member_status_updates',
'query' => \IPS\Db::i()->delete( 'core_member_status_updates', array( 'status_member_id NOT IN ( ' . \IPS\Db::i()->select( 'member_id', 'core_members' ) . ' )' ) )
);
\IPS\Db::i()->returnQuery = FALSE;
}
catch( \UnderflowException $e ) {}
/* Orphaned ignore entries */
try
{
\IPS\Db::i()->select( 'ignore_id', 'core_ignored_users', array( 'ignore_owner_id NOT IN ( ' . \IPS\Db::i()->select( 'member_id', 'core_members' ) . ' )' ), NULL, 1 )->first();
/* Remove the offending entries */
\IPS\Db::i()->returnQuery = TRUE;
$queries[] = array(
'table' => 'core_ignored_users',
'query' => \IPS\Db::i()->delete( 'core_ignored_users', array( 'ignore_owner_id NOT IN ( ' . \IPS\Db::i()->select( 'member_id', 'core_members' ) . ' )' ) )
);
\IPS\Db::i()->returnQuery = FALSE;
}
catch( \UnderflowException $e ) {}
/* Orphaned reputation data */
try
{
\IPS\Db::i()->select( 'id', 'core_reputation_index', array( 'member_id NOT IN ( ' . \IPS\Db::i()->select( 'member_id', 'core_members' ) . ' )' ), NULL, 1 )->first();
/* Remove the offending entries */
\IPS\Db::i()->returnQuery = TRUE;
$queries[] = array(
'table' => 'core_reputation_index',
'query' => \IPS\Db::i()->delete( 'core_reputation_index', array( 'member_id NOT IN ( ' . \IPS\Db::i()->select( 'member_id', 'core_members' ) . ' )' ) )
);
\IPS\Db::i()->returnQuery = FALSE;
}
catch( \UnderflowException $e ) {}
/* Is this site affected by any of these issues? */
if( !count( $queries ) )
{
return TRUE;
}
$toRun = \IPS\core\Setup\Upgrade::runManualQueries( $queries );
if ( count( $toRun ) )
{
\IPS\core\Setup\Upgrade::adjustMultipleRedirect( array( 1 => 'core', 'extra' => array( '_upgradeStep' => 3 ) ) );
/* Queries to run manually */
return array( 'html' => \IPS\Theme::i()->getTemplate( 'forms' )->queries( $toRun, \IPS\Http\Url::internal( 'controller=upgrade' )->setQueryString( array( 'key' => $_SESSION['uniqueKey'], 'mr_continue' => 1, 'mr' => \IPS\Request::i()->mr ) ) ) );
}
return TRUE;
}
/**
* Custom title for this step
*
* @return string
*/
public function step2CustomTitle()
{
return "Removing orphaned data";
}
/**
* Create/Convert Member History Table
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step3()
{
/* This step is different if Commerce is already installed */
if( \IPS\Db::i()->checkForTable( 'nexus_customer_history' ) )
{
$_SESSION['convertedMemberHistory'] = TRUE;
\IPS\Db::i()->renameTable( 'nexus_customer_history', 'core_member_history' );
\IPS\Db::i()->addColumn( 'core_member_history',
array(
'name' => 'log_app',
'type' => 'VARCHAR',
'length' => 250,
'allow_null' => FALSE,
'default' => '',
'comment' => 'Application'
)
);
}
else
{
\IPS\Db::i()->createTable( array(
'name' => 'core_member_history',
'columns' =>
array(
'log_id' =>
array(
'allow_null' => false,
'auto_increment' => true,
'binary' => false,
'comment' => 'ID Number',
'decimals' => NULL,
'default' => NULL,
'length' => 20,
'name' => 'log_id',
'type' => 'BIGINT',
'unsigned' => true,
'values' => array(),
'zerofill' => false,
),
'log_app' =>
array(
'allow_null' => false,
'auto_increment' => false,
'binary' => false,
'comment' => 'Application',
'decimals' => NULL,
'default' => '',
'length' => 250,
'name' => 'log_app',
'type' => 'VARCHAR',
'unsigned' => false,
'values' => array(),
'zerofill' => false,
),
'log_member' =>
array(
'allow_null' => false,
'auto_increment' => false,
'binary' => false,
'comment' => 'Member ID',
'decimals' => NULL,
'default' => '0',
'length' => 20,
'name' => 'log_member',
'type' => 'BIGINT',
'unsigned' => true,
'values' => array(),
'zerofill' => false,
),
'log_by' =>
array(
'allow_null' => true,
'auto_increment' => false,
'binary' => false,
'comment' => 'Action performed by',
'decimals' => NULL,
'default' => NULL,
'length' => 20,
'name' => 'log_by',
'type' => 'BIGINT',
'unsigned' => true,
'values' => array(),
'zerofill' => false,
),
'log_type' =>
array(
'allow_null' => true,
'auto_increment' => false,
'binary' => false,
'comment' => 'Log Type',
'decimals' => NULL,
'default' => NULL,
'length' => 32,
'name' => 'log_type',
'type' => 'VARCHAR',
'unsigned' => false,
'values' => array(),
'zerofill' => false,
),
'log_data' =>
array(
'allow_null' => true,
'auto_increment' => false,
'binary' => false,
'comment' => '',
'decimals' => NULL,
'default' => NULL,
'length' => 0,
'name' => 'log_data',
'type' => 'TEXT',
'unsigned' => false,
'values' => array(),
'zerofill' => false,
),
'log_date' =>
array(
'allow_null' => false,
'auto_increment' => false,
'binary' => false,
'comment' => '',
'decimals' => NULL,
'default' => '0',
'length' => 10,
'name' => 'log_date',
'type' => 'INT',
'unsigned' => false,
'values' => array(),
'zerofill' => false,
),
'log_ip_address' =>
array(
'allow_null' => true,
'auto_increment' => false,
'binary' => false,
'comment' => '',
'decimals' => NULL,
'default' => NULL,
'length' => 46,
'name' => 'log_ip_address',
'type' => 'VARCHAR',
'unsigned' => false,
'values' => array(),
'zerofill' => false,
)
),
'indexes' =>
array(
'PRIMARY' =>
array(
'type' => 'primary',
'name' => 'PRIMARY',
'length' =>
array(
0 => NULL,
),
'columns' =>
array(
0 => 'log_id',
),
),
'application' =>
array(
'type' => 'key',
'name' => 'application',
'length' =>
array(
0 => NULL,
),
'columns' =>
array(
0 => 'log_app',
),
),
'log_member' =>
array(
'type' => 'key',
'name' => 'log_member',
'length' =>
array(
0 => NULL,
),
'columns' =>
array(
0 => 'log_member',
),
),
'log_ip_address' =>
array(
'type' => 'key',
'name' => 'log_ip_address',
'length' =>
array(
0 => NULL,
),
'columns' =>
array(
0 => 'log_ip_address',
),
),
'log_date' =>
array(
'type' => 'key',
'name' => 'log_date',
'length' =>
array(
0 => NULL,
),
'columns' =>
array(
0 => 'log_date',
),
)
)
) );
}
return TRUE;
}
/**
* Custom title for this step
*
* @return string
*/
public function step3CustomTitle()
{
return "Setting up Member History";
}
/**
* Add index and set log_app
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step4()
{
/* Only perform this if converting from Nexus */
if( isset( $_SESSION['convertedMemberHistory'] ) )
{
\IPS\Db::i()->returnQuery = TRUE;
$queryApplication = \IPS\Db::i()->addIndex( 'core_member_history', array(
'type' => 'key',
'name' => 'application',
'length' =>
array(
0 => NULL,
),
'columns' =>
array(
0 => 'log_app',
)
) );
\IPS\Db::i()->returnQuery = FALSE;
\IPS\Db::i()->returnQuery = TRUE;
$updateQuery = \IPS\Db::i()->update( 'core_member_history', array( 'log_app' => 'nexus' ) );
\IPS\Db::i()->returnQuery = FALSE;
$toRun = \IPS\core\Setup\Upgrade::runManualQueries( array(
array(
'table' => 'core_member_history',
'query' => $queryApplication ),
array(
'table' => 'core_member_history',
'query' => $updateQuery )
) );
if ( count( $toRun ) )
{
\IPS\core\Setup\Upgrade::adjustMultipleRedirect( array( 'extra' => array( '_upgradeStep' => 5 ) ) );
/* Queries to run manually */
return array( 'html' => \IPS\Theme::i()->getTemplate( 'forms' )->queries( $toRun, \IPS\Http\Url::internal( 'controller=upgrade' )->setQueryString( array( 'key' => $_SESSION['uniqueKey'], 'mr_continue' => 1, 'mr' => \IPS\Request::i()->mr ) ) ) );
}
}
return TRUE;
}
/**
* Custom title for this step
*
* @return string
*/
public function step4CustomTitle()
{
return "Checking indexes";
}
/**
* Update Nexus 'info' types
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step5()
{
/* Only perform this if converting from Nexus */
if( isset( $_SESSION['convertedMemberHistory'] ) )
{
/* Some init */
$did = 0;
$limit = 0;
if( isset( \IPS\Request::i()->extra ) )
{
$limit = \IPS\Request::i()->extra;
}
/* Try to prevent timeouts to the extent possible */
$cutOff = \IPS\core\Setup\Upgrade::determineCutoff();
foreach( \IPS\Db::i()->select( '*', 'core_member_history', array( 'log_type=?', 'info' ), 'log_id ASC', array( $limit, 500 ) ) as $log )
{
if( $cutOff !== null AND time() >= $cutOff )
{
return ( $limit + $did );
}
$did++;
$data = json_decode( $log['log_data'], TRUE );
if( isset( $data['email'] ) )
{
\IPS\Db::i()->update( 'core_member_history', array(
'log_app' => 'core',
'log_type' => 'email_change',
'log_data' => json_encode( array( 'old' => $data['email'], 'new' => '' ) )
),
array( 'log_id=?', $log['log_id'] )
);
}
elseif( isset( $data['password'] ) )
{
\IPS\Db::i()->update( 'core_member_history', array(
'log_app' => 'core',
'log_type' => 'password_change',
'log_data' => json_encode( array( 'password' => '' ) )
),
array( 'log_id=?', $log['log_id'] )
);
}
}
if( $did )
{
return $limit + $did;
}
else
{
unset( $_SESSION['_step5Count'], $_SESSION['convertedMemberHistory'] );
return TRUE;
}
}
return TRUE;
}
/**
* Custom title for this step
*
* @return string
*/
public function step5CustomTitle()
{
$limit = isset( \IPS\Request::i()->extra ) ? \IPS\Request::i()->extra : 0;
if( !isset( $_SESSION['_step5Count'] ) )
{
$_SESSION['_step5Count'] = \IPS\Db::i()->select( 'COUNT(*)', 'core_member_history', array( 'log_type=?', 'info' ) )->first();
}
return "Converting customer history log types (Converted so far: " . ( ( $limit > $_SESSION['_step5Count'] ) ? $_SESSION['_step5Count'] : $limit ) . ' out of ' . $_SESSION['_step5Count'] . ')';
}
/**
* Move Display Name history to the Member History Table
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step6()
{
/* Some init */
$did = 0;
$limit = 0;
if( isset( \IPS\Request::i()->extra ) )
{
$limit = \IPS\Request::i()->extra;
}
/* Try to prevent timeouts to the extent possible */
$cutOff = \IPS\core\Setup\Upgrade::determineCutoff();
foreach( \IPS\Db::i()->select( '*', 'core_dnames_change', null, 'dname_id ASC', array( $limit, 500 ) ) as $displayName )
{
if( $cutOff !== null AND time() >= $cutOff )
{
return ( $limit + $did );
}
$did++;
\IPS\Db::i()->insert( 'core_member_history', array(
'log_app' => 'core',
'log_member' => $displayName['dname_member_id'],
'log_by' => NULL,
'log_type' => 'display_name',
'log_data' => json_encode( array( 'old' => $displayName['dname_previous'], 'new' => $displayName['dname_current'] ) ),
'log_date' => $displayName['dname_date'],
'log_ip_address' => $displayName['dname_ip_address']
) );
}
if( $did )
{
return $limit + $did;
}
else
{
/* Delete table */
\IPS\Db::i()->dropTable( 'core_dnames_change' );
unset( $_SESSION['_step6Count'] );
return TRUE;
}
}
/**
* Custom title for this step
*
* @return string
*/
public function step6CustomTitle()
{
$limit = isset( \IPS\Request::i()->extra ) ? \IPS\Request::i()->extra : 0;
if( !isset( $_SESSION['_step6Count'] ) )
{
$_SESSION['_step6Count'] = \IPS\Db::i()->select( 'COUNT(*)', 'core_dnames_change' )->first();
}
return "Moving Display Name history to the Member History system (Converted so far: " . ( ( $limit > $_SESSION['_step6Count'] ) ? $_SESSION['_step6Count'] : $limit ) . ' out of ' . $_SESSION['_step6Count'] . ')';
}
/**
* Fix not existing moderator groups
*
* @return bool
*/
public function step7()
{
\IPS\Db::i()->delete( 'core_moderators', array( 'type=? AND ' . \IPS\Db::i()->in( 'id', iterator_to_array( \IPS\Db::i()->select('g_id', 'core_groups' ) ), TRUE ), 'g' ) );
unset ( \IPS\Data\Store::i()->moderators );
return TRUE;
}
/**
* Custom title for this step
*
* @return string
*/
public function step7CustomTitle()
{
return "Removing non-existent moderator groups";
}
/**
* Step 8
* Set up promoted items
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step8()
{
/* Populate the table */
if ( ! \IPS\Db::i()->select( 'COUNT(*)', 'core_social_promote_sharers' )->first() )
{
foreach( array( 'Facebook', 'Twitter', 'Internal' ) as $service )
{
\IPS\Db::i()->insert( 'core_social_promote_sharers', array( 'sharer_key' => $service, 'sharer_settings' => '[]', 'sharer_enabled' => 0 ) );
}
/* Add menu item */
\IPS\core\FrontNavigation::insertMenuItem( NULL, array( 'app' => 'core', 'key' => 'Promoted' ), \IPS\Db::i()->select( 'MAX(position)', 'core_menu' )->first() );
}
return true;
}
/**
* Custom title for this step
*
* @return string
*/
public function step8CustomTitle()
{
return "Setting up defaults for promotion";
}
/**
* Step 9
* Create reaction types based on current settings
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step9()
{
$position = 0;
/* Go ahead and insert the default "Like" - if we aren't use likes, leave it disabled. */
$fileObj = \IPS\File::create( 'core_Reaction', 'react_like.png', file_get_contents( \IPS\ROOT_PATH . '/' . \IPS\CP_DIRECTORY . '/install/reaction/react_like.png' ), 'reactions', FALSE, NULL, FALSE );
$id = \IPS\Db::i()->insert( 'core_reactions', array(
'reaction_value' => 1,
'reaction_icon' => (string) $fileObj,
'reaction_position' => ++$position,
'reaction_enabled' => 1,
) );
\IPS\Lang::saveCustom( 'core', 'reaction_title_' . $id, 'Like' );
foreach( array( 'thanks', 'haha', 'confused', 'sad' ) AS $reaction )
{
$fileObj = \IPS\File::create( 'core_Reaction', "react_{$reaction}.png", file_get_contents( \IPS\ROOT_PATH . '/' . \IPS\CP_DIRECTORY . "/install/reaction/react_{$reaction}.png" ), 'reactions', FALSE, NULL, FALSE );
$id = \IPS\Db::i()->insert( 'core_reactions', array(
'reaction_value' => ( in_array( $reaction, array( 'confused', 'sad' ) ) ) ? 0 : 1,
'reaction_icon' => (string) $fileObj,
'reaction_position' => ++$position,
'reaction_enabled' => ( \IPS\Settings::i()->reputation_point_types == 'like' ) ? 1 : 0,
) );
\IPS\Lang::saveCustom( 'core', 'reaction_title_' . $id, ucwords( $reaction ) );
}
return TRUE;
}
/**
* Custom title for this step
*
* @return string
*/
public function step9CustomTitle()
{
return "Creating default reactions";
}
/**
* Step 10
* Create reaction types based on current settings
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step10()
{
$position = \IPS\Db::i()->select( 'max(reaction_position)', 'core_reactions' )->first();
/* Now insert a positive or negative row based on settings and then run queries to adjust current reputation */
switch( \IPS\Settings::i()->reputation_point_types )
{
case 'positive':
$fileObj = \IPS\File::create( 'core_Reaction', 'react_up.png', file_get_contents( \IPS\ROOT_PATH . '/' . \IPS\CP_DIRECTORY . '/install/reaction/react_up.png' ), 'reactions', FALSE, NULL, FALSE );
$id = \IPS\Db::i()->insert( 'core_reactions', array(
'reaction_value' => 1,
'reaction_icon' => (string) $fileObj,
'reaction_position' => ++$position,
'reaction_enabled' => 1,
) );
\IPS\Lang::saveCustom( 'core', 'reaction_title_' . $id, 'Upvote' );
break;
case 'negative':
$fileObj = \IPS\File::create( 'core_Reaction', 'react_down.png', file_get_contents( \IPS\ROOT_PATH . '/' . \IPS\CP_DIRECTORY . '/install/reaction/react_down.png' ), 'reactions', FALSE, NULL, FALSE );
$id = \IPS\Db::i()->insert( 'core_reactions', array(
'reaction_value' => -1,
'reaction_icon' => (string) $fileObj,
'reaction_position' => ++$position,
'reaction_enabled' => 1,
) );
\IPS\Lang::saveCustom( 'core', 'reaction_title_' . $id, 'Downvote' );
break;
case 'both':
$fileObj = \IPS\File::create( 'core_Reaction', 'react_up.png', file_get_contents( \IPS\ROOT_PATH . '/' . \IPS\CP_DIRECTORY . '/install/reaction/react_up.png' ), 'reactions', FALSE, NULL, FALSE );
$posId = \IPS\Db::i()->insert( 'core_reactions', array(
'reaction_value' => 1,
'reaction_icon' => (string) $fileObj,
'reaction_position' => ++$position,
'reaction_enabled' => 1,
) );
\IPS\Lang::saveCustom( 'core', 'reaction_title_' . $posId, 'Upvote' );
$fileObj = \IPS\File::create( 'core_Reaction', 'react_down.png', file_get_contents( \IPS\ROOT_PATH . '/' . \IPS\CP_DIRECTORY . '/install/reaction/react_down.png' ), 'reactions', FALSE, NULL, FALSE );
$negId = \IPS\Db::i()->insert( 'core_reactions', array(
'reaction_value' => -1,
'reaction_icon' => (string) $fileObj,
'reaction_position' => ++$position,
'reaction_enabled' => 1,
) );
\IPS\Lang::saveCustom( 'core', 'reaction_title_' . $negId, 'Downvote' );
break;
}
return TRUE;
}
/**
* Custom title for this step
*
* @return string
*/
public function step10CustomTitle()
{
return "Creating default reactions";
}
/**
* Step 11
* Map reaction types based on current settings
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step11()
{
/* Now insert a positive or negative row based on settings and then run queries to adjust current reputation */
switch( \IPS\Settings::i()->reputation_point_types )
{
case 'like':
$toRun = \IPS\core\Setup\Upgrade::runManualQueries( array( array(
'table' => 'core_reputation_index',
'query' => "UPDATE `" . \IPS\Db::i()->prefix . "core_reputation_index` SET reaction = 1 WHERE rep_rating = 1;"
) ) );
break;
case 'positive':
$id = \IPS\Db::i()->select( 'reaction_id', 'core_reactions', array( "reaction_icon LIKE CONCAT( '%', ? )", 'react_up.png' ) )->first();
$toRun = \IPS\core\Setup\Upgrade::runManualQueries( array( array(
'table' => 'core_reputation_index',
'query' => "UPDATE `" . \IPS\Db::i()->prefix . "core_reputation_index` SET reaction = {$id} WHERE rep_rating = 1;"
) ) );
break;
case 'negative':
$id = \IPS\Db::i()->select( 'reaction_id', 'core_reactions', array( "reaction_icon LIKE CONCAT( '%', ? )", 'react_down.png' ) )->first();
$toRun = \IPS\core\Setup\Upgrade::runManualQueries( array( array(
'table' => 'core_reputation_index',
'query' => "UPDATE `" . \IPS\Db::i()->prefix . "core_reputation_index` SET reaction = {$id} WHERE rep_rating = -1;"
) ) );
break;
case 'both':
$negId = \IPS\Db::i()->select( 'reaction_id', 'core_reactions', array( "reaction_icon LIKE CONCAT( '%', ? )", 'react_down.png' ) )->first();
$posId = \IPS\Db::i()->select( 'reaction_id', 'core_reactions', array( "reaction_icon LIKE CONCAT( '%', ? )", 'react_up.png' ) )->first();
$toRun = \IPS\core\Setup\Upgrade::runManualQueries( array( array(
'table' => 'core_reputation_index',
'query' => "UPDATE `" . \IPS\Db::i()->prefix . "core_reputation_index` SET reaction = {$negId} WHERE rep_rating = -1;"
),array(
'table' => 'core_reputation_index',
'query' => "UPDATE `" . \IPS\Db::i()->prefix . "core_reputation_index` SET reaction = {$posId} WHERE rep_rating = 1;"
) ) );
break;
}
if ( count( $toRun ) )
{
\IPS\core\Setup\Upgrade::adjustMultipleRedirect( array( 1 => 'core', 'extra' => array( '_upgradeStep' => 12 ) ) );
/* Queries to run manually */
return array( 'html' => \IPS\Theme::i()->getTemplate( 'forms' )->queries( $toRun, \IPS\Http\Url::internal( 'controller=upgrade' )->setQueryString( array( 'key' => $_SESSION['uniqueKey'], 'mr_continue' => 1, 'mr' => \IPS\Request::i()->mr ) ) ) );
}
return TRUE;
}
/**
* Custom title for this step
*
* @return string
*/
public function step11CustomTitle()
{
return "Mapping existing reactions";
}
/**
* Step 12
* Fix broken ranks
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step12()
{
\IPS\Db::i()->update( 'core_member_ranks', 'pips=100', array('pips>?', 100 ) );
return TRUE;
}
/**
* Custom title for this step
*
* @return string
*/
public function step12CustomTitle()
{
return 'Fixing ranks';
}
/**
* Step 13
* Convert group promotion rules
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step13()
{
$position = 1;
foreach( \IPS\Db::i()->select( '*', 'core_groups' ) as $group )
{
if( $group['g_promotion'] != '-1&-1' )
{
list( $gid, $gUnit ) = explode( '&', $group['g_promotion'] );
if ( $gid > 0 and $gUnit > 0)
{
$filters = array();
/* Join date */
if( $group['g_promotion_type'] == 1 )
{
$filters['core_Joined'] = array( 'days' => $gUnit );
}
/* Reputation */
elseif( $group['g_promotion_type'] == 2 )
{
$filters['core_Reputation'] = array( 'reputation_operator' => 'gt', 'reputation_score' => $gUnit );
}
/* Post count */
else
{
$filters['core_Content'] = array( 'content_count_operator' => 'gt', 'content_count_score' => $gUnit );
}
$filters['core_Group'] = array( 'groups' => $group['g_id'] );
$insertId = \IPS\Db::i()->insert( 'core_group_promotions', array(
'promote_position' => $position,
'promote_enabled' => 1,
'promote_filters' => json_encode( $filters ),
'promote_actions' => json_encode( array( 'primary_group' => $gid, 'secondary_group' => array(), 'secondary_remove' => array() ) )
) );
$defaultLanguageId =\IPS\Lang::defaultLanguage();
\IPS\Lang::saveCustom( 'core', "g_promotion_" . $insertId, 'From: ' . \IPS\Lang::load($defaultLanguageId)->get( "core_group_{$group['g_id']}" ) );
$position++;
}
}
}
/* Now drop the group columns that aren't needed */
\IPS\Db::i()->dropColumn( 'core_groups', array( 'g_promotion_type', 'g_promotion' ) );
/* And finally, set up the exclude flag by default for all admin and moderator groups */
foreach( \IPS\Db::i()->select( 'id', 'core_moderators', array( 'type=?', 'g' ) ) as $moderator )
{
\IPS\Db::i()->update( 'core_groups', array( 'g_promote_exclude' => 1 ), array( 'g_id=?', $moderator ) );
}
foreach( \IPS\Db::i()->select( 'row_id', 'core_admin_permission_rows', array( 'row_id_type=?', 'group' ) ) as $admin )
{
\IPS\Db::i()->update( 'core_groups', array( 'g_promote_exclude' => 1 ), array( 'g_id=?', $admin ) );
}
unset( \IPS\Data\Store::i()->groups );
return TRUE;
}
/**
* Custom title for this step
*
* @return string
*/
public function step13CustomTitle()
{
return 'Converting group promotion rules';
}
/**
* Step 14
* Convert Profile Fields to Profile Completion Steps
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step14()
{
if ( \IPS\Settings::i()->use_coppa OR \IPS\Settings::i()->minimum_age )
{
try
{
\IPS\Db::i()->select( 'conf_value', 'core_sys_conf_settings', array( 'conf_key=?', 'quick_register' ) )->first();
}
catch( \UnderflowException $ex )
{
$insert = array(
'conf_key' => 'quick_register',
'conf_value' => 0,
'conf_default' => 1,
'conf_keywords' => ''
);
/* This key was added in 4.0.8 so it may not exist */
\IPS\Db::i()->insert( 'core_sys_conf_settings', $insert );
}
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => 0 ), array( 'conf_key=?', 'quick_register' ) );
unset( \IPS\Data\Store::i()->settings );
}
$required = array();
foreach( \IPS\Db::i()->select( '*', 'core_pfields_data', array( "pf_not_null=?", 1 ) ) AS $row )
{
$required[] = "core_pfield_{$row['pf_id']}";
}
if ( count( $required ) )
{
$step = new \IPS\Member\ProfileStep;
$step->required = 1;
$step->extension = 'core_ProfileFields';
$step->completion_act = "profile_fields";
$step->subcompletion_act = $required;
$step->save();
\IPS\Lang::saveCustom( 'core', "profile_step_title_{$step->id}", "Required Profile Information" );
\IPS\Lang::saveCustom( 'core', "profile_step_text_{$step->id}", "Required Profile Information" );
}
$optional = array();
foreach( \IPS\Db::i()->select( '*', 'core_pfields_data', array( "pf_show_on_reg=? AND pf_not_null=?", 1, 0 ) ) AS $row )
{
$optional[] = "core_pfield_{$row['pf_id']}";
}
if ( count( $optional ) )
{
$step = new \IPS\Member\ProfileStep;
$step->required = 0;
$step->extension = 'core_ProfileFields';
$step->completion_act = "profile_fields";
$step->subcompletion_act = $optional;
$step->save();
\IPS\Lang::saveCustom( 'core', "profile_step_title_{$step->id}", "Optional Profile Information" );
\IPS\Lang::saveCustom( 'core', "profile_step_text_{$step->id}", "Optional Profile Information" );
}
return TRUE;
}
/**
* Custom title for this step
*
* @return string
*/
public function step14CustomTitle()
{
return 'Setting up Profile Completion';
}
/**
* Step 15
* Enable social promotion feature for admins
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step15()
{
foreach( \IPS\Db::i()->select( 'row_id', 'core_admin_permission_rows', array( 'row_id_type=?', 'group' ) ) as $admin )
{
\IPS\Db::i()->update( 'core_groups', "g_bitoptions2=g_bitoptions2|8", array( 'g_id=?', $admin ) );
}
return TRUE;
}
/**
* Custom title for this step
*
* @return string
*/
public function step15CustomTitle()
{
return 'Enabling social promotion for administrators';
}
/**
* Step 16
* Delete any orphaned moderator log entries
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step16()
{
/* Remove the offending entries */
\IPS\Db::i()->returnQuery = TRUE;
$query = array(
'table' => 'core_moderator_logs',
'query' => \IPS\Db::i()->delete( 'core_moderator_logs', array( 'appcomponent NOT IN ( ' . \IPS\Db::i()->select( 'app_directory', 'core_applications' ) . ' )' ) )
);
\IPS\Db::i()->returnQuery = FALSE;
$toRun = \IPS\core\Setup\Upgrade::runManualQueries( array( $query ) );
if ( count( $toRun ) )
{
\IPS\core\Setup\Upgrade::adjustMultipleRedirect( array( 1 => 'core', 'extra' => array( '_upgradeStep' => 17 ) ) );
/* Queries to run manually */
return array( 'html' => \IPS\Theme::i()->getTemplate( 'forms' )->queries( $toRun, \IPS\Http\Url::internal( 'controller=upgrade' )->setQueryString( array( 'key' => $_SESSION['uniqueKey'], 'mr_continue' => 1, 'mr' => \IPS\Request::i()->mr ) ) ) );
}
return true;
}
/**
* Custom title for this step
*
* @return string
*/
public function step16CustomTitle()
{
return 'Removing orphaned moderator logs';
}
/**
* Step 17
* Create a new default 4.2 theme
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step17()
{
$max = \IPS\Db::i()->select( 'MAX(set_order)', 'core_themes' )->first();
\IPS\Db::i()->update( 'core_themes', array( 'set_is_acp_default' => 0 ) );
/* Create a default theme */
$theme = new \IPS\Theme;
$theme->parent_array = '[]';
$theme->child_array = '[]';
$theme->parent_id = 0;
$theme->by_skin_gen = 0;
$theme->editor_skin = 'ips';
$theme->order = $max + 1;
$theme->is_default = FALSE;
$theme->is_acp_default = TRUE;
$theme->save();
$theme->installThemeSettings();
$theme->copyResourcesFromSet();
/* Name */
\IPS\Lang::saveCustom( 'core', "core_theme_set_title_{$theme->id}", "4.2" );
return TRUE;
}
/**
* Custom title for this step
*
* @return string
*/
public function step17CustomTitle()
{
return 'Creating 4.2 theme';
}
/**
* Step 18
* Add clubs menu entry
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step18()
{
\IPS\core\FrontNavigation::insertMenuItem( NULL, array( 'app' => 'core', 'key' => 'Clubs' ), \IPS\Db::i()->select( 'MAX(position)', 'core_menu' )->first() );
return TRUE;
}
/**
* Custom title for this step
*
* @return string
*/
public function step18CustomTitle()
{
return 'Adding clubs menu item';
}
/**
* Finish - This is run after all apps have been upgraded
*
* @return mixed If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
* @note We opted not to let users run this immediately during the upgrade because of potential issues (it taking a long time and users stopping it or getting frustrated) but we can revisit later
*/
public function finish()
{
\IPS\Content\Search\Index::i()->rebuild();
}
}