listInfo(); 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 node title.', '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, '>='); } } } /** * 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'] = \Drupal::languageManager()->getLanguage($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 ? SafeMarkup::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 ? SafeMarkup::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'] = \Drupal::languageManager()->getLanguage($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 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\SafeMarkup::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: * * function _additional_configuration_step(&$context) { * // Do stuff. * // If finished set $context['finished'] = 1. * } * * 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. * * If implementations of this hook add or remove configuration schema a * ConfigSchemaAlterException will be thrown. 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. * * @see \Drupal\Core\Config\TypedConfigManager * @see \Drupal\Core\Config\Schema\ConfigSchemaAlterException */ 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". */