Skip to content

Instantly share code, notes, and snippets.

@kingkool68
Created August 22, 2014 14:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kingkool68/71b81ccf96979f3b4bb3 to your computer and use it in GitHub Desktop.
Save kingkool68/71b81ccf96979f3b4bb3 to your computer and use it in GitHub Desktop.
Makes it easy for your site to use Facebook Connect, Google Connect, in a wholly modular way. Based on Simple Facebook Connect (http://ottopress.com/wordpress-plugins/simple-facebook-connect/) by Otto
<?php
/*
* Base
*
*/
// basic XFBML load into footer
function psc_fb_load_args() {
/*
global $sfc_comm_comments_form;
if ($sfc_comm_comments_form != true) {
return; // nothing to do, not showing comments
}
*/
if( comments_open() && !is_user_logged_in() ) {
$options = get_option('psc_options');
$defaults = array(
'appId' => $options['fb_appid'],
'channelUrl' => home_url('fb-channel-file/'),
'status' => true,
'cookie' => true,
'xfbml' => false,
'oauth' => true,
);
$args = apply_filters( 'psc_fb_args', $defaults );
$args = wp_parse_args($args, $defaults);
?>
var fbArgs = <?=json_encode($args);?>
<?php
}
};
add_action('psc_footer_script','psc_fb_load_args', 20); // 20, to put it at the end of the footer insertions. sub-plugins should use 30 for their code
function psc_channel_file() {
global $wp;
$options = get_option('psc_options');
$wp->add_query_var('fb-channel-file');
add_rewrite_rule('fb-channel-file' . '?$', 'index.php?fb-channel-file=1', 'top');
}
add_action('init','psc_channel_file');
function psc_fb_channel_file_catcher() {
if ( get_query_var('fb-channel-file') == 1 ) {
$cache_expire = 60*60*24*365;
header("Pragma: public");
header("Cache-Control: max-age=".$cache_expire);
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $cache_expire) . ' GMT');
echo '<script src="//connect.facebook.net/en_US/all.js"></script>';
exit;
}
}
add_action('template_redirect','psc_fb_channel_file_catcher');
// the cookie is signed using our application secret, so it's unfakable as long as you don't give away the secret
function psc_fb_cookie_parse() {
$options = get_option('psc_options');
$cookie = $_COOKIE['fbsr_' . $options['fb_appid']];
$args = array();
if ( !empty( $cookie ) ) {
if ( list($encoded_sig, $payload ) = explode('.', $cookie, 2) ) {
$sig = psc_base64_url_decode($encoded_sig);
if (hash_hmac('sha256', $payload, $options['fb_app_secret'], true) == $sig) {
$args = json_decode(psc_base64_url_decode($payload), true);
}
}
}
return $args;
}
// this is not a hack or a dangerous function.. the base64 decode is required because Facebook is sending back base64 encoded data in the signed_request bits.
// See http://developers.facebook.com/docs/authentication/signed_request/ for more info
function psc_base64_url_decode($input) {
return base64_decode( strtr($input, '-_', '+/') );
}
function psc_fb_remote($obj, $connection='', $args=array(), $type = 'GET') {
// save the access tokens for later use in the same request
static $saved_access_tokens;
if ( empty($args['access_token']) && isset($saved_access_tokens[$obj]) && $saved_access_tokens[$obj] = $obj ) {
$args['access_token'] = $saved_access_tokens[$obj];
}
$options = get_option('psc_options');
// get the access token
if ( empty($args['access_token']) && !empty($args['code']) ) {
$resp = wp_remote_get("https://graph.facebook.com/oauth/access_token?client_id={$options['fb_appid']}&redirect_uri=&client_secret={$options['fb_app_secret']}&code={$args['code']}");
if ( !is_wp_error($resp) && wp_remote_retrieve_response_code( $resp ) == 200 ) {
$args['access_token'] = str_replace( 'access_token=', '', $resp['body'] );
$saved_access_tokens[$obj] = $args['access_token'];
} else {
return false;
}
}
$type = strtoupper($type);
if ( empty($obj) ) {
return null;
}
$url = 'https://graph.facebook.com/' . $obj;
if ( !empty($connection) ) {
$url .= '/' . $connection;
}
if ($type == 'GET') {
$url .= '?' . http_build_query($args);
}
$args['sslverify'] = 0;
if ($type == 'POST') {
$data = wp_remote_post($url, $args);
} else if ($type == 'GET') {
$data = wp_remote_get($url, $args);
}
if ( $data && !is_wp_error($data) ) {
$resp = json_decode($data['body'], true);
return $resp;
}
return false;
}
// finds a item from an array in a string
if ( !function_exists('straipos') ) :
function straipos($haystack, $array, $offset=0) {
$occ = array();
for ($i = 0; $i<sizeof($array); $i++) {
$pos = strpos($haystack, $array[$i], $offset);
if ( is_bool($pos) ) continue;
$occ[$pos] = $i;
}
if ( sizeof($occ) < 1 ) { return false; }
ksort($occ);
reset($occ);
list($key, $value) = each($occ);
return array($key, $value);
}
endif;
/*
* Facebook Comments (sfc-comments.php)
*
*/
function psc_fb_button() {
?>
<div id="facebook-connect" class="button">
<p><a href="#"><span>Log In with </span>Facebook</a></p>
</div>
<?php
}
add_action('psc_add_button', 'psc_fb_button');
// generate facebook avatar code for FB user comments
function psc_fb_avatar($avatar, $id_or_email, $size = '96', $default = '', $alt = false) {
// check to be sure this is for a comment
if ( !is_object($id_or_email) || !isset($id_or_email->comment_ID) || $id_or_email->user_id) {
return $avatar;
}
// check for fbuid comment meta
$fbuid = get_comment_meta($id_or_email->comment_ID, 'fbuid', true);
if ($fbuid) {
// return the avatar code
return "<img width='{$size}' height='{$size}' class='avatar avatar-{$size} fbavatar' src='https://graph.facebook.com/{$fbuid}/picture?width={$size}&height={$size}' />";
}
return $avatar;
}
add_filter('get_avatar','psc_fb_avatar', 10, 5);
// Injects the data from Facebook into the $_POST object sent to the server.
function psc_fb_inject_comment_data($comment_post_ID) {
if ( is_user_logged_in() ) {
return; // do nothing to WP users
}
$uid = $_POST['psc_fb_user_id'];
$token = $_POST['psc_fb_token'];
if ( empty($uid) || empty($token) ) {
return; // need both of these to get the data from FB
}
$url = "https://graph.facebook.com/{$uid}/?fields=name,email&access_token={$token}";
$data = wp_remote_get( $url, array('sslverify' => 0) );
if ( !is_wp_error($data) ) {
$json = json_decode($data['body'], true);
if ($json) {
$json = apply_filters('psc_fb_user_data', $json, $uid);
//$_POST['author'] = $json['name'];
$_POST['url'] = "http://www.facebook.com/profile.php?id={$uid}"; //Even though we're not displaying the URL publically we can use this field to query how many commenters are logging in using Facebook.
$_POST['email'] = $json['email'];
}
}
}
add_filter('pre_comment_on_post','psc_fb_inject_comment_data');
// store the FB user ID as comment meta data ('fbuid')
function psc_fb_store_metadata($comment_id) {
$uid = $_POST['psc_fb_user_id'];
$token = $_POST['psc_fb_token'];
if ( !empty($uid) && !empty($token) ) {
// validate token
$url = "https://graph.facebook.com/{$uid}/?fields=name,email&access_token={$token}";
$data = wp_remote_get( $url, array('sslverify'=>0) );
if ( !is_wp_error($data) ) {
$json = json_decode( $data['body'], true );
if ( !empty( $json['name'] ) ) {
update_comment_meta($comment_id, 'fbuid', $uid);
}
}
}
}
add_action('comment_post','psc_fb_store_metadata', 10, 1);
<?php
/*
* Base
*
*/
function sgc_oauth_request_link($scope, $action='', $forceprompt=false) {
$options = get_option('psc_options');
$args['response_type'] = 'code';
$args['client_id'] = $options['goog_appid'];
$args['redirect_uri'] = home_url( $options['goog_oauthcallback'] );
$args['scope'] = $scope;
if ($forceprompt) {
$args['approval_prompt'] = 'force';
$args['access_type'] = 'offline';
} else {
$args['approval_prompt'] = 'auto';
$args['access_type'] = 'online';
}
if ( !empty($action) ) {
$args['state'] = $action;
}
$auth = 'https://accounts.google.com/o/oauth2/auth?' . http_build_query($args);
return $auth;
}
function sgc_get_userinfo($token) {
$headers['Authorization'] = 'Bearer '.$token;
$request['headers'] = $headers;
$request['sslverify'] = false;
$data = wp_remote_get('https://www.googleapis.com/oauth2/v1/userinfo', $request);
if ( is_wp_error( $data ) || 200 != wp_remote_retrieve_response_code( $data ) )
return false;
$resp = json_decode( wp_remote_retrieve_body( $data ), true );
return $resp;
}
function psc_goog_add_rewrite() {
global $wp;
$options = get_option('psc_options');
$wp->add_query_var($options['goog_oauthcallback']);
add_rewrite_rule($options['goog_oauthcallback'] . '?$', 'index.php?oauth2callback=1', 'top');
}
add_action('init','psc_goog_add_rewrite');
function psc_goog_oauth_catcher() {
if ( get_query_var('oauth2callback') == 1 ) {
$oauth = array();
if ( !empty( $_REQUEST['code'] ) ) {
$oauth['code'] = $_REQUEST['code'];
$oauth['token'] = psc_get_goog_token( $oauth['code'] );
}
else if ( !empty($_REQUEST['error']) ) {
$oauth['error'] = $_REQUEST['error'];
}
if ( !empty( $_REQUEST['state'] ) )
do_action('psc_goog_state_' . $_REQUEST['state'], $oauth );
// if we made it here, then the action didn't do anything so redirect to the home page
wp_redirect( home_url() );
}
}
add_action('template_redirect','psc_goog_oauth_catcher');
function psc_get_goog_token($code, $refresh=false) {
$options = get_option('psc_options');
if ($refresh) {
$req['refresh_token'] = $code;
} else {
$req['code'] = $code;
}
$req['client_id'] = $options['goog_appid'];
$req['client_secret'] = $options['goog_app_secret'];
if (!$refresh) {
$req['redirect_uri'] = home_url( $options['goog_oauthcallback'] );
}
if ($refresh) {
$req['grant_type'] = 'refresh_token';
} else {
$req['grant_type'] = 'authorization_code';
}
$args['sslverify'] = false;
$args['body'] = $req;
$data = wp_remote_post('https://accounts.google.com/o/oauth2/token', $args);
if ( is_wp_error( $data ) || wp_remote_retrieve_response_code( $data ) != 200 ) {
return false;
}
$resp = json_decode( wp_remote_retrieve_body( $data ), true );
return $resp;
}
function psc_get_goog_userinfo($token) {
$headers['Authorization'] = 'Bearer '.$token;
$request['headers'] = $headers;
$request['sslverify'] = false;
$data = wp_remote_get('https://www.googleapis.com/oauth2/v1/userinfo', $request);
if ( is_wp_error( $data ) || 200 != wp_remote_retrieve_response_code( $data ) )
return false;
$resp = json_decode( wp_remote_retrieve_body( $data ), true );
return $resp;
}
/*
* Google Comments (sgc-comments.php)
*
*/
function psc_goog_button() {
?>
<div id="google-connect" class="button">
<p><a href="#"><span>Sign In with </span>Google</a></p>
</div>
<?php
}
add_action('psc_add_button', 'psc_goog_button');
function psc_goog_load_args() {
if( comments_open() && !is_user_logged_in() ) {
$options = get_option('psc_options');
$defaults = array(
'callback' => 'googSignInCallback',
'clientid' => $options['goog_appid'],
'cookiepolicy' => 'single_host_origin',
'requestvisibleactions' => 'http://schemas.google.com/AddActivity',
'scope' => 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/plus.login'
);
$args = apply_filters( 'psc_goog_args', $defaults );
$args = wp_parse_args($args, $defaults);
?>
var googArgs = <?=json_encode($args);?>
<?php
}
};
add_action('psc_footer_script','psc_goog_load_args', 20); // 20, to put it at the end of the footer insertions. sub-plugins should use 30 for their code
// Add user fields for Google based commenters
function psc_goog_inject_comment_data($comment_post_ID) {
if ( is_user_logged_in() ) {
return; // do nothing to WP users
}
if ( empty( $_POST['psc_goog_token'] ) ) {
return;
}
$token = $_POST['psc_goog_token'];
global $goog_user;
if ( empty($goog_user) ) {
$goog_user = psc_get_goog_userinfo($token);
}
if ( !$goog_user ) {
return;
}
$goog_user = apply_filters('psc_goog_user_data', $goog_user);
//$_POST['author'] = $goog_user['name'];
$_POST['url'] = 'https://plus.google.com/' . $goog_user['id'] . '/';
$_POST['email'] = $goog_user['email'];
}
add_filter('pre_comment_on_post','psc_goog_inject_comment_data');
// store the user ID and picture as comment meta data
function psc_goog_store_metadata($comment_id) {
global $goog_user;
if ( empty($goog_user) || !isset($goog_user['id']) ) {
return;
}
update_comment_meta($comment_id, 'googleid', $goog_user['id']);
update_comment_meta($comment_id, 'googlepicture', 'https://plus.google.com/s2/photos/profile/' . $goog_user['id']);
}
add_action('comment_post','psc_goog_store_metadata', 10, 1);
// generate avatar code for Google user comments
function psc_goog_avatar($avatar, $id_or_email, $size = '96', $default = '', $alt = false) {
// check to be sure this is for a comment
if ( !is_object($id_or_email) || !isset($id_or_email->comment_ID) || $id_or_email->user_id) {
return $avatar;
}
// check for google picture comment meta
$gp = get_comment_meta($id_or_email->comment_ID, 'googlepicture', true);
if ($gp) {
// return the avatar code
$avatar = "<img class='avatar avatar-{$size} google-avatar' src='{$gp}?sz={$size}' width='{$size}' height='{$size}' />";
}
return $avatar;
}
add_filter('get_avatar','psc_goog_avatar', 10, 5);
<?php
/*
Plugin Name: Pew Social Connect
Description: Makes it easy for your site to use Facebook Connect, Google Connect, in a wholly modular way. Based on Simple Facebook Connect (http://ottopress.com/wordpress-plugins/simple-facebook-connect/) by Otto
Author: Russell Heimlich
Version: 0.1
Author URI: http://www.russellheimlich.com
License: GPL2
*/
// psc_ = Pew Social Connect
include 'facebook-connect.php';
include 'google-connect.php';
// Add the single sign-on container and load the button HTML.
function pew_social_connect() {
?>
<div id="single-sign-on" class="hide">
<?php do_action('psc_add_button', ''); ?>
</div>
<p class="or hide"><span>Or</span></p>
<?php
}
function pew_social_connect_footer() {
global $post;
if( is_single() && $post->comment_status === 'open' ):
?>
<script type="text/javascript">
var fbArgs, googArgs;
<?php do_action('psc_footer_script'); ?>
</script>
<?php
endif;
}
add_action('wp_footer','pew_social_connect_footer', 1);
// add the admin settings and such
function psc_admin_init() {
$options = get_option('psc_options');
if (empty($options['fb_app_secret']) || empty($options['fb_appid'])) {
add_action('admin_notices', create_function( '', "echo '<div class=\"error\"><p>" . sprintf('Facebook Connect needs configuration information on its <a href="%s">settings</a> page.', admin_url('options-general.php?page=pew-socialconnect')) . "</p></div>';" ) );
}
if (empty($options['goog_app_secret']) || empty($options['goog_appid'])) {
add_action('admin_notices', create_function( '', "echo '<div class=\"error\"><p>".sprintf('Google Connect needs configuration information on its <a href="%s">settings</a> page.', admin_url('options-general.php?page=pew-socialconnect'))."</p></div>';" ) );
}
wp_enqueue_script('jquery');
register_setting( 'psc_options', 'psc_options', 'psc_options_validate' );
add_settings_section('psc_fb', 'Facebook', 'psc_fb_section_text', 'psc_fb_section');
if (!defined('PSC_FB_APP_ID')) {
add_settings_field('psc_fb_appid', 'Facebook Application ID', 'psc_setting_fb_appid', 'psc_fb_section', 'psc_fb');
}
if (!defined('PSC_FB_APP_SECRET')) {
add_settings_field('psc_fb_app_secret', 'Facebook Application Secret', 'psc_setting_fb_app_secret', 'psc_fb_section', 'psc_fb');
}
add_settings_section('psc_goog', 'Google Plus', 'psc_goog_section_text', 'psc_goog_section');
if (!defined('PSC_GOOG_APP_ID')) {
add_settings_field('psc_goog_appid', 'Google Client ID', 'psc_setting_goog_appid', 'psc_goog_section', 'psc_goog');
}
if (!defined('PSC_GOOG_APP_SECRET')) {
add_settings_field('psc_goog_app_secret', 'Google Client Secret', 'psc_setting_goog_app_secret', 'psc_goog_section', 'psc_goog');
}
add_settings_field('psc_goog_oauth2callback', 'Google OAuth2 Callback', 'psc_setting_goog_oauthcallback', 'psc_goog_section', 'psc_goog');
}
add_action('admin_init', 'psc_admin_init', 9); // 9 to force it first, subplugins should use default
// add the admin options page
function psc_admin_add_page() {
global $psc_options_page;
$psc_options_page = add_options_page( 'Pew Social Connect', 'Pew Social Connect', 'manage_options', 'pew-socialconnect', 'psc_options_page');
}
add_action('admin_menu', 'psc_admin_add_page');
// display the admin options page
function psc_options_page() {
?>
<div class="wrap">
<?php screen_icon(); ?>
<h2>Pew Social Connect</h2>
<form method="post" action="options.php">
<?php settings_fields('psc_options'); ?>
<?php do_settings_sections('psc_fb_section'); ?>
<?php do_settings_sections('psc_goog_section'); ?>
<?php submit_button(); ?>
</form>
</div>
<?php
}
// Individual Settings Fields.
function psc_setting_fb_appid() {
if (defined('PSC_FB_APP_ID')) return;
$options = get_option('psc_options');
echo "<input type='text' id='psc-fb-appid' name='psc_options[fb_appid]' value='{$options['fb_appid']}' size='40' /> ";
}
function psc_setting_fb_app_secret() {
if (defined('PSC_FB_APP_SECRET')) return;
$options = get_option('psc_options');
echo "<input type='text' id='psc-fb-appsecret' name='psc_options[fb_app_secret]' value='{$options['fb_app_secret']}' size='40' /> ";
}
function psc_setting_goog_appid() {
if (defined('PSC_GOOG_APP_ID')) return;
$options = get_option('psc_options');
echo "<input type='text' id='psc-goog-appid' name='psc_options[goog_appid]' value='{$options['goog_appid']}' size='100' /> ";
}
function psc_setting_goog_app_secret() {
if (defined('PSC_GOOG_APP_SECRET')) return;
$options = get_option('psc_options');
echo "<input type='text' id='psc-goog-appsecret' name='psc_options[goog_app_secret]' value='{$options['goog_app_secret']}' size='40' /> ";
}
function psc_setting_goog_oauthcallback() {
$options = get_option('psc_options');
if ( empty( $options['goog_oauthcallback'] ) ) $options['goog_oauthcallback'] = "oauth2callback";
echo home_url('/')." <input type='text' id='psc-goog-oauthcallback' name='psc_options[goog_oauthcallback]' value='{$options['goog_oauthcallback']}' size='30' /><br />";
echo "You can use this field to change the callback endpoint. If you don't know what that means, leave it set to 'oauth2callback'. <br /> (Note: Setting this value incorrectly will break the plugin.)";
}
//Section Text
function psc_fb_section_text() {
$options = get_option('psc_options');
if (empty($options['fb_app_secret']) || empty($options['fb_appid'])) {
?>
<p>To connect your site to Facebook, you will need a Facebook Application. If you have already created one, please insert your Application Secret and Application ID below.</p>
<p><strong>Can't find your key?</strong></p>
<ol>
<li>Get a list of your applications from here: <a target="_blank" href="https://developers.facebook.com/apps">Facebook Application List</a></li>
<li>Select the application you want, then copy and paste the Application Secret and Application ID from there.</li>
</ol>
<p><strong>Haven't created an application yet?</strong> Don't worry, it's easy!</p>
<ol>
<li>Go to this link to create your application: <a target="_blank" href="https://developers.facebook.com/apps">Facebook Application Setup</a></li>
<li>After creating the application, put <strong><?= home_url('/'); ?></strong> in as the Site URL in the Website section.</li>
<li>You can get the API information from the application on the
<a target="_blank" href="https://developers.facebook.com/apps">Facebook Application List</a> page.</li>
<li>Select the application you created, then copy and paste the Application Secret and Application ID from there.</li>
</ol>
<?php
}
}
function psc_goog_section_text() {
$options = get_option('psc_options');
if (empty($options['goog_app_secret']) || empty($options['goog_appid'])) {
?>
<h3>Connecting to Google</h3>
<p>To connect your site to Google, you will first need to create a Google Application.
If you have already created one, please insert your Client ID and Client Secret below.</p>
<h3>Quick Link</h3>
<p><a target='_blank' href='https://code.google.com/apis/console/'>Google API Console</a></p>
<h3>Detailed Setup Instructions</h3>
<ol>
<li>First, visit the Google API Console: <a target='_blank' href='https://code.google.com/apis/console/'>Google API Console</a>.</li>
<li>Here, you will need to create a new project. Name the project using the name of your website, to make it easy to find later.</li>
<li>In the Services section, you will need to turn on the 'Google+ API' to enable the plugin to get information from Google+.</li>
<li>On the 'API Access' Tab, click the 'Create an OAuth 2.0 client ID' button.</li>
<li>The 'Product name' will be the name of your website. You can also upload a logo if you wish (you can do this later if you want).</li>
<li>The 'Application type' should be 'Web Application' and put in the address of your application. <br />
Also don't forget to select http or https correctly for the address of your website, if you choose incorrectly it will not work.</li>
<li>Note that you must put in your website's URL <strong>exactly</strong>. If your website doesn't actually have a www in it, then <em>don't put one in there</em>.</li>
<li>For reference, your website's url is <strong><?=home_url('/');?></strong> and this must be <em>exactly</em> what you enter into this screen.</li>
<li>The Redirect URI will thus be <strong><?=home_url('/' . $options['goog_oauthcallback']);?></strong>. If you see anything else, then you've entered your URL wrong.</li>
<li>Finally, after you click the 'Create ID' button, you will find the Client ID and Client Secret fields. Copy and paste those onto this configuration screen.</li>
</ol>
<?php
}
}
// this will override all the main options if they are pre-defined
function psc_override_options($options) {
if ( defined('PSC_FB_APP_SECRET') ) {
$options['fb_app_secret'] = PSC_FB_APP_SECRET;
}
if ( defined('PSC_FB_APP_ID') ) {
$options['fb_app_secret'] = PSC_FB_APP_SECRET;
}
if (defined('PSC_GOOG_APP_SECRET')) {
$options['goog_app_secret'] = PSC_GOOG_APP_SECRET;
}
if (defined('PSC_GOOG_APP_ID')) {
$options['goog_app_secret'] = PSC_GOOG_APP_SECRET;
}
return $options;
}
add_filter('option_psc_options', 'psc_override_options');
// validate our options
function psc_options_validate($input) {
if (!defined('PSC_FB_APP_SECRET')) {
// secrets are 32 bytes long and made of hex values
$input['fb_app_secret'] = trim($input['fb_app_secret']);
if ( !preg_match('/^[a-f0-9]{32}$/i', $input['fb_app_secret']) ) {
$input['fb_app_secret'] = '';
}
}
if (!defined('PSC_FB_APP_ID')) {
// app ids are big integers
$input['fb_appid'] = trim($input['fb_appid']);
if ( !preg_match('/^[0-9]+$/i', $input['fb_appid']) ) {
$input['fb_appid'] = '';
}
}
if ( empty( $input['goog_oauthcallback'] ) ) {
$input['goog_oauthcallback'] = "oauth2callback";
}
$input = apply_filters('psc_options_validate', $input); // filter to let sub-plugins validate their options too
// flush the rules to make sure the callback sticks
flush_rewrite_rules(false);
return $input;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment