Newer
Older
The Great Git Migration
committed
<?php
// $Id$
/**
* @file
* Primarily Drupal hooks and global API functions to manipulate views.
*
* This is the main module file for Views. The main entry points into
* this module are views_page() and views_block(), where it handles
* incoming page and block requests.
*/
/**
* Advertise the current views api version
*/
function views_api_version() {
Daniel Wehner
committed
return '3.0-alpha1';
}
/**
* Views will not load plugins advertising a version older than this.
*/
function views_api_minimum_version() {
return '2';
The Great Git Migration
committed
}
Daniel Wehner
committed
/**
* Implement hook_init().
*/
function views_init() {
drupal_add_css(drupal_get_path('module', 'views') .'/css/views.css');
}
The Great Git Migration
committed
/**
* Implement hook_theme(). Register views theming functions.
The Great Git Migration
committed
*/
function views_theme() {
$path = drupal_get_path('module', 'views');
include_once $path . '/theme/theme.inc';
The Great Git Migration
committed
// Some quasi clever array merging here.
$base = array(
'file' => 'theme.inc',
'path' => $path . '/theme',
The Great Git Migration
committed
);
// Our extra version of pager from pager.inc
$hooks['views_mini_pager'] = $base + array(
'variables' => array('tags' => array(), 'quantity' => 10, 'element' => 0, 'parameters' => array()),
The Great Git Migration
committed
'pattern' => 'views_mini_pager__',
);
$arguments = array(
'display' => array('view' => NULL),
'style' => array('view' => NULL, 'options' => NULL, 'rows' => NULL, 'title' => NULL),
'row' => array('view' => NULL, 'options' => NULL, 'row' => NULL, 'field_alias' => NULL),
);
// Default view themes
$hooks['views_view_field'] = $base + array(
'pattern' => 'views_view_field__',
'variables' => array('view' => NULL, 'field' => NULL, 'row' => NULL),
The Great Git Migration
committed
);
$plugins = views_fetch_plugin_data();
// Register theme functions for all style plugins
foreach ($plugins as $type => $info) {
foreach ($info as $plugin => $def) {
if (isset($def['theme'])) {
$hooks[$def['theme']] = array(
'pattern' => $def['theme'] . '__',
'file' => $def['theme file'],
'path' => $def['theme path'],
'variables' => $arguments[$type],
The Great Git Migration
committed
);
$include = DRUPAL_ROOT . '/' . $def['theme path'] . '/' . $def['theme file'];
The Great Git Migration
committed
if (file_exists($include)) {
require_once $include;
}
if (!function_exists('theme_' . $def['theme'])) {
$hooks[$def['theme']]['template'] = drupal_clean_css_identifier($def['theme']);
The Great Git Migration
committed
}
}
if (isset($def['additional themes'])) {
foreach ($def['additional themes'] as $theme => $theme_type) {
if (empty($theme_type)) {
$theme = $theme_type;
$theme_type = $type;
}
$hooks[$theme] = array(
'pattern' => $theme . '__',
'file' => $def['theme file'],
'path' => $def['theme path'],
'variables' => $arguments[$theme_type],
The Great Git Migration
committed
);
if (!function_exists('theme_' . $theme)) {
$hooks[$theme]['template'] = drupal_clean_css_identifier($theme);
The Great Git Migration
committed
}
}
}
}
}
$hooks['views_exposed_form'] = $base + array(
'template' => 'views-exposed-form',
'pattern' => 'views_exposed_form__',
'render element' => 'form',
The Great Git Migration
committed
);
$hooks['views_more'] = $base + array(
'template' => 'views-more',
'pattern' => 'views_more__',
'variables' => array('more_url' => NULL, 'link_text' => 'more'),
The Great Git Migration
committed
);
return $hooks;
}
/**
* A theme preprocess function to automatically allow view-based node
* templates if called from a view.
*
* The 'modules/node.views.inc' file is a better place for this, but
* we haven't got a chance to load that file before Drupal builds the
* node portion of the theme registry.
*/
function views_preprocess_node(&$vars) {
// The 'view' attribute of the node is added in template_preprocess_views_view_row_node()
if (!empty($vars['node']->view) && !empty($vars['node']->view->name)) {
$vars['view'] = &$vars['node']->view;
Daniel Wehner
committed
$vars['theme_hook_suggestions'][] = 'node__view__' . $vars['node']->view->name;
if (!empty($vars['node']->view->current_display)) {
Daniel Wehner
committed
$vars['theme_hook_suggestions'][] = 'node__view__' . $vars['node']->view->name . '__' . $vars['node']->view->current_display;
The Great Git Migration
committed
}
}
}
/**
* A theme preprocess function to automatically allow view-based node
* templates if called from a view.
*/
function views_preprocess_comment(&$vars) {
// The 'view' attribute of the node is added in template_preprocess_views_view_row_comment()
if (!empty($vars['node']->view) && !empty($vars['node']->view->name)) {
$vars['view'] = &$vars['node']->view;
Daniel Wehner
committed
$vars['theme_hook_suggestions'][] = 'comment__view__' . $vars['node']->view->name;
if (!empty($vars['node']->view->current_display)) {
Daniel Wehner
committed
$vars['theme_hook_suggestions'][] = 'comment__view__' . $vars['node']->view->name . '__' . $vars['node']->view->current_display;
The Great Git Migration
committed
}
}
}
/*
* Implement hook_permission().
The Great Git Migration
committed
*/
function views_permission() {
return array(
'administer views' => array(
'title' => t('Administer views'),
'description' => t('Access the views administration pages.'),
),
'access all views' => array(
'title' => t('Access all views'),
'description' => t('Bypass access control when accessing views.'),
),
);
The Great Git Migration
committed
}
/**
* Implement hook_menu().
The Great Git Migration
committed
*/
function views_menu() {
// Any event which causes a menu_rebuild could potentially mean that the
// Views data is updated -- module changes, profile changes, etc.
views_invalidate_cache();
$items = array();
$items['views/ajax'] = array(
'title' => 'Views',
'page callback' => 'views_ajax',
'access callback' => TRUE,
'description' => 'Ajax callback for view loading.',
'type' => MENU_CALLBACK,
);
// Path is not admin/structure/views due to menu complications with the wildcards from
The Great Git Migration
committed
// the generic ajax callback.
$items['admin/views/ajax/autocomplete/user'] = array(
'page callback' => 'views_ajax_autocomplete_user',
'access callback' => 'user_access',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
'file' => 'includes/ajax.inc',
The Great Git Migration
committed
);
// Define another taxonomy autocomplete because the default one of drupal
// does not support a vid a argument anymore
$items['admin/views/ajax/autocomplete/taxonomy'] = array(
'page callback' => 'views_ajax_autocomplete_taxonomy',
'access callback' => 'user_access',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
'file' => 'includes/ajax.inc',
);
The Great Git Migration
committed
return $items;
}
/**
* Implement hook_menu_alter().
The Great Git Migration
committed
*/
function views_menu_alter(&$callbacks) {
$our_paths = array();
$views = views_get_applicable_views('uses hook menu');
foreach ($views as $data) {
list($view, $display_id) = $data;
Earl Miles
committed
$result = $view->execute_hook_menu($display_id, $callbacks);
The Great Git Migration
committed
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
if (is_array($result)) {
// The menu system doesn't support having two otherwise
// identical paths with different placeholders. So we
// want to remove the existing items from the menu whose
// paths would conflict with ours.
// First, we must find any existing menu items that may
// conflict. We use a regular expression because we don't
// know what placeholders they might use. Note that we
// first construct the regex itself by replacing %views_arg
// in the display path, then we use this constructed regex
// (which will be something like '#^(foo/%[^/]*/bar)$#') to
// search through the existing paths.
$regex = '#^(' . preg_replace('#%views_arg#', '%[^/]*', implode('|', array_keys($result))) . ')$#';
$matches = preg_grep($regex, array_keys($callbacks));
// Remove any conflicting items that were found.
foreach ($matches as $path) {
// Don't remove the paths we just added!
if (!isset($our_paths[$path])) {
unset($callbacks[$path]);
}
}
foreach ($result as $path => $item) {
if (!isset($callbacks[$path])) {
// Add a new item, possibly replacing (and thus effectively
// overriding) one that we removed above.
$callbacks[$path] = $item;
}
else {
// This item already exists, so it must be one that we added.
// We change the various callback arguments to pass an array
// of possible display IDs instead of a single ID.
$callbacks[$path]['page arguments'][1] = (array)$callbacks[$path]['page arguments'][1];
$callbacks[$path]['page arguments'][1][] = $display_id;
$callbacks[$path]['access arguments'][] = $item['access arguments'][0];
$callbacks[$path]['load arguments'][1] = (array)$callbacks[$path]['load arguments'][1];
$callbacks[$path]['load arguments'][1][] = $display_id;
}
$our_paths[$path] = TRUE;
}
}
}
// Save memory: Destroy those views.
foreach ($views as $data) {
list($view, $display_id) = $data;
$view->destroy();
}
}
/**
* Helper function for menu loading. This will automatically be
* called in order to 'load' a views argument; primarily it
* will be used to perform validation.
*
* @param $value
* The actual value passed.
* @param $name
* The name of the view. This needs to be specified in the 'load function'
* of the menu entry.
* @param $index
* The menu argument index. This counts from 1.
*/
function views_arg_load($value, $name, $display_id, $index) {
if ($view = views_get_view($name)) {
$view->set_display($display_id);
$view->init_handlers();
$ids = array_keys($view->argument);
$indexes = array();
$path = explode('/', $view->get_path());
foreach ($path as $id => $piece) {
if ($piece == '%' && !empty($ids)) {
$indexes[$id] = array_shift($ids);
}
}
if (isset($indexes[$index])) {
if (isset($view->argument[$indexes[$index]])) {
$arg = $view->argument[$indexes[$index]]->validate_argument($value) ? $value : FALSE;
$view->destroy();
return $arg;
}
}
$view->destroy();
}
}
/**
* Page callback entry point; requires a view and a display id, then
* passes control to the display handler.
*/
function views_page() {
$args = func_get_args();
$name = array_shift($args);
$display_id = array_shift($args);
// Load the view
if ($view = views_get_view($name)) {
return $view->execute_display($display_id, $args);
}
// Fallback; if we get here no view was found or handler was not valid.
return drupal_not_found();
}
/**
* Implement hook_block_info().
The Great Git Migration
committed
*/
function views_block_info() {
Earl Miles
committed
// Try to avoid instantiating all the views just to get the blocks info.
views_include('cache');
$cache = views_cache_get('views_block_items', TRUE);
if ($cache && is_array($cache->data)) {
return $cache->data;
}
$items = array();
$views = views_get_all_views();
foreach ($views as $view) {
// disabled views get nothing.
if (!empty($view->disabled)) {
continue;
}
The Great Git Migration
committed
$view->init_display();
foreach ($view->display as $display_id => $display) {
The Great Git Migration
committed
if (isset($display->handler) && !empty($display->handler->definition['uses hook block'])) {
$result = $display->handler->execute_hook_block_list();
if (is_array($result)) {
$items = array_merge($items, $result);
The Great Git Migration
committed
}
}
if (isset($display->handler) && $display->handler->get_option('exposed_block')) {
$result = $display->handler->get_special_blocks();
if (is_array($result)) {
$items = array_merge($items, $result);
The Great Git Migration
committed
}
}
}
}
The Great Git Migration
committed
// block.module has a delta length limit of 32, but our deltas can
// unfortunately be longer because view names can be 32 and display IDs
// can also be 32. So for very long deltas, change to md5 hashes.
$hashes = array();
// get the keys because we're modifying the array and we don't want to
// confuse PHP too much.
$keys = array_keys($items);
foreach ($keys as $delta) {
if (strlen($delta) >= 32) {
$hash = md5($delta);
$hashes[$hash] = $delta;
$items[$hash] = $items[$delta];
unset($items[$delta]);
}
}
The Great Git Migration
committed
Daniel Wehner
committed
// Only save hashes if they have changed.
$old_hashes = variable_get('views_block_hashes', array());
if ($hashes != $old_hashes) {
variable_set('views_block_hashes', $hashes);
}
// Save memory: Destroy those views.
foreach ($views as $view) {
$view->destroy();
}
The Great Git Migration
committed
Earl Miles
committed
views_cache_set('views_block_items', $items, TRUE);
return $items;
}
/**
* Implement hook_block_view().
*/
function views_block_view($delta) {
$start = microtime(TRUE);
// if this is 32, this should be an md5 hash.
if (strlen($delta) == 32) {
$hashes = variable_get('views_block_hashes', array());
if (!empty($hashes[$delta])) {
$delta = $hashes[$delta];
}
}
The Great Git Migration
committed
// This indicates it's a special one.
if (substr($delta, 0, 1) == '-') {
list($nothing, $type, $name, $display_id) = explode('-', $delta);
// Put the - back on.
$type = '-' . $type;
if ($view = views_get_view($name)) {
if ($view->access($display_id)) {
$view->set_display($display_id);
if (isset($view->display_handler)) {
$output = $view->display_handler->view_special_blocks($type);
The Great Git Migration
committed
$view->destroy();
return $output;
}
}
$view->destroy();
}
}
list($name, $display_id) = explode('-', $delta);
// Load the view
if ($view = views_get_view($name)) {
if ($view->access($display_id)) {
$output = $view->execute_display($display_id);
$view->destroy();
return $output;
}
$view->destroy();
The Great Git Migration
committed
}
}
/**
Daniel Wehner
committed
* Implements hook_flush_caches().
The Great Git Migration
committed
*/
function views_flush_caches() {
return array('cache_views', 'cache_views_data');
}
Daniel Wehner
committed
/**
* Implements hook_field_create_instance.
*/
function views_field_create_instance($instance) {
cache_clear_all('*', 'cache_views', TRUE);
cache_clear_all('*', 'cache_views_data', TRUE);
}
/**
* Implements hook_field_update_instance.
*/
function views_field_update_instance($instance, $prior_instance) {
cache_clear_all('*', 'cache_views', TRUE);
cache_clear_all('*', 'cache_views_data', TRUE);
}
/**
* Implements hook_field_delete_instance.
*/
function views_field_delete_instance($instance) {
cache_clear_all('*', 'cache_views', TRUE);
cache_clear_all('*', 'cache_views_data', TRUE);
}
The Great Git Migration
committed
/**
* Invalidate the views cache, forcing a rebuild on the next grab of table data.
*/
function views_invalidate_cache() {
cache_clear_all('*', 'cache_views', TRUE);
The Great Git Migration
committed
}
/**
* Access callback to determine if the user can import Views.
*
* View imports require an additional access check because they are PHP
* code and PHP is more locked down than administer views.
*/
function views_import_access() {
Daniel Wehner
committed
return user_access('administer views') && user_access('use PHP for settings');
The Great Git Migration
committed
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
/**
* Determine if the logged in user has access to a view.
*
* This function should only be called from a menu hook or some other
* embedded source. Each argument is the result of a call to
* views_plugin_access::get_access_callback() which is then used
* to determine if that display is accessible. If *any* argument
* is accessible, then the view is accessible.
*/
function views_access() {
$args = func_get_args();
foreach ($args as $arg) {
if ($arg === TRUE) {
return TRUE;
}
if (!is_array($arg)) {
continue;
}
list($callback, $arguments) = $arg;
if (function_exists($callback) && call_user_func_array($callback, $arguments)) {
return TRUE;
}
}
return FALSE;
}
/**
Earl Miles
committed
* Access callback for the views_plugin_access_perm access plugin.
The Great Git Migration
committed
*
Earl Miles
committed
* Determine if the specified user has access to a view on the basis of
* permissions. If the $account argument is omitted, the current user
* is used.
*/
function views_check_perm($perm, $account = NULL) {
return user_access($perm, $account) || user_access('access all views', $account);
}
/**
* Access callback for the views_plugin_access_role access plugin.
* Determine if the specified user has access to a view on the basis of any of
* the requested roles. If the $account argument is omitted, the current user
* is used.
The Great Git Migration
committed
*/
Earl Miles
committed
function views_check_roles($rids, $account = NULL) {
The Great Git Migration
committed
global $user;
Earl Miles
committed
$account = isset($account) ? $account : $user;
$roles = array_keys($account->roles);
$roles[] = $account->uid ? DRUPAL_AUTHENTICATED_RID : DRUPAL_ANONYMOUS_RID;
return user_access('access all views', $account) || array_intersect(array_filter($rids), $roles);
The Great Git Migration
committed
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
}
// ------------------------------------------------------------------
// Functions to help identify views that are running or ran
/**
* Set the current 'page view' that is being displayed so that it is easy
* for other modules or the theme to identify.
*/
function &views_set_page_view($view = NULL) {
static $cache = NULL;
if (isset($view)) {
$cache = $view;
}
return $cache;
}
/**
* Find out what, if any, page view is currently in use. Please note that
* this returns a reference, so be careful! You can unintentionally modify the
* $view object.
*/
function &views_get_page_view() {
return views_set_page_view();
}
/**
* Set the current 'current view' that is being built/rendered so that it is
* easy for other modules or items in drupal_eval to identify
*/
function &views_set_current_view($view = NULL) {
static $cache = NULL;
if (isset($view)) {
$cache = $view;
}
return $cache;
}
/**
* Find out what, if any, current view is currently in use. Please note that
* this returns a reference, so be careful! You can unintentionally modify the
* $view object.
*/
function &views_get_current_view() {
return views_set_current_view();
}
// ------------------------------------------------------------------
// Include file helpers
/**
* Include views .inc files as necessary.
*/
function views_include($file) {
module_load_include('inc', 'views', "includes/$file");
The Great Git Migration
committed
}
/**
* Load views files on behalf of modules.
*/
Daniel Wehner
committed
function views_module_include($file, $reset = FALSE) {
foreach (views_get_module_apis($reset) as $module => $info) {
if (file_exists(DRUPAL_ROOT . "/$info[path]/$module.$file")) {
require_once DRUPAL_ROOT . "/$info[path]/$module.$file";
The Great Git Migration
committed
}
}
}
/**
* Get a list of modules that support the current views API.
*/
Daniel Wehner
committed
function views_get_module_apis($reset = FALSE) {
The Great Git Migration
committed
static $cache = NULL;
Daniel Wehner
committed
if (!isset($cache) || $reset) {
The Great Git Migration
committed
$cache = array();
foreach (module_implements('views_api') as $module) {
$info = module_invoke($module, 'views_api');
Daniel Wehner
committed
if (version_compare($info['api'], views_api_minimum_version(), '>=') &&
version_compare($info['api'], views_api_version(), '<=')) {
if (!isset($info['path'])) {
$info['path'] = drupal_get_path('module', $module);
}
Daniel Wehner
committed
$cache[$module] = $info;
The Great Git Migration
committed
}
}
}
return $cache;
}
/**
* Include views .css files.
*/
function views_add_css($file) {
// We set preprocess to FALSE because we are adding the files conditionally,
// and we don't want to generate duplicate cache files.
// TODO: at some point investigate adding some files unconditionally and
// allowing preprocess.
drupal_add_css(drupal_get_path('module', 'views') . "/css/$file.css", array('preprocess' => FALSE));
The Great Git Migration
committed
}
/**
* Include views .js files.
*/
function views_add_js($file) {
// If javascript has been disabled by the user, never add js files.
if (variable_get('views_no_javascript', FALSE)) {
return;
}
static $base = TRUE, $ajax = TRUE;
The Great Git Migration
committed
if ($base) {
drupal_add_js(drupal_get_path('module', 'views') . "/js/base.js");
$base = FALSE;
}
if ($ajax && $file == 'ajax') {
drupal_add_js('misc/ajax.js', array('weight' => -1));
$ajax = TRUE;
}
The Great Git Migration
committed
drupal_add_js(drupal_get_path('module', 'views') . "/js/$file.js");
}
/**
* Load views files on behalf of modules.
*/
Daniel Wehner
committed
function views_include_handlers($reset = FALSE) {
The Great Git Migration
committed
static $finished = FALSE;
// Ensure this only gets run once.
Daniel Wehner
committed
if ($finished && !$reset) {
The Great Git Migration
committed
return;
}
views_include('base');
views_include('handlers');
views_include('cache');
views_include('plugins');
_views_include_handlers();
$finished = TRUE;
}
/**
* Load default views files on behalf of modules.
*/
Daniel Wehner
committed
function views_include_default_views($reset = FALSE) {
The Great Git Migration
committed
static $finished = FALSE;
// Ensure this only gets run once.
Daniel Wehner
committed
if ($finished && !$reset) {
The Great Git Migration
committed
return;
}
// Default views hooks may be in the normal handler file,
// or in a separate views_default file at the discretion of
// the module author.
Daniel Wehner
committed
views_include_handlers($reset);
The Great Git Migration
committed
Daniel Wehner
committed
_views_include_default_views($reset);
The Great Git Migration
committed
$finished = TRUE;
}
// -----------------------------------------------------------------------
// Views handler functions
/**
* Fetch a handler from the data cache.
*
* @param $table
* The name of the table this handler is from.
* @param $field
* The name of the field this handler is from.
* @param $key
* The type of handler. i.e, sort, field, argument, filter, relationship
Daniel Wehner
committed
* @param $override
* Override the actual handler object with this class. Used for
* aggregation when the handler is redirected to the aggregation
* handler.
The Great Git Migration
committed
*
* @return
* An instance of a handler object. May be views_handler_broken.
*/
Daniel Wehner
committed
function views_get_handler($table, $field, $key, $override = NULL) {
The Great Git Migration
committed
$data = views_fetch_data($table);
Daniel Wehner
committed
$handler = NULL;
The Great Git Migration
committed
if (isset($data[$field][$key])) {
// Set up a default handler:
if (empty($data[$field][$key]['handler'])) {
$data[$field][$key]['handler'] = 'views_handler_' . $key;
}
Daniel Wehner
committed
if ($override) {
$data[$field][$key]['override handler'] = $override;
}
$handler = _views_prepare_handler($data[$field][$key], $data, $field);
The Great Git Migration
committed
}
Daniel Wehner
committed
if ($handler) {
return $handler;
}
The Great Git Migration
committed
// DEBUG -- identify missing handlers
debug("Missing handler: $table $field $key");
The Great Git Migration
committed
$broken = array(
'title' => t('Broken handler @table.@field', array('@table' => $table, '@field' => $field)),
'handler' => 'views_handler_' . $key . '_broken',
'table' => $table,
'field' => $field,
);
return _views_create_handler($broken);
}
/**
* Fetch Views' data from the cache
*/
Daniel Wehner
committed
function views_fetch_data($table = NULL, $reset = FALSE) {
The Great Git Migration
committed
views_include('cache');
Daniel Wehner
committed
return _views_fetch_data($table, $reset);
The Great Git Migration
committed
}
// -----------------------------------------------------------------------
// Views plugin functions
/**
* Fetch the plugin data from cache.
*/
Daniel Wehner
committed
function views_fetch_plugin_data($type = NULL, $plugin = NULL, $reset = FALSE) {
The Great Git Migration
committed
views_include('cache');
Daniel Wehner
committed
return _views_fetch_plugin_data($type, $plugin, $reset);
The Great Git Migration
committed
}
/**
* Get a handler for a plugin
*/
Daniel Wehner
committed
function views_get_plugin($type, $plugin, $reset = FALSE) {
views_include('handlers');
Daniel Wehner
committed
$definition = views_fetch_plugin_data($type, $plugin, $reset);
The Great Git Migration
committed
if (!empty($definition)) {
return _views_create_handler($definition, $type);
}
}
// -----------------------------------------------------------------------
// Views database functions
/**
* Get a view from the default views defined by modules.
*
* Default views are cached per-language. This function will rescan the
* default_views hook if necessary.
*
* @param $view_name
* The name of the view to load.
* @return
* A view object or NULL if it is not available.
*/
function &views_get_default_view($view_name, $reset = FALSE) {
The Great Git Migration
committed
$null = NULL;
// Attempt to load individually cached view from cache.
views_include('cache');
if (!$reset) {
$data = views_cache_get("views_default:{$view_name}", TRUE);
if (isset($data->data) && is_object($data->data)) {
return $data->data;
}
}
// Otherwise, allow entire cache to be rebuilt.
$cache = views_discover_default_views($reset);
The Great Git Migration
committed
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
if (isset($cache[$view_name])) {
return $cache[$view_name];
}
return $null;
}
/**
* Create an empty view to work with.
*
* @return
* A fully formed, empty $view object. This object must be populated before
* it can be successfully saved.
*/
function views_new_view() {
views_include('view');
$view = new view();
$view->vid = 'new';
$view->add_display('default');
return $view;
}
/**
* Scan all modules for default views and rebuild the default views cache.
*
* @return An associative array of all known default views.
*/
function views_discover_default_views($reset = FALSE) {
The Great Git Migration
committed
static $cache = array();
if (empty($cache) || $reset) {
The Great Git Migration
committed
views_include('cache');
$cache = _views_discover_default_views($reset);
The Great Git Migration
committed
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
}
return $cache;
}
/**
* Return a list of all views and display IDs that have a particular
* setting in their display's plugin settings.
*
* @return
* @code
* array(
* array($view, $display_id),
* array($view, $display_id),
* );
* @endcode
*/
function views_get_applicable_views($type) {
// @todo: Use a smarter flagging system so that we don't have to
// load every view for this.
$result = array();
$views = views_get_all_views();
foreach ($views as $view) {
// Skip disabled views.
if (!empty($view->disabled)) {
continue;
}
if (empty($view->display)) {
// Skip this view as it is broken.
vsm(t("Skipping broken view @view", array('@view' => $view->name)));
continue;
}
// Loop on array keys because something seems to muck with $view->display
// a bit in PHP4.
foreach (array_keys($view->display) as $id) {
$plugin = views_fetch_plugin_data('display', $view->display[$id]->display_plugin);
if (!empty($plugin[$type])) {
// This view uses hook menu. Clone it so that different handlers
// don't trip over each other, and add it to the list.
$v = $view->clone_view();
if ($v->set_display($id)) {
$result[] = array($v, $id);
}
// In PHP 4.4.7 and presumably earlier, if we do not unset $v
// here, we will find that it actually overwrites references
// possibly due to shallow copying issues.
unset($v);
}
}
}
return $result;
}
/**
* Return an array of all views as fully loaded $view objects.
*
* @param $reset
* If TRUE, reset the static cache forcing views to be reloaded.
*/
function views_get_all_views($reset = FALSE) {
static $views = array();
if (empty($views) || $reset) {
$views = array();
// First, get all applicable views.
views_include('view');
$views = view::load_views();
// Get all default views.
$status = variable_get('views_defaults', array());
foreach (views_discover_default_views($reset) as $view) {
The Great Git Migration
committed
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
// Determine if default view is enabled or disabled.
if (isset($status[$view->name])) {
$view->disabled = $status[$view->name];
}
// If overridden, also say so.
if (!empty($views[$view->name])) {
$views[$view->name]->type = t('Overridden');
}
else {
$view->type = t('Default');
$views[$view->name] = $view;
}
}
}
return $views;
}
/**
* Get a view from the database or from default views.
*
* This function is just a static wrapper around views::load(). This function
* isn't called 'views_load()' primarily because it might get a view
* from the default views which aren't technically loaded from the database.
*
* @param $name
* The name of the view.
* @param $reset
* If TRUE, reset this entry in the load cache.
* @return $view
* A reference to the $view object. Use $reset if you're sure you want
* a fresh one.
*/
function views_get_view($name, $reset = FALSE) {
views_include('view');
$view = view::load($name, $reset);
$default_view = views_get_default_view($name, $reset);
The Great Git Migration
committed
// The view does not exist.
The Great Git Migration
committed
if (empty($view) && empty($default_view)) {
return;
}
// The view is defined in code.
The Great Git Migration
committed
elseif (empty($view) && !empty($default_view)) {
Earl Miles
committed
$status = variable_get('views_defaults', array());
if (isset($status[$default_view->name])) {
$default_view->disabled = $status[$default_view->name];
}
The Great Git Migration
committed
$default_view->type = t('Default');
return $default_view->clone_view();
}
// The view is overriden/defined in the database.
The Great Git Migration
committed
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
elseif (!empty($view) && !empty($default_view)) {
$view->type = t('Overridden');
}
return $view->clone_view();
}
// ------------------------------------------------------------------
// Views debug helper functions
/**
* Debug messages
*/
function vsm($message) {
if (module_exists('devel')) {
dsm($message);
}
}
function views_trace() {
$message = '';
foreach (debug_backtrace() as $item) {
if (!empty($item['file']) && !in_array($item['function'], array('vsm_trace', 'vpr_trace', 'views_trace'))) {
$message .= basename($item['file']) . ": " . (empty($item['class']) ? '' : ($item['class'] . '->')) . "$item[function] line $item[line]" . "\n";
}
}
return $message;
}
function vsm_trace() {