/[drupal]/contributions/modules/upcomingorg/upcomingorg.module
ViewVC logotype

Contents of /contributions/modules/upcomingorg/upcomingorg.module

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


Revision 1.19 - (show annotations) (download) (as text)
Tue Mar 20 00:36:49 2007 UTC (2 years, 8 months ago) by karens
Branch: MAIN
CVS Tags: HEAD
Changes since 1.18: +328 -309 lines
File MIME type: text/x-php
A first pass at getting the module updated for Drupal 4.7 and 5.x code changes and for changes in the Upcoming.org API. The module was written in mid-2005 and never updated, so there are lots of changes needed. Not yet tested and debugged, not ready for production.
1 <?php
2 /* $Id: upcomingorg.module,v 1.18 2005/10/31 23:12:37 sjaensch Exp $ */
3
4 /**
5 * Create constant for the Upcoming.org rest url.
6 * This was originally http://upcoming.org/services/rest/, but has been
7 * changed to http://upcoming.yahooapis.com/services/rest/.
8 */
9 define('UPCOMINGORG_REST', 'http://upcoming.yahooapis.com/services/rest/');
10
11 define('UPCOMINGORG_PATH', drupal_get_path('module', 'upcomingorg'));
12 include_once(UPCOMINGORG_PATH.'/upcomingorg.inc');
13
14 /**
15 * Helper class to parse XML into an array structure. Taken from http://www.php.net/xml_parse.
16 * Slightly modified to prevent the special array member for data from clashing with XML tag names
17 * and to have tag and attribute names lowercased.
18 */
19 class _XML2Array {
20
21 var $stack=array();
22 var $stack_ref;
23 var $arrOutput = array();
24 var $resParser;
25 var $strXmlData;
26
27 function push_pos(&$pos) {
28 $this->stack[count($this->stack)]=&$pos;
29 $this->stack_ref=&$pos;
30 }
31
32 function pop_pos() {
33 unset($this->stack[count($this->stack)-1]);
34 $this->stack_ref=&$this->stack[count($this->stack)-1];
35 }
36
37 function parse($strInputXML) {
38 $this->resParser = drupal_xml_parser_create($strInputXML);
39 xml_set_object($this->resParser, $this);
40 xml_set_element_handler($this->resParser, 'tagOpen', 'tagClosed');
41
42 xml_set_character_data_handler($this->resParser, 'tagData');
43
44 $this->push_pos($this->arrOutput);
45
46 $this->strXmlData = xml_parse($this->resParser,$strInputXML );
47 if(!$this->strXmlData) {
48 die(sprintf('XML error: %s at line %d',
49 xml_error_string(xml_get_error_code($this->resParser)),
50 xml_get_current_line_number($this->resParser)));
51 }
52
53 xml_parser_free($this->resParser);
54
55 return $this->arrOutput;
56 }
57
58 function tagOpen($parser, $name, $attrs) {
59 $name = strtolower($name);
60 $lowerattrs = array();
61 foreach ($attrs as $key => $value) {
62 $lowerattrs[strtolower($key)] = $value;
63 }
64 $attrs = $lowerattrs;
65
66 if (isset($this->stack_ref[$name])) {
67 if (!isset($this->stack_ref[$name][0])) {
68 $tmp=$this->stack_ref[$name];
69 unset($this->stack_ref[$name]);
70 $this->stack_ref[$name][0] = $tmp;
71 }
72 $cnt=count($this->stack_ref[$name]);
73 $this->stack_ref[$name][$cnt]=array();
74 if (isset($attrs))
75 $this->stack_ref[$name][$cnt] = $attrs;
76 $this->push_pos($this->stack_ref[$name][$cnt]);
77 }
78 else {
79 $this->stack_ref[$name]=array();
80 if (isset($attrs))
81 $this->stack_ref[$name] = $attrs;
82 $this->push_pos($this->stack_ref[$name]);
83 }
84 }
85
86 function tagData($parser, $tagData) {
87 if(trim($tagData) != '') {
88 if(isset($this->stack_ref['_data']))
89 $this->stack_ref['_data'] .= $tagData;
90 else
91 $this->stack_ref['_data'] = $tagData;
92 }
93 }
94
95 function tagClosed($parser, $name) {
96 $this->pop_pos();
97 }
98 }
99
100 function upcomingorg_user_info() {
101 global $user;
102 $result = db_fetch_array(db_query('SELECT * FROM {upcomingorg_user} WHERE uid=%d', $user->uid));
103 if (!db_affected_rows()) {
104 drupal_set_message(t('You did not set up your Upcoming.org user integration. You can do this on the <a href="!url">user settings page</a>.', array('!url' => url('user/'. $user->uid .'/upcomingorg'), 'error')));
105 return array();
106 }
107 return $result;
108 }
109
110 function upcomingorg_is_setup() {
111 if (variable_get('upcomingorg_apikey', '') == '' || variable_get('upcomingorg_event_nodetype', '') == '' || variable_get('upcomingorg_venue_nodetype', '') == '') {
112 if (user_access('administer upcomingorg')) {
113 drupal_set_message(t('You did not set up the Upcoming.org site integration. You can do this on the <a href="!url">site settings page</a>.', array('!url' => url('admin/settings/upcomingorg'), 'error')));
114 }
115 else {
116 drupal_set_message(t('The Upcoming.org site integration has not yet been set up.'), 'error');
117 }
118 return FALSE;
119 }
120 return TRUE;
121 }
122
123 function _check_module_requirements() {
124 global $user;
125 if (!$user->uid) {
126 return t('You need to be logged in to use the Upcoming.org module.');
127 }
128 if (!module_exists('event')) {
129 return t('This module depends on the event module and will not work without it. Please see the INSTALL.txt file for further instructions.');
130 }
131 if (!module_exists('location')) {
132 return t('This module depends on the location module and will not work without it. Please see the INSTALL.txt file for further instructions.');
133 }
134 }
135
136 /*
137 * Stub for menu callback
138 */
139 function _upcomingorg_all() {
140 $error = _check_module_requirements();
141 if ($error)
142 return $error;
143 return drupal_get_form('_upcomingorg_all_form');
144 } // function _upcomingorg_all
145
146 function _upcomingorg_all_form() {
147 $form = array();
148 if (upcomingorg_is_setup() && upcomingorg_user_info()) {
149 $form['#value'] = '<div>'.t('Import events and venues from your Upcoming.org watchlist.') .'</div>';
150 $form['submit'] = array('#type' => 'submit', '#value' => t('Start import'));
151 }
152 return $form;
153 } // function _upcomingorg_all_form
154
155 function _upcomingorg_all_form_submit($form_id, $form_values) {
156 $success = upcomingorg_import_events() and upcomingorg_import_categories();
157 if ($success)
158 drupal_set_message(t('Your events and venues have been imported.'));
159 }
160
161 function upcomingorg_import_events() {
162 global $user;
163
164 $data = upcomingorg_user_info();
165 $api_key = rawurlencode(variable_get('upcomingorg_apikey', ''));
166 $user_id = rawurlencode($data['upcomingorg_user_id']);
167 $token = $data['upcomingorg_token'];
168 $rest_url = $data['upcomingorg_rest_url'];
169
170 // get the data
171 $url = $rest_url ."?api_key=". $api_key ."&method=user.getWatchlist&user_id=". $user_id ."&token=". $token;
172 $response = drupal_http_request($url);
173
174 if ($response->error) {
175 drupal_set_message(t('Error connecting to upcoming.org server: %msg', array('%msg' => $response->code." ".$response->error)));
176 return FALSE;
177 }
178
179 $parser = new _XML2Array();
180 $result = $parser->parse($response->data);
181
182 $result = $result['rsp'];
183
184 if ($result['event']) {
185 $events = $result['event'];
186 if ($events['id']) {
187 // only one result
188 $events = array($events);
189 }
190
191 $venues_to_update = array();
192 foreach ($events as $event) {
193 $event['event_start'] = strtotime($event['start_date'].' '.$event['start_time']);
194 if (($event['end_date'] and $event['end_date'] != '0000-00-00' and $event['end_date'] != '0') or $event['end_time']) {
195 $str = ($event['end_date'] ? $event['end_date'] : $event['start_date']).' '.$event['end_time'];
196 $event['event_end'] = strtotime($str);
197 } else {
198 $event['event_end'] = 0;
199 }
200
201 $event['venue_nid'] = db_result(db_query('SELECT nid from {upcomingorg_venue} WHERE venue_id=%d', $event['venue_id']));
202 if (!$event['venue_nid']) {
203 #die("Need to import venue $event[venue_id]");
204 $event['venue_nid'] = upcomingorg_import_venue($event['venue_id']);
205 if (!$event['venue_nid']) {
206 return FALSE;
207 }
208 } else {
209 // Mark this venue as needing an update. This way we get a list of all the users' used venues
210 // that have not been imported above (because they were already previously imported).
211 $venues_to_update[$event['venue_id']] = TRUE;
212 }
213
214 $event['is_imported'] = 1;
215 upcomingorg_save_event($event);
216 }
217
218 foreach ($venues_to_update as $id => $value) {
219 $result = upcomingorg_import_venue($id);
220 if (!$result) {
221 return FALSE;
222 }
223 }
224 }
225
226 return TRUE;
227 } // function upcomingorg_import_events
228
229
230 function upcomingorg_import_venue($venue_id) {
231 global $user;
232
233 $data = upcomingorg_user_info();
234 $api_key = rawurlencode(variable_get('upcomingorg_apikey', ''));
235 $rest_url = rawurlencode($data['upcomingorg_rest_url']);
236
237 // get the data
238 $response = drupal_http_request($rest_url."?api_key=$api_key&method=venue.getInfo&venue_id=".intval($venue_id));
239
240 if ($response->error) {
241 drupal_set_message(t('Error connecting to upcoming.org server: %msg', array('%msg' => $response->code." ".$response->error)));
242 return FALSE;
243 }
244
245 $parser = new _XML2Array(); // needs to be re-instantiated for every parsed document
246 $xml_result = $parser->parse($response->data);
247 $xml_result = $xml_result['rsp'];
248
249 $nid = FALSE;
250 if ($xml_result['venue']) {
251 $venue = $xml_result['venue'];
252 $venue['is_imported'] = 1;
253 $nid = upcomingorg_save_venue($venue);
254 }
255
256 if (!$nid) {
257 drupal_set_message(t('Error importing venue with ID %id', array('%id' => $venue['id'])));
258 }
259 return $nid;
260 }
261
262
263 function upcomingorg_import_categories() {
264 global $user;
265
266 $data = upcomingorg_user_info();
267 $api_key = rawurlencode(variable_get('upcomingorg_apikey', ''));
268 $rest_url = rawurlencode($data['upcomingorg_rest_url']);
269 // get the data
270 $response = drupal_http_request($rest_url."?api_key=$api_key&method=category.getList");
271
272 if ($response->error) {
273 drupal_set_message(t('Error connecting to upcoming.org server: %msg', array('%msg' => $response->code." ".$response->error)));
274 return FALSE;
275 }
276
277 db_query('DELETE FROM {upcomingorg_category}');
278
279 $parser = new _XML2Array();
280 $result = $parser->parse($response->data);
281
282 $result = $result['rsp'];
283
284 if ($result['category']) {
285 $categories = $result['category'];
286 if ($categories['id']) {
287 // only one result
288 $categories = array($categories);
289 }
290
291 foreach ($categories as $category) {
292 upcomingorg_save_category($category);
293 }
294 }
295
296 return TRUE;
297 } // function upcomingorg_import_categories
298
299
300 function upcomingorg_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
301 global $user;
302
303 if (variable_get('upcomingorg_event_nodetype', '') == $node->type) {
304 switch ($op) {
305 case 'insert':
306 if (!$user->uid) {
307 return;
308 }
309 db_query("INSERT INTO {upcomingorg_event} (nid, event_id, metro_id, venue_nid, token, category_id, description, tags, personal, selfpromotion, is_imported) VALUES (%d, %d, %d, %d, '%s', %d, '%s', '%s', %d, %d, %d)", $node->nid, $node->event_id, $node->metro_id, $node->venue_nid, $node->token, $node->category_id, $node->description, $node->tags, $node->personal, $node->selfpromotion, $node->is_imported);
310 break;
311
312 case 'update':
313 db_query("UPDATE {upcomingorg_event} SET metro_id=%d, venue_nid=%d, token='%s', category_id=%d, description='%s', tags='%s', personal=%d, selfpromotion=%d WHERE nid=%d", $node->metro_id, $node->venue_nid, $node->token, $node->category_id, $node->description, $node->tags, $node->personal, $node->selfpromotion, $node->nid);
314 break;
315
316 case 'delete':
317 db_query('DELETE FROM {upcomingorg_event} WHERE nid=%d', $node->nid);
318 break;
319
320 case 'load':
321 $result = db_query('SELECT e.*, v.venue_id, c.name AS category_name, c.description AS category_description FROM {upcomingorg_event} e JOIN {upcomingorg_venue} v ON e.venue_nid=v.nid LEFT OUTER JOIN {upcomingorg_category} c ON e.category_id=c.category_id WHERE e.nid=%d', $node->nid);
322 $data = db_fetch_object($result);
323 $fields = array('event_id', 'metro_id', 'venue_id', 'venue_nid', 'token', 'category_id', 'description', 'tags', 'personal', 'selfpromotion', 'is_imported', 'category_name', 'category_description');
324 foreach ($fields as $field) {
325 $node->$field = $data->$field;
326 }
327 break;
328
329 case 'view':
330 $venue = node_load($node->venue_nid);
331 $output .= '<div class="event-nodeapi"><div class="'.$node->type.'-category"><label>'.t('Category: ').'</label>'.htmlspecialchars("{$node->category_name} ({$node->category_description})").'</div></div>';
332 $output .= '<div class="event-nodeapi"><div class="'.$node->type.'-venue"><label>'.t('Venue: ').'</label>'.l($venue->location['name'], 'node/'.$venue->nid).'</div></div>';
333 $output .= '<div class="content"><p>'.htmlspecialchars($node->description).'</p></div>';
334 $node->content['upcomingorg_venue'] = array('#value' => $output);
335 return $node;
336 break;
337 }
338 }
339 else if (variable_get('upcomingorg_venue_nodetype', '') == $node->type) {
340 switch ($op) {
341 case 'insert':
342 if (!$user->uid) {
343 return;
344 }
345 db_query("INSERT INTO {upcomingorg_venue} (nid, venue_id, token, description, url, phone, private, is_imported) VALUES (%d, %d, '%s', '%s', '%s', '%s', %d, %d)", $node->nid, $node->venue_id, $node->token, $node->description, $node->url, $node->phone, $node->private, $node->is_imported);
346 break;
347
348 case 'update':
349 db_query("UPDATE {upcomingorg_venue} SET description='%s', url='%s', phone='%s', private=%d WHERE nid=%d", $node->description, $node->url, $node->phone, $node->private, $node->nid);
350 break;
351
352 case 'delete':
353 db_query('DELETE FROM {upcomingorg_venue} WHERE nid=%d', $node->nid);
354 db_query('UPDATE {upcomingorg_event} SET venue_nid=0 WHERE venue_nid=%d', $node->nid); // maybe deleting venues that are in use should be disallowed?
355 break;
356
357 case 'load':
358 $result = db_query('SELECT * FROM {upcomingorg_venue} WHERE nid=%d', $node->nid);
359 $data = db_fetch_object($result);
360 $fields = array('venue_id', 'token', 'description', 'url', 'phone', 'private', 'is_imported');
361 foreach ($fields as $field) {
362 $node->$field = $data->$field;
363 }
364 break;
365 }
366 }
367 } // function upcomingorg_nodeapi
368
369 function upcomingorg_form_alter($form_id, $form) {
370 global $user;
371 if (!$user->uid) {
372 // We need a logged-in user! This was in original code, not sure an unauthorized user could ever get this far anyway.
373 return;
374 }
375 if ($form_id == 'node_type_form') {
376 $node = (object) $form['#node'];
377 if (variable_get('upcomingorg_event_nodetype', '') == $node->type) {
378 return upcomingorg_event_form($node);
379 }
380 else if (variable_get('upcomingorg_venue_nodetype', '') == $node->type) {
381 return upcomingorg_venue_form($node);
382 }
383 }
384 } // function upcomingorg_form_alter
385
386 function upcomingorg_event_form($node) {
387 if ($node->nid) {
388 $result = db_query('SELECT * FROM {upcomingorg_event} WHERE nid=%d', $node->nid);
389 $data = db_fetch_object($result);
390 }
391 $venues = array();
392 $result = db_query('SELECT v.nid, l.name FROM {upcomingorg_venue} v JOIN {location} l ON v.nid=l.lid');
393 while ($row = db_fetch_object($result)) {
394 $venues[$row->nid] = $row->name;
395 }
396 $categories = array();
397 $result = db_query('SELECT * FROM {upcomingorg_category}');
398 while ($row = db_fetch_array($result)) {
399 $categories[$row['category_id']] = "$row[name] ($row[description])";
400 }
401 $form['category_id'] = array(
402 '#type' => 'select',
403 '#title' => t('Category'),
404 '#default_value' => $node->category_id ? $node->category_id : $data->category_id,
405 '#options' => $categories,
406 );
407 $form['description'] = array(
408 '#type' => 'textarea',
409 '#title' => t('Description'),
410 '#default_value' => $node->description ? $node->description : $data->description,
411 '#cols' => 40,
412 '#rows' => 8,
413 '#description' => t('The description of your upcoming.org event.'),
414 );
415 $form['venue_nid'] = array(
416 '#type' => 'select',
417 '#title' => t('Venue'),
418 '#default_value' => $node->venue_nid ? $node->venue_nid : $data->venue_nid,
419 '#options' => $venues,
420 '#description' => t('The venue where the event takes place.'),
421 );
422 $form['personal'] = array(
423 '#type' => 'checkbox',
424 '#title' => t('Personal/private'),
425 '#return_value' => 1,
426 '#default_value' => $node->personal ? $node->personal : $data->personal,
427 '#description' => t('Check this if the event is private (e.g. party, wedding, business lunch), leave empty if the event is public.'),
428 );
429 $form['selfpromotion'] = array(
430 '#type' => 'checkbox',
431 '#title' => t('Self-promotional'),
432 '#return_value' => 1,
433 '#default_value' => $node->selfpromotion ? $node->selfpromotion : $data->selfpromotion,
434 '#description' => t('Check this if you are organizing, promoting or performing.'),
435 );
436 return $form;
437 } // function upcomingorg_event_form
438
439 function upcomingorg_venue_form($node) {
440 if ($node->nid) {
441 $result = db_query('SELECT * FROM {upcomingorg_venue} WHERE nid=%d', $node->nid);
442 $data = db_fetch_object($result);
443 }
444 $form['description'] = array(
445 '#type' => 'textarea',
446 '#title' => t('Description'),
447 '#default_value' => $node->description ? $node->description : $data->description,
448 '#cols' => 40,
449 '#rows' => 8,
450 '#description' => t('The description of your upcoming.org venue.'),
451 );
452 $form['url'] = array(
453 '#type' => 'textfield',
454 '#title' => t('Venue URL'),
455 '#default_value' => $node->url ? $node->url : $data->url,
456 '#size' => 40,
457 '#maxlength' => 250,
458 '#description' => t('The URL of a webpage for this venue.'),
459 );
460 $form['phone'] = array(
461 '#type' => 'textfield',
462 '#title' => t('Phone number'),
463 '#default_value' => $node->phone ? $node->phone : $data->phone,
464 '#size' => 40,
465 '#maxlength' => 50,
466 '#description' => t('The phone number for this venue.'),
467 );
468 $form['private'] = array(
469 '#type' => 'checkbox',
470 '#title' => t('Personal/private'),
471 '#return_value' => 1,
472 '#default_value' => $node->private ? $node->private : $data->private,
473 '#description' => t('e.g. your apartment, home, or private space'),
474 );
475 return $form;
476 } // function upcomingorg_venue_form
477
478 function upcomingorg_menu($may_cache) {
479 global $user;
480
481 $items = array();
482 if ($may_cache) {
483 $items[] = array('path' => 'upcomingorg',
484 'title' => t('Upcoming.org'),
485 'callback' => '_upcomingorg_all',
486 'access' => $user->uid,
487 'type' => MENU_NORMAL_ITEM);
488 $items[] = array('path' => 'admin/settings/upcomingorg',
489 'title' => t('Upcoming.org'),
490 'description' => t('Site settings for Upcoming.org integration.'),
491 'callback' => 'upcomingorg_settings',
492 'access' => user_access('administer upcomingorg'),
493 'type' => MENU_NORMAL_ITEM);
494 $items[] = array('path' => 'upcomingorg/rest',
495 'title' => t('Upcoming.org REST interface'),
496 'callback' => 'upcomingorg_rest',
497 'access' => user_access('access content'),
498 'type' => MENU_CALLBACK);
499 }
500 else {
501 $items[] = array('path' => 'user/'. $user->uid .'/upcomingorg',
502 'title' => t('Upcoming.org'),
503 'description' => t('User settings for Upcoming.org integration.'),
504 'callback' => 'upcomingorg_user_settings',
505 'access' => $user->uid,
506 'type' => MENU_LOCAL_TASK,
507 'weight' => 10,
508 );
509 }
510 return $items;
511 } // function upcomingorg_menu
512
513
514 function upcomingorg_rest() {
515 global $user;
516 $user_save = $user;
517
518 if (!empty($_REQUEST['username'])) {
519 user_authenticate($_REQUEST['username'], $_REQUEST['password']);
520 }
521
522 switch ($_REQUEST['method']) {
523 case 'event.getInfo':
524 // Events not imported from upcoming.org have no event ID, don't randomly show one of those
525 // if no event ID is supplied
526 $nid = db_result(db_query("SELECT nid FROM {upcomingorg_event} WHERE event_id=%d AND event_id > 0", $_GET['event_id']));
527 if ($nid) {
528 $node = node_load($nid);
529 if (!$node->personal or $node->uid == $user->uid) {
530 $output = _upcomingorg_event2xml($node);
531 }
532 }
533 // right now (05-08-25) upcoming.org generates no error if the requested event is not found
534 $output = _upcomingorg_xml_response($output);
535 break;
536
537 case 'event.search':
538 $query = 'SELECT n.nid FROM {event} e, {upcomingorg_event} ue, node n WHERE n.nid=e.nid AND n.nid=ue.nid';
539 $params = array();
540 if ($_GET['search_text']) {
541 $query .= " AND (name LIKE '%%%s%%' OR description LIKE '%%%s%%')";
542 $params[] = $_GET['search_text'];
543 $params[] = $_GET['search_text'];
544 }
545 if ($_GET['tags']) {
546 $tags = explode(',', $_GET['tags']);
547 foreach ($tags as $tag) {
548 $query .= " AND tags LIKE '%%%s%%'";
549 $params[] = trim($tag);
550 }
551 }
552 if ($_GET['min_date']) {
553 $query = ' AND event_start >= %d';
554 $params[] = $_GET['min_date'];
555 }
556 if ($_GET['max_date']) {
557 $query = ' AND event_start <= %d';
558 $params[] = $_GET['max_date'];
559 }
560 if (isset($_GET['personal'])) {
561 $query = ' AND personal=%d';
562 $params[] = $_GET['personal'];
563 if ($_GET['personal']) {
564 // only retrieve the user's own personal events
565 $query = ' AND uid=%d';
566 $params[] = $user->uid;
567 }
568 }
569
570 $fields = array('metro_id', 'venue_id', 'selfpromotion'); // Currently searching by country or state ID is not supported
571 foreach ($fields as $field) {
572 if ($_GET[$field]) {
573 $query .= " AND $field=%d";
574 $params[] = $_GET[$field];
575 }
576 }
577
578 $orderfield = 'event_start';
579 $order = 'ASC';
580 if ($_GET['sort']) {
581 $order = (substr($_GET['sort'], -4) == 'desc') ? 'DESC' : 'ASC';
582 if (strpos($_GET['sort'], 'name') === 0) {
583 $orderfield = 'name';
584 }
585 else if (strpos($_GET['sort'], 'posted-date') === 0) {
586 $orderfield = 'created';
587 }
588 }
589 $query .= " ORDER BY $orderfield $order";
590
591 $per_page = intval($_GET['per_page']);
592 if ($per_page < 1 or $per_page > 100) {
593 $per_page = 100;
594 }
595 $page = intval($_GET['page']);
596 if ($page < 1) {
597 $page = 1;
598 }
599
600 $result = db_query_range($query, $params, $per_page*($page-1), $per_page);
601 $output = "";
602 while ($row = db_fetch_array($result)) {
603 $node = node_load($row['nid']);
604 $output .= _upcomingorg_event2xml($node);
605 }
606 $output = _upcomingorg_xml_response($output);
607 break;
608
609 case 'event.add':
610 if (!$user->uid) {
611 $output = _upcoming_xml_error('Missing valid username and/or password');
612 break;
613 }
614
615 $event = $_POST; // event.add is required to be POST
616 // Right now we just require a name, a valid venue ID and a start_date
617 $venue_id = db_result(db_query('SELECT venue_id FROM {upcomingorg_venue} WHERE venue_id=%d', $event['venue_id']));
618 if (!$venue_id) {
619 $output = _upcomingorg_xml_error('Missing valid venue id');
620 break;
621 }
622
623 if (empty($event['name'])) {
624 $output = _upcomingorg_xml_error('Missing event name');
625 break;
626 }
627
628 $event['event_start'] = strtotime($event['start_date'].' '.$event['start_time']);
629 // starting with PHP 5.1, strtotime returns FALSE on failure
630 if (empty($event['start_date']) or -1 == $event['event_start'] or FALSE === $event['event_start']) {
631 $output = _upcomingorg_xml_error('Missing valid start date');
632 break;
633 }
634 if ($event['end_date'] or $event['end_time']) {
635 $str = ($event['end_date'] ? $event['end_date'] : $event['start_date']).' '.$event['end_time'];
636 $event['event_end'] = strtotime($str);
637 } else {
638 $event['event_end'] = 0;
639 }
640
641 $event['is_imported'] = 2;
642 upcomingorg_save_event($event);
643 $output = _upcomingorg_xml_response();
644 break;
645
646 case 'user.getWatchlist':
647 // Contrary to upcoming.org, we do not require a user ID to be provided since
648 // the user already has to pass username and password
649 $result = db_query('SELECT n.nid FROM {node} n JOIN {upcomingorg_event} ue ON n.nid=ue.nid WHERE n.uid=%d', $user->uid);
650 while ($row = db_fetch_array($result)) {
651 $node = node_load($row['nid']);
652 $output .= _upcomingorg_event2xml($node);
653 }
654 $output = _upcomingorg_xml_response($output);
655 break;
656
657 case 'venue.getInfo':
658 // Venues created locally have no upcoming.org venue ID, don't randomly show one of those
659 // if no venue ID is supplied
660 $nid = db_result(db_query("SELECT nid FROM {upcomingorg_venue} WHERE venue_id=%d AND venue_id > 0", $_GET['venue_id']));
661 if ($nid) {
662 $node = node_load($nid);
663 if (!$node->private or $node->uid == $user->uid) {
664 $output = _upcomingorg_venue2xml($node);
665 }
666 }
667 // right now (05-08-27) upcoming.org generates no error if the requested venue is not found
668 $output = _upcomingorg_xml_response($output);
669 break;
670
671 default:
672 $output = _upcomingorg_xml_error('Sorry, method not implemented on this server');
673 } // switch ($_REQUEST['method'])
674
675 header('Content-type: text/xml');
676 echo $output;
677 $user = $user_save;
678 } // function upcomingorg_rest()
679
680
681 function _upcomingorg_xml_response($output='') {
682 return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rsp stat=\"ok\" version=\"1.0\">\n$output\n</rsp>\n";
683 }
684
685
686 function _upcomingorg_xml_error($errormsg='There was an error in processing your request') {
687 return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rsp stat=\"fail\">\n <error msg=\"".htmlspecialchars($errormsg)."\"/>\n</rsp>\n";
688 }
689
690
691 function _upcomingorg_event2xml($node) {
692 $start = getdate($node->event_start);
693 array_walk($start, '_upcomingorg_pad');
694
695 if ($node->event_end) {
696 $end = getdate($node->event_end);
697 array_walk($end, '_upcomingorg_pad');
698 }
699
700 $created = getdate($node->created);
701 array_walk($created, '_upcomingorg_pad');
702
703 $output = '<event id="'.$node->event_id.'" name="'.htmlspecialchars($node->title).'" tags="'.htmlspecialchars($node->tags).'" description="'.htmlspecialchars($node->tags).'" start_date="'."$start[year]-$start[mon]-$start[mday]".'"';
704 if ($end) {
705 $output .= " end_date=\"$end[year]-$end[mon]-$end[mday]\"";
706 }
707 $output .= " start_time=\"$start[hours]:$start[minutes]:$start[seconds]\" end_time=\"";
708 if ($end) {
709 $output .= "$end[hours]:$end[minutes]:$end[seconds]";
710 }
711 $output .= '"';
712 $fields = array('metro_id', 'venue_id', 'token', 'category_id');
713 foreach ($fields as $field) {
714 $output .= ' '.$field.'="'.$node->$field.'"';
715 }
716 $output .= " date_posted=\"$created[year]-$created[mon]-$created[mday]\" />\n";
717
718 return $output;
719 }
720
721
722 function _upcomingorg_venue2xml($node) {
723 $l = $node->location;
724 $output = '<venue id="'.$node->venue_id.'" name="'.htmlspecialchars($l['name']).'" address="'.htmlspecialchars($l['street']).'" city="'.htmlspecialchars($l['city']).'" zip="'.htmlspecialchars($l['postal_code']).'" phone="'.htmlspecialchars($node->phone).'" url="'.htmlspecialchars($node->url).'" description="'.htmlspecialchars($node->description).'" token="'.$node->token.'" private="'.$node->private.'"/>';
725
726 return $output;
727 }
728
729
730 /**
731 * Internal helper function for array_walk to pad dates and times.
732 */
733 function _upcomingorg_pad(&$item, $key) {
734 $item = str_pad($item, 2, '0', STR_PAD_LEFT);
735 }
736
737 function upcomingorg_user_settings() {
738 $error = _check_module_requirements();
739 if ($error)
740 return $error;
741
742 return drupal_get_form('upcomingorg_user_settings_form');
743 } // function upcoming_user_settings
744
745 function upcomingorg_user_settings_form() {
746 global $user;
747 if (!upcomingorg_is_setup()) {
748 return array();
749 }
750
751 $result = db_query('SELECT * FROM {upcomingorg_user} WHERE uid=%d', $user->uid);
752 $data = db_fetch_array($result);
753
754 // Hiding the REST url for now until there is a method for authorization for Drupal to Drupal interface.
755 $form['upcomingorg_rest_url'] = array(
756 '#type' => 'hidden',
757 '#title' => t('Upcoming.org REST URL'),
758 '#default_value' => $data['upcomingorg_rest_url'] ? $data['upcomingorg_rest_url'] : UPCOMINGORG_REST,
759 '#size' => 60,
760 '#maxlength' => 200,
761 '#description' => t('The URL of the REST interface for the Upcoming.org style server you want to connect to. For Upcoming.org itself, enter '. UPCOMINGORG_REST .'. For other Drupal-powered sites, enter http://www.example.com/upcomingorg/rest (change example.com to your domain).'),
762 '#attributes' => NULL,
763 '#required' => TRUE,
764 );
765 $form['upcomingorg_user_id'] = array(
766 '#type' => 'textfield',
767 '#title' => t('Upcoming.org User ID'),
768 '#default_value' => $data['upcomingorg_user_id'],
769 '#size' => 50,
770 '#maxlength' => 50,
771 '#description' => t('Your Upcoming.org User ID. When viewing your account on Upcoming.org you will see it in the address, as user/ID#.'),
772 '#attributes' => NULL,
773 '#required' => TRUE,
774 );
775 $form['upcomingorg_token'] = array(
776 '#type' => 'textfield',
777 '#title' => t('Upcoming.org token'),
778 '#default_value' => $data['upcomingorg_token'],
779 '#size' => 50,
780 '#maxlength' => 50,
781 '#description' => t('Your !link. Login to your Upcoming.org account, agree to allow this application to have access to your information, and paste the code you receive into this box.', array('!link' => l(t('Upcoming.org User Authorization'), 'http://upcoming.org/services/auth/?api_key='. variable_get('upcomingorg_apikey', '')))),
782 '#attributes' => NULL,
783 '#required' => TRUE,
784 );
785 $form[] = array(
786 '#type' => 'submit',
787 '#value' => t('Save configuration'),
788 );
789 return $form;
790
791 } // function upcoming_user_settings_form
792
793 function upcomingorg_user_settings_form_submit($form_id, $form_values) {
794 global $user;
795 $query = "UPDATE {upcomingorg_user} SET upcomingorg_user_id = %d, upcomingorg_rest_url = '%s', upcomingorg_token = '%s' where uid=%d";
796 db_query($query, $form_values['upcomingorg_user_id'], $form_values['upcomingorg_rest_url'], $form_values['upcomingorg_token'], $user->uid);
797 if (!db_affected_rows()) {
798 $query = "INSERT INTO {upcomingorg_user} VALUES(%d, %d, '%s', '%s')";
799 db_query($query, $user->uid, $form_values['upcomingorg_user_id'], $form_values['upcomingorg_rest_url'], $form_values['upcomingorg_token']);
800 }
801 drupal_set_message(t('The Upcoming.org user configuration options have been saved.'));
802 } // function upcoming_user_settings_form_submit
803
804 /**
805 * Valid permissions for this module
806 * @return array An array of valid permissions for the upcoming module
807 */
808 function upcomingorg_perm() {
809 return array('administer upcomingorg');
810 } // function upcomingorg_perm()
811
812
813 function upcomingorg_settings() {
814 if ($error = _check_module_requirements())
815 return $error;
816
817 return drupal_get_form('upcomingorg_settings_form');
818 } // end function upcomingorg_settings
819
820 function upcomingorg_settings_form() {
821 $form = array();
822 $form['upcomingorg_apikey'] = array(
823 '#type' => 'textfield',
824 '#title' => t('Upcoming.org API key'),
825 '#default_value' => variable_get('upcomingorg_apikey', ''),
826 '#size' => 20,
827 '#maxlength' => 20,
828 '#description' => t('The Upcoming.org API key for this site. Get one at <a href="%url">upcoming.org</a>.', array('%url' => 'http://upcoming.org/services/api/keygen.php')),
829 '#attributes' => NULL,
830 '#required' => TRUE,
831 );
832
833 $node_types = node_get_types('names');
834 $form['upcomingorg_event_nodetype'] = array(
835 '#type' => 'select',
836 '#title' => t('The node type to use for Upcoming.org events'),
837 '#default_value' => variable_get('upcomingorg_event_nodetype', ''),
838 '#options' => $node_types,
839 '#required' => TRUE,
840 );
841 $form['upcomingorg_venue_nodetype'] = array(
842 '#type' => 'select',
843 '#title' => t('The node type to use for Upcoming.org venues'),
844 '#default_value' => variable_get('upcomingorg_venue_nodetype', ''),
845 '#options' => $node_types,
846 '#description' => 'Warning: DO NOT choose the same node type as for events! This will not work!',
847 '#required' => TRUE,
848 );
849 $form['submit'] = array(
850 '#type' => 'submit',
851 '#value' => t('Submit'),
852 );
853 return $form;
854 } // end function upcomingorg_settings_form
855
856 function upcomingorg_settings_form_validate($form_id, $form_values) {
857 if ($form_values['upcomingorg_event_nodetype'] == $form_values['upcomingorg_venue_nodetype']) {
858 form_set_error('upcomingorg_venue_nodetype', t('The event node type and the venue node type cannot be the same!'));
859 }
860 }
861
862 function upcomingorg_settings_form_submit($form_id, $form_values) {
863 variable_set('upcomingorg_apikey', $form_values['upcomingorg_apikey']);
864 $event_type = variable_get('upcomingorg_event_nodetype', $form_values['upcomingorg_event_nodetype']);
865 variable_set('upcomingorg_event_nodetype', $event_type);
866 $venue_type = variable_get('upcomingorg_venue_nodetype', $form_values['upcomingorg_venue_nodetype']);
867 variable_set('upcomingorg_venue_nodetype', $venue_type);
868 // Enable display of our event node type in the event calendar
869 variable_set("event_nodeapi_$event_type", 'all');
870 // Location-enable our venue type and set appropriate variables
871 variable_set("location_$venue_type", 1);
872 variable_set("location_name_$venue_type", 2);
873 variable_set("location_street_$venue_type", 1);
874 variable_set("location_city_$venue_type", 1);
875 variable_set("location_postal_code_$venue_type", 1);
876 } // end function upcomingorg_settings_form_submit

  ViewVC Help
Powered by ViewVC 1.1.2