Newer
Older
Angie Byron
committed
<?php
/**
* @file
* Hooks provided by Drupal core and the System module.
*/
use Drupal\Component\Utility\String;
use Drupal\Core\Utility\UpdateException;
Angie Byron
committed
/**
* @addtogroup hooks
* @{
*/
/**
* 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.
*
* @see hook_hook_info_alter().
*/
function hook_hook_info() {
$hooks['token_info'] = array(
'group' => 'tokens',
);
$hooks['tokens'] = array(
'group' => 'tokens',
);
return $hooks;
}
Angie Byron
committed
/**
* Perform periodic actions.
*
* 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.
Angie Byron
committed
*
* Short-running or non-resource-intensive tasks can be executed directly in
* the hook_cron() implementation.
* 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
catch
committed
* more queues via hook_queue_info(). Then, add items that need to be
* processed to the defined queues.
Angie Byron
committed
*/
function hook_cron() {
// Short-running operation example, not using a queue:
// Delete all expired records since the last cron run.
$expires = \Drupal::state()->get('mymodule.cron_last_run', REQUEST_TIME);
db_delete('mymodule_table')
->condition('expires', $expires, '>=')
->execute();
\Drupal::state()->set('mymodule.cron_last_run', REQUEST_TIME);
Angie Byron
committed
// Long-running operation example, leveraging a queue:
// Fetch feeds from other sites.
Angie Byron
committed
$result = db_query('SELECT * FROM {aggregator_feed} WHERE checked + refresh < :time AND refresh <> :never', array(
':time' => REQUEST_TIME,
':never' => AGGREGATOR_CLEAR_NEVER,
));
$queue = \Drupal::queue('aggregator_feeds');
foreach ($result as $feed) {
$queue->createItem($feed);
Angie Byron
committed
}
}
Dries Buytaert
committed
/**
* 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';
}
Dries Buytaert
committed
/**
* 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
* 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.
Dries Buytaert
committed
*
catch
committed
* 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.
*
Dries Buytaert
committed
* @return
* An associative array where the key is the queue name and the value is
* again an associative array. Possible keys are:
Jennifer Hodgdon
committed
* - 'worker callback': A PHP callable to call that is an implementation of
* callback_queue_worker().
catch
committed
* - '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.
*
* @see hook_cron()
catch
committed
* @see hook_queue_info_alter()
Dries Buytaert
committed
*/
catch
committed
function hook_queue_info() {
Dries Buytaert
committed
$queues['aggregator_feeds'] = array(
catch
committed
'title' => t('Aggregator refresh'),
Alex Pott
committed
'worker callback' => array('Drupal\my_module\MyClass', 'aggregatorRefresh'),
catch
committed
// Only needed if this queue should be processed by cron.
'cron' => array(
'time' => 60,
),
Dries Buytaert
committed
);
return $queues;
}
Dries Buytaert
committed
/**
* Alter cron queue information before cron runs.
*
* Called by \Drupal\Core\Cron to allow modules to alter cron queue settings
Dries Buytaert
committed
* before any jobs are processesed.
*
* @param array $queues
* An array of cron queue information.
*
catch
committed
* @see hook_queue_info()
* @see \Drupal\Core\Cron
Dries Buytaert
committed
*/
catch
committed
function hook_queue_info_alter(&$queues) {
Dries Buytaert
committed
// This site has many feeds so let's spend 90 seconds on each cron run
// updating feeds instead of the default 60.
catch
committed
$queues['aggregator_feeds']['cron']['time'] = 90;
Dries Buytaert
committed
}
Jennifer Hodgdon
committed
/**
* Work on a single queue item.
*
* Callback for hook_queue_info().
*
* @param $queue_item_data
* The data that was passed to \Drupal\Core\Queue\QueueInterface::createItem()
* when the item was queued.
*
* @throws \Exception
* The worker callback may throw an exception to indicate there was a problem.
* The cron process will log the exception, and leave the item in the queue to
* be processed again later.
* @throws \Drupal\Core\Queue\SuspendQueueException
* More specifically, a SuspendQueueException should be thrown when the
* callback is aware that the problem will affect all subsequent workers of
* its queue. For example, a callback that makes HTTP requests may find that
* the remote server is not responding. The cron process will behave as with a
* normal Exception, and in addition will not attempt to process further items
* from the current item's queue during the current cron run.
Jennifer Hodgdon
committed
*
* @see \Drupal\Core\Cron::run()
*/
function callback_queue_worker($queue_item_data) {
$node = node_load($queue_item_data);
$node->title = 'Updated title';
$node->save();
}
Angie Byron
committed
/**
Jennifer Hodgdon
committed
* Allows modules to declare their own Form API element types and specify their
Angie Byron
committed
* 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
* merged with the elements returned by form constructor implementations and so
Angie Byron
committed
* can return defaults for any Form APIs keys in addition to those explicitly
Angie Byron
committed
* documented by \Drupal\Core\Render\ElementInfoManagerInterface::getInfo().
Angie Byron
committed
*
* @return array
* An associative array with structure identical to that of the return value
Angie Byron
committed
* of \Drupal\Core\Render\ElementInfoManagerInterface::getInfo().
*
* @deprecated Use an annotated class instead, see
* \Drupal\Core\Render\Element\ElementInterface.
Dries Buytaert
committed
*
* @see hook_element_info_alter()
Angie Byron
committed
*/
Dries Buytaert
committed
function hook_element_info() {
$types['filter_format'] = array(
'#input' => TRUE,
);
return $types;
Angie Byron
committed
}
Angie Byron
committed
/**
* 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.
*
* @param array $types
* An associative array with structure identical to that of the return value
Angie Byron
committed
* of \Drupal\Core\Render\ElementInfoManagerInterface::getInfo().
Angie Byron
committed
*
Dries Buytaert
committed
* @see hook_element_info()
Angie Byron
committed
*/
function hook_element_info_alter(array &$types) {
Angie Byron
committed
// Decrease the default size of textfields.
if (isset($types['textfield']['#size'])) {
$types['textfield']['#size'] = 40;
Angie Byron
committed
}
}
Angie Byron
committed
/**
* 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.
Dries Buytaert
committed
*
Angie Byron
committed
* @see _drupal_add_js()
Angie Byron
committed
* @see drupal_get_js()
* @see drupal_js_defaults()
*/
function hook_js_alter(&$javascript) {
// Swap out jQuery to use an updated version of the library.
catch
committed
$javascript['core/assets/vendor/jquery/jquery.js']['data'] = drupal_get_path('module', 'jquery_update') . '/jquery.js';
Angie Byron
committed
}
Angie Byron
committed
/**
* 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.
*/
function hook_library_info_alter(&$libraries, $module) {
Angie Byron
committed
// Update Farbtastic to version 2.0.
Angie Byron
committed
if ($module == 'core' && isset($libraries['jquery.farbtastic'])) {
Angie Byron
committed
// Verify existing version is older than the one we are updating to.
Angie Byron
committed
if (version_compare($libraries['jquery.farbtastic']['version'], '2.0', '<')) {
Angie Byron
committed
// Update the existing Farbtastic to version 2.0.
Angie Byron
committed
$libraries['jquery.farbtastic']['version'] = '2.0';
// To accurately replace library files, the order of files and the options
// of each file have to be retained; e.g., like this:
$old_path = 'assets/vendor/farbtastic';
// Since the replaced library files are no longer located in a directory
// relative to the original extension, specify an absolute path (relative
// to DRUPAL_ROOT / base_path()) to the new location.
$new_path = '/' . drupal_get_path('module', 'farbtastic_update') . '/js';
$new_js = array();
$replacements = array(
$old_path . '/farbtastic.js' => $new_path . '/farbtastic-2.0.js',
Angie Byron
committed
);
Angie Byron
committed
foreach ($libraries['jquery.farbtastic']['js'] as $source => $options) {
if (isset($replacements[$source])) {
$new_js[$replacements[$source]] = $options;
}
else {
$new_js[$source] = $options;
}
}
$libraries['jquery.farbtastic']['js'] = $new_js;
Angie Byron
committed
}
}
}
Angie Byron
committed
/**
* Alters a JavaScript/CSS library before it is attached.
*
* Allows modules and themes to dynamically attach further assets to a library
* when it is added to the page; e.g., to add JavaScript settings.
*
* This hook is only invoked once per library and page.
*
* @param array $library
* The JavaScript/CSS library that is being added.
* @param string $name
* The name of the library.
*
Angie Byron
committed
* @see _drupal_add_library()
Angie Byron
committed
*/
function hook_library_alter(array &$library, $name) {
if ($name == 'core/jquery.ui.datepicker') {
Angie Byron
committed
// Note: If the added assets do not depend on additional request-specific
// data supplied here, consider to statically register it directly via
// hook_library_info_alter() already.
$library['dependencies'][] = 'locale/drupal.locale.datepicker';
Angie Byron
committed
$language_interface = \Drupal::languageManager()->getCurrentLanguage();
Angie Byron
committed
$settings['jquery']['ui']['datepicker'] = array(
'isRTL' => $language_interface->direction == LanguageInterface::DIRECTION_RTL,
Angie Byron
committed
'firstDay' => \Drupal::config('system.date')->get('first_day'),
);
$library['js'][] = array(
'type' => 'setting',
'data' => $settings,
);
}
}
Dries Buytaert
committed
/**
* 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.
Dries Buytaert
committed
*
Angie Byron
committed
* @see _drupal_add_css()
Dries Buytaert
committed
* @see drupal_get_css()
*/
function hook_css_alter(&$css) {
// Remove defaults.css file.
unset($css[drupal_get_path('module', 'system') . '/defaults.css']);
}
Alex Pott
committed
* Alter the Ajax command data that is sent to the client.
Alex Pott
committed
* @param \Drupal\Core\Ajax\CommandInterface[] $data
* An array of all the rendered commands that will be sent to the client.
Dries Buytaert
committed
*
Alex Pott
committed
* @see \Drupal\Core\Ajax\AjaxResponse::ajaxRender()
Alex Pott
committed
function hook_ajax_render_alter(array &$data) {
// Inject any new status messages into the content area.
$status_messages = array('#theme' => 'status_messages');
Alex Pott
committed
$command = new \Drupal\Core\Ajax\PrependCommand('#block-system-main .content', drupal_render($status_messages));
$data[] = $command->render();
}
Angie Byron
committed
/**
* 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 DefaultHtmlFragmentRenderer::render()
Angie Byron
committed
*/
function hook_page_build(&$page) {
$path = drupal_get_path('module', 'foo');
// Add JavaScript/CSS assets to all pages.
// @see drupal_process_attached()
$page['#attached']['js'][$path . '/foo.js'] = 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.
catch
committed
if (\Drupal::request()->attributes->get('node')) {
Angie Byron
committed
$page['content']['disclaimer'] = array(
'#markup' => t('Acme, Inc. is not responsible for the contents of this sample code.'),
'#weight' => 25,
);
}
}
* Alters all the menu links discovered by the menu link plugin manager.
Angie Byron
committed
*
* @param array $links
* The link definitions to be altered.
*
* @return array
* An array of discovered menu links. Each link has a key that is the machine
* name, which must be unique. By default, use the route name as the
* machine name. In cases where multiple links use the same route name, such
* as two links to the same page in different menus, or two links using the
* same route name but different route parameters, the suggested machine name
* patten is the route name followed by a dot and a unique suffix. For
* example, an additional logout link might have a machine name of
* user.logout.navigation, and default links provided to edit the article and
Alex Pott
committed
* page content types could use machine names
* entity.node_type.edit_form.article and entity.node_type.edit_form.page.
* Since the machine name may be arbitrary, you should never write code that
* assumes it is identical to the route name.
*
* The value corresponding to each machine name key is an associative array
* that may contain the following key-value pairs:
Angie Byron
committed
* - title: (required) The untranslated title of the menu link.
* - description: The untranslated description of the link.
* - route_name: (optional) The route name to be used to build the path.
* Either a route_name or a link_path must be provided.
* - route_parameters: (optional) The route parameters to build the path.
* - link_path: (optional) If you have an external link use link_path instead
* of providing a route_name.
* - parent: (optional) The machine name of the link that is this link's menu
* parent.
* - weight: (optional) 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) The machine name of a menu to put the link in, if
* not the default Tools menu.
* - 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.
* - options: (optional) An array of options to be passed to l() when
* generating a link from this menu item.
Angie Byron
committed
*
* @ingroup menu
function hook_menu_links_discovered_alter(&$links) {
// Change the weight and title of the user.logout link.
$links['user.logout']['weight'] = -10;
Angie Byron
committed
$links['user.logout']['title'] = 'Logout';
Angie Byron
committed
/**
* 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. Additional tabs or actions may be added.
Angie Byron
committed
*
* 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.
* - localized_options: An array of options to pass to l().
* - #weight: The link's weight compared to other links.
Angie Byron
committed
* - #active: Whether the link should be marked as 'active'.
*
* @param array $data
Angie Byron
committed
* An associative array containing:
* - 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.
Angie Byron
committed
* @param string $route_name
* The route name of the page.
Angie Byron
committed
*/
Angie Byron
committed
function hook_menu_local_tasks(&$data, $route_name) {
Angie Byron
committed
// Add an action linking to node/add to all pages.
$data['actions']['node/add'] = array(
'#theme' => 'menu_local_action',
Angie Byron
committed
'#link' => array(
Angie Byron
committed
'title' => t('Add content'),
Angie Byron
committed
'href' => 'node/add',
'localized_options' => array(
'attributes' => array(
Angie Byron
committed
'title' => t('Add content'),
Angie Byron
committed
),
),
),
);
// Add a tab linking to node/add to all pages.
$data['tabs'][0]['node/add'] = array(
Angie Byron
committed
'#theme' => 'menu_local_task',
'#link' => array(
'title' => t('Example tab'),
'href' => 'node/add',
'localized_options' => array(
'attributes' => array(
Angie Byron
committed
'title' => t('Add content'),
Angie Byron
committed
),
),
),
);
}
/**
* 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.
Angie Byron
committed
* @param string $route_name
* The route name of the page.
*
* @see hook_menu_local_tasks()
Angie Byron
committed
*
* @ingroup menu
Angie Byron
committed
function hook_menu_local_tasks_alter(&$data, $route_name) {
Dries Buytaert
committed
/**
* 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
Angie Byron
committed
*
* @ingroup menu
Dries Buytaert
committed
*/
function hook_menu_local_actions_alter(&$local_actions) {
}
Dries Buytaert
committed
/**
* 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
*/
Dries Buytaert
committed
function hook_local_tasks_alter(&$local_tasks) {
Dries Buytaert
committed
// Remove a specified local task plugin.
unset($local_tasks['example_plugin_id']);
}
Angie Byron
committed
/**
* Alter contextual links before they are rendered.
*
* 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.
Angie Byron
committed
*
* Each contextual link contains the following entries:
Angie Byron
committed
* - title: The localized title of the link.
* - route_name: The route name of the link.
* - route_parameters: The route parameters of the link.
Angie Byron
committed
* - localized_options: An array of options to pass to url().
* - (optional) weight: The weight of the link, which is used to sort the links.
Angie Byron
committed
*
*
* @param array $links
* An associative array containing contextual links for the given $group,
Angie Byron
committed
* 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.
* @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
Angie Byron
committed
*
* @ingroup menu
Angie Byron
committed
*/
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.
catch
committed
$menu = \Drupal::entityManager()->getStorage('menu')->load($route_parameters['menu']);
$links['menu_edit']['title'] = t('Edit menu: !label', array('!label' => $menu->label()));
Angie Byron
committed
}
}
/**
* 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';
}
/**
* Perform alterations before a page is rendered.
*
Angie Byron
committed
* 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
* 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
Angie Byron
committed
* $page['page_top']
* $page['header']
Dries Buytaert
committed
* $page['sidebar_first']
* $page['content']
Dries Buytaert
committed
* $page['sidebar_second']
Angie Byron
committed
* $page['page_bottom']
* @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'].
*
* Pages built by Drupal's core Node module use a standard structure:
*
* @code
* // Node body.
Angie Byron
committed
* $page['content']['system_main']['nodes'][$nid]['body']
* // Array of links attached to the node (add comments, read more).
Angie Byron
committed
* $page['content']['system_main']['nodes'][$nid]['links']
* // The node entity itself.
Angie Byron
committed
* $page['content']['system_main']['nodes'][$nid]['#node']
* // The results pager.
Angie Byron
committed
* $page['content']['system_main']['pager']
* @endcode
*
* Blocks may be referenced by their module/delta pair within a region:
* @code
Dries Buytaert
committed
* // The login block in the first sidebar region.
Angie Byron
committed
* $page['sidebar_first']['user_login']['#block'];
* @endcode
*
* @param $page
* Nested array of renderable elements that make up the page.
*
Angie Byron
committed
* @see hook_page_build()
* @see DefaultHtmlFragmentRenderer::render()
*/
Angie Byron
committed
function hook_page_alter(&$page) {
// Add help text to the user login block.
$page['sidebar_first']['user_login']['help'] = array(
'#weight' => -10,
Angie Byron
committed
'#markup' => t('To post comments or add content, you first have to log in.'),
Angie Byron
committed
);
}
Angie Byron
committed
/**
* Perform alterations before a form is rendered.
*
* One popular use of this hook is to add form elements to the node form. When
* altering a node form, the node entity can be retrieved by invoking
* $form_state->getFormObject()->getEntity().
Angie Byron
committed
*
* 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.
Angie Byron
committed
*
Angie Byron
committed
* @param $form
* Nested array of form elements that comprise the form.
* @param $form_state
Dries Buytaert
committed
* The current state of the form. The arguments that
* \Drupal::formBuilder()->getForm() was originally called with are available
Angie Byron
committed
* in the array $form_state->getBuildInfo()['args'].
Angie Byron
committed
* @param $form_id
* String representing the name of the form itself. Typically this is the
* name of the function that generated the form.
* @see hook_form_BASE_FORM_ID_alter()
* @see hook_form_FORM_ID_alter()
Jennifer Hodgdon
committed
* @see forms_api_reference.html
Angie Byron
committed
*/
Dries Buytaert
committed
function hook_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
Angie Byron
committed
if (isset($form['type']) && $form['type']['#value'] . '_node_settings' == $form_id) {
$upload_enabled_types = \Drupal::config('mymodule.settings')->get('upload_enabled_types');
Angie Byron
committed
$form['workflow']['upload_' . $form['type']['#value']] = array(
'#type' => 'radios',
'#title' => t('Attachments'),
'#default_value' => in_array($form['type']['#value'], $upload_enabled_types) ? 1 : 0,
Angie Byron
committed
'#options' => array(t('Disabled'), t('Enabled')),
);
// 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';
Angie Byron
committed
}
}
/**
* 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.
*
* 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.
*
Angie Byron
committed
* @param $form
* Nested array of form elements that comprise the form.
* @param $form_state
Dries Buytaert
committed
* The current state of the form. The arguments that
* \Drupal::formBuilder()->getForm() was originally called with are available
Angie Byron
committed
* in the array $form_state->getBuildInfo()['args'].
Dries Buytaert
committed
* @param $form_id
* String representing the name of the form itself. Typically this is the
* name of the function that generated the form.
Angie Byron
committed
*
* @see hook_form_alter()
* @see hook_form_BASE_FORM_ID_alter()
Alex Pott
committed
* @see \Drupal\Core\Form\FormBuilderInterface::prepareForm()
Jennifer Hodgdon
committed
* @see forms_api_reference.html
Angie Byron
committed
*/
Dries Buytaert
committed
function hook_form_FORM_ID_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
Angie Byron
committed
// Modification for the form with the given form ID goes here. For example, if
// FORM_ID is "user_register_form" this code would run only on the user
Angie Byron
committed
// 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,
);
}
Dries Buytaert
committed
/**
* Provide a form-specific alteration for shared ('base') forms.
*
* By default, when \Drupal::formBuilder()->getForm() 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.
Dries Buytaert
committed
*
* Modules can implement hook_form_BASE_FORM_ID_alter() to modify a specific
* 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
Angie Byron
committed
* $form_state->getBuildInfo()['base_form_id'].
Dries Buytaert
committed
*
* 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.
Dries Buytaert
committed
*
* @param $form
* Nested array of form elements that comprise the form.
* @param $form_state
Dries Buytaert
committed
* The current state of the form.
Dries Buytaert
committed
* @param $form_id
* String representing the name of the form itself. Typically this is the
* name of the function that generated the form.
*
* @see hook_form_alter()
Dries Buytaert
committed
* @see hook_form_FORM_ID_alter()
Alex Pott
committed
* @see \Drupal\Core\Form\FormBuilderInterface::prepareForm()
Dries Buytaert
committed
*/
Dries Buytaert
committed
function hook_form_BASE_FORM_ID_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
Dries Buytaert
committed
// 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,
);
}
Angie Byron
committed
/**
Dries Buytaert
committed
* 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
* calling the drupal_mail_system()->mail() or PHP mail() function
* will not invoke this hook. All core modules use drupal_mail() for
* messaging, it is best practice but not mandatory in contributed modules.
Angie Byron
committed
*
* @param $message
Dries Buytaert
committed
* An array containing the message data. Keys in this array include:
Dries Buytaert
committed
* - 'id':
Dries Buytaert
committed
* The drupal_mail() id of the message. Look at module source code or
Dries Buytaert
committed
* drupal_mail() for possible id values.
Dries Buytaert
committed
* - 'to':
Dries Buytaert
committed
* The address or addresses the message will be sent to. The
Angie Byron
committed
* formatting of this string must comply with RFC 2822.
Dries Buytaert
committed
* - 'from':
Dries Buytaert
committed
* The address the message will be marked as being from, which is
* either a custom address or the site-wide default email address.
Dries Buytaert
committed
* - '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
Dries Buytaert
committed
* created by concatenating the individual array strings into a single text
Dries Buytaert
committed
* string using "\n\n" as a separator.
* - 'headers':
Dries Buytaert
committed
* Associative array containing mail headers, such as From, Sender,
Dries Buytaert
committed
* MIME-Version, Content-Type, etc.
Dries Buytaert
committed
* - '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.
* - 'send':
* Set to FALSE to abort sending this email message.
Dries Buytaert
committed
*
* @see drupal_mail()
Angie Byron
committed
*/
function hook_mail_alter(&$message) {
if ($message['id'] == 'modulename_messagekey') {
if (!example_notifications_optin($message['to'], $message['id'])) {
// If the recipient has opted to not receive such messages, cancel
// sending.
$message['send'] = FALSE;
return;
}
$message['body'][] = "--\nMail sent out from " . \Drupal::config('system.site')->get('name');
Angie Byron
committed
}
}
/**
* Alter the registry of modules implementing a hook.
*
* This hook is invoked during \Drupal::moduleHandler()->getImplementations().
catch
committed
* A module may implement this hook in order to reorder the implementing
* modules, which are otherwise ordered by the module's system weight.
* Note that hooks invoked using \Drupal::moduleHandler->alter() can have
* multiple variations(such as hook_form_alter() and hook_form_FORM_ID_alter()).
* \Drupal::moduleHandler->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 change the order of hook_form_alter() implementation in
Dries Buytaert
committed
* hook_module_implements_alter().
*
* @param $implementations
* 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') {
catch
committed
// Move my_module_rdf_mapping() to the end of the list.
// \Drupal::moduleHandler()->getImplementations()
// 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;
}
}
/**
* 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
Angie Byron
committed
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
* @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.
*/
Angie Byron
committed
function hook_system_breadcrumb_alter(array &$breadcrumb, \Drupal\Core\Routing\RouteMatchInterface $route_match, array $context) {
// Add an item to the end of the breadcrumb.
$breadcrumb[] = Drupal::l(t('Text'), 'example_route_name');
}
Angie Byron
committed
/**
* Alter the information parsed from module and theme .info.yml files
Angie Byron
committed
*
Angie Byron
committed
* This hook is invoked in _system_rebuild_module_data() and in
* _system_rebuild_theme_data(). A module may implement this hook in order to
* add to or alter the data generated by reading the .info.yml file with
* \Drupal\Core\Extension\InfoParser.
Angie Byron
committed
*
* @param array $info
* The .info.yml file contents, passed by reference so that it can be altered.
* @param \Drupal\Core\Extension\Extension $file
* Full information about the module or theme.
* @param string $type
* Either 'module' or 'theme', depending on the type of .info.yml file that
* was passed.
Angie Byron
committed
*/
function hook_system_info_alter(array &$info, \Drupal\Core\Extension\Extension $file, $type) {
// Only fill this in if the .info.yml file does not define a 'datestamp'.
Angie Byron
committed
if (empty($info['datestamp'])) {
$info['datestamp'] = $file->getMTime();
Angie Byron
committed
}
}
Jennifer Hodgdon
committed
/**
* Provide online user help.
*
* By implementing hook_help(), a module can make documentation available to
* the user for the module as a whole, or for specific pages. Help for
* developers should usually be provided via function header comments in the
* code, or in special API example files.
*
* The page-specific help information provided by this hook appears as a system
* help block on that page. The module overview help information is displayed
* by the Help module. It can be accessed from the page at admin/help or from
* the Extend page.
*
* For detailed usage examples of:
* - Module overview help, see content_translation_help(). Module overview
* help should follow
* @link https://drupal.org/node/632280 the standard help template. @endlink
* - Page-specific help using only routes, see book_help().
* - Page-specific help using routes and $request, see block_help().
*
* @param string $route_name
* For page-specific help, use the route name as identified in the
* module's routing.yml file. For module overview help, the route name
* will be in the form of "help.page.$modulename".
Angie Byron
committed
* @param Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match. This can be used to generate different help
Jennifer Hodgdon
committed
* output for different pages that share the same route.
*
* @return string
* A localized string containing the help text.
*/
Angie Byron
committed
function hook_help($route_name, \Drupal\Core\Routing\RouteMatchInterface $route_match) {
Jennifer Hodgdon
committed
switch ($route_name) {
// Main module help for the block module.
case 'help.page.block':
Jennifer Hodgdon
committed
return '<p>' . t('Blocks are boxes of content rendered into an area, or region, of a web page. The default theme Bartik, for example, implements the regions "Sidebar first", "Sidebar second", "Featured", "Content", "Header", "Footer", etc., and a block may appear in any one of these areas. The <a href="!blocks">blocks administration page</a> provides a drag-and-drop interface for assigning a block to a region, and for controlling the order of blocks within regions.', array('!blocks' => \Drupal::url('block.admin_display'))) . '</p>';
Jennifer Hodgdon
committed
// Help for another path in the block module.
case 'block.admin_display':
return '<p>' . t('This page provides a drag-and-drop interface for assigning a block to a region, and for controlling the order of blocks within regions. Since not all themes implement the same regions, or display regions in the same way, blocks are positioned on a per-theme basis. Remember that your changes will not be saved until you click the <em>Save blocks</em> button at the bottom of the page.') . '</p>';
}
}
Angie Byron
committed
/**
Jennifer Hodgdon
committed
* Register a module or theme's theme implementations.
Angie Byron
committed
*
Jennifer Hodgdon
committed
* 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.
Angie Byron
committed
*
* @param array $existing
Angie Byron
committed
* An array of existing implementations that may be used for override
* purposes. This is primarily useful for themes that may wish to examine