/[drupal]/contributions/modules/fb/fb_connect.module
ViewVC logotype

Contents of /contributions/modules/fb/fb_connect.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.31 - (show annotations) (download) (as text)
Tue Oct 27 21:03:10 2009 UTC (4 weeks, 4 days ago) by yogadex
Branch: MAIN
Changes since 1.30: +23 -6 lines
File MIME type: text/x-php
#614392 by vectoroc; support for http://wiki.developers.facebook.com/index.php/Facebook_Connect_Via_SSL
1 <?php
2
3 /**
4 * @file
5 * Support for Facebook Connect features
6 *
7 * Note that Facebook connect will work properly only with themes that are
8 * Facebook Connect aware.
9 */
10 function fb_connect_menu() {
11 $items = array();
12
13 // Cross-domain receiver.
14 $items['fb_connect/receiver'] = array(
15 'page callback' => 'fb_connect_receiver',
16 'type' => MENU_CALLBACK,
17 'access callback' => TRUE,
18 );
19
20 // Ajax helper
21 $items['fb_connect/js'] = array(
22 'page callback' => 'fb_connect_js_cb',
23 'type' => MENU_CALLBACK,
24 'access callback' => TRUE,
25 );
26
27 return $items;
28 }
29
30 function fb_connect_js_cb() {
31 $extra = fb_invoke(FB_OP_CONNECT_JS_INIT, $data, array());
32 $extra_js = implode("\n", $extra);
33 print $extra_js;
34 exit();
35 }
36
37 /**
38 * Without a receiver file, cross-domain javascript will not work.
39 *
40 * In their infinite wisdom, facebook has decreed that the URL for
41 * this static page be in the same place as the app's callback URL.
42 * So we have to make a Drupal callback for what would otherwise be a
43 * simple file.
44 *
45 * Supports SSL, http://wiki.developers.facebook.com/index.php/Facebook_Connect_Via_SSL.
46 */
47 function fb_connect_receiver() {
48 global $facebook_config;
49
50 $src_suffix = $facebook_config['debug']
51 ? '.debug'
52 : '' ;
53
54 $src = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on')
55 ? "https://ssl.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver$src_suffix.js"
56 : "http://static.ak.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver$src_suffix.js" ;
57
58 $output = <<<HTML
59 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
60 <html xmlns="http://www.w3.org/1999/xhtml" >
61 <body>
62 <!-- Drupal for Facebook cross-domain receiver. -->
63 <!-- http://wiki.developers.facebook.com/index.php/Cross_Domain_Communication_Channel -->
64 <script src="$src" type="text/javascript"></script>
65 </body>
66 </html>
67 HTML;
68 print $output;
69 die(); // prevent Drupal from writing anything else.
70 }
71
72 /**
73 * Returns an apikey, if the current page has facebook connect enabled.
74 */
75 function fb_connect_current_apikey() {
76 // TODO: return false on canvas pages
77 if ($GLOBALS['fb_connect_apikey'])
78 // Learned apikey from cookies.
79 return $GLOBALS['fb_connect_apikey'];
80 else if ($apikey = variable_get('fb_connect_primary_apikey', NULL)) {
81 // Primary connect app.
82 return $apikey;
83 }
84 }
85
86 /**
87 * Prepare for fbConnect use. Because a single Drupal might support
88 * multiple apps, we don't know in advance which is the fbConnect app.
89 * Theoretically, it might be possible to simultaneously use multiple
90 * apps and fbConnect, but my suspicion is facebook would throw a
91 * total hissy-fit if you tried.
92 */
93 function fb_connect_app_init($fb_app) {
94 if ($fb = fb_api_init($fb_app, FB_FBU_CURRENT)) {
95 $fbu = $fb->get_loggedin_user();
96 // TODO: sometimes this method indicates we are logged in when we really are not. Find a way to verify.
97 if ($fbu) {
98 // The user has authorized the app and we now know something about them. Use a hook to trigger the actions of other modules.
99 fb_invoke(FB_OP_APP_IS_AUTHORIZED, array('fbu' => $fbu,
100 'fb_app' => $fb_app,
101 'fb' => $fb));
102 }
103
104 // Store state in session
105 if (!$_SESSION['fb_connect']) {
106 $_SESSION['fb_connect'] = array();
107 }
108 $_SESSION['fb_connect'][$fb_app->apikey] = $fbu;
109
110 return $fb;
111 }
112 }
113
114 /**
115 * Are we already logged in to fbConnect?
116 */
117 function fb_connect_already_loggedin($fb_app) {
118 if ($_SESSION['fb_connect'])
119 return $_SESSION['fb_connect'][$fb_app->apikey];
120
121 return FALSE;
122 }
123
124 /**
125 * Which apps are fbConnect enabled?
126 */
127 function fb_connect_enabled_apps() {
128 // We do a bit of work for each enabled app, so really we want to restrict this list to only apps which have been "turned on".
129 // But for now we're lazy and just get the list of all apps.
130 $apps = fb_get_all_apps();
131 return $apps;
132 }
133
134 /**
135 * Implementation of hook_fb().
136 */
137 function fb_connect_fb($op, $data, &$return) {
138 //dpm(func_get_args(), "fb_connect_fb($op)");
139 if ($op == FB_OP_CURRENT_APP && !$return) {
140 // This will cause fb.module to set the global $fb when user is logged in via fbConnect.
141 if ($apikey = variable_get('fb_connect_primary_apikey', NULL)) {
142 $return = fb_get_app(array('apikey' => $apikey));
143 }
144 }
145 else if ($op == FB_OP_POST_INIT) {
146 if ($apikey = variable_get('fb_connect_primary_apikey', NULL)) {
147 if ($data['fb_app']->apikey == $apikey) {
148 // Init Facebook javascript for primary app
149 _fb_connect_add_js();
150 fb_connect_require_feature('XFBML', $fb_app);
151 // fb_connect_init_option('reloadIfSessionStateChanged', TRUE, $fb_app);
152 fb_connect_init_option('ifUserConnected', "{FB_Connect.on_connected}", $fb_app);
153 fb_connect_init_option('ifUserNotConnected', "{FB_Connect.on_not_connected}", $fb_app);
154 }
155 }
156 }
157 else if ($op == FB_OP_CONNECT_JS_INIT) {
158 foreach (fb_connect_init_js() as $js) {
159 $return[] = $js;
160 }
161 }
162 else if ($op == FB_OP_SET_PROPERTIES) {
163 // We need to set the Facebook Connect URL, but currently Facebook's APIs do not allow it.
164 $return['connect_url'] = fb_connect_get_connect_url($data['fb_app']);
165 }
166 else if ($op == FB_OP_LIST_PROPERTIES) {
167 $return[t('Connect URL')] = 'connect_url';
168 }
169
170 }
171
172 function _fb_connect_add_js() {
173 static $just_once;
174 if (!isset($just_once)) {
175 $base = drupal_get_path('module', 'fb_connect');
176 if (isset($GLOBALS['fb_connect_apikey'])) {
177 // If here, fb connect cookies are set.
178 $fbu = $_COOKIE[$GLOBALS['fb_connect_apikey'] . "_user"];
179 }
180 drupal_add_js(array('fb_connect' => array(
181 'front_url' => url('<front>'),
182 'fbu' => $fbu,
183 ),
184 ), 'setting');
185 drupal_add_js($base . '/fb_connect.js');
186 $just_once = TRUE;
187 }
188 }
189
190 /**
191 * Implementation of hook_user
192 *
193 * On logout, redirect the user so facebook can expire their session.
194 * Should be a facebook API to do this, but there's none I know of.
195 */
196 function fb_connect_user($op, &$edit, &$account, $category = NULL) {
197
198 if ($op == 'logout') {
199 $apps = fb_connect_enabled_apps();
200 foreach ($apps as $fb_app) {
201 try {
202 $fb = fb_api_init($fb_app, FB_FBU_CURRENT);
203
204 if ($fb && $fb->api_client->session_key) {
205 // Log out of facebook
206 $session_key = $fb->api_client->session_key;
207
208 // Figure out where to send the user.
209 if ($_REQUEST['destination']) {
210 $next = url($_REQUEST['destination'], array('absolute' => TRUE));
211 // It pains me to muck with $_REQUEST['destination'], but facebook's weak-ass API leaves us little choice.
212 unset($_REQUEST['destination']);
213 }
214 else {
215 $next = url('<front>', array('absolute' => TRUE));
216 }
217
218 // http://forum.developers.facebook.com/viewtopic.php?id=21879
219 // Use next parameter to expire session.
220 drupal_goto("http://www.facebook.com/logout.php?app_key={$fb_app->apikey}&session_key={$session_key}&next=" . $next);
221 }
222 } catch (Exception $e) {
223 fb_log_exception($e, t('Failed to log out of fbConnect session'));
224 }
225 }
226 }
227 }
228
229 function fb_connect_exit($url = NULL) {
230 if (isset($GLOBALS['fb_connect_logging_out'])) {
231 global $fb;
232 session_write_close(); // drupal_goto calls this, so why not us?
233 if (!isset($url))
234 $url = url('<front>', NULL, NULL, TRUE);
235 $fb->logout($url);
236 }
237 }
238
239 /**
240 * Allows other modules to specify which Facebook Connect features are
241 * required. This will affect how the FB_RequireFeatures javascript method is
242 * called.
243 */
244 function fb_connect_require_feature($feature = NULL, $fb_app = NULL) {
245 if ($feature && !isset($fb_app))
246 $fb_app = $GLOBALS['fb_app'];
247
248 // some features may apply without an app, but for now let's enforce that an app is required.
249 if ($feature && !$fb_app)
250 return;
251
252 static $features;
253 if (!$features)
254 $features = array();
255 if ($fb_app && !$features[$fb_app->apikey])
256 $features[$fb_app->apikey] = array('fb_app' => $fb_app,
257 'features' => array());
258 if ($feature)
259 $features[$fb_app->apikey]['features'][$feature] = $feature;
260 return $features;
261 }
262
263 /**
264 * Add an option when initializing facebook's javascript api.
265 */
266 function fb_connect_init_option($option = NULL, $value = NULL, $fb_app = NULL) {
267 if ($option && !isset($fb_app))
268 $fb_app = $GLOBALS['fb_app'];
269 if ($option && !$fb_app)
270 return;
271
272 static $options;
273 if (!$options)
274 $options = array();
275 if ($fb_app && !$options[$fb_app->apikey]) {
276 $options[$fb_app->apikey] = array();
277 }
278
279 if ($option)
280 $options[$fb_app->apikey][$option] = $value;
281 return $options;
282 }
283
284 /**
285 * Add javascript to a facebook connect page.
286 *
287 * Use this to add calls to facebook JS,
288 * http://wiki.developers.facebook.com/index.php/JS_API_Index.
289 *
290 * We use Drupal's cache to store the javascript until it is rendered
291 * to a page. This approach is analogous to drupal_set_message
292 * storing data temporarily in the session. We use cache instead of
293 * session, because the session is not shared between Facebook's event
294 * callbacks and regular page requests.
295 *
296 */
297 function fb_connect_init_js($js = NULL) {
298 $fbu = fb_facebook_user();
299 $fb_app = $GLOBALS['fb_app'];
300 $cid = 'fb_connect_init_js_' . $fb_app->apikey . '_' . $fbu;
301 $cache = cache_get($cid, 'cache');
302 if (!isset($cache->data)) {
303 $cache = new stdClass();
304 $cache->data = array();
305 }
306
307 if ($js) {
308 $cache->data[] = $js;
309 cache_set($cid, $cache->data, 'cache', time() + 60000); // Update cache
310 }
311 else if ($js === NULL) {
312 cache_clear_all($cid, 'cache');
313 }
314
315 return $cache->data;
316 }
317
318 /**
319 * Include facebook javascript in the footer of the current page.
320 */
321 function fb_connect_footer($is_front) {
322 // Do nothing on FBML pages
323 if (function_exists('fb_canvas_is_fbml') && fb_canvas_is_fbml())
324 return;
325
326 global $base_path;
327
328 $fb_feature_src = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on')
329 ? "https://ssl.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php"
330 : "http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php" ;
331
332 $feature_data = fb_connect_require_feature();
333 $option_data = fb_connect_init_option();
334
335 if (count($feature_data)) {
336 foreach ($feature_data as $data) {
337 // Give other modules a chance to add javascript which executes after init.
338 $extra = fb_invoke(FB_OP_CONNECT_JS_INIT, $data, array());
339 $extra_js = implode("\n", $extra);
340
341 $fb_app = $data['fb_app'];
342 $features = $data['features'];
343 $options = json_encode($option_data[$fb_app->apikey]);
344 // Hack! What's the way to json_encode a function name?
345 $options = str_replace('"{', '', $options);
346 $options = str_replace('}"', '', $options);
347
348 // drupal_add_js cannot add external javascript, so we use hook_footer instead.
349 $output = '<script src="'.$fb_feature_src.'" type="text/javascript"></script>';
350 $output .= "\n";
351 $feature_list = '["' . implode('","', $features) . '"]';
352 // Put together the URL for the receiver. The prefix must be identical to the apps connect URL.
353 $receiver = fb_connect_get_connect_url($fb_app) . "fb_connect/receiver";
354 $output .= "
355 <script type=\"text/javascript\">
356 $(document).ready(function() {
357 FB_RequireFeatures({$feature_list}, function () {
358
359 //FB.FBDebug.logLevel = 4;
360 //FB.FBDebug.isEnabled = true;
361
362 FB.init(\"{$fb_app->apikey}\", \"{$receiver}\", {$options});
363 });
364 });
365 ";
366 // Extra JS after successful fbConnect init.
367 $output .= "
368 FB.ensureInit(function()
369 {
370 FB_Connect.init();
371 {$extra_js}
372 });
373 ";
374
375 $output .= "
376 </script>\n";
377 }
378 }
379 return $output;
380 }
381
382
383 /**
384 * Convenience method to get an apps connect URL.
385 *
386 */
387 function fb_connect_get_connect_url($fb_app) {
388 // absolute URL with no rewriting applied
389 global $base_url;
390 $suffix = FB_SETTINGS_APP_NID . '/' . $fb_app->nid . '/';
391
392 // In regular pages, we need to add the suffix.
393 $url = $base_url . '/' . $suffix;
394
395 return $url;
396 }
397
398
399
400 function _fb_connect_block_login_defaults() {
401 return array('anon_not_connected' => array(
402 'title' => t('Facebook Connect'),
403 'body' => t('Facebook users login here. !button',
404 array('!button' => "<fb:login-button onclick='FB_Connect.login_onclick();'></fb:login-button>")),
405 ),
406 'user_not_connected' => array(
407 'title' => t('Facebook Connect'),
408 'body' => t('Link your account with Facebook. !button',
409 array('!button' => "<fb:login-button onclick='FB_Connect.login_onclick();'></fb:login-button>")),
410 ),
411 'connected' => array(
412 'title' => t('Facebook Connect'),
413 'body' => "<fb:profile-pic uid=!fbu></fb:profile-pic><fb:login-button onclick='FB_Connect.logout_onclick();' autologoutlink=true></fb:login-button>",
414 ),
415 );
416 }
417
418 /**
419 * Implementation of hook_block.
420 */
421 function fb_connect_block($op = 'list', $delta = 0, $edit = array()) {
422 if ($op == 'list') {
423 $items = array();
424 foreach (fb_connect_enabled_apps() as $fb_app) {
425 $d = 'login_' . $fb_app->label;
426 $items[$d] = array(
427 'info' => t('Facebook Connect Login to !app',
428 array('!app' => $fb_app->title)),
429 );
430 }
431 return $items;
432 }
433 else if ($op == 'configure') {
434 $defaults = variable_get('fb_connect_block_' . $delta, _fb_connect_block_login_defaults());
435 $form['config'] = array('#tree' => TRUE);
436 foreach(array('anon_not_connected', 'user_not_connected', 'connected') as $key) {
437 $form['config'][$key] = array(
438 '#type' => 'fieldset',
439 // title and description below
440 '#collapsible' => TRUE,
441 '#collapsed' => FALSE,
442 );
443 $form['config'][$key]['title'] = array(
444 '#type' => 'textfield',
445 '#title' => t('Default title'),
446 //'#description' => t('Default title.'),
447 '#default_value' => $defaults[$key]['title'],
448 );
449 $form['config'][$key]['body'] = array(
450 '#type' => 'textarea',
451 '#title' => t('Body'),
452 //'#description' => t('Block body'),
453 '#default_value' => $defaults[$key]['body'],
454 );
455 }
456 $form['config']['anon_not_connected']['#title'] = t('Anonymous user, not connected');
457 $form['config']['anon_not_connected']['#description'] = t('Settings when local user is Anonymous, and not connected to Facebook. Typically a new account will be created when the user clicks the connect button.');
458 $form['config']['user_not_connected']['#title'] = t('Registered user, not connected');
459 $form['config']['user_not_connected']['#description'] = t('Settings when local user is registered, and not connected to Facebook. Typically the facebook id will be linked to the local id after the user clicks the connect button.');
460 $form['config']['connected']['#title'] = t('Connected user');
461 $form['config']['connected']['#description'] = t('Settings when local user is connected to Facebook. You may render facebook\'s logout button, and/or information about the user.');
462 $form['config']['connected']['body']['#description'] .= t('Note that <em>!fbu</em> will be replaced with the user\'s facebook id.');
463
464 $form['config']['format'] = filter_form($defaults['format']);
465 $form['config']['format']['#description'] .= t('Format selected will apply to all body fields above. Be sure to select a format which allows FBML tags!');
466 $form['config']['format']['#collapsed'] = FALSE;
467
468 return $form;
469 }
470 else if ($op == 'save') {
471 $edit['config']['format'] = $edit['format'];
472 variable_set('fb_connect_block_' . $delta, $edit['config']);
473 }
474 else if ($op == 'view') {
475 if (strpos($delta, 'login_') === 0) {
476 // Login block
477 $label = substr($delta, 6); // length of 'login_'
478 $fb_app = fb_get_app(array('label' => $label));
479 $fb = fb_connect_app_init($fb_app);
480 $fbu = $fb->get_loggedin_user();
481 fb_connect_require_feature('XFBML', $fb_app);
482 //fb_connect_init_option('reloadIfSessionStateChanged', TRUE, $fb_app);
483 //fb_connect_init_option('doNotUseCachedConnectState', TRUE, $fb_app);
484
485 $base = drupal_get_path('module', 'fb_connect');
486 _fb_connect_add_js();
487
488 $defaults = variable_get('fb_connect_block_' . $delta, _fb_connect_block_login_defaults());
489 if ($fbu) {
490 $subject = $defaults['connected']['title'];
491 $content = $defaults['connected']['body'];
492 // substitute %fbu
493 $content = str_replace('!fbu', $fbu, $content);
494 } else if ($GLOBALS['user']->uid > 1) {
495 $subject = $defaults['user_not_connected']['title'];
496 $content = $defaults['user_not_connected']['body'];
497 } else if ($GLOBALS['user']->uid == 1) {
498 $subject = $defaults['user_not_connected']['title'];
499 $content = '<em>' . t('This block would normally show a Facebook Connect button. This feature is disabled for security because you are logged in as user #1.') . '</em>';
500 } else {
501 $subject = $defaults['anon_not_connected']['title'];
502 $content = $defaults['anon_not_connected']['body'];
503 }
504
505 // If user has changed defaults, run filter
506 if ($defaults['format']) {
507 $subject = check_plain($subject);
508 $content = check_markup($content, $defaults['format'], FALSE);
509 }
510
511 $block = array(
512 'subject' => $subject,
513 'content' => $content,
514 );
515 return $block;
516 }
517 }
518 }
519
520
521 function fb_connect_form_alter(&$form, &$form_state, $form_id) {
522 // Add our settings to the fb_app edit form.
523 if (is_array($form['fb_app_data'])) {
524 $node = $form['#node'];
525 $fb_app_data = fb_app_get_data($node->fb_app);
526 $fb_connect_data = $fb_app_data['fb_connect'];
527
528 $form['fb_app_data']['fb_connect'] = array(
529 '#type' => 'fieldset',
530 '#title' => 'Facebook Connect',
531 '#tree' => TRUE,
532 '#collapsible' => TRUE,
533 '#collapsed' => $node->nid ? TRUE : FALSE,
534 );
535
536 $form['fb_app_data']['fb_connect']['primary'] = array(
537 '#type' => 'checkbox',
538 '#title' => t('Primary'),
539 '#description' => t('Initialize fbConnect javascript on all (non-canvas) pages. If this site supports multiple Facebook Apps, this may be checked for at most one.'),
540 '#default_value' => $fb_connect_data['primary'],
541 );
542 if ($primary_apikey = variable_get('fb_connect_primary_apikey', NULL)) {
543 if ($primary_apikey != $node->fb_app->apikey) {
544 $primary = fb_get_app(array('apikey' => $primary_apikey));
545 $form['fb_app_data']['fb_connect']['primary']['#description'] .= '<br/>' . t('Note that checking this will replace %app as the primary Facebook Connect app.',
546 array('%app' => $primary ? $primary->title : $primary_apikey));
547 }
548 }
549 }
550 }
551
552 function fb_connect_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
553 if (($op == 'insert' || $op == 'update') && $node->type == 'fb_app') {
554 //dpm(func_get_args(), "fb_connect_nodeapi($op)"); // debug
555 if ($node->fb_app_data['fb_connect']['primary']) {
556 variable_set('fb_connect_primary_apikey', $node->fb_app['apikey']);
557 drupal_set_message(t('!node is now the primary Facebook Connect application.', array('!node' => l($node->title, 'node/' . $node->nid))));
558 }
559 }
560 }
561
562
563 /**
564 * Implementation of hook_theme_registry_alter().
565 *
566 * Override theme functions for things that can be displayed using
567 * XFBML. Currently overriding username and user_picture. We rename
568 * the original entries, as we will use them for users without
569 * javascript enabled.
570 *
571 * This hook is not well documented. Who knows what its supposed to
572 * return? No doubt this will need updating with each new version of
573 * Drupal.
574 */
575 function fb_connect_theme_registry_alter(&$theme_registry) {
576 // Re-register the original theme function under a new name.
577 $theme_registry['fb_connect_username_orig'] = $theme_registry['username'];
578 // Override theme username
579 $theme_registry['username'] = array(
580 'arguments' => array('object' => NULL),
581 'function' => 'fb_connect_theme_username_override',
582 );
583
584 // Re-register the original theme function under a new name.
585 $theme_registry['fb_connect_user_picture_orig'] = $theme_registry['user_picture'];
586 // Override theme username
587 $theme_registry['user_picture'] = array(
588 'arguments' => array('account' => NULL),
589 'function' => 'fb_connect_theme_user_picture_override',
590 );
591
592 }
593
594 /**
595 * Our replacement for theme('user_picture', ...)
596 */
597 function fb_connect_theme_user_picture_override($account) {
598
599 // First learn the Facebook id
600 if ($account->fbu) {
601 $fbu = $account->fbu;
602 }
603 else if ($pos = strpos($account->name, '@facebook')) {
604 // One option is to load the user object and get the definitive fbu. But that's expensive, so we rely on the NNNNNN@facebook naming convention.
605
606 $fbu = substr($account->name, 0, $pos);
607 }
608 else {
609 // Experimental. This can be expensive on pages with many comments or nodes!
610 //$fbu = fb_get_fbu($account->uid);
611 }
612
613 $orig = theme('fb_connect_user_picture_orig', $account); // Markup without fb_connect.
614 if (!isset($fbu) || !$fbu)
615 $output = $orig;
616 else {
617 $output = theme('fb_connect_fbml_user_picture', $orig, $account, $fbu);
618 }
619
620 return $output;
621
622 }
623
624 /**
625 * Our replacement for theme('username', ...)
626 */
627 function fb_connect_theme_username_override($object) {
628 // TODO: does this function need to account for canvas pages? Or can we assume every canvas page theme will override theme_username on its own?
629
630 // Theme the username with XFBML, using original username as backup.
631 return fb_connect_fbml_username($object, theme('fb_connect_username_orig', $object));
632 }
633
634 /**
635 * Helper function for themes to display the username.
636 */
637 function fb_connect_fbml_username($object, $orig_username = NULL) {
638 if (!isset($orig_username))
639 // What to display if javascript disabled.
640 $orig_username = theme_username($object);
641
642 // First learn the Facebook id
643 if ($object->fbu) {
644 $fbu = $object->fbu;
645 }
646 else if ($pos = strpos($object->name, '@facebook')) {
647 // One option is to load the user object and get the definitive fbu. But that's expensive, so we rely on the NNNNNN@facebook naming convention.
648
649 $fbu = substr($object->name, 0, $pos);
650 }
651 else {
652 // Experimental. This can be expensive on pages with many comments or nodes!
653 //$fbu = fb_get_fbu($object->uid);
654 }
655
656 if (isset($fbu) && is_numeric($fbu)) {
657 // Display both orig and XFBML, to degrade gracefully.
658 return theme(fb_connect_fbml_username, $orig_username, $object, $fbu);
659 }
660 else {
661 return $orig_username;
662 }
663 }
664
665
666 /**
667 * Implements hook_theme().
668 *
669 * We use theme function for XFBML username and picture so that the
670 * markup can be relatively easily customized.
671 */
672 function fb_connect_theme() {
673 return array(
674 'fb_connect_fbml_username' => array(
675 'arguments' => array(
676 'orig_username' => NULL,
677 'object' => NULL,
678 'fbu' => NULL,
679 ),
680 ),
681 'fb_connect_fbml_user_picture' => array(
682 'arguments' => array(
683 'orig' => NULL,
684 'account' => NULL,
685 'fbu' => NULL,
686 ),
687 ),
688 'fb_connect_fbml_popup' => array(
689 'arguments' => array('elements' => NULL),
690 ),
691 );
692 }
693
694 function theme_fb_connect_fbml_username($orig_username, $object, $fbu) {
695 return '<span class=fb_connect_hide>'.$orig_username.'</span><span class=fb_connect_show style="display:none"><a href="'. url('user/' . $object->uid) . '"><fb:name linked=false useyou=false uid=' . $fbu . '></fb:name></a></span>';
696 }
697
698 function theme_fb_connect_fbml_user_picture($orig, $account, $fbu) {
699 $output = ''; // Build the markup.
700 // First, the markup if javascript is disabled, degrade gracefully.
701 if ($orig)
702 $output .= '<span class=fb_connect_hide>'.$orig.'</span>';
703 // Next markup that will be made visible by javascript.
704 $output .= '<span class="fb_connect_show" style="display:none"><div class="picture"><a href="'.url('user/' . $account->uid).'"><fb:profile-pic uid='.$fbu.' linked=false></fb:profile-pic></a></div></span>';
705 return $output;
706 }
707
708 function theme_fb_connect_fbml_popup($elem) {
709 // Hide this markup until javascript shows it.
710 $t = '<div class="fb_connect_fbml_popup_wrap" style="display:none;" ' . ">\n";
711
712 $t .= '<a href="#" title="' . check_plain($elem['#title']) . '" ' . drupal_attributes($elem['#link_attributes']) . '>' . check_plain($elem['#link_text']) .'</a>';
713 $t .= '<div class="fb_connect_fbml_popup" ' . drupal_attributes($elem['#attributes']) . '>';
714 $t .= $elem['#children'];
715 $t .= "</div></div>\n";
716 return $t;
717 }

  ViewVC Help
Powered by ViewVC 1.1.2