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

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

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


Revision 1.15 - (show annotations) (download) (as text)
Tue Mar 31 03:03:00 2009 UTC (7 months, 4 weeks ago) by yogadex
Branch: MAIN
Changes since 1.14: +1 -1 lines
File MIME type: text/x-php
avoid use of FB_FBU_NO_SESSION, as it causes cookies to be set which conflict with Facebook Connect
1 <?php
2 /**
3 * @file
4 *
5 * Actions defined here interact with Facebook's API. This makes it
6 * possible to notify facebook of various activities as they happen.
7 */
8
9 /**
10 * Implemntation of hook_action_info()
11 */
12 function fb_actions_action_info() {
13 return array('fb_actions_profile_fbml' =>
14 array('type' => 'fb_action',
15 'description' => t('Write to Facebook profile'),
16 'configurable' => TRUE,
17 'hooks' => array('nodeapi' => array('delete', 'insert', 'update', 'view'),
18 'comment' => array('delete', 'insert', 'update', 'view'),
19 'user' => array('insert', 'update', 'delete', 'login', 'logout'),
20 'cron' => array('run'),
21 ),
22 ),
23 'fb_actions_ref_fbml' =>
24 array('type' => 'fb_action',
25 'description' => t('Write to Facebook reference FBML'),
26 'configurable' => TRUE,
27 'hooks' => array('nodeapi' => array('delete', 'insert', 'update', 'view'),
28 'comment' => array('delete', 'insert', 'update', 'view'),
29 'user' => array('insert', 'update', 'delete', 'login', 'logout'),
30 'cron' => array('run'),
31 ),
32 ),
33 'fb_actions_cron_per_user' =>
34 array('type' => 'fb_app',
35 'description' => t('Perform an Action once for each user of a Facebook App'),
36 'configurable' => TRUE,
37 'hooks' => array('cron' => array('run')),
38 ),
39 );
40
41 }
42
43
44
45
46 /**
47 * Implementation of an Action. See Actions module.
48 *
49 * This action updates a user's profile FBML.
50 */
51 function fb_actions_profile_fbml_form($values) {
52 $options = fb_get_app_options(TRUE);
53 $form['description'] = array('#value' => t('This action will update the current user\'s Facebook profile. Suitable for canvas pages and cron jobs (if infinite session is configured).'));
54 $form['fb_app_nid'] =
55 array('#type' => 'select',
56 '#title' => t('Application'),
57 '#default_value' => $values['fb_app_nid'],
58 '#options' => $options,
59 '#description' => t('Log into Facebook as which application? %current is OK when invoked from canvas pages or cron jobs.',
60 array('%current' => $options[FB_APP_CURRENT])),
61 );
62
63 $form['body'] = array('#type' => 'textarea',
64 '#title' => t('Profile Box FBML'),
65 '#default_value' => $values['body'],
66 '#description' => t('FBML to write to user\'s profile box. Make sure to choose an input filter that allows FBML!<br />The following token will be replaced: !token_help',
67 array('!token_help' => theme('token_help', 'fb_app'))),
68 );
69 $form['body_filter'] = filter_form($values['body_filter'],
70 NULL,
71 array('body_filter'));
72
73 $form['profile_main'] = array('#type' => 'textarea',
74 '#title' => t('Main Profile Box'),
75 '#default_value' => $values['profile_main'],
76 '#description' => t('FBML for the <a href=!url>narrow profile box</a> on the Wall and Info tabs page.',
77 array('!url' => 'http://wiki.developers.facebook.com/index.php/New_Design_Narrow_Boxes')),
78 );
79 $form['mobile_profile'] = array('#type' => 'textarea',
80 '#title' => t('Mobile Profile Box'),
81 '#default_value' => $values['mobule_profile'],
82 '#description' => t('FBML intended for mobile devices.'),
83 );
84
85 return $form;
86 }
87
88 function fb_actions_profile_fbml_validate($form_id, $values) {
89 // TODO
90 }
91
92 function fb_actions_profile_fbml_submit($form_id, $values) {
93 return array('fb_app_nid' => $values['fb_app_nid'],
94 'body' => $values['body'],
95 'body_filter' => $values['body_filter'],
96 'profile_main' => $values['profile_main'],
97 'mobile_profile' => $values['mobile_profile'],
98 );
99 }
100
101 function fb_actions_profile_fbml(&$object, $values) {
102 //dpm(func_get_args(), "fb_actions_profile_fbml");
103
104 if ($values['hook'] == 'nodeapi') {
105 $node = $values['node'];
106 }
107 else if ($values['hook'] == 'comment') {
108 $comment = $values['comment'];
109 $node = node_load($comment->nid);
110 }
111 else if ($values['hook'] == 'user') {
112 $account = $values['user']; // untested
113 }
114
115 // Determine which app to use
116 if ($object) {
117 $fb_app = $object;
118 }
119 else if ($values['fb_app_nid'] && is_numeric($values['fb_app_nid'])) {
120 $fb_app = fb_get_app(array('nid' => $values['fb_app_nid']));
121 }
122 else if ($values['fb_app_nid'] == FB_APP_CURRENT) {
123 $fb_app = $GLOBALS['fb_app'];
124 }
125
126 // Use already configured $fb if its passed in (cron jobs)
127 $fb = $values['fb'];
128 if (!$fb && $fb_app)
129 // Otherwise, login to facebook as either the current user or the infinite session
130 $fb = fb_api_init($fb_app, FB_FBU_ANY);
131
132 if ($fb) {
133 global $user;
134 $fbu = fb_get_fbu($user->uid, $fb_app);
135 // Replace fb_app related tokens
136 $body = token_replace($values['body'], 'fb_app', $fb_app);
137 $body = check_markup($body, $values['body_filter'], FALSE);
138 if ($profile_main)
139 $profile_main = check_markup($profile_main, $values['body_filter'], FALSE);
140 if ($mobile_profile)
141 $mobile_profile = check_markup($mobile_profile, $values['body_filter'], FALSE);
142
143 // Links in profile FBML must be fully-qualified. Here we attempt to
144 // replace relative links with fully qualified ones.
145 global $base_url, $base_path;
146 $patterns[] = '/"'.str_replace('/','\/', $base_path).'([^"]*)"/';
147 $replacements[] = '"'.$base_url.'/$1"';
148 $body = preg_replace($patterns, $replacements, $body);
149 if ($profile_main)
150 $profile_main = preg_replace($patterns, $replacements, $profile_main);
151 if ($mobile_profile)
152 $mobile_profile = preg_replace($patterns, $replacements, $mobile_profile);
153
154 // Rewrite links to reference canvas pages
155 if ($fb_app->canvas && function_exists('fb_canvas_process_fbml')) {
156 $body = fb_canvas_process_fbml($body, $fb_app);
157 if ($profile_main)
158 $profile_main = fb_canvas_process_fbml($profile_main, $fb_app);
159 if ($mobile_profile)
160 $mobile_profile = fb_canvas_process_fbml($mobile_profile, $fb_app);
161 }
162
163 if (variable_get('fb_actions_verbose', FALSE))
164 watchdog('fb_actions', 'Setting Facebook profile markup for !user to !body',
165 array('!user' => theme('username', $user),
166 '!body' => htmlentities($body)));
167 try {
168 // http://wiki.developers.facebook.com/index.php/Profile.setFBML
169 $fb->api_client->profile_setFBML(NULL, $fbu, $body, NULL, $mobile_profile, $profile_main);
170 } catch (Exception $e) {
171 fb_log_exception($e, t('Failed to set profile FBML'), $fb);
172 }
173 }
174 }
175
176 /**
177 * Implementation of an Action.
178 *
179 * This action updates reference FBML.
180 * http://developer.facebook.com/documentation.php?v=1.0&method=fbml.setRefHandle
181 */
182 function fb_actions_ref_fbml_form($values) {
183 $form['description'] = array('#value' => t('This action will update reference FBML. See Facebook\'s documentation of the &lt;fb:ref&gt; tag. Suitable for canvas pages and cron jobs (if infinite session is configured).'));
184 $options = fb_get_app_options(TRUE);
185 $form['fb_app_nid'] =
186 array('#type' => 'select',
187 '#title' => t('Application'),
188 '#default_value' => $values['fb_app_nid'],
189 '#options' => $options,
190 '#description' => t('Log into Facebook as which application? %current is OK when invoked from canvas pages or cron jobs.',
191 array('%current' => $options[FB_APP_CURRENT])),
192 );
193 $form['handle'] = array('#type' => 'textfield',
194 '#title' => t('Handle'),
195 '#default_value' => $values['handle'],
196 );
197 $form['body'] = array('#type' => 'textarea',
198 '#title' => t('Reference FBML'),
199 '#default_value' => $values['body'],
200 '#description' => t('FBML to write to user\'s profile.<br />The following token will be replaced: !token_help',
201 array('!token_help' => theme('token_help', 'fb_app'))),
202 );
203 $form['body_filter'] = filter_form($values['body_filter'],
204 NULL,
205 array('body_filter'));
206 return $form;
207 }
208 function fb_actions_ref_fbml_validate($form_id, $values) {
209 // TODO
210 }
211 function fb_actions_ref_fbml_submit($form_id, $values) {
212 return array('fb_app_nid' => $values['fb_app_nid'],
213 'handle' => $values['handle'],
214 'body' => $values['body'],
215 'body_filter' => $values['body_filter'],
216 );
217 }
218 function fb_actions_ref_fbml(&$object, $values) {
219 if ($values['hook'] == 'nodeapi') {
220 $node = &$object;
221 }
222 else if ($values['hook'] == 'comment') {
223 $node = node_load($object['nid']);
224 $comment = &$object;
225 }
226 else if ($values['hook'] == 'user') {
227 $account = &$object;
228 }
229
230 // Log into facebook as the current user.
231 if ($fb_app = $GLOBALS['fb_app'])
232 if ($values['fb_app_nid'] == FB_APP_CURRENT ||
233 $fb_app->nid == $values['fb_app_nid'])
234 // We're in a canvas page for the desired app. We're already logged in.
235 $fb = $GLOBALS['fb'];
236 if (!$fb && $values['fb_app_nid'] != FB_APP_CURRENT) {
237 // Need to log into this app.
238 $fb_app = fb_get_app(array('nid' => $values['fb_app_nid']));
239 $fb = fb_api_init($fb_app, FB_FBU_INFINITE_SESSION);
240 }
241
242 // This will be set on canvas pages and Facebook App cron actions.
243 if ($fb && $fb_app) {
244 // Replace fb_app related tokens
245 $body = token_replace($values['body'], 'fb_app', $fb_app);
246
247 $body = check_markup($body, $values['body_filter'], FALSE);
248 if ($fb_app->canvas && function_exists('fb_canvas_process_fbml')) {
249 $body = fb_canvas_process_fbml($body, $fb_app);
250 }
251 if (variable_get('fb_actions_verbose', FALSE))
252 watchdog('fb_actions', 'Setting Facebook ref FBML for %handle to %body',
253 array('%handle' => $values['handle'],
254 '%body' => htmlentities($body)));
255 $fb->api_client->fbml_setRefHandle($values['handle'], $body);
256 fb_report_errors($fb);
257 }
258 }
259
260
261 function fb_actions_cron_per_user_form($values) {
262 $form['description'] = array('#value' => t('This action will iterate through user\'s of a Facebook Application, attempt to log into the Facebook API as that user (or failing that, the infinite session user), and execute additional actions. Use this to perform per-user actions during a Facebook cron job.'));
263
264 $options = fb_get_app_options(FALSE);
265 $form['fb_app_nids'] =
266 array('#type' => 'select',
267 '#title' => t('Application'),
268 '#multiple' => TRUE,
269 '#required' => TRUE,
270 '#default_value' => $values['fb_app_nids'],
271 '#options' => $options,
272 '#description' => t('Perform these actions for each user of which applications?'),
273 );
274
275 foreach (actions_get_all_actions() as $aid => $action) {
276 $options[$action['type']][$aid] = $action['description'];
277 }
278 $form['actions'] = array('#type' => 'select',
279 '#title' => t('Actions'),
280 '#default_value' => $values['actions'],
281 '#multiple' => TRUE,
282 '#required' => TRUE,
283 '#options' => $options,
284 '#description' => t('Select one or more actions to perform while logged in as a Facebook Application user.'),
285 );
286 $form['throttle'] = array('#type' => 'textfield',
287 '#title' => t('Throttle'),
288 '#default_value' => $values['throttle'],
289 '#required' => TRUE,
290 '#description' => t('Number of users to iterate through each time this action is invoked. Recommended: start with a small number and increase when you are sure things are working.'),
291 );
292 return $form;
293 }
294
295 function fb_actions_cron_per_user_submit($form_id, $values) {
296 return array('fb_app_nids' => $values['fb_app_nids'],
297 'actions' => $values['actions'],
298 'throttle' => $values['throttle'],
299 );
300 }
301
302 /**
303 * Trigger an action several times, emulating a different user each
304 * time. Useful for cron jobs in which we update each users profile
305 * box, for example.
306 */
307 function fb_actions_cron_per_user($obj, $values) {
308 //$args = func_get_args();
309 //watchdog('fb_action_debug', "fb_actions_cron_per_user" . dpr($args, 1), WATCHDOG_ERROR);
310
311 foreach ($values['fb_app_nids'] as $nid) {
312 $fb_app = fb_get_app(array('nid' => $nid));
313 // Set paths as if on a canvas page.
314
315 // perform per-user actions by manipulating the global user variable.
316 $save_session = session_save_session();
317 session_save_session(FALSE);
318 // Save current settings
319 $before_fb = $GLOBALS['fb'];
320 $before_fb_app = $GLOBALS['fb_app'];
321 $before_user = $GLOBALS['user'];
322
323 // Find some users of the app, for whom cron has not run recently.
324 $result = db_query("SELECT * FROM {fb_user_app} WHERE apikey='%s' AND fbu > 0 AND added > 0 ORDER BY time_cron ASC LIMIT %d",
325 $fb_app->apikey,
326 $values['throttle']);
327 while ($data = db_fetch_object($result)) {
328 // Find a local account for the application user
329 $account = fb_user_get_local_user($data->fbu, $fb_app);
330 if (variable_get('fb_actions_verbose', FALSE))
331 watchdog('fb_action_debug', "fb_actions_cron_per_user fbu is $data->fbu, local user is " . theme('username', $account), array(), WATCHDOG_ERROR);
332
333 if (!$account || !$account->uid) {
334 watchdog('fb cron', 'Facebook user %fbu does not correspond to a local account.',
335 array('%fbu' => $data->fbu));
336 //db_query("DELETE FROM {fb_user_app} WHERE apikey='%s' AND fbu = %d",
337 // $fb_app->apikey,
338 // $data->fbu);
339 }
340 else {
341 // If here, local user has been found.
342 // The older facebook API required us to log in as the current user.
343 // In the new API we should not need a user account to perform tasks appropriate for cron jobs.
344 $fb = fb_api_init($fb_app, FB_FBU_CURRENT);
345 if ($fb) {
346 // Set things up as if this were a canvas page.
347 $GLOBALS['user'] = $account;
348 $GLOBALS['fb'] = $fb;
349 $GLOBALS['fb_app'] = $fb_app;
350
351 // Invoke any actions that we've been configured to invoke.
352 try {
353 actions_do($values['actions'], $fb_app,
354 array('fb' => $fb,
355 'fb_app' => $fb_app));
356 } catch (Exception $e) {
357 watchdog('fb cron', "Action per user failed. " . $e->getMessage(), array(), WATCHDOG_ERROR);
358 }
359
360 } // end if able to log into facebook
361 } // end if local user found.
362
363 // Record how recently cron was run for this user. We do this even if
364 // we failed to log in, because we don't want persistent problems to
365 // clog the cron queue. We'll get to this user again, eventually.
366 db_query("UPDATE {fb_user_app} SET time_cron=%d WHERE apikey='%s' AND fbu=%d",
367 time(), $fb_app->apikey, $data->fbu);
368
369 } // end loop per user
370
371 // Restore global variables
372 $GLOBALS['user'] = $before_user;
373 $GLOBALS['fb'] = $before_fb;
374 $GLOBALS['fb_app'] = $before_fb_app;
375 session_save_session($save_session);
376
377 }
378 }
379
380
381 ?>

  ViewVC Help
Powered by ViewVC 1.1.2