WP Embed Facebook - Version 1.9

Version Description

  • Facebook video embed code in case video type is not supported
  • Fix: Compatibility with other facebook plugins thanks to ozzWANTED
  • New filter: 'wpemfb_api_string' and 'wpemfb_2nd_api_string'
  • Show embedded posts on admin
  • Fix undefined variable on js
  • Fix languages on event time
Download this release

Release Info

Developer poxtron
Plugin Icon 128x128 WP Embed Facebook
Version 1.9
Comparing to
See all releases

Code changes from version 1.8.3 to 1.9

lib/admin.php CHANGED
@@ -9,11 +9,12 @@ class EmbFbAdmin{
9
  $url = "http://ajax.googleapis.com/ajax/libs/jqueryui/".$queryui->ver."/themes/smoothness/jquery-ui.css";
10
  wp_enqueue_style('jquery-ui-start', $url, false, null);
11
  }
12
- $translation_array = array( 'local' => get_locale(), 'fb_id'=>get_option('wpemfb_app_id'), 'fb_root'=>get_option('wpemfb_fb_root') );
13
- wp_localize_script( 'wpemfb', 'WEF', $translation_array );
 
14
  }
15
  static function admin_init(){
16
- $theme = get_option('wpemfb_theme');
17
  add_editor_style( WPEMFBURL.'templates/'.$theme.'/wpemfb.css' );
18
  }
19
  static function add_page(){
@@ -22,99 +23,115 @@ class EmbFbAdmin{
22
  static function savedata(){
23
  if(isset($_POST['wpemfb_app_secret'], $_POST['wpemfb_app_id' ] )) {
24
  if($_POST['wpemfb_app_id'] && $_POST['wpemfb_app_secret']){
25
- update_option('wpemfb_app_id',$_POST['wpemfb_app_id']);
26
- update_option('wpemfb_app_secret',$_POST['wpemfb_app_secret']);
27
  }
28
  if(isset($_POST['wpemfb_max_width'])){
29
- $prop = get_option('wpemfb_proportions') * $_POST['wpemfb_max_width'];
30
- update_option('wpemfb_max_width', $_POST['wpemfb_max_width']);
31
- update_option('wpemfb_height', $prop );
32
  }
33
  if(isset($_POST['wpemfb_max_photos'])){
34
- update_option('wpemfb_max_photos', $_POST['wpemfb_max_photos']);
35
  }
36
  if(isset($_POST['wpemfb_max_posts'])){
37
- update_option('wpemfb_max_posts', $_POST['wpemfb_max_posts']);
38
  }
39
  if(isset($_POST['wpemfb_theme'])){
40
- update_option('wpemfb_theme', $_POST['wpemfb_theme']);
41
  }
42
  if(isset($_POST['wpemfb_show_like'])){
43
- update_option('wpemfb_show_like', 'true');
44
  }else{
45
- update_option('wpemfb_show_like', 'false');
46
  }
47
  if(isset($_POST['wpemfb_enqueue_style'])){
48
- update_option('wpemfb_enqueue_style', 'true');
49
  }else{
50
- update_option('wpemfb_enqueue_style', 'false');
51
  }
52
  if(isset($_POST['wpemfb_fb_root'])){
53
- update_option('wpemfb_fb_root', 'true');
54
  }else{
55
- update_option('wpemfb_fb_root', 'false');
56
  }
57
  if(isset($_POST['wpemfb_show_follow'])){
58
- update_option('wpemfb_show_follow', 'true');
59
  }else{
60
- update_option('wpemfb_show_follow', 'false');
61
  }
62
  if(isset($_POST['wpemfb_raw_video'])){
63
- update_option('wpemfb_raw_video', 'true');
64
  }else{
65
- update_option('wpemfb_raw_video', 'false');
66
  }
67
  if(isset($_POST['wpemfb_raw_photo'])){
68
- update_option('wpemfb_raw_photo', 'true');
69
  }else{
70
- update_option('wpemfb_raw_photo', 'false');
71
  }
72
  if(isset($_POST['wpemfb_show_posts'])){
73
- update_option('wpemfb_show_posts', 'true');
74
  }else{
75
- update_option('wpemfb_show_posts', 'false');
76
  }
77
  if(isset($_POST['wpemfb_raw_post'])){
78
- update_option('wpemfb_raw_post', 'true');
79
  }else{
80
- update_option('wpemfb_raw_post', 'false');
81
  }
82
  if(isset($_POST['wpemfb_enq_lightbox'])){
83
- update_option('wpemfb_enq_lightbox', 'true');
84
  }else{
85
- update_option('wpemfb_enq_lightbox', 'false');
86
  }
87
  if(isset($_POST['wpemfb_enq_wpemfb'])){
88
- update_option('wpemfb_enq_wpemfb', 'true');
89
  }else{
90
- update_option('wpemfb_enq_wpemfb', 'false');
91
  }
92
  if(isset($_POST['wpemfb_enq_fbjs'])){
93
- update_option('wpemfb_enq_fbjs', 'true');
94
  }else{
95
- update_option('wpemfb_enq_fbjs', 'false');
96
- }
 
 
 
 
 
 
97
  }
98
- do_action('wpemfb_admin_savedata');
 
 
 
 
 
 
99
  }
100
  static function embedfb_page() {
101
- if(isset($_POST['submit']) && check_admin_referer( 'wp-embed-facebook','save-data' )){
102
  self::savedata();
 
103
  }
104
- $checked = (get_option('wpemfb_enqueue_style') === 'true') ? 'checked' : '' ;
105
- $checked2 = (get_option('wpemfb_show_like') === 'true') ? 'checked' : '' ;
106
- $checked3 = (get_option('wpemfb_fb_root') === 'true') ? 'checked' : '' ;
107
- $checked4 = (get_option('wpemfb_show_follow') === 'true') ? 'checked' : '' ;
108
- $checked5 = (get_option('wpemfb_raw_video') === 'true') ? 'checked' : '' ;
109
- $checked6 = (get_option('wpemfb_raw_photo') === 'true') ? 'checked' : '' ;
110
- $checked7 = (get_option('wpemfb_show_posts') === 'true') ? 'checked' : '' ;
111
 
112
- $checked8 = (get_option('wpemfb_raw_post') === 'true') ? 'checked' : '' ;
113
- $checked9 = (get_option('wpemfb_enq_lightbox') === 'true') ? 'checked' : '' ;
114
- $checked10 = (get_option('wpemfb_enq_wpemfb') === 'true') ? 'checked' : '' ;
115
- $checked11 = (get_option('wpemfb_enq_fbjs') === 'true') ? 'checked' : '' ;
116
- $sel1 = (get_option('wpemfb_theme') === 'default') ? 'selected' : '' ;
117
- $sel2 = (get_option('wpemfb_theme') === 'classic') ? 'selected' : '' ;
 
 
 
118
  ?>
119
  <style>
120
  .ui-widget-content th{
@@ -155,13 +172,13 @@ class EmbFbAdmin{
155
  <tr valign="middle">
156
  <th>App ID</th>
157
  <td>
158
- <input type="text" name="wpemfb_app_id" required value="<?php echo get_option('wpemfb_app_id') ?>" size="38" />
159
  </td>
160
  </tr>
161
  <tr valign="middle">
162
  <th>App Secret</th>
163
  <td>
164
- <input type="text" name="wpemfb_app_secret" required value="<?php echo get_option('wpemfb_app_secret') ?>" size="38" />
165
  </td>
166
  </tr>
167
  </table>
@@ -176,20 +193,28 @@ class EmbFbAdmin{
176
  <select name="wpemfb_theme">
177
  <option value="default" <?php echo $sel1 ?> >Default</option>
178
  <option value="classic" <?php echo $sel2 ?> >Classic</option>
179
- <?php do_action('wpemfb_admin_theme'); ?>
 
 
 
 
 
 
 
 
180
  </select>
181
  </td>
182
  </tr>
183
  <tr valign="middle">
184
  <th><?php _e('Embed Max-Width','wp-embed-facebook') ?></th>
185
  <td>
186
- <input type="number" name="wpemfb_max_width" value="<?php echo get_option('wpemfb_max_width') ?>" />
187
  </td>
188
  </tr>
189
  <tr valign="middle">
190
- <th><?php _e('Number of Photos <br> on Embedded Albums','wp-embed-facebook') ?></th>
191
  <td>
192
- <input type="number" name="wpemfb_max_photos" value="<?php echo get_option('wpemfb_max_photos') ?>" />
193
  </td>
194
  </tr>
195
  <tr valign="middle">
@@ -220,9 +245,15 @@ class EmbFbAdmin{
220
  <tr valign="middle">
221
  <th><?php _e('Number of posts','wp-embed-facebook') ?></th>
222
  <td>
223
- <input type="number" name="wpemfb_max_posts" value="<?php echo get_option('wpemfb_max_posts') ?>" style="width: 60px;"/>
224
  </td>
225
- </tr>
 
 
 
 
 
 
226
  </tbody>
227
  </table>
228
  </div>
@@ -253,11 +284,20 @@ class EmbFbAdmin{
253
  </td>
254
  </tr>
255
  */
256
- ?>
 
257
  </tbody>
258
  </table>
259
  </div>
260
- <?php do_action('wpemfb_options'); ?>
 
 
 
 
 
 
 
 
261
  <h5><?php _e('Advanced Options', 'wp-embed-facebook') ?></h5>
262
  <div>
263
  <table>
9
  $url = "http://ajax.googleapis.com/ajax/libs/jqueryui/".$queryui->ver."/themes/smoothness/jquery-ui.css";
10
  wp_enqueue_style('jquery-ui-start', $url, false, null);
11
  }
12
+ $translation_array = array( 'local' => get_locale(), 'fb_id'=>get_site_option('wpemfb_app_id'), 'fb_root'=>get_site_option('wpemfb_fb_root') );
13
+ wp_localize_script( 'wpemfb', 'WEF', $translation_array );
14
+ wp_enqueue_script('wpemfb');
15
  }
16
  static function admin_init(){
17
+ $theme = get_site_option('wpemfb_theme');
18
  add_editor_style( WPEMFBURL.'templates/'.$theme.'/wpemfb.css' );
19
  }
20
  static function add_page(){
23
  static function savedata(){
24
  if(isset($_POST['wpemfb_app_secret'], $_POST['wpemfb_app_id' ] )) {
25
  if($_POST['wpemfb_app_id'] && $_POST['wpemfb_app_secret']){
26
+ update_site_option('wpemfb_app_id',$_POST['wpemfb_app_id']);
27
+ update_site_option('wpemfb_app_secret',$_POST['wpemfb_app_secret']);
28
  }
29
  if(isset($_POST['wpemfb_max_width'])){
30
+ $prop = get_site_option('wpemfb_proportions') * $_POST['wpemfb_max_width'];
31
+ update_site_option('wpemfb_max_width', $_POST['wpemfb_max_width']);
32
+ update_site_option('wpemfb_height', $prop );
33
  }
34
  if(isset($_POST['wpemfb_max_photos'])){
35
+ update_site_option('wpemfb_max_photos', $_POST['wpemfb_max_photos']);
36
  }
37
  if(isset($_POST['wpemfb_max_posts'])){
38
+ update_site_option('wpemfb_max_posts', $_POST['wpemfb_max_posts']);
39
  }
40
  if(isset($_POST['wpemfb_theme'])){
41
+ update_site_option('wpemfb_theme', $_POST['wpemfb_theme']);
42
  }
43
  if(isset($_POST['wpemfb_show_like'])){
44
+ update_site_option('wpemfb_show_like', 'true');
45
  }else{
46
+ update_site_option('wpemfb_show_like', 'false');
47
  }
48
  if(isset($_POST['wpemfb_enqueue_style'])){
49
+ update_site_option('wpemfb_enqueue_style', 'true');
50
  }else{
51
+ update_site_option('wpemfb_enqueue_style', 'false');
52
  }
53
  if(isset($_POST['wpemfb_fb_root'])){
54
+ update_site_option('wpemfb_fb_root', 'true');
55
  }else{
56
+ update_site_option('wpemfb_fb_root', 'false');
57
  }
58
  if(isset($_POST['wpemfb_show_follow'])){
59
+ update_site_option('wpemfb_show_follow', 'true');
60
  }else{
61
+ update_site_option('wpemfb_show_follow', 'false');
62
  }
63
  if(isset($_POST['wpemfb_raw_video'])){
64
+ update_site_option('wpemfb_raw_video', 'true');
65
  }else{
66
+ update_site_option('wpemfb_raw_video', 'false');
67
  }
68
  if(isset($_POST['wpemfb_raw_photo'])){
69
+ update_site_option('wpemfb_raw_photo', 'true');
70
  }else{
71
+ update_site_option('wpemfb_raw_photo', 'false');
72
  }
73
  if(isset($_POST['wpemfb_show_posts'])){
74
+ update_site_option('wpemfb_show_posts', 'true');
75
  }else{
76
+ update_site_option('wpemfb_show_posts', 'false');
77
  }
78
  if(isset($_POST['wpemfb_raw_post'])){
79
+ update_site_option('wpemfb_raw_post', 'true');
80
  }else{
81
+ update_site_option('wpemfb_raw_post', 'false');
82
  }
83
  if(isset($_POST['wpemfb_enq_lightbox'])){
84
+ update_site_option('wpemfb_enq_lightbox', 'true');
85
  }else{
86
+ update_site_option('wpemfb_enq_lightbox', 'false');
87
  }
88
  if(isset($_POST['wpemfb_enq_wpemfb'])){
89
+ update_site_option('wpemfb_enq_wpemfb', 'true');
90
  }else{
91
+ update_site_option('wpemfb_enq_wpemfb', 'false');
92
  }
93
  if(isset($_POST['wpemfb_enq_fbjs'])){
94
+ update_site_option('wpemfb_enq_fbjs', 'true');
95
  }else{
96
+ update_site_option('wpemfb_enq_fbjs', 'false');
97
+ }
98
+ if(isset($_POST['wpemfb_ev_local_tz'])){
99
+ update_site_option('wpemfb_ev_local_tz', 'true');
100
+ }else{
101
+ update_site_option('wpemfb_ev_local_tz', 'false');
102
+ }
103
+
104
  }
105
+ /**
106
+ * Save extra options, requires coordination with 'wpemfb_options' action
107
+ *
108
+ * @since 1.8
109
+ *
110
+ */
111
+ do_action('wpemfb_admin_save_data');
112
  }
113
  static function embedfb_page() {
114
+ if( isset($_POST['save-data']) && wp_verify_nonce( $_POST['save-data'], 'wp-embed-facebook')){
115
  self::savedata();
116
+
117
  }
118
+ $checked = (get_site_option('wpemfb_enqueue_style') === 'true') ? 'checked' : '' ;
119
+ $checked2 = (get_site_option('wpemfb_show_like') === 'true') ? 'checked' : '' ;
120
+ $checked3 = (get_site_option('wpemfb_fb_root') === 'true') ? 'checked' : '' ;
121
+ $checked4 = (get_site_option('wpemfb_show_follow') === 'true') ? 'checked' : '' ;
122
+ $checked5 = (get_site_option('wpemfb_raw_video') === 'true') ? 'checked' : '' ;
123
+ $checked6 = (get_site_option('wpemfb_raw_photo') === 'true') ? 'checked' : '' ;
124
+ $checked7 = (get_site_option('wpemfb_show_posts') === 'true') ? 'checked' : '' ;
125
 
126
+ $checked8 = (get_site_option('wpemfb_raw_post') === 'true') ? 'checked' : '' ;
127
+ $checked9 = (get_site_option('wpemfb_enq_lightbox') === 'true') ? 'checked' : '' ;
128
+ $checked10 = (get_site_option('wpemfb_enq_wpemfb') === 'true') ? 'checked' : '' ;
129
+ $checked11 = (get_site_option('wpemfb_enq_fbjs') === 'true') ? 'checked' : '' ;
130
+ $checked12 = (get_site_option('wpemfb_ev_local_tz', 'true') === 'true') ? 'checked' : '' ;
131
+
132
+ $sel1 = (get_site_option('wpemfb_theme') === 'default') ? 'selected' : '' ;
133
+ $sel2 = (get_site_option('wpemfb_theme') === 'classic') ? 'selected' : '' ;
134
+
135
  ?>
136
  <style>
137
  .ui-widget-content th{
172
  <tr valign="middle">
173
  <th>App ID</th>
174
  <td>
175
+ <input type="text" name="wpemfb_app_id" required value="<?php echo get_site_option('wpemfb_app_id') ?>" size="38" />
176
  </td>
177
  </tr>
178
  <tr valign="middle">
179
  <th>App Secret</th>
180
  <td>
181
+ <input type="text" name="wpemfb_app_secret" required value="<?php echo get_site_option('wpemfb_app_secret') ?>" size="38" />
182
  </td>
183
  </tr>
184
  </table>
193
  <select name="wpemfb_theme">
194
  <option value="default" <?php echo $sel1 ?> >Default</option>
195
  <option value="classic" <?php echo $sel2 ?> >Classic</option>
196
+ <?php
197
+ /**
198
+ * Add a new theme option
199
+ *
200
+ * @since 1.8
201
+ *
202
+ */
203
+ do_action('wpemfb_admin_theme');
204
+ ?>
205
  </select>
206
  </td>
207
  </tr>
208
  <tr valign="middle">
209
  <th><?php _e('Embed Max-Width','wp-embed-facebook') ?></th>
210
  <td>
211
+ <input type="number" name="wpemfb_max_width" value="<?php echo get_site_option('wpemfb_max_width') ?>" />
212
  </td>
213
  </tr>
214
  <tr valign="middle">
215
+ <th><?php _e('Number of Photos <br>on Embedded Albums','wp-embed-facebook') ?></th>
216
  <td>
217
+ <input type="number" name="wpemfb_max_photos" value="<?php echo get_site_option('wpemfb_max_photos') ?>" />
218
  </td>
219
  </tr>
220
  <tr valign="middle">
245
  <tr valign="middle">
246
  <th><?php _e('Number of posts','wp-embed-facebook') ?></th>
247
  <td>
248
+ <input type="number" name="wpemfb_max_posts" value="<?php echo get_site_option('wpemfb_max_posts') ?>" style="width: 60px;"/>
249
  </td>
250
+ </tr>
251
+ <tr valign="middle">
252
+ <th><?php _e('Show events on local time','wp-embed-facebook') ?></th>
253
+ <td>
254
+ <input type="checkbox" name="wpemfb_ev_local_tz" <?php echo $checked12 ?> />
255
+ </td>
256
+ </tr>
257
  </tbody>
258
  </table>
259
  </div>
284
  </td>
285
  </tr>
286
  */
287
+ ?>
288
+
289
  </tbody>
290
  </table>
291
  </div>
292
+ <?php
293
+ /**
294
+ * Add more options to the plugin page save them with 'wpemfb_admin_save_data' action
295
+ *
296
+ * @since 1.8
297
+ *
298
+ */
299
+ do_action('wpemfb_options');
300
+ ?>
301
  <h5><?php _e('Advanced Options', 'wp-embed-facebook') ?></h5>
302
  <div>
303
  <table>
lib/core.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  * Main Class of the plugin.
4
  */
5
- wp_embed_register_handler("wpembedfb","/(http|https):\/\/www\.facebook\.com\/([^<\s]*)/",array("WP_Embed_FB","embed_register_handler"));
6
  class WP_Embed_FB {
7
  static $fbsdk;
8
  static $width = '';
@@ -10,49 +10,38 @@ class WP_Embed_FB {
10
  static $theme = '';
11
  static $raw = '';
12
  static $premium = '';
13
- /*
 
14
  * Save default values to data base
15
  */
16
  static function install(){
17
  $defaults = self::getdefaults();
18
  foreach ($defaults as $option => $value) {
19
- if ( !is_multisite() ) {
20
- $opt = get_option($option);
21
- if($opt === false)
22
- update_option($option, $value);
23
- }
24
- else {
25
- $opt = get_site_option($option);
26
- if($opt === false)
27
- update_site_option($option, $value);
28
- }
29
  if(!isset($type))
30
  $type = $opt==false?"activated":"reactivated";
31
  }
32
- self::whois($type);
33
  return;
34
  }
35
- /*
36
  * Delete all plugin options on uninstall
37
  */
38
  static function uninstall(){
39
  $defaults = self::getdefaults();
40
  foreach ($defaults as $option ) {
41
- if ( !is_multisite() ) {
42
- delete_option($option);
43
- }
44
- else {
45
- delete_site_option($option);
46
- }
47
  }
48
- self::whois('uninstalled');
49
  return;
50
  }
51
  static function deactivate(){
52
- self::whois('deactivated');
53
  return;
54
  }
55
- /*
56
  * Default options
57
  */
58
  static function getdefaults(){
@@ -75,7 +64,8 @@ class WP_Embed_FB {
75
  'wpemfb_raw_post' => 'false',
76
  'wpemfb_enq_lightbox' => 'true',
77
  'wpemfb_enq_wpemfb' => 'true',
78
- 'wpemfb_enq_fbjs' => 'true'
 
79
  );
80
  }
81
  //("uninstalled","deactivated","activated","reactivated")
@@ -85,21 +75,21 @@ class WP_Embed_FB {
85
  @file_get_contents("http://www.wpembedfb.com/api/?whois=$install&site_url=$home");
86
  return true;
87
  }
88
- /*
89
  * load translations and facebook sdk
90
  */
91
  static function init(){
92
  load_plugin_textdomain( 'wp-embed-facebook', false, WPEMFBSLUG . '/lang' );
93
  FaceInit::init();
94
  }
95
- /*
96
  * Enqueue wp embed facebook styles
97
  */
98
  static function wp_enqueue_scripts(){
99
  if(get_option('wpemfb_enqueue_style') == 'true'){
100
  $theme = get_option('wpemfb_theme');
101
- wp_register_style( 'wpemfb-style', WPEMFBURL.'/templates/'.$theme.'/wpemfb.css');
102
- wp_register_style( 'wpemfb-lightbox', WPEMFBURL.'/lib/lightbox2/css/lightbox.css');
103
  wp_enqueue_style('wpemfb-style');
104
  wp_enqueue_style('wpemfb-lightbox');
105
  }
@@ -127,13 +117,10 @@ class WP_Embed_FB {
127
  wp_localize_script( 'wpemfbjs', 'WEF', $translation_array );
128
  }
129
  }
130
- /* ?????? */
131
- static function tiny_mce_before_init(){
132
- $theme = get_option('wpemfb_theme');
133
- wp_register_style( 'wpemfb-style', WPEMFBURL.'templates/'.$theme.'/wpemfb.css');
134
- }
135
- /*
136
- * the_content filter to process fb url's
137
  */
138
  static function the_content($the_content){
139
  preg_match_all("/<p>(http|https):\/\/www\.facebook\.com\/([^<\s]*)<\/p>/", $the_content, $matches, PREG_SET_ORDER);
@@ -149,7 +136,8 @@ class WP_Embed_FB {
149
  }
150
  /**
151
  * Extract fb_id from the url
152
- * @param array $match[2]=the juice from the url
 
153
  */
154
  static function fb_embed($match){
155
  //extract fbid from url good for profiles, pages, comunity pages, raw photos, events
@@ -177,9 +165,15 @@ class WP_Embed_FB {
177
  $fb_id = $ids[1];
178
  }
179
  }
180
- //TODO: check if its event and pull cover photo, probably only fro premium
181
- //do_action('wpemfb_embed',$type,$clean,$vars,$match);
182
- $type = apply_filters('wpemfb_embed_type',$type,$clean);
 
 
 
 
 
 
183
  //its a post
184
  if( array_search('posts',$clean) !== false ){
185
  $fb_data = array( 'link' => $match[2],'is_post' => '' );
@@ -197,7 +191,7 @@ class WP_Embed_FB {
197
  if(isset($vars['v'])){ //is video
198
  if($raw_video == 'true'){
199
  //$fb_data = array( 'v_id' => $vars['v'], 'is_video' => '' );
200
- return self::fb_api_get($vars['v'], $match[2]);
201
  //return self::print_fb_data($fb_data);
202
  } else {
203
  $fb_data = array( 'link' => $match[2],'is_post' => '' );
@@ -207,65 +201,95 @@ class WP_Embed_FB {
207
  //photos
208
  if( 'photo.php' == $last || ( array_search('photos',$clean) !== false ) ){
209
  if($raw_photo == 'true'){
210
- return self::fb_api_get($fb_id, $match[2]);
211
  } else {
212
  $fb_data = array( 'link' => $match[2],'is_post' => '' );
213
  return self::print_fb_data($fb_data);
214
  }
215
  }
216
 
217
- return self::fb_api_get($fb_id, $match[2], $type);
218
  }
219
  /**
220
- * get data from fb using $fbsdk->api('/'.$fb_id) :)
221
- *
 
 
 
 
222
  */
223
  static function fb_api_get($fb_id, $url, $type=""){
224
  $wp_emb_fbsdk = self::$fbsdk;
225
- if(!self::$premium){
226
  try {
227
- if(empty($type))
228
- $fb_data = $wp_emb_fbsdk->api('/v1.0/'.$fb_id);
229
- elseif($type == 'album')
230
- $fb_data = $wp_emb_fbsdk->api('/'.$fb_id.'?fields=name,id,from,photos.fields(name,picture,source).limit('.get_option("wpemfb_max_photos").')');
231
- //$res = '<pre>'.print_r($fb_data,true).'</pre>'; //to inspect what elements are queried by default
232
- if(isset($fb_data['category']) && get_option("wpemfb_show_posts") == "true")
233
- $fb_data = $fb_data + $wp_emb_fbsdk->api('/'.$fb_data['id'].'?fields=posts.limit('.get_option("wpemfb_max_posts").'){message,shares,link,picture,object_id,likes.limit(1).summary(true),comments.limit(1).summary(true)}');
234
- elseif(isset($fb_data['embed_html']))
235
- $fb_data = array_merge($fb_data,array('is_video' => '1'));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  $res = self::print_fb_data($fb_data);
237
  } catch(FacebookApiException $e) {
238
  $res = '<p><a href="https://www.facebook.com/'.$url.'" target="_blank" rel="nofollow">https://www.facebook.com/'.$url.'</a>';
239
- //uncoment this lines to debug
240
- ///*
241
  if(is_super_admin()){
242
  $error = $e->getResult();
243
- $res .= '<br><span style="color: red">'.__('This facebook link is not public', 'wp-embed-facebook').'</span>';
244
  $res .= '<br>';
245
  $res .= $error['error']['message'];
246
  }
247
- //*/
248
  $res .= '</p>';
249
  }
250
- }
251
- else
252
- $res = WP_Embed_FB_Premium::fb_api_get($fb_id, $url, $type, $wp_emb_fbsdk);
253
  return $res;
254
  }
255
  /**
256
  * find out what kind of data we got from facebook
257
- * @param array result from facebook
 
 
258
  */
259
  static function print_fb_data($fb_data){
260
- if(empty(self::$width)){
261
- $width = get_option('wpemfb_max_width');
262
- $height = get_option('wpemfb_height');
263
- } else {
264
- $width = self::$width;
265
- $height = self::$height;
266
- }
267
- $prop = get_option('wpemfb_proportions');
268
-
269
  if(isset($fb_data['is_video'])) { //is raw video
270
  $template = self::locate_template('video');
271
  } elseif(isset($fb_data['is_post'])) { //is post
@@ -281,30 +305,62 @@ class WP_Embed_FB {
281
  $template = self::locate_template('com-page'); //is community page
282
  }else {
283
  $default = self::locate_template('page');
284
- /*
285
- *To add a new template for a specific facebook category for example a Museum add this to your functions.php file
286
- *
287
- add_filter( 'wpemfb_category_template', 'your_function', 10, 2 );
288
- function your_function( $default, $category ) {
289
- if($category == 'Museum/art gallery')
290
- return WP_Embed_FB::locate_template('museum');
291
- else
292
- return $default;
293
- }
294
- * then create a file named museum.php inside your-theme/plugins/wp-embed-facebook/
295
- */
 
 
 
 
 
 
 
 
296
  $template = apply_filters('wpemfb_category_template', $default, $fb_data['category']);
297
  }
298
  } else { //is profile
299
  $template = self::locate_template('profile');
300
  }
301
- ob_start();
302
- include(apply_filters('wpemfb_template',$template,$fb_data));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
  return preg_replace('/^\s+|\n|\r|\s+$/m', '', ob_get_clean());
304
  }
305
  /**
306
  * Locate the template inside plugin or theme
307
- * @param string Template Name album,profile...
 
 
308
  */
309
  static function locate_template($template_name){
310
  $theme = get_option('wpemfb_theme');
@@ -324,7 +380,8 @@ class WP_Embed_FB {
324
  */
325
  /**
326
  * If a user has a lot of websites registered on fb this function will only link to the first one
327
- * @param string urls separated by spaces
 
328
  */
329
  static function getwebsite($urls){
330
  $url = explode(' ',$urls);
@@ -332,17 +389,23 @@ class WP_Embed_FB {
332
  }
333
  /**
334
  * Shows a like button or a facebook like count of a page depending on settings
335
- * @param int facebook id
336
- * @param int show likes count
337
- * @param bool show share button
338
- * @param bool show faces
339
  */
340
  static function like_btn($fb_id,$likes=null,$share=false,$faces=false){
341
  $opt = get_option('wpemfb_show_like');
342
  if($opt === 'true') :
343
  ob_start();
344
  ?>
345
- <div class="fb-like" data-href="https://facebook.com/<?php echo $fb_id ?>" data-layout="button_count" data-action="like" data-show-faces="<?php echo $faces ? 'true' : 'false' ?>" data-share="<?php echo $share ? 'true' : 'false' ?>" ></div>
 
 
 
 
 
 
346
  <?php
347
  echo ob_get_clean();
348
  return;
@@ -353,23 +416,29 @@ class WP_Embed_FB {
353
  }
354
  /**
355
  * Shows a follow button depending on settings
356
- * @param facebook id
357
  */
358
  static function follow_btn($fb_id){
359
  $opt = get_option('wpemfb_show_follow');
360
  if($opt === 'true') :
361
  ob_start();
362
  ?>
363
- <div class="fb-follow" data-href="https://www.facebook.com/<?php echo $fb_id ?>" data-colorscheme="light" data-layout="button_count" data-show-faces="false"></div>
 
 
 
 
 
364
  <?php
365
  ob_end_flush();
366
  return;
367
  endif;
368
  }
369
  /**
370
- * Shotcode function
371
  * [facebook='url' width='600'] width is optional
372
- * @param array [0]=>url ['width']=>embed width ['raw']=>for videos and photos
 
373
  */
374
  static function shortcode($atts){
375
  if(!empty($atts) && isset($atts[0])){
@@ -381,11 +450,12 @@ class WP_Embed_FB {
381
  }
382
  if(isset($atts['raw'])){
383
  self::$raw = $atts['raw'];
384
- }
 
 
 
385
  $embed = self::the_content($url);
386
- self::$height = '';
387
- self::$width = '';
388
- self::$raw = '';
389
  return $embed;
390
  }
391
  return;
@@ -402,29 +472,29 @@ class WP_Embed_FB {
402
  }
403
  static function plugins_loaded(){
404
  $lic = get_option('wpemfb_license','');
405
- if(class_exists('WP_Embed_FB_Premium') && !empty($lic) )
406
  self::$premium = true;
407
  else
408
  self::$premium = false;
409
  }
410
  }
411
 
412
- /*
413
- * Trigering the FaceInit::init(); will give you access to the fb php sdk on FaceInit::$fbsdk which you can use to make any call shown here
414
  * https://developers.facebook.com/docs/reference/php/
415
  */
416
  class FaceInit {
417
  static $fbsdk;
418
  static function init(){
419
- if(!class_exists('Facebook'))
420
- require('fb/facebook.php');
421
  $config = array();
422
  $config['appId'] = get_option('wpemfb_app_id');
423
  $config['secret'] = get_option('wpemfb_app_secret');
424
  $config['fileUpload'] = false; // optional
425
  if($config['appId'] != '0' && $config['secret'] != '0' )
426
- self::$fbsdk = new Facebook($config);
427
  else
428
  self::$fbsdk = 'unactive';
429
  }
430
  }
 
2
  /*
3
  * Main Class of the plugin.
4
  */
5
+
6
  class WP_Embed_FB {
7
  static $fbsdk;
8
  static $width = '';
10
  static $theme = '';
11
  static $raw = '';
12
  static $premium = '';
13
+ static $num_posts = '';
14
+ /**
15
  * Save default values to data base
16
  */
17
  static function install(){
18
  $defaults = self::getdefaults();
19
  foreach ($defaults as $option => $value) {
20
+ $opt = get_site_option($option);
21
+ if($opt === false)
22
+ update_site_option($option, $value);
 
 
 
 
 
 
 
23
  if(!isset($type))
24
  $type = $opt==false?"activated":"reactivated";
25
  }
26
+ static::whois($type);
27
  return;
28
  }
29
+ /**
30
  * Delete all plugin options on uninstall
31
  */
32
  static function uninstall(){
33
  $defaults = self::getdefaults();
34
  foreach ($defaults as $option ) {
35
+ delete_site_option($option);
 
 
 
 
 
36
  }
37
+ static::whois('uninstalled');
38
  return;
39
  }
40
  static function deactivate(){
41
+ static::whois('deactivated');
42
  return;
43
  }
44
+ /**
45
  * Default options
46
  */
47
  static function getdefaults(){
64
  'wpemfb_raw_post' => 'false',
65
  'wpemfb_enq_lightbox' => 'true',
66
  'wpemfb_enq_wpemfb' => 'true',
67
+ 'wpemfb_enq_fbjs' => 'true',
68
+ 'wpemfb_ev_local_tz' => 'true'
69
  );
70
  }
71
  //("uninstalled","deactivated","activated","reactivated")
75
  @file_get_contents("http://www.wpembedfb.com/api/?whois=$install&site_url=$home");
76
  return true;
77
  }
78
+ /**
79
  * load translations and facebook sdk
80
  */
81
  static function init(){
82
  load_plugin_textdomain( 'wp-embed-facebook', false, WPEMFBSLUG . '/lang' );
83
  FaceInit::init();
84
  }
85
+ /**
86
  * Enqueue wp embed facebook styles
87
  */
88
  static function wp_enqueue_scripts(){
89
  if(get_option('wpemfb_enqueue_style') == 'true'){
90
  $theme = get_option('wpemfb_theme');
91
+ wp_register_style( 'wpemfb-style', WPEMFBURL.'templates/'.$theme.'/wpemfb.css');
92
+ wp_register_style( 'wpemfb-lightbox', WPEMFBURL.'lib/lightbox2/css/lightbox.css');
93
  wp_enqueue_style('wpemfb-style');
94
  wp_enqueue_style('wpemfb-lightbox');
95
  }
117
  wp_localize_script( 'wpemfbjs', 'WEF', $translation_array );
118
  }
119
  }
120
+ /**
121
+ * Find facebook urls on a string and return content
122
+ * @param string post content
123
+ * @return string content with embeds if present.
 
 
 
124
  */
125
  static function the_content($the_content){
126
  preg_match_all("/<p>(http|https):\/\/www\.facebook\.com\/([^<\s]*)<\/p>/", $the_content, $matches, PREG_SET_ORDER);
136
  }
137
  /**
138
  * Extract fb_id from the url
139
+ * @param array $match[2]=url without ' https://www.facebook.com/ '
140
+ * @return string Embedded content
141
  */
142
  static function fb_embed($match){
143
  //extract fbid from url good for profiles, pages, comunity pages, raw photos, events
165
  $fb_id = $ids[1];
166
  }
167
  }
168
+ /**
169
+ * Filter the embed type.
170
+ *
171
+ * @since 1.8
172
+ *
173
+ * @param string $type the embed type.
174
+ * @param array $clean url parts of the request.
175
+ */
176
+ $type = apply_filters('wpemfb_embed_type',$type,$clean);
177
  //its a post
178
  if( array_search('posts',$clean) !== false ){
179
  $fb_data = array( 'link' => $match[2],'is_post' => '' );
191
  if(isset($vars['v'])){ //is video
192
  if($raw_video == 'true'){
193
  //$fb_data = array( 'v_id' => $vars['v'], 'is_video' => '' );
194
+ return static::fb_api_get($vars['v'], $match[2]);
195
  //return self::print_fb_data($fb_data);
196
  } else {
197
  $fb_data = array( 'link' => $match[2],'is_post' => '' );
201
  //photos
202
  if( 'photo.php' == $last || ( array_search('photos',$clean) !== false ) ){
203
  if($raw_photo == 'true'){
204
+ return static::fb_api_get($fb_id, $match[2]);
205
  } else {
206
  $fb_data = array( 'link' => $match[2],'is_post' => '' );
207
  return self::print_fb_data($fb_data);
208
  }
209
  }
210
 
211
+ return static::fb_api_get($fb_id, $match[2], $type);
212
  }
213
  /**
214
+ * get data from fb using WP_Embed_FB::$fbsdk->api('/'.$fb_id) :)
215
+ *
216
+ * @param int facebook id
217
+ * @param string facebook url
218
+ * @type string type of embed
219
+ * @return facebook api resulto or error
220
  */
221
  static function fb_api_get($fb_id, $url, $type=""){
222
  $wp_emb_fbsdk = self::$fbsdk;
 
223
  try {
224
+ if($type == 'album')
225
+ $api_string = $fb_id.'?fields=name,id,from,description,photos.fields(name,picture,source).limit('.get_option("wpemfb_max_photos").')';
226
+ else
227
+ $api_string = $fb_id;
228
+
229
+ /**
230
+ * Filter the fist fbsdk query
231
+ *
232
+ * @since 1.9
233
+ *
234
+ * @param string $api_string The fb api request string according to type
235
+ * @param string $fb_id The id of the object being requested.
236
+ * @param string $type The detected type of embed
237
+ *
238
+ */
239
+ $fb_data = $wp_emb_fbsdk->api('/v2.0/'.apply_filters('wpemfb_api_string',$api_string,$fb_id,$type));
240
+ $num_posts = self::$num_posts !== '' && is_numeric(self::$num_posts) ? self::$num_posts : get_option("wpemfb_max_posts");
241
+ $api_string2 = '';
242
+ if(isset($fb_data['embed_html']))
243
+ $fb_data = array_merge($fb_data,array('is_video' => '1'));
244
+ elseif( isset($fb_data['category']) && get_option("wpemfb_show_posts") == "true")
245
+ $api_string2 = '/'.$fb_data['id'].'?fields=posts.limit('.$num_posts.'){message,shares,link,picture,object_id,likes.limit(1).summary(true),comments.limit(1).summary(true)}';
246
+
247
+ /**
248
+ * Filter the second fbsdk query if necessary
249
+ *
250
+ * @since 1.9
251
+ *
252
+ * @param string $api_string2 The second request string empty if not necessary
253
+ * @param array $fb_data The result from the first query
254
+ * @param string $type The detected type of embed
255
+ *
256
+ */
257
+ $api_string2 = apply_filters('wpemfb_2nd_api_string',$api_string2,$fb_data,$type);
258
+
259
+ if(!empty($api_string2)){
260
+ $extra_data = $wp_emb_fbsdk->api('/v2.0/'.$api_string2);
261
+ $fb_data = array_merge($fb_data,$extra_data);
262
+ }
263
+ /**
264
+ * Filter all data received from facebook.
265
+ *
266
+ * @since 1.9
267
+ *
268
+ * @param array $fb_data the final result
269
+ * @param string $type The detected type of embed
270
+ */
271
+ $fb_data = apply_filters('wpemfb_fb_data',$fb_data,$type);
272
+
273
  $res = self::print_fb_data($fb_data);
274
  } catch(FacebookApiException $e) {
275
  $res = '<p><a href="https://www.facebook.com/'.$url.'" target="_blank" rel="nofollow">https://www.facebook.com/'.$url.'</a>';
 
 
276
  if(is_super_admin()){
277
  $error = $e->getResult();
278
+ $res .= '<br><span style="color: #4a0e13">' .__('This facebook link is not public', 'wp-embed-facebook').'</span>';
279
  $res .= '<br>';
280
  $res .= $error['error']['message'];
281
  }
 
282
  $res .= '</p>';
283
  }
 
 
 
284
  return $res;
285
  }
286
  /**
287
  * find out what kind of data we got from facebook
288
+ *
289
+ * @param array $fb_data result from facebook
290
+ * @return string embedded content
291
  */
292
  static function print_fb_data($fb_data){
 
 
 
 
 
 
 
 
 
293
  if(isset($fb_data['is_video'])) { //is raw video
294
  $template = self::locate_template('video');
295
  } elseif(isset($fb_data['is_post'])) { //is post
305
  $template = self::locate_template('com-page'); //is community page
306
  }else {
307
  $default = self::locate_template('page');
308
+ /**
309
+ * Add a new template for a specific facebook category
310
+ *
311
+ * for example a Museum create the new template at your-theme/plugins/wp-embed-facebook/museum.php
312
+ * then on functions.php of your theme
313
+ *
314
+ * add_filter( 'wpemfb_category_template', 'your_function', 10, 2 );
315
+ *
316
+ * function your_function( $default, $category ) {
317
+ * if($category == 'Museum/art gallery')
318
+ * return WP_Embed_FB::locate_template('museum');
319
+ * else
320
+ * return $default;
321
+ * }
322
+ *
323
+ * @since 1.0
324
+ *
325
+ * @param string $default file full path
326
+ * @param array $fb_data['category'] data from facebook
327
+ */
328
  $template = apply_filters('wpemfb_category_template', $default, $fb_data['category']);
329
  }
330
  } else { //is profile
331
  $template = self::locate_template('profile');
332
  }
333
+ //get default variables to use on templates
334
+ if(empty(self::$width)){
335
+ $width = get_option('wpemfb_max_width');
336
+ $height = get_option('wpemfb_height');
337
+ } else {
338
+ $width = self::$width;
339
+ $height = self::$height;
340
+ }
341
+ $prop = get_option('wpemfb_proportions');
342
+ ob_start();
343
+ //show embed post on admin
344
+ if(is_admin() && isset($fb_data['is_post'])) : ?>
345
+ <script>(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/es_LA/sdk.js#xfbml=1&version=v2.3"; fjs.parentNode.insertBefore(js, fjs);}(document, 'script', 'facebook-jssdk'));</script>
346
+ <?php endif;
347
+ /**
348
+ * Change the file to include on a certain embed.
349
+ *
350
+ * @since 1.8
351
+ *
352
+ * @param string $template file full path
353
+ * @param array $fb_data data from facebook
354
+ */
355
+ $template = apply_filters('wpemfb_template',$template,$fb_data);
356
+ include( $template );
357
  return preg_replace('/^\s+|\n|\r|\s+$/m', '', ob_get_clean());
358
  }
359
  /**
360
  * Locate the template inside plugin or theme
361
+ *
362
+ * @param string $template_name Template file name
363
+ * @return string Template location
364
  */
365
  static function locate_template($template_name){
366
  $theme = get_option('wpemfb_theme');
380
  */
381
  /**
382
  * If a user has a lot of websites registered on fb this function will only link to the first one
383
+ * @param string $urls separated by spaces
384
+ * @return string first url
385
  */
386
  static function getwebsite($urls){
387
  $url = explode(' ',$urls);
389
  }
390
  /**
391
  * Shows a like button or a facebook like count of a page depending on settings
392
+ * @param int $fb_id facebook id
393
+ * @param int $likes show likes count
394
+ * @param bool $share show share button
395
+ * @param bool $faces show faces
396
  */
397
  static function like_btn($fb_id,$likes=null,$share=false,$faces=false){
398
  $opt = get_option('wpemfb_show_like');
399
  if($opt === 'true') :
400
  ob_start();
401
  ?>
402
+ <div class="fb-like"
403
+ data-href="https://facebook.com/<?php echo $fb_id ?>"
404
+ data-layout="button_count"
405
+ data-action="like"
406
+ data-show-faces="<?php echo $faces ? 'true' : 'false' ?>"
407
+ data-share="<?php echo $share ? 'true' : 'false' ?>" >
408
+ </div>
409
  <?php
410
  echo ob_get_clean();
411
  return;
416
  }
417
  /**
418
  * Shows a follow button depending on settings
419
+ * @param int $fb_id facebook id or username
420
  */
421
  static function follow_btn($fb_id){
422
  $opt = get_option('wpemfb_show_follow');
423
  if($opt === 'true') :
424
  ob_start();
425
  ?>
426
+ <div class="fb-follow"
427
+ data-href="https://www.facebook.com/<?php echo $fb_id ?>"
428
+ data-colorscheme="light"
429
+ data-layout="button_count"
430
+ data-show-faces="false">
431
+ </div>
432
  <?php
433
  ob_end_flush();
434
  return;
435
  endif;
436
  }
437
  /**
438
+ * Shortcode function
439
  * [facebook='url' width='600'] width is optional
440
+ * @param array $atts [0]=>url ['width']=>embed width ['raw']=>for videos and photos
441
+ * @return string
442
  */
443
  static function shortcode($atts){
444
  if(!empty($atts) && isset($atts[0])){
450
  }
451
  if(isset($atts['raw'])){
452
  self::$raw = $atts['raw'];
453
+ }
454
+ if(isset($atts['posts'])){
455
+ self::$num_posts = $atts['posts'];
456
+ }
457
  $embed = self::the_content($url);
458
+ self::$height = self::$width = self::$raw = self::$num_posts = '';
 
 
459
  return $embed;
460
  }
461
  return;
472
  }
473
  static function plugins_loaded(){
474
  $lic = get_option('wpemfb_license','');
475
+ if(class_exists('Wpemfb_Premium') && !empty($lic) )
476
  self::$premium = true;
477
  else
478
  self::$premium = false;
479
  }
480
  }
481
 
482
+ /**
483
+ * Triggering the FaceInit::init(); will give you access to the fb php sdk on FaceInit::$fbsdk which you can use to make any call shown here
484
  * https://developers.facebook.com/docs/reference/php/
485
  */
486
  class FaceInit {
487
  static $fbsdk;
488
  static function init(){
489
+ require('fb/facebook.php');
 
490
  $config = array();
491
  $config['appId'] = get_option('wpemfb_app_id');
492
  $config['secret'] = get_option('wpemfb_app_secret');
493
  $config['fileUpload'] = false; // optional
494
  if($config['appId'] != '0' && $config['secret'] != '0' )
495
+ self::$fbsdk = new Sigami_Facebook($config);
496
  else
497
  self::$fbsdk = 'unactive';
498
  }
499
  }
500
+ ?>
lib/fb/base_facebook.php CHANGED
@@ -22,6 +22,7 @@ if (!function_exists('json_decode')) {
22
  throw new Exception('Facebook needs the JSON PHP extension.');
23
  }
24
 
 
25
  /**
26
  * Thrown when an API call returns an exception.
27
  *
@@ -29,81 +30,85 @@ if (!function_exists('json_decode')) {
29
  */
30
  class FacebookApiException extends Exception
31
  {
32
- /**
33
- * The result from the API server that represents the exception information.
34
- */
35
- protected $result;
36
-
37
- /**
38
- * Make a new API Exception with the given result.
39
- *
40
- * @param array $result The result from the API server
41
- */
42
- public function __construct($result) {
43
- $this->result = $result;
44
-
45
- $code = isset($result['error_code']) ? $result['error_code'] : 0;
46
-
47
- if (isset($result['error_description'])) {
48
- // OAuth 2.0 Draft 10 style
49
- $msg = $result['error_description'];
50
- } else if (isset($result['error']) && is_array($result['error'])) {
51
- // OAuth 2.0 Draft 00 style
52
- $msg = $result['error']['message'];
53
- } else if (isset($result['error_msg'])) {
54
- // Rest server style
55
- $msg = $result['error_msg'];
56
- } else {
57
- $msg = 'Unknown Error. Check getResult()';
 
 
 
 
58
  }
59
 
60
- parent::__construct($msg, $code);
61
- }
62
-
63
- /**
64
- * Return the associated result object returned by the API server.
65
- *
66
- * @return array The result from the API server
67
- */
68
- public function getResult() {
69
- return $this->result;
70
- }
71
-
72
- /**
73
- * Returns the associated type for the error. This will default to
74
- * 'Exception' when a type is not available.
75
- *
76
- * @return string
77
- */
78
- public function getType() {
79
- if (isset($this->result['error'])) {
80
- $error = $this->result['error'];
81
- if (is_string($error)) {
82
- // OAuth 2.0 Draft 10 style
83
- return $error;
84
- } else if (is_array($error)) {
85
- // OAuth 2.0 Draft 00 style
86
- if (isset($error['type'])) {
87
- return $error['type'];
 
88
  }
89
- }
 
90
  }
91
 
92
- return 'Exception';
93
- }
94
-
95
- /**
96
- * To make debugging easier.
97
- *
98
- * @return 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
  /**
@@ -117,928 +122,966 @@ class FacebookApiException extends Exception
117
  */
118
  abstract class BaseFacebook
119
  {
120
- /**
121
- * Version.
122
- */
123
- const VERSION = '3.2.0';
124
-
125
- /**
126
- * Signed Request Algorithm.
127
- */
128
- const SIGNED_REQUEST_ALGORITHM = 'HMAC-SHA256';
129
-
130
- /**
131
- * Default options for curl.
132
- */
133
- public static $CURL_OPTS = array(
134
- CURLOPT_CONNECTTIMEOUT => 10,
135
- CURLOPT_RETURNTRANSFER => true,
136
- CURLOPT_TIMEOUT => 60,
137
- CURLOPT_USERAGENT => 'facebook-php-3.2',
138
- );
139
-
140
- /**
141
- * List of query parameters that get automatically dropped when rebuilding
142
- * the current URL.
143
- */
144
- protected static $DROP_QUERY_PARAMS = array(
145
- 'code',
146
- 'state',
147
- 'signed_request',
148
- );
149
-
150
- /**
151
- * Maps aliases to Facebook domains.
152
- */
153
- public static $DOMAIN_MAP = array(
154
- 'api' => 'https://api.facebook.com/',
155
- 'api_video' => 'https://api-video.facebook.com/',
156
- 'api_read' => 'https://api-read.facebook.com/',
157
- 'graph' => 'https://graph.facebook.com/',
158
- 'graph_video' => 'https://graph-video.facebook.com/',
159
- 'www' => 'https://www.facebook.com/',
160
- );
161
-
162
- /**
163
- * The Application ID.
164
- *
165
- * @var string
166
- */
167
- protected $appId;
168
-
169
- /**
170
- * The Application App Secret.
171
- *
172
- * @var string
173
- */
174
- protected $appSecret;
175
-
176
- /**
177
- * The ID of the Facebook user, or 0 if the user is logged out.
178
- *
179
- * @var integer
180
- */
181
- protected $user;
182
-
183
- /**
184
- * The data from the signed_request token.
185
- */
186
- protected $signedRequest;
187
-
188
- /**
189
- * A CSRF state variable to assist in the defense against CSRF attacks.
190
- */
191
- protected $state;
192
-
193
- /**
194
- * The OAuth access token received in exchange for a valid authorization
195
- * code. null means the access token has yet to be determined.
196
- *
197
- * @var string
198
- */
199
- protected $accessToken = null;
200
-
201
- /**
202
- * Indicates if the CURL based @ syntax for file uploads is enabled.
203
- *
204
- * @var boolean
205
- */
206
- protected $fileUploadSupport = false;
207
-
208
- /**
209
- * Indicates if we trust HTTP_X_FORWARDED_* headers.
210
- *
211
- * @var boolean
212
- */
213
- protected $trustForwarded = false;
214
-
215
- /**
216
- * Initialize a Facebook Application.
217
- *
218
- * The configuration:
219
- * - appId: the application ID
220
- * - secret: the application secret
221
- * - fileUpload: (optional) boolean indicating if file uploads are enabled
222
- *
223
- * @param array $config The application configuration
224
- */
225
- public function __construct($config) {
226
- $this->setAppId($config['appId']);
227
- $this->setAppSecret($config['secret']);
228
- if (isset($config['fileUpload'])) {
229
- $this->setFileUploadSupport($config['fileUpload']);
230
- }
231
- if (isset($config['trustForwarded']) && $config['trustForwarded']) {
232
- $this->trustForwarded = true;
233
- }
234
- $state = $this->getPersistentData('state');
235
- if (!empty($state)) {
236
- $this->state = $state;
237
- }
238
- }
239
-
240
- /**
241
- * Set the Application ID.
242
- *
243
- * @param string $appId The Application ID
244
- * @return BaseFacebook
245
- */
246
- public function setAppId($appId) {
247
- $this->appId = $appId;
248
- return $this;
249
- }
250
-
251
- /**
252
- * Get the Application ID.
253
- *
254
- * @return string the Application ID
255
- */
256
- public function getAppId() {
257
- return $this->appId;
258
- }
259
-
260
- /**
261
- * Set the App Secret.
262
- *
263
- * @param string $apiSecret The App Secret
264
- * @return BaseFacebook
265
- * @deprecated
266
- */
267
- public function setApiSecret($apiSecret) {
268
- $this->setAppSecret($apiSecret);
269
- return $this;
270
- }
271
-
272
- /**
273
- * Set the App Secret.
274
- *
275
- * @param string $appSecret The App Secret
276
- * @return BaseFacebook
277
- */
278
- public function setAppSecret($appSecret) {
279
- $this->appSecret = $appSecret;
280
- return $this;
281
- }
282
-
283
- /**
284
- * Get the App Secret.
285
- *
286
- * @return string the App Secret
287
- * @deprecated
288
- */
289
- public function getApiSecret() {
290
- return $this->getAppSecret();
291
- }
292
-
293
- /**
294
- * Get the App Secret.
295
- *
296
- * @return string the App Secret
297
- */
298
- public function getAppSecret() {
299
- return $this->appSecret;
300
- }
301
-
302
- /**
303
- * Set the file upload support status.
304
- *
305
- * @param boolean $fileUploadSupport The file upload support status.
306
- * @return BaseFacebook
307
- */
308
- public function setFileUploadSupport($fileUploadSupport) {
309
- $this->fileUploadSupport = $fileUploadSupport;
310
- return $this;
311
- }
312
-
313
- /**
314
- * Get the file upload support status.
315
- *
316
- * @return boolean true if and only if the server supports file upload.
317
- */
318
- public function getFileUploadSupport() {
319
- return $this->fileUploadSupport;
320
- }
321
-
322
- /**
323
- * DEPRECATED! Please use getFileUploadSupport instead.
324
- *
325
- * Get the file upload support status.
326
- *
327
- * @return boolean true if and only if the server supports file upload.
328
- */
329
- public function useFileUploadSupport() {
330
- return $this->getFileUploadSupport();
331
- }
332
-
333
- /**
334
- * Sets the access token for api calls. Use this if you get
335
- * your access token by other means and just want the SDK
336
- * to use it.
337
- *
338
- * @param string $access_token an access token.
339
- * @return BaseFacebook
340
- */
341
- public function setAccessToken($access_token) {
342
- $this->accessToken = $access_token;
343
- return $this;
344
- }
345
-
346
- /**
347
- * Extend an access token, while removing the short-lived token that might
348
- * have been generated via client-side flow. Thanks to http://bit.ly/b0Pt0H
349
- * for the workaround.
350
- */
351
- public function setExtendedAccessToken() {
352
- try {
353
- // need to circumvent json_decode by calling _oauthRequest
354
- // directly, since response isn't JSON format.
355
- $access_token_response = $this->_oauthRequest(
356
- $this->getUrl('graph', '/oauth/access_token'),
357
- $params = array(
358
- 'client_id' => $this->getAppId(),
359
- 'client_secret' => $this->getAppSecret(),
360
- 'grant_type' => 'fb_exchange_token',
361
- 'fb_exchange_token' => $this->getAccessToken(),
362
- )
363
- );
364
- }
365
- catch (FacebookApiException $e) {
366
- // most likely that user very recently revoked authorization.
367
- // In any event, we don't have an access token, so say so.
368
- return false;
369
- }
370
-
371
- if (empty($access_token_response)) {
372
- return false;
373
- }
374
-
375
- $response_params = array();
376
- parse_str($access_token_response, $response_params);
377
-
378
- if (!isset($response_params['access_token'])) {
379
- return false;
380
- }
381
-
382
- $this->destroySession();
383
-
384
- $this->setPersistentData(
385
- 'access_token', $response_params['access_token']
386
  );
387
- }
388
-
389
- /**
390
- * Determines the access token that should be used for API calls.
391
- * The first time this is called, $this->accessToken is set equal
392
- * to either a valid user access token, or it's set to the application
393
- * access token if a valid user access token wasn't available. Subsequent
394
- * calls return whatever the first call returned.
395
- *
396
- * @return string The access token
397
- */
398
- public function getAccessToken() {
399
- if ($this->accessToken !== null) {
400
- // we've done this already and cached it. Just return.
401
- return $this->accessToken;
402
- }
403
 
404
- // first establish access token to be the application
405
- // access token, in case we navigate to the /oauth/access_token
406
- // endpoint, where SOME access token is required.
407
- $this->setAccessToken($this->getApplicationAccessToken());
408
- $user_access_token = $this->getUserAccessToken();
409
- if ($user_access_token) {
410
- $this->setAccessToken($user_access_token);
411
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
412
 
413
- return $this->accessToken;
414
- }
415
-
416
- /**
417
- * Determines and returns the user access token, first using
418
- * the signed request if present, and then falling back on
419
- * the authorization code if present. The intent is to
420
- * return a valid user access token, or false if one is determined
421
- * to not be available.
422
- *
423
- * @return string A valid user access token, or false if one
424
- * could not be determined.
425
- */
426
- protected function getUserAccessToken() {
427
- // first, consider a signed request if it's supplied.
428
- // if there is a signed request, then it alone determines
429
- // the access token.
430
- $signed_request = $this->getSignedRequest();
431
- if ($signed_request) {
432
- // apps.facebook.com hands the access_token in the signed_request
433
- if (array_key_exists('oauth_token', $signed_request)) {
434
- $access_token = $signed_request['oauth_token'];
435
- $this->setPersistentData('access_token', $access_token);
436
- return $access_token;
437
- }
438
-
439
- // the JS SDK puts a code in with the redirect_uri of ''
440
- if (array_key_exists('code', $signed_request)) {
441
- $code = $signed_request['code'];
442
- $access_token = $this->getAccessTokenFromCode($code, '');
443
- if ($access_token) {
444
- $this->setPersistentData('code', $code);
445
- $this->setPersistentData('access_token', $access_token);
446
- return $access_token;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
447
  }
448
- }
449
 
450
- // signed request states there's no access token, so anything
451
- // stored should be cleared.
452
- $this->clearAllPersistentData();
453
- return false; // respect the signed request's data, even
454
- // if there's an authorization code or something else
 
 
 
 
 
455
  }
456
 
457
- $code = $this->getCode();
458
- if ($code && $code != $this->getPersistentData('code')) {
459
- $access_token = $this->getAccessTokenFromCode($code);
460
- if ($access_token) {
461
- $this->setPersistentData('code', $code);
462
- $this->setPersistentData('access_token', $access_token);
463
- return $access_token;
464
- }
465
-
466
- // code was bogus, so everything based on it should be invalidated.
467
- $this->clearAllPersistentData();
468
- return false;
469
  }
470
 
471
- // as a fallback, just return whatever is in the persistent
472
- // store, knowing nothing explicit (signed request, authorization
473
- // code, etc.) was present to shadow it (or we saw a code in $_REQUEST,
474
- // but it's the same as what's in the persistent store)
475
- return $this->getPersistentData('access_token');
476
- }
477
-
478
- /**
479
- * Retrieve the signed request, either from a request parameter or,
480
- * if not present, from a cookie.
481
- *
482
- * @return string the signed request, if available, or null otherwise.
483
- */
484
- public function getSignedRequest() {
485
- if (!$this->signedRequest) {
486
- if (isset($_REQUEST['signed_request'])) {
487
- $this->signedRequest = $this->parseSignedRequest(
488
- $_REQUEST['signed_request']);
489
- } else if (isset($_COOKIE[$this->getSignedRequestCookieName()])) {
490
- $this->signedRequest = $this->parseSignedRequest(
491
- $_COOKIE[$this->getSignedRequestCookieName()]);
492
- }
493
  }
494
- return $this->signedRequest;
495
- }
496
-
497
- /**
498
- * Get the UID of the connected user, or 0
499
- * if the Facebook user is not connected.
500
- *
501
- * @return string the UID if available.
502
- */
503
- public function getUser() {
504
- if ($this->user !== null) {
505
- // we've already determined this and cached the value.
506
- return $this->user;
507
  }
508
 
509
- return $this->user = $this->getUserFromAvailableData();
510
- }
511
-
512
- /**
513
- * Determines the connected user by first examining any signed
514
- * requests, then considering an authorization code, and then
515
- * falling back to any persistent store storing the user.
516
- *
517
- * @return integer The id of the connected Facebook user,
518
- * or 0 if no such user exists.
519
- */
520
- protected function getUserFromAvailableData() {
521
- // if a signed request is supplied, then it solely determines
522
- // who the user is.
523
- $signed_request = $this->getSignedRequest();
524
- if ($signed_request) {
525
- if (array_key_exists('user_id', $signed_request)) {
526
- $user = $signed_request['user_id'];
527
- $this->setPersistentData('user_id', $signed_request['user_id']);
528
- return $user;
529
- }
530
 
531
- // if the signed request didn't present a user id, then invalidate
532
- // all entries in any persistent store.
533
- $this->clearAllPersistentData();
534
- return 0;
 
 
 
 
535
  }
536
 
537
- $user = $this->getPersistentData('user_id', $default = 0);
538
- $persisted_access_token = $this->getPersistentData('access_token');
539
-
540
- // use access_token to fetch user id if we have a user access_token, or if
541
- // the cached access token has changed.
542
- $access_token = $this->getAccessToken();
543
- if ($access_token &&
544
- $access_token != $this->getApplicationAccessToken() &&
545
- !($user && $persisted_access_token == $access_token)) {
546
- $user = $this->getUserFromAccessToken();
547
- if ($user) {
548
- $this->setPersistentData('user_id', $user);
549
- } else {
550
- $this->clearAllPersistentData();
551
- }
552
  }
553
 
554
- return $user;
555
- }
556
-
557
- /**
558
- * Get a Login URL for use with redirects. By default, full page redirect is
559
- * assumed. If you are using the generated URL with a window.open() call in
560
- * JavaScript, you can pass in display=popup as part of the $params.
561
- *
562
- * The parameters:
563
- * - redirect_uri: the url to go to after a successful login
564
- * - scope: comma separated list of requested extended perms
565
- *
566
- * @param array $params Provide custom parameters
567
- * @return string The URL for the login flow
568
- */
569
- public function getLoginUrl($params=array()) {
570
- $this->establishCSRFTokenState();
571
- $currentUrl = $this->getCurrentUrl();
572
-
573
- // if 'scope' is passed as an array, convert to comma separated list
574
- $scopeParams = isset($params['scope']) ? $params['scope'] : null;
575
- if ($scopeParams && is_array($scopeParams)) {
576
- $params['scope'] = implode(',', $scopeParams);
577
  }
578
 
579
- return $this->getUrl(
580
- 'www',
581
- 'dialog/oauth',
582
- array_merge(array(
583
- 'client_id' => $this->getAppId(),
584
- 'redirect_uri' => $currentUrl, // possibly overwritten
585
- 'state' => $this->state),
586
- $params));
587
- }
588
-
589
- /**
590
- * Get a Logout URL suitable for use with redirects.
591
- *
592
- * The parameters:
593
- * - next: the url to go to after a successful logout
594
- *
595
- * @param array $params Provide custom parameters
596
- * @return string The URL for the logout flow
597
- */
598
- public function getLogoutUrl($params=array()) {
599
- return $this->getUrl(
600
- 'www',
601
- 'logout.php',
602
- array_merge(array(
603
- 'next' => $this->getCurrentUrl(),
604
- 'access_token' => $this->getUserAccessToken(),
605
- ), $params)
606
- );
607
- }
608
-
609
- /**
610
- * Get a login status URL to fetch the status from Facebook.
611
- *
612
- * The parameters:
613
- * - ok_session: the URL to go to if a session is found
614
- * - no_session: the URL to go to if the user is not connected
615
- * - no_user: the URL to go to if the user is not signed into facebook
616
- *
617
- * @param array $params Provide custom parameters
618
- * @return string The URL for the logout flow
619
- */
620
- public function getLoginStatusUrl($params=array()) {
621
- return $this->getUrl(
622
- 'www',
623
- 'extern/login_status.php',
624
- array_merge(array(
625
- 'api_key' => $this->getAppId(),
626
- 'no_session' => $this->getCurrentUrl(),
627
- 'no_user' => $this->getCurrentUrl(),
628
- 'ok_session' => $this->getCurrentUrl(),
629
- 'session_version' => 3,
630
- ), $params)
631
- );
632
- }
633
-
634
- /**
635
- * Make an API call.
636
- *
637
- * @return mixed The decoded response
638
- */
639
- public function api(/* polymorphic */) {
640
- $args = func_get_args();
641
- if (is_array($args[0])) {
642
- return $this->_restserver($args[0]);
643
- } else {
644
- return call_user_func_array(array($this, '_graph'), $args);
645
  }
646
- }
647
-
648
- /**
649
- * Constructs and returns the name of the cookie that
650
- * potentially houses the signed request for the app user.
651
- * The cookie is not set by the BaseFacebook class, but
652
- * it may be set by the JavaScript SDK.
653
- *
654
- * @return string the name of the cookie that would house
655
- * the signed request value.
656
- */
657
- protected function getSignedRequestCookieName() {
658
- return 'fbsr_'.$this->getAppId();
659
- }
660
-
661
- /**
662
- * Constructs and returns the name of the coookie that potentially contain
663
- * metadata. The cookie is not set by the BaseFacebook class, but it may be
664
- * set by the JavaScript SDK.
665
- *
666
- * @return string the name of the cookie that would house metadata.
667
- */
668
- protected function getMetadataCookieName() {
669
- return 'fbm_'.$this->getAppId();
670
- }
671
-
672
- /**
673
- * Get the authorization code from the query parameters, if it exists,
674
- * and otherwise return false to signal no authorization code was
675
- * discoverable.
676
- *
677
- * @return mixed The authorization code, or false if the authorization
678
- * code could not be determined.
679
- */
680
- protected function getCode() {
681
- if (isset($_REQUEST['code'])) {
682
- if ($this->state !== null &&
683
- isset($_REQUEST['state']) &&
684
- $this->state === $_REQUEST['state']) {
685
-
686
- // CSRF state has done its job, so clear it
687
- $this->state = null;
688
- $this->clearPersistentData('state');
689
- return $_REQUEST['code'];
690
- } else {
691
- self::errorLog('CSRF state token does not match one provided.');
692
- return false;
693
- }
694
  }
695
 
696
- return false;
697
- }
698
-
699
- /**
700
- * Retrieves the UID with the understanding that
701
- * $this->accessToken has already been set and is
702
- * seemingly legitimate. It relies on Facebook's Graph API
703
- * to retrieve user information and then extract
704
- * the user ID.
705
- *
706
- * @return integer Returns the UID of the Facebook user, or 0
707
- * if the Facebook user could not be determined.
708
- */
709
- protected function getUserFromAccessToken() {
710
- try {
711
- $user_info = $this->api('/me');
712
- return $user_info['id'];
713
- } catch (FacebookApiException $e) {
714
- return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
715
  }
716
- }
717
-
718
- /**
719
- * Returns the access token that should be used for logged out
720
- * users when no authorization code is available.
721
- *
722
- * @return string The application access token, useful for gathering
723
- * public information about users and applications.
724
- */
725
- protected function getApplicationAccessToken() {
726
- return $this->appId.'|'.$this->appSecret;
727
- }
728
-
729
- /**
730
- * Lays down a CSRF state token for this process.
731
- *
732
- * @return void
733
- */
734
- protected function establishCSRFTokenState() {
735
- if ($this->state === null) {
736
- $this->state = md5(uniqid(mt_rand(), true));
737
- $this->setPersistentData('state', $this->state);
 
 
 
 
 
738
  }
739
- }
740
-
741
- /**
742
- * Retrieves an access token for the given authorization code
743
- * (previously generated from www.facebook.com on behalf of
744
- * a specific user). The authorization code is sent to graph.facebook.com
745
- * and a legitimate access token is generated provided the access token
746
- * and the user for which it was generated all match, and the user is
747
- * either logged in to Facebook or has granted an offline access permission.
748
- *
749
- * @param string $code An authorization code.
750
- * @return mixed An access token exchanged for the authorization code, or
751
- * false if an access token could not be generated.
752
- */
753
- protected function getAccessTokenFromCode($code, $redirect_uri = null) {
754
- if (empty($code)) {
755
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
756
  }
757
 
758
- if ($redirect_uri === null) {
759
- $redirect_uri = $this->getCurrentUrl();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
760
  }
761
 
762
- try {
763
- // need to circumvent json_decode by calling _oauthRequest
764
- // directly, since response isn't JSON format.
765
- $access_token_response =
766
- $this->_oauthRequest(
767
- $this->getUrl('graph', '/oauth/access_token'),
768
- $params = array('client_id' => $this->getAppId(),
769
- 'client_secret' => $this->getAppSecret(),
770
- 'redirect_uri' => $redirect_uri,
771
- 'code' => $code));
772
- } catch (FacebookApiException $e) {
773
- // most likely that user very recently revoked authorization.
774
- // In any event, we don't have an access token, so say so.
775
- return false;
776
  }
777
 
778
- if (empty($access_token_response)) {
779
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
780
  }
781
 
782
- $response_params = array();
783
- parse_str($access_token_response, $response_params);
784
- if (!isset($response_params['access_token'])) {
785
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
786
  }
787
 
788
- return $response_params['access_token'];
789
- }
790
-
791
- /**
792
- * Invoke the old restserver.php endpoint.
793
- *
794
- * @param array $params Method call object
795
- *
796
- * @return mixed The decoded response object
797
- * @throws FacebookApiException
798
- */
799
- protected function _restserver($params) {
800
- // generic application level parameters
801
- $params['api_key'] = $this->getAppId();
802
- $params['format'] = 'json-strings';
803
-
804
- $result = json_decode($this->_oauthRequest(
805
- $this->getApiUrl($params['method']),
806
- $params
807
- ), true);
808
-
809
- // results are returned, errors are thrown
810
- if (is_array($result) && isset($result['error_code'])) {
811
- $this->throwAPIException($result);
812
- // @codeCoverageIgnoreStart
813
  }
814
- // @codeCoverageIgnoreEnd
815
 
816
- $method = strtolower($params['method']);
817
- if ($method === 'auth.expiresession' ||
818
- $method === 'auth.revokeauthorization') {
819
- $this->destroySession();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
820
  }
821
 
822
- return $result;
823
- }
824
-
825
- /**
826
- * Return true if this is video post.
827
- *
828
- * @param string $path The path
829
- * @param string $method The http method (default 'GET')
830
- *
831
- * @return boolean true if this is video post
832
- */
833
- protected function isVideoPost($path, $method = 'GET') {
834
- if ($method == 'POST' && preg_match("/^(\/)(.+)(\/)(videos)$/", $path)) {
835
- return true;
836
  }
837
- return false;
838
- }
839
-
840
- /**
841
- * Invoke the Graph API.
842
- *
843
- * @param string $path The path (required)
844
- * @param string $method The http method (default 'GET')
845
- * @param array $params The query/post data
846
- *
847
- * @return mixed The decoded response object
848
- * @throws FacebookApiException
849
- */
850
- protected function _graph($path, $method = 'GET', $params = array()) {
851
- if (is_array($method) && empty($params)) {
852
- $params = $method;
853
- $method = 'GET';
854
  }
855
- $params['method'] = $method; // method override as we always do a POST
856
 
857
- if ($this->isVideoPost($path, $method)) {
858
- $domainKey = 'graph_video';
859
- } else {
860
- $domainKey = 'graph';
 
 
 
 
 
 
861
  }
862
 
863
- $result = json_decode($this->_oauthRequest(
864
- $this->getUrl($domainKey, $path),
865
- $params
866
- ), true);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
867
 
868
- // results are returned, errors are thrown
869
- if (is_array($result) && isset($result['error'])) {
870
- $this->throwAPIException($result);
871
- // @codeCoverageIgnoreStart
872
  }
873
- // @codeCoverageIgnoreEnd
874
-
875
- return $result;
876
- }
877
-
878
- /**
879
- * Make a OAuth Request.
880
- *
881
- * @param string $url The path (required)
882
- * @param array $params The query/post data
883
- *
884
- * @return string The decoded response object
885
- * @throws FacebookApiException
886
- */
887
- protected function _oauthRequest($url, $params) {
888
- if (!isset($params['access_token'])) {
889
- $params['access_token'] = $this->getAccessToken();
 
 
890
  }
891
 
892
- // json_encode all params values that are not strings
893
- foreach ($params as $key => $value) {
894
- if (!is_string($value)) {
895
- $params[$key] = json_encode($value);
896
- }
 
 
 
 
 
897
  }
898
 
899
- return $this->makeRequest($url, $params);
900
- }
901
-
902
- /**
903
- * Makes an HTTP request. This method can be overridden by subclasses if
904
- * developers want to do fancier things or use something other than curl to
905
- * make the request.
906
- *
907
- * @param string $url The URL to make the request to
908
- * @param array $params The parameters to use for the POST body
909
- * @param CurlHandler $ch Initialized curl handle
910
- *
911
- * @return string The response text
912
- */
913
- protected function makeRequest($url, $params, $ch=null) {
914
- if (!$ch) {
915
- $ch = curl_init();
916
  }
917
 
918
- $opts = self::$CURL_OPTS;
919
- if ($this->getFileUploadSupport()) {
920
- $opts[CURLOPT_POSTFIELDS] = $params;
921
- } else {
922
- $opts[CURLOPT_POSTFIELDS] = http_build_query($params, null, '&');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
923
  }
924
- $opts[CURLOPT_URL] = $url;
925
-
926
- // disable the 'Expect: 100-continue' behaviour. This causes CURL to wait
927
- // for 2 seconds if the server does not support this header.
928
- if (isset($opts[CURLOPT_HTTPHEADER])) {
929
- $existing_headers = $opts[CURLOPT_HTTPHEADER];
930
- $existing_headers[] = 'Expect:';
931
- $opts[CURLOPT_HTTPHEADER] = $existing_headers;
932
- } else {
933
- $opts[CURLOPT_HTTPHEADER] = array('Expect:');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
934
  }
935
- //no ssl verification xz3 modifications
936
- $opts[CURLOPT_SSL_VERIFYPEER] = false;
937
- //end modifications
938
- curl_setopt_array($ch, $opts);
939
- $result = curl_exec($ch);
940
-
941
- if (curl_errno($ch) == 60) { // CURLE_SSL_CACERT
942
- self::errorLog('Invalid or no certificate authority found, '.
943
- 'using bundled information');
944
- curl_setopt($ch, CURLOPT_CAINFO,
945
- dirname(__FILE__) . '/fb_ca_chain_bundle.crt');
946
- $result = curl_exec($ch);
 
 
 
947
  }
948
 
949
- // With dual stacked DNS responses, it's possible for a server to
950
- // have IPv6 enabled but not have IPv6 connectivity. If this is
951
- // the case, curl will try IPv4 first and if that fails, then it will
952
- // fall back to IPv6 and the error EHOSTUNREACH is returned by the
953
- // operating system.
954
- if ($result === false && empty($opts[CURLOPT_IPRESOLVE])) {
955
- $matches = array();
956
- $regex = '/Failed to connect to ([^:].*): Network is unreachable/';
957
- if (preg_match($regex, curl_error($ch), $matches)) {
958
- if (strlen(@inet_pton($matches[1])) === 16) {
959
- self::errorLog('Invalid IPv6 configuration on server, '.
960
- 'Please disable or get native IPv6 on your server.');
961
- self::$CURL_OPTS[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
962
- curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
963
- $result = curl_exec($ch);
964
- }
965
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
966
  }
967
 
968
- if ($result === false) {
969
- $e = new FacebookApiException(array(
970
- 'error_code' => curl_errno($ch),
971
- 'error' => array(
972
- 'message' => curl_error($ch),
973
- 'type' => 'CurlException',
974
- ),
975
- ));
976
- curl_close($ch);
977
- throw $e;
 
 
 
 
 
 
 
 
 
 
 
 
 
978
  }
979
- curl_close($ch);
980
- return $result;
981
- }
982
-
983
- /**
984
- * Parses a signed_request and validates the signature.
985
- *
986
- * @param string $signed_request A signed token
987
- * @return array The payload inside it or null if the sig is wrong
988
- */
989
- protected function parseSignedRequest($signed_request) {
990
- list($encoded_sig, $payload) = explode('.', $signed_request, 2);
991
-
992
- // decode the data
993
- $sig = self::base64UrlDecode($encoded_sig);
994
- $data = json_decode(self::base64UrlDecode($payload), true);
995
-
996
- if (strtoupper($data['algorithm']) !== self::SIGNED_REQUEST_ALGORITHM) {
997
- self::errorLog(
998
- 'Unknown algorithm. Expected ' . self::SIGNED_REQUEST_ALGORITHM);
999
- return null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1000
  }
1001
 
1002
- // check sig
1003
- $expected_sig = hash_hmac('sha256', $payload,
1004
- $this->getAppSecret(), $raw = true);
1005
- if ($sig !== $expected_sig) {
1006
- self::errorLog('Bad Signed JSON signature!');
1007
- return null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1008
  }
1009
 
1010
- return $data;
1011
- }
1012
-
1013
- /**
1014
- * Makes a signed_request blob using the given data.
1015
- *
1016
- * @param array The data array.
1017
- * @return string The signed request.
1018
- */
1019
- protected function makeSignedRequest($data) {
1020
- if (!is_array($data)) {
1021
- throw new InvalidArgumentException(
1022
- 'makeSignedRequest expects an array. Got: ' . print_r($data, true));
 
 
 
 
 
 
1023
  }
1024
- $data['algorithm'] = self::SIGNED_REQUEST_ALGORITHM;
1025
- $data['issued_at'] = time();
1026
- $json = json_encode($data);
1027
- $b64 = self::base64UrlEncode($json);
1028
- $raw_sig = hash_hmac('sha256', $b64, $this->getAppSecret(), $raw = true);
1029
- $sig = self::base64UrlEncode($raw_sig);
1030
- return $sig.'.'.$b64;
1031
- }
1032
-
1033
- /**
1034
- * Build the URL for api given parameters.
1035
- *
1036
- * @param $method String the method name.
1037
- * @return string The URL for the given parameters
1038
- */
1039
- protected function getApiUrl($method) {
1040
- static $READ_ONLY_CALLS =
1041
- array('admin.getallocation' => 1,
1042
  'admin.getappproperties' => 1,
1043
  'admin.getbannedusers' => 1,
1044
  'admin.getlivestreamvialink' => 1,
@@ -1098,330 +1141,346 @@ abstract class BaseFacebook
1098
  'users.isappuser' => 1,
1099
  'users.isverified' => 1,
1100
  'video.getuploadlimits' => 1);
1101
- $name = 'api';
1102
- if (isset($READ_ONLY_CALLS[strtolower($method)])) {
1103
- $name = 'api_read';
1104
- } else if (strtolower($method) == 'video.upload') {
1105
- $name = 'api_video';
1106
- }
1107
- return self::getUrl($name, 'restserver.php');
1108
- }
1109
-
1110
- /**
1111
- * Build the URL for given domain alias, path and parameters.
1112
- *
1113
- * @param $name string The name of the domain
1114
- * @param $path string Optional path (without a leading slash)
1115
- * @param $params array Optional query parameters
1116
- *
1117
- * @return string The URL for the given parameters
1118
- */
1119
- protected function getUrl($name, $path='', $params=array()) {
1120
- $url = self::$DOMAIN_MAP[$name];
1121
- if ($path) {
1122
- if ($path[0] === '/') {
1123
- $path = substr($path, 1);
1124
- }
1125
- $url .= $path;
1126
- }
1127
- if ($params) {
1128
- $url .= '?' . http_build_query($params, null, '&');
1129
  }
1130
 
1131
- return $url;
1132
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1133
 
1134
- protected function getHttpHost() {
1135
- if ($this->trustForwarded && isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
1136
- return $_SERVER['HTTP_X_FORWARDED_HOST'];
1137
  }
1138
- return $_SERVER['HTTP_HOST'];
1139
- }
1140
-
1141
- protected function getHttpProtocol() {
1142
- if ($this->trustForwarded && isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
1143
- if ($_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
1144
- return 'https';
1145
- }
1146
- return 'http';
1147
  }
1148
- if (isset($_SERVER['HTTPS']) &&
1149
- ($_SERVER['HTTPS'] === 'on' || $_SERVER['HTTPS'] == 1)) {
1150
- return 'https';
 
 
 
 
 
 
 
 
 
 
 
 
1151
  }
1152
- return 'http';
1153
- }
1154
-
1155
- /**
1156
- * Get the base domain used for the cookie.
1157
- */
1158
- protected function getBaseDomain() {
1159
- // The base domain is stored in the metadata cookie if not we fallback
1160
- // to the current hostname
1161
- $metadata = $this->getMetadataCookie();
1162
- if (array_key_exists('base_domain', $metadata) &&
1163
- !empty($metadata['base_domain'])) {
1164
- return trim($metadata['base_domain'], '.');
 
 
1165
  }
1166
- return $this->getHttpHost();
1167
- }
1168
-
1169
- /**
1170
-
1171
- /**
1172
- * Returns the Current URL, stripping it of known FB parameters that should
1173
- * not persist.
1174
- *
1175
- * @return string The current URL
1176
- */
1177
- protected function getCurrentUrl() {
1178
- $protocol = $this->getHttpProtocol() . '://';
1179
- $host = $this->getHttpHost();
1180
- $currentUrl = $protocol.$host.$_SERVER['REQUEST_URI'];
1181
- $parts = parse_url($currentUrl);
1182
-
1183
- $query = '';
1184
- if (!empty($parts['query'])) {
1185
- // drop known fb params
1186
- $params = explode('&', $parts['query']);
1187
- $retained_params = array();
1188
- foreach ($params as $param) {
1189
- if ($this->shouldRetainParam($param)) {
1190
- $retained_params[] = $param;
 
 
 
 
 
1191
  }
1192
- }
1193
 
1194
- if (!empty($retained_params)) {
1195
- $query = '?'.implode($retained_params, '&');
1196
- }
1197
- }
 
 
1198
 
1199
- // use port if non default
1200
- $port =
1201
- isset($parts['port']) &&
1202
- (($protocol === 'http://' && $parts['port'] !== 80) ||
1203
- ($protocol === 'https://' && $parts['port'] !== 443))
1204
- ? ':' . $parts['port'] : '';
1205
-
1206
- // rebuild
1207
- return $protocol . $parts['host'] . $port . $parts['path'] . $query;
1208
- }
1209
-
1210
- /**
1211
- * Returns true if and only if the key or key/value pair should
1212
- * be retained as part of the query string. This amounts to
1213
- * a brute-force search of the very small list of Facebook-specific
1214
- * params that should be stripped out.
1215
- *
1216
- * @param string $param A key or key/value pair within a URL's query (e.g.
1217
- * 'foo=a', 'foo=', or 'foo'.
1218
- *
1219
- * @return boolean
1220
- */
1221
- protected function shouldRetainParam($param) {
1222
- foreach (self::$DROP_QUERY_PARAMS as $drop_query_param) {
1223
- if (strpos($param, $drop_query_param.'=') === 0) {
1224
- return false;
1225
- }
1226
  }
1227
 
1228
- return true;
1229
- }
1230
-
1231
- /**
1232
- * Analyzes the supplied result to see if it was thrown
1233
- * because the access token is no longer valid. If that is
1234
- * the case, then we destroy the session.
1235
- *
1236
- * @param $result array A record storing the error message returned
1237
- * by a failed API call.
1238
- */
1239
- protected function throwAPIException($result) {
1240
- $e = new FacebookApiException($result);
1241
- switch ($e->getType()) {
1242
- // OAuth 2.0 Draft 00 style
1243
- case 'OAuthException':
1244
- // OAuth 2.0 Draft 10 style
1245
- case 'invalid_token':
1246
- // REST server errors are just Exceptions
1247
- case 'Exception':
1248
- $message = $e->getMessage();
1249
- if ((strpos($message, 'Error validating access token') !== false) ||
1250
- (strpos($message, 'Invalid OAuth access token') !== false) ||
1251
- (strpos($message, 'An active access token must be used') !== false)
1252
- ) {
1253
- $this->destroySession();
1254
  }
1255
- break;
1256
- }
1257
 
1258
- throw $e;
1259
- }
1260
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1261
 
1262
- /**
1263
- * Prints to the error log if you aren't in command line mode.
1264
- *
1265
- * @param string $msg Log message
1266
- */
1267
- protected static function errorLog($msg) {
1268
- // disable error log if we are running in a CLI environment
1269
- // @codeCoverageIgnoreStart
1270
- if (php_sapi_name() != 'cli') {
1271
- error_log($msg);
1272
  }
1273
- // uncomment this if you want to see the errors on the page
1274
- // print 'error_log: '.$msg."\n";
1275
- // @codeCoverageIgnoreEnd
1276
- }
1277
-
1278
- /**
1279
- * Base64 encoding that doesn't need to be urlencode()ed.
1280
- * Exactly the same as base64_encode except it uses
1281
- * - instead of +
1282
- * _ instead of /
1283
- * No padded =
1284
- *
1285
- * @param string $input base64UrlEncoded string
1286
- * @return string
1287
- */
1288
- protected static function base64UrlDecode($input) {
1289
- return base64_decode(strtr($input, '-_', '+/'));
1290
- }
1291
-
1292
- /**
1293
- * Base64 encoding that doesn't need to be urlencode()ed.
1294
- * Exactly the same as base64_encode except it uses
1295
- * - instead of +
1296
- * _ instead of /
1297
- *
1298
- * @param string $input string
1299
- * @return string base64Url encoded string
1300
- */
1301
- protected static function base64UrlEncode($input) {
1302
- $str = strtr(base64_encode($input), '+/', '-_');
1303
- $str = str_replace('=', '', $str);
1304
- return $str;
1305
- }
1306
-
1307
- /**
1308
- * Destroy the current session
1309
- */
1310
- public function destroySession() {
1311
- $this->accessToken = null;
1312
- $this->signedRequest = null;
1313
- $this->user = null;
1314
- $this->clearAllPersistentData();
1315
-
1316
- // Javascript sets a cookie that will be used in getSignedRequest that we
1317
- // need to clear if we can
1318
- $cookie_name = $this->getSignedRequestCookieName();
1319
- if (array_key_exists($cookie_name, $_COOKIE)) {
1320
- unset($_COOKIE[$cookie_name]);
1321
- if (!headers_sent()) {
1322
- $base_domain = $this->getBaseDomain();
1323
- setcookie($cookie_name, '', 1, '/', '.'.$base_domain);
1324
- } else {
1325
  // @codeCoverageIgnoreStart
1326
- self::errorLog(
1327
- 'There exists a cookie that we wanted to clear that we couldn\'t '.
1328
- 'clear because headers was already sent. Make sure to do the first '.
1329
- 'API call before outputing anything.'
1330
- );
1331
  // @codeCoverageIgnoreEnd
1332
- }
1333
- }
1334
- }
1335
-
1336
- /**
1337
- * Parses the metadata cookie that our Javascript API set
1338
- *
1339
- * @return an array mapping key to value
1340
- */
1341
- protected function getMetadataCookie() {
1342
- $cookie_name = $this->getMetadataCookieName();
1343
- if (!array_key_exists($cookie_name, $_COOKIE)) {
1344
- return array();
1345
  }
1346
 
1347
- // The cookie value can be wrapped in "-characters so remove them
1348
- $cookie_value = trim($_COOKIE[$cookie_name], '"');
 
 
 
 
 
 
 
 
 
 
 
 
1349
 
1350
- if (empty($cookie_value)) {
1351
- return array();
 
 
 
 
 
 
 
 
 
 
 
 
1352
  }
1353
 
1354
- $parts = explode('&', $cookie_value);
1355
- $metadata = array();
1356
- foreach ($parts as $part) {
1357
- $pair = explode('=', $part, 2);
1358
- if (!empty($pair[0])) {
1359
- $metadata[urldecode($pair[0])] =
1360
- (count($pair) > 1) ? urldecode($pair[1]) : '';
1361
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1362
  }
1363
 
1364
- return $metadata;
1365
- }
 
 
 
 
 
 
 
 
 
 
 
 
1366
 
1367
- protected static function isAllowedDomain($big, $small) {
1368
- if ($big === $small) {
1369
- return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1370
  }
1371
- return self::endsWith($big, '.'.$small);
1372
- }
1373
 
1374
- protected static function endsWith($big, $small) {
1375
- $len = strlen($small);
1376
- if ($len === 0) {
1377
- return true;
 
 
 
1378
  }
1379
- return substr($big, -$len) === $small;
1380
- }
1381
-
1382
- /**
1383
- * Each of the following four methods should be overridden in
1384
- * a concrete subclass, as they are in the provided Facebook class.
1385
- * The Facebook class uses PHP sessions to provide a primitive
1386
- * persistent store, but another subclass--one that you implement--
1387
- * might use a database, memcache, or an in-memory cache.
1388
- *
1389
- * @see Facebook
1390
- */
1391
-
1392
- /**
1393
- * Stores the given ($key, $value) pair, so that future calls to
1394
- * getPersistentData($key) return $value. This call may be in another request.
1395
- *
1396
- * @param string $key
1397
- * @param array $value
1398
- *
1399
- * @return void
1400
- */
1401
- abstract protected function setPersistentData($key, $value);
1402
-
1403
- /**
1404
- * Get the data for $key, persisted by BaseFacebook::setPersistentData()
1405
- *
1406
- * @param string $key The key of the data to retrieve
1407
- * @param boolean $default The default value to return if $key is not found
1408
- *
1409
- * @return mixed
1410
- */
1411
- abstract protected function getPersistentData($key, $default = false);
1412
-
1413
- /**
1414
- * Clear the data with $key from the persistent storage
1415
- *
1416
- * @param string $key
1417
- * @return void
1418
- */
1419
- abstract protected function clearPersistentData($key);
1420
-
1421
- /**
1422
- * Clear all data from the persistent storage
1423
- *
1424
- * @return void
1425
- */
1426
- abstract protected function clearAllPersistentData();
1427
- }
22
  throw new Exception('Facebook needs the JSON PHP extension.');
23
  }
24
 
25
+
26
  /**
27
  * Thrown when an API call returns an exception.
28
  *
30
  */
31
  class FacebookApiException extends Exception
32
  {
33
+ /**
34
+ * The result from the API server that represents the exception information.
35
+ */
36
+ protected $result;
37
+
38
+ /**
39
+ * Make a new API Exception with the given result.
40
+ *
41
+ * @param array $result The result from the API server
42
+ */
43
+ public function __construct($result)
44
+ {
45
+ $this->result = $result;
46
+
47
+ $code = isset($result['error_code']) ? $result['error_code'] : 0;
48
+
49
+ if (isset($result['error_description'])) {
50
+ // OAuth 2.0 Draft 10 style
51
+ $msg = $result['error_description'];
52
+ } else if (isset($result['error']) && is_array($result['error'])) {
53
+ // OAuth 2.0 Draft 00 style
54
+ $msg = $result['error']['message'];
55
+ } else if (isset($result['error_msg'])) {
56
+ // Rest server style
57
+ $msg = $result['error_msg'];
58
+ } else {
59
+ $msg = 'Unknown Error. Check getResult()';
60
+ }
61
+
62
+ parent::__construct($msg, $code);
63
  }
64
 
65
+ /**
66
+ * Return the associated result object returned by the API server.
67
+ *
68
+ * @return array The result from the API server
69
+ */
70
+ public function getResult()
71
+ {
72
+ return $this->result;
73
+ }
74
+
75
+ /**
76
+ * Returns the associated type for the error. This will default to
77
+ * 'Exception' when a type is not available.
78
+ *
79
+ * @return string
80
+ */
81
+ public function getType()
82
+ {
83
+ if (isset($this->result['error'])) {
84
+ $error = $this->result['error'];
85
+ if (is_string($error)) {
86
+ // OAuth 2.0 Draft 10 style
87
+ return $error;
88
+ } else if (is_array($error)) {
89
+ // OAuth 2.0 Draft 00 style
90
+ if (isset($error['type'])) {
91
+ return $error['type'];
92
+ }
93
+ }
94
  }
95
+
96
+ return 'Exception';
97
  }
98
 
99
+ /**
100
+ * To make debugging easier.
101
+ *
102
+ * @return string The string representation of the error
103
+ */
104
+ public function __toString()
105
+ {
106
+ $str = $this->getType() . ': ';
107
+ if ($this->code != 0) {
108
+ $str .= $this->code . ': ';
109
+ }
110
+ return $str . $this->message;
111
  }
 
 
112
  }
113
 
114
  /**
122
  */
123
  abstract class BaseFacebook
124
  {
125
+ /**
126
+ * Version.
127
+ */
128
+ const VERSION = '3.2.0';
129
+
130
+ /**
131
+ * Signed Request Algorithm.
132
+ */
133
+ const SIGNED_REQUEST_ALGORITHM = 'HMAC-SHA256';
134
+
135
+ /**
136
+ * Default options for curl.
137
+ */
138
+ public static $CURL_OPTS = array(
139
+ CURLOPT_CONNECTTIMEOUT => 10,
140
+ CURLOPT_RETURNTRANSFER => true,
141
+ CURLOPT_TIMEOUT => 60,
142
+ CURLOPT_USERAGENT => 'facebook-php-3.2',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
 
145
+ /**
146
+ * List of query parameters that get automatically dropped when rebuilding
147
+ * the current URL.
148
+ */
149
+ protected static $DROP_QUERY_PARAMS = array(
150
+ 'code',
151
+ 'state',
152
+ 'signed_request',
153
+ );
154
+
155
+ /**
156
+ * Maps aliases to Facebook domains.
157
+ */
158
+ public static $DOMAIN_MAP = array(
159
+ 'api' => 'https://api.facebook.com/',
160
+ 'api_video' => 'https://api-video.facebook.com/',
161
+ 'api_read' => 'https://api-read.facebook.com/',
162
+ 'graph' => 'https://graph.facebook.com/',
163
+ 'graph_video' => 'https://graph-video.facebook.com/',
164
+ 'www' => 'https://www.facebook.com/',
165
+ );
166
 
167
+ /**
168
+ * The Application ID.
169
+ *
170
+ * @var string
171
+ */
172
+ protected $appId;
173
+
174
+ /**
175
+ * The Application App Secret.
176
+ *
177
+ * @var string
178
+ */
179
+ protected $appSecret;
180
+
181
+ /**
182
+ * The ID of the Facebook user, or 0 if the user is logged out.
183
+ *
184
+ * @var integer
185
+ */
186
+ protected $user;
187
+
188
+ /**
189
+ * The data from the signed_request token.
190
+ */
191
+ protected $signedRequest;
192
+
193
+ /**
194
+ * A CSRF state variable to assist in the defense against CSRF attacks.
195
+ */
196
+ protected $state;
197
+
198
+ /**
199
+ * The OAuth access token received in exchange for a valid authorization
200
+ * code. null means the access token has yet to be determined.
201
+ *
202
+ * @var string
203
+ */
204
+ protected $accessToken = null;
205
+
206
+ /**
207
+ * Indicates if the CURL based @ syntax for file uploads is enabled.
208
+ *
209
+ * @var boolean
210
+ */
211
+ protected $fileUploadSupport = false;
212
+
213
+ /**
214
+ * Indicates if we trust HTTP_X_FORWARDED_* headers.
215
+ *
216
+ * @var boolean
217
+ */
218
+ protected $trustForwarded = false;
219
+
220
+ /**
221
+ * Initialize a Facebook Application.
222
+ *
223
+ * The configuration:
224
+ * - appId: the application ID
225
+ * - secret: the application secret
226
+ * - fileUpload: (optional) boolean indicating if file uploads are enabled
227
+ *
228
+ * @param array $config The application configuration
229
+ */
230
+ public function __construct($config)
231
+ {
232
+ $this->setAppId($config['appId']);
233
+ $this->setAppSecret($config['secret']);
234
+ if (isset($config['fileUpload'])) {
235
+ $this->setFileUploadSupport($config['fileUpload']);
236
+ }
237
+ if (isset($config['trustForwarded']) && $config['trustForwarded']) {
238
+ $this->trustForwarded = true;
239
+ }
240
+ $state = $this->getPersistentData('state');
241
+ if (!empty($state)) {
242
+ $this->state = $state;
243
  }
244
+ }
245
 
246
+ /**
247
+ * Set the Application ID.
248
+ *
249
+ * @param string $appId The Application ID
250
+ * @return BaseFacebook
251
+ */
252
+ public function setAppId($appId)
253
+ {
254
+ $this->appId = $appId;
255
+ return $this;
256
  }
257
 
258
+ /**
259
+ * Get the Application ID.
260
+ *
261
+ * @return string the Application ID
262
+ */
263
+ public function getAppId()
264
+ {
265
+ return $this->appId;
 
 
 
 
266
  }
267
 
268
+ /**
269
+ * Set the App Secret.
270
+ *
271
+ * @param string $apiSecret The App Secret
272
+ * @return BaseFacebook
273
+ * @deprecated
274
+ */
275
+ public function setApiSecret($apiSecret)
276
+ {
277
+ $this->setAppSecret($apiSecret);
278
+ return $this;
 
 
 
 
 
 
 
 
 
 
 
279
  }
280
+
281
+ /**
282
+ * Set the App Secret.
283
+ *
284
+ * @param string $appSecret The App Secret
285
+ * @return BaseFacebook
286
+ */
287
+ public function setAppSecret($appSecret)
288
+ {
289
+ $this->appSecret = $appSecret;
290
+ return $this;
 
 
291
  }
292
 
293
+ /**
294
+ * Get the App Secret.
295
+ *
296
+ * @return string the App Secret
297
+ * @deprecated
298
+ */
299
+ public function getApiSecret()
300
+ {
301
+ return $this->getAppSecret();
302
+ }
 
 
 
 
 
 
 
 
 
 
 
303
 
304
+ /**
305
+ * Get the App Secret.
306
+ *
307
+ * @return string the App Secret
308
+ */
309
+ public function getAppSecret()
310
+ {
311
+ return $this->appSecret;
312
  }
313
 
314
+ /**
315
+ * Set the file upload support status.
316
+ *
317
+ * @param boolean $fileUploadSupport The file upload support status.
318
+ * @return BaseFacebook
319
+ */
320
+ public function setFileUploadSupport($fileUploadSupport)
321
+ {
322
+ $this->fileUploadSupport = $fileUploadSupport;
323
+ return $this;
 
 
 
 
 
324
  }
325
 
326
+ /**
327
+ * Get the file upload support status.
328
+ *
329
+ * @return boolean true if and only if the server supports file upload.
330
+ */
331
+ public function getFileUploadSupport()
332
+ {
333
+ return $this->fileUploadSupport;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
334
  }
335
 
336
+ /**
337
+ * DEPRECATED! Please use getFileUploadSupport instead.
338
+ *
339
+ * Get the file upload support status.
340
+ *
341
+ * @return boolean true if and only if the server supports file upload.
342
+ */
343
+ public function useFileUploadSupport()
344
+ {
345
+ return $this->getFileUploadSupport();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
346
  }
347
+
348
+ /**
349
+ * Sets the access token for api calls. Use this if you get
350
+ * your access token by other means and just want the SDK
351
+ * to use it.
352
+ *
353
+ * @param string $access_token an access token.
354
+ * @return BaseFacebook
355
+ */
356
+ public function setAccessToken($access_token)
357
+ {
358
+ $this->accessToken = $access_token;
359
+ return $this;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
360
  }
361
 
362
+ /**
363
+ * Extend an access token, while removing the short-lived token that might
364
+ * have been generated via client-side flow. Thanks to http://bit.ly/b0Pt0H
365
+ * for the workaround.
366
+ */
367
+ public function setExtendedAccessToken()
368
+ {
369
+ try {
370
+ // need to circumvent json_decode by calling _oauthRequest
371
+ // directly, since response isn't JSON format.
372
+ $access_token_response = $this->_oauthRequest(
373
+ $this->getUrl('graph', '/oauth/access_token'),
374
+ $params = array(
375
+ 'client_id' => $this->getAppId(),
376
+ 'client_secret' => $this->getAppSecret(),
377
+ 'grant_type' => 'fb_exchange_token',
378
+ 'fb_exchange_token' => $this->getAccessToken(),
379
+ )
380
+ );
381
+ } catch (FacebookApiException $e) {
382
+ // most likely that user very recently revoked authorization.
383
+ // In any event, we don't have an access token, so say so.
384
+ return false;
385
+ }
386
+
387
+ if (empty($access_token_response)) {
388
+ return false;
389
+ }
390
+
391
+ $response_params = array();
392
+ parse_str($access_token_response, $response_params);
393
+
394
+ if (!isset($response_params['access_token'])) {
395
+ return false;
396
+ }
397
+
398
+ $this->destroySession();
399
+
400
+ $this->setPersistentData(
401
+ 'access_token', $response_params['access_token']
402
+ );
403
  }
404
+
405
+ /**
406
+ * Determines the access token that should be used for API calls.
407
+ * The first time this is called, $this->accessToken is set equal
408
+ * to either a valid user access token, or it's set to the application
409
+ * access token if a valid user access token wasn't available. Subsequent
410
+ * calls return whatever the first call returned.
411
+ *
412
+ * @return string The access token
413
+ */
414
+ public function getAccessToken()
415
+ {
416
+ if ($this->accessToken !== null) {
417
+ // we've done this already and cached it. Just return.
418
+ return $this->accessToken;
419
+ }
420
+
421
+ // first establish access token to be the application
422
+ // access token, in case we navigate to the /oauth/access_token
423
+ // endpoint, where SOME access token is required.
424
+ $this->setAccessToken($this->getApplicationAccessToken());
425
+ $user_access_token = $this->getUserAccessToken();
426
+ if ($user_access_token) {
427
+ $this->setAccessToken($user_access_token);
428
+ }
429
+
430
+ return $this->accessToken;
431
  }
432
+
433
+ /**
434
+ * Determines and returns the user access token, first using
435
+ * the signed request if present, and then falling back on
436
+ * the authorization code if present. The intent is to
437
+ * return a valid user access token, or false if one is determined
438
+ * to not be available.
439
+ *
440
+ * @return string A valid user access token, or false if one
441
+ * could not be determined.
442
+ */
443
+ protected function getUserAccessToken()
444
+ {
445
+ // first, consider a signed request if it's supplied.
446
+ // if there is a signed request, then it alone determines
447
+ // the access token.
448
+ $signed_request = $this->getSignedRequest();
449
+ if ($signed_request) {
450
+ // apps.facebook.com hands the access_token in the signed_request
451
+ if (array_key_exists('oauth_token', $signed_request)) {
452
+ $access_token = $signed_request['oauth_token'];
453
+ $this->setPersistentData('access_token', $access_token);
454
+ return $access_token;
455
+ }
456
+
457
+ // the JS SDK puts a code in with the redirect_uri of ''
458
+ if (array_key_exists('code', $signed_request)) {
459
+ $code = $signed_request['code'];
460
+ $access_token = $this->getAccessTokenFromCode($code, '');
461
+ if ($access_token) {
462
+ $this->setPersistentData('code', $code);
463
+ $this->setPersistentData('access_token', $access_token);
464
+ return $access_token;
465
+ }
466
+ }
467
+
468
+ // signed request states there's no access token, so anything
469
+ // stored should be cleared.
470
+ $this->clearAllPersistentData();
471
+ return false; // respect the signed request's data, even
472
+ // if there's an authorization code or something else
473
+ }
474
+
475
+ $code = $this->getCode();
476
+ if ($code && $code != $this->getPersistentData('code')) {
477
+ $access_token = $this->getAccessTokenFromCode($code);
478
+ if ($access_token) {
479
+ $this->setPersistentData('code', $code);
480
+ $this->setPersistentData('access_token', $access_token);
481
+ return $access_token;
482
+ }
483
+
484
+ // code was bogus, so everything based on it should be invalidated.
485
+ $this->clearAllPersistentData();
486
+ return false;
487
+ }
488
+
489
+ // as a fallback, just return whatever is in the persistent
490
+ // store, knowing nothing explicit (signed request, authorization
491
+ // code, etc.) was present to shadow it (or we saw a code in $_REQUEST,
492
+ // but it's the same as what's in the persistent store)
493
+ return $this->getPersistentData('access_token');
494
  }
495
 
496
+ /**
497
+ * Retrieve the signed request, either from a request parameter or,
498
+ * if not present, from a cookie.
499
+ *
500
+ * @return string the signed request, if available, or null otherwise.
501
+ */
502
+ public function getSignedRequest()
503
+ {
504
+ if (!$this->signedRequest) {
505
+ if (isset($_REQUEST['signed_request'])) {
506
+ $this->signedRequest = $this->parseSignedRequest(
507
+ $_REQUEST['signed_request']);
508
+ } else if (isset($_COOKIE[$this->getSignedRequestCookieName()])) {
509
+ $this->signedRequest = $this->parseSignedRequest(
510
+ $_COOKIE[$this->getSignedRequestCookieName()]);
511
+ }
512
+ }
513
+ return $this->signedRequest;
514
  }
515
 
516
+ /**
517
+ * Get the UID of the connected user, or 0
518
+ * if the Facebook user is not connected.
519
+ *
520
+ * @return string the UID if available.
521
+ */
522
+ public function getUser()
523
+ {
524
+ if ($this->user !== null) {
525
+ // we've already determined this and cached the value.
526
+ return $this->user;
527
+ }
528
+
529
+ return $this->user = $this->getUserFromAvailableData();
530
  }
531
 
532
+ /**
533
+ * Determines the connected user by first examining any signed
534
+ * requests, then considering an authorization code, and then
535
+ * falling back to any persistent store storing the user.
536
+ *
537
+ * @return integer The id of the connected Facebook user,
538
+ * or 0 if no such user exists.
539
+ */
540
+ protected function getUserFromAvailableData()
541
+ {
542
+ // if a signed request is supplied, then it solely determines
543
+ // who the user is.
544
+ $signed_request = $this->getSignedRequest();
545
+ if ($signed_request) {
546
+ if (array_key_exists('user_id', $signed_request)) {
547
+ $user = $signed_request['user_id'];
548
+ $this->setPersistentData('user_id', $signed_request['user_id']);
549
+ return $user;
550
+ }
551
+
552
+ // if the signed request didn't present a user id, then invalidate
553
+ // all entries in any persistent store.
554
+ $this->clearAllPersistentData();
555
+ return 0;
556
+ }
557
+
558
+ $user = $this->getPersistentData('user_id', $default = 0);
559
+ $persisted_access_token = $this->getPersistentData('access_token');
560
+
561
+ // use access_token to fetch user id if we have a user access_token, or if
562
+ // the cached access token has changed.
563
+ $access_token = $this->getAccessToken();
564
+ if ($access_token &&
565
+ $access_token != $this->getApplicationAccessToken() &&
566
+ !($user && $persisted_access_token == $access_token)
567
+ ) {
568
+ $user = $this->getUserFromAccessToken();
569
+ if ($user) {
570
+ $this->setPersistentData('user_id', $user);
571
+ } else {
572
+ $this->clearAllPersistentData();
573
+ }
574
+ }
575
+
576
+ return $user;
577
  }
578
 
579
+ /**
580
+ * Get a Login URL for use with redirects. By default, full page redirect is
581
+ * assumed. If you are using the generated URL with a window.open() call in
582
+ * JavaScript, you can pass in display=popup as part of the $params.
583
+ *
584
+ * The parameters:
585
+ * - redirect_uri: the url to go to after a successful login
586
+ * - scope: comma separated list of requested extended perms
587
+ *
588
+ * @param array $params Provide custom parameters
589
+ * @return string The URL for the login flow
590
+ */
591
+ public function getLoginUrl($params = array())
592
+ {
593
+ $this->establishCSRFTokenState();
594
+ $currentUrl = $this->getCurrentUrl();
595
+
596
+ // if 'scope' is passed as an array, convert to comma separated list
597
+ $scopeParams = isset($params['scope']) ? $params['scope'] : null;
598
+ if ($scopeParams && is_array($scopeParams)) {
599
+ $params['scope'] = implode(',', $scopeParams);
600
+ }
601
+
602
+ return $this->getUrl(
603
+ 'www',
604
+ 'dialog/oauth',
605
+ array_merge(array(
606
+ 'client_id' => $this->getAppId(),
607
+ 'redirect_uri' => $currentUrl, // possibly overwritten
608
+ 'state' => $this->state),
609
+ $params));
610
  }
611
 
612
+ /**
613
+ * Get a Logout URL suitable for use with redirects.
614
+ *
615
+ * The parameters:
616
+ * - next: the url to go to after a successful logout
617
+ *
618
+ * @param array $params Provide custom parameters
619
+ * @return string The URL for the logout flow
620
+ */
621
+ public function getLogoutUrl($params = array())
622
+ {
623
+ return $this->getUrl(
624
+ 'www',
625
+ 'logout.php',
626
+ array_merge(array(
627
+ 'next' => $this->getCurrentUrl(),
628
+ 'access_token' => $this->getUserAccessToken(),
629
+ ), $params)
630
+ );
 
 
 
 
 
 
631
  }
 
632
 
633
+ /**
634
+ * Get a login status URL to fetch the status from Facebook.
635
+ *
636
+ * The parameters:
637
+ * - ok_session: the URL to go to if a session is found
638
+ * - no_session: the URL to go to if the user is not connected
639
+ * - no_user: the URL to go to if the user is not signed into facebook
640
+ *
641
+ * @param array $params Provide custom parameters
642
+ * @return string The URL for the logout flow
643
+ */
644
+ public function getLoginStatusUrl($params = array())
645
+ {
646
+ return $this->getUrl(
647
+ 'www',
648
+ 'extern/login_status.php',
649
+ array_merge(array(
650
+ 'api_key' => $this->getAppId(),
651
+ 'no_session' => $this->getCurrentUrl(),
652
+ 'no_user' => $this->getCurrentUrl(),
653
+ 'ok_session' => $this->getCurrentUrl(),
654
+ 'session_version' => 3,
655
+ ), $params)
656
+ );
657
  }
658
 
659
+ /**
660
+ * Make an API call.
661
+ *
662
+ * @return mixed The decoded response
663
+ */
664
+ public function api(/* polymorphic */)
665
+ {
666
+ $args = func_get_args();
667
+ if (is_array($args[0])) {
668
+ return $this->_restserver($args[0]);
669
+ } else {
670
+ return call_user_func_array(array($this, '_graph'), $args);
671
+ }
 
672
  }
673
+
674
+ /**
675
+ * Constructs and returns the name of the cookie that
676
+ * potentially houses the signed request for the app user.
677
+ * The cookie is not set by the BaseFacebook class, but
678
+ * it may be set by the JavaScript SDK.
679
+ *
680
+ * @return string the name of the cookie that would house
681
+ * the signed request value.
682
+ */
683
+ protected function getSignedRequestCookieName()
684
+ {
685
+ return 'fbsr_' . $this->getAppId();
 
 
 
 
686
  }
 
687
 
688
+ /**
689
+ * Constructs and returns the name of the coookie that potentially contain
690
+ * metadata. The cookie is not set by the BaseFacebook class, but it may be
691
+ * set by the JavaScript SDK.
692
+ *
693
+ * @return string the name of the cookie that would house metadata.
694
+ */
695
+ protected function getMetadataCookieName()
696
+ {
697
+ return 'fbm_' . $this->getAppId();
698
  }
699
 
700
+ /**
701
+ * Get the authorization code from the query parameters, if it exists,
702
+ * and otherwise return false to signal no authorization code was
703
+ * discoverable.
704
+ *
705
+ * @return mixed The authorization code, or false if the authorization
706
+ * code could not be determined.
707
+ */
708
+ protected function getCode()
709
+ {
710
+ if (isset($_REQUEST['code'])) {
711
+ if ($this->state !== null &&
712
+ isset($_REQUEST['state']) &&
713
+ $this->state === $_REQUEST['state']
714
+ ) {
715
+
716
+ // CSRF state has done its job, so clear it
717
+ $this->state = null;
718
+ $this->clearPersistentData('state');
719
+ return $_REQUEST['code'];
720
+ } else {
721
+ self::errorLog('CSRF state token does not match one provided.');
722
+ return false;
723
+ }
724
+ }
725
 
726
+ return false;
 
 
 
727
  }
728
+
729
+ /**
730
+ * Retrieves the UID with the understanding that
731
+ * $this->accessToken has already been set and is
732
+ * seemingly legitimate. It relies on Facebook's Graph API
733
+ * to retrieve user information and then extract
734
+ * the user ID.
735
+ *
736
+ * @return integer Returns the UID of the Facebook user, or 0
737
+ * if the Facebook user could not be determined.
738
+ */
739
+ protected function getUserFromAccessToken()
740
+ {
741
+ try {
742
+ $user_info = $this->api('/me');
743
+ return $user_info['id'];
744
+ } catch (FacebookApiException $e) {
745
+ return 0;
746
+ }
747
  }
748
 
749
+ /**
750
+ * Returns the access token that should be used for logged out
751
+ * users when no authorization code is available.
752
+ *
753
+ * @return string The application access token, useful for gathering
754
+ * public information about users and applications.
755
+ */
756
+ protected function getApplicationAccessToken()
757
+ {
758
+ return $this->appId . '|' . $this->appSecret;
759
  }
760
 
761
+ /**
762
+ * Lays down a CSRF state token for this process.
763
+ *
764
+ * @return void
765
+ */
766
+ protected function establishCSRFTokenState()
767
+ {
768
+ if ($this->state === null) {
769
+ $this->state = md5(uniqid(mt_rand(), true));
770
+ $this->setPersistentData('state', $this->state);
771
+ }
 
 
 
 
 
 
772
  }
773
 
774
+ /**
775
+ * Retrieves an access token for the given authorization code
776
+ * (previously generated from www.facebook.com on behalf of
777
+ * a specific user). The authorization code is sent to graph.facebook.com
778
+ * and a legitimate access token is generated provided the access token
779
+ * and the user for which it was generated all match, and the user is
780
+ * either logged in to Facebook or has granted an offline access permission.
781
+ *
782
+ * @param string $code An authorization code.
783
+ * @return mixed An access token exchanged for the authorization code, or
784
+ * false if an access token could not be generated.
785
+ */
786
+ protected function getAccessTokenFromCode($code, $redirect_uri = null)
787
+ {
788
+ if (empty($code)) {
789
+ return false;
790
+ }
791
+
792
+ if ($redirect_uri === null) {
793
+ $redirect_uri = $this->getCurrentUrl();
794
+ }
795
+
796
+ try {
797
+ // need to circumvent json_decode by calling _oauthRequest
798
+ // directly, since response isn't JSON format.
799
+ $access_token_response =
800
+ $this->_oauthRequest(
801
+ $this->getUrl('graph', '/oauth/access_token'),
802
+ $params = array('client_id' => $this->getAppId(),
803
+ 'client_secret' => $this->getAppSecret(),
804
+ 'redirect_uri' => $redirect_uri,
805
+ 'code' => $code));
806
+ } catch (FacebookApiException $e) {
807
+ // most likely that user very recently revoked authorization.
808
+ // In any event, we don't have an access token, so say so.
809
+ return false;
810
+ }
811
+
812
+ if (empty($access_token_response)) {
813
+ return false;
814
+ }
815
+
816
+ $response_params = array();
817
+ parse_str($access_token_response, $response_params);
818
+ if (!isset($response_params['access_token'])) {
819
+ return false;
820
+ }
821
+
822
+ return $response_params['access_token'];
823
  }
824
+
825
+ /**
826
+ * Invoke the old restserver.php endpoint.
827
+ *
828
+ * @param array $params Method call object
829
+ *
830
+ * @return mixed The decoded response object
831
+ * @throws FacebookApiException
832
+ */
833
+ protected function _restserver($params)
834
+ {
835
+ // generic application level parameters
836
+ $params['api_key'] = $this->getAppId();
837
+ $params['format'] = 'json-strings';
838
+
839
+ $result = json_decode($this->_oauthRequest(
840
+ $this->getApiUrl($params['method']),
841
+ $params
842
+ ), true);
843
+
844
+ // results are returned, errors are thrown
845
+ if (is_array($result) && isset($result['error_code'])) {
846
+ $this->throwAPIException($result);
847
+ // @codeCoverageIgnoreStart
848
+ }
849
+ // @codeCoverageIgnoreEnd
850
+
851
+ $method = strtolower($params['method']);
852
+ if ($method === 'auth.expiresession' ||
853
+ $method === 'auth.revokeauthorization'
854
+ ) {
855
+ $this->destroySession();
856
+ }
857
+
858
+ return $result;
859
  }
860
+
861
+ /**
862
+ * Return true if this is video post.
863
+ *
864
+ * @param string $path The path
865
+ * @param string $method The http method (default 'GET')
866
+ *
867
+ * @return boolean true if this is video post
868
+ */
869
+ protected function isVideoPost($path, $method = 'GET')
870
+ {
871
+ if ($method == 'POST' && preg_match("/^(\/)(.+)(\/)(videos)$/", $path)) {
872
+ return true;
873
+ }
874
+ return false;
875
  }
876
 
877
+ /**
878
+ * Invoke the Graph API.
879
+ *
880
+ * @param string $path The path (required)
881
+ * @param string $method The http method (default 'GET')
882
+ * @param array $params The query/post data
883
+ *
884
+ * @return mixed The decoded response object
885
+ * @throws FacebookApiException
886
+ */
887
+ protected function _graph($path, $method = 'GET', $params = array())
888
+ {
889
+ if (is_array($method) && empty($params)) {
890
+ $params = $method;
891
+ $method = 'GET';
 
892
  }
893
+ $params['method'] = $method; // method override as we always do a POST
894
+
895
+ if ($this->isVideoPost($path, $method)) {
896
+ $domainKey = 'graph_video';
897
+ } else {
898
+ $domainKey = 'graph';
899
+ }
900
+
901
+ $result = json_decode($this->_oauthRequest(
902
+ $this->getUrl($domainKey, $path),
903
+ $params
904
+ ), true);
905
+
906
+ // results are returned, errors are thrown
907
+ if (is_array($result) && isset($result['error'])) {
908
+ $this->throwAPIException($result);
909
+ // @codeCoverageIgnoreStart
910
+ }
911
+ // @codeCoverageIgnoreEnd
912
+
913
+ return $result;
914
  }
915
 
916
+ /**
917
+ * Make a OAuth Request.
918
+ *
919
+ * @param string $url The path (required)
920
+ * @param array $params The query/post data
921
+ *
922
+ * @return string The decoded response object
923
+ * @throws FacebookApiException
924
+ */
925
+ protected function _oauthRequest($url, $params)
926
+ {
927
+ if (!isset($params['access_token'])) {
928
+ $params['access_token'] = $this->getAccessToken();
929
+ }
930
+
931
+ // json_encode all params values that are not strings
932
+ foreach ($params as $key => $value) {
933
+ if (!is_string($value)) {
934
+ $params[$key] = json_encode($value);
935
+ }
936
+ }
937
+
938
+ return $this->makeRequest($url, $params);
939
  }
940
+
941
+ /**
942
+ * Makes an HTTP request. This method can be overridden by subclasses if
943
+ * developers want to do fancier things or use something other than curl to
944
+ * make the request.
945
+ *
946
+ * @param string $url The URL to make the request to
947
+ * @param array $params The parameters to use for the POST body
948
+ * @param CurlHandler $ch Initialized curl handle
949
+ *
950
+ * @return string The response text
951
+ */
952
+ protected function makeRequest($url, $params, $ch = null)
953
+ {
954
+ if (!$ch) {
955
+ $ch = curl_init();
956
+ }
957
+
958
+ $opts = self::$CURL_OPTS;
959
+ if ($this->getFileUploadSupport()) {
960
+ $opts[CURLOPT_POSTFIELDS] = $params;
961
+ } else {
962
+ $opts[CURLOPT_POSTFIELDS] = http_build_query($params, null, '&');
963
+ }
964
+ $opts[CURLOPT_URL] = $url;
965
+
966
+ // disable the 'Expect: 100-continue' behaviour. This causes CURL to wait
967
+ // for 2 seconds if the server does not support this header.
968
+ if (isset($opts[CURLOPT_HTTPHEADER])) {
969
+ $existing_headers = $opts[CURLOPT_HTTPHEADER];
970
+ $existing_headers[] = 'Expect:';
971
+ $opts[CURLOPT_HTTPHEADER] = $existing_headers;
972
+ } else {
973
+ $opts[CURLOPT_HTTPHEADER] = array('Expect:');
974
+ }
975
+ //no ssl verification xz3 modifications
976
+ $opts[CURLOPT_SSL_VERIFYPEER] = false;
977
+ //end modifications
978
+ curl_setopt_array($ch, $opts);
979
+ $result = curl_exec($ch);
980
+
981
+ if (curl_errno($ch) == 60) { // CURLE_SSL_CACERT
982
+ self::errorLog('Invalid or no certificate authority found, ' .
983
+ 'using bundled information');
984
+ curl_setopt($ch, CURLOPT_CAINFO,
985
+ dirname(__FILE__) . '/fb_ca_chain_bundle.crt');
986
+ $result = curl_exec($ch);
987
+ }
988
+
989
+ // With dual stacked DNS responses, it's possible for a server to
990
+ // have IPv6 enabled but not have IPv6 connectivity. If this is
991
+ // the case, curl will try IPv4 first and if that fails, then it will
992
+ // fall back to IPv6 and the error EHOSTUNREACH is returned by the
993
+ // operating system.
994
+ if ($result === false && empty($opts[CURLOPT_IPRESOLVE])) {
995
+ $matches = array();
996
+ $regex = '/Failed to connect to ([^:].*): Network is unreachable/';
997
+ if (preg_match($regex, curl_error($ch), $matches)) {
998
+ if (strlen(@inet_pton($matches[1])) === 16) {
999
+ self::errorLog('Invalid IPv6 configuration on server, ' .
1000
+ 'Please disable or get native IPv6 on your server.');
1001
+ self::$CURL_OPTS[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
1002
+ curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
1003
+ $result = curl_exec($ch);
1004
+ }
1005
+ }
1006
+ }
1007
+
1008
+ if ($result === false) {
1009
+ $e = new FacebookApiException(array(
1010
+ 'error_code' => curl_errno($ch),
1011
+ 'error' => array(
1012
+ 'message' => curl_error($ch),
1013
+ 'type' => 'CurlException',
1014
+ ),
1015
+ ));
1016
+ curl_close($ch);
1017
+ throw $e;
1018
+ }
1019
+ curl_close($ch);
1020
+ return $result;
1021
  }
1022
 
1023
+ /**
1024
+ * Parses a signed_request and validates the signature.
1025
+ *
1026
+ * @param string $signed_request A signed token
1027
+ * @return array The payload inside it or null if the sig is wrong
1028
+ */
1029
+ protected function parseSignedRequest($signed_request)
1030
+ {
1031
+ list($encoded_sig, $payload) = explode('.', $signed_request, 2);
1032
+
1033
+ // decode the data
1034
+ $sig = self::base64UrlDecode($encoded_sig);
1035
+ $data = json_decode(self::base64UrlDecode($payload), true);
1036
+
1037
+ if (strtoupper($data['algorithm']) !== self::SIGNED_REQUEST_ALGORITHM) {
1038
+ self::errorLog(
1039
+ 'Unknown algorithm. Expected ' . self::SIGNED_REQUEST_ALGORITHM);
1040
+ return null;
1041
+ }
1042
+
1043
+ // check sig
1044
+ $expected_sig = hash_hmac('sha256', $payload,
1045
+ $this->getAppSecret(), $raw = true);
1046
+ if ($sig !== $expected_sig) {
1047
+ self::errorLog('Bad Signed JSON signature!');
1048
+ return null;
1049
+ }
1050
+
1051
+ return $data;
1052
  }
1053
 
1054
+ /**
1055
+ * Makes a signed_request blob using the given data.
1056
+ *
1057
+ * @param array The data array.
1058
+ * @return string The signed request.
1059
+ */
1060
+ protected function makeSignedRequest($data)
1061
+ {
1062
+ if (!is_array($data)) {
1063
+ throw new InvalidArgumentException(
1064
+ 'makeSignedRequest expects an array. Got: ' . print_r($data, true));
1065
+ }
1066
+ $data['algorithm'] = self::SIGNED_REQUEST_ALGORITHM;
1067
+ $data['issued_at'] = time();
1068
+ $json = json_encode($data);
1069
+ $b64 = self::base64UrlEncode($json);
1070
+ $raw_sig = hash_hmac('sha256', $b64, $this->getAppSecret(), $raw = true);
1071
+ $sig = self::base64UrlEncode($raw_sig);
1072
+ return $sig . '.' . $b64;
1073
  }
1074
+
1075
+ /**
1076
+ * Build the URL for api given parameters.
1077
+ *
1078
+ * @param $method String the method name.
1079
+ * @return string The URL for the given parameters
1080
+ */
1081
+ protected function getApiUrl($method)
1082
+ {
1083
+ static $READ_ONLY_CALLS =
1084
+ array('admin.getallocation' => 1,
 
 
 
 
 
 
 
1085
  'admin.getappproperties' => 1,
1086
  'admin.getbannedusers' => 1,
1087
  'admin.getlivestreamvialink' => 1,
1141
  'users.isappuser' => 1,
1142
  'users.isverified' => 1,
1143
  'video.getuploadlimits' => 1);
1144
+ $name = 'api';
1145
+ if (isset($READ_ONLY_CALLS[strtolower($method)])) {
1146
+ $name = 'api_read';
1147
+ } else if (strtolower($method) == 'video.upload') {
1148
+ $name = 'api_video';
1149
+ }
1150
+ return self::getUrl($name, 'restserver.php');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1151
  }
1152
 
1153
+ /**
1154
+ * Build the URL for given domain alias, path and parameters.
1155
+ *
1156
+ * @param $name string The name of the domain
1157
+ * @param $path string Optional path (without a leading slash)
1158
+ * @param $params array Optional query parameters
1159
+ *
1160
+ * @return string The URL for the given parameters
1161
+ */
1162
+ protected function getUrl($name, $path = '', $params = array())
1163
+ {
1164
+ $url = self::$DOMAIN_MAP[$name];
1165
+ if ($path) {
1166
+ if ($path[0] === '/') {
1167
+ $path = substr($path, 1);
1168
+ }
1169
+ $url .= $path;
1170
+ }
1171
+ if ($params) {
1172
+ $url .= '?' . http_build_query($params, null, '&');
1173
+ }
1174
 
1175
+ return $url;
 
 
1176
  }
1177
+
1178
+ protected function getHttpHost()
1179
+ {
1180
+ if ($this->trustForwarded && isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
1181
+ return $_SERVER['HTTP_X_FORWARDED_HOST'];
1182
+ }
1183
+ return $_SERVER['HTTP_HOST'];
 
 
1184
  }
1185
+
1186
+ protected function getHttpProtocol()
1187
+ {
1188
+ if ($this->trustForwarded && isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
1189
+ if ($_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
1190
+ return 'https';
1191
+ }
1192
+ return 'http';
1193
+ }
1194
+ if (isset($_SERVER['HTTPS']) &&
1195
+ ($_SERVER['HTTPS'] === 'on' || $_SERVER['HTTPS'] == 1)
1196
+ ) {
1197
+ return 'https';
1198
+ }
1199
+ return 'http';
1200
  }
1201
+
1202
+ /**
1203
+ * Get the base domain used for the cookie.
1204
+ */
1205
+ protected function getBaseDomain()
1206
+ {
1207
+ // The base domain is stored in the metadata cookie if not we fallback
1208
+ // to the current hostname
1209
+ $metadata = $this->getMetadataCookie();
1210
+ if (array_key_exists('base_domain', $metadata) &&
1211
+ !empty($metadata['base_domain'])
1212
+ ) {
1213
+ return trim($metadata['base_domain'], '.');
1214
+ }
1215
+ return $this->getHttpHost();
1216
  }
1217
+
1218
+ /**
1219
+ *
1220
+ * /**
1221
+ * Returns the Current URL, stripping it of known FB parameters that should
1222
+ * not persist.
1223
+ *
1224
+ * @return string The current URL
1225
+ */
1226
+ protected function getCurrentUrl()
1227
+ {
1228
+ $protocol = $this->getHttpProtocol() . '://';
1229
+ $host = $this->getHttpHost();
1230
+ $currentUrl = $protocol . $host . $_SERVER['REQUEST_URI'];
1231
+ $parts = parse_url($currentUrl);
1232
+
1233
+ $query = '';
1234
+ if (!empty($parts['query'])) {
1235
+ // drop known fb params
1236
+ $params = explode('&', $parts['query']);
1237
+ $retained_params = array();
1238
+ foreach ($params as $param) {
1239
+ if ($this->shouldRetainParam($param)) {
1240
+ $retained_params[] = $param;
1241
+ }
1242
+ }
1243
+
1244
+ if (!empty($retained_params)) {
1245
+ $query = '?' . implode($retained_params, '&');
1246
+ }
1247
  }
 
1248
 
1249
+ // use port if non default
1250
+ $port =
1251
+ isset($parts['port']) &&
1252
+ (($protocol === 'http://' && $parts['port'] !== 80) ||
1253
+ ($protocol === 'https://' && $parts['port'] !== 443))
1254
+ ? ':' . $parts['port'] : '';
1255
 
1256
+ // rebuild
1257
+ return $protocol . $parts['host'] . $port . $parts['path'] . $query;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1258
  }
1259
 
1260
+ /**
1261
+ * Returns true if and only if the key or key/value pair should
1262
+ * be retained as part of the query string. This amounts to
1263
+ * a brute-force search of the very small list of Facebook-specific
1264
+ * params that should be stripped out.
1265
+ *
1266
+ * @param string $param A key or key/value pair within a URL's query (e.g.
1267
+ * 'foo=a', 'foo=', or 'foo'.
1268
+ *
1269
+ * @return boolean
1270
+ */
1271
+ protected function shouldRetainParam($param)
1272
+ {
1273
+ foreach (self::$DROP_QUERY_PARAMS as $drop_query_param) {
1274
+ if (strpos($param, $drop_query_param . '=') === 0) {
1275
+ return false;
1276
+ }
 
 
 
 
 
 
 
 
 
1277
  }
 
 
1278
 
1279
+ return true;
1280
+ }
1281
 
1282
+ /**
1283
+ * Analyzes the supplied result to see if it was thrown
1284
+ * because the access token is no longer valid. If that is
1285
+ * the case, then we destroy the session.
1286
+ *
1287
+ * @param $result array A record storing the error message returned
1288
+ * by a failed API call.
1289
+ */
1290
+ protected function throwAPIException($result)
1291
+ {
1292
+ $e = new FacebookApiException($result);
1293
+ switch ($e->getType()) {
1294
+ // OAuth 2.0 Draft 00 style
1295
+ case 'OAuthException':
1296
+ // OAuth 2.0 Draft 10 style
1297
+ case 'invalid_token':
1298
+ // REST server errors are just Exceptions
1299
+ case 'Exception':
1300
+ $message = $e->getMessage();
1301
+ if ((strpos($message, 'Error validating access token') !== false) ||
1302
+ (strpos($message, 'Invalid OAuth access token') !== false) ||
1303
+ (strpos($message, 'An active access token must be used') !== false)
1304
+ ) {
1305
+ $this->destroySession();
1306
+ }
1307
+ break;
1308
+ }
1309
 
1310
+ throw $e;
 
 
 
 
 
 
 
 
 
1311
  }
1312
+
1313
+
1314
+ /**
1315
+ * Prints to the error log if you aren't in command line mode.
1316
+ *
1317
+ * @param string $msg Log message
1318
+ */
1319
+ protected static function errorLog($msg)
1320
+ {
1321
+ // disable error log if we are running in a CLI environment
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1322
  // @codeCoverageIgnoreStart
1323
+ if (php_sapi_name() != 'cli') {
1324
+ error_log($msg);
1325
+ }
1326
+ // uncomment this if you want to see the errors on the page
1327
+ // print 'error_log: '.$msg."\n";
1328
  // @codeCoverageIgnoreEnd
 
 
 
 
 
 
 
 
 
 
 
 
 
1329
  }
1330
 
1331
+ /**
1332
+ * Base64 encoding that doesn't need to be urlencode()ed.
1333
+ * Exactly the same as base64_encode except it uses
1334
+ * - instead of +
1335
+ * _ instead of /
1336
+ * No padded =
1337
+ *
1338
+ * @param string $input base64UrlEncoded string
1339
+ * @return string
1340
+ */
1341
+ protected static function base64UrlDecode($input)
1342
+ {
1343
+ return base64_decode(strtr($input, '-_', '+/'));
1344
+ }
1345
 
1346
+ /**
1347
+ * Base64 encoding that doesn't need to be urlencode()ed.
1348
+ * Exactly the same as base64_encode except it uses
1349
+ * - instead of +
1350
+ * _ instead of /
1351
+ *
1352
+ * @param string $input string
1353
+ * @return string base64Url encoded string
1354
+ */
1355
+ protected static function base64UrlEncode($input)
1356
+ {
1357
+ $str = strtr(base64_encode($input), '+/', '-_');
1358
+ $str = str_replace('=', '', $str);
1359
+ return $str;
1360
  }
1361
 
1362
+ /**
1363
+ * Destroy the current session
1364
+ */
1365
+ public function destroySession()
1366
+ {
1367
+ $this->accessToken = null;
1368
+ $this->signedRequest = null;
1369
+ $this->user = null;
1370
+ $this->clearAllPersistentData();
1371
+
1372
+ // Javascript sets a cookie that will be used in getSignedRequest that we
1373
+ // need to clear if we can
1374
+ $cookie_name = $this->getSignedRequestCookieName();
1375
+ if (array_key_exists($cookie_name, $_COOKIE)) {
1376
+ unset($_COOKIE[$cookie_name]);
1377
+ if (!headers_sent()) {
1378
+ $base_domain = $this->getBaseDomain();
1379
+ setcookie($cookie_name, '', 1, '/', '.' . $base_domain);
1380
+ } else {
1381
+ // @codeCoverageIgnoreStart
1382
+ self::errorLog(
1383
+ 'There exists a cookie that we wanted to clear that we couldn\'t ' .
1384
+ 'clear because headers was already sent. Make sure to do the first ' .
1385
+ 'API call before outputing anything.'
1386
+ );
1387
+ // @codeCoverageIgnoreEnd
1388
+ }
1389
+ }
1390
  }
1391
 
1392
+ /**
1393
+ * Parses the metadata cookie that our Javascript API set
1394
+ *
1395
+ * @return an array mapping key to value
1396
+ */
1397
+ protected function getMetadataCookie()
1398
+ {
1399
+ $cookie_name = $this->getMetadataCookieName();
1400
+ if (!array_key_exists($cookie_name, $_COOKIE)) {
1401
+ return array();
1402
+ }
1403
+
1404
+ // The cookie value can be wrapped in "-characters so remove them
1405
+ $cookie_value = trim($_COOKIE[$cookie_name], '"');
1406
 
1407
+ if (empty($cookie_value)) {
1408
+ return array();
1409
+ }
1410
+
1411
+ $parts = explode('&', $cookie_value);
1412
+ $metadata = array();
1413
+ foreach ($parts as $part) {
1414
+ $pair = explode('=', $part, 2);
1415
+ if (!empty($pair[0])) {
1416
+ $metadata[urldecode($pair[0])] =
1417
+ (count($pair) > 1) ? urldecode($pair[1]) : '';
1418
+ }
1419
+ }
1420
+
1421
+ return $metadata;
1422
+ }
1423
+
1424
+ protected static function isAllowedDomain($big, $small)
1425
+ {
1426
+ if ($big === $small) {
1427
+ return true;
1428
+ }
1429
+ return self::endsWith($big, '.' . $small);
1430
  }
 
 
1431
 
1432
+ protected static function endsWith($big, $small)
1433
+ {
1434
+ $len = strlen($small);
1435
+ if ($len === 0) {
1436
+ return true;
1437
+ }
1438
+ return substr($big, -$len) === $small;
1439
  }
1440
+
1441
+ /**
1442
+ * Each of the following four methods should be overridden in
1443
+ * a concrete subclass, as they are in the provided Facebook class.
1444
+ * The Facebook class uses PHP sessions to provide a primitive
1445
+ * persistent store, but another subclass--one that you implement--
1446
+ * might use a database, memcache, or an in-memory cache.
1447
+ *
1448
+ * @see Facebook
1449
+ */
1450
+
1451
+ /**
1452
+ * Stores the given ($key, $value) pair, so that future calls to
1453
+ * getPersistentData($key) return $value. This call may be in another request.
1454
+ *
1455
+ * @param string $key
1456
+ * @param array $value
1457
+ *
1458
+ * @return void
1459
+ */
1460
+ abstract protected function setPersistentData($key, $value);
1461
+
1462
+ /**
1463
+ * Get the data for $key, persisted by BaseFacebook::setPersistentData()
1464
+ *
1465
+ * @param string $key The key of the data to retrieve
1466
+ * @param boolean $default The default value to return if $key is not found
1467
+ *
1468
+ * @return mixed
1469
+ */
1470
+ abstract protected function getPersistentData($key, $default = false);
1471
+
1472
+ /**
1473
+ * Clear the data with $key from the persistent storage
1474
+ *
1475
+ * @param string $key
1476
+ * @return void
1477
+ */
1478
+ abstract protected function clearPersistentData($key);
1479
+
1480
+ /**
1481
+ * Clear all data from the persistent storage
1482
+ *
1483
+ * @return void
1484
+ */
1485
+ abstract protected function clearAllPersistentData();
1486
+ }
 
 
lib/fb/facebook.php CHANGED
@@ -14,14 +14,14 @@
14
  * License for the specific language governing permissions and limitations
15
  * under the License.
16
  */
17
-
18
- require_once "base_facebook.php";
19
 
20
  /**
21
  * Extends the BaseFacebook class with the intent of using
22
  * PHP sessions to store user ids and access tokens.
23
  */
24
- class Facebook extends BaseFacebook
25
  {
26
  const FBSS_COOKIE_NAME = 'fbss';
27
 
14
  * License for the specific language governing permissions and limitations
15
  * under the License.
16
  */
17
+ if(!class_exists('FacebookApiException'))
18
+ require_once "base_facebook.php";
19
 
20
  /**
21
  * Extends the BaseFacebook class with the intent of using
22
  * PHP sessions to store user ids and access tokens.
23
  */
24
+ class Sigami_Facebook extends BaseFacebook
25
  {
26
  const FBSS_COOKIE_NAME = 'fbss';
27
 
lib/js/fb.js CHANGED
@@ -1,14 +1,12 @@
1
  jQuery(document).ready(function() {
2
  jQuery.ajaxSetup({ cache: true });
3
  var script_name = '//connect.facebook.net/'+ WEF.local +'/all.js';
4
- if(WEF.fb_root !== 'false'){
5
- jQuery.getScript(script_name, function(){
6
- FB.init({
7
- appId: WEF.fb_id,
8
- status: true,
9
- cookie: true,
10
- xfbml: true
11
- });
12
- });
13
- }
14
  });
1
  jQuery(document).ready(function() {
2
  jQuery.ajaxSetup({ cache: true });
3
  var script_name = '//connect.facebook.net/'+ WEF.local +'/all.js';
4
+ jQuery.getScript(script_name, function(){
5
+ FB.init({
6
+ appId: WEF.fb_id,
7
+ status: true,
8
+ cookie: true,
9
+ xfbml: true
10
+ });
11
+ });
 
 
12
  });
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: poxtron
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=R8Q85GT3Q8Q26
4
  Tags: Facebook, facebook, Social Plugins, embed facebook, facebook video, facebook posts, facebook publication, facebook publications, facebook event, facebook events, facebook pages, facebook page, facebook profiles, facebook album, facebook albums, facebook photos, facebook photo, social,
5
  Requires at least: 3.8.1
6
- Tested up to: 4.1.1
7
- Stable tag: 1.8.3
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -60,7 +60,7 @@ width and raw are optional, raw only works for videos and photos
60
 
61
  = Wny I can only see "Embedded post will show on publish" ? =
62
 
63
- It is possible that another plugin or your theme already has the Facebook SDK for javascript. Disable the enqueue of the script on the advanced options
64
 
65
  = Is there a way to embed an album with more than 100 photos ? =
66
 
@@ -79,6 +79,14 @@ The embedded post code comes directly from facebook so there is no easy way to c
79
 
80
  == Changelog ==
81
 
 
 
 
 
 
 
 
 
82
  = 1.8.3 =
83
  * Better Video Embeds
84
 
@@ -164,5 +172,10 @@ The embedded post code comes directly from facebook so there is no easy way to c
164
 
165
  == Upgrade Notice ==
166
 
167
- = 1.8.3 =
168
- Better video embeds
 
 
 
 
 
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=R8Q85GT3Q8Q26
4
  Tags: Facebook, facebook, Social Plugins, embed facebook, facebook video, facebook posts, facebook publication, facebook publications, facebook event, facebook events, facebook pages, facebook page, facebook profiles, facebook album, facebook albums, facebook photos, facebook photo, social,
5
  Requires at least: 3.8.1
6
+ Tested up to: 4.2
7
+ Stable tag: 1.9
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
60
 
61
  = Wny I can only see "Embedded post will show on publish" ? =
62
 
63
+ It is possible that another plugin or your theme already has the Facebook SDK for javascript. Disable the enqueue of the script on the advanced options and test, if this does not work create a new thread on the support forum, with a link.
64
 
65
  = Is there a way to embed an album with more than 100 photos ? =
66
 
79
 
80
  == Changelog ==
81
 
82
+ = 1.9 =
83
+ * Facebook video embed code in case video type is not supported
84
+ * Fix: Compatibility with other facebook plugins thanks to ozzWANTED
85
+ * New filter: 'wpemfb_api_string' and 'wpemfb_2nd_api_string'
86
+ * Show embedded posts on admin
87
+ * Fix undefined variable on js
88
+ * Fix languages on event time
89
+
90
  = 1.8.3 =
91
  * Better Video Embeds
92
 
172
 
173
  == Upgrade Notice ==
174
 
175
+ = 1.9 =
176
+ * Facebook video embed code in case video type is not supported
177
+ * Fix: Compatibility with other facebook plugins thanks to ozzWANTED
178
+ * New filters: 'wpemfb_api_string' and 'wpemfb_2nd_api_string'
179
+ * Show embedded posts on admin
180
+ * Fix undefined variable on js
181
+ * Fix languages on event time
templates/classic/event.php CHANGED
@@ -5,32 +5,35 @@
5
  */
6
  ?>
7
  <?php
8
- $start_time_format = !empty($fb_data['is_date_only']) ? '%e %b %Y' : '%e %b %Y %l:%M %P';
9
- $start_time = strtotime($fb_data['start_time']) + get_option('gmt_offset')*3600; //shows event date on local time
 
 
 
10
  ?>
11
  <div class="wpemfb-container" style="min-width:<?php echo $width ?>px">
12
 
13
- <div class="wpemfb-info">
14
- <div class="wpemfb-pic">
15
- <a href="http://www.facebook.com/<?php echo $fb_data['id'] ?>" target="_blank" rel="nofollow">
16
- <img src="http://graph.facebook.com/<?php echo $fb_data['id'] ?>/picture" />
17
- </a>
18
- </div>
19
- <div class="wpemfb-desc">
20
- <h4 class="wpemfb-title" >
21
- <a href="http://www.facebook.com/<?php echo $fb_data['id'] ?>" target="_blank" rel="nofollow">
22
- <?php echo $fb_data['name'] ?>
23
- </a>
24
- </h4>
25
- <?php echo strftime($start_time_format, $start_time ) ?><br>
26
- <?php
27
- if(isset($fb_data['venue']['id'])){
28
- echo '<a href="http://www.facebook.com/'.$fb_data['venue']['id'].'" target="_blank">'.$fb_data['location'].'</a>';
29
- } else {
30
- echo $fb_data['location'];
31
- } ?>
32
- <br>
33
- <?php echo __('Creator: ', 'wp-embed-facebook').'<a href="http://www.facebook.com/'.$fb_data['owner']['id'].'" target="_blank">'.$fb_data['owner']['name'].'</a>' ?>
34
- </div>
35
- </div>
36
  </div>
5
  */
6
  ?>
7
  <?php
8
+ $start_time_format = !empty($fb_data['is_date_only']) ? 'l, j F Y' : 'l, j F Y g:s a';
9
+ $start_time = strtotime($fb_data['start_time']);
10
+ if (get_site_option('wpemfb_ev_local_tz', 'true') == 'true') {
11
+ $start_time = $start_time + get_option('gmt_offset') * 3600; //shows event date on local time
12
+ }
13
  ?>
14
  <div class="wpemfb-container" style="min-width:<?php echo $width ?>px">
15
 
16
+ <div class="wpemfb-info">
17
+ <div class="wpemfb-pic">
18
+ <a href="http://www.facebook.com/<?php echo $fb_data['id'] ?>" target="_blank" rel="nofollow">
19
+ <img src="http://graph.facebook.com/<?php echo $fb_data['id'] ?>/picture" />
20
+ </a>
21
+ </div>
22
+ <div class="wpemfb-desc">
23
+ <h4 class="wpemfb-title" >
24
+ <a href="http://www.facebook.com/<?php echo $fb_data['id'] ?>" target="_blank" rel="nofollow">
25
+ <?php echo $fb_data['name'] ?>
26
+ </a>
27
+ </h4>
28
+ <?php echo date_i18n($start_time_format, $start_time) ?><br>
29
+ <?php
30
+ if(isset($fb_data['venue']['id'])){
31
+ echo '<a href="http://www.facebook.com/'.$fb_data['venue']['id'].'" target="_blank">'.$fb_data['location'].'</a>';
32
+ } else {
33
+ echo $fb_data['location'];
34
+ } ?>
35
+ <br>
36
+ <?php echo __('Creator: ', 'wp-embed-facebook').'<a href="http://www.facebook.com/'.$fb_data['owner']['id'].'" target="_blank">'.$fb_data['owner']['name'].'</a>' ?>
37
+ </div>
38
+ </div>
39
  </div>
templates/classic/video.php CHANGED
@@ -4,21 +4,27 @@
4
  * to access all fb data print_r($fb_data)
5
  */
6
  ?>
7
- <?php
8
- $url = $fb_data['source'];
9
- $file_array = explode('/',parse_url($url, PHP_URL_PATH));
10
- $file = end($file_array);
11
- $type_array = explode('.',$file);
12
- $type = end($type_array);
13
- $clean_type = strtolower($type);
14
- if( $clean_type == 'mp4' || $clean_type == 'webm' || $clean_type == 'ogg') :?>
 
 
15
 
16
- <video width="<?php echo $width ?>" height="280px" controls>
17
- <source src="<?php echo $fb_data['source'] ?>" type="video/<?php echo $clean_type ?>">
18
- </video>
19
 
20
- <?php else : ?>
21
 
22
- <iframe src="https://www.facebook.com/video/embed?video_id=<?php echo $fb_data['id'] ?>" width="<?php echo $width ?>" height="280px"></iframe>
 
 
23
 
24
- <?php endif; ?>
 
 
4
  * to access all fb data print_r($fb_data)
5
  */
6
  ?>
7
+ <div style="width: <?php echo $width ?>px">
8
+ <div class="wpemfb-video">
9
+ <?php
10
+ $url = $fb_data['source'];
11
+ $file_array = explode('/',parse_url($url, PHP_URL_PATH));
12
+ $file = end($file_array);
13
+ $type_array = explode('.',$file);
14
+ $type = end($type_array);
15
+ $clean_type = strtolower($type);
16
+ if( $clean_type == 'mp4' ) :?>
17
 
18
+ <video controls>
19
+ <source src="<?php echo $fb_data['source'] ?>" type="video/<?php echo $clean_type ?>">
20
+ </video>
21
 
22
+ <?php else : ?>
23
 
24
+ <div class="fb-video" data-allowfullscreen="true"
25
+ data-href="https://www.facebook.com/video/embed?video_id=<?php echo $fb_data['id'] ?>">
26
+ </div>
27
 
28
+ <?php endif; ?>
29
+ </div>
30
+ </div>
templates/classic/wpemfb.css CHANGED
@@ -86,4 +86,28 @@
86
  border: none !important;
87
  font-weight: normal !important;
88
  text-decoration: none !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  }
86
  border: none !important;
87
  font-weight: normal !important;
88
  text-decoration: none !important;
89
+ }
90
+
91
+ /**
92
+ * Video Embed
93
+ */
94
+ .wpemfb-video {
95
+ position: relative;
96
+ display: block;
97
+ height: 0;
98
+ padding: 0 0 56.25%;
99
+ overflow: hidden;
100
+ }
101
+ .wpemfb-video .wpemfb-video-item,
102
+ .wpemfb-video iframe,
103
+ .wpemfb-video embed,
104
+ .wpemfb-video object,
105
+ .wpemfb-video video {
106
+ position: absolute;
107
+ top: 0;
108
+ left: 0;
109
+ bottom: 0;
110
+ height: 100%;
111
+ width: 100%;
112
+ border: 0;
113
  }
templates/default/album.php CHANGED
@@ -3,7 +3,6 @@
3
  * You can create your own template by placing a copy of this file on yourtheme/plugins/wp-embed-fb/
4
  * to access all fb data print_r($fb_data)
5
  */
6
- $width = $width;
7
  ?>
8
  <div class="wpemfb-container" style="max-width: <?php echo $width ?>px">
9
  <div class="wpemfb-row">
3
  * You can create your own template by placing a copy of this file on yourtheme/plugins/wp-embed-fb/
4
  * to access all fb data print_r($fb_data)
5
  */
 
6
  ?>
7
  <div class="wpemfb-container" style="max-width: <?php echo $width ?>px">
8
  <div class="wpemfb-row">
templates/default/event.php CHANGED
@@ -3,37 +3,38 @@
3
  * You can create your own template by placing a copy of this file on yourtheme/plugins/wp-embed-fb/
4
  * to access all fb data print_r($fb_data)
5
  */
6
- $height = $width * $prop;
7
- $start_time_format = !empty($fb_data['is_date_only']) ? '%e %b %Y' : '%e %b %Y %l:%M %P';
8
- $start_time = strtotime($fb_data['start_time']) + get_option('gmt_offset')*3600; //shows event date on local time
 
 
 
9
  ?>
10
- <?php //Events have now covers but are not pulled from default request, maybe this will change in time. ?>
11
-
12
- <div class="wpemfb-container" style="max-width: <?php echo $width ?>px" >
13
- <?php do_action('wpemfb_event',$height,$fb_data); ?>
14
- <div class="wpemfb-row wpemfb-pad-top">
15
- <div class="wpemfb-col-3 wpemfb-text-center">
16
- <a href="http://www.facebook.com/<?php echo $fb_data['id'] ?>" target="_blank" rel="nofollow">
17
- <img src="http://graph.facebook.com/<?php echo $fb_data['id'] ?>/picture/large" />
18
- </a>
19
- </div>
20
- <div class="wpemfb-col-9 wpemfb-pl-none">
21
- <a class="wpemfb-title" href="http://www.facebook.com/<?php echo $fb_data['id'] ?>" target="_blank" rel="nofollow">
22
- <?php echo $fb_data['name'] ?>
23
- </a>
24
- <br>
25
- <?php echo strftime($start_time_format, $start_time ) ?>
26
- <br>
27
- <?php
28
- if(isset($fb_data['venue']['id'])){
29
- _e('@ ', 'wp-embed-facebook');
30
- echo '<a href="http://www.facebook.com/'.$fb_data['venue']['id'].'" target="_blank">'.$fb_data['location'].'</a>';
31
- } else {
32
- echo isset($fb_data['location']) ? __('@ ', 'wp-embed-facebook') . $fb_data['location'] : '';
33
- }
34
- ?>
35
- <br>
36
- <?php echo __('Creator: ', 'wp-embed-facebook').'<a href="http://www.facebook.com/'.$fb_data['owner']['id'].'" target="_blank">'.$fb_data['owner']['name'].'</a>' ?>
37
- </div>
38
- </div>
39
  </div>
3
  * You can create your own template by placing a copy of this file on yourtheme/plugins/wp-embed-fb/
4
  * to access all fb data print_r($fb_data)
5
  */
6
+ $height = $width * $prop;
7
+ $start_time_format = !empty($fb_data['is_date_only']) ? 'l, j F Y' : 'l, j F Y g:s a';
8
+ $start_time = strtotime($fb_data['start_time']);
9
+ if (get_site_option('wpemfb_ev_local_tz', 'true') == 'true') {
10
+ $start_time = $start_time + get_option('gmt_offset') * 3600; //shows event date on local time
11
+ }
12
  ?>
13
+ <div class="wpemfb-container" style="max-width: <?php echo $width ?>px">
14
+ <div class="wpemfb-row wpemfb-pad-top">
15
+ <div class="wpemfb-col-3 wpemfb-text-center">
16
+ <a href="http://www.facebook.com/<?php echo $fb_data['id'] ?>" target="_blank" rel="nofollow">
17
+ <img src="http://graph.facebook.com/<?php echo $fb_data['id'] ?>/picture/large"/>
18
+ </a>
19
+ </div>
20
+ <div class="wpemfb-col-9 wpemfb-pl-none">
21
+ <a class="wpemfb-title" href="http://www.facebook.com/<?php echo $fb_data['id'] ?>" target="_blank"
22
+ rel="nofollow">
23
+ <?php echo $fb_data['name'] ?>
24
+ </a>
25
+ <br>
26
+ <?php echo date_i18n($start_time_format, $start_time) ?>
27
+ <br>
28
+ <?php
29
+ if (isset($fb_data['venue']['id'])) {
30
+ _e('@ ', 'wp-embed-facebook');
31
+ echo '<a href="http://www.facebook.com/' . $fb_data['venue']['id'] . '" target="_blank">' . $fb_data['location'] . '</a>';
32
+ } else {
33
+ echo isset($fb_data['location']) ? __('@ ', 'wp-embed-facebook') . $fb_data['location'] : '';
34
+ }
35
+ ?>
36
+ <br>
37
+ <?php echo __('Creator: ', 'wp-embed-facebook') . '<a href="http://www.facebook.com/' . $fb_data['owner']['id'] . '" target="_blank">' . $fb_data['owner']['name'] . '</a>' ?>
38
+ </div>
39
+ </div>
 
 
40
  </div>
templates/default/page.php CHANGED
@@ -41,7 +41,7 @@
41
  <div style="float: right;"><?php WP_Embed_FB::like_btn($fb_data['id'],$fb_data['likes']) ?></div>
42
  </div>
43
  </div>
44
- <?php if($show_posts) : ?>
45
  <?php foreach($fb_data['posts']['data'] as $fbpost) : ?>
46
 
47
  <?php if(isset($fbpost['picture']) || isset($fbpost['message'])) : ?>
41
  <div style="float: right;"><?php WP_Embed_FB::like_btn($fb_data['id'],$fb_data['likes']) ?></div>
42
  </div>
43
  </div>
44
+ <?php if($show_posts && isset($fb_data['posts'])) : ?>
45
  <?php foreach($fb_data['posts']['data'] as $fbpost) : ?>
46
 
47
  <?php if(isset($fbpost['picture']) || isset($fbpost['message'])) : ?>
templates/default/page_old.php DELETED
@@ -1,73 +0,0 @@
1
- <?php
2
- /*
3
- * You can create your own template by placing a copy of this file on yourtheme/plugins/wp-embed-fb/
4
- * to access all fb data print_r($fb_data)
5
- */
6
- $width_out = $width;
7
- $width = $width_out - 10;
8
- $height = $width * $prop;
9
- $show_posts = get_option("wpemfb_show_posts") == "true" ? true : false;
10
- //$wp_emb_fbsdk = WP_Embed_FB::$fbsdk;
11
- ?>
12
- <div class="wpemfb-border" style="max-width: <?php echo $width ?>px">
13
- <div class="wpemfb-table">
14
- <div class="wpemfb-cell">
15
- <div class="wpemfb-cover"
16
- style= "
17
- height: <?php echo $height ?>px;
18
- background-image: url(<?php echo $fb_data['cover']['source'] ?>);
19
- background-position: 0% <?php echo $fb_data['cover']['offset_y'] ?>%;
20
- " onclick="window.open('<?php echo $fb_data['link'] ?>', '_blank')" >
21
- </div>
22
- </div>
23
- </div>
24
- <div class="wpemfb-table">
25
- <div class="wpemfb-cell-left">
26
- <a href="<?php echo $fb_data['link'] ?>" target="_blank" rel="nofollow">
27
- <img src="http://graph.facebook.com/<?php echo $fb_data['id'] ?>/picture" width="50px" height="50px" />
28
- </a>
29
- </div>
30
- <div class="wpemfb-cell-right">
31
- <a class="wpemfb-title wpemfb-clean-link" href="<?php echo $fb_data['link'] ?>" target="_blank" rel="nofollow">
32
- <?php echo $fb_data['name'] ?>
33
- </a>
34
- <br>
35
- <?php
36
- if($fb_data['category'] == 'Musician/band'){
37
- echo isset($fb_data['genre']) ? $fb_data['genre'] : '';
38
- } else {
39
- _e($fb_data['category'],'wp-embed-facebook');
40
- }
41
- ?><br>
42
- <?php if(isset($fb_data["website"])) : ?>
43
- <a class="wpemfb-clean-link wpemfb-color" href="<?php echo WP_Embed_FB::getwebsite($fb_data["website"]) ?>" title="<?php _e('Web Site', 'wp-embed-facebook') ?>" target="_blank">
44
- <?php _e('Web Site','wp-embed-facebook') ?>
45
- </a>
46
- <?php endif; ?>
47
- <div style="float: right;"><?php WP_Embed_FB::like_btn($fb_data['id'],$fb_data['likes']) ?></div>
48
- </div>
49
- </div>
50
- <?php if($show_posts) : ?>
51
- <br>
52
- <?php foreach($fb_data['posts']['data'] as $fbpost) : ?>
53
- <?php $link = explode("_", $fbpost['id']) ?>
54
- <div class="wpemfb-posts-table">
55
- <?php if(isset($fbpost['picture'])) : ?>
56
- <div class="wpemfb-cell-left">
57
- <a class="wpemfb-clean-link" href="<?php echo "https://www.facebook.com/".$link[0]."/posts/".$link[1] ?>" target="_blank" rel="nofollow">
58
- <img src="<?php echo $fbpost['picture'] ?>" width="70px" height"70px" />
59
- </a>
60
- </div>
61
- <?php endif; ?>
62
- <div class="wpemfb-cell-right">
63
- <span class="wpemfb-page-post"><?php echo make_clickable($fbpost['message']) ?></span>
64
- <a class="wpemfb-post-link wpemfb-clean-link" href="<?php echo "https://www.facebook.com/".$link[0]."/posts/".$link[1] ?> " target="_blank" rel="nofollow">
65
- <?php echo isset($fbpost['likes']) ? '<img src="https://fbstatic-a.akamaihd.net/rsrc.php/v2/y6/r/l9Fe9Ugss0S.gif" />'.$fbpost['likes']['summary']['total_count'].' ' : "" ?>
66
- <?php echo isset($fbpost['comments']) ? '<img src="https://fbstatic-a.akamaihd.net/rsrc.php/v2/yg/r/V8Yrm0eKZpi.gif" />'.$fbpost['comments']['summary']['total_count'].' ' : "" ?>
67
- <?php echo isset($fbpost['shares']) ? '<img src="https://fbstatic-a.akamaihd.net/rsrc.php/v2/y2/r/o19N6EzzbUm.png" />'.$fbpost['shares']['count'].' ' : "" ?>
68
- </a>
69
- </div>
70
- </div>
71
- <?php endforeach; ?>
72
- <?php endif; ?>
73
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/default/posts.php CHANGED
@@ -1,4 +1,3 @@
1
  <div class="wpemfb-container wpemfb-mesure" style="position:absolute; max-width: <?php echo $width ?>px;"></div>
2
  <div class="fb-post" data-href="https://www.facebook.com/<?php echo $fb_data['link'] ?>" data-width="<?php echo $width ?>">
3
- <?php _e('Embedded post will show on publish', 'wp-embed-facebook'); ?>
4
  </div>
1
  <div class="wpemfb-container wpemfb-mesure" style="position:absolute; max-width: <?php echo $width ?>px;"></div>
2
  <div class="fb-post" data-href="https://www.facebook.com/<?php echo $fb_data['link'] ?>" data-width="<?php echo $width ?>">
 
3
  </div>
templates/default/video.php CHANGED
@@ -4,21 +4,27 @@
4
  * to access all fb data print_r($fb_data)
5
  */
6
  ?>
7
- <?php
8
- $url = $fb_data['source'];
9
- $file_array = explode('/',parse_url($url, PHP_URL_PATH));
10
- $file = end($file_array);
11
- $type_array = explode('.',$file);
12
- $type = end($type_array);
13
- $clean_type = strtolower($type);
14
- if( $clean_type == 'mp4' || $clean_type == 'webm' || $clean_type == 'ogg') :?>
 
 
15
 
16
- <video width="<?php echo $width ?>" height="280px" controls>
17
- <source src="<?php echo $fb_data['source'] ?>" type="video/<?php echo $clean_type ?>">
18
- </video>
19
 
20
- <?php else : ?>
21
 
22
- <iframe src="https://www.facebook.com/video/embed?video_id=<?php echo $fb_data['id'] ?>" width="<?php echo $width ?>" height="280px"></iframe>
 
 
23
 
24
- <?php endif; ?>
 
 
4
  * to access all fb data print_r($fb_data)
5
  */
6
  ?>
7
+ <div style="width: <?php echo $width ?>px">
8
+ <div class="wpemfb-video">
9
+ <?php
10
+ $url = $fb_data['source'];
11
+ $file_array = explode('/',parse_url($url, PHP_URL_PATH));
12
+ $file = end($file_array);
13
+ $type_array = explode('.',$file);
14
+ $type = end($type_array);
15
+ $clean_type = strtolower($type);
16
+ if( $clean_type == 'mp4' ) :?>
17
 
18
+ <video controls>
19
+ <source src="<?php echo $fb_data['source'] ?>" type="video/<?php echo $clean_type ?>">
20
+ </video>
21
 
22
+ <?php else : ?>
23
 
24
+ <div class="fb-video" data-allowfullscreen="true"
25
+ data-href="https://www.facebook.com/video/embed?video_id=<?php echo $fb_data['id'] ?>">
26
+ </div>
27
 
28
+ <?php endif; ?>
29
+ </div>
30
+ </div>
templates/default/wpemfb.css CHANGED
@@ -141,4 +141,28 @@ a.wpemfb-post-link{
141
  margin: 1px;
142
  padding: 2px;
143
  width: 60px !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  }
141
  margin: 1px;
142
  padding: 2px;
143
  width: 60px !important;
144
+ }
145
+
146
+ /**
147
+ * Video Embed
148
+ */
149
+ .wpemfb-video {
150
+ position: relative;
151
+ display: block;
152
+ height: 0;
153
+ padding: 0 0 56.25%;
154
+ overflow: hidden;
155
+ }
156
+ .wpemfb-video .wpemfb-video-item,
157
+ .wpemfb-video iframe,
158
+ .wpemfb-video embed,
159
+ .wpemfb-video object,
160
+ .wpemfb-video video {
161
+ position: absolute;
162
+ top: 0;
163
+ left: 0;
164
+ bottom: 0;
165
+ height: 100%;
166
+ width: 100%;
167
+ border: 0;
168
  }
wp-embed-facebook.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: WP Embed Facebook
4
  Plugin URI: http://www.wpembedfb.com
5
  Description: Embed a Facebook video, photo, album, event, page, profile, or post. Copy any facebook url to a single line on your post, or use shortcode [facebook='url' width='' ] more info at <a href="http://www.wpembedfb.com" title="plugin website">www.wpembedfb.com</a>
6
  Author: Miguel Sirvent
7
- Version: 1.8.3
8
  Author URI: http://profiles.wordpress.org/poxtron/
9
  */
10
 
@@ -25,9 +25,9 @@ register_uninstall_hook(__FILE__, array('WP_Embed_FB', 'uninstall') );
25
  register_deactivation_hook(__FILE__, array('WP_Embed_FB', 'deactivate'));
26
  add_action('init',array('WP_Embed_FB','init'),1);
27
  add_action('wp_enqueue_scripts', array('WP_Embed_FB', 'wp_enqueue_scripts') );
28
- add_filter('the_content', array('WP_Embed_FB','the_content'),10,2);
29
  add_shortcode('facebook', array('WP_Embed_FB','shortcode') );
30
- add_action('plugins_loaded',array('WP_Embed_FB','plugins_loaded'));
31
  //optional filter to content anonymous function
32
  if( get_option('wpemfb_fb_root') === 'true' ){
33
  add_filter('the_content', array('WP_Embed_FB','fb_root'),10,1);
@@ -35,14 +35,52 @@ if( get_option('wpemfb_fb_root') === 'true' ){
35
 
36
  // wp-admin functions
37
 
 
 
 
 
 
 
 
 
 
38
  if(is_admin()){
39
  require_once WPEMFBDIR.'lib/admin.php';
40
  add_action('admin_menu', array('EmbFbAdmin','add_page'));
41
  add_action( 'admin_enqueue_scripts', array('EmbFbAdmin','admin_enqueue_scripts'), 10,1);
42
  add_action( 'admin_init', array('EmbFbAdmin','admin_init'));
43
  }
 
 
 
 
 
44
  //TODO: show like buttons on tiny mce
45
  //add_action( 'after_wp_tiny_mce', 'custom_after_wp_tiny_mce' );
46
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
  ?>
4
  Plugin URI: http://www.wpembedfb.com
5
  Description: Embed a Facebook video, photo, album, event, page, profile, or post. Copy any facebook url to a single line on your post, or use shortcode [facebook='url' width='' ] more info at <a href="http://www.wpembedfb.com" title="plugin website">www.wpembedfb.com</a>
6
  Author: Miguel Sirvent
7
+ Version: 1.9
8
  Author URI: http://profiles.wordpress.org/poxtron/
9
  */
10
 
25
  register_deactivation_hook(__FILE__, array('WP_Embed_FB', 'deactivate'));
26
  add_action('init',array('WP_Embed_FB','init'),1);
27
  add_action('wp_enqueue_scripts', array('WP_Embed_FB', 'wp_enqueue_scripts') );
28
+ wp_embed_register_handler("wpembedfb","/(http|https):\/\/www\.facebook\.com\/([^<\s]*)/",array("WP_Embed_FB","embed_register_handler"));
29
  add_shortcode('facebook', array('WP_Embed_FB','shortcode') );
30
+ add_action('plugins_loaded',array('WP_Embed_FB','plugins_loaded'),99);
31
  //optional filter to content anonymous function
32
  if( get_option('wpemfb_fb_root') === 'true' ){
33
  add_filter('the_content', array('WP_Embed_FB','fb_root'),10,1);
35
 
36
  // wp-admin functions
37
 
38
+ //Filters all in core
39
+
40
+ //wpemfb_embed_type
41
+ //wpemfb_api_string
42
+ //wpemfb_2nd_api_string
43
+ //wpemfb_category_template
44
+ //wpemfb_template
45
+
46
+
47
  if(is_admin()){
48
  require_once WPEMFBDIR.'lib/admin.php';
49
  add_action('admin_menu', array('EmbFbAdmin','add_page'));
50
  add_action( 'admin_enqueue_scripts', array('EmbFbAdmin','admin_enqueue_scripts'), 10,1);
51
  add_action( 'admin_init', array('EmbFbAdmin','admin_init'));
52
  }
53
+
54
+
55
+
56
+
57
+
58
  //TODO: show like buttons on tiny mce
59
  //add_action( 'after_wp_tiny_mce', 'custom_after_wp_tiny_mce' );
60
+ //add_action( 'after_wp_tiny_mce', 'custom_after_wp_tiny_mce' );
61
+ //function custom_after_wp_tiny_mce() {
62
+ //echo '
63
+ // <script type="text/javascript">
64
+ // jQuery.ajaxPrefilter(function(options, _, jqXHR) {
65
+ // jqXHR.complete(function() {
66
+ // window.fbAsyncInit = function() {
67
+ // FB.init({
68
+ // appId : "' . get_option('wpemfb_app_id') . '",
69
+ // xfbml : true,
70
+ // version : "v2.3"
71
+ // });
72
+ // };
73
+ // (function(d, s, id){
74
+ // var js, fjs = d.getElementsByTagName(s)[0];
75
+ // if (d.getElementById(id)) {return;}
76
+ // js = d.createElement(s); js.id = id;
77
+ // js.src = "//connect.facebook.net/' . get_locale() . '/sdk.js";
78
+ // fjs.parentNode.insertBefore(js, fjs);
79
+ // }(document, "script", "facebook-jssdk"));
80
+ // });
81
+ // });
82
+ // </script>
83
+ //';
84
+ //}
85
 
86
  ?>