commiting uncommited changes on live site
[weblabels.fsf.org.git] / crm.fsf.org / 20131203 / files / sites / all / modules-new / views / views.api.php
1 <?php
2
3 /**
4 * @file
5 * Describe hooks provided by the Views module.
6 */
7
8 /**
9 * @mainpage Views 3 API Manual
10 *
11 * Much of this information is actually stored in the advanced help; please
12 * check the API topic. This help will primarily be aimed at documenting
13 * classes and function calls.
14 *
15 * Topics:
16 * - @link views_lifetime The life of a view @endlink
17 * - @link views_hooks Views hooks @endlink
18 * - @link views_handlers About Views handlers @endlink
19 * - @link views_plugins About Views plugins @endlink
20 * - @link views_templates Views template files @endlink
21 * - @link views_module_handlers Views module handlers @endlink
22 */
23
24 /**
25 * @defgroup views_lifetime The life of a view
26 * @{
27 * This page explains the basic cycle of a view and what processes happen.
28 *
29 * @todo.
30 * @}
31 */
32
33 /**
34 * @defgroup views_handlers About Views handlers
35 * @{
36 * In Views, a handler is an object that is part of the view and is part of the
37 * query building flow.
38 *
39 * Handlers are objects; much of the time, the base handlers will work, but
40 * often you'll need to override the handler to achieve something meaningful.
41 * One typical handler override will be views_handler_filter_operator_in which
42 * allows you to have a filter select from a list of options; you'll need to
43 * override this to provide your list.
44 *
45 * Handlers have two distinct code flows; the UI flow and the view building
46 * flow.
47 *
48 * For the query flow:
49 * - handler->construct()
50 * - Create the initial handler; at this time it is not yet attached to a
51 * view. It is here that you can set basic defaults if needed, but there
52 * will be no knowledge of the environment yet.
53 * - handler->set_definition()
54 * - Set the data from hook_views_data() relevant to the handler.
55 * - handler->init()
56 * - Attach the handler to a view, and usually provides the options from the
57 * display.
58 * - handler->pre_query()
59 * - Run prior to the query() stage to do early processing.
60 * - handler->query()
61 * - Do the bulk of the work this handler needs to do to add itself to the
62 * query.
63 *
64 * Fields, being the only handlers concerned with output, also have an extended
65 * piece of the flow:
66 *
67 * - handler->pre_render(&$values)
68 * - Called prior to the actual rendering, this allows handlers to query for
69 * extra data; the entire resultset is available here, and this is where
70 * items that have "multiple values" per record can do their extra query for
71 * all of the records available. There are several examples of this at work
72 * in the code, see for example views_handler_field_user_roles.
73 * - handler->render()
74 * - This does the actual work of rendering the field.
75 *
76 * Most handlers are just extensions of existing classes with a few tweaks that
77 * are specific to the field in question. For example,
78 * views_handler_filter_in_operator provides a simple mechanism to set a
79 * multiple-value list for setting filter values. Below,
80 * views_handler_filter_node_type overrides the list options, but inherits
81 * everything else.
82 *
83 * @code
84 * class views_handler_filter_node_type extends views_handler_filter_in_operator {
85 * function get_value_options() {
86 * if (!isset($this->value_options)) {
87 * $this->value_title = t('Node type');
88 * $types = node_get_types();
89 * foreach ($types as $type => $info) {
90 * $options[$type] = $info-&gt;name;
91 * }
92 * $this->value_options = $options;
93 * }
94 * }
95 * }
96 * @endcode
97 *
98 * Handlers are stored in their own files and loaded on demand. Like all other
99 * module files, they must first be registered through the module's info file.
100 * For example:
101 *
102 * @code
103 * name = Example module
104 * description = "Gives an example of a module."
105 * core = 7.x
106 * files[] = example.module
107 * files[] = example.install
108 *
109 * ; Views handlers
110 * files[] = includes/views/handlers/example_handler_argument_string.inc
111 * @endcode
112 *
113 * The best place to learn more about handlers and how they work is to explore
114 * @link views_handlers Views' handlers @endlink and use existing handlers as a
115 * guide and a model. Understanding how views_handler and its child classes work
116 * is handy but you can do a lot just following these models. You can also
117 * explore the views module directory, particularly node.views.inc.
118 *
119 * Please note that while all handler names in views are prefixed with views_,
120 * you should use your own module's name to prefix your handler names in order
121 * to ensure namespace safety. Note that the basic pattern for handler naming
122 * goes like this:
123 *
124 * [module]_handler_[type]_[tablename]_[fieldname].
125 *
126 * Sometimes table and fieldname are not appropriate, but something that
127 * resembles what the table/field would be can be used.
128 *
129 * See also:
130 * - @link views_field_handlers Views field handlers @endlink
131 * - @link views_sort_handlers Views sort handlers @endlink
132 * - @link views_filter_handlers Views filter handlers @endlink
133 * - @link views_argument_handlers Views argument handlers @endlink
134 * - @link views_relationship_handlers Views relationship handlers @endlink
135 * - @link views_area_handlers Views area handlers @endlink
136 * @}
137 */
138
139 /**
140 * @defgroup views_plugins About Views plugins
141 *
142 * In Views, a plugin is a bit like a handler, but plugins are not directly
143 * responsible for building the query. Instead, they are objects that are used
144 * to display the view or make other modifications.
145 *
146 * There are several types of plugins in Views:
147 * - Display: Display plugins are responsible for controlling *where* a view
148 * lives; that is, how they are being exposed to other parts of Drupal. Page
149 * and block are the most common displays, as well as the ubiquitous 'master'
150 * (or 'default') display.
151 * - Style: Style plugins control how a view is displayed. For the most part
152 * they are object wrappers around theme templates. Styles could for example
153 * be HTML lists or tables.
154 * - Row style: Row styles handle each individual record from the main view
155 * table. The two included by default render the entire entity (nodes only),
156 * or selected fields.
157 * - Argument default: Argument default plugins allow pluggable ways of
158 * providing default values for contextual filters (previously 'arguments').
159 * This is useful for blocks and other display types lacking a natural
160 * argument input. Examples are plugins to extract node and user IDs from the
161 * URL.
162 * - Argument validator: Validator plugins can ensure arguments are valid, and
163 * even do transformations on the arguments. They can also provide replacement
164 * patterns for the view title. For example, the 'content' validator
165 * verifies verifies that the argument value corresponds to a node, loads
166 * that node and provides the node title as a replacement pattern.
167 * - Access: Access plugins are responsible for controlling access to the view.
168 * Views includes plugins for checking user roles and individual permissions.
169 * - Query: Query plugins generate and execute a query, so they can be seen as
170 * a data backend. The default implementation is using SQL. There are
171 * contributed modules reading data from other sources, see for example the
172 * Views XML Backend module.
173 * - Cache: Cache plugins control the storage and loading of caches. Currently
174 * they can do both result and render caching, but maybe one day cache the
175 * generated query.
176 * - Pager plugins: Pager plugins take care of everything regarding pagers.
177 * From getting and setting the total amount of items to render the pager and
178 * setting the global pager arrays.
179 * - Exposed form plugins: Exposed form plugins are responsible for building,
180 * rendering and controlling exposed forms. They can expose new parts of the
181 * view to the user and more.
182 * - Localization plugins: Localization plugins take care how the view options
183 * are translated. There are example implementations for t(), 'no
184 * translation' and i18n.
185 * - Display extenders: Display extender plugins allow scaling of views options
186 * horizontally. This means that you can add options and do stuff on all
187 * views displays. One theoretical example is metatags for views.
188 *
189 * Plugins are registered by implementing hook_views_plugins() in your
190 * modulename.views.inc file and returning an array of data.
191 * For examples please look at views_views_plugins() in
192 * views/includes/plugins.inc as it has examples for all of them.
193 *
194 * Similar to handlers, make sure that you add your plugin files to the
195 * module.info file.
196 *
197 * The array defining plugins will look something like this:
198 * @code
199 * return array(
200 * 'display' => array(
201 * // ... list of display plugins,
202 * ),
203 * 'style' => array(
204 * // ... list of style plugins,
205 * ),
206 * 'row' => array(
207 * // ... list of row style plugins,
208 * ),
209 * 'argument default' => array(
210 * // ... list of argument default plugins,
211 * ),
212 * 'argument validator' => array(
213 * // ... list of argument validator plugins,
214 * ),
215 * 'access' => array(
216 * // ... list of access plugins,
217 * ),
218 * 'query' => array(
219 * // ... list of query plugins,
220 * ),,
221 * 'cache' => array(
222 * // ... list of cache plugins,
223 * ),,
224 * 'pager' => array(
225 * // ... list of pager plugins,
226 * ),,
227 * 'exposed_form' => array(
228 * // ... list of exposed_form plugins,
229 * ),,
230 * 'localization' => array(
231 * // ... list of localization plugins,
232 * ),
233 * 'display_extender' => array(
234 * // ... list of display extender plugins,
235 * ),
236 * );
237 * @endcode
238 *
239 * Each plugin will be registered with an identifier for the plugin, plus a
240 * fairly lengthy list of items that can define how and where the plugin is
241 * used. Here is an example of a row style plugin from Views core:
242 * @code
243 * 'node' => array(
244 * 'title' => t('Node'),
245 * 'help' => t('Display the node with standard node view.'),
246 * 'handler' => 'views_plugin_row_node_view',
247 * 'path' => drupal_get_path('module', 'views') . '/modules/node', // not necessary for most modules
248 * 'theme' => 'views_view_row_node',
249 * 'base' => array('node'), // only works with 'node' as base.
250 * 'uses options' => TRUE,
251 * 'type' => 'normal',
252 * ),
253 * @endcode
254 *
255 * Of particular interest is the *path* directive, which works a little
256 * differently from handler registration; each plugin must define its own path,
257 * rather than relying on a global info for the paths. For example:
258 * @code
259 * 'feed' => array(
260 * 'title' => t('Feed'),
261 * 'help' => t('Display the view as a feed, such as an RSS feed.'),
262 * 'handler' => 'views_plugin_display_feed',
263 * 'uses hook menu' => TRUE,
264 * 'use ajax' => FALSE,
265 * 'use pager' => FALSE,
266 * 'accept attachments' => FALSE,
267 * 'admin' => t('Feed'),
268 * 'help topic' => 'display-feed',
269 * ),
270 * @endcode
271 *
272 * Please be sure to prefix your plugin identifiers with your module name to
273 * ensure namespace safety; after all, two different modules could try to
274 * implement the 'grid2' plugin, and that would cause one plugin to completely
275 * fail.
276 *
277 * @todo Finish this document.
278 *
279 * See also:
280 * - @link views_display_plugins Views display plugins @endlink
281 * - @link views_style_plugins Views style plugins @endlink
282 * - @link views_row_plugins Views row plugins @endlink
283 */
284
285 /**
286 * @defgroup views_hooks Views hooks
287 * @{
288 * Hooks that can be implemented by other modules in order to implement the
289 * Views API.
290 */
291
292 /**
293 * Describes data tables (or the equivalent) to Views.
294 *
295 * This hook should be placed in MODULENAME.views.inc and it will be
296 * auto-loaded. MODULENAME.views.inc must be in the directory specified by the
297 * 'path' key returned by MODULENAME_views_api(), or the same directory as the
298 * .module file, if 'path' is unspecified.
299 *
300 * @return
301 * An associative array describing the data structure. Primary key is the
302 * name used internally by Views for the table(s) – usually the actual table
303 * name. The values for the key entries are described in detail below.
304 */
305 function hook_views_data() {
306 // This example describes how to write hook_views_data() for the following
307 // table:
308 //
309 // CREATE TABLE example_table (
310 // nid INT(11) NOT NULL COMMENT 'Primary key; refers to {node}.nid.',
311 // plain_text_field VARCHAR(32) COMMENT 'Just a plain text field.',
312 // numeric_field INT(11) COMMENT 'Just a numeric field.',
313 // boolean_field INT(1) COMMENT 'Just an on/off field.',
314 // timestamp_field INT(8) COMMENT 'Just a timestamp field.',
315 // PRIMARY KEY(nid)
316 // );
317
318 // First, the entry $data['example_table']['table'] describes properties of
319 // the actual table – not its content.
320
321 // The 'group' index will be used as a prefix in the UI for any of this
322 // table's fields, sort criteria, etc. so it's easy to tell where they came
323 // from.
324 $data['example_table']['table']['group'] = t('Example table');
325
326 // Define this as a base table – a table that can be described in itself by
327 // views (and not just being brought in as a relationship). In reality this
328 // is not very useful for this table, as it isn't really a distinct object of
329 // its own, but it makes a good example.
330 $data['example_table']['table']['base'] = array(
331 'field' => 'nid', // This is the identifier field for the view.
332 'title' => t('Example table'),
333 'help' => t('Example table contains example content and can be related to nodes.'),
334 'weight' => -10,
335 );
336
337 // This table references the {node} table. The declaration below creates an
338 // 'implicit' relationship to the node table, so that when 'node' is the base
339 // table, the fields are automatically available.
340 $data['example_table']['table']['join'] = array(
341 // Index this array by the table name to which this table refers.
342 // 'left_field' is the primary key in the referenced table.
343 // 'field' is the foreign key in this table.
344 'node' => array(
345 'left_field' => 'nid',
346 'field' => 'nid',
347 ),
348 );
349
350 // Next, describe each of the individual fields in this table to Views. This
351 // is done by describing $data['example_table']['FIELD_NAME']. This part of
352 // the array may then have further entries:
353 // - title: The label for the table field, as presented in Views.
354 // - help: The description text for the table field.
355 // - relationship: A description of any relationship handler for the table
356 // field.
357 // - field: A description of any field handler for the table field.
358 // - sort: A description of any sort handler for the table field.
359 // - filter: A description of any filter handler for the table field.
360 // - argument: A description of any argument handler for the table field.
361 // - area: A description of any handler for adding content to header,
362 // footer or as no result behaviour.
363 //
364 // The handler descriptions are described with examples below.
365
366 // Node ID table field.
367 $data['example_table']['nid'] = array(
368 'title' => t('Example content'),
369 'help' => t('Some example content that references a node.'),
370 // Define a relationship to the {node} table, so example_table views can
371 // add a relationship to nodes. If you want to define a relationship the
372 // other direction, use hook_views_data_alter(), or use the 'implicit' join
373 // method described above.
374 'relationship' => array(
375 'base' => 'node', // The name of the table to join with.
376 'base field' => 'nid', // The name of the field on the joined table.
377 // 'field' => 'nid' -- see hook_views_data_alter(); not needed here.
378 'handler' => 'views_handler_relationship',
379 'label' => t('Default label for the relationship'),
380 'title' => t('Title shown when adding the relationship'),
381 'help' => t('More information on this relationship'),
382 ),
383 );
384
385 // Example plain text field.
386 $data['example_table']['plain_text_field'] = array(
387 'title' => t('Plain text field'),
388 'help' => t('Just a plain text field.'),
389 'field' => array(
390 'handler' => 'views_handler_field',
391 'click sortable' => TRUE, // This is use by the table display plugin.
392 ),
393 'sort' => array(
394 'handler' => 'views_handler_sort',
395 ),
396 'filter' => array(
397 'handler' => 'views_handler_filter_string',
398 ),
399 'argument' => array(
400 'handler' => 'views_handler_argument_string',
401 ),
402 );
403
404 // Example numeric text field.
405 $data['example_table']['numeric_field'] = array(
406 'title' => t('Numeric field'),
407 'help' => t('Just a numeric field.'),
408 'field' => array(
409 'handler' => 'views_handler_field_numeric',
410 'click sortable' => TRUE,
411 ),
412 'filter' => array(
413 'handler' => 'views_handler_filter_numeric',
414 ),
415 'sort' => array(
416 'handler' => 'views_handler_sort',
417 ),
418 );
419
420 // Example boolean field.
421 $data['example_table']['boolean_field'] = array(
422 'title' => t('Boolean field'),
423 'help' => t('Just an on/off field.'),
424 'field' => array(
425 'handler' => 'views_handler_field_boolean',
426 'click sortable' => TRUE,
427 ),
428 'filter' => array(
429 'handler' => 'views_handler_filter_boolean_operator',
430 // Note that you can override the field-wide label:
431 'label' => t('Published'),
432 // This setting is used by the boolean filter handler, as possible option.
433 'type' => 'yes-no',
434 // use boolean_field = 1 instead of boolean_field <> 0 in WHERE statement.
435 'use equal' => TRUE,
436 ),
437 'sort' => array(
438 'handler' => 'views_handler_sort',
439 ),
440 );
441
442 // Example timestamp field.
443 $data['example_table']['timestamp_field'] = array(
444 'title' => t('Timestamp field'),
445 'help' => t('Just a timestamp field.'),
446 'field' => array(
447 'handler' => 'views_handler_field_date',
448 'click sortable' => TRUE,
449 ),
450 'sort' => array(
451 'handler' => 'views_handler_sort_date',
452 ),
453 'filter' => array(
454 'handler' => 'views_handler_filter_date',
455 ),
456 );
457
458 return $data;
459 }
460
461 /**
462 * Alter table structure.
463 *
464 * You can add/edit/remove existing tables defined by hook_views_data().
465 *
466 * This hook should be placed in MODULENAME.views.inc and it will be
467 * auto-loaded. MODULENAME.views.inc must be in the directory specified by the
468 * 'path' key returned by MODULENAME_views_api(), or the same directory as the
469 * .module file, if 'path' is unspecified.
470 *
471 * @param $data
472 * An array of all Views data, passed by reference. See hook_views_data() for
473 * structure.
474 *
475 * @see hook_views_data()
476 */
477 function hook_views_data_alter(&$data) {
478 // This example alters the title of the node:nid field in the Views UI.
479 $data['node']['nid']['title'] = t('Node-Nid');
480
481 // This example adds an example field to the users table.
482 $data['users']['example_field'] = array(
483 'title' => t('Example field'),
484 'help' => t('Some example content that references a user'),
485 'field' => array(
486 'handler' => 'modulename_handler_field_example_field',
487 ),
488 );
489
490 // This example changes the handler of the node title field.
491 // In this handler you could do stuff, like preview of the node when clicking
492 // the node title.
493 $data['node']['title']['field']['handler'] = 'modulename_handler_field_node_title';
494
495 // This example adds a relationship to table {foo}, so that 'foo' views can
496 // add this table using a relationship. Because we don't want to write over
497 // the primary key field definition for the {foo}.fid field, we use a dummy
498 // field name as the key.
499 $data['foo']['dummy_name'] = array(
500 'title' => t('Example relationship'),
501 'help' => t('Example help'),
502 'relationship' => array(
503 'base' => 'example_table', // Table we're joining to.
504 'base field' => 'eid', // Field on the joined table.
505 'field' => 'fid', // Real field name on the 'foo' table.
506 'handler' => 'views_handler_relationship',
507 'label' => t('Default label for relationship'),
508 'title' => t('Title seen when adding relationship'),
509 'help' => t('More information about relationship.'),
510 ),
511 );
512
513 // Note that the $data array is not returned – it is modified by reference.
514 }
515
516 /**
517 * Override the default data for a Field API field.
518 *
519 * Field module's implementation of hook_views_data() invokes this for each
520 * field in the module that defines the field type (as declared in the field
521 * array). It is not invoked in other modules.
522 *
523 * If no hook implementation exists, hook_views_data() falls back to
524 * field_views_field_default_views_data().
525 *
526 * @see field_views_data()
527 * @see hook_field_views_data_alter()
528 * @see hook_field_views_data_views_data_alter()
529 *
530 * @param $field
531 * A field definition array, as returned by field_info_fields().
532 *
533 * @return
534 * An array of views data, in the same format as the return value of
535 * hook_views_data().
536 */
537 function hook_field_views_data($field) {
538
539 }
540
541 /**
542 * Alter the views data for a single Field API field.
543 *
544 * This is called even if there is no hook_field_views_data() implementation for
545 * the field, and therefore may be used to alter the default data that
546 * field_views_field_default_views_data() supplies for the field.
547 *
548 * @param $result
549 * An array of views table data provided for a single field. This has the same
550 * format as the return value of hook_views_data().
551 * @param $field
552 * A field definition array, as returned by field_info_fields().
553 * @param $module
554 * The module that defines the field type.
555 *
556 * @see field_views_data()
557 * @see hook_field_views_data()
558 * @see hook_field_views_data_views_data_alter()
559 */
560 function hook_field_views_data_alter(&$result, $field, $module) {
561
562 }
563
564 /**
565 * Alter the views data on a per field basis.
566 *
567 * Field module's implementation of hook_views_data_alter() invokes this for
568 * each field in the module that defines the field type (as declared in the
569 * field array). It is not invoked in other modules.
570 *
571 * Unlike hook_field_views_data_alter(), this operates on the whole of the views
572 * data. This allows a field module to add data that concerns its fields to
573 * other tables, which would not yet be defined at the point when
574 * hook_field_views_data() and hook_field_views_data_alter() are invoked. For
575 * example, entityreference adds reverse relationships on the tables for the
576 * entities which are referenced by entityreference fields.
577 *
578 * (Note: this is weirdly named so as not to conflict with
579 * hook_field_views_data_alter().)
580 *
581 * @see hook_field_views_data()
582 * @see hook_field_views_data_alter()
583 * @see field_views_data_alter()
584 */
585 function hook_field_views_data_views_data_alter(&$data, $field) {
586 $field_name = $field['field_name'];
587 $data_key = 'field_data_' . $field_name;
588 // Views data for this field is in $data[$data_key]
589 }
590
591 /**
592 * Describes plugins defined by the module.
593 *
594 * This hook should be placed in MODULENAME.views.inc and it will be
595 * auto-loaded. MODULENAME.views.inc must be in the directory specified by the
596 * 'path' key returned by MODULENAME_views_api(), or the same directory as the
597 * .module file, if 'path' is unspecified. All plugin files need to be
598 * referenced in MODULENAME.info with the files[] directive.
599 *
600 * @return
601 * An array on the form $plugins['PLUGIN TYPE']['PLUGIN NAME']. The plugin
602 * must be one of row, display, display_extender, style, argument default,
603 * argument validator, access, query, cache, pager, exposed_form or
604 * localization. The plugin name should be prefixed with your module name.
605 * The value for each entry is an associative array that may contain the
606 * following entries:
607 * - Used by all plugin types:
608 * - title (required): The name of the plugin, as shown in Views. Wrap in
609 * t().
610 * - handler (required): The name of the file containing the class
611 * describing the handler, which must also be the name of the handler's
612 * class.
613 * - path: Path to the handler. Only required if the handler is not placed
614 * in the same folder as the .module file or in the subfolder 'views'.
615 * - parent: The name of the plugin this plugin extends. Since Drupal 7 this
616 * is no longer required, but may still be useful from a code readability
617 * perspective.
618 * - no ui: Set to TRUE to denote that the plugin doesn't appear to be
619 * selectable in the ui, though on the api side they still exists.
620 * - uses options: Set to TRUE to denote that the plugin has an additional
621 * options form.
622 * - help: A short help text, wrapped in t() used as description on the plugin settings form.
623 * - help topic: The name of an entry by advanced help for the plugin.
624 * - theme: The name of a theme suggestion to use for the display.
625 * - js: An array with paths to js files that should be included for the
626 * display. Note that the path should be relative Drupal root, not module
627 * root.
628 * - type: Each plugin can specify a type parameter to group certain
629 * plugins together. For example all row plugins related to feeds are
630 * grouped together, because a rss style plugin only accepts feed row
631 * plugins.
632 *
633 * - Used by display plugins:
634 * - admin: The administrative name of the display, as displayed on the
635 * Views overview and also used as default name for new displays. Wrap in
636 * t().
637 * - no remove: Set to TRUE to make the display non-removable. (Basically
638 * only used for the master/default display.)
639 * - use ajax: Set to TRUE to allow AJAX loads in the display. If it's
640 * disabled there will be no ajax option in the ui.
641 * - use pager: Set to TRUE to allow paging in the display.
642 * - use more: Set to TRUE to allow the 'use more' setting in the display.
643 * - accept attachments: Set to TRUE to allow attachment displays to be
644 * attached to this display type.
645 * - contextual links locations: An array with places where contextual links
646 * should be added. Can for example be 'page' or 'block'. If you don't
647 * specify it there will be contextual links around the rendered view. If
648 * this is not set or regions have been specified, views will display an
649 * option to 'hide contextual links'. Use an empty array if you do not want
650 * this.
651 * - uses hook menu: Set to TRUE to have the display included by
652 * views_menu_alter(). views_menu_alter executes then execute_hook_menu
653 * on the display object.
654 * - uses hook block: Set to TRUE to have the display included by
655 * views_block_info().
656 * - theme: The name of a theme suggestion to use for the display.
657 * - js: An array with paths to js files that should be included for the
658 * display. Note that the path should be relative Drupal root, not module
659 * root.
660 *
661 * - Used by style plugins:
662 * - uses row plugin: Set to TRUE to allow row plugins for this style.
663 * - uses row class: Set to TRUE to allow the CSS class settings for rows.
664 * - uses fields: Set to TRUE to have the style plugin accept field
665 * handlers.
666 * - uses grouping: Set to TRUE to allow the grouping settings for rows.
667 * - even empty: May have the value 'even empty' to tell Views that the style
668 * should be rendered even if there are no results.
669 *
670 * - Used by row plugins:
671 * - uses fields: Set to TRUE to have the row plugin accept field handlers.
672 */
673 function hook_views_plugins() {
674 $plugins = array();
675 $plugins['argument validator'] = array(
676 'taxonomy_term' => array(
677 'title' => t('Taxonomy term'),
678 'handler' => 'views_plugin_argument_validate_taxonomy_term',
679 // Declaring path explicitly not necessary for most modules.
680 'path' => drupal_get_path('module', 'views') . '/modules/taxonomy',
681 ),
682 );
683
684 return array(
685 'module' => 'views', // This just tells our themes are elsewhere.
686 'argument validator' => array(
687 'taxonomy_term' => array(
688 'title' => t('Taxonomy term'),
689 'handler' => 'views_plugin_argument_validate_taxonomy_term',
690 'path' => drupal_get_path('module', 'views') . '/modules/taxonomy', // not necessary for most modules
691 ),
692 ),
693 'argument default' => array(
694 'taxonomy_tid' => array(
695 'title' => t('Taxonomy term ID from URL'),
696 'handler' => 'views_plugin_argument_default_taxonomy_tid',
697 'path' => drupal_get_path('module', 'views') . '/modules/taxonomy',
698 'parent' => 'fixed',
699 ),
700 ),
701 );
702 }
703
704 /**
705 * Alter existing plugins data, defined by modules.
706 *
707 * @see hook_views_plugins()
708 */
709 function hook_views_plugins_alter(&$plugins) {
710 // Add apachesolr to the base of the node row plugin.
711 $plugins['row']['node']['base'][] = 'apachesolr';
712 }
713
714 /**
715 * Register View API information.
716 *
717 * This is required for your module to have its include files loaded; for
718 * example, when implementing hook_views_default_views().
719 *
720 * @return
721 * An array with the following possible keys:
722 * - api: (required) The version of the Views API the module implements.
723 * - path: (optional) If includes are stored somewhere other than within the
724 * root module directory, specify its path here.
725 * - template path: (optional) A path where the module has stored it's views
726 * template files. When you have specified this key views automatically
727 * uses the template files for the views. You can use the same naming
728 * conventions like for normal views template files.
729 */
730 function hook_views_api() {
731 return array(
732 'api' => 3,
733 'path' => drupal_get_path('module', 'example') . '/includes/views',
734 'template path' => drupal_get_path('module', 'example') . '/themes',
735 );
736 }
737
738 /**
739 * This hook allows modules to provide their own views which can either be used
740 * as-is or as a "starter" for users to build from.
741 *
742 * This hook should be placed in MODULENAME.views_default.inc and it will be
743 * auto-loaded. MODULENAME.views_default.inc must be in the directory specified
744 * by the 'path' key returned by MODULENAME_views_api(), or the same directory
745 * as the .module file, if 'path' is unspecified.
746 *
747 * The $view->disabled boolean flag indicates whether the View should be
748 * enabled (FALSE) or disabled (TRUE) by default.
749 *
750 * @return
751 * An associative array containing the structures of views, as generated from
752 * the Export tab, keyed by the view name. A best practice is to go through
753 * and add t() to all title and label strings, with the exception of menu
754 * strings.
755 */
756 function hook_views_default_views() {
757 // Begin copy and paste of output from the Export tab of a view.
758 $view = new view;
759 $view->name = 'frontpage';
760 $view->description = 'Emulates the default Drupal front page; you may set the default home page path to this view to make it your front page.';
761 $view->tag = 'default';
762 $view->base_table = 'node';
763 $view->human_name = 'Front page';
764 $view->core = 0;
765 $view->api_version = '3.0';
766 $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
767
768 /* Display: Master */
769 $handler = $view->new_display('default', 'Master', 'default');
770 $handler->display->display_options['access']['type'] = 'none';
771 $handler->display->display_options['cache']['type'] = 'none';
772 $handler->display->display_options['query']['type'] = 'views_query';
773 $handler->display->display_options['query']['options']['query_comment'] = FALSE;
774 $handler->display->display_options['exposed_form']['type'] = 'basic';
775 $handler->display->display_options['pager']['type'] = 'full';
776 $handler->display->display_options['style_plugin'] = 'default';
777 $handler->display->display_options['row_plugin'] = 'node';
778 /* Sort criterion: Content: Sticky */
779 $handler->display->display_options['sorts']['sticky']['id'] = 'sticky';
780 $handler->display->display_options['sorts']['sticky']['table'] = 'node';
781 $handler->display->display_options['sorts']['sticky']['field'] = 'sticky';
782 $handler->display->display_options['sorts']['sticky']['order'] = 'DESC';
783 /* Sort criterion: Content: Post date */
784 $handler->display->display_options['sorts']['created']['id'] = 'created';
785 $handler->display->display_options['sorts']['created']['table'] = 'node';
786 $handler->display->display_options['sorts']['created']['field'] = 'created';
787 $handler->display->display_options['sorts']['created']['order'] = 'DESC';
788 /* Filter criterion: Content: Promoted to front page */
789 $handler->display->display_options['filters']['promote']['id'] = 'promote';
790 $handler->display->display_options['filters']['promote']['table'] = 'node';
791 $handler->display->display_options['filters']['promote']['field'] = 'promote';
792 $handler->display->display_options['filters']['promote']['value'] = '1';
793 $handler->display->display_options['filters']['promote']['group'] = 0;
794 $handler->display->display_options['filters']['promote']['expose']['operator'] = FALSE;
795 /* Filter criterion: Content: Published */
796 $handler->display->display_options['filters']['status']['id'] = 'status';
797 $handler->display->display_options['filters']['status']['table'] = 'node';
798 $handler->display->display_options['filters']['status']['field'] = 'status';
799 $handler->display->display_options['filters']['status']['value'] = '1';
800 $handler->display->display_options['filters']['status']['group'] = 0;
801 $handler->display->display_options['filters']['status']['expose']['operator'] = FALSE;
802
803 /* Display: Page */
804 $handler = $view->new_display('page', 'Page', 'page');
805 $handler->display->display_options['path'] = 'frontpage';
806
807 /* Display: Feed */
808 $handler = $view->new_display('feed', 'Feed', 'feed');
809 $handler->display->display_options['defaults']['title'] = FALSE;
810 $handler->display->display_options['title'] = 'Front page feed';
811 $handler->display->display_options['pager']['type'] = 'some';
812 $handler->display->display_options['style_plugin'] = 'rss';
813 $handler->display->display_options['row_plugin'] = 'node_rss';
814 $handler->display->display_options['path'] = 'rss.xml';
815 $handler->display->display_options['displays'] = array(
816 'default' => 'default',
817 'page' => 'page',
818 );
819 $handler->display->display_options['sitename_title'] = '1';
820
821 // (Export ends here.)
822
823 // Add view to list of views to provide.
824 $views[$view->name] = $view;
825
826 // ...Repeat all of the above for each view the module should provide.
827
828 // At the end, return array of default views.
829 return $views;
830 }
831
832 /**
833 * Alter default views defined by other modules.
834 *
835 * This hook is called right before all default views are cached to the
836 * database. It takes a keyed array of views by reference.
837 *
838 * Example usage to add a field to a view:
839 * @code
840 * $handler =& $view->display['DISPLAY_ID']->handler;
841 * // Add the user name field to the view.
842 * $handler->display->display_options['fields']['name']['id'] = 'name';
843 * $handler->display->display_options['fields']['name']['table'] = 'users';
844 * $handler->display->display_options['fields']['name']['field'] = 'name';
845 * $handler->display->display_options['fields']['name']['label'] = 'Author';
846 * $handler->display->display_options['fields']['name']['link_to_user'] = 1;
847 * @endcode
848 */
849 function hook_views_default_views_alter(&$views) {
850 if (isset($views['taxonomy_term'])) {
851 $views['taxonomy_term']->display['default']->display_options['title'] = 'Categories';
852 }
853 }
854
855 /**
856 * Performs replacements in the query before being performed.
857 *
858 * @param $view
859 * The View being executed.
860 * @return
861 * An array with keys being the strings to replace, and the values the strings
862 * to replace them with. The strings to replace are often surrounded with
863 * '***', as illustrated in the example implementation.
864 */
865 function hook_views_query_substitutions($view) {
866 // Example from views_views_query_substitutions().
867 global $language_content;
868 return array(
869 '***CURRENT_VERSION***' => VERSION,
870 '***CURRENT_TIME***' => REQUEST_TIME,
871 '***CURRENT_LANGUAGE***' => $language_content->language,
872 '***DEFAULT_LANGUAGE***' => language_default('language'),
873 );
874 }
875
876 /**
877 * This hook is called to get a list of placeholders and their substitutions,
878 * used when preprocessing a View with form elements.
879 *
880 * @return
881 * An array with keys being the strings to replace, and the values the strings
882 * to replace them with.
883 */
884 function hook_views_form_substitutions() {
885 return array(
886 '<!--views-form-example-substitutions-->' => 'Example Substitution',
887 );
888 }
889
890 /**
891 * Allows altering a view at the very beginning of views processing, before
892 * anything is done.
893 *
894 * Adding output to the view can be accomplished by placing text on
895 * $view->attachment_before and $view->attachment_after.
896 * @param $view
897 * The view object about to be processed.
898 * @param $display_id
899 * The machine name of the active display.
900 * @param $args
901 * An array of arguments passed into the view.
902 */
903 function hook_views_pre_view(&$view, &$display_id, &$args) {
904 // Change the display if the acting user has 'administer site configuration'
905 // permission, to display something radically different.
906 // (Note that this is not necessarily the best way to solve that task. Feel
907 // free to contribute another example!)
908 if (
909 $view->name == 'my_special_view' &&
910 user_access('administer site configuration') &&
911 $display_id == 'public_display'
912 ) {
913 $view->set_display('private_display');
914 }
915 }
916
917 /**
918 * This hook is called right before the build process, but after displays
919 * are attached and the display performs its pre_execute phase.
920 *
921 * Adding output to the view can be accomplished by placing text on
922 * $view->attachment_before and $view->attachment_after.
923 * @param $view
924 * The view object about to be processed.
925 */
926 function hook_views_pre_build(&$view) {
927 // Because of some inexplicable business logic, we should remove all
928 // attachments from all views on Mondays.
929 // (This alter could be done later in the execution process as well.)
930 if (date('D') == 'Mon') {
931 unset($view->attachment_before);
932 unset($view->attachment_after);
933 }
934 }
935
936 /**
937 * This hook is called right after the build process. The query is now fully
938 * built, but it has not yet been run through db_rewrite_sql.
939 *
940 * Adding output to the view can be accomplished by placing text on
941 * $view->attachment_before and $view->attachment_after.
942 * @param $view
943 * The view object about to be processed.
944 */
945 function hook_views_post_build(&$view) {
946 // If the exposed field 'type' is set, hide the column containing the content
947 // type. (Note that this is a solution for a particular view, and makes
948 // assumptions about both exposed filter settings and the fields in the view.
949 // Also note that this alter could be done at any point before the view being
950 // rendered.)
951 if ($view->name == 'my_view' && isset($view->exposed_raw_input['type']) && $view->exposed_raw_input['type'] != 'All') {
952 // 'Type' should be interpreted as content type.
953 if (isset($view->field['type'])) {
954 $view->field['type']->options['exclude'] = TRUE;
955 }
956 }
957 }
958
959 /**
960 * This hook is called right before the execute process. The query is now fully
961 * built, but it has not yet been run through db_rewrite_sql.
962 *
963 * Adding output to the view can be accomplished by placing text on
964 * $view->attachment_before and $view->attachment_after.
965 * @param $view
966 * The view object about to be processed.
967 */
968 function hook_views_pre_execute(&$view) {
969 // Whenever a view queries more than two tables, show a message that notifies
970 // view administrators that the query might be heavy.
971 // (This action could be performed later in the execution process, but not
972 // earlier.)
973 if (count($view->query->tables) > 2 && user_access('administer views')) {
974 drupal_set_message(t('The view %view may be heavy to execute.', array('%view' => $view->name)), 'warning');
975 }
976 }
977
978 /**
979 * This hook is called right after the execute process. The query has
980 * been executed, but the pre_render() phase has not yet happened for
981 * handlers.
982 *
983 * Adding output to the view can be accomplished by placing text on
984 * $view->attachment_before and $view->attachment_after. Altering the
985 * content can be achieved by editing the items of $view->result.
986 * @param $view
987 * The view object about to be processed.
988 */
989 function hook_views_post_execute(&$view) {
990 // If there are more than 100 results, show a message that encourages the user
991 // to change the filter settings.
992 // (This action could be performed later in the execution process, but not
993 // earlier.)
994 if ($view->total_rows > 100) {
995 drupal_set_message(t('You have more than 100 hits. Use the filter settings to narrow down your list.'));
996 }
997 }
998
999 /**
1000 * This hook is called right before the render process. The query has been
1001 * executed, and the pre_render() phase has already happened for handlers, so
1002 * all data should be available.
1003 *
1004 * Adding output to the view can be accomplished by placing text on
1005 * $view->attachment_before and $view->attachment_after. Altering the content
1006 * can be achieved by editing the items of $view->result.
1007 *
1008 * This hook can be utilized by themes.
1009 * @param $view
1010 * The view object about to be processed.
1011 */
1012 function hook_views_pre_render(&$view) {
1013 // Scramble the order of the rows shown on this result page.
1014 // Note that this could be done earlier, but not later in the view execution
1015 // process.
1016 shuffle($view->result);
1017 }
1018
1019 /**
1020 * Post process any rendered data.
1021 *
1022 * This can be valuable to be able to cache a view and still have some level of
1023 * dynamic output. In an ideal world, the actual output will include HTML
1024 * comment based tokens, and then the post process can replace those tokens.
1025 *
1026 * Example usage. If it is known that the view is a node view and that the
1027 * primary field will be a nid, you can do something like this:
1028 *
1029 * <!--post-FIELD-NID-->
1030 *
1031 * And then in the post render, create an array with the text that should
1032 * go there:
1033 *
1034 * strtr($output, array('<!--post-FIELD-1-->' => 'output for FIELD of nid 1');
1035 *
1036 * All of the cached result data will be available in $view->result, as well,
1037 * so all ids used in the query should be discoverable.
1038 *
1039 * This hook can be utilized by themes.
1040 * @param $view
1041 * The view object about to be processed.
1042 * @param $output
1043 * A flat string with the rendered output of the view.
1044 * @param $cache
1045 * The cache settings.
1046 */
1047 function hook_views_post_render(&$view, &$output, &$cache) {
1048 // When using full pager, disable any time-based caching if there are less
1049 // then 10 results.
1050 if ($view->query->pager instanceof views_plugin_pager_full && $cache->options['type'] == 'time' && count($view->result) < 10) {
1051 $cache['options']['results_lifespan'] = 0;
1052 $cache['options']['output_lifespan'] = 0;
1053 }
1054 }
1055
1056 /**
1057 * Alter the query before executing the query.
1058 *
1059 * This hook should be placed in MODULENAME.views.inc and it will be
1060 * auto-loaded. MODULENAME.views.inc must be in the directory specified by the
1061 * 'path' key returned by MODULENAME_views_api(), or the same directory as the
1062 * .module file, if 'path' is unspecified.
1063 *
1064 * @param $view
1065 * The view object about to be processed.
1066 * @param $query
1067 * An object describing the query.
1068 * @see hook_views_query_substitutions()
1069 */
1070 function hook_views_query_alter(&$view, &$query) {
1071 // (Example assuming a view with an exposed filter on node title.)
1072 // If the input for the title filter is a positive integer, filter against
1073 // node ID instead of node title.
1074 if ($view->name == 'my_view' && is_numeric($view->exposed_raw_input['title']) && $view->exposed_raw_input['title'] > 0) {
1075 // Traverse through the 'where' part of the query.
1076 foreach ($query->where as &$condition_group) {
1077 foreach ($condition_group['conditions'] as &$condition) {
1078 // If this is the part of the query filtering on title, change the
1079 // condition to filter on node ID.
1080 if ($condition['field'] == 'node.title') {
1081 $condition = array(
1082 'field' => 'node.nid',
1083 'value' => $view->exposed_raw_input['title'],
1084 'operator' => '=',
1085 );
1086 }
1087 }
1088 }
1089 }
1090 }
1091
1092 /**
1093 * Alter the information box that (optionally) appears with a view preview,
1094 * including query and performance statistics.
1095 *
1096 * This hook should be placed in MODULENAME.views.inc and it will be
1097 * auto-loaded. MODULENAME.views.inc must be in the directory specified by the
1098 * 'path' key returned by MODULENAME_views_api(), or the same directory as the
1099 * .module file, if 'path' is unspecified.
1100 *
1101 * Warning: $view is not a reference in PHP4 and cannot be modified here. But it
1102 * IS a reference in PHP5, and can be modified. Please be careful with it.
1103 *
1104 * @param $rows
1105 * An associative array with two keys:
1106 * - query: An array of rows suitable for theme('table'), containing
1107 * information about the query and the display title and path.
1108 * - statistics: An array of rows suitable for theme('table'), containing
1109 * performance statistics.
1110 * @param $view
1111 * The view object.
1112 * @see theme_table()
1113 */
1114 function hook_views_preview_info_alter(&$rows, $view) {
1115 // Adds information about the tables being queried by the view to the query
1116 // part of the info box.
1117 $rows['query'][] = array(
1118 t('<strong>Table queue</strong>'),
1119 count($view->query->table_queue) . ': (' . implode(', ', array_keys($view->query->table_queue)) . ')',
1120 );
1121 }
1122
1123 /**
1124 * This hooks allows to alter the links at the top of the view edit form. Some
1125 * modules might want to add links there.
1126 *
1127 * @param $links
1128 * An array of links which will be displayed at the top of the view edit form.
1129 * Each entry should be on a form suitable for theme('link').
1130 * @param view $view
1131 * The full view object which is currently edited.
1132 * @param $display_id
1133 * The current display id which is edited. For example that's 'default' or
1134 * 'page_1'.
1135 */
1136 function hook_views_ui_display_top_links_alter(&$links, $view, $display_id) {
1137 // Put the export link first in the list.
1138 if (isset($links['export'])) {
1139 $links = array('export' => $links['export']) + $links;
1140 }
1141 }
1142
1143 /**
1144 * This hook allows to alter the commands which are used on a views ajax
1145 * request.
1146 *
1147 * @param $commands
1148 * An array of ajax commands
1149 * @param $view view
1150 * The view which is requested.
1151 */
1152 function hook_views_ajax_data_alter(&$commands, $view) {
1153 // Replace Views' method for scrolling to the top of the element with your
1154 // custom scrolling method.
1155 foreach ($commands as &$command) {
1156 if ($command['command'] == 'viewsScrollTop') {
1157 $command['command'] .= 'myScrollTop';
1158 }
1159 }
1160 }
1161
1162 /**
1163 * Allow modules to respond to the Views cache being invalidated.
1164 *
1165 * This hook should fire whenever a view is enabled, disabled, created,
1166 * updated, or deleted.
1167 *
1168 * @see views_invalidate_cache()
1169 */
1170 function hook_views_invalidate_cache() {
1171 cache_clear_all('views:*', 'cache_mymodule', TRUE);
1172 }
1173
1174 /**
1175 * Allow modules to alter a view prior to being saved.
1176 */
1177 function hook_views_view_presave($view) {
1178 // Do some adjustments to the view. Handle with care.
1179 if (mymodule_check_view($view)) {
1180 mymodule_do_some_voodoo($view);
1181 }
1182 }
1183
1184 /**
1185 * Allow modules to respond to a view being saved.
1186 */
1187 function hook_views_view_save($view) {
1188 // Make a watchdog entry.
1189 watchdog('views', 'The view @name was deleted by @user at @time', array('@name' => $view->name, '@user' => $GLOBALS['user']->name, '@time' => format_date(time())));
1190 }
1191
1192 /**
1193 * Allow modules to respond to a view being deleted or reverted.
1194 */
1195 function hook_views_view_delete($view) {
1196 // Make a watchdog entry.
1197 watchdog('views', 'The view @name was deleted by @user at @time', array('@name' => $view->name, '@user' => $GLOBALS['user']->name, '@time' => format_date(time())));
1198 }
1199
1200 /**
1201 * @}
1202 */
1203
1204 /**
1205 * @defgroup views_module_handlers Views module handlers
1206 * @{
1207 * Handlers exposed by various modules to Views.
1208 * @}
1209 */