system.api.php 130 KB
Newer Older
1 2 3 4 5 6 7
<?php

/**
 * @file
 * Hooks provided by Drupal core and the System module.
 */

8 9
use Drupal\Core\Utility\UpdateException;

10 11 12 13 14
/**
 * @addtogroup hooks
 * @{
 */

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
/**
 * Defines one or more hooks that are exposed by a module.
 *
 * Normally hooks do not need to be explicitly defined. However, by declaring a
 * hook explicitly, a module may define a "group" for it. Modules that implement
 * a hook may then place their implementation in either $module.module or in
 * $module.$group.inc. If the hook is located in $module.$group.inc, then that
 * file will be automatically loaded when needed.
 * In general, hooks that are rarely invoked and/or are very large should be
 * placed in a separate include file, while hooks that are very short or very
 * frequently called should be left in the main module file so that they are
 * always available.
 *
 * @return
 *   An associative array whose keys are hook names and whose values are an
 *   associative array containing:
 *   - group: A string defining the group to which the hook belongs. The module
 *     system will determine whether a file with the name $module.$group.inc
 *     exists, and automatically load it when required.
 *
 * See system_hook_info() for all hook groups defined by Drupal core.
36 37
 *
 * @see hook_hook_info_alter().
38 39 40 41 42 43 44 45 46 47 48
 */
function hook_hook_info() {
  $hooks['token_info'] = array(
    'group' => 'tokens',
  );
  $hooks['tokens'] = array(
    'group' => 'tokens',
  );
  return $hooks;
}

49 50 51
/**
 * Define administrative paths.
 *
52
 * Modules may specify whether or not the routing paths they define are
53
 * to be considered administrative. Other modules may use this information to
54
 * display those pages differently.
55 56
 *
 * To change the administrative status of menu items defined in another module's
57
 * routing paths, modules should implement hook_admin_paths_alter().
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
 *
 * @return
 *   An associative array. For each item, the key is the path in question, in
 *   a format acceptable to drupal_match_path(). The value for each item should
 *   be TRUE (for paths considered administrative) or FALSE (for non-
 *   administrative paths).
 *
 * @see drupal_match_path()
 * @see hook_admin_paths_alter()
 */
function hook_admin_paths() {
  $paths = array(
    'mymodule/*/add' => TRUE,
    'mymodule/*/edit' => TRUE,
  );
  return $paths;
}

/**
 * Redefine administrative paths defined by other modules.
 *
 * @param $paths
 *   An associative array of administrative paths, as defined by implementations
 *   of hook_admin_paths().
 *
 * @see hook_admin_paths()
 */
function hook_admin_paths_alter(&$paths) {
  // Treat all user pages as administrative.
  $paths['user'] = TRUE;
  $paths['user/*'] = TRUE;
  // Treat the forum topic node form as a non-administrative page.
  $paths['node/add/forum'] = FALSE;
}

93 94 95
/**
 * Perform periodic actions.
 *
96 97 98 99 100
 * Modules that require some commands to be executed periodically can
 * implement hook_cron(). The engine will then call the hook whenever a cron
 * run happens, as defined by the administrator. Typical tasks managed by
 * hook_cron() are database maintenance, backups, recalculation of settings
 * or parameters, automated mailing, and retrieving remote data.
101
 *
102 103
 * Short-running or non-resource-intensive tasks can be executed directly in
 * the hook_cron() implementation.
104
 *
105 106 107
 * Long-running tasks and tasks that could time out, such as retrieving remote
 * data, sending email, and intensive file tasks, should use the queue API
 * instead of executing the tasks directly. To do this, first define one or
108
 * more queues via hook_queue_info(). Then, add items that need to be
109
 * processed to the defined queues.
110 111
 */
function hook_cron() {
112 113
  // Short-running operation example, not using a queue:
  // Delete all expired records since the last cron run.
114
  $expires = \Drupal::state()->get('mymodule.cron_last_run', REQUEST_TIME);
115 116 117
  db_delete('mymodule_table')
    ->condition('expires', $expires, '>=')
    ->execute();
118
  \Drupal::state()->set('mymodule.cron_last_run', REQUEST_TIME);
119

120 121
  // Long-running operation example, leveraging a queue:
  // Fetch feeds from other sites.
122
  $result = db_query('SELECT * FROM {aggregator_feed} WHERE checked + refresh < :time AND refresh <> :never', array(
123 124 125
    ':time' => REQUEST_TIME,
    ':never' => AGGREGATOR_CLEAR_NEVER,
  ));
126
  $queue = \Drupal::queue('aggregator_feeds');
127 128
  foreach ($result as $feed) {
    $queue->createItem($feed);
129 130 131
  }
}

132 133 134 135 136 137 138 139 140 141 142 143
/**
 * Alter available data types for typed data wrappers.
 *
 * @param array $data_types
 *   An array of data type information.
 *
 * @see hook_data_type_info()
 */
function hook_data_type_info_alter(&$data_types) {
  $data_types['email']['class'] = '\Drupal\mymodule\Type\Email';
}

144 145 146 147 148 149
/**
 * Declare queues holding items that need to be run periodically.
 *
 * While there can be only one hook_cron() process running at the same time,
 * there can be any number of processes defined here running. Because of
 * this, long running tasks are much better suited for this API. Items queued
150 151 152
 * in hook_cron() might be processed in the same cron run if there are not many
 * items in the queue, otherwise it might take several requests, which can be
 * run in parallel.
153
 *
154 155 156 157
 * You can create queues, add items to them, claim them, etc without declaring
 * the queue in this hook if you want, however, you need to take care of
 * processing the items in the queue in that case.
 *
158 159 160
 * @return
 *   An associative array where the key is the queue name and the value is
 *   again an associative array. Possible keys are:
161
 *   - 'worker callback': A PHP callable to call. It will be called
162
 *     with one argument, the item created via
163
 *     \Drupal\Core\Queue\QueueInterface::createItem().
164 165 166 167 168
 *   - 'cron': (optional) An associative array containing the optional key:
 *     - 'time': (optional) How much time Drupal cron should spend on calling
 *       this worker in seconds. Defaults to 15.
 *     If the cron key is not defined, the queue will not be processed by cron,
 *     and must be processed by other means.
169 170
 *
 * @see hook_cron()
171
 * @see hook_queue_info_alter()
172
 */
173
function hook_queue_info() {
174
  $queues['aggregator_feeds'] = array(
175
    'title' => t('Aggregator refresh'),
176
    'worker callback' => array('Drupal\my_module\MyClass', 'aggregatorRefresh'),
177 178 179 180
    // Only needed if this queue should be processed by cron.
    'cron' => array(
      'time' => 60,
    ),
181 182 183 184
  );
  return $queues;
}

185 186 187
/**
 * Alter cron queue information before cron runs.
 *
188
 * Called by \Drupal\Core\Cron to allow modules to alter cron queue settings
189 190 191 192 193
 * before any jobs are processesed.
 *
 * @param array $queues
 *   An array of cron queue information.
 *
194
 * @see hook_queue_info()
195
 * @see \Drupal\Core\Cron
196
 */
197
function hook_queue_info_alter(&$queues) {
198 199
  // This site has many feeds so let's spend 90 seconds on each cron run
  // updating feeds instead of the default 60.
200
  $queues['aggregator_feeds']['cron']['time'] = 90;
201 202
}

203
/**
204
 * Allows modules to declare their own Form API element types and specify their
205 206 207 208
 * default values.
 *
 * This hook allows modules to declare their own form element types and to
 * specify their default values. The values returned by this hook will be
209
 * merged with the elements returned by form constructor implementations and so
210 211 212 213 214 215 216
 * can return defaults for any Form APIs keys in addition to those explicitly
 * mentioned below.
 *
 * Each of the form element types defined by this hook is assumed to have
 * a matching theme function, e.g. theme_elementtype(), which should be
 * registered with hook_theme() as normal.
 *
217
 * For more information about custom element types see the explanation at
218 219 220 221 222 223 224 225
 * http://drupal.org/node/169815.
 *
 * @return
 *  An associative array describing the element types being defined. The array
 *  contains a sub-array for each element type, with the machine-readable type
 *  name as the key. Each sub-array has a number of possible attributes:
 *  - "#input": boolean indicating whether or not this element carries a value
 *    (even if it's hidden).
226 227
 *  - "#process": array of callback functions taking $element, $form_state,
 *    and $complete_form.
228
 *  - "#after_build": array of callables taking $element and $form_state.
229 230 231
 *  - "#validate": array of callback functions taking $form and $form_state.
 *  - "#element_validate": array of callback functions taking $element and
 *    $form_state.
232 233
 *  - "#pre_render": array of callables taking $element.
 *  - "#post_render": array of callables taking $children and $element.
234
 *  - "#submit": array of callback functions taking $form and $form_state.
235 236
 *  - "#title_display": optional string indicating if and how #title should be
 *    displayed, see theme_form_element() and theme_form_element_label().
237 238 239
 *
 * @see hook_element_info_alter()
 * @see system_element_info()
240
 */
241 242 243 244 245
function hook_element_info() {
  $types['filter_format'] = array(
    '#input' => TRUE,
  );
  return $types;
246 247
}

248 249 250 251 252 253
/**
 * Alter the element type information returned from modules.
 *
 * A module may implement this hook in order to alter the element type defaults
 * defined by a module.
 *
254
 * @param $type
255
 *   All element type defaults as collected by hook_element_info().
256
 *
257
 * @see hook_element_info()
258 259 260 261 262 263 264 265
 */
function hook_element_info_alter(&$type) {
  // Decrease the default size of textfields.
  if (isset($type['textfield']['#size'])) {
    $type['textfield']['#size'] = 40;
  }
}

266 267 268 269 270 271
/**
 * Perform necessary alterations to the JavaScript before it is presented on
 * the page.
 *
 * @param $javascript
 *   An array of all JavaScript being presented on the page.
272
 *
273
 * @see _drupal_add_js()
274 275 276 277 278
 * @see drupal_get_js()
 * @see drupal_js_defaults()
 */
function hook_js_alter(&$javascript) {
  // Swap out jQuery to use an updated version of the library.
279
  $javascript['core/assets/vendor/jquery/jquery.js']['data'] = drupal_get_path('module', 'jquery_update') . '/jquery.js';
280 281
}

282 283 284 285 286 287 288 289 290 291 292 293 294 295
/**
 * Registers JavaScript/CSS libraries associated with a module.
 *
 * Modules implementing this return an array of arrays. The key to each
 * sub-array is the machine readable name of the library. Each library may
 * contain the following items:
 *
 * - 'title': The human readable name of the library.
 * - 'website': The URL of the library's web site.
 * - 'version': A string specifying the version of the library; intentionally
 *   not a float because a version like "1.2.3" is not a valid float. Use PHP's
 *   version_compare() to compare different versions.
 * - 'js': An array of JavaScript elements; each element's key is used as $data
 *   argument, each element's value is used as $options array for
296
 *   _drupal_add_js(). To add library-specific (not module-specific) JavaScript
297 298 299
 *   settings, the key may be skipped, the value must specify
 *   'type' => 'setting', and the actual settings must be contained in a 'data'
 *   element of the value.
300
 * - 'css': Like 'js', an array of CSS elements passed to _drupal_add_css().
301
 * - 'dependencies': An array of libraries that are required for a library. Each
302 303 304
 *   element is an array listing the module and name of another library. Note
 *   that all dependencies for each dependent library will also be added when
 *   this library is added.
305 306 307 308 309 310 311 312
 *
 * Registered information for a library should contain re-usable data only.
 * Module- or implementation-specific data and integration logic should be added
 * separately.
 *
 * @return
 *   An array defining libraries associated with a module.
 *
313
 * @see system_library_info()
314
 * @see drupal_add_library()
315 316
 * @see drupal_get_library()
 */
317
function hook_library_info() {
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
  // Library One.
  $libraries['library-1'] = array(
    'title' => 'Library One',
    'website' => 'http://example.com/library-1',
    'version' => '1.2',
    'js' => array(
      drupal_get_path('module', 'my_module') . '/library-1.js' => array(),
    ),
    'css' => array(
      drupal_get_path('module', 'my_module') . '/library-2.css' => array(
        'type' => 'file',
        'media' => 'screen',
      ),
    ),
  );
  // Library Two.
  $libraries['library-2'] = array(
    'title' => 'Library Two',
    'website' => 'http://example.com/library-2',
    'version' => '3.1-beta1',
    'js' => array(
      // JavaScript settings may use the 'data' key.
      array(
        'type' => 'setting',
        'data' => array('library2' => TRUE),
      ),
    ),
    'dependencies' => array(
      // Require jQuery UI core by System module.
347
      array('system', 'jquery.ui.core'),
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
      // Require our other library.
      array('my_module', 'library-1'),
      // Require another library.
      array('other_module', 'library-3'),
    ),
  );
  return $libraries;
}

/**
 * Alters the JavaScript/CSS library registry.
 *
 * Allows certain, contributed modules to update libraries to newer versions
 * while ensuring backwards compatibility. In general, such manipulations should
 * only be done by designated modules, since most modules that integrate with a
 * certain library also depend on the API of a certain library version.
 *
 * @param $libraries
 *   The JavaScript/CSS libraries provided by $module. Keyed by internal library
 *   name and passed by reference.
 * @param $module
 *   The name of the module that registered the libraries.
 *
371
 * @see hook_library_info()
372
 */
373
function hook_library_info_alter(&$libraries, $module) {
374 375 376 377 378 379 380 381 382 383 384 385 386
  // Update Farbtastic to version 2.0.
  if ($module == 'system' && isset($libraries['farbtastic'])) {
    // Verify existing version is older than the one we are updating to.
    if (version_compare($libraries['farbtastic']['version'], '2.0', '<')) {
      // Update the existing Farbtastic to version 2.0.
      $libraries['farbtastic']['version'] = '2.0';
      $libraries['farbtastic']['js'] = array(
        drupal_get_path('module', 'farbtastic_update') . '/farbtastic-2.0.js' => array(),
      );
    }
  }
}

387 388 389 390 391
/**
 * Alter CSS files before they are output on the page.
 *
 * @param $css
 *   An array of all CSS items (files and inline CSS) being requested on the page.
392
 *
393
 * @see _drupal_add_css()
394 395 396 397 398 399 400
 * @see drupal_get_css()
 */
function hook_css_alter(&$css) {
  // Remove defaults.css file.
  unset($css[drupal_get_path('module', 'system') . '/defaults.css']);
}

401
/**
402
 * Alter the commands that are sent to the user through the Ajax framework.
403 404 405
 *
 * @param $commands
 *   An array of all commands that will be sent to the user.
406
 *
407 408 409 410
 * @see ajax_render()
 */
function hook_ajax_render_alter($commands) {
  // Inject any new status messages into the content area.
411 412
  $status_messages = array('#theme' => 'status_messages');
  $commands[] = ajax_command_prepend('#block-system-main .content', drupal_render($status_messages));
413 414
}

415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437
/**
 * Add elements to a page before it is rendered.
 *
 * Use this hook when you want to add elements at the page level. For your
 * additions to be printed, they have to be placed below a top level array key
 * of the $page array that has the name of a region of the active theme.
 *
 * By default, valid region keys are 'page_top', 'header', 'sidebar_first',
 * 'content', 'sidebar_second' and 'page_bottom'. To get a list of all regions
 * of the active theme, use system_region_list($theme). Note that $theme is a
 * global variable.
 *
 * If you want to alter the elements added by other modules or if your module
 * depends on the elements of other modules, use hook_page_alter() instead which
 * runs after this hook.
 *
 * @param $page
 *   Nested array of renderable elements that make up the page.
 *
 * @see hook_page_alter()
 * @see drupal_render_page()
 */
function hook_page_build(&$page) {
438 439 440 441 442 443 444 445 446 447 448 449 450
  $path = drupal_get_path('module', 'foo');
  // Add JavaScript/CSS assets to all pages.
  // @see drupal_process_attached()
  $page['#attached']['js'][$path . '/foo.css'] = array('every_page' => TRUE);
  $page['#attached']['css'][$path . '/foo.base.css'] = array('every_page' => TRUE);
  $page['#attached']['css'][$path . '/foo.theme.css'] = array('every_page' => TRUE);

  // Add a special CSS file to a certain page only.
  if (drupal_is_front_page()) {
    $page['#attached']['css'][] = $path . '/foo.front.css';
  }

  // Append a standard disclaimer to the content region on a node detail page.
451 452 453 454 455 456 457 458
  if (menu_get_object('node', 1)) {
    $page['content']['disclaimer'] = array(
      '#markup' => t('Acme, Inc. is not responsible for the contents of this sample code.'),
      '#weight' => 25,
    );
  }
}

459 460 461 462 463
/**
 * Alter a menu router item right after it has been retrieved from the database or cache.
 *
 * This hook is invoked by menu_get_item() and allows for run-time alteration of router
 * information (page_callback, title, and so on) before it is translated and checked for
464
 * access. The passed-in $router_item is statically cached for the current request, so this
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
 * hook is only invoked once for any router item that is retrieved via menu_get_item().
 *
 * Usually, modules will only want to inspect the router item and conditionally
 * perform other actions (such as preparing a state for the current request).
 * Note that this hook is invoked for any router item that is retrieved by
 * menu_get_item(), which may or may not be called on the path itself, so implementations
 * should check the $path parameter if the alteration should fire for the current request
 * only.
 *
 * @param $router_item
 *   The menu router item for $path.
 * @param $path
 *   The originally passed path, for which $router_item is responsible.
 * @param $original_map
 *   The path argument map, as contained in $path.
 *
 * @see menu_get_item()
 */
function hook_menu_get_item_alter(&$router_item, $path, $original_map) {
  // When retrieving the router item for the current path...
485
  if ($path == current_path()) {
486 487 488 489 490
    // ...call a function that prepares something for this request.
    mymodule_prepare_something();
  }
}

491
/**
492 493 494 495
 * Define links for menus.
 *
 * @section sec_menu_link Creating Menu Items
 * Menu item example of type MENU_NORMAL_ITEM:
496 497
 * @code
 * // Make "Foo settings" appear on the admin Config page
498
 * $items['admin/config/system/foo'] = array(
499 500
 *   'title' => 'Foo settings',
 *   'type' => MENU_NORMAL_ITEM,
501
 *   'route_name' => 'foo.settings'
502 503 504
 * );
 * @endcode
 *
505 506 507 508
 * @todo The section that used to be here about path argument substitution has
 *   been removed, but is still referred to in the return section. It needs to
 *   be added back in, or a corrected version of it.
 *
509 510 511 512 513 514 515 516 517 518
 * @return
 *   An array of menu items. Each menu item has a key corresponding to the
 *   Drupal path being registered. The corresponding array value is an
 *   associative array that may contain the following key-value pairs:
 *   - "title": Required. The untranslated title of the menu item.
 *   - "title callback": Function to generate the title; defaults to t().
 *     If you require only the raw string to be output, set this to FALSE.
 *   - "title arguments": Arguments to send to t() or your custom callback,
 *     with path component substitution as described above.
 *   - "description": The untranslated description of the menu item.
519 520 521 522
 *   - description callback: Function to generate the description; defaults to
 *     t(). If you require only the raw string to be output, set this to FALSE.
 *   - description arguments: Arguments to send to t() or your custom callback,
 *     with path component substitution as described above.
523 524 525 526
 *   - "weight": An integer that determines the relative position of items in
 *     the menu; higher-weighted items sink. Defaults to 0. Menu items with the
 *     same weight are ordered alphabetically.
 *   - "menu_name": Optional. Set this to a custom menu if you don't want your
527
 *     item to be placed in the default Tools menu.
528 529 530 531
 *   - "expanded": Optional. If set to TRUE, and if a menu link is provided for
 *     this menu item (as a result of other properties), then the menu link is
 *     always expanded, equivalent to its 'always expanded' checkbox being set
 *     in the UI.
532 533 534 535 536 537 538 539 540
 *   - "position": Position of the block ('left' or 'right') on the system
 *     administration page for this item.
 *   - "type": A bitmask of flags describing properties of the menu item.
 *     Many shortcut bitmasks are provided as constants in menu.inc:
 *     - MENU_NORMAL_ITEM: Normal menu items show up in the menu tree and can be
 *       moved/hidden by the administrator.
 *     - MENU_SUGGESTED_ITEM: Modules may "suggest" menu items that the
 *       administrator may enable.
 *     If the "type" element is omitted, MENU_NORMAL_ITEM is assumed.
541
 *   - "options": An array of options to be passed to l() when generating a link
542
 *     from this menu item.
543 544 545 546
 *
 * For a detailed usage example, see page_example.module.
 * For comprehensive documentation on the menu system, see
 * http://drupal.org/node/102338.
547 548
 *
 * @see menu
549 550
 */
function hook_menu() {
551 552
  $items['example'] = array(
    'title' => 'Example Page',
553
    'route_name' => 'example.page',
554
  );
555 556
  $items['example/feed'] = array(
    'title' => 'Example RSS feed',
557
    'route_name' => 'example.feed',
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
  );

  return $items;
}

/**
 * Alter the data being saved to the {menu_router} table after hook_menu is invoked.
 *
 * This hook is invoked by menu_router_build(). The menu definitions are passed
 * in by reference. Each element of the $items array is one item returned
 * by a module from hook_menu. Additional items may be added, or existing items
 * altered.
 *
 * @param $items
 *   Associative array of menu router definitions returned from hook_menu().
 */
function hook_menu_alter(&$items) {
  // Example - disable the page at node/add
  $items['node/add']['access callback'] = FALSE;
}

/**
 * Alter tabs and actions displayed on the page before they are rendered.
 *
 * This hook is invoked by menu_local_tasks(). The system-determined tabs and
583
 * actions are passed in by reference. Additional tabs or actions may be added.
584 585 586 587 588 589
 *
 * Each tab or action is an associative array containing:
 * - #theme: The theme function to use to render.
 * - #link: An associative array containing:
 *   - title: The localized title of the link.
 *   - href: The system path to link to.
590
 *   - localized_options: An array of options to pass to l().
591
 * - #weight: The link's weight compared to other links.
592 593
 * - #active: Whether the link should be marked as 'active'.
 *
594
 * @param array $data
595
 *   An associative array containing:
596 597 598 599
 *   - actions: A list of of actions keyed by their href, each one being an
 *     associative array as described above.
 *   - tabs: A list of (up to 2) tab levels that contain a list of of tabs keyed
 *     by their href, each one being an associative array as described above.
600 601
 * @param string $route_name
 *   The route name of the page.
602
 */
603
function hook_menu_local_tasks(&$data, $route_name) {
604
  // Add an action linking to node/add to all pages.
605 606
  $data['actions']['node/add'] = array(
    '#theme' => 'menu_local_action',
607 608 609 610 611 612 613 614 615 616 617 618
    '#link' => array(
      'title' => t('Add new content'),
      'href' => 'node/add',
      'localized_options' => array(
        'attributes' => array(
          'title' => t('Add new content'),
        ),
      ),
    ),
  );

  // Add a tab linking to node/add to all pages.
619
  $data['tabs'][0]['node/add'] = array(
620 621 622 623 624 625 626 627 628 629 630 631 632
    '#theme' => 'menu_local_task',
    '#link' => array(
      'title' => t('Example tab'),
      'href' => 'node/add',
      'localized_options' => array(
        'attributes' => array(
          'title' => t('Add new content'),
        ),
      ),
    ),
  );
}

633 634 635 636 637 638 639 640 641
/**
 * Alter tabs and actions displayed on the page before they are rendered.
 *
 * This hook is invoked by menu_local_tasks(). The system-determined tabs and
 * actions are passed in by reference. Existing tabs or actions may be altered.
 *
 * @param array $data
 *   An associative array containing tabs and actions. See
 *   hook_menu_local_tasks() for details.
642 643
 * @param string $route_name
 *   The route name of the page.
644 645 646
 *
 * @see hook_menu_local_tasks()
 */
647
function hook_menu_local_tasks_alter(&$data, $route_name) {
648 649
}

650 651 652 653 654 655 656 657 658 659 660 661
/**
 * Alter local actions plugins.
 *
 * @param array $local_actions
 *   The array of local action plugin definitions, keyed by plugin ID.
 *
 * @see \Drupal\Core\Menu\LocalActionInterface
 * @see \Drupal\Core\Menu\LocalActionManager
 */
function hook_menu_local_actions_alter(&$local_actions) {
}

662 663 664 665 666 667 668 669 670
/**
 * Alter local tasks plugins.
 *
 * @param array $local_tasks
 *   The array of local tasks plugin definitions, keyed by plugin ID.
 *
 * @see \Drupal\Core\Menu\LocalTaskInterface
 * @see \Drupal\Core\Menu\LocalTaskManager
 */
671
function hook_local_tasks_alter(&$local_tasks) {
672 673 674 675
  // Remove a specified local task plugin.
  unset($local_tasks['example_plugin_id']);
}

676 677 678
/**
 * Alter contextual links before they are rendered.
 *
679 680 681 682
 * This hook is invoked by
 * \Drupal\Core\Menu\ContextualLinkManager::getContextualLinkPluginsByGroup().
 * The system-determined contextual links are passed in by reference. Additional
 * links may be added and existing links can be altered.
683
 *
684
 * Each contextual link contains the following entries:
685
 * - title: The localized title of the link.
686 687
 * - route_name: The route name of the link.
 * - route_parameters: The route parameters of the link.
688
 * - localized_options: An array of options to pass to url().
689
 * - (optional) weight: The weight of the link, which is used to sort the links.
690
 *
691 692 693
 *
 * @param array $links
 *   An associative array containing contextual links for the given $group,
694 695 696
 *   as described above. The array keys are used to build CSS class names for
 *   contextual links and must therefore be unique for each set of contextual
 *   links.
697 698 699 700 701 702 703 704 705 706
 * @param string $group
 *   The group of contextual links being rendered.
 * @param array $route_parameters.
 *   The route parameters passed to each route_name of the contextual links.
 *   For example:
 *   @code
 *   array('node' => $node->id())
 *   @endcode
 *
 * @see \Drupal\Core\Menu\ContextualLinkManager
707
 */
708 709 710 711 712 713
function hook_contextual_links_alter(array &$links, $group, array $route_parameters) {
  if ($group == 'menu') {
    // Dynamically use the menu name for the title of the menu_edit contextual
    // link.
    $menu = \Drupal::entityManager()->getStorageController('menu')->load($route_parameters['menu']);
    $links['menu_edit']['title'] = t('Edit menu: !label', array('!label' => $menu->label()));
714 715 716
  }
}

717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733
/**
 * Alter the plugin definition of contextual links.
 *
 * @param array $contextual_links
 *   An array of contextual_links plugin definitions, keyed by contextual link
 *   ID. Each entry contains the following keys:
 *     - title: The displayed title of the link
 *     - route_name: The route_name of the contextual link to be displayed
 *     - group: The group under which the contextual links should be added to.
 *       Possible values are e.g. 'node' or 'menu'.
 *
 * @see \Drupal\Core\Menu\ContextualLinkManager
 */
function hook_contextual_links_plugins_alter(array &$contextual_links) {
  $contextual_links['menu_edit']['title'] = 'Edit the menu';
}

734 735 736
/**
 * Perform alterations before a page is rendered.
 *
737 738 739 740 741
 * Use this hook when you want to remove or alter elements at the page
 * level, or add elements at the page level that depend on an other module's
 * elements (this hook runs after hook_page_build().
 *
 * If you are making changes to entities such as forms, menus, or user
742 743 744 745 746
 * profiles, use those objects' native alter hooks instead (hook_form_alter(),
 * for example).
 *
 * The $page array contains top level elements for each block region:
 * @code
747
 *   $page['page_top']
748
 *   $page['header']
749
 *   $page['sidebar_first']
750
 *   $page['content']
751
 *   $page['sidebar_second']
752
 *   $page['page_bottom']
753 754 755 756 757 758 759
 * @endcode
 *
 * The 'content' element contains the main content of the current page, and its
 * structure will vary depending on what module is responsible for building the
 * page. Some legacy modules may not return structured content at all: their
 * pre-rendered markup will be located in $page['content']['main']['#markup'].
 *
760
 * Pages built by Drupal's core Node module use a standard structure:
761 762 763
 *
 * @code
 *   // Node body.
764
 *   $page['content']['system_main']['nodes'][$nid]['body']
765
 *   // Array of links attached to the node (add comments, read more).
766
 *   $page['content']['system_main']['nodes'][$nid]['links']
767
 *   // The node entity itself.
768
 *   $page['content']['system_main']['nodes'][$nid]['#node']
769
 *   // The results pager.
770
 *   $page['content']['system_main']['pager']
771
 * @endcode
772 773 774
 *
 * Blocks may be referenced by their module/delta pair within a region:
 * @code
775
 *   // The login block in the first sidebar region.
776
 *   $page['sidebar_first']['user_login']['#block'];
777 778 779 780 781
 * @endcode
 *
 * @param $page
 *   Nested array of renderable elements that make up the page.
 *
782
 * @see hook_page_build()
783 784
 * @see drupal_render_page()
 */
785 786 787 788 789 790
function hook_page_alter(&$page) {
  // Add help text to the user login block.
  $page['sidebar_first']['user_login']['help'] = array(
    '#weight' => -10,
    '#markup' => t('To post comments or add new content, you first have to log in.'),
  );
791 792
}

793 794 795 796
/**
 * Perform alterations before a form is rendered.
 *
 * One popular use of this hook is to add form elements to the node form. When
797
 * altering a node form, the node entity can be retrieved by invoking
798
 * $form_state['controller']->getEntity().
799
 *
800 801 802 803 804 805 806 807 808 809 810 811 812 813 814
 * In addition to hook_form_alter(), which is called for all forms, there are
 * two more specific form hooks available. The first,
 * hook_form_BASE_FORM_ID_alter(), allows targeting of a form/forms via a base
 * form (if one exists). The second, hook_form_FORM_ID_alter(), can be used to
 * target a specific form directly.
 *
 * The call order is as follows: all existing form alter functions are called
 * for module A, then all for module B, etc., followed by all for any base
 * theme(s), and finally for the theme itself. The module order is determined
 * by system weight, then by module name.
 *
 * Within each module, form alter hooks are called in the following order:
 * first, hook_form_alter(); second, hook_form_BASE_FORM_ID_alter(); third,
 * hook_form_FORM_ID_alter(). So, for each module, the more general hooks are
 * called first followed by the more specific.
815
 *
816 817 818
 * @param $form
 *   Nested array of form elements that comprise the form.
 * @param $form_state
819 820 821
 *   A keyed array containing the current state of the form. The arguments
 *   that drupal_get_form() was originally called with are available in the
 *   array $form_state['build_info']['args'].
822 823 824
 * @param $form_id
 *   String representing the name of the form itself. Typically this is the
 *   name of the function that generated the form.
825
 *
826
 * @see hook_form_BASE_FORM_ID_alter()
827
 * @see hook_form_FORM_ID_alter()
828
 * @see forms_api_reference.html
829
 */
830
function hook_form_alter(&$form, &$form_state, $form_id) {
831
  if (isset($form['type']) && $form['type']['#value'] . '_node_settings' == $form_id) {
832
    $upload_enabled_types = \Drupal::config('mymodule.settings')->get('upload_enabled_types');
833 834 835
    $form['workflow']['upload_' . $form['type']['#value']] = array(
      '#type' => 'radios',
      '#title' => t('Attachments'),
836
      '#default_value' => in_array($form['type']['#value'], $upload_enabled_types) ? 1 : 0,
837 838
      '#options' => array(t('Disabled'), t('Enabled')),
    );
839 840
    // Add a custom submit handler to save the array of types back to the config file.
    $form['actions']['submit']['#submit'][] = 'mymodule_upload_enabled_types_submit';
841 842 843 844 845 846 847 848 849 850
  }
}

/**
 * Provide a form-specific alteration instead of the global hook_form_alter().
 *
 * Modules can implement hook_form_FORM_ID_alter() to modify a specific form,
 * rather than implementing hook_form_alter() and checking the form ID, or
 * using long switch statements to alter multiple forms.
 *
851 852 853 854
 * Form alter hooks are called in the following order: hook_form_alter(),
 * hook_form_BASE_FORM_ID_alter(), hook_form_FORM_ID_alter(). See
 * hook_form_alter() for more details.
 *
855 856 857
 * @param $form
 *   Nested array of form elements that comprise the form.
 * @param $form_state
858 859 860
 *   A keyed array containing the current state of the form. The arguments
 *   that drupal_get_form() was originally called with are available in the
 *   array $form_state['build_info']['args'].
861 862 863
 * @param $form_id
 *   String representing the name of the form itself. Typically this is the
 *   name of the function that generated the form.
864
 *
865
 * @see hook_form_alter()
866
 * @see hook_form_BASE_FORM_ID_alter()
867
 * @see drupal_prepare_form()
868
 * @see forms_api_reference.html
869
 */
870
function hook_form_FORM_ID_alter(&$form, &$form_state, $form_id) {
871
  // Modification for the form with the given form ID goes here. For example, if
872
  // FORM_ID is "user_register_form" this code would run only on the user
873 874 875 876 877 878 879 880 881 882
  // registration form.

  // Add a checkbox to registration form about agreeing to terms of use.
  $form['terms_of_use'] = array(
    '#type' => 'checkbox',
    '#title' => t("I agree with the website's terms and conditions."),
    '#required' => TRUE,
  );
}

883
/**
884 885 886 887 888 889
 * Provide a form-specific alteration for shared ('base') forms.
 *
 * By default, when drupal_get_form() is called, Drupal looks for a function
 * with the same name as the form ID, and uses that function to build the form.
 * In contrast, base forms allow multiple form IDs to be mapped to a single base
 * (also called 'factory') form function.
890 891
 *
 * Modules can implement hook_form_BASE_FORM_ID_alter() to modify a specific
892 893 894 895 896 897
 * base form, rather than implementing hook_form_alter() and checking for
 * conditions that would identify the shared form constructor.
 *
 * To identify the base form ID for a particular form (or to determine whether
 * one exists) check the $form_state. The base form ID is stored under
 * $form_state['build_info']['base_form_id'].
898
 *
899 900
 * See hook_forms() for more information on how to implement base forms in
 * Drupal.
901
 *
902 903 904
 * Form alter hooks are called in the following order: hook_form_alter(),
 * hook_form_BASE_FORM_ID_alter(), hook_form_FORM_ID_alter(). See
 * hook_form_alter() for more details.
905 906 907 908 909 910 911 912 913
 *
 * @param $form
 *   Nested array of form elements that comprise the form.
 * @param $form_state
 *   A keyed array containing the current state of the form.
 * @param $form_id
 *   String representing the name of the form itself. Typically this is the
 *   name of the function that generated the form.
 *
914
 * @see hook_form_alter()
915 916
 * @see hook_form_FORM_ID_alter()
 * @see drupal_prepare_form()
917
 * @see hook_forms()
918 919 920 921 922 923 924 925 926 927 928 929 930 931
 */
function hook_form_BASE_FORM_ID_alter(&$form, &$form_state, $form_id) {
  // Modification for the form with the given BASE_FORM_ID goes here. For
  // example, if BASE_FORM_ID is "node_form", this code would run on every
  // node form, regardless of node type.

  // Add a checkbox to the node form about agreeing to terms of use.
  $form['terms_of_use'] = array(
    '#type' => 'checkbox',
    '#title' => t("I agree with the website's terms and conditions."),
    '#required' => TRUE,
  );
}

932
/**
933
 * Map form_ids to form builder functions.
934
 *
935 936
 * By default, when drupal_get_form() is called, the system will look for a
 * function with the same name as the form ID, and use that function to build
937 938 939 940 941 942 943 944 945 946 947 948
 * the form. If no such function is found, Drupal calls this hook. Modules
 * implementing this hook can then provide their own instructions for mapping
 * form IDs to constructor functions. As a result, you can easily map multiple
 * form IDs to a single form constructor (referred to as a 'base' form).
 *
 * Using a base form can help to avoid code duplication, by allowing many
 * similar forms to use the same code base. Another benefit is that it becomes
 * much easier for other modules to apply a general change to the group of
 * forms; hook_form_BASE_FORM_ID_alter() can be used to easily alter multiple
 * forms at once by directly targeting the shared base form.
 *
 * Two example use cases where base forms may be useful are given below.
949
 *
950 951 952 953
 * First, you can use this hook to tell the form system to use a different
 * function to build certain forms in your module; this is often used to define
 * a form "factory" function that is used to build several similar forms. In
 * this case, your hook implementation will likely ignore all of the input
954 955
 * arguments. See node_forms() for an example of this. Note, node_forms() is the
 * hook_forms() implementation; the base form itself is defined in node_form().
956
 *
957 958 959 960
 * Second, you could use this hook to define how to build a form with a
 * dynamically-generated form ID. In this case, you would need to verify that
 * the $form_id input matched your module's format for dynamically-generated
 * form IDs, and if so, act appropriately.
961
 *
962 963 964
 * @param $form_id
 *   The unique string identifying the desired form.
 * @param $args
965 966 967
 *   An array containing the original arguments provided to drupal_get_form()
 *   or drupal_form_submit(). These are always passed to the form builder and
 *   do not have to be specified manually in 'callback arguments'.
968
 *
969
 * @return
970 971
 *   An associative array whose keys define form_ids and whose values are an
 *   associative array defining the following keys:
972 973 974
 *   - callback: The name of the form builder function to invoke. This will be
 *     used for the base form ID, for example, to target a base form using
 *     hook_form_BASE_FORM_ID_alter().
975 976 977 978 979 980 981 982 983 984
 *   - callback arguments: (optional) Additional arguments to pass to the
 *     function defined in 'callback', which are prepended to $args.
 *   - wrapper_callback: (optional) The name of a form builder function to
 *     invoke before the form builder defined in 'callback' is invoked. This
 *     wrapper callback may prepopulate the $form array with form elements,
 *     which will then be already contained in the $form that is passed on to
 *     the form builder defined in 'callback'. For example, a wrapper callback
 *     could setup wizard-alike form buttons that are the same for a variety of
 *     forms that belong to the wizard, which all share the same wrapper
 *     callback.
985
 */
986
function hook_forms($form_id, $args) {
987 988
  // Simply reroute the (non-existing) $form_id 'mymodule_first_form' to
  // 'mymodule_main_form'.
989
  $forms['mymodule_first_form'] = array(
990
    'callback' => 'mymodule_main_form',
991
  );
992 993 994

  // Reroute the $form_id and prepend an additional argument that gets passed to
  // the 'mymodule_main_form' form builder function.
995
  $forms['mymodule_second_form'] = array(
996 997 998 999 1000 1001 1002 1003 1004 1005
    'callback' => 'mymodule_main_form',
    'callback arguments' => array('some parameter'),
  );

  // Reroute the $form_id, but invoke the form builder function
  // 'mymodule_main_form_wrapper' first, so we can prepopulate the $form array
  // that is passed to the actual form builder 'mymodule_main_form'.
  $forms['mymodule_wrapped_form'] = array(
    'callback' => 'mymodule_main_form',
    'wrapper_callback' => 'mymodule_main_form_wrapper',
1006
  );
1007

1008 1009 1010 1011
  return $forms;
}

/**
1012 1013 1014 1015 1016 1017 1018 1019
 * Alter an email message created with the drupal_mail() function.
 *
 * hook_mail_alter() allows modification of email messages created and sent
 * with drupal_mail(). Usage examples include adding and/or changing message
 * text, message fields, and message headers.
 *
 * Email messages sent using functions other than drupal_mail() will not
 * invoke hook_mail_alter(). For example, a contributed module directly
1020
 * calling the drupal_mail_system()->mail() or PHP mail() function
1021
 * will not invoke this hook. All core modules use drupal_mail() for
1022
 * messaging, it is best practice but not mandatory in contributed modules.
1023 1024
 *
 * @param $message
1025
 *   An array containing the message data. Keys in this array include:
1026
 *  - 'id':
1027
 *     The drupal_mail() id of the message. Look at module source code or
1028
 *     drupal_mail() for possible id values.
1029
 *  - 'to':
1030
 *     The address or addresses the message will be sent to. The
1031
 *     formatting of this string must comply with RFC 2822.
1032
 *  - 'from':
1033 1034
 *     The address the message will be marked as being from, which is
 *     either a custom address or the site-wide default email address.
1035 1036 1037 1038 1039
 *  - 'subject':
 *     Subject of the email to be sent. This must not contain any newline
 *     characters, or the email may not be sent properly.
 *  - 'body':
 *     An array of strings containing the message text. The message body is
1040
 *     created by concatenating the individual array strings into a single text
1041 1042
 *     string using "\n\n" as a separator.
 *  - 'headers':
1043
 *     Associative array containing mail headers, such as From, Sender,
1044
 *     MIME-Version, Content-Type, etc.
1045 1046 1047 1048 1049 1050
 *  - 'params':
 *     An array of optional parameters supplied by the caller of drupal_mail()
 *     that is used to build the message before hook_mail_alter() is invoked.
 *  - 'language':
 *     The language object used to build the message before hook_mail_alter()
 *     is invoked.
1051 1052
 *  - 'send':
 *     Set to FALSE to abort sending this email message.
1053 1054
 *
 * @see drupal_mail()
1055 1056
 */
function hook_mail_alter(&$message) {
1057
  if ($message['id'] == 'modulename_messagekey') {
1058 1059 1060 1061 1062 1063
    if (!example_notifications_optin($message['to'], $message['id'])) {
      // If the recipient has opted to not receive such messages, cancel
      // sending.
      $message['send'] = FALSE;
      return;
    }
1064
    $message['body'][] = "--\nMail sent out from " . \Drupal::config('system.site')->get('name');
1065 1066 1067
  }
}

1068 1069 1070
/**
 * Alter the registry of modules implementing a hook.
 *
1071
 * This hook is invoked during \Drupal::moduleHandler()->getImplementations().
1072 1073
 * A module may implement this hook in order to reorder the implementing
 * modules, which are otherwise ordered by the module's system weight.
1074
 *
1075 1076 1077 1078 1079 1080
 * Note that hooks invoked using drupal_alter() can have multiple variations
 * (such as hook_form_alter() and hook_form_FORM_ID_alter()). drupal_alter()
 * will call all such variants defined by a single module in turn. For the
 * purposes of hook_module_implements_alter(), these variants are treated as
 * a single hook. Thus, to ensure that your implementation of
 * hook_form_FORM_ID_alter() is called at the right time, you will have to
1081
 * change the order of hook_form_alter() implementation in
1082 1083
 * hook_module_implements_alter().
 *
1084
 * @param $implementations
1085 1086 1087 1088 1089 1090 1091 1092
 *   An array keyed by the module's name. The value of each item corresponds
 *   to a $group, which is usually FALSE, unless the implementation is in a
 *   file named $module.$group.inc.
 * @param $hook
 *   The name of the module hook being implemented.
 */
function hook_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'rdf_mapping') {
1093
    // Move my_module_rdf_mapping() to the end of the list.
1094
    // \Drupal::moduleHandler()->getImplementations()
1095 1096 1097 1098 1099 1100 1101 1102 1103
    // iterates through $implementations with a foreach loop which PHP iterates
    // in the order that the items were added, so to move an item to the end of
    // the array, we remove it and then add it.
    $group = $implementations['my_module'];
    unset($implementations['my_module']);
    $implementations['my_module'] = $group;
  }
}

1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126
/**
 * Perform alterations to the breadcrumb built by the BreadcrumbManager.
 *
 * @param array $breadcrumb
 *   An array of breadcrumb link a tags, returned by the breadcrumb manager
 *   build method, for example
 *   @code
 *     array('<a href="/">Home</a>');
 *   @endcode
 * @param array $attributes
 *   Attributes representing the current page, coming from
 *   \Drupal::request()->attributes.
 * @param array $context
 *   May include the following key:
 *   - builder: the instance of
 *     \Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface that constructed this
 *     breadcrumb, or NULL if no builder acted based on the current attributes.
 */
function hook_system_breadcrumb_alter(array &$breadcrumb, array $attributes, array $context) {
  // Add an item to the end of the breadcrumb.
  $breadcrumb[] = Drupal::l(t('Text'), 'example_route_name');
}

1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138
/**
 * Return additional themes provided by modules.
 *
 * Only use this hook for testing purposes. Use a hidden MYMODULE_test.module
 * to implement this hook. Testing themes should be hidden, too.
 *
 * This hook is invoked from _system_rebuild_theme_data() and allows modules to
 * register additional themes outside of the regular 'themes' directories of a
 * Drupal installation.
 *
 * @return
 *   An associative array. Each key is the system name of a theme and each value
1139
 *   is the corresponding path to the theme's .info.yml file.
1140 1141
 */
function hook_system_theme_info() {
1142
  $themes['mymodule_test_theme'] = drupal_get_path('module', 'mymodule') . '/mymodule_test_theme/mymodule_test_theme.info.yml';
1143 1144 1145
  return $themes;
}

1146
/**
1147
 * Alter the information parsed from module and theme .info.yml files
1148
 *
1149 1150
 * This hook is invoked in _system_rebuild_module_data() and in
 * _system_rebuild_theme_data(). A module may implement this hook in order to
1151
 * add to or alter the data generated by reading the .info.yml file with
1152
 * \Drupal\Core\Extension\InfoParser.
1153
 *
1154
 * @param $info
1155
 *   The .info.yml file contents, passed by reference so that it can be altered.
1156 1157 1158
 * @param $file
 *   Full information about the module or theme, including $file->name, and
 *   $file->filename
1159
 * @param $type
1160 1161
 *   Either 'module' or 'theme', depending on the type of .info.yml file that
 *   was passed.
1162
 */
1163
function hook_system_info_alter(&$info, $file, $type) {
1164
  // Only fill this in if the .info.yml file does not define a 'datestamp'.
1165 1166 1167 1168 1169 1170 1171 1172 1173
  if (empty($info['datestamp'])) {
    $info['datestamp'] = filemtime($file->filename);
  }
}

/**
 * Define user permissions.
 *
 * This hook can supply permissions that the module defines, so that they
1174
 * can be selected on the user permissions page and used to grant or restrict
1175 1176 1177 1178 1179
 * access to actions the module performs.
 *
 * Permissions are checked using user_access().
 *
 * For a detailed usage example, see page_example.module.
1180
 *
1181
 * @return
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194
 *   An array whose keys are permission names and whose corresponding values
 *   are arrays containing the following key-value pairs:
 *   - title: The human-readable name of the permission, to be shown on the
 *     permission administration page. This should be wrapped in the t()
 *     function so it can be translated.
 *   - description: (optional) A description of what the permission does. This
 *     should be wrapped in the t() function so it can be translated.
 *   - restrict access: (optional) A boolean which can be set to TRUE to
 *     indicate that site administrators should restrict access to this
 *     permission to trusted users. This should be used for permissions that
 *     have inherent security risks across a variety of potential use cases
 *     (for example, the "administer filters" and "bypass node access"
 *     permissions provided by Drupal core). When set to TRUE, a standard
1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207
 *     warning message defined in user_admin_permissions() and output via
 *     theme_user_permission_description() will be associated with the
 *     permission and displayed with it on the permission administration page.
 *     Defaults to FALSE.
 *   - warning: (optional) A translated warning message to display for this
 *     permission on the permission administration page. This warning overrides
 *     the automatic warning generated by 'restrict access' being set to TRUE.
 *     This should rarely be used, since it is important for all permissions to
 *     have a clear, consistent security warning that is the same across the
 *     site. Use the 'description' key instead to provide any information that
 *     is specific to the permission you are defining.
 *
 * @see theme_user_permission_description()
1208
 */
1209
function hook_permission() {
1210
  return array(
1211 1212 1213 1214
    'administer my module' =>  array(
      'title' => t('Administer my module'),
      'description' => t('Perform administration tasks for my module.'),
    ),
1215 1216 1217 1218
  );
}

/**
1219
 * Register a module or theme's theme implementations.
1220
 *
1221 1222 1223 1224 1225 1226
 * The implementations declared by this hook have several purposes:
 * - They can specify how a particular render array is to be rendered as HTML.
 *   This is usually the case if the theme function is assigned to the render
 *   array's #theme property.
 * - They can return HTML for default calls to theme().
 * - They can return HTML for calls to theme() for a theme suggestion.
1227
 *
1228
 * @param array $existing
1229 1230 1231 1232 1233
 *   An array of existing implementations that may be used for override
 *   purposes. This is primarily useful for themes that may wish to examine
 *   existing implementations to extract data (such as arguments) so that
 *   it may properly register its own, higher priority implementations.
 * @param $type
1234 1235 1236 1237 1238 1239 1240 1241 1242 1243
 *   Whether a theme, module, etc. is being processed. This is primarily useful
 *   so that themes tell if they are the actual theme being called or a parent
 *   theme. May be one of:
 *   - 'module': A module is being checked for theme implementations.
 *   - 'base_theme_engine': A theme engine is being checked for a theme that is
 *     a parent of the actual theme being used.
 *   - 'theme_engine': A theme engine is being checked for the actual theme
 *     being used.
 *   - 'base_theme': A base theme is being checked for theme implementations.
 *   - 'theme': The actual theme in use is being checked.
1244
 * @param $theme
1245
 *   The actual name of theme, module, etc. that is being being processed.
1246 1247 1248 1249
 * @param $path
 *   The directory path of the theme or module, so that it doesn't need to be
 *   looked up.
 *
1250
 * @return array
1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272
 *   An associative array of information about theme implementations. The keys
 *   on the outer array are known as "theme hooks". For simple theme
 *   implementations for regular calls to theme(), the theme hook is the first
 *   argument. For theme suggestions, instead of the array key being the base
 *   theme hook, the key is a theme suggestion name with the format
 *   'base_hook_name__sub_hook_name'. For render elements, the key is the
 *   machine name of the render element. The array values are themselves arrays
 *   containing information about the theme hook and its implementation. Each
 *   information array must contain either a 'variables' element (for theme()
 *   calls) or a 'render element' element (for render elements), but not both.
 *   The following elements may be part of each information array:
 *   - variables: Used for theme() call items only: an array of variables,
 *     where the array keys are the names of the variables, and the array
 *     values are the default values if they are not passed into theme().
 *     Template implementations receive each array key as a variable in the
 *     template file (so they must be legal PHP/Twig variable names). Function
 *     implementations are passed the variables in a single $variables function
 *     argument.
 *   - render element: Used for render element items only: the name of the
 *     renderable element or element tree to pass to the theme function. This
 *     name is used as the name of the variable that holds the renderable
 *     element or tree in preprocess and process functions.
1273 1274 1275 1276 1277
 *   - file: The file the implementation resides in. This file will be included
 *     prior to the theme being rendered, to make sure that the function or
 *     preprocess function (as needed) is actually loaded; this makes it
 *     possible to split theme functions out into separate files quite easily.
 *   - path: Override the path of the file to be used. Ordinarily the module or
1278 1279
 *     theme path will be used, but if the file will not be in the default
 *     path, include it here. This path should be relative to the Drupal root
1280
 *     directory.
1281
 *   - template: If specified, this theme implementation is a template, and
1282
 *     this is the template file without an extension. Do not put .html.twig on
1283
 *     this file; that extension will be added automatically by the default
1284 1285
 *     rendering engine (which is Twig). If 'path' above is specified, the
 *     template should also be in this path.
1286 1287 1288 1289 1290 1291
 *   - function: If specified, this will be the function name to invoke for
 *     this implementation. If neither 'template' nor 'function' is specified,
 *     a default function name will be assumed. For example, if a module
 *     registers the 'node' theme hook, 'theme_node' will be assigned to its
 *     function. If the chameleon theme registers the node hook, it will be
 *     assigned 'chameleon_node' as its function.
1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302
 *   - base hook: Used for theme() suggestions only: the base theme hook name.
 *     Instead of this suggestion's implementation being used directly, the base
 *     hook will be invoked with this implementation as its first suggestion.
 *     The base hook's files will be included and the base hook's preprocess
 *     functions will be called in place of any suggestion's preprocess
 *     functions. If an implementation of hook_theme_suggestions_HOOK() (where
 *     HOOK is the base hook) changes the suggestion order, a different
 *     suggestion may be used in place of this suggestion. If after
 *     hook_theme_suggestions_HOOK() this suggestion remains the first
 *     suggestion, then this suggestion's function or template will be used to
 *     generate the output for theme().
1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313
 *   - pattern: A regular expression pattern to be used to allow this theme
 *     implementation to have a dynamic name. The convention is to use __ to
 *     differentiate the dynamic portion of the theme. For example, to allow
 *     forums to be themed individually, the pattern might be: 'forum__'. Then,
 *     when the forum is themed, call:
 *     @code
 *     theme(array('forum__' . $tid, 'forum'), $forum)
 *     @endcode
 *   - preprocess functions: A list of functions used to preprocess this data.
 *     Ordinarily this won't be used; it's automatically filled in. By default,
 *     for a module this will be filled in as template_preprocess_HOOK. For
1314 1315
 *     a theme this will be filled in as twig_preprocess and
 *     twig_preprocess_HOOK as well as themename_preprocess and
1316
 *     themename_preprocess_HOOK.
1317 1318 1319
 *   - override preprocess functions: Set to TRUE when a theme does NOT want
 *     the standard preprocess functions to run. This can be used to give a
 *     theme FULL control over how variables are set. For example, if a theme
1320
 *     wants total control over how certain variables in the page.html.twig are
1321
 *     set, this can be set to true. Please keep in mind that when this is used
1322 1323 1324 1325 1326 1327
 *     by a theme, that theme becomes responsible for making sure necessary
 *     variables are set.
 *   - type: (automatically derived) Where the theme hook is defined:
 *     'module', 'theme_engine', or 'theme'.
 *   - theme path: (automatically derived) The directory path of the theme or
 *     module, so that it doesn't need to be looked up.
1328 1329
 *
 * @see hook_theme_registry_alter()
1330 1331 1332 1333
 */
function hook_theme($existing, $type, $theme, $path) {
  return array(
    'forum_display' => array(
1334
      'variables' => array('forums' => NULL, 'topics' => NULL, 'parents' => NULL, 'tid' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL),
1335 1336
    ),
    'forum_list' => array(
1337
      'variables' => array('forums' => NULL, 'parents' => NULL, 'tid' => NULL),
1338 1339
    ),
    'forum_topic_list' => array(
1340
      'variables' => array('tid' => NULL, 'topics' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL),
1341 1342
    ),
    'forum_icon' => array(
1343 1344 1345 1346 1347 1348
      'variables' => array('new_posts' => NULL, 'num_posts' => 0, 'comment_mode' => 0, 'sticky' => 0),
    ),
    'status_report' => array(
      'render element' => 'requirements',
      'file' => 'system.admin.inc',
    ),
1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363
  );
}

/**
 * Alter the theme registry information returned from hook_theme().
 *
 * The theme registry stores information about all available theme hooks,
 * including which callback functions those hooks will call when triggered,
 * what template files are exposed by these hooks, and so on.
 *
 * Note that this hook is only executed as the theme cache is re-built.
 * Changes here will not be visible until the next cache clear.
 *
 * The $theme_registry array is keyed by theme hook name, and contains the
 * information returned from hook_theme(), as well as additional properties
1364
 * added by \Drupal\Core\Theme\Registry::processExtension().
1365 1366 1367
 *
 * For example:
 * @code
1368
 * $theme_registry['user'] = array(
1369 1370 1371
 *   'variables' => array(
 *     'account' => NULL,
 *   ),
1372
 *   'template' => 'core/modules/user/user',
1373
 *   'file' => 'core/modules/user/user.pages.inc',
1374
 *   'type' => 'module',
1375
 *   'theme path' => 'core/modules/user',
Dries's avatar