system.api.php 199 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
<?php

/**
 * @file
 * Hooks provided by Drupal core and the System module.
 */

/**
 * @addtogroup hooks
 * @{
 */

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
 * Defines one or more hooks that are exposed by a module.
 *
 * Normally hooks do not need to be explicitly defined. However, by declaring a
 * hook explicitly, a module may define a "group" for it. Modules that implement
 * a hook may then place their implementation in either $module.module or in
 * $module.$group.inc. If the hook is located in $module.$group.inc, then that
 * file will be automatically loaded when needed.
 * In general, hooks that are rarely invoked and/or are very large should be
 * placed in a separate include file, while hooks that are very short or very
 * frequently called should be left in the main module file so that they are
 * always available.
 *
 * @return
 *   An associative array whose keys are hook names and whose values are an
 *   associative array containing:
 *   - group: A string defining the group to which the hook belongs. The module
 *     system will determine whether a file with the name $module.$group.inc
 *     exists, and automatically load it when required.
 *
 * See system_hook_info() for all hook groups defined by Drupal core.
34
35
 *
 * @see hook_hook_info_alter().
36
37
38
39
40
41
42
43
44
45
46
 */
function hook_hook_info() {
  $hooks['token_info'] = array(
    'group' => 'tokens',
  );
  $hooks['tokens'] = array(
    'group' => 'tokens',
  );
  return $hooks;
}

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/**
 * Alter information from hook_hook_info().
 *
 * @param $hooks
 *   Information gathered by module_hook_info() from other modules'
 *   implementations of hook_hook_info(). Alter this array directly.
 *   See hook_hook_info() for information on what this may contain.
 */
function hook_hook_info_alter(&$hooks) {
  // Our module wants to completely override the core tokens, so make
  // sure the core token hooks are not found.
  $hooks['token_info']['group'] = 'mytokens';
  $hooks['tokens']['group'] = 'mytokens';
}

62
63
64
65
66
67
68
69
70
/**
 * Inform the base system and the Field API about one or more entity types.
 *
 * Inform the system about one or more entity types (i.e., object types that
 * can be loaded via entity_load() and, optionally, to which fields can be
 * attached).
 *
 * @return
 *   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
76
 *     Leave blank to use the DrupalDefaultEntityController implementation.
 *   - 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
82
83
84
 *   - field cache: (used by Field API loading and saving of field data) FALSE
 *     to disable Field API's persistent cache of field data. Only recommended
 *     if a higher level persistent cache is available for the entity type.
 *     Defaults to TRUE.
85
86
 *   - load hook: The name of the hook which should be invoked by
 *     DrupalDefaultEntityController:attachLoad(), for example 'node_load'.
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
 *   - uri callback: The name of an implementation of
 *     callback_entity_info_uri().
 *   - label callback: (optional) The name of an implementation of
 *     callback_entity_info_label(), which returns the label of the entity. The
 *     entity label is the main string associated with an entity; for example,
 *     the title of a node or the subject of a comment. If there is an entity
 *     object property that defines the label, then using the 'label' element of
 *     the 'entity keys' return value component suffices to provide this
 *     information (see below). Alternatively, specifying this callback allows
 *     more complex logic to determine the label of an entity. See also the
 *     entity_label() function, which implements this logic.
 *   - language callback: (optional) The name of an implementation of
 *     callback_entity_info_language(). In most situations, when needing to
 *     determine this value, inspecting a property named after the 'language'
 *     element of the 'entity keys' should be enough. The language callback is
 *     meant to be used primarily for temporary alterations of the property
 *     value: entity-defining modules are encouraged to always define a
104
105
106
107
108
109
 *     language property, instead of using the callback as main entity language
 *     source. In fact not having a language property defined is likely to
 *     prevent an entity from being queried by language. Moreover, given that
 *     entity_language() is not necessarily used everywhere it would be
 *     appropriate, modules implementing the language callback should be aware
 *     that this might not be always called.
110
111
 *   - fieldable: Set to TRUE if you want your entity type to accept fields
 *     being attached to it.
112
113
114
115
 *   - translation: An associative array of modules registered as field
 *     translation handlers. Array keys are the module names, array values
 *     can be any data structure the module uses to provide field translation.
 *     Any empty value disallows the module to appear as a translation handler.
116
117
 *   - entity keys: (optional) An array describing how the Field API can extract
 *     the information it needs from the objects of the type. Elements:
118
 *     - id: The name of the property that contains the primary id of the
119
120
 *       entity. Every entity object passed to the Field API must have this
 *       property and its value must be numeric.
121
 *     - revision: The name of the property that contains the revision id of
122
123
 *       the entity. The Field API assumes that all revision ids are unique
 *       across all entities of a type. This entry can be omitted if the
124
 *       entities of this type are not versionable. Defaults to an empty string.
125
 *     - bundle: The name of the property that contains the bundle name for the
126
127
128
 *       entity. The bundle name defines which set of fields are attached to
 *       the entity (e.g. what nodes call "content type"). This entry can be
 *       omitted if this entity type exposes a single bundle (all entities have
129
 *       the same collection of fields). The name of this single bundle will be
130
 *       the same as the entity type. Defaults to an empty string.
131
 *     - label: The name of the property that contains the entity label. For
132
 *       example, if the entity's label is located in $entity->subject, then
133
134
135
 *       'subject' should be specified here. If complex logic is required to
 *       build the label, a 'label callback' should be defined instead (see
 *       the 'label callback' section above for details).
136
137
138
139
140
 *     - language: The name of the property, typically 'language', that contains
 *       the language code representing the language the entity has been created
 *       in. This value may be changed when editing the entity and represents
 *       the language its textual components are supposed to have. If no
 *       language property is available, the 'language callback' may be used
141
142
 *       instead. This entry can be omitted if the entities of this type are not
 *       language-aware.
143
 *   - bundle keys: An array describing how the Field API can extract the
144
145
146
147
148
149
150
151
152
 *     information it needs from the bundle objects for this type. This entry
 *     is required if the 'path' provided in the 'bundles'/'admin' section
 *     identifies the bundle using a named menu placeholder whose loader
 *     callback returns an object (e.g., $vocabulary for taxonomy terms, or
 *     $node_type for nodes). If the path does not include the bundle, or the
 *     bundle is just a string rather than an automatically loaded object, then
 *     this can be omitted. Elements:
 *     - bundle: The name of the property of the bundle object that contains
 *       the name of the bundle object.
153
154
 *   - bundles: An array describing all bundles for this object type. Keys are
 *     bundles machine names, as found in the objects' 'bundle' property
155
156
157
158
 *     (defined in the 'entity keys' entry above). This entry can be omitted if
 *     this entity type exposes a single bundle (all entities have the same
 *     collection of fields). The name of this single bundle will be the same as
 *     the entity type. Elements:
159
 *     - label: The human-readable name of the bundle.
160
161
162
163
 *     - uri callback: Same as the 'uri callback' key documented above for the
 *       entity type, but for the bundle only. When determining the URI of an
 *       entity, if a 'uri callback' is defined for both the entity type and
 *       the bundle, the one for the bundle is used.
164
165
 *     - admin: An array of information that allows Field UI pages to attach
 *       themselves to the existing administration pages for the bundle.
166
 *       Elements:
167
168
 *       - path: the path of the bundle's main administration page, as defined
 *         in hook_menu(). If the path includes a placeholder for the bundle,
169
170
171
 *         the 'bundle argument' and 'real path' keys below are required.
 *       - bundle argument: The position of the bundle placeholder in 'path', if
 *         any.
172
173
174
175
176
 *       - real path: The actual path (no placeholder) of the bundle's main
 *         administration page. This will be used to generate links.
 *       - access callback: As in hook_menu(). 'user_access' will be assumed if
 *         no value is provided.
 *       - access arguments: As in hook_menu().
177
178
179
180
181
182
 *   - view modes: An array describing the view modes for the entity type. View
 *     modes let entities be displayed differently depending on the context.
 *     For instance, a node can be displayed differently on its own page
 *     ('full' mode), on the home page or taxonomy listings ('teaser' mode), or
 *     in an RSS feed ('rss' mode). Modules taking part in the display of the
 *     entity (notably the Field API) can adjust their behavior depending on
183
184
185
186
187
188
189
190
 *     the requested view mode. An additional 'default' view mode is available
 *     for all entity types. This view mode is not intended for actual entity
 *     display, but holds default display settings. For each available view
 *     mode, administrators can configure whether it should use its own set of
 *     field display settings, or just replicate the settings of the 'default'
 *     view mode, thus reducing the amount of display configurations to keep
 *     track of. Keys of the array are view mode names. Each view mode is
 *     described by an array with the following key/value pairs:
191
 *     - label: The human-readable name of the view mode
192
 *     - custom settings: A boolean specifying whether the view mode should by
193
194
195
196
197
 *       default use its own custom field display settings. If FALSE, entities
 *       displayed in this view mode will reuse the 'default' display settings
 *       by default (e.g. right after the module exposing the view mode is
 *       enabled), but administrators can later use the Field UI to apply custom
 *       display settings specific to the view mode.
198
199
200
 *
 * @see entity_load()
 * @see hook_entity_info_alter()
201
202
203
204
 */
function hook_entity_info() {
  $return = array(
    'node' => array(
205
      'label' => t('Node'),
206
207
      'controller class' => 'NodeController',
      'base table' => 'node',
208
      'revision table' => 'node_revision',
209
      'uri callback' => 'node_uri',
210
      'fieldable' => TRUE,
211
212
213
      'translation' => array(
        'locale' => TRUE,
      ),
214
      'entity keys' => array(
215
216
217
        'id' => 'nid',
        'revision' => 'vid',
        'bundle' => 'type',
218
        'language' => 'language',
219
220
221
222
223
224
225
      ),
      'bundle keys' => array(
        'bundle' => 'type',
      ),
      'bundles' => array(),
      'view modes' => array(
        'full' => array(
226
227
          'label' => t('Full content'),
          'custom settings' => FALSE,
228
229
230
        ),
        'teaser' => array(
          'label' => t('Teaser'),
231
          'custom settings' => TRUE,
232
233
234
        ),
        'rss' => array(
          'label' => t('RSS'),
235
          'custom settings' => FALSE,
236
237
        ),
      ),
238
239
    ),
  );
240
241
242
243
244
245
246

  // Search integration is provided by node.module, so search-related
  // view modes for nodes are defined here and not in search.module.
  if (module_exists('search')) {
    $return['node']['view modes'] += array(
      'search_index' => array(
        'label' => t('Search index'),
247
        'custom settings' => FALSE,
248
249
      ),
      'search_result' => array(
250
        'label' => t('Search result highlighting input'),
251
        'custom settings' => FALSE,
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
      ),
    );
  }

  // Bundles must provide a human readable name so we can create help and error
  // messages, and the path to attach Field admin pages to.
  foreach (node_type_get_names() as $type => $name) {
    $return['node']['bundles'][$type] = array(
      'label' => $name,
      'admin' => array(
        'path' => 'admin/structure/types/manage/%node_type',
        'real path' => 'admin/structure/types/manage/' . str_replace('_', '-', $type),
        'bundle argument' => 4,
        'access arguments' => array('administer content types'),
      ),
    );
  }

270
271
272
273
274
275
276
277
278
279
280
281
  return $return;
}

/**
 * Alter the entity info.
 *
 * Modules may implement this hook to alter the information that defines an
 * entity. All properties that are available in hook_entity_info() can be
 * altered here.
 *
 * @param $entity_info
 *   The entity info array, keyed by entity name.
282
283
 *
 * @see hook_entity_info()
284
285
286
287
288
289
290
 */
function hook_entity_info_alter(&$entity_info) {
  // Set the controller class for nodes to an alternate implementation of the
  // DrupalEntityController interface.
  $entity_info['node']['controller class'] = 'MyCustomNodeController';
}

291
292
293
294
295
296
297
298
299
300
301
302
303
/**
 * Act on entities when loaded.
 *
 * This is a generic load hook called for all entity types loaded via the
 * entity API.
 *
 * @param $entities
 *   The entities keyed by entity ID.
 * @param $type
 *   The type of entities being loaded (i.e. node, user, comment).
 */
function hook_entity_load($entities, $type) {
  foreach ($entities as $entity) {
304
    $entity->foo = mymodule_add_something($entity, $type);
305
306
307
  }
}

308
309
310
311
312
313
314
315
316
317
318
319
/**
 * Act on an entity before it is about to be created or updated.
 *
 * @param $entity
 *   The entity object.
 * @param $type
 *   The type of entity being saved (i.e. node, user, comment).
 */
function hook_entity_presave($entity, $type) {
  $entity->changed = REQUEST_TIME;
}

320
321
322
323
324
325
326
327
328
/**
 * Act on entities when inserted.
 *
 * @param $entity
 *   The entity object.
 * @param $type
 *   The type of entity being inserted (i.e. node, user, comment).
 */
function hook_entity_insert($entity, $type) {
329
330
  // Insert the new entity into a fictional table of all entities.
  $info = entity_get_info($type);
331
  list($id) = entity_extract_ids($type, $entity);
332
333
334
335
336
337
338
339
  db_insert('example_entity')
    ->fields(array(
      'type' => $type,
      'id' => $id,
      'created' => REQUEST_TIME,
      'updated' => REQUEST_TIME,
    ))
    ->execute();
340
341
342
343
344
345
346
347
348
349
350
}

/**
 * Act on entities when updated.
 *
 * @param $entity
 *   The entity object.
 * @param $type
 *   The type of entity being updated (i.e. node, user, comment).
 */
function hook_entity_update($entity, $type) {
351
352
  // Update the entity's entry in a fictional table of all entities.
  $info = entity_get_info($type);
353
  list($id) = entity_extract_ids($type, $entity);
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
  db_update('example_entity')
    ->fields(array(
      'updated' => REQUEST_TIME,
    ))
    ->condition('type', $type)
    ->condition('id', $id)
    ->execute();
}

/**
 * Act on entities when deleted.
 *
 * @param $entity
 *   The entity object.
 * @param $type
 *   The type of entity being deleted (i.e. node, user, comment).
 */
function hook_entity_delete($entity, $type) {
  // Delete the entity's entry from a fictional table of all entities.
  $info = entity_get_info($type);
374
  list($id) = entity_extract_ids($type, $entity);
375
376
377
378
  db_delete('example_entity')
    ->condition('type', $type)
    ->condition('id', $id)
    ->execute();
379
380
}

381
382
383
384
385
386
387
388
389
390
391
392
393
394
/**
 * Alter or execute an EntityFieldQuery.
 *
 * @param EntityFieldQuery $query
 *   An EntityFieldQuery. One of the most important properties to be changed is
 *   EntityFieldQuery::executeCallback. If this is set to an existing function,
 *   this function will get the query as its single argument and its result
 *   will be the returned as the result of EntityFieldQuery::execute(). This can
 *   be used to change the behavior of EntityFieldQuery entirely. For example,
 *   the default implementation can only deal with one field storage engine, but
 *   it is possible to write a module that can query across field storage
 *   engines. Also, the default implementation presumes entities are stored in
 *   SQL, but the execute callback could instead query any other entity storage,
 *   local or remote.
395
396
397
398
399
400
401
 *
 *   Note the $query->altered attribute which is TRUE in case the query has
 *   already been altered once. This happens with cloned queries.
 *   If there is a pager, then such a cloned query will be executed to count
 *   all elements. This query can be detected by checking for
 *   ($query->pager && $query->count), allowing the driver to return 0 from
 *   the count query and disable the pager.
402
403
404
405
406
 */
function hook_entity_query_alter($query) {
  $query->executeCallback = 'my_module_query_callback';
}

407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
/**
 * Act on entities being assembled before rendering.
 *
 * @param $entity
 *   The entity object.
 * @param $type
 *   The type of entity being rendered (i.e. node, user, comment).
 * @param $view_mode
 *   The view mode the entity is rendered in.
 * @param $langcode
 *   The language code used for rendering.
 *
 * The module may add elements to $entity->content prior to rendering. The
 * structure of $entity->content is a renderable array as expected by
 * drupal_render().
 *
 * @see hook_entity_view_alter()
 * @see hook_comment_view()
 * @see hook_node_view()
 * @see hook_user_view()
 */
function hook_entity_view($entity, $type, $view_mode, $langcode) {
  $entity->content['my_additional_field'] = array(
    '#markup' => $additional_field,
    '#weight' => 10,
    '#theme' => 'mymodule_my_additional_field',
  );
}

/**
 * Alter the results of ENTITY_view().
 *
 * This hook is called after the content has been assembled in a structured
 * array and may be used for doing processing which requires that the complete
 * entity content structure has been built.
 *
 * If a module wishes to act on the rendered HTML of the entity rather than the
 * structured content array, it may use this hook to add a #post_render
 * callback. Alternatively, it could also implement hook_preprocess_ENTITY().
 * See drupal_render() and theme() for details.
 *
 * @param $build
 *   A renderable array representing the entity content.
 * @param $type
 *   The type of entity being rendered (i.e. node, user, comment).
 *
 * @see hook_entity_view()
 * @see hook_comment_view_alter()
 * @see hook_node_view_alter()
 * @see hook_taxonomy_term_view_alter()
 * @see hook_user_view_alter()
 */
function hook_entity_view_alter(&$build, $type) {
  if ($build['#view_mode'] == 'full' && isset($build['an_additional_field'])) {
    // Change its weight.
    $build['an_additional_field']['#weight'] = -10;

    // Add a #post_render callback to act on the rendered HTML of the entity.
    $build['#post_render'][] = 'my_module_node_post_render';
  }
}

469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
/**
 * Change the view mode of an entity that is being displayed.
 *
 * @param string $view_mode
 *   The view_mode that is to be used to display the entity.
 * @param array $context
 *   Array with contextual information, including:
 *   - entity_type: The type of the entity that is being viewed.
 *   - entity: The entity object.
 *   - langcode: The langcode the entity is being viewed in.
 */
function hook_entity_view_mode_alter(&$view_mode, $context) {
  // For nodes, change the view mode when it is teaser.
  if ($context['entity_type'] == 'node' && $view_mode == 'teaser') {
    $view_mode = 'my_custom_view_mode';
  }
}

487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
/**
 * Define administrative paths.
 *
 * Modules may specify whether or not the paths they define in hook_menu() are
 * to be considered administrative. Other modules may use this information to
 * display those pages differently (e.g. in a modal overlay, or in a different
 * theme).
 *
 * To change the administrative status of menu items defined in another module's
 * hook_menu(), modules should implement hook_admin_paths_alter().
 *
 * @return
 *   An associative array. For each item, the key is the path in question, in
 *   a format acceptable to drupal_match_path(). The value for each item should
 *   be TRUE (for paths considered administrative) or FALSE (for non-
 *   administrative paths).
 *
 * @see hook_menu()
 * @see drupal_match_path()
 * @see hook_admin_paths_alter()
 */
function hook_admin_paths() {
  $paths = array(
    'mymodule/*/add' => TRUE,
    'mymodule/*/edit' => TRUE,
  );
  return $paths;
}

/**
 * Redefine administrative paths defined by other modules.
 *
 * @param $paths
 *   An associative array of administrative paths, as defined by implementations
 *   of hook_admin_paths().
 *
 * @see hook_admin_paths()
 */
function hook_admin_paths_alter(&$paths) {
  // Treat all user pages as administrative.
  $paths['user'] = TRUE;
  $paths['user/*'] = TRUE;
  // Treat the forum topic node form as a non-administrative page.
  $paths['node/add/forum'] = FALSE;
}

533
534
535
536
537
538
539
540
541
542
543
/**
 * Act on entities as they are being prepared for view.
 *
 * Allows you to operate on multiple entities as they are being prepared for
 * view. Only use this if attaching the data during the entity_load() phase
 * is not appropriate, for example when attaching other 'entity' style objects.
 *
 * @param $entities
 *   The entities keyed by entity ID.
 * @param $type
 *   The type of entities being loaded (i.e. node, user, comment).
544
545
 * @param $langcode
 *   The language to display the entity in.
546
 */
547
function hook_entity_prepare_view($entities, $type, $langcode) {
548
549
550
551
552
553
554
555
556
  // Load a specific node into the user object for later theming.
  if ($type == 'user') {
    $nodes = mymodule_get_user_nodes(array_keys($entities));
    foreach ($entities as $uid => $entity) {
      $entity->user_node = $nodes[$uid];
    }
  }
}

557
558
559
/**
 * Perform periodic actions.
 *
560
561
562
563
564
 * Modules that require some commands to be executed periodically can
 * implement hook_cron(). The engine will then call the hook whenever a cron
 * run happens, as defined by the administrator. Typical tasks managed by
 * hook_cron() are database maintenance, backups, recalculation of settings
 * or parameters, automated mailing, and retrieving remote data.
565
 *
566
567
 * Short-running or non-resource-intensive tasks can be executed directly in
 * the hook_cron() implementation.
568
 *
569
570
571
572
573
 * Long-running tasks and tasks that could time out, such as retrieving remote
 * data, sending email, and intensive file tasks, should use the queue API
 * instead of executing the tasks directly. To do this, first define one or
 * more queues via hook_cron_queue_info(). Then, add items that need to be
 * processed to the defined queues.
574
575
 */
function hook_cron() {
576
577
578
579
580
581
582
  // Short-running operation example, not using a queue:
  // Delete all expired records since the last cron run.
  $expires = variable_get('mymodule_cron_last_run', REQUEST_TIME);
  db_delete('mymodule_table')
    ->condition('expires', $expires, '>=')
    ->execute();
  variable_set('mymodule_cron_last_run', REQUEST_TIME);
583

584
585
  // Long-running operation example, leveraging a queue:
  // Fetch feeds from other sites.
586
  $result = db_query('SELECT * FROM {aggregator_feed} WHERE checked + refresh < :time AND refresh <> :never', array(
587
588
589
590
591
592
    ':time' => REQUEST_TIME,
    ':never' => AGGREGATOR_CLEAR_NEVER,
  ));
  $queue = DrupalQueue::get('aggregator_feeds');
  foreach ($result as $feed) {
    $queue->createItem($feed);
593
594
595
  }
}

596
597
598
599
600
601
/**
 * Declare queues holding items that need to be run periodically.
 *
 * While there can be only one hook_cron() process running at the same time,
 * there can be any number of processes defined here running. Because of
 * this, long running tasks are much better suited for this API. Items queued
602
603
604
 * in hook_cron() might be processed in the same cron run if there are not many
 * items in the queue, otherwise it might take several requests, which can be
 * run in parallel.
605
606
607
608
 *
 * @return
 *   An associative array where the key is the queue name and the value is
 *   again an associative array. Possible keys are:
609
 *   - 'worker callback': The name of an implementation of
610
 *     callback_queue_worker().
611
612
 *   - 'time': (optional) How much time Drupal should spend on calling this
 *     worker in seconds. Defaults to 15.
613
614
615
 *   - 'skip on cron': (optional) Set to TRUE to avoid being processed during
 *     cron runs (for example, if you want to control all queue execution
 *     manually).
616
617
 *
 * @see hook_cron()
618
 * @see hook_cron_queue_info_alter()
619
620
621
622
 */
function hook_cron_queue_info() {
  $queues['aggregator_feeds'] = array(
    'worker callback' => 'aggregator_refresh',
623
    'time' => 60,
624
625
626
627
  );
  return $queues;
}

628
629
630
/**
 * Alter cron queue information before cron runs.
 *
631
 * Called by drupal_cron_run() to allow modules to alter cron queue settings
632
633
634
635
636
 * before any jobs are processesed.
 *
 * @param array $queues
 *   An array of cron queue information.
 *
637
638
 * @see hook_cron_queue_info()
 * @see drupal_cron_run()
639
640
641
642
643
644
645
 */
function hook_cron_queue_info_alter(&$queues) {
  // This site has many feeds so let's spend 90 seconds on each cron run
  // updating feeds instead of the default 60.
  $queues['aggregator_feeds']['time'] = 90;
}

646
/**
647
 * Allows modules to declare their own Form API element types and specify their
648
649
650
651
652
653
654
655
656
657
658
659
 * default values.
 *
 * This hook allows modules to declare their own form element types and to
 * specify their default values. The values returned by this hook will be
 * merged with the elements returned by hook_form() implementations and so
 * can return defaults for any Form APIs keys in addition to those explicitly
 * mentioned below.
 *
 * Each of the form element types defined by this hook is assumed to have
 * a matching theme function, e.g. theme_elementtype(), which should be
 * registered with hook_theme() as normal.
 *
660
 * For more information about custom element types see the explanation at
661
662
663
664
665
666
667
668
 * http://drupal.org/node/169815.
 *
 * @return
 *  An associative array describing the element types being defined. The array
 *  contains a sub-array for each element type, with the machine-readable type
 *  name as the key. Each sub-array has a number of possible attributes:
 *  - "#input": boolean indicating whether or not this element carries a value
 *    (even if it's hidden).
669
670
 *  - "#process": array of callback functions taking $element, $form_state,
 *    and $complete_form.
671
672
673
674
675
676
677
 *  - "#after_build": array of callback functions taking $element and $form_state.
 *  - "#validate": array of callback functions taking $form and $form_state.
 *  - "#element_validate": array of callback functions taking $element and
 *    $form_state.
 *  - "#pre_render": array of callback functions taking $element and $form_state.
 *  - "#post_render": array of callback functions taking $element and $form_state.
 *  - "#submit": array of callback functions taking $form and $form_state.
678
679
 *  - "#title_display": optional string indicating if and how #title should be
 *    displayed, see theme_form_element() and theme_form_element_label().
680
681
682
 *
 * @see hook_element_info_alter()
 * @see system_element_info()
683
 */
684
685
686
687
688
function hook_element_info() {
  $types['filter_format'] = array(
    '#input' => TRUE,
  );
  return $types;
689
690
}

691
692
693
694
695
696
/**
 * Alter the element type information returned from modules.
 *
 * A module may implement this hook in order to alter the element type defaults
 * defined by a module.
 *
697
 * @param $type
698
 *   All element type defaults as collected by hook_element_info().
699
 *
700
 * @see hook_element_info()
701
702
703
704
705
706
707
708
 */
function hook_element_info_alter(&$type) {
  // Decrease the default size of textfields.
  if (isset($type['textfield']['#size'])) {
    $type['textfield']['#size'] = 40;
  }
}

709
710
711
/**
 * Perform cleanup tasks.
 *
712
713
714
715
 * This hook is run at the end of most regular page requests. It is often
 * used for page logging and specialized cleanup. This hook MUST NOT print
 * anything because by the time it runs the response is already sent to
 * the browser.
716
717
 *
 * Only use this hook if your code must run even for cached page views.
718
719
 * If you have code which must run once on all non-cached pages, use
 * hook_init() instead. That is the usual case. If you implement this hook
720
721
722
723
724
725
726
727
728
 * and see an error like 'Call to undefined function', it is likely that
 * you are depending on the presence of a module which has not been loaded yet.
 * It is not loaded because Drupal is still in bootstrap mode.
 *
 * @param $destination
 *   If this hook is invoked as part of a drupal_goto() call, then this argument
 *   will be a fully-qualified URL that is the destination of the redirect.
 */
function hook_exit($destination = NULL) {
729
730
731
732
  db_update('counter')
    ->expression('hits', 'hits + 1')
    ->condition('type', 1)
    ->execute();
733
734
735
736
737
738
739
740
}

/**
 * Perform necessary alterations to the JavaScript before it is presented on
 * the page.
 *
 * @param $javascript
 *   An array of all JavaScript being presented on the page.
741
 *
742
743
744
745
746
747
748
749
750
 * @see drupal_add_js()
 * @see drupal_get_js()
 * @see drupal_js_defaults()
 */
function hook_js_alter(&$javascript) {
  // Swap out jQuery to use an updated version of the library.
  $javascript['misc/jquery.js']['data'] = drupal_get_path('module', 'jquery_update') . '/jquery.js';
}

751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
/**
 * Registers JavaScript/CSS libraries associated with a module.
 *
 * Modules implementing this return an array of arrays. The key to each
 * sub-array is the machine readable name of the library. Each library may
 * contain the following items:
 *
 * - 'title': The human readable name of the library.
 * - 'website': The URL of the library's web site.
 * - 'version': A string specifying the version of the library; intentionally
 *   not a float because a version like "1.2.3" is not a valid float. Use PHP's
 *   version_compare() to compare different versions.
 * - 'js': An array of JavaScript elements; each element's key is used as $data
 *   argument, each element's value is used as $options array for
 *   drupal_add_js(). To add library-specific (not module-specific) JavaScript
 *   settings, the key may be skipped, the value must specify
 *   'type' => 'setting', and the actual settings must be contained in a 'data'
 *   element of the value.
 * - 'css': Like 'js', an array of CSS elements passed to drupal_add_css().
 * - 'dependencies': An array of libraries that are required for a library. Each
771
772
773
 *   element is an array listing the module and name of another library. Note
 *   that all dependencies for each dependent library will also be added when
 *   this library is added.
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
 *
 * Registered information for a library should contain re-usable data only.
 * Module- or implementation-specific data and integration logic should be added
 * separately.
 *
 * @return
 *   An array defining libraries associated with a module.
 *
 * @see system_library()
 * @see drupal_add_library()
 * @see drupal_get_library()
 */
function hook_library() {
  // Library One.
  $libraries['library-1'] = array(
    'title' => 'Library One',
    'website' => 'http://example.com/library-1',
    'version' => '1.2',
    'js' => array(
      drupal_get_path('module', 'my_module') . '/library-1.js' => array(),
    ),
    'css' => array(
      drupal_get_path('module', 'my_module') . '/library-2.css' => array(
        'type' => 'file',
        'media' => 'screen',
      ),
    ),
  );
  // Library Two.
  $libraries['library-2'] = array(
    'title' => 'Library Two',
    'website' => 'http://example.com/library-2',
    'version' => '3.1-beta1',
    'js' => array(
      // JavaScript settings may use the 'data' key.
      array(
        'type' => 'setting',
        'data' => array('library2' => TRUE),
      ),
    ),
    'dependencies' => array(
      // Require jQuery UI core by System module.
816
      array('system', 'ui'),
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
      // Require our other library.
      array('my_module', 'library-1'),
      // Require another library.
      array('other_module', 'library-3'),
    ),
  );
  return $libraries;
}

/**
 * Alters the JavaScript/CSS library registry.
 *
 * Allows certain, contributed modules to update libraries to newer versions
 * while ensuring backwards compatibility. In general, such manipulations should
 * only be done by designated modules, since most modules that integrate with a
 * certain library also depend on the API of a certain library version.
 *
 * @param $libraries
 *   The JavaScript/CSS libraries provided by $module. Keyed by internal library
 *   name and passed by reference.
 * @param $module
 *   The name of the module that registered the libraries.
 *
 * @see hook_library()
 */
function hook_library_alter(&$libraries, $module) {
  // Update Farbtastic to version 2.0.
  if ($module == 'system' && isset($libraries['farbtastic'])) {
    // Verify existing version is older than the one we are updating to.
    if (version_compare($libraries['farbtastic']['version'], '2.0', '<')) {
      // Update the existing Farbtastic to version 2.0.
      $libraries['farbtastic']['version'] = '2.0';
      $libraries['farbtastic']['js'] = array(
        drupal_get_path('module', 'farbtastic_update') . '/farbtastic-2.0.js' => array(),
      );
    }
  }
}

856
857
858
859
860
/**
 * Alter CSS files before they are output on the page.
 *
 * @param $css
 *   An array of all CSS items (files and inline CSS) being requested on the page.
861
 *
862
863
864
865
866
867
868
869
 * @see drupal_add_css()
 * @see drupal_get_css()
 */
function hook_css_alter(&$css) {
  // Remove defaults.css file.
  unset($css[drupal_get_path('module', 'system') . '/defaults.css']);
}

870
/**
871
 * Alter the commands that are sent to the user through the Ajax framework.
872
873
874
 *
 * @param $commands
 *   An array of all commands that will be sent to the user.
875
 *
876
877
 * @see ajax_render()
 */
878
function hook_ajax_render_alter(&$commands) {
879
880
881
882
  // Inject any new status messages into the content area.
  $commands[] = ajax_command_prepend('#block-system-main .content', theme('status_messages'));
}

883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
/**
 * Add elements to a page before it is rendered.
 *
 * Use this hook when you want to add elements at the page level. For your
 * additions to be printed, they have to be placed below a top level array key
 * of the $page array that has the name of a region of the active theme.
 *
 * By default, valid region keys are 'page_top', 'header', 'sidebar_first',
 * 'content', 'sidebar_second' and 'page_bottom'. To get a list of all regions
 * of the active theme, use system_region_list($theme). Note that $theme is a
 * global variable.
 *
 * If you want to alter the elements added by other modules or if your module
 * depends on the elements of other modules, use hook_page_alter() instead which
 * runs after this hook.
 *
 * @param $page
 *   Nested array of renderable elements that make up the page.
 *
 * @see hook_page_alter()
 * @see drupal_render_page()
 */
function hook_page_build(&$page) {
  if (menu_get_object('node', 1)) {
    // We are on a node detail page. Append a standard disclaimer to the
    // content region.
    $page['content']['disclaimer'] = array(
      '#markup' => t('Acme, Inc. is not responsible for the contents of this sample code.'),
      '#weight' => 25,
    );
  }
}

916
917
918
919
920
/**
 * Alter a menu router item right after it has been retrieved from the database or cache.
 *
 * This hook is invoked by menu_get_item() and allows for run-time alteration of router
 * information (page_callback, title, and so on) before it is translated and checked for
921
 * access. The passed-in $router_item is statically cached for the current request, so this
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
 * hook is only invoked once for any router item that is retrieved via menu_get_item().
 *
 * Usually, modules will only want to inspect the router item and conditionally
 * perform other actions (such as preparing a state for the current request).
 * Note that this hook is invoked for any router item that is retrieved by
 * menu_get_item(), which may or may not be called on the path itself, so implementations
 * should check the $path parameter if the alteration should fire for the current request
 * only.
 *
 * @param $router_item
 *   The menu router item for $path.
 * @param $path
 *   The originally passed path, for which $router_item is responsible.
 * @param $original_map
 *   The path argument map, as contained in $path.
 *
 * @see menu_get_item()
 */
function hook_menu_get_item_alter(&$router_item, $path, $original_map) {
  // When retrieving the router item for the current path...
  if ($path == $_GET['q']) {
    // ...call a function that prepares something for this request.
    mymodule_prepare_something();
  }
}

948
949
950
951
952
953
954
955
956
957
958
959
960
961
/**
 * Define menu items and page callbacks.
 *
 * This hook enables modules to register paths in order to define how URL
 * requests are handled. Paths may be registered for URL handling only, or they
 * can register a link to be placed in a menu (usually the Navigation menu). A
 * path and its associated information is commonly called a "menu router item".
 * This hook is rarely called (for example, when modules are enabled), and
 * its results are cached in the database.
 *
 * hook_menu() implementations return an associative array whose keys define
 * paths and whose values are an associative array of properties for each
 * path. (The complete list of properties is in the return value section below.)
 *
962
 * @section sec_callback_funcs Callback Functions
963
964
965
966
967
968
969
970
971
972
 * The definition for each path may include a page callback function, which is
 * invoked when the registered path is requested. If there is no other
 * registered path that fits the requested path better, any further path
 * components are passed to the callback function. For example, your module
 * could register path 'abc/def':
 * @code
 *   function mymodule_menu() {
 *     $items['abc/def'] = array(
 *       'page callback' => 'mymodule_abc_view',
 *     );
973
 *     return $items;
974
975
976
977
978
979
980
981
982
983
984
985
986
 *   }
 *
 *   function mymodule_abc_view($ghi = 0, $jkl = '') {
 *     // ...
 *   }
 * @endcode
 * When path 'abc/def' is requested, no further path components are in the
 * request, and no additional arguments are passed to the callback function (so
 * $ghi and $jkl would take the default values as defined in the function
 * signature). When 'abc/def/123/foo' is requested, $ghi will be '123' and
 * $jkl will be 'foo'. Note that this automatic passing of optional path
 * arguments applies only to page and theme callback functions.
 *
987
 * @subsection sub_callback_arguments Callback Arguments
988
989
990
991
992
993
994
 * In addition to optional path arguments, the page callback and other callback
 * functions may specify argument lists as arrays. These argument lists may
 * contain both fixed/hard-coded argument values and integers that correspond
 * to path components. When integers are used and the callback function is
 * called, the corresponding path components will be substituted for the
 * integers. That is, the integer 0 in an argument list will be replaced with
 * the first path component, integer 1 with the second, and so on (path
995
996
997
998
999
 * components are numbered starting from zero). To pass an integer without it
 * being replaced with its respective path component, use the string value of
 * the integer (e.g., '1') as the argument value. This substitution feature
 * allows you to re-use a callback function for several different paths. For
 * example:
1000
1001
1002
1003
1004
1005
 * @code
 *   function mymodule_menu() {
 *     $items['abc/def'] = array(
 *       'page callback' => 'mymodule_abc_view',
 *       'page arguments' => array(1, 'foo'),
 *     );
1006
 *     return $items;
1007
1008
1009
1010
1011
 *   }
 * @endcode
 * When path 'abc/def' is requested, the page callback function will get 'def'
 * as the first argument and (always) 'foo' as the second argument.
 *
1012
1013
1014
1015
1016
1017
 * If a page callback function uses an argument list array, and its path is
 * requested with optional path arguments, then the list array's arguments are
 * passed to the callback function first, followed by the optional path
 * arguments. Using the above example, when path 'abc/def/bar/baz' is requested,
 * mymodule_abc_view() will be called with 'def', 'foo', 'bar' and 'baz' as
 * arguments, in that order.
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
 *
 * Special care should be taken for the page callback drupal_get_form(), because
 * your specific form callback function will always receive $form and
 * &$form_state as the first function arguments:
 * @code
 *   function mymodule_abc_form($form, &$form_state) {
 *     // ...
 *     return $form;
 *   }
 * @endcode
 * See @link form_api Form API documentation @endlink for details.
 *
1030
1031
 * @section sec_path_wildcards Wildcards in Paths
 * @subsection sub_simple_wildcards Simple Wildcards
1032
1033
1034
1035
1036
1037
1038
1039
1040
 * Wildcards within paths also work with integer substitution. For example,
 * your module could register path 'my-module/%/edit':
 * @code
 *   $items['my-module/%/edit'] = array(
 *     'page callback' => 'mymodule_abc_edit',
 *     'page arguments' => array(1),
 *   );
 * @endcode
 * When path 'my-module/foo/edit' is requested, integer 1 will be replaced
1041
1042
 * with 'foo' and passed to the callback function. Note that wildcards may not
 * be used as the first component.
1043
 *
1044
 * @subsection sub_autoload_wildcards Auto-Loader Wildcards
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
 * Registered paths may also contain special "auto-loader" wildcard components
 * in the form of '%mymodule_abc', where the '%' part means that this path
 * component is a wildcard, and the 'mymodule_abc' part defines the prefix for a
 * load function, which here would be named mymodule_abc_load(). When a matching
 * path is requested, your load function will receive as its first argument the
 * path component in the position of the wildcard; load functions may also be
 * passed additional arguments (see "load arguments" in the return value
 * section below). For example, your module could register path
 * 'my-module/%mymodule_abc/edit':
 * @code
 *   $items['my-module/%mymodule_abc/edit'] = array(
 *     'page callback' => 'mymodule_abc_edit',
 *     'page arguments' => array(1),
 *   );
 * @endcode
 * When path 'my-module/123/edit' is requested, your load function
 * mymodule_abc_load() will be invoked with the argument '123', and should
 * load and return an "abc" object with internal id 123:
 * @code
 *   function mymodule_abc_load($abc_id) {
 *     return db_query("SELECT * FROM {mymodule_abc} WHERE abc_id = :abc_id", array(':abc_id' => $abc_id))->fetchObject();
 *   }
 * @endcode
1068
1069
 * This 'abc' object will then be passed into the callback functions defined
 * for the menu item, such as the page callback function mymodule_abc_edit()
1070
 * to replace the integer 1 in the argument array. Note that a load function
1071
 * should return FALSE when it is unable to provide a loadable object. For
1072
1073
1074
 * example, the node_load() function for the 'node/%node/edit' menu item will
 * return FALSE for the path 'node/999/edit' if a node with a node ID of 999
 * does not exist. The menu routing system will return a 404 error in this case.
1075
 *
1076
 * @subsection sub_argument_wildcards Argument Wildcards
1077
1078
1079
1080
1081
 * You can also define a %wildcard_to_arg() function (for the example menu
 * entry above this would be 'mymodule_abc_to_arg()'). The _to_arg() function
 * is invoked to retrieve a value that is used in the path in place of the
 * wildcard. A good example is user.module, which defines
 * user_uid_optional_to_arg() (corresponding to the menu entry
1082
 * 'tracker/%user_uid_optional'). This function returns the user ID of the
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
 * current user.
 *
 * The _to_arg() function will get called with three arguments:
 * - $arg: A string representing whatever argument may have been supplied by
 *   the caller (this is particularly useful if you want the _to_arg()
 *   function only supply a (default) value if no other value is specified,
 *   as in the case of user_uid_optional_to_arg().
 * - $map: An array of all path fragments (e.g. array('node','123','edit') for
 *   'node/123/edit').
 * - $index: An integer indicating which element of $map corresponds to $arg.
 *
 * _load() and _to_arg() functions may seem similar at first glance, but they
 * have different purposes and are called at different times. _load()
 * functions are called when the menu system is collecting arguments to pass
 * to the callback functions defined for the menu item. _to_arg() functions
 * are called when the menu system is generating links to related paths, such
 * as the tabs for a set of MENU_LOCAL_TASK items.
1100
 *
1101
 * @section sec_render_tabs Rendering Menu Items As Tabs
1102
1103
1104
1105
1106
1107
1108
1109
1110
 * You can also make groups of menu items to be rendered (by default) as tabs
 * on a page. To do that, first create one menu item of type MENU_NORMAL_ITEM,
 * with your chosen path, such as 'foo'. Then duplicate that menu item, using a
 * subdirectory path, such as 'foo/tab1', and changing the type to
 * MENU_DEFAULT_LOCAL_TASK to make it the default tab for the group. Then add
 * the additional tab items, with paths such as "foo/tab2" etc., with type
 * MENU_LOCAL_TASK. Example:
 * @code
 * // Make "Foo settings" appear on the admin Config page
1111
 * $items['admin/config/system/foo'] = array(
1112
1113
 *   'title' => 'Foo settings',
 *   'type' => MENU_NORMAL_ITEM,
1114
 *   // Page callback, etc. need to be added here.
1115
 * );
1116
1117
1118
 * // Make "Tab 1" the main tab on the "Foo settings" page
 * $items['admin/config/system/foo/tab1'] = array(
 *   'title' => 'Tab 1',
1119
 *   'type' => MENU_DEFAULT_LOCAL_TASK,
1120
 *   // Access callback, page callback, and theme callback will be inherited
1121
 *   // from 'admin/config/system/foo', if not specified here to override.
1122
 * );
1123
1124
1125
 * // Make an additional tab called "Tab 2" on "Foo settings"
 * $items['admin/config/system/foo/tab2'] = array(
 *   'title' => 'Tab 2',
1126
 *   'type' => MENU_LOCAL_TASK,
1127
 *   // Page callback and theme callback will be inherited from
1128
 *   // 'admin/config/system/foo', if not specified here to override.
1129
 *   // Need to add access callback or access arguments.
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
 * );
 * @endcode
 *
 * @return
 *   An array of menu items. Each menu item has a key corresponding to the
 *   Drupal path being registered. The corresponding array value is an
 *   associative array that may contain the following key-value pairs:
 *   - "title": Required. The untranslated title of the menu item.
 *   - "title callback": Function to generate the title; defaults to t().
 *     If you require only the raw string to be output, set this to FALSE.
 *   - "title arguments": Arguments to send to t() or your custom callback,
 *     with path component substitution as described above.
 *   - "description": The untranslated description of the menu item.
 *   - "page callback": The function to call to display a web page when the user
 *     visits the path. If omitted, the parent menu item's callback will be used
 *     instead.
 *   - "page arguments": An array of arguments to pass to the page callback
 *     function, with path component substitution as described above.
 *   - "delivery callback": The function to call to package the result of the
 *     page callback function and send it to the browser. Defaults to
 *     drupal_deliver_html_page() unless a value is inherited from a parent menu
1151
1152
1153
 *     item. Note that this function is called even if the access checks fail,
 *     so any custom delivery callback function should take that into account.
 *     See drupal_deliver_html_page() for an example.
1154
1155
1156
1157
 *   - "access callback": A function returning TRUE if the user has access
 *     rights to this menu item, and FALSE if not. It can also be a boolean
 *     constant instead of a function, and you can also use numeric values
 *     (will be cast to boolean). Defaults to user_access() unless a value is
1158
1159
1160
1161
 *     inherited from the parent menu item; only MENU_DEFAULT_LOCAL_TASK items
 *     can inherit access callbacks. To use the user_access() default callback,
 *     you must specify the permission to check as 'access arguments' (see
 *     below).
1162
 *   - "access arguments": An array of arguments to pass to the access callback
1163
1164
1165
 *     function, with path component substitution as described above. If the
 *     access callback is inherited (see above), the access arguments will be
 *     inherited with it, unless overridden in the child menu item.
1166
 *   - "theme callback": (optional) A function returning the machine-readable
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
 *     name of the theme that will be used to render the page. If not provided,
 *     the value will be inherited from a parent menu item. If there is no
 *     theme callback, or if the function does not return the name of a current
 *     active theme on the site, the theme for this page will be determined by
 *     either hook_custom_theme() or the default theme instead. As a general
 *     rule, the use of theme callback functions should be limited to pages
 *     whose functionality is very closely tied to a particular theme, since
 *     they can only be overridden by modules which specifically target those
 *     pages in hook_menu_alter(). Modules implementing more generic theme
 *     switching functionality (for example, a module which allows the theme to
 *     be set dynamically based on the current user's role) should use
 *     hook_custom_theme() instead.
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
 *   - "theme arguments": An array of arguments to pass to the theme callback
 *     function, with path component substitution as described above.
 *   - "file": A file that will be included before the page callback is called;
 *     this allows page callback functions to be in separate files. The file
 *     should be relative to the implementing module's directory unless
 *     otherwise specified by the "file path" option. Does not apply to other
 *     callbacks (only page callback).
 *   - "file path": The path to the directory containing the file specified in
 *     "file". This defaults to the path to the module implementing the hook.
 *   - "load arguments": An array of arguments to be passed to each of the
 *     wildcard object loaders in the path, after the path argument itself.
 *     For example, if a module registers path node/%node/revisions/%/view
 *     with load arguments set to array(3), the '%node' in the path indicates
 *     that the loader function node_load() will be called with the second
 *     path component as the first argument. The 3 in the load arguments
 *     indicates that the fourth path component will also be passed to
 *     node_load() (numbering of path components starts at zero). So, if path
 *     node/12/revisions/29/view is requested, node_load(12, 29) will be called.
 *     There are also two "magic" values that can be used in load arguments.
 *     "%index" indicates the index of the wildcard path component. "%map"
 *     indicates the path components as an array. For example, if a module
 *     registers for several paths of the form 'user/%user_category/edit/*', all
 *     of them can use the same load function user_category_load(), by setting
 *     the load arguments to array('%map', '%index'). For instance, if the user
 *     is editing category 'foo' by requesting path 'user/32/edit/foo', the load
 *     function user_category_load() will be called with 32 as its first
 *     argument, the array ('user', 32, 'edit', 'foo') as the map argument,
 *     and 1 as the index argument (because %user_category is the second path
 *     component and numbering starts at zero). user_category_load() can then
 *     use these values to extract the information that 'foo' is the category
 *     being requested.
 *   - "weight": An integer that determines the relative position of items in
 *     the menu; higher-weighted items sink. Defaults to 0. Menu items with the
 *     same weight are ordered alphabetically.
 *   - "menu_name": Optional. Set this to a custom menu if you don't want your
 *     item to be placed in Navigation.
1215
1216
1217
1218
 *   - "expanded": Optional. If set to TRUE, and if a menu link is provided for
 *     this menu item (as a result of other properties), then the menu link is
 *     always expanded, equivalent to its 'always expanded' checkbox being set
 *     in the UI.
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
 *   - "context": (optional) Defines the context a tab may appear in. By
 *     default, all tabs are only displayed as local tasks when being rendered
 *     in a page context. All tabs that should be accessible as contextual links
 *     in page region containers outside of the parent menu item's primary page
 *     context should be registered using one of the following contexts:
 *     - MENU_CONTEXT_PAGE: (default) The tab is displayed as local task for the
 *       page context only.
 *     - MENU_CONTEXT_INLINE: The tab is displayed as contextual link outside of
 *       the primary page context only.
 *     Contexts can be combined. For example, to display a tab both on a page
 *     and inline, a menu router item may specify:
 *     @code
 *       'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
 *     @endcode
 *   - "tab_parent": For local task menu items, the path of the task's parent
 *     item; defaults to the same path without the last component (e.g., the
 *     default parent for 'admin/people/create' is 'admin/people').
 *   - "tab_root": For local task menu items, the path of the closest non-tab
 *     item; same default as "tab_parent".
 *   - "position": Position of the block ('left' or 'right') on the system
 *     administration page for this item.
 *   - "type": A bitmask of flags describing properties of the menu item.
 *     Many shortcut bitmasks are provided as constants in menu.inc:
 *     - MENU_NORMAL_ITEM: Normal menu items show up in the menu tree and can be
 *       moved/hidden by the administrator.
 *     - MENU_CALLBACK: Callbacks simply register a path so that the correct
 *       information is generated when the path is accessed.
 *     - MENU_SUGGESTED_ITEM: Modules may "suggest" menu items that the
 *       administrator may enable.
 *     - MENU_LOCAL_ACTION: Local actions are menu items that describe actions
 *       on the parent item such as adding a new user or block, and are
 *       rendered in the action-links list in your theme.
 *     - MENU_LOCAL_TASK: Local tasks are menu items that describe different
 *       displays of data, and are generally rendered as tabs.
 *     - MENU_DEFAULT_LOCAL_TASK: Every set of local tasks should provide one
 *       "default" task, which should display the same page as the parent item.
 *     If the "type" element is omitted, MENU_NORMAL_ITEM is assumed.
1256
 *   - "options": An array of options to be passed to l() when generating a link
1257
1258
 *     from this menu item. Note that the "options" parameter has no effect on
 *     MENU_LOCAL_TASK, MENU_DEFAULT_LOCAL_TASK, and MENU_LOCAL_ACTION items.
1259
1260
1261
1262
1263
1264
 *
 * For a detailed usage example, see page_example.module.
 * For comprehensive documentation on the menu system, see
 * http://drupal.org/node/102338.
 */
function hook_menu() {
1265
1266
1267
  $items['example'] = array(
    'title' => 'Example Page',
    'page callback' => 'example_page',
1268
1269
1270
    'access arguments' => array('access content'),
    'type' => MENU_SUGGESTED_ITEM,
  );
1271
1272
1273
  $items['example/feed'] = array(
    'title' => 'Example RSS feed',
    'page callback' => 'example_feed',
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
  );

  return $items;
}

/**
 * Alter the data being saved to the {menu_router} table after hook_menu is invoked.
 *
 * This hook is invoked by menu_router_build(). The menu definitions are passed
 * in by reference. Each element of the $items array is one item returned
 * by a module from hook_menu. Additional items may be added, or existing items
 * altered.
 *
 * @param $items
 *   Associative array of menu router definitions returned from hook_menu().
 */
function hook_menu_alter(&$items) {
  // Example - disable the page at node/add
  $items['node/add']['access callback'] = FALSE;
}

/**
 * Alter the data being saved to the {menu_links} table by menu_link_save().
 *
 * @param $item
 *   Associative array defining a menu link as passed into menu_link_save().
1302
1303
 *
 * @see hook_translated_menu_link_alter()
1304
1305
 */
function hook_menu_link_alter(&$item) {
1306
  // Make all new admin links hidden (a.k.a disabled).
1307
1308
1309
  if (strpos($item['link_path'], 'admin') === 0 && empty($item['mlid'])) {
    $item['hidden'] = 1;
  }
1310
  // Flag a link to be altered by hook_translated_menu_link_alter().
1311
1312
1313
  if ($item['link_path'] == 'devel/cache/clear') {
    $item['options']['alter'] = TRUE;
  }
1314
1315
1316
1317
1318
1319
  // Flag a link to be altered by hook_translated_menu_link_alter(), but only
  // if it is derived from a menu router item; i.e., do not alter a custom
  // menu link pointing to the same path that has been created by a user.
  if ($item['link_path'] == 'user' && $item['module'] == 'system') {
    $item['options']['alter'] = TRUE;
  }
1320
1321
1322
}

/**
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
 * Alter a menu link after it has been translated and before it is rendered.
 *
 * This hook is invoked from _menu_link_translate() after a menu link has been
 * translated; i.e., after dynamic path argument placeholders (%) have been
 * replaced with actual values, the user access to the link's target page has
 * been checked, and the link has been localized. It is only invoked if
 * $item['options']['alter'] has been set to a non-empty value (e.g., TRUE).
 * This flag should be set using hook_menu_link_alter().
 *
 * Implementations of this hook are able to alter any property of the menu link.
 * For example, this hook may be used to add a page-specific query string to all
 * menu links, or hide a certain link by setting:
 * @code
 *   'hidden' => 1,
 * @endcode
1338
1339
1340
1341
1342
 *
 * @param $item
 *   Associative array defining a menu link after _menu_link_translate()
 * @param $map
 *   Associative array containing the menu $map (path parts and/or objects).
1343
1344
 *
 * @see hook_menu_link_alter()
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
 */
function hook_translated_menu_link_alter(&$item, $map) {
  if ($item['href'] == 'devel/cache/clear') {
    $item['localized_options']['query'] = drupal_get_destination();
  }
}

/**
 * Inform modules that a menu link has been created.
 *
 * This hook is used to notify modules that menu items have been
 * created. Contributed modules may use the information to perform
 * actions based on the information entered into the menu system.
 *
 * @param $link
 *   Associative array defining a menu link as passed into menu_link_save().
 *
 * @see hook_menu_link_update()
 * @see hook_menu_link_delete()
 */
function hook_menu_link_insert($link) {
  // In our sample case, we track menu items as editing sections
  // of the site. These are stored in our table as 'disabled' items.
  $record['mlid'] = $link['mlid'];
  $record['menu_name'] = $link['menu_name'];
  $record['status'] = 0;
  drupal_write_record('menu_example', $record);
}

/**
 * Inform modules that a menu link has been updated.
 *
 * This hook is used to notify modules that menu items have been
 * updated. Contributed modules may use the information to perform
 * actions based on the information entered into the menu system.
 *
 * @param $link
 *   Associative array defining a menu link as passed into menu_link_save().
 *
 * @see hook_menu_link_insert()
 * @see hook_menu_link_delete()
 */
function hook_menu_link_update($link) {
  // If the parent menu has changed, update our record.
1389
  $menu_name = db_query("SELECT menu_name FROM {menu_example} WHERE mlid = :mlid", array(':mlid' => $link['mlid']))->fetchField();
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
  if ($menu_name != $link['menu_name']) {
    db_update('menu_example')
      ->fields(array('menu_name' => $link['menu_name']))
      ->condition('mlid', $link['mlid'])
      ->execute();
  }
}

/**
 * Inform modules that a menu link has been deleted.
 *
 * This hook is used to notify modules that menu items have been
 * deleted. Contributed modules may use the information to perform
 * actions based on the information entered into the menu system.
 *
 * @param $link
 *   Associative array defining a menu link as passed into menu_link_save().
 *
 * @see hook_menu_link_insert()
 * @see hook_menu_link_update()
 */
function hook_menu_link_delete($link) {
  // Delete the record from our table.
  db_delete('menu_example')
    ->condition('mlid', $link['mlid'])
    ->execute();
}

/**
 * Alter tabs and actions displayed on the page before they are rendered.
 *
 * This hook is invoked by menu_local_tasks(). The system-determined tabs and
 * actions are passed in by reference. Additional tabs or actions may be added,
 * or existing items altered.
 *
 * Each tab or action is an associative array containing:
 * - #theme: The theme function to use to render.
 * - #link: An associative array containing:
 *   - title: The localized title of the link.
 *   - href: The system path to link to.
1430
 *   - localized_options: An array of options to pass to l().
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
 * - #active: Whether the link should be marked as 'active'.
 *
 * @param $data
 *   An associative array containing:
 *   - actions: An associative array containing:
 *     - count: The amount of actions determined by the menu system, which can
 *       be ignored.
 *     - output: A list of of actions, each one being an associative array
 *       as described above.
 *   - tabs: An indexed array (list) of tab levels (up to 2 levels), each
 *     containing an associative array:
 *     - count: The amount of tabs determined by the menu system. This value
 *       does not need to be altered if there is more than one tab.
 *     - output: A list of of tabs, each one being an associative array as
 *       described above.
1446
1447
1448
1449
 * @param $router_item
 *   The menu system router item of the page.
 * @param $root_path
 *   The path to the root item for this set of tabs.
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
 */
function hook_menu_local_tasks_alter(&$data, $router_item, $root_path) {
  // Add an action linking to node/add to all pages.
  $data['actions']['output'][] = array(
    '#theme' => 'menu_local_task',
    '#link' => array(
      'title' => t('Add new content'),
      'href' => 'node/add',
      'localized_options' => array(
        'attributes' => array(
          'title' => t('Add new content'),
        ),
      ),
    ),
  );

  // Add a tab linking to node/add to all pages.
  $data['tabs'][0]['output'][] = array(
    '#theme' => 'menu_local_task',
    '#link' => array(
      'title' => t('Example tab'),
      'href' => 'node/add',
      'localized_options' => array(
        'attributes' => array(
          'title' => t('Add new content'),
        ),
      ),
    ),
    // Define whether this link is active. This can be omitted for
    // implementations that add links to pages outside of the current page
    // context.
    '#active' => ($router_item['path'] == $root_path),
  );
}

1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
/**
 * Alter links in the active trail before it is rendered as the breadcrumb.
 *
 * This hook is invoked by menu_get_active_breadcrumb() and allows alteration
 * of the breadcrumb links for the current page, which may be preferred instead
 * of setting a custom breadcrumb via drupal_set_breadcrumb().
 *
 * Implementations should take into account that menu_get_active_breadcrumb()
 * subsequently performs the following adjustments to the active trail *after*
 * this hook has been invoked:
 * - The last link in $active_trail is removed, if its 'href' is identical to
 *   the 'href' of $item. This happens, because the breadcrumb normally does
 *   not contain a link to the current page.
 * - The (second to) last link in $active_trail is removed, if the current $item
 *   is a MENU_DEFAULT_LOCAL_TASK. This happens in order to do not show a link
 *   to the current page, when being on the path for the default local task;
 *   e.g. when being on the path node/%/view, the breadcrumb should not contain
 *   a link to node/%.
 *
 * Each link in the active trail must contain:
 * - title: The localized title of the link.
 * - href: The system path to link to.
 * - localized_options: An array of options to pass to url().
 *
 * @param $active_trail
 *   An array containing breadcrumb links for the current page.
 * @param $item
 *   The menu router item of the current page.
 *
 * @see drupal_set_breadcrumb()
 * @see menu_get_active_breadcrumb()
 * @see menu_get_active_trail()
 * @see menu_set_active_trail()
 */
function hook_menu_breadcrumb_alter(&$active_trail, $item) {
  // Always display a link to the current page by duplicating the last link in
  // the active trail. This means that menu_get_active_breadcrumb() will remove
  // the last link (for the current page), but since it is added once more here,
  // it will appear.
  if (!drupal_is_front_page()) {
    $end = end($active_trail);
    if ($item['href'] == $end['href']) {
      $active_trail[] = $end;
    }
  }
}

1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
/**
 * Alter contextual links before they are rendered.
 *
 * This hook is invoked by menu_contextual_links(). The system-determined
 * contextual links are passed in by reference. Additional links may be added
 * or existing links can be altered.
 *
 * Each contextual link must at least contain:
 * - title: The localized title of the link.
 * - href: The system path to link to.
 * - localized_options: An array of options to pass to url().
 *
 * @param $links
 *   An associative array containing contextual links for the given $root_path,
 *   as described above. The array keys are used to build CSS class names for
 *   contextual links and must therefore be unique for each set of contextual
 *   links.
 * @param $router_item
 *   The menu router item belonging to the $root_path being requested.
 * @param $root_path
 *   The (parent) path that has been requested to build contextual links for.
 *   This is a normalized path, which means that an originally passed path of
 *   'node/123' became 'node/%'.
 *
1556
 * @see hook_contextual_links_view_alter()
1557
1558
 * @see menu_contextual_links()
 * @see hook_menu()
1559
 * @see contextual_preprocess()
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
 */
function hook_menu_contextual_links_alter(&$links, $router_item, $root_path) {
  // Add a link to all contextual links for nodes.
  if ($root_path == 'node/%') {
    $links['foo'] = array(
      'title' => t('Do fu'),
      'href' => 'foo/do',
      'localized_options' => array(
        'query' => array(
          'foo' => 'bar',
        ),
      ),
    );
  }
}

1576
1577
1578
/**
 * Perform alterations before a page is rendered.
 *
1579
1580
1581
1582
1583
 * Use this hook when you want to remove or alter elements at the page
 * level, or add elements at the page level that depend on an other module's
 * elements (this hook runs after hook_page_build().
 *
 * If you are making changes to entities such as forms, menus, or user
1584
1585
1586
1587
1588
 * profiles, use those objects' native alter hooks instead (hook_form_alter(),
 * for example).
 *
 * The $page array contains top level elements for each block region:
 * @code
1589
 *   $page['page_top']
1590
 *   $page['header']
1591
 *   $page['sidebar_first']
1592
 *   $page['content']
1593
 *   $page['sidebar_second']
1594
 *   $page['page_bottom']
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
 * @endcode
 *
 * The 'content' element contains the main content of the current page, and its
 * structure will vary depending on what module is responsible for building the
 * page. Some legacy modules may not return structured content at all: their
 * pre-rendered markup will be located in $page['content']['main']['#markup'].
 *
 * Pages built by Drupal's core Node and Blog modules use a standard structure:
 *
 * @code
 *   // Node body.
1606
 *   $page['content']['system_main']['nodes'][$nid]['body']
1607
 *   // Array of links attached to the node (add comments, read more).
1608
 *   $page['content']['system_main']['nodes'][$nid]['links']
1609
 *   // The node object itself.
1610
 *   $page['content']['system_main']['nodes'][$nid]['#node']
1611
 *   // The results pager.
1612
 *   $page['content']['system_main']['pager']
1613
 * @endcode
1614
1615
1616
 *
 * Blocks may be referenced by their module/delta pair within a region:
 * @code
1617
 *   // The login block in the first sidebar region.
1618
 *   $page['sidebar_first']['user_login']['#block'];
1619
1620
1621
1622
1623
 * @endcode
 *
 * @param $page
 *   Nested array of renderable elements that make up the page.
 *
1624
 * @see hook_page_build()
1625
1626
 * @see drupal_render_page()
 */
1627
1628
1629
1630
1631
1632
function hook_page_alter(&$page) {
  // Add help text to the user login block.
  $page['sidebar_first']['user_login']['help'] = array(
    '#weight' => -10,
    '#markup' => t('To post comments or add new content, you first have to log in.'),
  );
1633
1634
}

1635
1636
1637
1638
/**
 * Perform alterations before a form is rendered.
 *
 * One popular use of this hook is to add form elements to the node form. When
1639
 * altering a node form, the node object can be accessed at $form['#node'].
1640
 *
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
 * In addition to hook_form_alter(), which is called for all forms, there are
 * two more specific form hooks available. The first,
 * hook_form_BASE_FORM_ID_alter(), allows targeting of a form/forms via a base
 * form (if one exists). The second, hook_form_FORM_ID_alter(), can be used to
 * target a specific form directly.
 *
 * The call order is as follows: all existing form alter functions are called
 * for module A, then all for module B, etc., followed by all for any base
 * theme(s), and finally for the theme itself. The module order is determined
 * by system weight, then by module name.
 *
 * Within each module, form alter hooks are called in the following order:
 * first, hook_form_alter(); second, hook_form_BASE_FORM_ID_alter(); third,
 * hook_form_FORM_ID_alter(). So, for each module, the more general hooks are
 * called first followed by the more specific.
1656
 *
1657
1658
1659
 * @param $form
 *   Nested array of form elements that comprise the form.
 * @param $form_state
1660
1661
1662
 *   A keyed array containing the current state of the form. The arguments
 *   that drupal_get_form() was originally called with are available in the
 *   array $form_state['build_info']['args'].
1663
1664
1665
 * @param $form_id
 *   String representing the name of the form itself. Typically this is the
 *   name of the function that generated the form.
1666
 *
1667
 * @see hook_form_BASE_FORM_ID_alter()
1668
 * @see hook_form_FORM_ID_alter()
1669
 * @see forms_api_reference.html
1670
 */
1671
function hook_form_alter(&$form, &$form_state, $form_id) {
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
  if (isset($form['type']) && $form['type']['#value'] . '_node_settings' == $form_id) {
    $form['workflow']['upload_' . $form['type']['#value']] = array(
      '#type' => 'radios',
      '#title' => t('Attachments'),
      '#default_value' => variable_get('upload_' . $form['type']['#value'], 1),
      '#options' => array(t('Disabled'), t('Enabled')),
    );
  }
}

/**
 * Provide a form-specific alteration instead of the global hook_form_alter().
 *
 * Modules can implement hook_form_FORM_ID_alter() to modify a specific form,
 * rather than implementing hook_form_alter() and checking the form ID, or
 * using long switch statements to alter multiple forms.
 *
1689
1690
1691
1692
 * Form alter hooks are called in the following order: hook_form_alter(),
 * hook_form_BASE_FORM_ID_alter(), hook_form_FORM_ID_alter(). See
 * hook_form_alter() for more details.
 *
1693
1694
1695
 * @param $form
 *   Nested array of form elements that comprise the form.
 * @param $form_state
1696
1697
1698
 *   A keyed array containing the current state of the form. The arguments
 *   that drupal_get_form() was originally called with are available in the
 *   array $form_state['build_info']['args'].
1699
1700
1701
 * @param $form_id
 *   String representing the name of the form itself. Typically this is the
 *   name of the function that generated the form.
1702
 *
1703
 * @see hook_form_alter()
1704
 * @see hook_form_BASE_FORM_ID_alter()
1705
 * @see drupal_prepare_form()