drupal/core/modules/system/system.api.php

1066 lines
38 KiB
PHP

<?php
/**
* @file
* Hooks provided by Drupal core and the System module.
*/
use Drupal\Component\Utility\String;
use Drupal\Core\Mail\MailFormatHelper;
use Drupal\Core\Url;
/**
* @addtogroup hooks
* @{
*/
/**
* 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.
*
* 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
* more queues via a \Drupal\Core\Annotation\QueueWorker plugin. Then, add items
* that need to be processed to the defined queues.
*/
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);
// Long-running operation example, leveraging a queue:
// Fetch feeds from other sites.
$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);
}
}
/**
* 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';
}
/**
* Alter cron queue information before cron runs.
*
* Called by \Drupal\Core\Cron to allow modules to alter cron queue settings
* before any jobs are processesed.
*
* @param array $queues
* An array of cron queue information.
*
* @see \Drupal\Core\QueueWorker\QueueWorkerInterface
* @see \Drupal\Core\Annotation\QueueWorker
* @see \Drupal\Core\Cron
*/
function hook_queue_info_alter(&$queues) {
// This site has many feeds so let's spend 90 seconds on each cron run
// updating feeds instead of the default 60.
$queues['aggregator_feeds']['cron']['time'] = 90;
}
/**
* Alters all the menu links discovered by the menu link plugin manager.
*
* @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
* 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:
* - 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.
*
* @ingroup menu
*/
function hook_menu_links_discovered_alter(&$links) {
// Change the weight and title of the user.logout link.
$links['user.logout']['weight'] = -10;
$links['user.logout']['title'] = 'Logout';
}
/**
* 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.
*
* 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.
* - #active: Whether the link should be marked as 'active'.
*
* @param array $data
* 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.
* @param string $route_name
* The route name of the page.
*/
function hook_menu_local_tasks(&$data, $route_name) {
// Add an action linking to node/add to all pages.
$data['actions']['node/add'] = array(
'#theme' => 'menu_local_action',
'#link' => array(
'title' => t('Add content'),
'url' => Url::fromRoute('node.add_page'),
'localized_options' => array(
'attributes' => array(
'title' => t('Add content'),
),
),
),
);
// Add a tab linking to node/add to all pages.
$data['tabs'][0]['node/add'] = array(
'#theme' => 'menu_local_task',
'#link' => array(
'title' => t('Example tab'),
'url' => Url::fromRoute('node.add_page'),
'localized_options' => array(
'attributes' => array(
'title' => t('Add content'),
),
),
),
);
}
/**
* 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.
* @param string $route_name
* The route name of the page.
*
* @see hook_menu_local_tasks()
*
* @ingroup menu
*/
function hook_menu_local_tasks_alter(&$data, $route_name) {
}
/**
* 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
*
* @ingroup menu
*/
function hook_menu_local_actions_alter(&$local_actions) {
}
/**
* 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
*/
function hook_local_tasks_alter(&$local_tasks) {
// Remove a specified local task plugin.
unset($local_tasks['example_plugin_id']);
}
/**
* 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.
*
* Each contextual link contains the following entries:
* - title: The localized title of the link.
* - route_name: The route name of the link.
* - route_parameters: The route parameters of the link.
* - localized_options: An array of options to pass to _url().
* - (optional) weight: The weight of the link, which is used to sort the links.
*
*
* @param array $links
* An associative array containing contextual links for the given $group,
* 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
*
* @ingroup menu
*/
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()->getStorage('menu')->load($route_parameters['menu']);
$links['menu_edit']['title'] = t('Edit menu: !label', array('!label' => $menu->label()));
}
}
/**
* 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';
}
/**
* Alter an email message created with MailManagerInterface->mail().
*
* hook_mail_alter() allows modification of email messages created and sent
* with MailManagerInterface->mail(). Usage examples include adding and/or
* changing message text, message fields, and message headers.
*
* Email messages sent using functions other than MailManagerInterface->mail()
* will not invoke hook_mail_alter(). For example, a contributed module directly
* calling the MailInterface->mail() or PHP mail() function will not invoke
* this hook. All core modules use MailManagerInterface->mail() for messaging,
* it is best practice but not mandatory in contributed modules.
*
* @param $message
* An array containing the message data. Keys in this array include:
* - 'id':
* The MailManagerInterface->mail() id of the message. Look at module source
* code or MailManagerInterface->mail() for possible id values.
* - 'to':
* The address or addresses the message will be sent to. The
* formatting of this string must comply with RFC 2822.
* - 'from':
* The address the message will be marked as being from, which is
* either a custom address or the site-wide default email address.
* - '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
* created by concatenating the individual array strings into a single text
* string using "\n\n" as a separator.
* - 'headers':
* Associative array containing mail headers, such as From, Sender,
* MIME-Version, Content-Type, etc.
* - 'params':
* An array of optional parameters supplied by the caller of
* MailManagerInterface->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.
*
* @see \Drupal\Core\Mail\MailManagerInterface::mail()
*/
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');
}
}
/**
* 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 \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.
*/
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');
}
/**
* Prepares a message based on parameters;
*
* This hook is called from MailManagerInterface->mail(). Note that hook_mail(),
* unlike hook_mail_alter(), is only called on the $module argument to
* MailManagerInterface->mail(), not all modules.
*
* @param $key
* An identifier of the mail.
* @param $message
* An array to be filled in. Elements in this array include:
* - id: An ID to identify the mail sent. Look at module source code or
* MailManagerInterface->mail() for possible id values.
* - to: The address or addresses the message will be sent to. The
* formatting of this string must comply with RFC 2822.
* - subject: Subject of the email to be sent. This must not contain any
* newline characters, or the mail may not be sent properly.
* MailManagerInterface->mail() sets this to an empty
* string when the hook is invoked.
* - body: An array of lines containing the message to be sent. Drupal will
* format the correct line endings for you. MailManagerInterface->mail()
* sets this to an empty array when the hook is invoked.
* - from: The address the message will be marked as being from, which is
* set by MailManagerInterface->mail() to either a custom address or the
* site-wide default email address when the hook is invoked.
* - headers: Associative array containing mail headers, such as From,
* Sender, MIME-Version, Content-Type, etc.
* MailManagerInterface->mail() pre-fills several headers in this array.
* @param $params
* An array of parameters supplied by the caller of
* MailManagerInterface->mail().
*
* @see \Drupal\Core\Mail\MailManagerInterface->mail()
*/
function hook_mail($key, &$message, $params) {
$account = $params['account'];
$context = $params['context'];
$variables = array(
'%site_name' => \Drupal::config('system.site')->get('name'),
'%username' => user_format_name($account),
);
if ($context['hook'] == 'taxonomy') {
$entity = $params['entity'];
$vocabulary = entity_load('taxonomy_vocabulary', $entity->id());
$variables += array(
'%term_name' => $entity->name,
'%term_description' => $entity->description,
'%term_id' => $entity->id(),
'%vocabulary_name' => $vocabulary->label(),
'%vocabulary_description' => $vocabulary->getDescription(),
'%vocabulary_id' => $vocabulary->id(),
);
}
// Node-based variable translation is only available if we have a node.
if (isset($params['node'])) {
/** @var \Drupal\node\NodeInterface $node */
$node = $params['node'];
$variables += array(
'%uid' => $node->getOwnerId(),
'%url' => $node->url('canonical', array('absolute' => TRUE)),
'%node_type' => node_get_type_label($node),
'%title' => $node->getTitle(),
'%teaser' => $node->teaser,
'%body' => $node->body,
);
}
$subject = strtr($context['subject'], $variables);
$body = strtr($context['message'], $variables);
$message['subject'] .= str_replace(array("\r", "\n"), '', $subject);
$message['body'][] = MailFormatHelper::htmlToText($body);
}
/**
* Flush all persistent and static caches.
*
* This hook asks your module to clear all of its static caches,
* in order to ensure a clean environment for subsequently
* invoked data rebuilds.
*
* Do NOT use this hook for rebuilding information. Only use it to flush custom
* caches.
*
* Static caches using drupal_static() do not need to be reset manually.
* However, all other static variables that do not use drupal_static() must be
* manually reset.
*
* This hook is invoked by drupal_flush_all_caches(). It runs before module data
* is updated and before hook_rebuild().
*
* @see drupal_flush_all_caches()
* @see hook_rebuild()
*/
function hook_cache_flush() {
if (defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'update') {
_update_cache_clear();
}
}
/**
* Rebuild data based upon refreshed caches.
*
* This hook allows your module to rebuild its data based on the latest/current
* module data. It runs after hook_cache_flush() and after all module data has
* been updated.
*
* This hook is only invoked after the system has been completely cleared;
* i.e., all previously cached data is known to be gone and every API in the
* system is known to return current information, so your module can safely rely
* on all available data to rebuild its own.
*
* @see hook_cache_flush()
* @see drupal_flush_all_caches()
*/
function hook_rebuild() {
$themes = list_themes();
foreach ($themes as $theme) {
_block_rehash($theme->getName());
}
}
/**
* Define the current version of the database schema.
*
* A Drupal schema definition is an array structure representing one or more
* tables and their related keys and indexes. A schema is defined by
* hook_schema() which must live in your module's .install file.
*
* The tables declared by this hook will be automatically created when the
* module is installed, and removed when the module is uninstalled. This happens
* before hook_install() is invoked, and after hook_uninstall() is invoked,
* respectively.
*
* By declaring the tables used by your module via an implementation of
* hook_schema(), these tables will be available on all supported database
* engines. You don't have to deal with the different SQL dialects for table
* creation and alteration of the supported database engines.
*
* See the Schema API Handbook at http://drupal.org/node/146843 for details on
* schema definition structures.
*
* @return array
* A schema definition structure array. For each element of the
* array, the key is a table name and the value is a table structure
* definition.
*
* @see hook_schema_alter()
*
* @ingroup schemaapi
*/
function hook_schema() {
$schema['node'] = array(
// Example (partial) specification for table "node".
'description' => 'The base table for nodes.',
'fields' => array(
'nid' => array(
'description' => 'The primary identifier for a node.',
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
),
'vid' => array(
'description' => 'The current {node_field_revision}.vid version identifier.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'type' => array(
'description' => 'The type of this node.',
'type' => 'varchar',
'length' => 32,
'not null' => TRUE,
'default' => '',
),
'title' => array(
'description' => 'The title of this node, always treated as non-markup plain text.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
),
'indexes' => array(
'node_changed' => array('changed'),
'node_created' => array('created'),
),
'unique keys' => array(
'nid_vid' => array('nid', 'vid'),
'vid' => array('vid'),
),
'foreign keys' => array(
'node_revision' => array(
'table' => 'node_field_revision',
'columns' => array('vid' => 'vid'),
),
'node_author' => array(
'table' => 'users',
'columns' => array('uid' => 'uid'),
),
),
'primary key' => array('nid'),
);
return $schema;
}
/**
* Perform alterations to existing database schemas.
*
* When a module modifies the database structure of another module (by
* changing, adding or removing fields, keys or indexes), it should
* implement hook_schema_alter() to update the default $schema to take its
* changes into account.
*
* See hook_schema() for details on the schema definition structure.
*
* @param $schema
* Nested array describing the schemas for all modules.
*
* @ingroup schemaapi
*/
function hook_schema_alter(&$schema) {
// Add field to existing schema.
$schema['users']['fields']['timezone_id'] = array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'Per-user timezone configuration.',
);
}
/**
* Perform alterations to a structured query.
*
* Structured (aka dynamic) queries that have tags associated may be altered by any module
* before the query is executed.
*
* @param $query
* A Query object describing the composite parts of a SQL query.
*
* @see hook_query_TAG_alter()
* @see node_query_node_access_alter()
* @see AlterableInterface
* @see SelectInterface
*/
function hook_query_alter(Drupal\Core\Database\Query\AlterableInterface $query) {
if ($query->hasTag('micro_limit')) {
$query->range(0, 2);
}
}
/**
* Perform alterations to a structured query for a given tag.
*
* @param $query
* An Query object describing the composite parts of a SQL query.
*
* @see hook_query_alter()
* @see node_query_node_access_alter()
* @see AlterableInterface
* @see SelectInterface
*/
function hook_query_TAG_alter(Drupal\Core\Database\Query\AlterableInterface $query) {
// Skip the extra expensive alterations if site has no node access control modules.
if (!node_access_view_all_nodes()) {
// Prevent duplicates records.
$query->distinct();
// The recognized operations are 'view', 'update', 'delete'.
if (!$op = $query->getMetaData('op')) {
$op = 'view';
}
// Skip the extra joins and conditions for node admins.
if (!\Drupal::currentUser()->hasPermission('bypass node access')) {
// The node_access table has the access grants for any given node.
$access_alias = $query->join('node_access', 'na', '%alias.nid = n.nid');
$or = db_or();
// If any grant exists for the specified user, then user has access to the node for the specified operation.
foreach (node_access_grants($op, $query->getMetaData('account')) as $realm => $gids) {
foreach ($gids as $gid) {
$or->condition(db_and()
->condition($access_alias . '.gid', $gid)
->condition($access_alias . '.realm', $realm)
);
}
}
if (count($or->conditions())) {
$query->condition($or);
}
$query->condition($access_alias . 'grant_' . $op, 1, '>=');
}
}
}
/**
* Alter the list of mail backend plugin definitions.
*
* @param array $info
* The mail backend plugin definitions to be altered.
*
* @see \Drupal\Core\Annotation\Mail
* @see \Drupal\Core\Mail\MailManager
*/
function hook_mail_backend_info_alter(&$info) {
unset($info['test_mail_collector']);
}
/**
* Alters theme operation links.
*
* @param $theme_groups
* An associative array containing groups of themes.
*
* @see system_themes_page()
*/
function hook_system_themes_page_alter(&$theme_groups) {
foreach ($theme_groups as $state => &$group) {
foreach ($theme_groups[$state] as &$theme) {
// Add a foo link to each list of theme operations.
$theme->operations[] = array(
'title' => t('Foo'),
'url' => Url::fromRoute('system.themes_page'),
'query' => array('theme' => $theme->getName())
);
}
}
}
/**
* Provide replacement values for placeholder tokens.
*
* This hook is invoked when someone calls
* \Drupal\Core\Utility\Token::replace(). That function first scans the text for
* [type:token] patterns, and splits the needed tokens into groups by type.
* Then hook_tokens() is invoked on each token-type group, allowing your module
* to respond by providing replacement text for any of the tokens in the group
* that your module knows how to process.
*
* A module implementing this hook should also implement hook_token_info() in
* order to list its available tokens on editing screens.
*
* @param $type
* The machine-readable name of the type (group) of token being replaced, such
* as 'node', 'user', or another type defined by a hook_token_info()
* implementation.
* @param $tokens
* An array of tokens to be replaced. The keys are the machine-readable token
* names, and the values are the raw [type:token] strings that appeared in the
* original text.
* @param $data
* (optional) An associative array of data objects to be used when generating
* replacement values, as supplied in the $data parameter to
* \Drupal\Core\Utility\Token::replace().
* @param $options
* (optional) An associative array of options for token replacement; see
* \Drupal\Core\Utility\Token::replace() for possible values.
*
* @return
* An associative array of replacement values, keyed by the raw [type:token]
* strings from the original text.
*
* @see hook_token_info()
* @see hook_tokens_alter()
*/
function hook_tokens($type, $tokens, array $data = array(), array $options = array()) {
$token_service = \Drupal::token();
$url_options = array('absolute' => TRUE);
if (isset($options['langcode'])) {
$url_options['language'] = language_load($options['langcode']);
$langcode = $options['langcode'];
}
else {
$langcode = NULL;
}
$sanitize = !empty($options['sanitize']);
$replacements = array();
if ($type == 'node' && !empty($data['node'])) {
/** @var \Drupal\node\NodeInterface $node */
$node = $data['node'];
foreach ($tokens as $name => $original) {
switch ($name) {
// Simple key values on the node.
case 'nid':
$replacements[$original] = $node->nid;
break;
case 'title':
$replacements[$original] = $sanitize ? String::checkPlain($node->getTitle()) : $node->getTitle();
break;
case 'edit-url':
$replacements[$original] = $node->url('edit-form', $url_options);
break;
// Default values for the chained tokens handled below.
case 'author':
$account = $node->getOwner() ? $node->getOwner() : user_load(0);
$replacements[$original] = $sanitize ? String::checkPlain($account->label()) : $account->label();
break;
case 'created':
$replacements[$original] = format_date($node->getCreatedTime(), 'medium', '', NULL, $langcode);
break;
}
}
if ($author_tokens = $token_service->findWithPrefix($tokens, 'author')) {
$replacements += $token_service->generate('user', $author_tokens, array('user' => $node->getOwner()), $options);
}
if ($created_tokens = $token_service->findWithPrefix($tokens, 'created')) {
$replacements += $token_service->generate('date', $created_tokens, array('date' => $node->getCreatedTime()), $options);
}
}
return $replacements;
}
/**
* Alter replacement values for placeholder tokens.
*
* @param $replacements
* An associative array of replacements returned by hook_tokens().
* @param $context
* The context in which hook_tokens() was called. An associative array with
* the following keys, which have the same meaning as the corresponding
* parameters of hook_tokens():
* - 'type'
* - 'tokens'
* - 'data'
* - 'options'
*
* @see hook_tokens()
*/
function hook_tokens_alter(array &$replacements, array $context) {
$options = $context['options'];
if (isset($options['langcode'])) {
$url_options['language'] = language_load($options['langcode']);
$langcode = $options['langcode'];
}
else {
$langcode = NULL;
}
if ($context['type'] == 'node' && !empty($context['data']['node'])) {
$node = $context['data']['node'];
// Alter the [node:title] token, and replace it with the rendered content
// of a field (field_title).
if (isset($context['tokens']['title'])) {
$title = $node->field_title->view('default');
$replacements[$context['tokens']['title']] = drupal_render($title);
}
}
}
/**
* Provide information about available placeholder tokens and token types.
*
* Tokens are placeholders that can be put into text by using the syntax
* [type:token], where type is the machine-readable name of a token type, and
* token is the machine-readable name of a token within this group. This hook
* provides a list of types and tokens to be displayed on text editing screens,
* so that people editing text can see what their token options are.
*
* The actual token replacement is done by
* \Drupal\Core\Utility\Token::replace(), which invokes hook_tokens(). Your
* module will need to implement that hook in order to generate token
* replacements from the tokens defined here.
*
* @return
* An associative array of available tokens and token types. The outer array
* has two components:
* - types: An associative array of token types (groups). Each token type is
* an associative array with the following components:
* - name: The translated human-readable short name of the token type.
* - description (optional): A translated longer description of the token
* type.
* - needs-data: The type of data that must be provided to
* \Drupal\Core\Utility\Token::replace() in the $data argument (i.e., the
* key name in $data) in order for tokens of this type to be used in the
* $text being processed. For instance, if the token needs a node object,
* 'needs-data' should be 'node', and to use this token in
* \Drupal\Core\Utility\Token::replace(), the caller needs to supply a
* node object as $data['node']. Some token data can also be supplied
* indirectly; for instance, a node object in $data supplies a user object
* (the author of the node), allowing user tokens to be used when only
* a node data object is supplied.
* - tokens: An associative array of tokens. The outer array is keyed by the
* group name (the same key as in the types array). Within each group of
* tokens, each token item is keyed by the machine name of the token, and
* each token item has the following components:
* - name: The translated human-readable short name of the token.
* - description (optional): A translated longer description of the token.
* - type (optional): A 'needs-data' data type supplied by this token, which
* should match a 'needs-data' value from another token type. For example,
* the node author token provides a user object, which can then be used
* for token replacement data in \Drupal\Core\Utility\Token::replace()
* without having to supply a separate user object.
*
* @see hook_token_info_alter()
* @see hook_tokens()
*/
function hook_token_info() {
$type = array(
'name' => t('Nodes'),
'description' => t('Tokens related to individual nodes.'),
'needs-data' => 'node',
);
// Core tokens for nodes.
$node['nid'] = array(
'name' => t("Node ID"),
'description' => t("The unique ID of the node."),
);
$node['title'] = array(
'name' => t("Title"),
);
$node['edit-url'] = array(
'name' => t("Edit URL"),
'description' => t("The URL of the node's edit page."),
);
// Chained tokens for nodes.
$node['created'] = array(
'name' => t("Date created"),
'type' => 'date',
);
$node['author'] = array(
'name' => t("Author"),
'type' => 'user',
);
return array(
'types' => array('node' => $type),
'tokens' => array('node' => $node),
);
}
/**
* Alter the metadata about available placeholder tokens and token types.
*
* @param $data
* The associative array of token definitions from hook_token_info().
*
* @see hook_token_info()
*/
function hook_token_info_alter(&$data) {
// Modify description of node tokens for our site.
$data['tokens']['node']['nid'] = array(
'name' => t("Node ID"),
'description' => t("The unique ID of the article."),
);
$data['tokens']['node']['title'] = array(
'name' => t("Title"),
'description' => t("The title of the article."),
);
// Chained tokens for nodes.
$data['tokens']['node']['created'] = array(
'name' => t("Date created"),
'description' => t("The date the article was posted."),
'type' => 'date',
);
}
/**
* Alter the default country list.
*
* @param $countries
* The associative array of countries keyed by two-letter country code.
*
* @see \Drupal\Core\Locale\CountryManager::getList().
*/
function hook_countries_alter(&$countries) {
// Elbonia is now independent, so add it to the country list.
$countries['EB'] = 'Elbonia';
}
/**
* Alter the parameters for links.
*
* @param array $variables
* An associative array of variables defining a link. The link may be either a
* "route link" using \Drupal\Core\Utility\LinkGenerator::link(), which is
* exposed as the 'link_generator' service or a link generated by _l(). If the
* link is a "route link", 'route_name' will be set, otherwise 'path' will be
* set. The following keys can be altered:
* - text: The link text for the anchor tag as a translated string.
* - url_is_active: Whether or not the link points to the currently active
* URL.
* - url: The \Drupal\Core\Url object.
* - options: An associative array of additional options that will be passed
* to either \Drupal\Core\Routing\UrlGenerator::generateFromPath() or
* \Drupal\Core\Routing\UrlGenerator::generateFromRoute() to generate the
* href attribute for this link, and also used when generating the link.
* Defaults to an empty array. It may contain the following elements:
* - 'query': An array of query key/value-pairs (without any URL-encoding) to
* append to the URL.
* - absolute: Whether to force the output to be an absolute link (beginning
* with http:). Useful for links that will be displayed outside the site,
* such as in an RSS feed. Defaults to FALSE.
* - language: An optional language object. May affect the rendering of
* the anchor tag, such as by adding a language prefix to the path.
* - attributes: An associative array of HTML attributes to apply to the
* anchor tag. If element 'class' is included, it must be an array; 'title'
* must be a string; other elements are more flexible, as they just need
* to work as an argument for the constructor of the class
* Drupal\Core\Template\Attribute($options['attributes']).
* - html: Whether or not HTML should be allowed as the link text. If FALSE,
* the text will be run through
* \Drupal\Component\Utility\String::checkPlain() before being output.
*
* @see \Drupal\Core\Routing\UrlGenerator::generateFromPath()
* @see \Drupal\Core\Routing\UrlGenerator::generateFromRoute()
*/
function hook_link_alter(&$variables) {
// Add a warning to the end of route links to the admin section.
if (isset($variables['route_name']) && strpos($variables['route_name'], 'admin') !== FALSE) {
$variables['text'] .= ' (Warning!)';
}
}
/**
* Alter the configuration synchronization steps.
*
* @param array $sync_steps
* A one-dimensional array of \Drupal\Core\Config\ConfigImporter method names
* or callables that are invoked to complete the import, in the order that
* they will be processed. Each callable item defined in $sync_steps should
* either be a global function or a public static method. The callable should
* accept a $context array by reference. For example:
* <code>
* function _additional_configuration_step(&$context) {
* // Do stuff.
* // If finished set $context['finished'] = 1.
* }
* </code>
* For more information on creating batches, see the
* @link batch Batch operations @endlink documentation.
*
* @see callback_batch_operation()
* @see \Drupal\Core\Config\ConfigImporter::initialize()
*/
function hook_config_import_steps_alter(&$sync_steps, \Drupal\Core\Config\ConfigImporter $config_importer) {
$deletes = $config_importer->getUnprocessedConfiguration('delete');
if (isset($deletes['field.storage.node.body'])) {
$sync_steps[] = '_additional_configuration_step';
}
}
/**
* Alter config typed data definitions.
*
* For example you can alter the typed data types representing each
* configuration schema type to change default labels or form element renderers
* used for configuration translation.
*
* It is strongly advised not to use this hook to add new data types or to
* change the structure of existing ones. Keep in mind that there are tools
* that may use the configuration schema for static analysis of configuration
* files, like the string extractor for the localization system. Such systems
* won't work with dynamically defined configuration schemas.
*
* For adding new data types use configuration schema YAML files instead.
*
* @param $definitions
* Associative array of configuration type definitions keyed by schema type
* names. The elements are themselves array with information about the type.
*/
function hook_config_schema_info_alter(&$definitions) {
// Enhance the text and date type definitions with classes to generate proper
// form elements in ConfigTranslationFormBase. Other translatable types will
// appear as a one line textfield.
$definitions['text']['form_element_class'] = '\Drupal\config_translation\FormElement\Textarea';
$definitions['date_format']['form_element_class'] = '\Drupal\config_translation\FormElement\DateFormat';
}
/**
* @} End of "addtogroup hooks".
*/