3
\$\begingroup\$

I have to create open source code that allows a user to login to Facebook through an app and attaches that app's messenger bot to the user's pages. I have never written open source code before so I would like suggestions on how to improve the code.

<?php
require_once("/home/vjukebox/public_html/vendor/autoload.php");

define("FB_APP_ID",'App Id Goes Here');
define("FB_APP_SECRET",'App Secret Goes Here');
define("WIT_API_KEY",'Wit API key goes here');

use Facebook\FacebookRequest;

$fb = new Facebook\Facebook([
  'app_id'     => FB_APP_ID,//insert app id
  'app_secret' => FB_APP_SECRET,//app secret
  'default_graph_version' => 'v2.10',
  ]);
  $fbApp = $fb->getApp();
    if (isset($_POST['data'],$_POST['userToken'])) {
        $userToken = $_POST['userToken'];
        foreach ($_POST['data'] as $pageData) {
            $pageToken = $pageData["access_token"];

            $request = $fb->request('POST', '/me/subscribed_apps');//subscribe the user to you app
            $request->setAccessToken($pageToken);
            try {
                $response = $fb->getClient()->sendRequest($request);
            } catch (Facebook\Exceptions\FacebookResponseException $e) {
                // When Graph returns an error
                echo 'Graph returned an error: ' . $e->getMessage();
                exit;
            } catch (Facebook\Exceptions\FacebookSDKException $e) {
                // When validation fails or other local issues
                echo 'Facebook SDK returned an error: ' . $e->getMessage();
                exit;
            }
        }

        /*exchange user's short term access token for the user's
         long term access token*/
        $request = $fb->request('POST', '/oauth/access_token');
        $request->setAccessToken($userToken);
        $request->setParams(array(
              'grant_type' => 'fb_exchange_token',
              'client_id' => FB_APP_ID,
              'client_secret' => FB_APP_SECRET,
              'fb_exchange_token' => $userToken
          ));
        try {
            $response = $fb->getClient()->sendRequest($request);
        } catch (Facebook\Exceptions\FacebookResponseException $e) {
            // When Graph returns an error
            echo 'Graph returned an error: ' . $e->getMessage();
            exit;
        } catch (Facebook\Exceptions\FacebookSDKException $e) {
            // When validation fails or other local issues
            echo 'Facebook SDK returned an error: ' . $e->getMessage();
            exit;
        }
        $responseArr = $response->getDecodedBody();
        $longUserToken = $responseArr["access_token"];

        //get user's page data
        $request = $fb->request('GET', '/me/accounts');
        $request->setAccessToken($longUserToken);
        try {
            $response = $fb->getClient()->sendRequest($request);
        } catch (Facebook\Exceptions\FacebookResponseException $e) {
            // When Graph returns an error
            echo 'Graph returned an error: ' . $e->getMessage();
            exit;
        } catch (Facebook\Exceptions\FacebookSDKException $e) {
            // When validation fails or other local issues
            echo 'Facebook SDK returned an error: ' . $e->getMessage();
            exit;
        }
        $responseArr = $response->getDecodedBody();

        //iterate through pages, save data to database
        foreach ($responseArr["data"] as $pageData) {
            $pageName = $pageData["name"];
            $facebookPageId = $pageData["id"];
            $longPageToken = $pageData["access_token"];

            //Attach your wit api key if using NLP
            $request = $fb->request('POST', '/me/nlp_configs');
            $request->setAccessToken($longPageToken);
            $request->setParams(array(
                  'nlp_enabled' => 'true',
                  'custom_token' =>WIT_API_KEY
              ));

            try {
                $response = $fb->getClient()->sendRequest($request);
            } catch (Facebook\Exceptions\FacebookResponseException $e) {
                // When Graph returns an error
                echo 'Graph returned an error: ' . $e->getMessage();
                exit;
            } catch (Facebook\Exceptions\FacebookSDKException $e) {
                // When validation fails or other local issues
                echo 'Facebook SDK returned an error: ' . $e->getMessage();
                exit;
            }
            $responseArr = $response->getDecodedBody();

            /*
            Store the data into a database of your chosing
            */
        }
        die();
    }

?>

<body>
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script>
  window.fbAsyncInit = function() {
    FB.init({
      appId            : '<? echo FB_APP_ID ?>',
      autoLogAppEvents : true,
      xfbml            : true,
      version          : 'v2.10'
    });
    FB.AppEvents.logPageView();
  };

  function checkLoginState() {
      FB.getLoginStatus(function(response) {
        if (response.status === 'connected') {
          console.log('Logged in.');
          var userToken = FB.getAccessToken();
          FB.api('/me/accounts', function(accountResponse) {
              //accountResponse.data.access_token;
              var pageAccess = accountResponse.data[0].access_token;
              $.ajax({
                  type:"POST",
                  url: "facebookpages.php",
                  data:{
                      userToken:userToken,
                      data:accountResponse.data
                  },
                  success:function(data){
                      alert(data) //for debugging
                  },
                  error:function(data){
                  }
              });
          });
        }
        else {
            FB.login();
        }
      });
  }

  (function(d, s, id){
     var js, fjs = d.getElementsByTagName(s)[0];
     if (d.getElementById(id)) {return;}
     js = d.createElement(s); js.id = id;
     js.src = "//connect.facebook.net/en_US/sdk.js";
     fjs.parentNode.insertBefore(js, fjs);
 }(document, 'script', 'facebook-jssdk'));
</script>
<!--chose the scopes you want the user to log in with-->
<fb:login-button scope="public_profile,manage_pages,pages_messaging,pages_messaging_subscriptions,pages_show_list,pages_manage_cta" onlogin="checkLoginState();">
</fb:login-button>

</body>
\$\endgroup\$
2
\$\begingroup\$

Overall this feels like a lot of code thrown together. It isn't totally unorganized but feels like a lot to process when reading it. I do notice that most every try/catch block has the same exception handlers.

One improvement might be to make a controller class that can accept POST data and then have methods like subscribeUserToApp(), getAccessToken(), getAccounts() and then getNLPConfigs(). And each method could utilize a common method for making the request and catching the exceptions. Then those methods could be called from the page (facebookpages.php?) in series unless one throws an exception.

The controller could also store the constants (e.g. FB_APP_ID) for use in its methods.


Let's look at this loop:

foreach ($_POST['data'] as $pageData) {
    $pageToken = $pageData["access_token"];

    $request = $fb->request('POST', '/me/subscribed_apps');//subscribe the user to you app

Does the call to $fb->request() really need to be inside the foreach loop? If that can be called once before the loop, then it would not be called once for each item in the data list (though it isn't clear what that list looks like - perhaps it only has one item). But I understand that maybe calling that request and then calling setAccessToken() multiple times (in the foreach loop) would not succeed when it should.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.