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\Software\Core;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* vBulletin Core Converter
|
||||
*/
|
||||
class _Vbulletin extends \IPS\convert\Software
|
||||
{
|
||||
/**
|
||||
@@ -38,8 +41,8 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \IPS\convert\App The application to reference for database and other information.
|
||||
* @param bool Establish a DB connection
|
||||
* @param \IPS\convert\App $app The application to reference for database and other information.
|
||||
* @param bool $needDB Establish a DB connection
|
||||
* @return void
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
@@ -65,10 +68,9 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
static::$isLegacy = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* If this is vB4, what is the content type ID for posts? */
|
||||
if ( static::$postContentType === NULL AND ( static::$isLegacy === FALSE OR is_null( static::$isLegacy ) ) )
|
||||
if ( static::$postContentType === NULL AND ( static::$isLegacy === FALSE OR \is_null( static::$isLegacy ) ) )
|
||||
{
|
||||
static::$postContentType = $this->db->select( 'contenttypeid', 'contenttype', array( "class=?", 'Post' ) )->first();
|
||||
}
|
||||
@@ -155,7 +157,7 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
),
|
||||
'convertPrivateMessageReplies' => array(
|
||||
'table' => 'pm',
|
||||
'where' => array( 'folderid!=?', -1 )
|
||||
'where' => array( 'NOT (folderid= -1 AND parentpmid > 0)' )
|
||||
),
|
||||
'convertRanks' => array(
|
||||
'table' => 'usertitle',
|
||||
@@ -177,7 +179,7 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
*
|
||||
* @param string $table The table containing the rows to count.
|
||||
* @param array|NULL $where WHERE clause to only count specific rows, or NULL to count all.
|
||||
* @param bool $recache Skip cache and pull directly (updating cache)
|
||||
* @param bool $recache Skip cache and pull directly (updating cache)
|
||||
* @return integer
|
||||
* @throws \IPS\convert\Exception
|
||||
*/
|
||||
@@ -186,18 +188,32 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
switch( $table )
|
||||
{
|
||||
case 'userchangelog':
|
||||
return $this->db->select( 'count(changeid)', 'userchangelog', array( $this->db->in( 'fieldname', array_keys( static::$changeLogTypes ) ) ) )->first();
|
||||
try
|
||||
{
|
||||
return $this->db->select( 'count(changeid)', 'userchangelog', array( $this->db->in( 'fieldname', array_keys( static::$changeLogTypes ) ) ) )->first();
|
||||
}
|
||||
catch( \Exception $e )
|
||||
{
|
||||
throw new \IPS\convert\Exception( sprintf( \IPS\Member::loggedIn()->language()->get( 'could_not_count_rows' ), $table ) );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'pm':
|
||||
/* vB doesn't put an index on a column that makes this converison much quicker, so we'll do it. */
|
||||
if( !$this->db->checkForIndex( 'pm', 'parent_id' ) )
|
||||
try
|
||||
{
|
||||
$this->db->addIndex( 'pm', array(
|
||||
'type' => 'key',
|
||||
'name' => 'parent_id',
|
||||
'columns' => array( 'parentpmid', 'folderid' )
|
||||
) );
|
||||
/* vB doesn't put an index on a column that makes this converison much quicker, so we'll do it. */
|
||||
if( !$this->db->checkForIndex( 'pm', 'parent_id' ) )
|
||||
{
|
||||
$this->db->addIndex( 'pm', array(
|
||||
'type' => 'key',
|
||||
'name' => 'parent_id',
|
||||
'columns' => array( 'parentpmid', 'folderid' )
|
||||
) );
|
||||
}
|
||||
}
|
||||
catch( \Exception $e )
|
||||
{
|
||||
throw new \IPS\convert\Exception( sprintf( \IPS\Member::loggedIn()->language()->get( 'could_not_count_rows' ), $table ) );
|
||||
}
|
||||
|
||||
return parent::countRows( $table, $where, $recache );
|
||||
@@ -445,14 +461,24 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
'field_required' => TRUE,
|
||||
'field_extra' => array(
|
||||
'options' => array(
|
||||
'database' => \IPS\Member::loggedIn()->language()->addToStack( 'database' ),
|
||||
'file_system' => \IPS\Member::loggedIn()->language()->addToStack( 'file_system' ),
|
||||
'database' => \IPS\Member::loggedIn()->language()->addToStack( 'conv_store_database' ),
|
||||
'file_system' => \IPS\Member::loggedIn()->language()->addToStack( 'conv_store_file_system' ),
|
||||
),
|
||||
'userSuppliedInput' => 'file_system',
|
||||
),
|
||||
'field_hint' => NULL,
|
||||
'field_validation' => function( $value ) { if ( $value != 'database' AND !@is_dir( $value ) ) { throw new \DomainException( 'path_invalid' ); } },
|
||||
);
|
||||
|
||||
/* Find out where the avatar gallery photos live */
|
||||
$return['convertMembers']['avatar_gallery_location'] = array(
|
||||
'field_class' => 'IPS\\Helpers\\Form\\Text',
|
||||
'field_default' => NULL,
|
||||
'field_required' => TRUE,
|
||||
'field_extra' => array(),
|
||||
'field_hint' => \IPS\Member::loggedIn()->language()->addToStack('convert_vb_avatar_gallery_path'),
|
||||
'field_validation' => function( $value ) { if ( !@is_dir( $value ) ) { throw new \DomainException( 'path_invalid' ); } },
|
||||
);
|
||||
|
||||
/* And decide what to do about these... */
|
||||
foreach( array( 'homepage', 'icq', 'aim', 'yahoo', 'msn', 'skype' ) AS $field )
|
||||
@@ -476,15 +502,17 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
break;
|
||||
|
||||
case 'convertClubs':
|
||||
\IPS\Member::loggedIn()->language()->words['club_photo_location'] = \IPS\Member::loggedIn()->language()->addToStack( 'photo_location' );
|
||||
|
||||
$return['convertClubs'] = array();
|
||||
$return['convertClubs']['photo_location'] = array(
|
||||
$return['convertClubs']['club_photo_location'] = array(
|
||||
'field_class' => 'IPS\\Helpers\\Form\\Radio',
|
||||
'field_default' => 'database',
|
||||
'field_required' => TRUE,
|
||||
'field_extra' => array(
|
||||
'options' => array(
|
||||
'database' => \IPS\Member::loggedIn()->language()->addToStack( 'database' ),
|
||||
'file_system' => \IPS\Member::loggedIn()->language()->addToStack( 'file_system' ),
|
||||
'database' => \IPS\Member::loggedIn()->language()->addToStack( 'conv_store_database' ),
|
||||
'file_system' => \IPS\Member::loggedIn()->language()->addToStack( 'conv_store_file_system' ),
|
||||
),
|
||||
'userSuppliedInput' => 'file_system',
|
||||
),
|
||||
@@ -521,6 +549,7 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
|
||||
/* Content Counts */
|
||||
\IPS\Task::queue( 'core', 'RecountMemberContent', array( 'app' => $this->app->app_id ), 4, array( 'app' ) );
|
||||
\IPS\Task::queue( 'core', 'RebuildItemCounts', array( 'class' => 'IPS\core\Messenger\Message' ), 3, array( 'class' ) );
|
||||
|
||||
/* Clubs */
|
||||
\IPS\Task::queue( 'convert', 'RecountClubMembers', array( 'app' => $this->app->app_id ), 2, array( 'app' ) );
|
||||
@@ -537,30 +566,39 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
/**
|
||||
* Fix post data
|
||||
*
|
||||
* @param string raw post data
|
||||
* @return string parsed post data
|
||||
* @param string $post Raw post data
|
||||
* @return string Parsed post data
|
||||
*/
|
||||
public static function fixPostData( $post )
|
||||
{
|
||||
$post = preg_replace( "#\[sigpic\](.+?)\[\/sigpic\]#i", "", $post );
|
||||
if( \preg_match( "#\[sigpic]#i", $post ) )
|
||||
{
|
||||
$post = preg_replace( "#\[sigpic\](.+?)\[\/sigpic\]#i", "", $post );
|
||||
}
|
||||
$post = str_replace( "<", "<", $post );
|
||||
$post = str_replace( ">", ">", $post );
|
||||
$post = str_replace( "'", "'", $post );
|
||||
|
||||
$post = preg_replace( "#\[quote=([^\];]+?)\]#i", "[quote name='$1']", $post );
|
||||
$post = preg_replace( "#\[quote=([^\];]+?);\d+\]#i", "[quote name='$1']", $post );
|
||||
$post = preg_replace( "#\[quote=([^\];]+?);n\d+\]#i", "[quote name='$1']", $post );
|
||||
if( \preg_match( "#\[quote=#i", $post ) )
|
||||
{
|
||||
$post = preg_replace( "#\[quote=([^\];]+?)\]#i", "[quote name='$1']", $post );
|
||||
$post = preg_replace( "#\[quote=([^\];]+?);\d+\]#i", "[quote name='$1']", $post );
|
||||
$post = preg_replace( "#\[quote=([^\];]+?);n\d+\]#i", "[quote name='$1']", $post );
|
||||
}
|
||||
|
||||
/* Remove video tags and allow our parser to handle the embeds it supports */
|
||||
$post = preg_replace( "#\[video=[a-z]+;[a-z0-9_]+\](.*?)\[\/video\]#i", '$1', $post );
|
||||
if( \preg_match( "#\[video=#i", $post ) )
|
||||
{
|
||||
$post = preg_replace( "#\[video=[a-z_]+;[a-z0-9_]+\](.*?)\[\/video\]#i", '$1', $post );
|
||||
}
|
||||
|
||||
/* This is not a core feature in vBulletin, but is a popular addon and the code was supplied below.
|
||||
Addon URL: https://www.dragonbyte-tech.com/store/product/20-advanced-user-tagging/ */
|
||||
if( mb_stristr( $post, '[mention=' ) )
|
||||
if( \preg_match( "#\[mention=#i", $post ) )
|
||||
{
|
||||
preg_match_all( '#\[MENTION=(\d+)\](.+?)\[\/MENTION\]#i', $post, $matches );
|
||||
|
||||
if ( count( $matches ) )
|
||||
if ( \count( $matches ) )
|
||||
{
|
||||
/* Make sure we actually have mention data */
|
||||
if ( isset( $matches[1] ) AND \count( $matches[1] ) )
|
||||
@@ -574,22 +612,17 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
}
|
||||
}
|
||||
|
||||
$maps = array();
|
||||
$urls = array();
|
||||
$cardUrls = array();
|
||||
foreach ( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'core_members', array(\IPS\Db::i()->in( 'name', array_keys( $mentions ) )) ), 'IPS\Member' ) AS $member )
|
||||
{
|
||||
$maps[ $member->name ] = $member->member_id;
|
||||
$urls[ $member->name ] = $member->url();
|
||||
$cardUrls[$member->name] = $member->url()->setQueryString( 'do', 'hovercard' );
|
||||
}
|
||||
$maps = iterator_to_array( \IPS\Db::i()->select( 'name, member_id', 'core_members', array( \IPS\Db::i()->in( 'name', array_keys( $mentions ) ) ) )->setKeyField( 'name' )->setValueField( 'member_id' ) );
|
||||
|
||||
foreach ( $mentions AS $member_name => $member_id )
|
||||
foreach ( $mentions AS $memberName => $memberId )
|
||||
{
|
||||
$maps[ $member_name ] = preg_quote( $maps[ $member_name ], '#' );
|
||||
$member_name = preg_quote( $member_name, '#' );
|
||||
if( !isset( $maps[ $memberName ] ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$post = preg_replace( "#\[MENTION={$member_id}\]{$member_name}\[\/MENTION\]#i", "<a contenteditable=\"false\" rel=\"\" href=\"{$urls[ $member_name ]}\" data-mentionid=\"{$maps[ $member_name ]}\" data-ipshover-target=\"{$cardUrls[ $member_name ]}\" data-ipshover=\"\">@{$member_name}</a>", $post );
|
||||
$memberNameQuoted = preg_quote( $memberName, '#' );
|
||||
$post = preg_replace( "#\[MENTION={$memberId}\]{$memberNameQuoted}\[\/MENTION\]#i", "[mention={$maps[ $memberName ]}]{$memberName}[/mention]", $post );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -711,10 +744,31 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
}
|
||||
|
||||
$merge = ( $this->app->_session['more_info']['convertProfileFields']["map_pfield_{$field['profilefieldid']}"] != 'none' ) ? $this->app->_session['more_info']['convertProfileFields']["map_pfield_{$field['profilefieldid']}"] : NULL;
|
||||
|
||||
if ( in_array( mb_strtolower( $field['type'] ), array( 'select', 'radio', 'checkbox', 'select_multiple' ) ) )
|
||||
|
||||
if ( \in_array( mb_strtolower( $field['type'] ), array( 'select', 'radio', 'checkbox', 'select_multiple' ) ) )
|
||||
{
|
||||
$content = json_encode( \unserialize( $field['data'] ) );
|
||||
$options = @\unserialize( $field['data'] );
|
||||
if ( $options )
|
||||
{
|
||||
$content = json_encode( $options );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We can try to restore the serialized value */
|
||||
$data = preg_replace_callback( '/s:(\d+):"(.*?)";/i', function( $match ) {
|
||||
return ( $match[1] == \strlen( $match[2] ) ) ? $match[0] : 's:' . \strlen( $match[2] ) . ':"' . $match[2] . '";';
|
||||
}, $field['data'] );
|
||||
|
||||
if( $options = @\unserialize( $data ) )
|
||||
{
|
||||
$content = json_encode( $options );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing else we can really do here */
|
||||
$content = json_encode( array() );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -735,14 +789,13 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
'pf_desc' => $desc,
|
||||
'pf_type' => $type,
|
||||
'pf_content' => $content,
|
||||
'pf_not_null' => ( in_array( $field['required'], array( 1, 3 ) ) ) ? 1 : 0,
|
||||
'pf_member_hide' => $field['hidden'],
|
||||
'pf_not_null' => ( \in_array( $field['required'], array( 1, 3 ) ) ) ? 1 : 0,
|
||||
'pf_member_hide' => $field['hidden'] ? 'hide' : 'all',
|
||||
'pf_max_input' => $field['maxlength'],
|
||||
'pf_member_edit' => ( $field['editable'] >= 1 ) ? 1 : 0,
|
||||
'pf_position' => $field['displayorder'],
|
||||
'pf_show_on_reg' => ( $field['required'] == 2 ) ? 1 : 0,
|
||||
'pf_input_format' => $field['regex'],
|
||||
'pf_admin_only' => ( $field['editable'] == 0 ) ? 1 : 0,
|
||||
'pf_group_id' => $field['profilefieldcategoryid'],
|
||||
'pf_multiple' => $multiple
|
||||
);
|
||||
@@ -756,7 +809,7 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
/**
|
||||
* Maps vBulletin Profile Field type to the IPS Equivalent
|
||||
*
|
||||
* @param string The vB Field Type
|
||||
* @param string $type The vB Field Type
|
||||
* @return string The IPS Field Type
|
||||
*/
|
||||
protected static function _pfieldMap( $type )
|
||||
@@ -819,7 +872,7 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
$promotion = $this->db->select( '*', 'userpromotion', array( "usergroupid=?", $group['usergroupid'] ) )->first();
|
||||
|
||||
/* We only support Posts or Join Date */
|
||||
if ( in_array( $promotion['strategy'], array( 17, 18 ) ) )
|
||||
if ( \in_array( $promotion['strategy'], array( 17, 18 ) ) )
|
||||
{
|
||||
switch( $promotion['strategy'] )
|
||||
{
|
||||
@@ -917,7 +970,7 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
}
|
||||
|
||||
/* Now check for group promotions */
|
||||
if( count( $libraryClass->groupPromotions ) )
|
||||
if( \count( $libraryClass->groupPromotions ) )
|
||||
{
|
||||
foreach( $libraryClass->groupPromotions as $groupPromotion )
|
||||
{
|
||||
@@ -929,7 +982,7 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
/**
|
||||
* @brief Member history type map
|
||||
*/
|
||||
protected static $changeLogTypes = array( 'username' => 'display_name', 'email' => 'email_change', 'usergroupid' => 'member_group_id', 'membergroupids' => 'mgroup_others' );
|
||||
protected static $changeLogTypes = array( 'username' => 'display_name', 'email' => 'email_change', 'usergroupid' => 'group', 'membergroupids' => 'group' );
|
||||
|
||||
/**
|
||||
* Convert member history
|
||||
@@ -943,16 +996,23 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
|
||||
foreach( $this->fetch( 'userchangelog', 'changeid', array( $this->db->in( 'fieldname', array_keys( static::$changeLogTypes ) ) ) ) AS $change )
|
||||
{
|
||||
$libraryClass->convertMemberHistory( array(
|
||||
'log_id' => $change['changeid'],
|
||||
'log_member' => $change['userid'],
|
||||
'log_by' => $change['adminid'],
|
||||
'log_type' => static::$changeLogTypes[ $change['fieldname'] ],
|
||||
'log_data' => array( 'old' => $change['oldvalue'], 'new' => $change['newvalue'] ),
|
||||
'log_date' => $change['change_time']
|
||||
)
|
||||
$info = array(
|
||||
'log_id' => $change['changeid'],
|
||||
'log_member' => $change['userid'],
|
||||
'log_by' => $change['adminid'],
|
||||
'log_type' => static::$changeLogTypes[ $change['fieldname'] ],
|
||||
'log_data' => array( 'old' => $change['oldvalue'], 'new' => $change['newvalue'] ),
|
||||
'log_date' => $change['change_time']
|
||||
);
|
||||
|
||||
/* Add extra data for group change */
|
||||
if( static::$changeLogTypes[ $change['fieldname'] ] == 'group' )
|
||||
{
|
||||
$info['log_data']['type'] = $change['fieldname'] == 'usergroupid' ? 'primary' : 'secondary';
|
||||
$info['log_data']['by'] = 'manual';
|
||||
}
|
||||
|
||||
$libraryClass->convertMemberHistory( $info );
|
||||
$libraryClass->setLastKeyValue( $change['changeid'] );
|
||||
}
|
||||
}
|
||||
@@ -968,6 +1028,9 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
|
||||
$libraryClass::setKey( 'user.userid' );
|
||||
|
||||
/* User titles */
|
||||
$userTitles = iterator_to_array( $this->db->select( 'title', 'usertitle' ) );
|
||||
|
||||
foreach( $this->fetch( 'user', 'user.userid', NULL, 'user.*, usertextfield.signature' )->join( 'usertextfield', 'user.userid = usertextfield.userid' ) AS $user )
|
||||
{
|
||||
/* <3 Closures */
|
||||
@@ -1054,13 +1117,13 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
'member_id' => $user['userid'],
|
||||
'member_group_id' => $user['usergroupid'],
|
||||
'mgroup_others' => $user['membergroupids'],
|
||||
'name' => $user['username'],
|
||||
'name' => html_entity_decode( $user['username'], \ENT_QUOTES | \ENT_HTML5, 'UTF-8' ),
|
||||
'email' => $user['email'],
|
||||
'member_title' => $user['usertitle'],
|
||||
'member_title' => \in_array( $user['usertitle'], $userTitles ) ? NULL : $user['usertitle'],
|
||||
'joined' => $user['joindate'],
|
||||
'ip_address' => $user['ipaddress'],
|
||||
'warn_level' => ( $user['ipoints'] > 2147483647 ) ? 2147483647 : $user['ipoints'],
|
||||
'warn_lastwarn' => $lastWarning['dateline'],
|
||||
'warn_lastwarn' => ( \is_array( $lastWarning ) ) ? $lastWarning['dateline'] : $lastWarning,
|
||||
'bday_day' => $bday_day,
|
||||
'bday_month' => $bday_month,
|
||||
'bday_year' => $bday_year,
|
||||
@@ -1074,10 +1137,10 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
'members_bitoptions' => array(
|
||||
'view_sigs' => $checkpermission( 'useroptions', 'showsignatures' ), // View signatures?
|
||||
'coppa_user' => $checkpermission( 'useroptions', 'coppauser' ), // Was the member validated using coppa?
|
||||
'timezone_override' => !$checkpermission( 'useroptions', 'dstauto' ), // If TRUE, user's timezone will not be detected automatically
|
||||
),
|
||||
'members_bitoptions2' => array(
|
||||
'show_pm_popup' => $user['pmpopup'], // "Show pop-up when I have a new message"
|
||||
'is_anon' => $checkpermission( 'useroptions', 'invisible' ), // Anonymous status
|
||||
),
|
||||
'pp_setting_count_comments' => $checkpermission( 'useroptions', 'vm_enable' ),
|
||||
'pp_reputation_points' => $user['reputation'],
|
||||
@@ -1086,6 +1149,18 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
'members_disable_pm' => !$checkpermission( 'useroptions', 'receivepm' ),
|
||||
'member_posts' => $user['posts'],
|
||||
);
|
||||
|
||||
/* If there is a validation record for this user, treat them as validating */
|
||||
try
|
||||
{
|
||||
$activation = $this->db->select( '*', 'useractivation', array( "userid=?", $user['userid'] ) )->first();
|
||||
|
||||
$info['members_bitoptions']['validating'] = TRUE;
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
$activation = NULL;
|
||||
}
|
||||
|
||||
/* Profile Fields */
|
||||
try
|
||||
@@ -1129,11 +1204,10 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
'pf_desc' => '',
|
||||
'pf_type' => 'Text',
|
||||
'pf_content' => '[]',
|
||||
'pf_member_hide' => 0,
|
||||
'pf_member_hide' => 'all',
|
||||
'pf_max_input' => 255,
|
||||
'pf_member_edit' => 1,
|
||||
'pf_show_on_reg' => 0,
|
||||
'pf_admin_only' => 0,
|
||||
) );
|
||||
}
|
||||
|
||||
@@ -1257,15 +1331,42 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
list( $filedata, $filename, $filepath ) = array( NULL, NULL, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
/* We'll try the avatar gallery */
|
||||
if( empty( $filename ) AND empty( $filedata ) AND (int) $user['avatarid'] )
|
||||
{
|
||||
$avatar = $this->_getFromAvatarGallery( (int) $user['avatarid'] );
|
||||
|
||||
if( \is_array( $avatar ) )
|
||||
{
|
||||
$filename = $avatar['name'];
|
||||
$filedata = $avatar['data'];
|
||||
}
|
||||
}
|
||||
|
||||
$libraryClass->convertMember( $info, $profileFields, $filename, $filepath, $filedata );
|
||||
$memberId = $libraryClass->convertMember( $info, $profileFields, $filename, $filepath, $filedata );
|
||||
|
||||
/* If we are validating, store our validation row entry */
|
||||
if( $activation !== NULL AND $memberId )
|
||||
{
|
||||
\IPS\Db::i()->replace( 'core_validating', array(
|
||||
'vid' => md5( $activation['activationid'] . $activation['useractivationid'] ),
|
||||
'member_id' => $memberId,
|
||||
'entry_date' => $activation['dateline'],
|
||||
'new_reg' => ( $activation['emailchange'] == 0 ? TRUE : FALSE ),
|
||||
'email_chg' => ( $activation['emailchange'] == 1 ? TRUE : FALSE ),
|
||||
'user_verified' => FALSE,
|
||||
'ip_address' => $user['ipaddress'],
|
||||
'email_sent' => $activation['dateline']
|
||||
) );
|
||||
}
|
||||
|
||||
/* Any friends need converting to followers? */
|
||||
foreach( $this->db->select( '*', 'userlist', array( "type=? AND friend=? AND userid=?", 'buddy', 'yes', $user['userid'] ) ) AS $follower )
|
||||
{
|
||||
$libraryClass->convertFollow( array(
|
||||
'follow_app' => 'core',
|
||||
'follow_area' => 'members',
|
||||
'follow_area' => 'member',
|
||||
'follow_rel_id' => $follower['relationid'],
|
||||
'follow_rel_id_type' => 'core_members',
|
||||
'follow_member_id' => $follower['userid'],
|
||||
@@ -1482,78 +1583,10 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
$libraryClass->setLastKeyValue( $pm['pmid'] );
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$replies = $this->db->select( 'COUNT(*)', 'pm', array( "parentpmid=? AND folderid!=?", $pm['pmid'], -1 ) )->first();
|
||||
$replies += 1;
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
$replies = 1;
|
||||
}
|
||||
|
||||
$topic = array(
|
||||
'mt_id' => $pm['pmid'],
|
||||
'mt_date' => $pm['dateline'],
|
||||
'mt_title' => $pm['title'],
|
||||
'mt_starter_id' => $pm['fromuserid'],
|
||||
'mt_start_time' => $pm['dateline'],
|
||||
'mt_last_post_time' => $pm['dateline'],
|
||||
'mt_to_count' => count( @\unserialize( $pm['touserarray'] ) ),
|
||||
'mt_to_member_id' => $pm['userid'],
|
||||
'mt_replies' => $replies,
|
||||
'mt_first_msg_id' => $pm['pmid'],
|
||||
);
|
||||
|
||||
$authors = array();
|
||||
$authors[ $pm['fromuserid'] ] = $pm['fromuserid'];
|
||||
|
||||
try
|
||||
{
|
||||
foreach( $this->db->select( '*', 'pm', array( "parentpmid=?", $pm['pmid'] ) )->join( 'pmtext', 'pm.pmtextid = pmtext.pmtextid' ) AS $post )
|
||||
{
|
||||
if ( $post['folderid'] != -1 )
|
||||
{
|
||||
$authors[ $post['fromuserid'] ] = $post['fromuserid'];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( \UnderflowException $e ) {}
|
||||
|
||||
/* Use stored author ids */
|
||||
$toUsers = \unserialize( $pm['touserarray'] );
|
||||
if( isset( $toUsers['cc'] ) )
|
||||
{
|
||||
foreach( array_keys( $toUsers['cc'] ) as $id )
|
||||
{
|
||||
$authors[ $id ] = $id;
|
||||
}
|
||||
}
|
||||
elseif( \count( $toUsers ) AND isset( $toUsers['cc'] ) AND isset( $toUsers['bcc'] ) )
|
||||
{
|
||||
foreach( array_keys( $toUsers ) as $id )
|
||||
{
|
||||
$authors[ $id ] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
$maps = array();
|
||||
|
||||
foreach( $authors AS $mapAuthor )
|
||||
{
|
||||
$maps[ $mapAuthor ] = array(
|
||||
'map_user_id' => $mapAuthor,
|
||||
'map_topic_id' => $pm['pmid'],
|
||||
'map_user_active' => 1,
|
||||
'map_user_banned' => 0,
|
||||
'map_has_unread' => 0,
|
||||
'map_is_starter' => ( $mapAuthor == $pm['fromuserid'] ) ? 1 : 0,
|
||||
);
|
||||
}
|
||||
|
||||
$libraryClass->convertPrivateMessage( $topic, $maps );
|
||||
|
||||
/* Convert PM */
|
||||
$this->_convertPm( $libraryClass, $pm );
|
||||
|
||||
$libraryClass->setLastKeyValue( $pm['pmid'] );
|
||||
}
|
||||
}
|
||||
@@ -1569,11 +1602,22 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
|
||||
$libraryClass::setKey( 'pm.pmid' );
|
||||
|
||||
foreach( $this->fetch( 'pm', 'pm.pmid', array( 'pm.folderid!=?', -1 ), "pm.*, pmtext.*" )->join( 'pmtext', 'pm.pmtextid = pmtext.pmtextid' ) AS $pm )
|
||||
foreach( $this->fetch( 'pm', 'pm.pmid', array( 'NOT (pm.folderid= -1 AND pm.parentpmid > 0)' ), "pm.*, pmtext.*, test.pmid as parent_test" )
|
||||
->join( 'pmtext', 'pm.pmtextid = pmtext.pmtextid' )
|
||||
->join( array( 'pm', 'test' ), 'pm.parentpmid=test.pmid' )
|
||||
AS $pm )
|
||||
{
|
||||
/* See if the parent exists, or whether it's already been deleted in vBulletin. */
|
||||
$parentId = FALSE;
|
||||
if( $pm['parentpmid'] AND !$pm['parent_test'] )
|
||||
{
|
||||
/* It has previously been deleted, so this message can become it's own conversation */
|
||||
$parentId = $this->_convertPm( $libraryClass, $pm );
|
||||
}
|
||||
|
||||
$libraryClass->convertPrivateMessageReply( array(
|
||||
'msg_id' => $pm['pmid'],
|
||||
'msg_topic_id' => !$pm['parentpmid'] ? $pm['pmid'] : $pm['parentpmid'],
|
||||
'msg_topic_id' => (!$pm['parentpmid'] OR $parentId ) ? $pm['pmid'] : $pm['parentpmid'],
|
||||
'msg_date' => $pm['dateline'],
|
||||
'msg_post' => $pm['message'],
|
||||
'msg_author_id' => $pm['fromuserid'],
|
||||
@@ -1658,13 +1702,13 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
$icondata = NULL;
|
||||
if ( $icon )
|
||||
{
|
||||
if ( $this->app->_session['more_info']['convertClubs']['photo_location'] == 'database' )
|
||||
if ( $this->app->_session['more_info']['convertClubs']['club_photo_location'] == 'database' )
|
||||
{
|
||||
$icondata = $icon['filedata'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$iconpath = $this->app->_session['more_info']['convertClubs']['photo_location'] . "/socialgroupicon_{$icon['groupid']}_{$icon['dateline']}.gif";
|
||||
$iconpath = $this->app->_session['more_info']['convertClubs']['club_photo_location'] . "/socialgroupicon_{$icon['groupid']}_{$icon['dateline']}.gif";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1907,7 +1951,7 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
/**
|
||||
* Get Setting Value - useful for global settings that need to be translated to group or member settings
|
||||
*
|
||||
* @param $key The setting key
|
||||
* @param string $key The setting key
|
||||
* @return mixed
|
||||
*/
|
||||
protected function _setting( $key )
|
||||
@@ -1951,22 +1995,49 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
/* Attachment URLs are the same across VB 3.8 and VB 4 */
|
||||
if( mb_strpos( $url->data[ \IPS\Http\Url::COMPONENT_PATH ], 'attachment.php' ) !== FALSE )
|
||||
{
|
||||
$id = NULL;
|
||||
try
|
||||
{
|
||||
$data = (string) $this->app->getLink( \IPS\Request::i()->attachmentid, array( 'attachments', 'core_attachments' ) );
|
||||
|
||||
return \IPS\Http\Url::external( \IPS\Settings::i()->base_url . 'applications/core/interface/file/attachment.php' )->setQueryString( 'id', $data );
|
||||
$id = (string) $this->app->getLink( \IPS\Request::i()->attachmentid, array( 'attachments', 'core_attachments' ) );
|
||||
}
|
||||
/* Try any child conversions */
|
||||
catch( \Exception $e )
|
||||
{
|
||||
foreach( $this->app->children() as $child )
|
||||
{
|
||||
try
|
||||
{
|
||||
$id = (string) $child->getLink( \IPS\Request::i()->attachmentid, array( 'attachments', 'core_attachments' ) );
|
||||
break;
|
||||
}
|
||||
catch( \Exception $e ) {}
|
||||
}
|
||||
}
|
||||
|
||||
if( !$id )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return \IPS\Http\Url::external( \IPS\Settings::i()->base_url . 'applications/core/interface/file/attachment.php' )->setQueryString( 'id', $id );
|
||||
}
|
||||
/* Tag URLs are straightforward */
|
||||
elseif( mb_strpos( $url->data[ \IPS\Http\Url::COMPONENT_PATH ], 'tags.php' ) !== FALSE AND isset( \IPS\Request::i()->tag ) )
|
||||
{
|
||||
return \IPS\Http\Url::internal( "app=core&module=search&controller=search&tags=" . \IPS\Request::i()->tag, 'front', 'search' );
|
||||
}
|
||||
/* Club Index */
|
||||
elseif( mb_strpos( $url->data[ \IPS\Http\Url::COMPONENT_PATH ], 'group.php' ) !== FALSE AND isset( \IPS\Request::i()->groupid ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
return \IPS\Member\Club::loadAndCheckPerms( (string) $this->app->getLink( \IPS\Request::i()->groupid, array( 'core_clubs' ) ) )->url();
|
||||
}
|
||||
catch( \Exception $e )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If we can't access profiles, don't bother trying to redirect */
|
||||
@@ -2038,4 +2109,149 @@ class _Vbulletin extends \IPS\convert\Software
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Centralised PM conversation conversion
|
||||
*
|
||||
* @param $libraryClass \IPS\convert\Library
|
||||
* @param $pm array
|
||||
* @return mixed
|
||||
*/
|
||||
protected function _convertPm( \IPS\convert\Library $libraryClass, array $pm )
|
||||
{
|
||||
try
|
||||
{
|
||||
$replies = $this->db->select( 'COUNT(*)', 'pm', array( "parentpmid=? AND folderid!=?", $pm['pmid'], -1 ) )->first();
|
||||
$replies += 1;
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
$replies = 1;
|
||||
}
|
||||
|
||||
$toUserArray = @\unserialize( $pm['touserarray'] );
|
||||
|
||||
$topic = array(
|
||||
'mt_id' => $pm['pmid'],
|
||||
'mt_date' => $pm['dateline'],
|
||||
'mt_title' => $pm['title'],
|
||||
'mt_starter_id' => $pm['fromuserid'],
|
||||
'mt_start_time' => $pm['dateline'],
|
||||
'mt_last_post_time' => $pm['dateline'],
|
||||
'mt_to_count' => ( $toUserArray AND \is_array( $toUserArray ) ) ? \count( $toUserArray ) : 1,
|
||||
'mt_to_member_id' => $pm['userid'],
|
||||
'mt_replies' => $replies,
|
||||
'mt_first_msg_id' => $pm['pmid'],
|
||||
);
|
||||
|
||||
$authors = array();
|
||||
$authors[ $pm['fromuserid'] ] = $pm['fromuserid'];
|
||||
|
||||
try
|
||||
{
|
||||
foreach( $this->db->select( '*', 'pm', array( "parentpmid=?", $pm['pmid'] ) )->join( 'pmtext', 'pm.pmtextid = pmtext.pmtextid' ) AS $post )
|
||||
{
|
||||
if ( $post['folderid'] != -1 )
|
||||
{
|
||||
$authors[ $post['fromuserid'] ] = $post['fromuserid'];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( \UnderflowException $e ) {}
|
||||
|
||||
/* Use stored author ids */
|
||||
if( isset( $toUserArray['cc'] ) AND \is_array( $toUserArray['cc'] ) )
|
||||
{
|
||||
foreach( array_keys( $toUserArray['cc'] ) as $id )
|
||||
{
|
||||
$authors[ $id ] = $id;
|
||||
}
|
||||
}
|
||||
elseif( $toUserArray AND \is_array( $toUserArray ) AND \count( $toUserArray ) )
|
||||
{
|
||||
foreach( array_keys( $toUserArray ) as $id )
|
||||
{
|
||||
$authors[ $id ] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
$maps = array();
|
||||
|
||||
foreach( $authors AS $mapAuthor )
|
||||
{
|
||||
$maps[ $mapAuthor ] = array(
|
||||
'map_user_id' => $mapAuthor,
|
||||
'map_topic_id' => $pm['pmid'],
|
||||
'map_user_active' => 1,
|
||||
'map_user_banned' => 0,
|
||||
'map_has_unread' => 0,
|
||||
'map_is_starter' => ( $mapAuthor == $pm['fromuserid'] ) ? 1 : 0,
|
||||
);
|
||||
}
|
||||
|
||||
return $libraryClass->convertPrivateMessage( $topic, $maps );
|
||||
}
|
||||
|
||||
protected $_avatars = array();
|
||||
|
||||
/**
|
||||
* Fetch Avatar from Avatar Gallery
|
||||
*
|
||||
* @param int $id Avatar ID
|
||||
* @return array|bool Array of data/name or FALSE
|
||||
*/
|
||||
protected function _getFromAvatarGallery( int $id )
|
||||
{
|
||||
if( isset( $this->_avatars[ $id ] ) )
|
||||
{
|
||||
return $this->_avatars[ $id ];
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$avatar = $this->db->select( 'avatarpath', 'avatar', array( 'avatarid=?', $id ) )->first();
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
return $this->_avatars[ $id ] = FALSE;
|
||||
}
|
||||
|
||||
/* It might be a remote image */
|
||||
if( \substr( $avatar, 0, 8 ) === 'https://' OR \substr( $avatar, 0, 7 ) === 'http://' )
|
||||
{
|
||||
try
|
||||
{
|
||||
$profilePhotoName = pathinfo( parse_url( $avatar, PHP_URL_PATH ), PATHINFO_BASENAME );
|
||||
$profilePhotoData = \IPS\Http\Url::external( $avatar )->request()->get();
|
||||
|
||||
/* Check it's really an image */
|
||||
try
|
||||
{
|
||||
\IPS\Image::create( $profilePhotoData );
|
||||
}
|
||||
catch( \InvalidArgumentException $e )
|
||||
{
|
||||
return $this->_avatars[ $id ] = FALSE;
|
||||
}
|
||||
|
||||
return $this->_avatars[ $id ] = array( 'data' => $profilePhotoData, 'name' => $profilePhotoName );
|
||||
}
|
||||
catch ( \IPS\Http\Request\Exception $e )
|
||||
{
|
||||
return $this->_avatars[ $id ] = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* nope, it's a file */
|
||||
$dirName = pathinfo( $avatar, PATHINFO_DIRNAME );
|
||||
if( \substr( $this->app->_session['more_info']['convertMembers']['avatar_gallery_location'], -\strlen( $dirName ) ) == $dirName )
|
||||
{
|
||||
$profilePhotoName = pathinfo( $avatar, PATHINFO_BASENAME );
|
||||
$profilePhotoData = file_get_contents( rtrim( $this->app->_session['more_info']['convertMembers']['avatar_gallery_location'], '/' ) . '/' . $profilePhotoName );
|
||||
|
||||
return $this->_avatars[ $id ] = array( 'data' => $profilePhotoData, 'name' => $profilePhotoName );
|
||||
}
|
||||
|
||||
return $this->_avatars[ $id ] = FALSE;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user