...
"

How to create a WordPress plugin to login and register using Facebook API – Part 2

blog-img
blog-img
blog-img

As promised, here is the part 2 of our tutorial to create a Facebook WordPress plugin. Thanks a lot for your feedback.

Be sure to checkout part 1 before

Before starting off, a special thanks to Ovidiu Turean who made a pull request to the repository for the admin side developed in this part 2.

The complete code of this tutorial can be found in the same repository as part 1 under the branch V2.

So what’s on our agenda?

  1. Simple AJAX powered admin page to save the Facebook app ID and secret
  2. Sending an email upon new registration in order to provide the password and username to the user
  3. CSS styling of our Facebook button

Improvement 1: creating a new WordPress page for the plugin Settings

In order to create an admin page for our plugin, we will need to re-organize it so everything is clean and make sense.

So what did we changed?

  • alka-facebook.php is the plugin main file, it’s the one called by WordPress whenever the plugin is loaded
  • assets/ is a folder that will contain all our images, javaScript files as well as stylesheets (.css)
  • classes/ contains 2 classes called in alka-facebook.php, one for the API connection and user creation / login. The other is only for the admin page.

Let’s dive in the details by starting with the main file:

/**
 * Class AlkaAdmin
 *
 * This class creates a very simple Options page
 */
class AlkaAdmin
{
  /**
   * The security nonce
   *
   * @var string
   */
  private $_nonce = 'alka_facebook_admin';
  /**
   * AlkaAdmin constructor.
   */
  public function __construct()
{
    add_action( 'admin_menu', array( $this, 'addAdminMenu' ) );
    add_action( 'wp_ajax_alka_store_admin_creeds', array( $this, 'storeFacebookAdminCreeds' ) );
    add_action( 'admin_enqueue_scripts', array( $this, 'addAdminScripts' ) );
  }
}
/*
 * Starts our admin class, easy!
 */
new AlkaAdmin();

As you can see, the main difference with part 1 is that this file is just here to call other files. The Facebook SDK and then our plugin classes. We define as well 2 constants that will be used to retrieve the different files within the plugin.

  • ALKA_FACEBOOK_PATH for the PHP includes
  • ALKA_FACEBOOK_URL for the .js, .css and image calls from our browsers

Once this done, we can create our admin page, using the brand new AlkaAdmin.php file. Our admin page is really simple, 2 fields (Facebook App ID, Facebook App Secret), the callback URL to help the user.

We save everything using AJAX so we don’t have to reload the page. Therefore we will also use a WordPress Nonce to add an extra security layer.


/**
* Class AlkaAdmin
*
* This class creates a very simple Options page
*/
class AlkaAdmin
{/** * The security nonce * * @var string */
private $_nonce = 'alka_facebook_admin'; /** * AlkaAdmin constructor. */
public function __construct()
{
add_action('admin_menu', array($this, 'addAdminMenu'));
add_action('wp_ajax_alka_store_admin_creeds', array($this, 'storeFacebookAdminCreeds'));
add_action('admin_enqueue_scripts', array($this, 'addAdminScripts'));
}
}

/** Starts our admin class, easy! */
new AlkaAdmin();

So as you can see our class’s constructor will call 3 main methods: addAdminMenu, storeFacebookAdminCreeds and addAdminScripts.

Firstly, we use addAdminMenu to register our new page for WordPress:

/**
 * Adds Alka to WordPress Admin Sidebar Menu
 */
public function addAdminMenu() {
    add_menu_page(
        __( 'Alka Facebook', 'alkaweb' ),
        __( 'Alka Facebook', 'alkaweb' ),
        'manage_options',
        'alka_facebook',
        array( $this, 'adminlayout' ),
        ''
    );
}

As you can see, there is another callback to a new method (adminlayout) that will handle the HTML displayed within this page. You can load an other file to make your plugin even cleaner.

For the sake of simplicity, the HTML will be loaded within the class method (boooo…)

/**
 * Outputs the Admin Dashboard layout
 */
public function adminlayout() {
    $facebook_creeds = AlkaFacebook::getCredentials();
    $alka_app_id = (isset($facebook_creeds['app_id']) && !empty($facebook_creeds['app_id'])) ? $facebook_creeds['app_id'] : '';
    $alka_app_secret = (isset($facebook_creeds['app_secret']) && !empty($facebook_creeds['app_secret'])) ? $facebook_creeds['app_secret'] : '';
    ?>
    <div class="wrap">
        <h3><?php _e( 'Facebook API Settings', 'alkaweb' ); ?></h3>
        <table class="form-table">
            <tbody>
            <tr>
                <td>
                    <label><?php _e( 'Your callback url', 'alkaweb' ); ?></label>
                </td>
                <td>
                    <span class="highlight"><?php echo AlkaFacebook::getCallbackUrl(); ?></span>
                </td>
            </tr>
            <tr>
                <td scope="row">
                    <label><?php _e( 'Facebook App ID', 'alkaweb' ); ?></label>
                </td>
                <td>
                    <input id="alka-fb-app-id" class="regular-text" value="<?php echo $alka_app_id; ?>"/>
                </td>
            </tr>
            <tr>
                <td>
                    <label><?php _e( 'Facebook App Secret', 'alkaweb' ); ?></label>
                </td>
                <td>
                    <input id="alka-fb-app-secret" class="regular-text" value="<?php echo $alka_app_secret; ?>"/>
                </td>
            </tr>
            <tr>
                <td colspan="2">
                    <button class="button button-primary" id="alkaweb-facebook-details"><?php _e( 'Submit', 'alkaweb' ); ?></button>
                </td>
            </tr>
            </tbody>
        </table>
    </div>
    <?php
}

The 2 static methods we call from the AlkaFacebook class (see part 1 of this tutorial) will be defined later:

  • AlkaFacebook::getCredentials() returns the saved credentials from the database as an array
  • AlkaFacebook::getCallbackUrl() returns the callback URL that must be provided  to Facebook through the app portal

Once this done, we can enjoy a clean admin page for our plugin:

But nothing happen when we click the save button so far, which is (let’s be honest) quite an issue!

In order to save the data, we’ll add a javaScript file to the WordPress admin using the method: addAdminScripts(). This file will just “listen” to the admin actions, whenever the button is pushed, a request is made to your server. WordPress will redirect the request to our class’s method storeFacebookAdminCreeds(). That easy.

We enqueue our new javaScript file: assets/js/admin.js (you need to create it) using our constant define earlier.

/**
 * Adds Admin Scripts for the Ajax call
 */
public function addAdminScripts() {
    wp_enqueue_script( 'alka-facebook-admin', ALKA_FACEBOOK_URL. '/assets/js/admin.js', array(), 1.0 );
    $admin_options = array(
        'ajax_url' => admin_url( 'admin-ajax.php' ),
        '_nonce'   => wp_create_nonce( $this->_nonce ),
    );
    wp_localize_script( 'alka-facebook-admin', 'alka_facebook_admin', $admin_options );
}

As you can see we also pass 2 PHP variables to our JS file using an object  named: alka_facebook_admin.

We can know fill in the JavaScript file, we watch for the user click, build our request and send it using Ajax:

/**
 * Alka Facebook Saving process
 */
jQuery( document ).ready( function () {
    jQuery( document ).on( 'click', '#alkaweb-facebook-details', function ( e ) {
        e.preventDefault();
        var _app_id = jQuery( '#alka-fb-app-id' ).val(),
            _app_seccret = jQuery( '#alka-fb-app-secret' ).val();
        jQuery.ajax( {
            url: alka_facebook_admin.ajax_url,
            type: 'post',
            data: {
                action: 'alka_store_admin_creeds',
                security: alka_facebook_admin._nonce,
                app_id: _app_id,
                app_secret: _app_seccret
            },
            success: function ( response ) {
                alert(response);
            }
        } );
    } );
} );

The result is displayed through a basic alert(), but this can be changed with something more user friendly of course.

It’s now time to save the data we received from the page in our database using a handy method: storeFacebookAdminCreeds() which is linked to our WordPress ajax hook: alka_store_admin_creeds sent in our request. This is possible with this action we’ve added at the beginning in our constructor:

add_action( 'wp_ajax_alka_store_admin_creeds', array( $this, 'storeFacebookAdminCreeds' ) );

So the method below just takes the data sent through the Ajax request, validate them and save them in the wp_options table.

/**
 * Callback for the Ajax request
 *
 * Updates the FaceBook App ID and App Secret options
 */
public function storeFacebookAdminCreeds() {
    if ( wp_verify_nonce( $_POST['security'], $this->_nonce ) === false ) {
        die( 'Invalid Request!' );
    }
    if (
            (isset($_POST['app_id']) && !empty($_POST['app_id']))
            &&
            (isset($_POST['app_secret']) && !empty($_POST['app_secret']))
    ) {
        update_option( 'alka_facebook', array(
            'app_id'     => $_POST['app_id'],
            'app_secret' => $_POST['app_secret'],
        ) );
    }
    echo __('Saved!', 'Alkaweb');
    die();
}

That’s it! We can now receive and save the Facebook App ID as well as the Facebook App Secret from the WordPress admin dashboard. Cool! 

We now need to update the AlkaFacebook.php class defined in part 1 of this tutorial to no longer use private attributes but rather our saved option. In order to get the Facebook App ID and secret.

In the same way, we will create the method that returns the site callback url for Facebook (which was also an attribute before):

/**
 * Returns the Facebook credentials as an array containing app_id and app_secret
 *
 * @return array
 */
static function getCredentials() {
   return get_option( 'alka_facebook', array() );
}
/**
 * Returns the callback URL
 *
 * @return string
 */
static function getCallbackUrl() {
   return get_admin_url( null, 'admin-ajax.php?action=alka_facebook' );
}

We can now use them by re-defining our methods within the same class:

/**
 * Login URL to Facebook API
 *
 * @return string
 */
private function getLoginUrl() {
    if(!session_id()) {
        session_start();
    }
    $fb = $this->initApi();
    $helper = $fb->getRedirectLoginHelper();
    // Optional permissions
    $permissions = ['email'];
    $url = $helper->getLoginUrl(self::getCallbackUrl(), $permissions);
    return esc_url($url);
}

And lastly, for the credentials:

/**
 * Init the API Connection
 *
 * @return Facebook
 */
private function initApi() {
   $credentials = self::getCredentials();
   // Only if we have some credentials, ideally an Exception would be thrown here
   if(!isset($credentials['app_id']) || !isset($credentials['app_secret']))
      return null;
    $facebook = new Facebook([
        'app_id' => $credentials['app_id'],
        'app_secret' => $credentials['app_secret'],
        'default_graph_version' => 'v2.2',
        'persistent_data_handler' => 'session'
    ]);
    return $facebook;
}

Done! Our API connection is now using our options from the plugin’s options page.

You can test on your side to make sure it’s working as expected.

Improvement 2: sending the email to the user

For this one, you will need server to get the email sent as your Localhost probably don’t have any email driver.

We are simply gonna add a new method in createUser() method after the meta and before we log in the user.

// Setting the meta
update_user_meta( $new_user_id, 'first_name', $fb_user['first_name'] );
update_user_meta( $new_user_id, 'last_name', $fb_user['last_name'] );
update_user_meta( $new_user_id, 'user_url', $fb_user['link'] );
update_user_meta( $new_user_id, 'alka_facebook_id', $fb_user['id'] );
// Send a validation email
$this->sendConfirmation($username, $password, $fb_user['email']);
// Log the user ?
wp_set_auth_cookie( $new_user_id );

Now, it’s time to create this new method in our AlkaFacebook class:

/**
 * Sends a confirmation email to the new user
 *
 * @param string $username
 * @param string $password
 * @param string $email
 */
private function sendConfirmation($username, $password, $email) {
    $subject = __('Welcome! Your account has been created!', 'alkaweb');
    $headers = array('Content-Type: text/html; charset=UTF-8');
    $body = '';
    $body .= __('Your friends from', 'alkaweb') . ': <a href="' . get_site_url() . '">' . get_site_url() . '</a><br>';
    $body .= __('We are please to announce that your account has been successfully created!', 'alkaweb') . '</br>';
    $body .= __('You can login at anytime with your Facebook account, you can also always use the following credentials', 'alkaweb') .': <br>';
    $body .= __('User', 'alkaweb') . ': <b>' . $username . '</b><br>';
    $body .= __('Password', 'alkaweb') . ': <b>' . $password . '</b><br><br>';
    $body .= __('Thanks', 'alkaweb');
    wp_mail( $email, $subject, $body, $headers );
}

We simply use the wp_mail() function from WordPress to do the job for us. This function requires 4 parameters, you can find all the details on the documentation page related to that function.

You are free to customize the content and even design your own template. Note that we pass the username, password and email as method arguments to be sure we send the right data.

Improvement 3: designing our button

In part 1, the shortcode was just displaying a simple link, we’ll create a brand new button that’d impress any of your visitor.

The first thing we want to do it to change the shortcode’s HTML output:

/**
 * Render the shortcode [alka_facebook/]
 *
 * It displays our Login / Register button
 */
public function renderShortcode() {
    //... Same as Part 1
    // Button
    $logo = '<img src="'. ALKA_FACEBOOK_URL. '/assets/images/fb-logo.png" alt="Facebook logo">';
    $html .= '<a href="'.$this->getLoginUrl().'" class="btn" id="alka-facebook-button">'. $logo . $button_label .'</a>';
    $html .= '</div>';
    // Write it down
    return $html;
}

As you can see we’re adding a new icon, which can done be downloaded from the Facebook Brand Resources page. Pick up any icon from the .zip your download (possibly a white one) and place it in assets/images/, renamed as fb-logo.png.

We can also create a new css file assets/css/button-style.css:

/**
 * CSS for the Alka Facebook plugin
 */
#alka-facebook-wrapper{
    margin: 20px 0;
}
#alka-facebook-wrapper a#alka-facebook-button{
    color: #FFF;
    background: #3b5998;
    border-radius: 5px;
    box-shadow: 0 5px 0 0 #091e57;
    padding: 10px 30px 20px 30px;
    text-decoration: none;
    display: inline-block;
}
#alka-facebook-wrapper a#alka-facebook-button img{
    box-shadow: none;
    width: 30px;
    padding-right: 30px;
    box-sizing: content-box;
    display: inline-block;
    position: relative;
    bottom: -10px;
}

We now need to add our new css file whenever the page is loader. Similarly to the admin side, we just create a new action in the AlkaFacebook class’s constructor

// Add our button css file
add_action( 'wp_enqueue_scripts', array($this, 'addButtonCSS'));

So it looks like:

/**
 * AlkaFacebook constructor.
 */
public function __construct()
{
    // We register our shortcode
    add_shortcode( 'alka_facebook', array($this, 'renderShortcode') );
    // Start the session
    add_action( 'template_redirect', array($this, 'sessionInit') );
    // Callback URL
    add_action( 'wp_ajax_alka_facebook', array($this, 'apiCallback'));
    add_action( 'wp_ajax_nopriv_alka_facebook', array($this, 'apiCallback'));
    // Add our button css file
    add_action( 'wp_enqueue_scripts', array($this, 'addButtonCSS'));
}

We just have to enqueue the stylesheet with the method: addButtonCSS()

/**
 * Enqueue the plugin's css file
 */
public function addButtonCSS() {
    wp_enqueue_style( 'alka-facebook-button', ALKA_FACEBOOK_URL. '/assets/css/button-style.css' );
}

Here again, we are making great use of the constants defined at the beginning of this tutorial.

This is the expected result on a new page called “Facebook” containing only the shortcode. On the default WordPress theme:

Lastly, regarding the Facebook avatar and how to get it upon registration, well we didn’t build it in this part for a simple reason. As or right now, I have looked several plugins doing so and I find the process very “barbarian”. It’s just a filter on the get_avatar() function  to replace the path with a link to Facebook containing the user ID. Simply because it’s managed by Gravatar on WordPress. It’d be better, if we do it, to focus only on BuddyPress as their is a deeper avatar integration. With an upload process for example, which is not here by default on WordPress.

Any question? Fire away in the comments 🙂

blog-img
blog-img

Comments 12

  • And also it doesn’t work if callback was set into http://localhost/site/wp-admin/admin-ajax.php?action=alka_facebook . It only works if the button is located in the same call back URL

    • Hello,
      What do you mean by “the button is located in the same call back URL”? That callback is what you should provide to Facebook and is not a page. It’s a resource to handle the Facebook request.

    • Hello,
      Where do you get that error? That is likely coming from:
      $_SESSION['alka_facebook_message'] = $new_user_id->get_error_message();
      It means that the generated username:
      $username = sanitize_user(str_replace(' ', '_', strtolower($this->facebook_details['name'])));
      Is creating an username that already exists on your side but it cannot be logged in because it was not created through Facebook.
      You can prefix it to avoid that: $username .= 'fb_'.$username;
      Cheers

  • since the plugin store the session token, can we use it to retrieve the updated fb user’s profile info again?

  • Hi Thanks it looks like very simple, I have tried this but I get an error 500 when redirect (wp-admin/admin-ajax.php?action=alka_facebook&code=AQAbYiOr8maim7EYUzp8Me…….) do you have any idea?
    Thanks!

  • Hi
    Actually i want to make something like that too, i want to get access token (which never expires) to fetch feeds of user facebook page, can you help me with that? or you can write any exmaple for me? same this way that user click on Login with Facebook Button and it ask permission to give access and then it bring back access token
    Thanks

  • Hey,
    Thank you for this guide, everything is working perfectly. My only problem is that the facebook login form opens in a new tab. Is it possible to make it appear as a pop-up, like it normally does if you use Javascript SDK? Thanks for your answer

Comments are closed.