5 * This module provides support for "Profile Tabs" that can be added to
6 * facebook pages (no longer allowed for user profiles).
8 * http://developers.facebook.com/docs/guides/canvas/#tabs
12 define('FB_TAB_HOOK', 'fb_tab');
14 //// Hook_fb_tab operations
15 define('FB_TAB_OP_VIEW', 'fb_tab_view');
16 define('FB_TAB_OP_FORM', 'fb_tab_form');
18 define('FB_TAB_PATH_VIEW', 'fb_tab/view');
19 define('FB_TAB_PATH_FORM', 'fb_tab/config');
20 define('FB_TAB_PATH_FORM_ARGS', 2);
22 define('FB_TAB_VAR_PROCESS_FBML', 'fb_tab_process_fbml');
23 define('FB_TAB_VAR_PROCESS_IFRAME', 'fb_tab_process_iframe');
24 define('FB_TAB_VAR_PROCESS_ABSOLUTE', 'fb_tab_process_absolute_links');
25 define('FB_TAB_VAR_PROCESS_TO_CANVAS', 'fb_tab_process_to_canvas');
27 function fb_tab_menu() {
30 $items[FB_TAB_PATH_VIEW
] = array(
31 'page callback' => 'fb_tab_view',
32 'access arguments' => array('access content'),
33 'type' => MENU_CALLBACK
,
36 $items[FB_TAB_PATH_FORM
] = array(
37 'title' => 'Configure Tabs',
38 'page callback' => 'fb_tab_pages',
39 'access arguments' => array('access content'),
40 'type' => MENU_CALLBACK
,
43 $items[FB_TAB_PATH_FORM .
'/%'] = array(
44 'page callback' => 'drupal_get_form',
45 'page arguments' => array('fb_tab_config_form', FB_TAB_PATH_FORM_ARGS
),
46 'access arguments' => array('access content'),
47 'type' => MENU_CALLBACK
,
51 $items[FB_PATH_ADMIN .
'/fb_tab'] = array(
52 'title' => 'Page Tabs',
53 'description' => 'Configure Tabs',
54 'page callback' => 'drupal_get_form',
55 'page arguments' => array('fb_tab_admin_settings'),
56 'access arguments' => array(FB_PERM_ADMINISTER
),
57 'file' => 'fb_tab.admin.inc',
58 'type' => MENU_LOCAL_TASK
,
65 * Implementation of hook_fb
68 * @param $data -- data payload
71 function fb_tab_fb($op, $data, &$return) {
72 $fb = isset($data['fb']) ?
$data['fb'] : NULL
;
73 $fb_app = isset($data['fb_app']) ?
$data['fb_app'] : NULL
;
75 if ($op == FB_OP_POST_INIT
) {
76 // Include our admin hooks.
77 if (fb_is_fb_admin_page()) {
78 require
drupal_get_path('module', 'fb_tab') .
'/fb_tab.admin.inc';
82 // Include our javascript.
85 'fbu' => fb_facebook_user(),
86 'uid' => $GLOBALS['user']->uid
,
87 'canvas' => $fb_app->canvas
,
90 drupal_add_js(drupal_get_path('module', 'fb_tab') .
'/fb_tab.js');
93 elseif ($op == FB_OP_CURRENT_APP
&& fb_is_tab()) {
94 if ($id = fb_settings(FB_SETTINGS_CB
)) {
95 // Using fb_url_rewrite.
96 $fb_app = fb_get_app(array('id' => $id));
99 // DEPRECATED. For backward compatibility, accept apikey in FB_SETTINGS_CB
100 $fb_app = fb_get_app(array('apikey' => $id));
104 elseif ($id = fb_settings(FB_SETTINGS_ID
)) {
105 // New SDK includes ID when session is present.
106 $fb_app = fb_get_app(array('id' => $id));
109 // Old, deprecated, FBML tabs.
110 elseif (isset($_REQUEST['fb_sig_api_key'])) {
111 $return = fb_get_app(array('apikey' => $_REQUEST['fb_sig_api_key']));
118 elseif ($op == FB_OP_INITIALIZE
) {
120 $config = _fb_tab_get_config($fb_app);
121 if (!isset($GLOBALS['custom_theme'])) {
122 $GLOBALS['custom_theme'] = $config['custom_theme'];
124 if (fb_settings(FB_SETTINGS_TYPE
) == FB_SETTINGS_TYPE_PAGE_TAB
&&
125 variable_get(FB_TAB_VAR_PROCESS_IFRAME
, TRUE
)) {
129 elseif (fb_settings(FB_SETTINGS_TYPE
) == FB_SETTINGS_TYPE_PROFILE
&&
130 variable_get(FB_TAB_VAR_PROCESS_FBML
, TRUE
)) {
138 // Hack to init the theme before _drupal_maintenance_theme initializes the wrong one.
139 if (variable_get('site_offline', FALSE
)) {
140 $dummy = theme('dummy');
143 // Store entire page in output buffer. Will post-process on exit.
146 $GLOBALS['fb_tab_post_process'] = TRUE
;
149 // Override what Drupal renders.
150 if ($_REQUEST['q'] == FB_TAB_PATH_VIEW
) { // Do not override fb_tab/config.
151 $sr = $fb->getSignedRequest();
152 if ($sr['page'] && $sr['page']['liked'] && $config['profile_tab_url_liked']) {
153 $path = $config['profile_tab_url_liked'];
156 $path = $config['profile_tab_url'];
158 if ($path && $path != FB_TAB_PATH_VIEW
) {
159 // Tell Drupal what to really render.
160 menu_set_active_item(drupal_get_normal_path($path));
166 elseif ($op == FB_OP_EXIT
&& fb_is_tab()) {
167 if (isset($GLOBALS['fb_tab_post_process']) && $GLOBALS['fb_tab_post_process']) {
168 $output = ob_get_contents();
170 include_once(drupal_get_path('module', 'fb') .
'/fb.process.inc');
172 if (variable_get(FB_TAB_VAR_PROCESS_TO_CANVAS
, TRUE
)) {
173 $to_canvas = $fb_app->canvas
;
179 if (fb_settings(FB_SETTINGS_TYPE
) == FB_SETTINGS_TYPE_PAGE_TAB
) {
181 $output = fb_process($output, array(
182 'add_target' => '_top',
183 'absolute_links' => TRUE
,
184 'to_canvas' => $to_canvas,
187 elseif (fb_settings(FB_SETTINGS_TYPE
) == FB_SETTINGS_TYPE_PROFILE
) {
188 // Process FBML (deprecated)
189 $output = fb_process($output, array(
190 'add_target' => FALSE
,
191 'absolute_links' => TRUE
,
192 'to_canvas' => $to_canvas,
195 if (isset($output)) {
203 * Implements fb_tab_form_alter.
205 function fb_tab_form_alter(&$form, &$form_state, $form_id) {
206 if (isset($form['fb_app_data']) && is_array($form['fb_app_data'])) {
207 // Add our settings to the fb_app edit form.
208 //require 'fb_canvas.admin.inc';
209 fb_tab_admin_form_alter($form, $form_state, $form_id);
214 * Helper returns configuration for this module, on a per-app basis.
216 function _fb_tab_get_config($fb_app) {
217 $fb_app_data = fb_get_app_data($fb_app);
218 $config = isset($fb_app_data['fb_tab']) ?
$fb_app_data['fb_tab'] : array();
222 'custom_theme' => NULL
,
223 'tab_default_name' => isset($fb_app->title
) ?
$fb_app->title
: NULL
,
224 'profile_tab_url' => NULL
,
225 'profile_tab_url_liked' => NULL
,
226 'edit_url' => FB_TAB_PATH_FORM
,
232 * Another module provides the contents of the tab depending
233 * on the context that we give it (who is calling it, etc.)
235 function fb_tab_view() {
236 $fb_app = $GLOBALS['_fb_app'];
237 $fb = $GLOBALS['_fb'];
239 $profile_id = fb_settings(FB_SETTINGS_CB_PAGE
);
241 $config = fb_tab_fetch_config($fb_app, $profile_id);
243 $sr = $fb->getSignedRequest();
248 'profile_id' => $profile_id,
249 'config' => isset($config['data']) ?
$config['data'] : NULL
,
250 'page' => $sr['page'],
253 $content = fb_invoke(FB_TAB_OP_VIEW
, $data, array(), FB_TAB_HOOK
);
255 return drupal_render($content);
259 * Build the tab config form. Invokes hook_fb_tab() to get the custom settings.
261 function fb_tab_config_form($form_state, $profile_id) {
262 $fb_app = $GLOBALS['_fb_app'];
263 $fb = $GLOBALS['_fb'];
265 $config = fb_tab_fetch_config($fb_app, $profile_id);
266 $sr = $fb->getSignedRequest();
271 'profile_id' => $profile_id,
272 'config' => isset($config['data']) ?
$config['data'] : NULL
,
273 'page' => $sr['page'],
277 //$fbu = fb_facebook_user($fb);
278 $fbu = fb_require_authorization($fb);
279 $page_info = $fb->api($profile_id, array(
280 'access_token' => fb_get_token($fb),
282 $admin_info = fb_fql_query($fb, "SELECT uid, type FROM page_admin WHERE uid=$fbu AND page_id=$profile_id"); // FQL not SQL, no {curly_brackets}
283 //dpm($admin_info, __FUNCTION__);
285 // @TODO: if not page admin, prompt user to login or deny access.
290 '#value' => t('Tab settings for <a href="!href">%page</a>', array(
291 '!href' => $page_info['link'],
292 '%page' => $page_info['name'],
295 '#suffix' => '</h3>',
300 '#value' => $fb_app->label
,
302 'profile_id' => array(
304 '#value' => $profile_id,
307 // Modules will add their fields here.
312 '#value' => t('Submit'),
317 if (isset($config['fb_tab_id'])) {
318 $form['fb_tab_id'] = array(
320 '#value' => $config['fb_tab_id'],
324 $form['data'] = fb_invoke(FB_TAB_OP_FORM
, $data, $form['data'], FB_TAB_HOOK
);
326 //print('<pre>' . print_r($data, 1) . '</pre>'); flush();
327 //print(print_r($content, 1)); flush();
331 catch (Exception
$e) {
332 fb_log_exception($e, t('Failed to get details for facebook page %profile_id', array(
333 '%profile_id' => $profile_id,
337 '#value' => t('Unable to set properties.'),
344 * Submit handler for tab config form.
346 function fb_tab_config_form_submit($form, &$form_state) {
347 if ($profile_id = $form_state['values']['profile_id']) {
348 fb_tab_write_config($form_state['values']);
349 $data = fb_fql_query($GLOBALS['_fb'], "SELECT page_id, name, pic_small, page_url, type FROM page WHERE page_id=$profile_id"); // FQL, no {curly_brackets}
350 drupal_set_message(t('The tab settings for <a href="!url">%page</a> have been updated.', array(
351 '!url' => $data[0]['page_url'],
352 '%page' => $data[0]['name'],
358 * Store configuration data for a tab by application.
360 function fb_tab_write_config(&$row) {
361 if (!isset($row['created']))
362 $row['created'] = time();
363 $row['data'] = serialize($row['data']);
364 return drupal_write_record('fb_tab', $row,
365 isset($row['fb_tab_id']) ?
array('fb_tab_id') : NULL
);
369 * Return configuration of a tab by application (access via 'label') and page ID.
370 * Page ID exists because an app can present different views on different pages.
372 function fb_tab_fetch_config($fb_app, $profile_id) {
373 $result = db_query("SELECT * FROM {fb_tab} WHERE label = '%s' AND profile_id = %d" , $fb_app->label
, $profile_id);
375 $row = db_fetch_array($result);
377 $row['data'] = unserialize($row['data']);
386 * This page callback will show the user a list of pages they have authority
389 function fb_tab_pages() {
390 if ($fbu = fb_facebook_user()) {
392 // @TODO: broken on facebook's end??? this query used to work.
393 $result = fb_fql_query($GLOBALS['_fb'], "SELECT page_id, name, pic_small, page_url, type FROM page WHERE has_added_app=1 AND page_id IN (SELECT page_id FROM page_admin WHERE uid=$fbu)"); // FQL, no {curly_brackets}
395 if (count($result)) {
396 $output['pages'] = array(
398 '#suffix' => '</ul>',
400 foreach ($result as
$data) {
401 $output['pages'][$data['page_id']] = array(
402 '#value' => l($data['name'], fb_tab_config_url($data['page_id'], array('fb_canvas' => fb_is_canvas()))),
404 '#suffix' => '</li>',
407 $output['intro'] = array(
408 '#value' => t('Select one of your pages to configure:'),
414 $output['intro'] = array(
415 '#value' => t('Found no pages to configure.'),
420 return drupal_render($output);
429 * Provides the URL of the settings page for a given facebook page.
431 function fb_tab_config_url($profile_id = NULL
, $options = array()) {
433 $profile_id = fb_settings(FB_SETTINGS_CB_PAGE
);
435 return url(FB_TAB_PATH_FORM .
'/' .
$profile_id, $options);