'Facebook Connect', 'description' => 'Configure Facebook Connect', 'page callback' => 'drupal_get_form', 'page arguments' => array('fb_connect_admin_settings'), 'access arguments' => array(FB_PERM_ADMINISTER), 'file' => 'fb_connect.admin.inc', 'type' => MENU_LOCAL_TASK, ); return $items; } /** * Prepare for fbConnect use. Because a single Drupal might support * multiple apps, we don't know in advance which is the fbConnect app. */ function fb_connect_app_init($fb_app) { if (isset($GLOBALS['_fb_app']) && $GLOBALS['_fb_app']->apikey != $fb_app->apikey) { // If we're in an iframe, only support connect for the iframe app. return; } if ($fb = fb_api_init($fb_app)) { $fbu = $fb->getUser(); if ($fbu && (!isset($GLOBALS['_fb_app']) || $GLOBALS['_fb_app']->apikey != $fb_app->apikey)) { // The user has authorized the app and we now know something about them. Use a hook to trigger the actions of other modules. fb_invoke(FB_OP_APP_IS_AUTHORIZED, array( 'fbu' => $fbu, 'fb_app' => $fb_app, 'fb' => $fb)); } // Remember which app we've initialized. _fb_connect_set_app($fb_app); _fb_connect_add_js($fb_app, $fb); } return $fb; } /** * Helper function for other modules to know page is connected. * * Note that this may return data on connect pages and in iframe apps * (depending on how iframe is configured). */ function fb_connect_get_app() { return _fb_connect_set_app(); } function _fb_connect_set_app($fb_app = NULL) { static $cache; if (isset($fb_app)) { $cache = $fb_app; } return $cache; } /** * Implementation of hook_fb(). */ function fb_connect_fb($op, $data, &$return) { //dpm(func_get_args(), "fb_connect_fb($op)"); if ($op == FB_OP_CURRENT_APP && !$return && !fb_is_canvas()) { // This will cause fb.module to set the global $_fb when user is logged in via fbConnect. if ($apikey = variable_get(FB_VAR_APIKEY, NULL)) { // Use $conf['fb_apikey'] if set in settings.php. $return = fb_get_app(array('apikey' => $apikey)); } elseif ($label = variable_get(FB_CONNECT_VAR_PRIMARY, NULL)) { $return = fb_get_app(array('label' => $label)); } } elseif ($op == FB_OP_POST_INIT) { if (!fb_is_tab()) { // Init Facebook javascript for primary app _fb_connect_add_js($data['fb_app'], $data['fb']); } // Include our admin hooks. if (fb_is_fb_admin_page()) { module_load_include('inc', 'fb_connect', 'fb_connect.admin'); } } } /** * This wrapper function around drupal_add_js() ensures that our * settings are added once and only once when needed. * */ function _fb_connect_add_js($fb_app, $fb) { static $just_once; if (fb_is_tab()) // Tabs are FBML. return; if (!isset($just_once)) { drupal_add_js(array( 'fb_connect' => array( 'front_url' => url(''), 'fbu' => fb_facebook_user(), 'uid' => $GLOBALS['user']->uid, ), ), 'setting'); drupal_add_js(drupal_get_path('module', 'fb_connect') . '/fb_connect.js'); $just_once = TRUE; } // If we are not the global $_fb_app if ($fb_app) { $settings = fb_js_settings(); if (!isset($settings['fb_init_settings']['apiKey']) || $settings['fb_init_settings']['apiKey'] != $fb_app->apikey) { // Ensure JS initializes with the proper apikey. We may reach this if // there is no "primary" app. // @TODO fb.module should have a helper to make this cleaner. $settings['fb_init_settings']['apiKey'] = $fb_app->apikey; $settings['fb_init_settings']['session'] = $fb->getSession(); fb_js_settings('apikey', $fb_app->apikey); fb_js_settings('fbu', fb_facebook_user($fb)); fb_js_settings('fb_init_settings', $settings['fb_init_settings']); //$js = drupal_add_js(array('fb' => fb_js_settings()), 'setting'); // fb.module will add settings to footer. } } } /** * Default markup for our login block. */ function _fb_connect_block_login_defaults() { return array('anon_not_connected' => array( 'title' => t('Facebook Connect'), 'body' => 'Connect', ), 'user_not_connected' => array( 'title' => t('Facebook Connect'), 'body' => 'Connect', ), 'connected' => array( 'title' => t('Facebook Connect'), // Logout commented out, because drupal has logout link. 'body' => "", ), ); } /** * Implements hook_block(). */ function fb_connect_block($op = 'list', $delta = 0, $edit = array()) { if ($op == 'list') { $items = array(); foreach (fb_get_all_apps() as $fb_app) { $d = 'login_' . $fb_app->label; $items[$d] = array( 'info' => t('Facebook Connect Login to !app', array('!app' => $fb_app->title)), ); } return $items; } elseif ($op == 'configure') { $orig_defaults = _fb_connect_block_login_defaults(); $defaults = variable_get('fb_connect_block_' . $delta, $orig_defaults); $form['config'] = array('#tree' => TRUE); // Settings for each user status that we can detect. foreach (array('anon_not_connected', 'user_not_connected', 'connected') as $key) { $form['config'][$key] = array( '#type' => 'fieldset', // title and description below '#collapsible' => TRUE, '#collapsed' => FALSE, ); $form['config'][$key]['title'] = array( '#type' => 'textfield', '#title' => t('Default title'), //'#description' => t('Default title.'), '#default_value' => $defaults[$key]['title'], ); $form['config'][$key]['body'] = array( '#type' => 'textarea', '#title' => t('Body'), //'#description' => t('Block body'), '#default_value' => $defaults[$key]['body'], ); } $form['config']['anon_not_connected']['#title'] = t('Anonymous user, not connected'); $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.'); $form['config']['anon_not_connected']['body']['#description'] = t('Suggestion: %default .', array('%default' => $orig_defaults['anon_not_connected']['body'])); $form['config']['user_not_connected']['#title'] = t('Registered user, not connected'); $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.'); $form['config']['user_not_connected']['body']['#description'] = t('Suggestion: %default .', array('%default' => $orig_defaults['user_not_connected']['body'])); $form['config']['connected']['#title'] = t('Connected user'); $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. Consider using XFBML such as <fb:name uid=!fbu></fb:name> or <fb:profile-pic uid=!fbu></fb:profile-pic>', array('xfbml_url' => 'http://wiki.developers.facebook.com/index.php/XFBML')); $form['config']['connected']['body']['#description'] .= t('Note that !fbu will be replaced with the user\'s facebook id.
Suggestion: %default .', array('%default' => $orig_defaults['connected']['body'])); $form['config']['format'] = filter_form($defaults['format']); $form['config']['format']['#description'] .= t('

Be sure to select a format which allows XFBML tags! (That is, use Full HTML or PHP code, rather than Filtered HTML.)

Format selected will apply to all body fields above.

'); $form['config']['format']['#collapsed'] = FALSE; return $form; } elseif ($op == 'save') { $edit['config']['format'] = $edit['format']; variable_set('fb_connect_block_' . $delta, $edit['config']); } elseif ($op == 'view' && !fb_is_tab()) { // Hide block on tabs, where the $fbu is actually the page, not the user. if (strpos($delta, 'login_') === 0) { // Login block $label = substr($delta, 6); // length of 'login_' $fb_app = fb_get_app(array('label' => $label)); if ($fb_app && ($fb = fb_connect_app_init($fb_app))) { $fbu = $fb->getUser(); //_fb_connect_add_js($fb_app); moved to fb_connect_app_init() $base = drupal_get_path('module', 'fb_connect'); $defaults = variable_get('fb_connect_block_' . $delta, _fb_connect_block_login_defaults()); if ($fbu) { $subject = $defaults['connected']['title']; $content = $defaults['connected']['body']; // substitute %fbu $content = str_replace('!fbu', $fbu, $content); } elseif ($GLOBALS['user']->uid >= 1) { $subject = $defaults['user_not_connected']['title']; $content = $defaults['user_not_connected']['body']; } else { $subject = $defaults['anon_not_connected']['title']; $content = $defaults['anon_not_connected']['body']; } // substitute perms $perms = array(); drupal_alter('fb_required_perms', $perms); $content = str_replace('!perms', implode(',', $perms), $content); // If user has changed defaults, run filter if (isset($defaults['format'])) { $subject = check_plain($subject); $content = check_markup($content, $defaults['format'], FALSE); } $block = array( 'subject' => $subject, 'content' => $content, ); return $block; } } } } /** * Helper returns configuration for this module, on a per-app basis. */ function _fb_connect_get_config($fb_app) { $fb_app_data = fb_get_app_data($fb_app); $config = isset($fb_app_data['fb_connect']) ? $fb_app_data['fb_connect'] : array(); // Merge in defaults $config += array( ); return $config; } /** * Implements hook_form_alter(). */ function fb_connect_form_alter(&$form, &$form_state, $form_id) { // Add our settings to the fb_app edit form. if (isset($form['fb_app_data'])) { $fb_app = $form['#fb_app']; $form['fb_app_data']['fb_connect'] = array( '#type' => 'fieldset', '#title' => 'Facebook connect', '#tree' => TRUE, '#collapsible' => TRUE, '#collapsed' => $fb_app->label ? TRUE : FALSE, ); // "Primary" will be initialized on every non-canvas page. $primary_label = variable_get(FB_CONNECT_VAR_PRIMARY, NULL); $form['fb_app_data']['fb_connect']['primary'] = array( '#type' => 'checkbox', '#title' => t('Primary'), '#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.'), '#default_value' => isset($fb_app->label) && ($primary_label == $fb_app->label), ); if (($primary_label) && ($primary_label != $fb_app->label)) { $form['fb_app_data']['fb_connect']['primary']['#description'] .= '
' . t('Note that checking this will replace %app as the primary Facebook Connect app.', array('%app' => $primary_label)); } $form['#submit'][] = 'fb_connect_app_submit'; } } /** * Submit callback. Sets or unsets "primary" app. */ function fb_connect_app_submit($form, &$form_state) { $values = $form_state['values']; $label = $values['label']; $data = $values['fb_app_data']['fb_connect']; if ($data['primary']) { variable_set(FB_CONNECT_VAR_PRIMARY, $label); drupal_set_message(t('%label is the primary Facebook Connect application.', array('%label' => $label))); } elseif ($label == variable_get(FB_CONNECT_VAR_PRIMARY, NULL)) { // This app was the primary one, but the user has unchecked it. variable_set(FB_CONNECT_VAR_PRIMARY, NULL); } } /** * Implementation of hook_theme_registry_alter(). * * Override theme functions for things that can be displayed using * XFBML. Currently overriding username and user_picture. We rename * the original entries, as we will use them for users without * javascript enabled. * * This hook is not well documented. Who knows what its supposed to * return? No doubt this will need updating with each new version of * Drupal. */ function fb_connect_theme_registry_alter(&$theme_registry) { // Ideally, we'd do this only on themes which will certainly be used for facebook connect pages. if (variable_get(FB_CONNECT_VAR_THEME_USERNAME_2, TRUE) || (variable_get(FB_CONNECT_VAR_THEME_USERNAME_1, TRUE) && $theme_registry['username']['type'] == 'module')) { // Re-register the original theme function under a new name. $theme_registry['fb_connect_username_orig'] = $theme_registry['username']; // Override theme username $theme_registry['username'] = array( 'arguments' => array('object' => NULL), 'function' => 'fb_connect_theme_username_override', 'type' => 'module', ); } if (variable_get(FB_CONNECT_VAR_THEME_USERPIC_2, TRUE) || (variable_get(FB_CONNECT_VAR_THEME_USERPIC_1, TRUE) && $theme_registry['user_picture']['type'] == 'module')) { // Re-register the original theme function under a new name. $theme_registry['fb_connect_user_picture_orig'] = $theme_registry['user_picture']; // Override theme username $theme_registry['user_picture'] = array( 'arguments' => array('account' => NULL), 'function' => 'fb_connect_theme_user_picture_override', 'type' => 'module', ); } } /** * Our replacement for theme('user_picture', ...) */ function fb_connect_theme_user_picture_override($account) { // Markup without fb_connect. $orig = theme('fb_connect_user_picture_orig', $account); // Respect Drupal's profile pic, if uploaded. if (isset($account->picture) && $account->picture) { return $orig; } if ($fbu = fb_get_object_fbu($account)) { $output = theme('fb_user_picture', $fbu, $account, $orig); } else { $output = $orig; } return $output; } /** * Our replacement for theme('username', ...) */ function fb_connect_theme_username_override($object) { $orig = theme('fb_connect_username_orig', $object); if ($fbu = fb_get_object_fbu($object)) { // Theme the username with XFBML, using original username as backup. return theme('fb_username', $fbu, $object, $orig); } else { return $orig; } }