"Fossies" - the Fresh Open Source Software Archive

Member "drupal-8.9.10/core/modules/views/views.api.php" (26 Nov 2020, 45313 Bytes) of package /linux/www/drupal-8.9.10.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 <?php
    2 
    3 /**
    4  * @file
    5  * Describes hooks and plugins provided by the Views module.
    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  * @defgroup views_overview Views overview
   15  * @{
   16  * Overview of the Views module API
   17  *
   18  * The Views module is a generalized query and display engine, which can be used
   19  * to make views (formatted lists, grids, feeds, and other output) of items
   20  * (often entities, but can be other types of data). Developers can interact
   21  * with Views in several ways:
   22  * - Provide plugins: Views plugins govern nearly every aspect of views,
   23  *   including querying (sorting, filtering, etc.) and display (at several
   24  *   levels of granularity, ranging from the entire view to the details of a
   25  *   field). See the @link views_plugins Views plugins topic @endlink for
   26  *   more information.
   27  * - Provide data: Data types can be provided to Views by implementing
   28  *   hook_views_data(), and data types provided by other modules can be altered
   29  *   by implementing hook_views_data_alter(). To provide views data for an
   30  *   entity, create a class implementing
   31  *   \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  *   class. See the @link entity_api Entity API topic @endlink for more
   35  *   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  * - Theming: See the @link views_templates Views templates topic @endlink
   39  *   for more information.
   40  *
   41  * @see \Drupal\views\ViewExecutable
   42  * @see \Drupal\views\Views
   43  * @}
   44  */
   45 
   46 /**
   47  * @defgroup views_plugins Views plugins
   48  * @{
   49  * Overview of views plugins
   50  *
   51  * Views plugins are objects that are used to build and render the view.
   52  * See individual views plugin topics for more information about the
   53  * specifics of each plugin type, and the
   54  * @link plugin_api Plugin API topic @endlink for more information about
   55  * plugins in general.
   56  *
   57  * Some Views plugins are known as handlers. Handler plugins help build the
   58  * view query object: filtering, contextual filtering, sorting, relationships,
   59  * etc.
   60  *
   61  * @todo Document specific options on the appropriate plugin base classes.
   62  * @todo Add examples.
   63  *
   64  * @ingroup views_overview
   65  * @see \Drupal\views\Plugin\views\PluginBase
   66  * @see \Drupal\views\Plugin\views\HandlerBase
   67  * @see plugin_api
   68  * @see annotation
   69  * @}
   70  */
   71 
   72 /**
   73  * @defgroup views_hooks Views hooks
   74  * @{
   75  * Hooks that allow other modules to implement the Views API.
   76  * @ingroup views_overview
   77  * @}
   78  */
   79 
   80 /**
   81  * @addtogroup hooks
   82  * @{
   83  */
   84 
   85 /**
   86  * Analyze a view to provide warnings about its configuration.
   87  *
   88  * @param \Drupal\views\ViewExecutable $view
   89  *   The view being executed.
   90  *
   91  * @return array
   92  *   Array of warning messages built by Analyzer::formatMessage to be displayed
   93  *   to the user following analysis of the view.
   94  */
   95 function hook_views_analyze(Drupal\views\ViewExecutable $view) {
   96   $messages = [];
   97 
   98   if ($view->display_handler->options['pager']['type'] == 'none') {
   99     $messages[] = Drupal\views\Analyzer::formatMessage(t('This view has no pager. This could cause performance issues when the view contains many items.'), 'warning');
  100   }
  101 
  102   return $messages;
  103 }
  104 
  105 /**
  106  * Describe data tables and fields (or the equivalent) to Views.
  107  *
  108  * The table and fields are processed in Views using various plugins. See
  109  * the @link views_plugins Views plugins topic @endlink for more information.
  110  *
  111  * To provide views data for an entity, instead of implementing this hook,
  112  * create a class implementing \Drupal\views\EntityViewsDataInterface and
  113  * reference this in the "views" annotation in the entity class. The return
  114  * value of the getViewsData() method on the interface is the same as this hook,
  115  * and base class in \Drupal\views\EntityViewsData will take care of adding the
  116  * basic Views tables and fields for your entity. See the
  117  * @link entity_api Entity API topic @endlink for more information about
  118  * entities.
  119  *
  120  * The data described with this hook is fetched and retrieved by
  121  * \Drupal\views\Views::viewsData()->get().
  122  *
  123  * @return array
  124  *   An associative array describing the structure of database tables and fields
  125  *   (and their equivalents) provided for use in Views. At the outermost level,
  126  *   the keys are the names used internally by Views for the tables (usually the
  127  *   actual table name). Each table's array describes the table itself, how to
  128  *   join to other tables, and the fields that are part of the table. The sample
  129  *   function body provides documentation of the details.
  130  *
  131  * @see hook_views_data_alter()
  132  */
  133 function hook_views_data() {
  134   // This example describes how to write hook_views_data() for a table defined
  135   // like this:
  136   // CREATE TABLE example_table (
  137   //   nid INT(11) NOT NULL         COMMENT 'Primary key: {node}.nid.',
  138   //   plain_text_field VARCHAR(32) COMMENT 'Just a plain text field.',
  139   //   numeric_field INT(11)        COMMENT 'Just a numeric field.',
  140   //   boolean_field INT(1)         COMMENT 'Just an on/off field.',
  141   //   timestamp_field INT(8)       COMMENT 'Just a timestamp field.',
  142   //   langcode VARCHAR(12)         COMMENT 'Language code field.',
  143   //   PRIMARY KEY(nid)
  144   // );
  145 
  146   // Define the return array.
  147   $data = [];
  148 
  149   // The outermost keys of $data are Views table names, which should usually
  150   // be the same as the hook_schema() table names.
  151   $data['example_table'] = [];
  152 
  153   // The value corresponding to key 'table' gives properties of the table
  154   // itself.
  155   $data['example_table']['table'] = [];
  156 
  157   // Within 'table', the value of 'group' (translated string) is used as a
  158   // prefix in Views UI for this table's fields, filters, etc. When adding
  159   // a field, filter, etc. you can also filter by the group.
  160   $data['example_table']['table']['group'] = t('Example table');
  161 
  162   // Within 'table', the value of 'provider' is the module that provides schema
  163   // or the entity type that causes the table to exist. Setting this ensures
  164   // that views have the correct dependencies. This is automatically set to the
  165   // module that implements hook_views_data().
  166   $data['example_table']['table']['provider'] = 'example_module';
  167 
  168   // Some tables are "base" tables, meaning that they can be the base tables
  169   // for views. Non-base tables can only be brought in via relationships in
  170   // views based on other tables. To define a table to be a base table, add
  171   // key 'base' to the 'table' array:
  172   $data['example_table']['table']['base'] = [
  173     // Identifier (primary) field in this table for Views.
  174     'field' => 'nid',
  175     // Label in the UI.
  176     'title' => t('Example table'),
  177     // Longer description in the UI. Required.
  178     'help' => t('Example table contains example content and can be related to nodes.'),
  179     'weight' => -10,
  180   ];
  181 
  182   // Some tables have an implicit, automatic relationship to other tables,
  183   // meaning that when the other table is available in a view (either as the
  184   // base table or through a relationship), this table's fields, filters, etc.
  185   // are automatically made available without having to add an additional
  186   // relationship. To define an implicit relationship that will make your
  187   // table automatically available when another table is present, add a 'join'
  188   // section to your 'table' section. Note that it is usually only a good idea
  189   // to do this for one-to-one joins, because otherwise your automatic join
  190   // will add more rows to the view. It is also not a good idea to do this if
  191   // most views won't need your table -- if that is the case, define a
  192   // relationship instead (see below).
  193   //
  194   // If you've decided an automatic join is a good idea, here's how to do it;
  195   // the resulting SQL query will look something like this:
  196   //   ... FROM example_table et ... JOIN node_field_data nfd
  197   //   ON et.nid = nfd.nid AND ('extra' clauses will be here) ...
  198   // although the table aliases will be different.
  199   $data['example_table']['table']['join'] = [
  200     // Within the 'join' section, list one or more tables to automatically
  201     // join to. In this example, every time 'node_field_data' is available in
  202     // a view, 'example_table' will be too. The array keys here are the array
  203     // keys for the other tables, given in their hook_views_data()
  204     // implementations. If the table listed here is from another module's
  205     // hook_views_data() implementation, make sure your module depends on that
  206     // other module.
  207     'node_field_data' => [
  208       // Primary key field in node_field_data to use in the join.
  209       'left_field' => 'nid',
  210       // Foreign key field in example_table to use in the join.
  211       'field' => 'nid',
  212       // 'extra' is an array of additional conditions on the join.
  213       'extra' => [
  214         0 => [
  215           // Adds AND node_field_data.published = TRUE to the join.
  216           'field' => 'published',
  217           'value' => TRUE,
  218         ],
  219         1 => [
  220           // Adds AND example_table.numeric_field = 1 to the join.
  221           'left_field' => 'numeric_field',
  222           'value' => 1,
  223           // If true, the value will not be surrounded in quotes.
  224           'numeric' => TRUE,
  225         ],
  226         2 => [
  227           // Adds AND example_table.boolean_field <>
  228           // node_field_data.published to the join.
  229           'field' => 'published',
  230           'left_field' => 'boolean_field',
  231           // The operator used, Defaults to "=".
  232           'operator' => '!=',
  233         ],
  234       ],
  235     ],
  236   ];
  237 
  238   // You can also do a more complex join, where in order to get to a certain
  239   // base table defined in a hook_views_data() implementation, you will join
  240   // to a different table that Views knows how to auto-join to the base table.
  241   // For instance, if another module that your module depends on had
  242   // defined a table 'foo' with an automatic join to 'node_field_table' (as
  243   // shown above), you could join to 'node_field_table' via the 'foo' table.
  244   // Here's how to do this, and the resulting SQL query would look something
  245   // like this:
  246   //   ... FROM example_table et ... JOIN foo foo
  247   //   ON et.nid = foo.nid AND ('extra' clauses will be here) ...
  248   //   JOIN node_field_data nfd ON (definition of the join from the foo
  249   //   module goes here) ...
  250   // although the table aliases will be different.
  251   $data['example_table']['table']['join']['node_field_data'] = [
  252     // 'node_field_data' above is the base we're joining to in Views.
  253     // 'left_table' is the table we're actually joining to, in order to get to
  254     // 'node_field_data'. It has to be something that Views knows how to join
  255     // to 'node_field_data'.
  256     'left_table' => 'foo',
  257     'left_field' => 'nid',
  258     'field' => 'nid',
  259     // 'extra' is an array of additional conditions on the join.
  260     'extra' => [
  261       // This syntax matches additional fields in the two tables:
  262       // ... AND foo.langcode = example_table.langcode ...
  263       ['left_field' => 'langcode', 'field' => 'langcode'],
  264       // This syntax adds a condition on our table. 'operator' defaults to
  265       // '=' for non-array values, or 'IN' for array values.
  266       // ... AND example_table.numeric_field > 0 ...
  267       ['field' => 'numeric_field', 'value' => 0, 'numeric' => TRUE, 'operator' => '>'],
  268     ],
  269   ];
  270 
  271   // Other array elements at the top level of your table's array describe
  272   // individual database table fields made available to Views. The array keys
  273   // are the names (unique within the table) used by Views for the fields,
  274   // usually equal to the database field names.
  275   //
  276   // Each field entry must have the following elements:
  277   // - title: Translated label for the field in the UI.
  278   // - help: Description of the field in the UI.
  279   //
  280   // Each field entry may also have one or more of the following elements,
  281   // describing "handlers" (plugins) for the field:
  282   // - relationship: Specifies a handler that allows this field to be used
  283   //   to define a relationship to another table in Views.
  284   // - field: Specifies a handler to make it available to Views as a field.
  285   // - filter: Specifies a handler to make it available to Views as a filter.
  286   // - sort: Specifies a handler to make it available to Views as a sort.
  287   // - argument: Specifies a handler to make it available to Views as an
  288   //   argument, or contextual filter as it is known in the UI.
  289   // - area: Specifies a handler to make it available to Views to add content
  290   //   to the header, footer, or as no result behavior.
  291   //
  292   // Note that when specifying handlers, you must give the handler plugin ID
  293   // and you may also specify overrides for various settings that make up the
  294   // plugin definition. See examples below; the Boolean example demonstrates
  295   // setting overrides.
  296 
  297   // Node ID field, exposed as relationship only, since it is a foreign key
  298   // in this table.
  299   $data['example_table']['nid'] = [
  300     'title' => t('Example content'),
  301     'help' => t('Relate example content to the node content'),
  302 
  303     // Define a relationship to the node_field_data table, so views whose
  304     // base table is example_table can add a relationship to nodes. To make a
  305     // relationship in the other direction, you can:
  306     // - Use hook_views_data_alter() -- see the function body example on that
  307     //   hook for details.
  308     // - Use the implicit join method described above.
  309     'relationship' => [
  310       // Views name of the table to join to for the relationship.
  311       'base' => 'node_field_data',
  312       // Database field name in the other table to join on.
  313       'base field' => 'nid',
  314       // ID of relationship handler plugin to use.
  315       'id' => 'standard',
  316       // Default label for relationship in the UI.
  317       'label' => t('Example node'),
  318     ],
  319   ];
  320 
  321   // Plain text field, exposed as a field, sort, filter, and argument.
  322   $data['example_table']['plain_text_field'] = [
  323     'title' => t('Plain text field'),
  324     'help' => t('Just a plain text field.'),
  325 
  326     'field' => [
  327       // ID of field handler plugin to use.
  328       'id' => 'standard',
  329     ],
  330 
  331     'sort' => [
  332       // ID of sort handler plugin to use.
  333       'id' => 'standard',
  334     ],
  335 
  336     'filter' => [
  337       // ID of filter handler plugin to use.
  338       'id' => 'string',
  339     ],
  340 
  341     'argument' => [
  342       // ID of argument handler plugin to use.
  343       'id' => 'string',
  344     ],
  345   ];
  346 
  347   // Numeric field, exposed as a field, sort, filter, and argument.
  348   $data['example_table']['numeric_field'] = [
  349     'title' => t('Numeric field'),
  350     'help' => t('Just a numeric field.'),
  351 
  352     'field' => [
  353       // ID of field handler plugin to use.
  354       'id' => 'numeric',
  355     ],
  356 
  357     'sort' => [
  358       // ID of sort handler plugin to use.
  359       'id' => 'standard',
  360     ],
  361 
  362     'filter' => [
  363       // ID of filter handler plugin to use.
  364       'id' => 'numeric',
  365     ],
  366 
  367     'argument' => [
  368       // ID of argument handler plugin to use.
  369       'id' => 'numeric',
  370     ],
  371   ];
  372 
  373   // Boolean field, exposed as a field, sort, and filter. The filter section
  374   // illustrates overriding various settings.
  375   $data['example_table']['boolean_field'] = [
  376     'title' => t('Boolean field'),
  377     'help' => t('Just an on/off field.'),
  378 
  379     'field' => [
  380       // ID of field handler plugin to use.
  381       'id' => 'boolean',
  382     ],
  383 
  384     'sort' => [
  385       // ID of sort handler plugin to use.
  386       'id' => 'standard',
  387     ],
  388 
  389     'filter' => [
  390       // ID of filter handler plugin to use.
  391       'id' => 'boolean',
  392       // Override the generic field title, so that the filter uses a different
  393       // label in the UI.
  394       'label' => t('Published'),
  395       // Override the default BooleanOperator filter handler's 'type' setting,
  396       // to display this as a "Yes/No" filter instead of a "True/False" filter.
  397       'type' => 'yes-no',
  398       // Override the default Boolean filter handler's 'use_equal' setting, to
  399       // make the query use 'boolean_field = 1' instead of 'boolean_field <> 0'.
  400       'use_equal' => TRUE,
  401     ],
  402   ];
  403 
  404   // Integer timestamp field, exposed as a field, sort, and filter.
  405   $data['example_table']['timestamp_field'] = [
  406     'title' => t('Timestamp field'),
  407     'help' => t('Just a timestamp field.'),
  408 
  409     'field' => [
  410       // ID of field handler plugin to use.
  411       'id' => 'date',
  412     ],
  413 
  414     'sort' => [
  415       // ID of sort handler plugin to use.
  416       'id' => 'date',
  417     ],
  418 
  419     'filter' => [
  420       // ID of filter handler plugin to use.
  421       'id' => 'date',
  422     ],
  423   ];
  424 
  425   // Area example. Areas are not generally associated with actual data
  426   // tables and fields. This example is from views_views_data(), which defines
  427   // the "Global" table (not really a table, but a group of Fields, Filters,
  428   // etc. that are grouped into section "Global" in the UI). Here's the
  429   // definition of the generic "Text area":
  430   $data['views']['area'] = [
  431     'title' => t('Text area'),
  432     'help' => t('Provide markup text for the area.'),
  433     'area' => [
  434       // ID of the area handler plugin to use.
  435       'id' => 'text',
  436     ],
  437   ];
  438 
  439   return $data;
  440 }
  441 
  442 /**
  443  * Alter the table and field information from hook_views_data().
  444  *
  445  * @param array $data
  446  *   An array of all information about Views tables and fields, collected from
  447  *   hook_views_data(), passed by reference.
  448  *
  449  * @see hook_views_data()
  450  */
  451 function hook_views_data_alter(array &$data) {
  452   // Alter the title of the node_field_data:nid field in the Views UI.
  453   $data['node_field_data']['nid']['title'] = t('Node-Nid');
  454 
  455   // Add an additional field to the users_field_data table.
  456   $data['users_field_data']['example_field'] = [
  457     'title' => t('Example field'),
  458     'help' => t('Some example content that references a user'),
  459 
  460     'field' => [
  461       // ID of the field handler to use.
  462       'id' => 'example_field',
  463     ],
  464   ];
  465 
  466   // Change the handler of the node title field, presumably to a handler plugin
  467   // you define in your module. Give the ID of this plugin.
  468   $data['node_field_data']['title']['field']['id'] = 'node_title';
  469 
  470   // Add a relationship that will allow a view whose base table is 'foo' (from
  471   // another module) to have a relationship to 'example_table' (from my module),
  472   // via joining foo.fid to example_table.eid.
  473   //
  474   // This relationship has to be added to the 'foo' Views data, which my module
  475   // does not control, so it must be done in hook_views_data_alter(), not
  476   // hook_views_data().
  477   //
  478   // In Views data definitions, each field can have only one relationship. So
  479   // rather than adding this relationship directly to the $data['foo']['fid']
  480   // field entry, which could overwrite an existing relationship, we define
  481   // a dummy field key to handle the relationship.
  482   $data['foo']['unique_dummy_name'] = [
  483     'title' => t('Title seen while adding relationship'),
  484     'help' => t('More information about the relationship'),
  485 
  486     'relationship' => [
  487       // Views name of the table being joined to from foo.
  488       'base' => 'example_table',
  489       // Database field name in example_table for the join.
  490       'base field' => 'eid',
  491       // Real database field name in foo for the join, to override
  492       // 'unique_dummy_name'.
  493       'field' => 'fid',
  494       // ID of relationship handler plugin to use.
  495       'id' => 'standard',
  496       'label' => t('Default label for relationship'),
  497     ],
  498   ];
  499 
  500   // Note that the $data array is not returned – it is modified by reference.
  501 }
  502 
  503 /**
  504  * Override the default Views data for a Field API field.
  505  *
  506  * The field module's implementation of hook_views_data() invokes this for each
  507  * field storage, in the module that defines the field type. It is not invoked
  508  * in other modules.
  509  *
  510  * If no hook implementation exists, hook_views_data() falls back to
  511  * views_field_default_views_data().
  512  *
  513  * @param \Drupal\field\FieldStorageConfigInterface $field_storage
  514  *   The field storage config entity.
  515  *
  516  * @return array
  517  *   An array of views data, in the same format as the return value of
  518  *   hook_views_data().
  519  *
  520  * @see views_views_data()
  521  * @see hook_field_views_data_alter()
  522  * @see hook_field_views_data_views_data_alter()
  523  */
  524 function hook_field_views_data(\Drupal\field\FieldStorageConfigInterface $field_storage) {
  525   $data = views_field_default_views_data($field_storage);
  526   foreach ($data as $table_name => $table_data) {
  527     // Add the relationship only on the target_id field.
  528     $data[$table_name][$field_storage->getName() . '_target_id']['relationship'] = [
  529       'id' => 'standard',
  530       'base' => 'file_managed',
  531       'base field' => 'target_id',
  532       'label' => t('image from @field_name', ['@field_name' => $field_storage->getName()]),
  533     ];
  534   }
  535 
  536   return $data;
  537 }
  538 
  539 /**
  540  * Alter the Views data for a single Field API field.
  541  *
  542  * This is called on all modules even if there is no hook_field_views_data()
  543  * 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  *   The views data for the field storage. This has the same format as the
  549  *   return value of hook_views_data().
  550  * @param \Drupal\field\FieldStorageConfigInterface $field_storage
  551  *   The field storage config entity.
  552  *
  553  * @see views_views_data()
  554  * @see hook_field_views_data()
  555  * @see hook_field_views_data_views_data_alter()
  556  */
  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   $entity_type = \Drupal::entityTypeManager()->getDefinition($entity_type_id);
  561   $pseudo_field_name = 'reverse_' . $field_name . '_' . $entity_type_id;
  562   $table_mapping = \Drupal::entityTypeManager()->getStorage($entity_type_id)->getTableMapping();
  563 
  564   list($label) = views_entity_field_label($entity_type_id, $field_name);
  565 
  566   $data['file_managed'][$pseudo_field_name]['relationship'] = [
  567     'title' => t('@entity using @field', ['@entity' => $entity_type->getLabel(), '@field' => $label]),
  568     'help' => t('Relate each @entity with a @field set to the image.', ['@entity' => $entity_type->getLabel(), '@field' => $label]),
  569     'id' => 'entity_reverse',
  570     'field_name' => $field_name,
  571     'entity_type' => $entity_type_id,
  572     'field table' => $table_mapping->getDedicatedDataTableName($field_storage),
  573     'field field' => $field_name . '_target_id',
  574     'base' => $entity_type->getBaseTable(),
  575     'base field' => $entity_type->getKey('id'),
  576     'label' => $field_name,
  577     'join_extra' => [
  578       0 => [
  579         'field' => 'deleted',
  580         'value' => 0,
  581         'numeric' => TRUE,
  582       ],
  583     ],
  584   ];
  585 }
  586 
  587 /**
  588  * Alter the Views data on a per field basis.
  589  *
  590  * The field module's implementation of hook_views_data_alter() invokes this for
  591  * each field storage, in the module that defines the field type. It is not
  592  * 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  * other tables, which would not yet be defined at the point when
  597  * hook_field_views_data() and hook_field_views_data_alter() are invoked. For
  598  * example, entityreference adds reverse relationships on the tables for the
  599  * entities which are referenced by entityreference fields.
  600  *
  601  * (Note: this is weirdly named so as not to conflict with
  602  * hook_field_views_data_alter().)
  603  *
  604  * @param array $data
  605  *   The views data.
  606  * @param \Drupal\field\FieldStorageConfigInterface $field
  607  *   The field storage config entity.
  608  *
  609  * @see hook_field_views_data()
  610  * @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   $field_name = $field->getName();
  615   $data_key = 'field_data_' . $field_name;
  616   $entity_type_id = $field->entity_type;
  617   $entity_type = \Drupal::entityTypeManager()->getDefinition($entity_type_id);
  618   $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::entityTypeManager()->getStorage($entity_type_id)->getTableMapping();
  621 
  622   // Views data for this field is in $data[$data_key].
  623   $data[$data_key][$pseudo_field_name]['relationship'] = [
  624     'title' => t('@entity using @field', ['@entity' => $entity_type->getLabel(), '@field' => $label]),
  625     'help' => t('Relate each @entity with a @field set to the term.', ['@entity' => $entity_type->getLabel(), '@field' => $label]),
  626     'id' => 'entity_reverse',
  627     'field_name' => $field_name,
  628     'entity_type' => $entity_type_id,
  629     'field table' => $table_mapping->getDedicatedDataTableName($field),
  630     'field field' => $field_name . '_target_id',
  631     'base' => $entity_type->getBaseTable(),
  632     'base field' => $entity_type->getKey('id'),
  633     'label' => $field_name,
  634     'join_extra' => [
  635       0 => [
  636         'field' => 'deleted',
  637         'value' => 0,
  638         'numeric' => TRUE,
  639       ],
  640     ],
  641   ];
  642 }
  643 
  644 /**
  645  * Replace special strings in the query before it is executed.
  646  *
  647  * The idea is that certain dynamic values can be placed in a query when it is
  648  * built, and substituted at run-time, allowing the query to be cached and
  649  * still work correctly when executed.
  650  *
  651  * @param \Drupal\views\ViewExecutable $view
  652  *   The View being executed.
  653  *
  654  * @return array
  655  *   An associative array where each key is a string to be replaced, and the
  656  *   corresponding value is its replacement. The strings to replace are often
  657  *   surrounded with '***', as illustrated in the example implementation, to
  658  *   avoid collisions with other values in the query.
  659  */
  660 function hook_views_query_substitutions(ViewExecutable $view) {
  661   // Example from views_views_query_substitutions().
  662   return [
  663     '***CURRENT_VERSION***' => \Drupal::VERSION,
  664     '***CURRENT_TIME***' => REQUEST_TIME,
  665     '***LANGUAGE_language_content***' => \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId(),
  666     PluginBase::VIEWS_QUERY_LANGUAGE_SITE_DEFAULT => \Drupal::languageManager()->getDefaultLanguage()->getId(),
  667   ];
  668 }
  669 
  670 /**
  671  * Replace special strings when processing a view with form elements.
  672  *
  673  * @return array
  674  *   An associative array where each key is a string to be replaced, and the
  675  *   corresponding value is its replacement. The value will be escaped unless it
  676  *   is already marked safe.
  677  */
  678 function hook_views_form_substitutions() {
  679   return [
  680     '<!--views-form-example-substitutions-->' => 'Example Substitution',
  681   ];
  682 }
  683 
  684 /**
  685  * Alter a view at the very beginning of Views processing.
  686  *
  687  * Output can be added to the view by setting $view->attachment_before
  688  * and $view->attachment_after.
  689  *
  690  * @param \Drupal\views\ViewExecutable $view
  691  *   The view object about to be processed.
  692  * @param string $display_id
  693  *   The machine name of the active display.
  694  * @param array $args
  695  *   An array of arguments passed into the view.
  696  *
  697  * @see \Drupal\views\ViewExecutable
  698  */
  699 function hook_views_pre_view(ViewExecutable $view, $display_id, array &$args) {
  700 
  701   // Modify contextual filters for my_special_view if user has 'my special permission'.
  702   $account = \Drupal::currentUser();
  703 
  704   if ($view->id() == 'my_special_view' && $account->hasPermission('my special permission') && $display_id == 'public_display') {
  705     $args[0] = 'custom value';
  706   }
  707 }
  708 
  709 /**
  710  * Act on the view before the query is built, but after displays are attached.
  711  *
  712  * Output can be added to the view by setting $view->attachment_before
  713  * and $view->attachment_after.
  714  *
  715  * @param \Drupal\views\ViewExecutable $view
  716  *   The view object about to be processed.
  717  *
  718  * @see \Drupal\views\ViewExecutable
  719  */
  720 function hook_views_pre_build(ViewExecutable $view) {
  721   // Because of some inexplicable business logic, we should remove all
  722   // attachments from all views on Mondays.
  723   // (This alter could be done later in the execution process as well.)
  724   if (date('D') == 'Mon') {
  725     unset($view->attachment_before);
  726     unset($view->attachment_after);
  727   }
  728 }
  729 
  730 /**
  731  * Act on the view immediately after the query is built.
  732  *
  733  * Output can be added to the view by setting $view->attachment_before
  734  * and $view->attachment_after.
  735  *
  736  * @param \Drupal\views\ViewExecutable $view
  737  *   The view object about to be processed.
  738  *
  739  * @see \Drupal\views\ViewExecutable
  740  */
  741 function hook_views_post_build(ViewExecutable $view) {
  742   // If the exposed field 'type' is set, hide the column containing the content
  743   // type. (Note that this is a solution for a particular view, and makes
  744   // assumptions about both exposed filter settings and the fields in the view.
  745   // Also note that this alter could be done at any point before the view being
  746   // rendered.)
  747   if ($view->id() == 'my_view' && isset($view->exposed_raw_input['type']) && $view->exposed_raw_input['type'] != 'All') {
  748     // 'Type' should be interpreted as content type.
  749     if (isset($view->field['type'])) {
  750       $view->field['type']->options['exclude'] = TRUE;
  751     }
  752   }
  753 }
  754 
  755 /**
  756  * Act on the view after the query is built and just before it is executed.
  757  *
  758  * Output can be added to the view by setting $view->attachment_before
  759  * and $view->attachment_after.
  760  *
  761  * @param \Drupal\views\ViewExecutable $view
  762  *   The view object about to be processed.
  763  *
  764  * @see \Drupal\views\ViewExecutable
  765  */
  766 function hook_views_pre_execute(ViewExecutable $view) {
  767   // Whenever a view queries more than two tables, show a message that notifies
  768   // view administrators that the query might be heavy.
  769   // (This action could be performed later in the execution process, but not
  770   // earlier.)
  771   $account = \Drupal::currentUser();
  772 
  773   if (count($view->query->tables) > 2 && $account->hasPermission('administer views')) {
  774     \Drupal::messenger()->addWarning(t('The view %view may be heavy to execute.', ['%view' => $view->id()]));
  775   }
  776 }
  777 
  778 /**
  779  * Act on the view immediately after the query has been executed.
  780  *
  781  * At this point the query has been executed, but the preRender() phase has
  782  * not yet happened for handlers.
  783  *
  784  * Output can be added to the view by setting $view->attachment_before
  785  * and $view->attachment_after.
  786  *
  787  * @param \Drupal\views\ViewExecutable $view
  788  *   The view object about to be processed.
  789  *
  790  * @see \Drupal\views\ViewExecutable
  791  */
  792 function hook_views_post_execute(ViewExecutable $view) {
  793   // If there are more than 100 results, show a message that encourages the user
  794   // to change the filter settings.
  795   // (This action could be performed later in the execution process, but not
  796   // earlier.)
  797   if ($view->total_rows > 100) {
  798     \Drupal::messenger()->addStatus(t('You have more than 100 hits. Use the filter settings to narrow down your list.'));
  799   }
  800 }
  801 
  802 /**
  803  * Act on the view immediately before rendering it.
  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.
  808  *
  809  * Output can be added to the view by setting $view->attachment_before
  810  * and $view->attachment_after.
  811  *
  812  * @param \Drupal\views\ViewExecutable $view
  813  *   The view object about to be processed.
  814  *
  815  * @see \Drupal\views\ViewExecutable
  816  */
  817 function hook_views_pre_render(ViewExecutable $view) {
  818   // Scramble the order of the rows shown on this result page.
  819   // Note that this could be done earlier, but not later in the view execution
  820   // process.
  821   shuffle($view->result);
  822 }
  823 
  824 /**
  825  * Post-process any rendered data.
  826  *
  827  * This can be valuable to be able to cache a view and still have some level of
  828  * 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.
  831  *
  832  * Example usage. If it is known that the view is a node view and that the
  833  * primary field will be a nid, you can do something like this:
  834  * @code
  835  *   <!--post-FIELD-NID-->
  836  * @endcode
  837  * And then in the post-render, create an array with the text that should
  838  * go there:
  839  * @code
  840  *   strtr($output, array('<!--post-FIELD-1-->' => 'output for FIELD of nid 1');
  841  * @endcode
  842  * All of the cached result data will be available in $view->result, as well,
  843  * so all ids used in the query should be discoverable.
  844  *
  845  * @param \Drupal\views\ViewExecutable $view
  846  *   The view object about to be processed.
  847  * @param string $output
  848  *   A flat string with the rendered output of the view.
  849  * @param \Drupal\views\Plugin\views\cache\CachePluginBase $cache
  850  *   The cache settings.
  851  *
  852  * @see \Drupal\views\ViewExecutable
  853  */
  854 function hook_views_post_render(ViewExecutable $view, &$output, CachePluginBase $cache) {
  855   // When using full pager, disable any time-based caching if there are fewer
  856   // than 10 results.
  857   if ($view->pager instanceof Drupal\views\Plugin\views\pager\Full && $cache instanceof Drupal\views\Plugin\views\cache\Time && count($view->result) < 10) {
  858     $cache->options['results_lifespan'] = 0;
  859     $cache->options['output_lifespan'] = 0;
  860   }
  861 }
  862 
  863 /**
  864  * Alter the query before it is executed.
  865  *
  866  * @param \Drupal\views\ViewExecutable $view
  867  *   The view object about to be processed.
  868  * @param QueryPluginBase $query
  869  *   The query plugin object for the query.
  870  *
  871  * @see hook_views_query_substitutions()
  872  * @see \Drupal\views\Plugin\views\query\Sql
  873  */
  874 function hook_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
  875   // (Example assuming a view with an exposed filter on node title.)
  876   // If the input for the title filter is a positive integer, filter against
  877   // 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) {
  879     // Traverse through the 'where' part of the query.
  880     foreach ($query->where as &$condition_group) {
  881       foreach ($condition_group['conditions'] as &$condition) {
  882         // If this is the part of the query filtering on title, change the
  883         // condition to filter on node ID.
  884         if ($condition['field'] == 'node.title') {
  885           $condition = [
  886             'field' => 'node.nid',
  887             'value' => $view->exposed_raw_input['title'],
  888             'operator' => '=',
  889           ];
  890         }
  891       }
  892     }
  893   }
  894 }
  895 
  896 /**
  897  * Alter the view preview information.
  898  *
  899  * The view preview information is optionally displayed when a view is
  900  * previewed in the administrative UI. It includes query and performance
  901  * statistics.
  902  *
  903  * @param array $rows
  904  *   An associative array with two keys:
  905  *   - query: An array of rows suitable for '#type' => 'table', containing
  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
  910  *   The view object.
  911  *
  912  * @see \Drupal\views_ui\ViewUI
  913  * @see table.html.twig
  914  */
  915 function hook_views_preview_info_alter(array &$rows, ViewExecutable $view) {
  916   // Adds information about the tables being queried by the view to the query
  917   // part of the info box.
  918   $rows['query'][] = [
  919     t('<strong>Table queue</strong>'),
  920     count($view->query->table_queue) . ': (' . implode(', ', array_keys($view->query->table_queue)) . ')',
  921   ];
  922 }
  923 
  924 // @todo Describe how to alter a view ajax response with event listeners.
  925 
  926 /**
  927  * Allow modules to respond to the invalidation of the Views cache.
  928  *
  929  * This hook will fire whenever a view is enabled, disabled, created,
  930  * updated, or deleted.
  931  *
  932  * @see views_invalidate_cache()
  933  */
  934 function hook_views_invalidate_cache() {
  935   \Drupal\Core\Cache\Cache::invalidateTags(['views']);
  936 }
  937 
  938 /**
  939  * Modify the list of available views access plugins.
  940  *
  941  * This hook may be used to modify plugin properties after they have been
  942  * specified by other modules.
  943  *
  944  * @param array $plugins
  945  *   An array of all the existing plugin definitions, passed by reference.
  946  *
  947  * @see \Drupal\views\Plugin\ViewsPluginManager
  948  */
  949 function hook_views_plugins_access_alter(array &$plugins) {
  950   // Remove the available plugin because the users should not have access to it.
  951   unset($plugins['role']);
  952 }
  953 
  954 /**
  955  * Modify the list of available views default argument plugins.
  956  *
  957  * This hook may be used to modify plugin properties after they have been
  958  * specified by other modules.
  959  *
  960  * @param array $plugins
  961  *   An array of all the existing plugin definitions, passed by reference.
  962  *
  963  * @see \Drupal\views\Plugin\ViewsPluginManager
  964  */
  965 function hook_views_plugins_argument_default_alter(array &$plugins) {
  966   // Remove the available plugin because the users should not have access to it.
  967   unset($plugins['php']);
  968 }
  969 
  970 /**
  971  * Modify the list of available views argument validation plugins.
  972  *
  973  * This hook may be used to modify plugin properties after they have been
  974  * specified by other modules.
  975  *
  976  * @param array $plugins
  977  *   An array of all the existing plugin definitions, passed by reference.
  978  *
  979  * @see \Drupal\views\Plugin\ViewsPluginManager
  980  */
  981 function hook_views_plugins_argument_validator_alter(array &$plugins) {
  982   // Remove the available plugin because the users should not have access to it.
  983   unset($plugins['php']);
  984 }
  985 
  986 /**
  987  * Modify the list of available views cache plugins.
  988  *
  989  * This hook may be used to modify plugin properties after they have been
  990  * specified by other modules.
  991  *
  992  * @param array $plugins
  993  *   An array of all the existing plugin definitions, passed by reference.
  994  *
  995  * @see \Drupal\views\Plugin\ViewsPluginManager
  996  */
  997 function hook_views_plugins_cache_alter(array &$plugins) {
  998   // Change the title.
  999   $plugins['time']['title'] = t('Custom title');
 1000 }
 1001 
 1002 /**
 1003  * Modify the list of available views display extender plugins.
 1004  *
 1005  * This hook may be used to modify plugin properties after they have been
 1006  * specified by other modules.
 1007  *
 1008  * @param array $plugins
 1009  *   An array of all the existing plugin definitions, passed by reference.
 1010  *
 1011  * @see \Drupal\views\Plugin\ViewsPluginManager
 1012  */
 1013 function hook_views_plugins_display_extenders_alter(array &$plugins) {
 1014   // Alter the title of an existing plugin.
 1015   $plugins['time']['title'] = t('Custom title');
 1016 }
 1017 
 1018 /**
 1019  * Modify the list of available views display plugins.
 1020  *
 1021  * This hook may be used to modify plugin properties after they have been
 1022  * specified by other modules.
 1023  *
 1024  * @param array $plugins
 1025  *   An array of all the existing plugin definitions, passed by reference.
 1026  *
 1027  * @see \Drupal\views\Plugin\ViewsPluginManager
 1028  */
 1029 function hook_views_plugins_display_alter(array &$plugins) {
 1030   // Alter the title of an existing plugin.
 1031   $plugins['rest_export']['title'] = t('Export');
 1032 }
 1033 
 1034 /**
 1035  * Modify the list of available views exposed form plugins.
 1036  *
 1037  * This hook may be used to modify plugin properties after they have been
 1038  * specified by other modules.
 1039  *
 1040  * @param array $plugins
 1041  *   An array of all the existing plugin definitions, passed by reference.
 1042  *
 1043  * @see \Drupal\views\Plugin\ViewsPluginManager
 1044  */
 1045 function hook_views_plugins_exposed_form_alter(array &$plugins) {
 1046   // Remove the available plugin because the users should not have access to it.
 1047   unset($plugins['input_required']);
 1048 }
 1049 
 1050 /**
 1051  * Modify the list of available views join plugins.
 1052  *
 1053  * This hook may be used to modify plugin properties after they have been
 1054  * specified by other modules.
 1055  *
 1056  * @param array $plugins
 1057  *   An array of all the existing plugin definitions, passed by reference.
 1058  *
 1059  * @see \Drupal\views\Plugin\ViewsPluginManager
 1060  */
 1061 function hook_views_plugins_join_alter(array &$plugins) {
 1062   // Print out all join plugin names for debugging purposes.
 1063   debug($plugins);
 1064 }
 1065 
 1066 /**
 1067  * Modify the list of available views pager plugins.
 1068  *
 1069  * This hook may be used to modify plugin properties after they have been
 1070  * specified by other modules.
 1071  *
 1072  * @param array $plugins
 1073  *   An array of all the existing plugin definitions, passed by reference.
 1074  *
 1075  * @see \Drupal\views\Plugin\ViewsPluginManager
 1076  */
 1077 function hook_views_plugins_pager_alter(array &$plugins) {
 1078   // Remove the sql based plugin to force good performance.
 1079   unset($plugins['full']);
 1080 }
 1081 
 1082 /**
 1083  * Modify the list of available views query plugins.
 1084  *
 1085  * This hook may be used to modify plugin properties after they have been
 1086  * specified by other modules.
 1087  *
 1088  * @param array $plugins
 1089  *   An array of all the existing plugin definitions, passed by reference.
 1090  *
 1091  * @see \Drupal\views\Plugin\ViewsPluginManager
 1092  */
 1093 function hook_views_plugins_query_alter(array &$plugins) {
 1094   // Print out all query plugin names for debugging purposes.
 1095   debug($plugins);
 1096 }
 1097 
 1098 /**
 1099  * Modify the list of available views row plugins.
 1100  *
 1101  * This hook may be used to modify plugin properties after they have been
 1102  * specified by other modules.
 1103  *
 1104  * @param array $plugins
 1105  *   An array of all the existing plugin definitions, passed by reference.
 1106  *
 1107  * @see \Drupal\views\Plugin\ViewsPluginManager
 1108  */
 1109 function hook_views_plugins_row_alter(array &$plugins) {
 1110   // Change the used class of a plugin.
 1111   $plugins['entity:node']['class'] = 'Drupal\node\Plugin\views\row\NodeRow';
 1112   $plugins['entity:node']['module'] = 'node';
 1113 }
 1114 
 1115 /**
 1116  * Modify the list of available views style plugins.
 1117  *
 1118  * This hook may be used to modify plugin properties after they have been
 1119  * specified by other modules.
 1120  *
 1121  * @param array $plugins
 1122  *   An array of all the existing plugin definitions, passed by reference.
 1123  *
 1124  * @see \Drupal\views\Plugin\ViewsPluginManager
 1125  */
 1126 function hook_views_plugins_style_alter(array &$plugins) {
 1127   // Change the theme hook of a plugin.
 1128   $plugins['html_list']['theme'] = 'custom_views_view_list';
 1129 }
 1130 
 1131 /**
 1132  * Modify the list of available views wizard plugins.
 1133  *
 1134  * This hook may be used to modify plugin properties after they have been
 1135  * specified by other modules.
 1136  *
 1137  * @param array $plugins
 1138  *   An array of all the existing plugin definitions, passed by reference.
 1139  *
 1140  * @see \Drupal\views\Plugin\ViewsPluginManager
 1141  */
 1142 function hook_views_plugins_wizard_alter(array &$plugins) {
 1143   // Change the title of a plugin.
 1144   $plugins['node_revision']['title'] = t('Node revision wizard');
 1145 }
 1146 
 1147 /**
 1148  * Modify the list of available views area handler plugins.
 1149  *
 1150  * This hook may be used to modify handler properties after they have been
 1151  * specified by other modules.
 1152  *
 1153  * @param array $plugins
 1154  *   An array of all the existing handler definitions, passed by reference.
 1155  *
 1156  * @see \Drupal\views\Plugin\ViewsHandlerManager
 1157  */
 1158 function hook_views_plugins_area_alter(array &$plugins) {
 1159   // Change the 'title' handler class.
 1160   $plugins['title']['class'] = 'Drupal\\example\\ExampleClass';
 1161 }
 1162 
 1163 /**
 1164  * Modify the list of available views argument handler plugins.
 1165  *
 1166  * This hook may be used to modify handler properties after they have been
 1167  * specified by other modules.
 1168  *
 1169  * @param array $plugins
 1170  *   An array of all the existing handler definitions, passed by reference.
 1171  *
 1172  * @see \Drupal\views\Plugin\ViewsHandlerManager
 1173  */
 1174 function hook_views_plugins_argument_alter(array &$plugins) {
 1175   // Change the 'title' handler class.
 1176   $plugins['title']['class'] = 'Drupal\\example\\ExampleClass';
 1177 }
 1178 
 1179 /**
 1180  * Modify the list of available views field handler plugins.
 1181  *
 1182  * This hook may be used to modify handler properties after they have been
 1183  * specified by other modules.
 1184  *
 1185  * @param array $plugins
 1186  *   An array of all the existing handler definitions, passed by reference.
 1187  *
 1188  * @see \Drupal\views\Plugin\ViewsHandlerManager
 1189  */
 1190 function hook_views_plugins_field_alter(array &$plugins) {
 1191   // Change the 'title' handler class.
 1192   $plugins['title']['class'] = 'Drupal\\example\\ExampleClass';
 1193 }
 1194 
 1195 /**
 1196  * Modify the list of available views filter handler plugins.
 1197  *
 1198  * This hook may be used to modify handler properties after they have been
 1199  * specified by other modules.
 1200  *
 1201  * @param array $plugins
 1202  *   An array of all the existing handler definitions, passed by reference.
 1203  *
 1204  * @see \Drupal\views\Plugin\ViewsHandlerManager
 1205  */
 1206 function hook_views_plugins_filter_alter(array &$plugins) {
 1207   // Change the 'title' handler class.
 1208   $plugins['title']['class'] = 'Drupal\\example\\ExampleClass';
 1209 }
 1210 
 1211 /**
 1212  * Modify the list of available views relationship handler plugins.
 1213  *
 1214  * This hook may be used to modify handler properties after they have been
 1215  * specified by other modules.
 1216  *
 1217  * @param array $plugins
 1218  *   An array of all the existing handler definitions, passed by reference.
 1219  *
 1220  * @see \Drupal\views\Plugin\ViewsHandlerManager
 1221  */
 1222 function hook_views_plugins_relationship_alter(array &$plugins) {
 1223   // Change the 'title' handler class.
 1224   $plugins['title']['class'] = 'Drupal\\example\\ExampleClass';
 1225 }
 1226 
 1227 /**
 1228  * Modify the list of available views sort handler plugins.
 1229  *
 1230  * This hook may be used to modify handler properties after they have been
 1231  * specified by other modules.
 1232  *
 1233  * @param array $plugins
 1234  *   An array of all the existing handler definitions, passed by reference.
 1235  *
 1236  * @see \Drupal\views\Plugin\ViewsHandlerManager
 1237  */
 1238 function hook_views_plugins_sort_alter(array &$plugins) {
 1239   // Change the 'title' handler class.
 1240   $plugins['title']['class'] = 'Drupal\\example\\ExampleClass';
 1241 }
 1242 
 1243 /**
 1244  * @} End of "addtogroup hooks".
 1245  */
 1246 
 1247 /**
 1248  * @}
 1249  */