| 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
|