| 1 |
<?php
|
| 2 |
// $Id$
|
| 3 |
|
| 4 |
//////////////////////////////////////////////////////////////////////////////
|
| 5 |
// Module settings
|
| 6 |
|
| 7 |
define('EXHIBIT_DATE_FORMAT', '%Y-%m-%dT%H:%M:%SZ');
|
| 8 |
define('EXHIBIT_XMLNS_URL', 'http://simile.mit.edu/2006/11/exhibit#'); // TODO: What's this for? This needs to be updated or removed
|
| 9 |
define('EXHIBIT_JS_URL', variable_get('exhibit_js_url', 'http://api.simile-widgets.org/exhibit/2.2.0/exhibit-api.js'));
|
| 10 |
define('EXHIBIT_MAP_JS_URL', variable_get('exhibit_map_js_url', 'http://api.simile-widgets.org/exhibit/2.2.0/extensions/map/map-extension.js'));
|
| 11 |
define('EXHIBIT_BARCHART_JS_URL', variable_get('exhibit_barchart_js_url', 'http://api.simile-widgets.org/exhibit/2.2.0/extensions/chart/chart-extension.js'));
|
| 12 |
define('EXHIBIT_SCATTERPLOT_JS_URL', variable_get('exhibit_scatterplot_js_url', 'http://api.simile-widgets.org/exhibit/2.2.0/extensions/chart/chart-extension.js'));
|
| 13 |
define('EXHIBIT_TIMELINE_JS_URL', variable_get('exhibit_timeline_js_url', 'http://api.simile-widgets.org/exhibit/2.2.0/extensions/time/time-extension.js'));
|
| 14 |
define('EXHIBIT_CALENDAR_JS_URL', variable_get('exhibit_calendar_js_url', 'http://api.simile-widgets.org/exhibit/2.2.0/extensions/calendar/calendar-extension.js'));
|
| 15 |
define('EXHIBIT_FEED_LIFETIME', (int)variable_get('timeline_feed_lifetime', 0));
|
| 16 |
define('EXHIBIT_FEED_ETAG', (bool)variable_get('timeline_feed_etag', TRUE));
|
| 17 |
|
| 18 |
|
| 19 |
//////////////////////////////////////////////////////////////////////////////
|
| 20 |
// Core API hooks
|
| 21 |
|
| 22 |
/**
|
| 23 |
* Implementation of hook_help().
|
| 24 |
*/
|
| 25 |
function exhibit_help($path) {
|
| 26 |
switch ($path) {
|
| 27 |
case 'admin/help#exhibit':
|
| 28 |
return '<p>' . t('') . '</p>'; // TODO
|
| 29 |
case 'admin/settings/exhibit':
|
| 30 |
//return '<p>' . t('') . '</p>'; // TODO
|
| 31 |
}
|
| 32 |
}
|
| 33 |
|
| 34 |
/**
|
| 35 |
* Implementation of hook_perm().
|
| 36 |
*/
|
| 37 |
function exhibit_perm() {
|
| 38 |
return array(
|
| 39 |
'administer exhibit feeds',
|
| 40 |
//'use external exhibit feeds', // TODO
|
| 41 |
'access exhibits',
|
| 42 |
'create exhibits',
|
| 43 |
'edit exhibits',
|
| 44 |
'edit own exhibits',
|
| 45 |
'delete exhibits',
|
| 46 |
'delete own exhibits',
|
| 47 |
);
|
| 48 |
}
|
| 49 |
|
| 50 |
/**
|
| 51 |
* Implementation of hook_menu().
|
| 52 |
*/
|
| 53 |
function exhibit_menu() {
|
| 54 |
return array(
|
| 55 |
'node/%node/exhibit-json' => array(
|
| 56 |
'type' => MENU_CALLBACK,
|
| 57 |
'access callback' => 'user_access',
|
| 58 |
'access arguments' => array('access exhibits'),
|
| 59 |
'page callback' => 'exhibit_output_node',
|
| 60 |
'page arguments' => array(1),
|
| 61 |
'file' => 'exhibit.pages.inc',
|
| 62 |
),
|
| 63 |
'node/__history__.html' => array(
|
| 64 |
'type' => MENU_CALLBACK,
|
| 65 |
'access arguments' => array('access exhibits'),
|
| 66 |
'page callback' => 'exhibit_output_history',
|
| 67 |
'file' => 'exhibit.pages.inc',
|
| 68 |
),
|
| 69 |
'exhibit/tsv/%' => array(
|
| 70 |
'type' => MENU_CALLBACK,
|
| 71 |
'access arguments' => array('access exhibits'),
|
| 72 |
'page callback' => 'exhibit_output_convert',
|
| 73 |
'page arguments' => array(2, 'exhibit_parse_tsv', 'text/tab-separated-values'),
|
| 74 |
'file' => 'exhibit.pages.inc',
|
| 75 |
),
|
| 76 |
'exhibit/feeds/%exhibit_feed' => array(
|
| 77 |
'type' => MENU_CALLBACK,
|
| 78 |
'access arguments' => array('access exhibits'),
|
| 79 |
'page callback' => 'exhibit_output_feed',
|
| 80 |
'page arguments' => array(2),
|
| 81 |
'file' => 'exhibit.pages.inc',
|
| 82 |
),
|
| 83 |
'admin/settings/exhibit' => array(
|
| 84 |
'title' => 'Exhibits',
|
| 85 |
'description' => 'Settings for the Exhibit module.',
|
| 86 |
'access arguments' => array('administer site configuration'),
|
| 87 |
'page callback' => 'drupal_get_form',
|
| 88 |
'page arguments' => array('exhibit_admin_settings'),
|
| 89 |
'file' => 'exhibit.admin.inc',
|
| 90 |
),
|
| 91 |
'admin/content/exhibit' => array(
|
| 92 |
'title' => 'Exhibit feeds',
|
| 93 |
'access arguments' => array('administer exhibit feeds'),
|
| 94 |
'page callback' => 'exhibit_admin_feeds',
|
| 95 |
'file' => 'exhibit.admin.inc',
|
| 96 |
),
|
| 97 |
'admin/content/exhibit/list' => array(
|
| 98 |
'title' => 'List',
|
| 99 |
'type' => MENU_DEFAULT_LOCAL_TASK,
|
| 100 |
'access arguments' => array('administer exhibit feeds'),
|
| 101 |
'weight' => -10,
|
| 102 |
),
|
| 103 |
'admin/content/exhibit/add' => array(
|
| 104 |
'title' => 'Add data feed',
|
| 105 |
'type' => MENU_LOCAL_TASK,
|
| 106 |
'access arguments' => array('administer exhibit feeds'),
|
| 107 |
'page callback' => 'drupal_get_form',
|
| 108 |
'page arguments' => array('exhibit_admin_feed_form'),
|
| 109 |
'file' => 'exhibit.admin.inc',
|
| 110 |
'weight' => 10,
|
| 111 |
),
|
| 112 |
'admin/content/exhibit/edit/%exhibit_feed' => array(
|
| 113 |
'title' => 'Edit data feed',
|
| 114 |
'type' => MENU_CALLBACK,
|
| 115 |
'access arguments' => array('administer exhibit feeds'),
|
| 116 |
'page callback' => 'drupal_get_form',
|
| 117 |
'page arguments' => array('exhibit_admin_feed_form', 4),
|
| 118 |
'file' => 'exhibit.admin.inc',
|
| 119 |
),
|
| 120 |
'admin/content/exhibit/delete/%exhibit_feed' => array(
|
| 121 |
'title' => 'Delete data feed',
|
| 122 |
'type' => MENU_CALLBACK,
|
| 123 |
'access arguments' => array('administer exhibit feeds'),
|
| 124 |
'page callback' => 'drupal_get_form',
|
| 125 |
'page arguments' => array('exhibit_admin_feed_delete', 4),
|
| 126 |
'file' => 'exhibit.admin.inc',
|
| 127 |
),
|
| 128 |
);
|
| 129 |
}
|
| 130 |
|
| 131 |
/**
|
| 132 |
* Implementation of hook_block().
|
| 133 |
*/
|
| 134 |
function exhibit_block($op = 'list', $delta = 0, $edit = array()) {
|
| 135 |
switch ($op) {
|
| 136 |
case 'list':
|
| 137 |
return array('facets' => array('info' => t('Exhibit facets')));
|
| 138 |
case 'view':
|
| 139 |
switch ($delta) {
|
| 140 |
case 'facets':
|
| 141 |
if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) != 'edit') {
|
| 142 |
$node = node_load(arg(1));
|
| 143 |
$block['content'] = $node->exhibit['facet_definition'];
|
| 144 |
}
|
| 145 |
break;
|
| 146 |
}
|
| 147 |
return $block;
|
| 148 |
}
|
| 149 |
}
|
| 150 |
|
| 151 |
/**
|
| 152 |
* Implementation of hook_theme().
|
| 153 |
*/
|
| 154 |
function exhibit_theme() {
|
| 155 |
return array(
|
| 156 |
'exhibit_definition' => array(
|
| 157 |
'arguments' => array('node' => NULL),
|
| 158 |
),
|
| 159 |
);
|
| 160 |
}
|
| 161 |
|
| 162 |
//////////////////////////////////////////////////////////////////////////////
|
| 163 |
// Node API hooks
|
| 164 |
|
| 165 |
/**
|
| 166 |
* Implementation of hook_node_info().
|
| 167 |
*/
|
| 168 |
function exhibit_node_info() {
|
| 169 |
return array(
|
| 170 |
'exhibit' => array(
|
| 171 |
'name' => t('Exhibit'),
|
| 172 |
'module' => 'exhibit', //_node',
|
| 173 |
'description' => t('An <em>exhibit</em> displays structured data in the form of rich visualizations that can be searched, filtered and sorted using faceted browsing.'),
|
| 174 |
'has_title' => TRUE,
|
| 175 |
'title_label' => t('Title'),
|
| 176 |
'has_body' => TRUE,
|
| 177 |
'body_label' => t('Description'),
|
| 178 |
),
|
| 179 |
);
|
| 180 |
}
|
| 181 |
|
| 182 |
/**
|
| 183 |
* Implementation of hook_access().
|
| 184 |
*/
|
| 185 |
function exhibit_access($op, $node) {
|
| 186 |
switch ($op) {
|
| 187 |
case 'view':
|
| 188 |
return user_access('access exhibits');
|
| 189 |
case 'create':
|
| 190 |
return user_access('create exhibits');
|
| 191 |
case 'update':
|
| 192 |
global $user;
|
| 193 |
return user_access('edit exhibits') || (user_access('edit own exhibits') && $user->uid == $node->uid);
|
| 194 |
case 'delete':
|
| 195 |
global $user;
|
| 196 |
return user_access('delete exhibits') || (user_access('delete own exhibits') && $user->uid == $node->uid);
|
| 197 |
}
|
| 198 |
}
|
| 199 |
|
| 200 |
/**
|
| 201 |
* Implementation of hook_load().
|
| 202 |
*/
|
| 203 |
function exhibit_load($node) {
|
| 204 |
$exhibit = db_fetch_array(db_query('SELECT * FROM {exhibit_nodes} WHERE vid = %d', $node->vid));
|
| 205 |
$exhibit['feeds'] = explode(',', $exhibit['feeds']);
|
| 206 |
return (object)array('exhibit' => $exhibit);
|
| 207 |
}
|
| 208 |
|
| 209 |
/**
|
| 210 |
* Implementation of hook_validate().
|
| 211 |
*/
|
| 212 |
function exhibit_validate(&$node) {}
|
| 213 |
|
| 214 |
/**
|
| 215 |
* Implementation of hook_insert().
|
| 216 |
*/
|
| 217 |
function exhibit_insert($node) {
|
| 218 |
$node->exhibit['feeds'] = implode(',', array_filter(array_values($node->exhibit['feeds']), 'trim'));
|
| 219 |
db_query("INSERT INTO {exhibit_nodes} (nid, vid, feeds, definition, facet_definition) VALUES (%d, %d, '%s', '%s', '%s')", $node->nid, $node->vid, $node->exhibit['feeds'], $node->exhibit['definition'], $node->exhibit['facet_definition']);
|
| 220 |
}
|
| 221 |
|
| 222 |
/**
|
| 223 |
* Implementation of hook_update().
|
| 224 |
*/
|
| 225 |
function exhibit_update($node) {
|
| 226 |
if ($node->revision) {
|
| 227 |
return exhibit_insert($node);
|
| 228 |
}
|
| 229 |
$node->exhibit['feeds'] = implode(',', array_filter(array_values($node->exhibit['feeds']), 'trim'));
|
| 230 |
db_query("UPDATE {exhibit_nodes} SET feeds = '%s', definition = '%s', facet_definition = '%s' WHERE vid = %d", $node->exhibit['feeds'], $node->exhibit['definition'], $node->exhibit['facet_definition'], $node->vid);
|
| 231 |
}
|
| 232 |
|
| 233 |
/**
|
| 234 |
* Implementation of hook_delete().
|
| 235 |
*/
|
| 236 |
function exhibit_delete($node) {
|
| 237 |
db_query('DELETE FROM {exhibit_nodes} WHERE nid = %d', $node->nid);
|
| 238 |
}
|
| 239 |
|
| 240 |
/**
|
| 241 |
* Implementation of hook_nodeapi().
|
| 242 |
*/
|
| 243 |
function exhibit_nodeapi(&$node, $op, $teaser, $page) {
|
| 244 |
switch ($op) {
|
| 245 |
case 'delete revision':
|
| 246 |
db_query('DELETE FROM {exhibit_nodes} WHERE vid = %d', $node->vid);
|
| 247 |
break;
|
| 248 |
}
|
| 249 |
}
|
| 250 |
|
| 251 |
/**
|
| 252 |
* Implementation of hook_form().
|
| 253 |
*/
|
| 254 |
function exhibit_form(&$node, &$param) {
|
| 255 |
drupal_add_js(drupal_get_path('module', 'exhibit') .'/exhibit.js');
|
| 256 |
drupal_add_js(array('exhibit' => exhibit_get_feeds('url')), 'setting');
|
| 257 |
|
| 258 |
$type = node_get_types('type', $node);
|
| 259 |
|
| 260 |
if ($type->has_title) {
|
| 261 |
$form['title'] = array('#type' => 'textfield', '#title' => check_plain($type->title_label), '#required' => TRUE, '#default_value' => $node->title, '#weight' => -5);
|
| 262 |
}
|
| 263 |
|
| 264 |
if ($type->has_body) {
|
| 265 |
// FIXME: this works around a bug in node_submit(), lines 782-793, which
|
| 266 |
// causes the body field to be emptied when not using node_body_field()
|
| 267 |
// to generate the body and format fieldset. Need to submit a core patch.
|
| 268 |
$form['teaser_include'] = array('#type' => 'hidden', '#value' => '1');
|
| 269 |
|
| 270 |
$form['body_filter'] = array('#type' => 'fieldset', '#title' => check_plain($type->body_label), '#collapsible' => TRUE, '#collapsed' => TRUE);
|
| 271 |
$form['body_filter']['body'] = array('#type' => 'textarea', '#title' => t('Description'), '#default_value' => $node->body, '#required' => ($type->min_word_count > 0), '#rows' => 2);
|
| 272 |
$form['body_filter']['format'] = filter_form($node->format);
|
| 273 |
}
|
| 274 |
|
| 275 |
$form['exhibit'] = array('#type' => 'fieldset', '#title' => t('Exhibit'), '#collapsible' => TRUE, '#collapsed' => FALSE, '#tree' => TRUE);
|
| 276 |
$form['exhibit']['feeds'] = array('#type' => 'checkboxes', '#title' => t('Data feeds'), '#default_value' => !empty($node->exhibit['feeds']) ? $node->exhibit['feeds'] : array(), '#options' => exhibit_get_feeds('title'), '#attributes' => array('class' => 'exhibit-feed-checkbox'), '#prefix' => '<div id="feed-field-selection">', '#suffix' => '</div>');
|
| 277 |
$form['exhibit']['definition'] = array('#type' => 'textarea', '#title' => t('Definition'), '#default_value' => !empty($node->exhibit['definition']) ? $node->exhibit['definition'] : theme('exhibit_definition'), '#rows' => 10);
|
| 278 |
$form['exhibit']['facet_definition'] = array('#type' => 'textarea', '#title' => t('Facet definition'), '#default_value' => @$node->exhibit['facet_definition'], '#rows' => 5);
|
| 279 |
$form['exhibit']['facet-generator-form-wrapper'] = array('#type' => 'fieldset', '#title' => t('Facet Generator'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#tree' => TRUE, '#attributes' => array('id' => 'exhibit-facet-builder', 'style' => 'display:none;'), '#value' => '<div id="facet-generator-form"></div>');
|
| 280 |
|
| 281 |
return $form;
|
| 282 |
}
|
| 283 |
|
| 284 |
/**
|
| 285 |
* Implementation of hook_view().
|
| 286 |
*/
|
| 287 |
function exhibit_view($node, $teaser = FALSE, $page = FALSE) {
|
| 288 |
// Load the SIMILE Exhibit API and any enabled extensions
|
| 289 |
drupal_set_html_head('<script type="text/javascript" src="'. EXHIBIT_JS_URL .'"></script>'."\n");
|
| 290 |
|
| 291 |
// Load any enabled Exhibit extensions
|
| 292 |
foreach (exhibit_exhibit_views() as $id => $view) {
|
| 293 |
if (variable_get('exhibit_extensions_'. $id, FALSE)) {
|
| 294 |
drupal_set_html_head('<script type="text/javascript" src="'. $view['href'] .'"></script>'."\n");
|
| 295 |
}
|
| 296 |
}
|
| 297 |
|
| 298 |
// Insert <LINK> references to all enabled data feeds
|
| 299 |
foreach ($node->exhibit['feeds'] as $fid) {
|
| 300 |
if ($feed = exhibit_feed_load($fid)) {
|
| 301 |
exhibit_add_feed(exhibit_get_feed_url($feed), check_plain($feed['type']));
|
| 302 |
}
|
| 303 |
}
|
| 304 |
|
| 305 |
$node = node_prepare($node, $teaser);
|
| 306 |
$node->content['exhibit'] = array('#value' => $node->exhibit['definition'], '#weight' => 1);
|
| 307 |
return $node;
|
| 308 |
}
|
| 309 |
|
| 310 |
//////////////////////////////////////////////////////////////////////////////
|
| 311 |
// Views API hooks
|
| 312 |
|
| 313 |
/**
|
| 314 |
* Implementation of hook_views_api().
|
| 315 |
*/
|
| 316 |
function exhibit_views_api() {
|
| 317 |
return array(
|
| 318 |
'api' => 2,
|
| 319 |
'path' => drupal_get_path('module', 'exhibit'),
|
| 320 |
);
|
| 321 |
}
|
| 322 |
|
| 323 |
//////////////////////////////////////////////////////////////////////////////
|
| 324 |
// Exhibit API hooks
|
| 325 |
|
| 326 |
/**
|
| 327 |
* Implementation of hook_exhibit_views().
|
| 328 |
*/
|
| 329 |
function exhibit_exhibit_views() {
|
| 330 |
return array(
|
| 331 |
'tile' => array(
|
| 332 |
'title' => t('Tile (default)'),
|
| 333 |
'class' => '',
|
| 334 |
),
|
| 335 |
'thumbnail' => array(
|
| 336 |
'title' => t('Thumbnail'),
|
| 337 |
'class' => 'Thumbnail',
|
| 338 |
),
|
| 339 |
'map' => array(
|
| 340 |
'title' => t('Map'),
|
| 341 |
'class' => 'Map',
|
| 342 |
'href' => variable_get('exhibit_extensions_map_api', EXHIBIT_MAP_JS_URL) . '?gmapkey=' . (module_exists('gmap') ? gmap_get_key() : variable_get('exhibit_gmap_key', '')),
|
| 343 |
),
|
| 344 |
'barchart' => array(
|
| 345 |
'title' => t('Barchart'),
|
| 346 |
'class' => 'Barchart',
|
| 347 |
'href' => variable_get('exhibit_extensions_barchart_api', EXHIBIT_BARCHART_JS_URL),
|
| 348 |
),
|
| 349 |
'scatterplot' => array(
|
| 350 |
'title' => t('Scatterplot'),
|
| 351 |
'class' => 'Scatterplot',
|
| 352 |
'href' => variable_get('exhibit_extensions_scatterplot_api', EXHIBIT_SCATTERPLOT_JS_URL),
|
| 353 |
),
|
| 354 |
'timeline' => array(
|
| 355 |
'title' => t('Timeline'),
|
| 356 |
'class' => 'Timeline',
|
| 357 |
'href' => variable_get('exhibit_extensions_timeline_api', EXHIBIT_TIMELINE_JS_URL),
|
| 358 |
),
|
| 359 |
'calendar' => array(
|
| 360 |
'title' => t('Calendar'),
|
| 361 |
'class' => 'Calendar',
|
| 362 |
'href' => variable_get('exhibit_extensions_calendar_api', EXHIBIT_CALENDAR_JS_URL),
|
| 363 |
),
|
| 364 |
'tabular' => array(
|
| 365 |
'title' => t('Tabular'),
|
| 366 |
'class' => 'Tabular',
|
| 367 |
),
|
| 368 |
);
|
| 369 |
}
|
| 370 |
|
| 371 |
//////////////////////////////////////////////////////////////////////////////
|
| 372 |
// Exhibit API functions
|
| 373 |
|
| 374 |
function exhibit_add_link($url) {
|
| 375 |
drupal_add_link(array('rel' => 'meta', 'type' => 'application/json', 'title' => 'Exhibit JSON', 'href' => exhibit_get_url($url)));
|
| 376 |
}
|
| 377 |
|
| 378 |
function exhibit_get_url($url) {
|
| 379 |
if (exhibit_is_link_internal($url)) {
|
| 380 |
$url_parts = parse_url($url);
|
| 381 |
// Handle views args
|
| 382 |
if (isset($_GET['args'])) {
|
| 383 |
$url_parts['path'] = preg_replace('/\%/', $_GET['args'], $url_parts['path']);
|
| 384 |
}
|
| 385 |
if (empty($url_parts['query'])) {
|
| 386 |
return url($url_parts['path']);
|
| 387 |
}
|
| 388 |
else {
|
| 389 |
return url($url_parts['path'], array('query' => $url_parts['query']));
|
| 390 |
}
|
| 391 |
}
|
| 392 |
else {
|
| 393 |
return url($url, array('external' => TRUE));
|
| 394 |
}
|
| 395 |
}
|
| 396 |
|
| 397 |
function exhibit_is_link_internal($url) {
|
| 398 |
return (bool)!preg_match('!^[\w\d\+\-]+://!', $url);
|
| 399 |
}
|
| 400 |
|
| 401 |
function exhibit_add_feed($url, $type = 'application/json') {
|
| 402 |
switch ($type) {
|
| 403 |
case 'application/vnd.google-spreadsheet': // special case
|
| 404 |
drupal_add_link(array('rel' => 'exhibit/data', 'href' => $url, 'type' => 'application/jsonp', 'ex:converter' => 'googleSpreadsheets'));
|
| 405 |
break;
|
| 406 |
default:
|
| 407 |
drupal_add_link(array('rel' => 'exhibit/data', 'href' => $url, 'type' => $type));
|
| 408 |
break;
|
| 409 |
}
|
| 410 |
}
|
| 411 |
|
| 412 |
function exhibit_feed_load($fid) {
|
| 413 |
if (is_numeric($fid)) {
|
| 414 |
return db_fetch_array(db_query('SELECT f.* FROM {exhibit_feeds} f WHERE f.fid = %d', $fid));
|
| 415 |
}
|
| 416 |
else {
|
| 417 |
if (module_exists('views')) {
|
| 418 |
$views = views_get_all_views();
|
| 419 |
foreach ($views as $view) {
|
| 420 |
// Skip disabled views or broken views
|
| 421 |
if (!empty($view->disabled) || empty($view->display)) {
|
| 422 |
continue;
|
| 423 |
}
|
| 424 |
|
| 425 |
// Check each display, add those using the Exhibit JSON style plugin
|
| 426 |
foreach (array_keys($view->display) as $id) {
|
| 427 |
$plugin = views_fetch_plugin_data('display', $view->display[$id]->display_plugin);
|
| 428 |
$display_options = $view->display[$id]->display_options;
|
| 429 |
if ($plugin['handler'] == 'views_plugin_display_feed' && $display_options['style_plugin'] == 'exhibit_json') {
|
| 430 |
$view_feed_id = $view->vid . '_' . $id;
|
| 431 |
if ($view_feed_id == $fid) {
|
| 432 |
return array('fid' => $view_feed_id,
|
| 433 |
'module' => 'views',
|
| 434 |
'title' => $view->name . ': ' . $view->display[$id]->display_title,
|
| 435 |
'enabled' => TRUE,
|
| 436 |
'cache' => FALSE,
|
| 437 |
'type' => 'application/json',
|
| 438 |
'url' => $display_options['path']);
|
| 439 |
}
|
| 440 |
}
|
| 441 |
}
|
| 442 |
}
|
| 443 |
}
|
| 444 |
}
|
| 445 |
}
|
| 446 |
|
| 447 |
function exhibit_get_feeds($key = NULL) {
|
| 448 |
$feeds = array();
|
| 449 |
$result = db_query('SELECT f.* FROM {exhibit_feeds} f ORDER BY f.title ASC');
|
| 450 |
while ($feed = db_fetch_object($result)) {
|
| 451 |
$feeds[$feed->fid] = $key ? $feed->$key : $feed;
|
| 452 |
}
|
| 453 |
|
| 454 |
// Check for Exhibit JSON feeds in views and add automaticall add them to the list
|
| 455 |
if (module_exists('views')) {
|
| 456 |
$views = views_get_all_views();
|
| 457 |
foreach ($views as $view) {
|
| 458 |
// Skip disabled views or broken views
|
| 459 |
if (!empty($view->disabled) || empty($view->display)) {
|
| 460 |
continue;
|
| 461 |
}
|
| 462 |
|
| 463 |
// Check each display, add those using the Exhibit JSON style plugin
|
| 464 |
foreach (array_keys($view->display) as $id) {
|
| 465 |
$plugin = views_fetch_plugin_data('display', $view->display[$id]->display_plugin);
|
| 466 |
$display_options = $view->display[$id]->display_options;
|
| 467 |
if ($plugin['handler'] == 'views_plugin_display_feed' && $display_options['style_plugin'] == 'exhibit_json') {
|
| 468 |
$view_feed_id = $view->vid . '_' . $id;
|
| 469 |
if ($key) {
|
| 470 |
switch ($key) {
|
| 471 |
case 'fid':
|
| 472 |
$feeds[$view_feed_id] = $view_feed_id;
|
| 473 |
break;
|
| 474 |
case 'module':
|
| 475 |
$feeds[$view_feed_id] = 'views';
|
| 476 |
break;
|
| 477 |
case 'title':
|
| 478 |
$feeds[$view_feed_id] = l($view->name . ': ' . $view->display[$id]->display_title, 'admin/build/views/edit/' . $view->name);
|
| 479 |
break;
|
| 480 |
case 'enabled':
|
| 481 |
$feeds[$view_feed_id] = TRUE;
|
| 482 |
break;
|
| 483 |
case 'cache':
|
| 484 |
$feeds[$view_feed_id] = FALSE;
|
| 485 |
break;
|
| 486 |
case 'type':
|
| 487 |
$feeds[$view_feed_id] = 'application/json';
|
| 488 |
break;
|
| 489 |
case 'url':
|
| 490 |
$feeds[$view_feed_id] = $display_options['path'];
|
| 491 |
break;
|
| 492 |
}
|
| 493 |
}
|
| 494 |
else {
|
| 495 |
$feeds[$view_feed_id] = (object)array('fid' => $view_feed_id,
|
| 496 |
'module' => 'views',
|
| 497 |
'title' => l($view->name . ': ' . $view->display[$id]->display_title, 'admin/build/views/edit/' . $view->name),
|
| 498 |
'enabled' => TRUE,
|
| 499 |
'cache' => FALSE,
|
| 500 |
'type' => 'application/json',
|
| 501 |
'url' => $display_options['path']);
|
| 502 |
}
|
| 503 |
}
|
| 504 |
}
|
| 505 |
}
|
| 506 |
}
|
| 507 |
|
| 508 |
return $feeds;
|
| 509 |
}
|
| 510 |
|
| 511 |
function exhibit_get_feed_url($feed) {
|
| 512 |
$feed = (object)$feed;
|
| 513 |
return exhibit_get_url(!empty($feed->cache) ? 'exhibit/feeds/' . $feed->fid : $feed->url);
|
| 514 |
}
|
| 515 |
|
| 516 |
function exhibit_get_feed_contents($url) {
|
| 517 |
if (exhibit_is_link_internal($url)) {
|
| 518 |
// Internal Drupal path
|
| 519 |
ob_start();
|
| 520 |
$result = $url ? menu_execute_active_handler($url) : MENU_NOT_FOUND;
|
| 521 |
$output = ob_get_clean();
|
| 522 |
if (is_int($result)) {
|
| 523 |
switch ($result) {
|
| 524 |
case MENU_NOT_FOUND:
|
| 525 |
return die(drupal_not_found());
|
| 526 |
case MENU_ACCESS_DENIED:
|
| 527 |
return die(drupal_access_denied());
|
| 528 |
}
|
| 529 |
}
|
| 530 |
}
|
| 531 |
else {
|
| 532 |
// External URL
|
| 533 |
$output = file_get_contents($url);
|
| 534 |
}
|
| 535 |
return $output;
|
| 536 |
}
|
| 537 |
|
| 538 |
function exhibit_json($items, $types = NULL, $properties = NULL) {
|
| 539 |
return exhibit_compact_item(array(
|
| 540 |
'types' => $types,
|
| 541 |
'properties' => $properties,
|
| 542 |
'items' => $items,
|
| 543 |
));
|
| 544 |
}
|
| 545 |
|
| 546 |
function exhibit_compact_item($item) {
|
| 547 |
foreach ($item as $k => $v) {
|
| 548 |
if (is_null($v)) {
|
| 549 |
unset($item[$k]);
|
| 550 |
}
|
| 551 |
}
|
| 552 |
return $item;
|
| 553 |
}
|
| 554 |
|
| 555 |
//////////////////////////////////////////////////////////////////////////////
|
| 556 |
// Theme callbacks
|
| 557 |
|
| 558 |
function theme_exhibit_definition() { // TODO
|
| 559 |
return '<div ex:role="viewPanel"><div ex:role="view"></div></div>';
|
| 560 |
}
|
| 561 |
|
| 562 |
function theme_exhibit_lens() { // TODO
|
| 563 |
return '<div ex:content=".label" class="label"></div>';
|
| 564 |
}
|