system.api.php

  1. 7.x drupal/modules/system/system.api.php
  2. 8.x drupal/core/modules/system/system.api.php

Hooks provided by Drupal core and the System module.

Functions

Namesort descending Description
callback_queue_worker Work on a single queue item.
hook_ajax_render_alter Alter the Ajax command data that is sent to the client.
hook_archiver_info_alter Alter archiver information declared by other modules.
hook_batch_alter Alter batch information before a batch is processed.
hook_cache_flush Flush all persistent and static caches.
hook_config_import_steps_alter Alter the configuration synchronization steps.
hook_contextual_links_alter Alter contextual links before they are rendered.
hook_contextual_links_plugins_alter Alter the plugin definition of contextual links.
hook_countries_alter Alter the default country list.
hook_cron Perform periodic actions.
hook_css_alter Alter CSS files before they are output on the page.
hook_data_type_info_alter Alter available data types for typed data wrappers.
hook_element_info Allows modules to declare their own Form API element types and specify their default values.
hook_element_info_alter Alter the element type information returned from modules.
hook_filetransfer_info Register information about FileTransfer classes provided by a module.
hook_filetransfer_info_alter Alter the FileTransfer class registry.
hook_file_download Control access to private file downloads and specify HTTP headers.
hook_file_mimetype_mapping_alter Alter MIME type mappings used to determine MIME type from a file extension.
hook_file_url_alter Alter the URL to a file.
hook_form_alter Perform alterations before a form is rendered.
hook_form_BASE_FORM_ID_alter Provide a form-specific alteration for shared ('base') forms.
hook_form_FORM_ID_alter Provide a form-specific alteration instead of the global hook_form_alter().
hook_help Provide online user help.
hook_hook_info Defines one or more hooks that are exposed by a module.
hook_install Perform setup tasks when the module is installed.
hook_install_tasks Return an array of tasks to be performed by an installation profile.
hook_install_tasks_alter Alter the full list of installation tasks.
hook_js_alter Perform necessary alterations to the JavaScript before it is presented on the page.
hook_library_alter Alters a JavaScript/CSS library before it is attached.
hook_library_info_alter Alters the JavaScript/CSS library registry.
hook_link_alter Alter the parameters for links.
hook_local_tasks_alter Alter local tasks plugins.
hook_mail Prepare a message based on parameters; called from drupal_mail().
hook_mail_alter Alter an email message created with the drupal_mail() function.
hook_mail_backend_info_alter Alter the list of mail backend plugin definitions.
hook_menu_link_defaults_alter Alter links for menus.
hook_menu_local_actions_alter Alter local actions plugins.
hook_menu_local_tasks Alter tabs and actions displayed on the page before they are rendered.
hook_menu_local_tasks_alter Alter tabs and actions displayed on the page before they are rendered.
hook_modules_installed Perform necessary actions after modules are installed.
hook_modules_uninstalled Perform necessary actions after modules are uninstalled.
hook_module_implements_alter Alter the registry of modules implementing a hook.
hook_module_preinstall Perform necessary actions before a module is installed.
hook_module_preuninstall Perform necessary actions before a module is uninstalled.
hook_page_alter Perform alterations before a page is rendered.
hook_page_build Add elements to a page before it is rendered.
hook_permission Define user permissions.
hook_query_alter Perform alterations to a structured query.
hook_query_TAG_alter Perform alterations to a structured query for a given tag.
hook_queue_info Declare queues holding items that need to be run periodically.
hook_queue_info_alter Alter cron queue information before cron runs.
hook_rebuild Rebuild data based upon refreshed caches.
hook_requirements Check installation requirements and do status reporting.
hook_schema Define the current version of the database schema.
hook_schema_alter Perform alterations to existing database schemas.
hook_stream_wrappers Registers PHP stream wrapper implementations associated with a module.
hook_stream_wrappers_alter Alters the list of PHP stream wrapper implementations.
hook_system_breadcrumb_alter Perform alterations to the breadcrumb built by the BreadcrumbManager.
hook_system_info_alter Alter the information parsed from module and theme .info.yml files
hook_system_themes_page_alter Alters theme operation links.
hook_template_preprocess_default_variables_alter Alter the default, hook-independent variables for all templates.
hook_theme Register a module or theme's theme implementations.
hook_theme_registry_alter Alter the theme registry information returned from hook_theme().
hook_tokens Provide replacement values for placeholder tokens.
hook_tokens_alter Alter replacement values for placeholder tokens.
hook_token_info Provide information about available placeholder tokens and token types.
hook_token_info_alter Alter the metadata about available placeholder tokens and token types.
hook_uninstall Remove any information that the module sets.
hook_updater_info Provide information on Updaters (classes that can update Drupal).
hook_updater_info_alter Alter the Updater information array.
hook_update_dependencies Return an array of information about module update dependencies.
hook_update_last_removed Return a number which is no longer available as hook_update_N().
hook_update_N Perform a single update.

File

drupal/core/modules/system/system.api.php
View source
  1. <?php
  2. /**
  3. * @file
  4. * Hooks provided by Drupal core and the System module.
  5. */
  6. use Drupal\Component\Utility\String;
  7. use Drupal\Core\Utility\UpdateException;
  8. /**
  9. * @addtogroup hooks
  10. * @{
  11. */
  12. /**
  13. * Defines one or more hooks that are exposed by a module.
  14. *
  15. * Normally hooks do not need to be explicitly defined. However, by declaring a
  16. * hook explicitly, a module may define a "group" for it. Modules that implement
  17. * a hook may then place their implementation in either $module.module or in
  18. * $module.$group.inc. If the hook is located in $module.$group.inc, then that
  19. * file will be automatically loaded when needed.
  20. * In general, hooks that are rarely invoked and/or are very large should be
  21. * placed in a separate include file, while hooks that are very short or very
  22. * frequently called should be left in the main module file so that they are
  23. * always available.
  24. *
  25. * @return
  26. * An associative array whose keys are hook names and whose values are an
  27. * associative array containing:
  28. * - group: A string defining the group to which the hook belongs. The module
  29. * system will determine whether a file with the name $module.$group.inc
  30. * exists, and automatically load it when required.
  31. *
  32. * See system_hook_info() for all hook groups defined by Drupal core.
  33. *
  34. * @see hook_hook_info_alter().
  35. */
  36. function hook_hook_info() {
  37. $hooks['token_info'] = array(
  38. 'group' => 'tokens',
  39. );
  40. $hooks['tokens'] = array(
  41. 'group' => 'tokens',
  42. );
  43. return $hooks;
  44. }
  45. /**
  46. * Perform periodic actions.
  47. *
  48. * Modules that require some commands to be executed periodically can
  49. * implement hook_cron(). The engine will then call the hook whenever a cron
  50. * run happens, as defined by the administrator. Typical tasks managed by
  51. * hook_cron() are database maintenance, backups, recalculation of settings
  52. * or parameters, automated mailing, and retrieving remote data.
  53. *
  54. * Short-running or non-resource-intensive tasks can be executed directly in
  55. * the hook_cron() implementation.
  56. *
  57. * Long-running tasks and tasks that could time out, such as retrieving remote
  58. * data, sending email, and intensive file tasks, should use the queue API
  59. * instead of executing the tasks directly. To do this, first define one or
  60. * more queues via hook_queue_info(). Then, add items that need to be
  61. * processed to the defined queues.
  62. */
  63. function hook_cron() {
  64. // Short-running operation example, not using a queue:
  65. // Delete all expired records since the last cron run.
  66. $expires = \Drupal::state()->get('mymodule.cron_last_run', REQUEST_TIME);
  67. db_delete('mymodule_table')
  68. ->condition('expires', $expires, '>=')
  69. ->execute();
  70. \Drupal::state()->set('mymodule.cron_last_run', REQUEST_TIME);
  71. // Long-running operation example, leveraging a queue:
  72. // Fetch feeds from other sites.
  73. $result = db_query('SELECT * FROM {aggregator_feed} WHERE checked + refresh < :time AND refresh <> :never', array(
  74. ':time' => REQUEST_TIME,
  75. ':never' => AGGREGATOR_CLEAR_NEVER,
  76. ));
  77. $queue = \Drupal::queue('aggregator_feeds');
  78. foreach ($result as $feed) {
  79. $queue->createItem($feed);
  80. }
  81. }
  82. /**
  83. * Alter available data types for typed data wrappers.
  84. *
  85. * @param array $data_types
  86. * An array of data type information.
  87. *
  88. * @see hook_data_type_info()
  89. */
  90. function hook_data_type_info_alter(&$data_types) {
  91. $data_types['email']['class'] = '\Drupal\mymodule\Type\Email';
  92. }
  93. /**
  94. * Declare queues holding items that need to be run periodically.
  95. *
  96. * While there can be only one hook_cron() process running at the same time,
  97. * there can be any number of processes defined here running. Because of
  98. * this, long running tasks are much better suited for this API. Items queued
  99. * in hook_cron() might be processed in the same cron run if there are not many
  100. * items in the queue, otherwise it might take several requests, which can be
  101. * run in parallel.
  102. *
  103. * You can create queues, add items to them, claim them, etc without declaring
  104. * the queue in this hook if you want, however, you need to take care of
  105. * processing the items in the queue in that case.
  106. *
  107. * @return
  108. * An associative array where the key is the queue name and the value is
  109. * again an associative array. Possible keys are:
  110. * - 'worker callback': A PHP callable to call that is an implementation of
  111. * callback_queue_worker().
  112. * - 'cron': (optional) An associative array containing the optional key:
  113. * - 'time': (optional) How much time Drupal cron should spend on calling
  114. * this worker in seconds. Defaults to 15.
  115. * If the cron key is not defined, the queue will not be processed by cron,
  116. * and must be processed by other means.
  117. *
  118. * @see hook_cron()
  119. * @see hook_queue_info_alter()
  120. */
  121. function hook_queue_info() {
  122. $queues['aggregator_feeds'] = array(
  123. 'title' => t('Aggregator refresh'),
  124. 'worker callback' => array('Drupal\my_module\MyClass', 'aggregatorRefresh'),
  125. // Only needed if this queue should be processed by cron.
  126. 'cron' => array(
  127. 'time' => 60,
  128. ),
  129. );
  130. return $queues;
  131. }
  132. /**
  133. * Alter cron queue information before cron runs.
  134. *
  135. * Called by \Drupal\Core\Cron to allow modules to alter cron queue settings
  136. * before any jobs are processesed.
  137. *
  138. * @param array $queues
  139. * An array of cron queue information.
  140. *
  141. * @see hook_queue_info()
  142. * @see \Drupal\Core\Cron
  143. */
  144. function hook_queue_info_alter(&$queues) {
  145. // This site has many feeds so let's spend 90 seconds on each cron run
  146. // updating feeds instead of the default 60.
  147. $queues['aggregator_feeds']['cron']['time'] = 90;
  148. }
  149. /**
  150. * Work on a single queue item.
  151. *
  152. * Callback for hook_queue_info().
  153. *
  154. * @param $queue_item_data
  155. * The data that was passed to \Drupal\Core\Queue\QueueInterface::createItem()
  156. * when the item was queued.
  157. *
  158. * @throws \Exception
  159. * The worker callback may throw an exception to indicate there was a problem.
  160. * The cron process will log the exception, and leave the item in the queue to
  161. * be processed again later.
  162. * @throws \Drupal\Core\Queue\SuspendQueueException
  163. * More specifically, a SuspendQueueException should be thrown when the
  164. * callback is aware that the problem will affect all subsequent workers of
  165. * its queue. For example, a callback that makes HTTP requests may find that
  166. * the remote server is not responding. The cron process will behave as with a
  167. * normal Exception, and in addition will not attempt to process further items
  168. * from the current item's queue during the current cron run.
  169. *
  170. * @see \Drupal\Core\Cron::run()
  171. */
  172. function callback_queue_worker($queue_item_data) {
  173. $node = node_load($queue_item_data);
  174. $node->title = 'Updated title';
  175. $node->save();
  176. }
  177. /**
  178. * Allows modules to declare their own Form API element types and specify their
  179. * default values.
  180. *
  181. * This hook allows modules to declare their own form element types and to
  182. * specify their default values. The values returned by this hook will be
  183. * merged with the elements returned by form constructor implementations and so
  184. * can return defaults for any Form APIs keys in addition to those explicitly
  185. * documented by \Drupal\Core\Render\ElementInfoInterface::getInfo().
  186. *
  187. * @return array
  188. * An associative array with structure identical to that of the return value
  189. * of \Drupal\Core\Render\ElementInfoInterface::getInfo().
  190. *
  191. * @see hook_element_info_alter()
  192. * @see system_element_info()
  193. */
  194. function hook_element_info() {
  195. $types['filter_format'] = array(
  196. '#input' => TRUE,
  197. );
  198. return $types;
  199. }
  200. /**
  201. * Alter the element type information returned from modules.
  202. *
  203. * A module may implement this hook in order to alter the element type defaults
  204. * defined by a module.
  205. *
  206. * @param array $types
  207. * An associative array with structure identical to that of the return value
  208. * of \Drupal\Core\Render\ElementInfoInterface::getInfo().
  209. *
  210. * @see hook_element_info()
  211. */
  212. function hook_element_info_alter(array &$types) {
  213. // Decrease the default size of textfields.
  214. if (isset($types['textfield']['#size'])) {
  215. $types['textfield']['#size'] = 40;
  216. }
  217. }
  218. /**
  219. * Perform necessary alterations to the JavaScript before it is presented on
  220. * the page.
  221. *
  222. * @param $javascript
  223. * An array of all JavaScript being presented on the page.
  224. *
  225. * @see _drupal_add_js()
  226. * @see drupal_get_js()
  227. * @see drupal_js_defaults()
  228. */
  229. function hook_js_alter(&$javascript) {
  230. // Swap out jQuery to use an updated version of the library.
  231. $javascript['core/assets/vendor/jquery/jquery.js']['data'] = drupal_get_path('module', 'jquery_update') . '/jquery.js';
  232. }
  233. /**
  234. * Alters the JavaScript/CSS library registry.
  235. *
  236. * Allows certain, contributed modules to update libraries to newer versions
  237. * while ensuring backwards compatibility. In general, such manipulations should
  238. * only be done by designated modules, since most modules that integrate with a
  239. * certain library also depend on the API of a certain library version.
  240. *
  241. * @param $libraries
  242. * The JavaScript/CSS libraries provided by $module. Keyed by internal library
  243. * name and passed by reference.
  244. * @param $module
  245. * The name of the module that registered the libraries.
  246. */
  247. function hook_library_info_alter(&$libraries, $module) {
  248. // Update Farbtastic to version 2.0.
  249. if ($module == 'core' && isset($libraries['jquery.farbtastic'])) {
  250. // Verify existing version is older than the one we are updating to.
  251. if (version_compare($libraries['jquery.farbtastic']['version'], '2.0', '<')) {
  252. // Update the existing Farbtastic to version 2.0.
  253. $libraries['jquery.farbtastic']['version'] = '2.0';
  254. // To accurately replace library files, the order of files and the options
  255. // of each file have to be retained; e.g., like this:
  256. $old_path = 'assets/vendor/farbtastic';
  257. // Since the replaced library files are no longer located in a directory
  258. // relative to the original extension, specify an absolute path (relative
  259. // to DRUPAL_ROOT / base_path()) to the new location.
  260. $new_path = '/' . drupal_get_path('module', 'farbtastic_update') . '/js';
  261. $new_js = array();
  262. $replacements = array(
  263. $old_path . '/farbtastic.js' => $new_path . '/farbtastic-2.0.js',
  264. );
  265. foreach ($libraries['jquery.farbtastic']['js'] as $source => $options) {
  266. if (isset($replacements[$source])) {
  267. $new_js[$replacements[$source]] = $options;
  268. }
  269. else {
  270. $new_js[$source] = $options;
  271. }
  272. }
  273. $libraries['jquery.farbtastic']['js'] = $new_js;
  274. }
  275. }
  276. }
  277. /**
  278. * Alters a JavaScript/CSS library before it is attached.
  279. *
  280. * Allows modules and themes to dynamically attach further assets to a library
  281. * when it is added to the page; e.g., to add JavaScript settings.
  282. *
  283. * This hook is only invoked once per library and page.
  284. *
  285. * @param array $library
  286. * The JavaScript/CSS library that is being added.
  287. * @param string $name
  288. * The name of the library.
  289. *
  290. * @see _drupal_add_library()
  291. */
  292. function hook_library_alter(array &$library, $name) {
  293. if ($name == 'core/jquery.ui.datepicker') {
  294. // Note: If the added assets do not depend on additional request-specific
  295. // data supplied here, consider to statically register it directly via
  296. // hook_library_info_alter() already.
  297. $library['dependencies'][] = 'locale/drupal.locale.datepicker';
  298. $language_interface = \Drupal::languageManager()->getCurrentLanguage();
  299. $settings['jquery']['ui']['datepicker'] = array(
  300. 'isRTL' => $language_interface->direction == LanguageInterface::DIRECTION_RTL,
  301. 'firstDay' => \Drupal::config('system.date')->get('first_day'),
  302. );
  303. $library['js'][] = array(
  304. 'type' => 'setting',
  305. 'data' => $settings,
  306. );
  307. }
  308. }
  309. /**
  310. * Alter CSS files before they are output on the page.
  311. *
  312. * @param $css
  313. * An array of all CSS items (files and inline CSS) being requested on the page.
  314. *
  315. * @see _drupal_add_css()
  316. * @see drupal_get_css()
  317. */
  318. function hook_css_alter(&$css) {
  319. // Remove defaults.css file.
  320. unset($css[drupal_get_path('module', 'system') . '/defaults.css']);
  321. }
  322. /**
  323. * Alter the Ajax command data that is sent to the client.
  324. *
  325. * @param \Drupal\Core\Ajax\CommandInterface[] $data
  326. * An array of all the rendered commands that will be sent to the client.
  327. *
  328. * @see \Drupal\Core\Ajax\AjaxResponse::ajaxRender()
  329. */
  330. function hook_ajax_render_alter(array &$data) {
  331. // Inject any new status messages into the content area.
  332. $status_messages = array('#theme' => 'status_messages');
  333. $command = new \Drupal\Core\Ajax\PrependCommand('#block-system-main .content', drupal_render($status_messages));
  334. $data[] = $command->render();
  335. }
  336. /**
  337. * Add elements to a page before it is rendered.
  338. *
  339. * Use this hook when you want to add elements at the page level. For your
  340. * additions to be printed, they have to be placed below a top level array key
  341. * of the $page array that has the name of a region of the active theme.
  342. *
  343. * By default, valid region keys are 'page_top', 'header', 'sidebar_first',
  344. * 'content', 'sidebar_second' and 'page_bottom'. To get a list of all regions
  345. * of the active theme, use system_region_list($theme). Note that $theme is a
  346. * global variable.
  347. *
  348. * If you want to alter the elements added by other modules or if your module
  349. * depends on the elements of other modules, use hook_page_alter() instead which
  350. * runs after this hook.
  351. *
  352. * @param $page
  353. * Nested array of renderable elements that make up the page.
  354. *
  355. * @see hook_page_alter()
  356. * @see drupal_render_page()
  357. */
  358. function hook_page_build(&$page) {
  359. $path = drupal_get_path('module', 'foo');
  360. // Add JavaScript/CSS assets to all pages.
  361. // @see drupal_process_attached()
  362. $page['#attached']['js'][$path . '/foo.js'] = array('every_page' => TRUE);
  363. $page['#attached']['css'][$path . '/foo.base.css'] = array('every_page' => TRUE);
  364. $page['#attached']['css'][$path . '/foo.theme.css'] = array('every_page' => TRUE);
  365. // Add a special CSS file to a certain page only.
  366. if (drupal_is_front_page()) {
  367. $page['#attached']['css'][] = $path . '/foo.front.css';
  368. }
  369. // Append a standard disclaimer to the content region on a node detail page.
  370. if (\Drupal::request()->attributes->get('node')) {
  371. $page['content']['disclaimer'] = array(
  372. '#markup' => t('Acme, Inc. is not responsible for the contents of this sample code.'),
  373. '#weight' => 25,
  374. );
  375. }
  376. }
  377. /**
  378. * Alter links for menus.
  379. *
  380. * @param array $links
  381. * The link definitions to be altered.
  382. *
  383. * @return array
  384. * An array of default menu links. Each link has a key that is the machine
  385. * name, which must be unique. By default, use the route name as the
  386. * machine name. In cases where multiple links use the same route name, such
  387. * as two links to the same page in different menus, or two links using the
  388. * same route name but different route parameters, the suggested machine name
  389. * patten is the route name followed by a dot and a unique suffix. For
  390. * example, an additional logout link might have a machine name of
  391. * user.logout.navigation, and default links provided to edit the article and
  392. * page content types could use machine names node.type_edit.article and
  393. * node.type_edit.page. Since the machine name may be arbitrary, you should
  394. * never write code that assumes it is identical to the route name.
  395. *
  396. * The value corresponding to each machine name key is an associative array
  397. * that may contain the following key-value pairs:
  398. * - title: (required) The untranslated title of the menu link.
  399. * - description: The untranslated description of the link.
  400. * - route_name: (optional) The route name to be used to build the path.
  401. * Either a route_name or a link_path must be provided.
  402. * - route_parameters: (optional) The route parameters to build the path.
  403. * - link_path: (optional) If you have an external link use link_path instead
  404. * of providing a route_name.
  405. * - parent: (optional) The machine name of the link that is this link's menu
  406. * parent.
  407. * - weight: (optional) An integer that determines the relative position of
  408. * items in the menu; higher-weighted items sink. Defaults to 0. Menu items
  409. * with the same weight are ordered alphabetically.
  410. * - menu_name: (optional) The machine name of a menu to put the link in, if
  411. * not the default Tools menu.
  412. * - expanded: (optional) If set to TRUE, and if a menu link is provided for
  413. * this menu item (as a result of other properties), then the menu link is
  414. * always expanded, equivalent to its 'always expanded' checkbox being set
  415. * in the UI.
  416. * - options: (optional) An array of options to be passed to l() when
  417. * generating a link from this menu item.
  418. *
  419. * @ingroup menu
  420. */
  421. function hook_menu_link_defaults_alter(&$links) {
  422. // Change the weight and title of the user.logout link.
  423. $links['user.logout']['weight'] = -10;
  424. $links['user.logout']['title'] = 'Logout';
  425. }
  426. /**
  427. * Alter tabs and actions displayed on the page before they are rendered.
  428. *
  429. * This hook is invoked by menu_local_tasks(). The system-determined tabs and
  430. * actions are passed in by reference. Additional tabs or actions may be added.
  431. *
  432. * Each tab or action is an associative array containing:
  433. * - #theme: The theme function to use to render.
  434. * - #link: An associative array containing:
  435. * - title: The localized title of the link.
  436. * - href: The system path to link to.
  437. * - localized_options: An array of options to pass to l().
  438. * - #weight: The link's weight compared to other links.
  439. * - #active: Whether the link should be marked as 'active'.
  440. *
  441. * @param array $data
  442. * An associative array containing:
  443. * - actions: A list of of actions keyed by their href, each one being an
  444. * associative array as described above.
  445. * - tabs: A list of (up to 2) tab levels that contain a list of of tabs keyed
  446. * by their href, each one being an associative array as described above.
  447. * @param string $route_name
  448. * The route name of the page.
  449. */
  450. function hook_menu_local_tasks(&$data, $route_name) {
  451. // Add an action linking to node/add to all pages.
  452. $data['actions']['node/add'] = array(
  453. '#theme' => 'menu_local_action',
  454. '#link' => array(
  455. 'title' => t('Add content'),
  456. 'href' => 'node/add',
  457. 'localized_options' => array(
  458. 'attributes' => array(
  459. 'title' => t('Add content'),
  460. ),
  461. ),
  462. ),
  463. );
  464. // Add a tab linking to node/add to all pages.
  465. $data['tabs'][0]['node/add'] = array(
  466. '#theme' => 'menu_local_task',
  467. '#link' => array(
  468. 'title' => t('Example tab'),
  469. 'href' => 'node/add',
  470. 'localized_options' => array(
  471. 'attributes' => array(
  472. 'title' => t('Add content'),
  473. ),
  474. ),
  475. ),
  476. );
  477. }
  478. /**
  479. * Alter tabs and actions displayed on the page before they are rendered.
  480. *
  481. * This hook is invoked by menu_local_tasks(). The system-determined tabs and
  482. * actions are passed in by reference. Existing tabs or actions may be altered.
  483. *
  484. * @param array $data
  485. * An associative array containing tabs and actions. See
  486. * hook_menu_local_tasks() for details.
  487. * @param string $route_name
  488. * The route name of the page.
  489. *
  490. * @see hook_menu_local_tasks()
  491. *
  492. * @ingroup menu
  493. */
  494. function hook_menu_local_tasks_alter(&$data, $route_name) {
  495. }
  496. /**
  497. * Alter local actions plugins.
  498. *
  499. * @param array $local_actions
  500. * The array of local action plugin definitions, keyed by plugin ID.
  501. *
  502. * @see \Drupal\Core\Menu\LocalActionInterface
  503. * @see \Drupal\Core\Menu\LocalActionManager
  504. *
  505. * @ingroup menu
  506. */
  507. function hook_menu_local_actions_alter(&$local_actions) {
  508. }
  509. /**
  510. * Alter local tasks plugins.
  511. *
  512. * @param array $local_tasks
  513. * The array of local tasks plugin definitions, keyed by plugin ID.
  514. *
  515. * @see \Drupal\Core\Menu\LocalTaskInterface
  516. * @see \Drupal\Core\Menu\LocalTaskManager
  517. */
  518. function hook_local_tasks_alter(&$local_tasks) {
  519. // Remove a specified local task plugin.
  520. unset($local_tasks['example_plugin_id']);
  521. }
  522. /**
  523. * Alter contextual links before they are rendered.
  524. *
  525. * This hook is invoked by
  526. * \Drupal\Core\Menu\ContextualLinkManager::getContextualLinkPluginsByGroup().
  527. * The system-determined contextual links are passed in by reference. Additional
  528. * links may be added and existing links can be altered.
  529. *
  530. * Each contextual link contains the following entries:
  531. * - title: The localized title of the link.
  532. * - route_name: The route name of the link.
  533. * - route_parameters: The route parameters of the link.
  534. * - localized_options: An array of options to pass to url().
  535. * - (optional) weight: The weight of the link, which is used to sort the links.
  536. *
  537. *
  538. * @param array $links
  539. * An associative array containing contextual links for the given $group,
  540. * as described above. The array keys are used to build CSS class names for
  541. * contextual links and must therefore be unique for each set of contextual
  542. * links.
  543. * @param string $group
  544. * The group of contextual links being rendered.
  545. * @param array $route_parameters.
  546. * The route parameters passed to each route_name of the contextual links.
  547. * For example:
  548. * @code
  549. * array('node' => $node->id())
  550. * @endcode
  551. *
  552. * @see \Drupal\Core\Menu\ContextualLinkManager
  553. *
  554. * @ingroup menu
  555. */
  556. function hook_contextual_links_alter(array &$links, $group, array $route_parameters) {
  557. if ($group == 'menu') {
  558. // Dynamically use the menu name for the title of the menu_edit contextual
  559. // link.
  560. $menu = \Drupal::entityManager()->getStorage('menu')->load($route_parameters['menu']);
  561. $links['menu_edit']['title'] = t('Edit menu: !label', array('!label' => $menu->label()));
  562. }
  563. }
  564. /**
  565. * Alter the plugin definition of contextual links.
  566. *
  567. * @param array $contextual_links
  568. * An array of contextual_links plugin definitions, keyed by contextual link
  569. * ID. Each entry contains the following keys:
  570. * - title: The displayed title of the link
  571. * - route_name: The route_name of the contextual link to be displayed
  572. * - group: The group under which the contextual links should be added to.
  573. * Possible values are e.g. 'node' or 'menu'.
  574. *
  575. * @see \Drupal\Core\Menu\ContextualLinkManager
  576. */
  577. function hook_contextual_links_plugins_alter(array &$contextual_links) {
  578. $contextual_links['menu_edit']['title'] = 'Edit the menu';
  579. }
  580. /**
  581. * Perform alterations before a page is rendered.
  582. *
  583. * Use this hook when you want to remove or alter elements at the page
  584. * level, or add elements at the page level that depend on an other module's
  585. * elements (this hook runs after hook_page_build().
  586. *
  587. * If you are making changes to entities such as forms, menus, or user
  588. * profiles, use those objects' native alter hooks instead (hook_form_alter(),
  589. * for example).
  590. *
  591. * The $page array contains top level elements for each block region:
  592. * @code
  593. * $page['page_top']
  594. * $page['header']
  595. * $page['sidebar_first']
  596. * $page['content']
  597. * $page['sidebar_second']
  598. * $page['page_bottom']
  599. * @endcode
  600. *
  601. * The 'content' element contains the main content of the current page, and its
  602. * structure will vary depending on what module is responsible for building the
  603. * page. Some legacy modules may not return structured content at all: their
  604. * pre-rendered markup will be located in $page['content']['main']['#markup'].
  605. *
  606. * Pages built by Drupal's core Node module use a standard structure:
  607. *
  608. * @code
  609. * // Node body.
  610. * $page['content']['system_main']['nodes'][$nid]['body']
  611. * // Array of links attached to the node (add comments, read more).
  612. * $page['content']['system_main']['nodes'][$nid]['links']
  613. * // The node entity itself.
  614. * $page['content']['system_main']['nodes'][$nid]['#node']
  615. * // The results pager.
  616. * $page['content']['system_main']['pager']
  617. * @endcode
  618. *
  619. * Blocks may be referenced by their module/delta pair within a region:
  620. * @code
  621. * // The login block in the first sidebar region.
  622. * $page['sidebar_first']['user_login']['#block'];
  623. * @endcode
  624. *
  625. * @param $page
  626. * Nested array of renderable elements that make up the page.
  627. *
  628. * @see hook_page_build()
  629. * @see drupal_render_page()
  630. */
  631. function hook_page_alter(&$page) {
  632. // Add help text to the user login block.
  633. $page['sidebar_first']['user_login']['help'] = array(
  634. '#weight' => -10,
  635. '#markup' => t('To post comments or add content, you first have to log in.'),
  636. );
  637. }
  638. /**
  639. * Perform alterations before a form is rendered.
  640. *
  641. * One popular use of this hook is to add form elements to the node form. When
  642. * altering a node form, the node entity can be retrieved by invoking
  643. * $form_state['controller']->getEntity().
  644. *
  645. * In addition to hook_form_alter(), which is called for all forms, there are
  646. * two more specific form hooks available. The first,
  647. * hook_form_BASE_FORM_ID_alter(), allows targeting of a form/forms via a base
  648. * form (if one exists). The second, hook_form_FORM_ID_alter(), can be used to
  649. * target a specific form directly.
  650. *
  651. * The call order is as follows: all existing form alter functions are called
  652. * for module A, then all for module B, etc., followed by all for any base
  653. * theme(s), and finally for the theme itself. The module order is determined
  654. * by system weight, then by module name.
  655. *
  656. * Within each module, form alter hooks are called in the following order:
  657. * first, hook_form_alter(); second, hook_form_BASE_FORM_ID_alter(); third,
  658. * hook_form_FORM_ID_alter(). So, for each module, the more general hooks are
  659. * called first followed by the more specific.
  660. *
  661. * @param $form
  662. * Nested array of form elements that comprise the form.
  663. * @param $form_state
  664. * A keyed array containing the current state of the form. The arguments
  665. * that \Drupal::formBuilder()->getForm() was originally called with are
  666. * available in the array $form_state['build_info']['args'].
  667. * @param $form_id
  668. * String representing the name of the form itself. Typically this is the
  669. * name of the function that generated the form.
  670. *
  671. * @see hook_form_BASE_FORM_ID_alter()
  672. * @see hook_form_FORM_ID_alter()
  673. * @see forms_api_reference.html
  674. */
  675. function hook_form_alter(&$form, &$form_state, $form_id) {
  676. if (isset($form['type']) && $form['type']['#value'] . '_node_settings' == $form_id) {
  677. $upload_enabled_types = \Drupal::config('mymodule.settings')->get('upload_enabled_types');
  678. $form['workflow']['upload_' . $form['type']['#value']] = array(
  679. '#type' => 'radios',
  680. '#title' => t('Attachments'),
  681. '#default_value' => in_array($form['type']['#value'], $upload_enabled_types) ? 1 : 0,
  682. '#options' => array(t('Disabled'), t('Enabled')),
  683. );
  684. // Add a custom submit handler to save the array of types back to the config file.
  685. $form['actions']['submit']['#submit'][] = 'mymodule_upload_enabled_types_submit';
  686. }
  687. }
  688. /**
  689. * Provide a form-specific alteration instead of the global hook_form_alter().
  690. *
  691. * Modules can implement hook_form_FORM_ID_alter() to modify a specific form,
  692. * rather than implementing hook_form_alter() and checking the form ID, or
  693. * using long switch statements to alter multiple forms.
  694. *
  695. * Form alter hooks are called in the following order: hook_form_alter(),
  696. * hook_form_BASE_FORM_ID_alter(), hook_form_FORM_ID_alter(). See
  697. * hook_form_alter() for more details.
  698. *
  699. * @param $form
  700. * Nested array of form elements that comprise the form.
  701. * @param $form_state
  702. * A keyed array containing the current state of the form. The arguments
  703. * that \Drupal::formBuilder()->getForm() was originally called with are
  704. * available in the array $form_state['build_info']['args'].
  705. * @param $form_id
  706. * String representing the name of the form itself. Typically this is the
  707. * name of the function that generated the form.
  708. *
  709. * @see hook_form_alter()
  710. * @see hook_form_BASE_FORM_ID_alter()
  711. * @see \Drupal\Core\Form\FormBuilderInterface::prepareForm()
  712. * @see forms_api_reference.html
  713. */
  714. function hook_form_FORM_ID_alter(&$form, &$form_state, $form_id) {
  715. // Modification for the form with the given form ID goes here. For example, if
  716. // FORM_ID is "user_register_form" this code would run only on the user
  717. // registration form.
  718. // Add a checkbox to registration form about agreeing to terms of use.
  719. $form['terms_of_use'] = array(
  720. '#type' => 'checkbox',
  721. '#title' => t("I agree with the website's terms and conditions."),
  722. '#required' => TRUE,
  723. );
  724. }
  725. /**
  726. * Provide a form-specific alteration for shared ('base') forms.
  727. *
  728. * By default, when \Drupal::formBuilder()->getForm() is called, Drupal looks
  729. * for a function with the same name as the form ID, and uses that function to
  730. * build the form. In contrast, base forms allow multiple form IDs to be mapped
  731. * to a single base (also called 'factory') form function.
  732. *
  733. * Modules can implement hook_form_BASE_FORM_ID_alter() to modify a specific
  734. * base form, rather than implementing hook_form_alter() and checking for
  735. * conditions that would identify the shared form constructor.
  736. *
  737. * To identify the base form ID for a particular form (or to determine whether
  738. * one exists) check the $form_state. The base form ID is stored under
  739. * $form_state['build_info']['base_form_id'].
  740. *
  741. * Form alter hooks are called in the following order: hook_form_alter(),
  742. * hook_form_BASE_FORM_ID_alter(), hook_form_FORM_ID_alter(). See
  743. * hook_form_alter() for more details.
  744. *
  745. * @param $form
  746. * Nested array of form elements that comprise the form.
  747. * @param $form_state
  748. * A keyed array containing the current state of the form.
  749. * @param $form_id
  750. * String representing the name of the form itself. Typically this is the
  751. * name of the function that generated the form.
  752. *
  753. * @see hook_form_alter()
  754. * @see hook_form_FORM_ID_alter()
  755. * @see \Drupal\Core\Form\FormBuilderInterface::prepareForm()
  756. */
  757. function hook_form_BASE_FORM_ID_alter(&$form, &$form_state, $form_id) {
  758. // Modification for the form with the given BASE_FORM_ID goes here. For
  759. // example, if BASE_FORM_ID is "node_form", this code would run on every
  760. // node form, regardless of node type.
  761. // Add a checkbox to the node form about agreeing to terms of use.
  762. $form['terms_of_use'] = array(
  763. '#type' => 'checkbox',
  764. '#title' => t("I agree with the website's terms and conditions."),
  765. '#required' => TRUE,
  766. );
  767. }
  768. /**
  769. * Alter an email message created with the drupal_mail() function.
  770. *
  771. * hook_mail_alter() allows modification of email messages created and sent
  772. * with drupal_mail(). Usage examples include adding and/or changing message
  773. * text, message fields, and message headers.
  774. *
  775. * Email messages sent using functions other than drupal_mail() will not
  776. * invoke hook_mail_alter(). For example, a contributed module directly
  777. * calling the drupal_mail_system()->mail() or PHP mail() function
  778. * will not invoke this hook. All core modules use drupal_mail() for
  779. * messaging, it is best practice but not mandatory in contributed modules.
  780. *
  781. * @param $message
  782. * An array containing the message data. Keys in this array include:
  783. * - 'id':
  784. * The drupal_mail() id of the message. Look at module source code or
  785. * drupal_mail() for possible id values.
  786. * - 'to':
  787. * The address or addresses the message will be sent to. The
  788. * formatting of this string must comply with RFC 2822.
  789. * - 'from':
  790. * The address the message will be marked as being from, which is
  791. * either a custom address or the site-wide default email address.
  792. * - 'subject':
  793. * Subject of the email to be sent. This must not contain any newline
  794. * characters, or the email may not be sent properly.
  795. * - 'body':
  796. * An array of strings containing the message text. The message body is
  797. * created by concatenating the individual array strings into a single text
  798. * string using "\n\n" as a separator.
  799. * - 'headers':
  800. * Associative array containing mail headers, such as From, Sender,
  801. * MIME-Version, Content-Type, etc.
  802. * - 'params':
  803. * An array of optional parameters supplied by the caller of drupal_mail()
  804. * that is used to build the message before hook_mail_alter() is invoked.
  805. * - 'language':
  806. * The language object used to build the message before hook_mail_alter()
  807. * is invoked.
  808. * - 'send':
  809. * Set to FALSE to abort sending this email message.
  810. *
  811. * @see drupal_mail()
  812. */
  813. function hook_mail_alter(&$message) {
  814. if ($message['id'] == 'modulename_messagekey') {
  815. if (!example_notifications_optin($message['to'], $message['id'])) {
  816. // If the recipient has opted to not receive such messages, cancel
  817. // sending.
  818. $message['send'] = FALSE;
  819. return;
  820. }
  821. $message['body'][] = "--\nMail sent out from " . \Drupal::config('system.site')->get('name');
  822. }
  823. }
  824. /**
  825. * Alter the registry of modules implementing a hook.
  826. *
  827. * This hook is invoked during \Drupal::moduleHandler()->getImplementations().
  828. * A module may implement this hook in order to reorder the implementing
  829. * modules, which are otherwise ordered by the module's system weight.
  830. *
  831. * Note that hooks invoked using \Drupal::moduleHandler->alter() can have
  832. * multiple variations(such as hook_form_alter() and hook_form_FORM_ID_alter()).
  833. * \Drupal::moduleHandler->alter() will call all such variants defined by a
  834. * single module in turn. For the purposes of hook_module_implements_alter(),
  835. * these variants are treated as a single hook. Thus, to ensure that your
  836. * implementation of hook_form_FORM_ID_alter() is called at the right time,
  837. * you will have to change the order of hook_form_alter() implementation in
  838. * hook_module_implements_alter().
  839. *
  840. * @param $implementations
  841. * An array keyed by the module's name. The value of each item corresponds
  842. * to a $group, which is usually FALSE, unless the implementation is in a
  843. * file named $module.$group.inc.
  844. * @param $hook
  845. * The name of the module hook being implemented.
  846. */
  847. function hook_module_implements_alter(&$implementations, $hook) {
  848. if ($hook == 'rdf_mapping') {
  849. // Move my_module_rdf_mapping() to the end of the list.
  850. // \Drupal::moduleHandler()->getImplementations()
  851. // iterates through $implementations with a foreach loop which PHP iterates
  852. // in the order that the items were added, so to move an item to the end of
  853. // the array, we remove it and then add it.
  854. $group = $implementations['my_module'];
  855. unset($implementations['my_module']);
  856. $implementations['my_module'] = $group;
  857. }
  858. }
  859. /**
  860. * Perform alterations to the breadcrumb built by the BreadcrumbManager.
  861. *
  862. * @param array $breadcrumb
  863. * An array of breadcrumb link a tags, returned by the breadcrumb manager
  864. * build method, for example
  865. * @code
  866. * array('<a href="/">Home</a>');
  867. * @endcode
  868. * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
  869. * The current route match.
  870. * @param array $context
  871. * May include the following key:
  872. * - builder: the instance of
  873. * \Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface that constructed this
  874. * breadcrumb, or NULL if no builder acted based on the current attributes.
  875. */
  876. function hook_system_breadcrumb_alter(array &$breadcrumb, \Drupal\Core\Routing\RouteMatchInterface $route_match, array $context) {
  877. // Add an item to the end of the breadcrumb.
  878. $breadcrumb[] = Drupal::l(t('Text'), 'example_route_name');
  879. }
  880. /**
  881. * Alter the information parsed from module and theme .info.yml files
  882. *
  883. * This hook is invoked in _system_rebuild_module_data() and in
  884. * _system_rebuild_theme_data(). A module may implement this hook in order to
  885. * add to or alter the data generated by reading the .info.yml file with
  886. * \Drupal\Core\Extension\InfoParser.
  887. *
  888. * @param array $info
  889. * The .info.yml file contents, passed by reference so that it can be altered.
  890. * @param \Drupal\Core\Extension\Extension $file
  891. * Full information about the module or theme.
  892. * @param string $type
  893. * Either 'module' or 'theme', depending on the type of .info.yml file that
  894. * was passed.
  895. */
  896. function hook_system_info_alter(array &$info, \Drupal\Core\Extension\Extension $file, $type) {
  897. // Only fill this in if the .info.yml file does not define a 'datestamp'.
  898. if (empty($info['datestamp'])) {
  899. $info['datestamp'] = $file->getMTime();
  900. }
  901. }
  902. /**
  903. * Define user permissions.
  904. *
  905. * This hook can supply permissions that the module defines, so that they
  906. * can be selected on the user permissions page and used to grant or restrict
  907. * access to actions the module performs.
  908. *
  909. * Permissions are checked using \Drupal::currentUser()->hasPermission().
  910. *
  911. * For a detailed usage example, see page_example.module.
  912. *
  913. * @return
  914. * An array whose keys are permission names and whose corresponding values
  915. * are arrays containing the following key-value pairs:
  916. * - title: The human-readable name of the permission, to be shown on the
  917. * permission administration page. This should be wrapped in the t()
  918. * function so it can be translated.
  919. * - description: (optional) A description of what the permission does. This
  920. * should be wrapped in the t() function so it can be translated.
  921. * - restrict access: (optional) A boolean which can be set to TRUE to
  922. * indicate that site administrators should restrict access to this
  923. * permission to trusted users. This should be used for permissions that
  924. * have inherent security risks across a variety of potential use cases
  925. * (for example, the "administer filters" and "bypass node access"
  926. * permissions provided by Drupal core). When set to TRUE, a standard
  927. * warning message defined in user_admin_permissions() will be displayed
  928. * with the permission on the permission administration page. Defaults
  929. * to FALSE.
  930. * - warning: (optional) A translated warning message to display for this
  931. * permission on the permission administration page. This warning overrides
  932. * the automatic warning generated by 'restrict access' being set to TRUE.
  933. * This should rarely be used, since it is important for all permissions to
  934. * have a clear, consistent security warning that is the same across the
  935. * site. Use the 'description' key instead to provide any information that
  936. * is specific to the permission you are defining.
  937. *
  938. * @ingroup user_api
  939. */
  940. function hook_permission() {
  941. return array(
  942. 'administer my module' => array(
  943. 'title' => t('Administer my module'),
  944. 'description' => t('Perform administration tasks for my module.'),
  945. ),
  946. );
  947. }
  948. /**
  949. * Provide online user help.
  950. *
  951. * By implementing hook_help(), a module can make documentation available to
  952. * the user for the module as a whole, or for specific pages. Help for
  953. * developers should usually be provided via function header comments in the
  954. * code, or in special API example files.
  955. *
  956. * The page-specific help information provided by this hook appears as a system
  957. * help block on that page. The module overview help information is displayed
  958. * by the Help module. It can be accessed from the page at admin/help or from
  959. * the Extend page.
  960. *
  961. * For detailed usage examples of:
  962. * - Module overview help, see content_translation_help(). Module overview
  963. * help should follow
  964. * @link https://drupal.org/node/632280 the standard help template. @endlink
  965. * - Page-specific help using only routes, see book_help().
  966. * - Page-specific help using routes and $request, see block_help().
  967. *
  968. * @param string $route_name
  969. * For page-specific help, use the route name as identified in the
  970. * module's routing.yml file. For module overview help, the route name
  971. * will be in the form of "help.page.$modulename".
  972. * @param Drupal\Core\Routing\RouteMatchInterface $route_match
  973. * The current route match. This can be used to generate different help
  974. * output for different pages that share the same route.
  975. *
  976. * @return string
  977. * A localized string containing the help text.
  978. */
  979. function hook_help($route_name, \Drupal\Core\Routing\RouteMatchInterface $route_match) {
  980. switch ($route_name) {
  981. // Main module help for the block module.
  982. case 'help.page.block':
  983. 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>';
  984. // Help for another path in the block module.
  985. case 'block.admin_display':
  986. 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>';
  987. }
  988. }
  989. /**
  990. * Register a module or theme's theme implementations.
  991. *
  992. * The implementations declared by this hook have several purposes:
  993. * - They can specify how a particular render array is to be rendered as HTML.
  994. * This is usually the case if the theme function is assigned to the render
  995. * array's #theme property.
  996. * - They can return HTML for default calls to _theme().
  997. * - They can return HTML for calls to _theme() for a theme suggestion.
  998. *
  999. * @param array $existing
  1000. * An array of existing implementations that may be used for override
  1001. * purposes. This is primarily useful for themes that may wish to examine
  1002. * existing implementations to extract data (such as arguments) so that
  1003. * it may properly register its own, higher priority implementations.
  1004. * @param $type
  1005. * Whether a theme, module, etc. is being processed. This is primarily useful
  1006. * so that themes tell if they are the actual theme being called or a parent
  1007. * theme. May be one of:
  1008. * - 'module': A module is being checked for theme implementations.
  1009. * - 'base_theme_engine': A theme engine is being checked for a theme that is
  1010. * a parent of the actual theme being used.
  1011. * - 'theme_engine': A theme engine is being checked for the actual theme
  1012. * being used.
  1013. * - 'base_theme': A base theme is being checked for theme implementations.
  1014. * - 'theme': The actual theme in use is being checked.
  1015. * @param $theme
  1016. * The actual name of theme, module, etc. that is being being processed.
  1017. * @param $path
  1018. * The directory path of the theme or module, so that it doesn't need to be
  1019. * looked up.
  1020. *
  1021. * @return array
  1022. * An associative array of information about theme implementations. The keys
  1023. * on the outer array are known as "theme hooks". For simple theme
  1024. * implementations for regular calls to _theme(), the theme hook is the first
  1025. * argument. For theme suggestions, instead of the array key being the base
  1026. * theme hook, the key is a theme suggestion name with the format
  1027. * 'base_hook_name__sub_hook_name'. For render elements, the key is the
  1028. * machine name of the render element. The array values are themselves arrays
  1029. * containing information about the theme hook and its implementation. Each
  1030. * information array must contain either a 'variables' element (for _theme()
  1031. * calls) or a 'render element' element (for render elements), but not both.
  1032. * The following elements may be part of each information array:
  1033. * - variables: Used for _theme() call items only: an array of variables,
  1034. * where the array keys are the names of the variables, and the array
  1035. * values are the default values if they are not passed into _theme().
  1036. * Template implementations receive each array key as a variable in the
  1037. * template file (so they must be legal PHP/Twig variable names). Function
  1038. * implementations are passed the variables in a single $variables function
  1039. * argument.
  1040. * - render element: Used for render element items only: the name of the
  1041. * renderable element or element tree to pass to the theme function. This
  1042. * name is used as the name of the variable that holds the renderable
  1043. * element or tree in preprocess and process functions.
  1044. * - file: The file the implementation resides in. This file will be included
  1045. * prior to the theme being rendered, to make sure that the function or
  1046. * preprocess function (as needed) is actually loaded; this makes it
  1047. * possible to split theme functions out into separate files quite easily.
  1048. * - path: Override the path of the file to be used. Ordinarily the module or
  1049. * theme path will be used, but if the file will not be in the default
  1050. * path, include it here. This path should be relative to the Drupal root
  1051. * directory.
  1052. * - template: If specified, this theme implementation is a template, and
  1053. * this is the template file without an extension. Do not put .html.twig on
  1054. * this file; that extension will be added automatically by the default
  1055. * rendering engine (which is Twig). If 'path' above is specified, the
  1056. * template should also be in this path.
  1057. * - function: If specified, this will be the function name to invoke for
  1058. * this implementation. If neither 'template' nor 'function' is specified,
  1059. * a default function name will be assumed. For example, if a module
  1060. * registers the 'node' theme hook, 'theme_node' will be assigned to its
  1061. * function. If the chameleon theme registers the node hook, it will be
  1062. * assigned 'chameleon_node' as its function.
  1063. * - base hook: Used for _theme() suggestions only: the base theme hook name.
  1064. * Instead of this suggestion's implementation being used directly, the base
  1065. * hook will be invoked with this implementation as its first suggestion.
  1066. * The base hook's files will be included and the base hook's preprocess
  1067. * functions will be called in place of any suggestion's preprocess
  1068. * functions. If an implementation of hook_theme_suggestions_HOOK() (where
  1069. * HOOK is the base hook) changes the suggestion order, a different
  1070. * suggestion may be used in place of this suggestion. If after
  1071. * hook_theme_suggestions_HOOK() this suggestion remains the first
  1072. * suggestion, then this suggestion's function or template will be used to
  1073. * generate the output for _theme().
  1074. * - pattern: A regular expression pattern to be used to allow this theme
  1075. * implementation to have a dynamic name. The convention is to use __ to
  1076. * differentiate the dynamic portion of the theme. For example, to allow
  1077. * forums to be themed individually, the pattern might be: 'forum__'. Then,
  1078. * when the forum is themed, call:
  1079. * @code
  1080. * _theme(array('forum__' . $tid, 'forum'), $forum)
  1081. * @endcode
  1082. * - preprocess functions: A list of functions used to preprocess this data.
  1083. * Ordinarily this won't be used; it's automatically filled in. By default,
  1084. * for a module this will be filled in as template_preprocess_HOOK. For
  1085. * a theme this will be filled in as twig_preprocess and
  1086. * twig_preprocess_HOOK as well as themename_preprocess and
  1087. * themename_preprocess_HOOK.
  1088. * - override preprocess functions: Set to TRUE when a theme does NOT want
  1089. * the standard preprocess functions to run. This can be used to give a
  1090. * theme FULL control over how variables are set. For example, if a theme
  1091. * wants total control over how certain variables in the page.html.twig are
  1092. * set, this can be set to true. Please keep in mind that when this is used
  1093. * by a theme, that theme becomes responsible for making sure necessary
  1094. * variables are set.
  1095. * - type: (automatically derived) Where the theme hook is defined:
  1096. * 'module', 'theme_engine', or 'theme'.
  1097. * - theme path: (automatically derived) The directory path of the theme or
  1098. * module, so that it doesn't need to be looked up.
  1099. *
  1100. * @see hook_theme_registry_alter()
  1101. */
  1102. function hook_theme($existing, $type, $theme, $path) {
  1103. return array(
  1104. 'forum_display' => array(
  1105. 'variables' => array('forums' => NULL, 'topics' => NULL, 'parents' => NULL, 'tid' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL),
  1106. ),
  1107. 'forum_list' => array(
  1108. 'variables' => array('forums' => NULL, 'parents' => NULL, 'tid' => NULL),
  1109. ),
  1110. 'forum_icon' => array(
  1111. 'variables' => array('new_posts' => NULL, 'num_posts' => 0, 'comment_mode' => 0, 'sticky' => 0),
  1112. ),
  1113. 'status_report' => array(
  1114. 'render element' => 'requirements',
  1115. 'file' => 'system.admin.inc',
  1116. ),
  1117. );
  1118. }
  1119. /**
  1120. * Alter the theme registry information returned from hook_theme().
  1121. *
  1122. * The theme registry stores information about all available theme hooks,
  1123. * including which callback functions those hooks will call when triggered,
  1124. * what template files are exposed by these hooks, and so on.
  1125. *
  1126. * Note that this hook is only executed as the theme cache is re-built.
  1127. * Changes here will not be visible until the next cache clear.
  1128. *
  1129. * The $theme_registry array is keyed by theme hook name, and contains the
  1130. * information returned from hook_theme(), as well as additional properties
  1131. * added by \Drupal\Core\Theme\Registry::processExtension().
  1132. *
  1133. * For example:
  1134. * @code
  1135. * $theme_registry['user'] = array(
  1136. * 'variables' => array(
  1137. * 'account' => NULL,
  1138. * ),
  1139. * 'template' => 'core/modules/user/user',
  1140. * 'file' => 'core/modules/user/user.pages.inc',
  1141. * 'type' => 'module',
  1142. * 'theme path' => 'core/modules/user',
  1143. * 'preprocess functions' => array(
  1144. * 0 => 'template_preprocess',
  1145. * 1 => 'template_preprocess_user_profile',
  1146. * ),
  1147. * );
  1148. * @endcode
  1149. *
  1150. * @param $theme_registry
  1151. * The entire cache of theme registry information, post-processing.
  1152. *
  1153. * @see hook_theme()
  1154. * @see \Drupal\Core\Theme\Registry::processExtension()
  1155. */
  1156. function hook_theme_registry_alter(&$theme_registry) {
  1157. // Kill the next/previous forum topic navigation links.
  1158. foreach ($theme_registry['forum_topic_navigation']['preprocess functions'] as $key => $value) {
  1159. if ($value == 'template_preprocess_forum_topic_navigation') {
  1160. unset($theme_registry['forum_topic_navigation']['preprocess functions'][$key]);
  1161. }
  1162. }
  1163. }
  1164. /**
  1165. * Alter the default, hook-independent variables for all templates.
  1166. *
  1167. * Allows modules to provide additional default template variables or manipulate
  1168. * existing. This hook is invoked from template_preprocess() after basic default
  1169. * template variables have been set up and before the next template preprocess
  1170. * function is invoked.
  1171. *
  1172. * Note that the default template variables are statically cached within a
  1173. * request. When adding a template variable that depends on other context, it is
  1174. * your responsibility to appropriately reset the static cache in
  1175. * template_preprocess() when needed:
  1176. * @code
  1177. * drupal_static_reset('template_preprocess');
  1178. * @endcode
  1179. *
  1180. * See user_template_preprocess_default_variables_alter() for an example.
  1181. *
  1182. * @param array $variables
  1183. * An associative array of default template variables, as set up by
  1184. * _template_preprocess_default_variables(). Passed by reference.
  1185. *
  1186. * @see template_preprocess()
  1187. * @see _template_preprocess_default_variables()
  1188. */
  1189. function hook_template_preprocess_default_variables_alter(&$variables) {
  1190. $variables['is_admin'] = \Drupal::currentUser()->hasPermission('access administration pages');
  1191. }
  1192. /**
  1193. * Prepare a message based on parameters; called from drupal_mail().
  1194. *
  1195. * Note that hook_mail(), unlike hook_mail_alter(), is only called on the
  1196. * $module argument to drupal_mail(), not all modules.
  1197. *
  1198. * @param $key
  1199. * An identifier of the mail.
  1200. * @param $message
  1201. * An array to be filled in. Elements in this array include:
  1202. * - id: An ID to identify the mail sent. Look at module source code
  1203. * or drupal_mail() for possible id values.
  1204. * - to: The address or addresses the message will be sent to. The
  1205. * formatting of this string must comply with RFC 2822.
  1206. * - subject: Subject of the email to be sent. This must not contain any
  1207. * newline characters, or the mail may not be sent properly. drupal_mail()
  1208. * sets this to an empty string when the hook is invoked.
  1209. * - body: An array of lines containing the message to be sent. Drupal will
  1210. * format the correct line endings for you. drupal_mail() sets this to an
  1211. * empty array when the hook is invoked.
  1212. * - from: The address the message will be marked as being from, which is
  1213. * set by drupal_mail() to either a custom address or the site-wide
  1214. * default email address when the hook is invoked.
  1215. * - headers: Associative array containing mail headers, such as From,
  1216. * Sender, MIME-Version, Content-Type, etc. drupal_mail() pre-fills
  1217. * several headers in this array.
  1218. * @param $params
  1219. * An array of parameters supplied by the caller of drupal_mail().
  1220. */
  1221. function hook_mail($key, &$message, $params) {
  1222. $account = $params['account'];
  1223. $context = $params['context'];
  1224. $variables = array(
  1225. '%site_name' => \Drupal::config('system.site')->get('name'),
  1226. '%username' => user_format_name($account),
  1227. );
  1228. if ($context['hook'] == 'taxonomy') {
  1229. $entity = $params['entity'];
  1230. $vocabulary = entity_load('taxonomy_vocabulary', $entity->id());
  1231. $variables += array(
  1232. '%term_name' => $entity->name,
  1233. '%term_description' => $entity->description,
  1234. '%term_id' => $entity->id(),
  1235. '%vocabulary_name' => $vocabulary->name,
  1236. '%vocabulary_description' => $vocabulary->description,
  1237. '%vocabulary_id' => $vocabulary->id(),
  1238. );
  1239. }
  1240. // Node-based variable translation is only available if we have a node.
  1241. if (isset($params['node'])) {
  1242. /** @var \Drupal\node\NodeInterface $node */
  1243. $node = $params['node'];
  1244. $variables += array(
  1245. '%uid' => $node->getOwnerId(),
  1246. '%url' => url('node/' . $node->id(), array('absolute' => TRUE)),
  1247. '%node_type' => node_get_type_label($node),
  1248. '%title' => $node->getTitle(),
  1249. '%teaser' => $node->teaser,
  1250. '%body' => $node->body,
  1251. );
  1252. }
  1253. $subject = strtr($context['subject'], $variables);
  1254. $body = strtr($context['message'], $variables);
  1255. $message['subject'] .= str_replace(array("\r", "\n"), '', $subject);
  1256. $message['body'][] = drupal_html_to_text($body);
  1257. }
  1258. /**
  1259. * Flush all persistent and static caches.
  1260. *
  1261. * This hook asks your module to clear all of its static caches,
  1262. * in order to ensure a clean environment for subsequently
  1263. * invoked data rebuilds.
  1264. *
  1265. * Do NOT use this hook for rebuilding information. Only use it to flush custom
  1266. * caches.
  1267. *
  1268. * Static caches using drupal_static() do not need to be reset manually.
  1269. * However, all other static variables that do not use drupal_static() must be
  1270. * manually reset.
  1271. *
  1272. * This hook is invoked by drupal_flush_all_caches(). It runs before module data
  1273. * is updated and before hook_rebuild().
  1274. *
  1275. * @see drupal_flush_all_caches()
  1276. * @see hook_rebuild()
  1277. */
  1278. function hook_cache_flush() {
  1279. if (defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'update') {
  1280. _update_cache_clear();
  1281. }
  1282. }
  1283. /**
  1284. * Rebuild data based upon refreshed caches.
  1285. *
  1286. * This hook allows your module to rebuild its data based on the latest/current
  1287. * module data. It runs after hook_cache_flush() and after all module data has
  1288. * been updated.
  1289. *
  1290. * This hook is only invoked after the system has been completely cleared;
  1291. * i.e., all previously cached data is known to be gone and every API in the
  1292. * system is known to return current information, so your module can safely rely
  1293. * on all available data to rebuild its own.
  1294. *
  1295. * @see hook_cache_flush()
  1296. * @see drupal_flush_all_caches()
  1297. */
  1298. function hook_rebuild() {
  1299. $themes = list_themes();
  1300. foreach ($themes as $theme) {
  1301. _block_rehash($theme->getName());
  1302. }
  1303. }
  1304. /**
  1305. * Perform necessary actions before a module is installed.
  1306. *
  1307. * @param string $module
  1308. * The name of the module about to be installed.
  1309. */
  1310. function hook_module_preinstall($module) {
  1311. mymodule_cache_clear();
  1312. }
  1313. /**
  1314. * Perform necessary actions after modules are installed.
  1315. *
  1316. * This function differs from hook_install() in that it gives all other modules
  1317. * a chance to perform actions when a module is installed, whereas
  1318. * hook_install() is only called on the module actually being installed. See
  1319. * \Drupal\Core\Extension\ModuleHandler::install() for a detailed description of
  1320. * the order in which install hooks are invoked.
  1321. *
  1322. * @param $modules
  1323. * An array of the modules that were installed.
  1324. *
  1325. * @see \Drupal\Core\Extension\ModuleHandler::install()
  1326. * @see hook_install()
  1327. */
  1328. function hook_modules_installed($modules) {
  1329. if (in_array('lousy_module', $modules)) {
  1330. \Drupal::state()->set('mymodule.lousy_module_compatibility', TRUE);
  1331. }
  1332. }
  1333. /**
  1334. * Perform necessary actions before a module is uninstalled.
  1335. *
  1336. * @param string $module
  1337. * The name of the module about to be uninstalled.
  1338. */
  1339. function hook_module_preuninstall($module) {
  1340. mymodule_cache_clear();
  1341. }
  1342. /**
  1343. * Perform necessary actions after modules are uninstalled.
  1344. *
  1345. * This function differs from hook_uninstall() in that it gives all other
  1346. * modules a chance to perform actions when a module is uninstalled, whereas
  1347. * hook_uninstall() is only called on the module actually being uninstalled.
  1348. *
  1349. * It is recommended that you implement this hook if your module stores
  1350. * data that may have been set by other modules.
  1351. *
  1352. * @param $modules
  1353. * An array of the modules that were uninstalled.
  1354. *
  1355. * @see hook_uninstall()
  1356. * @see hook_modules_disabled()
  1357. */
  1358. function hook_modules_uninstalled($modules) {
  1359. if (in_array('lousy_module', $modules)) {
  1360. \Drupal::state()->delete('mymodule.lousy_module_compatibility');
  1361. }
  1362. mymodule_cache_rebuild();
  1363. }
  1364. /**
  1365. * Registers PHP stream wrapper implementations associated with a module.
  1366. *
  1367. * Provide a facility for managing and querying user-defined stream wrappers
  1368. * in PHP. PHP's internal stream_get_wrappers() doesn't return the class
  1369. * registered to handle a stream, which we need to be able to find the handler
  1370. * for class instantiation.
  1371. *
  1372. * If a module registers a scheme that is already registered with PHP, it will
  1373. * be unregistered and replaced with the specified class.
  1374. *
  1375. * @return
  1376. * A nested array, keyed first by scheme name ("public" for "public://"),
  1377. * then keyed by the following values:
  1378. * - 'name' A short string to name the wrapper.
  1379. * - 'class' A string specifying the PHP class that implements the
  1380. * Drupal\Core\StreamWrapper\StreamWrapperInterface interface.
  1381. * - 'description' A string with a short description of what the wrapper does.
  1382. * - 'type' (Optional) A bitmask of flags indicating what type of streams this
  1383. * wrapper will access - local or remote, readable and/or writeable, etc.
  1384. * Many shortcut constants are defined in file.inc. Defaults to
  1385. * STREAM_WRAPPERS_NORMAL which includes all of these bit flags:
  1386. * - STREAM_WRAPPERS_READ
  1387. * - STREAM_WRAPPERS_WRITE
  1388. * - STREAM_WRAPPERS_VISIBLE
  1389. *
  1390. * @see file_get_stream_wrappers()
  1391. * @see hook_stream_wrappers_alter()
  1392. * @see system_stream_wrappers()
  1393. */
  1394. function hook_stream_wrappers() {
  1395. return array(
  1396. 'public' => array(
  1397. 'name' => t('Public files'),
  1398. 'class' => 'Drupal\Core\StreamWrapper\PublicStream',
  1399. 'description' => t('Public local files served by the webserver.'),
  1400. 'type' => STREAM_WRAPPERS_LOCAL_NORMAL,
  1401. ),
  1402. 'private' => array(
  1403. 'name' => t('Private files'),
  1404. 'class' => 'Drupal\Core\StreamWrapper\PrivateStream',
  1405. 'description' => t('Private local files served by Drupal.'),
  1406. 'type' => STREAM_WRAPPERS_LOCAL_NORMAL,
  1407. ),
  1408. 'temp' => array(
  1409. 'name' => t('Temporary files'),
  1410. 'class' => 'Drupal\Core\StreamWrapper\TemporaryStream',
  1411. 'description' => t('Temporary local files for upload and previews.'),
  1412. 'type' => STREAM_WRAPPERS_LOCAL_HIDDEN,
  1413. ),
  1414. 'cdn' => array(
  1415. 'name' => t('Content delivery network files'),
  1416. // @todo: Fix the name of this class when we decide on module PSR-0 usage.
  1417. 'class' => 'MyModuleCDNStream',
  1418. 'description' => t('Files served by a content delivery network.'),
  1419. // 'type' can be omitted to use the default of STREAM_WRAPPERS_NORMAL
  1420. ),
  1421. 'youtube' => array(
  1422. 'name' => t('YouTube video'),
  1423. // @todo: Fix the name of this class when we decide on module PSR-0 usage.
  1424. 'class' => 'MyModuleYouTubeStream',
  1425. 'description' => t('Video streamed from YouTube.'),
  1426. // A module implementing YouTube integration may decide to support using
  1427. // the YouTube API for uploading video, but here, we assume that this
  1428. // particular module only supports playing YouTube video.
  1429. 'type' => STREAM_WRAPPERS_READ_VISIBLE,
  1430. ),
  1431. );
  1432. }
  1433. /**
  1434. * Alters the list of PHP stream wrapper implementations.
  1435. *
  1436. * @see file_get_stream_wrappers()
  1437. * @see hook_stream_wrappers()
  1438. */
  1439. function hook_stream_wrappers_alter(&$wrappers) {
  1440. // Change the name of private files to reflect the performance.
  1441. $wrappers['private']['name'] = t('Slow files');
  1442. }
  1443. /**
  1444. * Control access to private file downloads and specify HTTP headers.
  1445. *
  1446. * This hook allows modules to enforce permissions on file downloads whenever
  1447. * Drupal is handling file download, as opposed to the web server bypassing
  1448. * Drupal and returning the file from a public directory. Modules can also
  1449. * provide headers to specify information like the file's name or MIME type.
  1450. *
  1451. * @param $uri
  1452. * The URI of the file.
  1453. * @return
  1454. * If the user does not have permission to access the file, return -1. If the
  1455. * user has permission, return an array with the appropriate headers. If the
  1456. * file is not controlled by the current module, the return value should be
  1457. * NULL.
  1458. *
  1459. * @see file_download()
  1460. */
  1461. function hook_file_download($uri) {
  1462. // Check to see if this is a config download.
  1463. $scheme = file_uri_scheme($uri);
  1464. $target = file_uri_target($uri);
  1465. if ($scheme == 'temporary' && $target == 'config.tar.gz') {
  1466. return array(
  1467. 'Content-disposition' => 'attachment; filename="config.tar.gz"',
  1468. );
  1469. }
  1470. }
  1471. /**
  1472. * Alter the URL to a file.
  1473. *
  1474. * This hook is called from file_create_url(), and is called fairly
  1475. * frequently (10+ times per page), depending on how many files there are in a
  1476. * given page.
  1477. * If CSS and JS aggregation are disabled, this can become very frequently
  1478. * (50+ times per page) so performance is critical.
  1479. *
  1480. * This function should alter the URI, if it wants to rewrite the file URL.
  1481. *
  1482. * @param $uri
  1483. * The URI to a file for which we need an external URL, or the path to a
  1484. * shipped file.
  1485. */
  1486. function hook_file_url_alter(&$uri) {
  1487. $user = \Drupal::currentUser();
  1488. // User 1 will always see the local file in this example.
  1489. if ($user->id() == 1) {
  1490. return;
  1491. }
  1492. $cdn1 = 'http://cdn1.example.com';
  1493. $cdn2 = 'http://cdn2.example.com';
  1494. $cdn_extensions = array('css', 'js', 'gif', 'jpg', 'jpeg', 'png');
  1495. // Most CDNs don't support private file transfers without a lot of hassle,
  1496. // so don't support this in the common case.
  1497. $schemes = array('public');
  1498. $scheme = file_uri_scheme($uri);
  1499. // Only serve shipped files and public created files from the CDN.
  1500. if (!$scheme || in_array($scheme, $schemes)) {
  1501. // Shipped files.
  1502. if (!$scheme) {
  1503. $path = $uri;
  1504. }
  1505. // Public created files.
  1506. else {
  1507. $wrapper = file_stream_wrapper_get_instance_by_scheme($scheme);
  1508. $path = $wrapper->getDirectoryPath() . '/' . file_uri_target($uri);
  1509. }
  1510. // Clean up Windows paths.
  1511. $path = str_replace('\\', '/', $path);
  1512. // Serve files with one of the CDN extensions from CDN 1, all others from
  1513. // CDN 2.
  1514. $pathinfo = pathinfo($path);
  1515. if (isset($pathinfo['extension']) && in_array($pathinfo['extension'], $cdn_extensions)) {
  1516. $uri = $cdn1 . '/' . $path;
  1517. }
  1518. else {
  1519. $uri = $cdn2 . '/' . $path;
  1520. }
  1521. }
  1522. }
  1523. /**
  1524. * Check installation requirements and do status reporting.
  1525. *
  1526. * This hook has three closely related uses, determined by the $phase argument:
  1527. * - Checking installation requirements ($phase == 'install').
  1528. * - Checking update requirements ($phase == 'update').
  1529. * - Status reporting ($phase == 'runtime').
  1530. *
  1531. * Note that this hook, like all others dealing with installation and updates,
  1532. * must reside in a module_name.install file, or it will not properly abort
  1533. * the installation of the module if a critical requirement is missing.
  1534. *
  1535. * During the 'install' phase, modules can for example assert that
  1536. * library or server versions are available or sufficient.
  1537. * Note that the installation of a module can happen during installation of
  1538. * Drupal itself (by install.php) with an installation profile or later by hand.
  1539. * As a consequence, install-time requirements must be checked without access
  1540. * to the full Drupal API, because it is not available during install.php.
  1541. * If a requirement has a severity of REQUIREMENT_ERROR, install.php will abort
  1542. * or at least the module will not install.
  1543. * Other severity levels have no effect on the installation.
  1544. * Module dependencies do not belong to these installation requirements,
  1545. * but should be defined in the module's .info.yml file.
  1546. *
  1547. * The 'runtime' phase is not limited to pure installation requirements
  1548. * but can also be used for more general status information like maintenance
  1549. * tasks and security issues.
  1550. * The returned 'requirements' will be listed on the status report in the
  1551. * administration section, with indication of the severity level.
  1552. * Moreover, any requirement with a severity of REQUIREMENT_ERROR severity will
  1553. * result in a notice on the administration configuration page.
  1554. *
  1555. * @param $phase
  1556. * The phase in which requirements are checked:
  1557. * - install: The module is being installed.
  1558. * - update: The module is enabled and update.php is run.
  1559. * - runtime: The runtime requirements are being checked and shown on the
  1560. * status report page.
  1561. *
  1562. * @return
  1563. * An associative array where the keys are arbitrary but must be unique (it
  1564. * is suggested to use the module short name as a prefix) and the values are
  1565. * themselves associative arrays with the following elements:
  1566. * - title: The name of the requirement.
  1567. * - value: The current value (e.g., version, time, level, etc). During
  1568. * install phase, this should only be used for version numbers, do not set
  1569. * it if not applicable.
  1570. * - description: The description of the requirement/status.
  1571. * - severity: The requirement's result/severity level, one of:
  1572. * - REQUIREMENT_INFO: For info only.
  1573. * - REQUIREMENT_OK: The requirement is satisfied.
  1574. * - REQUIREMENT_WARNING: The requirement failed with a warning.
  1575. * - REQUIREMENT_ERROR: The requirement failed with an error.
  1576. */
  1577. function hook_requirements($phase) {
  1578. $requirements = array();
  1579. // Report Drupal version
  1580. if ($phase == 'runtime') {
  1581. $requirements['drupal'] = array(
  1582. 'title' => t('Drupal'),
  1583. 'value' => \Drupal::VERSION,
  1584. 'severity' => REQUIREMENT_INFO
  1585. );
  1586. }
  1587. // Test PHP version
  1588. $requirements['php'] = array(
  1589. 'title' => t('PHP'),
  1590. 'value' => ($phase == 'runtime') ? l(phpversion(), 'admin/reports/status/php') : phpversion(),
  1591. );
  1592. if (version_compare(phpversion(), DRUPAL_MINIMUM_PHP) < 0) {
  1593. $requirements['php']['description'] = t('Your PHP installation is too old. Drupal requires at least PHP %version.', array('%version' => DRUPAL_MINIMUM_PHP));
  1594. $requirements['php']['severity'] = REQUIREMENT_ERROR;
  1595. }
  1596. // Report cron status
  1597. if ($phase == 'runtime') {
  1598. $cron_last = \Drupal::state()->get('system.cron_last');
  1599. if (is_numeric($cron_last)) {
  1600. $requirements['cron']['value'] = t('Last run !time ago', array('!time' => \Drupal::service('date')->formatInterval(REQUEST_TIME - $cron_last)));
  1601. }
  1602. else {
  1603. $requirements['cron'] = array(
  1604. 'description' => t('Cron has not run. It appears cron jobs have not been setup on your system. Check the help pages for <a href="@url">configuring cron jobs</a>.', array('@url' => 'http://drupal.org/cron')),
  1605. 'severity' => REQUIREMENT_ERROR,
  1606. 'value' => t('Never run'),
  1607. );
  1608. }
  1609. $requirements['cron']['description'] .= ' ' . t('You can <a href="@cron">run cron manually</a>.', array('@cron' => url('admin/reports/status/run-cron')));
  1610. $requirements['cron']['title'] = t('Cron maintenance tasks');
  1611. }
  1612. return $requirements;
  1613. }
  1614. /**
  1615. * Define the current version of the database schema.
  1616. *
  1617. * A Drupal schema definition is an array structure representing one or more
  1618. * tables and their related keys and indexes. A schema is defined by
  1619. * hook_schema() which must live in your module's .install file.
  1620. *
  1621. * The tables declared by this hook will be automatically created when the
  1622. * module is installed, and removed when the module is uninstalled. This happens
  1623. * before hook_install() is invoked, and after hook_uninstall() is invoked,
  1624. * respectively.
  1625. *
  1626. * By declaring the tables used by your module via an implementation of
  1627. * hook_schema(), these tables will be available on all supported database
  1628. * engines. You don't have to deal with the different SQL dialects for table
  1629. * creation and alteration of the supported database engines.
  1630. *
  1631. * See the Schema API Handbook at http://drupal.org/node/146843 for details on
  1632. * schema definition structures.
  1633. *
  1634. * @return array
  1635. * A schema definition structure array. For each element of the
  1636. * array, the key is a table name and the value is a table structure
  1637. * definition.
  1638. *
  1639. * @see hook_schema_alter()
  1640. *
  1641. * @ingroup schemaapi
  1642. */
  1643. function hook_schema() {
  1644. $schema['node'] = array(
  1645. // Example (partial) specification for table "node".
  1646. 'description' => 'The base table for nodes.',
  1647. 'fields' => array(
  1648. 'nid' => array(
  1649. 'description' => 'The primary identifier for a node.',
  1650. 'type' => 'serial',
  1651. 'unsigned' => TRUE,
  1652. 'not null' => TRUE,
  1653. ),
  1654. 'vid' => array(
  1655. 'description' => 'The current {node_field_revision}.vid version identifier.',
  1656. 'type' => 'int',
  1657. 'unsigned' => TRUE,
  1658. 'not null' => TRUE,
  1659. 'default' => 0,
  1660. ),
  1661. 'type' => array(
  1662. 'description' => 'The type of this node.',
  1663. 'type' => 'varchar',
  1664. 'length' => 32,
  1665. 'not null' => TRUE,
  1666. 'default' => '',
  1667. ),
  1668. 'title' => array(
  1669. 'description' => 'The title of this node, always treated as non-markup plain text.',
  1670. 'type' => 'varchar',
  1671. 'length' => 255,
  1672. 'not null' => TRUE,
  1673. 'default' => '',
  1674. ),
  1675. ),
  1676. 'indexes' => array(
  1677. 'node_changed' => array('changed'),
  1678. 'node_created' => array('created'),
  1679. ),
  1680. 'unique keys' => array(
  1681. 'nid_vid' => array('nid', 'vid'),
  1682. 'vid' => array('vid'),
  1683. ),
  1684. 'foreign keys' => array(
  1685. 'node_revision' => array(
  1686. 'table' => 'node_field_revision',
  1687. 'columns' => array('vid' => 'vid'),
  1688. ),
  1689. 'node_author' => array(
  1690. 'table' => 'users',
  1691. 'columns' => array('uid' => 'uid'),
  1692. ),
  1693. ),
  1694. 'primary key' => array('nid'),
  1695. );
  1696. return $schema;
  1697. }
  1698. /**
  1699. * Perform alterations to existing database schemas.
  1700. *
  1701. * When a module modifies the database structure of another module (by
  1702. * changing, adding or removing fields, keys or indexes), it should
  1703. * implement hook_schema_alter() to update the default $schema to take its
  1704. * changes into account.
  1705. *
  1706. * See hook_schema() for details on the schema definition structure.
  1707. *
  1708. * @param $schema
  1709. * Nested array describing the schemas for all modules.
  1710. *
  1711. * @ingroup schemaapi
  1712. */
  1713. function hook_schema_alter(&$schema) {
  1714. // Add field to existing schema.
  1715. $schema['users']['fields']['timezone_id'] = array(
  1716. 'type' => 'int',
  1717. 'not null' => TRUE,
  1718. 'default' => 0,
  1719. 'description' => 'Per-user timezone configuration.',
  1720. );
  1721. }
  1722. /**
  1723. * Perform alterations to a structured query.
  1724. *
  1725. * Structured (aka dynamic) queries that have tags associated may be altered by any module
  1726. * before the query is executed.
  1727. *
  1728. * @param $query
  1729. * A Query object describing the composite parts of a SQL query.
  1730. *
  1731. * @see hook_query_TAG_alter()
  1732. * @see node_query_node_access_alter()
  1733. * @see AlterableInterface
  1734. * @see SelectInterface
  1735. */
  1736. function hook_query_alter(Drupal\Core\Database\Query\AlterableInterface $query) {
  1737. if ($query->hasTag('micro_limit')) {
  1738. $query->range(0, 2);
  1739. }
  1740. }
  1741. /**
  1742. * Perform alterations to a structured query for a given tag.
  1743. *
  1744. * @param $query
  1745. * An Query object describing the composite parts of a SQL query.
  1746. *
  1747. * @see hook_query_alter()
  1748. * @see node_query_node_access_alter()
  1749. * @see AlterableInterface
  1750. * @see SelectInterface
  1751. */
  1752. function hook_query_TAG_alter(Drupal\Core\Database\Query\AlterableInterface $query) {
  1753. // Skip the extra expensive alterations if site has no node access control modules.
  1754. if (!node_access_view_all_nodes()) {
  1755. // Prevent duplicates records.
  1756. $query->distinct();
  1757. // The recognized operations are 'view', 'update', 'delete'.
  1758. if (!$op = $query->getMetaData('op')) {
  1759. $op = 'view';
  1760. }
  1761. // Skip the extra joins and conditions for node admins.
  1762. if (!\Drupal::currentUser()->hasPermission('bypass node access')) {
  1763. // The node_access table has the access grants for any given node.
  1764. $access_alias = $query->join('node_access', 'na', '%alias.nid = n.nid');
  1765. $or = db_or();
  1766. // If any grant exists for the specified user, then user has access to the node for the specified operation.
  1767. foreach (node_access_grants($op, $query->getMetaData('account')) as $realm => $gids) {
  1768. foreach ($gids as $gid) {
  1769. $or->condition(db_and()
  1770. ->condition($access_alias . '.gid', $gid)
  1771. ->condition($access_alias . '.realm', $realm)
  1772. );
  1773. }
  1774. }
  1775. if (count($or->conditions())) {
  1776. $query->condition($or);
  1777. }
  1778. $query->condition($access_alias . 'grant_' . $op, 1, '>=');
  1779. }
  1780. }
  1781. }
  1782. /**
  1783. * Perform setup tasks when the module is installed.
  1784. *
  1785. * If the module implements hook_schema(), the database tables will
  1786. * be created before this hook is fired.
  1787. *
  1788. * Implementations of this hook are by convention declared in the module's
  1789. * .install file. The implementation can rely on the .module file being loaded.
  1790. * The hook will only be called when a module is installed. The module's schema
  1791. * version will be set to the module's greatest numbered update hook. Because of
  1792. * this, any time a hook_update_N() is added to the module, this function needs
  1793. * to be updated to reflect the current version of the database schema.
  1794. *
  1795. * See the @link http://drupal.org/node/146843 Schema API documentation @endlink
  1796. * for details on hook_schema and how database tables are defined.
  1797. *
  1798. * Note that since this function is called from a full bootstrap, all functions
  1799. * (including those in modules enabled by the current page request) are
  1800. * available when this hook is called. Use cases could be displaying a user
  1801. * message, or calling a module function necessary for initial setup, etc.
  1802. *
  1803. * Please be sure that anything added or modified in this function that can
  1804. * be removed during uninstall should be removed with hook_uninstall().
  1805. *
  1806. * @see hook_schema()
  1807. * @see \Drupal\Core\Extension\ModuleHandler::install()
  1808. * @see hook_uninstall()
  1809. * @see hook_modules_installed()
  1810. */
  1811. function hook_install() {
  1812. // Create the styles directory and ensure it's writable.
  1813. $directory = file_default_scheme() . '://styles';
  1814. $mode = isset($GLOBALS['install_state']['mode']) ? $GLOBALS['install_state']['mode'] : NULL;
  1815. file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS, $mode);
  1816. }
  1817. /**
  1818. * Perform a single update.
  1819. *
  1820. * For each change that requires one or more actions to be performed when
  1821. * updating a site, add a new hook_update_N(), which will be called by
  1822. * update.php. The documentation block preceding this function is stripped of
  1823. * newlines and used as the description for the update on the pending updates
  1824. * task list. Schema updates should adhere to the
  1825. * @link http://drupal.org/node/150215 Schema API. @endlink
  1826. *
  1827. * Implementations of hook_update_N() are named (module name)_update_(number).
  1828. * The numbers are composed of three parts:
  1829. * - 1 digit for Drupal core compatibility.
  1830. * - 1 digit for your module's major release version (e.g., is this the 8.x-1.*
  1831. * (1) or 8.x-2.* (2) series of your module).
  1832. * - 2 digits for sequential counting, starting with 01.
  1833. *
  1834. * Examples:
  1835. * - mymodule_update_8100(): This is the first update to get the database ready
  1836. * to run mymodule 8.x-1.*.
  1837. * - mymodule_update_8200(): This is the first update to get the database ready
  1838. * to run mymodule 8.x-2.*.
  1839. *
  1840. * As of Drupal 8.0, the database upgrade system no longer supports updating a
  1841. * database from an earlier major version of Drupal: update.php can be used to
  1842. * upgrade from 7.x-1.x to 7.x-2.x, or 8.x-1.x to 8.x-2.x, but not from 7.x to
  1843. * 8.x. Therefore, only update hooks numbered 8001 or later will run for
  1844. * Drupal 8. 8000 is reserved for the minimum core schema version and defining
  1845. * mymodule_update_8000() will result in an exception. Use the
  1846. * @link https://drupal.org/node/2127611 Migration API @endlink instead to
  1847. * migrate data from an earlier major version of Drupal.
  1848. *
  1849. * For further information about releases and release numbers see:
  1850. * @link http://drupal.org/node/711070 Maintaining a drupal.org project with Git @endlink
  1851. *
  1852. * Never renumber update functions.
  1853. *
  1854. * Implementations of this hook should be placed in a mymodule.install file in
  1855. * the same directory as mymodule.module. Drupal core's updates are implemented
  1856. * using the system module as a name and stored in database/updates.inc.
  1857. *
  1858. * Not all module functions are available from within a hook_update_N() function.
  1859. * In order to call a function from your mymodule.module or an include file,
  1860. * you need to explicitly load that file first.
  1861. *
  1862. * During database updates the schema of any module could be out of date. For
  1863. * this reason, caution is needed when using any API function within an update
  1864. * function - particularly CRUD functions, functions that depend on the schema
  1865. * (for example by using drupal_write_record()), and any functions that invoke
  1866. * hooks.
  1867. *
  1868. * The $sandbox parameter should be used when a multipass update is needed, in
  1869. * circumstances where running the whole update at once could cause PHP to
  1870. * timeout. Each pass is run in a way that avoids PHP timeouts, provided each
  1871. * pass remains under the timeout limit. To signify that an update requires
  1872. * at least one more pass, set $sandbox['#finished'] to a number less than 1
  1873. * (you need to do this each pass). The value of $sandbox['#finished'] will be
  1874. * unset between passes but all other data in $sandbox will be preserved. The
  1875. * system will stop iterating this update when $sandbox['#finished'] is left
  1876. * unset or set to a number higher than 1. It is recommended that
  1877. * $sandbox['#finished'] is initially set to 0, and then updated each pass to a
  1878. * number between 0 and 1 that represents the overall % completed for this
  1879. * update, finishing with 1.
  1880. *
  1881. * See the @link batch Batch operations topic @endlink for more information on
  1882. * how to use the Batch API.
  1883. *
  1884. * @param array $sandbox
  1885. * Stores information for multipass updates. See above for more information.
  1886. *
  1887. * @throws \Drupal\Core\Utility\UpdateException|PDOException
  1888. * In case of error, update hooks should throw an instance of
  1889. * Drupal\Core\Utility\UpdateException with a meaningful message for the user.
  1890. * If a database query fails for whatever reason, it will throw a
  1891. * PDOException.
  1892. *
  1893. * @return string|null
  1894. * Optionally, update hooks may return a translated string that will be
  1895. * displayed to the user after the update has completed. If no message is
  1896. * returned, no message will be presented to the user.
  1897. *
  1898. * @see batch
  1899. * @see schemaapi
  1900. * @see hook_update_last_removed()
  1901. * @see update_get_update_list()
  1902. */
  1903. function hook_update_N(&$sandbox) {
  1904. // For non-multipass updates, the signature can simply be;
  1905. // function hook_update_N() {
  1906. // For most updates, the following is sufficient.
  1907. db_add_field('mytable1', 'newcol', array('type' => 'int', 'not null' => TRUE, 'description' => 'My new integer column.'));
  1908. // However, for more complex operations that may take a long time,
  1909. // you may hook into Batch API as in the following example.
  1910. // Update 3 users at a time to have an exclamation point after their names.
  1911. // (They're really happy that we can do batch API in this hook!)
  1912. if (!isset($sandbox['progress'])) {
  1913. $sandbox['progress'] = 0;
  1914. $sandbox['current_uid'] = 0;
  1915. // We'll -1 to disregard the uid 0...
  1916. $sandbox['max'] = db_query('SELECT COUNT(DISTINCT uid) FROM {users}')->fetchField() - 1;
  1917. }
  1918. $users = db_select('users', 'u')
  1919. ->fields('u', array('uid', 'name'))
  1920. ->condition('uid', $sandbox['current_uid'], '>')
  1921. ->range(0, 3)
  1922. ->orderBy('uid', 'ASC')
  1923. ->execute();
  1924. foreach ($users as $user) {
  1925. $user->setUsername($user->getUsername() . '!');
  1926. db_update('users')
  1927. ->fields(array('name' => $user->getUsername()))
  1928. ->condition('uid', $user->id())
  1929. ->execute();
  1930. $sandbox['progress']++;
  1931. $sandbox['current_uid'] = $user->id();
  1932. }
  1933. $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);
  1934. if ($some_error_condition_met) {
  1935. // In case of an error, simply throw an exception with an error message.
  1936. throw new UpdateException('Something went wrong; here is what you should do.');
  1937. }
  1938. // To display a message to the user when the update is completed, return it.
  1939. // If you do not want to display a completion message, simply return nothing.
  1940. return t('The update did what it was supposed to do.');
  1941. }
  1942. /**
  1943. * Return an array of information about module update dependencies.
  1944. *
  1945. * This can be used to indicate update functions from other modules that your
  1946. * module's update functions depend on, or vice versa. It is used by the update
  1947. * system to determine the appropriate order in which updates should be run, as
  1948. * well as to search for missing dependencies.
  1949. *
  1950. * Implementations of this hook should be placed in a mymodule.install file in
  1951. * the same directory as mymodule.module.
  1952. *
  1953. * @return
  1954. * A multidimensional array containing information about the module update
  1955. * dependencies. The first two levels of keys represent the module and update
  1956. * number (respectively) for which information is being returned, and the
  1957. * value is an array of information about that update's dependencies. Within
  1958. * this array, each key represents a module, and each value represents the
  1959. * number of an update function within that module. In the event that your
  1960. * update function depends on more than one update from a particular module,
  1961. * you should always list the highest numbered one here (since updates within
  1962. * a given module always run in numerical order).
  1963. *
  1964. * @see update_resolve_dependencies()
  1965. * @see hook_update_N()
  1966. */
  1967. function hook_update_dependencies() {
  1968. // Indicate that the mymodule_update_8001() function provided by this module
  1969. // must run after the another_module_update_8003() function provided by the
  1970. // 'another_module' module.
  1971. $dependencies['mymodule'][8001] = array(
  1972. 'another_module' => 8003,
  1973. );
  1974. // Indicate that the mymodule_update_8002() function provided by this module
  1975. // must run before the yet_another_module_update_8005() function provided by
  1976. // the 'yet_another_module' module. (Note that declaring dependencies in this
  1977. // direction should be done only in rare situations, since it can lead to the
  1978. // following problem: If a site has already run the yet_another_module
  1979. // module's database updates before it updates its codebase to pick up the
  1980. // newest mymodule code, then the dependency declared here will be ignored.)
  1981. $dependencies['yet_another_module'][8005] = array(
  1982. 'mymodule' => 8002,
  1983. );
  1984. return $dependencies;
  1985. }
  1986. /**
  1987. * Return a number which is no longer available as hook_update_N().
  1988. *
  1989. * If you remove some update functions from your mymodule.install file, you
  1990. * should notify Drupal of those missing functions. This way, Drupal can
  1991. * ensure that no update is accidentally skipped.
  1992. *
  1993. * Implementations of this hook should be placed in a mymodule.install file in
  1994. * the same directory as mymodule.module.
  1995. *
  1996. * @return
  1997. * An integer, corresponding to hook_update_N() which has been removed from
  1998. * mymodule.install.
  1999. *
  2000. * @see hook_update_N()
  2001. */
  2002. function hook_update_last_removed() {
  2003. // We've removed the 8.x-1.x version of mymodule, including database updates.
  2004. // The next update function is mymodule_update_8200().
  2005. return 8103;
  2006. }
  2007. /**
  2008. * Remove any information that the module sets.
  2009. *
  2010. * The information that the module should remove includes:
  2011. * - state that the module has set using \Drupal::state()
  2012. * - modifications to existing tables
  2013. *
  2014. * The module should not remove its entry from the module configuration.
  2015. * Database tables defined by hook_schema() will be removed automatically.
  2016. *
  2017. * The uninstall hook must be implemented in the module's .install file. It
  2018. * will fire when the module gets uninstalled but before the module's database
  2019. * tables are removed, allowing your module to query its own tables during
  2020. * this routine.
  2021. *
  2022. * @see hook_install()
  2023. * @see hook_schema()
  2024. * @see hook_disable()
  2025. * @see hook_modules_uninstalled()
  2026. */
  2027. function hook_uninstall() {
  2028. // Remove the styles directory and generated images.
  2029. file_unmanaged_delete_recursive(file_default_scheme() . '://styles');
  2030. }
  2031. /**
  2032. * Return an array of tasks to be performed by an installation profile.
  2033. *
  2034. * Any tasks you define here will be run, in order, after the installer has
  2035. * finished the site configuration step but before it has moved on to the
  2036. * final import of languages and the end of the installation. You can have any
  2037. * number of custom tasks to perform during this phase.
  2038. *
  2039. * Each task you define here corresponds to a callback function which you must
  2040. * separately define and which is called when your task is run. This function
  2041. * will receive the global installation state variable, $install_state, as
  2042. * input, and has the opportunity to access or modify any of its settings. See
  2043. * the install_state_defaults() function in the installer for the list of
  2044. * $install_state settings used by Drupal core.
  2045. *
  2046. * At the end of your task function, you can indicate that you want the
  2047. * installer to pause and display a page to the user by returning any themed
  2048. * output that should be displayed on that page (but see below for tasks that
  2049. * use the form API or batch API; the return values of these task functions are
  2050. * handled differently). You should also use #title within the task
  2051. * callback function to set a custom page title. For some tasks, however, you
  2052. * may want to simply do some processing and pass control to the next task
  2053. * without ending the page request; to indicate this, simply do not send back
  2054. * a return value from your task function at all. This can be used, for
  2055. * example, by installation profiles that need to configure certain site
  2056. * settings in the database without obtaining any input from the user.
  2057. *
  2058. * The task function is treated specially if it defines a form or requires
  2059. * batch processing; in that case, you should return either the form API
  2060. * definition or batch API array, as appropriate. See below for more
  2061. * information on the 'type' key that you must define in the task definition
  2062. * to inform the installer that your task falls into one of those two
  2063. * categories. It is important to use these APIs directly, since the installer
  2064. * may be run non-interactively (for example, via a command line script), all
  2065. * in one page request; in that case, the installer will automatically take
  2066. * care of submitting forms and processing batches correctly for both types of
  2067. * installations. You can inspect the $install_state['interactive'] boolean to
  2068. * see whether or not the current installation is interactive, if you need
  2069. * access to this information.
  2070. *
  2071. * Remember that a user installing Drupal interactively will be able to reload
  2072. * an installation page multiple times, so you should use \Drupal::state() to
  2073. * store any data that you may need later in the installation process. Any
  2074. * temporary state must be removed using \Drupal::state()->delete() before
  2075. * your last task has completed and control is handed back to the installer.
  2076. *
  2077. * @param array $install_state
  2078. * An array of information about the current installation state.
  2079. *
  2080. * @return array
  2081. * A keyed array of tasks the profile will perform during the final stage of
  2082. * the installation. Each key represents the name of a function (usually a
  2083. * function defined by this profile, although that is not strictly required)
  2084. * that is called when that task is run. The values are associative arrays
  2085. * containing the following key-value pairs (all of which are optional):
  2086. * - display_name: The human-readable name of the task. This will be
  2087. * displayed to the user while the installer is running, along with a list
  2088. * of other tasks that are being run. Leave this unset to prevent the task
  2089. * from appearing in the list.
  2090. * - display: This is a boolean which can be used to provide finer-grained
  2091. * control over whether or not the task will display. This is mostly useful
  2092. * for tasks that are intended to display only under certain conditions;
  2093. * for these tasks, you can set 'display_name' to the name that you want to
  2094. * display, but then use this boolean to hide the task only when certain
  2095. * conditions apply.
  2096. * - type: A string representing the type of task. This parameter has three
  2097. * possible values:
  2098. * - normal: (default) This indicates that the task will be treated as a
  2099. * regular callback function, which does its processing and optionally
  2100. * returns HTML output.
  2101. * - batch: This indicates that the task function will return a batch API
  2102. * definition suitable for batch_set(). The installer will then take care
  2103. * of automatically running the task via batch processing.
  2104. * - form: This indicates that the task function will return a standard
  2105. * form API definition (and separately define validation and submit
  2106. * handlers, as appropriate). The installer will then take care of
  2107. * automatically directing the user through the form submission process.
  2108. * - run: A constant representing the manner in which the task will be run.
  2109. * This parameter has three possible values:
  2110. * - INSTALL_TASK_RUN_IF_NOT_COMPLETED: (default) This indicates that the
  2111. * task will run once during the installation of the profile.
  2112. * - INSTALL_TASK_SKIP: This indicates that the task will not run during
  2113. * the current installation page request. It can be used to skip running
  2114. * an installation task when certain conditions are met, even though the
  2115. * task may still show on the list of installation tasks presented to the
  2116. * user.
  2117. * - INSTALL_TASK_RUN_IF_REACHED: This indicates that the task will run on
  2118. * each installation page request that reaches it. This is rarely
  2119. * necessary for an installation profile to use; it is primarily used by
  2120. * the Drupal installer for bootstrap-related tasks.
  2121. * - function: Normally this does not need to be set, but it can be used to
  2122. * force the installer to call a different function when the task is run
  2123. * (rather than the function whose name is given by the array key). This
  2124. * could be used, for example, to allow the same function to be called by
  2125. * two different tasks.
  2126. *
  2127. * @see install_state_defaults()
  2128. * @see batch_set()
  2129. */
  2130. function hook_install_tasks(&$install_state) {
  2131. // Here, we define a variable to allow tasks to indicate that a particular,
  2132. // processor-intensive batch process needs to be triggered later on in the
  2133. // installation.
  2134. $myprofile_needs_batch_processing = \Drupal::state()->get('myprofile.needs_batch_processing', FALSE);
  2135. $tasks = array(
  2136. // This is an example of a task that defines a form which the user who is
  2137. // installing the site will be asked to fill out. To implement this task,
  2138. // your profile would define a function named myprofile_data_import_form()
  2139. // as a normal form API callback function, with associated validation and
  2140. // submit handlers. In the submit handler, in addition to saving whatever
  2141. // other data you have collected from the user, you might also call
  2142. // \Drupal::state()->set('myprofile.needs_batch_processing', TRUE) if the
  2143. // user has entered data which requires that batch processing will need to
  2144. // occur later on.
  2145. 'myprofile_data_import_form' => array(
  2146. 'display_name' => t('Data import options'),
  2147. 'type' => 'form',
  2148. ),
  2149. // Similarly, to implement this task, your profile would define a function
  2150. // named myprofile_settings_form() with associated validation and submit
  2151. // handlers. This form might be used to collect and save additional
  2152. // information from the user that your profile needs. There are no extra
  2153. // steps required for your profile to act as an "installation wizard"; you
  2154. // can simply define as many tasks of type 'form' as you wish to execute,
  2155. // and the forms will be presented to the user, one after another.
  2156. 'myprofile_settings_form' => array(
  2157. 'display_name' => t('Additional options'),
  2158. 'type' => 'form',
  2159. ),
  2160. // This is an example of a task that performs batch operations. To
  2161. // implement this task, your profile would define a function named
  2162. // myprofile_batch_processing() which returns a batch API array definition
  2163. // that the installer will use to execute your batch operations. Due to the
  2164. // 'myprofile.needs_batch_processing' variable used here, this task will be
  2165. // hidden and skipped unless your profile set it to TRUE in one of the
  2166. // previous tasks.
  2167. 'myprofile_batch_processing' => array(
  2168. 'display_name' => t('Import additional data'),
  2169. 'display' => $myprofile_needs_batch_processing,
  2170. 'type' => 'batch',
  2171. 'run' => $myprofile_needs_batch_processing ? INSTALL_TASK_RUN_IF_NOT_COMPLETED : INSTALL_TASK_SKIP,
  2172. ),
  2173. // This is an example of a task that will not be displayed in the list that
  2174. // the user sees. To implement this task, your profile would define a
  2175. // function named myprofile_final_site_setup(), in which additional,
  2176. // automated site setup operations would be performed. Since this is the
  2177. // last task defined by your profile, you should also use this function to
  2178. // call \Drupal::state()->delete('myprofile.needs_batch_processing') and
  2179. // clean up the state that was used above. If you want the user to pass
  2180. // to the final Drupal installation tasks uninterrupted, return no output
  2181. // from this function. Otherwise, return themed output that the user will
  2182. // see (for example, a confirmation page explaining that your profile's
  2183. // tasks are complete, with a link to reload the current page and therefore
  2184. // pass on to the final Drupal installation tasks when the user is ready to
  2185. // do so).
  2186. 'myprofile_final_site_setup' => array(
  2187. ),
  2188. );
  2189. return $tasks;
  2190. }
  2191. /**
  2192. * Alter the full list of installation tasks.
  2193. *
  2194. * You can use this hook to change or replace any part of the Drupal
  2195. * installation process that occurs after the installation profile is selected.
  2196. *
  2197. * @param $tasks
  2198. * An array of all available installation tasks, including those provided by
  2199. * Drupal core. You can modify this array to change or replace individual
  2200. * steps within the installation process.
  2201. * @param $install_state
  2202. * An array of information about the current installation state.
  2203. */
  2204. function hook_install_tasks_alter(&$tasks, $install_state) {
  2205. // Replace the entire site configuration form provided by Drupal core
  2206. // with a custom callback function defined by this installation profile.
  2207. $tasks['install_configure_form']['function'] = 'myprofile_install_configure_form';
  2208. }
  2209. /**
  2210. * Alter MIME type mappings used to determine MIME type from a file extension.
  2211. *
  2212. * Invoked by \Drupal\Core\File\MimeType\ExtensionMimeTypeGuesser::guess(). It
  2213. * is used to allow modules to add to or modify the default mapping from
  2214. * \Drupal\Core\File\MimeType\ExtensionMimeTypeGuesser::$defaultMapping.
  2215. *
  2216. * @param $mapping
  2217. * An array of mimetypes correlated to the extensions that relate to them.
  2218. * The array has 'mimetypes' and 'extensions' elements, each of which is an
  2219. * array.
  2220. *
  2221. * @see \Drupal\Core\File\MimeType\ExtensionMimeTypeGuesser::guess()
  2222. * @see \Drupal\Core\File\MimeType\ExtensionMimeTypeGuesser::$defaultMapping
  2223. */
  2224. function hook_file_mimetype_mapping_alter(&$mapping) {
  2225. // Add new MIME type 'drupal/info'.
  2226. $mapping['mimetypes']['example_info'] = 'drupal/info';
  2227. // Add new extension '.info.yml' and map it to the 'drupal/info' MIME type.
  2228. $mapping['extensions']['info'] = 'example_info';
  2229. // Override existing extension mapping for '.ogg' files.
  2230. $mapping['extensions']['ogg'] = 189;
  2231. }
  2232. /**
  2233. * Alter archiver information declared by other modules.
  2234. *
  2235. * See hook_archiver_info() for a description of archivers and the archiver
  2236. * information structure.
  2237. *
  2238. * @param $info
  2239. * Archiver information to alter (return values from hook_archiver_info()).
  2240. */
  2241. function hook_archiver_info_alter(&$info) {
  2242. $info['tar']['extensions'][] = 'tgz';
  2243. }
  2244. /**
  2245. * Alter the list of mail backend plugin definitions.
  2246. *
  2247. * @param array $info
  2248. * The mail backend plugin definitions to be altered.
  2249. *
  2250. * @see \Drupal\Core\Annotation\Mail
  2251. * @see \Drupal\Core\Mail\MailManager
  2252. */
  2253. function hook_mail_backend_info_alter(&$info) {
  2254. unset($info['test_mail_collector']);
  2255. }
  2256. /**
  2257. * Alters theme operation links.
  2258. *
  2259. * @param $theme_groups
  2260. * An associative array containing groups of themes.
  2261. *
  2262. * @see system_themes_page()
  2263. */
  2264. function hook_system_themes_page_alter(&$theme_groups) {
  2265. foreach ($theme_groups as $state => &$group) {
  2266. foreach ($theme_groups[$state] as &$theme) {
  2267. // Add a foo link to each list of theme operations.
  2268. $theme->operations[] = array(
  2269. 'title' => t('Foo'),
  2270. 'href' => 'admin/appearance/foo',
  2271. 'query' => array('theme' => $theme->getName())
  2272. );
  2273. }
  2274. }
  2275. }
  2276. /**
  2277. * Provide replacement values for placeholder tokens.
  2278. *
  2279. * This hook is invoked when someone calls
  2280. * \Drupal\Core\Utility\Token::replace(). That function first scans the text for
  2281. * [type:token] patterns, and splits the needed tokens into groups by type.
  2282. * Then hook_tokens() is invoked on each token-type group, allowing your module
  2283. * to respond by providing replacement text for any of the tokens in the group
  2284. * that your module knows how to process.
  2285. *
  2286. * A module implementing this hook should also implement hook_token_info() in
  2287. * order to list its available tokens on editing screens.
  2288. *
  2289. * @param $type
  2290. * The machine-readable name of the type (group) of token being replaced, such
  2291. * as 'node', 'user', or another type defined by a hook_token_info()
  2292. * implementation.
  2293. * @param $tokens
  2294. * An array of tokens to be replaced. The keys are the machine-readable token
  2295. * names, and the values are the raw [type:token] strings that appeared in the
  2296. * original text.
  2297. * @param $data
  2298. * (optional) An associative array of data objects to be used when generating
  2299. * replacement values, as supplied in the $data parameter to
  2300. * \Drupal\Core\Utility\Token::replace().
  2301. * @param $options
  2302. * (optional) An associative array of options for token replacement; see
  2303. * \Drupal\Core\Utility\Token::replace() for possible values.
  2304. *
  2305. * @return
  2306. * An associative array of replacement values, keyed by the raw [type:token]
  2307. * strings from the original text.
  2308. *
  2309. * @see hook_token_info()
  2310. * @see hook_tokens_alter()
  2311. */
  2312. function hook_tokens($type, $tokens, array $data = array(), array $options = array()) {
  2313. $token_service = \Drupal::token();
  2314. $url_options = array('absolute' => TRUE);
  2315. if (isset($options['langcode'])) {
  2316. $url_options['language'] = language_load($options['langcode']);
  2317. $langcode = $options['langcode'];
  2318. }
  2319. else {
  2320. $langcode = NULL;
  2321. }
  2322. $sanitize = !empty($options['sanitize']);
  2323. $replacements = array();
  2324. if ($type == 'node' && !empty($data['node'])) {
  2325. /** @var \Drupal\node\NodeInterface $node */
  2326. $node = $data['node'];
  2327. foreach ($tokens as $name => $original) {
  2328. switch ($name) {
  2329. // Simple key values on the node.
  2330. case 'nid':
  2331. $replacements[$original] = $node->nid;
  2332. break;
  2333. case 'title':
  2334. $replacements[$original] = $sanitize ? String::checkPlain($node->getTitle()) : $node->getTitle();
  2335. break;
  2336. case 'edit-url':
  2337. $replacements[$original] = url('node/' . $node->id() . '/edit', $url_options);
  2338. break;
  2339. // Default values for the chained tokens handled below.
  2340. case 'author':
  2341. $account = $node->getOwner() ? $node->getOwner() : user_load(0);
  2342. $replacements[$original] = $sanitize ? String::checkPlain($account->label()) : $account->label();
  2343. break;
  2344. case 'created':
  2345. $replacements[$original] = format_date($node->getCreatedTime(), 'medium', '', NULL, $langcode);
  2346. break;
  2347. }
  2348. }
  2349. if ($author_tokens = $token_service->findWithPrefix($tokens, 'author')) {
  2350. $replacements += $token_service->generate('user', $author_tokens, array('user' => $node->getOwner()), $options);
  2351. }
  2352. if ($created_tokens = $token_service->findWithPrefix($tokens, 'created')) {
  2353. $replacements += $token_service->generate('date', $created_tokens, array('date' => $node->getCreatedTime()), $options);
  2354. }
  2355. }
  2356. return $replacements;
  2357. }
  2358. /**
  2359. * Alter replacement values for placeholder tokens.
  2360. *
  2361. * @param $replacements
  2362. * An associative array of replacements returned by hook_tokens().
  2363. * @param $context
  2364. * The context in which hook_tokens() was called. An associative array with
  2365. * the following keys, which have the same meaning as the corresponding
  2366. * parameters of hook_tokens():
  2367. * - 'type'
  2368. * - 'tokens'
  2369. * - 'data'
  2370. * - 'options'
  2371. *
  2372. * @see hook_tokens()
  2373. */
  2374. function hook_tokens_alter(array &$replacements, array $context) {
  2375. $options = $context['options'];
  2376. if (isset($options['langcode'])) {
  2377. $url_options['language'] = language_load($options['langcode']);
  2378. $langcode = $options['langcode'];
  2379. }
  2380. else {
  2381. $langcode = NULL;
  2382. }
  2383. if ($context['type'] == 'node' && !empty($context['data']['node'])) {
  2384. $node = $context['data']['node'];
  2385. // Alter the [node:title] token, and replace it with the rendered content
  2386. // of a field (field_title).
  2387. if (isset($context['tokens']['title'])) {
  2388. $title = $node->field_title->view('default');
  2389. $replacements[$context['tokens']['title']] = drupal_render($title);
  2390. }
  2391. }
  2392. }
  2393. /**
  2394. * Provide information about available placeholder tokens and token types.
  2395. *
  2396. * Tokens are placeholders that can be put into text by using the syntax
  2397. * [type:token], where type is the machine-readable name of a token type, and
  2398. * token is the machine-readable name of a token within this group. This hook
  2399. * provides a list of types and tokens to be displayed on text editing screens,
  2400. * so that people editing text can see what their token options are.
  2401. *
  2402. * The actual token replacement is done by
  2403. * \Drupal\Core\Utility\Token::replace(), which invokes hook_tokens(). Your
  2404. * module will need to implement that hook in order to generate token
  2405. * replacements from the tokens defined here.
  2406. *
  2407. * @return
  2408. * An associative array of available tokens and token types. The outer array
  2409. * has two components:
  2410. * - types: An associative array of token types (groups). Each token type is
  2411. * an associative array with the following components:
  2412. * - name: The translated human-readable short name of the token type.
  2413. * - description (optional): A translated longer description of the token
  2414. * type.
  2415. * - needs-data: The type of data that must be provided to
  2416. * \Drupal\Core\Utility\Token::replace() in the $data argument (i.e., the
  2417. * key name in $data) in order for tokens of this type to be used in the
  2418. * $text being processed. For instance, if the token needs a node object,
  2419. * 'needs-data' should be 'node', and to use this token in
  2420. * \Drupal\Core\Utility\Token::replace(), the caller needs to supply a
  2421. * node object as $data['node']. Some token data can also be supplied
  2422. * indirectly; for instance, a node object in $data supplies a user object
  2423. * (the author of the node), allowing user tokens to be used when only
  2424. * a node data object is supplied.
  2425. * - tokens: An associative array of tokens. The outer array is keyed by the
  2426. * group name (the same key as in the types array). Within each group of
  2427. * tokens, each token item is keyed by the machine name of the token, and
  2428. * each token item has the following components:
  2429. * - name: The translated human-readable short name of the token.
  2430. * - description (optional): A translated longer description of the token.
  2431. * - type (optional): A 'needs-data' data type supplied by this token, which
  2432. * should match a 'needs-data' value from another token type. For example,
  2433. * the node author token provides a user object, which can then be used
  2434. * for token replacement data in \Drupal\Core\Utility\Token::replace()
  2435. * without having to supply a separate user object.
  2436. *
  2437. * @see hook_token_info_alter()
  2438. * @see hook_tokens()
  2439. */
  2440. function hook_token_info() {
  2441. $type = array(
  2442. 'name' => t('Nodes'),
  2443. 'description' => t('Tokens related to individual nodes.'),
  2444. 'needs-data' => 'node',
  2445. );
  2446. // Core tokens for nodes.
  2447. $node['nid'] = array(
  2448. 'name' => t("Node ID"),
  2449. 'description' => t("The unique ID of the node."),
  2450. );
  2451. $node['title'] = array(
  2452. 'name' => t("Title"),
  2453. );
  2454. $node['edit-url'] = array(
  2455. 'name' => t("Edit URL"),
  2456. 'description' => t("The URL of the node's edit page."),
  2457. );
  2458. // Chained tokens for nodes.
  2459. $node['created'] = array(
  2460. 'name' => t("Date created"),
  2461. 'type' => 'date',
  2462. );
  2463. $node['author'] = array(
  2464. 'name' => t("Author"),
  2465. 'type' => 'user',
  2466. );
  2467. return array(
  2468. 'types' => array('node' => $type),
  2469. 'tokens' => array('node' => $node),
  2470. );
  2471. }
  2472. /**
  2473. * Alter the metadata about available placeholder tokens and token types.
  2474. *
  2475. * @param $data
  2476. * The associative array of token definitions from hook_token_info().
  2477. *
  2478. * @see hook_token_info()
  2479. */
  2480. function hook_token_info_alter(&$data) {
  2481. // Modify description of node tokens for our site.
  2482. $data['tokens']['node']['nid'] = array(
  2483. 'name' => t("Node ID"),
  2484. 'description' => t("The unique ID of the article."),
  2485. );
  2486. $data['tokens']['node']['title'] = array(
  2487. 'name' => t("Title"),
  2488. 'description' => t("The title of the article."),
  2489. );
  2490. // Chained tokens for nodes.
  2491. $data['tokens']['node']['created'] = array(
  2492. 'name' => t("Date created"),
  2493. 'description' => t("The date the article was posted."),
  2494. 'type' => 'date',
  2495. );
  2496. }
  2497. /**
  2498. * Alter batch information before a batch is processed.
  2499. *
  2500. * Called by batch_process() to allow modules to alter a batch before it is
  2501. * processed.
  2502. *
  2503. * @param $batch
  2504. * The associative array of batch information. See batch_set() for details on
  2505. * what this could contain.
  2506. *
  2507. * @see batch_set()
  2508. * @see batch_process()
  2509. *
  2510. * @ingroup batch
  2511. */
  2512. function hook_batch_alter(&$batch) {
  2513. }
  2514. /**
  2515. * Provide information on Updaters (classes that can update Drupal).
  2516. *
  2517. * Drupal\Core\Updater\Updater is a class that knows how to update various parts
  2518. * of the Drupal file system, for example to update modules that have newer
  2519. * releases, or to install a new theme.
  2520. *
  2521. * @return
  2522. * An associative array of information about the updater(s) being provided.
  2523. * This array is keyed by a unique identifier for each updater, and the
  2524. * values are subarrays that can contain the following keys:
  2525. * - class: The name of the PHP class which implements this updater.
  2526. * - name: Human-readable name of this updater.
  2527. * - weight: Controls what order the Updater classes are consulted to decide
  2528. * which one should handle a given task. When an update task is being run,
  2529. * the system will loop through all the Updater classes defined in this
  2530. * registry in weight order and let each class respond to the task and
  2531. * decide if each Updater wants to handle the task. In general, this
  2532. * doesn't matter, but if you need to override an existing Updater, make
  2533. * sure your Updater has a lighter weight so that it comes first.
  2534. *
  2535. * @see drupal_get_updaters()
  2536. * @see hook_updater_info_alter()
  2537. */
  2538. function hook_updater_info() {
  2539. return array(
  2540. 'module' => array(
  2541. 'class' => 'Drupal\Core\Updater\Module',
  2542. 'name' => t('Update modules'),
  2543. 'weight' => 0,
  2544. ),
  2545. 'theme' => array(
  2546. 'class' => 'Drupal\Core\Updater\Theme',
  2547. 'name' => t('Update themes'),
  2548. 'weight' => 0,
  2549. ),
  2550. );
  2551. }
  2552. /**
  2553. * Alter the Updater information array.
  2554. *
  2555. * An Updater is a class that knows how to update various parts of the Drupal
  2556. * file system, for example to update modules that have newer releases, or to
  2557. * install a new theme.
  2558. *
  2559. * @param array $updaters
  2560. * Associative array of updaters as defined through hook_updater_info().
  2561. * Alter this array directly.
  2562. *
  2563. * @see drupal_get_updaters()
  2564. * @see hook_updater_info()
  2565. */
  2566. function hook_updater_info_alter(&$updaters) {
  2567. // Adjust weight so that the theme Updater gets a chance to handle a given
  2568. // update task before module updaters.
  2569. $updaters['theme']['weight'] = -1;
  2570. }
  2571. /**
  2572. * Alter the default country list.
  2573. *
  2574. * @param $countries
  2575. * The associative array of countries keyed by two-letter country code.
  2576. *
  2577. * @see \Drupal\Core\Locale\CountryManager::getList().
  2578. */
  2579. function hook_countries_alter(&$countries) {
  2580. // Elbonia is now independent, so add it to the country list.
  2581. $countries['EB'] = 'Elbonia';
  2582. }
  2583. /**
  2584. * Register information about FileTransfer classes provided by a module.
  2585. *
  2586. * The FileTransfer class allows transferring files over a specific type of
  2587. * connection. Core provides classes for FTP and SSH. Contributed modules are
  2588. * free to extend the FileTransfer base class to add other connection types,
  2589. * and if these classes are registered via hook_filetransfer_info(), those
  2590. * connection types will be available to site administrators using the Update
  2591. * manager when they are redirected to the authorize.php script to authorize
  2592. * the file operations.
  2593. *
  2594. * @return array
  2595. * Nested array of information about FileTransfer classes. Each key is a
  2596. * FileTransfer type (not human readable, used for form elements and
  2597. * variable names, etc), and the values are subarrays that define properties
  2598. * of that type. The keys in each subarray are:
  2599. * - 'title': Required. The human-readable name of the connection type.
  2600. * - 'class': Required. The name of the FileTransfer class. The constructor
  2601. * will always be passed the full path to the root of the site that should
  2602. * be used to restrict where file transfer operations can occur (the $jail)
  2603. * and an array of settings values returned by the settings form.
  2604. * - 'file': Required. The include file containing the FileTransfer class.
  2605. * This should be a separate .inc file, not just the .module file, so that
  2606. * the minimum possible code is loaded when authorize.php is running.
  2607. * - 'file path': Optional. The directory (relative to the Drupal root)
  2608. * where the include file lives. If not defined, defaults to the base
  2609. * directory of the module implementing the hook.
  2610. * - 'weight': Optional. Integer weight used for sorting connection types on
  2611. * the authorize.php form.
  2612. *
  2613. * @see \Drupal\Core\FileTransfer\FileTransfer
  2614. * @see authorize.php
  2615. * @see hook_filetransfer_info_alter()
  2616. * @see drupal_get_filetransfer_info()
  2617. */
  2618. function hook_filetransfer_info() {
  2619. $info['sftp'] = array(
  2620. 'title' => t('SFTP (Secure FTP)'),
  2621. 'class' => 'Drupal\Core\FileTransfer\SFTP',
  2622. 'weight' => 10,
  2623. );
  2624. return $info;
  2625. }
  2626. /**
  2627. * Alter the FileTransfer class registry.
  2628. *
  2629. * @param array $filetransfer_info
  2630. * Reference to a nested array containing information about the FileTransfer
  2631. * class registry.
  2632. *
  2633. * @see hook_filetransfer_info()
  2634. */
  2635. function hook_filetransfer_info_alter(&$filetransfer_info) {
  2636. // Remove the FTP option entirely.
  2637. unset($filetransfer_info['ftp']);
  2638. // Make sure the SSH option is listed first.
  2639. $filetransfer_info['ssh']['weight'] = -10;
  2640. }
  2641. /**
  2642. * Alter the parameters for links.
  2643. *
  2644. * @param array $variables
  2645. * An associative array of variables defining a link. The link may be either a
  2646. * "route link" using \Drupal\Core\Utility\LinkGenerator::link(), which is
  2647. * exposed as the 'link_generator' service or a link generated by l(). If the
  2648. * link is a "route link", 'route_name' will be set, otherwise 'path' will be
  2649. * set. The following keys can be altered:
  2650. * - text: The link text for the anchor tag as a translated string.
  2651. * - url_is_active: Whether or not the link points to the currently active
  2652. * URL.
  2653. * - url: The \Drupal\Core\Url object.
  2654. * - options: An associative array of additional options that will be passed
  2655. * to either \Drupal\Core\Routing\UrlGenerator::generateFromPath() or
  2656. * \Drupal\Core\Routing\UrlGenerator::generateFromRoute() to generate the
  2657. * href attribute for this link, and also used when generating the link.
  2658. * Defaults to an empty array. It may contain the following elements:
  2659. * - 'query': An array of query key/value-pairs (without any URL-encoding) to
  2660. * append to the URL.
  2661. * - absolute: Whether to force the output to be an absolute link (beginning
  2662. * with http:). Useful for links that will be displayed outside the site,
  2663. * such as in an RSS feed. Defaults to FALSE.
  2664. * - language: An optional language object. May affect the rendering of
  2665. * the anchor tag, such as by adding a language prefix to the path.
  2666. * - attributes: An associative array of HTML attributes to apply to the
  2667. * anchor tag. If element 'class' is included, it must be an array; 'title'
  2668. * must be a string; other elements are more flexible, as they just need
  2669. * to work as an argument for the constructor of the class
  2670. * Drupal\Core\Template\Attribute($options['attributes']).
  2671. * - html: Whether or not HTML should be allowed as the link text. If FALSE,
  2672. * the text will be run through
  2673. * \Drupal\Component\Utility\String::checkPlain() before being output.
  2674. *
  2675. * @see \Drupal\Core\Routing\UrlGenerator::generateFromPath()
  2676. * @see \Drupal\Core\Routing\UrlGenerator::generateFromRoute()
  2677. */
  2678. function hook_link_alter(&$variables) {
  2679. // Add a warning to the end of route links to the admin section.
  2680. if (isset($variables['route_name']) && strpos($variables['route_name'], 'admin') !== FALSE) {
  2681. $variables['text'] .= ' (Warning!)';
  2682. }
  2683. }
  2684. /**
  2685. * Alter the configuration synchronization steps.
  2686. *
  2687. * @param array $sync_steps
  2688. * A one-dimensional array of \Drupal\Core\Config\ConfigImporter method names
  2689. * or callables that are invoked to complete the import, in the order that
  2690. * they will be processed. Each callable item defined in $sync_steps should
  2691. * either be a global function or a public static method. The callable should
  2692. * accept a $context array by reference. For example:
  2693. * <code>
  2694. * function _additional_configuration_step(&$context) {
  2695. * // Do stuff.
  2696. * // If finished set $context['finished'] = 1.
  2697. * }
  2698. * </code>
  2699. * For more information on creating batches, see the
  2700. * @link batch Batch operations @endlink documentation.
  2701. *
  2702. * @see callback_batch_operation()
  2703. * @see \Drupal\Core\Config\ConfigImporter::initialize()
  2704. */
  2705. function hook_config_import_steps_alter(&$sync_steps, \Drupal\Core\Config\ConfigImporter $config_importer) {
  2706. $deletes = $config_importer->getUnprocessedConfiguration('delete');
  2707. if (isset($deletes['field.storage.node.body'])) {
  2708. $sync_steps[] = '_additional_configuration_step';
  2709. }
  2710. }
  2711. /**
  2712. * @} End of "addtogroup hooks".
  2713. */
  2714. /**
  2715. * @defgroup annotation Annotations
  2716. * @{
  2717. * Annotations for class discovery and metadata description.
  2718. *
  2719. * The Drupal plugin system has a set of reusable components that developers
  2720. * can use, override, and extend in their modules. Most of the plugins use
  2721. * annotations, which let classes register themselves as plugins and describe
  2722. * their metadata. (Annotations can also be used for other purposes, though
  2723. * at the moment, Drupal only uses them for the plugin system.)
  2724. *
  2725. * To annotate a class as a plugin, add code similar to the following to the
  2726. * end of the documentation block immediately preceding the class declaration:
  2727. * @code
  2728. * * @ContentEntityType(
  2729. * * id = "comment",
  2730. * * label = @Translation("Comment"),
  2731. * * ...
  2732. * * base_table = "comment"
  2733. * * )
  2734. * @endcode
  2735. *
  2736. * Note that you must use double quotes; single quotes will not work in
  2737. * annotations.
  2738. *
  2739. * The available annotation classes are listed in this topic, and can be
  2740. * identified when you are looking at the Drupal source code by having
  2741. * "@ Annotation" in their documentation blocks (without the space after @). To
  2742. * find examples of annotation for a particular annotation class, such as
  2743. * EntityType, look for class files that have an @ annotation section using the
  2744. * annotation class.
  2745. * @}
  2746. */