| Drupal | PHP Cross Reference | Content Management Systems |
1 <?php 2 3 /** 4 * @file 5 * Hooks provided by Drupal core and the System module. 6 */ 7 8 /** 9 * @addtogroup hooks 10 * @{ 11 */ 12 13 /** 14 * Defines one or more hooks that are exposed by a module. 15 * 16 * Normally hooks do not need to be explicitly defined. However, by declaring a 17 * hook explicitly, a module may define a "group" for it. Modules that implement 18 * a hook may then place their implementation in either $module.module or in 19 * $module.$group.inc. If the hook is located in $module.$group.inc, then that 20 * file will be automatically loaded when needed. 21 * In general, hooks that are rarely invoked and/or are very large should be 22 * placed in a separate include file, while hooks that are very short or very 23 * frequently called should be left in the main module file so that they are 24 * always available. 25 * 26 * @return 27 * An associative array whose keys are hook names and whose values are an 28 * associative array containing: 29 * - group: A string defining the group to which the hook belongs. The module 30 * system will determine whether a file with the name $module.$group.inc 31 * exists, and automatically load it when required. 32 * 33 * See system_hook_info() for all hook groups defined by Drupal core. 34 * 35 * @see hook_hook_info_alter(). 36 */ 37 function hook_hook_info() { 38 $hooks['token_info'] = array( 39 'group' => 'tokens', 40 ); 41 $hooks['tokens'] = array( 42 'group' => 'tokens', 43 ); 44 return $hooks; 45 } 46 47 /** 48 * Alter information from hook_hook_info(). 49 * 50 * @param $hooks 51 * Information gathered by module_hook_info() from other modules' 52 * implementations of hook_hook_info(). Alter this array directly. 53 * See hook_hook_info() for information on what this may contain. 54 */ 55 function hook_hook_info_alter(&$hooks) { 56 // Our module wants to completely override the core tokens, so make 57 // sure the core token hooks are not found. 58 $hooks['token_info']['group'] = 'mytokens'; 59 $hooks['tokens']['group'] = 'mytokens'; 60 } 61 62 /** 63 * Inform the base system and the Field API about one or more entity types. 64 * 65 * Inform the system about one or more entity types (i.e., object types that 66 * can be loaded via entity_load() and, optionally, to which fields can be 67 * attached). 68 * 69 * @return 70 * An array whose keys are entity type names and whose values identify 71 * properties of those types that the system needs to know about: 72 * - label: The human-readable name of the type. 73 * - controller class: The name of the class that is used to load the objects. 74 * The class has to implement the DrupalEntityControllerInterface interface. 75 * Leave blank to use the DrupalDefaultEntityController implementation. 76 * - base table: (used by DrupalDefaultEntityController) The name of the 77 * entity type's base table. 78 * - revision table: The name of the entity type's revision table (if any). 79 * - static cache: (used by DrupalDefaultEntityController) FALSE to disable 80 * static caching of entities during a page request. Defaults to TRUE. 81 * - field cache: (used by Field API loading and saving of field data) FALSE 82 * to disable Field API's persistent cache of field data. Only recommended 83 * if a higher level persistent cache is available for the entity type. 84 * Defaults to TRUE. 85 * - load hook: The name of the hook which should be invoked by 86 * DrupalDefaultEntityController:attachLoad(), for example 'node_load'. 87 * - uri callback: A function taking an entity as argument and returning the 88 * URI elements of the entity, e.g. 'path' and 'options'. The actual entity 89 * URI can be constructed by passing these elements to url(). 90 * - label callback: (optional) A function taking an entity and an entity type 91 * as arguments and returning the label of the entity. The entity label is 92 * the main string associated with an entity; for example, the title of a 93 * node or the subject of a comment. If there is an entity object property 94 * that defines the label, use the 'label' element of the 'entity keys' 95 * return value component to provide this information (see below). If more 96 * complex logic is needed to determine the label of an entity, you can 97 * instead specify a callback function here, which will be called to 98 * determine the entity label. See also the entity_label() function, which 99 * implements this logic. 100 * - language callback: (optional) A function taking an entity and an entity 101 * type as arguments and returning a language code. In most situations, when 102 * needing to determine this value, inspecting a property named after the 103 * 'language' element of the 'entity keys' should be enough. The language 104 * callback is meant to be used primarily for temporary alterations of the 105 * property value: entity-defining modules are encouraged to always define a 106 * language property, instead of using the callback as main entity language 107 * source. In fact not having a language property defined is likely to 108 * prevent an entity from being queried by language. Moreover, given that 109 * entity_language() is not necessarily used everywhere it would be 110 * appropriate, modules implementing the language callback should be aware 111 * that this might not be always called. 112 * - fieldable: Set to TRUE if you want your entity type to accept fields 113 * being attached to it. 114 * - translation: An associative array of modules registered as field 115 * translation handlers. Array keys are the module names, array values 116 * can be any data structure the module uses to provide field translation. 117 * Any empty value disallows the module to appear as a translation handler. 118 * - entity keys: An array describing how the Field API can extract the 119 * information it needs from the objects of the type. Elements: 120 * - id: The name of the property that contains the primary id of the 121 * entity. Every entity object passed to the Field API must have this 122 * property and its value must be numeric. 123 * - revision: The name of the property that contains the revision id of 124 * the entity. The Field API assumes that all revision ids are unique 125 * across all entities of a type. This entry can be omitted if the 126 * entities of this type are not versionable. 127 * - bundle: The name of the property that contains the bundle name for the 128 * entity. The bundle name defines which set of fields are attached to 129 * the entity (e.g. what nodes call "content type"). This entry can be 130 * omitted if this entity type exposes a single bundle (all entities have 131 * the same collection of fields). The name of this single bundle will be 132 * the same as the entity type. 133 * - label: The name of the property that contains the entity label. For 134 * example, if the entity's label is located in $entity->subject, then 135 * 'subject' should be specified here. If complex logic is required to 136 * build the label, a 'label callback' should be defined instead (see 137 * the 'label callback' section above for details). 138 * - language: The name of the property, typically 'language', that contains 139 * the language code representing the language the entity has been created 140 * in. This value may be changed when editing the entity and represents 141 * the language its textual components are supposed to have. If no 142 * language property is available, the 'language callback' may be used 143 * instead. This entry can be omitted if the entities of this type are not 144 * language-aware. 145 * - bundle keys: An array describing how the Field API can extract the 146 * information it needs from the bundle objects for this type. This entry 147 * is required if the 'path' provided in the 'bundles'/'admin' section 148 * identifies the bundle using a named menu placeholder whose loader 149 * callback returns an object (e.g., $vocabulary for taxonomy terms, or 150 * $node_type for nodes). If the path does not include the bundle, or the 151 * bundle is just a string rather than an automatically loaded object, then 152 * this can be omitted. Elements: 153 * - bundle: The name of the property of the bundle object that contains 154 * the name of the bundle object. 155 * - bundles: An array describing all bundles for this object type. Keys are 156 * bundles machine names, as found in the objects' 'bundle' property 157 * (defined in the 'entity keys' entry above). Elements: 158 * - label: The human-readable name of the bundle. 159 * - uri callback: Same as the 'uri callback' key documented above for the 160 * entity type, but for the bundle only. When determining the URI of an 161 * entity, if a 'uri callback' is defined for both the entity type and 162 * the bundle, the one for the bundle is used. 163 * - admin: An array of information that allows Field UI pages to attach 164 * themselves to the existing administration pages for the bundle. 165 * Elements: 166 * - path: the path of the bundle's main administration page, as defined 167 * in hook_menu(). If the path includes a placeholder for the bundle, 168 * the 'bundle argument' and 'real path' keys below are required. 169 * - bundle argument: The position of the bundle placeholder in 'path', if 170 * any. 171 * - real path: The actual path (no placeholder) of the bundle's main 172 * administration page. This will be used to generate links. 173 * - access callback: As in hook_menu(). 'user_access' will be assumed if 174 * no value is provided. 175 * - access arguments: As in hook_menu(). 176 * - view modes: An array describing the view modes for the entity type. View 177 * modes let entities be displayed differently depending on the context. 178 * For instance, a node can be displayed differently on its own page 179 * ('full' mode), on the home page or taxonomy listings ('teaser' mode), or 180 * in an RSS feed ('rss' mode). Modules taking part in the display of the 181 * entity (notably the Field API) can adjust their behavior depending on 182 * the requested view mode. An additional 'default' view mode is available 183 * for all entity types. This view mode is not intended for actual entity 184 * display, but holds default display settings. For each available view 185 * mode, administrators can configure whether it should use its own set of 186 * field display settings, or just replicate the settings of the 'default' 187 * view mode, thus reducing the amount of display configurations to keep 188 * track of. Keys of the array are view mode names. Each view mode is 189 * described by an array with the following key/value pairs: 190 * - label: The human-readable name of the view mode 191 * - custom settings: A boolean specifying whether the view mode should by 192 * default use its own custom field display settings. If FALSE, entities 193 * displayed in this view mode will reuse the 'default' display settings 194 * by default (e.g. right after the module exposing the view mode is 195 * enabled), but administrators can later use the Field UI to apply custom 196 * display settings specific to the view mode. 197 * 198 * @see entity_load() 199 * @see hook_entity_info_alter() 200 */ 201 function hook_entity_info() { 202 $return = array( 203 'node' => array( 204 'label' => t('Node'), 205 'controller class' => 'NodeController', 206 'base table' => 'node', 207 'revision table' => 'node_revision', 208 'uri callback' => 'node_uri', 209 'fieldable' => TRUE, 210 'translation' => array( 211 'locale' => TRUE, 212 ), 213 'entity keys' => array( 214 'id' => 'nid', 215 'revision' => 'vid', 216 'bundle' => 'type', 217 'language' => 'language', 218 ), 219 'bundle keys' => array( 220 'bundle' => 'type', 221 ), 222 'bundles' => array(), 223 'view modes' => array( 224 'full' => array( 225 'label' => t('Full content'), 226 'custom settings' => FALSE, 227 ), 228 'teaser' => array( 229 'label' => t('Teaser'), 230 'custom settings' => TRUE, 231 ), 232 'rss' => array( 233 'label' => t('RSS'), 234 'custom settings' => FALSE, 235 ), 236 ), 237 ), 238 ); 239 240 // Search integration is provided by node.module, so search-related 241 // view modes for nodes are defined here and not in search.module. 242 if (module_exists('search')) { 243 $return['node']['view modes'] += array( 244 'search_index' => array( 245 'label' => t('Search index'), 246 'custom settings' => FALSE, 247 ), 248 'search_result' => array( 249 'label' => t('Search result'), 250 'custom settings' => FALSE, 251 ), 252 ); 253 } 254 255 // Bundles must provide a human readable name so we can create help and error 256 // messages, and the path to attach Field admin pages to. 257 foreach (node_type_get_names() as $type => $name) { 258 $return['node']['bundles'][$type] = array( 259 'label' => $name, 260 'admin' => array( 261 'path' => 'admin/structure/types/manage/%node_type', 262 'real path' => 'admin/structure/types/manage/' . str_replace('_', '-', $type), 263 'bundle argument' => 4, 264 'access arguments' => array('administer content types'), 265 ), 266 ); 267 } 268 269 return $return; 270 } 271 272 /** 273 * Alter the entity info. 274 * 275 * Modules may implement this hook to alter the information that defines an 276 * entity. All properties that are available in hook_entity_info() can be 277 * altered here. 278 * 279 * @param $entity_info 280 * The entity info array, keyed by entity name. 281 * 282 * @see hook_entity_info() 283 */ 284 function hook_entity_info_alter(&$entity_info) { 285 // Set the controller class for nodes to an alternate implementation of the 286 // DrupalEntityController interface. 287 $entity_info['node']['controller class'] = 'MyCustomNodeController'; 288 } 289 290 /** 291 * Act on entities when loaded. 292 * 293 * This is a generic load hook called for all entity types loaded via the 294 * entity API. 295 * 296 * @param $entities 297 * The entities keyed by entity ID. 298 * @param $type 299 * The type of entities being loaded (i.e. node, user, comment). 300 */ 301 function hook_entity_load($entities, $type) { 302 foreach ($entities as $entity) { 303 $entity->foo = mymodule_add_something($entity, $type); 304 } 305 } 306 307 /** 308 * Act on an entity before it is about to be created or updated. 309 * 310 * @param $entity 311 * The entity object. 312 * @param $type 313 * The type of entity being saved (i.e. node, user, comment). 314 */ 315 function hook_entity_presave($entity, $type) { 316 $entity->changed = REQUEST_TIME; 317 } 318 319 /** 320 * Act on entities when inserted. 321 * 322 * @param $entity 323 * The entity object. 324 * @param $type 325 * The type of entity being inserted (i.e. node, user, comment). 326 */ 327 function hook_entity_insert($entity, $type) { 328 // Insert the new entity into a fictional table of all entities. 329 $info = entity_get_info($type); 330 list($id) = entity_extract_ids($type, $entity); 331 db_insert('example_entity') 332 ->fields(array( 333 'type' => $type, 334 'id' => $id, 335 'created' => REQUEST_TIME, 336 'updated' => REQUEST_TIME, 337 )) 338 ->execute(); 339 } 340 341 /** 342 * Act on entities when updated. 343 * 344 * @param $entity 345 * The entity object. 346 * @param $type 347 * The type of entity being updated (i.e. node, user, comment). 348 */ 349 function hook_entity_update($entity, $type) { 350 // Update the entity's entry in a fictional table of all entities. 351 $info = entity_get_info($type); 352 list($id) = entity_extract_ids($type, $entity); 353 db_update('example_entity') 354 ->fields(array( 355 'updated' => REQUEST_TIME, 356 )) 357 ->condition('type', $type) 358 ->condition('id', $id) 359 ->execute(); 360 } 361 362 /** 363 * Act on entities when deleted. 364 * 365 * @param $entity 366 * The entity object. 367 * @param $type 368 * The type of entity being deleted (i.e. node, user, comment). 369 */ 370 function hook_entity_delete($entity, $type) { 371 // Delete the entity's entry from a fictional table of all entities. 372 $info = entity_get_info($type); 373 list($id) = entity_extract_ids($type, $entity); 374 db_delete('example_entity') 375 ->condition('type', $type) 376 ->condition('id', $id) 377 ->execute(); 378 } 379 380 /** 381 * Alter or execute an EntityFieldQuery. 382 * 383 * @param EntityFieldQuery $query 384 * An EntityFieldQuery. One of the most important properties to be changed is 385 * EntityFieldQuery::executeCallback. If this is set to an existing function, 386 * this function will get the query as its single argument and its result 387 * will be the returned as the result of EntityFieldQuery::execute(). This can 388 * be used to change the behavior of EntityFieldQuery entirely. For example, 389 * the default implementation can only deal with one field storage engine, but 390 * it is possible to write a module that can query across field storage 391 * engines. Also, the default implementation presumes entities are stored in 392 * SQL, but the execute callback could instead query any other entity storage, 393 * local or remote. 394 * 395 * Note the $query->altered attribute which is TRUE in case the query has 396 * already been altered once. This happens with cloned queries. 397 * If there is a pager, then such a cloned query will be executed to count 398 * all elements. This query can be detected by checking for 399 * ($query->pager && $query->count), allowing the driver to return 0 from 400 * the count query and disable the pager. 401 */ 402 function hook_entity_query_alter($query) { 403 $query->executeCallback = 'my_module_query_callback'; 404 } 405 406 /** 407 * Act on entities being assembled before rendering. 408 * 409 * @param $entity 410 * The entity object. 411 * @param $type 412 * The type of entity being rendered (i.e. node, user, comment). 413 * @param $view_mode 414 * The view mode the entity is rendered in. 415 * @param $langcode 416 * The language code used for rendering. 417 * 418 * The module may add elements to $entity->content prior to rendering. The 419 * structure of $entity->content is a renderable array as expected by 420 * drupal_render(). 421 * 422 * @see hook_entity_view_alter() 423 * @see hook_comment_view() 424 * @see hook_node_view() 425 * @see hook_user_view() 426 */ 427 function hook_entity_view($entity, $type, $view_mode, $langcode) { 428 $entity->content['my_additional_field'] = array( 429 '#markup' => $additional_field, 430 '#weight' => 10, 431 '#theme' => 'mymodule_my_additional_field', 432 ); 433 } 434 435 /** 436 * Alter the results of ENTITY_view(). 437 * 438 * This hook is called after the content has been assembled in a structured 439 * array and may be used for doing processing which requires that the complete 440 * entity content structure has been built. 441 * 442 * If a module wishes to act on the rendered HTML of the entity rather than the 443 * structured content array, it may use this hook to add a #post_render 444 * callback. Alternatively, it could also implement hook_preprocess_ENTITY(). 445 * See drupal_render() and theme() for details. 446 * 447 * @param $build 448 * A renderable array representing the entity content. 449 * @param $type 450 * The type of entity being rendered (i.e. node, user, comment). 451 * 452 * @see hook_entity_view() 453 * @see hook_comment_view_alter() 454 * @see hook_node_view_alter() 455 * @see hook_taxonomy_term_view_alter() 456 * @see hook_user_view_alter() 457 */ 458 function hook_entity_view_alter(&$build, $type) { 459 if ($build['#view_mode'] == 'full' && isset($build['an_additional_field'])) { 460 // Change its weight. 461 $build['an_additional_field']['#weight'] = -10; 462 463 // Add a #post_render callback to act on the rendered HTML of the entity. 464 $build['#post_render'][] = 'my_module_node_post_render'; 465 } 466 } 467 468 /** 469 * Change the view mode of an entity that is being displayed. 470 * 471 * @param string $view_mode 472 * The view_mode that is to be used to display the entity. 473 * @param array $context 474 * Array with contextual information, including: 475 * - entity_type: The type of the entity that is being viewed. 476 * - entity: The entity object. 477 * - langcode: The langcode the entity is being viewed in. 478 */ 479 function hook_entity_view_mode_alter(&$view_mode, $context) { 480 // For nodes, change the view mode when it is teaser. 481 if ($context['entity_type'] == 'node' && $view_mode == 'teaser') { 482 $view_mode = 'my_custom_view_mode'; 483 } 484 } 485 486 /** 487 * Define administrative paths. 488 * 489 * Modules may specify whether or not the paths they define in hook_menu() are 490 * to be considered administrative. Other modules may use this information to 491 * display those pages differently (e.g. in a modal overlay, or in a different 492 * theme). 493 * 494 * To change the administrative status of menu items defined in another module's 495 * hook_menu(), modules should implement hook_admin_paths_alter(). 496 * 497 * @return 498 * An associative array. For each item, the key is the path in question, in 499 * a format acceptable to drupal_match_path(). The value for each item should 500 * be TRUE (for paths considered administrative) or FALSE (for non- 501 * administrative paths). 502 * 503 * @see hook_menu() 504 * @see drupal_match_path() 505 * @see hook_admin_paths_alter() 506 */ 507 function hook_admin_paths() { 508 $paths = array( 509 'mymodule/*/add' => TRUE, 510 'mymodule/*/edit' => TRUE, 511 ); 512 return $paths; 513 } 514 515 /** 516 * Redefine administrative paths defined by other modules. 517 * 518 * @param $paths 519 * An associative array of administrative paths, as defined by implementations 520 * of hook_admin_paths(). 521 * 522 * @see hook_admin_paths() 523 */ 524 function hook_admin_paths_alter(&$paths) { 525 // Treat all user pages as administrative. 526 $paths['user'] = TRUE; 527 $paths['user/*'] = TRUE; 528 // Treat the forum topic node form as a non-administrative page. 529 $paths['node/add/forum'] = FALSE; 530 } 531 532 /** 533 * Act on entities as they are being prepared for view. 534 * 535 * Allows you to operate on multiple entities as they are being prepared for 536 * view. Only use this if attaching the data during the entity_load() phase 537 * is not appropriate, for example when attaching other 'entity' style objects. 538 * 539 * @param $entities 540 * The entities keyed by entity ID. 541 * @param $type 542 * The type of entities being loaded (i.e. node, user, comment). 543 * @param $langcode 544 * The language to display the entity in. 545 */ 546 function hook_entity_prepare_view($entities, $type, $langcode) { 547 // Load a specific node into the user object for later theming. 548 if ($type == 'user') { 549 $nodes = mymodule_get_user_nodes(array_keys($entities)); 550 foreach ($entities as $uid => $entity) { 551 $entity->user_node = $nodes[$uid]; 552 } 553 } 554 } 555 556 /** 557 * Perform periodic actions. 558 * 559 * Modules that require some commands to be executed periodically can 560 * implement hook_cron(). The engine will then call the hook whenever a cron 561 * run happens, as defined by the administrator. Typical tasks managed by 562 * hook_cron() are database maintenance, backups, recalculation of settings 563 * or parameters, automated mailing, and retrieving remote data. 564 * 565 * Short-running or non-resource-intensive tasks can be executed directly in 566 * the hook_cron() implementation. 567 * 568 * Long-running tasks and tasks that could time out, such as retrieving remote 569 * data, sending email, and intensive file tasks, should use the queue API 570 * instead of executing the tasks directly. To do this, first define one or 571 * more queues via hook_cron_queue_info(). Then, add items that need to be 572 * processed to the defined queues. 573 */ 574 function hook_cron() { 575 // Short-running operation example, not using a queue: 576 // Delete all expired records since the last cron run. 577 $expires = variable_get('mymodule_cron_last_run', REQUEST_TIME); 578 db_delete('mymodule_table') 579 ->condition('expires', $expires, '>=') 580 ->execute(); 581 variable_set('mymodule_cron_last_run', REQUEST_TIME); 582 583 // Long-running operation example, leveraging a queue: 584 // Fetch feeds from other sites. 585 $result = db_query('SELECT * FROM {aggregator_feed} WHERE checked + refresh < :time AND refresh <> :never', array( 586 ':time' => REQUEST_TIME, 587 ':never' => AGGREGATOR_CLEAR_NEVER, 588 )); 589 $queue = DrupalQueue::get('aggregator_feeds'); 590 foreach ($result as $feed) { 591 $queue->createItem($feed); 592 } 593 } 594 595 /** 596 * Declare queues holding items that need to be run periodically. 597 * 598 * While there can be only one hook_cron() process running at the same time, 599 * there can be any number of processes defined here running. Because of 600 * this, long running tasks are much better suited for this API. Items queued 601 * in hook_cron() might be processed in the same cron run if there are not many 602 * items in the queue, otherwise it might take several requests, which can be 603 * run in parallel. 604 * 605 * @return 606 * An associative array where the key is the queue name and the value is 607 * again an associative array. Possible keys are: 608 * - 'worker callback': The name of the function to call. It will be called 609 * with one argument, the item created via DrupalQueue::createItem() in 610 * hook_cron(). 611 * - 'time': (optional) How much time Drupal should spend on calling this 612 * worker in seconds. Defaults to 15. 613 * 614 * @see hook_cron() 615 * @see hook_cron_queue_info_alter() 616 */ 617 function hook_cron_queue_info() { 618 $queues['aggregator_feeds'] = array( 619 'worker callback' => 'aggregator_refresh', 620 'time' => 60, 621 ); 622 return $queues; 623 } 624 625 /** 626 * Alter cron queue information before cron runs. 627 * 628 * Called by drupal_cron_run() to allow modules to alter cron queue settings 629 * before any jobs are processesed. 630 * 631 * @param array $queues 632 * An array of cron queue information. 633 * 634 * @see hook_cron_queue_info() 635 * @see drupal_cron_run() 636 */ 637 function hook_cron_queue_info_alter(&$queues) { 638 // This site has many feeds so let's spend 90 seconds on each cron run 639 // updating feeds instead of the default 60. 640 $queues['aggregator_feeds']['time'] = 90; 641 } 642 643 /** 644 * Allows modules to declare their own Form API element types and specify their 645 * default values. 646 * 647 * This hook allows modules to declare their own form element types and to 648 * specify their default values. The values returned by this hook will be 649 * merged with the elements returned by hook_form() implementations and so 650 * can return defaults for any Form APIs keys in addition to those explicitly 651 * mentioned below. 652 * 653 * Each of the form element types defined by this hook is assumed to have 654 * a matching theme function, e.g. theme_elementtype(), which should be 655 * registered with hook_theme() as normal. 656 * 657 * For more information about custom element types see the explanation at 658 * http://drupal.org/node/169815. 659 * 660 * @return 661 * An associative array describing the element types being defined. The array 662 * contains a sub-array for each element type, with the machine-readable type 663 * name as the key. Each sub-array has a number of possible attributes: 664 * - "#input": boolean indicating whether or not this element carries a value 665 * (even if it's hidden). 666 * - "#process": array of callback functions taking $element, $form_state, 667 * and $complete_form. 668 * - "#after_build": array of callback functions taking $element and $form_state. 669 * - "#validate": array of callback functions taking $form and $form_state. 670 * - "#element_validate": array of callback functions taking $element and 671 * $form_state. 672 * - "#pre_render": array of callback functions taking $element and $form_state. 673 * - "#post_render": array of callback functions taking $element and $form_state. 674 * - "#submit": array of callback functions taking $form and $form_state. 675 * - "#title_display": optional string indicating if and how #title should be 676 * displayed, see theme_form_element() and theme_form_element_label(). 677 * 678 * @see hook_element_info_alter() 679 * @see system_element_info() 680 */ 681 function hook_element_info() { 682 $types['filter_format'] = array( 683 '#input' => TRUE, 684 ); 685 return $types; 686 } 687 688 /** 689 * Alter the element type information returned from modules. 690 * 691 * A module may implement this hook in order to alter the element type defaults 692 * defined by a module. 693 * 694 * @param $type 695 * All element type defaults as collected by hook_element_info(). 696 * 697 * @see hook_element_info() 698 */ 699 function hook_element_info_alter(&$type) { 700 // Decrease the default size of textfields. 701 if (isset($type['textfield']['#size'])) { 702 $type['textfield']['#size'] = 40; 703 } 704 } 705 706 /** 707 * Perform cleanup tasks. 708 * 709 * This hook is run at the end of each page request. It is often used for 710 * page logging and specialized cleanup. This hook MUST NOT print anything 711 * because by the time it runs the response is already sent to the browser. 712 * 713 * Only use this hook if your code must run even for cached page views. 714 * If you have code which must run once on all non-cached pages, use 715 * hook_init() instead. That is the usual case. If you implement this hook 716 * and see an error like 'Call to undefined function', it is likely that 717 * you are depending on the presence of a module which has not been loaded yet. 718 * It is not loaded because Drupal is still in bootstrap mode. 719 * 720 * @param $destination 721 * If this hook is invoked as part of a drupal_goto() call, then this argument 722 * will be a fully-qualified URL that is the destination of the redirect. 723 */ 724 function hook_exit($destination = NULL) { 725 db_update('counter') 726 ->expression('hits', 'hits + 1') 727 ->condition('type', 1) 728 ->execute(); 729 } 730 731 /** 732 * Perform necessary alterations to the JavaScript before it is presented on 733 * the page. 734 * 735 * @param $javascript 736 * An array of all JavaScript being presented on the page. 737 * 738 * @see drupal_add_js() 739 * @see drupal_get_js() 740 * @see drupal_js_defaults() 741 */ 742 function hook_js_alter(&$javascript) { 743 // Swap out jQuery to use an updated version of the library. 744 $javascript['misc/jquery.js']['data'] = drupal_get_path('module', 'jquery_update') . '/jquery.js'; 745 } 746 747 /** 748 * Registers JavaScript/CSS libraries associated with a module. 749 * 750 * Modules implementing this return an array of arrays. The key to each 751 * sub-array is the machine readable name of the library. Each library may 752 * contain the following items: 753 * 754 * - 'title': The human readable name of the library. 755 * - 'website': The URL of the library's web site. 756 * - 'version': A string specifying the version of the library; intentionally 757 * not a float because a version like "1.2.3" is not a valid float. Use PHP's 758 * version_compare() to compare different versions. 759 * - 'js': An array of JavaScript elements; each element's key is used as $data 760 * argument, each element's value is used as $options array for 761 * drupal_add_js(). To add library-specific (not module-specific) JavaScript 762 * settings, the key may be skipped, the value must specify 763 * 'type' => 'setting', and the actual settings must be contained in a 'data' 764 * element of the value. 765 * - 'css': Like 'js', an array of CSS elements passed to drupal_add_css(). 766 * - 'dependencies': An array of libraries that are required for a library. Each 767 * element is an array listing the module and name of another library. Note 768 * that all dependencies for each dependent library will also be added when 769 * this library is added. 770 * 771 * Registered information for a library should contain re-usable data only. 772 * Module- or implementation-specific data and integration logic should be added 773 * separately. 774 * 775 * @return 776 * An array defining libraries associated with a module. 777 * 778 * @see system_library() 779 * @see drupal_add_library() 780 * @see drupal_get_library() 781 */ 782 function hook_library() { 783 // Library One. 784 $libraries['library-1'] = array( 785 'title' => 'Library One', 786 'website' => 'http://example.com/library-1', 787 'version' => '1.2', 788 'js' => array( 789 drupal_get_path('module', 'my_module') . '/library-1.js' => array(), 790 ), 791 'css' => array( 792 drupal_get_path('module', 'my_module') . '/library-2.css' => array( 793 'type' => 'file', 794 'media' => 'screen', 795 ), 796 ), 797 ); 798 // Library Two. 799 $libraries['library-2'] = array( 800 'title' => 'Library Two', 801 'website' => 'http://example.com/library-2', 802 'version' => '3.1-beta1', 803 'js' => array( 804 // JavaScript settings may use the 'data' key. 805 array( 806 'type' => 'setting', 807 'data' => array('library2' => TRUE), 808 ), 809 ), 810 'dependencies' => array( 811 // Require jQuery UI core by System module. 812 array('system', 'ui'), 813 // Require our other library. 814 array('my_module', 'library-1'), 815 // Require another library. 816 array('other_module', 'library-3'), 817 ), 818 ); 819 return $libraries; 820 } 821 822 /** 823 * Alters the JavaScript/CSS library registry. 824 * 825 * Allows certain, contributed modules to update libraries to newer versions 826 * while ensuring backwards compatibility. In general, such manipulations should 827 * only be done by designated modules, since most modules that integrate with a 828 * certain library also depend on the API of a certain library version. 829 * 830 * @param $libraries 831 * The JavaScript/CSS libraries provided by $module. Keyed by internal library 832 * name and passed by reference. 833 * @param $module 834 * The name of the module that registered the libraries. 835 * 836 * @see hook_library() 837 */ 838 function hook_library_alter(&$libraries, $module) { 839 // Update Farbtastic to version 2.0. 840 if ($module == 'system' && isset($libraries['farbtastic'])) { 841 // Verify existing version is older than the one we are updating to. 842 if (version_compare($libraries['farbtastic']['version'], '2.0', '<')) { 843 // Update the existing Farbtastic to version 2.0. 844 $libraries['farbtastic']['version'] = '2.0'; 845 $libraries['farbtastic']['js'] = array( 846 drupal_get_path('module', 'farbtastic_update') . '/farbtastic-2.0.js' => array(), 847 ); 848 } 849 } 850 } 851 852 /** 853 * Alter CSS files before they are output on the page. 854 * 855 * @param $css 856 * An array of all CSS items (files and inline CSS) being requested on the page. 857 * 858 * @see drupal_add_css() 859 * @see drupal_get_css() 860 */ 861 function hook_css_alter(&$css) { 862 // Remove defaults.css file. 863 unset($css[drupal_get_path('module', 'system') . '/defaults.css']); 864 } 865 866 /** 867 * Alter the commands that are sent to the user through the Ajax framework. 868 * 869 * @param $commands 870 * An array of all commands that will be sent to the user. 871 * 872 * @see ajax_render() 873 */ 874 function hook_ajax_render_alter($commands) { 875 // Inject any new status messages into the content area. 876 $commands[] = ajax_command_prepend('#block-system-main .content', theme('status_messages')); 877 } 878 879 /** 880 * Add elements to a page before it is rendered. 881 * 882 * Use this hook when you want to add elements at the page level. For your 883 * additions to be printed, they have to be placed below a top level array key 884 * of the $page array that has the name of a region of the active theme. 885 * 886 * By default, valid region keys are 'page_top', 'header', 'sidebar_first', 887 * 'content', 'sidebar_second' and 'page_bottom'. To get a list of all regions 888 * of the active theme, use system_region_list($theme). Note that $theme is a 889 * global variable. 890 * 891 * If you want to alter the elements added by other modules or if your module 892 * depends on the elements of other modules, use hook_page_alter() instead which 893 * runs after this hook. 894 * 895 * @param $page 896 * Nested array of renderable elements that make up the page. 897 * 898 * @see hook_page_alter() 899 * @see drupal_render_page() 900 */ 901 function hook_page_build(&$page) { 902 if (menu_get_object('node', 1)) { 903 // We are on a node detail page. Append a standard disclaimer to the 904 // content region. 905 $page['content']['disclaimer'] = array( 906 '#markup' => t('Acme, Inc. is not responsible for the contents of this sample code.'), 907 '#weight' => 25, 908 ); 909 } 910 } 911 912 /** 913 * Alter a menu router item right after it has been retrieved from the database or cache. 914 * 915 * This hook is invoked by menu_get_item() and allows for run-time alteration of router 916 * information (page_callback, title, and so on) before it is translated and checked for 917 * access. The passed-in $router_item is statically cached for the current request, so this 918 * hook is only invoked once for any router item that is retrieved via menu_get_item(). 919 * 920 * Usually, modules will only want to inspect the router item and conditionally 921 * perform other actions (such as preparing a state for the current request). 922 * Note that this hook is invoked for any router item that is retrieved by 923 * menu_get_item(), which may or may not be called on the path itself, so implementations 924 * should check the $path parameter if the alteration should fire for the current request 925 * only. 926 * 927 * @param $router_item 928 * The menu router item for $path. 929 * @param $path 930 * The originally passed path, for which $router_item is responsible. 931 * @param $original_map 932 * The path argument map, as contained in $path. 933 * 934 * @see menu_get_item() 935 */ 936 function hook_menu_get_item_alter(&$router_item, $path, $original_map) { 937 // When retrieving the router item for the current path... 938 if ($path == $_GET['q']) { 939 // ...call a function that prepares something for this request. 940 mymodule_prepare_something(); 941 } 942 } 943 944 /** 945 * Define menu items and page callbacks. 946 * 947 * This hook enables modules to register paths in order to define how URL 948 * requests are handled. Paths may be registered for URL handling only, or they 949 * can register a link to be placed in a menu (usually the Navigation menu). A 950 * path and its associated information is commonly called a "menu router item". 951 * This hook is rarely called (for example, when modules are enabled), and 952 * its results are cached in the database. 953 * 954 * hook_menu() implementations return an associative array whose keys define 955 * paths and whose values are an associative array of properties for each 956 * path. (The complete list of properties is in the return value section below.) 957 * 958 * The definition for each path may include a page callback function, which is 959 * invoked when the registered path is requested. If there is no other 960 * registered path that fits the requested path better, any further path 961 * components are passed to the callback function. For example, your module 962 * could register path 'abc/def': 963 * @code 964 * function mymodule_menu() { 965 * $items['abc/def'] = array( 966 * 'page callback' => 'mymodule_abc_view', 967 * ); 968 * return $items; 969 * } 970 * 971 * function mymodule_abc_view($ghi = 0, $jkl = '') { 972 * // ... 973 * } 974 * @endcode 975 * When path 'abc/def' is requested, no further path components are in the 976 * request, and no additional arguments are passed to the callback function (so 977 * $ghi and $jkl would take the default values as defined in the function 978 * signature). When 'abc/def/123/foo' is requested, $ghi will be '123' and 979 * $jkl will be 'foo'. Note that this automatic passing of optional path 980 * arguments applies only to page and theme callback functions. 981 * 982 * In addition to optional path arguments, the page callback and other callback 983 * functions may specify argument lists as arrays. These argument lists may 984 * contain both fixed/hard-coded argument values and integers that correspond 985 * to path components. When integers are used and the callback function is 986 * called, the corresponding path components will be substituted for the 987 * integers. That is, the integer 0 in an argument list will be replaced with 988 * the first path component, integer 1 with the second, and so on (path 989 * components are numbered starting from zero). To pass an integer without it 990 * being replaced with its respective path component, use the string value of 991 * the integer (e.g., '1') as the argument value. This substitution feature 992 * allows you to re-use a callback function for several different paths. For 993 * example: 994 * @code 995 * function mymodule_menu() { 996 * $items['abc/def'] = array( 997 * 'page callback' => 'mymodule_abc_view', 998 * 'page arguments' => array(1, 'foo'), 999 * ); 1000 * return $items; 1001 * } 1002 * @endcode 1003 * When path 'abc/def' is requested, the page callback function will get 'def' 1004 * as the first argument and (always) 'foo' as the second argument. 1005 * 1006 * If a page callback function uses an argument list array, and its path is 1007 * requested with optional path arguments, then the list array's arguments are 1008 * passed to the callback function first, followed by the optional path 1009 * arguments. Using the above example, when path 'abc/def/bar/baz' is requested, 1010 * mymodule_abc_view() will be called with 'def', 'foo', 'bar' and 'baz' as 1011 * arguments, in that order. 1012 * 1013 * Special care should be taken for the page callback drupal_get_form(), because 1014 * your specific form callback function will always receive $form and 1015 * &$form_state as the first function arguments: 1016 * @code 1017 * function mymodule_abc_form($form, &$form_state) { 1018 * // ... 1019 * return $form; 1020 * } 1021 * @endcode 1022 * See @link form_api Form API documentation @endlink for details. 1023 * 1024 * Wildcards within paths also work with integer substitution. For example, 1025 * your module could register path 'my-module/%/edit': 1026 * @code 1027 * $items['my-module/%/edit'] = array( 1028 * 'page callback' => 'mymodule_abc_edit', 1029 * 'page arguments' => array(1), 1030 * ); 1031 * @endcode 1032 * When path 'my-module/foo/edit' is requested, integer 1 will be replaced 1033 * with 'foo' and passed to the callback function. Note that wildcards may not 1034 * be used as the first component. 1035 * 1036 * Registered paths may also contain special "auto-loader" wildcard components 1037 * in the form of '%mymodule_abc', where the '%' part means that this path 1038 * component is a wildcard, and the 'mymodule_abc' part defines the prefix for a 1039 * load function, which here would be named mymodule_abc_load(). When a matching 1040 * path is requested, your load function will receive as its first argument the 1041 * path component in the position of the wildcard; load functions may also be 1042 * passed additional arguments (see "load arguments" in the return value 1043 * section below). For example, your module could register path 1044 * 'my-module/%mymodule_abc/edit': 1045 * @code 1046 * $items['my-module/%mymodule_abc/edit'] = array( 1047 * 'page callback' => 'mymodule_abc_edit', 1048 * 'page arguments' => array(1), 1049 * ); 1050 * @endcode 1051 * When path 'my-module/123/edit' is requested, your load function 1052 * mymodule_abc_load() will be invoked with the argument '123', and should 1053 * load and return an "abc" object with internal id 123: 1054 * @code 1055 * function mymodule_abc_load($abc_id) { 1056 * return db_query("SELECT * FROM {mymodule_abc} WHERE abc_id = :abc_id", array(':abc_id' => $abc_id))->fetchObject(); 1057 * } 1058 * @endcode 1059 * This 'abc' object will then be passed into the callback functions defined 1060 * for the menu item, such as the page callback function mymodule_abc_edit() 1061 * to replace the integer 1 in the argument array. Note that a load function 1062 * should return FALSE when it is unable to provide a loadable object. For 1063 * example, the node_load() function for the 'node/%node/edit' menu item will 1064 * return FALSE for the path 'node/999/edit' if a node with a node ID of 999 1065 * does not exist. The menu routing system will return a 404 error in this case. 1066 * 1067 * You can also define a %wildcard_to_arg() function (for the example menu 1068 * entry above this would be 'mymodule_abc_to_arg()'). The _to_arg() function 1069 * is invoked to retrieve a value that is used in the path in place of the 1070 * wildcard. A good example is user.module, which defines 1071 * user_uid_optional_to_arg() (corresponding to the menu entry 1072 * 'tracker/%user_uid_optional'). This function returns the user ID of the 1073 * current user. 1074 * 1075 * The _to_arg() function will get called with three arguments: 1076 * - $arg: A string representing whatever argument may have been supplied by 1077 * the caller (this is particularly useful if you want the _to_arg() 1078 * function only supply a (default) value if no other value is specified, 1079 * as in the case of user_uid_optional_to_arg(). 1080 * - $map: An array of all path fragments (e.g. array('node','123','edit') for 1081 * 'node/123/edit'). 1082 * - $index: An integer indicating which element of $map corresponds to $arg. 1083 * 1084 * _load() and _to_arg() functions may seem similar at first glance, but they 1085 * have different purposes and are called at different times. _load() 1086 * functions are called when the menu system is collecting arguments to pass 1087 * to the callback functions defined for the menu item. _to_arg() functions 1088 * are called when the menu system is generating links to related paths, such 1089 * as the tabs for a set of MENU_LOCAL_TASK items. 1090 * 1091 * You can also make groups of menu items to be rendered (by default) as tabs 1092 * on a page. To do that, first create one menu item of type MENU_NORMAL_ITEM, 1093 * with your chosen path, such as 'foo'. Then duplicate that menu item, using a 1094 * subdirectory path, such as 'foo/tab1', and changing the type to 1095 * MENU_DEFAULT_LOCAL_TASK to make it the default tab for the group. Then add 1096 * the additional tab items, with paths such as "foo/tab2" etc., with type 1097 * MENU_LOCAL_TASK. Example: 1098 * @code 1099 * // Make "Foo settings" appear on the admin Config page 1100 * $items['admin/config/system/foo'] = array( 1101 * 'title' => 'Foo settings', 1102 * 'type' => MENU_NORMAL_ITEM, 1103 * // Page callback, etc. need to be added here. 1104 * ); 1105 * // Make "Tab 1" the main tab on the "Foo settings" page 1106 * $items['admin/config/system/foo/tab1'] = array( 1107 * 'title' => 'Tab 1', 1108 * 'type' => MENU_DEFAULT_LOCAL_TASK, 1109 * // Access callback, page callback, and theme callback will be inherited 1110 * // from 'admin/config/system/foo', if not specified here to override. 1111 * ); 1112 * // Make an additional tab called "Tab 2" on "Foo settings" 1113 * $items['admin/config/system/foo/tab2'] = array( 1114 * 'title' => 'Tab 2', 1115 * 'type' => MENU_LOCAL_TASK, 1116 * // Page callback and theme callback will be inherited from 1117 * // 'admin/config/system/foo', if not specified here to override. 1118 * // Need to add access callback or access arguments. 1119 * ); 1120 * @endcode 1121 * 1122 * @return 1123 * An array of menu items. Each menu item has a key corresponding to the 1124 * Drupal path being registered. The corresponding array value is an 1125 * associative array that may contain the following key-value pairs: 1126 * - "title": Required. The untranslated title of the menu item. 1127 * - "title callback": Function to generate the title; defaults to t(). 1128 * If you require only the raw string to be output, set this to FALSE. 1129 * - "title arguments": Arguments to send to t() or your custom callback, 1130 * with path component substitution as described above. 1131 * - "description": The untranslated description of the menu item. 1132 * - "page callback": The function to call to display a web page when the user 1133 * visits the path. If omitted, the parent menu item's callback will be used 1134 * instead. 1135 * - "page arguments": An array of arguments to pass to the page callback 1136 * function, with path component substitution as described above. 1137 * - "delivery callback": The function to call to package the result of the 1138 * page callback function and send it to the browser. Defaults to 1139 * drupal_deliver_html_page() unless a value is inherited from a parent menu 1140 * item. Note that this function is called even if the access checks fail, 1141 * so any custom delivery callback function should take that into account. 1142 * See drupal_deliver_html_page() for an example. 1143 * - "access callback": A function returning TRUE if the user has access 1144 * rights to this menu item, and FALSE if not. It can also be a boolean 1145 * constant instead of a function, and you can also use numeric values 1146 * (will be cast to boolean). Defaults to user_access() unless a value is 1147 * inherited from the parent menu item; only MENU_DEFAULT_LOCAL_TASK items 1148 * can inherit access callbacks. To use the user_access() default callback, 1149 * you must specify the permission to check as 'access arguments' (see 1150 * below). 1151 * - "access arguments": An array of arguments to pass to the access callback 1152 * function, with path component substitution as described above. If the 1153 * access callback is inherited (see above), the access arguments will be 1154 * inherited with it, unless overridden in the child menu item. 1155 * - "theme callback": (optional) A function returning the machine-readable 1156 * name of the theme that will be used to render the page. If not provided, 1157 * the value will be inherited from a parent menu item. If there is no 1158 * theme callback, or if the function does not return the name of a current 1159 * active theme on the site, the theme for this page will be determined by 1160 * either hook_custom_theme() or the default theme instead. As a general 1161 * rule, the use of theme callback functions should be limited to pages 1162 * whose functionality is very closely tied to a particular theme, since 1163 * they can only be overridden by modules which specifically target those 1164 * pages in hook_menu_alter(). Modules implementing more generic theme 1165 * switching functionality (for example, a module which allows the theme to 1166 * be set dynamically based on the current user's role) should use 1167 * hook_custom_theme() instead. 1168 * - "theme arguments": An array of arguments to pass to the theme callback 1169 * function, with path component substitution as described above. 1170 * - "file": A file that will be included before the page callback is called; 1171 * this allows page callback functions to be in separate files. The file 1172 * should be relative to the implementing module's directory unless 1173 * otherwise specified by the "file path" option. Does not apply to other 1174 * callbacks (only page callback). 1175 * - "file path": The path to the directory containing the file specified in 1176 * "file". This defaults to the path to the module implementing the hook. 1177 * - "load arguments": An array of arguments to be passed to each of the 1178 * wildcard object loaders in the path, after the path argument itself. 1179 * For example, if a module registers path node/%node/revisions/%/view 1180 * with load arguments set to array(3), the '%node' in the path indicates 1181 * that the loader function node_load() will be called with the second 1182 * path component as the first argument. The 3 in the load arguments 1183 * indicates that the fourth path component will also be passed to 1184 * node_load() (numbering of path components starts at zero). So, if path 1185 * node/12/revisions/29/view is requested, node_load(12, 29) will be called. 1186 * There are also two "magic" values that can be used in load arguments. 1187 * "%index" indicates the index of the wildcard path component. "%map" 1188 * indicates the path components as an array. For example, if a module 1189 * registers for several paths of the form 'user/%user_category/edit/*', all 1190 * of them can use the same load function user_category_load(), by setting 1191 * the load arguments to array('%map', '%index'). For instance, if the user 1192 * is editing category 'foo' by requesting path 'user/32/edit/foo', the load 1193 * function user_category_load() will be called with 32 as its first 1194 * argument, the array ('user', 32, 'edit', 'foo') as the map argument, 1195 * and 1 as the index argument (because %user_category is the second path 1196 * component and numbering starts at zero). user_category_load() can then 1197 * use these values to extract the information that 'foo' is the category 1198 * being requested. 1199 * - "weight": An integer that determines the relative position of items in 1200 * the menu; higher-weighted items sink. Defaults to 0. Menu items with the 1201 * same weight are ordered alphabetically. 1202 * - "menu_name": Optional. Set this to a custom menu if you don't want your 1203 * item to be placed in Navigation. 1204 * - "context": (optional) Defines the context a tab may appear in. By 1205 * default, all tabs are only displayed as local tasks when being rendered 1206 * in a page context. All tabs that should be accessible as contextual links 1207 * in page region containers outside of the parent menu item's primary page 1208 * context should be registered using one of the following contexts: 1209 * - MENU_CONTEXT_PAGE: (default) The tab is displayed as local task for the 1210 * page context only. 1211 * - MENU_CONTEXT_INLINE: The tab is displayed as contextual link outside of 1212 * the primary page context only. 1213 * Contexts can be combined. For example, to display a tab both on a page 1214 * and inline, a menu router item may specify: 1215 * @code 1216 * 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, 1217 * @endcode 1218 * - "tab_parent": For local task menu items, the path of the task's parent 1219 * item; defaults to the same path without the last component (e.g., the 1220 * default parent for 'admin/people/create' is 'admin/people'). 1221 * - "tab_root": For local task menu items, the path of the closest non-tab 1222 * item; same default as "tab_parent". 1223 * - "position": Position of the block ('left' or 'right') on the system 1224 * administration page for this item. 1225 * - "type": A bitmask of flags describing properties of the menu item. 1226 * Many shortcut bitmasks are provided as constants in menu.inc: 1227 * - MENU_NORMAL_ITEM: Normal menu items show up in the menu tree and can be 1228 * moved/hidden by the administrator. 1229 * - MENU_CALLBACK: Callbacks simply register a path so that the correct 1230 * information is generated when the path is accessed. 1231 * - MENU_SUGGESTED_ITEM: Modules may "suggest" menu items that the 1232 * administrator may enable. 1233 * - MENU_LOCAL_ACTION: Local actions are menu items that describe actions 1234 * on the parent item such as adding a new user or block, and are 1235 * rendered in the action-links list in your theme. 1236 * - MENU_LOCAL_TASK: Local tasks are menu items that describe different 1237 * displays of data, and are generally rendered as tabs. 1238 * - MENU_DEFAULT_LOCAL_TASK: Every set of local tasks should provide one 1239 * "default" task, which should display the same page as the parent item. 1240 * If the "type" element is omitted, MENU_NORMAL_ITEM is assumed. 1241 * - "options": An array of options to be passed to l() when generating a link 1242 * from this menu item. Note that the "options" parameter has no effect on 1243 * MENU_LOCAL_TASK, MENU_DEFAULT_LOCAL_TASK, and MENU_LOCAL_ACTION items. 1244 * 1245 * For a detailed usage example, see page_example.module. 1246 * For comprehensive documentation on the menu system, see 1247 * http://drupal.org/node/102338. 1248 */ 1249 function hook_menu() { 1250 $items['example'] = array( 1251 'title' => 'Example Page', 1252 'page callback' => 'example_page', 1253 'access arguments' => array('access content'), 1254 'type' => MENU_SUGGESTED_ITEM, 1255 ); 1256 $items['example/feed'] = array( 1257 'title' => 'Example RSS feed', 1258 'page callback' => 'example_feed', 1259 'access arguments' => array('access content'), 1260 'type' => MENU_CALLBACK, 1261 ); 1262 1263 return $items; 1264 } 1265 1266 /** 1267 * Alter the data being saved to the {menu_router} table after hook_menu is invoked. 1268 * 1269 * This hook is invoked by menu_router_build(). The menu definitions are passed 1270 * in by reference. Each element of the $items array is one item returned 1271 * by a module from hook_menu. Additional items may be added, or existing items 1272 * altered. 1273 * 1274 * @param $items 1275 * Associative array of menu router definitions returned from hook_menu(). 1276 */ 1277 function hook_menu_alter(&$items) { 1278 // Example - disable the page at node/add 1279 $items['node/add']['access callback'] = FALSE; 1280 } 1281 1282 /** 1283 * Alter the data being saved to the {menu_links} table by menu_link_save(). 1284 * 1285 * @param $item 1286 * Associative array defining a menu link as passed into menu_link_save(). 1287 * 1288 * @see hook_translated_menu_link_alter() 1289 */ 1290 function hook_menu_link_alter(&$item) { 1291 // Make all new admin links hidden (a.k.a disabled). 1292 if (strpos($item['link_path'], 'admin') === 0 && empty($item['mlid'])) { 1293 $item['hidden'] = 1; 1294 } 1295 // Flag a link to be altered by hook_translated_menu_link_alter(). 1296 if ($item['link_path'] == 'devel/cache/clear') { 1297 $item['options']['alter'] = TRUE; 1298 } 1299 // Flag a link to be altered by hook_translated_menu_link_alter(), but only 1300 // if it is derived from a menu router item; i.e., do not alter a custom 1301 // menu link pointing to the same path that has been created by a user. 1302 if ($item['link_path'] == 'user' && $item['module'] == 'system') { 1303 $item['options']['alter'] = TRUE; 1304 } 1305 } 1306 1307 /** 1308 * Alter a menu link after it has been translated and before it is rendered. 1309 * 1310 * This hook is invoked from _menu_link_translate() after a menu link has been 1311 * translated; i.e., after dynamic path argument placeholders (%) have been 1312 * replaced with actual values, the user access to the link's target page has 1313 * been checked, and the link has been localized. It is only invoked if 1314 * $item['options']['alter'] has been set to a non-empty value (e.g., TRUE). 1315 * This flag should be set using hook_menu_link_alter(). 1316 * 1317 * Implementations of this hook are able to alter any property of the menu link. 1318 * For example, this hook may be used to add a page-specific query string to all 1319 * menu links, or hide a certain link by setting: 1320 * @code 1321 * 'hidden' => 1, 1322 * @endcode 1323 * 1324 * @param $item 1325 * Associative array defining a menu link after _menu_link_translate() 1326 * @param $map 1327 * Associative array containing the menu $map (path parts and/or objects). 1328 * 1329 * @see hook_menu_link_alter() 1330 */ 1331 function hook_translated_menu_link_alter(&$item, $map) { 1332 if ($item['href'] == 'devel/cache/clear') { 1333 $item['localized_options']['query'] = drupal_get_destination(); 1334 } 1335 } 1336 1337 /** 1338 * Inform modules that a menu link has been created. 1339 * 1340 * This hook is used to notify modules that menu items have been 1341 * created. Contributed modules may use the information to perform 1342 * actions based on the information entered into the menu system. 1343 * 1344 * @param $link 1345 * Associative array defining a menu link as passed into menu_link_save(). 1346 * 1347 * @see hook_menu_link_update() 1348 * @see hook_menu_link_delete() 1349 */ 1350 function hook_menu_link_insert($link) { 1351 // In our sample case, we track menu items as editing sections 1352 // of the site. These are stored in our table as 'disabled' items. 1353 $record['mlid'] = $link['mlid']; 1354 $record['menu_name'] = $link['menu_name']; 1355 $record['status'] = 0; 1356 drupal_write_record('menu_example', $record); 1357 } 1358 1359 /** 1360 * Inform modules that a menu link has been updated. 1361 * 1362 * This hook is used to notify modules that menu items have been 1363 * updated. Contributed modules may use the information to perform 1364 * actions based on the information entered into the menu system. 1365 * 1366 * @param $link 1367 * Associative array defining a menu link as passed into menu_link_save(). 1368 * 1369 * @see hook_menu_link_insert() 1370 * @see hook_menu_link_delete() 1371 */ 1372 function hook_menu_link_update($link) { 1373 // If the parent menu has changed, update our record. 1374 $menu_name = db_query("SELECT menu_name FROM {menu_example} WHERE mlid = :mlid", array(':mlid' => $link['mlid']))->fetchField(); 1375 if ($menu_name != $link['menu_name']) { 1376 db_update('menu_example') 1377 ->fields(array('menu_name' => $link['menu_name'])) 1378 ->condition('mlid', $link['mlid']) 1379 ->execute(); 1380 } 1381 } 1382 1383 /** 1384 * Inform modules that a menu link has been deleted. 1385 * 1386 * This hook is used to notify modules that menu items have been 1387 * deleted. Contributed modules may use the information to perform 1388 * actions based on the information entered into the menu system. 1389 * 1390 * @param $link 1391 * Associative array defining a menu link as passed into menu_link_save(). 1392 * 1393 * @see hook_menu_link_insert() 1394 * @see hook_menu_link_update() 1395 */ 1396 function hook_menu_link_delete($link) { 1397 // Delete the record from our table. 1398 db_delete('menu_example') 1399 ->condition('mlid', $link['mlid']) 1400 ->execute(); 1401 } 1402 1403 /** 1404 * Alter tabs and actions displayed on the page before they are rendered. 1405 * 1406 * This hook is invoked by menu_local_tasks(). The system-determined tabs and 1407 * actions are passed in by reference. Additional tabs or actions may be added, 1408 * or existing items altered. 1409 * 1410 * Each tab or action is an associative array containing: 1411 * - #theme: The theme function to use to render. 1412 * - #link: An associative array containing: 1413 * - title: The localized title of the link. 1414 * - href: The system path to link to. 1415 * - localized_options: An array of options to pass to url(). 1416 * - #active: Whether the link should be marked as 'active'. 1417 * 1418 * @param $data 1419 * An associative array containing: 1420 * - actions: An associative array containing: 1421 * - count: The amount of actions determined by the menu system, which can 1422 * be ignored. 1423 * - output: A list of of actions, each one being an associative array 1424 * as described above. 1425 * - tabs: An indexed array (list) of tab levels (up to 2 levels), each 1426 * containing an associative array: 1427 * - count: The amount of tabs determined by the menu system. This value 1428 * does not need to be altered if there is more than one tab. 1429 * - output: A list of of tabs, each one being an associative array as 1430 * described above. 1431 * @param $router_item 1432 * The menu system router item of the page. 1433 * @param $root_path 1434 * The path to the root item for this set of tabs. 1435 */ 1436 function hook_menu_local_tasks_alter(&$data, $router_item, $root_path) { 1437 // Add an action linking to node/add to all pages. 1438 $data['actions']['output'][] = array( 1439 '#theme' => 'menu_local_task', 1440 '#link' => array( 1441 'title' => t('Add new content'), 1442 'href' => 'node/add', 1443 'localized_options' => array( 1444 'attributes' => array( 1445 'title' => t('Add new content'), 1446 ), 1447 ), 1448 ), 1449 ); 1450 1451 // Add a tab linking to node/add to all pages. 1452 $data['tabs'][0]['output'][] = array( 1453 '#theme' => 'menu_local_task', 1454 '#link' => array( 1455 'title' => t('Example tab'), 1456 'href' => 'node/add', 1457 'localized_options' => array( 1458 'attributes' => array( 1459 'title' => t('Add new content'), 1460 ), 1461 ), 1462 ), 1463 // Define whether this link is active. This can be omitted for 1464 // implementations that add links to pages outside of the current page 1465 // context. 1466 '#active' => ($router_item['path'] == $root_path), 1467 ); 1468 } 1469 1470 /** 1471 * Alter links in the active trail before it is rendered as the breadcrumb. 1472 * 1473 * This hook is invoked by menu_get_active_breadcrumb() and allows alteration 1474 * of the breadcrumb links for the current page, which may be preferred instead 1475 * of setting a custom breadcrumb via drupal_set_breadcrumb(). 1476 * 1477 * Implementations should take into account that menu_get_active_breadcrumb() 1478 * subsequently performs the following adjustments to the active trail *after* 1479 * this hook has been invoked: 1480 * - The last link in $active_trail is removed, if its 'href' is identical to 1481 * the 'href' of $item. This happens, because the breadcrumb normally does 1482 * not contain a link to the current page. 1483 * - The (second to) last link in $active_trail is removed, if the current $item 1484 * is a MENU_DEFAULT_LOCAL_TASK. This happens in order to do not show a link 1485 * to the current page, when being on the path for the default local task; 1486 * e.g. when being on the path node/%/view, the breadcrumb should not contain 1487 * a link to node/%. 1488 * 1489 * Each link in the active trail must contain: 1490 * - title: The localized title of the link. 1491 * - href: The system path to link to. 1492 * - localized_options: An array of options to pass to url(). 1493 * 1494 * @param $active_trail 1495 * An array containing breadcrumb links for the current page. 1496 * @param $item 1497 * The menu router item of the current page. 1498 * 1499 * @see drupal_set_breadcrumb() 1500 * @see menu_get_active_breadcrumb() 1501 * @see menu_get_active_trail() 1502 * @see menu_set_active_trail() 1503 */ 1504 function hook_menu_breadcrumb_alter(&$active_trail, $item) { 1505 // Always display a link to the current page by duplicating the last link in 1506 // the active trail. This means that menu_get_active_breadcrumb() will remove 1507 // the last link (for the current page), but since it is added once more here, 1508 // it will appear. 1509 if (!drupal_is_front_page()) { 1510 $end = end($active_trail); 1511 if ($item['href'] == $end['href']) { 1512 $active_trail[] = $end; 1513 } 1514 } 1515 } 1516 1517 /** 1518 * Alter contextual links before they are rendered. 1519 * 1520 * This hook is invoked by menu_contextual_links(). The system-determined 1521 * contextual links are passed in by reference. Additional links may be added 1522 * or existing links can be altered. 1523 * 1524 * Each contextual link must at least contain: 1525 * - title: The localized title of the link. 1526 * - href: The system path to link to. 1527 * - localized_options: An array of options to pass to url(). 1528 * 1529 * @param $links 1530 * An associative array containing contextual links for the given $root_path, 1531 * as described above. The array keys are used to build CSS class names for 1532 * contextual links and must therefore be unique for each set of contextual 1533 * links. 1534 * @param $router_item 1535 * The menu router item belonging to the $root_path being requested. 1536 * @param $root_path 1537 * The (parent) path that has been requested to build contextual links for. 1538 * This is a normalized path, which means that an originally passed path of 1539 * 'node/123' became 'node/%'. 1540 * 1541 * @see hook_contextual_links_view_alter() 1542 * @see menu_contextual_links() 1543 * @see hook_menu() 1544 * @see contextual_preprocess() 1545 */ 1546 function hook_menu_contextual_links_alter(&$links, $router_item, $root_path) { 1547 // Add a link to all contextual links for nodes. 1548 if ($root_path == 'node/%') { 1549 $links['foo'] = array( 1550 'title' => t('Do fu'), 1551 'href' => 'foo/do', 1552 'localized_options' => array( 1553 'query' => array( 1554 'foo' => 'bar', 1555 ), 1556 ), 1557 ); 1558 } 1559 } 1560 1561 /** 1562 * Perform alterations before a page is rendered. 1563 * 1564 * Use this hook when you want to remove or alter elements at the page 1565 * level, or add elements at the page level that depend on an other module's 1566 * elements (this hook runs after hook_page_build(). 1567 * 1568 * If you are making changes to entities such as forms, menus, or user 1569 * profiles, use those objects' native alter hooks instead (hook_form_alter(), 1570 * for example). 1571 * 1572 * The $page array contains top level elements for each block region: 1573 * @code 1574 * $page['page_top'] 1575 * $page['header'] 1576 * $page['sidebar_first'] 1577 * $page['content'] 1578 * $page['sidebar_second'] 1579 * $page['page_bottom'] 1580 * @endcode 1581 * 1582 * The 'content' element contains the main content of the current page, and its 1583 * structure will vary depending on what module is responsible for building the 1584 * page. Some legacy modules may not return structured content at all: their 1585 * pre-rendered markup will be located in $page['content']['main']['#markup']. 1586 * 1587 * Pages built by Drupal's core Node and Blog modules use a standard structure: 1588 * 1589 * @code 1590 * // Node body. 1591 * $page['content']['system_main']['nodes'][$nid]['body'] 1592 * // Array of links attached to the node (add comments, read more). 1593 * $page['content']['system_main']['nodes'][$nid]['links'] 1594 * // The node object itself. 1595 * $page['content']['system_main']['nodes'][$nid]['#node'] 1596 * // The results pager. 1597 * $page['content']['system_main']['pager'] 1598 * @endcode 1599 * 1600 * Blocks may be referenced by their module/delta pair within a region: 1601 * @code 1602 * // The login block in the first sidebar region. 1603 * $page['sidebar_first']['user_login']['#block']; 1604 * @endcode 1605 * 1606 * @param $page 1607 * Nested array of renderable elements that make up the page. 1608 * 1609 * @see hook_page_build() 1610 * @see drupal_render_page() 1611 */ 1612 function hook_page_alter(&$page) { 1613 // Add help text to the user login block. 1614 $page['sidebar_first']['user_login']['help'] = array( 1615 '#weight' => -10, 1616 '#markup' => t('To post comments or add new content, you first have to log in.'), 1617 ); 1618 } 1619 1620 /** 1621 * Perform alterations before a form is rendered. 1622 * 1623 * One popular use of this hook is to add form elements to the node form. When 1624 * altering a node form, the node object can be accessed at $form['#node']. 1625 * 1626 * In addition to hook_form_alter(), which is called for all forms, there are 1627 * two more specific form hooks available. The first, 1628 * hook_form_BASE_FORM_ID_alter(), allows targeting of a form/forms via a base 1629 * form (if one exists). The second, hook_form_FORM_ID_alter(), can be used to 1630 * target a specific form directly. 1631 * 1632 * The call order is as follows: all existing form alter functions are called 1633 * for module A, then all for module B, etc., followed by all for any base 1634 * theme(s), and finally for the theme itself. The module order is determined 1635 * by system weight, then by module name. 1636 * 1637 * Within each module, form alter hooks are called in the following order: 1638 * first, hook_form_alter(); second, hook_form_BASE_FORM_ID_alter(); third, 1639 * hook_form_FORM_ID_alter(). So, for each module, the more general hooks are 1640 * called first followed by the more specific. 1641 * 1642 * @param $form 1643 * Nested array of form elements that comprise the form. 1644 * @param $form_state 1645 * A keyed array containing the current state of the form. The arguments 1646 * that drupal_get_form() was originally called with are available in the 1647 * array $form_state['build_info']['args']. 1648 * @param $form_id 1649 * String representing the name of the form itself. Typically this is the 1650 * name of the function that generated the form. 1651 * 1652 * @see hook_form_BASE_FORM_ID_alter() 1653 * @see hook_form_FORM_ID_alter() 1654 * @see forms_api_reference.html 1655 */ 1656 function hook_form_alter(&$form, &$form_state, $form_id) { 1657 if (isset($form['type']) && $form['type']['#value'] . '_node_settings' == $form_id) { 1658 $form['workflow']['upload_' . $form['type']['#value']] = array( 1659 '#type' => 'radios', 1660 '#title' => t('Attachments'), 1661 '#default_value' => variable_get('upload_' . $form['type']['#value'], 1), 1662 '#options' => array(t('Disabled'), t('Enabled')), 1663 ); 1664 } 1665 } 1666 1667 /** 1668 * Provide a form-specific alteration instead of the global hook_form_alter(). 1669 * 1670 * Modules can implement hook_form_FORM_ID_alter() to modify a specific form, 1671 * rather than implementing hook_form_alter() and checking the form ID, or 1672 * using long switch statements to alter multiple forms. 1673 * 1674 * Form alter hooks are called in the following order: hook_form_alter(), 1675 * hook_form_BASE_FORM_ID_alter(), hook_form_FORM_ID_alter(). See 1676 * hook_form_alter() for more details. 1677 * 1678 * @param $form 1679 * Nested array of form elements that comprise the form. 1680 * @param $form_state 1681 * A keyed array containing the current state of the form. The arguments 1682 * that drupal_get_form() was originally called with are available in the 1683 * array $form_state['build_info']['args']. 1684 * @param $form_id 1685 * String representing the name of the form itself. Typically this is the 1686 * name of the function that generated the form. 1687 * 1688 * @see hook_form_alter() 1689 * @see hook_form_BASE_FORM_ID_alter() 1690 * @see drupal_prepare_form() 1691 * @see forms_api_reference.html 1692 */ 1693 function hook_form_FORM_ID_alter(&$form, &$form_state, $form_id) { 1694 // Modification for the form with the given form ID goes here. For example, if 1695 // FORM_ID is "user_register_form" this code would run only on the user 1696 // registration form. 1697 1698 // Add a checkbox to registration form about agreeing to terms of use. 1699 $form['terms_of_use'] = array( 1700 '#type' => 'checkbox', 1701 '#title' => t("I agree with the website's terms and conditions."), 1702 '#required' => TRUE, 1703 ); 1704 } 1705 1706 /** 1707 * Provide a form-specific alteration for shared ('base') forms. 1708 * 1709 * By default, when drupal_get_form() is called, Drupal looks for a function 1710 * with the same name as the form ID, and uses that function to build the form. 1711 * In contrast, base forms allow multiple form IDs to be mapped to a single base 1712 * (also called 'factory') form function. 1713 * 1714 * Modules can implement hook_form_BASE_FORM_ID_alter() to modify a specific 1715 * base form, rather than implementing hook_form_alter() and checking for 1716 * conditions that would identify the shared form constructor. 1717 * 1718 * To identify the base form ID for a particular form (or to determine whether 1719 * one exists) check the $form_state. The base form ID is stored under 1720 * $form_state['build_info']['base_form_id']. 1721 * 1722 * See hook_forms() for more information on how to implement base forms in 1723 * Drupal. 1724 * 1725 * Form alter hooks are called in the following order: hook_form_alter(), 1726 * hook_form_BASE_FORM_ID_alter(), hook_form_FORM_ID_alter(). See 1727 * hook_form_alter() for more details. 1728 * 1729 * @param $form 1730 * Nested array of form elements that comprise the form. 1731 * @param $form_state 1732 * A keyed array containing the current state of the form. 1733 * @param $form_id 1734 * String representing the name of the form itself. Typically this is the 1735 * name of the function that generated the form. 1736 * 1737 * @see hook_form_alter() 1738 * @see hook_form_FORM_ID_alter() 1739 * @see drupal_prepare_form() 1740 * @see hook_forms() 1741 */ 1742 function hook_form_BASE_FORM_ID_alter(&$form, &$form_state, $form_id) { 1743 // Modification for the form with the given BASE_FORM_ID goes here. For 1744 // example, if BASE_FORM_ID is "node_form", this code would run on every 1745 // node form, regardless of node type. 1746 1747 // Add a checkbox to the node form about agreeing to terms of use. 1748 $form['terms_of_use'] = array( 1749 '#type' => 'checkbox', 1750 '#title' => t("I agree with the website's terms and conditions."), 1751 '#required' => TRUE, 1752 ); 1753 } 1754 1755 /** 1756 * Map form_ids to form builder functions. 1757 * 1758 * By default, when drupal_get_form() is called, the system will look for a 1759 * function with the same name as the form ID, and use that function to build 1760 * the form. If no such function is found, Drupal calls this hook. Modules 1761 * implementing this hook can then provide their own instructions for mapping 1762 * form IDs to constructor functions. As a result, you can easily map multiple 1763 * form IDs to a single form constructor (referred to as a 'base' form). 1764 * 1765 * Using a base form can help to avoid code duplication, by allowing many 1766 * similar forms to use the same code base. Another benefit is that it becomes 1767 * much easier for other modules to apply a general change to the group of 1768 * forms; hook_form_BASE_FORM_ID_alter() can be used to easily alter multiple 1769 * forms at once by directly targeting the shared base form. 1770 * 1771 * Two example use cases where base forms may be useful are given below. 1772 * 1773 * First, you can use this hook to tell the form system to use a different 1774 * function to build certain forms in your module; this is often used to define 1775 * a form "factory" function that is used to build several similar forms. In 1776 * this case, your hook implementation will likely ignore all of the input 1777 * arguments. See node_forms() for an example of this. Note, node_forms() is the 1778 * hook_forms() implementation; the base form itself is defined in node_form(). 1779 * 1780 * Second, you could use this hook to define how to build a form with a 1781 * dynamically-generated form ID. In this case, you would need to verify that 1782 * the $form_id input matched your module's format for dynamically-generated 1783 * form IDs, and if so, act appropriately. 1784 * 1785 * @param $form_id 1786 * The unique string identifying the desired form. 1787 * @param $args 1788 * An array containing the original arguments provided to drupal_get_form() 1789 * or drupal_form_submit(). These are always passed to the form builder and 1790 * do not have to be specified manually in 'callback arguments'. 1791 * 1792 * @return 1793 * An associative array whose keys define form_ids and whose values are an 1794 * associative array defining the following keys: 1795 * - callback: The name of the form builder function to invoke. This will be 1796 * used for the base form ID, for example, to target a base form using 1797 * hook_form_BASE_FORM_ID_alter(). 1798 * - callback arguments: (optional) Additional arguments to pass to the 1799 * function defined in 'callback', which are prepended to $args. 1800 * - wrapper_callback: (optional) The name of a form builder function to 1801 * invoke before the form builder defined in 'callback' is invoked. This 1802 * wrapper callback may prepopulate the $form array with form elements, 1803 * which will then be already contained in the $form that is passed on to 1804 * the form builder defined in 'callback'. For example, a wrapper callback 1805 * could setup wizard-alike form buttons that are the same for a variety of 1806 * forms that belong to the wizard, which all share the same wrapper 1807 * callback. 1808 */ 1809 function hook_forms($form_id, $args) { 1810 // Simply reroute the (non-existing) $form_id 'mymodule_first_form' to 1811 // 'mymodule_main_form'. 1812 $forms['mymodule_first_form'] = array( 1813 'callback' => 'mymodule_main_form', 1814 ); 1815 1816 // Reroute the $form_id and prepend an additional argument that gets passed to 1817 // the 'mymodule_main_form' form builder function. 1818 $forms['mymodule_second_form'] = array( 1819 'callback' => 'mymodule_main_form', 1820 'callback arguments' => array('some parameter'), 1821 ); 1822 1823 // Reroute the $form_id, but invoke the form builder function 1824 // 'mymodule_main_form_wrapper' first, so we can prepopulate the $form array 1825 // that is passed to the actual form builder 'mymodule_main_form'. 1826 $forms['mymodule_wrapped_form'] = array( 1827 'callback' => 'mymodule_main_form', 1828 'wrapper_callback' => 'mymodule_main_form_wrapper', 1829 ); 1830 1831 return $forms; 1832 } 1833 1834 /** 1835 * Perform setup tasks for all page requests. 1836 * 1837 * This hook is run at the beginning of the page request. It is typically 1838 * used to set up global parameters that are needed later in the request. 1839 * 1840 * Only use this hook if your code must run even for cached page views. This 1841 * hook is called before the theme, modules, or most include files are loaded 1842 * into memory. It happens while Drupal is still in bootstrap mode. 1843 * 1844 * @see hook_init() 1845 */ 1846 function hook_boot() { 1847 // We need user_access() in the shutdown function. Make sure it gets loaded. 1848 drupal_load('module', 'user'); 1849 drupal_register_shutdown_function('devel_shutdown'); 1850 } 1851 1852 /** 1853 * Perform setup tasks for non-cached page requests. 1854 * 1855 * This hook is run at the beginning of the page request. It is typically 1856 * used to set up global parameters that are needed later in the request. 1857 * When this hook is called, the theme and all modules are already loaded in 1858 * memory. 1859 * 1860 * This hook is not run on cached pages. 1861 * 1862 * To add CSS or JS that should be present on all pages, modules should not 1863 * implement this hook, but declare these files in their .info file. 1864 * 1865 * @see hook_boot() 1866 */ 1867 function hook_init() { 1868 // Since this file should only be loaded on the front page, it cannot be 1869 // declared in the info file. 1870 if (drupal_is_front_page()) { 1871 drupal_add_css(drupal_get_path('module', 'foo') . '/foo.css'); 1872 } 1873 } 1874 1875 /** 1876 * Define image toolkits provided by this module. 1877 * 1878 * The file which includes each toolkit's functions must be declared as part of 1879 * the files array in the module .info file so that the registry will find and 1880 * parse it. 1881 * 1882 * The toolkit's functions must be named image_toolkitname_operation(). 1883 * where the operation may be: 1884 * - 'load': Required. See image_gd_load() for usage. 1885 * - 'save': Required. See image_gd_save() for usage. 1886 * - 'settings': Optional. See image_gd_settings() for usage. 1887 * - 'resize': Optional. See image_gd_resize() for usage. 1888 * - 'rotate': Optional. See image_gd_rotate() for usage. 1889 * - 'crop': Optional. See image_gd_crop() for usage. 1890 * - 'desaturate': Optional. See image_gd_desaturate() for usage. 1891 * 1892 * @return 1893 * An array with the toolkit name as keys and sub-arrays with these keys: 1894 * - 'title': A string with the toolkit's title. 1895 * - 'available': A Boolean value to indicate that the toolkit is operating 1896 * properly, e.g. all required libraries exist. 1897 * 1898 * @see system_image_toolkits() 1899 */ 1900 function hook_image_toolkits() { 1901 return array( 1902 'working' => array( 1903 'title' => t('A toolkit that works.'), 1904 'available' => TRUE, 1905 ), 1906 'broken' => array( 1907 'title' => t('A toolkit that is "broken" and will not be listed.'), 1908 'available' => FALSE, 1909 ), 1910 ); 1911 } 1912 1913 /** 1914 * Alter an email message created with the drupal_mail() function. 1915 * 1916 * hook_mail_alter() allows modification of email messages created and sent 1917 * with drupal_mail(). Usage examples include adding and/or changing message 1918 * text, message fields, and message headers. 1919 * 1920 * Email messages sent using functions other than drupal_mail() will not 1921 * invoke hook_mail_alter(). For example, a contributed module directly 1922 * calling the drupal_mail_system()->mail() or PHP mail() function 1923 * will not invoke this hook. All core modules use drupal_mail() for 1924 * messaging, it is best practice but not mandatory in contributed modules. 1925 * 1926 * @param $message 1927 * An array containing the message data. Keys in this array include: 1928 * - 'id': 1929 * The drupal_mail() id of the message. Look at module source code or 1930 * drupal_mail() for possible id values. 1931 * - 'to': 1932 * The address or addresses the message will be sent to. The 1933 * formatting of this string must comply with RFC 2822. 1934 * - 'from': 1935 * The address the message will be marked as being from, which is 1936 * either a custom address or the site-wide default email address. 1937 * - 'subject': 1938 * Subject of the email to be sent. This must not contain any newline 1939 * characters, or the email may not be sent properly. 1940 * - 'body': 1941 * An array of strings containing the message text. The message body is 1942 * created by concatenating the individual array strings into a single text 1943 * string using "\n\n" as a separator. 1944 * - 'headers': 1945 * Associative array containing mail headers, such as From, Sender, 1946 * MIME-Version, Content-Type, etc. 1947 * - 'params': 1948 * An array of optional parameters supplied by the caller of drupal_mail() 1949 * that is used to build the message before hook_mail_alter() is invoked. 1950 * - 'language': 1951 * The language object used to build the message before hook_mail_alter() 1952 * is invoked. 1953 * - 'send': 1954 * Set to FALSE to abort sending this email message. 1955 * 1956 * @see drupal_mail() 1957 */ 1958 function hook_mail_alter(&$message) { 1959 if ($message['id'] == 'modulename_messagekey') { 1960 if (!example_notifications_optin($message['to'], $message['id'])) { 1961 // If the recipient has opted to not receive such messages, cancel 1962 // sending. 1963 $message['send'] = FALSE; 1964 return; 1965 } 1966 $message['body'][] = "--\nMail sent out from " . variable_get('site_name', t('Drupal')); 1967 } 1968 } 1969 1970 /** 1971 * Alter the registry of modules implementing a hook. 1972 * 1973 * This hook is invoked during module_implements(). A module may implement this 1974 * hook in order to reorder the implementing modules, which are otherwise 1975 * ordered by the module's system weight. 1976 * 1977 * Note that hooks invoked using drupal_alter() can have multiple variations 1978 * (such as hook_form_alter() and hook_form_FORM_ID_alter()). drupal_alter() 1979 * will call all such variants defined by a single module in turn. For the 1980 * purposes of hook_module_implements_alter(), these variants are treated as 1981 * a single hook. Thus, to ensure that your implementation of 1982 * hook_form_FORM_ID_alter() is called at the right time, you will have to 1983 * change the order of hook_form_alter() implementation in 1984 * hook_module_implements_alter(). 1985 * 1986 * @param $implementations 1987 * An array keyed by the module's name. The value of each item corresponds 1988 * to a $group, which is usually FALSE, unless the implementation is in a 1989 * file named $module.$group.inc. 1990 * @param $hook 1991 * The name of the module hook being implemented. 1992 */ 1993 function hook_module_implements_alter(&$implementations, $hook) { 1994 if ($hook == 'rdf_mapping') { 1995 // Move my_module_rdf_mapping() to the end of the list. module_implements() 1996 // iterates through $implementations with a foreach loop which PHP iterates 1997 // in the order that the items were added, so to move an item to the end of 1998 // the array, we remove it and then add it. 1999 $group = $implementations['my_module']; 2000 unset($implementations['my_module']); 2001 $implementations['my_module'] = $group; 2002 } 2003 } 2004 2005 /** 2006 * Return additional themes provided by modules. 2007 * 2008 * Only use this hook for testing purposes. Use a hidden MYMODULE_test.module 2009 * to implement this hook. Testing themes should be hidden, too. 2010 * 2011 * This hook is invoked from _system_rebuild_theme_data() and allows modules to 2012 * register additional themes outside of the regular 'themes' directories of a 2013 * Drupal installation. 2014 * 2015 * @return 2016 * An associative array. Each key is the system name of a theme and each value 2017 * is the corresponding path to the theme's .info file. 2018 */ 2019 function hook_system_theme_info() { 2020 $themes['mymodule_test_theme'] = drupal_get_path('module', 'mymodule') . '/mymodule_test_theme/mymodule_test_theme.info'; 2021 return $themes; 2022 } 2023 2024 /** 2025 * Alter the information parsed from module and theme .info files 2026 * 2027 * This hook is invoked in _system_rebuild_module_data() and in 2028 * _system_rebuild_theme_data(). A module may implement this hook in order to 2029 * add to or alter the data generated by reading the .info file with 2030 * drupal_parse_info_file(). 2031 * 2032 * @param $info 2033 * The .info file contents, passed by reference so that it can be altered. 2034 * @param $file 2035 * Full information about the module or theme, including $file->name, and 2036 * $file->filename 2037 * @param $type 2038 * Either 'module' or 'theme', depending on the type of .info file that was 2039 * passed. 2040 */ 2041 function hook_system_info_alter(&$info, $file, $type) { 2042 // Only fill this in if the .info file does not define a 'datestamp'. 2043 if (empty($info['datestamp'])) { 2044 $info['datestamp'] = filemtime($file->filename); 2045 } 2046 } 2047 2048 /** 2049 * Define user permissions. 2050 * 2051 * This hook can supply permissions that the module defines, so that they 2052 * can be selected on the user permissions page and used to grant or restrict 2053 * access to actions the module performs. 2054 * 2055 * Permissions are checked using user_access(). 2056 * 2057 * For a detailed usage example, see page_example.module. 2058 * 2059 * @return 2060 * An array whose keys are permission names and whose corresponding values 2061 * are arrays containing the following key-value pairs: 2062 * - title: The human-readable name of the permission, to be shown on the 2063 * permission administration page. This should be wrapped in the t() 2064 * function so it can be translated. 2065 * - description: (optional) A description of what the permission does. This 2066 * should be wrapped in the t() function so it can be translated. 2067 * - restrict access: (optional) A boolean which can be set to TRUE to 2068 * indicate that site administrators should restrict access to this 2069 * permission to trusted users. This should be used for permissions that 2070 * have inherent security risks across a variety of potential use cases 2071 * (for example, the "administer filters" and "bypass node access" 2072 * permissions provided by Drupal core). When set to TRUE, a standard 2073 * warning message defined in user_admin_permissions() and output via 2074 * theme_user_permission_description() will be associated with the 2075 * permission and displayed with it on the permission administration page. 2076 * Defaults to FALSE. 2077 * - warning: (optional) A translated warning message to display for this 2078 * permission on the permission administration page. This warning overrides 2079 * the automatic warning generated by 'restrict access' being set to TRUE. 2080 * This should rarely be used, since it is important for all permissions to 2081 * have a clear, consistent security warning that is the same across the 2082 * site. Use the 'description' key instead to provide any information that 2083 * is specific to the permission you are defining. 2084 * 2085 * @see theme_user_permission_description() 2086 */ 2087 function hook_permission() { 2088 return array( 2089 'administer my module' => array( 2090 'title' => t('Administer my module'), 2091 'description' => t('Perform administration tasks for my module.'), 2092 ), 2093 ); 2094 } 2095 2096 /** 2097 * Register a module (or theme's) theme implementations. 2098 * 2099 * The implementations declared by this hook have two purposes: either they 2100 * specify how a particular render array is to be rendered as HTML (this is 2101 * usually the case if the theme function is assigned to the render array's 2102 * #theme property), or they return the HTML that should be returned by an 2103 * invocation of theme(). 2104 * 2105 * The following parameters are all optional. 2106 * 2107 * @param array $existing 2108 * An array of existing implementations that may be used for override 2109 * purposes. This is primarily useful for themes that may wish to examine 2110 * existing implementations to extract data (such as arguments) so that 2111 * it may properly register its own, higher priority implementations. 2112 * @param $type 2113 * Whether a theme, module, etc. is being processed. This is primarily useful 2114 * so that themes tell if they are the actual theme being called or a parent 2115 * theme. May be one of: 2116 * - 'module': A module is being checked for theme implementations. 2117 * - 'base_theme_engine': A theme engine is being checked for a theme that is 2118 * a parent of the actual theme being used. 2119 * - 'theme_engine': A theme engine is being checked for the actual theme 2120 * being used. 2121 * - 'base_theme': A base theme is being checked for theme implementations. 2122 * - 'theme': The actual theme in use is being checked. 2123 * @param $theme 2124 * The actual name of theme, module, etc. that is being being processed. 2125 * @param $path 2126 * The directory path of the theme or module, so that it doesn't need to be 2127 * looked up. 2128 * 2129 * @return array 2130 * An associative array of theme hook information. The keys on the outer 2131 * array are the internal names of the hooks, and the values are arrays 2132 * containing information about the hook. Each information array must contain 2133 * either a 'variables' element or a 'render element' element, but not both. 2134 * Use 'render element' if you are theming a single element or element tree 2135 * composed of elements, such as a form array, a page array, or a single 2136 * checkbox element. Use 'variables' if your theme implementation is 2137 * intended to be called directly through theme() and has multiple arguments 2138 * for the data and style; in this case, the variables not supplied by the 2139 * calling function will be given default values and passed to the template 2140 * or theme function. The returned theme information array can contain the 2141 * following key/value pairs: 2142 * - variables: (see above) Each array key is the name of the variable, and 2143 * the value given is used as the default value if the function calling 2144 * theme() does not supply it. Template implementations receive each array 2145 * key as a variable in the template file (so they must be legal PHP 2146 * variable names). Function implementations are passed the variables in a 2147 * single $variables function argument. 2148 * - render element: (see above) The name of the renderable element or element 2149 * tree to pass to the theme function. This name is used as the name of the 2150 * variable that holds the renderable element or tree in preprocess and 2151 * process functions. 2152 * - file: The file the implementation resides in. This file will be included 2153 * prior to the theme being rendered, to make sure that the function or 2154 * preprocess function (as needed) is actually loaded; this makes it 2155 * possible to split theme functions out into separate files quite easily. 2156 * - path: Override the path of the file to be used. Ordinarily the module or 2157 * theme path will be used, but if the file will not be in the default 2158 * path, include it here. This path should be relative to the Drupal root 2159 * directory. 2160 * - template: If specified, this theme implementation is a template, and 2161 * this is the template file without an extension. Do not put .tpl.php on 2162 * this file; that extension will be added automatically by the default 2163 * rendering engine (which is PHPTemplate). If 'path', above, is specified, 2164 * the template should also be in this path. 2165 * - function: If specified, this will be the function name to invoke for 2166 * this implementation. If neither 'template' nor 'function' is specified, 2167 * a default function name will be assumed. For example, if a module 2168 * registers the 'node' theme hook, 'theme_node' will be assigned to its 2169 * function. If the chameleon theme registers the node hook, it will be 2170 * assigned 'chameleon_node' as its function. 2171 * - base hook: A string declaring the base theme hook if this theme 2172 * implementation is actually implementing a suggestion for another theme 2173 * hook. 2174 * - pattern: A regular expression pattern to be used to allow this theme 2175 * implementation to have a dynamic name. The convention is to use __ to 2176 * differentiate the dynamic portion of the theme. For example, to allow 2177 * forums to be themed individually, the pattern might be: 'forum__'. Then, 2178 * when the forum is themed, call: 2179 * @code 2180 * theme(array('forum__' . $tid, 'forum'), $forum) 2181 * @endcode 2182 * - preprocess functions: A list of functions used to preprocess this data. 2183 * Ordinarily this won't be used; it's automatically filled in. By default, 2184 * for a module this will be filled in as template_preprocess_HOOK. For 2185 * a theme this will be filled in as phptemplate_preprocess and 2186 * phptemplate_preprocess_HOOK as well as themename_preprocess and 2187 * themename_preprocess_HOOK. 2188 * - override preprocess functions: Set to TRUE when a theme does NOT want 2189 * the standard preprocess functions to run. This can be used to give a 2190 * theme FULL control over how variables are set. For example, if a theme 2191 * wants total control over how certain variables in the page.tpl.php are 2192 * set, this can be set to true. Please keep in mind that when this is used 2193 * by a theme, that theme becomes responsible for making sure necessary 2194 * variables are set. 2195 * - type: (automatically derived) Where the theme hook is defined: 2196 * 'module', 'theme_engine', or 'theme'. 2197 * - theme path: (automatically derived) The directory path of the theme or 2198 * module, so that it doesn't need to be looked up. 2199 */ 2200 function hook_theme($existing, $type, $theme, $path) { 2201 return array( 2202 'forum_display' => array( 2203 'variables' => array('forums' => NULL, 'topics' => NULL, 'parents' => NULL, 'tid' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL), 2204 ), 2205 'forum_list' => array( 2206 'variables' => array('forums' => NULL, 'parents' => NULL, 'tid' => NULL), 2207 ), 2208 'forum_topic_list' => array( 2209 'variables' => array('tid' => NULL, 'topics' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL), 2210 ), 2211 'forum_icon' => array( 2212 'variables' => array('new_posts' => NULL, 'num_posts' => 0, 'comment_mode' => 0, 'sticky' => 0), 2213 ), 2214 'status_report' => array( 2215 'render element' => 'requirements', 2216 'file' => 'system.admin.inc', 2217 ), 2218 'system_date_time_settings' => array( 2219 'render element' => 'form', 2220 'file' => 'system.admin.inc', 2221 ), 2222 ); 2223 } 2224 2225 /** 2226 * Alter the theme registry information returned from hook_theme(). 2227 * 2228 * The theme registry stores information about all available theme hooks, 2229 * including which callback functions those hooks will call when triggered, 2230 * what template files are exposed by these hooks, and so on. 2231 * 2232 * Note that this hook is only executed as the theme cache is re-built. 2233 * Changes here will not be visible until the next cache clear. 2234 * 2235 * The $theme_registry array is keyed by theme hook name, and contains the 2236 * information returned from hook_theme(), as well as additional properties 2237 * added by _theme_process_registry(). 2238 * 2239 * For example: 2240 * @code 2241 * $theme_registry['user_profile'] = array( 2242 * 'variables' => array( 2243 * 'account' => NULL, 2244 * ), 2245 * 'template' => 'modules/user/user-profile', 2246 * 'file' => 'modules/user/user.pages.inc', 2247 * 'type' => 'module', 2248 * 'theme path' => 'modules/user', 2249 * 'preprocess functions' => array( 2250 * 0 => 'template_preprocess', 2251 * 1 => 'template_preprocess_user_profile', 2252 * ), 2253 * ); 2254 * @endcode 2255 * 2256 * @param $theme_registry 2257 * The entire cache of theme registry information, post-processing. 2258 * 2259 * @see hook_theme() 2260 * @see _theme_process_registry() 2261 */ 2262 function hook_theme_registry_alter(&$theme_registry) { 2263 // Kill the next/previous forum topic navigation links. 2264 foreach ($theme_registry['forum_topic_navigation']['preprocess functions'] as $key => $value) { 2265 if ($value == 'template_preprocess_forum_topic_navigation') { 2266 unset($theme_registry['forum_topic_navigation']['preprocess functions'][$key]); 2267 } 2268 } 2269 } 2270 2271 /** 2272 * Return the machine-readable name of the theme to use for the current page. 2273 * 2274 * This hook can be used to dynamically set the theme for the current page 2275 * request. It should be used by modules which need to override the theme 2276 * based on dynamic conditions (for example, a module which allows the theme to 2277 * be set based on the current user's role). The return value of this hook will 2278 * be used on all pages except those which have a valid per-page or per-section 2279 * theme set via a theme callback function in hook_menu(); the themes on those 2280 * pages can only be overridden using hook_menu_alter(). 2281 * 2282 * Note that returning different themes for the same path may not work with page 2283 * caching. This is most likely to be a problem if an anonymous user on a given 2284 * path could have different themes returned under different conditions. 2285 * 2286 * Since only one theme can be used at a time, the last (i.e., highest 2287 * weighted) module which returns a valid theme name from this hook will 2288 * prevail. 2289 * 2290 * @return 2291 * The machine-readable name of the theme that should be used for the current 2292 * page request. The value returned from this function will only have an 2293 * effect if it corresponds to a currently-active theme on the site. 2294 */ 2295 function hook_custom_theme() { 2296 // Allow the user to request a particular theme via a query parameter. 2297 if (isset($_GET['theme'])) { 2298 return $_GET['theme']; 2299 } 2300 } 2301 2302 /** 2303 * Register XML-RPC callbacks. 2304 * 2305 * This hook lets a module register callback functions to be called when 2306 * particular XML-RPC methods are invoked by a client. 2307 * 2308 * @return 2309 * An array which maps XML-RPC methods to Drupal functions. Each array 2310 * element is either a pair of method => function or an array with four 2311 * entries: 2312 * - The XML-RPC method name (for example, module.function). 2313 * - The Drupal callback function (for example, module_function). 2314 * - The method signature is an array of XML-RPC types. The first element 2315 * of this array is the type of return value and then you should write a 2316 * list of the types of the parameters. XML-RPC types are the following 2317 * (See the types at http://www.xmlrpc.com/spec): 2318 * - "boolean": 0 (false) or 1 (true). 2319 * - "double": a floating point number (for example, -12.214). 2320 * - "int": a integer number (for example, -12). 2321 * - "array": an array without keys (for example, array(1, 2, 3)). 2322 * - "struct": an associative array or an object (for example, 2323 * array('one' => 1, 'two' => 2)). 2324 * - "date": when you return a date, then you may either return a 2325 * timestamp (time(), mktime() etc.) or an ISO8601 timestamp. When 2326 * date is specified as an input parameter, then you get an object, 2327 * which is described in the function xmlrpc_date 2328 * - "base64": a string containing binary data, automatically 2329 * encoded/decoded automatically. 2330 * - "string": anything else, typically a string. 2331 * - A descriptive help string, enclosed in a t() function for translation 2332 * purposes. 2333 * Both forms are shown in the example. 2334 */ 2335 function hook_xmlrpc() { 2336 return array( 2337 'drupal.login' => 'drupal_login', 2338 array( 2339 'drupal.site.ping', 2340 'drupal_directory_ping', 2341 array('boolean', 'string', 'string', 'string', 'string', 'string'), 2342 t('Handling ping request')) 2343 ); 2344 } 2345 2346 /** 2347 * Alters the definition of XML-RPC methods before they are called. 2348 * 2349 * This hook allows modules to modify the callback definition of declared 2350 * XML-RPC methods, right before they are invoked by a client. Methods may be 2351 * added, or existing methods may be altered. 2352 * 2353 * Note that hook_xmlrpc() supports two distinct and incompatible formats to 2354 * define a callback, so care must be taken when altering other methods. 2355 * 2356 * @param $methods 2357 * An asssociative array of method callback definitions, as returned from 2358 * hook_xmlrpc() implementations. 2359 * 2360 * @see hook_xmlrpc() 2361 * @see xmlrpc_server() 2362 */ 2363 function hook_xmlrpc_alter(&$methods) { 2364 // Directly change a simple method. 2365 $methods['drupal.login'] = 'mymodule_login'; 2366 2367 // Alter complex definitions. 2368 foreach ($methods as $key => &$method) { 2369 // Skip simple method definitions. 2370 if (!is_int($key)) { 2371 continue; 2372 } 2373 // Perform the wanted manipulation. 2374 if ($method[0] == 'drupal.site.ping') { 2375 $method[1] = 'mymodule_directory_ping'; 2376 } 2377 } 2378 } 2379 2380 /** 2381 * Log an event message. 2382 * 2383 * This hook allows modules to route log events to custom destinations, such as 2384 * SMS, Email, pager, syslog, ...etc. 2385 * 2386 * @param $log_entry 2387 * An associative array containing the following keys: 2388 * - type: The type of message for this entry. 2389 * - user: The user object for the user who was logged in when the event 2390 * happened. 2391 * - uid: The user ID for the user who was logged in when the event happened. 2392 * - request_uri: The request URI for the page the event happened in. 2393 * - referer: The page that referred the user to the page where the event 2394 * occurred. 2395 * - ip: The IP address where the request for the page came from. 2396 * - timestamp: The UNIX timestamp of the date/time the event occurred. 2397 * - severity: The severity of the message; one of the following values as 2398 * defined in @link http://www.faqs.org/rfcs/rfc3164.html RFC 3164: @endlink 2399 * - WATCHDOG_EMERGENCY: Emergency, system is unusable. 2400 * - WATCHDOG_ALERT: Alert, action must be taken immediately. 2401 * - WATCHDOG_CRITICAL: Critical conditions. 2402 * - WATCHDOG_ERROR: Error conditions. 2403 * - WATCHDOG_WARNING: Warning conditions. 2404 * - WATCHDOG_NOTICE: Normal but significant conditions. 2405 * - WATCHDOG_INFO: Informational messages. 2406 * - WATCHDOG_DEBUG: Debug-level messages. 2407 * - link: An optional link provided by the module that called the watchdog() 2408 * function. 2409 * - message: The text of the message to be logged. Variables in the message 2410 * are indicated by using placeholder strings alongside the variables 2411 * argument to declare the value of the placeholders. See t() for 2412 * documentation on how the message and variable parameters interact. 2413 * - variables: An array of variables to be inserted into the message on 2414 * display. Will be NULL or missing if a message is already translated or if 2415 * the message is not possible to translate. 2416 */ 2417 function hook_watchdog(array $log_entry) { 2418 global $base_url, $language; 2419 2420 $severity_list = array( 2421 WATCHDOG_EMERGENCY => t('Emergency'), 2422 WATCHDOG_ALERT => t('Alert'), 2423 WATCHDOG_CRITICAL => t('Critical'), 2424 WATCHDOG_ERROR => t('Error'), 2425 WATCHDOG_WARNING => t('Warning'), 2426 WATCHDOG_NOTICE => t('Notice'), 2427 WATCHDOG_INFO => t('Info'), 2428 WATCHDOG_DEBUG => t('Debug'), 2429 ); 2430 2431 $to = 'someone@example.com'; 2432 $params = array(); 2433 $params['subject'] = t('[@site_name] @severity_desc: Alert from your web site', array( 2434 '@site_name' => variable_get('site_name', 'Drupal'), 2435 '@severity_desc' => $severity_list[$log_entry['severity']], 2436 )); 2437 2438 $params['message'] = "\nSite: @base_url"; 2439 $params['message'] .= "\nSeverity: (@severity) @severity_desc"; 2440 $params['message'] .= "\nTimestamp: @timestamp"; 2441 $params['message'] .= "\nType: @type"; 2442 $params['message'] .= "\nIP Address: @ip"; 2443 $params['message'] .= "\nRequest URI: @request_uri"; 2444 $params['message'] .= "\nReferrer URI: @referer_uri"; 2445 $params['message'] .= "\nUser: (@uid) @name"; 2446 $params['message'] .= "\nLink: @link"; 2447 $params['message'] .= "\nMessage: \n\n@message"; 2448 2449 $params['message'] = t($params['message'], array( 2450 '@base_url' => $base_url, 2451 '@severity' => $log_entry['severity'], 2452 '@severity_desc' => $severity_list[$log_entry['severity']], 2453 '@timestamp' => format_date($log_entry['timestamp']), 2454 '@type' => $log_entry['type'], 2455 '@ip' => $log_entry['ip'], 2456 '@request_uri' => $log_entry['request_uri'], 2457 '@referer_uri' => $log_entry['referer'], 2458 '@uid' => $log_entry['uid'], 2459 '@name' => $log_entry['user']->name, 2460 '@link' => strip_tags($log_entry['link']), 2461 '@message' => strip_tags($log_entry['message']), 2462 )); 2463 2464 drupal_mail('emaillog', 'entry', $to, $language, $params); 2465 } 2466 2467 /** 2468 * Prepare a message based on parameters; called from drupal_mail(). 2469 * 2470 * Note that hook_mail(), unlike hook_mail_alter(), is only called on the 2471 * $module argument to drupal_mail(), not all modules. 2472 * 2473 * @param $key 2474 * An identifier of the mail. 2475 * @param $message 2476 * An array to be filled in. Elements in this array include: 2477 * - id: An ID to identify the mail sent. Look at module source code 2478 * or drupal_mail() for possible id values. 2479 * - to: The address or addresses the message will be sent to. The 2480 * formatting of this string must comply with RFC 2822. 2481 * - subject: Subject of the e-mail to be sent. This must not contain any 2482 * newline characters, or the mail may not be sent properly. drupal_mail() 2483 * sets this to an empty string when the hook is invoked. 2484 * - body: An array of lines containing the message to be sent. Drupal will 2485 * format the correct line endings for you. drupal_mail() sets this to an 2486 * empty array when the hook is invoked. 2487 * - from: The address the message will be marked as being from, which is 2488 * set by drupal_mail() to either a custom address or the site-wide 2489 * default email address when the hook is invoked. 2490 * - headers: Associative array containing mail headers, such as From, 2491 * Sender, MIME-Version, Content-Type, etc. drupal_mail() pre-fills 2492 * several headers in this array. 2493 * @param $params 2494 * An array of parameters supplied by the caller of drupal_mail(). 2495 */ 2496 function hook_mail($key, &$message, $params) { 2497 $account = $params['account']; 2498 $context = $params['context']; 2499 $variables = array( 2500 '%site_name' => variable_get('site_name', 'Drupal'), 2501 '%username' => format_username($account), 2502 ); 2503 if ($context['hook'] == 'taxonomy') { 2504 $entity = $params['entity']; 2505 $vocabulary = taxonomy_vocabulary_load($entity->vid); 2506 $variables += array( 2507 '%term_name' => $entity->name, 2508 '%term_description' => $entity->description, 2509 '%term_id' => $entity->tid, 2510 '%vocabulary_name' => $vocabulary->name, 2511 '%vocabulary_description' => $vocabulary->description, 2512 '%vocabulary_id' => $vocabulary->vid, 2513 ); 2514 } 2515 2516 // Node-based variable translation is only available if we have a node. 2517 if (isset($params['node'])) { 2518 $node = $params['node']; 2519 $variables += array( 2520 '%uid' => $node->uid, 2521 '%node_url' => url('node/' . $node->nid, array('absolute' => TRUE)), 2522 '%node_type' => node_type_get_name($node), 2523 '%title' => $node->title, 2524 '%teaser' => $node->teaser, 2525 '%body' => $node->body, 2526 ); 2527 } 2528 $subject = strtr($context['subject'], $variables); 2529 $body = strtr($context['message'], $variables); 2530 $message['subject'] .= str_replace(array("\r", "\n"), '', $subject); 2531 $message['body'][] = drupal_html_to_text($body); 2532 } 2533 2534 /** 2535 * Add a list of cache tables to be cleared. 2536 * 2537 * This hook allows your module to add cache table names to the list of cache 2538 * tables that will be cleared by the Clear button on the Performance page or 2539 * whenever drupal_flush_all_caches is invoked. 2540 * 2541 * @return 2542 * An array of cache table names. 2543 * 2544 * @see drupal_flush_all_caches() 2545 */ 2546 function hook_flush_caches() { 2547 return array('cache_example'); 2548 } 2549 2550 /** 2551 * Perform necessary actions after modules are installed. 2552 * 2553 * This function differs from hook_install() in that it gives all other modules 2554 * a chance to perform actions when a module is installed, whereas 2555 * hook_install() is only called on the module actually being installed. See 2556 * module_enable() for a detailed description of the order in which install and 2557 * enable hooks are invoked. 2558 * 2559 * @param $modules 2560 * An array of the modules that were installed. 2561 * 2562 * @see module_enable() 2563 * @see hook_modules_enabled() 2564 * @see hook_install() 2565 */ 2566 function hook_modules_installed($modules) { 2567 if (in_array('lousy_module', $modules)) { 2568 variable_set('lousy_module_conflicting_variable', FALSE); 2569 } 2570 } 2571 2572 /** 2573 * Perform necessary actions after modules are enabled. 2574 * 2575 * This function differs from hook_enable() in that it gives all other modules a 2576 * chance to perform actions when modules are enabled, whereas hook_enable() is 2577 * only called on the module actually being enabled. See module_enable() for a 2578 * detailed description of the order in which install and enable hooks are 2579 * invoked. 2580 * 2581 * @param $modules 2582 * An array of the modules that were enabled. 2583 * 2584 * @see hook_enable() 2585 * @see hook_modules_installed() 2586 * @see module_enable() 2587 */ 2588 function hook_modules_enabled($modules) { 2589 if (in_array('lousy_module', $modules)) { 2590 drupal_set_message(t('mymodule is not compatible with lousy_module'), 'error'); 2591 mymodule_disable_functionality(); 2592 } 2593 } 2594 2595 /** 2596 * Perform necessary actions after modules are disabled. 2597 * 2598 * This function differs from hook_disable() in that it gives all other modules 2599 * a chance to perform actions when modules are disabled, whereas hook_disable() 2600 * is only called on the module actually being disabled. 2601 * 2602 * @param $modules 2603 * An array of the modules that were disabled. 2604 * 2605 * @see hook_disable() 2606 * @see hook_modules_uninstalled() 2607 */ 2608 function hook_modules_disabled($modules) { 2609 if (in_array('lousy_module', $modules)) { 2610 mymodule_enable_functionality(); 2611 } 2612 } 2613 2614 /** 2615 * Perform necessary actions after modules are uninstalled. 2616 * 2617 * This function differs from hook_uninstall() in that it gives all other 2618 * modules a chance to perform actions when a module is uninstalled, whereas 2619 * hook_uninstall() is only called on the module actually being uninstalled. 2620 * 2621 * It is recommended that you implement this hook if your module stores 2622 * data that may have been set by other modules. 2623 * 2624 * @param $modules 2625 * An array of the modules that were uninstalled. 2626 * 2627 * @see hook_uninstall() 2628 * @see hook_modules_disabled() 2629 */ 2630 function hook_modules_uninstalled($modules) { 2631 foreach ($modules as $module) { 2632 db_delete('mymodule_table') 2633 ->condition('module', $module) 2634 ->execute(); 2635 } 2636 mymodule_cache_rebuild(); 2637 } 2638 2639 /** 2640 * Registers PHP stream wrapper implementations associated with a module. 2641 * 2642 * Provide a facility for managing and querying user-defined stream wrappers 2643 * in PHP. PHP's internal stream_get_wrappers() doesn't return the class 2644 * registered to handle a stream, which we need to be able to find the handler 2645 * for class instantiation. 2646 * 2647 * If a module registers a scheme that is already registered with PHP, it will 2648 * be unregistered and replaced with the specified class. 2649 * 2650 * @return 2651 * A nested array, keyed first by scheme name ("public" for "public://"), 2652 * then keyed by the following values: 2653 * - 'name' A short string to name the wrapper. 2654 * - 'class' A string specifying the PHP class that implements the 2655 * DrupalStreamWrapperInterface interface. 2656 * - 'description' A string with a short description of what the wrapper does. 2657 * - 'type' (Optional) A bitmask of flags indicating what type of streams this 2658 * wrapper will access - local or remote, readable and/or writeable, etc. 2659 * Many shortcut constants are defined in stream_wrappers.inc. Defaults to 2660 * STREAM_WRAPPERS_NORMAL which includes all of these bit flags: 2661 * - STREAM_WRAPPERS_READ 2662 * - STREAM_WRAPPERS_WRITE 2663 * - STREAM_WRAPPERS_VISIBLE 2664 * 2665 * @see file_get_stream_wrappers() 2666 * @see hook_stream_wrappers_alter() 2667 * @see system_stream_wrappers() 2668 */ 2669 function hook_stream_wrappers() { 2670 return array( 2671 'public' => array( 2672 'name' => t('Public files'), 2673 'class' => 'DrupalPublicStreamWrapper', 2674 'description' => t('Public local files served by the webserver.'), 2675 'type' => STREAM_WRAPPERS_LOCAL_NORMAL, 2676 ), 2677 'private' => array( 2678 'name' => t('Private files'), 2679 'class' => 'DrupalPrivateStreamWrapper', 2680 'description' => t('Private local files served by Drupal.'), 2681 'type' => STREAM_WRAPPERS_LOCAL_NORMAL, 2682 ), 2683 'temp' => array( 2684 'name' => t('Temporary files'), 2685 'class' => 'DrupalTempStreamWrapper', 2686 'description' => t('Temporary local files for upload and previews.'), 2687 'type' => STREAM_WRAPPERS_LOCAL_HIDDEN, 2688 ), 2689 'cdn' => array( 2690 'name' => t('Content delivery network files'), 2691 'class' => 'MyModuleCDNStreamWrapper', 2692 'description' => t('Files served by a content delivery network.'), 2693 // 'type' can be omitted to use the default of STREAM_WRAPPERS_NORMAL 2694 ), 2695 'youtube' => array( 2696 'name' => t('YouTube video'), 2697 'class' => 'MyModuleYouTubeStreamWrapper', 2698 'description' => t('Video streamed from YouTube.'), 2699 // A module implementing YouTube integration may decide to support using 2700 // the YouTube API for uploading video, but here, we assume that this 2701 // particular module only supports playing YouTube video. 2702 'type' => STREAM_WRAPPERS_READ_VISIBLE, 2703 ), 2704 ); 2705 } 2706 2707 /** 2708 * Alters the list of PHP stream wrapper implementations. 2709 * 2710 * @see file_get_stream_wrappers() 2711 * @see hook_stream_wrappers() 2712 */ 2713 function hook_stream_wrappers_alter(&$wrappers) { 2714 // Change the name of private files to reflect the performance. 2715 $wrappers['private']['name'] = t('Slow files'); 2716 } 2717 2718 /** 2719 * Load additional information into file objects. 2720 * 2721 * file_load_multiple() calls this hook to allow modules to load 2722 * additional information into each file. 2723 * 2724 * @param $files 2725 * An array of file objects, indexed by fid. 2726 * 2727 * @see file_load_multiple() 2728 * @see file_load() 2729 */ 2730 function hook_file_load($files) { 2731 // Add the upload specific data into the file object. 2732 $result = db_query('SELECT * FROM {upload} u WHERE u.fid IN (:fids)', array(':fids' => array_keys($files)))->fetchAll(PDO::FETCH_ASSOC); 2733 foreach ($result as $record) { 2734 foreach ($record as $key => $value) { 2735 $files[$record['fid']]->$key = $value; 2736 } 2737 } 2738 } 2739 2740 /** 2741 * Check that files meet a given criteria. 2742 * 2743 * This hook lets modules perform additional validation on files. They're able 2744 * to report a failure by returning one or more error messages. 2745 * 2746 * @param $file 2747 * The file object being validated. 2748 * @return 2749 * An array of error messages. If there are no problems with the file return 2750 * an empty array. 2751 * 2752 * @see file_validate() 2753 */ 2754 function hook_file_validate($file) { 2755 $errors = array(); 2756 2757 if (empty($file->filename)) { 2758 $errors[] = t("The file's name is empty. Please give a name to the file."); 2759 } 2760 if (strlen($file->filename) > 255) { 2761 $errors[] = t("The file's name exceeds the 255 characters limit. Please rename the file and try again."); 2762 } 2763 2764 return $errors; 2765 } 2766 2767 /** 2768 * Act on a file being inserted or updated. 2769 * 2770 * This hook is called when a file has been added to the database. The hook 2771 * doesn't distinguish between files created as a result of a copy or those 2772 * created by an upload. 2773 * 2774 * @param $file 2775 * The file that has just been created. 2776 * 2777 * @see file_save() 2778 */ 2779 function hook_file_presave($file) { 2780 // Change the file timestamp to an hour prior. 2781 $file->timestamp -= 3600; 2782 } 2783 2784 /** 2785 * Respond to a file being added. 2786 * 2787 * This hook is called after a file has been added to the database. The hook 2788 * doesn't distinguish between files created as a result of a copy or those 2789 * created by an upload. 2790 * 2791 * @param $file 2792 * The file that has been added. 2793 * 2794 * @see file_save() 2795 */ 2796 function hook_file_insert($file) { 2797 // Add a message to the log, if the file is a jpg 2798 $validate = file_validate_extensions($file, 'jpg'); 2799 if (empty($validate)) { 2800 watchdog('file', 'A jpg has been added.'); 2801 } 2802 } 2803 2804 /** 2805 * Respond to a file being updated. 2806 * 2807 * This hook is called when file_save() is called on an existing file. 2808 * 2809 * @param $file 2810 * The file that has just been updated. 2811 * 2812 * @see file_save() 2813 */ 2814 function hook_file_update($file) { 2815 2816 } 2817 2818 /** 2819 * Respond to a file that has been copied. 2820 * 2821 * @param $file 2822 * The newly copied file object. 2823 * @param $source 2824 * The original file before the copy. 2825 * 2826 * @see file_copy() 2827 */ 2828 function hook_file_copy($file, $source) { 2829 2830 } 2831 2832 /** 2833 * Respond to a file that has been moved. 2834 * 2835 * @param $file 2836 * The updated file object after the move. 2837 * @param $source 2838 * The original file object before the move. 2839 * 2840 * @see file_move() 2841 */ 2842 function hook_file_move($file, $source) { 2843 2844 } 2845 2846 /** 2847 * Respond to a file being deleted. 2848 * 2849 * @param $file 2850 * The file that has just been deleted. 2851 * 2852 * @see file_delete() 2853 */ 2854 function hook_file_delete($file) { 2855 // Delete all information associated with the file. 2856 db_delete('upload')->condition('fid', $file->fid)->execute(); 2857 } 2858 2859 /** 2860 * Control access to private file downloads and specify HTTP headers. 2861 * 2862 * This hook allows modules enforce permissions on file downloads when the 2863 * private file download method is selected. Modules can also provide headers 2864 * to specify information like the file's name or MIME type. 2865 * 2866 * @param $uri 2867 * The URI of the file. 2868 * @return 2869 * If the user does not have permission to access the file, return -1. If the 2870 * user has permission, return an array with the appropriate headers. If the 2871 * file is not controlled by the current module, the return value should be 2872 * NULL. 2873 * 2874 * @see file_download() 2875 */ 2876 function hook_file_download($uri) { 2877 // Check if the file is controlled by the current module. 2878 if (!file_prepare_directory($uri)) { 2879 $uri = FALSE; 2880 } 2881 if (strpos(file_uri_target($uri), variable_get('user_picture_path', 'pictures') . '/picture-') === 0) { 2882 if (!user_access('access user profiles')) { 2883 // Access to the file is denied. 2884 return -1; 2885 } 2886 else { 2887 $info = image_get_info($uri); 2888 return array('Content-Type' => $info['mime_type']); 2889 } 2890 } 2891 } 2892 2893 /** 2894 * Alter the URL to a file. 2895 * 2896 * This hook is called from file_create_url(), and is called fairly 2897 * frequently (10+ times per page), depending on how many files there are in a 2898 * given page. 2899 * If CSS and JS aggregation are disabled, this can become very frequently 2900 * (50+ times per page) so performance is critical. 2901 * 2902 * This function should alter the URI, if it wants to rewrite the file URL. 2903 * 2904 * @param $uri 2905 * The URI to a file for which we need an external URL, or the path to a 2906 * shipped file. 2907 */ 2908 function hook_file_url_alter(&$uri) { 2909 global $user; 2910 2911 // User 1 will always see the local file in this example. 2912 if ($user->uid == 1) { 2913 return; 2914 } 2915 2916 $cdn1 = 'http://cdn1.example.com'; 2917 $cdn2 = 'http://cdn2.example.com'; 2918 $cdn_extensions = array('css', 'js', 'gif', 'jpg', 'jpeg', 'png'); 2919 2920 // Most CDNs don't support private file transfers without a lot of hassle, 2921 // so don't support this in the common case. 2922 $schemes = array('public'); 2923 2924 $scheme = file_uri_scheme($uri); 2925 2926 // Only serve shipped files and public created files from the CDN. 2927 if (!$scheme || in_array($scheme, $schemes)) { 2928 // Shipped files. 2929 if (!$scheme) { 2930 $path = $uri; 2931 } 2932 // Public created files. 2933 else { 2934 $wrapper = file_stream_wrapper_get_instance_by_scheme($scheme); 2935 $path = $wrapper->getDirectoryPath() . '/' . file_uri_target($uri); 2936 } 2937 2938 // Clean up Windows paths. 2939 $path = str_replace('\\', '/', $path); 2940 2941 // Serve files with one of the CDN extensions from CDN 1, all others from 2942 // CDN 2. 2943 $pathinfo = pathinfo($path); 2944 if (isset($pathinfo['extension']) && in_array($pathinfo['extension'], $cdn_extensions)) { 2945 $uri = $cdn1 . '/' . $path; 2946 } 2947 else { 2948 $uri = $cdn2 . '/' . $path; 2949 } 2950 } 2951 } 2952 2953 /** 2954 * Check installation requirements and do status reporting. 2955 * 2956 * This hook has three closely related uses, determined by the $phase argument: 2957 * - Checking installation requirements ($phase == 'install'). 2958 * - Checking update requirements ($phase == 'update'). 2959 * - Status reporting ($phase == 'runtime'). 2960 * 2961 * Note that this hook, like all others dealing with installation and updates, 2962 * must reside in a module_name.install file, or it will not properly abort 2963 * the installation of the module if a critical requirement is missing. 2964 * 2965 * During the 'install' phase, modules can for example assert that 2966 * library or server versions are available or sufficient. 2967 * Note that the installation of a module can happen during installation of 2968 * Drupal itself (by install.php) with an installation profile or later by hand. 2969 * As a consequence, install-time requirements must be checked without access 2970 * to the full Drupal API, because it is not available during install.php. 2971 * For localization you should for example use $t = get_t() to 2972 * retrieve the appropriate localization function name (t() or st()). 2973 * If a requirement has a severity of REQUIREMENT_ERROR, install.php will abort 2974 * or at least the module will not install. 2975 * Other severity levels have no effect on the installation. 2976 * Module dependencies do not belong to these installation requirements, 2977 * but should be defined in the module's .info file. 2978 * 2979 * The 'runtime' phase is not limited to pure installation requirements 2980 * but can also be used for more general status information like maintenance 2981 * tasks and security issues. 2982 * The returned 'requirements' will be listed on the status report in the 2983 * administration section, with indication of the severity level. 2984 * Moreover, any requirement with a severity of REQUIREMENT_ERROR severity will 2985 * result in a notice on the administration configuration page. 2986 * 2987 * @param $phase 2988 * The phase in which requirements are checked: 2989 * - install: The module is being installed. 2990 * - update: The module is enabled and update.php is run. 2991 * - runtime: The runtime requirements are being checked and shown on the 2992 * status report page. 2993 * 2994 * @return 2995 * A keyed array of requirements. Each requirement is itself an array with 2996 * the following items: 2997 * - title: The name of the requirement. 2998 * - value: The current value (e.g., version, time, level, etc). During 2999 * install phase, this should only be used for version numbers, do not set 3000 * it if not applicable. 3001 * - description: The description of the requirement/status. 3002 * - severity: The requirement's result/severity level, one of: 3003 * - REQUIREMENT_INFO: For info only. 3004 * - REQUIREMENT_OK: The requirement is satisfied. 3005 * - REQUIREMENT_WARNING: The requirement failed with a warning. 3006 * - REQUIREMENT_ERROR: The requirement failed with an error. 3007 */ 3008 function hook_requirements($phase) { 3009 $requirements = array(); 3010 // Ensure translations don't break during installation. 3011 $t = get_t(); 3012 3013 // Report Drupal version 3014 if ($phase == 'runtime') { 3015 $requirements['drupal'] = array( 3016 'title' => $t('Drupal'), 3017 'value' => VERSION, 3018 'severity' => REQUIREMENT_INFO 3019 ); 3020 } 3021 3022 // Test PHP version 3023 $requirements['php'] = array( 3024 'title' => $t('PHP'), 3025 'value' => ($phase == 'runtime') ? l(phpversion(), 'admin/reports/status/php') : phpversion(), 3026 ); 3027 if (version_compare(phpversion(), DRUPAL_MINIMUM_PHP) < 0) { 3028 $requirements['php']['description'] = $t('Your PHP installation is too old. Drupal requires at least PHP %version.', array('%version' => DRUPAL_MINIMUM_PHP)); 3029 $requirements['php']['severity'] = REQUIREMENT_ERROR; 3030 } 3031 3032 // Report cron status 3033 if ($phase == 'runtime') { 3034 $cron_last = variable_get('cron_last'); 3035 3036 if (is_numeric($cron_last)) { 3037 $requirements['cron']['value'] = $t('Last run !time ago', array('!time' => format_interval(REQUEST_TIME - $cron_last))); 3038 } 3039 else { 3040 $requirements['cron'] = array( 3041 'description' => $t('Cron has not run. It appears cron jobs have not been setup on your system. Check the help pages for <a href="@url">configuring cron jobs</a>.', array('@url' => 'http://drupal.org/cron')), 3042 'severity' => REQUIREMENT_ERROR, 3043 'value' => $t('Never run'), 3044 ); 3045 } 3046 3047 $requirements['cron']['description'] .= ' ' . $t('You can <a href="@cron">run cron manually</a>.', array('@cron' => url('admin/reports/status/run-cron'))); 3048 3049 $requirements['cron']['title'] = $t('Cron maintenance tasks'); 3050 } 3051 3052 return $requirements; 3053 } 3054 3055 /** 3056 * Define the current version of the database schema. 3057 * 3058 * A Drupal schema definition is an array structure representing one or 3059 * more tables and their related keys and indexes. A schema is defined by 3060 * hook_schema() which must live in your module's .install file. 3061 * 3062 * This hook is called at install and uninstall time, and in the latter 3063 * case, it cannot rely on the .module file being loaded or hooks being known. 3064 * If the .module file is needed, it may be loaded with drupal_load(). 3065 * 3066 * The tables declared by this hook will be automatically created when 3067 * the module is first enabled, and removed when the module is uninstalled. 3068 * This happens before hook_install() is invoked, and after hook_uninstall() 3069 * is invoked, respectively. 3070 * 3071 * By declaring the tables used by your module via an implementation of 3072 * hook_schema(), these tables will be available on all supported database 3073 * engines. You don't have to deal with the different SQL dialects for table 3074 * creation and alteration of the supported database engines. 3075 * 3076 * See the Schema API Handbook at http://drupal.org/node/146843 for 3077 * details on schema definition structures. 3078 * 3079 * @return 3080 * A schema definition structure array. For each element of the 3081 * array, the key is a table name and the value is a table structure 3082 * definition. 3083 * 3084 * @ingroup schemaapi 3085 */ 3086 function hook_schema() { 3087 $schema['node'] = array( 3088 // example (partial) specification for table "node" 3089 'description' => 'The base table for nodes.', 3090 'fields' => array( 3091 'nid' => array( 3092 'description' => 'The primary identifier for a node.', 3093 'type' => 'serial', 3094 'unsigned' => TRUE, 3095 'not null' => TRUE), 3096 'vid' => array( 3097 'description' => 'The current {node_revision}.vid version identifier.', 3098 'type' => 'int', 3099 'unsigned' => TRUE, 3100 'not null' => TRUE, 3101 'default' => 0), 3102 'type' => array( 3103 'description' => 'The {node_type} of this node.', 3104 'type' => 'varchar', 3105 'length' => 32, 3106 'not null' => TRUE, 3107 'default' => ''), 3108 'title' => array( 3109 'description' => 'The title of this node, always treated as non-markup plain text.', 3110 'type' => 'varchar', 3111 'length' => 255, 3112 'not null' => TRUE, 3113 'default' => ''), 3114 ), 3115 'indexes' => array( 3116 'node_changed' => array('changed'), 3117 'node_created' => array('created'), 3118 ), 3119 'unique keys' => array( 3120 'nid_vid' => array('nid', 'vid'), 3121 'vid' => array('vid') 3122 ), 3123 'foreign keys' => array( 3124 'node_revision' => array( 3125 'table' => 'node_revision', 3126 'columns' => array('vid' => 'vid'), 3127 ), 3128 'node_author' => array( 3129 'table' => 'users', 3130 'columns' => array('uid' => 'uid') 3131 ), 3132 ), 3133 'primary key' => array('nid'), 3134 ); 3135 return $schema; 3136 } 3137 3138 /** 3139 * Perform alterations to existing database schemas. 3140 * 3141 * When a module modifies the database structure of another module (by 3142 * changing, adding or removing fields, keys or indexes), it should 3143 * implement hook_schema_alter() to update the default $schema to take its 3144 * changes into account. 3145 * 3146 * See hook_schema() for details on the schema definition structure. 3147 * 3148 * @param $schema 3149 * Nested array describing the schemas for all modules. 3150 */ 3151 function hook_schema_alter(&$schema) { 3152 // Add field to existing schema. 3153 $schema['users']['fields']['timezone_id'] = array( 3154 'type' => 'int', 3155 'not null' => TRUE, 3156 'default' => 0, 3157 'description' => 'Per-user timezone configuration.', 3158 ); 3159 } 3160 3161 /** 3162 * Perform alterations to a structured query. 3163 * 3164 * Structured (aka dynamic) queries that have tags associated may be altered by any module 3165 * before the query is executed. 3166 * 3167 * @param $query 3168 * A Query object describing the composite parts of a SQL query. 3169 * 3170 * @see hook_query_TAG_alter() 3171 * @see node_query_node_access_alter() 3172 * @see QueryAlterableInterface 3173 * @see SelectQueryInterface 3174 */ 3175 function hook_query_alter(QueryAlterableInterface $query) { 3176 if ($query->hasTag('micro_limit')) { 3177 $query->range(0, 2); 3178 } 3179 } 3180 3181 /** 3182 * Perform alterations to a structured query for a given tag. 3183 * 3184 * @param $query 3185 * An Query object describing the composite parts of a SQL query. 3186 * 3187 * @see hook_query_alter() 3188 * @see node_query_node_access_alter() 3189 * @see QueryAlterableInterface 3190 * @see SelectQueryInterface 3191 */ 3192 function hook_query_TAG_alter(QueryAlterableInterface $query) { 3193 // Skip the extra expensive alterations if site has no node access control modules. 3194 if (!node_access_view_all_nodes()) { 3195 // Prevent duplicates records. 3196 $query->distinct(); 3197 // The recognized operations are 'view', 'update', 'delete'. 3198 if (!$op = $query->getMetaData('op')) { 3199 $op = 'view'; 3200 } 3201 // Skip the extra joins and conditions for node admins. 3202 if (!user_access('bypass node access')) { 3203 // The node_access table has the access grants for any given node. 3204 $access_alias = $query->join('node_access', 'na', '%alias.nid = n.nid'); 3205 $or = db_or(); 3206 // If any grant exists for the specified user, then user has access to the node for the specified operation. 3207 foreach (node_access_grants($op, $query->getMetaData('account')) as $realm => $gids) { 3208 foreach ($gids as $gid) { 3209 $or->condition(db_and() 3210 ->condition($access_alias . '.gid', $gid) 3211 ->condition($access_alias . '.realm', $realm) 3212 ); 3213 } 3214 } 3215 3216 if (count($or->conditions())) { 3217 $query->condition($or); 3218 } 3219 3220 $query->condition($access_alias . 'grant_' . $op, 1, '>='); 3221 } 3222 } 3223 } 3224 3225 /** 3226 * Perform setup tasks when the module is installed. 3227 * 3228 * If the module implements hook_schema(), the database tables will 3229 * be created before this hook is fired. 3230 * 3231 * Implementations of this hook are by convention declared in the module's 3232 * .install file. The implementation can rely on the .module file being loaded. 3233 * The hook will only be called the first time a module is enabled or after it 3234 * is re-enabled after being uninstalled. The module's schema version will be 3235 * set to the module's greatest numbered update hook. Because of this, any time 3236 * a hook_update_N() is added to the module, this function needs to be updated 3237 * to reflect the current version of the database schema. 3238 * 3239 * See the Schema API documentation at 3240 * @link http://drupal.org/node/146843 http://drupal.org/node/146843 @endlink 3241 * for details on hook_schema and how database tables are defined. 3242 * 3243 * Note that since this function is called from a full bootstrap, all functions 3244 * (including those in modules enabled by the current page request) are 3245 * available when this hook is called. Use cases could be displaying a user 3246 * message, or calling a module function necessary for initial setup, etc. 3247 * 3248 * Please be sure that anything added or modified in this function that can 3249 * be removed during uninstall should be removed with hook_uninstall(). 3250 * 3251 * @see hook_schema() 3252 * @see module_enable() 3253 * @see hook_enable() 3254 * @see hook_disable() 3255 * @see hook_uninstall() 3256 * @see hook_modules_installed() 3257 */ 3258 function hook_install() { 3259 // Populate the default {node_access} record. 3260 db_insert('node_access') 3261 ->fields(array( 3262 'nid' => 0, 3263 'gid' => 0, 3264 'realm' => 'all', 3265 'grant_view' => 1, 3266 'grant_update' => 0, 3267 'grant_delete' => 0, 3268 )) 3269 ->execute(); 3270 } 3271 3272 /** 3273 * Perform a single update. 3274 * 3275 * For each change that requires one or more actions to be performed when 3276 * updating a site, add a new hook_update_N(), which will be called by 3277 * update.php. The documentation block preceding this function is stripped of 3278 * newlines and used as the description for the update on the pending updates 3279 * task list. Schema updates should adhere to the 3280 * @link http://drupal.org/node/150215 Schema API. @endlink 3281 * 3282 * Implementations of hook_update_N() are named (module name)_update_(number). 3283 * The numbers are composed of three parts: 3284 * - 1 digit for Drupal core compatibility. 3285 * - 1 digit for your module's major release version (e.g., is this the 7.x-1.* 3286 * (1) or 7.x-2.* (2) series of your module?). This digit should be 0 for 3287 * initial porting of your module to a new Drupal core API. 3288 * - 2 digits for sequential counting, starting with 00. 3289 * 3290 * Examples: 3291 * - mymodule_update_7000(): This is the required update for mymodule to run 3292 * with Drupal core API 7.x when upgrading from Drupal core API 6.x. 3293 * - mymodule_update_7100(): This is the first update to get the database ready 3294 * to run mymodule 7.x-1.*. 3295 * - mymodule_update_7200(): This is the first update to get the database ready 3296 * to run mymodule 7.x-2.*. Users can directly update from 6.x-2.* to 7.x-2.* 3297 * and they get all 70xx and 72xx updates, but not 71xx updates, because 3298 * those reside in the 7.x-1.x branch only. 3299 * 3300 * A good rule of thumb is to remove updates older than two major releases of 3301 * Drupal. See hook_update_last_removed() to notify Drupal about the removals. 3302 * For further information about releases and release numbers see: 3303 * @link http://drupal.org/node/711070 Maintaining a drupal.org project with Git @endlink 3304 * 3305 * Never renumber update functions. 3306 * 3307 * Implementations of this hook should be placed in a mymodule.install file in 3308 * the same directory as mymodule.module. Drupal core's updates are implemented 3309 * using the system module as a name and stored in database/updates.inc. 3310 * 3311 * Not all module functions are available from within a hook_update_N() function. 3312 * In order to call a function from your mymodule.module or an include file, 3313 * you need to explicitly load that file first. 3314 * 3315 * During database updates the schema of any module could be out of date. For 3316 * this reason, caution is needed when using any API function within an update 3317 * function - particularly CRUD functions, functions that depend on the schema 3318 * (for example by using drupal_write_record()), and any functions that invoke 3319 * hooks. See @link update_api Update versions of API functions @endlink for 3320 * details. 3321 * 3322 * If your update task is potentially time-consuming, you'll need to implement a 3323 * multipass update to avoid PHP timeouts. Multipass updates use the $sandbox 3324 * parameter provided by the batch API (normally, $context['sandbox']) to store 3325 * information between successive calls, and the $sandbox['#finished'] value 3326 * to provide feedback regarding completion level. 3327 * 3328 * See the batch operations page for more information on how to use the 3329 * @link http://drupal.org/node/180528 Batch API. @endlink 3330 * 3331 * @param $sandbox 3332 * Stores information for multipass updates. See above for more information. 3333 * 3334 * @throws DrupalUpdateException, PDOException 3335 * In case of error, update hooks should throw an instance of DrupalUpdateException 3336 * with a meaningful message for the user. If a database query fails for whatever 3337 * reason, it will throw a PDOException. 3338 * 3339 * @return 3340 * Optionally, update hooks may return a translated string that will be 3341 * displayed to the user after the update has completed. If no message is 3342 * returned, no message will be presented to the user. 3343 * 3344 * @see batch 3345 * @see schemaapi 3346 * @see update_api 3347 * @see hook_update_last_removed() 3348 * @see update_get_update_list() 3349 */ 3350 function hook_update_N(&$sandbox) { 3351 // For non-multipass updates, the signature can simply be; 3352 // function hook_update_N() { 3353 3354 // For most updates, the following is sufficient. 3355 db_add_field('mytable1', 'newcol', array('type' => 'int', 'not null' => TRUE, 'description' => 'My new integer column.')); 3356 3357 // However, for more complex operations that may take a long time, 3358 // you may hook into Batch API as in the following example. 3359 3360 // Update 3 users at a time to have an exclamation point after their names. 3361 // (They're really happy that we can do batch API in this hook!) 3362 if (!isset($sandbox['progress'])) { 3363 $sandbox['progress'] = 0; 3364 $sandbox['current_uid'] = 0; 3365 // We'll -1 to disregard the uid 0... 3366 $sandbox['max'] = db_query('SELECT COUNT(DISTINCT uid) FROM {users}')->fetchField() - 1; 3367 } 3368 3369 $users = db_select('users', 'u') 3370 ->fields('u', array('uid', 'name')) 3371 ->condition('uid', $sandbox['current_uid'], '>') 3372 ->range(0, 3) 3373 ->orderBy('uid', 'ASC') 3374 ->execute(); 3375 3376 foreach ($users as $user) { 3377 $user->name .= '!'; 3378 db_update('users') 3379 ->fields(array('name' => $user->name)) 3380 ->condition('uid', $user->uid) 3381 ->execute(); 3382 3383 $sandbox['progress']++; 3384 $sandbox['current_uid'] = $user->uid; 3385 } 3386 3387 $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']); 3388 3389 // To display a message to the user when the update is completed, return it. 3390 // If you do not want to display a completion message, simply return nothing. 3391 return t('The update did what it was supposed to do.'); 3392 3393 // In case of an error, simply throw an exception with an error message. 3394 throw new DrupalUpdateException('Something went wrong; here is what you should do.'); 3395 } 3396 3397 /** 3398 * Return an array of information about module update dependencies. 3399 * 3400 * This can be used to indicate update functions from other modules that your 3401 * module's update functions depend on, or vice versa. It is used by the update 3402 * system to determine the appropriate order in which updates should be run, as 3403 * well as to search for missing dependencies. 3404 * 3405 * Implementations of this hook should be placed in a mymodule.install file in 3406 * the same directory as mymodule.module. 3407 * 3408 * @return 3409 * A multidimensional array containing information about the module update 3410 * dependencies. The first two levels of keys represent the module and update 3411 * number (respectively) for which information is being returned, and the 3412 * value is an array of information about that update's dependencies. Within 3413 * this array, each key represents a module, and each value represents the 3414 * number of an update function within that module. In the event that your 3415 * update function depends on more than one update from a particular module, 3416 * you should always list the highest numbered one here (since updates within 3417 * a given module always run in numerical order). 3418 * 3419 * @see update_resolve_dependencies() 3420 * @see hook_update_N() 3421 */ 3422 function hook_update_dependencies() { 3423 // Indicate that the mymodule_update_7000() function provided by this module 3424 // must run after the another_module_update_7002() function provided by the 3425 // 'another_module' module. 3426 $dependencies['mymodule'][7000] = array( 3427 'another_module' => 7002, 3428 ); 3429 // Indicate that the mymodule_update_7001() function provided by this module 3430 // must run before the yet_another_module_update_7004() function provided by 3431 // the 'yet_another_module' module. (Note that declaring dependencies in this 3432 // direction should be done only in rare situations, since it can lead to the 3433 // following problem: If a site has already run the yet_another_module 3434 // module's database updates before it updates its codebase to pick up the 3435 // newest mymodule code, then the dependency declared here will be ignored.) 3436 $dependencies['yet_another_module'][7004] = array( 3437 'mymodule' => 7001, 3438 ); 3439 return $dependencies; 3440 } 3441 3442 /** 3443 * Return a number which is no longer available as hook_update_N(). 3444 * 3445 * If you remove some update functions from your mymodule.install file, you 3446 * should notify Drupal of those missing functions. This way, Drupal can 3447 * ensure that no update is accidentally skipped. 3448 * 3449 * Implementations of this hook should be placed in a mymodule.install file in 3450 * the same directory as mymodule.module. 3451 * 3452 * @return 3453 * An integer, corresponding to hook_update_N() which has been removed from 3454 * mymodule.install. 3455 * 3456 * @see hook_update_N() 3457 */ 3458 function hook_update_last_removed() { 3459 // We've removed the 5.x-1.x version of mymodule, including database updates. 3460 // The next update function is mymodule_update_5200(). 3461 return 5103; 3462 } 3463 3464 /** 3465 * Remove any information that the module sets. 3466 * 3467 * The information that the module should remove includes: 3468 * - variables that the module has set using variable_set() or system_settings_form() 3469 * - modifications to existing tables 3470 * 3471 * The module should not remove its entry from the {system} table. Database 3472 * tables defined by hook_schema() will be removed automatically. 3473 * 3474 * The uninstall hook must be implemented in the module's .install file. It 3475 * will fire when the module gets uninstalled but before the module's database 3476 * tables are removed, allowing your module to query its own tables during 3477 * this routine. 3478 * 3479 * When hook_uninstall() is called, your module will already be disabled, so 3480 * its .module file will not be automatically included. If you need to call API 3481 * functions from your .module file in this hook, use drupal_load() to make 3482 * them available. (Keep this usage to a minimum, though, especially when 3483 * calling API functions that invoke hooks, or API functions from modules 3484 * listed as dependencies, since these may not be available or work as expected 3485 * when the module is disabled.) 3486 * 3487 * @see hook_install() 3488 * @see hook_schema() 3489 * @see hook_disable() 3490 * @see hook_modules_uninstalled() 3491 */ 3492 function hook_uninstall() { 3493 variable_del('upload_file_types'); 3494 } 3495 3496 /** 3497 * Perform necessary actions after module is enabled. 3498 * 3499 * The hook is called every time the module is enabled. It should be 3500 * implemented in the module's .install file. The implementation can 3501 * rely on the .module file being loaded. 3502 * 3503 * @see module_enable() 3504 * @see hook_install() 3505 * @see hook_modules_enabled() 3506 */ 3507 function hook_enable() { 3508 mymodule_cache_rebuild(); 3509 } 3510 3511 /** 3512 * Perform necessary actions before module is disabled. 3513 * 3514 * The hook is called every time the module is disabled. It should be 3515 * implemented in the module's .install file. The implementation can rely 3516 * on the .module file being loaded. 3517 * 3518 * @see hook_uninstall() 3519 * @see hook_modules_disabled() 3520 */ 3521 function hook_disable() { 3522 mymodule_cache_rebuild(); 3523 } 3524 3525 /** 3526 * Perform necessary alterations to the list of files parsed by the registry. 3527 * 3528 * Modules can manually modify the list of files before the registry parses 3529 * them. The $modules array provides the .info file information, which includes 3530 * the list of files registered to each module. Any files in the list can then 3531 * be added to the list of files that the registry will parse, or modify 3532 * attributes of a file. 3533 * 3534 * A necessary alteration made by the core SimpleTest module is to force .test 3535 * files provided by disabled modules into the list of files parsed by the 3536 * registry. 3537 * 3538 * @param $files 3539 * List of files to be parsed by the registry. The list will contain 3540 * files found in each enabled module's info file and the core includes 3541 * directory. The array is keyed by the file path and contains an array of 3542 * the related module's name and weight as used internally by 3543 * _registry_update() and related functions. 3544 * 3545 * For example: 3546 * @code 3547 * $files["modules/system/system.module"] = array( 3548 * 'module' => 'system', 3549 * 'weight' => 0, 3550 * ); 3551 * @endcode 3552 * @param $modules 3553 * An array containing all module information stored in the {system} table. 3554 * Each element of the array also contains the module's .info file 3555 * information in the property 'info'. An additional 'dir' property has been 3556 * added to the module information which provides the path to the directory 3557 * in which the module resides. The example shows how to take advantage of 3558 * both properties. 3559 * 3560 * @see _registry_update() 3561 * @see simpletest_test_get_all() 3562 */ 3563 function hook_registry_files_alter(&$files, $modules) { 3564 foreach ($modules as $module) { 3565 // Only add test files for disabled modules, as enabled modules should 3566 // already include any test files they provide. 3567 if (!$module->status) { 3568 $dir = $module->dir; 3569 foreach ($module->info['files'] as $file) { 3570 if (substr($file, -5) == '.test') { 3571 $files["$dir/$file"] = array('module' => $module->name, 'weight' => $module->weight); 3572 } 3573 } 3574 } 3575 } 3576 } 3577 3578 /** 3579 * Return an array of tasks to be performed by an installation profile. 3580 * 3581 * Any tasks you define here will be run, in order, after the installer has 3582 * finished the site configuration step but before it has moved on to the 3583 * final import of languages and the end of the installation. You can have any 3584 * number of custom tasks to perform during this phase. 3585 * 3586 * Each task you define here corresponds to a callback function which you must 3587 * separately define and which is called when your task is run. This function 3588 * will receive the global installation state variable, $install_state, as 3589 * input, and has the opportunity to access or modify any of its settings. See 3590 * the install_state_defaults() function in the installer for the list of 3591 * $install_state settings used by Drupal core. 3592 * 3593 * At the end of your task function, you can indicate that you want the 3594 * installer to pause and display a page to the user by returning any themed 3595 * output that should be displayed on that page (but see below for tasks that 3596 * use the form API or batch API; the return values of these task functions are 3597 * handled differently). You should also use drupal_set_title() within the task 3598 * callback function to set a custom page title. For some tasks, however, you 3599 * may want to simply do some processing and pass control to the next task 3600 * without ending the page request; to indicate this, simply do not send back 3601 * a return value from your task function at all. This can be used, for 3602 * example, by installation profiles that need to configure certain site 3603 * settings in the database without obtaining any input from the user. 3604 * 3605 * The task function is treated specially if it defines a form or requires 3606 * batch processing; in that case, you should return either the form API 3607 * definition or batch API array, as appropriate. See below for more 3608 * information on the 'type' key that you must define in the task definition 3609 * to inform the installer that your task falls into one of those two 3610 * categories. It is important to use these APIs directly, since the installer 3611 * may be run non-interactively (for example, via a command line script), all 3612 * in one page request; in that case, the installer will automatically take 3613 * care of submitting forms and processing batches correctly for both types of 3614 * installations. You can inspect the $install_state['interactive'] boolean to 3615 * see whether or not the current installation is interactive, if you need 3616 * access to this information. 3617 * 3618 * Remember that a user installing Drupal interactively will be able to reload 3619 * an installation page multiple times, so you should use variable_set() and 3620 * variable_get() if you are collecting any data that you need to store and 3621 * inspect later. It is important to remove any temporary variables using 3622 * variable_del() before your last task has completed and control is handed 3623 * back to the installer. 3624 * 3625 * @return 3626 * A keyed array of tasks the profile will perform during the final stage of 3627 * the installation. Each key represents the name of a function (usually a 3628 * function defined by this profile, although that is not strictly required) 3629 * that is called when that task is run. The values are associative arrays 3630 * containing the following key-value pairs (all of which are optional): 3631 * - 'display_name' 3632 * The human-readable name of the task. This will be displayed to the 3633 * user while the installer is running, along with a list of other tasks 3634 * that are being run. Leave this unset to prevent the task from 3635 * appearing in the list. 3636 * - 'display' 3637 * This is a boolean which can be used to provide finer-grained control 3638 * over whether or not the task will display. This is mostly useful for 3639 * tasks that are intended to display only under certain conditions; for 3640 * these tasks, you can set 'display_name' to the name that you want to 3641 * display, but then use this boolean to hide the task only when certain 3642 * conditions apply. 3643 * - 'type' 3644 * A string representing the type of task. This parameter has three 3645 * possible values: 3646 * - 'normal': This indicates that the task will be treated as a regular 3647 * callback function, which does its processing and optionally returns 3648 * HTML output. This is the default behavior which is used when 'type' is 3649 * not set. 3650 * - 'batch': This indicates that the task function will return a batch 3651 * API definition suitable for batch_set(). The installer will then take 3652 * care of automatically running the task via batch processing. 3653 * - 'form': This indicates that the task function will return a standard 3654 * form API definition (and separately define validation and submit 3655 * handlers, as appropriate). The installer will then take care of 3656 * automatically directing the user through the form submission process. 3657 * - 'run' 3658 * A constant representing the manner in which the task will be run. This 3659 * parameter has three possible values: 3660 * - INSTALL_TASK_RUN_IF_NOT_COMPLETED: This indicates that the task will 3661 * run once during the installation of the profile. This is the default 3662 * behavior which is used when 'run' is not set. 3663 * - INSTALL_TASK_SKIP: This indicates that the task will not run during 3664 * the current installation page request. It can be used to skip running 3665 * an installation task when certain conditions are met, even though the 3666 * task may still show on the list of installation tasks presented to the 3667 * user. 3668 * - INSTALL_TASK_RUN_IF_REACHED: This indicates that the task will run 3669 * on each installation page request that reaches it. This is rarely 3670 * necessary for an installation profile to use; it is primarily used by 3671 * the Drupal installer for bootstrap-related tasks. 3672 * - 'function' 3673 * Normally this does not need to be set, but it can be used to force the 3674 * installer to call a different function when the task is run (rather 3675 * than the function whose name is given by the array key). This could be 3676 * used, for example, to allow the same function to be called by two 3677 * different tasks. 3678 * 3679 * @see install_state_defaults() 3680 * @see batch_set() 3681 */ 3682 function hook_install_tasks() { 3683 // Here, we define a variable to allow tasks to indicate that a particular, 3684 // processor-intensive batch process needs to be triggered later on in the 3685 // installation. 3686 $myprofile_needs_batch_processing = variable_get('myprofile_needs_batch_processing', FALSE); 3687 $tasks = array( 3688 // This is an example of a task that defines a form which the user who is 3689 // installing the site will be asked to fill out. To implement this task, 3690 // your profile would define a function named myprofile_data_import_form() 3691 // as a normal form API callback function, with associated validation and 3692 // submit handlers. In the submit handler, in addition to saving whatever 3693 // other data you have collected from the user, you might also call 3694 // variable_set('myprofile_needs_batch_processing', TRUE) if the user has 3695 // entered data which requires that batch processing will need to occur 3696 // later on. 3697 'myprofile_data_import_form' => array( 3698 'display_name' => st('Data import options'), 3699 'type' => 'form', 3700 ), 3701 // Similarly, to implement this task, your profile would define a function 3702 // named myprofile_settings_form() with associated validation and submit 3703 // handlers. This form might be used to collect and save additional 3704 // information from the user that your profile needs. There are no extra 3705 // steps required for your profile to act as an "installation wizard"; you 3706 // can simply define as many tasks of type 'form' as you wish to execute, 3707 // and the forms will be presented to the user, one after another. 3708 'myprofile_settings_form' => array( 3709 'display_name' => st('Additional options'), 3710 'type' => 'form', 3711 ), 3712 // This is an example of a task that performs batch operations. To 3713 // implement this task, your profile would define a function named 3714 // myprofile_batch_processing() which returns a batch API array definition 3715 // that the installer will use to execute your batch operations. Due to the 3716 // 'myprofile_needs_batch_processing' variable used here, this task will be 3717 // hidden and skipped unless your profile set it to TRUE in one of the 3718 // previous tasks. 3719 'myprofile_batch_processing' => array( 3720 'display_name' => st('Import additional data'), 3721 'display' => $myprofile_needs_batch_processing, 3722 'type' => 'batch', 3723 'run' => $myprofile_needs_batch_processing ? INSTALL_TASK_RUN_IF_NOT_COMPLETED : INSTALL_TASK_SKIP, 3724 ), 3725 // This is an example of a task that will not be displayed in the list that 3726 // the user sees. To implement this task, your profile would define a 3727 // function named myprofile_final_site_setup(), in which additional, 3728 // automated site setup operations would be performed. Since this is the 3729 // last task defined by your profile, you should also use this function to 3730 // call variable_del('myprofile_needs_batch_processing') and clean up the 3731 // variable that was used above. If you want the user to pass to the final 3732 // Drupal installation tasks uninterrupted, return no output from this 3733 // function. Otherwise, return themed output that the user will see (for 3734 // example, a confirmation page explaining that your profile's tasks are 3735 // complete, with a link to reload the current page and therefore pass on 3736 // to the final Drupal installation tasks when the user is ready to do so). 3737 'myprofile_final_site_setup' => array( 3738 ), 3739 ); 3740 return $tasks; 3741 } 3742 3743 /** 3744 * Change the page the user is sent to by drupal_goto(). 3745 * 3746 * @param $path 3747 * A Drupal path or a full URL. 3748 * @param $options 3749 * An associative array of additional URL options to pass to url(). 3750 * @param $http_response_code 3751 * The HTTP status code to use for the redirection. See drupal_goto() for more 3752 * information. 3753 */ 3754 function hook_drupal_goto_alter(&$path, &$options, &$http_response_code) { 3755 // A good addition to misery module. 3756 $http_response_code = 500; 3757 } 3758 3759 /** 3760 * Alter XHTML HEAD tags before they are rendered by drupal_get_html_head(). 3761 * 3762 * Elements available to be altered are only those added using 3763 * drupal_add_html_head_link() or drupal_add_html_head(). CSS and JS files 3764 * are handled using drupal_add_css() and drupal_add_js(), so the head links 3765 * for those files will not appear in the $head_elements array. 3766 * 3767 * @param $head_elements 3768 * An array of renderable elements. Generally the values of the #attributes 3769 * array will be the most likely target for changes. 3770 */ 3771 function hook_html_head_alter(&$head_elements) { 3772 foreach ($head_elements as $key => $element) { 3773 if (isset($element['#attributes']['rel']) && $element['#attributes']['rel'] == 'canonical') { 3774 // I want a custom canonical URL. 3775 $head_elements[$key]['#attributes']['href'] = mymodule_canonical_url(); 3776 } 3777 } 3778 } 3779 3780 /** 3781 * Alter the full list of installation tasks. 3782 * 3783 * @param $tasks 3784 * An array of all available installation tasks, including those provided by 3785 * Drupal core. You can modify this array to change or replace any part of 3786 * the Drupal installation process that occurs after the installation profile 3787 * is selected. 3788 * @param $install_state 3789 * An array of information about the current installation state. 3790 */ 3791 function hook_install_tasks_alter(&$tasks, $install_state) { 3792 // Replace the "Choose language" installation task provided by Drupal core 3793 // with a custom callback function defined by this installation profile. 3794 $tasks['install_select_locale']['function'] = 'myprofile_locale_selection'; 3795 } 3796 3797 /** 3798 * Alter MIME type mappings used to determine MIME type from a file extension. 3799 * 3800 * This hook is run when file_mimetype_mapping() is called. It is used to 3801 * allow modules to add to or modify the default mapping from 3802 * file_default_mimetype_mapping(). 3803 * 3804 * @param $mapping 3805 * An array of mimetypes correlated to the extensions that relate to them. 3806 * The array has 'mimetypes' and 'extensions' elements, each of which is an 3807 * array. 3808 * 3809 * @see file_default_mimetype_mapping() 3810 */ 3811 function hook_file_mimetype_mapping_alter(&$mapping) { 3812 // Add new MIME type 'drupal/info'. 3813 $mapping['mimetypes']['example_info'] = 'drupal/info'; 3814 // Add new extension '.info' and map it to the 'drupal/info' MIME type. 3815 $mapping['extensions']['info'] = 'example_info'; 3816 // Override existing extension mapping for '.ogg' files. 3817 $mapping['extensions']['ogg'] = 189; 3818 } 3819 3820 /** 3821 * Declares information about actions. 3822 * 3823 * Any module can define actions, and then call actions_do() to make those 3824 * actions happen in response to events. The trigger module provides a user 3825 * interface for associating actions with module-defined triggers, and it makes 3826 * sure the core triggers fire off actions when their events happen. 3827 * 3828 * An action consists of two or three parts: 3829 * - an action definition (returned by this hook) 3830 * - a function which performs the action (which by convention is named 3831 * MODULE_description-of-function_action) 3832 * - an optional form definition function that defines a configuration form 3833 * (which has the name of the action function with '_form' appended to it.) 3834 * 3835 * The action function takes two to four arguments, which come from the input 3836 * arguments to actions_do(). 3837 * 3838 * @return 3839 * An associative array of action descriptions. The keys of the array 3840 * are the names of the action functions, and each corresponding value 3841 * is an associative array with the following key-value pairs: 3842 * - 'type': The type of object this action acts upon. Core actions have types 3843 * 'node', 'user', 'comment', and 'system'. 3844 * - 'label': The human-readable name of the action, which should be passed 3845 * through the t() function for translation. 3846 * - 'configurable': If FALSE, then the action doesn't require any extra 3847 * configuration. If TRUE, then your module must define a form function with 3848 * the same name as the action function with '_form' appended (e.g., the 3849 * form for 'node_assign_owner_action' is 'node_assign_owner_action_form'.) 3850 * This function takes $context as its only parameter, and is paired with 3851 * the usual _submit function, and possibly a _validate function. 3852 * - 'triggers': An array of the events (that is, hooks) that can trigger this 3853 * action. For example: array('node_insert', 'user_update'). You can also 3854 * declare support for any trigger by returning array('any') for this value. 3855 * - 'behavior': (optional) A machine-readable array of behaviors of this 3856 * action, used to signal additionally required actions that may need to be 3857 * triggered. Currently recognized behaviors by Trigger module: 3858 * - 'changes_property': If an action with this behavior is assigned to a 3859 * trigger other than a "presave" hook, any save actions also assigned to 3860 * this trigger are moved later in the list. If no save action is present, 3861 * one will be added. 3862 * Modules that are processing actions (like Trigger module) should take 3863 * special care for the "presave" hook, in which case a dependent "save" 3864 * action should NOT be invoked. 3865 * 3866 * @ingroup actions 3867 */ 3868 function hook_action_info() { 3869 return array( 3870 'comment_unpublish_action' => array( 3871 'type' => 'comment', 3872 'label' => t('Unpublish comment'), 3873 'configurable' => FALSE, 3874 'behavior' => array('changes_property'), 3875 'triggers' => array('comment_presave', 'comment_insert', 'comment_update'), 3876 ), 3877 'comment_unpublish_by_keyword_action' => array( 3878 'type' => 'comment', 3879 'label' => t('Unpublish comment containing keyword(s)'), 3880 'configurable' => TRUE, 3881 'behavior' => array('changes_property'), 3882 'triggers' => array('comment_presave', 'comment_insert', 'comment_update'), 3883 ), 3884 'comment_save_action' => array( 3885 'type' => 'comment', 3886 'label' => t('Save comment'), 3887 'configurable' => FALSE, 3888 'triggers' => array('comment_insert', 'comment_update'), 3889 ), 3890 ); 3891 } 3892 3893 /** 3894 * Executes code after an action is deleted. 3895 * 3896 * @param $aid 3897 * The action ID. 3898 */ 3899 function hook_actions_delete($aid) { 3900 db_delete('actions_assignments') 3901 ->condition('aid', $aid) 3902 ->execute(); 3903 } 3904 3905 /** 3906 * Alters the actions declared by another module. 3907 * 3908 * Called by actions_list() to allow modules to alter the return values from 3909 * implementations of hook_action_info(). 3910 * 3911 * @see trigger_example_action_info_alter() 3912 */ 3913 function hook_action_info_alter(&$actions) { 3914 $actions['node_unpublish_action']['label'] = t('Unpublish and remove from public view.'); 3915 } 3916 3917 /** 3918 * Declare archivers to the system. 3919 * 3920 * An archiver is a class that is able to package and unpackage one or more files 3921 * into a single possibly compressed file. Common examples of such files are 3922 * zip files and tar.gz files. All archiver classes must implement 3923 * ArchiverInterface. 3924 * 3925 * Each entry should be keyed on a unique value, and specify three 3926 * additional keys: 3927 * - class: The name of the PHP class for this archiver. 3928 * - extensions: An array of file extensions that this archiver supports. 3929 * - weight: This optional key specifies the weight of this archiver. 3930 * When mapping file extensions to archivers, the first archiver by 3931 * weight found that supports the requested extension will be used. 3932 * 3933 * @see hook_archiver_info_alter() 3934 */ 3935 function hook_archiver_info() { 3936 return array( 3937 'tar' => array( 3938 'class' => 'ArchiverTar', 3939 'extensions' => array('tar', 'tar.gz', 'tar.bz2'), 3940 ), 3941 ); 3942 } 3943 3944 /** 3945 * Alter archiver information declared by other modules. 3946 * 3947 * See hook_archiver_info() for a description of archivers and the archiver 3948 * information structure. 3949 * 3950 * @param $info 3951 * Archiver information to alter (return values from hook_archiver_info()). 3952 */ 3953 function hook_archiver_info_alter(&$info) { 3954 $info['tar']['extensions'][] = 'tgz'; 3955 } 3956 3957 /** 3958 * Define additional date types. 3959 * 3960 * Next to the 'long', 'medium' and 'short' date types defined in core, any 3961 * module can define additional types that can be used when displaying dates, 3962 * by implementing this hook. A date type is basically just a name for a date 3963 * format. 3964 * 3965 * Date types are used in the administration interface: a user can assign 3966 * date format types defined in hook_date_formats() to date types defined in 3967 * this hook. Once a format has been assigned by a user, the machine name of a 3968 * type can be used in the format_date() function to format a date using the 3969 * chosen formatting. 3970 * 3971 * To define a date type in a module and make sure a format has been assigned to 3972 * it, without requiring a user to visit the administrative interface, use 3973 * @code variable_set('date_format_' . $type, $format); @endcode 3974 * where $type is the machine-readable name defined here, and $format is a PHP 3975 * date format string. 3976 * 3977 * To avoid namespace collisions with date types defined by other modules, it is 3978 * recommended that each date type starts with the module name. A date type 3979 * can consist of letters, numbers and underscores. 3980 * 3981 * @return 3982 * An array of date types where the keys are the machine-readable names and 3983 * the values are the human-readable labels. 3984 * 3985 * @see hook_date_formats() 3986 * @see format_date() 3987 */ 3988 function hook_date_format_types() { 3989 // Define the core date format types. 3990 return array( 3991 'long' => t('Long'), 3992 'medium' => t('Medium'), 3993 'short' => t('Short'), 3994 ); 3995 } 3996 3997 /** 3998 * Modify existing date types. 3999 * 4000 * Allows other modules to modify existing date types like 'long'. Called by 4001 * _system_date_format_types_build(). For instance, A module may use this hook 4002 * to apply settings across all date types, such as locking all date types so 4003 * they appear to be provided by the system. 4004 * 4005 * @param $types 4006 * A list of date types. Each date type is keyed by the machine-readable name 4007 * and the values are associative arrays containing: 4008 * - is_new: Set to FALSE to override previous settings. 4009 * - module: The name of the module that created the date type. 4010 * - type: The machine-readable date type name. 4011 * - title: The human-readable date type name. 4012 * - locked: Specifies that the date type is system-provided. 4013 */ 4014 function hook_date_format_types_alter(&$types) { 4015 foreach ($types as $name => $type) { 4016 $types[$name]['locked'] = 1; 4017 } 4018 } 4019 4020 /** 4021 * Define additional date formats. 4022 * 4023 * This hook is used to define the PHP date format strings that can be assigned 4024 * to date types in the administrative interface. A module can provide date 4025 * format strings for the core-provided date types ('long', 'medium', and 4026 * 'short'), or for date types defined in hook_date_format_types() by itself 4027 * or another module. 4028 * 4029 * Since date formats can be locale-specific, you can specify the locales that 4030 * each date format string applies to. There may be more than one locale for a 4031 * format. There may also be more than one format for the same locale. For 4032 * example d/m/Y and Y/m/d work equally well in some locales. You may wish to 4033 * define some additional date formats that aren't specific to any one locale, 4034 * for example, "Y m". For these cases, the 'locales' component of the return 4035 * value should be omitted. 4036 * 4037 * Providing a date format here does not normally assign the format to be 4038 * used with the associated date type -- a user has to choose a format for each 4039 * date type in the administrative interface. There is one exception: locale 4040 * initialization chooses a locale-specific format for the three core-provided 4041 * types (see locale_get_localized_date_format() for details). If your module 4042 * needs to ensure that a date type it defines has a format associated with it, 4043 * call @code variable_set('date_format_' . $type, $format); @endcode 4044 * where $type is the machine-readable name defined in hook_date_format_types(), 4045 * and $format is a PHP date format string. 4046 * 4047 * @return 4048 * A list of date formats to offer as choices in the administrative 4049 * interface. Each date format is a keyed array consisting of three elements: 4050 * - 'type': The date type name that this format can be used with, as 4051 * declared in an implementation of hook_date_format_types(). 4052 * - 'format': A PHP date format string to use when formatting dates. It 4053 * can contain any of the formatting options described at 4054 * http://php.net/manual/en/function.date.php 4055 * - 'locales': (optional) An array of 2 and 5 character locale codes, 4056 * defining which locales this format applies to (for example, 'en', 4057 * 'en-us', etc.). If your date format is not language-specific, leave this 4058 * array empty. 4059 * 4060 * @see hook_date_format_types() 4061 */ 4062 function hook_date_formats() { 4063 return array( 4064 array( 4065 'type' => 'mymodule_extra_long', 4066 'format' => 'l jS F Y H:i:s e', 4067 'locales' => array('en-ie'), 4068 ), 4069 array( 4070 'type' => 'mymodule_extra_long', 4071 'format' => 'l jS F Y h:i:sa', 4072 'locales' => array('en', 'en-us'), 4073 ), 4074 array( 4075 'type' => 'short', 4076 'format' => 'F Y', 4077 'locales' => array(), 4078 ), 4079 ); 4080 } 4081 4082 /** 4083 * Alter date formats declared by another module. 4084 * 4085 * Called by _system_date_format_types_build() to allow modules to alter the 4086 * return values from implementations of hook_date_formats(). 4087 */ 4088 function hook_date_formats_alter(&$formats) { 4089 foreach ($formats as $id => $format) { 4090 $formats[$id]['locales'][] = 'en-ca'; 4091 } 4092 } 4093 4094 /** 4095 * Alters the delivery callback used to send the result of the page callback to the browser. 4096 * 4097 * Called by drupal_deliver_page() to allow modules to alter how the 4098 * page is delivered to the browser. 4099 * 4100 * This hook is intended for altering the delivery callback based on 4101 * information unrelated to the path of the page accessed. For example, 4102 * it can be used to set the delivery callback based on a HTTP request 4103 * header (as shown in the code sample). To specify a delivery callback 4104 * based on path information, use hook_menu() or hook_menu_alter(). 4105 * 4106 * This hook can also be used as an API function that can be used to explicitly 4107 * set the delivery callback from some other function. For example, for a module 4108 * named MODULE: 4109 * @code 4110 * function MODULE_page_delivery_callback_alter(&$callback, $set = FALSE) { 4111 * static $stored_callback; 4112 * if ($set) { 4113 * $stored_callback = $callback; 4114 * } 4115 * elseif (isset($stored_callback)) { 4116 * $callback = $stored_callback; 4117 * } 4118 * } 4119 * function SOMEWHERE_ELSE() { 4120 * $desired_delivery_callback = 'foo'; 4121 * MODULE_page_delivery_callback_alter($desired_delivery_callback, TRUE); 4122 * } 4123 * @endcode 4124 * 4125 * @param $callback 4126 * The name of a function. 4127 * 4128 * @see drupal_deliver_page() 4129 */ 4130 function hook_page_delivery_callback_alter(&$callback) { 4131 // jQuery sets a HTTP_X_REQUESTED_WITH header of 'XMLHttpRequest'. 4132 // If a page would normally be delivered as an html page, and it is called 4133 // from jQuery, deliver it instead as an Ajax response. 4134 if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' && $callback == 'drupal_deliver_html_page') { 4135 $callback = 'ajax_deliver'; 4136 } 4137 } 4138 4139 /** 4140 * Alters theme operation links. 4141 * 4142 * @param $theme_groups 4143 * An associative array containing groups of themes. 4144 * 4145 * @see system_themes_page() 4146 */ 4147 function hook_system_themes_page_alter(&$theme_groups) { 4148 foreach ($theme_groups as $state => &$group) { 4149 foreach ($theme_groups[$state] as &$theme) { 4150 // Add a foo link to each list of theme operations. 4151 $theme->operations[] = array( 4152 'title' => t('Foo'), 4153 'href' => 'admin/appearance/foo', 4154 'query' => array('theme' => $theme->name) 4155 ); 4156 } 4157 } 4158 } 4159 4160 /** 4161 * Alters inbound URL requests. 4162 * 4163 * @param $path 4164 * The path being constructed, which, if a path alias, has been resolved to a 4165 * Drupal path by the database, and which also may have been altered by other 4166 * modules before this one. 4167 * @param $original_path 4168 * The original path, before being checked for path aliases or altered by any 4169 * modules. 4170 * @param $path_language 4171 * The language of the path. 4172 * 4173 * @see drupal_get_normal_path() 4174 */ 4175 function hook_url_inbound_alter(&$path, $original_path, $path_language) { 4176 // Create the path user/me/edit, which allows a user to edit their account. 4177 if (preg_match('|^user/me/edit(/.*)?|', $path, $matches)) { 4178 global $user; 4179 $path = 'user/' . $user->uid . '/edit' . $matches[1]; 4180 } 4181 } 4182 4183 /** 4184 * Alters outbound URLs. 4185 * 4186 * @param $path 4187 * The outbound path to alter, not adjusted for path aliases yet. It won't be 4188 * adjusted for path aliases until all modules are finished altering it, thus 4189 * being consistent with hook_url_inbound_alter(), which adjusts for all path 4190 * aliases before allowing modules to alter it. This may have been altered by 4191 * other modules before this one. 4192 * @param $options 4193 * A set of URL options for the URL so elements such as a fragment or a query 4194 * string can be added to the URL. 4195 * @param $original_path 4196 * The original path, before being altered by any modules. 4197 * 4198 * @see url() 4199 */ 4200 function hook_url_outbound_alter(&$path, &$options, $original_path) { 4201 // Use an external RSS feed rather than the Drupal one. 4202 if ($path == 'rss.xml') { 4203 $path = 'http://example.com/rss.xml'; 4204 $options['external'] = TRUE; 4205 } 4206 4207 // Instead of pointing to user/[uid]/edit, point to user/me/edit. 4208 if (preg_match('|^user/([0-9]*)/edit(/.*)?|', $path, $matches)) { 4209 global $user; 4210 if ($user->uid == $matches[1]) { 4211 $path = 'user/me/edit' . $matches[2]; 4212 } 4213 } 4214 } 4215 4216 /** 4217 * Alter the username that is displayed for a user. 4218 * 4219 * Called by format_username() to allow modules to alter the username that's 4220 * displayed. Can be used to ensure user privacy in situations where 4221 * $account->name is too revealing. 4222 * 4223 * @param $name 4224 * The string that format_username() will return. 4225 * 4226 * @param $account 4227 * The account object passed to format_username(). 4228 * 4229 * @see format_username() 4230 */ 4231 function hook_username_alter(&$name, $account) { 4232 // Display the user's uid instead of name. 4233 if (isset($account->uid)) { 4234 $name = t('User !uid', array('!uid' => $account->uid)); 4235 } 4236 } 4237 4238 /** 4239 * Provide replacement values for placeholder tokens. 4240 * 4241 * This hook is invoked when someone calls token_replace(). That function first 4242 * scans the text for [type:token] patterns, and splits the needed tokens into 4243 * groups by type. Then hook_tokens() is invoked on each token-type group, 4244 * allowing your module to respond by providing replacement text for any of 4245 * the tokens in the group that your module knows how to process. 4246 * 4247 * A module implementing this hook should also implement hook_token_info() in 4248 * order to list its available tokens on editing screens. 4249 * 4250 * @param $type 4251 * The machine-readable name of the type (group) of token being replaced, such 4252 * as 'node', 'user', or another type defined by a hook_token_info() 4253 * implementation. 4254 * @param $tokens 4255 * An array of tokens to be replaced. The keys are the machine-readable token 4256 * names, and the values are the raw [type:token] strings that appeared in the 4257 * original text. 4258 * @param $data 4259 * (optional) An associative array of data objects to be used when generating 4260 * replacement values, as supplied in the $data parameter to token_replace(). 4261 * @param $options 4262 * (optional) An associative array of options for token replacement; see 4263 * token_replace() for possible values. 4264 * 4265 * @return 4266 * An associative array of replacement values, keyed by the raw [type:token] 4267 * strings from the original text. 4268 * 4269 * @see hook_token_info() 4270 * @see hook_tokens_alter() 4271 */ 4272 function hook_tokens($type, $tokens, array $data = array(), array $options = array()) { 4273 $url_options = array('absolute' => TRUE); 4274 if (isset($options['language'])) { 4275 $url_options['language'] = $options['language']; 4276 $language_code = $options['language']->language; 4277 } 4278 else { 4279 $language_code = NULL; 4280 } 4281 $sanitize = !empty($options['sanitize']); 4282 4283 $replacements = array(); 4284 4285 if ($type == 'node' && !empty($data['node'])) { 4286 $node = $data['node']; 4287 4288 foreach ($tokens as $name => $original) { 4289 switch ($name) { 4290 // Simple key values on the node. 4291 case 'nid': 4292 $replacements[$original] = $node->nid; 4293 break; 4294 4295 case 'title': 4296 $replacements[$original] = $sanitize ? check_plain($node->title) : $node->title; 4297 break; 4298 4299 case 'edit-url': 4300 $replacements[$original] = url('node/' . $node->nid . '/edit', $url_options); 4301 break; 4302 4303 // Default values for the chained tokens handled below. 4304 case 'author': 4305 $name = ($node->uid == 0) ? variable_get('anonymous', t('Anonymous')) : $node->name; 4306 $replacements[$original] = $sanitize ? filter_xss($name) : $name; 4307 break; 4308 4309 case 'created': 4310 $replacements[$original] = format_date($node->created, 'medium', '', NULL, $language_code); 4311 break; 4312 } 4313 } 4314 4315 if ($author_tokens = token_find_with_prefix($tokens, 'author')) { 4316 $author = user_load($node->uid); 4317 $replacements += token_generate('user', $author_tokens, array('user' => $author), $options); 4318 } 4319 4320 if ($created_tokens = token_find_with_prefix($tokens, 'created')) { 4321 $replacements += token_generate('date', $created_tokens, array('date' => $node->created), $options); 4322 } 4323 } 4324 4325 return $replacements; 4326 } 4327 4328 /** 4329 * Alter replacement values for placeholder tokens. 4330 * 4331 * @param $replacements 4332 * An associative array of replacements returned by hook_tokens(). 4333 * @param $context 4334 * The context in which hook_tokens() was called. An associative array with 4335 * the following keys, which have the same meaning as the corresponding 4336 * parameters of hook_tokens(): 4337 * - 'type' 4338 * - 'tokens' 4339 * - 'data' 4340 * - 'options' 4341 * 4342 * @see hook_tokens() 4343 */ 4344 function hook_tokens_alter(array &$replacements, array $context) { 4345 $options = $context['options']; 4346 4347 if (isset($options['language'])) { 4348 $url_options['language'] = $options['language']; 4349 $language_code = $options['language']->language; 4350 } 4351 else { 4352 $language_code = NULL; 4353 } 4354 $sanitize = !empty($options['sanitize']); 4355 4356 if ($context['type'] == 'node' && !empty($context['data']['node'])) { 4357 $node = $context['data']['node']; 4358 4359 // Alter the [node:title] token, and replace it with the rendered content 4360 // of a field (field_title). 4361 if (isset($context['tokens']['title'])) { 4362 $title = field_view_field('node', $node, 'field_title', 'default', $language_code); 4363 $replacements[$context['tokens']['title']] = drupal_render($title); 4364 } 4365 } 4366 } 4367 4368 /** 4369 * Provide information about available placeholder tokens and token types. 4370 * 4371 * Tokens are placeholders that can be put into text by using the syntax 4372 * [type:token], where type is the machine-readable name of a token type, and 4373 * token is the machine-readable name of a token within this group. This hook 4374 * provides a list of types and tokens to be displayed on text editing screens, 4375 * so that people editing text can see what their token options are. 4376 * 4377 * The actual token replacement is done by token_replace(), which invokes 4378 * hook_tokens(). Your module will need to implement that hook in order to 4379 * generate token replacements from the tokens defined here. 4380 * 4381 * @return 4382 * An associative array of available tokens and token types. The outer array 4383 * has two components: 4384 * - types: An associative array of token types (groups). Each token type is 4385 * an associative array with the following components: 4386 * - name: The translated human-readable short name of the token type. 4387 * - description: A translated longer description of the token type. 4388 * - needs-data: The type of data that must be provided to token_replace() 4389 * in the $data argument (i.e., the key name in $data) in order for tokens 4390 * of this type to be used in the $text being processed. For instance, if 4391 * the token needs a node object, 'needs-data' should be 'node', and to 4392 * use this token in token_replace(), the caller needs to supply a node 4393 * object as $data['node']. Some token data can also be supplied 4394 * indirectly; for instance, a node object in $data supplies a user object 4395 * (the author of the node), allowing user tokens to be used when only 4396 * a node data object is supplied. 4397 * - tokens: An associative array of tokens. The outer array is keyed by the 4398 * group name (the same key as in the types array). Within each group of 4399 * tokens, each token item is keyed by the machine name of the token, and 4400 * each token item has the following components: 4401 * - name: The translated human-readable short name of the token. 4402 * - description: A translated longer description of the token. 4403 * - type (optional): A 'needs-data' data type supplied by this token, which 4404 * should match a 'needs-data' value from another token type. For example, 4405 * the node author token provides a user object, which can then be used 4406 * for token replacement data in token_replace() without having to supply 4407 * a separate user object. 4408 * 4409 * @see hook_token_info_alter() 4410 * @see hook_tokens() 4411 */ 4412 function hook_token_info() { 4413 $type = array( 4414 'name' => t('Nodes'), 4415 'description' => t('Tokens related to individual nodes.'), 4416 'needs-data' => 'node', 4417 ); 4418 4419 // Core tokens for nodes. 4420 $node['nid'] = array( 4421 'name' => t("Node ID"), 4422 'description' => t("The unique ID of the node."), 4423 ); 4424 $node['title'] = array( 4425 'name' => t("Title"), 4426 'description' => t("The title of the node."), 4427 ); 4428 $node['edit-url'] = array( 4429 'name' => t("Edit URL"), 4430 'description' => t("The URL of the node's edit page."), 4431 ); 4432 4433 // Chained tokens for nodes. 4434 $node['created'] = array( 4435 'name' => t("Date created"), 4436 'description' => t("The date the node was posted."), 4437 'type' => 'date', 4438 ); 4439 $node['author'] = array( 4440 'name' => t("Author"), 4441 'description' => t("The author of the node."), 4442 'type' => 'user', 4443 ); 4444 4445 return array( 4446 'types' => array('node' => $type), 4447 'tokens' => array('node' => $node), 4448 ); 4449 } 4450 4451 /** 4452 * Alter the metadata about available placeholder tokens and token types. 4453 * 4454 * @param $data 4455 * The associative array of token definitions from hook_token_info(). 4456 * 4457 * @see hook_token_info() 4458 */ 4459 function hook_token_info_alter(&$data) { 4460 // Modify description of node tokens for our site. 4461 $data['tokens']['node']['nid'] = array( 4462 'name' => t("Node ID"), 4463 'description' => t("The unique ID of the article."), 4464 ); 4465 $data['tokens']['node']['title'] = array( 4466 'name' => t("Title"), 4467 'description' => t("The title of the article."), 4468 ); 4469 4470 // Chained tokens for nodes. 4471 $data['tokens']['node']['created'] = array( 4472 'name' => t("Date created"), 4473 'description' => t("The date the article was posted."), 4474 'type' => 'date', 4475 ); 4476 } 4477 4478 /** 4479 * Alter batch information before a batch is processed. 4480 * 4481 * Called by batch_process() to allow modules to alter a batch before it is 4482 * processed. 4483 * 4484 * @param $batch 4485 * The associative array of batch information. See batch_set() for details on 4486 * what this could contain. 4487 * 4488 * @see batch_set() 4489 * @see batch_process() 4490 * 4491 * @ingroup batch 4492 */ 4493 function hook_batch_alter(&$batch) { 4494 // If the current page request is inside the overlay, add ?render=overlay to 4495 // the success callback URL, so that it appears correctly within the overlay. 4496 if (overlay_get_mode() == 'child') { 4497 if (isset($batch['url_options']['query'])) { 4498 $batch['url_options']['query']['render'] = 'overlay'; 4499 } 4500 else { 4501 $batch['url_options']['query'] = array('render' => 'overlay'); 4502 } 4503 } 4504 } 4505 4506 /** 4507 * Provide information on Updaters (classes that can update Drupal). 4508 * 4509 * An Updater is a class that knows how to update various parts of the Drupal 4510 * file system, for example to update modules that have newer releases, or to 4511 * install a new theme. 4512 * 4513 * @return 4514 * An associative array of information about the updater(s) being provided. 4515 * This array is keyed by a unique identifier for each updater, and the 4516 * values are subarrays that can contain the following keys: 4517 * - class: The name of the PHP class which implements this updater. 4518 * - name: Human-readable name of this updater. 4519 * - weight: Controls what order the Updater classes are consulted to decide 4520 * which one should handle a given task. When an update task is being run, 4521 * the system will loop through all the Updater classes defined in this 4522 * registry in weight order and let each class respond to the task and 4523 * decide if each Updater wants to handle the task. In general, this 4524 * doesn't matter, but if you need to override an existing Updater, make 4525 * sure your Updater has a lighter weight so that it comes first. 4526 * 4527 * @see drupal_get_updaters() 4528 * @see hook_updater_info_alter() 4529 */ 4530 function hook_updater_info() { 4531 return array( 4532 'module' => array( 4533 'class' => 'ModuleUpdater', 4534 'name' => t('Update modules'), 4535 'weight' => 0, 4536 ), 4537 'theme' => array( 4538 'class' => 'ThemeUpdater', 4539 'name' => t('Update themes'), 4540 'weight' => 0, 4541 ), 4542 ); 4543 } 4544 4545 /** 4546 * Alter the Updater information array. 4547 * 4548 * An Updater is a class that knows how to update various parts of the Drupal 4549 * file system, for example to update modules that have newer releases, or to 4550 * install a new theme. 4551 * 4552 * @param array $updaters 4553 * Associative array of updaters as defined through hook_updater_info(). 4554 * Alter this array directly. 4555 * 4556 * @see drupal_get_updaters() 4557 * @see hook_updater_info() 4558 */ 4559 function hook_updater_info_alter(&$updaters) { 4560 // Adjust weight so that the theme Updater gets a chance to handle a given 4561 // update task before module updaters. 4562 $updaters['theme']['weight'] = -1; 4563 } 4564 4565 /** 4566 * Alter the default country list. 4567 * 4568 * @param $countries 4569 * The associative array of countries keyed by ISO 3166-1 country code. 4570 * 4571 * @see country_get_list() 4572 * @see _country_get_predefined_list() 4573 */ 4574 function hook_countries_alter(&$countries) { 4575 // Elbonia is now independent, so add it to the country list. 4576 $countries['EB'] = 'Elbonia'; 4577 } 4578 4579 /** 4580 * Control site status before menu dispatching. 4581 * 4582 * The hook is called after checking whether the site is offline but before 4583 * the current router item is retrieved and executed by 4584 * menu_execute_active_handler(). If the site is in offline mode, 4585 * $menu_site_status is set to MENU_SITE_OFFLINE. 4586 * 4587 * @param $menu_site_status 4588 * Supported values are MENU_SITE_OFFLINE, MENU_ACCESS_DENIED, 4589 * MENU_NOT_FOUND and MENU_SITE_ONLINE. Any other value than 4590 * MENU_SITE_ONLINE will skip the default menu handling system and be passed 4591 * for delivery to drupal_deliver_page() with a NULL 4592 * $default_delivery_callback. 4593 * @param $path 4594 * Contains the system path that is going to be loaded. This is read only, 4595 * use hook_url_inbound_alter() to change the path. 4596 */ 4597 function hook_menu_site_status_alter(&$menu_site_status, $path) { 4598 // Allow access to my_module/authentication even if site is in offline mode. 4599 if ($menu_site_status == MENU_SITE_OFFLINE && user_is_anonymous() && $path == 'my_module/authentication') { 4600 $menu_site_status = MENU_SITE_ONLINE; 4601 } 4602 } 4603 4604 /** 4605 * Register information about FileTransfer classes provided by a module. 4606 * 4607 * The FileTransfer class allows transferring files over a specific type of 4608 * connection. Core provides classes for FTP and SSH. Contributed modules are 4609 * free to extend the FileTransfer base class to add other connection types, 4610 * and if these classes are registered via hook_filetransfer_info(), those 4611 * connection types will be available to site administrators using the Update 4612 * manager when they are redirected to the authorize.php script to authorize 4613 * the file operations. 4614 * 4615 * @return array 4616 * Nested array of information about FileTransfer classes. Each key is a 4617 * FileTransfer type (not human readable, used for form elements and 4618 * variable names, etc), and the values are subarrays that define properties 4619 * of that type. The keys in each subarray are: 4620 * - 'title': Required. The human-readable name of the connection type. 4621 * - 'class': Required. The name of the FileTransfer class. The constructor 4622 * will always be passed the full path to the root of the site that should 4623 * be used to restrict where file transfer operations can occur (the $jail) 4624 * and an array of settings values returned by the settings form. 4625 * - 'file': Required. The include file containing the FileTransfer class. 4626 * This should be a separate .inc file, not just the .module file, so that 4627 * the minimum possible code is loaded when authorize.php is running. 4628 * - 'file path': Optional. The directory (relative to the Drupal root) 4629 * where the include file lives. If not defined, defaults to the base 4630 * directory of the module implementing the hook. 4631 * - 'weight': Optional. Integer weight used for sorting connection types on 4632 * the authorize.php form. 4633 * 4634 * @see FileTransfer 4635 * @see authorize.php 4636 * @see hook_filetransfer_info_alter() 4637 * @see drupal_get_filetransfer_info() 4638 */ 4639 function hook_filetransfer_info() { 4640 $info['sftp'] = array( 4641 'title' => t('SFTP (Secure FTP)'), 4642 'file' => 'sftp.filetransfer.inc', 4643 'class' => 'FileTransferSFTP', 4644 'weight' => 10, 4645 ); 4646 return $info; 4647 } 4648 4649 /** 4650 * Alter the FileTransfer class registry. 4651 * 4652 * @param array $filetransfer_info 4653 * Reference to a nested array containing information about the FileTransfer 4654 * class registry. 4655 * 4656 * @see hook_filetransfer_info() 4657 */ 4658 function hook_filetransfer_info_alter(&$filetransfer_info) { 4659 if (variable_get('paranoia', FALSE)) { 4660 // Remove the FTP option entirely. 4661 unset($filetransfer_info['ftp']); 4662 // Make sure the SSH option is listed first. 4663 $filetransfer_info['ssh']['weight'] = -10; 4664 } 4665 } 4666 4667 /** 4668 * @} End of "addtogroup hooks". 4669 */ 4670 4671 /** 4672 * @defgroup update_api Update versions of API functions 4673 * @{ 4674 * Functions that are similar to normal API functions, but do not invoke hooks. 4675 * 4676 * These simplified versions of core API functions are provided for use by 4677 * update functions (hook_update_N() implementations). 4678 * 4679 * During database updates the schema of any module could be out of date. For 4680 * this reason, caution is needed when using any API function within an update 4681 * function - particularly CRUD functions, functions that depend on the schema 4682 * (for example by using drupal_write_record()), and any functions that invoke 4683 * hooks. 4684 * 4685 * Instead, a simplified utility function should be used. If a utility version 4686 * of the API function you require does not already exist, then you should 4687 * create a new function. The new utility function should be named 4688 * _update_N_mymodule_my_function(). N is the schema version the function acts 4689 * on (the schema version is the number N from the hook_update_N() 4690 * implementation where this schema was introduced, or a number following the 4691 * same numbering scheme), and mymodule_my_function is the name of the original 4692 * API function including the module's name. 4693 * 4694 * Examples: 4695 * - _update_6000_mymodule_save(): This function performs a save operation 4696 * without invoking any hooks using the 6.x schema. 4697 * - _update_7000_mymodule_save(): This function performs the same save 4698 * operation using the 7.x schema. 4699 * 4700 * The utility function should not invoke any hooks, and should perform database 4701 * operations using functions from the 4702 * @link database Database abstraction layer, @endlink 4703 * like db_insert(), db_update(), db_delete(), db_query(), and so on. 4704 * 4705 * If a change to the schema necessitates a change to the utility function, a 4706 * new function should be created with a name based on the version of the schema 4707 * it acts on. See _update_7000_bar_get_types() and _update_7001_bar_get_types() 4708 * in the code examples that follow. 4709 * 4710 * For example, foo.install could contain: 4711 * @code 4712 * function foo_update_dependencies() { 4713 * // foo_update_7010() needs to run after bar_update_7000(). 4714 * $dependencies['foo'][7010] = array( 4715 * 'bar' => 7000, 4716 * ); 4717 * 4718 * // foo_update_7036() needs to run after bar_update_7001(). 4719 * $dependencies['foo'][7036] = array( 4720 * 'bar' => 7001, 4721 * ); 4722 * 4723 * return $dependencies; 4724 * } 4725 * 4726 * function foo_update_7000() { 4727 * // No updates have been run on the {bar_types} table yet, so this needs 4728 * // to work with the 6.x schema. 4729 * foreach (_update_6000_bar_get_types() as $type) { 4730 * // Rename a variable. 4731 * } 4732 * } 4733 * 4734 * function foo_update_7010() { 4735 * // Since foo_update_7010() is going to run after bar_update_7000(), it 4736 * // needs to operate on the new schema, not the old one. 4737 * foreach (_update_7000_bar_get_types() as $type) { 4738 * // Rename a different variable. 4739 * } 4740 * } 4741 * 4742 * function foo_update_7036() { 4743 * // This update will run after bar_update_7001(). 4744 * foreach (_update_7001_bar_get_types() as $type) { 4745 * } 4746 * } 4747 * @endcode 4748 * 4749 * And bar.install could contain: 4750 * @code 4751 * function bar_update_7000() { 4752 * // Type and bundle are confusing, so we renamed the table. 4753 * db_rename_table('bar_types', 'bar_bundles'); 4754 * } 4755 * 4756 * function bar_update_7001() { 4757 * // Database table names should be singular when possible. 4758 * db_rename_table('bar_bundles', 'bar_bundle'); 4759 * } 4760 * 4761 * function _update_6000_bar_get_types() { 4762 * db_query('SELECT * FROM {bar_types}')->fetchAll(); 4763 * } 4764 * 4765 * function _update_7000_bar_get_types() { 4766 * db_query('SELECT * FROM {bar_bundles'})->fetchAll(); 4767 * } 4768 * 4769 * function _update_7001_bar_get_types() { 4770 * db_query('SELECT * FROM {bar_bundle}')->fetchAll(); 4771 * } 4772 * @endcode 4773 * 4774 * @see hook_update_N() 4775 * @see hook_update_dependencies() 4776 */ 4777 4778 /** 4779 * @} End of "defgroup update_api". 4780 */
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
title