- Patch #1417754 by mkadin: hook_menu() docs need to explain that options don't work...
[project/drupal.git] / modules / system / system.api.php
CommitLineData
66df6025 1<?php
66df6025
AB
2
3/**
4 * @file
5 * Hooks provided by Drupal core and the System module.
6 */
7
8/**
9 * @addtogroup hooks
10 * @{
11 */
12
13/**
13d3072f
DB
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.
269da037
AB
34 *
35 * @see hook_hook_info_alter().
13d3072f
DB
36 */
37function 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/**
269da037
AB
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 */
55function 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/**
3f36af04
DB
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 *
3f36af04
DB
69 * @return
70 * An array whose keys are entity type names and whose values identify
53748ab5 71 * properties of those types that the system needs to know about:
539ba0dc 72 * - label: The human-readable name of the type.
4c686375 73 * - controller class: The name of the class that is used to load the objects.
42f9d899 74 * The class has to implement the DrupalEntityControllerInterface interface.
539ba0dc
DB
75 * Leave blank to use the DrupalDefaultEntityController implementation.
76 * - base table: (used by DrupalDefaultEntityController) The name of the
4c686375 77 * entity type's base table.
66f93d71 78 * - revision table: The name of the entity type's revision table (if any).
539ba0dc 79 * - static cache: (used by DrupalDefaultEntityController) FALSE to disable
3f36af04 80 * static caching of entities during a page request. Defaults to TRUE.
d864fc63
DB
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.
4c686375
DB
85 * - load hook: The name of the hook which should be invoked by
86 * DrupalDefaultEntityController:attachLoad(), for example 'node_load'.
52195a6b
AB
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().
267b9c43 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.
66f93d71 100 * - fieldable: Set to TRUE if you want your entity type to accept fields
101 * being attached to it.
d073fa2a
AB
102 * - translation: An associative array of modules registered as field
103 * translation handlers. Array keys are the module names, array values
104 * can be any data structure the module uses to provide field translation.
105 * Any empty value disallows the module to appear as a translation handler.
7d4b84b8 106 * - entity keys: An array describing how the Field API can extract the
4c686375 107 * information it needs from the objects of the type. Elements:
3f36af04 108 * - id: The name of the property that contains the primary id of the
6c049009
DB
109 * entity. Every entity object passed to the Field API must have this
110 * property and its value must be numeric.
3f36af04 111 * - revision: The name of the property that contains the revision id of
6c049009
DB
112 * the entity. The Field API assumes that all revision ids are unique
113 * across all entities of a type. This entry can be omitted if the
114 * entities of this type are not versionable.
3f36af04 115 * - bundle: The name of the property that contains the bundle name for the
6c049009
DB
116 * entity. The bundle name defines which set of fields are attached to
117 * the entity (e.g. what nodes call "content type"). This entry can be
118 * omitted if this entity type exposes a single bundle (all entities have
ce08394b
DB
119 * the same collection of fields). The name of this single bundle will be
120 * the same as the entity type.
6d13ffa4 121 * - label: The name of the property that contains the entity label. For
b06d19e3 122 * example, if the entity's label is located in $entity->subject, then
6d13ffa4
AB
123 * 'subject' should be specified here. If complex logic is required to
124 * build the label, a 'label callback' should be defined instead (see
125 * the 'label callback' section above for details).
3f36af04 126 * - bundle keys: An array describing how the Field API can extract the
eeadb939
DB
127 * information it needs from the bundle objects for this type. This entry
128 * is required if the 'path' provided in the 'bundles'/'admin' section
129 * identifies the bundle using a named menu placeholder whose loader
130 * callback returns an object (e.g., $vocabulary for taxonomy terms, or
131 * $node_type for nodes). If the path does not include the bundle, or the
132 * bundle is just a string rather than an automatically loaded object, then
133 * this can be omitted. Elements:
134 * - bundle: The name of the property of the bundle object that contains
135 * the name of the bundle object.
6c049009
DB
136 * - bundles: An array describing all bundles for this object type. Keys are
137 * bundles machine names, as found in the objects' 'bundle' property
138 * (defined in the 'entity keys' entry above). Elements:
3f36af04 139 * - label: The human-readable name of the bundle.
ba96cffd
DB
140 * - uri callback: Same as the 'uri callback' key documented above for the
141 * entity type, but for the bundle only. When determining the URI of an
142 * entity, if a 'uri callback' is defined for both the entity type and
143 * the bundle, the one for the bundle is used.
ea51c321
DB
144 * - admin: An array of information that allows Field UI pages to attach
145 * themselves to the existing administration pages for the bundle.
e92e8ddb 146 * Elements:
3f36af04
DB
147 * - path: the path of the bundle's main administration page, as defined
148 * in hook_menu(). If the path includes a placeholder for the bundle,
eeadb939
DB
149 * the 'bundle argument' and 'real path' keys below are required.
150 * - bundle argument: The position of the bundle placeholder in 'path', if
151 * any.
3f36af04
DB
152 * - real path: The actual path (no placeholder) of the bundle's main
153 * administration page. This will be used to generate links.
154 * - access callback: As in hook_menu(). 'user_access' will be assumed if
155 * no value is provided.
156 * - access arguments: As in hook_menu().
53748ab5
DB
157 * - view modes: An array describing the view modes for the entity type. View
158 * modes let entities be displayed differently depending on the context.
159 * For instance, a node can be displayed differently on its own page
160 * ('full' mode), on the home page or taxonomy listings ('teaser' mode), or
161 * in an RSS feed ('rss' mode). Modules taking part in the display of the
162 * entity (notably the Field API) can adjust their behavior depending on
5ff0c0d3
DB
163 * the requested view mode. An additional 'default' view mode is available
164 * for all entity types. This view mode is not intended for actual entity
165 * display, but holds default display settings. For each available view
166 * mode, administrators can configure whether it should use its own set of
167 * field display settings, or just replicate the settings of the 'default'
168 * view mode, thus reducing the amount of display configurations to keep
169 * track of. Keys of the array are view mode names. Each view mode is
170 * described by an array with the following key/value pairs:
53748ab5 171 * - label: The human-readable name of the view mode
5ff0c0d3 172 * - custom settings: A boolean specifying whether the view mode should by
f9de90e1
DB
173 * default use its own custom field display settings. If FALSE, entities
174 * displayed in this view mode will reuse the 'default' display settings
175 * by default (e.g. right after the module exposing the view mode is
176 * enabled), but administrators can later use the Field UI to apply custom
177 * display settings specific to the view mode.
87f1bf45
DB
178 *
179 * @see entity_load()
180 * @see hook_entity_info_alter()
3f36af04
DB
181 */
182function hook_entity_info() {
183 $return = array(
184 'node' => array(
539ba0dc 185 'label' => t('Node'),
3f36af04
DB
186 'controller class' => 'NodeController',
187 'base table' => 'node',
539ba0dc 188 'revision table' => 'node_revision',
5ff0c0d3 189 'uri callback' => 'node_uri',
3f36af04 190 'fieldable' => TRUE,
d073fa2a
AB
191 'translation' => array(
192 'locale' => TRUE,
193 ),
7d4b84b8 194 'entity keys' => array(
539ba0dc
DB
195 'id' => 'nid',
196 'revision' => 'vid',
197 'bundle' => 'type',
198 ),
199 'bundle keys' => array(
200 'bundle' => 'type',
201 ),
539ba0dc
DB
202 'bundles' => array(),
203 'view modes' => array(
204 'full' => array(
5ff0c0d3
DB
205 'label' => t('Full content'),
206 'custom settings' => FALSE,
539ba0dc
DB
207 ),
208 'teaser' => array(
209 'label' => t('Teaser'),
5ff0c0d3 210 'custom settings' => TRUE,
539ba0dc
DB
211 ),
212 'rss' => array(
213 'label' => t('RSS'),
5ff0c0d3 214 'custom settings' => FALSE,
539ba0dc
DB
215 ),
216 ),
3f36af04
DB
217 ),
218 );
539ba0dc
DB
219
220 // Search integration is provided by node.module, so search-related
221 // view modes for nodes are defined here and not in search.module.
222 if (module_exists('search')) {
223 $return['node']['view modes'] += array(
224 'search_index' => array(
225 'label' => t('Search index'),
5ff0c0d3 226 'custom settings' => FALSE,
539ba0dc
DB
227 ),
228 'search_result' => array(
229 'label' => t('Search result'),
5ff0c0d3 230 'custom settings' => FALSE,
539ba0dc
DB
231 ),
232 );
233 }
234
235 // Bundles must provide a human readable name so we can create help and error
236 // messages, and the path to attach Field admin pages to.
237 foreach (node_type_get_names() as $type => $name) {
238 $return['node']['bundles'][$type] = array(
239 'label' => $name,
240 'admin' => array(
241 'path' => 'admin/structure/types/manage/%node_type',
242 'real path' => 'admin/structure/types/manage/' . str_replace('_', '-', $type),
243 'bundle argument' => 4,
244 'access arguments' => array('administer content types'),
245 ),
246 );
247 }
248
3f36af04
DB
249 return $return;
250}
251
252/**
253 * Alter the entity info.
254 *
255 * Modules may implement this hook to alter the information that defines an
256 * entity. All properties that are available in hook_entity_info() can be
257 * altered here.
258 *
3f36af04
DB
259 * @param $entity_info
260 * The entity info array, keyed by entity name.
87f1bf45
DB
261 *
262 * @see hook_entity_info()
3f36af04
DB
263 */
264function hook_entity_info_alter(&$entity_info) {
265 // Set the controller class for nodes to an alternate implementation of the
266 // DrupalEntityController interface.
267 $entity_info['node']['controller class'] = 'MyCustomNodeController';
268}
269
270/**
1c7bca0b
AB
271 * Act on entities when loaded.
272 *
273 * This is a generic load hook called for all entity types loaded via the
274 * entity API.
275 *
276 * @param $entities
277 * The entities keyed by entity ID.
278 * @param $type
279 * The type of entities being loaded (i.e. node, user, comment).
280 */
281function hook_entity_load($entities, $type) {
282 foreach ($entities as $entity) {
5674b54f 283 $entity->foo = mymodule_add_something($entity, $type);
1c7bca0b
AB
284 }
285}
286
287/**
71c4e3ec
AB
288 * Act on an entity before it is about to be created or updated.
289 *
290 * @param $entity
291 * The entity object.
292 * @param $type
293 * The type of entity being saved (i.e. node, user, comment).
294 */
295function hook_entity_presave($entity, $type) {
296 $entity->changed = REQUEST_TIME;
297}
298
299/**
02c1eeee
AB
300 * Act on entities when inserted.
301 *
02c1eeee
AB
302 * @param $entity
303 * The entity object.
304 * @param $type
305 * The type of entity being inserted (i.e. node, user, comment).
306 */
307function hook_entity_insert($entity, $type) {
91bc8bed
AB
308 // Insert the new entity into a fictional table of all entities.
309 $info = entity_get_info($type);
fee217fa 310 list($id) = entity_extract_ids($type, $entity);
91bc8bed
AB
311 db_insert('example_entity')
312 ->fields(array(
313 'type' => $type,
314 'id' => $id,
315 'created' => REQUEST_TIME,
316 'updated' => REQUEST_TIME,
317 ))
318 ->execute();
02c1eeee
AB
319}
320
321/**
322 * Act on entities when updated.
323 *
02c1eeee
AB
324 * @param $entity
325 * The entity object.
326 * @param $type
327 * The type of entity being updated (i.e. node, user, comment).
328 */
329function hook_entity_update($entity, $type) {
91bc8bed
AB
330 // Update the entity's entry in a fictional table of all entities.
331 $info = entity_get_info($type);
fee217fa 332 list($id) = entity_extract_ids($type, $entity);
91bc8bed
AB
333 db_update('example_entity')
334 ->fields(array(
335 'updated' => REQUEST_TIME,
336 ))
337 ->condition('type', $type)
338 ->condition('id', $id)
339 ->execute();
340}
341
342/**
343 * Act on entities when deleted.
344 *
345 * @param $entity
346 * The entity object.
347 * @param $type
348 * The type of entity being deleted (i.e. node, user, comment).
349 */
350function hook_entity_delete($entity, $type) {
351 // Delete the entity's entry from a fictional table of all entities.
352 $info = entity_get_info($type);
fee217fa 353 list($id) = entity_extract_ids($type, $entity);
91bc8bed
AB
354 db_delete('example_entity')
355 ->condition('type', $type)
356 ->condition('id', $id)
357 ->execute();
02c1eeee
AB
358}
359
360/**
9cf21be9
DB
361 * Alter or execute an EntityFieldQuery.
362 *
363 * @param EntityFieldQuery $query
364 * An EntityFieldQuery. One of the most important properties to be changed is
365 * EntityFieldQuery::executeCallback. If this is set to an existing function,
366 * this function will get the query as its single argument and its result
367 * will be the returned as the result of EntityFieldQuery::execute(). This can
368 * be used to change the behavior of EntityFieldQuery entirely. For example,
369 * the default implementation can only deal with one field storage engine, but
370 * it is possible to write a module that can query across field storage
371 * engines. Also, the default implementation presumes entities are stored in
372 * SQL, but the execute callback could instead query any other entity storage,
373 * local or remote.
0c33e863
AB
374 *
375 * Note the $query->altered attribute which is TRUE in case the query has
376 * already been altered once. This happens with cloned queries.
377 * If there is a pager, then such a cloned query will be executed to count
378 * all elements. This query can be detected by checking for
379 * ($query->pager && $query->count), allowing the driver to return 0 from
380 * the count query and disable the pager.
9cf21be9
DB
381 */
382function hook_entity_query_alter($query) {
383 $query->executeCallback = 'my_module_query_callback';
384}
385
386/**
43558501
AB
387 * Act on entities being assembled before rendering.
388 *
389 * @param $entity
390 * The entity object.
391 * @param $type
392 * The type of entity being rendered (i.e. node, user, comment).
393 * @param $view_mode
394 * The view mode the entity is rendered in.
395 * @param $langcode
396 * The language code used for rendering.
397 *
398 * The module may add elements to $entity->content prior to rendering. The
399 * structure of $entity->content is a renderable array as expected by
400 * drupal_render().
401 *
402 * @see hook_entity_view_alter()
403 * @see hook_comment_view()
404 * @see hook_node_view()
405 * @see hook_user_view()
406 */
407function hook_entity_view($entity, $type, $view_mode, $langcode) {
408 $entity->content['my_additional_field'] = array(
409 '#markup' => $additional_field,
410 '#weight' => 10,
411 '#theme' => 'mymodule_my_additional_field',
412 );
413}
414
415/**
416 * Alter the results of ENTITY_view().
417 *
418 * This hook is called after the content has been assembled in a structured
419 * array and may be used for doing processing which requires that the complete
420 * entity content structure has been built.
421 *
422 * If a module wishes to act on the rendered HTML of the entity rather than the
423 * structured content array, it may use this hook to add a #post_render
424 * callback. Alternatively, it could also implement hook_preprocess_ENTITY().
425 * See drupal_render() and theme() for details.
426 *
427 * @param $build
428 * A renderable array representing the entity content.
429 * @param $type
430 * The type of entity being rendered (i.e. node, user, comment).
431 *
432 * @see hook_entity_view()
433 * @see hook_comment_view_alter()
434 * @see hook_node_view_alter()
435 * @see hook_taxonomy_term_view_alter()
436 * @see hook_user_view_alter()
437 */
438function hook_entity_view_alter(&$build, $type) {
439 if ($build['#view_mode'] == 'full' && isset($build['an_additional_field'])) {
440 // Change its weight.
441 $build['an_additional_field']['#weight'] = -10;
442
443 // Add a #post_render callback to act on the rendered HTML of the entity.
444 $build['#post_render'][] = 'my_module_node_post_render';
445 }
446}
447
448/**
c9120083
AB
449 * Define administrative paths.
450 *
451 * Modules may specify whether or not the paths they define in hook_menu() are
452 * to be considered administrative. Other modules may use this information to
453 * display those pages differently (e.g. in a modal overlay, or in a different
454 * theme).
455 *
456 * To change the administrative status of menu items defined in another module's
457 * hook_menu(), modules should implement hook_admin_paths_alter().
458 *
459 * @return
460 * An associative array. For each item, the key is the path in question, in
461 * a format acceptable to drupal_match_path(). The value for each item should
462 * be TRUE (for paths considered administrative) or FALSE (for non-
463 * administrative paths).
464 *
465 * @see hook_menu()
466 * @see drupal_match_path()
467 * @see hook_admin_paths_alter()
468 */
469function hook_admin_paths() {
470 $paths = array(
471 'mymodule/*/add' => TRUE,
472 'mymodule/*/edit' => TRUE,
473 );
474 return $paths;
475}
476
477/**
478 * Redefine administrative paths defined by other modules.
479 *
480 * @param $paths
481 * An associative array of administrative paths, as defined by implementations
482 * of hook_admin_paths().
483 *
484 * @see hook_admin_paths()
485 */
486function hook_admin_paths_alter(&$paths) {
487 // Treat all user pages as administrative.
488 $paths['user'] = TRUE;
489 $paths['user/*'] = TRUE;
490 // Treat the forum topic node form as a non-administrative page.
491 $paths['node/add/forum'] = FALSE;
492}
493
494/**
3a0f6b33
AB
495 * Act on entities as they are being prepared for view.
496 *
497 * Allows you to operate on multiple entities as they are being prepared for
498 * view. Only use this if attaching the data during the entity_load() phase
499 * is not appropriate, for example when attaching other 'entity' style objects.
500 *
501 * @param $entities
502 * The entities keyed by entity ID.
503 * @param $type
504 * The type of entities being loaded (i.e. node, user, comment).
75a0deb2 505 * @param $langcode
506 * The language to display the entity in.
3a0f6b33 507 */
75a0deb2 508function hook_entity_prepare_view($entities, $type, $langcode) {
3a0f6b33
AB
509 // Load a specific node into the user object for later theming.
510 if ($type == 'user') {
511 $nodes = mymodule_get_user_nodes(array_keys($entities));
512 foreach ($entities as $uid => $entity) {
513 $entity->user_node = $nodes[$uid];
514 }
515 }
516}
517
518/**
66df6025
AB
519 * Perform periodic actions.
520 *
f1b30b89
AB
521 * Modules that require some commands to be executed periodically can
522 * implement hook_cron(). The engine will then call the hook whenever a cron
523 * run happens, as defined by the administrator. Typical tasks managed by
524 * hook_cron() are database maintenance, backups, recalculation of settings
525 * or parameters, automated mailing, and retrieving remote data.
66df6025 526 *
f1b30b89
AB
527 * Short-running or non-resource-intensive tasks can be executed directly in
528 * the hook_cron() implementation.
9e638424 529 *
f1b30b89
AB
530 * Long-running tasks and tasks that could time out, such as retrieving remote
531 * data, sending email, and intensive file tasks, should use the queue API
532 * instead of executing the tasks directly. To do this, first define one or
533 * more queues via hook_cron_queue_info(). Then, add items that need to be
534 * processed to the defined queues.
66df6025
AB
535 */
536function hook_cron() {
9e638424
DB
537 // Short-running operation example, not using a queue:
538 // Delete all expired records since the last cron run.
539 $expires = variable_get('mymodule_cron_last_run', REQUEST_TIME);
540 db_delete('mymodule_table')
541 ->condition('expires', $expires, '>=')
542 ->execute();
543 variable_set('mymodule_cron_last_run', REQUEST_TIME);
66df6025 544
9e638424
DB
545 // Long-running operation example, leveraging a queue:
546 // Fetch feeds from other sites.
5dedc4c4 547 $result = db_query('SELECT * FROM {aggregator_feed} WHERE checked + refresh < :time AND refresh <> :never', array(
9e638424
DB
548 ':time' => REQUEST_TIME,
549 ':never' => AGGREGATOR_CLEAR_NEVER,
550 ));
551 $queue = DrupalQueue::get('aggregator_feeds');
552 foreach ($result as $feed) {
553 $queue->createItem($feed);
66df6025
AB
554 }
555}
556
557/**
762be09f
DB
558 * Declare queues holding items that need to be run periodically.
559 *
560 * While there can be only one hook_cron() process running at the same time,
561 * there can be any number of processes defined here running. Because of
562 * this, long running tasks are much better suited for this API. Items queued
9e638424
DB
563 * in hook_cron() might be processed in the same cron run if there are not many
564 * items in the queue, otherwise it might take several requests, which can be
565 * run in parallel.
762be09f
DB
566 *
567 * @return
568 * An associative array where the key is the queue name and the value is
569 * again an associative array. Possible keys are:
9e638424
DB
570 * - 'worker callback': The name of the function to call. It will be called
571 * with one argument, the item created via DrupalQueue::createItem() in
572 * hook_cron().
573 * - 'time': (optional) How much time Drupal should spend on calling this
574 * worker in seconds. Defaults to 15.
575 *
576 * @see hook_cron()
3cd6a773 577 * @see hook_cron_queue_info_alter()
762be09f
DB
578 */
579function hook_cron_queue_info() {
580 $queues['aggregator_feeds'] = array(
581 'worker callback' => 'aggregator_refresh',
3cd6a773 582 'time' => 60,
762be09f
DB
583 );
584 return $queues;
585}
586
587/**
3cd6a773
DB
588 * Alter cron queue information before cron runs.
589 *
bdffe481 590 * Called by drupal_cron_run() to allow modules to alter cron queue settings
3cd6a773
DB
591 * before any jobs are processesed.
592 *
593 * @param array $queues
594 * An array of cron queue information.
595 *
ba6d89a4
DB
596 * @see hook_cron_queue_info()
597 * @see drupal_cron_run()
3cd6a773
DB
598 */
599function hook_cron_queue_info_alter(&$queues) {
600 // This site has many feeds so let's spend 90 seconds on each cron run
601 // updating feeds instead of the default 60.
602 $queues['aggregator_feeds']['time'] = 90;
603}
604
605/**
66df6025
AB
606 * Allows modules to declare their own Forms API element types and specify their
607 * default values.
608 *
609 * This hook allows modules to declare their own form element types and to
610 * specify their default values. The values returned by this hook will be
611 * merged with the elements returned by hook_form() implementations and so
612 * can return defaults for any Form APIs keys in addition to those explicitly
613 * mentioned below.
614 *
615 * Each of the form element types defined by this hook is assumed to have
616 * a matching theme function, e.g. theme_elementtype(), which should be
617 * registered with hook_theme() as normal.
618 *
6f1a855a 619 * For more information about custom element types see the explanation at
66df6025
AB
620 * http://drupal.org/node/169815.
621 *
622 * @return
623 * An associative array describing the element types being defined. The array
624 * contains a sub-array for each element type, with the machine-readable type
625 * name as the key. Each sub-array has a number of possible attributes:
626 * - "#input": boolean indicating whether or not this element carries a value
627 * (even if it's hidden).
2ac0eb58
DB
628 * - "#process": array of callback functions taking $element, $form_state,
629 * and $complete_form.
66df6025
AB
630 * - "#after_build": array of callback functions taking $element and $form_state.
631 * - "#validate": array of callback functions taking $form and $form_state.
632 * - "#element_validate": array of callback functions taking $element and
633 * $form_state.
634 * - "#pre_render": array of callback functions taking $element and $form_state.
635 * - "#post_render": array of callback functions taking $element and $form_state.
636 * - "#submit": array of callback functions taking $form and $form_state.
99833c62
DB
637 * - "#title_display": optional string indicating if and how #title should be
638 * displayed, see theme_form_element() and theme_form_element_label().
d481f1cd
DB
639 *
640 * @see hook_element_info_alter()
641 * @see system_element_info()
66df6025 642 */
d481f1cd
DB
643function hook_element_info() {
644 $types['filter_format'] = array(
645 '#input' => TRUE,
646 );
647 return $types;
66df6025
AB
648}
649
650/**
dbb5457c
AB
651 * Alter the element type information returned from modules.
652 *
653 * A module may implement this hook in order to alter the element type defaults
654 * defined by a module.
655 *
a22d7770 656 * @param $type
d481f1cd 657 * All element type defaults as collected by hook_element_info().
dbb5457c 658 *
d481f1cd 659 * @see hook_element_info()
dbb5457c
AB
660 */
661function hook_element_info_alter(&$type) {
662 // Decrease the default size of textfields.
663 if (isset($type['textfield']['#size'])) {
664 $type['textfield']['#size'] = 40;
665 }
666}
667
668/**
66df6025
AB
669 * Perform cleanup tasks.
670 *
671 * This hook is run at the end of each page request. It is often used for
24c259cd 672 * page logging and specialized cleanup. This hook MUST NOT print anything.
66df6025
AB
673 *
674 * Only use this hook if your code must run even for cached page views.
7f0feebe
DB
675 * If you have code which must run once on all non-cached pages, use
676 * hook_init() instead. That is the usual case. If you implement this hook
66df6025
AB
677 * and see an error like 'Call to undefined function', it is likely that
678 * you are depending on the presence of a module which has not been loaded yet.
679 * It is not loaded because Drupal is still in bootstrap mode.
680 *
681 * @param $destination
682 * If this hook is invoked as part of a drupal_goto() call, then this argument
683 * will be a fully-qualified URL that is the destination of the redirect.
66df6025
AB
684 */
685function hook_exit($destination = NULL) {
196da1b8
DB
686 db_update('counter')
687 ->expression('hits', 'hits + 1')
688 ->condition('type', 1)
689 ->execute();
66df6025
AB
690}
691
692/**
66df6025
AB
693 * Perform necessary alterations to the JavaScript before it is presented on
694 * the page.
695 *
696 * @param $javascript
697 * An array of all JavaScript being presented on the page.
d428fe37 698 *
66df6025
AB
699 * @see drupal_add_js()
700 * @see drupal_get_js()
701 * @see drupal_js_defaults()
702 */
703function hook_js_alter(&$javascript) {
704 // Swap out jQuery to use an updated version of the library.
705 $javascript['misc/jquery.js']['data'] = drupal_get_path('module', 'jquery_update') . '/jquery.js';
706}
707
708/**
4a4a6570
AB
709 * Registers JavaScript/CSS libraries associated with a module.
710 *
711 * Modules implementing this return an array of arrays. The key to each
712 * sub-array is the machine readable name of the library. Each library may
713 * contain the following items:
714 *
715 * - 'title': The human readable name of the library.
716 * - 'website': The URL of the library's web site.
717 * - 'version': A string specifying the version of the library; intentionally
718 * not a float because a version like "1.2.3" is not a valid float. Use PHP's
719 * version_compare() to compare different versions.
720 * - 'js': An array of JavaScript elements; each element's key is used as $data
721 * argument, each element's value is used as $options array for
722 * drupal_add_js(). To add library-specific (not module-specific) JavaScript
723 * settings, the key may be skipped, the value must specify
724 * 'type' => 'setting', and the actual settings must be contained in a 'data'
725 * element of the value.
726 * - 'css': Like 'js', an array of CSS elements passed to drupal_add_css().
727 * - 'dependencies': An array of libraries that are required for a library. Each
648d8ab8
DB
728 * element is an array listing the module and name of another library. Note
729 * that all dependencies for each dependent library will also be added when
730 * this library is added.
4a4a6570
AB
731 *
732 * Registered information for a library should contain re-usable data only.
733 * Module- or implementation-specific data and integration logic should be added
734 * separately.
735 *
736 * @return
737 * An array defining libraries associated with a module.
738 *
739 * @see system_library()
740 * @see drupal_add_library()
741 * @see drupal_get_library()
742 */
743function hook_library() {
744 // Library One.
745 $libraries['library-1'] = array(
746 'title' => 'Library One',
747 'website' => 'http://example.com/library-1',
748 'version' => '1.2',
749 'js' => array(
750 drupal_get_path('module', 'my_module') . '/library-1.js' => array(),
751 ),
752 'css' => array(
753 drupal_get_path('module', 'my_module') . '/library-2.css' => array(
754 'type' => 'file',
755 'media' => 'screen',
756 ),
757 ),
758 );
759 // Library Two.
760 $libraries['library-2'] = array(
761 'title' => 'Library Two',
762 'website' => 'http://example.com/library-2',
763 'version' => '3.1-beta1',
764 'js' => array(
765 // JavaScript settings may use the 'data' key.
766 array(
767 'type' => 'setting',
768 'data' => array('library2' => TRUE),
769 ),
770 ),
771 'dependencies' => array(
772 // Require jQuery UI core by System module.
648d8ab8 773 array('system', 'ui'),
4a4a6570
AB
774 // Require our other library.
775 array('my_module', 'library-1'),
776 // Require another library.
777 array('other_module', 'library-3'),
778 ),
779 );
780 return $libraries;
781}
782
783/**
784 * Alters the JavaScript/CSS library registry.
785 *
786 * Allows certain, contributed modules to update libraries to newer versions
787 * while ensuring backwards compatibility. In general, such manipulations should
788 * only be done by designated modules, since most modules that integrate with a
789 * certain library also depend on the API of a certain library version.
790 *
791 * @param $libraries
792 * The JavaScript/CSS libraries provided by $module. Keyed by internal library
793 * name and passed by reference.
794 * @param $module
795 * The name of the module that registered the libraries.
796 *
797 * @see hook_library()
798 */
799function hook_library_alter(&$libraries, $module) {
800 // Update Farbtastic to version 2.0.
801 if ($module == 'system' && isset($libraries['farbtastic'])) {
802 // Verify existing version is older than the one we are updating to.
803 if (version_compare($libraries['farbtastic']['version'], '2.0', '<')) {
804 // Update the existing Farbtastic to version 2.0.
805 $libraries['farbtastic']['version'] = '2.0';
806 $libraries['farbtastic']['js'] = array(
807 drupal_get_path('module', 'farbtastic_update') . '/farbtastic-2.0.js' => array(),
808 );
809 }
810 }
811}
812
813/**
1a5c71e2
DB
814 * Alter CSS files before they are output on the page.
815 *
816 * @param $css
817 * An array of all CSS items (files and inline CSS) being requested on the page.
d428fe37 818 *
1a5c71e2
DB
819 * @see drupal_add_css()
820 * @see drupal_get_css()
821 */
822function hook_css_alter(&$css) {
823 // Remove defaults.css file.
824 unset($css[drupal_get_path('module', 'system') . '/defaults.css']);
825}
826
827/**
fa39282e 828 * Alter the commands that are sent to the user through the Ajax framework.
1fed2bf2
AB
829 *
830 * @param $commands
831 * An array of all commands that will be sent to the user.
d428fe37 832 *
1fed2bf2
AB
833 * @see ajax_render()
834 */
835function hook_ajax_render_alter($commands) {
836 // Inject any new status messages into the content area.
837 $commands[] = ajax_command_prepend('#block-system-main .content', theme('status_messages'));
838}
839
840/**
a244b45c
AB
841 * Add elements to a page before it is rendered.
842 *
843 * Use this hook when you want to add elements at the page level. For your
844 * additions to be printed, they have to be placed below a top level array key
845 * of the $page array that has the name of a region of the active theme.
846 *
847 * By default, valid region keys are 'page_top', 'header', 'sidebar_first',
848 * 'content', 'sidebar_second' and 'page_bottom'. To get a list of all regions
849 * of the active theme, use system_region_list($theme). Note that $theme is a
850 * global variable.
851 *
852 * If you want to alter the elements added by other modules or if your module
853 * depends on the elements of other modules, use hook_page_alter() instead which
854 * runs after this hook.
855 *
856 * @param $page
857 * Nested array of renderable elements that make up the page.
858 *
859 * @see hook_page_alter()
860 * @see drupal_render_page()
861 */
862function hook_page_build(&$page) {
863 if (menu_get_object('node', 1)) {
864 // We are on a node detail page. Append a standard disclaimer to the
865 // content region.
866 $page['content']['disclaimer'] = array(
867 '#markup' => t('Acme, Inc. is not responsible for the contents of this sample code.'),
868 '#weight' => 25,
869 );
870 }
871}
872
873/**
9b3c8c52
AB
874 * Alter a menu router item right after it has been retrieved from the database or cache.
875 *
876 * This hook is invoked by menu_get_item() and allows for run-time alteration of router
877 * information (page_callback, title, and so on) before it is translated and checked for
8cdf750e 878 * access. The passed-in $router_item is statically cached for the current request, so this
9b3c8c52
AB
879 * hook is only invoked once for any router item that is retrieved via menu_get_item().
880 *
881 * Usually, modules will only want to inspect the router item and conditionally
882 * perform other actions (such as preparing a state for the current request).
883 * Note that this hook is invoked for any router item that is retrieved by
884 * menu_get_item(), which may or may not be called on the path itself, so implementations
885 * should check the $path parameter if the alteration should fire for the current request
886 * only.
887 *
888 * @param $router_item
889 * The menu router item for $path.
890 * @param $path
891 * The originally passed path, for which $router_item is responsible.
892 * @param $original_map
893 * The path argument map, as contained in $path.
894 *
895 * @see menu_get_item()
896 */
897function hook_menu_get_item_alter(&$router_item, $path, $original_map) {
898 // When retrieving the router item for the current path...
899 if ($path == $_GET['q']) {
900 // ...call a function that prepares something for this request.
901 mymodule_prepare_something();
902 }
903}
904
905/**
5c5bd803
AB
906 * Define menu items and page callbacks.
907 *
908 * This hook enables modules to register paths in order to define how URL
909 * requests are handled. Paths may be registered for URL handling only, or they
910 * can register a link to be placed in a menu (usually the Navigation menu). A
911 * path and its associated information is commonly called a "menu router item".
912 * This hook is rarely called (for example, when modules are enabled), and
913 * its results are cached in the database.
914 *
915 * hook_menu() implementations return an associative array whose keys define
916 * paths and whose values are an associative array of properties for each
917 * path. (The complete list of properties is in the return value section below.)
918 *
919 * The definition for each path may include a page callback function, which is
920 * invoked when the registered path is requested. If there is no other
921 * registered path that fits the requested path better, any further path
922 * components are passed to the callback function. For example, your module
923 * could register path 'abc/def':
924 * @code
925 * function mymodule_menu() {
926 * $items['abc/def'] = array(
927 * 'page callback' => 'mymodule_abc_view',
928 * );
20b62b29 929 * return $items;
5c5bd803
AB
930 * }
931 *
932 * function mymodule_abc_view($ghi = 0, $jkl = '') {
933 * // ...
934 * }
935 * @endcode
936 * When path 'abc/def' is requested, no further path components are in the
937 * request, and no additional arguments are passed to the callback function (so
938 * $ghi and $jkl would take the default values as defined in the function
939 * signature). When 'abc/def/123/foo' is requested, $ghi will be '123' and
940 * $jkl will be 'foo'. Note that this automatic passing of optional path
941 * arguments applies only to page and theme callback functions.
942 *
943 * In addition to optional path arguments, the page callback and other callback
944 * functions may specify argument lists as arrays. These argument lists may
945 * contain both fixed/hard-coded argument values and integers that correspond
946 * to path components. When integers are used and the callback function is
947 * called, the corresponding path components will be substituted for the
948 * integers. That is, the integer 0 in an argument list will be replaced with
949 * the first path component, integer 1 with the second, and so on (path
e45c7803 950 * components are numbered starting from zero). To pass an integer without it
951 * being replaced with its respective path component, use the string value of
952 * the integer (e.g., '1') as the argument value. This substitution feature
953 * allows you to re-use a callback function for several different paths. For
954 * example:
5c5bd803
AB
955 * @code
956 * function mymodule_menu() {
957 * $items['abc/def'] = array(
958 * 'page callback' => 'mymodule_abc_view',
959 * 'page arguments' => array(1, 'foo'),
960 * );
20b62b29 961 * return $items;
5c5bd803
AB
962 * }
963 * @endcode
964 * When path 'abc/def' is requested, the page callback function will get 'def'
965 * as the first argument and (always) 'foo' as the second argument.
966 *
9de419ad 967 * If a page callback function uses an argument list array, and its path is
968 * requested with optional path arguments, then the list array's arguments are
969 * passed to the callback function first, followed by the optional path
970 * arguments. Using the above example, when path 'abc/def/bar/baz' is requested,
971 * mymodule_abc_view() will be called with 'def', 'foo', 'bar' and 'baz' as
972 * arguments, in that order.
5c5bd803
AB
973 *
974 * Special care should be taken for the page callback drupal_get_form(), because
975 * your specific form callback function will always receive $form and
976 * &$form_state as the first function arguments:
977 * @code
978 * function mymodule_abc_form($form, &$form_state) {
979 * // ...
980 * return $form;
981 * }
982 * @endcode
983 * See @link form_api Form API documentation @endlink for details.
984 *
985 * Wildcards within paths also work with integer substitution. For example,
986 * your module could register path 'my-module/%/edit':
987 * @code
988 * $items['my-module/%/edit'] = array(
989 * 'page callback' => 'mymodule_abc_edit',
990 * 'page arguments' => array(1),
991 * );
992 * @endcode
993 * When path 'my-module/foo/edit' is requested, integer 1 will be replaced
ac274733
D
994 * with 'foo' and passed to the callback function. Note that wildcards may not
995 * be used as the first component.
5c5bd803
AB
996 *
997 * Registered paths may also contain special "auto-loader" wildcard components
998 * in the form of '%mymodule_abc', where the '%' part means that this path
999 * component is a wildcard, and the 'mymodule_abc' part defines the prefix for a
1000 * load function, which here would be named mymodule_abc_load(). When a matching
1001 * path is requested, your load function will receive as its first argument the
1002 * path component in the position of the wildcard; load functions may also be
1003 * passed additional arguments (see "load arguments" in the return value
1004 * section below). For example, your module could register path
1005 * 'my-module/%mymodule_abc/edit':
1006 * @code
1007 * $items['my-module/%mymodule_abc/edit'] = array(
1008 * 'page callback' => 'mymodule_abc_edit',
1009 * 'page arguments' => array(1),
1010 * );
1011 * @endcode
1012 * When path 'my-module/123/edit' is requested, your load function
1013 * mymodule_abc_load() will be invoked with the argument '123', and should
1014 * load and return an "abc" object with internal id 123:
1015 * @code
1016 * function mymodule_abc_load($abc_id) {
1017 * return db_query("SELECT * FROM {mymodule_abc} WHERE abc_id = :abc_id", array(':abc_id' => $abc_id))->fetchObject();
1018 * }
1019 * @endcode
aeb6712b
DB
1020 * This 'abc' object will then be passed into the callback functions defined
1021 * for the menu item, such as the page callback function mymodule_abc_edit()
2c51f2d6 1022 * to replace the integer 1 in the argument array. Note that a load function
1023 * should return FALSE when it is unable to provide a loadable object. For
1024 * example, the node_load() function for the 'node/%node/edit' menu item will
1025 * return FALSE for the path 'node/999/edit' if a node with a node ID of 999
1026 * does not exist. The menu routing system will return a 404 error in this case.
aeb6712b
DB
1027 *
1028 * You can also define a %wildcard_to_arg() function (for the example menu
1029 * entry above this would be 'mymodule_abc_to_arg()'). The _to_arg() function
1030 * is invoked to retrieve a value that is used in the path in place of the
1031 * wildcard. A good example is user.module, which defines
1032 * user_uid_optional_to_arg() (corresponding to the menu entry
1033 * 'user/%user_uid_optional'). This function returns the user ID of the
1034 * current user.
1035 *
1036 * The _to_arg() function will get called with three arguments:
1037 * - $arg: A string representing whatever argument may have been supplied by
1038 * the caller (this is particularly useful if you want the _to_arg()
1039 * function only supply a (default) value if no other value is specified,
1040 * as in the case of user_uid_optional_to_arg().
1041 * - $map: An array of all path fragments (e.g. array('node','123','edit') for
1042 * 'node/123/edit').
1043 * - $index: An integer indicating which element of $map corresponds to $arg.
1044 *
1045 * _load() and _to_arg() functions may seem similar at first glance, but they
1046 * have different purposes and are called at different times. _load()
1047 * functions are called when the menu system is collecting arguments to pass
1048 * to the callback functions defined for the menu item. _to_arg() functions
1049 * are called when the menu system is generating links to related paths, such
1050 * as the tabs for a set of MENU_LOCAL_TASK items.
5c5bd803
AB
1051 *
1052 * You can also make groups of menu items to be rendered (by default) as tabs
1053 * on a page. To do that, first create one menu item of type MENU_NORMAL_ITEM,
1054 * with your chosen path, such as 'foo'. Then duplicate that menu item, using a
1055 * subdirectory path, such as 'foo/tab1', and changing the type to
1056 * MENU_DEFAULT_LOCAL_TASK to make it the default tab for the group. Then add
1057 * the additional tab items, with paths such as "foo/tab2" etc., with type
1058 * MENU_LOCAL_TASK. Example:
1059 * @code
1060 * // Make "Foo settings" appear on the admin Config page
c8334a08 1061 * $items['admin/config/system/foo'] = array(
5c5bd803
AB
1062 * 'title' => 'Foo settings',
1063 * 'type' => MENU_NORMAL_ITEM,
24de8090 1064 * // Page callback, etc. need to be added here.
5c5bd803 1065 * );
c8334a08
DB
1066 * // Make "Tab 1" the main tab on the "Foo settings" page
1067 * $items['admin/config/system/foo/tab1'] = array(
1068 * 'title' => 'Tab 1',
5c5bd803 1069 * 'type' => MENU_DEFAULT_LOCAL_TASK,
24de8090 1070 * // Access callback, page callback, and theme callback will be inherited
c8334a08 1071 * // from 'admin/config/system/foo', if not specified here to override.
5c5bd803 1072 * );
c8334a08
DB
1073 * // Make an additional tab called "Tab 2" on "Foo settings"
1074 * $items['admin/config/system/foo/tab2'] = array(
1075 * 'title' => 'Tab 2',
5c5bd803 1076 * 'type' => MENU_LOCAL_TASK,
24de8090 1077 * // Page callback and theme callback will be inherited from
c8334a08 1078 * // 'admin/config/system/foo', if not specified here to override.
24de8090 1079 * // Need to add access callback or access arguments.
5c5bd803
AB
1080 * );
1081 * @endcode
1082 *
1083 * @return
1084 * An array of menu items. Each menu item has a key corresponding to the
1085 * Drupal path being registered. The corresponding array value is an
1086 * associative array that may contain the following key-value pairs:
1087 * - "title": Required. The untranslated title of the menu item.
1088 * - "title callback": Function to generate the title; defaults to t().
1089 * If you require only the raw string to be output, set this to FALSE.
1090 * - "title arguments": Arguments to send to t() or your custom callback,
1091 * with path component substitution as described above.
1092 * - "description": The untranslated description of the menu item.
1093 * - "page callback": The function to call to display a web page when the user
1094 * visits the path. If omitted, the parent menu item's callback will be used
1095 * instead.
1096 * - "page arguments": An array of arguments to pass to the page callback
1097 * function, with path component substitution as described above.
1098 * - "delivery callback": The function to call to package the result of the
1099 * page callback function and send it to the browser. Defaults to
1100 * drupal_deliver_html_page() unless a value is inherited from a parent menu
98745678
AB
1101 * item. Note that this function is called even if the access checks fail,
1102 * so any custom delivery callback function should take that into account.
1103 * See drupal_deliver_html_page() for an example.
a6cb5bbf
DB
1104 * - "access callback": A function returning TRUE if the user has access
1105 * rights to this menu item, and FALSE if not. It can also be a boolean
1106 * constant instead of a function, and you can also use numeric values
1107 * (will be cast to boolean). Defaults to user_access() unless a value is
24de8090
AB
1108 * inherited from the parent menu item; only MENU_DEFAULT_LOCAL_TASK items
1109 * can inherit access callbacks. To use the user_access() default callback,
1110 * you must specify the permission to check as 'access arguments' (see
1111 * below).
5c5bd803 1112 * - "access arguments": An array of arguments to pass to the access callback
24de8090
AB
1113 * function, with path component substitution as described above. If the
1114 * access callback is inherited (see above), the access arguments will be
1115 * inherited with it, unless overridden in the child menu item.
a6cb5bbf 1116 * - "theme callback": (optional) A function returning the machine-readable
84c72d06
DB
1117 * name of the theme that will be used to render the page. If not provided,
1118 * the value will be inherited from a parent menu item. If there is no
1119 * theme callback, or if the function does not return the name of a current
1120 * active theme on the site, the theme for this page will be determined by
1121 * either hook_custom_theme() or the default theme instead. As a general
1122 * rule, the use of theme callback functions should be limited to pages
1123 * whose functionality is very closely tied to a particular theme, since
1124 * they can only be overridden by modules which specifically target those
1125 * pages in hook_menu_alter(). Modules implementing more generic theme
1126 * switching functionality (for example, a module which allows the theme to
1127 * be set dynamically based on the current user's role) should use
1128 * hook_custom_theme() instead.
5c5bd803
AB
1129 * - "theme arguments": An array of arguments to pass to the theme callback
1130 * function, with path component substitution as described above.
1131 * - "file": A file that will be included before the page callback is called;
1132 * this allows page callback functions to be in separate files. The file
1133 * should be relative to the implementing module's directory unless
1134 * otherwise specified by the "file path" option. Does not apply to other
1135 * callbacks (only page callback).
1136 * - "file path": The path to the directory containing the file specified in
1137 * "file". This defaults to the path to the module implementing the hook.
1138 * - "load arguments": An array of arguments to be passed to each of the
1139 * wildcard object loaders in the path, after the path argument itself.
1140 * For example, if a module registers path node/%node/revisions/%/view
1141 * with load arguments set to array(3), the '%node' in the path indicates
1142 * that the loader function node_load() will be called with the second
1143 * path component as the first argument. The 3 in the load arguments
1144 * indicates that the fourth path component will also be passed to
1145 * node_load() (numbering of path components starts at zero). So, if path
1146 * node/12/revisions/29/view is requested, node_load(12, 29) will be called.
1147 * There are also two "magic" values that can be used in load arguments.
1148 * "%index" indicates the index of the wildcard path component. "%map"
1149 * indicates the path components as an array. For example, if a module
1150 * registers for several paths of the form 'user/%user_category/edit/*', all
1151 * of them can use the same load function user_category_load(), by setting
1152 * the load arguments to array('%map', '%index'). For instance, if the user
1153 * is editing category 'foo' by requesting path 'user/32/edit/foo', the load
1154 * function user_category_load() will be called with 32 as its first
1155 * argument, the array ('user', 32, 'edit', 'foo') as the map argument,
1156 * and 1 as the index argument (because %user_category is the second path
1157 * component and numbering starts at zero). user_category_load() can then
1158 * use these values to extract the information that 'foo' is the category
1159 * being requested.
1160 * - "weight": An integer that determines the relative position of items in
1161 * the menu; higher-weighted items sink. Defaults to 0. Menu items with the
1162 * same weight are ordered alphabetically.
1163 * - "menu_name": Optional. Set this to a custom menu if you don't want your
1164 * item to be placed in Navigation.
1165 * - "context": (optional) Defines the context a tab may appear in. By
1166 * default, all tabs are only displayed as local tasks when being rendered
1167 * in a page context. All tabs that should be accessible as contextual links
1168 * in page region containers outside of the parent menu item's primary page
1169 * context should be registered using one of the following contexts:
1170 * - MENU_CONTEXT_PAGE: (default) The tab is displayed as local task for the
1171 * page context only.
1172 * - MENU_CONTEXT_INLINE: The tab is displayed as contextual link outside of
1173 * the primary page context only.
1174 * Contexts can be combined. For example, to display a tab both on a page
1175 * and inline, a menu router item may specify:
1176 * @code
1177 * 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
1178 * @endcode
1179 * - "tab_parent": For local task menu items, the path of the task's parent
1180 * item; defaults to the same path without the last component (e.g., the
1181 * default parent for 'admin/people/create' is 'admin/people').
1182 * - "tab_root": For local task menu items, the path of the closest non-tab
1183 * item; same default as "tab_parent".
5c5bd803
AB
1184 * - "position": Position of the block ('left' or 'right') on the system
1185 * administration page for this item.
1186 * - "type": A bitmask of flags describing properties of the menu item.
1187 * Many shortcut bitmasks are provided as constants in menu.inc:
1188 * - MENU_NORMAL_ITEM: Normal menu items show up in the menu tree and can be
1189 * moved/hidden by the administrator.
1190 * - MENU_CALLBACK: Callbacks simply register a path so that the correct
1191 * information is generated when the path is accessed.
1192 * - MENU_SUGGESTED_ITEM: Modules may "suggest" menu items that the
1193 * administrator may enable.
1194 * - MENU_LOCAL_ACTION: Local actions are menu items that describe actions
1195 * on the parent item such as adding a new user or block, and are
1196 * rendered in the action-links list in your theme.
1197 * - MENU_LOCAL_TASK: Local tasks are menu items that describe different
1198 * displays of data, and are generally rendered as tabs.
1199 * - MENU_DEFAULT_LOCAL_TASK: Every set of local tasks should provide one
1200 * "default" task, which should display the same page as the parent item.
1201 * If the "type" element is omitted, MENU_NORMAL_ITEM is assumed.
5eb6a99c 1202 * - "options": An array of options to be passed to l() when generating a link
a5f9c985
D
1203 * from this menu item. Note that the "options" parameter has no effect on
1204 * MENU_LOCAL_TASK, MENU_DEFAULT_LOCAL_TASK, and MENU_LOCAL_ACTION items.
5c5bd803
AB
1205 *
1206 * For a detailed usage example, see page_example.module.
1207 * For comprehensive documentation on the menu system, see
1208 * http://drupal.org/node/102338.
1209 */
1210function hook_menu() {
1211 $items['blog'] = array(
1212 'title' => 'blogs',
1213 'page callback' => 'blog_page',
1214 'access arguments' => array('access content'),
1215 'type' => MENU_SUGGESTED_ITEM,
1216 );
1217 $items['blog/feed'] = array(
1218 'title' => 'RSS feed',
1219 'page callback' => 'blog_feed',
1220 'access arguments' => array('access content'),
1221 'type' => MENU_CALLBACK,
1222 );
1223
1224 return $items;
1225}
1226
1227/**
1228 * Alter the data being saved to the {menu_router} table after hook_menu is invoked.
1229 *
1230 * This hook is invoked by menu_router_build(). The menu definitions are passed
1231 * in by reference. Each element of the $items array is one item returned
1232 * by a module from hook_menu. Additional items may be added, or existing items
1233 * altered.
1234 *
1235 * @param $items
1236 * Associative array of menu router definitions returned from hook_menu().
1237 */
1238function hook_menu_alter(&$items) {
1239 // Example - disable the page at node/add
1240 $items['node/add']['access callback'] = FALSE;
1241}
1242
1243/**
1244 * Alter the data being saved to the {menu_links} table by menu_link_save().
1245 *
1246 * @param $item
1247 * Associative array defining a menu link as passed into menu_link_save().
f3ab0a0f
DB
1248 *
1249 * @see hook_translated_menu_link_alter()
5c5bd803
AB
1250 */
1251function hook_menu_link_alter(&$item) {
f3ab0a0f 1252 // Make all new admin links hidden (a.k.a disabled).
5c5bd803
AB
1253 if (strpos($item['link_path'], 'admin') === 0 && empty($item['mlid'])) {
1254 $item['hidden'] = 1;
1255 }
f3ab0a0f 1256 // Flag a link to be altered by hook_translated_menu_link_alter().
5c5bd803
AB
1257 if ($item['link_path'] == 'devel/cache/clear') {
1258 $item['options']['alter'] = TRUE;
1259 }
f3ab0a0f
DB
1260 // Flag a link to be altered by hook_translated_menu_link_alter(), but only
1261 // if it is derived from a menu router item; i.e., do not alter a custom
1262 // menu link pointing to the same path that has been created by a user.
1263 if ($item['link_path'] == 'user' && $item['module'] == 'system') {
1264 $item['options']['alter'] = TRUE;
1265 }
5c5bd803
AB
1266}
1267
1268/**
f3ab0a0f
DB
1269 * Alter a menu link after it has been translated and before it is rendered.
1270 *
1271 * This hook is invoked from _menu_link_translate() after a menu link has been
1272 * translated; i.e., after dynamic path argument placeholders (%) have been
1273 * replaced with actual values, the user access to the link's target page has
1274 * been checked, and the link has been localized. It is only invoked if
1275 * $item['options']['alter'] has been set to a non-empty value (e.g., TRUE).
1276 * This flag should be set using hook_menu_link_alter().
1277 *
1278 * Implementations of this hook are able to alter any property of the menu link.
1279 * For example, this hook may be used to add a page-specific query string to all
1280 * menu links, or hide a certain link by setting:
1281 * @code
1282 * 'hidden' => 1,
1283 * @endcode
5c5bd803
AB
1284 *
1285 * @param $item
1286 * Associative array defining a menu link after _menu_link_translate()
1287 * @param $map
1288 * Associative array containing the menu $map (path parts and/or objects).
f3ab0a0f
DB
1289 *
1290 * @see hook_menu_link_alter()
5c5bd803
AB
1291 */
1292function hook_translated_menu_link_alter(&$item, $map) {
1293 if ($item['href'] == 'devel/cache/clear') {
1294 $item['localized_options']['query'] = drupal_get_destination();
1295 }
1296}
1297
1298/**
1299 * Inform modules that a menu link has been created.
1300 *
1301 * This hook is used to notify modules that menu items have been
1302 * created. Contributed modules may use the information to perform
1303 * actions based on the information entered into the menu system.
1304 *
1305 * @param $link
1306 * Associative array defining a menu link as passed into menu_link_save().
1307 *
1308 * @see hook_menu_link_update()
1309 * @see hook_menu_link_delete()
1310 */
1311function hook_menu_link_insert($link) {
1312 // In our sample case, we track menu items as editing sections
1313 // of the site. These are stored in our table as 'disabled' items.
1314 $record['mlid'] = $link['mlid'];
1315 $record['menu_name'] = $link['menu_name'];
1316 $record['status'] = 0;
1317 drupal_write_record('menu_example', $record);
1318}
1319
1320/**
1321 * Inform modules that a menu link has been updated.
1322 *
1323 * This hook is used to notify modules that menu items have been
1324 * updated. Contributed modules may use the information to perform
1325 * actions based on the information entered into the menu system.
1326 *
1327 * @param $link
1328 * Associative array defining a menu link as passed into menu_link_save().
1329 *
1330 * @see hook_menu_link_insert()
1331 * @see hook_menu_link_delete()
1332 */
1333function hook_menu_link_update($link) {
1334 // If the parent menu has changed, update our record.
4538ad0e 1335 $menu_name = db_query("SELECT menu_name FROM {menu_example} WHERE mlid = :mlid", array(':mlid' => $link['mlid']))->fetchField();
5c5bd803
AB
1336 if ($menu_name != $link['menu_name']) {
1337 db_update('menu_example')
1338 ->fields(array('menu_name' => $link['menu_name']))
1339 ->condition('mlid', $link['mlid'])
1340 ->execute();
1341 }
1342}
1343
1344/**
1345 * Inform modules that a menu link has been deleted.
1346 *
1347 * This hook is used to notify modules that menu items have been
1348 * deleted. Contributed modules may use the information to perform
1349 * actions based on the information entered into the menu system.
1350 *
1351 * @param $link
1352 * Associative array defining a menu link as passed into menu_link_save().
1353 *
1354 * @see hook_menu_link_insert()
1355 * @see hook_menu_link_update()
1356 */
1357function hook_menu_link_delete($link) {
1358 // Delete the record from our table.
1359 db_delete('menu_example')
1360 ->condition('mlid', $link['mlid'])
1361 ->execute();
1362}
1363
1364/**
1365 * Alter tabs and actions displayed on the page before they are rendered.
1366 *
1367 * This hook is invoked by menu_local_tasks(). The system-determined tabs and
1368 * actions are passed in by reference. Additional tabs or actions may be added,
1369 * or existing items altered.
1370 *
1371 * Each tab or action is an associative array containing:
1372 * - #theme: The theme function to use to render.
1373 * - #link: An associative array containing:
1374 * - title: The localized title of the link.
1375 * - href: The system path to link to.
1376 * - localized_options: An array of options to pass to url().
1377 * - #active: Whether the link should be marked as 'active'.
1378 *
1379 * @param $data
1380 * An associative array containing:
1381 * - actions: An associative array containing:
1382 * - count: The amount of actions determined by the menu system, which can
1383 * be ignored.
1384 * - output: A list of of actions, each one being an associative array
1385 * as described above.
1386 * - tabs: An indexed array (list) of tab levels (up to 2 levels), each
1387 * containing an associative array:
1388 * - count: The amount of tabs determined by the menu system. This value
1389 * does not need to be altered if there is more than one tab.
1390 * - output: A list of of tabs, each one being an associative array as
1391 * described above.
50787d83
DB
1392 * @param $router_item
1393 * The menu system router item of the page.
1394 * @param $root_path
1395 * The path to the root item for this set of tabs.
5c5bd803
AB
1396 */
1397function hook_menu_local_tasks_alter(&$data, $router_item, $root_path) {
1398 // Add an action linking to node/add to all pages.
1399 $data['actions']['output'][] = array(
1400 '#theme' => 'menu_local_task',
1401 '#link' => array(
1402 'title' => t('Add new content'),
1403 'href' => 'node/add',
1404 'localized_options' => array(
1405 'attributes' => array(
1406 'title' => t('Add new content'),
1407 ),
1408 ),
1409 ),
1410 );
1411
1412 // Add a tab linking to node/add to all pages.
1413 $data['tabs'][0]['output'][] = array(
1414 '#theme' => 'menu_local_task',
1415 '#link' => array(
1416 'title' => t('Example tab'),
1417 'href' => 'node/add',
1418 'localized_options' => array(
1419 'attributes' => array(
1420 'title' => t('Add new content'),
1421 ),
1422 ),
1423 ),
1424 // Define whether this link is active. This can be omitted for
1425 // implementations that add links to pages outside of the current page
1426 // context.
1427 '#active' => ($router_item['path'] == $root_path),
1428 );
1429}
1430
1431/**
c9de4646
DB
1432 * Alter links in the active trail before it is rendered as the breadcrumb.
1433 *
1434 * This hook is invoked by menu_get_active_breadcrumb() and allows alteration
1435 * of the breadcrumb links for the current page, which may be preferred instead
1436 * of setting a custom breadcrumb via drupal_set_breadcrumb().
1437 *
1438 * Implementations should take into account that menu_get_active_breadcrumb()
1439 * subsequently performs the following adjustments to the active trail *after*
1440 * this hook has been invoked:
1441 * - The last link in $active_trail is removed, if its 'href' is identical to
1442 * the 'href' of $item. This happens, because the breadcrumb normally does
1443 * not contain a link to the current page.
1444 * - The (second to) last link in $active_trail is removed, if the current $item
1445 * is a MENU_DEFAULT_LOCAL_TASK. This happens in order to do not show a link
1446 * to the current page, when being on the path for the default local task;
1447 * e.g. when being on the path node/%/view, the breadcrumb should not contain
1448 * a link to node/%.
1449 *
1450 * Each link in the active trail must contain:
1451 * - title: The localized title of the link.
1452 * - href: The system path to link to.
1453 * - localized_options: An array of options to pass to url().
1454 *
1455 * @param $active_trail
1456 * An array containing breadcrumb links for the current page.
1457 * @param $item
1458 * The menu router item of the current page.
1459 *
1460 * @see drupal_set_breadcrumb()
1461 * @see menu_get_active_breadcrumb()
1462 * @see menu_get_active_trail()
1463 * @see menu_set_active_trail()
1464 */
1465function hook_menu_breadcrumb_alter(&$active_trail, $item) {
1466 // Always display a link to the current page by duplicating the last link in
1467 // the active trail. This means that menu_get_active_breadcrumb() will remove
1468 // the last link (for the current page), but since it is added once more here,
1469 // it will appear.
1470 if (!drupal_is_front_page()) {
1471 $end = end($active_trail);
1472 if ($item['href'] == $end['href']) {
1473 $active_trail[] = $end;
1474 }
1475 }
1476}
1477
1478/**
5c5bd803
AB
1479 * Alter contextual links before they are rendered.
1480 *
1481 * This hook is invoked by menu_contextual_links(). The system-determined
1482 * contextual links are passed in by reference. Additional links may be added
1483 * or existing links can be altered.
1484 *
1485 * Each contextual link must at least contain:
1486 * - title: The localized title of the link.
1487 * - href: The system path to link to.
1488 * - localized_options: An array of options to pass to url().
1489 *
1490 * @param $links
1491 * An associative array containing contextual links for the given $root_path,
1492 * as described above. The array keys are used to build CSS class names for
1493 * contextual links and must therefore be unique for each set of contextual
1494 * links.
1495 * @param $router_item
1496 * The menu router item belonging to the $root_path being requested.
1497 * @param $root_path
1498 * The (parent) path that has been requested to build contextual links for.
1499 * This is a normalized path, which means that an originally passed path of
1500 * 'node/123' became 'node/%'.
1501 *
84e5d10b 1502 * @see hook_contextual_links_view_alter()
5c5bd803
AB
1503 * @see menu_contextual_links()
1504 * @see hook_menu()
84e5d10b 1505 * @see contextual_preprocess()
5c5bd803
AB
1506 */
1507function hook_menu_contextual_links_alter(&$links, $router_item, $root_path) {
1508 // Add a link to all contextual links for nodes.
1509 if ($root_path == 'node/%') {
1510 $links['foo'] = array(
1511 'title' => t('Do fu'),
1512 'href' => 'foo/do',
1513 'localized_options' => array(
1514 'query' => array(
1515 'foo' => 'bar',
1516 ),
1517 ),
1518 );
1519 }
1520}
1521
1522/**
2e8ca690
DB
1523 * Perform alterations before a page is rendered.
1524 *
a244b45c
AB
1525 * Use this hook when you want to remove or alter elements at the page
1526 * level, or add elements at the page level that depend on an other module's
1527 * elements (this hook runs after hook_page_build().
1528 *
1529 * If you are making changes to entities such as forms, menus, or user
2e8ca690
DB
1530 * profiles, use those objects' native alter hooks instead (hook_form_alter(),
1531 * for example).
1532 *
1533 * The $page array contains top level elements for each block region:
1534 * @code
a244b45c 1535 * $page['page_top']
2e8ca690 1536 * $page['header']
62e0ddc7 1537 * $page['sidebar_first']
2e8ca690 1538 * $page['content']
62e0ddc7 1539 * $page['sidebar_second']
a244b45c 1540 * $page['page_bottom']
2e8ca690
DB
1541 * @endcode
1542 *
1543 * The 'content' element contains the main content of the current page, and its
1544 * structure will vary depending on what module is responsible for building the
1545 * page. Some legacy modules may not return structured content at all: their
1546 * pre-rendered markup will be located in $page['content']['main']['#markup'].
1547 *
1548 * Pages built by Drupal's core Node and Blog modules use a standard structure:
1549 *
1550 * @code
1551 * // Node body.
b922148c 1552 * $page['content']['system_main']['nodes'][$nid]['body']
2e8ca690 1553 * // Array of links attached to the node (add comments, read more).
b922148c 1554 * $page['content']['system_main']['nodes'][$nid]['links']
2e8ca690 1555 * // The node object itself.
b922148c 1556 * $page['content']['system_main']['nodes'][$nid]['#node']
2e8ca690 1557 * // The results pager.
b922148c 1558 * $page['content']['system_main']['pager']
1dafc60c 1559 * @endcode
2e8ca690
DB
1560 *
1561 * Blocks may be referenced by their module/delta pair within a region:
1562 * @code
62e0ddc7 1563 * // The login block in the first sidebar region.
a244b45c 1564 * $page['sidebar_first']['user_login']['#block'];
2e8ca690
DB
1565 * @endcode
1566 *
1567 * @param $page
1568 * Nested array of renderable elements that make up the page.
1569 *
a244b45c 1570 * @see hook_page_build()
2e8ca690
DB
1571 * @see drupal_render_page()
1572 */
a244b45c
AB
1573function hook_page_alter(&$page) {
1574 // Add help text to the user login block.
1575 $page['sidebar_first']['user_login']['help'] = array(
1576 '#weight' => -10,
1577 '#markup' => t('To post comments or add new content, you first have to log in.'),
1578 );
2e8ca690
DB
1579}
1580
1581/**
66df6025
AB
1582 * Perform alterations before a form is rendered.
1583 *
1584 * One popular use of this hook is to add form elements to the node form. When
4ce4c4eb 1585 * altering a node form, the node object can be accessed at $form['#node'].
66df6025 1586 *
184c145d
D
1587 * In addition to hook_form_alter(), which is called for all forms, there are
1588 * two more specific form hooks available. The first,
1589 * hook_form_BASE_FORM_ID_alter(), allows targeting of a form/forms via a base
1590 * form (if one exists). The second, hook_form_FORM_ID_alter(), can be used to
1591 * target a specific form directly.
1592 *
1593 * The call order is as follows: all existing form alter functions are called
1594 * for module A, then all for module B, etc., followed by all for any base
1595 * theme(s), and finally for the theme itself. The module order is determined
1596 * by system weight, then by module name.
1597 *
1598 * Within each module, form alter hooks are called in the following order:
1599 * first, hook_form_alter(); second, hook_form_BASE_FORM_ID_alter(); third,
1600 * hook_form_FORM_ID_alter(). So, for each module, the more general hooks are
1601 * called first followed by the more specific.
ad84a926 1602 *
66df6025
AB
1603 * @param $form
1604 * Nested array of form elements that comprise the form.
1605 * @param $form_state
d3c83c02
DB
1606 * A keyed array containing the current state of the form. The arguments
1607 * that drupal_get_form() was originally called with are available in the
1608 * array $form_state['build_info']['args'].
66df6025
AB
1609 * @param $form_id
1610 * String representing the name of the form itself. Typically this is the
1611 * name of the function that generated the form.
19a45ce5 1612 *
184c145d 1613 * @see hook_form_BASE_FORM_ID_alter()
19a45ce5 1614 * @see hook_form_FORM_ID_alter()
66df6025 1615 */
7dd203c4 1616function hook_form_alter(&$form, &$form_state, $form_id) {
66df6025
AB
1617 if (isset($form['type']) && $form['type']['#value'] . '_node_settings' == $form_id) {
1618 $form['workflow']['upload_' . $form['type']['#value']] = array(
1619 '#type' => 'radios',
1620 '#title' => t('Attachments'),
1621 '#default_value' => variable_get('upload_' . $form['type']['#value'], 1),
1622 '#options' => array(t('Disabled'), t('Enabled')),
1623 );
1624 }
1625}
1626
1627/**
1628 * Provide a form-specific alteration instead of the global hook_form_alter().
1629 *
1630 * Modules can implement hook_form_FORM_ID_alter() to modify a specific form,
1631 * rather than implementing hook_form_alter() and checking the form ID, or
1632 * using long switch statements to alter multiple forms.
1633 *
184c145d
D
1634 * Form alter hooks are called in the following order: hook_form_alter(),
1635 * hook_form_BASE_FORM_ID_alter(), hook_form_FORM_ID_alter(). See
1636 * hook_form_alter() for more details.
1637 *
66df6025
AB
1638 * @param $form
1639 * Nested array of form elements that comprise the form.
1640 * @param $form_state
d3c83c02
DB
1641 * A keyed array containing the current state of the form. The arguments
1642 * that drupal_get_form() was originally called with are available in the
1643 * array $form_state['build_info']['args'].
eaee909a
DB
1644 * @param $form_id
1645 * String representing the name of the form itself. Typically this is the
1646 * name of the function that generated the form.
66df6025 1647 *
19a45ce5 1648 * @see hook_form_alter()
184c145d 1649 * @see hook_form_BASE_FORM_ID_alter()
d428fe37 1650 * @see drupal_prepare_form()
66df6025 1651 */
eaee909a 1652function hook_form_FORM_ID_alter(&$form, &$form_state, $form_id) {
66df6025 1653 // Modification for the form with the given form ID goes here. For example, if
d16bead1 1654 // FORM_ID is "user_register_form" this code would run only on the user
66df6025
AB
1655 // registration form.
1656
1657 // Add a checkbox to registration form about agreeing to terms of use.
1658 $form['terms_of_use'] = array(
1659 '#type' => 'checkbox',
1660 '#title' => t("I agree with the website's terms and conditions."),
1661 '#required' => TRUE,
1662 );
1663}
1664
1665/**
184c145d
D
1666 * Provide a form-specific alteration for shared ('base') forms.
1667 *
1668 * By default, when drupal_get_form() is called, Drupal looks for a function
1669 * with the same name as the form ID, and uses that function to build the form.
1670 * In contrast, base forms allow multiple form IDs to be mapped to a single base
1671 * (also called 'factory') form function.
eaee909a
DB
1672 *
1673 * Modules can implement hook_form_BASE_FORM_ID_alter() to modify a specific
184c145d
D
1674 * base form, rather than implementing hook_form_alter() and checking for
1675 * conditions that would identify the shared form constructor.
1676 *
1677 * To identify the base form ID for a particular form (or to determine whether
1678 * one exists) check the $form_state. The base form ID is stored under
1679 * $form_state['build_info']['base_form_id'].
eaee909a 1680 *
184c145d
D
1681 * See hook_forms() for more information on how to implement base forms in
1682 * Drupal.
eaee909a 1683 *
184c145d
D
1684 * Form alter hooks are called in the following order: hook_form_alter(),
1685 * hook_form_BASE_FORM_ID_alter(), hook_form_FORM_ID_alter(). See
1686 * hook_form_alter() for more details.
eaee909a
DB
1687 *
1688 * @param $form
1689 * Nested array of form elements that comprise the form.
1690 * @param $form_state
1691 * A keyed array containing the current state of the form.
1692 * @param $form_id
1693 * String representing the name of the form itself. Typically this is the
1694 * name of the function that generated the form.
1695 *
184c145d 1696 * @see hook_form_alter()
eaee909a
DB
1697 * @see hook_form_FORM_ID_alter()
1698 * @see drupal_prepare_form()
184c145d 1699 * @see hook_forms()
eaee909a
DB
1700 */
1701function hook_form_BASE_FORM_ID_alter(&$form, &$form_state, $form_id) {
1702 // Modification for the form with the given BASE_FORM_ID goes here. For
1703 // example, if BASE_FORM_ID is "node_form", this code would run on every
1704 // node form, regardless of node type.
1705
1706 // Add a checkbox to the node form about agreeing to terms of use.
1707 $form['terms_of_use'] = array(
1708 '#type' => 'checkbox',
1709 '#title' => t("I agree with the website's terms and conditions."),
1710 '#required' => TRUE,
1711 );
1712}
1713
1714/**
7511394e 1715 * Map form_ids to form builder functions.
66df6025 1716 *
7511394e
DB
1717 * By default, when drupal_get_form() is called, the system will look for a
1718 * function with the same name as the form ID, and use that function to build
184c145d
D
1719 * the form. If no such function is found, Drupal calls this hook. Modules
1720 * implementing this hook can then provide their own instructions for mapping
1721 * form IDs to constructor functions. As a result, you can easily map multiple
1722 * form IDs to a single form constructor (referred to as a 'base' form).
1723 *
1724 * Using a base form can help to avoid code duplication, by allowing many
1725 * similar forms to use the same code base. Another benefit is that it becomes
1726 * much easier for other modules to apply a general change to the group of
1727 * forms; hook_form_BASE_FORM_ID_alter() can be used to easily alter multiple
1728 * forms at once by directly targeting the shared base form.
1729 *
1730 * Two example use cases where base forms may be useful are given below.
66df6025 1731 *
7511394e
DB
1732 * First, you can use this hook to tell the form system to use a different
1733 * function to build certain forms in your module; this is often used to define
1734 * a form "factory" function that is used to build several similar forms. In
1735 * this case, your hook implementation will likely ignore all of the input
184c145d
D
1736 * arguments. See node_forms() for an example of this. Note, node_forms() is the
1737 * hook_forms() implementation; the base form itself is defined in node_form().
66df6025 1738 *
7511394e
DB
1739 * Second, you could use this hook to define how to build a form with a
1740 * dynamically-generated form ID. In this case, you would need to verify that
1741 * the $form_id input matched your module's format for dynamically-generated
1742 * form IDs, and if so, act appropriately.
66df6025 1743 *
a4dc8467
DB
1744 * @param $form_id
1745 * The unique string identifying the desired form.
1746 * @param $args
7511394e
DB
1747 * An array containing the original arguments provided to drupal_get_form()
1748 * or drupal_form_submit(). These are always passed to the form builder and
1749 * do not have to be specified manually in 'callback arguments'.
b006ec6c 1750 *
66df6025 1751 * @return
b006ec6c
AB
1752 * An associative array whose keys define form_ids and whose values are an
1753 * associative array defining the following keys:
184c145d
D
1754 * - callback: The name of the form builder function to invoke. This will be
1755 * used for the base form ID, for example, to target a base form using
1756 * hook_form_BASE_FORM_ID_alter().
b006ec6c
AB
1757 * - callback arguments: (optional) Additional arguments to pass to the
1758 * function defined in 'callback', which are prepended to $args.
1759 * - wrapper_callback: (optional) The name of a form builder function to
1760 * invoke before the form builder defined in 'callback' is invoked. This
1761 * wrapper callback may prepopulate the $form array with form elements,
1762 * which will then be already contained in the $form that is passed on to
1763 * the form builder defined in 'callback'. For example, a wrapper callback
1764 * could setup wizard-alike form buttons that are the same for a variety of
1765 * forms that belong to the wizard, which all share the same wrapper
1766 * callback.
66df6025 1767 */
a4dc8467 1768function hook_forms($form_id, $args) {
b006ec6c
AB
1769 // Simply reroute the (non-existing) $form_id 'mymodule_first_form' to
1770 // 'mymodule_main_form'.
66df6025 1771 $forms['mymodule_first_form'] = array(
b006ec6c 1772 'callback' => 'mymodule_main_form',
66df6025 1773 );
b006ec6c
AB
1774
1775 // Reroute the $form_id and prepend an additional argument that gets passed to
1776 // the 'mymodule_main_form' form builder function.
66df6025 1777 $forms['mymodule_second_form'] = array(
b006ec6c
AB
1778 'callback' => 'mymodule_main_form',
1779 'callback arguments' => array('some parameter'),
1780 );
1781
1782 // Reroute the $form_id, but invoke the form builder function
1783 // 'mymodule_main_form_wrapper' first, so we can prepopulate the $form array
1784 // that is passed to the actual form builder 'mymodule_main_form'.
1785 $forms['mymodule_wrapped_form'] = array(
1786 'callback' => 'mymodule_main_form',
1787 'wrapper_callback' => 'mymodule_main_form_wrapper',
66df6025 1788 );
a4dc8467 1789
66df6025
AB
1790 return $forms;
1791}
1792
1793/**
7f0feebe 1794 * Perform setup tasks for all page requests.
66df6025
AB
1795 *
1796 * This hook is run at the beginning of the page request. It is typically
7f0feebe 1797 * used to set up global parameters that are needed later in the request.
66df6025 1798 *
7f0feebe
DB
1799 * Only use this hook if your code must run even for cached page views. This
1800 * hook is called before modules or most include files are loaded into memory.
66df6025 1801 * It happens while Drupal is still in bootstrap mode.
7f0feebe
DB
1802 *
1803 * @see hook_init()
66df6025
AB
1804 */
1805function hook_boot() {
7f0feebe 1806 // We need user_access() in the shutdown function. Make sure it gets loaded.
66df6025 1807 drupal_load('module', 'user');
8d01aeb4 1808 drupal_register_shutdown_function('devel_shutdown');
66df6025
AB
1809}
1810
1811/**
7f0feebe 1812 * Perform setup tasks for non-cached page requests.
66df6025
AB
1813 *
1814 * This hook is run at the beginning of the page request. It is typically
7f0feebe
DB
1815 * used to set up global parameters that are needed later in the request.
1816 * When this hook is called, all modules are already loaded in memory.
66df6025 1817 *
fb9c1df0
DB
1818 * This hook is not run on cached pages.
1819 *
1820 * To add CSS or JS that should be present on all pages, modules should not
1821 * implement this hook, but declare these files in their .info file.
7f0feebe
DB
1822 *
1823 * @see hook_boot()
66df6025
AB
1824 */
1825function hook_init() {
5834cd45
AB
1826 // Since this file should only be loaded on the front page, it cannot be
1827 // declared in the info file.
1828 if (drupal_is_front_page()) {
1829 drupal_add_css(drupal_get_path('module', 'foo') . '/foo.css');
1830 }
66df6025
AB
1831}
1832
1833/**
0ea65350
DB
1834 * Define image toolkits provided by this module.
1835 *
1836 * The file which includes each toolkit's functions must be declared as part of
1837 * the files array in the module .info file so that the registry will find and
1838 * parse it.
1839 *
1840 * The toolkit's functions must be named image_toolkitname_operation().
1841 * where the operation may be:
1842 * - 'load': Required. See image_gd_load() for usage.
1843 * - 'save': Required. See image_gd_save() for usage.
1844 * - 'settings': Optional. See image_gd_settings() for usage.
1845 * - 'resize': Optional. See image_gd_resize() for usage.
a4ee7092 1846 * - 'rotate': Optional. See image_gd_rotate() for usage.
0ea65350
DB
1847 * - 'crop': Optional. See image_gd_crop() for usage.
1848 * - 'desaturate': Optional. See image_gd_desaturate() for usage.
1849 *
1850 * @return
1851 * An array with the toolkit name as keys and sub-arrays with these keys:
1852 * - 'title': A string with the toolkit's title.
1853 * - 'available': A Boolean value to indicate that the toolkit is operating
1854 * properly, e.g. all required libraries exist.
1855 *
1856 * @see system_image_toolkits()
1857 */
66df6025 1858function hook_image_toolkits() {
0ea65350
DB
1859 return array(
1860 'working' => array(
1861 'title' => t('A toolkit that works.'),
1862 'available' => TRUE,
1863 ),
1864 'broken' => array(
1865 'title' => t('A toolkit that is "broken" and will not be listed.'),
1866 'available' => FALSE,
1867 ),
1868 );
66df6025
AB
1869}
1870
1871/**
45da7480
DB
1872 * Alter an email message created with the drupal_mail() function.
1873 *
1874 * hook_mail_alter() allows modification of email messages created and sent
1875 * with drupal_mail(). Usage examples include adding and/or changing message
1876 * text, message fields, and message headers.
1877 *
1878 * Email messages sent using functions other than drupal_mail() will not
1879 * invoke hook_mail_alter(). For example, a contributed module directly
13d3072f 1880 * calling the drupal_mail_system()->mail() or PHP mail() function
c4a548f6 1881 * will not invoke this hook. All core modules use drupal_mail() for
af3f94b3 1882 * messaging, it is best practice but not mandatory in contributed modules.
66df6025
AB
1883 *
1884 * @param $message
45da7480 1885 * An array containing the message data. Keys in this array include:
9850918a 1886 * - 'id':
45da7480 1887 * The drupal_mail() id of the message. Look at module source code or
cef10893 1888 * drupal_mail() for possible id values.
45da7480 1889 * - 'to':
9850918a 1890 * The address or addresses the message will be sent to. The
66df6025 1891 * formatting of this string must comply with RFC 2822.
45da7480 1892 * - 'from':
9850918a
DB
1893 * The address the message will be marked as being from, which is
1894 * either a custom address or the site-wide default email address.
45da7480
DB
1895 * - 'subject':
1896 * Subject of the email to be sent. This must not contain any newline
1897 * characters, or the email may not be sent properly.
1898 * - 'body':
1899 * An array of strings containing the message text. The message body is
cef10893 1900 * created by concatenating the individual array strings into a single text
45da7480
DB
1901 * string using "\n\n" as a separator.
1902 * - 'headers':
9850918a 1903 * Associative array containing mail headers, such as From, Sender,
5fbaa4b8 1904 * MIME-Version, Content-Type, etc.
45da7480
DB
1905 * - 'params':
1906 * An array of optional parameters supplied by the caller of drupal_mail()
1907 * that is used to build the message before hook_mail_alter() is invoked.
1908 * - 'language':
1909 * The language object used to build the message before hook_mail_alter()
1910 * is invoked.
13874568 1911 * - 'send':
1912 * Set to FALSE to abort sending this email message.
45da7480
DB
1913 *
1914 * @see drupal_mail()
66df6025
AB
1915 */
1916function hook_mail_alter(&$message) {
22273a43 1917 if ($message['id'] == 'modulename_messagekey') {
13874568 1918 if (!example_notifications_optin($message['to'], $message['id'])) {
1919 // If the recipient has opted to not receive such messages, cancel
1920 // sending.
1921 $message['send'] = FALSE;
1922 return;
1923 }
9ae311ba 1924 $message['body'][] = "--\nMail sent out from " . variable_get('site_name', t('Drupal'));
66df6025
AB
1925 }
1926}
1927
1928/**
453032c1
AB
1929 * Alter the registry of modules implementing a hook.
1930 *
1931 * This hook is invoked during module_implements(). A module may implement this
1932 * hook in order to reorder the implementing modules, which are otherwise
1933 * ordered by the module's system weight.
1934 *
b96a83b4
D
1935 * Note that hooks invoked using drupal_alter() can have multiple variations
1936 * (such as hook_form_alter() and hook_form_FORM_ID_alter()). drupal_alter()
1937 * will call all such variants defined by a single module in turn. For the
1938 * purposes of hook_module_implements_alter(), these variants are treated as
1939 * a single hook. Thus, to ensure that your implementation of
1940 * hook_form_FORM_ID_alter() is called at the right time, you will have to
1941 * have to change the order of hook_form_alter() implementation in
1942 * hook_module_implements_alter().
1943 *
a22d7770 1944 * @param $implementations
453032c1
AB
1945 * An array keyed by the module's name. The value of each item corresponds
1946 * to a $group, which is usually FALSE, unless the implementation is in a
1947 * file named $module.$group.inc.
1948 * @param $hook
1949 * The name of the module hook being implemented.
1950 */
1951function hook_module_implements_alter(&$implementations, $hook) {
1952 if ($hook == 'rdf_mapping') {
1953 // Move my_module_rdf_mapping() to the end of the list. module_implements()
1954 // iterates through $implementations with a foreach loop which PHP iterates
1955 // in the order that the items were added, so to move an item to the end of
1956 // the array, we remove it and then add it.
1957 $group = $implementations['my_module'];
1958 unset($implementations['my_module']);
1959 $implementations['my_module'] = $group;
1960 }
1961}
1962
1963/**
11d884be 1964 * Return additional themes provided by modules.
1965 *
1966 * Only use this hook for testing purposes. Use a hidden MYMODULE_test.module
1967 * to implement this hook. Testing themes should be hidden, too.
1968 *
1969 * This hook is invoked from _system_rebuild_theme_data() and allows modules to
1970 * register additional themes outside of the regular 'themes' directories of a
1971 * Drupal installation.
1972 *
1973 * @return
1974 * An associative array. Each key is the system name of a theme and each value
1975 * is the corresponding path to the theme's .info file.
1976 */
1977function hook_system_theme_info() {
1978 $themes['mymodule_test_theme'] = drupal_get_path('module', 'mymodule') . '/mymodule_test_theme/mymodule_test_theme.info';
1979 return $themes;
1980}
1981
1982/**
66df6025
AB
1983 * Alter the information parsed from module and theme .info files
1984 *
89d04ea7
AB
1985 * This hook is invoked in _system_rebuild_module_data() and in
1986 * _system_rebuild_theme_data(). A module may implement this hook in order to
1987 * add to or alter the data generated by reading the .info file with
1988 * drupal_parse_info_file().
66df6025 1989 *
a22d7770 1990 * @param $info
66df6025
AB
1991 * The .info file contents, passed by reference so that it can be altered.
1992 * @param $file
1993 * Full information about the module or theme, including $file->name, and
1994 * $file->filename
9e638424
DB
1995 * @param $type
1996 * Either 'module' or 'theme', depending on the type of .info file that was
1997 * passed.
66df6025 1998 */
9e638424 1999function hook_system_info_alter(&$info, $file, $type) {
66df6025
AB
2000 // Only fill this in if the .info file does not define a 'datestamp'.
2001 if (empty($info['datestamp'])) {
2002 $info['datestamp'] = filemtime($file->filename);
2003 }
2004}
2005
2006/**
2007 * Define user permissions.
2008 *
2009 * This hook can supply permissions that the module defines, so that they
da794083 2010 * can be selected on the user permissions page and used to grant or restrict
66df6025
AB
2011 * access to actions the module performs.
2012 *
66df6025
AB
2013 * Permissions are checked using user_access().
2014 *
2015 * For a detailed usage example, see page_example.module.
6586b764 2016 *
1a2d10ec 2017 * @return
25feb96f
DB
2018 * An array whose keys are permission names and whose corresponding values
2019 * are arrays containing the following key-value pairs:
2020 * - title: The human-readable name of the permission, to be shown on the
2021 * permission administration page. This should be wrapped in the t()
2022 * function so it can be translated.
2023 * - description: (optional) A description of what the permission does. This
2024 * should be wrapped in the t() function so it can be translated.
2025 * - restrict access: (optional) A boolean which can be set to TRUE to
2026 * indicate that site administrators should restrict access to this
2027 * permission to trusted users. This should be used for permissions that
2028 * have inherent security risks across a variety of potential use cases
2029 * (for example, the "administer filters" and "bypass node access"
2030 * permissions provided by Drupal core). When set to TRUE, a standard
170208b2 2031 * warning message defined in user_admin_permissions() and output via
2032 * theme_user_permission_description() will be associated with the
2033 * permission and displayed with it on the permission administration page.
2034 * Defaults to FALSE.
2035 * - warning: (optional) A translated warning message to display for this
2036 * permission on the permission administration page. This warning overrides
2037 * the automatic warning generated by 'restrict access' being set to TRUE.
2038 * This should rarely be used, since it is important for all permissions to
2039 * have a clear, consistent security warning that is the same across the
2040 * site. Use the 'description' key instead to provide any information that
2041 * is specific to the permission you are defining.
2042 *
2043 * @see theme_user_permission_description()
66df6025 2044 */
e4a4b7cc 2045function hook_permission() {
66df6025 2046 return array(
da794083
DB
2047 'administer my module' => array(
2048 'title' => t('Administer my module'),
2049 'description' => t('Perform administration tasks for my module.'),
2050 ),
66df6025
AB
2051 );
2052}
2053
2054/**
2055 * Register a module (or theme's) theme implementations.
2056 *
9ebcbc70 2057 * The implementations declared by this hook have two purposes: either they
2058 * specify how a particular render array is to be rendered as HTML (this is
2059 * usually the case if the theme function is assigned to the render array's
2060 * #theme property), or they return the HTML that should be returned by an
2061 * invocation of theme().
2062 *
66df6025
AB
2063 * The following parameters are all optional.
2064 *
06585e6b 2065 * @param array $existing
66df6025
AB
2066 * An array of existing implementations that may be used for override
2067 * purposes. This is primarily useful for themes that may wish to examine
2068 * existing implementations to extract data (such as arguments) so that
2069 * it may properly register its own, higher priority implementations.
2070 * @param $type
06585e6b
AB
2071 * Whether a theme, module, etc. is being processed. This is primarily useful
2072 * so that themes tell if they are the actual theme being called or a parent
2073 * theme. May be one of:
2074 * - 'module': A module is being checked for theme implementations.
2075 * - 'base_theme_engine': A theme engine is being checked for a theme that is
2076 * a parent of the actual theme being used.
2077 * - 'theme_engine': A theme engine is being checked for the actual theme
2078 * being used.
2079 * - 'base_theme': A base theme is being checked for theme implementations.
2080 * - 'theme': The actual theme in use is being checked.
66df6025 2081 * @param $theme
06585e6b 2082 * The actual name of theme, module, etc. that is being being processed.
66df6025
AB
2083 * @param $path
2084 * The directory path of the theme or module, so that it doesn't need to be
2085 * looked up.
2086 *
06585e6b
AB
2087 * @return array
2088 * An associative array of theme hook information. The keys on the outer
2089 * array are the internal names of the hooks, and the values are arrays
9ebcbc70 2090 * containing information about the hook. Each information array must contain
2091 * either a 'variables' element or a 'render element' element, but not both.
2092 * Use 'render element' if you are theming a single element or element tree
2093 * composed of elements, such as a form array, a page array, or a single
2094 * checkbox element. Use 'variables' if your theme implementation is
2095 * intended to be called directly through theme() and has multiple arguments
2096 * for the data and style; in this case, the variables not supplied by the
2097 * calling function will be given default values and passed to the template
2098 * or theme function. The returned theme information array can contain the
2099 * following key/value pairs:
2100 * - variables: (see above) Each array key is the name of the variable, and
2101 * the value given is used as the default value if the function calling
2102 * theme() does not supply it. Template implementations receive each array
2103 * key as a variable in the template file (so they must be legal PHP
2104 * variable names). Function implementations are passed the variables in a
2105 * single $variables function argument.
2106 * - render element: (see above) The name of the renderable element or element
2107 * tree to pass to the theme function. This name is used as the name of the
2108 * variable that holds the renderable element or tree in preprocess and
2109 * process functions.
06585e6b
AB
2110 * - file: The file the implementation resides in. This file will be included
2111 * prior to the theme being rendered, to make sure that the function or
2112 * preprocess function (as needed) is actually loaded; this makes it
2113 * possible to split theme functions out into separate files quite easily.
2114 * - path: Override the path of the file to be used. Ordinarily the module or
d48016fc 2115 * theme path will be used, but if the file will not be in the default
2116 * path, include it here. This path should be relative to the Drupal root
06585e6b 2117 * directory.
d48016fc 2118 * - template: If specified, this theme implementation is a template, and
2119 * this is the template file without an extension. Do not put .tpl.php on
2120 * this file; that extension will be added automatically by the default
2121 * rendering engine (which is PHPTemplate). If 'path', above, is specified,
2122 * the template should also be in this path.
2123 * - function: If specified, this will be the function name to invoke for
2124 * this implementation. If neither 'template' nor 'function' is specified,
2125 * a default function name will be assumed. For example, if a module
2126 * registers the 'node' theme hook, 'theme_node' will be assigned to its
2127 * function. If the chameleon theme registers the node hook, it will be
2128 * assigned 'chameleon_node' as its function.
06585e6b
AB
2129 * - pattern: A regular expression pattern to be used to allow this theme
2130 * implementation to have a dynamic name. The convention is to use __ to
2131 * differentiate the dynamic portion of the theme. For example, to allow
2132 * forums to be themed individually, the pattern might be: 'forum__'. Then,
2133 * when the forum is themed, call:
2134 * @code
2135 * theme(array('forum__' . $tid, 'forum'), $forum)
2136 * @endcode
2137 * - preprocess functions: A list of functions used to preprocess this data.
2138 * Ordinarily this won't be used; it's automatically filled in. By default,
2139 * for a module this will be filled in as template_preprocess_HOOK. For
2140 * a theme this will be filled in as phptemplate_preprocess and
2141 * phptemplate_preprocess_HOOK as well as themename_preprocess and
2142 * themename_preprocess_HOOK.
d48016fc 2143 * - override preprocess functions: Set to TRUE when a theme does NOT want
2144 * the standard preprocess functions to run. This can be used to give a
2145 * theme FULL control over how variables are set. For example, if a theme
2146 * wants total control over how certain variables in the page.tpl.php are
2147 * set, this can be set to true. Please keep in mind that when this is used
06585e6b
AB
2148 * by a theme, that theme becomes responsible for making sure necessary
2149 * variables are set.
2150 * - type: (automatically derived) Where the theme hook is defined:
2151 * 'module', 'theme_engine', or 'theme'.
2152 * - theme path: (automatically derived) The directory path of the theme or
2153 * module, so that it doesn't need to be looked up.
66df6025
AB
2154 */
2155function hook_theme($existing, $type, $theme, $path) {
2156 return array(
2157 'forum_display' => array(
a7149821 2158 'variables' => array('forums' => NULL, 'topics' => NULL, 'parents' => NULL, 'tid' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL),
66df6025
AB
2159 ),
2160 'forum_list' => array(
a7149821 2161 'variables' => array('forums' => NULL, 'parents' => NULL, 'tid' => NULL),
66df6025
AB
2162 ),
2163 'forum_topic_list' => array(
a7149821 2164 'variables' => array('tid' => NULL, 'topics' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL),
66df6025
AB
2165 ),
2166 'forum_icon' => array(
a7149821
AB
2167 'variables' => array('new_posts' => NULL, 'num_posts' => 0, 'comment_mode' => 0, 'sticky' => 0),
2168 ),
2169 'status_report' => array(
2170 'render element' => 'requirements',
2171 'file' => 'system.admin.inc',
2172 ),
2173 'system_date_time_settings' => array(
2174 'render element' => 'form',
2175 'file' => 'system.admin.inc',
66df6025 2176 ),
66df6025
AB
2177 );
2178}
2179
2180/**
2181 * Alter the theme registry information returned from hook_theme().
2182 *
2183 * The theme registry stores information about all available theme hooks,
2184 * including which callback functions those hooks will call when triggered,
2185 * what template files are exposed by these hooks, and so on.
2186 *
2187 * Note that this hook is only executed as the theme cache is re-built.
2188 * Changes here will not be visible until the next cache clear.
2189 *
2190 * The $theme_registry array is keyed by theme hook name, and contains the
2191 * information returned from hook_theme(), as well as additional properties
2192 * added by _theme_process_registry().
2193 *
2194 * For example:
2195 * @code
03d4cbdb
DB
2196 * $theme_registry['user_profile'] = array(
2197 * 'variables' => array(
2198 * 'account' => NULL,
2199 * ),
2200 * 'template' => 'modules/user/user-profile',
2201 * 'file' => 'modules/user/user.pages.inc',
2202 * 'type' => 'module',
2203 * 'theme path' => 'modules/user',
2204 * 'preprocess functions' => array(
2205 * 0 => 'template_preprocess',
2206 * 1 => 'template_preprocess_user_profile',
2207 * ),
66df6025
AB
2208 * );
2209 * @endcode
2210 *
2211 * @param $theme_registry
2212 * The entire cache of theme registry information, post-processing.
87f1bf45 2213 *
66df6025
AB
2214 * @see hook_theme()
2215 * @see _theme_process_registry()
2216 */
2217function hook_theme_registry_alter(&$theme_registry) {
2218 // Kill the next/previous forum topic navigation links.
2219 foreach ($theme_registry['forum_topic_navigation']['preprocess functions'] as $key => $value) {
b53e9583 2220 if ($value == 'template_preprocess_forum_topic_navigation') {
66df6025
AB
2221 unset($theme_registry['forum_topic_navigation']['preprocess functions'][$key]);
2222 }
2223 }
2224}
2225
2226/**
196aaa7d
AB
2227 * Return the machine-readable name of the theme to use for the current page.
2228 *
2229 * This hook can be used to dynamically set the theme for the current page
84c72d06
DB
2230 * request. It should be used by modules which need to override the theme
2231 * based on dynamic conditions (for example, a module which allows the theme to
2232 * be set based on the current user's role). The return value of this hook will
2233 * be used on all pages except those which have a valid per-page or per-section
2234 * theme set via a theme callback function in hook_menu(); the themes on those
2235 * pages can only be overridden using hook_menu_alter().
196aaa7d
AB
2236 *
2237 * Since only one theme can be used at a time, the last (i.e., highest
2238 * weighted) module which returns a valid theme name from this hook will
2239 * prevail.
2240 *
2241 * @return
2242 * The machine-readable name of the theme that should be used for the current
2243 * page request. The value returned from this function will only have an
2244 * effect if it corresponds to a currently-active theme on the site.
2245 */
2246function hook_custom_theme() {
2247 // Allow the user to request a particular theme via a query parameter.
2248 if (isset($_GET['theme'])) {
2249 return $_GET['theme'];
2250 }
2251}
2252
2253/**
66df6025
AB
2254 * Register XML-RPC callbacks.
2255 *
2256 * This hook lets a module register callback functions to be called when
2257 * particular XML-RPC methods are invoked by a client.
2258 *
2259 * @return
2260 * An array which maps XML-RPC methods to Drupal functions. Each array
2261 * element is either a pair of method => function or an array with four
2262 * entries:
2263 * - The XML-RPC method name (for example, module.function).
2264 * - The Drupal callback function (for example, module_function).
2265 * - The method signature is an array of XML-RPC types. The first element
2266 * of this array is the type of return value and then you should write a
2267 * list of the types of the parameters. XML-RPC types are the following
2268 * (See the types at http://www.xmlrpc.com/spec):
2269 * - "boolean": 0 (false) or 1 (true).
2270 * - "double": a floating point number (for example, -12.214).
2271 * - "int": a integer number (for example, -12).
2272 * - "array": an array without keys (for example, array(1, 2, 3)).
2273 * - "struct": an associative array or an object (for example,
2274 * array('one' => 1, 'two' => 2)).
2275 * - "date": when you return a date, then you may either return a
2276 * timestamp (time(), mktime() etc.) or an ISO8601 timestamp. When
2277 * date is specified as an input parameter, then you get an object,
2278 * which is described in the function xmlrpc_date
2279 * - "base64": a string containing binary data, automatically
2280 * encoded/decoded automatically.
2281 * - "string": anything else, typically a string.
2282 * - A descriptive help string, enclosed in a t() function for translation
2283 * purposes.
2284 * Both forms are shown in the example.
2285 */
2286function hook_xmlrpc() {
2287 return array(
2288 'drupal.login' => 'drupal_login',
2289 array(
2290 'drupal.site.ping',
2291 'drupal_directory_ping',
2292 array('boolean', 'string', 'string', 'string', 'string', 'string'),
2293 t('Handling ping request'))
2294 );
2295}
2296
2297/**
579310a4 2298 * Alters the definition of XML-RPC methods before they are called.
a1e08d93 2299 *
579310a4
DB
2300 * This hook allows modules to modify the callback definition of declared
2301 * XML-RPC methods, right before they are invoked by a client. Methods may be
2302 * added, or existing methods may be altered.
a1e08d93 2303 *
579310a4
DB
2304 * Note that hook_xmlrpc() supports two distinct and incompatible formats to
2305 * define a callback, so care must be taken when altering other methods.
a1e08d93 2306 *
a1e08d93 2307 * @param $methods
579310a4
DB
2308 * An asssociative array of method callback definitions, as returned from
2309 * hook_xmlrpc() implementations.
87f1bf45
DB
2310 *
2311 * @see hook_xmlrpc()
579310a4 2312 * @see xmlrpc_server()
a1e08d93
DB
2313 */
2314function hook_xmlrpc_alter(&$methods) {
579310a4 2315 // Directly change a simple method.
a1e08d93
DB
2316 $methods['drupal.login'] = 'mymodule_login';
2317
579310a4 2318 // Alter complex definitions.
a1e08d93 2319 foreach ($methods as $key => &$method) {
579310a4 2320 // Skip simple method definitions.
a1e08d93
DB
2321 if (!is_int($key)) {
2322 continue;
2323 }
579310a4 2324 // Perform the wanted manipulation.
a1e08d93
DB
2325 if ($method[0] == 'drupal.site.ping') {
2326 $method[1] = 'mymodule_directory_ping';
2327 }
2328 }
2329}
2330
2331/**
66df6025
AB
2332 * Log an event message
2333 *
2334 * This hook allows modules to route log events to custom destinations, such as
2335 * SMS, Email, pager, syslog, ...etc.
2336 *
2337 * @param $log_entry
5bbad8a4 2338 * An associative array containing the following keys:
66df6025
AB
2339 * - type: The type of message for this entry. For contributed modules, this is
2340 * normally the module name. Do not use 'debug', use severity WATCHDOG_DEBUG instead.
2341 * - user: The user object for the user who was logged in when the event happened.
2342 * - request_uri: The Request URI for the page the event happened in.
2343 * - referer: The page that referred the use to the page where the event occurred.
2344 * - ip: The IP address where the request for the page came from.
af3f94b3 2345 * - timestamp: The UNIX timestamp of the date/time the event occurred
66df6025 2346 * - severity: One of the following values as defined in RFC 3164 http://www.faqs.org/rfcs/rfc3164.html
052a1da5 2347 * WATCHDOG_EMERGENCY Emergency: system is unusable
66df6025
AB
2348 * WATCHDOG_ALERT Alert: action must be taken immediately
2349 * WATCHDOG_CRITICAL Critical: critical conditions
2350 * WATCHDOG_ERROR Error: error conditions
2351 * WATCHDOG_WARNING Warning: warning conditions
2352 * WATCHDOG_NOTICE Notice: normal but significant condition
2353 * WATCHDOG_INFO Informational: informational messages
2354 * WATCHDOG_DEBUG Debug: debug-level messages
2355 * - link: an optional link provided by the module that called the watchdog() function.
2356 * - message: The text of the message to be logged.
66df6025 2357 */
5bbad8a4
DB
2358function hook_watchdog(array $log_entry) {
2359 global $base_url, $language;
66df6025
AB
2360
2361 $severity_list = array(
052a1da5
DB
2362 WATCHDOG_EMERGENCY => t('Emergency'),
2363 WATCHDOG_ALERT => t('Alert'),
2364 WATCHDOG_CRITICAL => t('Critical'),
2365 WATCHDOG_ERROR => t('Error'),
2366 WATCHDOG_WARNING => t('Warning'),
2367 WATCHDOG_NOTICE => t('Notice'),
2368 WATCHDOG_INFO => t('Info'),
2369 WATCHDOG_DEBUG => t('Debug'),
66df6025
AB
2370 );
2371
5bbad8a4
DB
2372 $to = 'someone@example.com';
2373 $params = array();
2374 $params['subject'] = t('[@site_name] @severity_desc: Alert from your web site', array(
2375 '@site_name' => variable_get('site_name', 'Drupal'),
2376 '@severity_desc' => $severity_list[$log_entry['severity']],
2377 ));
2378
2379 $params['message'] = "\nSite: @base_url";
2380 $params['message'] .= "\nSeverity: (@severity) @severity_desc";
2381 $params['message'] .= "\nTimestamp: @timestamp";
2382 $params['message'] .= "\nType: @type";
2383 $params['message'] .= "\nIP Address: @ip";
2384 $params['message'] .= "\nRequest URI: @request_uri";
2385 $params['message'] .= "\nReferrer URI: @referer_uri";
2386 $params['message'] .= "\nUser: (@uid) @name";
2387 $params['message'] .= "\nLink: @link";
2388 $params['message'] .= "\nMessage: \n\n@message";
2389
2390 $params['message'] = t($params['message'], array(
66df6025 2391 '@base_url' => $base_url,
5bbad8a4
DB
2392 '@severity' => $log_entry['severity'],
2393 '@severity_desc' => $severity_list[$log_entry['severity']],
2394 '@timestamp' => format_date($log_entry['timestamp']),
2395 '@type' => $log_entry['type'],
2396 '@ip' => $log_entry['ip'],
2397 '@request_uri' => $log_entry['request_uri'],
2398 '@referer_uri' => $log_entry['referer'],
2399 '@uid' => $log_entry['user']->uid,
2400 '@name' => $log_entry['user']->name,
2401 '@link' => strip_tags($log_entry['link']),
2402 '@message' => strip_tags($log_entry['message']),
66df6025
AB
2403 ));
2404
5bbad8a4 2405 drupal_mail('emaillog', 'entry', $to, $language, $params);
66df6025
AB
2406}
2407
2408/**
9850918a 2409 * Prepare a message based on parameters; called from drupal_mail().
66df6025 2410 *
b077fb56
DB
2411 * Note that hook_mail(), unlike hook_mail_alter(), is only called on the
2412 * $module argument to drupal_mail(), not all modules.
2413 *
66df6025
AB
2414 * @param $key
2415 * An identifier of the mail.
2416 * @param $message
b077fb56
DB
2417 * An array to be filled in. Elements in this array include:
2418 * - id: An ID to identify the mail sent. Look at module source code
9850918a 2419 * or drupal_mail() for possible id values.
b077fb56 2420 * - to: The address or addresses the message will be sent to. The
66df6025 2421 * formatting of this string must comply with RFC 2822.
b077fb56
DB
2422 * - subject: Subject of the e-mail to be sent. This must not contain any
2423 * newline characters, or the mail may not be sent properly. drupal_mail()
2424 * sets this to an empty string when the hook is invoked.
2425 * - body: An array of lines containing the message to be sent. Drupal will
2426 * format the correct line endings for you. drupal_mail() sets this to an
2427 * empty array when the hook is invoked.
2428 * - from: The address the message will be marked as being from, which is
5fbaa4b8 2429 * set by drupal_mail() to either a custom address or the site-wide
9850918a 2430 * default email address when the hook is invoked.
b077fb56
DB
2431 * - headers: Associative array containing mail headers, such as From,
2432 * Sender, MIME-Version, Content-Type, etc. drupal_mail() pre-fills
9850918a 2433 * several headers in this array.
66df6025 2434 * @param $params
9850918a 2435 * An array of parameters supplied by the caller of drupal_mail().
66df6025
AB
2436 */
2437function hook_mail($key, &$message, $params) {
2438 $account = $params['account'];
2439 $context = $params['context'];
2440 $variables = array(
2441 '%site_name' => variable_get('site_name', 'Drupal'),
ca8eee75 2442 '%username' => format_username($account),
66df6025
AB
2443 );
2444 if ($context['hook'] == 'taxonomy') {
7d4b84b8 2445 $entity = $params['entity'];
7562a8ef 2446 $vocabulary = taxonomy_vocabulary_load($entity->vid);
66df6025 2447 $variables += array(
7562a8ef
AB
2448 '%term_name' => $entity->name,
2449 '%term_description' => $entity->description,
2450 '%term_id' => $entity->tid,
66df6025
AB
2451 '%vocabulary_name' => $vocabulary->name,
2452 '%vocabulary_description' => $vocabulary->description,
2453 '%vocabulary_id' => $vocabulary->vid,
2454 );
2455 }
2456
2457 // Node-based variable translation is only available if we have a node.
2458 if (isset($params['node'])) {
2459 $node = $params['node'];
2460 $variables += array(
2461 '%uid' => $node->uid,
2462 '%node_url' => url('node/' . $node->nid, array('absolute' => TRUE)),
cab88a70 2463 '%node_type' => node_type_get_name($node),
147bb138 2464 '%title' => $node->title,
66df6025
AB
2465 '%teaser' => $node->teaser,
2466 '%body' => $node->body,
2467 );
2468 }
2469 $subject = strtr($context['subject'], $variables);
2470 $body = strtr($context['message'], $variables);
2471 $message['subject'] .= str_replace(array("\r", "\n"), '', $subject);
2472 $message['body'][] = drupal_html_to_text($body);
2473}
2474
2475/**
2476 * Add a list of cache tables to be cleared.
2477 *
2478 * This hook allows your module to add cache table names to the list of cache
2479 * tables that will be cleared by the Clear button on the Performance page or
2480 * whenever drupal_flush_all_caches is invoked.
2481 *
66df6025
AB
2482 * @return
2483 * An array of cache table names.
87f1bf45
DB
2484 *
2485 * @see drupal_flush_all_caches()
66df6025
AB
2486 */
2487function hook_flush_caches() {
2488 return array('cache_example');
2489}
2490
2491/**
2492 * Perform necessary actions after modules are installed.
2493 *
77f6e36f
DB
2494 * This function differs from hook_install() in that it gives all other modules
2495 * a chance to perform actions when a module is installed, whereas
2496 * hook_install() is only called on the module actually being installed. See
2497 * module_enable() for a detailed description of the order in which install and
2498 * enable hooks are invoked.
66df6025
AB
2499 *
2500 * @param $modules
69c8ff26 2501 * An array of the modules that were installed.
77f6e36f
DB
2502 *
2503 * @see module_enable()
2504 * @see hook_modules_enabled()
2505 * @see hook_install()
66df6025
AB
2506 */
2507function hook_modules_installed($modules) {
2508 if (in_array('lousy_module', $modules)) {
2509 variable_set('lousy_module_conflicting_variable', FALSE);
2510 }
2511}
2512
2513/**
2514 * Perform necessary actions after modules are enabled.
2515 *
77f6e36f
DB
2516 * This function differs from hook_enable() in that it gives all other modules a
2517 * chance to perform actions when modules are enabled, whereas hook_enable() is
2518 * only called on the module actually being enabled. See module_enable() for a
2519 * detailed description of the order in which install and enable hooks are
2520 * invoked.
66df6025
AB
2521 *
2522 * @param $modules
69c8ff26 2523 * An array of the modules that were enabled.
77f6e36f
DB
2524 *
2525 * @see hook_enable()
2526 * @see hook_modules_installed()
2527 * @see module_enable()
66df6025
AB
2528 */
2529function hook_modules_enabled($modules) {
2530 if (in_array('lousy_module', $modules)) {
2531 drupal_set_message(t('mymodule is not compatible with lousy_module'), 'error');
2532 mymodule_disable_functionality();
2533 }
2534}
2535
2536/**
2537 * Perform necessary actions after modules are disabled.
2538 *
77f6e36f
DB
2539 * This function differs from hook_disable() in that it gives all other modules
2540 * a chance to perform actions when modules are disabled, whereas hook_disable()
2541 * is only called on the module actually being disabled.
66df6025
AB
2542 *
2543 * @param $modules
69c8ff26 2544 * An array of the modules that were disabled.
77f6e36f
DB
2545 *
2546 * @see hook_disable()
2547 * @see hook_modules_uninstalled()
66df6025
AB
2548 */
2549function hook_modules_disabled($modules) {
2550 if (in_array('lousy_module', $modules)) {
2551 mymodule_enable_functionality();
2552 }
2553}
2554
2555/**
2556 * Perform necessary actions after modules are uninstalled.
2557 *
77f6e36f
DB
2558 * This function differs from hook_uninstall() in that it gives all other
2559 * modules a chance to perform actions when a module is uninstalled, whereas
2560 * hook_uninstall() is only called on the module actually being uninstalled.
66df6025 2561 *
f1cc8651
DB
2562 * It is recommended that you implement this hook if your module stores
2563 * data that may have been set by other modules.
66df6025 2564 *
66df6025 2565 * @param $modules
69c8ff26 2566 * An array of the modules that were uninstalled.
77f6e36f
DB
2567 *
2568 * @see hook_uninstall()
2569 * @see hook_modules_disabled()
66df6025
AB
2570 */
2571function hook_modules_uninstalled($modules) {
2572 foreach ($modules as $module) {
2573 db_delete('mymodule_table')
2574 ->condition('module', $module)
2575 ->execute();
2576 }
2577 mymodule_cache_rebuild();
2578}
2579
2580/**
5468b47b
DB
2581 * Registers PHP stream wrapper implementations associated with a module.
2582 *
2583 * Provide a facility for managing and querying user-defined stream wrappers
2584 * in PHP. PHP's internal stream_get_wrappers() doesn't return the class
2585 * registered to handle a stream, which we need to be able to find the handler
2586 * for class instantiation.
2587 *
2588 * If a module registers a scheme that is already registered with PHP, it will
2589 * be unregistered and replaced with the specified class.
2590 *
2591 * @return
2592 * A nested array, keyed first by scheme name ("public" for "public://"),
2593 * then keyed by the following values:
2594 * - 'name' A short string to name the wrapper.
2595 * - 'class' A string specifying the PHP class that implements the
2596 * DrupalStreamWrapperInterface interface.
2597 * - 'description' A string with a short description of what the wrapper does.
2a0e3264
DB
2598 * - 'type' (Optional) A bitmask of flags indicating what type of streams this
2599 * wrapper will access - local or remote, readable and/or writeable, etc.
2600 * Many shortcut constants are defined in stream_wrappers.inc. Defaults to
2601 * STREAM_WRAPPERS_NORMAL which includes all of these bit flags:
2602 * - STREAM_WRAPPERS_READ
2603 * - STREAM_WRAPPERS_WRITE
2604 * - STREAM_WRAPPERS_VISIBLE
5468b47b
DB
2605 *
2606 * @see file_get_stream_wrappers()
2607 * @see hook_stream_wrappers_alter()
2608 * @see system_stream_wrappers()
2609 */
2610function hook_stream_wrappers() {
2611 return array(
2612 'public' => array(
2613 'name' => t('Public files'),
2614 'class' => 'DrupalPublicStreamWrapper',
2615 'description' => t('Public local files served by the webserver.'),
2a0e3264 2616 'type' => STREAM_WRAPPERS_LOCAL_NORMAL,
5468b47b
DB
2617 ),
2618 'private' => array(
2619 'name' => t('Private files'),
2620 'class' => 'DrupalPrivateStreamWrapper',
2621 'description' => t('Private local files served by Drupal.'),
2a0e3264 2622 'type' => STREAM_WRAPPERS_LOCAL_NORMAL,
5468b47b
DB
2623 ),
2624 'temp' => array(
2625 'name' => t('Temporary files'),
2626 'class' => 'DrupalTempStreamWrapper',
2627 'description' => t('Temporary local files for upload and previews.'),
2a0e3264
DB
2628 'type' => STREAM_WRAPPERS_LOCAL_HIDDEN,
2629 ),
2630 'cdn' => array(
2631 'name' => t('Content delivery network files'),
2632 'class' => 'MyModuleCDNStreamWrapper',
2633 'description' => t('Files served by a content delivery network.'),
2634 // 'type' can be omitted to use the default of STREAM_WRAPPERS_NORMAL
2635 ),
2636 'youtube' => array(
2637 'name' => t('YouTube video'),
2638 'class' => 'MyModuleYouTubeStreamWrapper',
2639 'description' => t('Video streamed from YouTube.'),
2640 // A module implementing YouTube integration may decide to support using
2641 // the YouTube API for uploading video, but here, we assume that this
2642 // particular module only supports playing YouTube video.
2643 'type' => STREAM_WRAPPERS_READ_VISIBLE,
2644 ),
5468b47b
DB
2645 );
2646}
2647
2648/**
2649 * Alters the list of PHP stream wrapper implementations.
2650 *
2651 * @see file_get_stream_wrappers()
2652 * @see hook_stream_wrappers()
2653 */
2654function hook_stream_wrappers_alter(&$wrappers) {
2655 // Change the name of private files to reflect the performance.
2656 $wrappers['private']['name'] = t('Slow files');
2657}
2658
2659/**
d813e367 2660 * Load additional information into file objects.
66df6025 2661 *
d813e367
DB
2662 * file_load_multiple() calls this hook to allow modules to load
2663 * additional information into each file.
66df6025 2664 *
d813e367
DB
2665 * @param $files
2666 * An array of file objects, indexed by fid.
66df6025 2667 *
d813e367 2668 * @see file_load_multiple()
15e66edf 2669 * @see file_load()
66df6025 2670 */
d813e367 2671function hook_file_load($files) {
66df6025 2672 // Add the upload specific data into the file object.
d813e367
DB
2673 $result = db_query('SELECT * FROM {upload} u WHERE u.fid IN (:fids)', array(':fids' => array_keys($files)))->fetchAll(PDO::FETCH_ASSOC);
2674 foreach ($result as $record) {
2675 foreach ($record as $key => $value) {
2676 $files[$record['fid']]->$key = $value;
2677 }
66df6025
AB
2678 }
2679}
2680
2681/**
2682 * Check that files meet a given criteria.
2683 *
2684 * This hook lets modules perform additional validation on files. They're able
2685 * to report a failure by returning one or more error messages.
2686 *
2687 * @param $file
2688 * The file object being validated.
2689 * @return
2690 * An array of error messages. If there are no problems with the file return
2691 * an empty array.
2692 *
2693 * @see file_validate()
2694 */
80aacdb0 2695function hook_file_validate($file) {
66df6025
AB
2696 $errors = array();
2697
2698 if (empty($file->filename)) {
2699 $errors[] = t("The file's name is empty. Please give a name to the file.");
2700 }
2701 if (strlen($file->filename) > 255) {
2702 $errors[] = t("The file's name exceeds the 255 characters limit. Please rename the file and try again.");
2703 }
2704
2705 return $errors;
2706}
2707
2708/**
71c4e3ec 2709 * Act on a file being inserted or updated.
66df6025
AB
2710 *
2711 * This hook is called when a file has been added to the database. The hook
2712 * doesn't distinguish between files created as a result of a copy or those
2713 * created by an upload.
2714 *
2715 * @param $file
2716 * The file that has just been created.
66df6025
AB
2717 *
2718 * @see file_save()
2719 */
71c4e3ec
AB
2720function hook_file_presave($file) {
2721 // Change the file timestamp to an hour prior.
2722 $file->timestamp -= 3600;
2723}
2724
2725/**
2726 * Respond to a file being added.
2727 *
b30fae02 2728 * This hook is called after a file has been added to the database. The hook
71c4e3ec
AB
2729 * doesn't distinguish between files created as a result of a copy or those
2730 * created by an upload.
2731 *
2732 * @param $file
b30fae02 2733 * The file that has been added.
71c4e3ec
AB
2734 *
2735 * @see file_save()
2736 */
b0ab9f28 2737function hook_file_insert($file) {
b30fae02
DB
2738 // Add a message to the log, if the file is a jpg
2739 $validate = file_validate_extensions($file, 'jpg');
2740 if (empty($validate)) {
2741 watchdog('file', 'A jpg has been added.');
2742 }
66df6025
AB
2743}
2744
2745/**
2746 * Respond to a file being updated.
2747 *
2748 * This hook is called when file_save() is called on an existing file.
2749 *
2750 * @param $file
2751 * The file that has just been updated.
66df6025
AB
2752 *
2753 * @see file_save()
2754 */
b0ab9f28 2755function hook_file_update($file) {
66df6025
AB
2756
2757}
2758
2759/**
2760 * Respond to a file that has been copied.
2761 *
2762 * @param $file
2763 * The newly copied file object.
2764 * @param $source
2765 * The original file before the copy.
66df6025
AB
2766 *
2767 * @see file_copy()
2768 */
2769function hook_file_copy($file, $source) {
2770
2771}
2772
2773/**
2774 * Respond to a file that has been moved.
2775 *
2776 * @param $file
2777 * The updated file object after the move.
2778 * @param $source
2779 * The original file object before the move.
66df6025
AB
2780 *
2781 * @see file_move()
2782 */
2783function hook_file_move($file, $source) {
2784
2785}
2786
2787/**
66df6025
AB
2788 * Respond to a file being deleted.
2789 *
2790 * @param $file
2791 * The file that has just been deleted.
66df6025
AB
2792 *
2793 * @see file_delete()
66df6025
AB
2794 */
2795function hook_file_delete($file) {
2796 // Delete all information associated with the file.
2797 db_delete('upload')->condition('fid', $file->fid)->execute();
2798}
2799
2800/**
66df6025
AB
2801 * Control access to private file downloads and specify HTTP headers.
2802 *
2803 * This hook allows modules enforce permissions on file downloads when the
2804 * private file download method is selected. Modules can also provide headers
2805 * to specify information like the file's name or MIME type.
2806 *
0d2b7fe8
DB
2807 * @param $uri
2808 * The URI of the file.
66df6025
AB
2809 * @return
2810 * If the user does not have permission to access the file, return -1. If the
2811 * user has permission, return an array with the appropriate headers. If the
2812 * file is not controlled by the current module, the return value should be
2813 * NULL.
2814 *
2815 * @see file_download()
66df6025 2816 */
0d2b7fe8 2817function hook_file_download($uri) {
66df6025 2818 // Check if the file is controlled by the current module.
0d2b7fe8
DB
2819 if (!file_prepare_directory($uri)) {
2820 $uri = FALSE;
b4132364 2821 }
c448440c 2822 if (strpos(file_uri_target($uri), variable_get('user_picture_path', 'pictures') . '/picture-') === 0) {
2823 if (!user_access('access user profiles')) {
2824 // Access to the file is denied.
66df6025
AB
2825 return -1;
2826 }
c448440c 2827 else {
2828 $info = image_get_info($uri);
2829 return array('Content-Type' => $info['mime_type']);
2830 }
66df6025
AB
2831 }
2832}
2833
2834/**
feb48454
DB
2835 * Alter the URL to a file.
2836 *
2837 * This hook is called from file_create_url(), and is called fairly
2838 * frequently (10+ times per page), depending on how many files there are in a
2839 * given page.
2840 * If CSS and JS aggregation are disabled, this can become very frequently
2841 * (50+ times per page) so performance is critical.
2842 *
2843 * This function should alter the URI, if it wants to rewrite the file URL.
feb48454
DB
2844 *
2845 * @param $uri
2846 * The URI to a file for which we need an external URL, or the path to a
2847 * shipped file.
2848 */
2849function hook_file_url_alter(&$uri) {
2850 global $user;
2851
2852 // User 1 will always see the local file in this example.
2853 if ($user->uid == 1) {
2854 return;
2855 }
2856
2857 $cdn1 = 'http://cdn1.example.com';
2858 $cdn2 = 'http://cdn2.example.com';
2859 $cdn_extensions = array('css', 'js', 'gif', 'jpg', 'jpeg', 'png');
2860
2861 // Most CDNs don't support private file transfers without a lot of hassle,
2862 // so don't support this in the common case.
2863 $schemes = array('public');
2864
2865 $scheme = file_uri_scheme($uri);
2866
2867 // Only serve shipped files and public created files from the CDN.
2868 if (!$scheme || in_array($scheme, $schemes)) {
2869 // Shipped files.
2870 if (!$scheme) {
2871 $path = $uri;
2872 }
2873 // Public created files.
2874 else {
2875 $wrapper = file_stream_wrapper_get_instance_by_scheme($scheme);
2876 $path = $wrapper->getDirectoryPath() . '/' . file_uri_target($uri);
2877 }
2878
2879 // Clean up Windows paths.
2880 $path = str_replace('\\', '/', $path);
2881
2882 // Serve files with one of the CDN extensions from CDN 1, all others from
2883 // CDN 2.
2884 $pathinfo = pathinfo($path);
1d0f6479 2885 if (isset($pathinfo['extension']) && in_array($pathinfo['extension'], $cdn_extensions)) {
feb48454
DB
2886 $uri = $cdn1 . '/' . $path;
2887 }
2888 else {
2889 $uri = $cdn2 . '/' . $path;
2890 }
2891 }
2892}
729a23e1
DB
2893
2894/**
66df6025
AB
2895 * Check installation requirements and do status reporting.
2896 *
585a2b96
DB
2897 * This hook has three closely related uses, determined by the $phase argument:
2898 * - Checking installation requirements ($phase == 'install').
2899 * - Checking update requirements ($phase == 'update').
2900 * - Status reporting ($phase == 'runtime').
66df6025
AB
2901 *
2902 * Note that this hook, like all others dealing with installation and updates,
2903 * must reside in a module_name.install file, or it will not properly abort
2904 * the installation of the module if a critical requirement is missing.
2905 *
2906 * During the 'install' phase, modules can for example assert that
2907 * library or server versions are available or sufficient.
2908 * Note that the installation of a module can happen during installation of
2909 * Drupal itself (by install.php) with an installation profile or later by hand.
2910 * As a consequence, install-time requirements must be checked without access
2911 * to the full Drupal API, because it is not available during install.php.
92a8adea
DB
2912 * For localization you should for example use $t = get_t() to
2913 * retrieve the appropriate localization function name (t() or st()).
66df6025
AB
2914 * If a requirement has a severity of REQUIREMENT_ERROR, install.php will abort
2915 * or at least the module will not install.
2916 * Other severity levels have no effect on the installation.
2917 * Module dependencies do not belong to these installation requirements,
2918 * but should be defined in the module's .info file.
2919 *
2920 * The 'runtime' phase is not limited to pure installation requirements
2921 * but can also be used for more general status information like maintenance
2922 * tasks and security issues.
2923 * The returned 'requirements' will be listed on the status report in the
2924 * administration section, with indication of the severity level.
2925 * Moreover, any requirement with a severity of REQUIREMENT_ERROR severity will
2926 * result in a notice on the the administration overview page.
2927 *
2928 * @param $phase
729a23e1
DB
2929 * The phase in which requirements are checked:
2930 * - install: The module is being installed.
2931 * - update: The module is enabled and update.php is run.
2932 * - runtime: The runtime requirements are being checked and shown on the
2933 * status report page.
66df6025
AB
2934 *
2935 * @return
2936 * A keyed array of requirements. Each requirement is itself an array with
2937 * the following items:
729a23e1
DB
2938 * - title: The name of the requirement.
2939 * - value: The current value (e.g., version, time, level, etc). During
2940 * install phase, this should only be used for version numbers, do not set
2941 * it if not applicable.
2942 * - description: The description of the requirement/status.
2943 * - severity: The requirement's result/severity level, one of:
2944 * - REQUIREMENT_INFO: For info only.
2945 * - REQUIREMENT_OK: The requirement is satisfied.
2946 * - REQUIREMENT_WARNING: The requirement failed with a warning.
2947 * - REQUIREMENT_ERROR: The requirement failed with an error.
66df6025
AB
2948 */
2949function hook_requirements($phase) {
2950 $requirements = array();
2951 // Ensure translations don't break at install time
2952 $t = get_t();
2953
2954 // Report Drupal version
2955 if ($phase == 'runtime') {
2956 $requirements['drupal'] = array(
2957 'title' => $t('Drupal'),
2958 'value' => VERSION,
2959 'severity' => REQUIREMENT_INFO
2960 );
2961 }
2962
2963 // Test PHP version
2964 $requirements['php'] = array(
2965 'title' => $t('PHP'),
b26aa370 2966 'value' => ($phase == 'runtime') ? l(phpversion(), 'admin/reports/status/php') : phpversion(),
66df6025
AB
2967 );
2968 if (version_compare(phpversion(), DRUPAL_MINIMUM_PHP) < 0) {
2969 $requirements['php']['description'] = $t('Your PHP installation is too old. Drupal requires at least PHP %version.', array('%version' => DRUPAL_MINIMUM_PHP));
2970 $requirements['php']['severity'] = REQUIREMENT_ERROR;
2971 }
2972
2973 // Report cron status
2974 if ($phase == 'runtime') {
2c381622 2975 $cron_last = variable_get('cron_last');
66df6025
AB
2976
2977 if (is_numeric($cron_last)) {
2978 $requirements['cron']['value'] = $t('Last run !time ago', array('!time' => format_interval(REQUEST_TIME - $cron_last)));
2979 }
2980 else {
2981 $requirements['cron'] = array(
71ee49de 2982 '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')),
66df6025
AB
2983 'severity' => REQUIREMENT_ERROR,
2984 'value' => $t('Never run'),
2985 );
2986 }
2987
b26aa370 2988 $requirements['cron']['description'] .= ' ' . $t('You can <a href="@cron">run cron manually</a>.', array('@cron' => url('admin/reports/status/run-cron')));
66df6025
AB
2989
2990 $requirements['cron']['title'] = $t('Cron maintenance tasks');
2991 }
2992
2993 return $requirements;
2994}
2995
2996/**
2997 * Define the current version of the database schema.
2998 *
2999 * A Drupal schema definition is an array structure representing one or
3000 * more tables and their related keys and indexes. A schema is defined by
3001 * hook_schema() which must live in your module's .install file.
3002 *
5d735a07 3003 * This hook is called at both install and uninstall time, and in the latter
3004 * case, it cannot rely on the .module file being loaded or hooks being known.
3005 * If the .module file is needed, it may be loaded with drupal_load().
3006 *
c545f6ee 3007 * The tables declared by this hook will be automatically created when
3008 * the module is first enabled, and removed when the module is uninstalled.
3009 * This happens before hook_install() is invoked, and after hook_uninstall()
3010 * is invoked, respectively.
3011 *
3012 * By declaring the tables used by your module via an implementation of
3013 * hook_schema(), these tables will be available on all supported database
3014 * engines. You don't have to deal with the different SQL dialects for table
8ad62e2d 3015 * creation and alteration of the supported database engines.
3016 *
66df6025
AB
3017 * See the Schema API Handbook at http://drupal.org/node/146843 for
3018 * details on schema definition structures.
3019 *
3020 * @return
f833423b
DB
3021 * A schema definition structure array. For each element of the
3022 * array, the key is a table name and the value is a table structure
3023 * definition.
3024 *
3025 * @ingroup schemaapi
66df6025
AB
3026 */
3027function hook_schema() {
3028 $schema['node'] = array(
3029 // example (partial) specification for table "node"
9c79816c 3030 'description' => 'The base table for nodes.',
66df6025
AB
3031 'fields' => array(
3032 'nid' => array(
9c79816c 3033 'description' => 'The primary identifier for a node.',
66df6025
AB
3034 'type' => 'serial',
3035 'unsigned' => TRUE,
3036 'not null' => TRUE),
3037 'vid' => array(
9c79816c 3038 'description' => 'The current {node_revision}.vid version identifier.',
66df6025
AB
3039 'type' => 'int',
3040 'unsigned' => TRUE,
3041 'not null' => TRUE,
3042 'default' => 0),
3043 'type' => array(
9c79816c 3044 'description' => 'The {node_type} of this node.',
66df6025
AB
3045 'type' => 'varchar',
3046 'length' => 32,
3047 'not null' => TRUE,
3048 'default' => ''),
3049 'title' => array(
401d1bb8 3050 'description' => 'The title of this node, always treated as non-markup plain text.',
66df6025
AB
3051 'type' => 'varchar',
3052 'length' => 255,
3053 'not null' => TRUE,
3054 'default' => ''),
3055 ),
3056 'indexes' => array(
3057 'node_changed' => array('changed'),
3058 'node_created' => array('created'),
3059 ),
3060 'unique keys' => array(
3061 'nid_vid' => array('nid', 'vid'),
3062 'vid' => array('vid')
3063 ),
db536802
DB
3064 'foreign keys' => array(
3065 'node_revision' => array(
3066 'table' => 'node_revision',
3067 'columns' => array('vid' => 'vid'),
3068 ),
3069 'node_author' => array(
3070 'table' => 'users',
3071 'columns' => array('uid' => 'uid')
3072 ),
3073 ),
66df6025
AB
3074 'primary key' => array('nid'),
3075 );
3076 return $schema;
3077}
3078
3079/**
3080 * Perform alterations to existing database schemas.
3081 *
3082 * When a module modifies the database structure of another module (by
3083 * changing, adding or removing fields, keys or indexes), it should
0ed10779
DB
3084 * implement hook_schema_alter() to update the default $schema to take its
3085 * changes into account.
66df6025
AB
3086 *
3087 * See hook_schema() for details on the schema definition structure.
3088 *
3089 * @param $schema
3090 * Nested array describing the schemas for all modules.
66df6025
AB
3091 */
3092function hook_schema_alter(&$schema) {
3093 // Add field to existing schema.
665c9fdc 3094 $schema['users']['fields']['timezone_id'] = array(
66df6025
AB
3095 'type' => 'int',
3096 'not null' => TRUE,
3097 'default' => 0,
9c79816c 3098 'description' => 'Per-user timezone configuration.',
66df6025
AB
3099 );
3100}
3101
3102/**
63437929
DB
3103 * Perform alterations to a structured query.
3104 *
3105 * Structured (aka dynamic) queries that have tags associated may be altered by any module
3106 * before the query is executed.
3107 *
87f1bf45
DB
3108 * @param $query
3109 * A Query object describing the composite parts of a SQL query.
3110 *
63437929
DB
3111 * @see hook_query_TAG_alter()
3112 * @see node_query_node_access_alter()
01a33182
DB
3113 * @see QueryAlterableInterface
3114 * @see SelectQueryInterface
63437929
DB
3115 */
3116function hook_query_alter(QueryAlterableInterface $query) {
01a33182
DB
3117 if ($query->hasTag('micro_limit')) {
3118 $query->range(0, 2);
3119 }
63437929
DB
3120}
3121
3122/**
3123 * Perform alterations to a structured query for a given tag.
3124 *
87f1bf45
DB
3125 * @param $query
3126 * An Query object describing the composite parts of a SQL query.
3127 *
63437929
DB
3128 * @see hook_query_alter()
3129 * @see node_query_node_access_alter()
01a33182
DB
3130 * @see QueryAlterableInterface
3131 * @see SelectQueryInterface
63437929
DB
3132 */
3133function hook_query_TAG_alter(QueryAlterableInterface $query) {
3134 // Skip the extra expensive alterations if site has no node access control modules.
3135 if (!node_access_view_all_nodes()) {
3136 // Prevent duplicates records.
3137 $query->distinct();
3138 // The recognized operations are 'view', 'update', 'delete'.
3139 if (!$op = $query->getMetaData('op')) {
3140 $op = 'view';
3141 }
3142 // Skip the extra joins and conditions for node admins.
3143 if (!user_access('bypass node access')) {
3144 // The node_access table has the access grants for any given node.
7b77b90c 3145 $access_alias = $query->join('node_access', 'na', '%alias.nid = n.nid');
63437929
DB
3146 $or = db_or();
3147 // If any grant exists for the specified user, then user has access to the node for the specified operation.
3148 foreach (node_access_grants($op, $query->getMetaData('account')) as $realm => $gids) {
3149 foreach ($gids as $gid) {
3150 $or->condition(db_and()
7b77b90c
DB
3151 ->condition($access_alias . '.gid', $gid)
3152 ->condition($access_alias . '.realm', $realm)
63437929
DB
3153 );
3154 }
3155 }
3156
3157 if (count($or->conditions())) {
3158 $query->condition($or);
3159 }
6d3d75fe 3160
7b77b90c 3161 $query->condition($access_alias . 'grant_' . $op, 1, '>=');
63437929
DB
3162 }
3163 }
3164}
3165
3166/**
029c48c6
DB
3167 * Perform setup tasks when the module is installed.
3168 *
3169 * If the module implements hook_schema(), the database tables will
3170 * be created before this hook is fired.
66df6025 3171 *
18b96d0c 3172 * Implementations of this hook are by convention declared in the module's
5d735a07 3173 * .install file. The implementation can rely on the .module file being loaded.
3174 * The hook will only be called the first time a module is enabled or after it
3175 * is re-enabled after being uninstalled. The module's schema version will be
3176 * set to the module's greatest numbered update hook. Because of this, any time
3177 * a hook_update_N() is added to the module, this function needs to be updated
3178 * to reflect the current version of the database schema.
66df6025 3179 *
d2feb622
AB
3180 * See the Schema API documentation at