4 function views_init() {
5 // hook init is called even on cached pages, but we don't want to
6 // actually do anything in that case.
7 if (!function_exists('drupal_get_path')) {
10 // Load all our module 'on behalfs'.
11 $path = drupal_get_path('module', 'views') .
'/modules';
12 $files = system_listing('views_.*\.inc$', $path, 'name', 0);
14 foreach($files as
$file) {
15 // The filename format is very specific. It must be views_MODULENAME.inc
16 $module = substr_replace($file->name
, '', 0, 6);
17 if (module_exist($module)) {
18 require_once($file->filename
);
23 // ---------------------------------------------------------------------------
27 * Return the arguments array; construct one if we haven't already. The
28 * array is cached in a global, safely named variable so that arguments
29 * are only constructed once per run.
31 function _views_get_arguments($titles = false
) {
32 static
$views_arguments;
35 if (!$views_arguments) {
36 $data = cache_get("views_arguments:$locale");
37 $cache = unserialize($data->data
);
38 if (is_array($cache)) {
39 $views_arguments = $cache;
42 $arguments = module_invoke_all('views_arguments');
43 foreach ($arguments as
$name => $arg) {
44 if ($arg['option'] && !is_array($arg['option'])) {
45 if ($arg['option'] == 'string' || $arg['option'] == 'integer') {
46 $arg['option'] = array('#type' => 'textfield', '#size' => 10, '#maxlength' => 255);
49 $arg['option'] = array('#type' => 'select', '#options' => $arg['option']);
52 $views_arguments['base'][$name] = $arg['name'];
53 $views_arguments['title'][$name] = $arg;
55 $cache = $views_arguments;
56 cache_set("views_arguments:$locale", serialize($cache));
59 return ($titles ?
$views_arguments['base'] : $views_arguments['title']);
63 * Constructs the full table information array. Caches it into a global array
64 * so that it will only be called once per run.
66 function _views_get_tables($full = false
) {
71 $data = cache_get("views_tables:$locale");
72 $cache = unserialize($data->data
);
74 if (is_array($cache)) {
75 $views_tables = $cache;
78 $table_data = module_invoke_all('views_tables');
79 $views_tables['tables'] = $table_data;
81 foreach ($table_data as
$name => $table) {
82 if (is_array($table['filters'])) {
83 foreach ($table['filters'] as
$filter => $data) {
84 $data['table'] = $name;
85 // translate for deprecated APIs...
86 if ($data['option'] && !is_array($data['option'])) {
87 if ($data['option'] == 'string' || $data['option'] == 'integer') {
88 $data['option'] = array('#type' => 'textfield', '#size' => 10, '#maxlength' => 255);
91 $data['option'] = array('#type' => 'select', '#options' => $data['option']);
95 $data['value'] = array('#type' => 'select', '#options' => $data['list']);
96 if ($data['list-type'] != 'select') {
97 $data['value']['#multiple'] = TRUE
;
100 else if (!$data['value']) {
101 $data['value'] = array('#type' => 'textfield', '#size' => 10, '#maxlength' => 255);
103 $views_tables['filters']['titles']["$name.$filter"] = $data['name'];
104 $views_tables['filters']['base']["$name.$filter"] = $data;
107 if (is_array($table['fields'])) {
108 foreach ($table['fields'] as
$field => $data) {
109 if ($data['option'] && !is_array($data['option'])) {
110 if ($data['option'] == 'string' || $data['option'] == 'integer') {
111 $data['option'] = array('#type' => 'textfield', '#size' => 10, '#maxlength' => 255);
114 $data['option'] = array('#type' => 'select', '#options' => $data['option']);
117 $data['table'] = $name;
118 $views_tables['fields']['titles']["$name.$field"] = $data['name'];
119 $views_tables['fields']['base']["$name.$field"] = $data;
122 if (is_array($table['sorts'])) {
123 foreach ($table['sorts'] as
$field => $data) {
124 $data['table'] = $name;
125 if ($data['option'] && !is_array($data['option'])) {
126 if ($data['option'] == 'string' || $data['option'] == 'integer') {
127 $data['option'] = array('#type' => 'textfield', '#size' => 10, '#maxlength' => 255);
130 $data['option'] = array('#type' => 'select', '#options' => $data['option']);
133 $views_tables['sorts']['titles']["$name.$field"] = $data['name'];
134 $views_tables['sorts']['base']["$name.$field"] = $data;
138 cache_set("views_tables:$locale", serialize($views_tables));
141 return ($full ?
$views_tables : $views_tables['tables']);
145 * Gets the filter information; if it doesn't exist, call the function
146 * that constructs all that.
148 function _views_get_filters($titles = false
) {
149 $table_data = _views_get_tables(true
);
150 return ($titles ?
$table_data['filters']['titles'] : $table_data['filters']['base']);
154 * Gets the field information; if it doesn't exist, call the function
155 * that constructs all that.
157 function _views_get_fields($titles = false
) {
158 $table_data = _views_get_tables(true
);
159 return ($titles ?
$table_data['fields']['titles'] : $table_data['fields']['base']);
163 * Gets the sort information; if it doesn't exist, call the function
164 * that constructs all that.
166 function _views_get_sorts($titles = false
) {
167 $table_data = _views_get_tables(true
);
168 return ($titles ?
$table_data['sorts']['titles'] : $table_data['sorts']['base']);
172 * Invalidate the views cache, forcing a rebuild on the next grab of table data.
174 function views_invalidate_cache() {
175 cache_clear_all('views_', true
);
179 * Ensures that views have legitimate information; a bit more is stored on
180 * the $view object than is in the database, and this isn't necessarily
181 * set when a view is constructed externally.
183 function _views_sanitize_view(&$view) {
184 _views_check_arrays($view); // so reference works.
185 foreach ($view->field as
$i => $field) {
186 $view->field
[$i]['id'] = $view->field
[$i]['fullname'] = "$field[tablename].$field[field]";
187 $view->field
[$i]['queryname'] = "$field[tablename]_$field[field]";
190 foreach ($view->filter as
$i => $filter) {
191 $view->filter
[$i]['id'] = $view->filter
[$i]['field'] = "$filter[tablename].$filter[field]";
194 foreach ($view->exposed_filter as
$i => $exposed_filter) {
195 $view->exposed_filter
[$i]['id'] = $view->exposed_filter
[$i]['field'] = "$exposed_filter[tablename].$exposed_filter[field]";
198 foreach ($view->sort as
$i => $sort) {
199 $view->sort[$i]['id'] = $view->sort[$i]['field'] = "$sort[tablename].$sort[field]";
202 foreach ($view->argument as
$i => $argument) {
203 $view->argument
[$i]['id'] = $view->argument
[$i]['type'];
208 * Build default view information from all modules and cache it.
210 function _views_get_default_views() {
211 static
$views_default_views;
214 if (!$views_default_views) {
215 $data = cache_get("views_default_views:$locale");
216 $cache = unserialize($data->data
);
218 if (is_array($cache)) {
219 $views_default_views = $cache;
222 // We have to make sure table data is built in order to be sure about providers.
223 $tables = array_keys(_views_get_tables());
225 $views = module_invoke_all('views_default_views');
226 $views_default_views = array();
227 foreach ($views as
$i => $view) {
228 if (!is_array($view->requires
) || !array_diff($view->requires
, $tables)) {
229 _views_sanitize_view($view);
230 $views_default_views[$i] = $view;
233 cache_set("views_default_views:$locale", serialize($views_default_views));
236 return $views_default_views;
240 * Return the style plugins; construct one if we haven't already. The
241 * array is cached in a static variable so that arguments
242 * are only constructed once per run.
244 function _views_get_style_plugins($titles = false
) {
245 static
$views_style_plugins;
248 if (!$views_style_plugins) {
249 $data = cache_get("views_style_plugins:$locale");
250 $cache = unserialize($data->data
);
251 if (is_array($cache)) {
252 $views_style_plugins = $cache;
255 $arguments = module_invoke_all('views_style_plugins');
256 foreach ($arguments as
$name => $arg) {
257 $views_style_plugins['title'][$name] = $arg['name'];
258 $views_style_plugins['base'][$name] = $arg;
260 $cache = $views_style_plugins;
261 cache_set("views_style_plugins:$locale", serialize($cache));
264 return ($titles ?
$views_style_plugins['title'] : $views_style_plugins['base']);
267 // ---------------------------------------------------------------------------
271 * Implementation of hook_help()
273 function views_help($section) {
275 case
'admin/help#views':
276 case
'admin/modules#description':
277 return t('The views module creates customized views of node lists.');
282 * Implementation of hook_menu()
284 function views_menu($may_cache) {
289 // Invalidate the views cache to ensure that views data gets rebuilt.
290 // This is the best way to tell that module configuration has changed.
291 if (arg(0) == 'admin' && arg(1) == 'modules') {
292 views_invalidate_cache();
295 $result = db_query("SELECT * FROM {view_view} WHERE page = 1");
296 $views_with_inline_args = array();
298 while ($view = db_fetch_object($result)) {
300 $view->access
= ($view->access ?
explode(', ', $view->access
) : array());
302 // This happens before the next check; even if it's put off for later
304 $used[$view->name
] = true
;
306 if (strrpos($view->url
, '$arg')) {
307 $arg_result = db_query("SELECT * FROM {view_argument} WHERE vid = %d", $view->vid
);
308 while ($view->argument
[] = db_fetch_array($arg_result));
309 array_pop($view->argument
); // get rid of the NULL at the end.
310 $views_with_inline_args[$view->name
] = $view;
313 _views_create_menu_item($items, $view, $view->url
, array($view->name
));
315 $default_views = _views_get_default_views();
316 $views_status = variable_get('views_defaults', array());
318 foreach ($default_views as
$name => $view) {
319 if ($view->page
&& !$used[$name] &&
320 ($views_status[$name] == 'enabled' || (!$view->disabled
&& $views_status[$name] != 'disabled'))) {
322 if (strrpos($view->url
, '$arg')) {
323 $views_with_inline_args[$view->name
] = $view;
327 _views_create_menu_item($items, $view, $view->url
, array($view->name
));
330 cache_set("views_with_inline_args:$locale", serialize($views_with_inline_args), CACHE_TEMPORARY
);
333 $data = cache_get("views_with_inline_args:$locale");
334 $views = unserialize($data->data
);
336 if (is_array($views)) {
337 foreach ($views as
$view) {
338 // Do substitution on args.
339 $view_args = array($view->name
);
340 $menu_path = array();
341 foreach (explode('/', $view->url
) as
$num => $element) {
342 if ($element == '$arg') {
343 $menu_path[] = arg($num);
344 $view_args[] = arg($num);
345 $view->args
[] = arg($num);
348 $menu_path[] = $element;
351 $path = implode('/', $menu_path);
352 _views_create_menu_item($items, $view, $path, $view_args, MENU_CALLBACK
);
360 * Helper function to add a menu item for a view.
362 function _views_create_menu_item(&$items, $view, $path, $args, $local_task_type = MENU_NORMAL_ITEM
) {
363 static
$roles = NULL
;
364 if ($roles == NULL
) {
366 $roles = array_keys($user->roles
);
368 $title = views_get_title($view, 'menu');
369 $type = _views_menu_type($view);
370 if ($type == MENU_LOCAL_TASK
|| $type == MENU_DEFAULT_LOCAL_TASK
) {
371 $weight = $view->menu_tab_weight
;
373 $access = !$view->access
|| array_intersect($view->access
, $roles);
374 $items[] = _views_menu_item($path, $title, $args, $access, $type, $weight);
376 if ($type == MENU_DEFAULT_LOCAL_TASK
) {
377 $items[] = _views_menu_item(dirname($path), $title, $args, $access, $local_task_type, $weight);
382 * Helper function to create a menu item for a view.
384 function _views_menu_item($path, $title, $args, $access, $type, $weight = NULL
) {
385 $retval = array('path' => $path,
387 'callback' => 'views_view_page',
388 'callback arguments' => $args,
392 if ($weight !== NULL
) {
393 $retval['weight'] = $weight;
399 * Determine what menu type a view needs to use.
401 function _views_menu_type($view) {
403 if ($view->menu_tab_default
) {
404 $type = MENU_DEFAULT_LOCAL_TASK
;
406 else if ($view->menu_tab
) {
407 $type = MENU_LOCAL_TASK
;
410 $type = MENU_NORMAL_ITEM
;
414 $type = MENU_CALLBACK
;
420 * Implementation of hook_block()
422 function views_block($op = 'list', $delta = 0) {
425 // Grab views from the database and provide them as blocks.
426 $result = db_query("SELECT vid, block_title, page_title, name FROM {view_view} WHERE block = 1");
427 while ($view = db_fetch_object($result)) {
428 $block[$view->name
]['info'] = views_get_title($view, 'block-info');
431 $default_views = _views_get_default_views();
432 $views_status = variable_get('views_defaults', array());
434 foreach ($default_views as
$name => $view) {
435 if (!isset($block[$name]) && $view->block
&&
436 ($views_status[$name] == 'enabled' || (!$view->disabled
&& $views_status[$name] != 'disabled'))) {
437 $block[$name]['info'] = views_get_title($view, 'block');
442 else if ($op == 'view') {
443 return views_view_block($delta);
447 // ---------------------------------------------------------------------------
451 * Ensure that all the arrays in a view exist so we don't run into array
452 * operations on a non-array error.
454 function _views_check_arrays(&$view) {
455 $fields = array('field', 'sort', 'argument', 'filter', 'exposed_filter', 'access');
457 foreach($fields as
$field) {
458 if (!is_array($view->$field)) {
459 $view->$field = array();
466 * This function loads a view by name or vid; if not found in db, it looks
467 * for a default view by that name.
469 function views_get_view($view_name) {
470 $view = _views_load_view($view_name);
475 if (is_int($view_name)) {
476 return; // don't bother looking if view_name is an int!
479 $default_views = _views_get_default_views();
481 if (isset($default_views[$view_name])) {
482 return $default_views[$view_name];
487 * This views a view by page, and should only be used as a callback.
489 function views_view_page() {
490 $args = func_get_args();
491 // FIXME: Most of this code is unnecessary now that we add our
492 // $view info as a callback argument via the menu hook.
493 while ($next = array_shift($args)) {
498 $view_name .
= "/$next";
501 if ($view = views_get_view($view_name)) {
510 $output = views_build_view('page', $view, $args, $view->use_pager
, $view->nodes_per_page
);
511 if ($output === FALSE
) {
520 * This views a view by block. Can be used as a callback or programmatically.
522 function views_view_block($vid) {
523 $view = views_get_view($vid);
525 if (!$view || !$view->block
) {
530 $roles = array_keys($user->roles
);
531 if ($view->access
&& !array_intersect($roles, $view->access
)) {
535 $content = views_build_view('block', $view, array(), false
, $view->nodes_per_block
);
537 $block['content'] = $content;
538 $block['subject'] = views_get_title($view, 'block');
547 * This builds the basic view.
549 * 'page' -- Produce output as a page, sent through theme.
550 * The only real difference between this and block is that
551 * a page uses drupal_set_title to change the page title.
552 * 'block' -- Produce output as a block, sent through theme.
553 * 'embed' -- Use this if you want to embed a view onto another page,
554 * and don't want any block or page specific things to happen to it.
555 * 'result' -- return an $info array. The array contains:
556 * query: The actual query ran.
557 * countquery: The count query that would be run if limiting was required.
558 * summary: True if an argument was missing and a summary was generated.
559 * level: What level the missing argument was at.
560 * result: Database object you can use db_fetch_object on.
561 * 'items' -- return info array as above, except instead of result,
562 * items: An array of objects containing the results of the query.
564 * The actual view object. Use views_get_view() if you only have the name or
567 * args taken from the URL. Not relevant for many views. Can be null.
569 * If set, use a pager. Set this to the pager id you want it
570 * to use if you plan on using multiple pagers on a page. To go with the
571 * default setting, set to $view->use_pager.
573 * Required if $use_pager is set; if $limit is set and $use_pager is
574 * not, this will be the maximum number of records returned. This is ignored
575 * if using a view set to return a random result. To go with the default
576 * setting set to $view->nodes_per_page or $view->nodes_per_block. If
577 * $use_pager is set and this field is not, you'll get a SQL error. Don't
580 * $use_pager is false, and $limit is !0, $page tells it what page to start
581 * on, in case for some reason a particular section of view is needed,
584 function views_build_view($type, $view, $args = array(), $use_pager = false
, $limit = 0, $page = 0) {
585 $GLOBALS['current_view'] = &$view;
587 $viewtype = ($type == 'block' ?
$view->block_type
: $view->page_type
);
589 if ($view->view_args_php
) {
591 $args = eval($view->view_args_php
);
596 $info['query'] = $view->query
;
597 $info['countquery'] = $view->countquery
;
599 if ($viewtype == 'table') {
600 $view->table_header
= _views_construct_header($view, $fields);
604 $path = drupal_get_path('module', 'views');
605 require_once("$path/views_query.inc");
607 $info = _views_build_query($view, $args);
613 // Run-time replacement so we can do cacheing
614 $replacements = module_invoke_all('views_query_substitutions', $view);
615 foreach ($replacements as
$src => $dest) {
616 $info['query'] = str_replace($src, $dest, $info['query']);
617 $info['countquery'] = str_replace($src, $dest, $info['countquery']);
619 foreach ($info['args'] as
$id => $arg) {
620 $info['args'][$id] = str_replace($src, $dest, $arg);
624 $query = db_rewrite_sql($info['query'], 'node');
627 $cquery = db_rewrite_sql($info['countquery'], 'node', 'nid', $info['rewrite_args']);
628 $result = pager_query($query, $limit, $use_pager, $cquery, $info['args']);
631 $result = ($limit ?
db_query_range($query, $info['args'], $page * $limit, $limit) : db_query($query, $info['args']));
634 if ($type == 'result') {
635 $info['result'] = $result;
640 while ($item = db_fetch_object($result)) {
644 if ($type == 'items') {
645 $info['items'] = $items;
649 // Call a hook that'll let modules modify the view just before it is displayed.
650 foreach (module_implements('views_pre_view') as
$module) {
651 $function = $module .
'_views_pre_view';
652 $output .
= $function($view, $items);
656 // In block mode, change $view->url to include the proper arguments.
657 if ($type == 'block' && $args) {
658 $url = views_get_summary_link_base($view->argument[count($args)-1]['type'], $view->url, count($args), $args);
664 $view->real_url
= views_get_url($view, $args);
666 $view->use_pager
= $use_pager;
667 $output .
= views_theme('views_view', $view, $type, $items, $info['level'], $args);
669 // Call a hook that'll let modules modify the view just after it is displayed.
670 foreach (module_implements('views_post_view') as
$module) {
671 $function = $module .
'_views_post_view';
672 $output .
= $function($view, $items, $output);
678 // ---------------------------------------------------------------------------
682 * Easily theme any item to a view.
684 * The name of the function to call.
686 * The view being themed.
688 function views_theme() {
689 $args = func_get_args();
690 $function = array_shift($args);
693 if (!($func = theme_get_function($function .
"_" .
$view->name
))) {
694 $func = theme_get_function($function);
698 return call_user_func_array($func, $args);
703 * Easily theme any item to a field name.
704 * field name will be in the format of TABLENAME_FIELDNAME
705 * You have to understand a bit about the views data to utilize this.
708 * The name of the function to call.
710 * The field being themed.
712 function views_theme_field() {
713 $args = func_get_args();
714 $function = array_shift($args);
715 $field_name = array_shift($args);
717 if (!($func = theme_get_function($function .
"_" .
$field_name))) {
718 $func = theme_get_function($function);
722 return call_user_func_array($func, $args);
727 * Figure out what timezone we're in; needed for some date manipulations.
729 function _views_get_timezone() {
731 if (variable_get('configurable_timezones', 1) && $user->uid
&& strlen($user->timezone
)) {
732 $timezone = $user->timezone
;
735 $timezone = variable_get('date_default_timezone', 0);
742 * Figure out what the URL of the view we're currently looking at is.
744 function views_get_url($view, $args) {
748 foreach ($args as
$arg) {
749 // This odd construct prevents us from strposing once there is no
750 // longer an $arg to replace.
751 if ($where && $where = strpos('$arg', $url)) {
752 $url = str_replace($url, $arg, $where, 4);
763 * Figure out what the title of a view should be.
765 function views_get_title($view, $context = 'menu', $args = NULL
) {
766 if ($context == 'menu' && $view->menu_title
)
767 return $view->menu_title
;
769 if ($context == 'block' && $view->block_title
) {
770 return $view->block_title
;
773 if ($context == 'block-info') {
774 return $view->description ?
$view->description
: $view->name
;
780 $count = count($args);
781 if ($count >= count($view->argument
)) {
782 $title = $view->page_title
;
785 $title = $view->argument
[$count]['title'];
787 if (!$title && $context == 'menu') {
788 $title = $view->block_title
;
791 if (!$view->argument
) {
795 $arginfo = _views_get_arguments();
796 foreach ($view->argument as
$i => $arg) {
797 if (!isset($args[$i])) {
800 $argtype = $arg['type'];
801 if (function_exists($arginfo[$argtype]['handler'])) {
803 $rep = $arginfo[$argtype]['handler']('title', $args[$i], $argtype);
804 $title = str_replace("%" .
($i + 1), $rep, $title);
812 * Determine whether or not a view is cacheable. A view is not cacheable if
813 * there is some kind of user input or data required. For example, views
814 * that need to restrict to the 'current' user, or any views that require
815 * arguments or allow click-sorting are not cacheable.
817 function _views_is_cacheable(&$view) {
818 // views with arguments are immediately not cacheable.
819 if (!empty($view->argument
) || !empty($view->exposed_filter
)) {
823 $filters = _views_get_filters();
825 foreach ($view->filter as
$i => $filter) {
826 if ($filters[$filter['field']]['cacheable'] == 'no') {
831 foreach ($view->field as
$i => $field) {
832 if ($field['sortable']) {
839 // ---------------------------------------------------------------------------
840 // Database functions
843 * Provide all the fields in a view.
845 function _views_view_fields() {
846 return array('vid', 'name', 'description', 'access', 'page', 'page_title', 'page_header', 'page_header_format', 'page_footer', 'page_footer_format', 'page_empty', 'page_empty_format', 'page_type', 'use_pager', 'nodes_per_page', 'url', 'menu', 'menu_tab', 'menu_tab_default', 'menu_tab_weight', 'menu_title', 'block', 'block_title', 'block_use_page_header', 'block_header', 'block_header_format', 'block_use_page_footer', 'block_footer', 'block_footer_format', 'block_use_page_empty', 'block_empty', 'block_empty_format', 'block_type', 'nodes_per_block', 'block_more', 'url', 'breadcrumb_no_home', 'changed', 'query', 'countquery', 'view_args_php');
850 * Delete a view from the database.
852 function _views_delete_view($view) {
853 $view->vid
= intval($view->vid
);
858 db_query("DELETE FROM {view_view} where vid=%d", $view->vid
);
859 db_query("DELETE FROM {view_sort} where vid=%d", $view->vid
);
860 db_query("DELETE FROM {view_argument} where vid=%d", $view->vid
);
861 db_query("DELETE FROM {view_tablefield} where vid=%d", $view->vid
);
865 * Load a view from the database.
867 function _views_load_view($arg) {
868 static
$cache = array();
869 $which = is_numeric($arg) ?
'vid' : 'name';
870 if (isset($cache[$which][$arg])) {
871 return $cache[$which][$arg];
874 $where = (is_numeric($arg) ?
"v.vid = %d" : "v.name = '%s'");
875 $view = db_fetch_object(db_query("SELECT v.* FROM {view_view} v WHERE $where", $arg));
881 $view->access
= ($view->access ?
explode(', ', $view->access
) : array());
883 // load the sorting criteria too.
884 $result = db_query("SELECT * FROM {view_sort} vs WHERE vid = $view->vid ORDER BY position ASC");
886 $view->sort = array();
887 while ($sort = db_fetch_array($result)) {
888 if (substr($sort['field'], 0, 2) == 'n.') {
889 $sort['field'] = 'node' .
substr($sort['field'], 1);
891 $sort['id'] = $sort['field'];
892 $view->sort[] = $sort;
895 $result = db_query("SELECT * FROM {view_argument} WHERE vid = $view->vid ORDER BY position ASC");
897 $view->argument
= array();
898 while ($arg = db_fetch_array($result)) {
899 $arg['id'] = $arg['type'];
900 $view->argument
[] = $arg;
903 $result = db_query("SELECT * FROM {view_tablefield} WHERE vid = $view->vid ORDER BY position ASC");
905 $view->field
= array();
906 while ($arg = db_fetch_array($result)) {
907 if ($arg['tablename'] == 'n') {
908 $arg['tablename'] = 'node';
910 $arg['id'] = $arg['fullname'] = "$arg[tablename].$arg[field]";
911 $arg['queryname'] = "$arg[tablename]_$arg[field]";
912 $view->field
[] = $arg;
915 $result = db_query("SELECT * FROM {view_filter} WHERE vid = $view->vid ORDER BY position ASC");
917 $filters = _views_get_filters();
918 $view->filter
= array();
919 while ($filter = db_fetch_array($result)) {
920 if (substr($filter['field'], 0, 2) == 'n.') {
921 $filter['field'] = 'node' .
substr($filter['field'], 1);
924 if ($filter['operator'] == 'AND' ||
925 $filter['operator'] == 'OR' ||
926 $filter['operator'] == 'NOR' ||
927 $filters[$filter['field']]['value-type'] == 'array' ) {
928 if ($filter['value'] !== NULL
&& $filter['value'] !== '') {
929 $filter['value'] = explode(',', $filter['value']);
932 $filter['value'] = array();
935 $filter['id'] = $filter['field'];
936 $view->filter
[] = $filter;
939 $result = db_query("SELECT * FROM {view_exposed_filter} WHERE vid = $view->vid ORDER BY position ASC");
941 $view->exposed_filter
= array();
942 while ($arg = db_fetch_array($result)) {
943 $arg['id'] = $arg['field'];
944 $view->exposed_filter
[] = $arg;
947 $cache['vid'][$view->vid
] = $view;
948 $cache['name'][$view->name
] = $view;
954 * Save a view to the database.
956 function _views_save_view($view) {
957 _views_check_arrays($view);
960 if (_views_is_cacheable($view)) {
961 $path = drupal_get_path('module', 'views');
962 require_once("$path/views_query.inc");
964 $info = _views_build_query($view);
965 $view->query
= _views_replace_args($info['query'], $info['args']);
966 $view->countquery
= _views_replace_args($info['countquery'], $info['args']);
970 $view->countquery
= NULL
;
973 $view->access
= implode(', ', $view->access
);
975 $view->changed
= time();
976 $fields = _views_view_fields();
979 // Prepare the query:
980 foreach ($view as
$key => $value) {
981 if (in_array($key, $fields)) {
982 $q[] = db_escape_string($key) .
" = '%s'";
987 // Update the view in the database:
988 db_query("UPDATE {view_view} SET ".
implode(', ', $q) .
" WHERE vid = '$view->vid'", $v);
989 db_query("DELETE from {view_sort} WHERE vid='$view->vid'");
990 db_query("DELETE from {view_argument} WHERE vid='$view->vid'");
991 db_query("DELETE from {view_tablefield} WHERE vid='$view->vid'");
992 db_query("DELETE from {view_filter} WHERE vid='$view->vid'");
993 db_query("DELETE from {view_exposed_filter} WHERE vid='$view->vid'");
998 // This method really saves on typos, and makes it a lot easier to add fields
1000 $view->vid
= db_next_id('{view_view}_vid');
1002 // Prepare the query:
1003 foreach ($view as
$key => $value) {
1004 if (in_array((string) $key, $fields)) {
1005 $k[] = db_escape_string($key);
1007 $s[] = is_numeric($value) ?
'%d' : "'%s'";
1011 db_query("INSERT INTO {view_view} (".
implode(", ", $k) .
") VALUES (".
implode(", ", $s) .
")", $v);
1014 foreach ($view->sort as
$i => $sort) {
1015 db_query("INSERT INTO {view_sort} (vid, position, field, sortorder, options) VALUES (%d, %d, '%s', '%s', '%s')", $view->vid
, $i, $sort['field'], $sort['sortorder'], $sort['options']);
1018 foreach ($view->argument as
$i => $arg) {
1019 db_query("INSERT INTO {view_argument} (vid, type, argdefault, title, options, position) VALUES (%d, '%s', %d, '%s', '%s', %d)", $view->vid
, $arg['type'], $arg['argdefault'], $arg['title'], $arg['options'], $i);
1022 foreach ($view->field as
$i => $arg) {
1023 db_query("INSERT INTO {view_tablefield} (vid, tablename, field, label, handler, sortable, defaultsort, options, position) VALUES (%d, '%s', '%s', '%s', '%s', %d, '%s', '%s', %d)", $view->vid
, $arg['tablename'], $arg['field'], $arg['label'], $arg['handler'], $arg['sortable'], $arg['defaultsort'], $arg['options'], $i);
1026 foreach ($view->filter as
$i => $arg) {
1027 if (is_array($arg['value'])) {
1028 $arg['value'] = implode(',', $arg['value']);
1030 db_query("INSERT INTO {view_filter} (vid, tablename, field, value, operator, options, position) VALUES (%d, '%s', '%s', '%s', '%s', '%s', %d)", $view->vid
, $arg['tablename'], $arg['field'], $arg['value'], $arg['operator'], $arg['options'], $i);
1033 foreach ($view->exposed_filter as
$i => $arg) {
1034 db_query("INSERT INTO {view_exposed_filter} (vid, field, label, optional, is_default, single, operator, position) VALUES (%d, '%s', '%s', %d, %d, %d, %d, %d)", $view->vid
, $arg['field'], $arg['label'], $arg['optional'], $arg['is_default'], $arg['single'], $arg['operator'], $i);
1038 // ---------------------------------------------------------------------------
1039 // Helper functions to build views and view data
1042 * Helper function to make table creation a little easier. It adds the necessary
1043 * data to a $table array and returns it.
1045 function views_new_table($table_name, $provider, $left_table, $left_field, $right_field, $extra = NULL
) {
1046 $table['name'] = $table_name;
1047 $table['provider'] = $provider;
1048 $table['join']['left']['table'] = $left_table;
1049 $table['join']['left']['field'] = $left_field;
1050 $table['join']['right']['field'] = $left_field;
1052 $table['join']['extra'] = $extra;
1058 * Helper function to make table creation a little easier. It adds the necessary
1059 * data to the $table array.
1061 function views_table_add_field(&$table, $name, $label, $help, $others = array()) {
1062 views_table_add_data($table, 'fields', $name, $label, $help, $others);
1066 * Helper function to make table creation a little easier. It adds the necessary
1067 * data to the $table array.
1069 function views_table_add_filter(&$table, $name, $label, $help, $others = array()) {
1070 views_table_add_data($table, 'filters', $name, $label, $help, $others);
1074 * Helper function to make table creation a little easier. It adds the necessary
1075 * data to the $table array.
1077 function views_table_add_sort(&$table, $name, $label, $help, $others = array()) {
1078 views_table_add_data($table, 'sorts', $name, $label, $help, $others);
1082 * Helper function to make table creation a little easier. It adds the necessary
1083 * data to the $table array.
1085 function views_table_add_data(&$table, $type, $name, $label, $help, $others = array()) {
1086 $table[$type][$name]['name'] = $label;
1087 $table[$type][$name]['help'] = $help;
1088 foreach ($others as
$key => $value) {
1089 $table[$type][$name][$key] = $value;
1094 * Create a blank view.
1096 function views_create_view($name, $description, $access = array()) {
1097 $view = new
stdClass();
1098 _views_check_arrays($view);
1100 $view->name
= $name;
1101 $view->description
= $description;
1102 $view->access
= $access;
1104 // ensure some things are numerically 0.
1105 $view->nodes_per_page
= 0;
1106 $view->nodes_per_block
= 0;
1111 * Add page info to a view.
1113 function views_view_add_page(&$view, $title, $url, $type, $pager, $nodes_per_page, $header, $header_format, $breadcrumb_no_home = FALSE
) {
1115 $view->page_title
= $title;
1117 $view->page_type
= $type;
1118 $view->use_pager
= $pager;
1119 $view->nodes_per_page
= $nodes_per_page;
1120 $view->page_header
= $header;
1121 $view->page_header_format
= $header_format;
1122 $view->breadcrumb_no_home
= $breadcrumb_no_home;
1126 * Add menu info to a view.
1128 function views_view_add_menu(&$view, $title, $tab, $tab_weight, $default_tab) {
1130 $view->menu_title
= $title;
1131 $view->menu_tab
= $tab;
1132 $view->menu_tab_weight
= $tab_weight;
1133 $view->menu_tab_default
= $default_tab;
1137 * Add block info to a view.
1139 function views_view_add_block(&$view, $title, $type, $nodes_per_block, $more, $use_page_header, $header = '', $header_format = 0) {
1140 $view->block
= TRUE
;
1141 $view->block_title
= $title;
1142 $view->block_type
= $type;
1143 $view->nodes_per_block
= $nodes_per_block;
1144 $view->block_more
= $more;
1145 $view->block_use_page_header
= $use_page_header;
1146 $view->block_header
= $header;
1147 $view->block_header_format
= $header_format;
1151 * Add field info to a view.
1153 function views_view_add_field(&$view, $table, $field, $label, $sortable = FALSE
, $default_sort = 0, $handler = '') {
1154 $view->filter
[] = array(
1155 'tablename' => $table,
1158 'sortable' => $sortable,
1159 'defaultsort' => $default_sort,
1160 'handler' => $handler
1165 * Add argument info to a view.
1167 function views_view_add_argument(&$view, $type, $default, $title, $option = '') {
1168 $view->argument
[] = array(
1170 'argdefault' => $default,
1172 'options' => $option,
1177 * Add filter info to a view.
1179 function views_view_add_filter(&$view, $table, $field, $operator, $value, $option) {
1180 $view->filter
[] = array(
1181 'tablename' => $table,
1183 'operator' => $operator,
1185 'options' => $option,
1190 * Add exposed_filter info to a view.
1192 function views_view_add_exposed_filter(&$view, $table, $field, $optional, $is_default, $lock_operator, $single) {
1193 $view->exposed_filter
[] = array(
1194 'tablename' => $table,
1196 'optional' => $optional,
1197 'is_default' => $is_default,
1198 'operator' => $lock_operator,
1204 * Add sort info to a view.
1206 function views_view_add_sort(&$view, $table, $field, $order, $option) {
1207 $view->sort[] = array(
1208 'tablename' => $table,
1210 'sortorder' => $order,
1211 'options' => $option
1215 // ---------------------------------------------------------------------------
1216 // Themeable and support for themeables.
1219 * Figure out how to display the data of a field. Many fields simply display
1220 * the data as-is, but many fields have to massage that data, which is
1221 * done through handlers.
1223 * DEPRECATED. Left in for backward compatibility.
1225 function _views_handle_field($fields, $field, $data) {
1226 return views_theme_field('views_handle_field', $field['queryname'], $fields, $field, $data);
1230 * Themeable function to handle displaying a specific field.
1232 function theme_views_handle_field($fields, $field, $data) {
1233 $info = $fields[$field['fullname']];
1235 if ($field['handler'] && function_exists($field['handler'])) {
1236 return $field['handler']($info, $field, $data->$field['queryname'], $data);
1239 if ($info['handler'] && is_string($info['handler']) && function_exists($info['handler'])) {
1240 return $info['handler']($info, $field, $data->$field['queryname'], $data);
1243 return check_plain($data->$field['queryname']);
1247 * Construct a header for a table view.
1249 function _views_construct_header($view, $fields) {
1250 foreach ($view->field as
$field) {
1252 $info = $fields[$field['fullname']];
1254 $header['data'] = ($field['label'] ?
$field['label'] : $info['name']);
1256 if ($field['sortable']) {
1257 $header['field'] = $field['fullname'];
1259 if ($field['defaultsort']) {
1260 $header['sort'] = strtolower($field['defaultsort']);
1263 // Add CSS id to table cell header cell.
1264 $header['id'] = "view-field-$field[queryname]";
1265 $header['class'] = "view-cell-header";
1266 $headers[] = $header;
1271 function theme_views_display_filters($view) {
1272 $filters = _views_get_filters();
1273 foreach ($view->exposed_filter as
$count => $expose) {
1274 $id = $expose['id'];
1275 $filterinfo = $filters[$id];
1276 foreach ($view->filter as
$filter) {
1277 if ($filter['id'] == $id) {
1282 // set up the operator widget.
1283 if (!$expose['operator']) {
1284 // 'operator' is either an array or a handler
1285 $operator = $filterinfo['operator'];
1286 if (!is_array($operator) && function_exists($filterinfo['operator'])) {
1287 $operator = $filterinfo['operator']('operator', $filterinfo);
1290 $form["op$count"] = array(
1291 '#name' => "op$count", // get rid of edit[] array.
1292 '#type' => 'select',
1293 '#default_value' => $filter['operator'],
1294 '#options' => $operator,
1296 if (array_key_exists("op$count", $_GET)) {
1297 $form["op$count"]["#default_value"] = $_GET["op$count"];
1301 // set up the filter widget.
1302 $item = $filterinfo['value'];
1303 $item['#name'] = "filter$count";
1305 if (!is_array($item['#options']) && function_exists($item['#options'])) {
1306 $item['#options'] = $item['#options']('value', $filterinfo);
1308 if (!$expose['optional'] || $expose['is_default']) {
1309 $item['#default_value'] = $filter['value'];
1312 if ($expose['single']) {
1313 unset($item['#multiple']);
1315 if ($expose['optional'] && is_array($item['#options'])) {
1316 $item['#options'] = array('**ALL**' => t('<All>')) + $item['#options'];
1319 if (array_key_exists("filter$count", $_GET)) {
1320 $item["#default_value"] = $_GET["filter$count"];
1322 $form["filter$count"] = $item;
1324 $form['#method'] = 'get';
1325 $form['view'] = array('#type' => 'value', '#value' => $view);
1326 $form['submit'] = array('#type' => 'button', '#value' => t('Submit'));
1328 return drupal_get_form("views_filters_$view->name", $form, 'views_filters');
1331 function theme_views_filters($form) {
1332 $view = $form['view']['#value'];
1333 foreach ($view->exposed_filter as
$count => $expose) {
1334 $row[] = form_render($form["op$count"]) .
form_render($form["filter$count"]);
1335 $label[] = $expose['label'];
1337 $row[] = form_render($form['submit']);
1338 $label[] = ''; // so the column count is the same.
1339 return theme('table', $label, array($row)) .
form_render($form);
1343 * Display the nodes of a view as a list.
1345 function theme_views_view_list($view, $nodes) {
1346 $fields = _views_get_fields();
1348 foreach ($nodes as
$node) {
1350 foreach ($view->field as
$field) {
1351 if ($field['label']) {
1352 $item .
= "<div class='view-label view-label-$field[queryname]'>" .
$field['label'] .
"</div>";
1354 $item .
= "<div class='view-field view-data-$field[queryname]'>" .
views_theme_field('views_handle_field', $field['queryname'], $fields, $field, $node) .
"</div>";
1356 $items[] = "<div class='view-item view-item-$view->name'>$item</div>\n"; // l($node->title, "node/$node->nid");
1359 return theme('item_list', $items);
1364 * Display the nodes of a view as a table.
1366 function theme_views_view_table($view, $nodes) {
1367 $fields = _views_get_fields();
1369 foreach ($nodes as
$node) {
1371 foreach ($view->field as
$field) {
1372 $cell['data'] = views_theme_field('views_handle_field', $field['queryname'], $fields, $field, $node);
1373 $cell['class'] = "view-field view-field-$field[queryname]";
1378 return theme('table', $view->table_header
, $rows);
1382 * Display the nodes of a view as teasers.
1384 function theme_views_view_teasers($view, $nodes) {
1385 return views_theme('views_view_nodes', $view, $nodes, true
);
1389 * Display the nodes of a view as plain nodes.
1391 function theme_views_view_nodes($view, $nodes, $teasers = false
, $links = true
) {
1392 foreach ($nodes as
$n) {
1393 $node = node_load($n->nid
);
1394 $output .
= node_view($node, $teasers, false
, $links);
1399 function views_set_breadcrumb($view) {
1400 $breadcrumb = drupal_get_breadcrumb();
1401 if ($view->breadcrumb_no_home
) {
1402 array_shift($breadcrumb);
1406 // Add a breadcrumb trail for each level of argument we're at.
1410 foreach ($view->args as
$level => $arg) {
1411 if ($view->argument
[$level]['argdefault'] != 1) {
1412 $breadcrumb[] = l(views_get_title($view, 'page', $args), $url);
1416 if ($where && $where = strpos('$arg', $url)) {
1417 $url = str_replace($url, $arg, $where, 4);
1425 drupal_set_breadcrumb($breadcrumb);
1428 function views_get_textarea($view, $type, $textarea) {
1429 $use_page = "block_use_page_$textarea";
1430 $var = ($type != 'block' || $view->$use_page ?
'page_' : 'block_') .
$textarea;
1431 $format = $var .
'_format';
1434 return "<div class='view-$textarea view-$textarea-$view->name'>"
1435 .
check_markup($view->$var, $view->$format, false
) .
"</div>\n";
1442 function theme_views_view($view, $type, $nodes, $level = NULL
, $args = NULL
) {
1443 $num_nodes = count($nodes);
1445 if ($type == 'page') {
1446 drupal_set_title(views_get_title($view, 'page'));
1447 views_set_breadcrumb($view);
1451 $output .
= views_get_textarea($view, $type, 'header');
1454 if ($type != 'block' && $view->exposed_filter
) {
1455 $output .
= views_theme('views_display_filters', $view);
1460 if ($level !== NULL
) {
1461 $output .
= views_theme('views_summary', $view, $type, $level, $nodes, $args);
1464 $plugins = _views_get_style_plugins();
1465 $view_type = ($type == 'block') ?
$view->block_type
: $view->page_type
;
1466 $output .
= views_theme($plugins[$view_type]['theme'], $view, $nodes);
1468 $output .
= views_get_textarea($view, $type, 'footer');
1470 if ($type == 'block' && $view->block_more
&& $num_nodes >= $view->nodes_per_block
) {
1471 $output .
= theme('views_more', $view->real_url
);
1475 $output .
= views_get_textarea($view, $type, 'empty');
1478 if ($view->use_pager
) {
1479 $output .
= theme('pager', '', $limit, $view->use_pager
);
1483 $output = "<div class='view view-$view->name'>$output</div>\n";
1489 * Format the 'more' link for a view. Personally I prefer [More] but I've
1490 * been convinced to go with simply 'more'.
1492 function theme_views_more($url) {
1493 return "<div class='more-link'>" .
l(t('more'), $url) .
"</div>";
1497 * Get the summary link for a view.
1499 function views_get_summary_link($argtype, $item, $base) {
1500 $arginfo = _views_get_arguments();
1501 return $arginfo[$argtype]['handler']('link', $item, $argtype, $base);
1505 * In a summary view, each entry links to a more specific entry
1506 * in that view. Construct the base of that link.
1509 function views_get_summary_link_base($argtype, $url, $level, $args) {
1510 $arginfo = _views_get_arguments();
1511 if (!function_exists($arginfo[$argtype]['handler'])) {
1516 for ($i = 0; $i < $level; $i++) {
1517 $arg .= "/$args[$i]";
1524 * Display a summary version of a view.
1526 function theme_views_summary($view, $type, $level, $nodes, $args) {
1527 // $base = views_get_summary_link_base($view->argument[$level]['type'], $view->url, $level, $args);
1528 foreach ($nodes as
$node) {
1529 $items[] = views_get_summary_link($view->argument
[$level]['type'], $node, $view->real_url
) .
" (" .
$node->num_nodes .
")";
1532 $output .
= theme('item_list', $items);
1538 // ---------------------------------------------------------------------------
1539 // Generic handlers. These make sense to be used in a lot of different places.
1542 * Field handlers accept the following arguments:
1544 * The array of info for that field from the global tables array.
1546 * All of the info about that field in the database.
1548 * The value of the field fetched from the database.
1550 * The rest of the data about the node fetched from the database, in case
1551 * the handler needs more than just the field.
1557 function views_handler_field_date($fieldinfo, $fielddata, $value, $data) {
1558 return format_date($value);
1562 * Format a date using small representation.
1564 function views_handler_field_date_small($fieldinfo, $fielddata, $value, $data) {
1565 return format_date($value, 'small');
1569 * Format a date using large representation.
1571 function views_handler_field_date_large($fieldinfo, $fielddata, $value, $data) {
1572 return format_date($value, 'large');
1576 * Format a date using custom representation.
1578 function views_handler_field_date_custom($fieldinfo, $fielddata, $value, $data) {
1579 return format_date($value, 'custom', $fielddata['options']);
1582 * Format a date as "X time ago".
1584 function views_handler_field_since($fieldinfo, $fielddata, $value, $data) {
1585 return format_interval(time() - $value);
1589 * Provide a list of all standard supproted date output handlers.
1591 function views_handler_field_dates() {
1593 'views_handler_field_date_small' => t('As Short Date'),
1594 'views_handler_field_date' => t('As Medium Date'),
1595 'views_handler_field_date_large' => t('As Long Date'),
1596 'views_handler_field_date_custom' => t('As Custom Date'),
1597 'views_handler_field_since' => t('As Time Ago')
1602 * Format a field as an integer.
1604 function views_handler_field_int($fieldinfo, $fielddata, $value, $data) {
1605 return intval($value);
1609 * Argument handlers take up to 4 fields, which vary based upon the operation.
1611 * The operation to perform:
1612 * 'summary': A summary view is being constructed. In this case the handler
1613 * is to add the necessary components to the query to display
1614 * the summary. It must return a $fieldinfo array with 'field'
1615 * set to the field the summary is ordered by; if this is aliased
1616 * for some reason (such as being an aggregate field) set 'fieldname'
1618 * 'sort': Set up the view to sort based upon the setting in $a2.
1619 * 'filter': Filter the view based upon the argument sent; essentially just
1620 * add the where clause here.
1621 * 'link': Provide a link from a summary view based upon the argument sent.
1622 * 'title': Provide the title of a view for substitution.
1624 * For summary, filter and link, this is the actual query object; for title this is
1625 * simply the value of the argument.
1627 * For summary, this is the type of the argument. For the others, this is the info
1628 * for the argument from the global table. (Why is this not consistent? I dunno).
1630 * For summary, this is the 'options' field from the db. For 'filter' this is
1631 * the argument received. For 'link' this is the base URL of the link. Not used
1636 // ---------------------------------------------------------------------------
1640 * There are two kinds of filter handlers here; the easy kind simply creates an
1641 * array of options. For example, for taxonomy we provide a list of all taxonomy
1642 * terms which is placed in the select box.
1644 * The other type is the 'custom' handler which is used to create a customized
1645 * WHERE clause for specialized filters.
1647 * It takes 4 parameters.
1649 * At this time it will always be 'handler'.
1651 * Information on the filter from the database, including 'options', 'value' and 'operator'.
1652 * @param $filterinfo
1653 * Information on the filter from the global table array.
1655 * The query object being worked on.
1659 * A list of and/or/nor.
1661 function views_handler_operator_andor() {
1662 return array('AND' => t('Is All Of'), 'OR' => t('Is One Of'), 'NOR' => t('Is None Of'));
1668 function views_handler_operator_or() {
1669 return array('OR' => t('Is One Of'), 'NOR' => t('Is None Of'));
1673 * A list of equal or not equal to.
1675 function views_handler_operator_eqneq() {
1676 return array('=' => t('Is Equal To'), '!=' => t('Is Not Equal To'));
1680 * A list of greater / equal / less than
1682 function views_handler_operator_gtlt() {
1683 return array('>' => t("Is Greater Than"), '>=' => t("Is Greater Than Or Equals"), '=' => t("Is Equal To"), '!=' => t("Is Not Equal To"), '<=' => t("Is Less Than Or Equals"), '<' => t("Is Less Than"));
1689 function views_handler_operator_yesno() {
1690 return array('1' => t('Yes'), '0' => t('No'));
1694 * Default Views style plugins. Implementation of hook_views_style_plugins()
1696 function views_views_style_plugins() {
1699 'name' => t('List View'),
1700 'theme' => 'views_view_list',
1701 'validate' => 'views_ui_plugin_validate_list',
1704 'name' => t('Table View'),
1705 'theme' => 'views_view_table',
1706 'validate' => 'views_ui_plugin_validate_table',
1709 'name' => t('Teaser List'),
1710 'theme' => 'views_view_teasers',
1713 'name' => t('Full Nodes'),
1714 'theme' => 'views_view_nodes',
1720 * A list of options to be used in LIKE queries
1722 function views_handler_operator_like() {
1723 return array('=' => t('Is Equal To'), 'contains' => t('Contains'), 'starts' => t('Starts With'), 'ends' => t('Ends With'), 'not' => t('Does Not Contain'));
1727 * Custom filter for LIKE operations
1729 function views_handler_filter_like($op, $filter, $filterinfo, &$query) {
1730 switch (trim($filter['value'])) {
1737 $fieldbits = explode('.', $filter['field']);
1738 $query->ensure_table($fieldbits[0]);
1739 switch ($filter['operator']) {
1741 $query->add_where("UPPER(%s) LIKE UPPER('%%%s%%')",
1742 $filter['field'], $filter['value']);
1745 $query->add_where("UPPER(%s) LIKE UPPER('%s%%')",
1746 $filter['field'], $filter['value']);
1749 $query->add_where("UPPER(%s) LIKE UPPER('%%%s')",
1750 $filter['field'], $filter['value']);
1753 $query->add_where("UPPER(%s) NOT LIKE UPPER('%%%s%%')",
1754 $filter['field'], $filter['value']);
1757 $query->add_where("UPPER(%s) = '%%%s%%'",
1758 $filter['field'], $filter['value']);
1766 * Format a field as file size.
1768 function views_handler_field_filesize($fieldinfo, $fielddata, $value, $data) {
1769 return format_size($value);
1773 * Handle a timestamp filter.
1775 function views_handler_filter_timestamp($op, $filter, $filterinfo, &$query) {
1776 $value = $filter['value'] == 'now' ?
"***CURRENT_TIME***" : strtotime($filter['value']);
1778 $field = $filter['field'];
1779 if ($filterinfo['from_unixtime']) {
1780 $field = "from_UNIXTIME($field)";
1783 $query->add_where("%s %s %s + %d", $field, $filter['operator'], $value, $filter['options']);
1787 * Provide a form gadget for dates.
1789 function views_handler_filter_date_value_form() {
1791 '#type' => 'textfield',
1792 '#attributes' => array('class' => 'jscalendar'),
1796 * Substitute current time; this works with cached queries.
1798 function views_views_query_substitutions($view) {
1800 return array('***CURRENT_TIME***' => time());