WordPress.org

Plugin Directory

Changeset 457935


Ignore:
Timestamp:
10/31/11 18:04:41 (2 years ago)
Author:
hd-J
Message:

Update to latest Facebook PHP SDK, handle featured image differently, fix bugs

Location:
wp-facebook-applications/trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • wp-facebook-applications/trunk/lib/facebook.php

    r382711 r457935  
    11<?php 
    22/** 
    3  * 
    43 * Copyright 2011 Facebook, Inc. 
    54 * 
     
    1716 */ 
    1817 
    19 if (!function_exists('curl_init')) { 
    20   throw new Exception('Facebook needs the CURL PHP extension.'); 
    21 } 
    22 if (!function_exists('json_decode')) { 
    23   throw new Exception('Facebook needs the JSON PHP extension.'); 
    24 } 
     18require_once "base_facebook.php"; 
    2519 
    2620/** 
    27  * Thrown when an API call returns an exception. 
    28  * 
    29  * @author Naitik Shah <naitik@facebook.com> 
     21 * Extends the BaseFacebook class with the intent of using 
     22 * PHP sessions to store user ids and access tokens. 
    3023 */ 
    31 class FacebookApiException extends Exception 
     24class Facebook extends BaseFacebook 
    3225{ 
    3326  /** 
    34    * The result from the API server that represents the exception information. 
     27   * Identical to the parent constructor, except that 
     28   * we start a PHP session to store the user ID and 
     29   * access token if during the course of execution 
     30   * we discover them. 
     31   * 
     32   * @param Array $config the application configuration. 
     33   * @see BaseFacebook::__construct in facebook.php 
    3534   */ 
    36   protected $result; 
     35  public function __construct($config) { 
     36    if (!session_id()) { 
     37      session_start(); 
     38    } 
     39    parent::__construct($config); 
     40  } 
     41 
     42  protected static $kSupportedKeys = 
     43    array('state', 'code', 'access_token', 'user_id'); 
    3744 
    3845  /** 
    39    * Make a new API Exception with the given result. 
    40    * 
    41    * @param Array $result the result from the API server 
     46   * Provides the implementations of the inherited abstract 
     47   * methods.  The implementation uses PHP sessions to maintain 
     48   * a store for authorization codes, user ids, CSRF states, and 
     49   * access tokens. 
    4250   */ 
    43   public function __construct($result) { 
    44     $this->result = $result; 
    45  
    46     $code = isset($result['error_code']) ? $result['error_code'] : 0; 
    47  
    48     if (isset($result['error_description'])) { 
    49       // OAuth 2.0 Draft 10 style 
    50       $msg = $result['error_description']; 
    51     } else if (isset($result['error']) && is_array($result['error'])) { 
    52       // OAuth 2.0 Draft 00 style 
    53       $msg = $result['error']['message']; 
    54     } else if (isset($result['error_msg'])) { 
    55       // Rest server style 
    56       $msg = $result['error_msg']; 
    57     } else { 
    58       $msg = 'Unknown Error. Check getResult()'; 
     51  protected function setPersistentData($key, $value) { 
     52    if (!in_array($key, self::$kSupportedKeys)) { 
     53      self::errorLog('Unsupported key passed to setPersistentData.'); 
     54      return; 
    5955    } 
    6056 
    61     parent::__construct($msg, $code); 
     57    $session_var_name = $this->constructSessionVariableName($key); 
     58    $_SESSION[$session_var_name] = $value; 
    6259  } 
    6360 
    64   /** 
    65    * Return the associated result object returned by the API server. 
    66    * 
    67    * @returns Array the result from the API server 
    68    */ 
    69   public function getResult() { 
    70     return $this->result; 
     61  protected function getPersistentData($key, $default = false) { 
     62    if (!in_array($key, self::$kSupportedKeys)) { 
     63      self::errorLog('Unsupported key passed to getPersistentData.'); 
     64      return $default; 
     65    } 
     66 
     67    $session_var_name = $this->constructSessionVariableName($key); 
     68    return isset($_SESSION[$session_var_name]) ? 
     69      $_SESSION[$session_var_name] : $default; 
    7170  } 
    7271 
    73   /** 
    74    * Returns the associated type for the error. This will default to 
    75    * 'Exception' when a type is not available. 
    76    * 
    77    * @return String 
    78    */ 
    79   public function getType() { 
    80     if (isset($this->result['error'])) { 
    81       $error = $this->result['error']; 
    82       if (is_string($error)) { 
    83         // OAuth 2.0 Draft 10 style 
    84         return $error; 
    85       } else if (is_array($error)) { 
    86         // OAuth 2.0 Draft 00 style 
    87         if (isset($error['type'])) { 
    88           return $error['type']; 
    89         } 
    90       } 
     72  protected function clearPersistentData($key) { 
     73    if (!in_array($key, self::$kSupportedKeys)) { 
     74      self::errorLog('Unsupported key passed to clearPersistentData.'); 
     75      return; 
    9176    } 
    92     return 'Exception'; 
     77 
     78    $session_var_name = $this->constructSessionVariableName($key); 
     79    unset($_SESSION[$session_var_name]); 
    9380  } 
    9481 
    95   /** 
    96    * To make debugging easier. 
    97    * 
    98    * @returns String the string representation of the error 
    99    */ 
    100   public function __toString() { 
    101     $str = $this->getType() . ': '; 
    102     if ($this->code != 0) { 
    103       $str .= $this->code . ': '; 
    104     } 
    105     return $str . $this->message; 
    106   } 
    107 } 
    108  
    109 /** 
    110  * Provides access to the Facebook Platform. 
    111  * 
    112  * @author Naitik Shah <naitik@facebook.com> 
    113  */ 
    114 class Facebook 
    115 { 
    116   /** 
    117    * Version. 
    118    */ 
    119   const VERSION = '2.1.2'; 
    120  
    121   /** 
    122    * Default options for curl. 
    123    */ 
    124   public static $CURL_OPTS = array( 
    125     CURLOPT_CONNECTTIMEOUT => 10, 
    126     CURLOPT_RETURNTRANSFER => true, 
    127     CURLOPT_TIMEOUT        => 60, 
    128     CURLOPT_USERAGENT      => 'facebook-php-2.0', 
    129   ); 
    130  
    131   /** 
    132    * List of query parameters that get automatically dropped when rebuilding 
    133    * the current URL. 
    134    */ 
    135   protected static $DROP_QUERY_PARAMS = array( 
    136     'session', 
    137     'signed_request', 
    138   ); 
    139  
    140   /** 
    141    * Maps aliases to Facebook domains. 
    142    */ 
    143   public static $DOMAIN_MAP = array( 
    144     'api'       => 'https://api.facebook.com/', 
    145     'api_video' => 'https://api-video.facebook.com/', 
    146     'api_read'  => 'https://api-read.facebook.com/', 
    147     'graph'     => 'https://graph.facebook.com/', 
    148     'www'       => 'https://www.facebook.com/', 
    149   ); 
    150  
    151   /** 
    152    * The Application ID. 
    153    */ 
    154   protected $appId; 
    155  
    156   /** 
    157    * The Application API Secret. 
    158    */ 
    159   protected $apiSecret; 
    160  
    161   /** 
    162    * The active user session, if one is available. 
    163    */ 
    164   protected $session; 
    165  
    166   /** 
    167    * The data from the signed_request token. 
    168    */ 
    169   protected $signedRequest; 
    170  
    171   /** 
    172    * Indicates that we already loaded the session as best as we could. 
    173    */ 
    174   protected $sessionLoaded = false; 
    175  
    176   /** 
    177    * Indicates if Cookie support should be enabled. 
    178    */ 
    179   protected $cookieSupport = false; 
    180  
    181   /** 
    182    * Base domain for the Cookie. 
    183    */ 
    184   protected $baseDomain = ''; 
    185  
    186   /** 
    187    * Indicates if the CURL based @ syntax for file uploads is enabled. 
    188    */ 
    189   protected $fileUploadSupport = false; 
    190  
    191   /** 
    192    * Initialize a Facebook Application. 
    193    * 
    194    * The configuration: 
    195    * - appId: the application ID 
    196    * - secret: the application secret 
    197    * - cookie: (optional) boolean true to enable cookie support 
    198    * - domain: (optional) domain for the cookie 
    199    * - fileUpload: (optional) boolean indicating if file uploads are enabled 
    200    * 
    201    * @param Array $config the application configuration 
    202    */ 
    203   public function __construct($config) { 
    204     $this->setAppId($config['appId']); 
    205     $this->setApiSecret($config['secret']); 
    206     if (isset($config['cookie'])) { 
    207       $this->setCookieSupport($config['cookie']); 
    208     } 
    209     if (isset($config['domain'])) { 
    210       $this->setBaseDomain($config['domain']); 
    211     } 
    212     if (isset($config['fileUpload'])) { 
    213       $this->setFileUploadSupport($config['fileUpload']); 
     82  protected function clearAllPersistentData() { 
     83    foreach (self::$kSupportedKeys as $key) { 
     84      $this->clearPersistentData($key); 
    21485    } 
    21586  } 
    21687 
    217   /** 
    218    * Set the Application ID. 
    219    * 
    220    * @param String $appId the Application ID 
    221    */ 
    222   public function setAppId($appId) { 
    223     $this->appId = $appId; 
    224     return $this; 
    225   } 
    226  
    227   /** 
    228    * Get the Application ID. 
    229    * 
    230    * @return String the Application ID 
    231    */ 
    232   public function getAppId() { 
    233     return $this->appId; 
    234   } 
    235  
    236   /** 
    237    * Set the API Secret. 
    238    * 
    239    * @param String $appId the API Secret 
    240    */ 
    241   public function setApiSecret($apiSecret) { 
    242     $this->apiSecret = $apiSecret; 
    243     return $this; 
    244   } 
    245  
    246   /** 
    247    * Get the API Secret. 
    248    * 
    249    * @return String the API Secret 
    250    */ 
    251   public function getApiSecret() { 
    252     return $this->apiSecret; 
    253   } 
    254  
    255   /** 
    256    * Set the Cookie Support status. 
    257    * 
    258    * @param Boolean $cookieSupport the Cookie Support status 
    259    */ 
    260   public function setCookieSupport($cookieSupport) { 
    261     $this->cookieSupport = $cookieSupport; 
    262     return $this; 
    263   } 
    264  
    265   /** 
    266    * Get the Cookie Support status. 
    267    * 
    268    * @return Boolean the Cookie Support status 
    269    */ 
    270   public function useCookieSupport() { 
    271     return $this->cookieSupport; 
    272   } 
    273  
    274   /** 
    275    * Set the base domain for the Cookie. 
    276    * 
    277    * @param String $domain the base domain 
    278    */ 
    279   public function setBaseDomain($domain) { 
    280     $this->baseDomain = $domain; 
    281     return $this; 
    282   } 
    283  
    284   /** 
    285    * Get the base domain for the Cookie. 
    286    * 
    287    * @return String the base domain 
    288    */ 
    289   public function getBaseDomain() { 
    290     return $this->baseDomain; 
    291   } 
    292  
    293   /** 
    294    * Set the file upload support status. 
    295    * 
    296    * @param String $domain the base domain 
    297    */ 
    298   public function setFileUploadSupport($fileUploadSupport) { 
    299     $this->fileUploadSupport = $fileUploadSupport; 
    300     return $this; 
    301   } 
    302  
    303   /** 
    304    * Get the file upload support status. 
    305    * 
    306    * @return String the base domain 
    307    */ 
    308   public function useFileUploadSupport() { 
    309     return $this->fileUploadSupport; 
    310   } 
    311  
    312   /** 
    313    * Get the data from a signed_request token 
    314    * 
    315    * @return String the base domain 
    316    */ 
    317   public function getSignedRequest() { 
    318     if (!$this->signedRequest) { 
    319       if (isset($_REQUEST['signed_request'])) { 
    320         $this->signedRequest = $this->parseSignedRequest( 
    321           $_REQUEST['signed_request']); 
    322       } 
    323     } 
    324     return $this->signedRequest; 
    325   } 
    326  
    327   /** 
    328    * Set the Session. 
    329    * 
    330    * @param Array $session the session 
    331    * @param Boolean $write_cookie indicate if a cookie should be written. this 
    332    * value is ignored if cookie support has been disabled. 
    333    */ 
    334   public function setSession($session=null, $write_cookie=true) { 
    335     $session = $this->validateSessionObject($session); 
    336     $this->sessionLoaded = true; 
    337     $this->session = $session; 
    338     if ($write_cookie) { 
    339       $this->setCookieFromSession($session); 
    340     } 
    341     return $this; 
    342   } 
    343  
    344   /** 
    345    * Get the session object. This will automatically look for a signed session 
    346    * sent via the signed_request, Cookie or Query Parameters if needed. 
    347    * 
    348    * @return Array the session 
    349    */ 
    350   public function getSession() { 
    351     if (!$this->sessionLoaded) { 
    352       $session = null; 
    353       $write_cookie = true; 
    354  
    355       // try loading session from signed_request in $_REQUEST 
    356       $signedRequest = $this->getSignedRequest(); 
    357       if ($signedRequest) { 
    358         // sig is good, use the signedRequest 
    359         $session = $this->createSessionFromSignedRequest($signedRequest); 
    360       } 
    361  
    362       // try loading session from $_REQUEST 
    363       if (!$session && isset($_REQUEST['session'])) { 
    364         $session = json_decode( 
    365           get_magic_quotes_gpc() 
    366             ? stripslashes($_REQUEST['session']) 
    367             : $_REQUEST['session'], 
    368           true 
    369         ); 
    370         $session = $this->validateSessionObject($session); 
    371       } 
    372  
    373       // try loading session from cookie if necessary 
    374       if (!$session && $this->useCookieSupport()) { 
    375         $cookieName = $this->getSessionCookieName(); 
    376         if (isset($_COOKIE[$cookieName])) { 
    377           $session = array(); 
    378           parse_str(trim( 
    379             get_magic_quotes_gpc() 
    380               ? stripslashes($_COOKIE[$cookieName]) 
    381               : $_COOKIE[$cookieName], 
    382             '"' 
    383           ), $session); 
    384           $session = $this->validateSessionObject($session); 
    385           // write only if we need to delete a invalid session cookie 
    386           $write_cookie = empty($session); 
    387         } 
    388       } 
    389  
    390       $this->setSession($session, $write_cookie); 
    391     } 
    392  
    393     return $this->session; 
    394   } 
    395  
    396   /** 
    397    * Get the UID from the session. 
    398    * 
    399    * @return String the UID if available 
    400    */ 
    401   public function getUser() { 
    402     $session = $this->getSession(); 
    403     return $session ? $session['uid'] : null; 
    404   } 
    405  
    406   /** 
    407    * Gets a OAuth access token. 
    408    * 
    409    * @return String the access token 
    410    */ 
    411   public function getAccessToken() { 
    412     $session = $this->getSession(); 
    413     // either user session signed, or app signed 
    414     if ($session) { 
    415       return $session['access_token']; 
    416     } else { 
    417       return $this->getAppId() .'|'. $this->getApiSecret(); 
    418     } 
    419   } 
    420  
    421   /** 
    422    * Get a Login URL for use with redirects. By default, full page redirect is 
    423    * assumed. If you are using the generated URL with a window.open() call in 
    424    * JavaScript, you can pass in display=popup as part of the $params. 
    425    * 
    426    * The parameters: 
    427    * - next: the url to go to after a successful login 
    428    * - cancel_url: the url to go to after the user cancels 
    429    * - req_perms: comma separated list of requested extended perms 
    430    * - display: can be "page" (default, full page) or "popup" 
    431    * 
    432    * @param Array $params provide custom parameters 
    433    * @return String the URL for the login flow 
    434    */ 
    435   public function getLoginUrl($params=array()) { 
    436     $currentUrl = $this->getCurrentUrl(); 
    437     return $this->getUrl( 
    438       'www', 
    439       'login.php', 
    440       array_merge(array( 
    441         'api_key'         => $this->getAppId(), 
    442         'cancel_url'      => $currentUrl, 
    443         'display'         => 'page', 
    444         'fbconnect'       => 1, 
    445         'next'            => $currentUrl, 
    446         'return_session'  => 1, 
    447         'session_version' => 3, 
    448         'v'               => '1.0', 
    449       ), $params) 
    450     ); 
    451   } 
    452  
    453   /** 
    454    * Get a Logout URL suitable for use with redirects. 
    455    * 
    456    * The parameters: 
    457    * - next: the url to go to after a successful logout 
    458    * 
    459    * @param Array $params provide custom parameters 
    460    * @return String the URL for the logout flow 
    461    */ 
    462   public function getLogoutUrl($params=array()) { 
    463     return $this->getUrl( 
    464       'www', 
    465       'logout.php', 
    466       array_merge(array( 
    467         'next'         => $this->getCurrentUrl(), 
    468         'access_token' => $this->getAccessToken(), 
    469       ), $params) 
    470     ); 
    471   } 
    472  
    473   /** 
    474    * Get a login status URL to fetch the status from facebook. 
    475    * 
    476    * The parameters: 
    477    * - ok_session: the URL to go to if a session is found 
    478    * - no_session: the URL to go to if the user is not connected 
    479    * - no_user: the URL to go to if the user is not signed into facebook 
    480    * 
    481    * @param Array $params provide custom parameters 
    482    * @return String the URL for the logout flow 
    483    */ 
    484   public function getLoginStatusUrl($params=array()) { 
    485     return $this->getUrl( 
    486       'www', 
    487       'extern/login_status.php', 
    488       array_merge(array( 
    489         'api_key'         => $this->getAppId(), 
    490         'no_session'      => $this->getCurrentUrl(), 
    491         'no_user'         => $this->getCurrentUrl(), 
    492         'ok_session'      => $this->getCurrentUrl(), 
    493         'session_version' => 3, 
    494       ), $params) 
    495     ); 
    496   } 
    497  
    498   /** 
    499    * Make an API call. 
    500    * 
    501    * @param Array $params the API call parameters 
    502    * @return the decoded response 
    503    */ 
    504   public function api(/* polymorphic */) { 
    505     $args = func_get_args(); 
    506     if (is_array($args[0])) { 
    507       return $this->_restserver($args[0]); 
    508     } else { 
    509       return call_user_func_array(array($this, '_graph'), $args); 
    510     } 
    511   } 
    512  
    513   /** 
    514    * Invoke the old restserver.php endpoint. 
    515    * 
    516    * @param Array $params method call object 
    517    * @return the decoded response object 
    518    * @throws FacebookApiException 
    519    */ 
    520   protected function _restserver($params) { 
    521     // generic application level parameters 
    522     $params['api_key'] = $this->getAppId(); 
    523     $params['format'] = 'json-strings'; 
    524  
    525     $result = json_decode($this->_oauthRequest( 
    526       $this->getApiUrl($params['method']), 
    527       $params 
    528     ), true); 
    529  
    530     // results are returned, errors are thrown 
    531     if (is_array($result) && isset($result['error_code'])) { 
    532       throw new FacebookApiException($result); 
    533     } 
    534     return $result; 
    535   } 
    536  
    537   /** 
    538    * Invoke the Graph API. 
    539    * 
    540    * @param String $path the path (required) 
    541    * @param String $method the http method (default 'GET') 
    542    * @param Array $params the query/post data 
    543    * @return the decoded response object 
    544    * @throws FacebookApiException 
    545    */ 
    546   protected function _graph($path, $method='GET', $params=array()) { 
    547     if (is_array($method) && empty($params)) { 
    548       $params = $method; 
    549       $method = 'GET'; 
    550     } 
    551     $params['method'] = $method; // method override as we always do a POST 
    552  
    553     $result = json_decode($this->_oauthRequest( 
    554       $this->getUrl('graph', $path), 
    555       $params 
    556     ), true); 
    557  
    558     // results are returned, errors are thrown 
    559     if (is_array($result) && isset($result['error'])) { 
    560       $e = new FacebookApiException($result); 
    561       switch ($e->getType()) { 
    562         // OAuth 2.0 Draft 00 style 
    563         case 'OAuthException': 
    564         // OAuth 2.0 Draft 10 style 
    565         case 'invalid_token': 
    566           $this->setSession(null); 
    567       } 
    568       throw $e; 
    569     } 
    570     return $result; 
    571   } 
    572  
    573   /** 
    574    * Make a OAuth Request 
    575    * 
    576    * @param String $path the path (required) 
    577    * @param Array $params the query/post data 
    578    * @return the decoded response object 
    579    * @throws FacebookApiException 
    580    */ 
    581   protected function _oauthRequest($url, $params) { 
    582     if (!isset($params['access_token'])) { 
    583       $params['access_token'] = $this->getAccessToken(); 
    584     } 
    585  
    586     // json_encode all params values that are not strings 
    587     foreach ($params as $key => $value) { 
    588       if (!is_string($value)) { 
    589         $params[$key] = json_encode($value); 
    590       } 
    591     } 
    592     return $this->makeRequest($url, $params); 
    593   } 
    594  
    595   /** 
    596    * Makes an HTTP request. This method can be overriden by subclasses if 
    597    * developers want to do fancier things or use something other than curl to 
    598    * make the request. 
    599    * 
    600    * @param String $url the URL to make the request to 
    601    * @param Array $params the parameters to use for the POST body 
    602    * @param CurlHandler $ch optional initialized curl handle 
    603    * @return String the response text 
    604    */ 
    605   protected function makeRequest($url, $params, $ch=null) { 
    606     if (!$ch) { 
    607       $ch = curl_init(); 
    608     } 
    609  
    610     $opts = self::$CURL_OPTS; 
    611     if ($this->useFileUploadSupport()) { 
    612       $opts[CURLOPT_POSTFIELDS] = $params; 
    613     } else { 
    614       $opts[CURLOPT_POSTFIELDS] = http_build_query($params, null, '&'); 
    615     } 
    616     $opts[CURLOPT_URL] = $url; 
    617  
    618     // disable the 'Expect: 100-continue' behaviour. This causes CURL to wait 
    619     // for 2 seconds if the server does not support this header. 
    620     if (isset($opts[CURLOPT_HTTPHEADER])) { 
    621       $existing_headers = $opts[CURLOPT_HTTPHEADER]; 
    622       $existing_headers[] = 'Expect:'; 
    623       $opts[CURLOPT_HTTPHEADER] = $existing_headers; 
    624     } else { 
    625       $opts[CURLOPT_HTTPHEADER] = array('Expect:'); 
    626     } 
    627  
    628     curl_setopt_array($ch, $opts); 
    629     $result = curl_exec($ch); 
    630  
    631     if (curl_errno($ch) == 60) { // CURLE_SSL_CACERT 
    632       self::errorLog('Invalid or no certificate authority found, using bundled information'); 
    633       curl_setopt($ch, CURLOPT_CAINFO, 
    634                   dirname(__FILE__) . '/fb_ca_chain_bundle.crt'); 
    635       $result = curl_exec($ch); 
    636     } 
    637  
    638     if ($result === false) { 
    639       $e = new FacebookApiException(array( 
    640         'error_code' => curl_errno($ch), 
    641         'error'      => array( 
    642           'message' => curl_error($ch), 
    643           'type'    => 'CurlException', 
    644         ), 
    645       )); 
    646       curl_close($ch); 
    647       throw $e; 
    648     } 
    649     curl_close($ch); 
    650     return $result; 
    651   } 
    652  
    653   /** 
    654    * The name of the Cookie that contains the session. 
    655    * 
    656    * @return String the cookie name 
    657    */ 
    658   protected function getSessionCookieName() { 
    659     return 'fbs_' . $this->getAppId(); 
    660   } 
    661  
    662   /** 
    663    * Set a JS Cookie based on the _passed in_ session. It does not use the 
    664    * currently stored session -- you need to explicitly pass it in. 
    665    * 
    666    * @param Array $session the session to use for setting the cookie 
    667    */ 
    668   protected function setCookieFromSession($session=null) { 
    669     if (!$this->useCookieSupport()) { 
    670       return; 
    671     } 
    672  
    673     $cookieName = $this->getSessionCookieName(); 
    674     $value = 'deleted'; 
    675     $expires = time() - 3600; 
    676     $domain = $this->getBaseDomain(); 
    677     if ($session) { 
    678       $value = '"' . http_build_query($session, null, '&') . '"'; 
    679       if (isset($session['base_domain'])) { 
    680         $domain = $session['base_domain']; 
    681       } 
    682       $expires = $session['expires']; 
    683     } 
    684  
    685     // prepend dot if a domain is found 
    686     if ($domain) { 
    687       $domain = '.' . $domain; 
    688     } 
    689  
    690     // if an existing cookie is not set, we dont need to delete it 
    691     if ($value == 'deleted' && empty($_COOKIE[$cookieName])) { 
    692       return; 
    693     } 
    694  
    695     if (headers_sent()) { 
    696       self::errorLog('Could not set cookie. Headers already sent.'); 
    697  
    698     // ignore for code coverage as we will never be able to setcookie in a CLI 
    699     // environment 
    700     // @codeCoverageIgnoreStart 
    701     } else { 
    702       setcookie($cookieName, $value, $expires, '/', $domain); 
    703     } 
    704     // @codeCoverageIgnoreEnd 
    705   } 
    706  
    707   /** 
    708    * Validates a session_version=3 style session object. 
    709    * 
    710    * @param Array $session the session object 
    711    * @return Array the session object if it validates, null otherwise 
    712    */ 
    713   protected function validateSessionObject($session) { 
    714     // make sure some essential fields exist 
    715     if (is_array($session) && 
    716         isset($session['uid']) && 
    717         isset($session['access_token']) && 
    718         isset($session['sig'])) { 
    719       // validate the signature 
    720       $session_without_sig = $session; 
    721       unset($session_without_sig['sig']); 
    722       $expected_sig = self::generateSignature( 
    723         $session_without_sig, 
    724         $this->getApiSecret() 
    725       ); 
    726       if ($session['sig'] != $expected_sig) { 
    727         self::errorLog('Got invalid session signature in cookie.'); 
    728         $session = null; 
    729       } 
    730       // check expiry time 
    731     } else { 
    732       $session = null; 
    733     } 
    734     return $session; 
    735   } 
    736  
    737   /** 
    738    * Returns something that looks like our JS session object from the 
    739    * signed token's data 
    740    * 
    741    * TODO: Nuke this once the login flow uses OAuth2 
    742    * 
    743    * @param Array the output of getSignedRequest 
    744    * @return Array Something that will work as a session 
    745    */ 
    746   protected function createSessionFromSignedRequest($data) { 
    747     if (!isset($data['oauth_token'])) { 
    748       return null; 
    749     } 
    750  
    751     $session = array( 
    752       'uid'          => $data['user_id'], 
    753       'access_token' => $data['oauth_token'], 
    754       'expires'      => $data['expires'], 
    755     ); 
    756  
    757     // put a real sig, so that validateSignature works 
    758     $session['sig'] = self::generateSignature( 
    759       $session, 
    760       $this->getApiSecret() 
    761     ); 
    762  
    763     return $session; 
    764   } 
    765  
    766   /** 
    767    * Parses a signed_request and validates the signature. 
    768    * Then saves it in $this->signed_data 
    769    * 
    770    * @param String A signed token 
    771    * @param Boolean Should we remove the parts of the payload that 
    772    *                are used by the algorithm? 
    773    * @return Array the payload inside it or null if the sig is wrong 
    774    */ 
    775   protected function parseSignedRequest($signed_request) { 
    776     list($encoded_sig, $payload) = explode('.', $signed_request, 2); 
    777  
    778     // decode the data 
    779     $sig = self::base64UrlDecode($encoded_sig); 
    780     $data = json_decode(self::base64UrlDecode($payload), true); 
    781  
    782     if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') { 
    783       self::errorLog('Unknown algorithm. Expected HMAC-SHA256'); 
    784       return null; 
    785     } 
    786  
    787     // check sig 
    788     $expected_sig = hash_hmac('sha256', $payload, 
    789                               $this->getApiSecret(), $raw = true); 
    790     if ($sig !== $expected_sig) { 
    791       self::errorLog('Bad Signed JSON signature!'); 
    792       return null; 
    793     } 
    794  
    795     return $data; 
    796   } 
    797  
    798   /** 
    799    * Build the URL for api given parameters. 
    800    * 
    801    * @param $method String the method name. 
    802    * @return String the URL for the given parameters 
    803    */ 
    804   protected function getApiUrl($method) { 
    805     static $READ_ONLY_CALLS = 
    806       array('admin.getallocation' => 1, 
    807             'admin.getappproperties' => 1, 
    808             'admin.getbannedusers' => 1, 
    809             'admin.getlivestreamvialink' => 1, 
    810             'admin.getmetrics' => 1, 
    811             'admin.getrestrictioninfo' => 1, 
    812             'application.getpublicinfo' => 1, 
    813             'auth.getapppublickey' => 1, 
    814             'auth.getsession' => 1, 
    815             'auth.getsignedpublicsessiondata' => 1, 
    816             'comments.get' => 1, 
    817             'connect.getunconnectedfriendscount' => 1, 
    818             'dashboard.getactivity' => 1, 
    819             'dashboard.getcount' => 1, 
    820             'dashboard.getglobalnews' => 1, 
    821             'dashboard.getnews' => 1, 
    822             'dashboard.multigetcount' => 1, 
    823             'dashboard.multigetnews' => 1, 
    824             'data.getcookies' => 1, 
    825             'events.get' => 1, 
    826             'events.getmembers' => 1, 
    827             'fbml.getcustomtags' => 1, 
    828             'feed.getappfriendstories' => 1, 
    829             'feed.getregisteredtemplatebundlebyid' => 1, 
    830             'feed.getregisteredtemplatebundles' => 1, 
    831             'fql.multiquery' => 1, 
    832             'fql.query' => 1, 
    833             'friends.arefriends' => 1, 
    834             'friends.get' => 1, 
    835             'friends.getappusers' => 1, 
    836             'friends.getlists' => 1, 
    837             'friends.getmutualfriends' => 1, 
    838             'gifts.get' => 1, 
    839             'groups.get' => 1, 
    840             'groups.getmembers' => 1, 
    841             'intl.gettranslations' => 1, 
    842             'links.get' => 1, 
    843             'notes.get' => 1, 
    844             'notifications.get' => 1, 
    845             'pages.getinfo' => 1, 
    846             'pages.isadmin' => 1, 
    847             'pages.isappadded' => 1, 
    848             'pages.isfan' => 1, 
    849             'permissions.checkavailableapiaccess' => 1, 
    850             'permissions.checkgrantedapiaccess' => 1, 
    851             'photos.get' => 1, 
    852             'photos.getalbums' => 1, 
    853             'photos.gettags' => 1, 
    854             'profile.getinfo' => 1, 
    855             'profile.getinfooptions' => 1, 
    856             'stream.get' => 1, 
    857             'stream.getcomments' => 1, 
    858             'stream.getfilters' => 1, 
    859             'users.getinfo' => 1, 
    860             'users.getloggedinuser' => 1, 
    861             'users.getstandardinfo' => 1, 
    862             'users.hasapppermission' => 1, 
    863             'users.isappuser' => 1, 
    864             'users.isverified' => 1, 
    865             'video.getuploadlimits' => 1); 
    866     $name = 'api'; 
    867     if (isset($READ_ONLY_CALLS[strtolower($method)])) { 
    868       $name = 'api_read'; 
    869     } else if (strtolower($method) == 'video.upload') { 
    870       $name = 'api_video'; 
    871     } 
    872     return self::getUrl($name, 'restserver.php'); 
    873   } 
    874  
    875   /** 
    876    * Build the URL for given domain alias, path and parameters. 
    877    * 
    878    * @param $name String the name of the domain 
    879    * @param $path String optional path (without a leading slash) 
    880    * @param $params Array optional query parameters 
    881    * @return String the URL for the given parameters 
    882    */ 
    883   protected function getUrl($name, $path='', $params=array()) { 
    884     $url = self::$DOMAIN_MAP[$name]; 
    885     if ($path) { 
    886       if ($path[0] === '/') { 
    887         $path = substr($path, 1); 
    888       } 
    889       $url .= $path; 
    890     } 
    891     if ($params) { 
    892       $url .= '?' . http_build_query($params, null, '&'); 
    893     } 
    894     return $url; 
    895   } 
    896  
    897   /** 
    898    * Returns the Current URL, stripping it of known FB parameters that should 
    899    * not persist. 
    900    * 
    901    * @return String the current URL 
    902    */ 
    903   protected function getCurrentUrl() { 
    904     $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' 
    905       ? 'https://' 
    906       : 'http://'; 
    907     $currentUrl = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; 
    908     $parts = parse_url($currentUrl); 
    909  
    910     // drop known fb params 
    911     $query = ''; 
    912     if (!empty($parts['query'])) { 
    913       $params = array(); 
    914       parse_str($parts['query'], $params); 
    915       foreach(self::$DROP_QUERY_PARAMS as $key) { 
    916         unset($params[$key]); 
    917       } 
    918       if (!empty($params)) { 
    919         $query = '?' . http_build_query($params, null, '&'); 
    920       } 
    921     } 
    922  
    923     // use port if non default 
    924     $port = 
    925       isset($parts['port']) && 
    926       (($protocol === 'http://' && $parts['port'] !== 80) || 
    927        ($protocol === 'https://' && $parts['port'] !== 443)) 
    928       ? ':' . $parts['port'] : ''; 
    929  
    930     // rebuild 
    931     return $protocol . $parts['host'] . $port . $parts['path'] . $query; 
    932   } 
    933  
    934   /** 
    935    * Generate a signature for the given params and secret. 
    936    * 
    937    * @param Array $params the parameters to sign 
    938    * @param String $secret the secret to sign with 
    939    * @return String the generated signature 
    940    */ 
    941   protected static function generateSignature($params, $secret) { 
    942     // work with sorted data 
    943     ksort($params); 
    944  
    945     // generate the base string 
    946     $base_string = ''; 
    947     foreach($params as $key => $value) { 
    948       $base_string .= $key . '=' . $value; 
    949     } 
    950     $base_string .= $secret; 
    951  
    952     return md5($base_string); 
    953   } 
    954  
    955   /** 
    956    * Prints to the error log if you aren't in command line mode. 
    957    * 
    958    * @param String log message 
    959    */ 
    960   protected static function errorLog($msg) { 
    961     // disable error log if we are running in a CLI environment 
    962     // @codeCoverageIgnoreStart 
    963     if (php_sapi_name() != 'cli') { 
    964       error_log($msg); 
    965     } 
    966     // uncomment this if you want to see the errors on the page 
    967     // print 'error_log: '.$msg."\n"; 
    968     // @codeCoverageIgnoreEnd 
    969   } 
    970  
    971   /** 
    972    * Base64 encoding that doesn't need to be urlencode()ed. 
    973    * Exactly the same as base64_encode except it uses 
    974    *   - instead of + 
    975    *   _ instead of / 
    976    * 
    977    * @param String base64UrlEncodeded string 
    978    */ 
    979   protected static function base64UrlDecode($input) { 
    980     return base64_decode(strtr($input, '-_', '+/')); 
     88  protected function constructSessionVariableName($key) { 
     89    return implode('_', array('fb', 
     90                              $this->getAppId(), 
     91                              $key)); 
    98192  } 
    98293} 
  • wp-facebook-applications/trunk/readme.txt

    r383485 r457935  
    44Tags: facebook, application, campaign, tab, custom post type, custom fields 
    55Requires at least: 3.0 
    6 Tested up to: 3.2 
    7 Stable tag: 0.3.1 
     6Tested up to: 3.2.1 
     7Stable tag: 0.4.2 
    88 
    99Create custom tabs for your Facebook pages, hosted on your WordPress blog. 
     
    1111== Description == 
    1212 
    13 WP-Facebook applications adds a new menu to your WordPress admin panel, and allows you to create new pages to use as iFrame app tabs on your Facebook pages. When creating an application, you define a default landing tab that users will see if they are not fans of your Facebook page, and then you create content that will appear once they are fans. Optionally, you can add a Facebook comments box at the bottom of the content. 
     13WP-Facebook applications adds a new menu to your WordPress admin panel, and allows you to create new pages to use as iFrame app tabs on your Facebook pages. When creating an application, you can define a default landing tab that users will see if they are not fans of your Facebook page, and then you create content that will appear once they are fans. Optionally, you can add a Facebook comments box at the bottom of the content. 
    1414 
    1515Thus you can integrate text, pictures, videos, comment forms, hidden for people who are not fans of your page yet. 
     
    1717Thus plugin allows you to create as many tabs as you wish through WordPress. 
    1818 
    19 For more information, visit:  
    20 * [Page officielle - FR](http://jeremy.tagada.hu/extension-wp-facebook-applications/ "Extension : WP Facebook Applications")  
     19For more information, check the documentation: 
     20- [Documentation - EN](http://www.werewp.com/my-plugins/wp-facebook-applications/ "WP Facebook Applications documentation") 
     21- [Documentation - FR](http://jeremy.tagada.hu/extension-wp-facebook-applications/ "Extension : WP Facebook Applications")  
    2122 
    2223This plugin is a work in progress. Do not hesitate to send me your remarks, suggestions and ideas for the future version of this plugin. 
    2324 
    24 Please note that this plugin uses the [Facebook PHP SDK](https://github.com/facebook/php-sdk "Facebook PHP SDK") 
     25Please note that this plugin uses the [Facebook PHP SDK](http://github.com/facebook/php-sdk "Facebook PHP SDK") 
    2526 
    2627== Installation == 
     
    37384. If you want a Facebook Comments box at the bottom of your content, simply specify how many comments do you want the box to show by default. 
    38395. Enter content that will appear when the user is fan in the content area. 
    39 6. Upload the image to see when the user is not a fan, and set this image as *featured image*. 
     406. Upload the image to see when the user is not a fan, and set this image as *featured image*. If you want users to see the content of the page even if they are not fans of your page, do not assign any featured image. 
    40417. Publish this page, note down the URL and change your Facebook application settings to point to that URL. 
    41428. You're done, enjoy! 
     
    5657The only way to solve the issue is to buy an SSL certificate for your domain, and once set, fill in the secure URL for your tab in the applications settings. 
    5758 
     59= How do I add the application I just created to my page? = 
     60 
     61When viewing your [application settings page](http://www.facebook.com/developers/apps.php "Facebook Apps overview"), you will see a link to your Application's Profile Page. On that page, below the profile page, click the *Add to my page* link. Then you can add your application to any of the pages you administer. 
     62 
    5863== Changelog == 
     64 
     65= 0.4.2 = 
     66* Update to the latest version of Facebook PHP SDK 
     67 
     68= 0.4.1 = 
     69* Solve bug causing TinyMCE buttons disappearing 
     70 
     71= 0.4 = 
     72* i18n of the plugin 
     73* Plugin is now translated to French and Hungarian 
     74* Add possibility not to filter content for non-fans 
     75 
     76= 0.3.1 = 
     77* Changing version number in plugin root file 
    5978 
    6079= 0.3 = 
  • wp-facebook-applications/trunk/template.php

    r382709 r457935  
    6161 
    6262<?php else : ?> 
     63 
     64    <?php if ( has_post_thumbnail() ) : ?> 
    6365     
    64     <div class="photo clearfix"> 
    65  
    66         <?php the_post_thumbnail( 'fb-nonfans' ); ?> 
     66        <div class="photo clearfix">     
     67            <?php the_post_thumbnail( 'fb-nonfans' ); ?>     
     68        </div><!-- .photo --> 
    6769     
    68     </div><!-- .photo --> 
     70    <?php else : ?> 
     71     
     72        <div class="container clearfix">     
     73            <div <?php post_class() ?> id="post-<?php the_ID(); ?>"> 
     74            <?php the_content(); ?> 
     75            </div>   
     76        </div><!-- .container --> 
     77     
     78    <?php endif; ?>  
    6979 
    7080<?php endif; ?>  
     
    8090          status  : true, // check login status 
    8191          cookie  : true, // enable cookies to allow the server to access the session 
    82           xfbml   : true // parse XFBML 
     92          xfbml   : true, // parse XFBML 
     93          oauth   : true 
    8394        }); 
    8495 
     
    95106      function sizeChangeCallback() { 
    96107            FB.Canvas.setAutoResize(); 
    97         } 
     108      } 
    98109 
    99110      (function() { 
  • wp-facebook-applications/trunk/wp-fb-applications.php

    r383485 r457935  
    22/* 
    33Plugin Name: WP-Facebook applications 
    4 Version: 0.3.1 
    5 Plugin URI: http://jeremy.tagada.hu 
     4Version: 0.4.2 
     5Plugin URI: http://www.werewp.com/my-plugins/wp-facebook-applications/ 
    66Description: Create custom tabs for your Facebook pages, hosted on your WordPress blog. 
    77Author: Jeremy Herve 
     
    2424    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
    2525*/ 
    26 ?> 
    27 <?php  
    2826 
    2927define( 'WPFBAPPS_URL', plugin_dir_url(__FILE__) ); 
     28 
     29// Internationalization 
     30function werewp_fbapp_load_plugin_textdomain() { 
     31    load_plugin_textdomain( 'werewpfbapps', false, 'wp-facebook-applications/languages' ); 
     32} 
     33add_action( 'init', 'werewp_fbapp_load_plugin_textdomain' ); 
    3034 
    3135/* 
     
    3842        array( 
    3943            'labels' => array( 
    40                 'name' => __( 'Applications' ), 
    41                 'singular_name' => __( 'Application' ), 
    42                 'add_new' => __( 'Add New' ), 
    43                 'add_new_item' => __( 'Add New Facebook tab' ), 
    44                 'edit' => __( 'Edit' ), 
    45                 'edit_item' => __( 'Edit Facebook tab' ), 
    46                 'view' => __( 'View Facebook tab' ) 
     44                'name' => __( 'Applications', 'werewpfbapps' ), 
     45                'singular_name' => __( 'Application', 'werewpfbapps' ), 
     46                'add_new' => __( 'Add New', 'werewpfbapps' ), 
     47                'add_new_item' => __( 'Add New Facebook tab', 'werewpfbapps' ), 
     48                'edit' => __( 'Edit', 'werewpfbapps' ), 
     49                'edit_item' => __( 'Edit Facebook tab', 'werewpfbapps' ), 
     50                'view' => __( 'View Facebook tab', 'werewpfbapps' ) 
    4751            ), 
    48         'description' => __( 'The Applications post type allows you to create new pages with a custom style and custom options. Creating new applications will allow you to create custom tabs on your Facebook pages.' ), 
     52        'description' => __( 'The Applications post type allows you to create new pages with a custom style and custom options. Creating new applications will allow you to create custom tabs on your Facebook pages.', 'werewpfbapps' ), 
    4953        'public' => true, 
    5054        'has_archive' => true, 
     
    6872    add_theme_support( 'post-thumbnails' ); 
    6973    if ( function_exists( 'add_image_size' ) ) { 
    70         add_image_size( 'fb-nonfans', 520, 2000, true ); // Facebook applications thumbnails 
     74        add_image_size( 'fb-nonfans', 520, 2000, true ); 
    7175    } 
    7276} 
     
    7680/* 
    7781 * Customize our Edit Custom type panel to be able to 
    78  * entre Facebook application settings 
     82 * include Facebook application settings 
    7983 */ 
    8084// Change Enter the title prompt on page 
     
    8387  
    8488     if  ( 'werewp_fbapp' == $screen->post_type ) { 
    85           $title = 'Enter the name of your Facebook tab'; 
     89          $title = __( 'Enter the name of your Facebook tab', 'werewpfbapps' ); 
    8690     } 
    8791  
     
    9296// Add metaboxes with custom fields 
    9397function werewp_fbapps_metaboxes(){ 
    94     add_meta_box( 'appid_meta', 'Application parameters', 'werewp_fbappappparameters', 'werewp_fbapp', 'advanced', 'core' ); 
     98    add_meta_box( 'appid_meta', __( 'Application parameters', 'werewpfbapps'), 'werewp_fbappappparameters', 'werewp_fbapp', 'advanced', 'core' ); 
    9599} 
    96100add_action( 'admin_init', 'werewp_fbapps_metaboxes' ); 
     
    103107    $fbcomments = $custom['fbcomments'][0]; 
    104108    ?> 
    105     <h3>Create your application on Facebook</h3> 
    106     <p>Before to start creating content, you must create an application on Facebook : <a href="http://www.facebook.com/developers/createapp.php" target="_blank">Create application</a>. Once it is done, provide a description and icons to that application. Then, in the <strong>Web Site</strong> tab, fill in with your website's URL.</p> 
    107     <h3>Fill it application details</h3> 
    108     <p>You now have the necessary information to fill in the parameters below:</p> 
    109     <p><label><strong>Application ID:</strong></label><br /> 
     109    <h3><?php _e( 'Create your application on Facebook', 'werewpfbapps' ); ?></h3> 
     110    <p><?php _e( 'Before to start creating content, you must create an application on Facebook:', 'werewpfbapps' ); ?> 
     111     <a href="http://www.facebook.com/developers/createapp.php" target="_blank"><?php _e( 'Create application.', 'werewpfbapps' ); ?></a>  
     112     <?php _e( 'Once it is done, provide a description and icons to that application. Then, in the <strong>Web Site</strong> tab, fill in with your website\'s URL.', 'werewpfbapps'); ?></p> 
     113    <h3><?php _e( 'Fill it application details', 'werewpfbapps' ); ?></h3> 
     114    <p><?php _e( 'You now have the necessary information to fill in the parameters below:', 'werewpfbapps' ); ?></p> 
     115    <p><label><strong><?php _e( 'Application ID:', 'werewpfbapps' ); ?></strong></label><br /> 
    110116    <textarea cols="50" rows="1" name="appid"><?php echo $appid; ?></textarea></p> 
    111     <p><label><strong>Application Secret:</strong></label><br /> 
     117    <p><label><strong><?php _e( 'Application Secret:', 'werewpfbapps' ); ?></strong></label><br /> 
    112118    <textarea cols="50" rows="1" name="appsecret"><?php echo $appsecret; ?></textarea></p> 
    113     <p><label><strong>Number of Facebook comments displayed</strong> (leave empty if you do not wish to have this feature enabled):</label><br /> 
     119    <p><label><strong><?php _e( 'Number of Facebook comments displayed</strong> (leave empty if you do not wish to have this feature enabled):', 'werewpfbapps' ); ?></label><br /> 
    114120    <textarea cols="1" rows="1" name="fbcomments"><?php echo $fbcomments; ?></textarea></p> 
    115     <h3>Choose the image displayed to the non-fans of your page</h3> 
    116     <p>Facebook users who are not fans of your page will see a single image, that you input in the <strong>Featured image</strong> area of this page.</p> 
    117     <h3>Add content for your fans to see</h3> 
    118     <p>In the content area, add the content you want your fans to see. Publish, copy the URL of the created page to your clipboard: <br/><br/><code><?php the_permalink(); ?></code></p> 
    119     <p>Back to Facebook and your application settings, in the <strong>Facebook integration tab</strong>, scroll to the bottom and paste your URL into the <em>Tab URL</em> box.</p> 
    120     <p>And that's it!</p> 
     121    <h3><?php _e( 'Choose the image displayed to the non-fans of your page', 'werewpfbapps' ); ?></h3> 
     122    <p><?php _e( 'Facebook users who are not fans of your page will see a single image, that you input in the <strong>Featured image</strong> area of this page.<br/>If you don\'t want any specific content for the non-fans, simply leave the Featured Image empty, and all viewers will see all the content.', 'werewpfbapps' ); ?></p> 
     123    <h3><?php _e( 'Add content for your fans to see', 'werewpfbapps' ); ?></h3> 
     124    <p><?php _e( 'In the content area, add the content you want your fans to see. Publish, copy the URL of the created page to your clipboard:', 'werewpfbapps' ); ?><br/><br/><code><?php the_permalink(); ?></code></p> 
     125    <p><?php _e( 'Back to Facebook and your application settings, in the <strong>Facebook integration tab</strong>, scroll to the bottom and paste your URL into the <em>Tab URL</em> box.', 'werewpfbapps' ); ?></p> 
     126    <p><?php _e( 'And that\'s it!', 'werewpfbapps' ); ?></p> 
    121127    <?php 
    122128} 
     
    134140function werewp_fbapp_edit_columns($columns){ 
    135141  $columns = array( 
    136     'cb' => '<input type=\"checkbox\" />', 
    137     'title' => 'Application title', 
    138     'appid' => 'Application ID', 
    139     'appsecret' => 'Application secret', 
     142    'cb' => '<input type="checkbox" />', 
     143    'title' => __( 'Application title', 'werewpfbapps' ), 
     144    'appid' => __( 'Application ID', 'werewpfbapps' ), 
     145    'appsecret' => __( 'Application secret', 'werewpfbapps' ), 
    140146  ); 
    141147  
Note: See TracChangeset for help on using the changeset viewer.