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