1. 8.2.x vendor/twig/twig/lib/Twig/Extension/Core.php
  2. 8.0.x vendor/twig/twig/lib/Twig/Extension/Core.php
  3. 8.1.x vendor/twig/twig/lib/Twig/Extension/Core.php
  4. 8.3.x vendor/twig/twig/lib/Twig/Extension/Core.php
  5. 4.6.x developer/hooks/core.php
  6. 4.7.x developer/hooks/core.php
  7. 5.x developer/hooks/core.php
  8. 6.x developer/hooks/core.php

These are the hooks that are invoked by the Drupal core.

Core hooks are typically called in all modules at once using module_invoke_all().

File

developer/hooks/core.php
View source
  1. <?php
  2. /**
  3. * @file
  4. * These are the hooks that are invoked by the Drupal core.
  5. *
  6. * Core hooks are typically called in all modules at once using
  7. * module_invoke_all().
  8. */
  9. /**
  10. * @addtogroup hooks
  11. * @{
  12. */
  13. /**
  14. * Declare information about one or more Drupal actions.
  15. *
  16. * Any module can define any number of Drupal actions. The trigger module is an
  17. * example of a module that uses actions. An action consists of two or three
  18. * parts: (1) an action definition (returned by this hook), (2) a function which
  19. * does the action (which by convention is named module + '_' + description of
  20. * what the function does + '_action'), and an optional form definition
  21. * function that defines a configuration form (which has the name of the action
  22. * with '_form' appended to it.)
  23. *
  24. * @return
  25. * - An array of action descriptions. Each action description is an associative
  26. * array, where the key of the item is the action's function, and the
  27. * following key-value pairs:
  28. * - 'type': (required) the type is determined by what object the action
  29. * acts on. Possible choices are node, user, comment, and system. Or
  30. * whatever your own custom type is. So, for the nodequeue module, the
  31. * type might be set to 'nodequeue' if the action would be performed on a
  32. * nodequeue.
  33. * - 'description': (required) The human-readable name of the action.
  34. * - 'configurable': (required) If FALSE, then the action doesn't require
  35. * any extra configuration. If TRUE, then you should define a form
  36. * function with the same name as the key, but with '_form' appended to
  37. * it (i.e., the form for 'node_assign_owner_action' is
  38. * 'node_assign_owner_action_form'.)
  39. * This function will take the $context as the only parameter, and is
  40. * paired with the usual _submit function, and possibly a _validate
  41. * function.
  42. * - 'hooks': (required) An array of all of the operations this action is
  43. * appropriate for, keyed by hook name. The trigger module uses this to
  44. * filter out inappropriate actions when presenting the interface for
  45. * assigning actions to events. If you are writing actions in your own
  46. * modules and you simply want to declare support for all possible hooks,
  47. * you can set 'hooks' => array('any' => TRUE). Common hooks are 'user',
  48. * 'nodeapi', 'comment', or 'taxonomy'. Any hook that has been described
  49. * to Drupal in hook_hook_info() will work is a possiblity.
  50. * - 'behavior': (optional) Human-readable array of behavior descriptions.
  51. * The only one we have now is 'changes node property'. You will almost
  52. * certainly never have to return this in your own implementations of this
  53. * hook.
  54. *
  55. * The function that is called when the action is triggered is passed two
  56. * parameters - an object of the same type as the 'type' value of the
  57. * hook_action_info array, and a context variable that contains the context
  58. * under which the action is currently running, sent as an array. For example,
  59. * the actions module sets the 'hook' and 'op' keys of the context array (so,
  60. * 'hook' may be 'nodeapi' and 'op' may be 'insert').
  61. *
  62. * @ingroup actions
  63. */
  64. function hook_action_info() {
  65. return array(
  66. 'comment_unpublish_action' => array(
  67. 'description' => t('Unpublish comment'),
  68. 'type' => 'comment',
  69. 'configurable' => FALSE,
  70. 'hooks' => array(
  71. 'comment' => array('insert', 'update'),
  72. )
  73. ),
  74. 'comment_unpublish_by_keyword_action' => array(
  75. 'description' => t('Unpublish comment containing keyword(s)'),
  76. 'type' => 'comment',
  77. 'configurable' => TRUE,
  78. 'hooks' => array(
  79. 'comment' => array('insert', 'update'),
  80. )
  81. )
  82. );
  83. }
  84. /**
  85. * Execute code after an action is deleted.
  86. *
  87. * @param $aid
  88. * The action ID.
  89. */
  90. function hook_actions_delete($aid) {
  91. db_query("DELETE FROM {actions_assignments} WHERE aid = '%s'", $aid);
  92. }
  93. /**
  94. * Alter the actions declared by another module.
  95. *
  96. * Called by actions_list() to allow modules to alter the return
  97. * values from implementations of hook_action_info().
  98. *
  99. * @see trigger_example_action_info_alter().
  100. */
  101. function hook_action_info_alter(&$actions) {
  102. $actions['node_unpublish_action']['description'] = t('Unpublish and remove from public view.');
  103. }
  104. /**
  105. * Declare a block or set of blocks.
  106. *
  107. * Any module can declare a block (or blocks) to be displayed by implementing
  108. * hook_block(), which also allows you to specify any custom configuration
  109. * settings, and how to display the block.
  110. *
  111. * In hook_block(), each block your module provides is given a unique
  112. * identifier referred to as "delta" (the array key in the return value for the
  113. * 'list' operation). Delta values only need to be unique within your module,
  114. * and they are used in the following ways:
  115. * - Passed into the other hook_block() operations as an argument to
  116. * identify the block being configured or viewed.
  117. * - Used to construct the default HTML ID of "block-MODULE-DELTA" applied to
  118. * each block when it is rendered (which can then be used for CSS styling or
  119. * JavaScript programming).
  120. * - Used to define a theming template suggestion of block__MODULE__DELTA, for
  121. * advanced theming possibilities.
  122. * The values of delta can be strings or numbers, but because of the uses above
  123. * it is preferable to use descriptive strings whenever possible, and only use a
  124. * numeric identifier if you have to (for instance if your module allows users
  125. * to create several similar blocks that you identify within your module code
  126. * with numeric IDs).
  127. *
  128. * @param $op
  129. * What kind of information to retrieve about the block or blocks.
  130. * Possible values:
  131. * - 'list': A list of all blocks defined by the module.
  132. * - 'configure': Configuration form for the block.
  133. * - 'save': Save the configuration options.
  134. * - 'view': Process the block when enabled in a region in order to view its
  135. * contents.
  136. * @param $delta
  137. * Which block to return (not applicable if $op is 'list'). See above for more
  138. * information about delta values.
  139. * @param $edit
  140. * If $op is 'save', the submitted form data from the configuration form.
  141. * @return
  142. * - If $op is 'list': An array of block descriptions. Each block description
  143. * is an associative array, with the following key-value pairs:
  144. * - 'info': (required) The human-readable name of the block. This is used
  145. * to identify the block on administration screens, and is not displayed
  146. * to non-administrative users.
  147. * - 'cache': A bitmask of flags describing how the block should behave with
  148. * respect to block caching. The following shortcut bitmasks are provided
  149. * as constants in block.module:
  150. * - BLOCK_CACHE_PER_ROLE (default): The block can change depending on the
  151. * roles the user viewing the page belongs to.
  152. * - BLOCK_CACHE_PER_USER: The block can change depending on the user
  153. * viewing the page. This setting can be resource-consuming for sites
  154. * with large number of users, and should only be used when
  155. * BLOCK_CACHE_PER_ROLE is not sufficient.
  156. * - BLOCK_CACHE_PER_PAGE: The block can change depending on the page
  157. * being viewed.
  158. * - BLOCK_CACHE_GLOBAL: The block is the same for every user on every
  159. * page where it is visible.
  160. * - BLOCK_NO_CACHE: The block should not get cached.
  161. * - 'weight': (optional) Initial value for the ordering weight of this
  162. * block. Most modules do not provide an initial value, and any value
  163. * provided can be modified by a user on the block configuration screen.
  164. * - 'status': (optional) Initial value for block enabled status. (1 =
  165. * enabled, 0 = disabled). Most modules do not provide an initial value,
  166. * and any value provided can be modified by a user on the block
  167. * configuration screen.
  168. * - 'region': (optional) Initial value for theme region within which this
  169. * block is set. Most modules do not provide an initial value, and
  170. * any value provided can be modified by a user on the block configuration
  171. * screen. Note: If you set a region that isn't available in the currently
  172. * enabled theme, the block will be disabled.
  173. * - 'visibility': (optional) Initial value for the visibility flag, which
  174. * tells how to interpret the 'pages' value. Possible values are:
  175. * - 0: Show on all pages except listed pages. 'pages' lists the paths
  176. * where the block should not be shown.
  177. * - 1: Show only on listed pages. 'pages' lists the paths where the block
  178. * should be shown.
  179. * - 2: Use custom PHP code to determine visibility. 'pages' gives the PHP
  180. * code to use.
  181. * Most modules do not provide an initial value for 'visibility' or
  182. * 'pages', and any value provided can be modified by a user on the block
  183. * configuration screen.
  184. * - 'pages': (optional) See 'visibility' above. A string that contains one
  185. * or more page paths separated by '\n', '\r', or '\r\n' when 'visibility'
  186. * is set to 0 or 1, or custom PHP code when 'visibility' is set to 2.
  187. * Paths may use '*' as a wildcard (matching any number of characters);
  188. * '<front>' designates the site's front page. For 'visibility' setting of
  189. * 2, the PHP code's return value should be TRUE if the block is to be
  190. * made visible or FALSE if the block should not be visible.
  191. * - If $op is 'configure': optionally return the configuration form.
  192. * - If $op is 'save': return nothing; save the configuration values.
  193. * - If $op is 'view': return an array which must define a 'subject' element
  194. * (the localized block title) and a 'content' element (the block body)
  195. * defining the block indexed by $delta. If the "content" element
  196. * is empty, no block will be displayed even if "subject" is present.
  197. *
  198. * For a detailed usage example, see block_example.module.
  199. */
  200. function hook_block($op = 'list', $delta = 0, $edit = array()) {
  201. if ($op == 'list') {
  202. $blocks[0] = array('info' => t('Mymodule block #1 shows ...'),
  203. 'weight' => 0, 'status' => 1, 'region' => 'left');
  204. // BLOCK_CACHE_PER_ROLE will be assumed for block 0.
  205. $blocks[1] = array('info' => t('Mymodule block #2 describes ...'),
  206. 'cache' => BLOCK_CACHE_PER_ROLE | BLOCK_CACHE_PER_PAGE);
  207. return $blocks;
  208. }
  209. else if ($op == 'configure' && $delta == 0) {
  210. $form['items'] = array(
  211. '#type' => 'select',
  212. '#title' => t('Number of items'),
  213. '#default_value' => variable_get('mymodule_block_items', 0),
  214. '#options' => array('1', '2', '3'),
  215. );
  216. return $form;
  217. }
  218. else if ($op == 'save' && $delta == 0) {
  219. variable_set('mymodule_block_items', $edit['items']);
  220. }
  221. else if ($op == 'view') {
  222. switch($delta) {
  223. case 0:
  224. // Your module will need to define this function to render the block.
  225. $block = array('subject' => t('Title of block #1'),
  226. 'content' => mymodule_display_block_1());
  227. break;
  228. case 1:
  229. // Your module will need to define this function to render the block.
  230. $block = array('subject' => t('Title of block #2'),
  231. 'content' => mymodule_display_block_2());
  232. break;
  233. }
  234. return $block;
  235. }
  236. }
  237. /**
  238. * Respond to comment actions.
  239. *
  240. * This hook allows modules to extend the comments system by responding when
  241. * certain actions take place.
  242. *
  243. * @param $a1
  244. * Argument; meaning is dependent on the action being performed.
  245. * - For "validate", "update", and "insert": an array of form values
  246. * submitted by the user.
  247. * - For all other operations, the comment the action is being performed on.
  248. * @param $op
  249. * The action being performed. Possible values:
  250. * - "insert": The comment is being inserted.
  251. * - "update": The comment is being updated.
  252. * - "view": The comment is being viewed. This hook can be used to add
  253. * additional data to the comment before theming.
  254. * - "validate": The user has just finished editing the comment and is
  255. * trying to preview or submit it. This hook can be used to check
  256. * the comment. Errors should be set with form_set_error().
  257. * - "publish": The comment is being published by the moderator.
  258. * - "unpublish": The comment is being unpublished by the moderator.
  259. * - "delete": The comment is being deleted by the moderator.
  260. */
  261. function hook_comment(&$a1, $op) {
  262. if ($op == 'insert' || $op == 'update') {
  263. $nid = $a1['nid'];
  264. }
  265. cache_clear_all_like(drupal_url(array('id' => $nid)));
  266. }
  267. /**
  268. * Perform periodic actions.
  269. *
  270. * Modules that require to schedule some commands to be executed at regular
  271. * intervals can implement hook_cron(). The engine will then call the hook
  272. * at the appropriate intervals defined by the administrator. This interface
  273. * is particularly handy to implement timers or to automate certain tasks.
  274. * Database maintenance, recalculation of settings or parameters, and
  275. * automatic mailings are good candidates for cron tasks.
  276. *
  277. * @return
  278. * None.
  279. *
  280. * This hook will only be called if cron.php is run (e.g. by crontab).
  281. */
  282. function hook_cron() {
  283. $result = db_query('SELECT * FROM {site} WHERE checked = 0 OR checked
  284. + refresh < %d', time());
  285. while ($site = db_fetch_array($result)) {
  286. cloud_update($site);
  287. }
  288. }
  289. /**
  290. * Expose a list of triggers (events) that users can assign actions to.
  291. *
  292. * @see hook_action_info(), which allows your module to define actions.
  293. *
  294. * Note: Implementing this hook doesn't actually make any action functions run.
  295. * It just lets the trigger module set up an admin page that will let a site
  296. * administrator assign actions to hooks. To make this work, module needs to:
  297. * - Detect that the event has happened
  298. * - Figure out which actions have been associated with the event. Currently,
  299. * the best way to do that is to call _trigger_get_hook_aids(), whose inputs
  300. * are the name of the hook and the name of the operation, as defined in your
  301. * hook_hook_info() return value)
  302. * - Call the associated action functions using the actions_do() function.
  303. *
  304. * @return
  305. * A nested array:
  306. * - The outermost array key must be the name of your module.
  307. * - The next key represents the name of the hook that triggers the
  308. * events, but for custom and contributed modules, it actually must
  309. * be the name of your module.
  310. * - The next key is the name of the operation within the hook. The
  311. * array values at this level are arrays; currently, the only
  312. * recognized key in that array is 'runs when', whose array value gives
  313. * a translated description of the hook.
  314. */
  315. function hook_hook_info() {
  316. return array(
  317. 'comment' => array(
  318. 'comment' => array(
  319. 'insert' => array(
  320. 'runs when' => t('After saving a new comment'),
  321. ),
  322. 'update' => array(
  323. 'runs when' => t('After saving an updated comment'),
  324. ),
  325. 'delete' => array(
  326. 'runs when' => t('After deleting a comment')
  327. ),
  328. 'view' => array(
  329. 'runs when' => t('When a comment is being viewed by an authenticated user')
  330. ),
  331. ),
  332. ),
  333. );
  334. }
  335. /**
  336. * Alter the data being saved to the {menu_router} table after hook_menu is invoked.
  337. *
  338. * This hook is invoked by menu_router_build(). The menu definitions are passed
  339. * in by reference. Each element of the $items array is one item returned
  340. * by a module from hook_menu. Additional items may be added, or existing items
  341. * altered.
  342. *
  343. * @param $items
  344. * Associative array of menu router definitions returned from hook_menu().
  345. * @return
  346. * None.
  347. */
  348. function hook_menu_alter(&$items) {
  349. // Example - disable the page at node/add
  350. $items['node/add']['access callback'] = FALSE;
  351. }
  352. /**
  353. * Alter the data being saved to the {menu_links} table by menu_link_save().
  354. *
  355. * @param $item
  356. * Associative array defining a menu link as passed into menu_link_save().
  357. * @param $menu
  358. * Associative array containg the menu router returned from menu_router_build().
  359. * @return
  360. * None.
  361. */
  362. function hook_menu_link_alter(&$item, $menu) {
  363. // Example 1 - make all new admin links hidden (a.k.a disabled).
  364. if (strpos($item['link_path'], 'admin') === 0 && empty($item['mlid'])) {
  365. $item['hidden'] = 1;
  366. }
  367. // Example 2 - flag a link to be altered by hook_translated_menu_link_alter()
  368. if ($item['link_path'] == 'devel/cache/clear') {
  369. $item['options']['alter'] = TRUE;
  370. }
  371. }
  372. /**
  373. * Alter a menu link after it's translated, but before it's rendered.
  374. *
  375. * This hook may be used, for example, to add a page-specific query string.
  376. * For performance reasons, only links that have $item['options']['alter'] == TRUE
  377. * will be passed into this hook. The $item['options']['alter'] flag should
  378. * generally be set using hook_menu_link_alter().
  379. *
  380. * @param $item
  381. * Associative array defining a menu link after _menu_link_translate()
  382. * @param $map
  383. * Associative array containing the menu $map (path parts and/or objects).
  384. * @return
  385. * None.
  386. */
  387. function hook_translated_menu_link_alter(&$item, $map) {
  388. if ($item['href'] == 'devel/cache/clear') {
  389. $item['localized_options']['query'] = drupal_get_destination();
  390. }
  391. }
  392. /**
  393. * Rewrite database queries, usually for access control.
  394. *
  395. * Add JOIN and WHERE statements to queries and decide whether the primary_field
  396. * shall be made DISTINCT. For node objects, primary field is always called nid.
  397. * For taxonomy terms, it is tid and for vocabularies it is vid. For comments,
  398. * it is cid. Primary table is the table where the primary object (node, file,
  399. * term_node etc.) is.
  400. *
  401. * You shall return an associative array. Possible keys are 'join', 'where' and
  402. * 'distinct'. The value of 'distinct' shall be 1 if you want that the
  403. * primary_field made DISTINCT.
  404. *
  405. * @param $query
  406. * Query to be rewritten.
  407. * @param $primary_table
  408. * Name or alias of the table which has the primary key field for this query.
  409. * Typical table names would be: {blocks}, {comments}, {forum}, {node},
  410. * {menu}, {term_data} or {vocabulary}. However, it is more common for
  411. * $primary_table to contain the usual table alias: b, c, f, n, m, t or v.
  412. * @param $primary_field
  413. * Name of the primary field.
  414. * @param $args
  415. * Array of additional arguments.
  416. * @return
  417. * An array of join statements, where statements, distinct decision.
  418. */
  419. function hook_db_rewrite_sql($query, $primary_table, $primary_field, $args) {
  420. switch ($primary_field) {
  421. case 'nid':
  422. // this query deals with node objects
  423. $return = array();
  424. if ($primary_table != 'n') {
  425. $return['join'] = "LEFT JOIN {node} n ON $primary_table.nid = n.nid";
  426. }
  427. $return['where'] = 'created >' . mktime(0, 0, 0, 1, 1, 2005);
  428. return $return;
  429. break;
  430. case 'tid':
  431. // this query deals with taxonomy objects
  432. break;
  433. case 'vid':
  434. // this query deals with vocabulary objects
  435. break;
  436. }
  437. }
  438. /**
  439. * Allows modules to declare their own Forms API element types and specify their
  440. * default values.
  441. *
  442. * This hook allows modules to declare their own form element types and to
  443. * specify their default values. The values returned by this hook will be
  444. * merged with the elements returned by hook_form() implementations and so
  445. * can return defaults for any Form APIs keys in addition to those explicitly
  446. * mentioned below.
  447. *
  448. * Each of the form element types defined by this hook is assumed to have
  449. * a matching theme function, e.g. theme_elementtype(), which should be
  450. * registered with hook_theme() as normal.
  451. *
  452. * For more information about custom element types see the explanation at
  453. * @link http://drupal.org/node/169815 http://drupal.org/node/169815 @endlink .
  454. *
  455. * @return
  456. * An associative array describing the element types being defined. The array
  457. * contains a sub-array for each element type, with the machine-readable type
  458. * name as the key. Each sub-array has a number of possible attributes:
  459. * - "#input": boolean indicating whether or not this element carries a value
  460. * (even if it's hidden).
  461. * - "#process": array of callback functions taking $element, $edit,
  462. * $form_state, and $complete_form.
  463. * - "#after_build": array of callback functions taking $element and $form_state.
  464. * - "#validate": array of callback functions taking $form and $form_state.
  465. * - "#element_validate": array of callback functions taking $element and
  466. * $form_state.
  467. * - "#pre_render": array of callback functions taking $element and $form_state.
  468. * - "#post_render": array of callback functions taking $element and $form_state.
  469. * - "#submit": array of callback functions taking $form and $form_state.
  470. */
  471. function hook_elements() {
  472. $type['filter_format'] = array('#input' => TRUE);
  473. return $type;
  474. }
  475. /**
  476. * Perform cleanup tasks.
  477. *
  478. * This hook is run at the end of most regular page requests. It is often
  479. * used for page logging and specialized cleanup. This hook MUST NOT print
  480. * anything because by the time it runs the response is already sent to
  481. * the browser.
  482. *
  483. * Only use this hook if your code must run even for cached page views.
  484. * If you have code which must run once on all non cached pages, use
  485. * hook_init instead. Thats the usual case. If you implement this hook
  486. * and see an error like 'Call to undefined function', it is likely that
  487. * you are depending on the presence of a module which has not been loaded yet.
  488. * It is not loaded because Drupal is still in bootstrap mode.
  489. *
  490. * @param $destination
  491. * If this hook is invoked as part of a drupal_goto() call, then this argument
  492. * will be a fully-qualified URL that is the destination of the redirect.
  493. * Modules may use this to react appropriately; for example, nothing should
  494. * be output in this case, because PHP will then throw a "headers cannot be
  495. * modified" error when attempting the redirection.
  496. * @return
  497. * None.
  498. */
  499. function hook_exit($destination = NULL) {
  500. db_query('UPDATE {counter} SET hits = hits + 1 WHERE type = 1');
  501. }
  502. /**
  503. * Control access to private file downloads and specify HTTP headers.
  504. *
  505. * This hook allows modules enforce permissions on file downloads when the
  506. * private file download method is selected. Modules can also provide headers
  507. * to specify information like the file's name or MIME type.
  508. *
  509. * @param $filepath
  510. * String of the file's path.
  511. * @return
  512. * If the user does not have permission to access the file, return -1. If the
  513. * user has permission, return an array with the appropriate headers. If the file
  514. * is not controlled by the current module, the return value should be NULL.
  515. */
  516. function hook_file_download($filepath) {
  517. if ($filemime = db_result(db_query("SELECT filemime FROM {fileupload} WHERE filepath = '%s'", file_create_path($filepath)))) {
  518. if (user_access('access content')) {
  519. return array('Content-type:' . $filemime);
  520. }
  521. else {
  522. return -1;
  523. }
  524. }
  525. }
  526. /**
  527. * Define content filters.
  528. *
  529. * Content in Drupal is passed through all enabled filters before it is
  530. * output. This lets a module modify content to the site administrator's
  531. * liking.
  532. *
  533. * This hook contains all that is needed for having a module provide filtering
  534. * functionality.
  535. *
  536. * Depending on $op, different tasks are performed.
  537. *
  538. * A module can contain as many filters as it wants. The 'list' operation tells
  539. * the filter system which filters are available. Every filter has a numerical
  540. * 'delta' which is used to refer to it in every operation.
  541. *
  542. * Filtering is a two-step process. First, the content is 'prepared' by calling
  543. * the 'prepare' operation for every filter. The purpose of 'prepare' is to
  544. * escape HTML-like structures. For example, imagine a filter which allows the
  545. * user to paste entire chunks of programming code without requiring manual
  546. * escaping of special HTML characters like @< or @&. If the programming code
  547. * were left untouched, then other filters could think it was HTML and change
  548. * it. For most filters however, the prepare-step is not necessary, and they can
  549. * just return the input without changes.
  550. *
  551. * Filters should not use the 'prepare' step for anything other than escaping,
  552. * because that would short-circuits the control the user has over the order
  553. * in which filters are applied.
  554. *
  555. * The second step is the actual processing step. The result from the
  556. * prepare-step gets passed to all the filters again, this time with the
  557. * 'process' operation. It's here that filters should perform actual changing of
  558. * the content: transforming URLs into hyperlinks, converting smileys into
  559. * images, etc.
  560. *
  561. * An important aspect of the filtering system are 'input formats'. Every input
  562. * format is an entire filter setup: which filters to enable, in what order
  563. * and with what settings. Filters that provide settings should usually store
  564. * these settings per format.
  565. *
  566. * If the filter's behaviour depends on an extensive list and/or external data
  567. * (e.g. a list of smileys, a list of glossary terms) then filters are allowed
  568. * to provide a separate, global configuration page rather than provide settings
  569. * per format. In that case, there should be a link from the format-specific
  570. * settings to the separate settings page.
  571. *
  572. * For performance reasons content is only filtered once; the result is stored
  573. * in the cache table and retrieved the next time the piece of content is
  574. * displayed. If a filter's output is dynamic it can override the cache
  575. * mechanism, but obviously this feature should be used with caution: having one
  576. * 'no cache' filter in a particular input format disables caching for the
  577. * entire format, not just for one filter.
  578. *
  579. * Beware of the filter cache when developing your module: it is advised to set
  580. * your filter to 'no cache' while developing, but be sure to remove it again
  581. * if it's not needed. You can clear the cache by running the SQL query 'DELETE
  582. * FROM cache_filter';
  583. *
  584. * @param $op
  585. * Which filtering operation to perform. Possible values:
  586. * - list: provide a list of available filters.
  587. * Returns an associative array of filter names with numerical keys.
  588. * These keys are used for subsequent operations and passed back through
  589. * the $delta parameter.
  590. * - no cache: Return true if caching should be disabled for this filter.
  591. * - description: Return a short description of what this filter does.
  592. * - prepare: Return the prepared version of the content in $text.
  593. * - process: Return the processed version of the content in $text.
  594. * - settings: Return HTML form controls for the filter's settings. These
  595. * settings are stored with variable_set() when the form is submitted.
  596. * Remember to use the $format identifier in the variable and control names
  597. * to store settings per input format (e.g. "mymodule_setting_$format").
  598. * @param $delta
  599. * Which of the module's filters to use (applies to every operation except
  600. * 'list'). Modules that only contain one filter can ignore this parameter.
  601. * @param $format
  602. * Which input format the filter is being used in (applies to 'prepare',
  603. * 'process' and 'settings').
  604. * @param $text
  605. * The content to filter (applies to 'prepare' and 'process').
  606. * @param $cache_id
  607. * The cache id of the content.
  608. * @return
  609. * The return value depends on $op. The filter hook is designed so that a
  610. * module can return $text for operations it does not use/need.
  611. *
  612. * For a detailed usage example, see filter_example.module. For an example of
  613. * using multiple filters in one module, see filter_filter() and
  614. * filter_filter_tips().
  615. */
  616. function hook_filter($op, $delta = 0, $format = -1, $text = '', $cache_id = 0) {
  617. switch ($op) {
  618. case 'list':
  619. return array(0 => t('Code filter'));
  620. case 'description':
  621. return t('Allows users to post code verbatim using &lt;code&gt; and &lt;?php ?&gt; tags.');
  622. case 'prepare':
  623. // Note: we use [ and ] to replace < > during the filtering process.
  624. // For more information, see "Temporary placeholders and
  625. // delimiters" at http://drupal.org/node/209715.
  626. $text = preg_replace('@<code>(.+?)</code>@se', "'[codefilter-code]' . codefilter_escape('\\1') . '[/codefilter-code]'", $text);
  627. $text = preg_replace('@<(\?(php)?|%)(.+?)(\?|%)>@se', "'[codefilter-php]' . codefilter_escape('\\3') . '[/codefilter-php]'", $text);
  628. return $text;
  629. case "process":
  630. $text = preg_replace('@[codefilter-code](.+?)[/codefilter-code]@se', "codefilter_process_code('$1')", $text);
  631. $text = preg_replace('@[codefilter-php](.+?)[/codefilter-php]@se', "codefilter_process_php('$1')", $text);
  632. return $text;
  633. default:
  634. return $text;
  635. }
  636. }
  637. /**
  638. * Provide tips for using filters.
  639. *
  640. * A module's tips should be informative and to the point. Short tips are
  641. * preferably one-liners.
  642. *
  643. * @param $delta
  644. * Which of this module's filters to use. Modules which only implement one
  645. * filter can ignore this parameter.
  646. * @param $format
  647. * Which format we are providing tips for.
  648. * @param $long
  649. * If set to true, long tips are requested, otherwise short tips are needed.
  650. * @return
  651. * The text of the filter tip.
  652. *
  653. *
  654. */
  655. function hook_filter_tips($delta, $format, $long = FALSE) {
  656. if ($long) {
  657. return t('To post pieces of code, surround them with &lt;code&gt;...&lt;/code&gt; tags. For PHP code, you can use &lt;?php ... ?&gt;, which will also colour it based on syntax.');
  658. }
  659. else {
  660. return t('You may post code using &lt;code&gt;...&lt;/code&gt; (generic) or &lt;?php ... ?&gt; (highlighted PHP) tags.');
  661. }
  662. }
  663. /**
  664. * Insert closing HTML.
  665. *
  666. * This hook enables modules to insert HTML just before the \</body\> closing
  667. * tag of web pages. This is useful for adding JavaScript code to the footer
  668. * and for outputting debug information. It is not possible to add JavaScript
  669. * to the header at this point, and developers wishing to do so should use
  670. * hook_init() instead.
  671. *
  672. * @param $main
  673. * Whether the current page is the front page of the site.
  674. * @return
  675. * The HTML to be inserted.
  676. */
  677. function hook_footer($main = 0) {
  678. if (variable_get('dev_query', 0)) {
  679. return '<div style="clear:both;">'. devel_query_table() .'</div>';
  680. }
  681. }
  682. /**
  683. * Performs alterations to existing database schemas.
  684. *
  685. * When a module modifies the database structure of another module (by
  686. * changing, adding or removing fields, keys or indexes), it should
  687. * implement hook_schema_alter() to update the default $schema to take
  688. * its changes into account.
  689. *
  690. * See hook_schema() for details on the schema definition structure.
  691. *
  692. * @param $schema
  693. * Nested array describing the schemas for all modules.
  694. * @return
  695. * None.
  696. */
  697. function hook_schema_alter(&$schema) {
  698. // Add field to existing schema.
  699. $schema['users']['fields']['timezone_id'] = array(
  700. 'type' => 'int',
  701. 'not null' => TRUE,
  702. 'default' => 0,
  703. 'description' => 'Per-user timezone configuration.',
  704. );
  705. }
  706. /**
  707. * Perform alterations before a form is rendered.
  708. *
  709. * One popular use of this hook is to add form elements to the node form. When
  710. * altering a node form, the node object can be retrieved from $form['#node'].
  711. *
  712. * Note that instead of hook_form_alter(), which is called for all forms, you
  713. * can also use hook_form_FORM_ID_alter() to alter a specific form.
  714. *
  715. * @param $form
  716. * Nested array of form elements that comprise the form. The arguments
  717. * that drupal_get_form() was originally called with are available in the
  718. * array $form['#parameters'].
  719. * @param $form_state
  720. * A keyed array containing the current state of the form.
  721. * @param $form_id
  722. * String representing the name of the form itself. Typically this is the
  723. * name of the function that generated the form.
  724. */
  725. function hook_form_alter(&$form, &$form_state, $form_id) {
  726. if (isset($form['type']) && isset($form['#node']) && $form['type']['#value'] .'_node_form' == $form_id) {
  727. $path = isset($form['#node']->path) ? $form['#node']->path : NULL;
  728. $form['path'] = array(
  729. '#type' => 'fieldset',
  730. '#title' => t('URL path settings'),
  731. '#collapsible' => TRUE,
  732. '#collapsed' => empty($path),
  733. '#access' => user_access('create url aliases'),
  734. '#weight' => 30,
  735. );
  736. $form['path']['path'] = array(
  737. '#type' => 'textfield',
  738. '#default_value' => $path,
  739. '#maxlength' => 128,
  740. '#collapsible' => TRUE,
  741. '#collapsed' => TRUE,
  742. '#description' => t('Optionally specify an alternative URL by which this node can be accessed. For example, type "about" when writing an about page. Use a relative path and don\'t add a trailing slash or the URL alias won\'t work.'),
  743. );
  744. if ($path) {
  745. $form['path']['pid'] = array(
  746. '#type' => 'value',
  747. '#value' => db_result(db_query("SELECT pid FROM {url_alias} WHERE dst = '%s' AND language = '%s'", $path, $form['#node']->language))
  748. );
  749. }
  750. }
  751. }
  752. /**
  753. * Provide a form-specific alteration instead of the global hook_form_alter().
  754. *
  755. * Modules can implement hook_form_FORM_ID_alter() to modify a specific form,
  756. * rather than implementing hook_form_alter() and checking the form ID, or
  757. * using long switch statements to alter multiple forms.
  758. *
  759. * Note that this hook fires before hook_form_alter(). Therefore all
  760. * implementations of hook_form_FORM_ID_alter() will run before all
  761. * implementations of hook_form_alter(), regardless of the module order.
  762. *
  763. * @param $form
  764. * Nested array of form elements that comprise the form. The arguments
  765. * that drupal_get_form() was originally called with are available in the
  766. * array $form['#parameters'].
  767. * @param $form_state
  768. * A keyed array containing the current state of the form.
  769. *
  770. * @see hook_form_alter()
  771. * @see drupal_prepare_form()
  772. */
  773. function hook_form_FORM_ID_alter(&$form, &$form_state) {
  774. // Modification for the form with the given form ID goes here. For example, if
  775. // FORM_ID is "user_register" this code would run only on the user
  776. // registration form.
  777. // Add a checkbox to registration form about agreeing to terms of use.
  778. $form['terms_of_use'] = array(
  779. '#type' => 'checkbox',
  780. '#title' => t("I agree with the website's terms and conditions."),
  781. '#required' => TRUE,
  782. );
  783. }
  784. /**
  785. * Map form_ids to builder functions.
  786. *
  787. * This hook allows modules to build multiple forms from a single form "factory"
  788. * function but each form will have a different form id for submission,
  789. * validation, theming or alteration by other modules.
  790. *
  791. * The callback arguments will be passed as parameters to the function. Callers
  792. * of drupal_get_form() are also able to pass in parameters. These will be
  793. * appended after those specified by hook_forms().
  794. *
  795. * See node_forms() for an actual example of how multiple forms share a common
  796. * building function.
  797. *
  798. * @param $form_id
  799. * The unique string identifying the desired form.
  800. * @param $args
  801. * An array containing the original arguments provided to drupal_get_form().
  802. * @return
  803. * An array keyed by form id with callbacks and optional, callback arguments.
  804. */
  805. function hook_forms($form_id, $args) {
  806. $forms['mymodule_first_form'] = array(
  807. 'callback' => 'mymodule_form_builder',
  808. 'callback arguments' => array('some parameter'),
  809. );
  810. $forms['mymodule_second_form'] = array(
  811. 'callback' => 'mymodule_form_builder',
  812. );
  813. return $forms;
  814. }
  815. /**
  816. * Provide online user help.
  817. *
  818. * By implementing hook_help(), a module can make documentation
  819. * available to the user for the module as a whole, or for specific paths.
  820. * Help for developers should usually be provided via function
  821. * header comments in the code, or in special API example files.
  822. *
  823. * For a detailed usage example, see page_example.module.
  824. *
  825. * @param $path
  826. * The router menu path, as defined in hook_menu(), for the help that
  827. * is being requested; e.g., 'admin/node' or 'user/edit'. If the router path
  828. * includes a % wildcard, then this will appear in $path; for example,
  829. * node pages would have $path equal to 'node/%' or 'node/%/view'. Your hook
  830. * implementation may also be called with special descriptors after a
  831. * "#" sign. Some examples:
  832. * - admin/help#modulename
  833. * The main module help text, displayed on the admin/help/modulename
  834. * page and linked to from the admin/help page.
  835. * - user/help#modulename
  836. * The help for a distributed authorization module (if applicable).
  837. * @param $arg
  838. * An array that corresponds to the return value of the arg() function, for
  839. * modules that want to provide help that is specific to certain values
  840. * of wildcards in $path. For example, you could provide help for the path
  841. * 'user/1' by looking for the path 'user/%' and $arg[1] == '1'. This
  842. * array should always be used rather than directly invoking arg(), because
  843. * your hook implementation may be called for other purposes besides building
  844. * the current page's help. Note that depending on which module is invoking
  845. * hook_help, $arg may contain only empty strings. Regardless, $arg[0] to
  846. * $arg[11] will always be set.
  847. * @return
  848. * A localized string containing the help text.
  849. */
  850. function hook_help($path, $arg) {
  851. switch ($path) {
  852. // Main module help for the block module
  853. case 'admin/help#block':
  854. return '<p>' . t('Blocks are boxes of content rendered into an area, or region, of a web page. The default theme Garland, for example, implements the regions "left sidebar", "right sidebar", "content", "header", and "footer", 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' => url('admin/structure/block'))) . '</p>';
  855. // Help for another path in the block module
  856. case 'admin/build/block':
  857. 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>';
  858. }
  859. }
  860. /**
  861. * Outputs a cached page.
  862. *
  863. * By implementing page_cache_fastpath(), a special cache handler can skip
  864. * most of the bootstrap process, including the database connection.
  865. * This function is invoked during DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE.
  866. *
  867. * @return
  868. * TRUE if a page was output successfully.
  869. *
  870. * @see _drupal_bootstrap()
  871. */
  872. function page_cache_fastpath() {
  873. $page = mycache_fetch($base_root . request_uri(), 'cache_page');
  874. if (!empty($page)) {
  875. drupal_page_header();
  876. print $page;
  877. return TRUE;
  878. }
  879. }
  880. /**
  881. * Perform setup tasks. See also, hook_init.
  882. *
  883. * This hook is run at the beginning of the page request. It is typically
  884. * used to set up global parameters which are needed later in the request.
  885. *
  886. * Only use this hook if your code must run even for cached page views.This hook
  887. * is called before modules or most include files are loaded into memory.
  888. * It happens while Drupal is still in bootstrap mode.
  889. *
  890. * @return
  891. * None.
  892. */
  893. function hook_boot() {
  894. // we need user_access() in the shutdown function. make sure it gets loaded
  895. drupal_load('module', 'user');
  896. register_shutdown_function('devel_shutdown');
  897. }
  898. /**
  899. * Perform setup tasks. See also, hook_boot.
  900. *
  901. * This hook is run at the beginning of the page request. It is typically
  902. * used to set up global parameters which are needed later in the request.
  903. * when this hook is called, all modules are already loaded in memory.
  904. *
  905. * For example, this hook is a typical place for modules to add CSS or JS
  906. * that should be present on every page. This hook is not run on cached
  907. * pages - though CSS or JS added this way will be present on a cached page.
  908. *
  909. * @return
  910. * None.
  911. */
  912. function hook_init() {
  913. drupal_add_css(drupal_get_path('module', 'book') .'/book.css');
  914. }
  915. /**
  916. * Define internal Drupal links.
  917. *
  918. * This hook enables modules to add links to many parts of Drupal. Links
  919. * may be added in nodes or in the navigation block, for example.
  920. *
  921. * The returned array should be a keyed array of link entries. Each link can
  922. * be in one of two formats.
  923. *
  924. * The first format will use the l() function to render the link:
  925. * - attributes: Optional. See l() for usage.
  926. * - fragment: Optional. See l() for usage.
  927. * - href: Required. The URL of the link.
  928. * - html: Optional. See l() for usage.
  929. * - query: Optional. See l() for usage.
  930. * - title: Required. The name of the link.
  931. *
  932. * The second format can be used for non-links. Leaving out the href index will
  933. * select this format:
  934. * - title: Required. The text or HTML code to display.
  935. * - attributes: Optional. An associative array of HTML attributes to apply to the span tag.
  936. * - html: Optional. If not set to true, check_plain() will be run on the title before it is displayed.
  937. *
  938. * @param $type
  939. * An identifier declaring what kind of link is being requested.
  940. * Possible values:
  941. * - comment: Links to be placed below a comment being viewed.
  942. * - node: Links to be placed below a node being viewed.
  943. * @param $object
  944. * A node object or a comment object according to the $type.
  945. * @param $teaser
  946. * In case of node link: a 0/1 flag depending on whether the node is
  947. * displayed with its teaser or its full form.
  948. * @return
  949. * An array of the requested links.
  950. *
  951. */
  952. function hook_link($type, $object, $teaser = FALSE) {
  953. $links = array();
  954. if ($type == 'node' && isset($object->parent)) {
  955. if (!$teaser) {
  956. if (book_access('create', $object)) {
  957. $links['book_add_child'] = array(
  958. 'title' => t('add child page'),
  959. 'href' => "node/add/book/parent/$object->nid",
  960. );
  961. }
  962. if (user_access('see printer-friendly version')) {
  963. $links['book_printer'] = array(
  964. 'title' => t('printer-friendly version'),
  965. 'href' => 'book/export/html/'. $object->nid,
  966. 'attributes' => array('title' => t('Show a printer-friendly version of this book page and its sub-pages.'))
  967. );
  968. }
  969. }
  970. }
  971. $links['sample_link'] = array(
  972. 'title' => t('go somewhere'),
  973. 'href' => 'node/add',
  974. 'query' => 'foo=bar',
  975. 'fragment' => 'anchorname',
  976. 'attributes' => array('title' => t('go to another page')),
  977. );
  978. // Example of a link that's not an anchor
  979. if ($type == 'video') {
  980. if (variable_get('video_playcounter', 1) && user_access('view play counter')) {
  981. $links['play_counter'] = array(
  982. 'title' => format_plural($object->play_counter, '1 play', '@count plays'),
  983. );
  984. }
  985. }
  986. return $links;
  987. }
  988. /**
  989. * Perform alterations before links on a node or comment are rendered.
  990. *
  991. * One popular use of this hook is to modify/remove links from other modules.
  992. * If you want to add a link to the links section of a node or comment, use
  993. * hook_link() instead.
  994. *
  995. * @param $links
  996. * Nested array of links for the node or comment keyed by providing module.
  997. * @param $node
  998. * A node object.
  999. * @param $comment
  1000. * An optional comment object if the links are comment links. If not
  1001. * provided, the links are node links.
  1002. *
  1003. * @see hook_link()
  1004. */
  1005. function hook_link_alter(&$links, $node, $comment = NULL) {
  1006. foreach ($links as $module => $link) {
  1007. if (strstr($module, 'taxonomy_term')) {
  1008. // Link back to the forum and not the taxonomy term page
  1009. $links[$module]['href'] = str_replace('taxonomy/term', 'forum', $link['href']);
  1010. }
  1011. }
  1012. }
  1013. /**
  1014. * Alter profile items before they are rendered.
  1015. *
  1016. * You may omit/add/re-sort/re-categorize, etc.
  1017. *
  1018. * @param $account
  1019. * A user object whose profile is being rendered. Profile items
  1020. * are stored in $account->content.
  1021. */
  1022. function hook_profile_alter(&$account) {
  1023. foreach ($account->content AS $key => $field) {
  1024. // do something
  1025. }
  1026. }
  1027. /**
  1028. * Alter any aspect of email sent by Drupal. You can use this hook to add a
  1029. * common site footer to all outgoing email, add extra header fields, and/or
  1030. * modify the email in any way. HTML-izing the outgoing email is one possibility.
  1031. * See also drupal_mail().
  1032. *
  1033. * @param $message
  1034. * A structured array containing the message to be altered. Keys in this
  1035. * array include:
  1036. * - 'id'
  1037. * An id to identify the mail sent. Look at module source code or
  1038. * drupal_mail() for possible id values.
  1039. * - 'to'
  1040. * The mail address or addresses the message will be sent to. The
  1041. * formatting of this string must comply with RFC 2822.
  1042. * - 'subject'
  1043. * Subject of the e-mail to be sent. This must not contain any newline
  1044. * characters, or the mail may not be sent properly.
  1045. * - 'body'
  1046. * An array of lines containing the message to be sent. Drupal will format
  1047. * the correct line endings for you.
  1048. * - 'from'
  1049. * The address the message will be marked as being from, which is either a
  1050. * custom address or the site-wide default email address.
  1051. * - 'headers'
  1052. * Associative array containing mail headers, such as From, Sender,
  1053. * MIME-Version, Content-Type, etc.
  1054. * - 'params'
  1055. * An array of optional parameters supplied by the caller of drupal_mail()
  1056. * that is used to build the message before hook_mail_alter() is invoked.
  1057. * - language'
  1058. * The language object used to build the message before hook_mail_alter()
  1059. * is invoked.
  1060. */
  1061. function hook_mail_alter(&$message) {
  1062. if ($message['id'] == 'modulename_messagekey') {
  1063. $message['body'][] = "--\nMail sent out from " . variable_get('sitename', t('Drupal'));
  1064. }
  1065. }
  1066. /**
  1067. * Define menu items and page callbacks.
  1068. *
  1069. * This hook enables modules to register paths in order to define how URL
  1070. * requests are handled. Paths may be registered for URL handling only, or they
  1071. * can register a link to be placed in a menu (usually the Navigation menu). A
  1072. * path and its associated information is commonly called a "menu router item".
  1073. * This hook is rarely called (for example, when modules are enabled), and
  1074. * its results are cached in the database.
  1075. *
  1076. * hook_menu() implementations return an associative array whose keys define
  1077. * paths and whose values are an associative array of properties for each
  1078. * path. (The complete list of properties is in the return value section below.)
  1079. *
  1080. * The definition for each path may include a page callback function, which is
  1081. * invoked when the registered path is requested. If there is no other
  1082. * registered path that fits the requested path better, any further path
  1083. * components are passed to the callback function. For example, your module
  1084. * could register path 'abc/def':
  1085. * @code
  1086. * function mymodule_menu() {
  1087. * $items['abc/def'] = array(
  1088. * 'page callback' => 'mymodule_abc_view',
  1089. * );
  1090. * return $items;
  1091. * }
  1092. *
  1093. * function mymodule_abc_view($ghi = 0, $jkl = '') {
  1094. * // ...
  1095. * }
  1096. * @endcode
  1097. * When path 'abc/def' is requested, no further path components are in the
  1098. * request, and no additional arguments are passed to the callback function (so
  1099. * $ghi and $jkl would take the default values as defined in the function
  1100. * signature). When 'abc/def/123/foo' is requested, $ghi will be '123' and
  1101. * $jkl will be 'foo'. Note that this automatic passing of optional path
  1102. * arguments applies only to page and theme callback functions.
  1103. *
  1104. * In addition to optional path arguments, the page callback and other callback
  1105. * functions may specify argument lists as arrays. These argument lists may
  1106. * contain both fixed/hard-coded argument values and integers that correspond
  1107. * to path components. When integers are used and the callback function is
  1108. * called, the corresponding path components will be substituted for the
  1109. * integers. That is, the integer 0 in an argument list will be replaced with
  1110. * the first path component, integer 1 with the second, and so on (path
  1111. * components are numbered starting from zero). To pass an integer without it
  1112. * being replaced with its respective path component, use the string value of
  1113. * the integer (e.g., '1') as the argument value. This substitution feature
  1114. * allows you to re-use a callback function for several different paths. For
  1115. * example:
  1116. * @code
  1117. * function mymodule_menu() {
  1118. * $items['abc/def'] = array(
  1119. * 'page callback' => 'mymodule_abc_view',
  1120. * 'page arguments' => array(1, 'foo'),
  1121. * );
  1122. * return $items;
  1123. * }
  1124. * @endcode
  1125. * When path 'abc/def' is requested, the page callback function will get 'def'
  1126. * as the first argument and (always) 'foo' as the second argument.
  1127. *
  1128. * If a page callback function uses an argument list array, and its path is
  1129. * requested with optional path arguments, then the list array's arguments are
  1130. * passed to the callback function first, followed by the optional path
  1131. * arguments. Using the above example, when path 'abc/def/bar/baz' is requested,
  1132. * mymodule_abc_view() will be called with 'def', 'foo', 'bar' and 'baz' as
  1133. * arguments, in that order.
  1134. *
  1135. * Wildcards within paths also work with integer substitution. For example,
  1136. * your module could register path 'my-module/%/edit':
  1137. * @code
  1138. * $items['my-module/%/edit'] = array(
  1139. * 'page callback' => 'mymodule_abc_edit',
  1140. * 'page arguments' => array(1),
  1141. * );
  1142. * @endcode
  1143. * When path 'my-module/foo/edit' is requested, integer 1 will be replaced
  1144. * with 'foo' and passed to the callback function.
  1145. *
  1146. * Registered paths may also contain special "auto-loader" wildcard components
  1147. * in the form of '%mymodule_abc', where the '%' part means that this path
  1148. * component is a wildcard, and the 'mymodule_abc' part defines the prefix for a
  1149. * load function, which here would be named mymodule_abc_load(). When a matching
  1150. * path is requested, your load function will receive as its first argument the
  1151. * path component in the position of the wildcard; load functions may also be
  1152. * passed additional arguments (see "load arguments" in the return value
  1153. * section below). For example, your module could register path
  1154. * 'my-module/%mymodule_abc/edit':
  1155. * @code
  1156. * $items['my-module/%mymodule_abc/edit'] = array(
  1157. * 'page callback' => 'mymodule_abc_edit',
  1158. * 'page arguments' => array(1),
  1159. * );
  1160. * @endcode
  1161. * When path 'my-module/123/edit' is requested, your load function
  1162. * mymodule_abc_load() will be invoked with the argument '123', and should
  1163. * load and return an "abc" object with internal id 123:
  1164. * @code
  1165. * function mymodule_abc_load($abc_id) {
  1166. * return db_query("SELECT * FROM {mymodule_abc} WHERE abc_id = :abc_id", array(':abc_id' => $abc_id))->fetchObject();
  1167. * }
  1168. * @endcode
  1169. * This 'abc' object will then be passed into the callback functions defined
  1170. * for the menu item, such as the page callback function mymodule_abc_edit()
  1171. * to replace the integer 1 in the argument array. Note that a load function
  1172. * should return FALSE when it is unable to provide a loadable object. For
  1173. * example, the node_load() function for the 'node/%node/edit' menu item will
  1174. * return FALSE for the path 'node/999/edit' if a node with a node ID of 999
  1175. * does not exist. The menu routing system will return a 404 error in this case.
  1176. *
  1177. * You can also make groups of menu items to be rendered (by default) as tabs
  1178. * on a page. To do that, first create one menu item of type MENU_NORMAL_ITEM,
  1179. * with your chosen path, such as 'foo'. Then duplicate that menu item, using a
  1180. * subdirectory path, such as 'foo/tab1', and changing the type to
  1181. * MENU_DEFAULT_LOCAL_TASK to make it the default tab for the group. Then add
  1182. * the additional tab items, with paths such as "foo/tab2" etc., with type
  1183. * MENU_LOCAL_TASK. Example:
  1184. * @code
  1185. * // Make "Foo settings" appear on the admin Config page
  1186. * $items['admin/config/foo'] = array(
  1187. * 'title' => 'Foo settings',
  1188. * 'type' => MENU_NORMAL_ITEM,
  1189. * // Page callback, etc. need to be added here.
  1190. * );
  1191. * // Make "Global settings" the main tab on the "Foo settings" page
  1192. * $items['admin/config/foo/global'] = array(
  1193. * 'title' => 'Global settings',
  1194. * 'type' => MENU_DEFAULT_LOCAL_TASK,
  1195. * // Access callback, page callback, and theme callback will be inherited
  1196. * // from 'admin/config/foo', if not specified here to override.
  1197. * );
  1198. * // Make an additional tab called "Node settings" on "Foo settings"
  1199. * $items['admin/config/foo/node'] = array(
  1200. * 'title' => 'Node settings',
  1201. * 'type' => MENU_LOCAL_TASK,
  1202. * // Page callback and theme callback will be inherited from
  1203. * // 'admin/config/foo', if not specified here to override.
  1204. * // Need to add access callback or access arguments.
  1205. * );
  1206. * @endcode
  1207. *
  1208. * @return
  1209. * An array of menu items. Each menu item has a key corresponding to the
  1210. * Drupal path being registered. The corresponding array value is an
  1211. * associative array that may contain the following key-value pairs:
  1212. * - "title": Required. The untranslated title of the menu item.
  1213. * - "title callback": Function to generate the title; defaults to t().
  1214. * If you require only the raw string to be output, set this to FALSE.
  1215. * - "title arguments": Arguments to send to t() or your custom callback,
  1216. * with path component substitution as described above.
  1217. * - "description": The untranslated description of the menu item.
  1218. * - "page callback": The function to call to display a web page when the user
  1219. * visits the path. If omitted, the parent menu item's callback will be used
  1220. * instead.
  1221. * - "page arguments": An array of arguments to pass to the page callback
  1222. * function, with path component substitution as described above.
  1223. * - "access callback": A function returning TRUE if the user has access
  1224. * rights to this menu item, and FALSE if not. It can also be a boolean
  1225. * constant instead of a function, and you can also use numeric values
  1226. * (will be cast to boolean). Defaults to user_access() unless a value is
  1227. * inherited from the parent menu item; only MENU_DEFAULT_LOCAL_TASK items
  1228. * can inherit access callbacks. To use the user_access() default callback,
  1229. * you must specify the permission to check as 'access arguments' (see
  1230. * below).
  1231. * - "access arguments": An array of arguments to pass to the access callback
  1232. * function, with path component substitution as described above. If the
  1233. * access callback is inherited (see above), the access arguments will be
  1234. * inherited with it, unless overridden in the child menu item.
  1235. * - "file": A file that will be included before the page callback is called;
  1236. * this allows page callback functions to be in separate files. The file
  1237. * should be relative to the implementing module's directory unless
  1238. * otherwise specified by the "file path" option. Does not apply to other
  1239. * callbacks (only page callback).
  1240. * - "file path": The path to the directory containing the file specified in
  1241. * "file". This defaults to the path to the module implementing the hook.
  1242. * - "load arguments": An array of arguments to be passed to each of the
  1243. * wildcard object loaders in the path, after the path argument itself.
  1244. * For example, if a module registers path node/%node/revisions/%/view
  1245. * with load arguments set to array(3), the '%node' in the path indicates
  1246. * that the loader function node_load() will be called with the second
  1247. * path component as the first argument. The 3 in the load arguments
  1248. * indicates that the fourth path component will also be passed to
  1249. * node_load() (numbering of path components starts at zero). So, if path
  1250. * node/12/revisions/29/view is requested, node_load(12, 29) will be called.
  1251. * There are also two "magic" values that can be used in load arguments.
  1252. * "%index" indicates the index of the wildcard path component. "%map"
  1253. * indicates the path components as an array. For example, if a module
  1254. * registers for several paths of the form 'user/%user_category/edit/*', all
  1255. * of them can use the same load function user_category_load(), by setting
  1256. * the load arguments to array('%map', '%index'). For instance, if the user
  1257. * is editing category 'foo' by requesting path 'user/32/edit/foo', the load
  1258. * function user_category_load() will be called with 32 as its first
  1259. * argument, the array ('user', 32, 'edit', 'foo') as the map argument,
  1260. * and 1 as the index argument (because %user_category is the second path
  1261. * component and numbering starts at zero). user_category_load() can then
  1262. * use these values to extract the information that 'foo' is the category
  1263. * being requested.
  1264. * - "weight": An integer that determines the relative position of items in
  1265. * the menu; higher-weighted items sink. Defaults to 0. Menu items with the
  1266. * same weight are ordered alphabetically.
  1267. * - "menu_name": Optional. Set this to a custom menu if you don't want your
  1268. * item to be placed in Navigation.
  1269. * - "tab_parent": For local task menu items, the path of the task's parent
  1270. * item; defaults to the same path without the last component (e.g., the
  1271. * default parent for 'admin/people/create' is 'admin/people').
  1272. * - "tab_root": For local task menu items, the path of the closest non-tab
  1273. * item; same default as "tab_parent".
  1274. * - "position": Position of the block ('left' or 'right') on the system
  1275. * administration page for this item.
  1276. * - "type": A bitmask of flags describing properties of the menu item.
  1277. * Many shortcut bitmasks are provided as constants in menu.inc:
  1278. * - MENU_NORMAL_ITEM: Normal menu items show up in the menu tree and can be
  1279. * moved/hidden by the administrator.
  1280. * - MENU_CALLBACK: Callbacks simply register a path so that the correct
  1281. * information is generated when the path is accessed.
  1282. * - MENU_SUGGESTED_ITEM: Modules may "suggest" menu items that the
  1283. * administrator may enable.
  1284. * - MENU_LOCAL_TASK: Local tasks are menu items that describe different
  1285. * displays of data, and are generally rendered as tabs.
  1286. * - MENU_DEFAULT_LOCAL_TASK: Every set of local tasks should provide one
  1287. * "default" task, which should display the same page as the parent item.
  1288. * If the "type" element is omitted, MENU_NORMAL_ITEM is assumed.
  1289. *
  1290. * For a detailed usage example, see page_example.module.
  1291. * For comprehensive documentation on the menu system, see
  1292. * http://drupal.org/node/102338.
  1293. */
  1294. function hook_menu() {
  1295. $items = array();
  1296. $items['example'] = array(
  1297. 'title' => 'Example Page',
  1298. 'page callback' => 'example_page',
  1299. 'access arguments' => array('access content'),
  1300. 'type' => MENU_SUGGESTED_ITEM,
  1301. );
  1302. $items['example/feed'] = array(
  1303. 'title' => 'Example RSS feed',
  1304. 'page callback' => 'example_feed',
  1305. 'access arguments' => array('access content'),
  1306. 'type' => MENU_CALLBACK,
  1307. );
  1308. return $items;
  1309. }
  1310. /**
  1311. * Alter the information parsed from module and theme .info files
  1312. *
  1313. * This hook is invoked in module_rebuild_cache() and in system_theme_data().
  1314. * A module may implement this hook in order to add to or alter the data
  1315. * generated by reading the .info file with drupal_parse_info_file().
  1316. *
  1317. * @param &$info
  1318. * The .info file contents, passed by reference so that it can be altered.
  1319. * @param $file
  1320. * Full information about the module or theme, including $file->name, and
  1321. * $file->filename
  1322. */
  1323. function hook_system_info_alter(&$info, $file) {
  1324. // Only fill this in if the .info file does not define a 'datestamp'.
  1325. if (empty($info['datestamp'])) {
  1326. $info['datestamp'] = filemtime($file->filename);
  1327. }
  1328. }
  1329. /**
  1330. * Alter the information about available updates for projects.
  1331. *
  1332. * @param $projects
  1333. * Reference to an array of information about available updates to each
  1334. * project installed on the system.
  1335. *
  1336. * @see update_calculate_project_data()
  1337. */
  1338. function hook_update_status_alter(&$projects) {
  1339. $settings = variable_get('update_advanced_project_settings', array());
  1340. foreach ($projects as $project => $project_info) {
  1341. if (isset($settings[$project]) && isset($settings[$project]['check']) &&
  1342. ($settings[$project]['check'] == 'never' ||
  1343. (isset($project_info['recommended']) &&
  1344. $settings[$project]['check'] === $project_info['recommended']))) {
  1345. $projects[$project]['status'] = UPDATE_NOT_CHECKED;
  1346. $projects[$project]['reason'] = t('Ignored from settings');
  1347. if (!empty($settings[$project]['notes'])) {
  1348. $projects[$project]['extra'][] = array(
  1349. 'class' => 'admin-note',
  1350. 'label' => t('Administrator note'),
  1351. 'data' => $settings[$project]['notes'],
  1352. );
  1353. }
  1354. }
  1355. }
  1356. }
  1357. /**
  1358. * Alter the list of projects before fetching data and comparing versions.
  1359. *
  1360. * Most modules will never need to implement this hook. It is for advanced
  1361. * interaction with the update status module: mere mortals need not apply.
  1362. * The primary use-case for this hook is to add projects to the list, for
  1363. * example, to provide update status data on disabled modules and themes. A
  1364. * contributed module might want to hide projects from the list, for example,
  1365. * if there is a site-specific module that doesn't have any official releases,
  1366. * that module could remove itself from this list to avoid "No available
  1367. * releases found" warnings on the available updates report. In rare cases, a
  1368. * module might want to alter the data associated with a project already in
  1369. * the list.
  1370. *
  1371. * @param $projects
  1372. * Reference to an array of the projects installed on the system. This
  1373. * includes all the metadata documented in the comments below for each
  1374. * project (either module or theme) that is currently enabled. The array is
  1375. * initially populated inside update_get_projects() with the help of
  1376. * _update_process_info_list(), so look there for examples of how to
  1377. * populate the array with real values.
  1378. *
  1379. * @see update_get_projects()
  1380. * @see _update_process_info_list()
  1381. */
  1382. function hook_update_projects_alter(&$projects) {
  1383. // Hide a site-specific module from the list.
  1384. unset($projects['site_specific_module']);
  1385. // Add a disabled module to the list.
  1386. // The key for the array should be the machine-readable project "short name".
  1387. $projects['disabled_project_name'] = array(
  1388. // Machine-readable project short name (same as the array key above).
  1389. 'name' => 'disabled_project_name',
  1390. // Array of values from the main .info file for this project.
  1391. 'info' => array(
  1392. 'name' => 'Some disabled module',
  1393. 'description' => 'A module not enabled on the site that you want to see in the available updates report.',
  1394. 'version' => '6.x-1.0',
  1395. 'core' => '6.x',
  1396. // The maximum file change time (the "ctime" returned by the filectime()
  1397. // PHP method) for all of the .info files included in this project.
  1398. '_info_file_ctime' => 1243888165,
  1399. ),
  1400. // The date stamp when the project was released, if known. If the disabled
  1401. // project was an officially packaged release from drupal.org, this will
  1402. // be included in the .info file as the 'datestamp' field. This only
  1403. // really matters for development snapshot releases that are regenerated,
  1404. // so it can be left undefined or set to 0 in most cases.
  1405. 'datestamp' => 1243888185,
  1406. // Any modules (or themes) included in this project. Keyed by machine-
  1407. // readable "short name", value is the human-readable project name printed
  1408. // in the UI.
  1409. 'includes' => array(
  1410. 'disabled_project' => 'Disabled module',
  1411. 'disabled_project_helper' => 'Disabled module helper module',
  1412. 'disabled_project_foo' => 'Disabled module foo add-on module',
  1413. ),
  1414. // Does this project contain a 'module', 'theme', 'disabled-module', or
  1415. // 'disabled-theme'?
  1416. 'project_type' => 'disabled-module',
  1417. );
  1418. }
  1419. /**
  1420. * Inform the node access system what permissions the user has.
  1421. *
  1422. * This hook is for implementation by node access modules. In this hook,
  1423. * the module grants a user different "grant IDs" within one or more
  1424. * "realms". In hook_node_access_records(), the realms and grant IDs are
  1425. * associated with permission to view, edit, and delete individual nodes.
  1426. *
  1427. * The realms and grant IDs can be arbitrarily defined by your node access
  1428. * module; it is common to use role IDs as grant IDs, but that is not
  1429. * required. Your module could instead maintain its own list of users, where
  1430. * each list has an ID. In that case, the return value of this hook would be
  1431. * an array of the list IDs that this user is a member of.
  1432. *
  1433. * A node access module may implement as many realms as necessary to
  1434. * properly define the access privileges for the nodes.
  1435. *
  1436. * @param $account
  1437. * The user object whose grants are requested.
  1438. * @param $op
  1439. * The node operation to be performed, such as "view", "update", or "delete".
  1440. *
  1441. * @return
  1442. * An array whose keys are "realms" of grants, and whose values are arrays of
  1443. * the grant IDs within this realm that this user is being granted.
  1444. *
  1445. * For a detailed example, see node_access_example.module.
  1446. *
  1447. * @ingroup node_access
  1448. */
  1449. function hook_node_grants($account, $op) {
  1450. if (user_access('access private content', $account)) {
  1451. $grants['example'] = array(1);
  1452. }
  1453. $grants['example_owner'] = array($account->uid);
  1454. return $grants;
  1455. }
  1456. /**
  1457. * Set permissions for a node to be written to the database.
  1458. *
  1459. * When a node is saved, a module implementing hook_node_access_records() will
  1460. * be asked if it is interested in the access permissions for a node. If it is
  1461. * interested, it must respond with an array of permissions arrays for that
  1462. * node.
  1463. *
  1464. * Each permissions item in the array is an array with the following elements:
  1465. * - 'realm': The name of a realm that the module has defined in
  1466. * hook_node_grants().
  1467. * - 'gid': A 'grant ID' from hook_node_grants().
  1468. * - 'grant_view': If set to TRUE a user that has been identified as a member
  1469. * of this gid within this realm can view this node.
  1470. * - 'grant_update': If set to TRUE a user that has been identified as a member
  1471. * of this gid within this realm can edit this node.
  1472. * - 'grant_delete': If set to TRUE a user that has been identified as a member
  1473. * of this gid within this realm can delete this node.
  1474. * - 'priority': If multiple modules seek to set permissions on a node, the
  1475. * realms that have the highest priority will win out, and realms with a lower
  1476. * priority will not be written. If there is any doubt, it is best to
  1477. * leave this 0.
  1478. *
  1479. * @ingroup node_access
  1480. */
  1481. function hook_node_access_records($node) {
  1482. if (node_access_example_disabling()) {
  1483. return;
  1484. }
  1485. // We only care about the node if it's been marked private. If not, it is
  1486. // treated just like any other node and we completely ignore it.
  1487. if ($node->private) {
  1488. $grants = array();
  1489. $grants[] = array(
  1490. 'realm' => 'example',
  1491. 'gid' => 1,
  1492. 'grant_view' => TRUE,
  1493. 'grant_update' => FALSE,
  1494. 'grant_delete' => FALSE,
  1495. 'priority' => 0,
  1496. );
  1497. // For the example_author array, the GID is equivalent to a UID, which
  1498. // means there are many many groups of just 1 user.
  1499. $grants[] = array(
  1500. 'realm' => 'example_author',
  1501. 'gid' => $node->uid,
  1502. 'grant_view' => TRUE,
  1503. 'grant_update' => TRUE,
  1504. 'grant_delete' => TRUE,
  1505. 'priority' => 0,
  1506. );
  1507. return $grants;
  1508. }
  1509. }
  1510. /**
  1511. * Add mass node operations.
  1512. *
  1513. * This hook enables modules to inject custom operations into the mass operations
  1514. * dropdown found at admin/content/node, by associating a callback function with
  1515. * the operation, which is called when the form is submitted. The callback function
  1516. * receives one initial argument, which is an array of the checked nodes.
  1517. *
  1518. * @return
  1519. * An array of operations. Each operation is an associative array that may
  1520. * contain the following key-value pairs:
  1521. * - "label": Required. The label for the operation, displayed in the dropdown menu.
  1522. * - "callback": Required. The function to call for the operation.
  1523. * - "callback arguments": Optional. An array of additional arguments to pass to
  1524. * the callback function.
  1525. *
  1526. */
  1527. function hook_node_operations() {
  1528. $operations = array(
  1529. 'approve' => array(
  1530. 'label' => t('Approve the selected posts'),
  1531. 'callback' => 'node_operations_approve',
  1532. ),
  1533. 'promote' => array(
  1534. 'label' => t('Promote the selected posts'),
  1535. 'callback' => 'node_operations_promote',
  1536. ),
  1537. 'sticky' => array(
  1538. 'label' => t('Make the selected posts sticky'),
  1539. 'callback' => 'node_operations_sticky',
  1540. ),
  1541. 'demote' => array(
  1542. 'label' => t('Demote the selected posts'),
  1543. 'callback' => 'node_operations_demote',
  1544. ),
  1545. 'unpublish' => array(
  1546. 'label' => t('Unpublish the selected posts'),
  1547. 'callback' => 'node_operations_unpublish',
  1548. ),
  1549. 'delete' => array(
  1550. 'label' => t('Delete the selected posts'),
  1551. ),
  1552. );
  1553. return $operations;
  1554. }
  1555. /**
  1556. * Act on nodes defined by other modules.
  1557. *
  1558. * Despite what its name might make you think, hook_nodeapi() is not
  1559. * reserved for node modules. On the contrary, it allows modules to react
  1560. * to actions affecting all kinds of nodes, regardless of whether that
  1561. * module defined the node.
  1562. *
  1563. * It is common to find hook_nodeapi() used in conjunction with
  1564. * hook_form_alter(). Modules use hook_form_alter() to place additional form
  1565. * elements onto the node edit form, and hook_nodeapi() is used to read and
  1566. * write those values to and from the database.
  1567. *
  1568. * @param &$node
  1569. * The node the action is being performed on.
  1570. * @param $op
  1571. * What kind of action is being performed. Possible values:
  1572. * - "alter": the $node->content array has been rendered, so the node body or
  1573. * teaser is filtered and now contains HTML. This op should only be used when
  1574. * text substitution, filtering, or other raw text operations are necessary.
  1575. * - "delete": The node is being deleted.
  1576. * - "delete revision": The revision of the node is deleted. You can delete data
  1577. * associated with that revision.
  1578. * - "insert": The node has just been created (inserted in the database).
  1579. * - "load": The node is about to be loaded from the database. This hook
  1580. * can be used to load additional data at this time.
  1581. * - "prepare": The node is about to be shown on the add/edit form.
  1582. * - "prepare translation": The node is being cloned for translation. Load
  1583. * additional data or copy values from $node->translation_source.
  1584. * - "print": Prepare a node view for printing. Used for printer-friendly
  1585. * view in book_module
  1586. * - "rss item": An RSS feed is generated. The module can return properties
  1587. * to be added to the RSS item generated for this node. See comment_nodeapi()
  1588. * and upload_nodeapi() for examples. The $node passed can also be modified
  1589. * to add or remove contents to the feed item.
  1590. * - "search result": The node is displayed as a search result. If you
  1591. * want to display extra information with the result, return it.
  1592. * - "presave": The node passed validation and is about to be saved. Modules may
  1593. * use this to make changes to the node before it is saved to the database.
  1594. * - "update": The node has just been updated in the database.
  1595. * - "update index": The node is being indexed. If you want additional
  1596. * information to be indexed which is not already visible through
  1597. * nodeapi "view", then you should return it here.
  1598. * - "validate": The user has just finished editing the node and is
  1599. * trying to preview or submit it. This hook can be used to check
  1600. * the node data. Errors should be set with form_set_error().
  1601. * - "view": The node content is being assembled before rendering. The module
  1602. * may add elements $node->content prior to rendering. This hook will be
  1603. * called after hook_view(). The format of $node->content is the same as
  1604. * used by Forms API.
  1605. * @param $a3
  1606. * - For "view" and "alter", passes in the $teaser parameter from node_view().
  1607. * - For "validate", passes in the $form parameter from node_validate().
  1608. * @param $a4
  1609. * - For "view" and "alter", passes in the $page parameter from node_view().
  1610. * @return
  1611. * This varies depending on the operation.
  1612. * - The "presave", "insert", "update", "delete", "print" and "view"
  1613. * operations have no return value.
  1614. * - The "load" operation should return an array containing pairs
  1615. * of fields => values to be merged into the node object.
  1616. *
  1617. * If you are writing a node module, do not use this hook to perform
  1618. * actions on your type of node alone. Instead, use the hooks set aside
  1619. * for node modules, such as hook_insert() and hook_form(). That said, for
  1620. * some operations, such as "delete revision" or "rss item" there is no
  1621. * corresponding hook so even the module defining the node will need to
  1622. * implement hook_nodeapi().
  1623. */
  1624. function hook_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  1625. switch ($op) {
  1626. case 'presave':
  1627. if ($node->nid && $node->moderate) {
  1628. // Reset votes when node is updated:
  1629. $node->score = 0;
  1630. $node->users = '';
  1631. $node->votes = 0;
  1632. }
  1633. break;
  1634. case 'insert':
  1635. case 'update':
  1636. if ($node->moderate && user_access('access submission queue')) {
  1637. drupal_set_message(t('The post is queued for approval'));
  1638. }
  1639. elseif ($node->moderate) {
  1640. drupal_set_message(t('The post is queued for approval. The editors will decide whether it should be published.'));
  1641. }
  1642. break;
  1643. case 'view':
  1644. $node->content['my_additional_field'] = array(
  1645. '#value' => theme('mymodule_my_additional_field', $additional_field),
  1646. '#weight' => 10,
  1647. );
  1648. break;
  1649. }
  1650. }
  1651. /**
  1652. * Allow modules to modify the OpenID request parameters.
  1653. *
  1654. * @param $op
  1655. * The operation to be performed.
  1656. * Possible values:
  1657. * - request: Modify parameters before they are sent to the OpenID provider.
  1658. * @param $request
  1659. * An associative array of parameter defaults to which to modify or append.
  1660. * @return
  1661. * An associative array of parameters to be merged with the default list.
  1662. *
  1663. */
  1664. function hook_openid($op, $request) {
  1665. if ($op == 'request') {
  1666. $request['openid.identity'] = 'http://myname.myopenid.com/';
  1667. }
  1668. return $request;
  1669. }
  1670. /**
  1671. * Define user permissions.
  1672. *
  1673. * This hook can supply permissions that the module defines, so that they
  1674. * can be selected on the user permissions page and used to grant or restrict
  1675. * access to actions the module performs.
  1676. *
  1677. * Permissions are checked using user_access().
  1678. *
  1679. * For a detailed usage example, see page_example.module.
  1680. *
  1681. * @return
  1682. * An array of permission strings. The strings must not be wrapped with
  1683. * the t() function, since the string extractor takes care of
  1684. * extracting permission names defined in the perm hook for
  1685. * translation.
  1686. */
  1687. function hook_perm() {
  1688. return array('administer my module');
  1689. }
  1690. /**
  1691. * Ping another server.
  1692. *
  1693. * This hook allows a module to notify other sites of updates on your
  1694. * Drupal site.
  1695. *
  1696. * @param $name
  1697. * The name of your Drupal site.
  1698. * @param $url
  1699. * The URL of your Drupal site.
  1700. * @return
  1701. * None.
  1702. */
  1703. function hook_ping($name = '', $url = '') {
  1704. $feed = url('node/feed');
  1705. $client = new xmlrpc_client('/RPC2', 'rpc.weblogs.com', 80);
  1706. $message = new xmlrpcmsg('weblogUpdates.ping',
  1707. array(new xmlrpcval($name), new xmlrpcval($url)));
  1708. $result = $client->send($message);
  1709. if (!$result || $result->faultCode()) {
  1710. watchdog('error', 'failed to notify "weblogs.com" (site)');
  1711. }
  1712. unset($client);
  1713. }
  1714. /**
  1715. * Define a custom search routine.
  1716. *
  1717. * This hook allows a module to perform searches on content it defines
  1718. * (custom node types, users, or comments, for example) when a site search
  1719. * is performed.
  1720. *
  1721. * Note that you can use form API to extend the search. You will need to use
  1722. * hook_form_alter() to add any additional required form elements. You can
  1723. * process their values on submission using a custom validation function.
  1724. * You will need to merge any custom search values into the search keys
  1725. * using a key:value syntax. This allows all search queries to have a clean
  1726. * and permanent URL. See node_form_alter() for an example.
  1727. *
  1728. * The example given here is for node.module, which uses the indexed search
  1729. * capabilities. To do this, node module also implements hook_update_index()
  1730. * which is used to create and maintain the index.
  1731. *
  1732. * We call do_search() with the keys, the module name, and extra SQL fragments
  1733. * to use when searching. See hook_update_index() for more information.
  1734. *
  1735. * @param $op
  1736. * A string defining which operation to perform:
  1737. * - 'admin': The hook should return a form array, containing any fieldsets
  1738. * the module wants to add to the Search settings page at
  1739. * admin/settings/search.
  1740. * - 'name': The hook should return a translated name defining the type of
  1741. * items that are searched for with this module ('content', 'users', ...).
  1742. * - 'reset': The search index is going to be rebuilt. Modules which use
  1743. * hook_update_index() should update their indexing bookkeeping so that it
  1744. * starts from scratch the next time hook_update_index() is called.
  1745. * - 'search': The hook should perform a search using the keywords in $keys.
  1746. * - 'status': If the module implements hook_update_index(), it should return
  1747. * an array containing the following keys:
  1748. * - remaining: The amount of items that still need to be indexed.
  1749. * - total: The total amount of items (both indexed and unindexed).
  1750. * @param $keys
  1751. * The search keywords as entered by the user.
  1752. * @return
  1753. * This varies depending on the operation.
  1754. * - 'admin': The form array for the Search settings page at
  1755. * admin/settings/search.
  1756. * - 'name': The translated string of 'Content'.
  1757. * - 'reset': None.
  1758. * - 'search': An array of search results. To use the default search result
  1759. * display, each item should have the following keys':
  1760. * - 'link': Required. The URL of the found item.
  1761. * - 'type': The type of item.
  1762. * - 'title': Required. The name of the item.
  1763. * - 'user': The author of the item.
  1764. * - 'date': A timestamp when the item was last modified.
  1765. * - 'extra': An array of optional extra information items.
  1766. * - 'snippet': An excerpt or preview to show with the result (can be
  1767. * generated with search_excerpt()).
  1768. * - 'status': An associative array with the key-value pairs:
  1769. * - 'remaining': The number of items left to index.
  1770. * - 'total': The total number of items to index.
  1771. *
  1772. * @ingroup search
  1773. */
  1774. function hook_search($op = 'search', $keys = NULL) {
  1775. switch ($op) {
  1776. case 'name':
  1777. return t('Content');
  1778. case 'reset':
  1779. db_query("UPDATE {search_dataset} SET reindex = %d WHERE type = 'node'", time());
  1780. return;
  1781. case 'status':
  1782. $total = db_result(db_query('SELECT COUNT(*) FROM {node} WHERE status = 1'));
  1783. $remaining = db_result(db_query("SELECT COUNT(*) FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE n.status = 1 AND (d.sid IS NULL OR d.reindex <> 0)"));
  1784. return array('remaining' => $remaining, 'total' => $total);
  1785. case 'admin':
  1786. $form = array();
  1787. // Output form for defining rank factor weights.
  1788. $form['content_ranking'] = array(
  1789. '#type' => 'fieldset',
  1790. '#title' => t('Content ranking'),
  1791. );
  1792. $form['content_ranking']['#theme'] = 'node_search_admin';
  1793. $form['content_ranking']['info'] = array(
  1794. '#value' => '<em>'. t('The following numbers control which properties the content search should favor when ordering the results. Higher numbers mean more influence, zero means the property is ignored. Changing these numbers does not require the search index to be rebuilt. Changes take effect immediately.') .'</em>'
  1795. );
  1796. $ranking = array('node_rank_relevance' => t('Keyword relevance'),
  1797. 'node_rank_recent' => t('Recently posted'));
  1798. if (module_exists('comment')) {
  1799. $ranking['node_rank_comments'] = t('Number of comments');
  1800. }
  1801. if (module_exists('statistics') && variable_get('statistics_count_content_views', 0)) {
  1802. $ranking['node_rank_views'] = t('Number of views');
  1803. }
  1804. // Note: reversed to reflect that higher number = higher ranking.
  1805. $options = drupal_map_assoc(range(0, 10));
  1806. foreach ($ranking as $var => $title) {
  1807. $form['content_ranking']['factors'][$var] = array(
  1808. '#title' => $title,
  1809. '#type' => 'select',
  1810. '#options' => $options,
  1811. '#default_value' => variable_get($var, 5),
  1812. );
  1813. }
  1814. return $form;
  1815. case 'search':
  1816. // Build matching conditions
  1817. list($join1, $where1) = _db_rewrite_sql();
  1818. $arguments1 = array();
  1819. $conditions1 = 'n.status = 1';
  1820. if ($type = search_query_extract($keys, 'type')) {
  1821. $types = array();
  1822. foreach (explode(',', $type) as $t) {
  1823. $types[] = "n.type = '%s'";
  1824. $arguments1[] = $t;
  1825. }
  1826. $conditions1 .= ' AND ('. implode(' OR ', $types) .')';
  1827. $keys = search_query_insert($keys, 'type');
  1828. }
  1829. if ($category = search_query_extract($keys, 'category')) {
  1830. $categories = array();
  1831. foreach (explode(',', $category) as $c) {
  1832. $categories[] = "tn.tid = %d";
  1833. $arguments1[] = $c;
  1834. }
  1835. $conditions1 .= ' AND ('. implode(' OR ', $categories) .')';
  1836. $join1 .= ' INNER JOIN {term_node} tn ON n.vid = tn.vid';
  1837. $keys = search_query_insert($keys, 'category');
  1838. }
  1839. // Build ranking expression (we try to map each parameter to a
  1840. // uniform distribution in the range 0..1).
  1841. $ranking = array();
  1842. $arguments2 = array();
  1843. $join2 = '';
  1844. // Used to avoid joining on node_comment_statistics twice
  1845. $stats_join = FALSE;
  1846. $total = 0;
  1847. if ($weight = (int)variable_get('node_rank_relevance', 5)) {
  1848. // Average relevance values hover around 0.15
  1849. $ranking[] = '%d * i.relevance';
  1850. $arguments2[] = $weight;
  1851. $total += $weight;
  1852. }
  1853. if ($weight = (int)variable_get('node_rank_recent', 5)) {
  1854. // Exponential decay with half-life of 6 months, starting at last indexed node
  1855. $ranking[] = '%d * POW(2, (GREATEST(MAX(n.created), MAX(n.changed), MAX(c.last_comment_timestamp)) - %d) * 6.43e-8)';
  1856. $arguments2[] = $weight;
  1857. $arguments2[] = (int)variable_get('node_cron_last', 0);
  1858. $join2 .= ' LEFT JOIN {node_comment_statistics} c ON c.nid = i.sid';
  1859. $stats_join = TRUE;
  1860. $total += $weight;
  1861. }
  1862. if (module_exists('comment') && $weight = (int)variable_get('node_rank_comments', 5)) {
  1863. // Inverse law that maps the highest reply count on the site to 1 and 0 to 0.
  1864. $scale = variable_get('node_cron_comments_scale', 0.0);
  1865. $ranking[] = '%d * (2.0 - 2.0 / (1.0 + MAX(c.comment_count) * %f))';
  1866. $arguments2[] = $weight;
  1867. $arguments2[] = $scale;
  1868. if (!$stats_join) {
  1869. $join2 .= ' LEFT JOIN {node_comment_statistics} c ON c.nid = i.sid';
  1870. }
  1871. $total += $weight;
  1872. }
  1873. if (module_exists('statistics') && variable_get('statistics_count_content_views', 0) &&
  1874. $weight = (int)variable_get('node_rank_views', 5)) {
  1875. // Inverse law that maps the highest view count on the site to 1 and 0 to 0.
  1876. $scale = variable_get('node_cron_views_scale', 0.0);
  1877. $ranking[] = '%d * (2.0 - 2.0 / (1.0 + MAX(nc.totalcount) * %f))';
  1878. $arguments2[] = $weight;
  1879. $arguments2[] = $scale;
  1880. $join2 .= ' LEFT JOIN {node_counter} nc ON nc.nid = i.sid';
  1881. $total += $weight;
  1882. }
  1883. // When all search factors are disabled (ie they have a weight of zero),
  1884. // the default score is based only on keyword relevance and there is no need to
  1885. // adjust the score of each item.
  1886. if ($total == 0) {
  1887. $select2 = 'i.relevance AS score';
  1888. $total = 1;
  1889. }
  1890. else {
  1891. $select2 = implode(' + ', $ranking) . ' AS score';
  1892. }
  1893. // Do search.
  1894. $find = do_search($keys, 'node', 'INNER JOIN {node} n ON n.nid = i.sid '. $join1, $conditions1 . (empty($where1) ? '' : ' AND '. $where1), $arguments1, $select2, $join2, $arguments2);
  1895. // Load results.
  1896. $results = array();
  1897. foreach ($find as $item) {
  1898. // Build the node body.
  1899. $node = node_load($item->sid);
  1900. $node->build_mode = NODE_BUILD_SEARCH_RESULT;
  1901. $node = node_build_content($node, FALSE, FALSE);
  1902. $node->body = drupal_render($node->content);
  1903. // Fetch comments for snippet.
  1904. $node->body .= module_invoke('comment', 'nodeapi', $node, 'update index');
  1905. // Fetch terms for snippet.
  1906. $node->body .= module_invoke('taxonomy', 'nodeapi', $node, 'update index');
  1907. $extra = node_invoke_nodeapi($node, 'search result');
  1908. $results[] = array(
  1909. 'link' => url('node/'. $item->sid, array('absolute' => TRUE)),
  1910. 'type' => check_plain(node_get_types('name', $node)),
  1911. 'title' => $node->title,
  1912. 'user' => theme('username', $node),
  1913. 'date' => $node->changed,
  1914. 'node' => $node,
  1915. 'extra' => $extra,
  1916. 'score' => $item->score / $total,
  1917. 'snippet' => search_excerpt($keys, $node->body),
  1918. );
  1919. }
  1920. return $results;
  1921. }
  1922. }
  1923. /**
  1924. * Preprocess text for the search index.
  1925. *
  1926. * This hook is called both for text added to the search index, as well as
  1927. * the keywords users have submitted for searching.
  1928. *
  1929. * This is required for example to allow Japanese or Chinese text to be
  1930. * searched. As these languages do not use spaces, it needs to be split into
  1931. * separate words before it can be indexed. There are various external
  1932. * libraries for this.
  1933. *
  1934. * @param $text
  1935. * The text to split. This is a single piece of plain-text that was
  1936. * extracted from between two HTML tags. Will not contain any HTML entities.
  1937. * @return
  1938. * The text after processing.
  1939. */
  1940. function hook_search_preprocess($text) {
  1941. // Do processing on $text
  1942. return $text;
  1943. }
  1944. /**
  1945. * Override the rendering of search results.
  1946. *
  1947. * A module that implements hook_search() to define a type of search
  1948. * may implement this hook in order to override the default theming of
  1949. * its search results, which is otherwise themed using
  1950. * theme('search_results').
  1951. *
  1952. * Note that by default, theme('search_results') and
  1953. * theme('search_result') work together to create a definition
  1954. * list. So your hook_search_page() implementation should probably do
  1955. * this as well.
  1956. *
  1957. * @see search-result.tpl.php
  1958. * @see search-results.tpl.php
  1959. *
  1960. * @param $results
  1961. * An array of search results.
  1962. * @return
  1963. * An HTML string containing the formatted search results, with
  1964. * a pager included.
  1965. */
  1966. function hook_search_page($results) {
  1967. $output = '<dl class="search-results">';
  1968. foreach ($results as $entry) {
  1969. $output .= theme('search_result', $entry, $type);
  1970. }
  1971. $output .= '</dl>';
  1972. $output .= theme('pager', NULL);
  1973. return $output;
  1974. }
  1975. /**
  1976. * Act on taxonomy changes.
  1977. *
  1978. * This hook allows modules to take action when the terms and vocabularies
  1979. * in the taxonomy are modified.
  1980. *
  1981. * @param $op
  1982. * What is being done to $array. Possible values:
  1983. * - "delete"
  1984. * - "insert"
  1985. * - "update"
  1986. * @param $type
  1987. * What manner of item $array is. Possible values:
  1988. * - "term"
  1989. * - "vocabulary"
  1990. * @param $array
  1991. * The item on which $op is being performed. Possible values:
  1992. * - for vocabularies, 'insert' and 'update' ops:
  1993. * $form_values from taxonomy_form_vocabulary_submit()
  1994. * - for vocabularies, 'delete' op:
  1995. * $vocabulary from taxonomy_get_vocabulary() cast to an array
  1996. * - for terms, 'insert' and 'update' ops:
  1997. * $form_values from taxonomy_form_term_submit()
  1998. * - for terms, 'delete' op:
  1999. * $term from taxonomy_get_term() cast to an array
  2000. * @return
  2001. * None.
  2002. */
  2003. function hook_taxonomy($op, $type, $array = NULL) {
  2004. if ($type == 'vocabulary' && ($op == 'insert' || $op == 'update')) {
  2005. if (variable_get('forum_nav_vocabulary', '') == ''
  2006. && in_array('forum', $array['nodes'])) {
  2007. // since none is already set, silently set this vocabulary as the
  2008. // navigation vocabulary
  2009. variable_set('forum_nav_vocabulary', $array['vid']);
  2010. }
  2011. }
  2012. }
  2013. /**
  2014. * Register a module (or theme's) theme implementations.
  2015. *
  2016. * Modules and themes implementing this hook return an array of arrays. The key
  2017. * to each sub-array is the internal name of the hook, and the array contains
  2018. * information about the hook. Each array may contain the following elements:
  2019. *
  2020. * - arguments: (required) An array of arguments that this theme hook uses. This
  2021. * value allows the theme layer to properly utilize templates. The array keys
  2022. * represent the name of the variable, and the value will be used as the
  2023. * default value if not passed to the theme() function. These arguments must
  2024. * be in the same order that they will be given to the theme() function.
  2025. * Default values will only be passed to templates. If you want your theme
  2026. * function to assume defaults, specify them as usual in the argument list in
  2027. * the theme_HOOK_NAME() default implementation.
  2028. * - file: The file the implementation resides in. This file will be included
  2029. * prior to the theme being rendered, to make sure that the function or
  2030. * preprocess function (as needed) is actually loaded; this makes it possible
  2031. * to split theme functions out into separate files quite easily.
  2032. * - path: Override the path of the file to be used. Ordinarily the module or
  2033. * theme path will be used, but if the file will not be in the default path,
  2034. * include it here. This path should be relative to the Drupal root directory.
  2035. * - template: If specified, this theme implementation is a template, and this
  2036. * is the template file without an extension. Do not put .tpl.php on this
  2037. * file; that extension will be added automatically by the default rendering
  2038. * engine (which is PHPTemplate). If 'path', above, is specified, the template
  2039. * should also be in this path.
  2040. * - function: If specified, this will be the function name to invoke for this
  2041. * implementation. If neither 'template' nor 'function' is specified, a
  2042. * default function name will be assumed. For example, if a module registers
  2043. * the 'node' theme hook, 'theme_node' will be assigned to its function. If
  2044. * the chameleon theme registers the node hook, it will be assigned
  2045. * 'chameleon_node' as its function.
  2046. * - original hook: A string declaring the original theme hook if this theme
  2047. * implementation is actually implementing a suggestion for another theme
  2048. * hook.
  2049. * - pattern: A regular expression pattern to be used to allow this theme
  2050. * implementation to have a dynamic name. The convention is to use __ to
  2051. * differentiate the dynamic portion of the theme. For example, to allow
  2052. * forums to be themed individually, the pattern might be: 'forum__'. Then,
  2053. * when the forum is themed, call: theme(array('forum__'. $tid, 'forum'),
  2054. * $forum).
  2055. * - preprocess functions: A list of functions used to preprocess this data.
  2056. * Ordinarily this won't be used; it's automatically filled in. By default,
  2057. * for a module this will be filled in as template_preprocess_HOOK. For a
  2058. * theme this will be filled in as phptemplate_preprocess and
  2059. * phptemplate_preprocess_HOOK as well as themename_preprocess and
  2060. * themename_preprocess_HOOK.
  2061. * - override preprocess functions: Set to TRUE when a theme does NOT want the
  2062. * standard preprocess functions to run. This can be used to give a theme FULL
  2063. * control over how variables are set. For example, if a theme wants total
  2064. * control over how certain variables in the page.tpl.php are set, this can be
  2065. * set to true. Please keep in mind that when this is use by a theme, that
  2066. * theme becomes responsible for making sure necessary variables are set.
  2067. * - type: (automatically derived) Where the theme hook is defined: 'module',
  2068. * 'theme_engine', or 'theme'.
  2069. * - theme path: (automatically derived) The directory path of the theme or
  2070. * module, so that it doesn't need to be looked up.
  2071. * - theme paths: (automatically derived) An array of template suggestions where
  2072. * .tpl.php files related to this theme hook may be found.
  2073. *
  2074. * The following parameters are all optional.
  2075. *
  2076. * @param $existing
  2077. * An array of existing implementations that may be used for override
  2078. * purposes. This is primarily useful for themes that may wish to examine
  2079. * existing implementations to extract data (such as arguments) so that
  2080. * it may properly register its own, higher priority implementations.
  2081. * @param $type
  2082. * What 'type' is being processed. This is primarily useful so that themes
  2083. * tell if they are the actual theme being called or a parent theme.
  2084. * May be one of:
  2085. * - module: A module is being checked for theme implementations.
  2086. * - base_theme_engine: A theme engine is being checked for a theme which is a
  2087. * parent of the actual theme being used.
  2088. * - theme_engine: A theme engine is being checked for the actual theme being
  2089. * used.
  2090. * - base_theme: A base theme is being checked for theme implementations.
  2091. * - theme: The actual theme in use is being checked.
  2092. * @param $theme
  2093. * The actual name of theme that is being being checked (mostly only useful
  2094. * for theme engine).
  2095. * @param $path
  2096. * The directory path of the theme or module, so that it doesn't need to be
  2097. * looked up.
  2098. *
  2099. * @return
  2100. * A keyed array of theme hooks.
  2101. */
  2102. function hook_theme($existing, $type, $theme, $path) {
  2103. return array(
  2104. 'forum_display' => array(
  2105. 'arguments' => array('forums' => NULL, 'topics' => NULL, 'parents' => NULL, 'tid' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL),
  2106. ),
  2107. 'forum_list' => array(
  2108. 'arguments' => array('forums' => NULL, 'parents' => NULL, 'tid' => NULL),
  2109. ),
  2110. 'forum_topic_list' => array(
  2111. 'arguments' => array('tid' => NULL, 'topics' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL),
  2112. ),
  2113. 'forum_icon' => array(
  2114. 'arguments' => array('new_posts' => NULL, 'num_posts' => 0, 'comment_mode' => 0, 'sticky' => 0),
  2115. ),
  2116. 'forum_topic_navigation' => array(
  2117. 'arguments' => array('node' => NULL),
  2118. ),
  2119. 'node' => array(
  2120. 'arguments' => array('node' => NULL, 'teaser' => FALSE, 'page' => FALSE),
  2121. 'template' => 'node',
  2122. ),
  2123. 'node_filter_form' => array(
  2124. 'arguments' => array('form' => NULL),
  2125. 'file' => 'node.admin.inc',
  2126. ),
  2127. );
  2128. }
  2129. /**
  2130. * Alter the theme registry information returned from hook_theme().
  2131. *
  2132. * The theme registry stores information about all available theme hooks,
  2133. * including which callback functions those hooks will call when triggered,
  2134. * what template files are exposed by these hooks, and so on.
  2135. *
  2136. * Note that this hook is only executed as the theme cache is re-built.
  2137. * Changes here will not be visible until the next cache clear.
  2138. *
  2139. * The $theme_registry array is keyed by theme hook name, and contains the
  2140. * information returned from hook_theme(), as well as additional properties
  2141. * added by _theme_process_registry().
  2142. *
  2143. * For example:
  2144. * @code
  2145. * $theme_registry['user_profile'] = array(
  2146. * 'arguments' => array(
  2147. * 'account' => NULL,
  2148. * ),
  2149. * 'template' => 'modules/user/user-profile',
  2150. * 'file' => 'modules/user/user.pages.inc',
  2151. * 'type' => 'module',
  2152. * 'theme path' => 'modules/user',
  2153. * 'theme paths' => array(
  2154. * 0 => 'modules/user',
  2155. * ),
  2156. * 'preprocess functions' => array(
  2157. * 0 => 'template_preprocess',
  2158. * 1 => 'template_preprocess_user_profile',
  2159. * ),
  2160. * );
  2161. * @endcode
  2162. *
  2163. * @param $theme_registry
  2164. * The entire cache of theme registry information, post-processing.
  2165. *
  2166. * @see hook_theme()
  2167. * @see _theme_process_registry()
  2168. */
  2169. function hook_theme_registry_alter(&$theme_registry) {
  2170. // Kill the next/previous forum topic navigation links.
  2171. foreach ($theme_registry['forum_topic_navigation']['preprocess functions'] as $key => $value) {
  2172. if ($value == 'template_preprocess_forum_topic_navigation') {
  2173. unset($theme_registry['forum_topic_navigation']['preprocess functions'][$key]);
  2174. }
  2175. }
  2176. }
  2177. /**
  2178. * Preprocess theme variables for template files.
  2179. *
  2180. * This hook allows modules to preprocess theme variables for theme templates.
  2181. * It is only called for theme hooks implemented as template files, but
  2182. * not for those implemented as theme functions. The purpose of this hook is
  2183. * to allow modules to add to or override variables for all template files.
  2184. *
  2185. * For more detailed information, see theme().
  2186. *
  2187. * @param $variables
  2188. * The variables array (modify in place).
  2189. * @param $hook
  2190. * The name of the theme hook.
  2191. */
  2192. function hook_preprocess(&$variables, $hook) {
  2193. // Add the name of the current theme hook as a variable
  2194. $variables['theme_hook'] = $hook;
  2195. }
  2196. /**
  2197. * Preprocess theme variables for a specific theme hook.
  2198. *
  2199. * This hook allows modules to preprocess theme variables for a specific theme
  2200. * hook. It should only be used if a module needs to override or add to the
  2201. * theme preprocessing for a theme hook it didn't define.
  2202. *
  2203. * Note that, as all preprocess hooks, this hook is only invoked for theme hooks
  2204. * implemented as template files, but not those implemented as theme functions.
  2205. *
  2206. * For more detailed information, see theme().
  2207. *
  2208. * @param $variables
  2209. * The variables array (modify in place).
  2210. */
  2211. function hook_preprocess_HOOK(&$variables) {
  2212. $variables['drupal_major_version'] = '6.x';
  2213. }
  2214. /**
  2215. * Update Drupal's full-text index for this module.
  2216. *
  2217. * Modules can implement this hook if they want to use the full-text indexing
  2218. * mechanism in Drupal.
  2219. *
  2220. * This hook is called every cron run if search.module is enabled. A module
  2221. * should check which of its items were modified or added since the last
  2222. * run. It is advised that you implement a throttling mechanism which indexes
  2223. * at most 'search_cron_limit' items per run (see example below).
  2224. *
  2225. * You should also be aware that indexing may take too long and be aborted if
  2226. * there is a PHP time limit. That's why you should update your internal
  2227. * bookkeeping multiple times per run, preferably after every item that
  2228. * is indexed.
  2229. *
  2230. * Per item that needs to be indexed, you should call search_index() with
  2231. * its content as a single HTML string. The search indexer will analyse the
  2232. * HTML and use it to assign higher weights to important words (such as
  2233. * titles). It will also check for links that point to nodes, and use them to
  2234. * boost the ranking of the target nodes.
  2235. *
  2236. * @ingroup search
  2237. */
  2238. function hook_update_index() {
  2239. $last = variable_get('node_cron_last', 0);
  2240. $limit = (int)variable_get('search_cron_limit', 100);
  2241. $result = db_query_range('SELECT n.nid, c.last_comment_timestamp FROM {node} n LEFT JOIN {node_comment_statistics} c ON n.nid = c.nid WHERE n.status = 1 AND n.moderate = 0 AND (n.created > %d OR n.changed > %d OR c.last_comment_timestamp > %d) ORDER BY GREATEST(n.created, n.changed, c.last_comment_timestamp) ASC', $last, $last, $last, 0, $limit);
  2242. while ($node = db_fetch_object($result)) {
  2243. $last_comment = $node->last_comment_timestamp;
  2244. $node = node_load(array('nid' => $node->nid));
  2245. // We update this variable per node in case cron times out, or if the node
  2246. // cannot be indexed (PHP nodes which call drupal_goto, for example).
  2247. // In rare cases this can mean a node is only partially indexed, but the
  2248. // chances of this happening are very small.
  2249. variable_set('node_cron_last', max($last_comment, $node->changed, $node->created));
  2250. // Get node output (filtered and with module-specific fields).
  2251. if (node_hook($node, 'view')) {
  2252. node_invoke($node, 'view', false, false);
  2253. }
  2254. else {
  2255. $node = node_prepare($node, false);
  2256. }
  2257. // Allow modules to change $node->body before viewing.
  2258. node_invoke_nodeapi($node, 'view', false, false);
  2259. $text = '<h1>'. drupal_specialchars($node->title) .'</h1>'. $node->body;
  2260. // Fetch extra data normally not visible
  2261. $extra = node_invoke_nodeapi($node, 'update index');
  2262. foreach ($extra as $t) {
  2263. $text .= $t;
  2264. }
  2265. // Update index
  2266. search_index($node->nid, 'node', $text);
  2267. }
  2268. }
  2269. /**
  2270. * Act on user account actions.
  2271. *
  2272. * This hook allows modules to react when operations are performed on user
  2273. * accounts.
  2274. *
  2275. * @param $op
  2276. * What kind of action is being performed. Possible values (in alphabetical
  2277. * order):
  2278. * - after_update: The user object has been updated and changed. Use this
  2279. * (probably along with 'insert') if you want to reuse some information from
  2280. * the user object.
  2281. * - categories: A set of user information categories is requested.
  2282. * - delete: The user account is being deleted. The module should remove its
  2283. * custom additions to the user object from the database.
  2284. * - form: The user account edit form is about to be displayed. The module
  2285. * should present the form elements it wishes to inject into the form.
  2286. * - insert: The user account is being added. The module should save its
  2287. * custom additions to the user object into the database and set the saved
  2288. * fields to NULL in $edit.
  2289. * - load: The user account is being loaded. The module may respond to this
  2290. * and insert additional information into the user object.
  2291. * - login: The user just logged in.
  2292. * - logout: The user just logged out.
  2293. * - register: The user account registration form is about to be displayed.
  2294. * The module should present the form elements it wishes to inject into the
  2295. * form.
  2296. * - submit: Modify the account before it gets saved.
  2297. * - update: The user account is being changed. The module should save its
  2298. * custom additions to the user object into the database and set the saved
  2299. * fields to NULL in $edit.
  2300. * - validate: The user account is about to be modified. The module should
  2301. * validate its custom additions to the user object, registering errors as
  2302. * necessary.
  2303. * - view: The user's account information is being displayed. The module
  2304. * should format its custom additions for display, and add them to the
  2305. * $account->content array.
  2306. * @param $edit
  2307. * The array of form values submitted by the user.
  2308. * @param $account
  2309. * The user object on which the operation is being performed.
  2310. * @param $category
  2311. * The active category of user information being edited.
  2312. *
  2313. * @return
  2314. * This varies depending on the operation.
  2315. * - categories: An array of associative arrays representing the categories
  2316. * added by the implementing module. Each array can have the following
  2317. * keys:
  2318. * - name: The internal name of the category.
  2319. * - title: The human-readable, localized name of the category.
  2320. * - weight: An integer specifying the category's sort ordering.
  2321. * - access callback: Name of a menu access callback function to use when
  2322. * editing this category. Defaults to using user_edit_access() if not
  2323. * specified. See hook_menu() for more information on menu access
  2324. * callbacks.
  2325. * - access arguments: Arguments for the access callback function.
  2326. * Defaults to array(1) if not specified.
  2327. * - delete: None.
  2328. * - form, register: An array containing the form elements to add to the form.
  2329. * - insert: None.
  2330. * - load: None.
  2331. * - login: None.
  2332. * - logout: None.
  2333. * - submit: None.
  2334. * - update: None.
  2335. * - validate: None.
  2336. * - view: None.
  2337. */
  2338. function hook_user($op, &$edit, &$account, $category = NULL) {
  2339. if ($op == 'form' && $category == 'account') {
  2340. $form['comment_settings'] = array(
  2341. '#type' => 'fieldset',
  2342. '#title' => t('Comment settings'),
  2343. '#collapsible' => TRUE,
  2344. '#weight' => 4);
  2345. $form['comment_settings']['signature'] = array(
  2346. '#type' => 'textarea',
  2347. '#title' => t('Signature'),
  2348. '#default_value' => $edit['signature'],
  2349. '#description' => t('Your signature will be publicly displayed at the end of your comments.'));
  2350. return $form;
  2351. }
  2352. }
  2353. /**
  2354. * Add mass user operations.
  2355. *
  2356. * This hook enables modules to inject custom operations into the mass operations
  2357. * dropdown found at admin/user/user, by associating a callback function with
  2358. * the operation, which is called when the form is submitted. The callback function
  2359. * receives one initial argument, which is an array of the checked users.
  2360. *
  2361. * @return
  2362. * An array of operations. Each operation is an associative array that may
  2363. * contain the following key-value pairs:
  2364. * - "label": Required. The label for the operation, displayed in the dropdown menu.
  2365. * - "callback": Required. The function to call for the operation.
  2366. * - "callback arguments": Optional. An array of additional arguments to pass to
  2367. * the callback function.
  2368. *
  2369. */
  2370. function hook_user_operations() {
  2371. $operations = array(
  2372. 'unblock' => array(
  2373. 'label' => t('Unblock the selected users'),
  2374. 'callback' => 'user_user_operations_unblock',
  2375. ),
  2376. 'block' => array(
  2377. 'label' => t('Block the selected users'),
  2378. 'callback' => 'user_user_operations_block',
  2379. ),
  2380. 'delete' => array(
  2381. 'label' => t('Delete the selected users'),
  2382. ),
  2383. );
  2384. return $operations;
  2385. }
  2386. /**
  2387. * Register XML-RPC callbacks.
  2388. *
  2389. * This hook lets a module register callback functions to be called when
  2390. * particular XML-RPC methods are invoked by a client.
  2391. *
  2392. * @return
  2393. * An array which maps XML-RPC methods to Drupal functions. Each array
  2394. * element is either a pair of method => function or an array with four
  2395. * entries:
  2396. * - The XML-RPC method name (for example, module.function).
  2397. * - The Drupal callback function (for example, module_function).
  2398. * - The method signature is an array of XML-RPC types. The first element
  2399. * of this array is the type of return value and then you should write a
  2400. * list of the types of the parameters. XML-RPC types are the following
  2401. * (See the types at @link http://www.xmlrpc.com/spec http://www.xmlrpc.com/spec @endlink ):
  2402. * - "boolean": 0 (false) or 1 (true).
  2403. * - "double": a floating point number (for example, -12.214).
  2404. * - "int": a integer number (for example, -12).
  2405. * - "array": an array without keys (for example, array(1, 2, 3)).
  2406. * - "struct": an associative array or an object (for example,
  2407. * array('one' => 1, 'two' => 2)).
  2408. * - "date": when you return a date, then you may either return a
  2409. * timestamp (time(), mktime() etc.) or an ISO8601 timestamp. When
  2410. * date is specified as an input parameter, then you get an object,
  2411. * which is described in the function xmlrpc_date
  2412. * - "base64": a string containing binary data, automatically
  2413. * encoded/decoded automatically.
  2414. * - "string": anything else, typically a string.
  2415. * - A descriptive help string, enclosed in a t() function for translation
  2416. * purposes.
  2417. * Both forms are shown in the example.
  2418. */
  2419. function hook_xmlrpc() {
  2420. return array(
  2421. 'drupal.login' => 'drupal_login',
  2422. array(
  2423. 'drupal.site.ping',
  2424. 'drupal_directory_ping',
  2425. array('boolean', 'string', 'string', 'string', 'string', 'string'),
  2426. t('Handling ping request'))
  2427. );
  2428. }
  2429. /**
  2430. * Log an event message
  2431. *
  2432. * This hook allows modules to route log events to custom destinations, such as
  2433. * SMS, Email, pager, syslog, ...etc.
  2434. *
  2435. * @param $log_entry
  2436. * An associative array containing the following keys:
  2437. * - type: The type of message for this entry. For contributed modules, this is
  2438. * normally the module name. Do not use 'debug', use severity WATCHDOG_DEBUG instead.
  2439. * - user: The user object for the user who was logged in when the event happened.
  2440. * - request_uri: The Request URI for the page the event happened in.
  2441. * - referer: The page that referred the use to the page where the event occurred.
  2442. * - ip: The IP address where the request for the page came from.
  2443. * - timestamp: The UNIX timetamp of the date/time the event occurred
  2444. * - severity: One of the following values as defined in RFC 3164 http://www.faqs.org/rfcs/rfc3164.html
  2445. * WATCHDOG_EMERG Emergency: system is unusable
  2446. * WATCHDOG_ALERT Alert: action must be taken immediately
  2447. * WATCHDOG_CRITICAL Critical: critical conditions
  2448. * WATCHDOG_ERROR Error: error conditions
  2449. * WATCHDOG_WARNING Warning: warning conditions
  2450. * WATCHDOG_NOTICE Notice: normal but significant condition
  2451. * WATCHDOG_INFO Informational: informational messages
  2452. * WATCHDOG_DEBUG Debug: debug-level messages
  2453. * - link: an optional link provided by the module that called the watchdog() function.
  2454. * - message: The text of the message to be logged.
  2455. *
  2456. * @return
  2457. * None.
  2458. */
  2459. function hook_watchdog($log_entry) {
  2460. global $base_url, $language;
  2461. $severity_list = array(
  2462. WATCHDOG_EMERG => t('Emergency'),
  2463. WATCHDOG_ALERT => t('Alert'),
  2464. WATCHDOG_CRITICAL => t('Critical'),
  2465. WATCHDOG_ERROR => t('Error'),
  2466. WATCHDOG_WARNING => t('Warning'),
  2467. WATCHDOG_NOTICE => t('Notice'),
  2468. WATCHDOG_INFO => t('Info'),
  2469. WATCHDOG_DEBUG => t('Debug'),
  2470. );
  2471. $to = 'someone@example.com';
  2472. $params = array();
  2473. $params['subject'] = t('[@site_name] @severity_desc: Alert from your web site', array(
  2474. '@site_name' => variable_get('site_name', 'Drupal'),
  2475. '@severity_desc' => $severity_list[$log_entry['severity']]
  2476. ));
  2477. $params['message'] = "\nSite: @base_url";
  2478. $params['message'] .= "\nSeverity: (@severity) @severity_desc";
  2479. $params['message'] .= "\nTimestamp: @timestamp";
  2480. $params['message'] .= "\nType: @type";
  2481. $params['message'] .= "\nIP Address: @ip";
  2482. $params['message'] .= "\nRequest URI: @request_uri";
  2483. $params['message'] .= "\nReferrer URI: @referer_uri";
  2484. $params['message'] .= "\nUser: (@uid) @name";
  2485. $params['message'] .= "\nLink: @link";
  2486. $params['message'] .= "\nMessage: \n\n@message";
  2487. $params['message'] = t($params['message'], array(
  2488. '@base_url' => $base_url,
  2489. '@severity' => $log_entry['severity'],
  2490. '@severity_desc' => $severity_list[$log_entry['severity']],
  2491. '@timestamp' => format_date($log_entry['timestamp']),
  2492. '@type' => $log_entry['type'],
  2493. '@ip' => $log_entry['ip'],
  2494. '@request_uri' => $log_entry['request_uri'],
  2495. '@referer_uri' => $log_entry['referer'],
  2496. '@uid' => $log_entry['user']->uid,
  2497. '@name' => $log_entry['user']->name,
  2498. '@link' => strip_tags($log_entry['link']),
  2499. '@message' => strip_tags($log_entry['message']),
  2500. ));
  2501. drupal_mail('emaillog', 'log', $to, $language, $params);
  2502. }
  2503. /**
  2504. * Prepare a message based on parameters; called from drupal_mail().
  2505. *
  2506. * @param $key
  2507. * An identifier of the mail.
  2508. * @param $message
  2509. * An array to be filled in. Keys in this array include:
  2510. * - 'id':
  2511. * An id to identify the mail sent. Look at module source code
  2512. * or drupal_mail() for possible id values.
  2513. * - 'to':
  2514. * The address or addresses the message will be sent to. The
  2515. * formatting of this string must comply with RFC 2822.
  2516. * - 'subject':
  2517. * Subject of the e-mail to be sent. This must not contain any
  2518. * newline characters, or the mail may not be sent properly.
  2519. * drupal_mail() sets this to an empty string when the hook is invoked.
  2520. * - 'body':
  2521. * An array of lines containing the message to be sent. Drupal will format
  2522. * the correct line endings for you. drupal_mail() sets this to an empty array
  2523. * when the hook is invoked.
  2524. * - 'from':
  2525. * The address the message will be marked as being from, which is set by
  2526. * drupal_mail() to either a custom address or the site-wide default email
  2527. * address when the hook is invoked.
  2528. * - 'headers:
  2529. * Associative array containing mail headers, such as From, Sender, MIME-Version,
  2530. * Content-Type, etc. drupal_mail() pre-fills several headers in this array.
  2531. * @param $params
  2532. * An arbitrary array of parameters set by the caller to drupal_mail.
  2533. */
  2534. function hook_mail($key, &$message, $params) {
  2535. $account = $params['account'];
  2536. $context = $params['context'];
  2537. $variables = array(
  2538. '%site_name' => variable_get('site_name', 'Drupal'),
  2539. '%username' => $account->name,
  2540. );
  2541. if ($context['hook'] == 'taxonomy') {
  2542. $object = $params['object'];
  2543. $vocabulary = taxonomy_vocabulary_load($object->vid);
  2544. $variables += array(
  2545. '%term_name' => $object->name,
  2546. '%term_description' => $object->description,
  2547. '%term_id' => $object->tid,
  2548. '%vocabulary_name' => $vocabulary->name,
  2549. '%vocabulary_description' => $vocabulary->description,
  2550. '%vocabulary_id' => $vocabulary->vid,
  2551. );
  2552. }
  2553. // Node-based variable translation is only available if we have a node.
  2554. if (isset($params['node'])) {
  2555. $node = $params['node'];
  2556. $variables += array(
  2557. '%uid' => $node->uid,
  2558. '%node_url' => url('node/'. $node->nid, array('absolute' => TRUE)),
  2559. '%node_type' => node_get_types('name', $node),
  2560. '%title' => $node->title,
  2561. '%teaser' => $node->teaser,
  2562. '%body' => $node->body,
  2563. );
  2564. }
  2565. $subject = strtr($context['subject'], $variables);
  2566. $body = strtr($context['message'], $variables);
  2567. $message['subject'] .= str_replace(array("\r", "\n"), '', $subject);
  2568. $message['body'][] = drupal_html_to_text($body);
  2569. }
  2570. /**
  2571. * Add a list of cache tables to be cleared.
  2572. *
  2573. * This hook allows your module to add cache table names to the list of cache
  2574. * tables that will be cleared by the Clear button on the Performance page or
  2575. * whenever drupal_flush_all_caches is invoked.
  2576. *
  2577. * @see drupal_flush_all_caches()
  2578. * @see system_clear_cache_submit()
  2579. *
  2580. * @param None.
  2581. *
  2582. * @return
  2583. * An array of cache table names.
  2584. */
  2585. function hook_flush_caches() {
  2586. return array('cache_example');
  2587. }
  2588. /**
  2589. * Allows modules to provide an alternative path for the terms it manages.
  2590. *
  2591. * For vocabularies not maintained by taxonomy.module, give the maintaining
  2592. * module a chance to provide a path for terms in that vocabulary.
  2593. *
  2594. * "Not maintained by taxonomy.module" is misleading. It means that the vocabulary
  2595. * table contains a module name in the 'module' column. Any module may update this
  2596. * column and will then be called to provide an alternative path for the terms
  2597. * it recognizes (manages).
  2598. *
  2599. * This hook should be used rather than hard-coding a "taxonomy/term/xxx" path.
  2600. *
  2601. * @see taxonomy_term_path()
  2602. *
  2603. * @param $term
  2604. * A term object.
  2605. * @return
  2606. * An internal Drupal path.
  2607. */
  2608. function hook_term_path($term) {
  2609. return 'taxonomy/term/'. $term->tid;
  2610. }
  2611. /**
  2612. * Allows modules to define their own text groups that can be translated.
  2613. *
  2614. * @param $op
  2615. * Type of operation. Currently, only supports 'groups'.
  2616. */
  2617. function hook_locale($op = 'groups') {
  2618. switch ($op) {
  2619. case 'groups':
  2620. return array('custom' => t('Custom'));
  2621. }
  2622. }
  2623. /**
  2624. * custom_url_rewrite_outbound is not a hook, it's a function you can add to
  2625. * settings.php to alter all links generated by Drupal. This function is called from url().
  2626. * This function is called very frequently (100+ times per page) so performance is
  2627. * critical.
  2628. *
  2629. * This function should change the value of $path and $options by reference.
  2630. *
  2631. * @param $path
  2632. * The alias of the $original_path as defined in the database.
  2633. * If there is no match in the database it'll be the same as $original_path
  2634. * @param $options
  2635. * An array of link attributes such as querystring and fragment. See url().
  2636. * @param $original_path
  2637. * The unaliased Drupal path that is being linked to.
  2638. */
  2639. function custom_url_rewrite_outbound(&$path, &$options, $original_path) {
  2640. global $user;
  2641. // Change all 'node' to 'article'.
  2642. if (preg_match('|^node(/.*)|', $path, $matches)) {
  2643. $path = 'article'. $matches[1];
  2644. }
  2645. // Create a path called 'e' which lands the user on her profile edit page.
  2646. if ($path == 'user/'. $user->uid .'/edit') {
  2647. $path = 'e';
  2648. }
  2649. }
  2650. /**
  2651. * custom_url_rewrite_inbound is not a hook, it's a function you can add to
  2652. * settings.php to alter incoming requests so they map to a Drupal path.
  2653. * This function is called before modules are loaded and
  2654. * the menu system is initialized and it changes $_GET['q'].
  2655. *
  2656. * This function should change the value of $result by reference.
  2657. *
  2658. * @param $result
  2659. * The Drupal path based on the database. If there is no match in the database it'll be the same as $path.
  2660. * @param $path
  2661. * The path to be rewritten.
  2662. * @param $path_language
  2663. * An optional language code to rewrite the path into.
  2664. */
  2665. function custom_url_rewrite_inbound(&$result, $path, $path_language) {
  2666. global $user;
  2667. // Change all article/x requests to node/x
  2668. if (preg_match('|^article(/.*)|', $path, $matches)) {
  2669. $result = 'node'. $matches[1];
  2670. }
  2671. // Redirect a path called 'e' to the user's profile edit page.
  2672. if ($path == 'e') {
  2673. $result = 'user/'. $user->uid .'/edit';
  2674. }
  2675. }
  2676. /**
  2677. * Perform alterations on translation links.
  2678. *
  2679. * A translation link may need to point to a different path or use a translated
  2680. * link text before going through l(), which will just handle the path aliases.
  2681. *
  2682. * @param $links
  2683. * Nested array of links keyed by language code.
  2684. * @param $path
  2685. * The current path.
  2686. * @return
  2687. * None.
  2688. */
  2689. function hook_translation_link_alter(&$links, $path) {
  2690. global $language;
  2691. if (isset($links[$language])) {
  2692. foreach ($links[$language] as $link) {
  2693. $link['attributes']['class'] .= ' active-language';
  2694. }
  2695. }
  2696. }
  2697. /**
  2698. * @} End of "addtogroup hooks".
  2699. */

Functions

Namesort descending Description
custom_url_rewrite_inbound custom_url_rewrite_inbound is not a hook, it's a function you can add to settings.php to alter incoming requests so they map to a Drupal path. This function is called before modules are loaded and the menu system is initialized and it changes…
custom_url_rewrite_outbound custom_url_rewrite_outbound is not a hook, it's a function you can add to settings.php to alter all links generated by Drupal. This function is called from url(). This function is called very frequently (100+ times per page) so performance…
hook_actions_delete Execute code after an action is deleted.
hook_action_info Declare information about one or more Drupal actions.
hook_action_info_alter Alter the actions declared by another module.
hook_block Declare a block or set of blocks.
hook_boot Perform setup tasks. See also, hook_init.
hook_comment Respond to comment actions.
hook_cron Perform periodic actions.
hook_db_rewrite_sql Rewrite database queries, usually for access control.
hook_elements Allows modules to declare their own Forms API element types and specify their default values.
hook_exit Perform cleanup tasks.
hook_file_download Control access to private file downloads and specify HTTP headers.
hook_filter Define content filters.
hook_filter_tips Provide tips for using filters.
hook_flush_caches Add a list of cache tables to be cleared.
hook_footer Insert closing HTML.
hook_forms Map form_ids to builder functions.
hook_form_alter Perform alterations before a form is rendered.
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 Expose a list of triggers (events) that users can assign actions to.
hook_init Perform setup tasks. See also, hook_boot.
hook_link Define internal Drupal links.
hook_link_alter Perform alterations before links on a node or comment are rendered.
hook_locale Allows modules to define their own text groups that can be translated.
hook_mail Prepare a message based on parameters; called from drupal_mail().
hook_mail_alter Alter any aspect of email sent by Drupal. You can use this hook to add a common site footer to all outgoing email, add extra header fields, and/or modify the email in any way. HTML-izing the outgoing email is one possibility. See also drupal_mail().
hook_menu Define menu items and page callbacks.
hook_menu_alter Alter the data being saved to the {menu_router} table after hook_menu is invoked.
hook_menu_link_alter Alter the data being saved to the {menu_links} table by menu_link_save().
hook_nodeapi Act on nodes defined by other modules.
hook_node_access_records Set permissions for a node to be written to the database.
hook_node_grants Inform the node access system what permissions the user has.
hook_node_operations Add mass node operations.
hook_openid Allow modules to modify the OpenID request parameters.
hook_perm Define user permissions.
hook_ping Ping another server.
hook_preprocess Preprocess theme variables for template files.
hook_preprocess_HOOK Preprocess theme variables for a specific theme hook.
hook_profile_alter Alter profile items before they are rendered.
hook_schema_alter Performs alterations to existing database schemas.
hook_search Define a custom search routine.
hook_search_page Override the rendering of search results.
hook_search_preprocess Preprocess text for the search index.
hook_system_info_alter Alter the information parsed from module and theme .info files
hook_taxonomy Act on taxonomy changes.
hook_term_path Allows modules to provide an alternative path for the terms it manages.
hook_theme Register a module (or theme's) theme implementations.
hook_theme_registry_alter Alter the theme registry information returned from hook_theme().
hook_translated_menu_link_alter Alter a menu link after it's translated, but before it's rendered.
hook_translation_link_alter Perform alterations on translation links.
hook_update_index Update Drupal's full-text index for this module.
hook_update_projects_alter Alter the list of projects before fetching data and comparing versions.
hook_update_status_alter Alter the information about available updates for projects.
hook_user Act on user account actions.
hook_user_operations Add mass user operations.
hook_watchdog Log an event message
hook_xmlrpc Register XML-RPC callbacks.
page_cache_fastpath Outputs a cached page.