5 * Primarily Drupal hooks and global API functions to manipulate views.
7 * This is the main module file for Views. The main entry points into
8 * this module are views_page() and views_block(), where it handles
9 * incoming page and block requests.
13 * Advertise the current views api version
15 function views_api_version() {
20 * Implementation of hook_theme(). Register views theming functions.
22 function views_theme() {
23 $path = drupal_get_path('module', 'views');
24 require_once
"./$path/theme/theme.inc";
26 // Some quasi clever array merging here.
28 'file' => 'theme.inc',
29 'path' => "$path/theme",
32 // Our extra version of pager from pager.inc
33 $hooks['views_mini_pager'] = $base + array(
34 'arguments' => array('tags' => array(), 'limit' => 10, 'element' => 0, 'parameters' => array()),
35 'pattern' => 'views_mini_pager__',
39 'display' => array('view' => NULL
),
40 'style' => array('view' => NULL
, 'options' => NULL
, 'rows' => NULL
, 'title' => NULL
),
41 'row' => array('view' => NULL
, 'options' => NULL
, 'row' => NULL
, 'field_alias' => NULL
),
44 // Default view themes
45 $hooks['views_view_field'] = $base + array(
46 'pattern' => 'views_view_field__',
47 'arguments' => array('view' => NULL
, 'field' => NULL
, 'row' => NULL
),
50 $plugins = views_fetch_plugin_data();
52 // Register theme functions for all style plugins
53 foreach ($plugins as
$type => $info) {
54 foreach ($info as
$plugin => $def) {
55 if (isset($def['theme'])) {
56 $hooks[$def['theme']] = array(
57 'pattern' => $def['theme'] .
'__',
58 'file' => $def['theme file'],
59 'path' => $def['theme path'],
60 'arguments' => $arguments[$type],
63 $include = './' .
$def['theme path'] .
'/' .
$def['theme file'];
64 if (file_exists($include)) {
65 require_once
$include;
68 if (!function_exists('theme_' .
$def['theme'])) {
69 $hooks[$def['theme']]['template'] = views_css_safe($def['theme']);
72 if (isset($def['additional themes'])) {
73 foreach ($def['additional themes'] as
$theme => $theme_type) {
74 if (empty($theme_type)) {
79 $hooks[$theme] = array(
80 'pattern' => $theme .
'__',
81 'file' => $def['theme file'],
82 'path' => $def['theme path'],
83 'arguments' => $arguments[$theme_type],
86 if (!function_exists('theme_' .
$theme)) {
87 $hooks[$theme]['template'] = views_css_safe($theme);
94 $hooks['views_exposed_form'] = $base + array(
95 'template' => 'views-exposed-form',
96 'pattern' => 'views_exposed_form__',
97 'arguments' => array('form' => NULL
),
100 $hooks['views_more'] = $base + array(
101 'template' => 'views-more',
102 'pattern' => 'views_more__',
103 'arguments' => array('more_url' => NULL
),
109 * A theme preprocess function to automatically allow view-based node
110 * templates if called from a view.
112 * The 'modules/node.views.inc' file is a better place for this, but
113 * we haven't got a chance to load that file before Drupal builds the
114 * node portion of the theme registry.
116 function views_preprocess_node(&$vars) {
117 // The 'view' attribute of the node is added in template_preprocess_views_view_row_node()
118 if (!empty($vars['node']->view
) && !empty($vars['node']->view
->name
)) {
119 $vars['view'] = &$vars['node']->view
;
120 $vars['template_files'][] = 'node-view-' .
$vars['node']->view
->name
;
121 if(!empty($vars['node']->view
->current_display
)) {
122 $vars['template_files'][] = 'node-view-' .
$vars['node']->view
->name .
'-' .
$vars['node']->view
->current_display
;
128 * A theme preprocess function to automatically allow view-based node
129 * templates if called from a view.
131 function views_preprocess_comment(&$vars) {
132 // The 'view' attribute of the node is added in template_preprocess_views_view_row_comment()
133 if (!empty($vars['node']->view
) && !empty($vars['node']->view
->name
)) {
134 $vars['view'] = &$vars['node']->view
;
135 $vars['template_files'][] = 'comment-view-' .
$vars['node']->view
->name
;
136 if(!empty($vars['node']->view
->current_display
)) {
137 $vars['template_files'][] = 'comment-view-' .
$vars['node']->view
->name .
'-' .
$vars['node']->view
->current_display
;
143 * Implementation of hook_perm()
145 function views_perm() {
146 return array('access all views', 'administer views');
150 * Implementation of hook_menu().
152 function views_menu() {
153 // Any event which causes a menu_rebuild could potentially mean that the
154 // Views data is updated -- module changes, profile changes, etc.
155 views_invalidate_cache();
157 $items['views/ajax'] = array(
159 'page callback' => 'views_ajax',
160 'access callback' => 'user_access',
161 'access arguments' => array('access content'),
162 'description' => 'Ajax callback for view loading.',
163 'file' => 'includes/ajax.inc',
164 'type' => MENU_CALLBACK
,
166 // Path is not admin/build/views due to menu complications with the wildcards from
167 // the generic ajax callback.
168 $items['admin/views/ajax/autocomplete/user'] = array(
169 'page callback' => 'views_ajax_autocomplete_user',
170 'access callback' => 'user_access',
171 'access arguments' => array('access content'),
172 'file' => 'includes/ajax.inc',
173 'type' => MENU_CALLBACK
,
179 * Implementation of hook_menu_alter().
181 function views_menu_alter(&$callbacks) {
182 $our_paths = array();
183 $views = views_get_applicable_views('uses hook menu');
184 foreach ($views as
$data) {
185 list($view, $display_id) = $data;
186 $result = $view->execute_hook_menu($display_id);
187 if (is_array($result)) {
188 // The menu system doesn't support having two otherwise
189 // identical paths with different placeholders. So we
190 // want to remove the existing items from the menu whose
191 // paths would conflict with ours.
193 // First, we must find any existing menu items that may
194 // conflict. We use a regular expression because we don't
195 // know what placeholders they might use. Note that we
196 // first construct the regex itself by replacing %views_arg
197 // in the display path, then we use this constructed regex
198 // (which will be something like '#^(foo/%[^/]*/bar)$#') to
199 // search through the existing paths.
200 $regex = '#^(' .
preg_replace('#%views_arg#', '%[^/]*', implode('|', array_keys($result))) .
')$#';
201 $matches = preg_grep($regex, array_keys($callbacks));
203 // Remove any conflicting items that were found.
204 foreach ($matches as
$path) {
205 // Don't remove the paths we just added!
206 if (!isset($our_paths[$path])) {
207 unset($callbacks[$path]);
210 foreach ($result as
$path => $item) {
211 if (!isset($callbacks[$path])) {
212 // Add a new item, possibly replacing (and thus effectively
213 // overriding) one that we removed above.
214 $callbacks[$path] = $item;
217 // This item already exists, so it must be one that we added.
218 // We change the various callback arguments to pass an array
219 // of possible display IDs instead of a single ID.
220 $callbacks[$path]['page arguments'][1] = (array)$callbacks[$path]['page arguments'][1];
221 $callbacks[$path]['page arguments'][1][] = $display_id;
222 $callbacks[$path]['access arguments'][] = $item['access arguments'][0];
223 $callbacks[$path]['load arguments'][1] = (array)$callbacks[$path]['load arguments'][1];
224 $callbacks[$path]['load arguments'][1][] = $display_id;
226 $our_paths[$path] = TRUE
;
231 // Save memory: Destroy those views.
232 foreach ($views as
$data) {
233 list($view, $display_id) = $data;
239 * Helper function for menu loading. This will automatically be
240 * called in order to 'load' a views argument; primarily it
241 * will be used to perform validation.
244 * The actual value passed.
246 * The name of the view. This needs to be specified in the 'load function'
249 * The menu argument index. This counts from 1.
251 function views_arg_load($value, $name, $display_id, $index) {
252 if ($view = views_get_view($name)) {
253 $view->set_display($display_id);
254 $view->init_handlers();
256 $ids = array_keys($view->argument
);
259 $path = explode('/', $view->get_path());
261 foreach ($path as
$id => $piece) {
262 if ($piece == '%' && !empty($ids)) {
263 $indexes[$id] = array_shift($ids);
267 if (isset($indexes[$index])) {
268 if (isset($view->argument
[$indexes[$index]])) {
269 $arg = $view->argument
[$indexes[$index]]->validate_argument($value) ?
$value : FALSE
;
279 * Page callback entry point; requires a view and a display id, then
280 * passes control to the display handler.
282 function views_page() {
283 $args = func_get_args();
284 $name = array_shift($args);
285 $display_id = array_shift($args);
288 if ($view = views_get_view($name)) {
289 return $view->execute_display($display_id, $args);
292 // Fallback; if we get here no view was found or handler was not valid.
293 return drupal_not_found();
297 * Implementation of hook_block
299 function views_block($op = 'list', $delta = 0, $edit = array()) {
303 $views = views_get_all_views();
304 foreach ($views as
$view) {
305 // disabled views get nothing.
306 if (!empty($view->disabled
)) {
310 $view->init_display();
311 foreach ($view->display as
$display_id => $display) {
313 if (isset($display->handler
) && !empty($display->handler
->definition
['uses hook block'])) {
314 $result = $display->handler
->execute_hook_block();
315 if (is_array($result)) {
316 $items = array_merge($items, $result);
320 if (isset($display->handler
) && $display->handler
->get_option('exposed_block')) {
321 $result = $display->handler
->get_special_blocks();
322 if (is_array($result)) {
323 $items = array_merge($items, $result);
329 // block.module has a delta length limit of 32, but our deltas can
330 // unfortunately be longer because view names can be 32 and display IDs
331 // can also be 32. So for very long deltas, change to md5 hashes.
334 // get the keys because we're modifying the array and we don't want to
335 // confuse PHP too much.
336 $keys = array_keys($items);
337 foreach ($keys as
$delta) {
338 if (strlen($delta) >= 32) {
340 $hashes[$hash] = $delta;
341 $items[$hash] = $items[$delta];
342 unset($items[$delta]);
346 variable_set('views_block_hashes', $hashes);
347 // Save memory: Destroy those views.
348 foreach ($views as
$view) {
354 $start = views_microtime();
355 // if this is 32, this should be an md5 hash.
356 if (strlen($delta) == 32) {
357 $hashes = variable_get('views_block_hashes', array());
358 if (!empty($hashes[$delta])) {
359 $delta = $hashes[$delta];
363 // This indicates it's a special one.
364 if (substr($delta, 0, 1) == '-') {
365 list($nothing, $type, $name, $display_id) = explode('-', $delta);
366 // Put the - back on.
368 if ($view = views_get_view($name)) {
369 if ($view->access($display_id)) {
370 $view->set_display($display_id);
371 if (isset($view->display_handler
)) {
372 $output = $view->display_handler
->view_special_blocks($type);
381 list($name, $display_id) = explode('-', $delta);
383 if ($view = views_get_view($name)) {
384 if ($view->access($display_id)) {
385 $output = $view->execute_display($display_id);
386 vpr("Block $view->name execute time: " .
(views_microtime() - $start) * 1000 .
"ms");
397 * Implementation of hook_flush_caches().
399 function views_flush_caches() {
400 return array('cache_views');
404 * Invalidate the views cache, forcing a rebuild on the next grab of table data.
406 function views_invalidate_cache() {
407 cache_clear_all('*', 'cache_views', true
);
411 * Determine if the logged in user has access to a view.
413 * This function should only be called from a menu hook or some other
414 * embedded source. Each argument is the result of a call to
415 * views_plugin_access::get_access_callback() which is then used
416 * to determine if that display is accessible. If *any* argument
417 * is accessible, then the view is accessible.
419 function views_access() {
420 if (user_access('access all views')) {
424 $args = func_get_args();
425 foreach ($args as
$arg) {
430 if (!is_array($arg)) {
434 list($callback, $arguments) = $arg;
435 if (function_exists($callback) && call_user_func_array($callback, $arguments)) {
444 * Access callback to determine if the logged in user has any of the
447 * This must be in views.module as it is called by menu access callback
448 * and can be called often.
450 function views_check_roles($rids) {
452 $roles = array_keys($user->roles
);
453 $roles[] = $user->uid ? DRUPAL_AUTHENTICATED_RID
: DRUPAL_ANONYMOUS_RID
;
454 return array_intersect(array_filter($rids), $roles);
456 // ------------------------------------------------------------------
457 // Functions to help identify views that are running or ran
460 * Set the current 'page view' that is being displayed so that it is easy
461 * for other modules or the theme to identify.
463 function &views_set_page_view($view = NULL
) {
464 static
$cache = NULL
;
473 * Find out what, if any, page view is currently in use. Please note that
474 * this returns a reference, so be careful! You can unintentionally modify the
477 function &views_get_page_view() {
478 return views_set_page_view();
482 * Set the current 'current view' that is being built/rendered so that it is
483 * easy for other modules or items in drupal_eval to identify
485 function &views_set_current_view($view = NULL
) {
486 static
$cache = NULL
;
495 * Find out what, if any, current view is currently in use. Please note that
496 * this returns a reference, so be careful! You can unintentionally modify the
499 function &views_get_current_view() {
500 return views_set_current_view();
503 // ------------------------------------------------------------------
504 // Include file helpers
507 * Include views .inc files as necessary.
509 function views_include($file) {
510 static
$used = array();
511 if (!isset($used[$file])) {
512 require_once
'./' .
drupal_get_path('module', 'views') .
"/includes/$file.inc";
519 * Load views files on behalf of modules.
521 function views_module_include($file) {
522 foreach (views_get_module_apis() as
$module => $info) {
523 if (file_exists("./$info[path]/$module.$file")) {
524 require_once
"./$info[path]/$module.$file";
530 * Get a list of modules that support the current views API.
532 function views_get_module_apis() {
533 static
$cache = NULL
;
534 if (!isset($cache)) {
536 foreach (module_implements('views_api') as
$module) {
537 $function = $module .
'_views_api';
539 if (isset($info['api']) && $info['api'] == 2.000) {
540 if (!isset($info['path'])) {
541 $info['path'] = drupal_get_path('module', $module);
543 $cache[$module] = $info;
552 * Include views .css files.
554 function views_add_css($file) {
555 // We set preprocess to FALSE because we are adding the files conditionally,
556 // and we don't want to generate duplicate cache files.
557 // TODO: at some point investigate adding some files unconditionally and
558 // allowing preprocess.
559 drupal_add_css(drupal_get_path('module', 'views') .
"/css/$file.css", 'module', 'all', FALSE
);
563 * Include views .js files.
565 function views_add_js($file) {
566 // If javascript has been disabled by the user, never add js files.
567 if (variable_get('views_no_javascript', FALSE
)) {
573 drupal_add_js(drupal_get_path('module', 'views') .
"/js/base.js");
576 drupal_add_js(drupal_get_path('module', 'views') .
"/js/$file.js");
580 * Load views files on behalf of modules.
582 function views_include_handlers() {
583 static
$finished = FALSE
;
584 // Ensure this only gets run once.
589 views_include('base');
590 views_include('handlers');
591 views_include('cache');
592 views_include('plugins');
593 _views_include_handlers();
598 * Load default views files on behalf of modules.
600 function views_include_default_views() {
601 static
$finished = FALSE
;
602 // Ensure this only gets run once.
607 // Default views hooks may be in the normal handler file,
608 // or in a separate views_default file at the discretion of
609 // the module author.
610 views_include_handlers();
612 _views_include_default_views();
616 // -----------------------------------------------------------------------
617 // Views handler functions
620 * Fetch a handler from the data cache.
623 * The name of the table this handler is from.
625 * The name of the field this handler is from.
627 * The type of handler. i.e, sort, field, argument, filter, relationship
630 * An instance of a handler object. May be views_handler_broken.
632 function views_get_handler($table, $field, $key) {
633 $data = views_fetch_data($table);
634 if (isset($data[$field][$key])) {
635 // Set up a default handler:
636 if (empty($data[$field][$key]['handler'])) {
637 $data[$field][$key]['handler'] = 'views_handler_' .
$key;
639 return _views_prepare_handler($data[$field][$key], $data, $field);
641 // DEBUG -- identify missing handlers
642 vpr("Missing handler: $table $field $key");
644 'title' => t('Broken handler @table.@field', array('@table' => $table, '@field' => $field)),
645 'handler' => 'views_handler_' .
$key .
'_broken',
649 return _views_create_handler($broken);
653 * Fetch Views' data from the cache
655 function views_fetch_data($table = NULL
) {
656 views_include('cache');
657 return _views_fetch_data($table);
660 // -----------------------------------------------------------------------
661 // Views plugin functions
664 * Fetch the plugin data from cache.
666 function views_fetch_plugin_data($type = NULL
, $plugin = NULL
) {
667 views_include('cache');
668 return _views_fetch_plugin_data($type, $plugin);
672 * Get a handler for a plugin
674 function views_get_plugin($type, $plugin) {
675 $definition = views_fetch_plugin_data($type, $plugin);
676 if (!empty($definition)) {
677 return _views_create_handler($definition, $type);
681 // -----------------------------------------------------------------------
682 // Views database functions
685 * Get a view from the default views defined by modules.
687 * Default views are cached per-language. This function will rescan the
688 * default_views hook if necessary.
691 * The name of the view to load.
693 * A view object or NULL if it is not available.
695 function &views_get_default_view($view_name) {
697 $cache = views_discover_default_views();
699 if (isset($cache[$view_name])) {
700 return $cache[$view_name];
706 * Create an empty view to work with.
709 * A fully formed, empty $view object. This object must be populated before
710 * it can be successfully saved.
712 function views_new_view() {
713 views_include('view');
716 $view->add_display('default');
722 * Scan all modules for default views and rebuild the default views cache.
724 * @return An associative array of all known default views.
726 function views_discover_default_views() {
727 static
$cache = array();
730 views_include('cache');
731 $cache = _views_discover_default_views();
737 * Return a list of all views and display IDs that have a particular
738 * setting in their display's plugin settings.
743 * array($view, $display_id),
744 * array($view, $display_id),
748 function views_get_applicable_views($type) {
749 // @todo: Use a smarter flagging system so that we don't have to
750 // load every view for this.
752 $views = views_get_all_views();
754 foreach ($views as
$view) {
755 // Skip disabled views.
756 if (!empty($view->disabled
)) {
760 if (empty($view->display
)) {
761 // Skip this view as it is broken.
762 vsm(t("Skipping broken view @view", array('@view' => $view->name
)));
766 // Loop on array keys because something seems to muck with $view->display
768 foreach (array_keys($view->display
) as
$id) {
769 $plugin = views_fetch_plugin_data('display', $view->display
[$id]->display_plugin
);
770 if (!empty($plugin[$type])) {
771 // This view uses hook menu. Clone it so that different handlers
772 // don't trip over each other, and add it to the list.
773 $v = $view->clone_view();
774 if ($v->set_display($id)) {
775 $result[] = array($v, $id);
777 // In PHP 4.4.7 and presumably earlier, if we do not unset $v
778 // here, we will find that it actually overwrites references
779 // possibly due to shallow copying issues.
788 * Return an array of all views as fully loaded $view objects.
791 * If TRUE, reset the static cache forcing views to be reloaded.
793 function views_get_all_views($reset = FALSE
) {
794 static
$views = array();
796 if (empty($views) || $reset) {
799 // First, get all applicable views.
800 views_include('view');
801 $views = view
::load_views();
803 // Get all default views.
804 $status = variable_get('views_defaults', array());
806 foreach (views_discover_default_views() as
$view) {
807 // Determine if default view is enabled or disabled.
808 if (isset($status[$view->name
])) {
809 $view->disabled
= $status[$view->name
];
812 // If overridden, also say so.
813 if (!empty($views[$view->name
])) {
814 $views[$view->name
]->type
= t('Overridden');
817 $view->type
= t('Default');
818 $views[$view->name
] = $view;
827 * Get a view from the database or from default views.
829 * This function is just a static wrapper around views::load(). This function
830 * isn't called 'views_load()' primarily because it might get a view
831 * from the default views which aren't technically loaded from the database.
834 * The name of the view.
836 * If TRUE, reset this entry in the load cache.
838 * A reference to the $view object. Use $reset if you're sure you want
841 function views_get_view($name, $reset = FALSE
) {
842 views_include('view');
843 $view = view
::load($name, $reset);
844 $default_view = views_get_default_view($name);
846 if (empty($view) && empty($default_view)) {
849 elseif (empty($view) && !empty($default_view)) {
850 $default_view->type
= t('Default');
851 return $default_view->clone_view();
853 elseif (!empty($view) && !empty($default_view)) {
854 $view->type
= t('Overridden');
857 return $view->clone_view();
861 // ------------------------------------------------------------------
862 // Views debug helper functions
865 * Provide debug output for Views. This relies on devel.module
867 function views_debug($message) {
868 if (module_exists('devel') && variable_get('views_devel_output', FALSE
) && user_access('access devel information')) {
869 if (is_string($message)) {
873 $output = var_export($message, TRUE
);
875 drupal_set_content(variable_get('views_devel_region', 'footer'), '<pre>' .
$output .
'</pre>');
880 * Shortcut to views_debug()
882 function vpr($message) {
883 views_debug($message);
889 function vsm($message) {
890 if (module_exists('devel')) {
895 function views_trace() {
897 foreach (debug_backtrace() as
$item) {
898 if (!empty($item['file']) && !in_array($item['function'], array('vsm_trace', 'vpr_trace', 'views_trace'))) {
899 $message .
= basename($item['file']) .
": " .
(empty($item['class']) ?
'' : ($item['class'] .
'->')) .
"$item[function] line $item[line]" .
"\n";
905 function vsm_trace() {
909 function vpr_trace() {
913 // ------------------------------------------------------------------
914 // Exposed widgets form
917 * Form builder for the exposed widgets form.
919 * Be sure that $view and $display are references.
921 function views_exposed_form(&$form_state) {
922 // Don't show the form when batch operations are in progress.
923 $batch =& batch_get();
924 if (!empty($batch)) {
926 // Set the theme callback to be nothing to avoid errors in template_preprocess_views_exposed_form().
931 // Make sure that we validate because this form might be submitted
932 // multiple times per page.
933 $form_state['must_validate'] = TRUE
;
934 $view = &$form_state['view'];
935 $display = &$form_state['display'];
937 // Check if the form was already created
938 if ($cache = views_exposed_form_cache($view->name
, $view->current_display
)) {
942 $form_state['input'] = $view->get_exposed_input();
944 // Let form plugins know this is for exposed widgets.
945 $form_state['exposed'] = TRUE
;
947 $form['#info'] = array();
949 if (!variable_get('clean_url', FALSE
)) {
952 '#value' => $view->get_url(),
956 // Go through each filter and let it generate its info.
957 foreach ($view->filter as
$id => $filter) {
958 $view->filter
[$id]->exposed_form($form, $form_state);
959 if ($info = $view->filter
[$id]->exposed_info()) {
960 $form['#info']['filter-' .
$id] = $info;
964 // @todo deal with exposed sorts
966 $form['submit'] = array(
967 '#name' => '', // prevent from showing up in $_GET.
969 '#value' => t('Apply'),
972 $form['#action'] = url($view->get_url());
973 $form['#theme'] = views_theme_functions('views_exposed_form', $view, $display);
974 $form['#id'] = views_css_safe('views_exposed_form-' .
check_plain($view->name
) .
'-' .
check_plain($display->id
));
975 // $form['#attributes']['class'] = array('views-exposed-form');
977 // If using AJAX, we need the form plugin.
978 if ($view->use_ajax
) {
979 drupal_add_js('misc/jquery.form.js');
981 views_add_js('dependent');
984 views_exposed_form_cache($view->name
, $view->current_display
, $form);
990 * Validate handler for exposed filters
992 function views_exposed_form_validate(&$form, &$form_state) {
993 foreach (array('field', 'filter') as
$type) {
994 $handlers = &$form_state['view']->$type;
995 foreach ($handlers as
$key => $handler) {
996 $handlers[$key]->exposed_validate($form, $form_state);
1002 * Submit handler for exposed filters
1004 function views_exposed_form_submit(&$form, &$form_state) {
1005 foreach (array('field', 'filter') as
$type) {
1006 $handlers = &$form_state['view']->$type;
1007 foreach ($handlers as
$key => $info) {
1008 $handlers[$key]->exposed_submit($form, $form_state);
1011 $form_state['view']->exposed_data
= $form_state['values'];
1012 $form_state['view']->exposed_raw_input
= array();
1014 foreach ($form_state['values'] as
$key => $value) {
1015 if (!in_array($key, array('q', 'submit', 'form_build_id', 'form_id', 'form_token', ''))) {
1016 $form_state['view']->exposed_raw_input
[$key] = $value;
1022 * Save the Views exposed form for later use.
1024 * @param $views_name
1025 * String. The views name.
1026 * @param $display_name
1027 * String. The current view display name.
1028 * @param $form_output
1029 * Array (optional). The form structure. Only needed when inserting the value.
1031 * Array. The form structure, if any. Otherwise, return FALSE.
1033 function views_exposed_form_cache($views_name, $display_name, $form_output = NULL
) {
1034 static
$views_exposed;
1036 // Save the form output
1037 if (!empty($form_output)) {
1038 $views_exposed[$views_name][$display_name] = $form_output;
1042 // Return the form output, if any
1043 return empty($views_exposed[$views_name][$display_name]) ? FALSE
: $views_exposed[$views_name][$display_name];
1046 // ------------------------------------------------------------------
1050 * Build a list of theme function names for use most everywhere.
1052 function views_theme_functions($hook, $view, $display = NULL
) {
1053 require_once
'./' .
drupal_get_path('module', 'views') .
"/theme/theme.inc";
1054 return _views_theme_functions($hook, $view, $display);
1058 * Views' replacement for drupal_get_form so that we can do more with
1061 * Items that can be set on the form_state include:
1062 * - input: The source of input. If unset this will be $_POST.
1063 * - no_redirect: Absolutely do not redirect the form even if instructed
1065 * - rerender: If no_redirect is set and the form was successfully submitted,
1066 * rerender the form. Otherwise it will just return.
1069 function drupal_build_form($form_id, &$form_state) {
1070 views_include('form');
1071 return _drupal_build_form($form_id, $form_state);
1075 * Substitute current time; this works with cached queries.
1077 function views_views_query_substitutions($view) {
1080 '***CURRENT_VERSION***' => VERSION
,
1081 '***CURRENT_TIME***' => time(),
1082 '***CURRENT_LANGUAGE***' => $language->language
,
1083 '***DEFAULT_LANGUAGE***' => language_default('language'),
1084 '***NO_LANGUAGE***' => '',
1089 * Embed a view using a PHP snippet.
1091 * This function is meant to be called from PHP snippets, should one wish to
1092 * embed a view in a node or something. It's meant to provide the simplest
1093 * solution and doesn't really offer a lot of options, but breaking the function
1094 * apart is pretty easy, and this provides a worthwhile guide to doing so.
1096 * Note that this function does NOT display the title of the view. If you want
1097 * to do that, you will need to do what this function does manually, by
1098 * loading the view, getting the preview and then getting $view->get_title().
1101 * The name of the view to embed.
1102 * @param $display_id
1103 * The display id to embed. If unsure, use 'default', as it will always be
1104 * valid. But things like 'page' or 'block' should work here.
1106 * Any additional parameters will be passed as arguments.
1108 function views_embed_view($name, $display_id = 'default') {
1109 $args = func_get_args();
1110 array_shift($args); // remove $name
1112 array_shift($args); // remove $display_id
1115 $view = views_get_view($name);
1120 return $view->preview($display_id, $args);
1126 function views_var_export($var, $prefix = '', $init = TRUE
) {
1127 if (is_array($var)) {
1129 $output = 'array()';
1132 $output = "array(\n";
1133 foreach ($var as
$key => $value) {
1134 $output .
= " '$key' => " .
views_var_export($value, ' ', FALSE
) .
",\n";
1139 else if (is_bool($var)) {
1140 $output = $var ?
'TRUE' : 'FALSE';
1142 else if (is_string($var) && strpos($var, "\n") !== FALSE
) {
1143 // Replace line breaks in strings with a token for replacement
1144 // at the very end. This protects multi-line strings from
1145 // unintentional indentation.
1146 $var = str_replace("\n", "***BREAK***", $var);
1147 $output = var_export($var, TRUE
);
1150 $output = var_export($var, TRUE
);
1154 $output = str_replace("\n", "\n$prefix", $output);
1158 $output = str_replace("***BREAK***", "\n", $output);
1165 * Prepare the specified string for use as a CSS identifier.
1167 function views_css_safe($string) {
1168 return str_replace('_', '-', $string);
1172 * Implementation of hook_views_exportables().
1174 function views_views_exportables($op = 'list', $views = NULL
, $name = 'foo') {
1175 $all_views = views_get_all_views();
1176 if ($op == 'list') {
1178 foreach ($all_views as
$name => $view) {
1179 // in list, $views is a list of tags.
1180 if (empty($views) || in_array($view->tag
, $views)) {
1181 $return[$name] = array(
1182 'name' => check_plain($name),
1183 'desc' => check_plain($view->description
),
1184 'tag' => check_plain($view->tag
)
1191 if ($op == 'export') {
1193 $code .
= " * Implementation of hook_views_default_views().\n";
1195 $code .
= "function " .
$name .
"_views_default_views() {\n";
1196 foreach ($views as
$view => $truth) {
1198 $code .
= " * View ".
var_export($all_views[$view]->name
, TRUE
) .
"\n";
1200 $code .
= $all_views[$view]->export(' ');
1201 $code .
= ' $views[$view->name] = $view;' .
"\n\n";
1203 $code .
= " return \$views;\n";
1211 * Microtime helper function to return a float time value (php4 & php5 safe).
1213 function views_microtime() {
1214 list($usec, $sec) = explode(' ', microtime());
1215 return (float)$sec + (float)$usec;