Файл: IPBMafia.ru_IPB_3.4.6_Final_Rus _Nulled/board/upload/admin/sources/base/ipsMember.php
Строк: 2971
<?php
/**
* <pre>
* Invision Power Services
* IP.Board v3.4.6
* Static Member Class for IP.Board 3
*
* Last Updated: $Date: 2013-10-16 19:11:24 -0400 (Wed, 16 Oct 2013) $
* </pre>
*
* @author $Author: rashbrook $
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
* @license http://www.invisionpower.com/company/standards.php#license
* @package IP.Board
* @link http://www.invisionpower.com
* @since 12th March 2002
* @version $Revision: 12381 $
*
* @author Matt
*/
/**
* Some constants
*/
define( 'IPS_MEMBER_PHOTO_NO_CACHE', true );
/**
* IPSMember
*
* This deals with member data and some member functions
*/
class IPSMember
{
/**
* Custom fields class
*
* @var object
*/
static protected $custom_fields_class;
/**
* Member cache
*
* @var array
*/
static protected $memberCache = array();
/**
* Ignore cache
*
* @var boolean
*/
static protected $ignoreCache = FALSE;
/**
* Debug data
*
* @var array
*/
static public $debugData = array();
/**
* memberFunctions object reference
*
* @var object
*/
static protected $_memberFunctions;
/**
* Parsed signatures to save resources
*
* @var array
*/
static protected $_parsedSignatures = array();
/**
* Parsed custom fields to save resources
*
* @var array
*/
static protected $_parsedCustomFields = array();
/**
* Parsed custom fields to save resources
*
* @var array
*/
static protected $_parsedCustomGroups = array();
/**
* Ban filters cache
*
* @var array
*/
static public $_banFiltersCache = NULL;
/**
* Signature parser object
* @var unknown_type
*/
static protected $_sigParser = null;
/**
* Member data array
*
* @var array
*/
static public $data = array( 'member_id' => 0,
'name' => "",
'members_display_name' => "",
'member_group_id' => 0,
'member_forum_markers' => array() );
/**
* Remapped table array used in load and save
*
* @var array
*/
static protected $remap = array( 'core' => 'members',
'extendedProfile' => 'profile_portal',
'customFields' => 'pfields_content',
'itemMarkingStorage' => 'core_item_markers_storage' );
/**
* Create profile link
*
* @param string User's display name
* @param integer User's DB ID
* @param string SEO display name
* @param string Classname
* @param string Title
* @param int Active/inactive (member_banned, bw_is_spammer)
* @return string Link title
* @since 2.0
*/
static public function makeProfileLink( $name, $id=0, $_seoName="", $className='', $title='', $inactive=0 )
{
/* Cache so we don't have to rebuild on each call */
static $cache = array();
/* Did we just send in an array of data? */
if ( is_array( $name ) && ! empty( $name['member_id'] ) )
{
$_name = $name;
$name = $_name['members_display_name'];
$id = $_name['member_id'];
$_seoName = $_name['members_seo_name'];
$className = $_name['_className'];
$title = $_name['_title'];
$inactive = $inactive ? $inactive : self::isInactive($_name);
}
$_key = md5($id.$name.$_seoName.$className.$title.$inactive);
if ( isset($cache[ $_key ]) )
{
return $cache[ $_key ];
}
if ( $id > 0 && ipsRegistry::member()->getProperty('g_mem_info') )
{
$_seoName = ( $_seoName ) ? $_seoName : IPSText::makeSeoTitle( $name );
$cache[ $_key ] = ipsRegistry::getClass('output')->getTemplate('global')->userHoverCard( array( 'member_id' => $id, 'members_display_name' => $name, 'members_seo_name' => $_seoName, '_hoverClass' => $className, '_hoverTitle' => $title, 'inactive' => $inactive ) );
}
else
{
if( $className )
{
$cache[ $_key ] = "<span class='{$className}'>" . $name . "</span>";
}
else
{
$cache[ $_key ] = $name;
}
}
return $cache[ $_key ];
}
/**
* Unpack group bitwise options
*
* @param array
* @param bool Do not warn on overwrite
* @return array
*/
static public function unpackGroup( $group, $silence=false, $forceReload=false )
{
/* Cache to prevent having to thaw each call, which could be hundreds on a given page */
static $cache = array();
if( !$forceReload and $cache[ $group['g_id'] ] )
{
return array_merge( $group, $cache[ $group['g_id'] ] );
}
/* Unpack photo limits */
list( $p_max, $p_width, $p_height ) = explode( ":", $group['g_photo_max_vars'] );
$cache[ $group['g_id'] ]['photoMaxKb'] = intval( $p_max );
$cache[ $group['g_id'] ]['photoMaxWidth'] = intval( $p_width );
$cache[ $group['g_id'] ]['photoMaxHeight'] = intval( $p_height );
/* Unpack bitwise fields */
$_tmp = IPSBWOptions::thaw( $group['g_bitoptions'], 'groups', 'global' );
if ( count( $_tmp ) )
{
foreach( $_tmp as $k => $v )
{
/* Trigger notice if we have DB field */
if ( $silence === false AND isset( $group[ $k ] ) )
{
trigger_error( "Thawing bitwise options for GROUPS: Bitwise field '$k' has overwritten DB field '$k'", E_USER_WARNING );
}
$cache[ $group['g_id'] ][ $k ] = $v;
}
}
return array_merge( $group, $cache[ $group['g_id'] ] );
}
/**
* Create a random 15 character password
*
* @return string Password
* @since 2.0
*/
public static function makePassword()
{
$pass = "";
// Want it random you say, eh?
// (enter evil laugh)
$unique_id = uniqid( mt_rand(), TRUE );
$prefix = IPSMember::generatePasswordSalt();
$unique_id .= md5( $prefix );
usleep( mt_rand(15000,1000000) );
// Hmm, wonder how long we slept for
$new_uniqueid = uniqid( mt_rand(), TRUE );
$final_rand = md5( $unique_id . $new_uniqueid );
for ($i = 0; $i < 15; $i++)
{
$pass .= $final_rand{ mt_rand(0, 31) };
}
return $pass;
}
/**
* Checks to see if the logged in user can recieve mobile notifications
*
* @param array $memberData Optional, logged in user will be used if this is not passed in
* @return BOOL
*/
static public function canReceiveMobileNotifications( $memberData=array() )
{
/* Mobile notifications are currently deprecated http://community.invisionpower.com/resources/bugs.html/_/ip-board/remove-push-notification-references-r40643 */
return false;
/* INIT */
$memberData = ( is_array( $memberData ) && count( $memberData ) ) ? $memberData : ipsRegistry::member()->fetchMemberData();
/* Check to see if notifications are enabled */
if( ! ipsRegistry::$settings['iphone_notifications_enabled'] )
{
return false;
}
/* Check to see if the user has permission to get notifications */
if( ipsRegistry::$settings['iphone_notifications_groups'] )
{
if( IPSMember::isInGroup( $memberData, explode( ',', ipsRegistry::$settings['iphone_notifications_groups'] ) ) )
{
return true;
}
else
{
return false;
}
}
return true;
}
/**
* Format name based on group suffix/prefix
*
* @param string User's display name
* @param integer User's group ID
* @param string Optional prefix override (uses group setting if not provided)
* @param string Optional suffix override (uses group setting if not provided)
* @return string Formatted name
* @since 2.2
*/
public static function makeNameFormatted($name='', $group_id="", $prefix="", $suffix="")
{
if ( ipsRegistry::$settings['ipb_disable_group_psformat'] )
{
return $name;
}
if ( ! $group_id )
{
$group_id = 0;
}
$groupCache = ipsRegistry::cache()->getCache('group_cache');
if ( ! $prefix )
{
if( $groupCache[ $group_id ]['prefix'] )
{
$prefix = $groupCache[ $group_id ]['prefix'];
}
}
if( ! $suffix )
{
if( $groupCache[ $group_id ]['suffix'] )
{
$suffix = $groupCache[ $group_id ]['suffix'];
}
}
if ( ! $name )
{
if( $groupCache[ $group_id ]['g_title'] )
{
$name = $groupCache[ $group_id ]['g_title'];
}
}
return $prefix.$name.$suffix;
}
/**
* Create new member
* Very basic functionality at this point.
*
* @param array Fields to save in the following format: array( 'members' => array( 'email' => 'test@test.com',
* 'joined' => time() ),
* 'extendedProfile' => array( 'signature' => 'My signature' ) );
* Tables: members, pfields_content, profile_portal.
* You can also use the aliases: 'core [members]', 'extendedProfile [profile_portal]', and 'customFields [pfields_content]'
* @param bool Flag to attempt to auto create a name if the desired is taken
* @param bool Bypass custom field saving (if using the sso session integration this is required as member object isn't ready yet)
* @param bool Whether or not to recache the stats so as to update the board's last member data
* @return array Final member Data including member_id
*
* EXCEPTION CODES
* CUSTOM_FIELDS_EMPTY - Custom fields were not populated
* CUSTOM_FIELDS_INVALID - Custom fields were invalid
* CUSTOM_FIELDS_TOOBIG - Custom fields too big
*/
static public function create( $tables=array(), $autoCreateName=FALSE, $bypassCfields=FALSE, $doStatsRecache=TRUE )
{
//-----------------------------------------
// INIT
//-----------------------------------------
$finalTables = array();
$password = '';
$plainPassword = '';
$bitWiseFields = ipsRegistry::fetchBitWiseOptions( 'global' );
$md_5_password = '';
//-----------------------------------------
// Remap tables if required
//-----------------------------------------
foreach( $tables as $table => $data )
{
$_name = ( isset( self::$remap[ $table ] ) ) ? self::$remap[ $table ] : $table;
if ( $_name == 'members' )
{
/* Magic password field */
if ( ! empty( $data['md5_hash_password'] ) )
{
$md_5_password = trim( $data['md5_hash_password'] );
$plainPassword = null;
unset( $data['md5_hash_password'] );
}
else
{
$password = ( isset( $data['password'] ) ) ? trim( $data['password'] ) : self::makePassword();
$plainPassword = $password;
$md_5_password = md5( $password );
unset( $data['password'] );
}
}
$finalTables[ $_name ] = $data;
}
//-----------------------------------------
// Custom profile field stuff
//-----------------------------------------
if( !$bypassCfields )
{
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/customfields/profileFields.php', 'customProfileFields' );
$fields = new $classToLoad();
if ( is_array( $finalTables['pfields_content'] ) AND count( $finalTables['pfields_content'] ) )
{
$fields->member_data = $finalTables['pfields_content'];
}
$fields->initData( 'edit' );
$fields->parseToSave( $finalTables['pfields_content'], 'register' );
/* Check */
/*if( count( $fields->error_fields['empty'] ) )
{
throw new Exception( 'CUSTOM_FIELDS_EMPTY' );
}
if( count( $fields->error_fields['invalid'] ) )
{
throw new Exception( 'CUSTOM_FIELDS_INVALID' );
}
if( count( $fields->error_fields['toobig'] ) )
{
throw new Exception( 'CUSTOM_FIELDS_TOOBIG' );
}*/
}
//-----------------------------------------
// Make sure the account doesn't exist
//-----------------------------------------
if( $finalTables['members']['email'] )
{
if ( IPSText::mbstrlen( $finalTables['members']['email'] ) > 150 OR strstr( $finalTables['members']['email'], ' ' ) )
{
/* Allow it to be auto created */
$finalTables['members']['email'] = false;
}
else
{
$existing = IPSMember::load( $finalTables['members']['email'], 'all' );
if( $existing['member_id'] )
{
$existing['full'] = true;
$existing['timenow'] = time();
return $existing;
}
}
}
//-----------------------------------------
// Fix up usernames and display names
//-----------------------------------------
/* Ensure we have a display name */
if( $autoCreateName AND $finalTables['members']['members_display_name'] !== FALSE )
{
$finalTables['members']['members_display_name'] = ( $finalTables['members']['members_display_name'] ) ? $finalTables['members']['members_display_name'] : $finalTables['members']['name'];
}
//-----------------------------------------
// Remove some basic HTML tags
//-----------------------------------------
if( $finalTables['members']['members_display_name'] )
{
if ( IPSText::mbstrlen( $finalTables['members']['members_display_name'] ) > 255 )
{
$finalTables['members']['members_display_name'] = false;
}
$finalTables['members']['members_display_name'] = str_replace( array( '<', '>', '"' ), '', $finalTables['members']['members_display_name'] );
}
if( $finalTables['members']['name'] )
{
if ( IPSText::mbstrlen( $finalTables['members']['name'] ) > 255 )
{
$finalTables['members']['name'] = false;
}
$finalTables['members']['name'] = str_replace( array( '<', '>', '"' ), '', $finalTables['members']['name'] );
}
//-----------------------------------------
// Make sure the names are unique
//-----------------------------------------
/* Can specify display name of FALSE to force no entry to force partial member */
if( $finalTables['members']['members_display_name'] !== FALSE )
{
try
{
if( IPSMember::getFunction()->checkNameExists( $finalTables['members']['members_display_name'], array(), 'members_display_name', true ) === true )
{
if ( $autoCreateName === TRUE )
{
/* Now, make sure we have a unique display name */
$max = ipsRegistry::DB()->buildAndFetch( array( 'select' => 'MAX(member_id) as max',
'from' => 'members',
'where' => "members_l_display_name LIKE '" . ipsRegistry::DB()->addSlashes( IPSText::mbstrtolower( $finalTables['members']['members_display_name'] ) ) . "%'" ) );
if ( $max['max'] )
{
$_num = $max['max'] + 1;
$finalTables['members']['members_display_name'] = $finalTables['members']['members_display_name'] . '_' . $_num;
}
}
else
{
$finalTables['members']['members_display_name'] = '';
}
}
}
catch( Exception $e )
{}
}
if( $finalTables['members']['name'] )
{
try
{
if( IPSMember::getFunction()->checkNameExists( $finalTables['members']['name'], array(), 'name', true ) === true )
{
if ( $autoCreateName === TRUE )
{
/* Now, make sure we have a unique username */
$max = ipsRegistry::DB()->buildAndFetch( array( 'select' => 'MAX(member_id) as max',
'from' => 'members',
'where' => "members_l_username LIKE '" . ipsRegistry::DB()->addSlashes( IPSText::mbstrtolower( $finalTables['members']['name'] ) ) . "%'" ) );
if ( $max['max'] )
{
$_num = $max['max'] + 1;
$finalTables['members']['name'] = $finalTables['members']['name'] . '_' . $_num;
}
}
else
{
$finalTables['members']['name'] = '';
}
}
}
catch( Exception $e )
{}
}
//-----------------------------------------
// Clean up characters
//-----------------------------------------
if( $finalTables['members']['name'] )
{
$userName = IPSMember::getFunction()->cleanAndCheckName( $finalTables['members']['name'], array(), 'name' );
if( $userName['errors'] )
{
$finalTables['members']['name'] = $finalTables['members']['email'];
}
else
{
$finalTables['members']['name'] = $userName['username'];
}
}
if( $finalTables['members']['members_display_name'] )
{
$displayName = IPSMember::getFunction()->cleanAndCheckName( $finalTables['members']['members_display_name'] );
if( $displayName['errors'] )
{
$finalTables['members']['members_display_name'] = '';
}
else
{
$finalTables['members']['members_display_name'] = $displayName['members_display_name'];
}
}
//-----------------------------------------
// Populate member table(s)
//-----------------------------------------
$finalTables['members']['members_l_username'] = isset($finalTables['members']['name']) ? IPSText::mbstrtolower($finalTables['members']['name']) : '';
$finalTables['members']['joined'] = $finalTables['members']['joined'] ? $finalTables['members']['joined'] : time();
$finalTables['members']['email'] = $finalTables['members']['email'] ? $finalTables['members']['email'] : $finalTables['members']['name'] . '@' . $finalTables['members']['joined'];
$finalTables['members']['member_group_id'] = $finalTables['members']['member_group_id'] ? $finalTables['members']['member_group_id'] : ipsRegistry::$settings['member_group'];
$finalTables['members']['ip_address'] = $finalTables['members']['ip_address'] ? $finalTables['members']['ip_address'] : ipsRegistry::member()->ip_address;
$finalTables['members']['members_created_remote'] = intval( $finalTables['members']['members_created_remote'] );
$finalTables['members']['member_login_key'] = IPSMember::generateAutoLoginKey();
$finalTables['members']['member_login_key_expire'] = ( ipsRegistry::$settings['login_key_expire'] ) ? ( time() + ( intval( ipsRegistry::$settings['login_key_expire'] ) * 86400 ) ) : 0;
$finalTables['members']['view_sigs'] = 1;
$finalTables['members']['bday_day'] = intval( $finalTables['members']['bday_day'] );
$finalTables['members']['bday_month'] = intval( $finalTables['members']['bday_month'] );
$finalTables['members']['bday_year'] = intval( $finalTables['members']['bday_year'] );
$finalTables['members']['restrict_post'] = intval( $finalTables['members']['restrict_post'] );
$finalTables['members']['auto_track'] = $finalTables['members']['auto_track'] ? $finalTables['members']['auto_track'] : ipsRegistry::$settings['auto_track_method'];
$finalTables['members']['msg_count_total'] = 0;
$finalTables['members']['msg_count_new'] = 0;
$finalTables['members']['msg_show_notification'] = 1;
$finalTables['members']['coppa_user'] = 0;
$finalTables['members']['auto_track'] = substr( $finalTables['members']['auto_track'], 0, 50 );
$finalTables['members']['last_visit'] = $finalTables['members']['last_visit'] ? $finalTables['members']['last_visit'] : time();
$finalTables['members']['last_activity'] = $finalTables['members']['last_activity'] ? $finalTables['members']['last_activity'] : time();
$finalTables['members']['language'] = $finalTables['members']['language'] ? $finalTables['members']['language'] : IPSLib::getDefaultLanguage();
$finalTables['members']['member_uploader'] = ipsRegistry::$settings['uploadFormType'] ? 'flash' : 'default';
$finalTables['members']['members_pass_salt'] = IPSMember::generatePasswordSalt(5);
$finalTables['members']['members_pass_hash'] = IPSMember::generateCompiledPasshash( $finalTables['members']['members_pass_salt'], $md_5_password );
$finalTables['members']['members_display_name'] = isset($finalTables['members']['members_display_name']) ? $finalTables['members']['members_display_name'] : '';
$finalTables['members']['members_l_display_name'] = isset($finalTables['members']['members_display_name']) ? IPSText::mbstrtolower($finalTables['members']['members_display_name']) : '';
$finalTables['members']['fb_uid'] = isset($finalTables['members']['fb_uid']) ? $finalTables['members']['fb_uid'] : 0;
$finalTables['members']['vk_uid'] = isset($finalTables['members']['vk_uid']) ? $finalTables['members']['vk_uid'] : 0;
$finalTables['members']['fb_emailhash'] = isset($finalTables['members']['fb_emailhash']) ? strtolower($finalTables['members']['fb_emailhash']) : '';
$finalTables['members']['members_seo_name'] = IPSText::makeSeoTitle( $finalTables['members']['members_display_name'] );
$finalTables['members']['bw_is_spammer'] = intval( $finalTables['members']['bw_is_spammer'] );
//-----------------------------------------
// Insert: MEMBERS
//-----------------------------------------
ipsRegistry::DB()->setDataType( array( 'name', 'members_l_username', 'members_display_name', 'members_l_display_name', 'members_seo_name', 'email' ), 'string' );
/* Bitwise options */
if ( is_array( $bitWiseFields['members'] ) )
{
$_freeze = array();
foreach( $bitWiseFields['members'] as $field )
{
if ( isset( $finalTables['members'][ $field ] ) )
{
/* Add to freezeable array */
$_freeze[ $field ] = $finalTables['members'][ $field ];
/* Remove it from the fields to save to DB */
unset( $finalTables['members'][ $field ] );
}
}
if ( count( $_freeze ) )
{
$finalTables['members']['members_bitoptions'] = IPSBWOptions::freeze( $_freeze, 'members', 'global' );
}
}
ipsRegistry::DB()->insert( 'members', $finalTables['members'] );
//-----------------------------------------
// Get the member id
//-----------------------------------------
$finalTables['members']['member_id'] = ipsRegistry::DB()->getInsertId();
//-----------------------------------------
// Insert: PROFILE PORTAL
//-----------------------------------------
$finalTables['profile_portal']['pp_member_id'] = $finalTables['members']['member_id'];
$finalTables['profile_portal']['pp_setting_count_friends'] = 1;
$finalTables['profile_portal']['pp_setting_count_comments'] = 1;
$finalTables['profile_portal']['pp_setting_count_visitors'] = 1;
$finalTables['profile_portal']['pp_customization'] = serialize( array() );
foreach( array( 'pp_last_visitors', 'pp_about_me', 'signature', 'fb_photo', 'fb_photo_thumb', 'pconversation_filters' ) as $f )
{
$finalTables['profile_portal'][ $f ] = ( $finalTables['profile_portal'][ $f ] ) ? $finalTables['profile_portal'][ $f ] : '';
}
ipsRegistry::DB()->insert( 'profile_portal', $finalTables['profile_portal'] );
//-----------------------------------------
// Insert into the custom profile fields DB
//-----------------------------------------
if( !$bypassCfields )
{
/* Check the website url field */
$website_field = $fields->getFieldIDByKey( 'website' );
if( $website_field && $fields->out_fields[ 'field_' . $website_field ] )
{
if( stristr( $fields->out_fields[ 'field_' . $website_field ], 'http://' ) === FALSE && stristr( $fields->out_fields[ 'field_' . $website_field ], 'https://' ) === FALSE )
{
$fields->out_fields[ 'field_' . $website_field ] = 'http://' . $fields->out_fields[ 'field_' . $website_field ];
}
}
$fields->out_fields['member_id'] = $finalTables['members']['member_id'];
ipsRegistry::DB()->delete( 'pfields_content', 'member_id=' . $finalTables['members']['member_id'] );
ipsRegistry::DB()->insert( 'pfields_content', $fields->out_fields );
}
else
{
ipsRegistry::DB()->delete( 'pfields_content', 'member_id=' . $finalTables['members']['member_id'] );
ipsRegistry::DB()->insert( 'pfields_content', array( 'member_id' => $finalTables['members']['member_id'] ) );
}
//-----------------------------------------
// Insert into partial ID table
//-----------------------------------------
$full_account = false;
if( $finalTables['members']['members_display_name'] AND $finalTables['members']['name'] AND $finalTables['members']['email'] AND $finalTables['members']['email'] != $finalTables['members']['name'] . '@' . $finalTables['members']['joined'] )
{
$full_account = true;
}
if ( ! $full_account )
{
ipsRegistry::DB()->insert( 'members_partial', array( 'partial_member_id' => $finalTables['members']['member_id'],
'partial_date' => $finalTables['members']['joined'],
'partial_email_ok' => ( $finalTables['members']['email'] == $finalTables['members']['name'] . '@' . $finalTables['members']['joined'] ) ? 0 : 1,
) );
}
/* Add plain password and run sync */
$finalTables['members']['plainPassword'] = $plainPassword;
IPSLib::runMemberSync( 'onCreateAccount', $finalTables['members'] );
/* Remove plain password */
unset( $finalTables['members']['plainPassword'] );
//-----------------------------------------
// Recache our stats (Ticket 627608)
//-----------------------------------------
if ( $doStatsRecache == TRUE )
{
ipsRegistry::cache()->rebuildCache( 'stats', 'global' );
}
return array_merge( $finalTables['members'], $finalTables['profile_portal'], !$bypassCfields ? $fields->out_fields : array(), array( 'timenow' => $finalTables['members']['joined'], 'full' => $full_account ) );
}
/**
* Save member
*
* @param int Member key: Either Array, ID or email address. If it's an array, it must be in the format:
* array( 'core' => array( 'field' => 'member_id', 'value' => 1 ) ) - useful for passing custom fields through
* @param array Fields to save in the following format: array( 'members' => array( 'email' => 'test@test.com',
* 'joined' => time() ),
* 'extendedProfile' => array( 'signature' => 'My signature' ) );
* Tables: members, pfields_content, profile_portal.
* You can also use the aliases: 'core [members]', 'extendedProfile [profile_portal]', and 'customFields [pfields_content]'
* @return boolean True if the save was successful
*
* Exception Error Codes:
* NO_DATA : No data to save
* NO_VALID_KEY : No valid key to save
* NO_AUTO_LOAD : Could not autoload the member as she does not exist
* INCORRECT_TABLE : Table one is attempting to save to does not exist
* NO_MEMBER_GROUP_ID: Member group ID is in the array but blank
*/
static public function save( $member_key, $save=array() )
{
$member_id = 0;
$member_email = '';
$member_field = '';
$_updated = 0;
$bitWiseFields = ipsRegistry::fetchBitWiseOptions( 'global' );
$member_k_array = array( 'members' => array(), 'pfields_content' => array(), 'profile_portal' => array() );
$_tables = array_keys( $save );
$_MEMBERKEY = 'member_id';
$_MEMBERVALUE = $member_key;
//-----------------------------------------
// Test...
//-----------------------------------------
if ( ! is_array( $save ) OR ! count( $save ) )
{
throw new Exception( 'NO_DATA' );
}
//-----------------------------------------
// ID or email?
//-----------------------------------------
if ( ! is_array( $member_key ) )
{
if ( strstr( $member_key, '@' ) )
{
$_MEMBERKEY = 'email';
if ( IPSText::mbstrlen( $member_key ) > 150 )
{
throw new Exception( 'NO_VALID_KEY' );
}
$member_k_array['members'] = array( 'field' => 'email',
'value' => "'" . ipsRegistry::instance()->DB()->addSlashes( strtolower( $member_key ) ) . "'" );
//-----------------------------------------
// Check to see if we've got more than the core
// table to save on.
//-----------------------------------------
$_got_more_than_core = FALSE;
foreach( $_tables as $table )
{
if ( isset( self::$remap[ $table ] ) )
{
$table = self::$remap[ $table ];
}
if ( $table != 'members' )
{
$_got_more_than_core = TRUE;
break;
}
}
if ( $_got_more_than_core === TRUE )
{
/* Get the ID */
$_memberTmp = self::load( $member_key, 'core' );
if ( $_memberTmp['member_id'] )
{
$member_k_array['pfields_content'] = array( 'field' => 'member_id' , 'value' => $_memberTmp['member_id'] );
$member_k_array['profile_portal'] = array( 'field' => 'pp_member_id', 'value' => $_memberTmp['member_id'] );
}
else
{
throw new Exception( "NO_AUTO_LOAD" );
}
}
}
else
{
$member_k_array['members'] = array( 'field' => 'member_id' , 'value' => intval( $member_key ) );
$member_k_array['pfields_content'] = array( 'field' => 'member_id' , 'value' => intval( $member_key ) );
$member_k_array['profile_portal'] = array( 'field' => 'pp_member_id' , 'value' => intval( $member_key ) );
self::_updateCache( $member_key, $save );
}
}
else
{
$_member_k_array = $member_k_array;
foreach( $member_key as $table => $data )
{
if ( isset( self::$remap[ $table ] ) )
{
$table = self::$remap[ $table ];
}
if ( ! in_array( $table, array_keys( $_member_k_array ) ) )
{
throw new Exception( 'INCORRECT_TABLE' );
}
$member_k_array[ $table ] = $data;
}
}
//-----------------------------------------
// Test...
//-----------------------------------------
if ( ! is_array( $member_k_array ) OR ! count( $member_k_array ) )
{
throw new Exception( 'NO_DATA' );
}
//-----------------------------------------
// Now save...
//-----------------------------------------
foreach( $save as $table => $data )
{
if ( isset( self::$remap[ $table ] ) )
{
$table = self::$remap[ $table ];
}
if ( $table == 'profile_portal' )
{
$data[ $member_k_array[ $table ]['field'] ] = $member_k_array[ $table ]['value'];
//-----------------------------------------
// Does row exist?
//-----------------------------------------
$check = ipsRegistry::DB()->buildAndFetch( array( 'select' => 'pp_member_id', 'from' => 'profile_portal', 'where' => 'pp_member_id=' . $data['pp_member_id'] ) );
if( !$check['pp_member_id'] )
{
ipsRegistry::DB()->insert( $table, $data );
}
else
{
ipsRegistry::DB()->update( $table, $data, 'pp_member_id=' . $data['pp_member_id'] );
}
}
else if ( $table == 'pfields_content' )
{
$data[ $member_k_array[ $table ]['field'] ] = $member_k_array[ $table ]['value'];
//-----------------------------------------
// Does row exist?
//-----------------------------------------
$check = ipsRegistry::DB()->buildAndFetch( array( 'select' => 'member_id', 'from' => 'pfields_content', 'where' => 'member_id=' . $data['member_id'] ) );
ipsRegistry::DB()->setDataType( array_keys( $data ), 'string' );
if( !$check['member_id'] )
{
ipsRegistry::DB()->insert( $table, $data );
}
else
{
ipsRegistry::DB()->update( $table, $data, 'member_id=' . $data['member_id'] );
}
}
else
{
if ( $table == 'members' )
{
/* Make sure we have a value for member_group_id if passed */
if ( isset( $data['member_group_id'] ) AND ! $data['member_group_id'] )
{
throw new Exception( "NO_MEMBER_GROUP_ID" );
}
/* Some stuff that can end up here */
unset( $data['_canBeIgnored'] );
/* Bitwise options */
if ( is_array( $bitWiseFields['members'] ) )
{
$_freeze = array();
foreach( $bitWiseFields['members'] as $field )
{
if ( isset( $data[ $field ] ) )
{
/* Add to freezeable array */
$_freeze[ $field ] = $data[ $field ];
/* Remove it from the fields to save to DB */
unset( $data[ $field ] );
}
}
if ( count( $_freeze ) )
{
$data['members_bitoptions'] = IPSBWOptions::freeze( $_freeze, 'members', 'global' );
}
}
if( isset($data['members_display_name']) AND $data['members_display_name'] )
{
if ( IPSText::mbstrlen( $data['members_display_name'] ) > 255 )
{
throw new Exception( 'NO_VALID_KEY' );
}
$data['members_l_display_name'] = IPSText::mbstrtolower($data['members_display_name']);
$data['members_seo_name'] = IPSText::makeSeoTitle( $data['members_display_name'] );
}
if( isset($data['name']) AND $data['name'] )
{
if ( IPSText::mbstrlen( $data['name'] ) > 255 )
{
throw new Exception( 'NO_VALID_KEY' );
}
$data['members_l_username'] = IPSText::mbstrtolower($data['name']);
}
ipsRegistry::DB()->setDataType( array( 'name', 'title', 'members_l_username', 'members_display_name', 'members_l_display_name', 'members_seo_name' ), 'string' );
ipsRegistry::DB()->setDataType( array( 'msg_count_total', 'msg_count_new', 'members_bitoptions' ), 'int' );
}
ipsRegistry::DB()->update( $table, $data, $member_k_array[ $table ]['field'] . '=' . $member_k_array[ $table ]['value'] );
}
$_updated += ipsRegistry::instance()->DB()->getAffectedRows();
}
//-----------------------------------------
// If member login key is updated during
// session creation, this causes fatal error
//-----------------------------------------
if( is_object( ipsRegistry::member() ) )
{
$save[ $_MEMBERKEY ] = $_MEMBERVALUE;
IPSLib::runMemberSync( 'onProfileUpdate', $save );
}
return ( $_updated > 0 ) ? TRUE : FALSE;
}
/**
* Load member
*
* @param string Member key: Either ID or email address OR array of IDs when $key_type is either ID or not set OR a list of $key_type strings (email address, name, etc)
* @param string Extra tables to load(all, none or comma delisted tables) Tables: members, pfields_content, profile_portal, groups, sessions, core_item_markers_storage, members_partial.
* You can also use the aliases: 'extendedProfile', 'customFields' and 'itemMarkingStorage'
* @param string Key type. Leave it blank to auto-detect or specify "id", "email", "username", "displayname".
* @return array Array containing member data
* <code>
* # Single member
* $member = IPSMember::load( 1, 'extendedProfile,groups' );
* $member = IPSMember::load( 'matt@email.com', 'all' );
* $member = IPSMember::load( 'MattM', 'all', 'displayname' ); // Can also use 'username', 'email' or 'id'
* # Multiple members
* $members = IPSMember::load( array( 1, 2, 10 ), 'all' );
* $members = IPSMember::load( array( 'MattM, 'JoeD', 'DaveP' ), 'all', 'displayname' );
* </code>
*/
static public function load( $member_key, $extra_tables='all', $key_type='' )
{
//-----------------------------------------
// INIT
//-----------------------------------------
$member_value = 0;
$members = array();
$multiple_ids = array();
$member_field = '';
$joins = array();
$tables = array( 'pfields_content' => 0, 'profile_portal' => 0, 'groups' => 0, 'sessions' => 0, 'members_partial' => 0 );
$remap = array( 'extendedProfile' => 'profile_portal',
'customFields' => 'pfields_content');
//-----------------------------------------
// ID or email?
//-----------------------------------------
if ( ! $key_type )
{
if ( is_array( $member_key ) )
{
$multiple_ids = array_map( 'intval', $member_key ); // Bug #20908
$member_field = 'member_id';
}
else
{
if ( strstr( $member_key, '@' ) )
{
if( strstr( $member_key, ' ' ) )
{
$member_key = '';
}
$member_key = IPSText::mbsubstr( $member_key, 0, 150 );
$member_value = "'" . ipsRegistry::DB()->addSlashes( strtolower( $member_key ) ) . "'";
$member_field = 'email';
}
else
{
$member_value = intval( $member_key );
$member_field = 'member_id';
}
}
}
else
{
switch( $key_type )
{
default:
case 'id':
if ( is_array( $member_key ) )
{
$multiple_ids = $member_key;
}
else
{
$member_value = intval( $member_key );
}
$member_field = 'member_id';
break;
case 'fb_uid':
if ( is_array( $member_key ) )
{
$multiple_ids = $member_key;
}
else
{
$member_value = is_numeric( $member_key ) ? $member_key : 0;
}
$member_field = 'fb_uid';
if ( $member_value == 0 )
{
return array();
}
break;
case 'twitter_id':
if ( is_array( $member_key ) )
{
$multiple_ids = $member_key;
}
else
{
$member_value = is_numeric( $member_key ) ? $member_key : 0;
}
$member_field = 'twitter_id';
if ( $member_value == 0 )
{
return array();
}
break;
case 'vk_uid':
if ( is_array( $member_key ) )
{
$multiple_ids = $member_key;
}
else
{
$member_value = is_numeric( $member_key ) ? $member_key : 0;
}
$member_field = 'vk_uid';
if ( $member_value == 0 )
{
return array();
}
break;
case 'email':
if ( is_array( $member_key ) )
{
array_walk( $member_key, create_function( '&$v,$k', '$v="'".( ( strstr( $v, ' ' ) ) ? '' : ipsRegistry::DB()->addSlashes( IPSText::mbsubstr( strtolower( $v ), 0, 150 ) ) ) . "'";' ) );
$multiple_ids = $member_key;
}
else
{
if( strstr( $member_key, ' ' ) )
{
$member_key = '';
}
$member_key = substr( $member_key, 0, 150 );
$member_value = "'" . ipsRegistry::DB()->addSlashes( strtolower( $member_key ) ) . "'";
}
$member_field = 'email';
break;
case 'username':
if ( is_array( $member_key ) )
{
array_walk( $member_key, create_function( '&$v,$k', '$v="'".ipsRegistry::DB()->addSlashes( IPSText::mbsubstr( IPSText::mbstrtolower( $v ), 0, 255 ) ) . "'";' ) );
$multiple_ids = $member_key;
}
else
{
$member_key = substr( $member_key, 0, 255 );
$member_value = "'" . ipsRegistry::DB()->addSlashes( strtolower( $member_key ) ) . "'";
}
$member_field = 'members_l_username';
break;
case 'displayname':
if ( is_array( $member_key ) )
{
array_walk( $member_key, create_function( '&$v,$k', '$v="'".ipsRegistry::DB()->addSlashes( IPSText::mbsubstr( IPSText::mbstrtolower( $v ), 0, 255 ) ) . "'";' ) );
$multiple_ids = $member_key;
}
else
{
$member_key = substr( $member_key, 0, 255 );
$member_value = "'" . ipsRegistry::DB()->addSlashes( strtolower( $member_key ) ) . "'";
}
$member_field = 'members_l_display_name';
break;
case 'ipsconnect':
if ( is_array( $member_key ) )
{
$multiple_ids = $member_key;
}
else
{
$member_value = intval( $member_key );
}
$member_field = 'ipsconnect_id';
break;
}
}
//-----------------------------------------
// Protected against member_id=0
//-----------------------------------------
if( !count($multiple_ids) OR !is_array($multiple_ids) )
{
if( $member_field == 'member_id' AND !$member_value )
{
return array();
}
}
//-----------------------------------------
// Sort out joins...
//-----------------------------------------
if ( $extra_tables == 'all' )
{
foreach( $tables as $_table => $_val )
{
/* Let's not load sessions or members_partial unless specifically requested */
if ( $_table == 'sessions' or $_table == 'members_partial' )
{
continue;
}
$tables[ $_table ] = 1;
}
}
else if ( $extra_tables )
{
$_tables = explode( ",", $extra_tables );
foreach( $_tables as $_t )
{
$_t = trim( $_t );
if ( isset( $tables[ $_t ] ) )
{
$tables[ $_t ] = 1;
}
else if ( isset( self::$remap[ $_t ] ) )
{
if ( strstr( $tables[ self::$remap[ $_t ] ], ',' ) )
{
$__tables = explode( ',', $tables[ self::$remap[ $_t ] ] );
foreach( $__tables as $__t )
{
$tables[ $__t ] = 1;
}
}
else
{
$tables[ self::$remap[ $_t ] ] = 1;
}
}
}
}
//-----------------------------------------
// Grab used tables
//-----------------------------------------
$_usedTables = array();
foreach( $tables as $_name => $_use )
{
if ( $_use )
{
$_usedTables[] = $_name;
}
}
//-----------------------------------------
// Check the cache first...
//-----------------------------------------
if ( $member_field == 'member_id' AND $member_value )
{
$member = self::_fetchFromCache( $member_value, $_usedTables );
if ( $member !== FALSE )
{
return $member;
}
}
else if( count($multiple_ids) AND is_array($multiple_ids) )
{
$_totalUsers = count($multiple_ids);
$_gotFromCache = 0;
$_fromCache = array();
foreach( $multiple_ids as $_memberValue )
{
$member = self::_fetchFromCache( $_memberValue, $_usedTables );
if ( $member !== FALSE )
{
$_fromCache[ $member['member_id'] ] = $member;
$_gotFromCache++;
}
}
//-----------------------------------------
// Did we find all the members in cache?
//-----------------------------------------
if( $_gotFromCache == $_totalUsers )
{
return $_fromCache;
}
}
self::$ignoreCache = FALSE;
//-----------------------------------------
// Fix up joins...
//-----------------------------------------
if ( $tables['pfields_content'] )
{
$joins[] = array( 'select' => 'p.*',
'from' => array( 'pfields_content' => 'p' ),
'where' => 'p.member_id=m.member_id',
'type' => 'left' );
}
if ( $tables['profile_portal'] )
{
$joins[] = array( 'select' => 'pp.*',
'from' => array( 'profile_portal' => 'pp' ),
'where' => 'pp.pp_member_id=m.member_id',
'type' => 'left' );
}
if ( $tables['groups'] )
{
$joins[] = array( 'select' => 'g.*',
'from' => array( 'groups' => 'g' ),
'where' => 'g.g_id=m.member_group_id',
'type' => 'left' );
}
if ( $tables['sessions'] )
{
$joins[] = array( 'select' => 's.*',
'from' => array( 'sessions' => 's' ),
'where' => 's.member_id=m.member_id',
'type' => 'left' );
}
if ( $tables['core_item_markers_storage'] )
{
$joins[] = array( 'select' => 'im.*',
'from' => array( 'core_item_markers_storage' => 'im' ),
'where' => 'im.item_member_id=m.member_id',
'type' => 'left' );
}
if ( $tables['members_partial'] )
{
$joins[] = array( 'select' => 'mp.*',
'from' => array( 'members_partial' => 'mp' ),
'where' => 'mp.partial_member_id=m.member_id',
'type' => 'left' );
}
if ( IPSContentCache::isEnabled() )
{
if ( IPSContentCache::fetchSettingValue( 'sig' ) )
{
$joins[] = IPSContentCache::join( 'sig' , 'm.member_id', 'ccb', 'left', 'ccb.cache_content' );
}
}
//-----------------------------------------
// Do eeet
//-----------------------------------------
if ( count( $joins ) )
{
ipsRegistry::DB()->build( array( 'select' => 'm.*, m.member_id as my_member_id',
'from' => array( 'members' => 'm' ),
'where' => ( is_array( $multiple_ids ) AND count( $multiple_ids ) ) ? 'm.'. $member_field . ' IN (' . implode( ',', $multiple_ids ) . ')' : 'm.'. $member_field . '=' . $member_value,
'add_join' => $joins ) );
}
else
{
ipsRegistry::DB()->build( array( 'select' => '*',
'from' => 'members',
'where' => ( is_array( $multiple_ids ) AND count( $multiple_ids ) ) ? $member_field . ' IN (' . implode( ',', $multiple_ids ) . ')' : $member_field . '=' . $member_value ) );
}
//-----------------------------------------
// Execute
//-----------------------------------------
ipsRegistry::DB()->execute();
while( $mem = ipsRegistry::DB()->fetch() )
{
if ( isset( $mem['my_member_id'] ) )
{
$mem['member_id'] = $mem['my_member_id'];
}
$mem['full'] = true;
if( !$mem['email'] OR !$mem['members_display_name'] OR $mem['email'] == $mem['name'] . '@' . $mem['joined'] )
{
$mem['full'] = false;
$mem['timenow'] = $mem['joined'];
}
/* Clean secondary groups */
$mem['mgroup_others'] = ($mem['mgroup_others'] != '') ? IPSText::cleanPermString($mem['mgroup_others']) : '';
//-----------------------------------------
// Be sure we properly apply secondary permissions
//-----------------------------------------
if ( $tables['groups'] )
{
$mem = ips_MemberRegistry::setUpSecondaryGroups( $mem );
/* Unpack groups */
$mem = IPSMember::unpackGroup( $mem, TRUE, TRUE /* We can't use the cache as this member will have different secondary groups to other members in this group */ );
}
//-----------------------------------------
// Unblockable
//-----------------------------------------
$mem['_canBeIgnored'] = self::isIgnorable( $mem['member_group_id'], $mem['mgroup_others'] );
/* Bitwise Options */
$mem = self::buildBitWiseOptions( $mem );
/* Twitter is disabled them remove twitter tokens and such */
if ( $mem['twitter_id'] && ! IPSLib::twitter_enabled() )
{
$mem['twitter_token'] = '';
$mem['twitter_secret'] = '';
$mem['twitter_id'] = '';
}
/* Add to array */
$members[ $mem['member_id'] ] = $mem;
//-----------------------------------------
// Add to cache
//-----------------------------------------
self::_addToCache( $mem, $_usedTables );
}
//-----------------------------------------
// Return just a single if we only sent one id
//-----------------------------------------
return ( is_array( $multiple_ids ) AND count( $multiple_ids ) ) ? $members : array_shift( $members );
}
/**
* Delete member(s)
*
* @param mixed [Integer] member ID or [Array] array of member ids
* @param boolean Check if request is from an admin
* @return boolean Action completed successfully
*/
static public function remove( $id, $check_admin=true )
{
/* Init vars */
$mids = '';
$tmp_mids = array();
$emails = array();
//-----------------------------------------
// Sort out thingie
//-----------------------------------------
if ( is_array( $id ) )
{
$id = IPSLib::cleanIntArray( $id );
if ( count($id) )
{
$mids = ' IN (' . implode( ",", $id ) . ')';
}
}
else
{
$id = intval($id);
if ( $id > 0 )
{
$mids = ' = ' . $id;
}
}
if ( empty($mids) )
{
return false;
}
//-----------------------------------------
// Get accounts and check IDS
//-----------------------------------------
ipsRegistry::DB()->build( array(
'select' => 'm.member_id, m.name, m.member_group_id, m.email',
'from' => array( 'members' => 'm' ),
'where' => 'm.member_id' . $mids,
'add_join' => array(
array(
'select' => 'g.g_access_cp',
'from' => array( 'groups' => 'g' ),
'where' => 'g.g_id=m.member_group_id',
'type' => 'left',
)
)
) );
ipsRegistry::DB()->execute();
while ( $r = ipsRegistry::DB()->fetch() )
{
//-----------------------------------------
// Non root admin attempting to edit root admin?
//-----------------------------------------
if( $check_admin )
{
if ( !ipsRegistry::member()->getProperty('g_access_cp') )
{
if ( $r['g_access_cp'] )
{
continue;
}
}
}
$tmp_mids[] = $r['member_id'];
$emails[] = $r['email'];
self::_removeFromCache( $r['member_id'] );
}
if ( ! count( $tmp_mids ) )
{
return false;
}
$mids = ' IN (' . implode( ",", $tmp_mids ) . ')';
//-----------------------------------------
// Login modules
// (Have to do this first otherwise we've
// deleted stuff we may need like email, etc.)
//-----------------------------------------
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/handlers/han_login.php', 'han_login' );
$han_login = new $classToLoad( ipsRegistry::instance() );
$han_login->init();
$han_login->deleteAccount( $id );
//-----------------------------------------
// Get photo
//-----------------------------------------
$delete_files = array();
ipsRegistry::DB()->build( array( 'select' => '*', 'from' => 'profile_portal', 'where' => 'pp_member_id' . $mids ) );
ipsRegistry::DB()->execute();
while( $r = ipsRegistry::DB()->fetch() )
{
if ( $r['pp_main_photo'] )
{
$delete_files[] = $r['pp_main_photo'];
}
if ( $r['pp_thumb_photo'] )
{
$delete_files[] = $r['pp_thumb_photo'];
}
$_customizations = IPSLib::safeUnserialize($r['pp_customization']);
if( $_customizations['type'] == 'upload' AND $_customizations['bg_url'] )
{
$delete_files[] = $_customizations['bg_url'];
}
}
//-----------------------------------------
// Take care of forum stuff
//-----------------------------------------
ipsRegistry::DB()->update( 'posts' , array( 'author_id' => 0 ), "author_id" . $mids );
ipsRegistry::DB()->update( 'topics' , array( 'starter_id' => 0 ), "starter_id" . $mids );
ipsRegistry::DB()->update( 'topics' , array( 'last_poster_id' => 0 ), "last_poster_id" . $mids );
ipsRegistry::DB()->update( 'announcements' , array( 'announce_member_id' => 0 ), "announce_member_id" . $mids );
ipsRegistry::DB()->update( 'attachments' , array( 'attach_member_id' => 0 ), "attach_member_id" . $mids );
ipsRegistry::DB()->update( 'polls' , array( 'starter_id' => 0 ), "starter_id" . $mids );
/**
* @todo Why is this query commented? Need to investigate and change for 3.4 if needed
*/
//ipsRegistry::DB()->update( 'topic_ratings' , array( 'rating_member_id' => 0 ), "rating_member_id" . $mids );
ipsRegistry::DB()->update( 'voters' , array( 'member_id' => 0 ), "member_id" . $mids );
ipsRegistry::DB()->update( 'forums' , array( 'last_poster_id' => 0, 'last_poster_name' => '', 'seo_last_name' => '' ), "last_poster_id" . $mids );
ipsRegistry::DB()->delete( 'core_share_links_log' , "log_member_id" . $mids );
ipsRegistry::DB()->delete( 'core_soft_delete_log' , "sdl_obj_member_id" . $mids );
ipsRegistry::DB()->delete( 'mobile_device_map' , "member_id" . $mids );
ipsRegistry::DB()->update( 'rss_import' , array( 'rss_import_mid' => 0 ), "rss_import_mid" . $mids );
ipsRegistry::DB()->update( 'core_tags' , array( 'tag_member_id' => 0 ), "tag_member_id" . $mids );
/* Update archived posts */
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/archive/writer.php', 'classes_archive_writer' );
$archiveWriter = new $classToLoad();
$archiveWriter->setApp('forums');
$archiveWriter->update( array( 'archive_author_id' => 0 ), 'archive_author_id' . $mids );
//-----------------------------------------
// Likes - also invalidates likes cache
// @todo - Move this into like class - problem is like object expects to know what plugin to use in bootstrap method, but we want to remove for all plugins...
//-----------------------------------------
$_likes = array();
ipsRegistry::DB()->build( array( 'select' => 'like_lookup_id', 'from' => 'core_like', 'where' => "like_member_id" . $mids ) );
ipsRegistry::DB()->execute();
while( $r = ipsRegistry::DB()->fetch() )
{
$_likes[] = $r['like_lookup_id'];
}
if( count($_likes) )
{
ipsRegistry::DB()->delete( 'core_like' , "like_member_id" . $mids );
ipsRegistry::DB()->delete( 'core_like_cache' , "like_cache_id IN('" . implode( "','", array_map( 'addslashes', $_likes ) ) . "')" );
}
//-----------------------------------------
// Clean up profile stuff
//-----------------------------------------
ipsRegistry::DB()->update( 'profile_ratings' , array( 'rating_by_member_id' => 0 ), "rating_by_member_id" . $mids );
ipsRegistry::DB()->delete( 'profile_ratings' , "rating_for_member_id" . $mids );
ipsRegistry::DB()->delete( 'profile_portal' , "pp_member_id" . $mids );
ipsRegistry::DB()->delete( 'profile_portal_views' , "views_member_id" . $mids );
$_friendMemberIds = array();
ipsRegistry::DB()->build( array( 'select' => '*', 'from' => 'profile_friends', 'where' => "friends_member_id" . $mids . " OR friends_friend_id" . $mids ) );
ipsRegistry::DB()->execute();
while( $r = ipsRegistry::DB()->fetch() )
{
if( !in_array( $r['friends_friend_id'], $tmp_mids ) )
{
$_friendMemberIds[ $r['friends_friend_id'] ] = $r['friends_friend_id'];
}
if( !in_array( $r['friends_member_id'], $tmp_mids ) )
{
$_friendMemberIds[ $r['friends_member_id'] ] = $r['friends_member_id'];
}
}
ipsRegistry::DB()->delete( 'profile_friends' , "friends_member_id" . $mids );
ipsRegistry::DB()->delete( 'profile_friends' , "friends_friend_id" . $mids );
ipsRegistry::DB()->delete( 'profile_friends_flood' , "friends_member_id" . $mids . " OR friends_friend_id" . $mids );
ipsRegistry::DB()->delete( 'dnames_change' , "dname_member_id" . $mids );
ipsRegistry::DB()->delete( 'mobile_notifications' , "member_id" . $mids );
//-----------------------------------------
// Delete member...
//-----------------------------------------
ipsRegistry::DB()->delete( 'pfields_content' , "member_id" . $mids );
ipsRegistry::DB()->delete( 'members_partial' , "partial_member_id" . $mids );
ipsRegistry::DB()->delete( 'moderators' , "member_id" . $mids );
ipsRegistry::DB()->delete( 'sessions' , "member_id" . $mids );
ipsRegistry::DB()->delete( 'search_sessions' , "session_member_id" . $mids );
ipsRegistry::DB()->delete( 'upgrade_sessions' , "session_member_id" . $mids );
ipsRegistry::DB()->delete( 'members_warn_logs' , "wl_member" . $mids );
ipsRegistry::DB()->update( 'members_warn_logs' , array( 'wl_moderator' => 0 ), "wl_moderator" . $mids );
ipsRegistry::DB()->delete( 'member_status_actions' , "action_member_id" . $mids );
ipsRegistry::DB()->delete( 'member_status_actions' , "action_status_owner" . $mids );
ipsRegistry::DB()->delete( 'member_status_replies' , "reply_member_id" . $mids );
ipsRegistry::DB()->delete( 'member_status_updates' , "status_member_id" . $mids );
ipsRegistry::DB()->delete( 'member_status_updates' , "status_author_id" . $mids );
//-----------------------------------------
// Update admin stuff and logs
//-----------------------------------------
ipsRegistry::DB()->delete( 'admin_permission_rows' , "row_id_type='member' AND row_id" . $mids );
ipsRegistry::DB()->delete( 'core_sys_cp_sessions' , 'session_member_id' . $mids );
ipsRegistry::DB()->delete( 'core_sys_login' , 'sys_login_id' . $mids );
ipsRegistry::DB()->update( 'upgrade_history' , array( 'upgrade_mid' => 0 ), "upgrade_mid" . $mids );
ipsRegistry::DB()->update( 'admin_logs' , array( 'member_id' => 0 ), "member_id" . $mids );
ipsRegistry::DB()->update( 'error_logs' , array( 'log_member' => 0 ), "log_member" . $mids );
ipsRegistry::DB()->update( 'moderator_logs' , array( 'member_id' => 0, 'member_name' => '' ), "member_id" . $mids );
//-----------------------------------------
// Delete PMs
//-----------------------------------------
$messageIds = array();
ipsRegistry::DB()->build( array( 'select' => 'map_topic_id, map_user_id', 'from' => 'message_topic_user_map', 'where' => 'map_user_id' . $mids ) );
ipsRegistry::DB()->execute();
while( $r = ipsRegistry::DB()->fetch() )
{
$messageIds[ $r['map_user_id'] ][] = $r['map_topic_id'];
}
if( count($messageIds) )
{
$classToLoad = IPSLib::loadLibrary( IPSLib::getAppDir('members') . '/sources/classes/messaging/messengerFunctions.php', 'messengerFunctions', 'members' );
$messenger = new $classToLoad( ipsRegistry::instance() );
foreach( $messageIds as $user => $topics )
{
$messenger->deleteTopics( $user, $topics );
}
}
//-----------------------------------------
// Fallback cleanup
//-----------------------------------------
ipsRegistry::DB()->delete( 'message_topic_user_map' , 'map_user_id' . $mids );
ipsRegistry::DB()->update( 'message_posts' , array( 'msg_author_id' => 0 ), 'msg_author_id' . $mids );
ipsRegistry::DB()->update( 'message_topics' , array( 'mt_starter_id' => 0 ), 'mt_starter_id' . $mids );
ipsRegistry::DB()->update( 'message_topics' , array( 'mt_to_member_id' => 0 ), 'mt_to_member_id' . $mids );
//-----------------------------------------
// Delete subs, views, markers, etc.
//-----------------------------------------
ipsRegistry::DB()->delete( 'ignored_users' , "ignore_owner_id" . $mids . " or ignore_ignore_id" . $mids );
ipsRegistry::DB()->delete( 'inline_notifications' , "notify_to_id" . $mids );
ipsRegistry::DB()->update( 'inline_notifications' , array( 'notify_from_id' => 0 ), 'notify_from_id' . $mids );
ipsRegistry::DB()->delete( 'core_item_markers' , "item_member_id" . $mids );
ipsRegistry::DB()->delete( 'core_item_markers_storage', "item_member_id" . $mids );
ipsRegistry::DB()->update( 'rc_comments' , array( 'comment_by' => 0 ), "comment_by" . $mids );
ipsRegistry::DB()->delete( 'rc_modpref' , "mem_id" . $mids );
ipsRegistry::DB()->update( 'rc_reports' , array( 'report_by' => 0 ), "report_by" . $mids );
ipsRegistry::DB()->update( 'rc_reports_index' , array( 'updated_by' => 0 ), "updated_by" . $mids );
ipsRegistry::DB()->delete( 'rc_reports_index' , "seotemplate='showuser' AND exdat1" . $mids );
ipsRegistry::DB()->delete( 'reputation_cache' , "type='member' AND type_id" . $mids );
ipsRegistry::DB()->delete( 'reputation_index' , "member_id" . $mids );
$cache = ipsRegistry::cache()->getCache('report_cache');
$cache['last_updated'] = time();
ipsRegistry::cache()->setCache( 'report_cache', $cache, array( 'array' => 1 ) );
//-----------------------------------------
// Delete from validating..
//-----------------------------------------
ipsRegistry::DB()->delete( 'validating' , "member_id" . $mids );
ipsRegistry::DB()->delete( 'members' , "member_id" . $mids );
/* Delete from profile cache */
if ( count( $_friendMemberIds ) )
{
$classToLoad = IPSLib::loadLibrary( IPSLib::getAppDir('members') . '/sources/friends.php', 'profileFriendsLib', 'members' );
$friends = new $classToLoad( ipsRegistry::instance() );
foreach( $_friendMemberIds as $_mid )
{
$friends->recacheFriends( array( 'member_id' => $_mid ) );
}
}
//-----------------------------------------
// Delete photos
//-----------------------------------------
if ( count($delete_files) )
{
foreach( $delete_files as $file )
{
@unlink( ipsRegistry::$settings['upload_dir'] . "/" . $file );
}
}
//-----------------------------------------
// memberSync
//-----------------------------------------
IPSLib::runMemberSync( 'onDelete', $mids );
//-----------------------------------------
// Remove from cache
//-----------------------------------------
IPSContentCache::drop( 'sig', $tmp_mids );
//-----------------------------------------
// Get current stats...
//-----------------------------------------
ipsRegistry::cache()->rebuildCache( 'stats', 'global' );
ipsRegistry::cache()->rebuildCache( 'moderators', 'forums' );
ipsRegistry::cache()->rebuildCache( 'birthdays', 'calendar' );
ipsRegistry::cache()->rebuildCache( 'announcements', 'forums' );
return true;
}
/**
* Set up moderator, populate moderator functions
*
* @param array Array of member data
* @return array Array of member data populated with moderator details
*/
static public function setUpModerator( $member )
{
static $cache = array();
if( $cache[ $member['member_id'] ] )
{
return array_merge( $member, $cache[ $member['member_id'] ] );
}
$other_mgroups = array();
$return = array();
if ( $member['member_group_id'] != ipsRegistry::$settings['guest_group'] )
{
//-----------------------------------------
// Sprinkle on some moderator stuff...
//-----------------------------------------
if ( $member['g_is_supmod'] == 1 )
{
$return['is_mod'] = 1;
}
else if ( is_array(ipsRegistry::cache()->getCache('moderators')) AND count(ipsRegistry::cache()->getCache('moderators')) )
{
$other_mgroups = array();
if ( IPSText::cleanPermString( $member['mgroup_others'] ) )
{
$other_mgroups = explode( ",", IPSText::cleanPermString( $member['mgroup_others'] ) );
}
}
if( is_array(ipsRegistry::cache()->getCache('moderators')) AND count(ipsRegistry::cache()->getCache('moderators')) )
{
$_mod_forums = isset( $member['forumsModeratorData'] ) && is_array( $member['forumsModeratorData'] ) ? $member['forumsModeratorData'] : array();
foreach( ipsRegistry::cache()->getCache('moderators') as $r )
{
$modForumIds = explode( ',', IPSText::cleanPermString( $r['forum_id'] ) );
if ( $r['member_id'] AND $r['member_id'] == $member['member_id'] )
{
foreach( $modForumIds as $modForumId )
{
$_mod_forums[ $modForumId ] = $r;
}
$return['is_mod'] = 1;
}
else if( $r['group_id'] AND $r['group_id'] == $member['member_group_id'] )
{
// Individual mods override group mod settings
// If array is set, don't override it
foreach( $modForumIds as $modForumId )
{
if( !is_array($_mod_forums[ $modForumId ]) OR !count($_mod_forums[ $modForumId ]) )
{
$_mod_forums[ $modForumId ] = $r;
}
}
$return['is_mod'] = 1;
}
else if( $r['group_id'] AND count( $other_mgroups ) AND in_array( $r['group_id'], $other_mgroups ) )
{
// Individual mods override group mod settings
// If array is set, don't override it
foreach( $modForumIds as $modForumId )
{
if( !is_array($_mod_forums[ $modForumId ]) OR !count($_mod_forums[ $modForumId ]) )
{
$_mod_forums[ $modForumId ] = $r;
}
}
$return['is_mod'] = 1;
}
}
$return['forumsModeratorData'] = $_mod_forums;
}
}
$cache[ $member['member_id'] ] = $return;
return array_merge( $member, $cache[ $member['member_id'] ] );
}
/**
* Fetches SEO name, updating the table if required
*
* @param array Member data
* @return string SEO Name
*/
static public function fetchSeoName( $memberData )
{
if ( ! is_array( $memberData ) OR ! $memberData['member_id'] )
{
return;
}
if ( !empty( $memberData['members_seo_name'] ) )
{
return $memberData['members_seo_name'];
}
else if ( !empty( $memberData['members_display_name'] ) )
{
$_seoName = IPSText::makeSeoTitle( $memberData['members_display_name'] );
ipsRegistry::DB()->update( 'members', array( 'members_seo_name' => $_seoName ), 'member_id=' . $memberData['member_id'] );
return $_seoName;
}
else
{
return '-';
}
}
/**
* Fetches Ignore user data
*
* @param array Member data
* @return array Array of ignored users
*/
static public function fetchIgnoredUsers( $memberData )
{
/* INIT */
$ignore_users = array();
if ( $memberData['member_id'] )
{
/* < 3.0.0 used comma delisted string. 3.0.0+ uses serialized array */
if ( strstr( $memberData['ignored_users'], 'a:' ) )
{
$data = unserialize( $memberData['ignored_users'] );
return ( is_array( $data ) ) ? $data : array();
}
else
{
if ( $memberData['ignored_users'] )
{
$_data = explode( ",", $memberData['ignored_users'] );
foreach( $_data as $id )
{
if ( $id )
{
$ignore_users[ $id ] = array( 'ignore_ignore_id' => $id,
'ignore_messages' => 0,
'ignore_signatures' => 0,
'ignore_topics' => 1 );
}
}
}
/* Now fetch them from the DB */
ipsRegistry::DB()->build( array( 'select' => '*', 'from' => 'ignored_users', 'where' => "ignore_owner_id=" . $memberData['member_id'] ) );
ipsRegistry::DB()->execute();
while( $r = ipsRegistry::DB()->fetch() )
{
$ignore_users[ $r['ignore_ignore_id'] ] = array( 'ignore_ignore_id' => $r['ignore_ignore_id'],
'ignore_messages' => $r['ignore_messages'],
'ignore_signatures' => $r['ignore_signatures'],
'ignore_topics' => $r['ignore_topics'] );
}
/* Update.... */
self::save( $memberData['member_id'], array( 'core' => array( 'ignored_users' => serialize( $ignore_users ) ) ) );
}
}
return $ignore_users;
}
/**
* Updates member.ignored_users
*
* @param mixed Member ID or Member data
* @return array Array of ignored users
*/
static public function rebuildIgnoredUsersCache( $member )
{
/* INIT */
$ignore_users = array();
$memberData = ( ! is_array( $member ) ) ? self::load( $member, 'all' ) : $member;
/* Continue */
if ( $memberData['member_id'] )
{
/* Fetch from DB */
ipsRegistry::DB()->build( array( 'select' => '*', 'from' => 'ignored_users', 'where' => "ignore_owner_id=" . $memberData['member_id'] ) );
ipsRegistry::DB()->execute();
while( $r = ipsRegistry::DB()->fetch() )
{
$ignore_users[ $r['ignore_ignore_id'] ] = array( 'ignore_ignore_id' => $r['ignore_ignore_id'],
'ignore_messages' => $r['ignore_messages'],
'ignore_signatures' => $r['ignore_signatures'],
'ignore_topics' => $r['ignore_topics'],
'ignore_chats' => $r['ignore_chats'] );
}
/* Update.... */
self::save( $memberData['member_id'], array( 'core' => array( 'ignored_users' => serialize( $ignore_users ) ) ) );
}
}
/**
* Retrieve the member's location
*
* @author Brandon Farber
* @param array Member information (including session info!)
* @return array Member info with session info parsed
* @since IPB 3.0
*/
static public function getLocation( $member )
{
$member['online_extra'] = "";
//-----------------------------------------
// Grab 'where' info
//-----------------------------------------
if( !$member['in_error'] AND $member['current_appcomponent'] AND IPSLib::appIsInstalled( $member['current_appcomponent'] ) )
{
$member['current_appcomponent'] = IPSText::alphanumericalClean($member['current_appcomponent']);
$filename = IPSLib::getAppDir( $member['current_appcomponent'] ) . '/extensions/coreExtensions.php';
if ( is_file( $filename ) )
{
$toload = IPSLib::loadLibrary( $filename, 'publicSessions__' . $member['current_appcomponent'], $member['current_appcomponent'] );
if( class_exists( $toload ) )
{
$loader = new $toload();
if( method_exists( $loader, 'parseOnlineEntries' ) )
{
$tmp = $loader->parseOnlineEntries( array( $member['id'] => $member ) );
// Yes, this is really id - it's session id, not member id
if( isset( $tmp[ $member['id'] ] ) && is_array( $tmp[ $member['id'] ] ) && count( $tmp[ $member['id'] ] ) )
{
if ( isset( $tmp[ $member['id'] ]['_whereLinkSeo']) )
{
$member['online_extra'] = "{$tmp[ $member['id'] ]['where_line']} <a href='" . $tmp[ $member['id'] ]['_whereLinkSeo'] . "' title='" . IPSText::stripTags($tmp[ $member['id'] ]['where_line']) . ' ' . IPSText::stripTags($tmp[ $member['id'] ]['where_line_more']) . "'>" . IPSText::truncate( IPSText::stripTags( $tmp[ $member['id'] ]['where_line_more'] ), 35 ) . "</a>";
}
/* @link http://community.invisionpower.com/tracker/issue-20598-where-link-not-taken-into-account-on-profile-page-if-no-where-line-more-specified/ */
else if ( isset($tmp[ $member['id'] ]['where_link']) AND $tmp[ $member['id'] ]['where_line_more'] )
{
$member['online_extra'] = "{$tmp[ $member['id'] ]['where_line']} <a href='" . ipsRegistry::$settings['base_url'] . "{$tmp[ $member['id'] ]['where_link']}' title='" . IPSText::stripTags($tmp[ $member['id'] ]['where_line']) . ' ' . IPSText::stripTags($tmp[ $member['id'] ]['where_line_more']) . "'>" . IPSText::truncate( IPSText::stripTags( $tmp[ $member['id'] ]['where_line_more'] ), 35 ) . "</a>";
}
else if ( isset($tmp[ $member['id'] ]['where_link']) )
{
$member['online_extra'] = "<a href='" . ipsRegistry::$settings['base_url'] . "{$tmp[ $member['id'] ]['where_link']}' title='" . IPSText::stripTags($tmp[ $member['id'] ]['where_line']) . "'>" . IPSText::truncate( IPSText::stripTags( $tmp[ $member['id'] ]['where_line'] ), 35 ) . "</a>";
}
else
{
$member['online_extra'] = $tmp[ $member['id'] ]['where_line'];
}
}
}
}
}
}
if ( ! $member['online_extra'] )
{
$member['online_extra'] = $member['id'] ? ipsRegistry::getClass('class_localization')->words['board_index']
: ipsRegistry::getClass('class_localization')->words['not_online'];
}
return $member;
}
/**
* Determine if two members are friends
*
* @author Brandon Farber
* @param integer Member ID to check for
* @param integer Member ID to check against (defaults to current member id)
* @param bool Only return true if the friend is approved
* @return boolean Whether they are friends or not
* @since IPB 3.0
*/
static public function checkFriendStatus( $memberId, $checkAgainst=0, $onlyVerified=false )
{
/**
* If no member id, obviously not friends
*/
if( !$memberId )
{
return false;
}
/**
* Get member data
*/
$memberData = array();
if( !$checkAgainst )
{
$memberData = ipsRegistry::instance()->member()->getProperty('_cache');
}
else
{
$member = self::load( $checkAgainst, 'extendedProfile' );
$memberData = self::unpackMemberCache( $member['members_cache'] );
}
/**
* Do we have a friends cache array?
*/
if( !$memberData['friends'] OR !is_array($memberData['friends']) OR !count($memberData['friends']) )
{
return false;
}
/**
* If there is, then check it..
*/
if( $onlyVerified )
{
if( isset($memberData['friends'][ $memberId ]) AND $memberData['friends'][ $memberId ] )
{
return true;
}
return false;
}
else
{
return isset($memberData['friends'][ $memberId ]) ? true : false;
}
return false;
}
/**
* Determine if a member is ignoring another member
*
* @author Brandon Farber
* @param integer Member ID to check for
* @param integer Member ID to check against (defaults to current member id)
* @param string Type of ignoring to check [messages|topics]. Omit to check any type.
* @return boolean Whether the member id to check for is being ignored by the member id to check against
* @since IPB 3.0
*/
static public function checkIgnoredStatus( $memberId, $checkAgainst=0, $type=false )
{
/**
* If no member id, obviously not ignored
*/
if( !$memberId )
{
return false;
}
/**
* Get member data
*/
$memberData = array();
if( !$checkAgainst )
{
/**
* Ignored users loaded at runtime and stored in an array...loop
*/
foreach( ipsRegistry::instance()->member()->ignored_users as $ignoredUser )
{
/**
* We found the user?
*/
if( $ignoredUser['ignore_ignore_id'] )
{
/**
* If not specifying a type, then just return
*/
if( !$type )
{
return true;
}
/**
* Otherwise verify we are ignoring that type
*/
else if( $ignoredUser[ 'ignore_' . $type ] )
{
return true;
}
}
}
}
else
{
/**
* See if checkAgainst is ignoring memberId
*/
$checkAgainst = intval($checkAgainst);
$ignoredUser = ipsRegistry::DB()->buildAndFetch( array( 'select' => '*', 'from' => 'ignored_users', 'where' => 'ignore_owner_id=' . $checkAgainst . ' AND ignore_ignore_id=' . $memberId ) );
/**
* No?
*/
if( !$ignoredUser['ignore_id'] )
{
return false;
}
/**
* He is?
*/
else
{
/**
* If not specifying a type, then just return
*/
if( !$type )
{
return true;
}
/**
* Otherwise verify we are ignoring that type
*/
else if( $ignoredUser[ 'ignore_' . $type ] )
{
return true;
}
}
}
/**
* If we're here (which we shouldn't be) just return false
*/
return false;
}
/**
* Retrieve all IP addresses a user (or multiple users) have used
*
* @param mixed [Integer] member ID or [Array] array of member ids
* @param string Defaults to 'All', otherwise specify which tables to check (comma separated)
* @return array Multi-dimensional array of found IP addresses in which sections
*/
static public function findIPAddresses( $id, $tables_to_check='all' )
{
//-----------------------------------------
// INIT
//-----------------------------------------
$ip_addresses = array();
$tables = array(
'admin_logs' => array( 'member_id', 'ip_address', 'ctime' ),
'dnames_change' => array( 'dname_member_id', 'dname_ip_address', 'dname_date' ),
'members' => array( 'member_id', 'ip_address', 'joined' ),
'message_posts' => array( 'msg_author_id', 'msg_ip_address', 'msg_date' ),
'moderator_logs' => array( 'member_id', 'ip_address', 'ctime' ),
'posts' => array( 'author_id', 'ip_address', 'post_date' ),
'member_status_updates' => array( 'status_author_id', 'status_author_ip', 'status_date' ),
'profile_ratings' => array( 'rating_by_member_id', 'rating_ip_address', '' ),
'sessions' => array( 'member_id', 'ip_address', 'running_time' ),
'topic_ratings' => array( 'rating_member_id', 'rating_ip_address', '' ),
'validating' => array( 'member_id', 'ip_address', 'entry_date' ),
'voters' => array( 'member_id', 'ip_address', 'vote_date' ),
'error_logs' => array( 'log_member', 'log_ip_address', 'log_date' ),
);
//-----------------------------------------
// Check apps
// @see http://forums.invisionpower.com/tracker/issue-16966-members-download-manag/
//-----------------------------------------
foreach( ipsRegistry::$applications as $appDir => $data )
{
if( is_file( IPSLib::getAppDir( $appDir ) . "/extensions/coreExtensions.php") )
{
$classX = IPSLib::loadLibrary( IPSLib::getAppDir( $appDir ) . "/extensions/coreExtensions.php", $appDir . '_findIpAddress', $appDir );
if( class_exists( $classX . '_findIpAddress' ) )
{
$ipLookup = new $classX( ipsRegistry::instance() );
if( method_exists( $ipLookup, 'getTables' ) )
{
$tables = array_merge( $tables, $ipLookup->getTables() );
}
}
}
}
//-----------------------------------------
// Sort out thingie
//-----------------------------------------
if ( is_array( $id ) )
{
$id = IPSLib::cleanIntArray( $id );
$mids = ' IN (' . implode( ",", $id ) . ')';
}
else
{
$mids = ' = ' . intval($id);
}
//-----------------------------------------
// Got tables?
//-----------------------------------------
$_tables = explode( ',', $tables_to_check );
if( !is_array($_tables) OR !count($_tables) )
{
return array();
}
//-----------------------------------------
// Loop through them and grab the IPs
//-----------------------------------------
foreach( $tables as $tablename => $fields )
{
if( $tables_to_check == 'all' OR in_array( $tablename, $_tables ) )
{
$extra = '';
if( $fields[2] )
{
$extra = ', ' . $fields[2] . ' as date';
}
ipsRegistry::DB()->build( array( 'select' => $fields[1] . $extra, 'from' => $tablename, 'where' => $fields[0] . $mids ) );
ipsRegistry::DB()->execute();
while( $r = ipsRegistry::DB()->fetch() )
{
if( $r[ $fields[1] ] )
{
$r['date'] = $r['date'] > $ip_addresses[ $r[ $fields[1] ] ][1] ? $r['date'] : ( $ip_addresses[ $r[ $fields[1] ] ][1] ? $ip_addresses[ $r[ $fields[1] ] ][1] : 0 );
$ip_addresses[ $r[ $fields[1] ] ] = array( intval($ip_addresses[ $r[ $fields[1] ] ][0]) + 1, $r['date'] );
}
}
}
}
//-----------------------------------------
// Here are your IPs kind sir. kthxbai
//-----------------------------------------
return $ip_addresses;
}
/**
* Get / set member's ban info
*
* @param array Ban info (unit, timespan, date_end, date_start)
* @return mixed
* @since 2.0
*/
static public function processBanEntry( $bline )
{
if ( is_array( $bline ) )
{
// Some systems can only handle < 2038 @link http://community.invisionpower.com/tracker/issue-36840-suspending-user/
$endOf2037 = 2145830340;
$factor = $bline['unit'] == 'd' ? 86400 : 3600;
$date_end = time() + ( $bline['timespan'] * $factor );
if ( $date_end < 0 OR $date_end > $endOf2037 )
{
$date_end = $endOf2037;
}
return time() . ':' . $date_end . ':' . $bline['timespan'] . ':' . $bline['unit'];
}
else
{
$arr = array();
list( $arr['date_start'], $arr['date_end'], $arr['timespan'], $arr['unit'] ) = explode( ":", $bline );
return $arr;
}
}
/**
* Unpacks a member's cache.
* Left as a function for any other processing
*
* @deprecated Will be removed in 3.3
* @param string Serialized cache array
* @return array Unpacked array
*/
static public function unpackMemberCache( $cache_serialized_array="" )
{
return IPSLib::safeUnserialize( $cache_serialized_array );
}
/**
* Fetch an item from a member's cache
* @param MIXED (int or memberData ) $member
* @param MIXED (string or array of keys) $key
*/
static public function getFromMemberCache( $member, $key )
{
$return = array();
if ( is_integer( $member ) )
{
$member = self::load( $member, 'core' );
}
if ( IPSLib::isSerialized( $member['members_cache'] ) )
{
$cache = IPSLib::safeUnserialize( $member['members_cache'] );
$keys = ( is_array( $key ) ) ? $key : array( $key );
foreach( $keys as $k )
{
$return[ $k ] = isset( $cache[ $k ] ) ? $cache[ $k ] : null;
}
return ( is_array( $key ) ) ? $return : $return[ $key ];
}
else
{
return false;
}
}
/**
* Sets items to the cache
* @param MIXED (int or memberData ) $member
* @param array $store
*/
static public function setToMemberCache( $member, $store )
{
$cache = array();
if ( is_integer( $member ) )
{
$member = self::load( $member, 'core' );
}
elseif ( $member['member_id'] and !isset( $member['members_cache'] ) )
{
$member = self::load( $member['member_id'], 'core' );
}
/* Check */
if ( empty( $member['member_id'] ) or ! is_array( $store ) )
{
return false;
}
/* fetch current cache */
if ( IPSLib::isSerialized( $member['members_cache'] ) )
{
$cache = IPSLib::safeUnserialize( $member['members_cache'] );
}
/* loop and update */
foreach( $store as $k => $v )
{
$cache[ $k ] = $v;
}
/* Save */
ipsRegistry::DB()->update( 'members', array( 'members_cache' => serialize( $cache ) ), 'member_id='.$member['member_id'] );
/* Update local cache */
if ( self::$data['member_id'] == $member['member_id'] )
{
self::$data['_cache'] = $cache;
self::$data['members_cache'] = serialize( $cache );
}
}
/**
* Packs up member's cache
*
* Takes an existing array and updates member's DB row
* This will overwrite any existing entries by the same
* key and create new entries for non-existing rows
*
* @deprecated Will be removed in 3.3
* @param integer Member ID
* @param array New array
* @param array Current Array (optional)
* @return boolean
*/
static public function packMemberCache( $member_id, $new_cache_array, $current_cache_array='' )
{
//-----------------------------------------
// INIT
//-----------------------------------------
$member_id = intval( $member_id );
//-----------------------------------------
// Got a member ID?
//-----------------------------------------
if ( ! $member_id )
{
return FALSE;
}
//-----------------------------------------
// Got anything to update?
//-----------------------------------------
if ( ! is_array( $new_cache_array ) )
{
return FALSE;
}
//-----------------------------------------
// Got a current cache?
//-----------------------------------------
if ( ! is_array( $current_cache_array ) )
{
$member = ipsRegistry::DB()->buildAndFetch( array( 'select' => "members_cache", 'from' => 'members', 'where' => 'member_id='.$member_id ) );
$member['members_cache'] = $member['members_cache'] ? $member['members_cache'] : array();
$current_cache_array = IPSLib::safeUnserialize( $member['members_cache'] );
}
//-----------------------------------------
// Overwrite...
//-----------------------------------------
foreach( $new_cache_array as $k => $v )
{
$current_cache_array[ $k ] = $v;
}
//-----------------------------------------
// Update...
//-----------------------------------------
ipsRegistry::DB()->update( 'members', array( 'members_cache' => serialize( $current_cache_array ) ), 'member_id='.$member_id );
//-----------------------------------------
// Set member array right...
//-----------------------------------------
if ( self::$data['member_id'] == $member_id )
{
self::$data['_cache'] = $current_cache_array;
self::$data['members_cache'] = serialize( $current_cache_array );
}
}
/**
* Check forum permissions
*
* @param string Permission type
* @param int Forum ID to check against
* @return boolean
* @since 2.0
*/
static public function checkPermissions( $perm="", $forumID=0 )
{
/* Bit of a hack here, ugly */
if ( ipsRegistry::isClassLoaded('class_forums') !== TRUE )
{
$classToLoad = IPSLib::loadLibrary( IPSLib::getAppDir( 'forums' ) . "/sources/classes/forums/class_forums.php", 'class_forums' );
ipsRegistry::setClass( 'class_forums', new $classToLoad( ipsRegistry::instance() ) );
ipsRegistry::getClass('class_forums')->strip_invisible = 1;
ipsRegistry::getClass('class_forums')->forumsInit();
}
return ipsRegistry::getClass( 'permissions' )->check( $perm, ipsRegistry::getClass('class_forums')->forum_by_id[ $forumID ] );
}
/**
* Set up defaults for a guest user
*
* @param string Guest name
* @return array Guest record
* @since 2.0
*/
static public function setUpGuest( $name="" )
{
$cache = ipsRegistry::cache()->getCache('group_cache');
$name = $name ? $name : ( ipsRegistry::isClassLoaded('class_localization') ? ipsRegistry::getClass('class_localization')->words['global_guestname'] : 'Guest' );
$array = array( 'name' => $name,
'members_display_name' => $name,
'_members_display_name' => $name,
'members_seo_name' => IPSText::makeSeoTitle( $name ),
'member_id' => 0,
'password' => '',
'email' => '',
'title' => '',
'posts' => 0,
'member_group_id' => ipsRegistry::$settings['guest_group'],
'view_sigs' => ipsRegistry::$settings['guests_sig'],
'member_forum_markers' => array(),
'member_posts' => '',
'g_dohtml' => 0,
'g_title' => $cache[ ipsRegistry::$settings['guest_group'] ]['g_title'],
'member_rank_img' => '',
'member_joined' => '',
'member_number' => '',
'members_auto_dst' => 0,
'has_blog' => 0,
'has_gallery' => 0,
'is_mod' => 0,
'last_visit' => time(),
'login_anonymous' => '',
'mgroup_others' => '',
'org_perm_id' => '',
'auto_track' => 0,
'ignored_users' => NULL,
'_cache' => array( 'friends' => array() ),
'_group_formatted' => self::makeNameFormatted( $cache[ ipsRegistry::$settings['guest_group'] ]['g_title'], ipsRegistry::$settings['guest_group'] ),
);
/* Add in the group image, if we have one */
$member['member_rank_img'] = '';
$member['member_rank_img_i'] = '';
if ( $cache[ $array['member_group_id'] ]['g_icon'] )
{
$_img = $cache[ $array['member_group_id'] ]['g_icon'];
if ( substr( $_img, 0, 4 ) != 'http' AND strpos( $_img, '{style_images_url}' ) === false )
{
$_img = ipsRegistry::$settings['_original_base_url'] . '/' . ltrim( $_img, '/' );
}
$array['member_rank_img_i'] = 'img';
$array['member_rank_img'] = $_img;
}
return is_array( $cache[ ipsRegistry::$settings['guest_group'] ] ) ? array_merge( $array, $cache[ ipsRegistry::$settings['guest_group'] ] ) : $array;
}
/**
* Parse a member's profile photo
*
* @param mixed Either array of member data, or member ID to self load
* @param string Size to return tag (thumb/full/mini/small) if no size, just returns array of parsed data
* @param bool Add random string so no cache is used
* @return array Member's photo details
*/
static public function buildProfilePhoto( $member, $size=null, $noCache=false )
{
//-----------------------------------------
// Load the member?
//-----------------------------------------
if ( ! is_array( $member ) AND ( $member == intval( $member ) ) AND $member > 0 )
{
$member = self::load( $member, 'extendedProfile' );
}
else if ( $member == 0 )
{
$member = array();
}
/* No photo? Per this bug report, we're going to force showing profile photos, rather than hide them if you can't view profiles
@link http://community.invisionpower.com/tracker/issue-30986-board-index-unregistered-guests-can-not-view-avatars-option-removed-from-acp */
if ( empty( $member['pp_main_photo'] ) or $member['pp_photo_type'] == 'gravatar' /*OR ! ipsRegistry::member()->getProperty('g_mem_info')*/ )
{
return self::buildNoPhoto( $member, $size, $noCache );
}
/* Add RND bit to prevent CDN caching */
$member['pp_thumb_photo'] = ( strstr( $member['pp_thumb_photo'], '?' ) ) ? $member['pp_thumb_photo'] : $member['pp_thumb_photo'] . '?_r=' . intval( $member['pp_profile_update'] );
$member['pp_main_photo'] = ( strstr( $member['pp_main_photo'] , '?' ) ) ? $member['pp_main_photo'] : $member['pp_main_photo'] . '?_r=' . intval( $member['pp_profile_update'] );
/* @link http://community.invisionpower.com/tracker/issue-32991-profile-photo-conversion */
$member['pp_main_photo'] = str_replace( 'upload:', '', $member['pp_main_photo'] );
$member['pp_thumb_photo'] = str_replace( 'upload:', '', $member['pp_thumb_photo'] );
/* Main photo */
$member['pp_main_photo'] = ( ! ( strstr( $member['pp_main_photo'], 'http://' ) || strstr( $member['pp_main_photo'], 'https://' ) ) ) ? ipsRegistry::$settings['upload_url'] . '/' . $member['pp_main_photo'] : $member['pp_main_photo'];
$member['_has_photo'] = 1;
/* Thumb */
$member['pp_thumb_photo'] = ( ! ( strstr( $member['pp_thumb_photo'], 'http://' ) || strstr( $member['pp_thumb_photo'], 'https://' ) ) ) ? ipsRegistry::$settings['upload_url'] . '/' . $member['pp_thumb_photo'] : $member['pp_thumb_photo'];
/* Small */
$_data = IPSLib::scaleImage( array( 'max_height' => 50, 'max_width' => 50, 'cur_width' => $member['pp_thumb_width'], 'cur_height' => $member['pp_thumb_height'] ) );
$member['pp_small_photo'] = $member['pp_thumb_photo'];
$member['pp_small_width'] = $_data['img_width'];
$member['pp_small_height'] = $_data['img_height'];
/* Mini */
$_data = IPSLib::scaleImage( array( 'max_height' => 25, 'max_width' => 25, 'cur_width' => $member['pp_thumb_width'], 'cur_height' => $member['pp_thumb_height'] ) );
$member['pp_mini_photo'] = $member['pp_thumb_photo'];
$member['pp_mini_width'] = $_data['img_width'];
$member['pp_mini_height'] = $_data['img_height'];
if ( $size === null )
{
return $member;
}
else
{
return self::buildPhotoTag( $member, $size, $noCache );
}
}
/**
* Returns a 'no photo' tag or data
*
* @param array Member Data
* @param string Optional: Full / thumb / mini / small - will return complete tag
* @param bool Add random string so no cache is used
* @param bool If true, ipsUserPhoto class will not be added
* @return string
*/
static public function buildNoPhoto( $member, $size=null, $noCache=false, $noBorder=false )
{
/* Load member */
if ( ! is_array( $member ) AND ( $member == intval( $member ) ) AND $member > 0 )
{
$member = self::load( $member, 'extendedProfile' );
}
else if ( $member == 0 )
{
$member = array();
}
//-----------------------------------------
// Gravatar
//-----------------------------------------
if ( ipsRegistry::$settings['allow_gravatars'] and ! $member['bw_disable_gravatar'] )
{
$gravatarUrl = ( ipsRegistry::getClass('output')->isHTTPS ) ? 'https://secure.gravatar.com/' : 'http://www.gravatar.com/';
$default = urlencode( ipsRegistry::$settings['img_url'] . '/profile/default_large.png' );
$avHash = md5( strtolower( trim( $member['pp_gravatar'] ? $member['pp_gravatar'] : $member['email'] ) ) );
/* Main photo */
$member['pp_main_photo'] = "{$gravatarUrl}avatar/{$avHash}?s=125&d={$default}";
$member['pp_main_width'] = 125;
$member['pp_main_height'] = 125;
$member['_has_photo'] = 0;
/* Thumb */
$member['pp_thumb_photo'] = "{$gravatarUrl}avatar/{$avHash}?s=100&d={$default}";
$member['pp_thumb_width'] = 100;
$member['pp_thumb_height'] = 100;
}
//-----------------------------------------
// Normal
//-----------------------------------------
else
{
/* Main photo */
$member['pp_main_photo'] = ipsRegistry::$settings['img_url'] . '/profile/default_large.png';
$member['pp_main_width'] = 125;
$member['pp_main_height'] = 125;
$member['_has_photo'] = 0;
/* Thumb */
$member['pp_thumb_photo'] = ipsRegistry::$settings['img_url'] . '/profile/default_large.png';
$member['pp_thumb_width'] = 100;
$member['pp_thumb_height'] = 100;
}
/* Small */
$_data = IPSLib::scaleImage( array( 'max_height' => 50, 'max_width' => 50, 'cur_width' => $member['pp_thumb_width'], 'cur_height' => $member['pp_thumb_height'] ) );
$member['pp_small_photo'] = $member['pp_thumb_photo'];
$member['pp_small_width'] = $_data['img_width'];
$member['pp_small_height'] = $_data['img_height'];
/* Mini */
$_data = IPSLib::scaleImage( array( 'max_height' => 25, 'max_width' => 25, 'cur_width' => $member['pp_thumb_width'], 'cur_height' => $member['pp_thumb_height'] ) );
$member['pp_mini_photo'] = $member['pp_thumb_photo'];
$member['pp_mini_width'] = $_data['img_width'];
$member['pp_mini_height'] = $_data['img_height'];
if ( $size === null )
{
return $member;
}
else
{
return self::buildPhotoTag( $member, $size, $noCache, $noBorder );
}
}
/**
* Tagify a member's profile photo from data
*
* @param array Processed member data that has photo info
* @param string Size (full/thumb/mini/small)
* @param bool Add random string so no cache is used
* @param bool If true, ipsUserPhoto class will not be added
* @return string
*/
static public function buildPhotoTag( $member, $size='thumb', $noCache=false, $noBorder=false )
{
$rnd = ( $noCache === true ) ? "?_r=" . md5( uniqid() ) : '';
$cls = '';
switch( $size )
{
default:
case 'thumb':
$src = $member['pp_thumb_photo'];
$w = $member['pp_thumb_width'];
$h = $member['pp_thumb_height'];
break;
case 'main':
case 'full':
$src = $member['pp_main_photo'];
$w = $member['pp_main_width'];
$h = $member['pp_main_height'];
break;
case 'small':
$_data = IPSLib::scaleImage( array( 'max_height' => 50, 'max_width' => 50, 'cur_width' => $member['pp_thumb_width'], 'cur_height' => $member['pp_thumb_height'] ) );
$src = $member['pp_thumb_photo'];
$w = $_data['img_width'];
$h = $_data['img_height'];
$cls = 'ipsUserPhoto_medium';
break;
case 'mini':
$_data = IPSLib::scaleImage( array( 'max_height' => 25, 'max_width' => 25, 'cur_width' => $member['pp_thumb_width'], 'cur_height' => $member['pp_thumb_height'] ) );
$src = $member['pp_thumb_photo'];
$w = $_data['img_width'];
$h = $_data['img_height'];
$cls = 'ipsUserPhoto_mini';
break;
case 'inset':
$_data = IPSLib::scaleImage( array( 'max_height' => 25, 'max_width' => 25, 'cur_width' => $member['pp_thumb_width'], 'cur_height' => $member['pp_thumb_height'] ) );
$src = $member['pp_thumb_photo'];
$w = $_data['img_width'];
$h = $_data['img_height'];
$cls = 'ipsUserPhoto_inset';
break;
case 'icon':
$_data = IPSLib::scaleImage( array( 'max_height' => 16, 'max_width' => 16, 'cur_width' => $member['pp_thumb_width'], 'cur_height' => $member['pp_thumb_height'] ) );
$src = $member['pp_thumb_photo'];
$w = $_data['img_width'];
$h = $_data['img_height'];
$cls = 'ipsUserPhoto_icon';
break;
}
$classes = $noBorder ? '' : "ipsUserPhoto {$cls}";
return "<img src='" . $src . $rnd . "' width='" . $w . "' height='" . $h . "' class='" . $classes . "' />";
}
/**
* Parse a member for display
*
* @param mixed Either array of member data, or member ID to self load
* @param array Array of flags to parse: 'signature', 'customFields', 'warn'
* @return array Parsed member data
*/
static public function buildDisplayData( $member, $_parseFlags=array() )
{
$_NOW = IPSDebug::getMemoryDebugFlag();
/* test to see if member_title has been passed */
if ( isset( $member['member_title'] ) )
{
$member['title'] = $member['member_title'];
}
//-----------------------------------------
// Figure out parse flags
//-----------------------------------------
$parseFlags = array( 'signature' => isset( $_parseFlags['signature'] ) ? $_parseFlags['signature'] : 0,
'customFields' => isset( $_parseFlags['customFields'] ) ? $_parseFlags['customFields'] : 0,
'reputation' => isset( $_parseFlags['reputation'] ) ? $_parseFlags['reputation'] : 1,
'warn' => isset( $_parseFlags['warn'] ) ? $_parseFlags['warn'] : 1,
'cfSkinGroup' => isset( $_parseFlags['cfSkinGroup'] ) ? $_parseFlags['cfSkinGroup'] : '',
'cfGetGroupData' => isset( $_parseFlags['cfGetGroupData'] ) ? $_parseFlags['cfGetGroupData'] : '',
'cfLocation' => isset( $_parseFlags['cfLocation'] ) ? $_parseFlags['cfLocation'] : '',
'checkFormat' => isset( $_parseFlags['checkFormat'] ) ? $_parseFlags['checkFormat'] : 0,
'photoTagSize' => isset( $_parseFlags['photoTagSize'] ) ? $_parseFlags['photoTagSize'] : false,
'spamStatus' => isset( $_parseFlags['spamStatus'] ) ? $_parseFlags['spamStatus'] : 0 );
if ( isset( $_parseFlags['__all__'] ) )
{
foreach( $parseFlags as $k => $v )
{
if( in_array( $k, array( 'cfSkinGroup', 'cfGetGroupData', 'photoTagSize' ) ) )
{
continue;
}
$parseFlags[ $k ] = 1;
}
$parseFlags['spamStatus'] = !empty( $parseFlags['spamStatus'] ) ? 1 : 0;
}
//-----------------------------------------
// Load the member?
//-----------------------------------------
if ( ! is_array( $member ) AND ( $member == intval( $member ) AND $member > 0 ) )
{
$member = self::load( $member, 'all' );
}
//-----------------------------------------
// Caching
//-----------------------------------------
static $buildMembers = array();
$_key = $member['member_id'];
$_arr = serialize( $member );
foreach( $parseFlags as $_flag => $_value )
{
$_key .= $_flag . $_value;
}
$_key = md5($_key.$_arr);
if( isset( $buildMembers[ $_key ] ) )
{
IPSDebug::setMemoryDebugFlag( "IPSMember::buildDisplayData: ".$member['member_id']. " - CACHED", $_NOW );
return $buildMembers[ $_key ];
}
//-----------------------------------------
// Basics
//-----------------------------------------
if ( ! $member['member_group_id'] )
{
$member['member_group_id'] = ipsRegistry::$settings['guest_group'];
}
/* Unpack bitwise if required */
if ( ! isset( $member['bw_is_spammer'] ) )
{
$member = self::buildBitWiseOptions( $member );
}
//-----------------------------------------
// INIT
//-----------------------------------------
$rank_cache = ipsRegistry::cache()->getCache( 'ranks' );
$group_cache = ipsRegistry::cache()->getCache( 'group_cache' );
$group_name = self::makeNameFormatted( $group_cache[ $member['member_group_id'] ]['g_title'], $member['member_group_id'] );
$pips = 0;
$topic_id = intval( isset( ipsRegistry::$request[ 't' ] ) ? ipsRegistry::$request[ 't' ] : 0 );
$forum_id = intval( isset( ipsRegistry::$request[ 'f' ] ) ? ipsRegistry::$request[ 'f' ] : 0 );
//-----------------------------------------
// SEO Name
//-----------------------------------------
$member['members_seo_name'] = self::fetchSeoName( $member );
$member['_group_formatted'] = $group_name;
//-----------------------------------------
// Ranks
//-----------------------------------------
if ( is_array( $rank_cache ) AND count( $rank_cache ) )
{
foreach( $rank_cache as $k => $v)
{
if ( $member['posts'] >= $v['POSTS'] )
{
if ( empty( $member['title'] ) )
{
$member['title'] = $v['TITLE'];
}
$pips = $v['PIPS'];
break;
}
}
}
//-----------------------------------------
// Group image
//-----------------------------------------
$member['member_rank_img'] = '';
$member['member_rank_img_i'] = '';
if ( $group_cache[ $member['member_group_id'] ]['g_icon'] )
{
$_img = $group_cache[ $member['member_group_id'] ]['g_icon'];
if ( substr( $_img, 0, 4 ) != 'http' AND strpos( $_img, '{style_images_url}' ) === false )
{
$_img = ipsRegistry::$settings['_original_base_url'] . '/' . ltrim( $_img, '/' );
}
$member['member_rank_img_i'] = 'img';
$member['member_rank_img'] = $_img;
}
else if ( $pips AND $member['member_id'] ) /* Added member ID check per @link http://community.invisionpower.com/tracker/issue-31761-guest-in-messanger-have-pips/ */
{
if ( is_numeric( $pips ) )
{
for ($i = 1; $i <= $pips; ++$i)
{
$member['member_rank_img_i'] = 'pips';
$member['member_rank_img'] = $member['member_rank_img'] . ipsRegistry::getClass('output')->getReplacement('pip_pip');
}
}
else
{
$member['member_rank_img_i'] = 'img';
$member['member_rank_img'] = ipsRegistry::$settings['public_dir'] . 'style_extra/team_icons/' . $pips;
}
}
//-----------------------------------------
// Moderator data
//-----------------------------------------
if( ( $parseFlags['spamStatus'] OR $parseFlags['warn'] ) AND $member['member_id'] )
{
/* Possible forums class isn't init at this point */
if ( ! ipsRegistry::isClassLoaded('class_forums' ) )
{
try
{
$viewingMember = IPSMember::setUpModerator( ipsRegistry::member()->fetchMemberData() );
ipsRegistry::member()->setProperty('forumsModeratorData', $viewingMember['forumsModeratorData'] );
}
catch( Exception $error )
{
IPS_exception_error( $error );
}
}
$moderator = ipsRegistry::member()->getProperty('forumsModeratorData');
}
$forum_id = isset(ipsRegistry::$request['f']) ? intval( ipsRegistry::$request['f'] ) : 0;
//-----------------------------------------
// Spammer status
//-----------------------------------------
if ( $parseFlags['spamStatus'] AND $member['member_id'] AND ipsRegistry::member()->getProperty('member_id') )
{
/* Defaults */
$member['spamStatus'] = NULL;
$member['spamImage'] = NULL;
if ( !empty( $moderator[ $forum_id ]['bw_flag_spammers'] ) OR ipsRegistry::member()->getProperty('g_is_supmod') )
{
if ( ! ipsRegistry::$settings['warn_on'] OR ! IPSMember::isInGroup( $member, explode( ',', ipsRegistry::$settings['warn_protected'] ) ) )
{
if ( $member['bw_is_spammer'] )
{
$member['spamStatus'] = TRUE;
}
else
{
$member['spamStatus'] = FALSE;
}
}
}
}
//-----------------------------------------
// Warny porny?
//-----------------------------------------
$member['show_warn'] = FALSE;
if ( $parseFlags['warn'] AND $member['member_id'] )
{
if ( ipsRegistry::$settings['warn_on'] and ! IPSMember::isInGroup( $member, explode( ',', ipsRegistry::$settings['warn_protected'] ) ) )
{
/* Warnings */
if ( !empty($moderator[ $forum_id ]['allow_warn']) OR ipsRegistry::member()->getProperty('g_is_supmod') OR ( ipsRegistry::$settings['warn_show_own'] and ipsRegistry::member()->getProperty('member_id') == $member['member_id'] ) )
{
$member['show_warn'] = TRUE;
}
else if ( is_array( $moderator ) && count( $moderator ) && !$forum_id )
{
foreach( $moderator as $forum )
{
if( $forum['allow_warn'] )
{
$member['show_warn'] = TRUE;
break;
}
}
}
}
}
//-----------------------------------------
// Profile fields stuff
//-----------------------------------------
$member['custom_fields'] = "";
if( $parseFlags['customFields'] == 1 AND $member['member_id'] )
{
if ( isset( self::$_parsedCustomFields[ $member['member_id'] ] ) )
{
$member['custom_fields'] = self::$_parsedCustomFields[ $member['member_id'] ];
if ( $parseFlags['cfGetGroupData'] AND isset( self::$_parsedCustomGroups[ $member['member_id'] ] ) AND is_array( self::$_parsedCustomGroups[ $member['member_id'] ] ) )
{
$member['custom_field_groups'] = self::$_parsedCustomGroups[ $member['member_id'] ];
}
else if( $parseFlags['cfGetGroupData'] )
{
$member['custom_field_groups'] = self::$custom_fields_class->fetchGroupTitles();
self::$_parsedCustomGroups[ $member['member_id'] ] = $member['custom_field_groups'];
}
}
else
{
if ( !is_object( self::$custom_fields_class ) )
{
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/customfields/profileFields.php', 'customProfileFields' );
self::$custom_fields_class = new $classToLoad();
}
if ( self::$custom_fields_class )
{
self::$custom_fields_class->member_data = $member;
self::$custom_fields_class->skinGroup = $parseFlags['cfSkinGroup'];
self::$custom_fields_class->initData();
self::$custom_fields_class->parseToView( $parseFlags['checkFormat'], $parseFlags['cfLocation'] );
$member['custom_fields'] = self::$custom_fields_class->out_fields;
self::$_parsedCustomFields[ $member['member_id'] ] = $member['custom_fields'];
if ( $parseFlags['cfGetGroupData'] )
{
$member['custom_field_groups'] = self::$custom_fields_class->fetchGroupTitles();
self::$_parsedCustomGroups[ $member['member_id'] ] = $member['custom_field_groups'];
}
}
}
}
//-----------------------------------------
// Profile photo
//-----------------------------------------
$member = self::buildProfilePhoto( $member );
if ( ! empty( $parseFlags['photoTagSize'] ) )
{
$parseFlags['photoTagSize'] = ( is_array( $parseFlags['photoTagSize'] ) ) ? $parseFlags['photoTagSize'] : array( $parseFlags['photoTagSize'] );
foreach( $parseFlags['photoTagSize'] as $size )
{
$member['photoTag' . ucfirst( $size ) ] = self::buildPhotoTag( $member, $size );
}
}
//-----------------------------------------
// Signature bbcode
//-----------------------------------------
if ( !empty( $member['signature'] ) AND $parseFlags['signature'] )
{
if( isset(self::$_parsedSignatures[ $member['member_id'] ]) )
{
$member['signature'] = self::$_parsedSignatures[ $member['member_id'] ];
}
else
{
if ( $member['cache_content'] )
{
$member['signature'] = '<!--signature-cached-' . gmdate( 'r', $member['cache_updated'] ) . '-->' . $member['cache_content'];
}
else
{
/* Grab the parser file */
if ( self::$_sigParser === null )
{
/* Load parser */
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/text/parser.php', 'classes_text_parser' );
self::$_sigParser = new $classToLoad();
}
/* set up parser */
self::$_sigParser->set( array( 'memberData' => $member,
'parseBBCode' => 1,
'parseHtml' => ( $group_cache[ $member['member_group_id'] ]['g_dohtml'] && $member['bw_html_sig'] ),
'parseEmoticons' => 1,
'parseArea' => 'signatures' ) );
$member['signature'] = self::$_sigParser->display( $member['signature'] );
IPSContentCache::update( $member['member_id'], 'sig', $member['signature'] );
}
self::$_parsedSignatures[ $member['member_id'] ] = $member['signature'];
}
}
//-----------------------------------------
// If current session, reset last_activity
//-----------------------------------------
if( ! empty( $member['running_time'] ) )
{
$member['last_activity'] = $member['running_time'] > $member['last_activity'] ? $member['running_time'] : $member['last_activity'];
}
//-----------------------------------------
// Online?
//-----------------------------------------
$time_limit = time() - ( ipsRegistry::$settings['au_cutoff'] * 60 );
$member['_online'] = 0;
$bypass_anon = ipsRegistry::member()->getProperty('g_access_cp') ? 1 : 0;
list( $be_anon, $loggedin ) = explode( '&', empty($member['login_anonymous']) ? '0&0' : $member['login_anonymous'] );
/* Is not anon but the group might be forced to? */
if ( empty($be_anon) && self::isLoggedInAnon($member) )
{
$be_anon = 1;
}
/* Finally set the online flag */
if ( ( ( $member['last_visit'] > $time_limit OR $member['last_activity'] > $time_limit ) AND ( $be_anon != 1 OR $bypass_anon == 1 ) ) AND $loggedin == 1 )
{
$member['_online'] = 1;
}
//-----------------------------------------
// Last Active
//-----------------------------------------
$member['_last_active'] = ipsRegistry::getClass('class_localization')->getDate( $member['last_activity'], 'SHORT' );
// Member last logged in anonymous ?
if( $be_anon == 1 && ! ipsRegistry::member()->getProperty('g_access_cp') )
{
$member['_last_active'] = ipsRegistry::getClass('class_localization')->words['private'];
}
//-----------------------------------------
// Rating
//-----------------------------------------
$member['_pp_rating_real'] = intval( $member['pp_rating_real'] );
//-----------------------------------------
// Display name formatted
//-----------------------------------------
$member['members_display_name_formatted'] = self::makeNameFormatted( $member['members_display_name'], $member['member_id'] ? $member['member_group_id'] : ipsRegistry::$settings['guest_group'] );
//-----------------------------------------
// Long display names
//-----------------------------------------
$member['members_display_name_short'] = IPSText::truncate( $member['members_display_name'], 16 );
//-----------------------------------------
// Reputation
//-----------------------------------------
$member['pp_reputation_points'] = $member['pp_reputation_points'] ? $member['pp_reputation_points'] : 0;
if( $parseFlags['reputation'] AND $member['member_id'] )
{
if( ! ipsRegistry::isClassLoaded( 'repCache' ) )
{
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/class_reputation_cache.php', 'classReputationCache' );
ipsRegistry::setClass( 'repCache', new $classToLoad() );
}
$member['author_reputation'] = ipsRegistry::getClass( 'repCache' )->getReputation( $member['pp_reputation_points'] );
}
//-----------------------------------------
// Other stuff not worthy of individual comments
//-----------------------------------------
$member['members_profile_views'] = isset($member['members_profile_views']) ? $member['members_profile_views'] : 0;
/* BG customization */
if ( $member['pp_customization'] AND !empty($member['gbw_allow_customization']) AND ! $member['bw_disable_customization'] )
{
$member['customization'] = IPSLib::safeUnserialize( $member['pp_customization'] );
if ( is_array( $member['customization'] ) )
{
/* Figure out BG URL */
if ( $member['customization']['type'] == 'url' AND $member['customization']['bg_url'] AND $member['gbw_allow_url_bgimage'] )
{
$member['customization']['_bgUrl'] = $member['customization']['bg_url'];
}
else if ( $member['customization']['type'] == 'upload' AND $member['customization']['bg_url'] AND $member['gbw_allow_upload_bgimage'] )
{
$member['customization']['_bgUrl'] = ipsRegistry::$settings['upload_url'] . '/' . $member['customization']['bg_url'];
}
else if ( $member['customization']['bg_color'] )
{
$member['customization']['type'] = 'bgColor';
}
}
}
/* Title is ambigious */
$member['member_title'] = $member['title'];
IPSDebug::setMemoryDebugFlag( "IPSMember::buildDisplayData: ".$member['member_id']. " - Completed", $_NOW );
$buildMembers[ $_key ] = $member;
return $member;
}
/**
* Build member's bitwise field
*
* @param mixed Either an array of member data or a member ID
* @return array
*/
static public function buildBitWiseOptions( $member )
{
//-----------------------------------------
// Load the member?
//-----------------------------------------
if ( ! is_array( $member ) AND ( $member == intval( $member ) ) )
{
$member = self::load( $member, 'core,extendedProfile' );
}
/* Unpack bitwise fields */
$_tmp = IPSBWOptions::thaw( isset($member['members_bitoptions']) ? $member['members_bitoptions'] : 0, 'members', 'global' );
if ( count( $_tmp ) )
{
foreach( $_tmp as $k => $v )
{
/* Trigger notice if we have DB field */
if ( isset( $member[ $k ] ) )
{
trigger_error( "Thawing bitwise options for MEMBERS: Bitwise field '$k' has overwritten DB field '$k'", E_USER_WARNING );
}
$member[ $k ] = $v;
}
}
return $member;
}
/**
* Returns user's avatar [DEPRICATED]
* @todo Remove in 3.3 this is depricated
*
* @param mixed Either an array of member data or a member ID
* @param bool Whether to avoid caching
* @param bool Whether to show avatar even if view_avs is off for member
* @return string HTML
* @since 2.0
*
* @deprecated
*/
static public function buildAvatar( $member, $no_cache=0, $overRide=0 )
{
return self::buildProfilePhoto( $member, 'thumb' );
}
/**
* Checks for a DB row that matches $email
*
* @param string Email address
* @return boolean Record exists
*/
static public function checkByEmail( $email )
{
$test = self::load( $email, '', 'email' );
if ( $test['member_id'] )
{
return true;
}
else
{
return false;
}
}
/**
* Updates member's DB row password
*
* @param string Key: either member_id or email
* @param string MD5-once hash of new password
* @return boolean Update successful
*/
static public function updatePassword( $member_key, $new_md5_pass )
{
if ( ! $member_key or ! $new_md5_pass )
{
return false;
}
/* Load member */
$member = self::load( $member_key );
$new_pass = md5( md5( $member['members_pass_salt'] ) . $new_md5_pass );
self::save( $member_key, array( 'core' => array( 'members_pass_hash' => $new_pass ) ) );
return true;
}
/**
* Check supplied password with database
*
* @param string Key: either member_id or email
* @param string MD5 of entered password
* @return boolean Password is correct
*/
static public function authenticateMember( $member_key, $md5_once_password )
{
/* Load member */
$member = self::load( $member_key );
if ( ! $member['member_id'] )
{
return FALSE;
}
if ( $member['members_pass_hash'] == self::generateCompiledPasshash( $member['members_pass_salt'], $md5_once_password ) )
{
return true;
}
else
{
return false;
}
}
/**
* Generates a compiled passhash.
* Returns a new MD5 hash of the supplied salt and MD5 hash of the password
*
* @param string User's salt (5 random chars)
* @param string User's MD5 hash of their password
* @return string MD5 hash of compiled salted password
*/
static public function generateCompiledPasshash( $salt, $md5_once_password )
{
return md5( md5( $salt ) . $md5_once_password );
}
/**
* Generates a password salt.
* Returns n length string of any char except backslash
*
* @param integer Length of desired salt, 5 by default
* @return string n character random string
*/
static public function generatePasswordSalt($len=5)
{
$salt = '';
for ( $i = 0; $i < $len; $i++ )
{
$num = mt_rand(33, 126);
if ( $num == '92' )
{
$num = 93;
}
$salt .= chr( $num );
}
return $salt;
}
/**
* Generates a log in key
*
* @param integer Length of desired random chars to MD5
* @return string MD5 hash of random characters
*/
static public function generateAutoLoginKey( $len=60 )
{
$pass = self::generatePasswordSalt( $len );
return md5($pass);
}
/**
* Check to see if a member is inactive (member_banned, bw_is_spammer)
* @param mixed Either INT (member_id) OR Array of member data [MUST at least include member_group_id and mgroup_others]
* @return boolean TRUE (is inactive) - FALSE (not in inactive)
*/
static public function isInactive( $member )
{
$memberData = ( is_array( $member ) ) ? $member : self::load( $member, 'core' );
return ( empty( $member['member_banned'] ) && empty( $member['bw_is_spammer'] ) && empty( $member['inactive'] ) ) ? false : true;
}
/**
* Check to see if a member is in a group or not
*
* @param mixed Either INT (member_id) OR Array of member data [MUST at least include member_group_id and mgroup_others]
* @param mixed Either INT (group ID) or array of group IDs
* @param boolean TRUE (default, check secondary groups also), FALSE (check primary only)
* @return boolean TRUE (is in group) - FALSE (not in group)
*/
static public function isInGroup( $member, $group, $checkSecondary=true )
{
$memberData = ( is_array( $member ) ) ? $member : self::load( $member, 'core' );
$group = ( is_array( $group ) ) ? $group : array( $group );
$others = empty($memberData['mgroup_others']) ? array() : explode( ',', $memberData['mgroup_others'] );
if ( ! $memberData['member_group_id'] OR ! count( $group ) )
{
return FALSE;
}
/* Loop */
foreach( $group as $gid )
{
if ( $gid )
{
if ( $gid == $memberData['member_group_id'] )
{
return true;
}
if ( $checkSecondary AND count( $others ) AND in_array( $gid, $others ) )
{
return true;
}
}
}
return false;
}
/**
* Check to see if a member is banned (or not)
*
* @param string Type of ban check (ip/ipAddress, name, email)
* @param string String to check
* @return boolean TRUE (banned) - FALSE (not banned)
*/
static public function isBanned( $type, $string )
{
/* Try and be helpful */
switch ( strtolower( $type ) )
{
case 'ip':
$type = 'ipAddress';
break;
case 'emailaddress':
$type = 'email';
break;
case 'username':
case 'displayname':
$type = 'name';
break;
}
if ( $type == 'ipAddress' )
{
$banCache = ipsRegistry::cache()->getCache('banfilters');
}
else
{
if ( ! is_array( self::$_banFiltersCache ) )
{
self::$_banFiltersCache = array();
/* Load Ban Filters */
ipsRegistry::DB()->build( array( 'select' => '*', 'from' => 'banfilters' ) );
ipsRegistry::DB()->execute();
while( $r = ipsRegistry::DB()->fetch() )
{
self::$_banFiltersCache[ $r['ban_type'] ][] = $r['ban_content'];
}
}
$banCache = self::$_banFiltersCache[ $type ];
}
if ( is_array( $banCache ) and count( $banCache ) )
{
foreach( $banCache as $entry )
{
$ip = str_replace( '*', '.*', preg_quote( trim($entry), "/") );
if ( $ip AND preg_match( "/^$ip$/", $string ) )
{
return TRUE;
}
}
}
return FALSE;
}
/**
* Check to see if a member is ignorable or not
*
* @param int Member's primary group ID
* @param string Comma delisted list of 'other' member groups
* @param string Type: 'post' or 'pm'
* @return boolean True (member is ignorable) or False (member can not be ignored)
*/
static public function isIgnorable( $member_group_id, $mgroup_others, $type='post' )
{
if( ! isset( ipsRegistry::$settings['_unblockableArray'] ) OR ! is_array( ipsRegistry::$settings['_unblockableArray'] ) )
{
ipsRegistry::$settings['_unblockableArray'] = ipsRegistry::$settings['cannot_ignore_groups'] ? explode( ",", IPSText::cleanPermString( ipsRegistry::$settings['cannot_ignore_groups'] ) ) : array();
}
$myGroups = array( $member_group_id );
if ( $mgroup_others )
{
$myGroups = array_merge( $myGroups, explode( ",", IPSText::cleanPermString( $mgroup_others ) ) );
}
/* Check PMs first */
if ( $type == 'pm' )
{
$unblockable = explode( ",", ipsRegistry::$settings['unblockable_pm_groups'] );
/* Override with groups */
if ( is_array( $unblockable ) AND count( $unblockable ) )
{
if ( in_array( $member_group_id, $unblockable ) )
{
return FALSE;
}
}
}
foreach( $myGroups as $member_group )
{
if ( in_array( $member_group, ipsRegistry::$settings['_unblockableArray'] ) )
{
return FALSE;
}
}
return TRUE;
}
/**
* Returns whether current member is logged in anonymously.
*
* @param array $memberData Member data
* @param integer $groupId Override group ID from member data
* @return @e integer 1 for anonymous or 0 otherwise
*/
static public function isLoggedInAnon( $memberData, $groupId=0 )
{
/**
* Falls back to 'not anonymous' if the anoymous login
* is disabled or the member field is empty
*/
$isAnon = 0;
/* 1: Check if the group is forced as anonymous and override the global setting */
$groupId = empty($groupId) ? $memberData['member_group_id'] : $groupId;
$groupCache = ipsRegistry::cache()->getCache('group_cache');
if ( ! empty($groupCache[ $groupId ]['g_hide_online_list']) )
{
$isAnon = 1;
}
/* 2: Anonymous login is enabled and the member field is not empty? Not anonymous then.. maybe.. */
elseif ( empty(ipsRegistry::$settings['disable_anonymous']) && ! empty($memberData['login_anonymous']) )
{
$isAnon = substr( $memberData['login_anonymous'], 0, 1 );
}
return $isAnon;
}
/**
* Easy peasy way to grab a function from member/memberFunctions.php
* without having to bother setting it up each time.
*
* @return object memberFunctions object
* @author MattMecham
*/
static public function getFunction()
{
if ( ! is_object( self::$_memberFunctions ) )
{
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/member/memberFunctions.php', 'memberFunctions' );
self::$_memberFunctions = new $classToLoad( ipsRegistry::instance() );
}
return self::$_memberFunctions;
}
/**
* Set the cache to ignore
* Works for one LOAD only! It's reset again for the next load
*
* @return @e void
*/
static public function ignoreCache()
{
self::$ignoreCache = TRUE;
}
/**
* Can upload a photo
*
* @param array $memberData
* @param bool If true, also checks if we can use linked or gravatar photos
* @return boolean
*/
static public function canUploadPhoto( $memberData, $checkAll=FALSE )
{
if ( $checkAll and ( ipsRegistry::$settings['mem_photo_url'] or ipsRegistry::$settings['allow_gravatars'] ) )
{
return TRUE;
}
return ( ( $memberData['g_edit_profile'] && $memberData['photoMaxKb'] && $memberData['photoMaxWidth'] && $memberData['photoMaxHeight'] ) || IN_ACP ) ? true : false;
}
/**
* Kludgy function to prevent long strings of HTML logic
*
* @param array Array of data (has_given_rep, etc)
* @param array Member Data
* @return boolean
*/
static public function canRepUp( $data, $memberData=array() )
{
return ( ( ipsRegistry::$settings['reputation_point_types'] == 'like' AND empty( $data['has_given_rep'] ) ) OR in_array( ipsRegistry::$settings['reputation_point_types'], array( 'positive', 'both' ) ) && empty( $data['has_given_rep'] ) and ipsRegistry::member()->getProperty('g_rep_max_positive') ) ? true : false;
}
/**
* Kludgy function to prevent long strings of HTML logic
*
* @param array Array of data (has_given_rep, etc)
* @param array Member Data
* @return boolean
*/
static public function canRepDown( $data, $memberData=array() )
{
return ( $data['has_given_rep'] == 1 AND ipsRegistry::$settings['reputation_point_types'] == 'like' ) OR ( empty( $data['has_given_rep'] ) AND in_array( ipsRegistry::$settings['reputation_point_types'], array( 'negative', 'both' ) ) ) and ipsRegistry::member()->getProperty('g_rep_max_negative') ? true : false;
}
/**
* Can give rep to an item
*
* @param array Array of data (has_given_rep, etc)
* @param array Member data
*/
static public function canGiveRep( $data, $memberData )
{
$reppedArray = unserialize( $data['rep_like_cache'] );
if( is_array( $reppedArray ) )
{
$repped = $reppedArray['cache_data']['memberIds'];
if ( is_array( $repped ) )
{
if( in_array( ipsRegistry::member()->getProperty('member_id'), $repped ) )
{
return false;
}
}
}
return ( $data['has_given_rep'] == 1 AND ipsRegistry::$settings['reputation_point_types'] == 'like' ) OR ( $data['has_given_rep'] != 1 ) AND ( $memberData['member_id'] != 0 ) && ( ipsRegistry::$settings['reputation_can_self_vote'] OR ( $memberData['member_id'] != ipsRegistry::member()->getProperty('member_id') ) ) ? true : false;
}
/**
* Determines if we can share socially or not
* @param string $method (If false, it'll check all services and return true of one or more allow it) facebook/twitter
* @param array $memberData
*/
static public function canSocialShare( $method=false, $memberData=null )
{
$memberData = ( $memberData === null ) ? ipsRegistry::member()->fetchMemberData() : $memberData;
if ( $method == false )
{
$method = array( 'twitter', 'facebook' );
}
else if ( is_string( $method ) )
{
$method = array( $method );
}
$canShare = false;
if ( is_array( $method ) )
{
foreach( $method as $s )
{
switch( $s )
{
case 'twitter':
$canShare = ( IPSLib::twitter_enabled() AND ( $memberData['twitter_token'] ) ) ? true : false;
break;
case 'facebook':
$canShare = ( IPSLib::fbc_enabled() AND ( $memberData['fb_token'] ) ) ? true : false;
break;
}
if ( $canShare === true )
{
return true;
}
}
}
return $canShare;
}
/**
* Send out the social shares
* @param array $data array( 'title' => 'Eat Pie!', 'url' => 'http://eatpie.com/' )
* @param array $services array of services to share with
*/
static public function sendSocialShares( array $data, $services=null, $memberData=null )
{
$memberData = ( $memberData === null ) ? ipsRegistry::member()->fetchMemberData() : $memberData;
$checkedServices = array();
if ( ! count( $services ) || $services === null )
{
/* What are we sharing? */
foreach( ipsRegistry::$request as $k => $v )
{
if ( stristr( $k, 'share_x_' ) and ! empty( $v ) )
{
$services[] = str_ireplace( 'share_x_', '', $k );
}
}
}
if( is_array($services) AND count($services) )
{
foreach( $services as $service )
{
if ( self::canSocialShare( $service, $memberData ) )
{
$checkedServices[] = $service;
}
}
}
/* Process them */
foreach( $checkedServices as $service )
{
switch( $service )
{
case 'twitter':
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/twitter/connect.php', 'twitter_connect' );
$twitter = new $classToLoad( ipsRegistry::instance(), $memberData['twitter_token'], $memberData['twitter_secret'] );
try
{
$twitter->updateStatusWithUrl( IPSText::UNhtmlspecialchars( $data['title'] ), $data['url'], TRUE );
}
catch( Exception $ex ) { }
break;
case 'facebook':
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/facebook/connect.php', 'facebook_connect' );
$facebook = new $classToLoad( ipsRegistry::instance() );
try
{
$facebook->postLinkToWall( $data['url'], IPSText::UNhtmlspecialchars( $data['title'] ) );
}
catch( Exception $ex ) { }
break;
}
}
}
/**
* Adds a member to the cache
*
* @param array Member Data
* @param array Tables queried
* @return @e void
*/
static protected function _addToCache( $memberData, $tables )
{
if ( ! $memberData['member_id'] OR ! is_array( $tables ) )
{
return FALSE;
}
$_tables = self::__buildTableHash( $tables );
self::$memberCache[ $memberData['member_id'] ][ $_tables ] = $memberData;
self::$debugData[] = "ADDED: Member ID: " . $memberData['member_id'] . " with tables " . implode( ",", $tables ). ' key ('.$_tables.')';
}
/**
* Removes a member from the cache
*
* @param int Member ID
* @return @e void
*/
static protected function _removeFromCache( $memberID )
{
if ( is_array( self::$memberCache[ $memberID ] ) )
{
unset( self::$memberCache[ $memberID ] );
self::$debugData[] = "REMOVED: Member ID: " . $memberID;
}
}
/**
* Removes a member from the cache
*
* @param int Member ID to look for
* @param array Tables required
* @return mixed Array of data if a match is found, or FALSE if not.
*/
static protected function _fetchFromCache( $memberID, $tables )
{
if ( self::$ignoreCache === TRUE )
{
return FALSE;
}
if ( ! $memberID OR ! is_array( $tables ) )
{
return FALSE;
}
$_tables = self::__buildTableHash( $tables );
if ( isset( self::$memberCache[ $memberID ][ $_tables ] ) && is_array( self::$memberCache[ $memberID ][ $_tables ] ) )
{
self::$debugData[] = "FETCHED: Member ID: " . $memberID. ' key ('.$_tables.')';
return self::$memberCache[ $memberID ][ $_tables ];
}
else
{
return FALSE;
}
}
/**
* Updates a member from the cache
*
* @param int Member ID to update
* @param array Array of data to update(eg: array( 'core' => 'member_login_key' => 'xxxxx' ) )
* @return mixed Array of data if a match is found, or FALSE if not.
*/
static protected function _updateCache( $memberID, $data )
{
if ( ! $memberID OR ! is_array( $data ) )
{
return FALSE;
}
if ( is_array( self::$memberCache[ $memberID ] ) )
{
foreach( self::$memberCache[ $memberID ] as $tableData => $memberData )
{
foreach( $data as $table => $newData )
{
foreach( $newData as $k => $v )
{
self::$memberCache[ $memberID ][ $tableData ][ $k ] = $v;
}
}
}
self::$debugData[] = "Updated: Member ID: " . $memberID;
return TRUE;
}
else
{
return FALSE;
}
}
/**
* Build table key.
* Takes an array of tables and returns an MD5 comparison hash
*
* @param array Array of tables
* @return string MD5 hash
*/
static protected function __buildTableHash( $tables )
{
sort( $tables );
return md5( implode( ',', $tables ) );
}
/**
* Sends a query to the IPS Spam Service
*
* @param string $email Email address to check/report
* @param string [$ip] IP Address to check report, ipsRegistry::member()->ip_address will be used if the address is not specified
* @param string [$type] Either register or markspam, register is default
* @return string
*/
static public function querySpamService( $email, $ip='', $type='register', $test=0 )
{
/* Get the response */
$key = trim( ipsRegistry::$settings['ipb_reg_number'] );
if( !$key )
{
return 0;
}
$domain = ipsRegistry::$settings['board_url'];
$ip = ( $ip AND ip2long( $ip ) ) ? $ip : ipsRegistry::member()->ip_address;
$response = false;
$testConn = $test ? '&debug_mode=1' : '';
/* Get the file managemnet class */
$classToLoad = IPSLib::loadLibrary( IPS_KERNEL_PATH . 'classFileManagement.php', 'classFileManagement' );
$query = new $classToLoad();
$query->timeout = ipsRegistry::$settings['spam_service_timeout'];
/* Query the service */
$response = $query->getFileContents( "https://ips-spam-service.com/new-api/index.php?key={$key}&domain={$domain}&type={$type}&email={$email}&ip={$ip}{$testConn}" );
if( ! $response )
{
return 'timeout';
}
$response = explode( "n", $response );
$responseCode = $response[0];
$responseMsg = $response[1];
if( $test )
{
return $responseMsg;
}
/* Log Request */
if( $type == 'register' )
{
ipsRegistry::DB()->insert( 'spam_service_log', array( 'log_date' => time(),
'log_code' => $responseCode,
'log_msg' => $responseMsg,
'email_address' => $email,
'ip_address' => $ip ) );
}
return intval( $responseCode );
}
/**
* Check if a member's posts need to be approved
* Note that this only takes into the global mod queue status, individual forums, etc. may
* set posts to be moderated and have custom permissions
*
* @param int|array Member ID or array of data
* @return bool|null If TRUE - mod queue post. If FALSE - do not. If NULL - member is banned or restricted from posting and should not be able to post at all.
*/
public static function isOnModQueue( $memberData )
{
//-----------------------------------------
// Get Data
//-----------------------------------------
if ( !is_array( $memberData ) && $memberData > 0 )
{
$memberData = IPSMember::load( $memberData );
}
//-----------------------------------------
// Check we can post at all
//-----------------------------------------
/* Banned */
if ( $memberData['member_banned'] )
{
return NULL;
}
/* Suspended */
if ( $memberData['temp_ban'] )
{
$data = IPSMember::processBanEntry( $memberData['temp_ban'] );
if ( $data['date_end'] )
{
if ( time() >= $data['date_end'] )
{
IPSMember::save( $memberData['member_id'], array( 'core' => array( 'temp_ban' => 0 ) ) );
}
else
{
return NULL;
}
}
else
{
return NULL;
}
}
/* Restricted from posting */
if ( $memberData['restrict_post'] )
{
$data = IPSMember::processBanEntry( $memberData['restrict_post'] );
if ( $data['date_end'] )
{
if ( time() >= $data['date_end'] )
{
IPSMember::save( $memberData['member_id'], array( 'core' => array( 'restrict_post' => 0 ) ) );
}
else
{
return NULL;
}
}
else
{
return NULL;
}
}
//-----------------------------------------
// So are we mod queued?
//-----------------------------------------
if ( $memberData['mod_posts'] )
{
$data = IPSMember::processBanEntry( $memberData['mod_posts'] );
if ( $data['date_end'] )
{
if ( time() >= $data['date_end'] )
{
IPSMember::save( $memberData['member_id'], array( 'core' => array( 'mod_posts' => 0 ) ) );
}
else
{
return TRUE;
}
}
else
{
return TRUE;
}
}
//-----------------------------------------
// How about the group?
//-----------------------------------------
if ( $memberData['g_mod_preview'] )
{
/* Do we only limit for x posts/days? */
if ( $memberData['g_mod_post_unit'] )
{
if ( $memberData['gbw_mod_post_unit_type'] )
{
/* Days.. .*/
if ( $memberData['joined'] > ( IPS_UNIX_TIME_NOW - ( 86400 * $memberData['g_mod_post_unit'] ) ) )
{
return TRUE;
}
}
else
{
/* Posts */
if ( $memberData['posts'] < $memberData['g_mod_post_unit'] )
{
return TRUE;
}
}
}
else
{
/* No limit, but still checking moderating */
return TRUE;
}
}
//-----------------------------------------
// Still here - which means we're fine
//-----------------------------------------
return FALSE;
}
/**
* Hide / Unhide / Delete Constants
*/
const CONTENT_DELETE = 1;
const CONTENT_HIDE = 2;
const CONTENT_UNHIDE = 3;
/**
* Can hide/unhide content
*
* @param array Member Data
* @param int Action - see constants above
* @param int Item's owner ID
*/
public static function canModerateContent( $member, $action, $owner=NULL )
{
if ( $member['g_is_supmod'] )
{
return TRUE;
}
elseif ( !is_null( $owner ) and $member['member_id'] == $owner )
{
switch ( $action )
{
case self::CONTENT_DELETE:
return $member['g_delete_own_posts'];
break;
case self::CONTENT_HIDE:
return $member['gbw_soft_delete_own'];
break;
case self::CONTENT_UNHIDE:
return FALSE;
break;
}
}
return FALSE;
}
/**
* Flag an account as spammer
*
* @param int|array $member Member Data
* @param array $marker The person marking this person a spammer
* @param bool $resetLastMember If FALSE skips resetting the last registered member
* @return void
*/
public static function flagMemberAsSpammer( $member, $marker=NULL, $resetLastMember=TRUE )
{
//-----------------------------------------
// Init
//-----------------------------------------
/* Load Member */
if ( !is_array( $member ) )
{
$member = self::load( $member );
}
/* Load moderator library (we'll need this to unapprove posts and log) */
$classToLoad = IPSLib::loadLibrary( IPSLib::getAppDir( 'forums' ) . '/sources/classes/moderate.php', 'moderatorLibrary', 'forums' );
$modLibrary = new $classToLoad( ipsRegistry::instance() );
//-----------------------------------------
// Do it
//-----------------------------------------
$toSave = array();
$toSave['core']['bw_is_spammer'] = TRUE;
/* Shut off twitter/FB status importing */
$bwOptions = IPSBWOptions::thaw( $member['tc_bwoptions'], 'twitter' );
$bwOptions['tc_si_status'] = 0;
$twitter = IPSBWOptions::freeze( $bwOptions, 'twitter' );
$bwOptions = IPSBWOptions::thaw( $member['fb_bwoptions'], 'facebook' );
$bwOptions['fbc_si_status'] = 0;
$facebook = IPSBWOptions::freeze( $bwOptions, 'facebook' );
$toSave['extendedProfile']['tc_bwoptions'] = $twitter;
$toSave['extendedProfile']['fb_bwoptions'] = $facebook;
/* Do any disabling, unapproving, banning - no breaks here since if we ban, we also want to unapprove posts, etc. */
/* Note that there are DELIBERATELY no breaks in this switch since the options are cascading (if you ban, you also want to unapprove content) */
switch( ipsRegistry::$settings['spm_option'] )
{
/* Empty profile and ban account */
case 'ban':
// ban
$toSave['core']['member_banned'] = TRUE;
// wipe data
$toSave['core']['title'] = '';
$toSave['extendedProfile']['signature'] = '';
$toSave['extendedProfile']['pp_about_me'] = '';
// wipe photo
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/member/photo.php', 'classes_member_photo' );
$photos = new $classToLoad( ipsRegistry::instance() );
$photos->remove( $member['member_id'] );
// wipe custom fields
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/customfields/profileFields.php', 'customProfileFields' );
$fields = new $classToLoad();
$fields->member_data = $member;
$fields->initData( 'edit' );
$fields->parseToSave( array() );
if ( count( $fields->out_fields ) )
{
$toSave['customFields'] = $fields->out_fields;
}
// wipe signature
IPSContentCache::update( $member['member_id'], 'sig', '' );
/* Unapprove posts */
case 'unapprove':
$modLibrary->deleteMemberContent( $member['member_id'], 'all', intval( ipsRegistry::$settings['spm_post_days'] ) * 24 );
/* Disable Post/PM permission */
case 'disable':
$toSave['core']['restrict_post'] = 1;
$toSave['core']['members_disable_pm'] = 2;
}
self::save( $member['member_id'], $toSave );
//-----------------------------------------
// Run memberSync
//-----------------------------------------
IPSLib::runMemberSync( 'onSetAsSpammer', array_merge( $member, $toSave ) );
//-----------------------------------------
// Let the admin know if necessary
//-----------------------------------------
if ( $marker !== NULL and ipsRegistry::$settings['spm_notify'] and ( ipsRegistry::$settings['email_in'] != $marker['email'] ) )
{
ipsRegistry::getClass('class_localization')->loadLanguageFile( array( 'public_mod' ), 'forums' );
ipsRegistry::getClass('class_localization')->loadLanguageFile( array( 'admin_member' ), 'members' );
IPSText::getTextClass('email')->getTemplate( 'possibleSpammer' );
IPSText::getTextClass('email')->buildMessage( array( 'DATE' => ipsRegistry::getClass('class_localization')->getDate( $member['joined'], 'LONG', 1 ),
'MEMBER_NAME' => $member['members_display_name'],
'IP' => $member['ip_address'],
'EMAIL' => $member['email'],
'LINK' => ipsRegistry::getClass('output')->buildSEOUrl( "showuser=" . $member['member_id'], 'public', $member['members_seo_name'], 'showuser' ) ) );
IPSText::getTextClass('email')->subject = sprintf( ipsRegistry::getClass('class_localization')->words['new_registration_email_spammer'], ipsRegistry::$settings['board_name'] );
IPSText::getTextClass('email')->to = ipsRegistry::$settings['email_in'];
IPSText::getTextClass('email')->sendMail();
}
/* Reset last member? */
if ( $resetLastMember )
{
self::resetLastRegisteredMember();
}
//-----------------------------------------
// Let IPS know
//-----------------------------------------
if( ipsRegistry::$settings['spam_service_send_to_ips'] )
{
self::querySpamService( $member['email'], $member['ip_address'], 'markspam' );
}
//-----------------------------------------
// Log
//-----------------------------------------
ipsRegistry::getClass('class_localization')->loadLanguageFile( array( 'public_modcp' ), 'core' );
$modLibrary->addModerateLog( 0, 0, 0, 0, ipsRegistry::getClass('class_localization')->words['flag_spam_done'] . ': ' . $member['member_id'] . ' - ' . $member['email'] );
}
/**
* Resets the last registered member
*
* @param bool $return If TRUE returns the value instead of updating it
* @return @e mixed
*/
public static function resetLastRegisteredMember( $return=false )
{
/* Init vsrs */
$groups = array();
$_extra = '';
$update = array( 'last_mem_id' => 0, 'last_mem_name' => '', 'last_mem_name_seo' => '' );
/* Exclude certain groups */
foreach( ipsRegistry::cache()->getCache('group_cache') as $_gid => $_gdata )
{
if( $_gdata['g_hide_online_list'] || $_gid == ipsRegistry::$settings['auth_group'] )
{
$groups[] = $_gid;
}
}
/* Groups to skip? */
$_extra = count($groups) ? "member_group_id NOT IN (" . implode( ',', $groups ) . ") AND " : '';
$r = ipsRegistry::DB()->buildAndFetch( array( 'select' => 'member_id, members_display_name, members_seo_name',
'from' => 'members',
'where' => "{$_extra} members_display_name != '' AND members_display_name " . ipsRegistry::DB()->buildIsNull( false ) . " AND member_banned=0 AND ( ! " . IPSBWOptions::sql( 'bw_is_spammer', 'members_bitoptions', 'members', 'global', 'has' ) . ")",
'order' => "member_id DESC",
'limit' => array( 0, 1 )
) );
$update['last_mem_id'] = intval($r['member_id']);
$update['last_mem_name'] = trim($r['members_display_name']);
$update['last_mem_name_seo'] = trim($r['members_seo_name']);
/* Update our stats or return? */
if ( $return )
{
return $update;
}
else
{
$stats = ipsRegistry::cache()->getCache('stats');
$stats = array_merge( $stats, $update );
ipsRegistry::cache()->setCache( 'stats', $stats, array( 'array' => 1 ) );
}
}
}