views.api.php 45.2 KB
Newer Older
merlinofchaos's avatar
merlinofchaos committed
1
2
3
4
<?php

/**
 * @file
5
 * Describes hooks and plugins provided by the Views module.
merlinofchaos's avatar
merlinofchaos committed
6
7
 */

8
use Drupal\Core\Language\LanguageInterface;
9
use Drupal\views\Plugin\views\cache\CachePluginBase;
10
use Drupal\views\Plugin\views\PluginBase;
11
use Drupal\views\ViewExecutable;
12

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
 * @defgroup views_overview Views overview
 * @{
 * Overview of the Views module API
 *
 * The Views module is a generalized query and display engine, which can be used
 * to make views (formatted lists, grids, feeds, and other output) of items
 * (often entities, but can be other types of data). Developers can interact
 * with Views in several ways:
 * - Provide plugins: Views plugins govern nearly every aspect of views,
 *   including querying (sorting, filtering, etc.) and display (at several
 *   levels of granularity, ranging from the entire view to the details of a
 *   field). See the @link views_plugins Views plugins topic @endlink for
 *   more information.
 * - Provide data: Data types can be provided to Views by implementing
28
29
30
31
 *   hook_views_data(), and data types provided by other modules can be altered
 *   by implementing hook_views_data_alter(). To provide views data for an
 *   entity, create a class implementing
 *   \Drupal\views\EntityViewsDataInterface and reference this in the
32
 *   "views_data" annotation in the entity class. You can autogenerate big parts
33
 *   of the integration if you extend the \Drupal\views\EntityViewsData base
34
35
 *   class. See the @link entity_api Entity API topic @endlink for more
 *   information about entities.
36
 * - Implement hooks: A few operations in Views can be influenced by hooks.
37
 *   See the @link views_hooks Views hooks topic @endlink for a list.
38
39
40
41
 * - Theming: See the @link views_templates Views templates topic @endlink
 *   for more information.
 *
 * @see \Drupal\views\ViewExecutable
42
 * @see \Drupal\views\Views
43
44
45
 * @}
 */

merlinofchaos's avatar
merlinofchaos committed
46
/**
47
 * @defgroup views_plugins Views plugins
48
 * @{
49
 * Overview of views plugins
merlinofchaos's avatar
merlinofchaos committed
50
 *
51
 * Views plugins are objects that are used to build and render the view.
52
53
54
55
 * See individual views plugin topics for more information about the
 * specifics of each plugin type, and the
 * @link plugin_api Plugin API topic @endlink for more information about
 * plugins in general.
merlinofchaos's avatar
merlinofchaos committed
56
 *
57
58
59
 * Some Views plugins are known as handlers. Handler plugins help build the
 * view query object: filtering, contextual filtering, sorting, relationships,
 * etc.
60
 *
61
62
 * @todo Document specific options on the appropriate plugin base classes.
 * @todo Add examples.
merlinofchaos's avatar
merlinofchaos committed
63
 *
64
 * @ingroup views_overview
65
66
 * @see \Drupal\views\Plugin\views\PluginBase
 * @see \Drupal\views\Plugin\views\HandlerBase
67
68
 * @see plugin_api
 * @see annotation
69
 * @}
merlinofchaos's avatar
merlinofchaos committed
70
71
72
73
74
 */

/**
 * @defgroup views_hooks Views hooks
 * @{
75
 * Hooks that allow other modules to implement the Views API.
76
77
 * @ingroup views_overview
 * @}
merlinofchaos's avatar
merlinofchaos committed
78
79
 */

80
81
82
83
84
/**
 * @addtogroup hooks
 * @{
 */

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/**
 * Analyze a view to provide warnings about its configuration.
 *
 * @param \Drupal\views\ViewExecutable $view
 *   The view being executed.
 *
 * @return array
 *   Array of warning messages built by Analyzer::formatMessage to be displayed
 *   to the user following analysis of the view.
 */
function hook_views_analyze(Drupal\views\ViewExecutable $view) {
  $messages = array();

  if ($view->display_handler->options['pager']['type'] == 'none') {
    $messages[] = Drupal\views\Analyzer::formatMessage(t('This view has no pager. This could cause performance issues when the view contains many items.'), 'warning');
  }

  return $messages;
}

merlinofchaos's avatar
merlinofchaos committed
105
/**
106
107
108
109
 * Describe data tables and fields (or the equivalent) to Views.
 *
 * The table and fields are processed in Views using various plugins. See
 * the @link views_plugins Views plugins topic @endlink for more information.
110
 *
111
112
113
 * To provide views data for an entity, instead of implementing this hook,
 * create a class implementing \Drupal\views\EntityViewsDataInterface and
 * reference this in the "views" annotation in the entity class. The return
114
115
116
117
 * value of the getViewsData() method on the interface is the same as this hook,
 * and base class in \Drupal\views\EntityViewsData will take care of adding the
 * basic Views tables and fields for your entity. See the
 * @link entity_api Entity API topic @endlink for more information about
118
119
 * entities.
 *
120
 * The data described with this hook is fetched and retrieved by
121
 * \Drupal\views\Views::viewsData()->get().
122
 *
123
 * @return array
124
125
126
127
128
129
130
131
 *   An associative array describing the structure of database tables and fields
 *   (and their equivalents) provided for use in Views. At the outermost level,
 *   the keys are the names used internally by Views for the tables (usually the
 *   actual table name). Each table's array describes the table itself, how to
 *   join to other tables, and the fields that are part of the table. The sample
 *   function body provides documentation of the details.
 *
 * @see hook_views_data_alter()
merlinofchaos's avatar
merlinofchaos committed
132
133
 */
function hook_views_data() {
134
135
  // This example describes how to write hook_views_data() for a table defined
  // like this:
merlinofchaos's avatar
merlinofchaos committed
136
  // CREATE TABLE example_table (
137
  //   nid INT(11) NOT NULL         COMMENT 'Primary key: {node}.nid.',
merlinofchaos's avatar
merlinofchaos committed
138
139
140
141
  //   plain_text_field VARCHAR(32) COMMENT 'Just a plain text field.',
  //   numeric_field INT(11)        COMMENT 'Just a numeric field.',
  //   boolean_field INT(1)         COMMENT 'Just an on/off field.',
  //   timestamp_field INT(8)       COMMENT 'Just a timestamp field.',
142
  //   langcode VARCHAR(12)         COMMENT 'Language code field.',
merlinofchaos's avatar
merlinofchaos committed
143
144
145
  //   PRIMARY KEY(nid)
  // );

146
147
  // Define the return array.
  $data = array();
merlinofchaos's avatar
merlinofchaos committed
148

149
150
151
152
153
154
155
156
157
158
159
  // The outermost keys of $data are Views table names, which should usually
  // be the same as the hook_schema() table names.
  $data['example_table'] = array();

  // The value corresponding to key 'table' gives properties of the table
  // itself.
  $data['example_table']['table'] = array();

  // Within 'table', the value of 'group' (translated string) is used as a
  // prefix in Views UI for this table's fields, filters, etc. When adding
  // a field, filter, etc. you can also filter by the group.
merlinofchaos's avatar
merlinofchaos committed
160
161
  $data['example_table']['table']['group'] = t('Example table');

162
163
164
165
166
167
  // Within 'table', the value of 'provider' is the module that provides schema
  // or the entity type that causes the table to exist. Setting this ensures
  // that views have the correct dependencies. This is automatically set to the
  // module that implements hook_views_data().
  $data['example_table']['table']['provider'] = 'example_module';

168
169
170
171
  // Some tables are "base" tables, meaning that they can be the base tables
  // for views. Non-base tables can only be brought in via relationships in
  // views based on other tables. To define a table to be a base table, add
  // key 'base' to the 'table' array:
merlinofchaos's avatar
merlinofchaos committed
172
  $data['example_table']['table']['base'] = array(
173
174
175
    // Identifier (primary) field in this table for Views.
    'field' => 'nid',
    // Label in the UI.
merlinofchaos's avatar
merlinofchaos committed
176
    'title' => t('Example table'),
177
    // Longer description in the UI. Required.
merlinofchaos's avatar
merlinofchaos committed
178
179
180
181
    'help' => t('Example table contains example content and can be related to nodes.'),
    'weight' => -10,
  );

182
183
184
185
186
187
188
189
190
191
  // Some tables have an implicit, automatic relationship to other tables,
  // meaning that when the other table is available in a view (either as the
  // base table or through a relationship), this table's fields, filters, etc.
  // are automatically made available without having to add an additional
  // relationship. To define an implicit relationship that will make your
  // table automatically available when another table is present, add a 'join'
  // section to your 'table' section. Note that it is usually only a good idea
  // to do this for one-to-one joins, because otherwise your automatic join
  // will add more rows to the view. It is also not a good idea to do this if
  // most views won't need your table -- if that is the case, define a
192
  // relationship instead (see below).
193
  //
194
195
196
197
198
  // If you've decided an automatic join is a good idea, here's how to do it;
  // the resulting SQL query will look something like this:
  //   ... FROM example_table et ... JOIN node_field_data nfd
  //   ON et.nid = nfd.nid AND ('extra' clauses will be here) ...
  // although the table aliases will be different.
merlinofchaos's avatar
merlinofchaos committed
199
  $data['example_table']['table']['join'] = array(
200
    // Within the 'join' section, list one or more tables to automatically
201
202
203
204
205
206
    // join to. In this example, every time 'node_field_data' is available in
    // a view, 'example_table' will be too. The array keys here are the array
    // keys for the other tables, given in their hook_views_data()
    // implementations. If the table listed here is from another module's
    // hook_views_data() implementation, make sure your module depends on that
    // other module.
207
    'node_field_data' => array(
208
      // Primary key field in node_field_data to use in the join.
merlinofchaos's avatar
merlinofchaos committed
209
      'left_field' => 'nid',
210
      // Foreign key field in example_table to use in the join.
merlinofchaos's avatar
merlinofchaos committed
211
      'field' => 'nid',
212
      // 'extra' is an array of additional conditions on the join.
213
214
      'extra' => array(
        0 => array(
215
          // Adds AND node_field_data.published = TRUE to the join.
216
217
218
219
220
221
222
223
224
225
226
          'field' => 'published',
          'value' => TRUE,
        ),
        1 => array(
          // Adds AND example_table.numeric_field = 1 to the join.
          'left_field' => 'numeric_field',
          'value' => 1,
          // If true, the value will not be surrounded in quotes.
          'numeric' => TRUE,
        ),
        2 => array(
227
228
          // Adds AND example_table.boolean_field <>
          // node_field_data.published to the join.
229
230
231
232
233
234
          'field' => 'published',
          'left_field' => 'boolean_field',
          // The operator used, Defaults to "=".
          'operator' => '!=',
        ),
      ),
merlinofchaos's avatar
merlinofchaos committed
235
236
237
    ),
  );

238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
  // You can also do a more complex join, where in order to get to a certain
  // base table defined in a hook_views_data() implementation, you will join
  // to a different table that Views knows how to auto-join to the base table.
  // For instance, if another module that your module depends on had
  // defined a table 'foo' with an automatic join to 'node_field_table' (as
  // shown above), you could join to 'node_field_table' via the 'foo' table.
  // Here's how to do this, and the resulting SQL query would look something
  // like this:
  //   ... FROM example_table et ... JOIN foo foo
  //   ON et.nid = foo.nid AND ('extra' clauses will be here) ...
  //   JOIN node_field_data nfd ON (definition of the join from the foo
  //   module goes here) ...
  // although the table aliases will be different.
  $data['example_table']['table']['join']['node_field_data'] = array(
    // 'node_field_data' above is the base we're joining to in Views.
    // 'left_table' is the table we're actually joining to, in order to get to
    // 'node_field_data'. It has to be something that Views knows how to join
    // to 'node_field_data'.
    'left_table' => 'foo',
    'left_field' => 'nid',
    'field' => 'nid',
    // 'extra' is an array of additional conditions on the join.
    'extra' => array(
      // This syntax matches additional fields in the two tables:
      // ... AND foo.langcode = example_table.langcode ...
      array('left_field' => 'langcode', 'field' => 'langcode'),
      // This syntax adds a condition on our table. 'operator' defaults to
      // '=' for non-array values, or 'IN' for array values.
      // ... AND example_table.numeric_field > 0 ...
      array('field' => 'numeric_field', 'value' => 0, 'numeric' => TRUE, 'operator' => '>'),
    ),
  );

271
272
273
274
  // Other array elements at the top level of your table's array describe
  // individual database table fields made available to Views. The array keys
  // are the names (unique within the table) used by Views for the fields,
  // usually equal to the database field names.
merlinofchaos's avatar
merlinofchaos committed
275
  //
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
  // Each field entry must have the following elements:
  // - title: Translated label for the field in the UI.
  // - help: Description of the field in the UI.
  //
  // Each field entry may also have one or more of the following elements,
  // describing "handlers" (plugins) for the field:
  // - relationship: Specifies a handler that allows this field to be used
  //   to define a relationship to another table in Views.
  // - field: Specifies a handler to make it available to Views as a field.
  // - filter: Specifies a handler to make it available to Views as a filter.
  // - sort: Specifies a handler to make it available to Views as a sort.
  // - argument: Specifies a handler to make it available to Views as an
  //   argument, or contextual filter as it is known in the UI.
  // - area: Specifies a handler to make it available to Views to add content
  //   to the header, footer, or as no result behavior.
  //
  // Note that when specifying handlers, you must give the handler plugin ID
  // and you may also specify overrides for various settings that make up the
  // plugin definition. See examples below; the Boolean example demonstrates
  // setting overrides.
merlinofchaos's avatar
merlinofchaos committed
296

297
298
  // Node ID field, exposed as relationship only, since it is a foreign key
  // in this table.
merlinofchaos's avatar
merlinofchaos committed
299
300
  $data['example_table']['nid'] = array(
    'title' => t('Example content'),
301
302
    'help' => t('Relate example content to the node content'),

303
304
    // Define a relationship to the node_field_data table, so views whose
    // base table is example_table can add a relationship to nodes. To make a
305
306
307
308
    // relationship in the other direction, you can:
    // - Use hook_views_data_alter() -- see the function body example on that
    //   hook for details.
    // - Use the implicit join method described above.
merlinofchaos's avatar
merlinofchaos committed
309
    'relationship' => array(
310
      // Views name of the table to join to for the relationship.
311
      'base' => 'node_field_data',
312
313
314
      // Database field name in the other table to join on.
      'base field' => 'nid',
      // ID of relationship handler plugin to use.
aspilicious's avatar
aspilicious committed
315
      'id' => 'standard',
316
      // Default label for relationship in the UI.
dawehner's avatar
dawehner committed
317
      'label' => t('Example node'),
merlinofchaos's avatar
merlinofchaos committed
318
319
320
    ),
  );

321
  // Plain text field, exposed as a field, sort, filter, and argument.
merlinofchaos's avatar
merlinofchaos committed
322
323
324
  $data['example_table']['plain_text_field'] = array(
    'title' => t('Plain text field'),
    'help' => t('Just a plain text field.'),
325

merlinofchaos's avatar
merlinofchaos committed
326
    'field' => array(
327
      // ID of field handler plugin to use.
aspilicious's avatar
aspilicious committed
328
      'id' => 'standard',
merlinofchaos's avatar
merlinofchaos committed
329
    ),
330

merlinofchaos's avatar
merlinofchaos committed
331
    'sort' => array(
332
      // ID of sort handler plugin to use.
aspilicious's avatar
aspilicious committed
333
      'id' => 'standard',
merlinofchaos's avatar
merlinofchaos committed
334
    ),
335

merlinofchaos's avatar
merlinofchaos committed
336
    'filter' => array(
337
      // ID of filter handler plugin to use.
aspilicious's avatar
aspilicious committed
338
      'id' => 'string',
merlinofchaos's avatar
merlinofchaos committed
339
    ),
340

merlinofchaos's avatar
merlinofchaos committed
341
    'argument' => array(
342
      // ID of argument handler plugin to use.
aspilicious's avatar
aspilicious committed
343
      'id' => 'string',
merlinofchaos's avatar
merlinofchaos committed
344
345
346
    ),
  );

347
  // Numeric field, exposed as a field, sort, filter, and argument.
merlinofchaos's avatar
merlinofchaos committed
348
349
350
  $data['example_table']['numeric_field'] = array(
    'title' => t('Numeric field'),
    'help' => t('Just a numeric field.'),
351

merlinofchaos's avatar
merlinofchaos committed
352
    'field' => array(
353
      // ID of field handler plugin to use.
aspilicious's avatar
aspilicious committed
354
      'id' => 'numeric',
355
    ),
356
357
358
359
360
361

    'sort' => array(
      // ID of sort handler plugin to use.
      'id' => 'standard',
    ),

merlinofchaos's avatar
merlinofchaos committed
362
    'filter' => array(
363
      // ID of filter handler plugin to use.
aspilicious's avatar
aspilicious committed
364
      'id' => 'numeric',
merlinofchaos's avatar
merlinofchaos committed
365
    ),
366
367
368
369

    'argument' => array(
      // ID of argument handler plugin to use.
      'id' => 'numeric',
merlinofchaos's avatar
merlinofchaos committed
370
371
372
    ),
  );

373
374
  // Boolean field, exposed as a field, sort, and filter. The filter section
  // illustrates overriding various settings.
merlinofchaos's avatar
merlinofchaos committed
375
376
377
  $data['example_table']['boolean_field'] = array(
    'title' => t('Boolean field'),
    'help' => t('Just an on/off field.'),
378

merlinofchaos's avatar
merlinofchaos committed
379
    'field' => array(
380
      // ID of field handler plugin to use.
aspilicious's avatar
aspilicious committed
381
      'id' => 'boolean',
merlinofchaos's avatar
merlinofchaos committed
382
    ),
383
384
385
386
387
388

    'sort' => array(
      // ID of sort handler plugin to use.
      'id' => 'standard',
    ),

merlinofchaos's avatar
merlinofchaos committed
389
    'filter' => array(
390
      // ID of filter handler plugin to use.
aspilicious's avatar
aspilicious committed
391
      'id' => 'boolean',
392
393
      // Override the generic field title, so that the filter uses a different
      // label in the UI.
merlinofchaos's avatar
merlinofchaos committed
394
      'label' => t('Published'),
395
396
      // Override the default BooleanOperator filter handler's 'type' setting,
      // to display this as a "Yes/No" filter instead of a "True/False" filter.
merlinofchaos's avatar
merlinofchaos committed
397
      'type' => 'yes-no',
398
399
      // Override the default Boolean filter handler's 'use_equal' setting, to
      // make the query use 'boolean_field = 1' instead of 'boolean_field <> 0'.
400
      'use_equal' => TRUE,
merlinofchaos's avatar
merlinofchaos committed
401
402
403
    ),
  );

404
  // Integer timestamp field, exposed as a field, sort, and filter.
merlinofchaos's avatar
merlinofchaos committed
405
406
407
  $data['example_table']['timestamp_field'] = array(
    'title' => t('Timestamp field'),
    'help' => t('Just a timestamp field.'),
408

merlinofchaos's avatar
merlinofchaos committed
409
    'field' => array(
410
      // ID of field handler plugin to use.
aspilicious's avatar
aspilicious committed
411
      'id' => 'date',
merlinofchaos's avatar
merlinofchaos committed
412
    ),
413

merlinofchaos's avatar
merlinofchaos committed
414
    'sort' => array(
415
      // ID of sort handler plugin to use.
aspilicious's avatar
aspilicious committed
416
      'id' => 'date',
merlinofchaos's avatar
merlinofchaos committed
417
    ),
418

merlinofchaos's avatar
merlinofchaos committed
419
    'filter' => array(
420
      // ID of filter handler plugin to use.
aspilicious's avatar
aspilicious committed
421
      'id' => 'date',
merlinofchaos's avatar
merlinofchaos committed
422
423
424
    ),
  );

425
426
427
428
429
430
431
432
433
434
435
436
437
438
  // Area example. Areas are not generally associated with actual data
  // tables and fields. This example is from views_views_data(), which defines
  // the "Global" table (not really a table, but a group of Fields, Filters,
  // etc. that are grouped into section "Global" in the UI). Here's the
  // definition of the generic "Text area":
  $data['views']['area'] = array(
    'title' => t('Text area'),
    'help' => t('Provide markup text for the area.'),
    'area' => array(
      // ID of the area handler plugin to use.
      'id' => 'text',
    ),
  );

merlinofchaos's avatar
merlinofchaos committed
439
440
441
442
  return $data;
}

/**
443
 * Alter the table and field information from hook_views_data().
merlinofchaos's avatar
merlinofchaos committed
444
 *
445
 * @param array $data
446
447
 *   An array of all information about Views tables and fields, collected from
 *   hook_views_data(), passed by reference.
merlinofchaos's avatar
merlinofchaos committed
448
449
450
 *
 * @see hook_views_data()
 */
451
function hook_views_data_alter(array &$data) {
452
453
  // Alter the title of the node_field_data:nid field in the Views UI.
  $data['node_field_data']['nid']['title'] = t('Node-Nid');
merlinofchaos's avatar
merlinofchaos committed
454

455
456
  // Add an additional field to the users_field_data table.
  $data['users_field_data']['example_field'] = array(
merlinofchaos's avatar
merlinofchaos committed
457
458
    'title' => t('Example field'),
    'help' => t('Some example content that references a user'),
459

460
    'field' => array(
461
      // ID of the field handler to use.
462
463
      'id' => 'example_field',
    ),
merlinofchaos's avatar
merlinofchaos committed
464
465
  );

466
467
  // Change the handler of the node title field, presumably to a handler plugin
  // you define in your module. Give the ID of this plugin.
468
  $data['node_field_data']['title']['field']['id'] = 'node_title';
merlinofchaos's avatar
merlinofchaos committed
469

470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
  // Add a relationship that will allow a view whose base table is 'foo' (from
  // another module) to have a relationship to 'example_table' (from my module),
  // via joining foo.fid to example_table.eid.
  //
  // This relationship has to be added to the 'foo' Views data, which my module
  // does not control, so it must be done in hook_views_data_alter(), not
  // hook_views_data().
  //
  // In Views data definitions, each field can have only one relationship. So
  // rather than adding this relationship directly to the $data['foo']['fid']
  // field entry, which could overwrite an existing relationship, we define
  // a dummy field key to handle the relationship.
  $data['foo']['unique_dummy_name'] = array(
    'title' => t('Title seen while adding relationship'),
    'help' => t('More information about the relationship'),

486
    'relationship' => array(
487
488
489
490
491
492
493
494
      // Views name of the table being joined to from foo.
      'base' => 'example_table',
      // Database field name in example_table for the join.
      'base field' => 'eid',
      // Real database field name in foo for the join, to override
      // 'unique_dummy_name'.
      'field' => 'fid',
      // ID of relationship handler plugin to use.
aspilicious's avatar
aspilicious committed
495
      'id' => 'standard',
496
497
498
499
      'label' => t('Default label for relationship'),
    ),
  );

merlinofchaos's avatar
merlinofchaos committed
500
501
502
  // Note that the $data array is not returned – it is modified by reference.
}

503
504
505
506
/**
 * Override the default Views data for a Field API field.
 *
 * The field module's implementation of hook_views_data() invokes this for each
507
508
 * field storage, in the module that defines the field type. It is not invoked
 * in other modules.
509
510
 *
 * If no hook implementation exists, hook_views_data() falls back to
511
 * views_field_default_views_data().
512
 *
513
514
 * @param \Drupal\field\FieldStorageConfigInterface $field_storage
 *   The field storage config entity.
515
516
517
518
519
 *
 * @return array
 *   An array of views data, in the same format as the return value of
 *   hook_views_data().
 *
520
 * @see views_views_data()
521
522
523
 * @see hook_field_views_data_alter()
 * @see hook_field_views_data_views_data_alter()
 */
524
function hook_field_views_data(\Drupal\field\FieldStorageConfigInterface $field_storage) {
525
  $data = views_field_default_views_data($field_storage);
526
527
  foreach ($data as $table_name => $table_data) {
    // Add the relationship only on the target_id field.
528
    $data[$table_name][$field_storage->getName() . '_target_id']['relationship'] = array(
529
530
531
      'id' => 'standard',
      'base' => 'file_managed',
      'base field' => 'target_id',
532
      'label' => t('image from @field_name', array('@field_name' => $field_storage->getName())),
533
534
535
536
537
538
539
540
541
542
543
    );
  }

  return $data;
}

/**
 * Alter the Views data for a single Field API field.
 *
 * This is called on all modules even if there is no hook_field_views_data()
 * implementation for the field, and therefore may be used to alter the
544
 * default data that views_field_default_views_data() supplies for the
545
 * field storage.
546
547
 *
 *  @param array $data
548
549
550
551
 *    The views data for the field storage. This has the same format as the
 *    return value of hook_views_data().
 *  @param \Drupal\field\FieldStorageConfigInterface $field_storage
 *    The field storage config entity.
552
 *
553
 * @see views_views_data()
554
555
556
 * @see hook_field_views_data()
 * @see hook_field_views_data_views_data_alter()
 */
557
function hook_field_views_data_alter(array &$data, \Drupal\field\FieldStorageConfigInterface $field_storage) {
558
  $entity_type_id = $field_storage->getTargetEntityTypeId();
559
  $field_name = $field_storage->getName();
560
561
  $entity_type = \Drupal::entityManager()->getDefinition($entity_type_id);
  $pseudo_field_name = 'reverse_' . $field_name . '_' . $entity_type_id;
562
  $table_mapping = \Drupal::entityManager()->getStorage($entity_type_id)->getTableMapping();
563

564
  list($label) = views_entity_field_label($entity_type_id, $field_name);
565
566
567
568
569
570
571

  $data['file_managed'][$pseudo_field_name]['relationship'] = array(
    'title' => t('@entity using @field', array('@entity' => $entity_type->getLabel(), '@field' => $label)),
    'help' => t('Relate each @entity with a @field set to the image.', array('@entity' => $entity_type->getLabel(), '@field' => $label)),
    'id' => 'entity_reverse',
    'field_name' => $field_name,
    'entity_type' => $entity_type_id,
572
    'field table' => $table_mapping->getDedicatedDataTableName($field_storage),
573
574
575
    'field field' => $field_name . '_target_id',
    'base' => $entity_type->getBaseTable(),
    'base field' => $entity_type->getKey('id'),
576
    'label' => $field_name,
577
578
579
580
581
582
583
584
585
586
587
588
589
590
    'join_extra' => array(
      0 => array(
        'field' => 'deleted',
        'value' => 0,
        'numeric' => TRUE,
      ),
    ),
  );
}

/**
 * Alter the Views data on a per field basis.
 *
 * The field module's implementation of hook_views_data_alter() invokes this for
591
592
 * each field storage, in the module that defines the field type. It is not
 * invoked in other modules.
593
594
 *
 * Unlike hook_field_views_data_alter(), this operates on the whole of the views
595
 * data. This allows a field type to add data that concerns its fields in
596
597
598
599
600
601
602
603
604
605
 * other tables, which would not yet be defined at the point when
 * hook_field_views_data() and hook_field_views_data_alter() are invoked. For
 * example, entityreference adds reverse relationships on the tables for the
 * entities which are referenced by entityreference fields.
 *
 * (Note: this is weirdly named so as not to conflict with
 * hook_field_views_data_alter().)
 *
 * @param array $data
 *   The views data.
606
607
 * @param \Drupal\field\FieldStorageConfigInterface $field
 *   The field storage config entity.
608
609
610
 *
 * @see hook_field_views_data()
 * @see hook_field_views_data_alter()
611
 * @see views_views_data_alter()
612
 */
613
function hook_field_views_data_views_data_alter(array &$data, \Drupal\field\FieldStorageConfigInterface $field) {
614
615
616
617
618
  $field_name = $field->getName();
  $data_key = 'field_data_' . $field_name;
  $entity_type_id = $field->entity_type;
  $entity_type = \Drupal::entityManager()->getDefinition($entity_type_id);
  $pseudo_field_name = 'reverse_' . $field_name . '_' . $entity_type_id;
619
  list($label) = views_entity_field_label($entity_type_id, $field_name);
620
  $table_mapping = \Drupal::entityManager()->getStorage($entity_type_id)->getTableMapping();
621
622
623
624
625
626
627
628

  // Views data for this field is in $data[$data_key].
  $data[$data_key][$pseudo_field_name]['relationship'] = array(
    'title' => t('@entity using @field', array('@entity' => $entity_type->getLabel(), '@field' => $label)),
    'help' => t('Relate each @entity with a @field set to the term.', array('@entity' => $entity_type->getLabel(), '@field' => $label)),
    'id' => 'entity_reverse',
    'field_name' => $field_name,
    'entity_type' => $entity_type_id,
629
    'field table' => $table_mapping->getDedicatedDataTableName($field),
630
631
632
    'field field' => $field_name . '_target_id',
    'base' => $entity_type->getBaseTable(),
    'base field' => $entity_type->getKey('id'),
633
    'label' => $field_name,
634
635
636
637
638
639
640
641
642
643
    'join_extra' => array(
      0 => array(
        'field' => 'deleted',
        'value' => 0,
        'numeric' => TRUE,
      ),
    ),
  );
}

merlinofchaos's avatar
merlinofchaos committed
644
/**
645
 * Replace special strings in the query before it is executed.
merlinofchaos's avatar
merlinofchaos committed
646
 *
647
648
649
650
 * The idea is that certain dynamic values can be placed in a query when it is
 * built, and substituted at run-time, allowing the query to be cached and
 * still work correctly when executed.
 *
651
 * @param \Drupal\views\ViewExecutable $view
merlinofchaos's avatar
merlinofchaos committed
652
 *   The View being executed.
653
 *
654
655
656
 * @return array
 *   An associative array where each key is a string to be replaced, and the
 *   corresponding value is its replacement. The strings to replace are often
657
658
 *   surrounded with '***', as illustrated in the example implementation, to
 *   avoid collisions with other values in the query.
merlinofchaos's avatar
merlinofchaos committed
659
 */
660
function hook_views_query_substitutions(ViewExecutable $view) {
merlinofchaos's avatar
merlinofchaos committed
661
662
  // Example from views_views_query_substitutions().
  return array(
663
    '***CURRENT_VERSION***' => \Drupal::VERSION,
merlinofchaos's avatar
merlinofchaos committed
664
    '***CURRENT_TIME***' => REQUEST_TIME,
665
666
    '***LANGUAGE_language_content***' => \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId(),
    PluginBase::VIEWS_QUERY_LANGUAGE_SITE_DEFAULT => \Drupal::languageManager()->getDefaultLanguage()->getId(),
merlinofchaos's avatar
merlinofchaos committed
667
668
669
670
  );
}

/**
671
 * Replace special strings when processing a view with form elements.
merlinofchaos's avatar
merlinofchaos committed
672
 *
673
674
 * @return array
 *   An associative array where each key is a string to be replaced, and the
675
676
 *   corresponding value is its replacement. The value will be escaped unless it
 *   is already marked safe.
merlinofchaos's avatar
merlinofchaos committed
677
678
679
680
681
682
683
684
 */
function hook_views_form_substitutions() {
  return array(
    '<!--views-form-example-substitutions-->' => 'Example Substitution',
  );
}

/**
685
 * Alter a view at the very beginning of Views processing.
merlinofchaos's avatar
merlinofchaos committed
686
 *
687
688
689
 * Output can be added to the view by setting $view->attachment_before
 * and $view->attachment_after.
 *
690
 * @param \Drupal\views\ViewExecutable $view
merlinofchaos's avatar
merlinofchaos committed
691
 *   The view object about to be processed.
692
 * @param string $display_id
merlinofchaos's avatar
merlinofchaos committed
693
 *   The machine name of the active display.
694
 * @param array $args
merlinofchaos's avatar
merlinofchaos committed
695
 *   An array of arguments passed into the view.
696
 *
697
 * @see \Drupal\views\ViewExecutable
merlinofchaos's avatar
merlinofchaos committed
698
 */
699
700
701
function hook_views_pre_view(ViewExecutable $view, $display_id, array &$args) {

  // Modify contextual filters for my_special_view if user has 'my special permission'.
702
703
  $account = \Drupal::currentUser();

704
  if ($view->id() == 'my_special_view' && $account->hasPermission('my special permission') && $display_id == 'public_display') {
705
    $args[0] = 'custom value';
merlinofchaos's avatar
merlinofchaos committed
706
707
708
709
  }
}

/**
710
 * Act on the view before the query is built, but after displays are attached.
merlinofchaos's avatar
merlinofchaos committed
711
 *
712
713
714
 * Output can be added to the view by setting $view->attachment_before
 * and $view->attachment_after.
 *
715
 * @param \Drupal\views\ViewExecutable $view
merlinofchaos's avatar
merlinofchaos committed
716
 *   The view object about to be processed.
717
 *
718
 * @see \Drupal\views\ViewExecutable
merlinofchaos's avatar
merlinofchaos committed
719
 */
720
function hook_views_pre_build(ViewExecutable $view) {
721
  // Because of some inexplicable business logic, we should remove all
merlinofchaos's avatar
merlinofchaos committed
722
723
724
725
726
727
728
729
730
  // attachments from all views on Mondays.
  // (This alter could be done later in the execution process as well.)
  if (date('D') == 'Mon') {
    unset($view->attachment_before);
    unset($view->attachment_after);
  }
}

/**
731
 * Act on the view immediately after the query is built.
merlinofchaos's avatar
merlinofchaos committed
732
 *
733
734
735
 * Output can be added to the view by setting $view->attachment_before
 * and $view->attachment_after.
 *
736
 * @param \Drupal\views\ViewExecutable $view
merlinofchaos's avatar
merlinofchaos committed
737
 *   The view object about to be processed.
738
 *
739
 * @see \Drupal\views\ViewExecutable
merlinofchaos's avatar
merlinofchaos committed
740
 */
741
function hook_views_post_build(ViewExecutable $view) {
merlinofchaos's avatar
merlinofchaos committed
742
743
744
745
746
  // If the exposed field 'type' is set, hide the column containing the content
  // type. (Note that this is a solution for a particular view, and makes
  // assumptions about both exposed filter settings and the fields in the view.
  // Also note that this alter could be done at any point before the view being
  // rendered.)
747
  if ($view->id() == 'my_view' && isset($view->exposed_raw_input['type']) && $view->exposed_raw_input['type'] != 'All') {
merlinofchaos's avatar
merlinofchaos committed
748
749
750
751
752
753
754
755
    // 'Type' should be interpreted as content type.
    if (isset($view->field['type'])) {
      $view->field['type']->options['exclude'] = TRUE;
    }
  }
}

/**
756
 * Act on the view after the query is built and just before it is executed.
merlinofchaos's avatar
merlinofchaos committed
757
 *
758
759
760
 * Output can be added to the view by setting $view->attachment_before
 * and $view->attachment_after.
 *
761
 * @param \Drupal\views\ViewExecutable $view
merlinofchaos's avatar
merlinofchaos committed
762
 *   The view object about to be processed.
763
 *
764
 * @see \Drupal\views\ViewExecutable
merlinofchaos's avatar
merlinofchaos committed
765
 */
766
function hook_views_pre_execute(ViewExecutable $view) {
merlinofchaos's avatar
merlinofchaos committed
767
768
769
770
  // Whenever a view queries more than two tables, show a message that notifies
  // view administrators that the query might be heavy.
  // (This action could be performed later in the execution process, but not
  // earlier.)
771
772
773
  $account = \Drupal::currentUser();

  if (count($view->query->tables) > 2 && $account->hasPermission('administer views')) {
774
    drupal_set_message(t('The view %view may be heavy to execute.', array('%view' => $view->id())), 'warning');
merlinofchaos's avatar
merlinofchaos committed
775
776
777
778
  }
}

/**
779
 * Act on the view immediately after the query has been executed.
merlinofchaos's avatar
merlinofchaos committed
780
 *
781
 * At this point the query has been executed, but the preRender() phase has
782
783
784
785
786
 * not yet happened for handlers.
 *
 * Output can be added to the view by setting $view->attachment_before
 * and $view->attachment_after.
 *
787
 * @param \Drupal\views\ViewExecutable $view
merlinofchaos's avatar
merlinofchaos committed
788
 *   The view object about to be processed.
789
 *
790
 * @see \Drupal\views\ViewExecutable
merlinofchaos's avatar
merlinofchaos committed
791
 */
792
function hook_views_post_execute(ViewExecutable $view) {
merlinofchaos's avatar
merlinofchaos committed
793
794
795
796
797
798
799
800
801
802
  // If there are more than 100 results, show a message that encourages the user
  // to change the filter settings.
  // (This action could be performed later in the execution process, but not
  // earlier.)
  if ($view->total_rows > 100) {
    drupal_set_message(t('You have more than 100 hits. Use the filter settings to narrow down your list.'));
  }
}

/**
803
 * Act on the view immediately before rendering it.
merlinofchaos's avatar
merlinofchaos committed
804
 *
805
 * At this point the query has been executed, and the preRender() phase has
806
 * already happened for handlers, so all data should be available. This hook
807
 * can be used by themes.
merlinofchaos's avatar
merlinofchaos committed
808
 *
809
810
811
 * Output can be added to the view by setting $view->attachment_before
 * and $view->attachment_after.
 *
812
 * @param \Drupal\views\ViewExecutable $view
merlinofchaos's avatar
merlinofchaos committed
813
 *   The view object about to be processed.
814
 *
815
 * @see \Drupal\views\ViewExecutable
merlinofchaos's avatar
merlinofchaos committed
816
 */
817
function hook_views_pre_render(ViewExecutable $view) {
merlinofchaos's avatar
merlinofchaos committed
818
819
820
821
822
823
824
  // Scramble the order of the rows shown on this result page.
  // Note that this could be done earlier, but not later in the view execution
  // process.
  shuffle($view->result);
}

/**
825
 * Post-process any rendered data.
merlinofchaos's avatar
merlinofchaos committed
826
827
828
 *
 * This can be valuable to be able to cache a view and still have some level of
 * dynamic output. In an ideal world, the actual output will include HTML
829
 * comment-based tokens, and then the post process can replace those tokens.
830
 * This hook can be used by themes.
merlinofchaos's avatar
merlinofchaos committed
831
832
833
 *
 * Example usage. If it is known that the view is a node view and that the
 * primary field will be a nid, you can do something like this:
834
835
 * @code
 *   <!--post-FIELD-NID-->
836
 * @endcode
837
 * And then in the post-render, create an array with the text that should
merlinofchaos's avatar
merlinofchaos committed
838
 * go there:
839
840
 * @code
 *   strtr($output, array('<!--post-FIELD-1-->' => 'output for FIELD of nid 1');
841
 * @endcode
merlinofchaos's avatar
merlinofchaos committed
842
843
844
 * All of the cached result data will be available in $view->result, as well,
 * so all ids used in the query should be discoverable.
 *
845
 * @param \Drupal\views\ViewExecutable $view
merlinofchaos's avatar
merlinofchaos committed
846
 *   The view object about to be processed.
847
 * @param string $output
merlinofchaos's avatar
merlinofchaos committed
848
 *   A flat string with the rendered output of the view.
849
 * @param \Drupal\views\Plugin\views\cache\CachePluginBase $cache
merlinofchaos's avatar
merlinofchaos committed
850
 *   The cache settings.
851
 *
852
 * @see \Drupal\views\ViewExecutable
merlinofchaos's avatar
merlinofchaos committed
853
 */
854
function hook_views_post_render(ViewExecutable $view, &$output, CachePluginBase $cache) {
855
856
857
858
859
  // When using full pager, disable any time-based caching if there are fewer
  // than 10 results.
  if ($view->pager instanceof Drupal\views\Plugin\views\pager\Full && $cache instanceof Drupal\views\Plugin\views\cache\Time && count($view->result) < 10) {
    $cache->options['results_lifespan'] = 0;
    $cache->options['output_lifespan'] = 0;
merlinofchaos's avatar
merlinofchaos committed
860
861
862
863
  }
}

/**
864
 * Alter the query before it is executed.
merlinofchaos's avatar
merlinofchaos committed
865
 *
866
 * @param \Drupal\views\ViewExecutable $view
merlinofchaos's avatar
merlinofchaos committed
867
 *   The view object about to be processed.
868
869
870
 * @param QueryPluginBase $query
 *   The query plugin object for the query.
 *
merlinofchaos's avatar
merlinofchaos committed
871
 * @see hook_views_query_substitutions()
872
 * @see \Drupal\views\Plugin\views\query\Sql
merlinofchaos's avatar
merlinofchaos committed
873
 */
874
function hook_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
merlinofchaos's avatar
merlinofchaos committed
875
876
877
  // (Example assuming a view with an exposed filter on node title.)
  // If the input for the title filter is a positive integer, filter against
  // node ID instead of node title.
878
  if ($view->id() == 'my_view' && is_numeric($view->exposed_raw_input['title']) && $view->exposed_raw_input['title'] > 0) {
merlinofchaos's avatar
merlinofchaos committed
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
    // Traverse through the 'where' part of the query.
    foreach ($query->where as &$condition_group) {
      foreach ($condition_group['conditions'] as &$condition) {
        // If this is the part of the query filtering on title, chang the
        // condition to filter on node ID.
        if ($condition['field'] == 'node.title') {
          $condition = array(
            'field' => 'node.nid',
            'value' => $view->exposed_raw_input['title'],
            'operator' => '=',
          );
        }
      }
    }
  }
}

/**
897
898
899
900
901
 * Alter the view preview information.
 *
 * The view preview information is optionally displayed when a view is
 * previewed in the administrative UI. It includes query and performance
 * statistics.
merlinofchaos's avatar
merlinofchaos committed
902
 *
903
 * @param array $rows
merlinofchaos's avatar
merlinofchaos committed
904
 *   An associative array with two keys:
905
 *   - query: An array of rows suitable for '#type' => 'table', containing
merlinofchaos's avatar
merlinofchaos committed
906
 *     information about the query and the display title and path.
907
 *   - statistics: An array of rows suitable for '#type' => 'table',
908
 *     containing performance statistics.
909
 * @param \Drupal\views\ViewExecutable $view
merlinofchaos's avatar
merlinofchaos committed
910
 *   The view object.
911
 *
912
 * @see \Drupal\views_ui\ViewUI
913
 * @see table.html.twig
merlinofchaos's avatar
merlinofchaos committed
914
 */
915
function hook_views_preview_info_alter(array &$rows, ViewExecutable $view) {
merlinofchaos's avatar
merlinofchaos committed
916
917
918
919
920
921
922
923
924
  // Adds information about the tables being queried by the view to the query
  // part of the info box.
  $rows['query'][] = array(
    t('<strong>Table queue</strong>'),
    count($view->query->table_queue) . ': (' . implode(', ', array_keys($view->query->table_queue)) . ')',
  );
}

/**
925
926
927
928
 * Alter the links displayed at the top of the view edit form.
 *
 * @param array $links
 *   A renderable array of links which will be displayed at the top of the
929
 *   view edit form. Each entry will be in a form suitable for
930
 *   '#theme' => 'links'.
931
932
933
934
935
936
 * @param \Drupal\views\ViewExecutable $view
 *   The view object being edited.
 * @param string $display_id
 *   The ID of the display being edited, e.g. 'default' or 'page_1'.
 *
 * @see \Drupal\views_ui\ViewUI::renderDisplayTop()
merlinofchaos's avatar
merlinofchaos committed
937
 */
938
function hook_views_ui_display_top_links_alter(array &$links, ViewExecutable $view, $display_id) {
merlinofchaos's avatar
merlinofchaos committed
939
940
941
942
943
944
  // Put the export link first in the list.
  if (isset($links['export'])) {
    $links = array('export' => $links['export']) + $links;
  }
}

945
// @todo Describe how to alter a view ajax response with event listeners.
merlinofchaos's avatar
merlinofchaos committed
946

947
/**
948
 * Allow modules to respond to the invalidation of the Views cache.
949
 *
950
 * This hook will fire whenever a view is enabled, disabled, created,
951
952
953
954
955
 * updated, or deleted.
 *
 * @see views_invalidate_cache()
 */
function hook_views_invalidate_cache() {
956
  \Drupal\Core\Cache\Cache::invalidateTags(array('views'));
957
958
}

959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
/**
 * Modify the list of available views access plugins.
 *
 * This hook may be used to modify plugin properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing plugin definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsPluginManager
 */
function hook_views_plugins_access_alter(array &$plugins) {
  // Remove the available plugin because the users should not have access to it.
  unset($plugins['role']);
}

/**
 * Modify the list of available views default argument plugins.
 *
 * This hook may be used to modify plugin properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing plugin definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsPluginManager
 */
function hook_views_plugins_argument_default_alter(array &$plugins) {
  // Remove the available plugin because the users should not have access to it.
  unset($plugins['php']);
}

/**
 * Modify the list of available views argument validation plugins.
 *
 * This hook may be used to modify plugin properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing plugin definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsPluginManager
 */
function hook_views_plugins_argument_validator_alter(array &$plugins) {
  // Remove the available plugin because the users should not have access to it.
  unset($plugins['php']);
}

/**
 * Modify the list of available views cache plugins.
 *
 * This hook may be used to modify plugin properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing plugin definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsPluginManager
 */
function hook_views_plugins_cache_alter(array &$plugins) {
  // Change the title.
  $plugins['time']['title'] = t('Custom title');
}

/**
 * Modify the list of available views display extender plugins.
 *
 * This hook may be used to modify plugin properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing plugin definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsPluginManager
 */
function hook_views_plugins_display_extenders_alter(array &$plugins) {
  // Alter the title of an existing plugin.
  $plugins['time']['title'] = t('Custom title');
}

/**
 * Modify the list of available views display plugins.
 *
 * This hook may be used to modify plugin properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing plugin definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsPluginManager
 */
function hook_views_plugins_display_alter(array &$plugins) {
  // Alter the title of an existing plugin.
  $plugins['rest_export']['title'] = t('Export');
}

/**
 * Modify the list of available views exposed form plugins.
 *
 * This hook may be used to modify plugin properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing plugin definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsPluginManager
 */
function hook_views_plugins_exposed_form_alter(array &$plugins) {
  // Remove the available plugin because the users should not have access to it.
  unset($plugins['input_required']);
}

/**
 * Modify the list of available views join plugins.
 *
 * This hook may be used to modify plugin properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing plugin definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsPluginManager
 */
function hook_views_plugins_join_alter(array &$plugins) {
  // Print out all join plugin names for debugging purposes.
  debug($plugins);
}

/**
 * Modify the list of available views join plugins.
 *
 * This hook may be used to modify plugin properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing plugin definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsPluginManager
 */
function hook_views_plugins_pager_alter(array &$plugins) {
  // Remove the sql based plugin to force good performance.
  unset($plugins['full']);
}

/**
 * Modify the list of available views query plugins.
 *
 * This hook may be used to modify plugin properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing plugin definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsPluginManager
 */
function hook_views_plugins_query_alter(array &$plugins) {
  // Print out all query plugin names for debugging purposes.
  debug($plugins);
}

/**
 * Modify the list of available views row plugins.
 *
 * This hook may be used to modify plugin properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing plugin definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsPluginManager
 */
function hook_views_plugins_row_alter(array &$plugins) {
  // Change the used class of a plugin.
  $plugins['entity:node']['class'] = 'Drupal\node\Plugin\views\row\NodeRow';
  $plugins['entity:node']['module'] = 'node';
}

/**
 * Modify the list of available views style plugins.
 *
 * This hook may be used to modify plugin properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing plugin definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsPluginManager
 */
function hook_views_plugins_style_alter(array &$plugins) {
  // Change the theme hook of a plugin.
  $plugins['html_list']['theme'] = 'custom_views_view_list';
}

/**
 * Modify the list of available views wizard plugins.
 *
 * This hook may be used to modify plugin properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing plugin definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsPluginManager
 */
function hook_views_plugins_wizard_alter(array &$plugins) {
  // Change the title of a plugin.
  $plugins['node_revision']['title'] = t('Node revision wizard');
}

1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
/**
 * Modify the list of available views area handler plugins.
 *
 * This hook may be used to modify handler properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing handler definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsHandlerManager
 */
function hook_views_plugins_area_alter(array &$plugins) {
  // Change the 'title' handler class.
  $plugins['title']['class'] = 'Drupal\\example\\ExampleClass';
}

/**
 * Modify the list of available views argument handler plugins.
 *
 * This hook may be used to modify handler properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing handler definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsHandlerManager
 */
function hook_views_plugins_argument_alter(array &$plugins) {
  // Change the 'title' handler class.
  $plugins['title']['class'] = 'Drupal\\example\\ExampleClass';
}

/**
 * Modify the list of available views field handler plugins.
 *
 * This hook may be used to modify handler properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing handler definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsHandlerManager
 */
function hook_views_plugins_field_alter(array &$plugins) {
  // Change the 'title' handler class.
  $plugins['title']['class'] = 'Drupal\\example\\ExampleClass';
}

/**
 * Modify the list of available views filter handler plugins.
 *
 * This hook may be used to modify handler properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing handler definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsHandlerManager
 */
function hook_views_plugins_filter_alter(array &$plugins) {
  // Change the 'title' handler class.
  $plugins['title']['class'] = 'Drupal\\example\\ExampleClass';
}

/**
 * Modify the list of available views relationship handler plugins.
 *
 * This hook may be used to modify handler properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing handler definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsHandlerManager
 */
function hook_views_plugins_relationship_alter(array &$plugins) {
  // Change the 'title' handler class.
  $plugins['title']['class'] = 'Drupal\\example\\ExampleClass';
}

/**
 * Modify the list of available views sort handler plugins.
 *
 * This hook may be used to modify handler properties after they have been
 * specified by other modules.
 *
 * @param array $plugins
 *   An array of all the existing handler definitions, passed by reference.
 *
 * @see \Drupal\views\Plugin\ViewsHandlerManager
 */
function hook_views_plugins_sort_alter(array &$plugins) {
  // Change the 'title' handler class.
  $plugins['title']['class'] = 'Drupal\\example\\ExampleClass';
}

1264
1265
1266
1267
/**
 * @} End of "addtogroup hooks".
 */

merlinofchaos's avatar
merlinofchaos committed
1268
1269
1270
/**
 * @}
 */