999 lines
27 KiB
PHP
999 lines
27 KiB
PHP
<?php
|
|
/**
|
|
* <pre>
|
|
* Invision Power Services
|
|
* IP.Board v3.4.9
|
|
* Twitter Connect Library
|
|
* Created by Matt Mecham
|
|
* Last Updated: $Date: 2014-11-11 16:19:43 -0500 (Tue, 11 Nov 2014) $
|
|
* </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
|
|
* @version $Rev: 12569 $
|
|
*
|
|
*/
|
|
|
|
class facebook_connect
|
|
{
|
|
/**#@+
|
|
* Registry Object Shortcuts
|
|
*
|
|
* @access protected
|
|
* @var object
|
|
*/
|
|
protected $registry;
|
|
protected $DB;
|
|
protected $settings;
|
|
protected $request;
|
|
protected $lang;
|
|
protected $member;
|
|
protected $memberData;
|
|
protected $cache;
|
|
protected $caches;
|
|
/**#@-*/
|
|
|
|
/**
|
|
* Facebook wrapper
|
|
*
|
|
* @access protected
|
|
* @var object
|
|
*/
|
|
protected $_api;
|
|
|
|
/**
|
|
* Facebook OAUTH wrapper
|
|
*
|
|
* @access protected
|
|
* @var object
|
|
*/
|
|
protected $_oauth;
|
|
|
|
/**
|
|
* IPBs log in handler
|
|
*
|
|
* @access protected
|
|
* @var object
|
|
*/
|
|
protected $_login;
|
|
|
|
/**
|
|
* User connected
|
|
*
|
|
* @access protected
|
|
* @var boolean
|
|
*/
|
|
protected $_connected = false;
|
|
|
|
/**
|
|
* User: Token
|
|
*
|
|
* @access protected
|
|
* @var string
|
|
*/
|
|
protected $_userToken;
|
|
|
|
/**
|
|
* User: ID
|
|
*
|
|
* @access protected
|
|
* @var int
|
|
*/
|
|
protected $_userId;
|
|
|
|
/**
|
|
* User: Data
|
|
*
|
|
* @access protected
|
|
* @var array
|
|
*/
|
|
protected $_userData = array();
|
|
|
|
/**
|
|
* Required permissions
|
|
*
|
|
* @access public
|
|
* @var array
|
|
*/
|
|
public $extendedPerms = array( 'email', 'user_status', 'publish_actions' );
|
|
|
|
/**
|
|
* Construct.
|
|
* $this->memberData['twitter_token'] $this->memberData['twitter_secret']
|
|
* @param object Registry object
|
|
* @param string Facebook user token
|
|
* @param int User ID
|
|
* @param boolean Force an exception to be thrown rather than output error (used in IPSMember::buildDisplayPhoto)
|
|
* @access public
|
|
* @return @e void
|
|
*/
|
|
public function __construct( $registry, $token='', $userId=0, $forceThrowException=false )
|
|
{
|
|
/* Make object */
|
|
$this->registry = $registry;
|
|
$this->DB = $this->registry->DB();
|
|
$this->settings =& $this->registry->fetchSettings();
|
|
$this->request =& $this->registry->fetchRequest();
|
|
$this->lang = $this->registry->getClass('class_localization');
|
|
$this->member = $this->registry->member();
|
|
$this->memberData =& $this->registry->member()->fetchMemberData();
|
|
$this->cache = $this->registry->cache();
|
|
$this->caches =& $this->registry->cache()->fetchCaches();
|
|
|
|
define("FACEBOOK_APP_ID" , trim( $this->settings['fbc_appid'] ) );
|
|
define("FACEBOOK_APP_SECRET" , trim( $this->settings['fbc_secret'] ) );
|
|
define("FACEBOOK_CALLBACK" , $this->settings['_original_base_url'] . '/interface/facebook/index.php?m=' . $this->memberData['member_id'] );
|
|
|
|
/* Auto do it man */
|
|
if ( ! $token AND $this->memberData['member_id'] AND $this->memberData['fb_token'] )
|
|
{
|
|
$token = $this->memberData['fb_token'];
|
|
}
|
|
|
|
/* Auto do it man */
|
|
if ( ! $userId AND $this->memberData['member_id'] AND $this->memberData['fb_uid'] )
|
|
{
|
|
$userId = $this->memberData['fb_uid'];
|
|
}
|
|
|
|
$this->_userToken = trim( $token );
|
|
$this->_userId = trim( $userId ); /* never int - max ids are larger than int */
|
|
|
|
/* Test */
|
|
if ( ! FACEBOOK_APP_ID OR ! FACEBOOK_APP_SECRET )
|
|
{
|
|
/* Give upgraders a helping hand */
|
|
if ( ! FACEBOOK_APP_ID )
|
|
{
|
|
if ( $forceThrowException === false )
|
|
{
|
|
$this->registry->output->showError( $this->lang->words['gbl_fb_no_app_id'], 1090001 );
|
|
}
|
|
else
|
|
{
|
|
throw new Exception( 'FACEBOOK_NO_APP_ID' );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new Exception( 'FACEBOOK_NOT_SET_UP' );
|
|
}
|
|
}
|
|
|
|
/* Reset the API */
|
|
$this->resetApi( $token, $userId );
|
|
}
|
|
|
|
/**
|
|
* Resets API
|
|
*
|
|
* @access public
|
|
* @param string OAUTH user token
|
|
*/
|
|
public function resetApi( $token='', $userId='' )
|
|
{
|
|
$this->_userToken = trim( $token );
|
|
$this->_userId = trim( $userId );
|
|
|
|
/* A user token is always > 32 */
|
|
if ( strlen( $this->_userToken ) <= 32 )
|
|
{
|
|
/* we store a tmp md5 key during auth, so ensure we don't pass this as a token */
|
|
$this->_userToken = '';
|
|
}
|
|
|
|
/* Load oAuth */
|
|
require_once( IPS_KERNEL_PATH . 'facebook/facebookoauth.php' );/*noLibHook*/
|
|
$this->_oauth = new FacebookOAuth( FACEBOOK_APP_ID, FACEBOOK_APP_SECRET, FACEBOOK_CALLBACK, $this->extendedPerms );
|
|
|
|
/* Load API */
|
|
require_once( IPS_KERNEL_PATH . 'facebook/facebook.php' );/*noLibHook*/
|
|
$this->_api = new Facebook( array( 'appId' => FACEBOOK_APP_ID, 'secret' => FACEBOOK_APP_SECRET, 'cookie' => true ) );
|
|
|
|
if ( $this->_userToken AND $this->_userId )
|
|
{
|
|
try
|
|
{
|
|
$_userData = $this->_api->api( '/v2.1/' . $this->_userId, array( 'access_token' => $this->_userToken ) );
|
|
}
|
|
catch( Exception $e )
|
|
{
|
|
/* Try re-authorising */
|
|
if ( stristr( $e->getMessage(), 'invalid' ) )
|
|
{
|
|
$this->redirectToConnectPage();
|
|
}
|
|
}
|
|
|
|
if ( $_userData['id'] AND $_userData['id'] == $this->_userId )
|
|
{
|
|
$this->_userData = $_userData;
|
|
$this->_connected = true;
|
|
}
|
|
else
|
|
{
|
|
$this->_userData = array();
|
|
$this->_connected = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$this->_userData = array();
|
|
$this->_connected = false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Revoke app authorization
|
|
*
|
|
* @access public
|
|
* @return boolean
|
|
*/
|
|
public function revokeAuthorization()
|
|
{
|
|
if ( $this->_userToken AND $this->_userId )
|
|
{
|
|
try
|
|
{
|
|
$val = $this->_api->api( "/v2.1/{$this->_userId}/permissions", 'DELETE', array( 'access_token' => $this->_userToken ) );
|
|
}
|
|
catch( Exception $e )
|
|
{
|
|
$this->registry->output->logErrorMessage( $e->getMessage(), 'FB-EXCEPTION' );
|
|
}
|
|
}
|
|
|
|
return $val;
|
|
}
|
|
|
|
|
|
/**
|
|
* User has removed app from Facebook
|
|
* @link http://wiki.developers.facebook.com/index.php/Post-Remove_Callback_URL
|
|
*
|
|
* @access public
|
|
*/
|
|
public function userHasRemovedApp()
|
|
{
|
|
/* INIT */
|
|
$sig = '';
|
|
$userId = intval( $_POST['fb_sig_user'] );
|
|
|
|
/* Generate signature */
|
|
ksort($_POST);
|
|
|
|
foreach( $_POST as $key => $val )
|
|
{
|
|
if ( substr( $key, 0, 7 ) == 'fb_sig_' )
|
|
{
|
|
$sig .= substr( $key, 7 ) . '=' . $val;
|
|
}
|
|
}
|
|
|
|
$sig .= FACEBOOK_APP_SECRET;
|
|
$verify = md5($sig);
|
|
|
|
if ( $userId AND $verify == $_POST['fb_sig'] )
|
|
{
|
|
/* Load user */
|
|
$_member = IPSMember::load( $userId, 'all', 'fb_uid' );
|
|
|
|
if ( $_member['member_id'] )
|
|
{
|
|
/* Remove any FB stuffs */
|
|
IPSMember::save( $_member['member_id'], array( 'core' => array( 'fb_uid' => 0, 'fb_lastsync' => 0, 'fb_session' => '', 'fb_emailhash' => '', 'fb_token' => '' ) ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetch user has app permission
|
|
* Wrapper so we can change it later
|
|
*
|
|
* @access public
|
|
* @param string Permission mask ('email', etc)
|
|
* @return boolean
|
|
*/
|
|
public function fetchHasAppPermission( $permission )
|
|
{
|
|
if ( $this->_userToken AND $this->_userId )
|
|
{
|
|
try
|
|
{
|
|
$val = $this->_api->api( "/v2.1/{$this->_userId}/permissions", array( 'access_token' => $this->_userToken, 'permission' => $permission ) );
|
|
}
|
|
catch( Exception $e )
|
|
{
|
|
$this->registry->output->logErrorMessage( $e->getMessage(), 'FB-EXCEPTION' );
|
|
}
|
|
}
|
|
|
|
return $val;
|
|
}
|
|
|
|
/**
|
|
* Return user data
|
|
*
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function fetchUserData( $token='', $picType='square' )
|
|
{
|
|
$token = ( $token ) ? $token : $this->_userToken;
|
|
|
|
if ( $token AND is_array( $this->_userData ) AND $this->_userData['id'] AND ! isset( $this->_userData['pic'] ) )
|
|
{
|
|
/* Query extra data - returns annoying https images */
|
|
try
|
|
{
|
|
$updates = $this->_api->api( "/v2.1/{$this->_userData['id']}", array( 'access_token' => $token ) );
|
|
$photo = $this->_api->api( "/v2.1/{$this->_userData['id']}/picture", array( 'type' => $picType, 'redirect' => 'false' ) );
|
|
$updates['photo'] = $photo['data']['url'];
|
|
}
|
|
catch( Exception $e )
|
|
{
|
|
/* Try re-authorising */
|
|
if ( stristr( $e->getMessage(), 'invalid' ) )
|
|
{
|
|
$this->redirectToConnectPage();
|
|
}
|
|
}
|
|
|
|
if ( count( $updates ) )
|
|
{
|
|
foreach( $updates as $k => $v )
|
|
{
|
|
$this->_userData[ $k ] = $v;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $this->_userData;
|
|
}
|
|
|
|
/**
|
|
* Return whether or not the user is connected to twitter
|
|
*
|
|
* @access public
|
|
* @return boolean
|
|
*/
|
|
public function isConnected()
|
|
{
|
|
return ( $this->_connected == true ) ? true : false;
|
|
}
|
|
|
|
/**
|
|
* Post a link to the user's FB wall
|
|
*
|
|
* @access public
|
|
* @param string URL
|
|
* @param string Comment (can be NUFING)
|
|
*/
|
|
public function postLinkToWall( $url, $comment='', $shorten=true )
|
|
{
|
|
$memberData = $this->memberData;
|
|
|
|
/* Got a member? */
|
|
if ( ! $memberData['member_id'] )
|
|
{
|
|
throw new Exception( 'NO_MEMBER' );
|
|
}
|
|
|
|
/* Linked account? */
|
|
if ( ! $memberData['fb_uid'] OR ! $memberData['fb_token'] )
|
|
{
|
|
throw new Exception( 'NOT_LINKED' );
|
|
}
|
|
|
|
/* Shorten? */
|
|
if ( $shorten )
|
|
{
|
|
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/url/shorten.php', 'urlShorten' );
|
|
$shortenApi = new $classToLoad();
|
|
|
|
$data = $shortenApi->shorten( $url, IPS_URL_SHORTEN_SERVICE );
|
|
$url = $data['url'];
|
|
}
|
|
|
|
/* POST the data */
|
|
try
|
|
{
|
|
$this->_api->api( '/v2.1/me/links', 'POST', array( 'access_token' => $this->_userToken, 'link' => $url, 'message' => $comment ) );
|
|
}
|
|
catch( Exception $e )
|
|
{
|
|
$this->registry->output->logErrorMessage( $e->getMessage(), 'FB-EXCEPTION' );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Post a status update to Facebook based on native content
|
|
* Which may be longer and such and so on and so forth, etc
|
|
*
|
|
* @access public
|
|
* @param string Content
|
|
* @param string URL to add
|
|
* @param bool Always add the URL regardless of content length
|
|
*/
|
|
public function updateStatusWithUrl( $content, $url, $alwaysAdd=false )
|
|
{
|
|
$memberData = $this->memberData;
|
|
|
|
/* Got a member? */
|
|
if ( ! $memberData['member_id'] )
|
|
{
|
|
throw new Exception( 'NO_MEMBER' );
|
|
}
|
|
|
|
/* Linked account? */
|
|
if ( ! $memberData['fb_uid'] )
|
|
{
|
|
throw new Exception( 'NOT_LINKED' );
|
|
}
|
|
|
|
/* Ensure content is correctly de-html-ized */
|
|
$content = IPSText::UNhtmlspecialchars( $content );
|
|
|
|
/* Ensure it's converted cleanly into utf-8 */
|
|
$content = html_entity_decode( $content, ENT_QUOTES, 'UTF-8' );
|
|
|
|
/* Is the text longer than 140 chars? */
|
|
if ( $alwaysAdd === TRUE or IPSText::mbstrlen( $content ) > 500 )
|
|
{
|
|
/* Leave 26 chars for URL shortener */
|
|
$content = IPSText::mbsubstr( $content, 0, 474 ) . '...';
|
|
|
|
if ( IPSText::mbstrlen( $url ) > 26 )
|
|
{
|
|
/* Generate short URL */
|
|
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/url/shorten.php', 'urlShorten' );
|
|
$shorten = new $classToLoad();
|
|
|
|
try
|
|
{
|
|
$data = $shorten->shorten( $url, IPS_URL_SHORTEN_SERVICE );
|
|
$url = $data['url'];
|
|
}
|
|
catch( Exception $ex )
|
|
{
|
|
/* Stop the exception bubbling back to parent classes */
|
|
}
|
|
}
|
|
|
|
$content .= ' ' . $url;
|
|
}
|
|
|
|
/* POST the data */
|
|
try
|
|
{
|
|
$return = $this->_api->api( "/v2.1/{$this->_userId}/feed", 'POST', array( 'access_token' => $this->_userToken, 'message' => $content ) );
|
|
}
|
|
catch( Exception $e )
|
|
{
|
|
$this->registry->output->logErrorMessage( $e->getMessage(), 'FB-EXCEPTION' );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Redirects a user to the oauth connect page.
|
|
*
|
|
* @access public
|
|
* @return redirect
|
|
*/
|
|
public function redirectToConnectPage()
|
|
{
|
|
/* Stop - no need to redirect if ACP / IN_TASK */
|
|
if ( IN_ACP OR IPS_IS_TASK )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/* Reset api to ensure user is not logged in */
|
|
$this->resetApi();
|
|
|
|
/* Append OAUTH URL */
|
|
$_urlExtra = '';
|
|
$key = md5( uniqid( microtime() ) );
|
|
$_urlExtra = '&key=' . $key;
|
|
|
|
if ( $this->request['_reg'] )
|
|
{
|
|
$_urlExtra .= '&_reg=1';
|
|
}
|
|
|
|
/* Update user's row */
|
|
if ( $this->memberData['member_id'] )
|
|
{
|
|
IPSMember::save( $this->memberData['member_id'], array( 'core' => array( 'fb_token' => $key ) ) );
|
|
}
|
|
|
|
/* Is mobile? */
|
|
if ( $this->member->isMobileApp || ! empty( $_REQUEST['mobile'] ) )
|
|
{
|
|
$this->_oauth->setFormFactor( 'touch' );
|
|
}
|
|
|
|
/* Update callback url */
|
|
$this->_oauth->setCallBackUrl( FACEBOOK_CALLBACK . $_urlExtra );
|
|
|
|
$url = $this->_oauth->getAuthorizeURL();
|
|
$this->registry->output->silentRedirect( $url );
|
|
}
|
|
|
|
/**
|
|
* Completes the connection
|
|
*
|
|
* @access public
|
|
* @return redirect
|
|
*/
|
|
public function finishLogin()
|
|
{
|
|
/* From reg flag */
|
|
if ( $_REQUEST['code'] )
|
|
{
|
|
/* Load oAuth */
|
|
require_once( IPS_KERNEL_PATH . 'facebook/facebookoauth.php' );/*noLibHook*/
|
|
$this->_oauth = new FacebookOAuth( FACEBOOK_APP_ID, FACEBOOK_APP_SECRET, FACEBOOK_CALLBACK, $this->extendedPerms );
|
|
|
|
/* Load API */
|
|
require_once( IPS_KERNEL_PATH . 'facebook/facebook.php' );/*noLibHook*/
|
|
$this->_api = new Facebook( array( 'appId' => FACEBOOK_APP_ID, 'secret' => FACEBOOK_APP_SECRET, 'cookie' => true ) );
|
|
|
|
/* Ensure URL is correct */
|
|
$_urlExtra = '';
|
|
|
|
if ( $_REQUEST['key'] )
|
|
{
|
|
$_urlExtra .= '&key=' . $_REQUEST['key'];
|
|
}
|
|
|
|
if ( $_REQUEST['_reg'] )
|
|
{
|
|
$_urlExtra .= '&_reg=1';
|
|
}
|
|
|
|
/* Update callback url */
|
|
$this->_oauth->setCallBackUrl( FACEBOOK_CALLBACK . $_urlExtra );
|
|
|
|
/* Generate oAuth token */
|
|
$rToken = $this->_oauth->getAccessToken( $_REQUEST['code'] );
|
|
|
|
if ( is_string( $rToken ) )
|
|
{
|
|
try
|
|
{
|
|
$_userData = $this->_api->api('/v2.1/me', array( 'access_token' => $rToken ) );
|
|
}
|
|
catch( Exception $e )
|
|
{
|
|
/* Try re-authorising */
|
|
if ( stristr( $e->getMessage(), 'invalid' ) )
|
|
{
|
|
$this->redirectToConnectPage();
|
|
}
|
|
}
|
|
|
|
/* A little gymnastics */
|
|
$this->_userData = $_userData;
|
|
$_userData = $this->fetchUserData( $rToken );
|
|
|
|
/* Got a member linked already? */
|
|
$_member = IPSMember::load( $_userData['id'], 'all', 'fb_uid' );
|
|
|
|
/* Not connected, check email address */
|
|
if ( ! $_member['member_id'] AND $_userData['email'] )
|
|
{
|
|
$_member = IPSMember::load( $_userData['email'], 'all', 'email' );
|
|
|
|
/* We do have an existing account, so trash email forcing user to sign up with new */
|
|
if ( $_member['member_id'] )
|
|
{
|
|
/* Update row */
|
|
IPSMember::save( $_member['member_id'], array( 'core' => array( 'fb_uid' => $_userData['id'], 'fb_token' => $rToken ) ) );
|
|
}
|
|
}
|
|
|
|
if ( $_member['member_id'] )
|
|
{
|
|
$memberData = $_member;
|
|
|
|
/* Ensure user's row is up to date */
|
|
IPSMember::save( $memberData['member_id'], array( 'core' => array( 'fb_token' => $rToken ) ) );
|
|
|
|
/* Here, so log us in!! */
|
|
$data = $this->_login()->loginWithoutCheckingCredentials( $memberData['member_id'], TRUE );
|
|
|
|
$this->registry->getClass('output')->silentRedirect( $data[1], '', true );
|
|
}
|
|
else
|
|
{
|
|
/* No? Create a new member */
|
|
foreach( array( 'fbc_s_pic', 'fbc_s_status', 'fbc_s_aboutme' ) as $field )
|
|
{
|
|
$toSave[ $field ] = 1;
|
|
}
|
|
|
|
$fb_bwoptions = IPSBWOptions::freeze( $toSave, 'facebook' );
|
|
$safeFBName = ( IPS_DOC_CHAR_SET != 'UTF-8' ) ? IPSText::utf8ToEntities( $_userData['name'] ) : $_userData['name'];
|
|
|
|
/* Make sure usernames are safe */
|
|
if ( $this->settings['username_characters'] )
|
|
{
|
|
$check_against = preg_quote( $this->settings['username_characters'], "/" );
|
|
$check_against = str_replace( '\-', '-', $check_against );
|
|
|
|
$safeFBName = preg_replace( '/[^' . $check_against . ']+/i', '', $safeFBName );
|
|
}
|
|
|
|
/* Check ban filters? */
|
|
if ( IPSMember::isBanned( 'email', $_userData['email'] ) or IPSMember::isBanned( 'name', $safeFBName ) )
|
|
{
|
|
$this->registry->output->showError( 'you_are_banned', 1090003 );
|
|
}
|
|
|
|
$displayName = ( $this->settings['fb_realname'] == 'enforced' ) ? $safeFBName : '';
|
|
|
|
/* From reg, so create new account properly */
|
|
$toSave = array( 'core' => array( 'name' => IPSText::parseCleanValue( $safeFBName ),
|
|
'members_display_name' => FALSE, // Enforce a partial member here so users are presented with the option to link with an account on sign-in. We'll take care of enforced names later.
|
|
'members_created_remote' => 1,
|
|
'member_group_id' => ( $this->settings['fbc_mgid'] ) ? $this->settings['fbc_mgid'] : $this->settings['member_group'],
|
|
'email' => $_userData['email'],
|
|
'fb_uid' => $_userData['id'],
|
|
'time_offset' => $_userData['timezone'],
|
|
'members_auto_dst' => 1,
|
|
'fb_token' => $rToken ),
|
|
'extendedProfile' => array( 'pp_about_me' => IPSText::getTextClass( 'bbcode' )->stripBadWords( IPSText::convertCharsets( $_userData['about'], 'utf-8', IPS_DOC_CHAR_SET ) ),
|
|
'fb_bwoptions' => $fb_bwoptions ) );
|
|
|
|
|
|
$memberData = IPSMember::create( $toSave, FALSE, FALSE, TRUE );
|
|
|
|
if ( ! $memberData['member_id'] )
|
|
{
|
|
throw new Exception( 'CREATION_FAIL' );
|
|
}
|
|
|
|
/* Sync up photo */
|
|
$this->syncMember( $memberData['member_id'] );
|
|
|
|
$pmember = $this->DB->buildAndFetch( array( 'select' => '*', 'from' => 'members_partial', 'where' => "partial_member_id=" . $memberData['member_id'] ) );
|
|
|
|
if ( $pmember['partial_member_id'] )
|
|
{
|
|
$this->registry->getClass('output')->silentRedirect( $this->settings['base_url'] . 'app=core&module=global§ion=register&do=complete_login&mid='. $memberData['member_id'].'&key='.$pmember['partial_date'] );
|
|
}
|
|
else
|
|
{
|
|
/* Already got a display name */
|
|
if ( $displayName )
|
|
{
|
|
/* Here, so log us in!! */
|
|
$data = $this->_login()->loginWithoutCheckingCredentials( $memberData['member_id'], TRUE );
|
|
|
|
IPSLib::runMemberSync( 'onCompleteAccount', $memberData );
|
|
|
|
if ( $this->settings['new_reg_notify'] )
|
|
{
|
|
$this->registry->class_localization->loadLanguageFile( array( 'public_register' ), 'core' );
|
|
|
|
IPSText::getTextClass('email')->setPlainTextTemplate( IPSText::getTextClass('email')->getTemplate("admin_newuser") );
|
|
|
|
IPSText::getTextClass('email')->buildMessage( array( 'DATE' => $this->registry->getClass('class_localization')->getDate( time(), 'LONG', 1 ),
|
|
'LOG_IN_NAME' => $safeFBName,
|
|
'EMAIL' => $_userData['email'],
|
|
'IP' => $this->member->ip_address,
|
|
'DISPLAY_NAME' => $displayName ) );
|
|
|
|
IPSText::getTextClass('email')->subject = sprintf( $this->lang->words['new_registration_email'], $this->settings['board_name'] );
|
|
IPSText::getTextClass('email')->to = $this->settings['email_in'];
|
|
IPSText::getTextClass('email')->sendMail();
|
|
}
|
|
|
|
$this->registry->getClass('output')->silentRedirect( $data[1] ? $data[1] : $this->settings['base_url'] );
|
|
}
|
|
else
|
|
{
|
|
throw new Exception( 'CREATION_FAIL' );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new Exception( 'CREATION_FAIL' );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Need to re-auth */
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Completes the connection
|
|
*
|
|
* @access public
|
|
* @return redirect
|
|
*/
|
|
public function finishConnection()
|
|
{
|
|
if ( $_REQUEST['m'] AND $_REQUEST['code'] )
|
|
{
|
|
/* Load user */
|
|
$member = IPSMember::load( intval( $_REQUEST['m'] ) );
|
|
|
|
if ( $member['fb_token'] == $_REQUEST['key'] )
|
|
{
|
|
/* Load oAuth */
|
|
require_once( IPS_KERNEL_PATH . 'facebook/facebookoauth.php' );/*noLibHook*/
|
|
$this->_oauth = new FacebookOAuth( FACEBOOK_APP_ID, FACEBOOK_APP_SECRET, FACEBOOK_CALLBACK, $this->extendedPerms );
|
|
|
|
/* Load API */
|
|
require_once( IPS_KERNEL_PATH . 'facebook/facebook.php' );/*noLibHook*/
|
|
$this->_api = new Facebook( array( 'appId' => FACEBOOK_APP_ID, 'secret' => FACEBOOK_APP_SECRET, 'cookie' => true ) );
|
|
|
|
/* Ensure URL is correct */
|
|
$_urlExtra = '';
|
|
|
|
if ( $_REQUEST['key'] )
|
|
{
|
|
$_urlExtra .= '&key=' . $_REQUEST['key'];
|
|
}
|
|
|
|
if ( $_REQUEST['_reg'] )
|
|
{
|
|
$_urlExtra .= '&_reg=1';
|
|
}
|
|
|
|
/* Update callback url */
|
|
$this->_oauth->setCallBackUrl( FACEBOOK_CALLBACK . $_urlExtra );
|
|
|
|
/* Generate oAuth token */
|
|
$rToken = $this->_oauth->getAccessToken( $_REQUEST['code'] );
|
|
|
|
if ( is_string( $rToken ) )
|
|
{
|
|
try
|
|
{
|
|
$_userData = $this->_api->api('/v2.1/me', array( 'access_token' => $rToken ) );
|
|
}
|
|
catch( Exception $e )
|
|
{
|
|
$this->registry->output->logErrorMessage( $e->getMessage(), 'FB-EXCEPTION' );
|
|
}
|
|
|
|
/* Ensure user's row is up to date */
|
|
IPSMember::save( $member['member_id'], array( 'core' => array( 'fb_uid' => $_userData['id'],
|
|
'fb_token' => $rToken ) ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Redirect back to settings page */
|
|
$this->registry->getClass('output')->silentRedirect( $this->settings['base_url'] . 'app=core&module=usercp&tab=core&area=facebook' );
|
|
}
|
|
|
|
/**
|
|
* Finish a log-in connection
|
|
* WARNING: NO PERMISSION CHECKS ARE PERFORMED IN THIS FUNCTION.
|
|
*
|
|
* @access public
|
|
* @param int Forum ID of original member (member to keep)
|
|
* @param int Forum ID of linking member (member to remove)
|
|
* @return boolean
|
|
*/
|
|
public function finishNewConnection( $originalId, $newId )
|
|
{
|
|
if ( $originalId AND $newId )
|
|
{
|
|
$original = IPSMember::load( $originalId, 'all' );
|
|
$new = IPSMember::load( $newId, 'all' );
|
|
|
|
if ( $original['member_id'] AND $new['fb_uid'] AND $new['fb_token'] )
|
|
{
|
|
IPSMember::save( $original['member_id'], array( 'core' => array( 'fb_uid' => $new['fb_uid'], 'fb_token' => $new['fb_token'] ) ) );
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Function to resync a member's Facebook data
|
|
*
|
|
* @access public
|
|
* @param mixed Member Data in an array form (result of IPSMember::load( $id, 'all' ) ) or a member ID
|
|
* @return array Updated member data
|
|
*
|
|
* EXCEPTION CODES:
|
|
* NO_MEMBER Member ID does not exist
|
|
* NOT_LINKED Member ID or data specified is not linked to a FB profile
|
|
*/
|
|
public function syncMember( $memberData )
|
|
{
|
|
//-----------------------------------------
|
|
// INIT
|
|
//-----------------------------------------
|
|
|
|
$exProfile = array();
|
|
|
|
/* Do we need to load a member? */
|
|
if ( ! is_array( $memberData ) )
|
|
{
|
|
$memberData = IPSMember::load( intval( $memberData ), 'all' );
|
|
}
|
|
|
|
/* Got a member? */
|
|
if ( ! $memberData['member_id'] )
|
|
{
|
|
throw new Exception( 'NO_MEMBER' );
|
|
}
|
|
|
|
/* Linked account? */
|
|
if ( ! $memberData['fb_uid'] )
|
|
{
|
|
throw new Exception( 'NOT_LINKED' );
|
|
}
|
|
|
|
/* Thaw Options */
|
|
$bwOptions = IPSBWOptions::thaw( $memberData['fb_bwoptions'], 'facebook' );
|
|
|
|
/* Grab the data */
|
|
try
|
|
{
|
|
$this->resetApi( $memberData['fb_token'], $memberData['fb_uid'] );
|
|
|
|
if ( $this->isConnected() )
|
|
{
|
|
$user = $this->fetchUserData();
|
|
|
|
/* Load library */
|
|
if ( $bwOptions['fbc_s_pic'] )
|
|
{
|
|
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/member/photo.php', 'classes_member_photo' );
|
|
$photo = new $classToLoad( $this->registry );
|
|
|
|
$photo->save( $memberData, 'facebook' );
|
|
}
|
|
|
|
if ( $bwOptions['fbc_si_status'] AND ( isset( $memberData['gbw_no_status_import'] ) AND ! $memberData['gbw_no_status_import'] ) AND !$memberData['bw_no_status_update'] )
|
|
{
|
|
/* Fetch timeline */
|
|
//$memberData['tc_last_sid_import'] = ( $memberData['tc_last_sid_import'] < 1 ) ? 100 : $memberData['tc_last_sid_import'];
|
|
$_updates = $this->fetchUserTimeline( $user['id'], 0, true );
|
|
|
|
/* Got any? */
|
|
if ( count( $_updates ) )
|
|
{
|
|
$update = array_shift( $_updates );
|
|
|
|
if ( is_array( $update ) AND isset( $update['message'] ) )
|
|
{
|
|
/* @link http://community.invisionpower.com/tracker/issue-27746-video-in-facebook-status */
|
|
$update['message'] = strip_tags( $update['message'] );
|
|
|
|
/* Load status class */
|
|
if ( ! $this->registry->isClassLoaded( 'memberStatus' ) )
|
|
{
|
|
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/member/status.php', 'memberStatus' );
|
|
$this->registry->setClass( 'memberStatus', new $classToLoad( ipsRegistry::instance() ) );
|
|
}
|
|
|
|
/* Set Author */
|
|
$this->registry->getClass('memberStatus')->setAuthor( $memberData );
|
|
$this->registry->getClass('memberStatus')->setStatusOwner( $memberData );
|
|
|
|
/* Convert if need be */
|
|
if ( IPS_DOC_CHAR_SET != 'UTF-8' )
|
|
{
|
|
$update['message'] = IPSText::utf8ToEntities( $update['message'] );
|
|
}
|
|
|
|
/* Set Content */
|
|
$this->registry->getClass('memberStatus')->setContent( trim( IPSText::getTextClass( 'bbcode' )->stripBadWords( $update['message'] ) ) );
|
|
|
|
/* Set as imported */
|
|
$this->registry->getClass('memberStatus')->setIsImport( 1 );
|
|
|
|
/* Set creator */
|
|
$this->registry->getClass('memberStatus')->setCreator( 'facebook' );
|
|
|
|
/* Can we reply? */
|
|
if ( $this->registry->getClass('memberStatus')->canCreate() )
|
|
{
|
|
$this->registry->getClass('memberStatus')->create();
|
|
|
|
//$exProfile['tc_last_sid_import'] = $update['id'];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Update member */
|
|
IPSMember::save( $memberData['member_id'], array( 'core' => array( 'fb_lastsync' => time() ),
|
|
'extendedProfile' => $exProfile ) );
|
|
|
|
/* merge and return */
|
|
$memberData['fb_lastsync'] = time();
|
|
$memberData = array_merge( $memberData, $exProfile );
|
|
}
|
|
else
|
|
{
|
|
/* Update member even if it failed so it's not selected on next task run */
|
|
IPSMember::save( $memberData['member_id'], array( 'core' => array( 'fb_lastsync' => time() ) ) );
|
|
}
|
|
}
|
|
catch( Exception $e )
|
|
{
|
|
/* Update member even if it failed so it's not selected on next task run */
|
|
IPSMember::save( $memberData['member_id'], array( 'core' => array( 'fb_lastsync' => time() ) ) );
|
|
|
|
$this->registry->output->logErrorMessage( $e->getMessage(), 'FB-EXCEPTION' );
|
|
}
|
|
|
|
return $memberData;
|
|
}
|
|
|
|
/**
|
|
* Fetch a user's recent status updates (max 50)
|
|
*
|
|
* @access public
|
|
* @param int Twitter ID
|
|
* @param bool Strip @replies (true default)
|
|
* @param int Minimum ID to grab from
|
|
* @return array
|
|
*/
|
|
public function fetchUserTimeline( $userId=0, $minId=0, $stripReplies=true )
|
|
{
|
|
$userId = ( $userId ) ? $userId : $this->_userData['id'];
|
|
$count = 50;
|
|
$final = array();
|
|
|
|
if ( $this->_userToken AND $userId )
|
|
{
|
|
try
|
|
{
|
|
$updates = $this->_api->api( "/v2.1/{$userId}/statuses", array( 'access_token' => $this->_userToken ) );
|
|
}
|
|
catch( Exception $e )
|
|
{
|
|
$this->registry->output->logErrorMessage( $e->getMessage(), 'FB-EXCEPTION' );
|
|
}
|
|
|
|
if ( is_array( $updates['data'] ) AND count( $updates['data'] ) )
|
|
{
|
|
foreach( $updates['data'] as $update )
|
|
{
|
|
$final[] = $update;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $final;
|
|
}
|
|
|
|
/**
|
|
* Accessor for the log in functions
|
|
*
|
|
* @access public
|
|
* @return object
|
|
*/
|
|
public function _login()
|
|
{
|
|
if ( ! is_object( $this->_login ) )
|
|
{
|
|
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/handlers/han_login.php', 'han_login' );
|
|
$this->_login = new $classToLoad( $this->registry );
|
|
$this->_login->init();
|
|
}
|
|
|
|
return $this->_login;
|
|
}
|
|
} |