Projet

Général

Profil

Paste
Télécharger (46,1 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / views / views.api.php @ d756b39a

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
 * @}
1176
 */
1177

    
1178
/**
1179
 * @defgroup views_module_handlers Views module handlers
1180
 * @{
1181
 * Handlers exposed by various modules to Views.
1182
 * @}
1183
 */