/[drupal]/drupal/modules/system/system.api.php
ViewVC logotype

Contents of /drupal/modules/system/system.api.php

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.102 - (show annotations) (download) (as text)
Fri Nov 6 03:59:06 2009 UTC (3 weeks ago) by webchick
Branch: MAIN
CVS Tags: DRUPAL-7-0-UNSTABLE-10
Changes since 1.101: +20 -9 lines
File MIME type: text/x-php
#585868 by sun: Provide a generic way for actions to denote that they change a property.
1 <?php
2 // $Id: system.api.php,v 1.101 2009/11/05 03:04:24 dries Exp $
3
4 /**
5 * @file
6 * Hooks provided by Drupal core and the System module.
7 */
8
9 /**
10 * @addtogroup hooks
11 * @{
12 */
13
14 /**
15 * Defines one or more hooks that are exposed by a module.
16 *
17 * Normally hooks do not need to be explicitly defined. However, by declaring a
18 * hook explicitly, a module may define a "group" for it. Modules that implement
19 * a hook may then place their implementation in either $module.module or in
20 * $module.$group.inc. If the hook is located in $module.$group.inc, then that
21 * file will be automatically loaded when needed.
22 * In general, hooks that are rarely invoked and/or are very large should be
23 * placed in a separate include file, while hooks that are very short or very
24 * frequently called should be left in the main module file so that they are
25 * always available.
26 *
27 * @return
28 * An associative array whose keys are hook names and whose values are an
29 * associative array containing:
30 * - group: A string defining the group to which the hook belongs. The module
31 * system will determine whether a file with the name $module.$group.inc
32 * exists, and automatically load it when required.
33 *
34 * See system_hook_info() for all hook groups defined by Drupal core.
35 */
36 function hook_hook_info() {
37 $hooks['token_info'] = array(
38 'group' => 'tokens',
39 );
40 $hooks['tokens'] = array(
41 'group' => 'tokens',
42 );
43 return $hooks;
44 }
45
46 /**
47 * Inform the base system and the Field API about one or more entity types.
48 *
49 * Inform the system about one or more entity types (i.e., object types that
50 * can be loaded via entity_load() and, optionally, to which fields can be
51 * attached).
52 *
53 * @see entity_load()
54 * @see hook_entity_info_alter()
55 *
56 * @return
57 * An array whose keys are entity type names and whose values identify
58 * properties of those types that the system needs to know about:
59 * - name: The human-readable name of the type.
60 * - controller class: The name of the class that is used to load the objects.
61 * The class has to implement the DrupalEntityController interface. Leave
62 * blank to use the DefaultDrupalEntityController implementation.
63 * - base table: (used by DefaultDrupalEntityController) The name of the
64 * entity type's base table.
65 * - static cache: (used by DefaultDrupalEntityController) FALSE to disable
66 * static caching of entities during a page request. Defaults to TRUE.
67 * - load hook: The name of the hook which should be invoked by
68 * DrupalDefaultEntityController:attachLoad(), for example 'node_load'.
69 * - fieldable: Set to TRUE if you want your entity type to be fieldable.
70 * - object keys: An array describing how the Field API can extract the
71 * information it needs from the objects of the type. Elements:
72 * - id: The name of the property that contains the primary id of the
73 * object. Every object passed to the Field API must have this property
74 * and its value must be numeric.
75 * - revision: The name of the property that contains the revision id of
76 * the object. The Field API assumes that all revision ids are unique
77 * across all objects of a type.
78 * This element can be omitted if the objects of this type are not
79 * versionable.
80 * - bundle: The name of the property that contains the bundle name for the
81 * object. The bundle name defines which set of fields are attached to
82 * the object (e.g. what nodes call "content type").
83 * This element can be omitted if this type has no bundles (all objects
84 * have the same fields).
85 * - bundle keys: An array describing how the Field API can extract the
86 * information it needs from the bundle objects for this type (e.g
87 * $vocabulary objects for terms; not applicable for nodes).
88 * This element can be omitted if this type's bundles do not exist as
89 * standalone objects. Elements:
90 * - bundle: The name of the property that contains the name of the bundle
91 * object.
92 * - cacheable: A boolean indicating whether Field API should cache
93 * loaded fields for each object, reducing the cost of
94 * field_attach_load().
95 * - bundles: An array describing all bundles for this object type.
96 * Keys are bundles machine names, as found in the objects' 'bundle'
97 * property (defined in the 'object keys' entry above). Elements:
98 * - label: The human-readable name of the bundle.
99 * - admin: An array of information that allow Field UI pages (currently
100 * implemented in a contributed module) to attach themselves to the
101 * existing administration pages for the bundle. Elements:
102 * - path: the path of the bundle's main administration page, as defined
103 * in hook_menu(). If the path includes a placeholder for the bundle,
104 * the 'bundle argument', 'bundle helper' and 'real path' keys below
105 * are required.
106 * - bundle argument: The position of the placeholder in 'path', if any.
107 * - real path: The actual path (no placeholder) of the bundle's main
108 * administration page. This will be used to generate links.
109 * - access callback: As in hook_menu(). 'user_access' will be assumed if
110 * no value is provided.
111 * - access arguments: As in hook_menu().
112 */
113 function hook_entity_info() {
114 $return = array(
115 'node' => array(
116 'name' => t('Node'),
117 'controller class' => 'NodeController',
118 'base table' => 'node',
119 'id key' => 'nid',
120 'revision key' => 'vid',
121 'fieldable' => TRUE,
122 'bundle key' => 'type',
123 // Node.module handles its own caching.
124 // 'cacheable' => FALSE,
125 // Bundles must provide human readable name so
126 // we can create help and error messages about them.
127 'bundles' => node_type_get_names(),
128 ),
129 );
130 return $return;
131 }
132
133 /**
134 * Alter the entity info.
135 *
136 * Modules may implement this hook to alter the information that defines an
137 * entity. All properties that are available in hook_entity_info() can be
138 * altered here.
139 *
140 * @see hook_entity_info()
141 *
142 * @param $entity_info
143 * The entity info array, keyed by entity name.
144 */
145 function hook_entity_info_alter(&$entity_info) {
146 // Set the controller class for nodes to an alternate implementation of the
147 // DrupalEntityController interface.
148 $entity_info['node']['controller class'] = 'MyCustomNodeController';
149 }
150
151 /**
152 * Act on entities when loaded.
153 *
154 * This is a generic load hook called for all entity types loaded via the
155 * entity API.
156 *
157 * @param $entities
158 * The entities keyed by entity ID.
159 * @param $type
160 * The type of entities being loaded (i.e. node, user, comment).
161 */
162 function hook_entity_load($entities, $type) {
163 foreach ($entities as $entity) {
164 $entity->foo = mymodule_add_something($entity, $entity_type);
165 }
166 }
167
168 /**
169 * Perform periodic actions.
170 *
171 * This hook will only be called if cron.php is run (e.g. by crontab).
172 *
173 * Modules that require to schedule some commands to be executed at regular
174 * intervals can implement hook_cron(). The engine will then call the hook
175 * at the appropriate intervals defined by the administrator. This interface
176 * is particularly handy to implement timers or to automate certain tasks.
177 * Database maintenance, recalculation of settings or parameters are good
178 * candidates for cron tasks.
179 *
180 * Short-running or not resource intensive tasks can be executed directly.
181 *
182 * Long-running tasks should use the queue API. To do this, one or more queues
183 * need to be defined via hook_cron_queue_info(). Items that need to be
184 * processed are appended to the defined queue, instead of processing them
185 * directly in hook_cron().
186 * Examples of jobs that are good candidates for
187 * hook_cron_queue_info() include automated mailing, retrieving remote data, and
188 * intensive file tasks.
189 *
190 * @return
191 * None.
192 *
193 * @see hook_cron_queue_info()
194 */
195 function hook_cron() {
196 // Short-running operation example, not using a queue:
197 // Delete all expired records since the last cron run.
198 $expires = variable_get('mymodule_cron_last_run', REQUEST_TIME);
199 db_delete('mymodule_table')
200 ->condition('expires', $expires, '>=')
201 ->execute();
202 variable_set('mymodule_cron_last_run', REQUEST_TIME);
203
204 // Long-running operation example, leveraging a queue:
205 // Fetch feeds from other sites.
206 $result = db_query('SELECT * FROM {aggregator_feed} WHERE checked + refresh < :time AND refresh != :never', array(
207 ':time' => REQUEST_TIME,
208 ':never' => AGGREGATOR_CLEAR_NEVER,
209 ));
210 $queue = DrupalQueue::get('aggregator_feeds');
211 foreach ($result as $feed) {
212 $queue->createItem($feed);
213 }
214 }
215
216 /**
217 * Declare queues holding items that need to be run periodically.
218 *
219 * While there can be only one hook_cron() process running at the same time,
220 * there can be any number of processes defined here running. Because of
221 * this, long running tasks are much better suited for this API. Items queued
222 * in hook_cron() might be processed in the same cron run if there are not many
223 * items in the queue, otherwise it might take several requests, which can be
224 * run in parallel.
225 *
226 * @return
227 * An associative array where the key is the queue name and the value is
228 * again an associative array. Possible keys are:
229 * - 'worker callback': The name of the function to call. It will be called
230 * with one argument, the item created via DrupalQueue::createItem() in
231 * hook_cron().
232 * - 'time': (optional) How much time Drupal should spend on calling this
233 * worker in seconds. Defaults to 15.
234 *
235 * @see hook_cron()
236 */
237 function hook_cron_queue_info() {
238 $queues['aggregator_feeds'] = array(
239 'worker callback' => 'aggregator_refresh',
240 'time' => 15,
241 );
242 return $queues;
243 }
244
245 /**
246 * Allows modules to declare their own Forms API element types and specify their
247 * default values.
248 *
249 * This hook allows modules to declare their own form element types and to
250 * specify their default values. The values returned by this hook will be
251 * merged with the elements returned by hook_form() implementations and so
252 * can return defaults for any Form APIs keys in addition to those explicitly
253 * mentioned below.
254 *
255 * Each of the form element types defined by this hook is assumed to have
256 * a matching theme function, e.g. theme_elementtype(), which should be
257 * registered with hook_theme() as normal.
258 *
259 * Form more information about custom element types see the explanation at
260 * http://drupal.org/node/169815.
261 *
262 * @return
263 * An associative array describing the element types being defined. The array
264 * contains a sub-array for each element type, with the machine-readable type
265 * name as the key. Each sub-array has a number of possible attributes:
266 * - "#input": boolean indicating whether or not this element carries a value
267 * (even if it's hidden).
268 * - "#process": array of callback functions taking $element, $form_state,
269 * and $complete_form.
270 * - "#after_build": array of callback functions taking $element and $form_state.
271 * - "#validate": array of callback functions taking $form and $form_state.
272 * - "#element_validate": array of callback functions taking $element and
273 * $form_state.
274 * - "#pre_render": array of callback functions taking $element and $form_state.
275 * - "#post_render": array of callback functions taking $element and $form_state.
276 * - "#submit": array of callback functions taking $form and $form_state.
277 *
278 * @see hook_element_info_alter()
279 * @see system_element_info()
280 */
281 function hook_element_info() {
282 $types['filter_format'] = array(
283 '#input' => TRUE,
284 );
285 return $types;
286 }
287
288 /**
289 * Alter the element type information returned from modules.
290 *
291 * A module may implement this hook in order to alter the element type defaults
292 * defined by a module.
293 *
294 * @param &$type
295 * All element type defaults as collected by hook_element_info().
296 *
297 * @see hook_element_info()
298 */
299 function hook_element_info_alter(&$type) {
300 // Decrease the default size of textfields.
301 if (isset($type['textfield']['#size'])) {
302 $type['textfield']['#size'] = 40;
303 }
304 }
305
306 /**
307 * Perform cleanup tasks.
308 *
309 * This hook is run at the end of each page request. It is often used for
310 * page logging and specialized cleanup. This hook MUST NOT print anything.
311 *
312 * Only use this hook if your code must run even for cached page views.
313 * If you have code which must run once on all non cached pages, use
314 * hook_init instead. Thats the usual case. If you implement this hook
315 * and see an error like 'Call to undefined function', it is likely that
316 * you are depending on the presence of a module which has not been loaded yet.
317 * It is not loaded because Drupal is still in bootstrap mode.
318 *
319 * @param $destination
320 * If this hook is invoked as part of a drupal_goto() call, then this argument
321 * will be a fully-qualified URL that is the destination of the redirect.
322 */
323 function hook_exit($destination = NULL) {
324 db_update('counter')
325 ->expression('hits', 'hits + 1')
326 ->condition('type', 1)
327 ->execute();
328 }
329
330 /**
331 * Perform necessary alterations to the JavaScript before it is presented on
332 * the page.
333 *
334 * @param $javascript
335 * An array of all JavaScript being presented on the page.
336 * @see drupal_add_js()
337 * @see drupal_get_js()
338 * @see drupal_js_defaults()
339 */
340 function hook_js_alter(&$javascript) {
341 // Swap out jQuery to use an updated version of the library.
342 $javascript['misc/jquery.js']['data'] = drupal_get_path('module', 'jquery_update') . '/jquery.js';
343 }
344
345 /**
346 * Registers JavaScript/CSS libraries associated with a module.
347 *
348 * Modules implementing this return an array of arrays. The key to each
349 * sub-array is the machine readable name of the library. Each library may
350 * contain the following items:
351 *
352 * - 'title': The human readable name of the library.
353 * - 'website': The URL of the library's web site.
354 * - 'version': A string specifying the version of the library; intentionally
355 * not a float because a version like "1.2.3" is not a valid float. Use PHP's
356 * version_compare() to compare different versions.
357 * - 'js': An array of JavaScript elements; each element's key is used as $data
358 * argument, each element's value is used as $options array for
359 * drupal_add_js(). To add library-specific (not module-specific) JavaScript
360 * settings, the key may be skipped, the value must specify
361 * 'type' => 'setting', and the actual settings must be contained in a 'data'
362 * element of the value.
363 * - 'css': Like 'js', an array of CSS elements passed to drupal_add_css().
364 * - 'dependencies': An array of libraries that are required for a library. Each
365 * element is an array containing the module and name of the registered
366 * library. Note that all dependencies for each dependent library will be
367 * added when this library is added.
368 *
369 * Registered information for a library should contain re-usable data only.
370 * Module- or implementation-specific data and integration logic should be added
371 * separately.
372 *
373 * @return
374 * An array defining libraries associated with a module.
375 *
376 * @see system_library()
377 * @see drupal_add_library()
378 * @see drupal_get_library()
379 */
380 function hook_library() {
381 // Library One.
382 $libraries['library-1'] = array(
383 'title' => 'Library One',
384 'website' => 'http://example.com/library-1',
385 'version' => '1.2',
386 'js' => array(
387 drupal_get_path('module', 'my_module') . '/library-1.js' => array(),
388 ),
389 'css' => array(
390 drupal_get_path('module', 'my_module') . '/library-2.css' => array(
391 'type' => 'file',
392 'media' => 'screen',
393 ),
394 ),
395 );
396 // Library Two.
397 $libraries['library-2'] = array(
398 'title' => 'Library Two',
399 'website' => 'http://example.com/library-2',
400 'version' => '3.1-beta1',
401 'js' => array(
402 // JavaScript settings may use the 'data' key.
403 array(
404 'type' => 'setting',
405 'data' => array('library2' => TRUE),
406 ),
407 ),
408 'dependencies' => array(
409 // Require jQuery UI core by System module.
410 array('system' => 'ui'),
411 // Require our other library.
412 array('my_module', 'library-1'),
413 // Require another library.
414 array('other_module', 'library-3'),
415 ),
416 );
417 return $libraries;
418 }
419
420 /**
421 * Alters the JavaScript/CSS library registry.
422 *
423 * Allows certain, contributed modules to update libraries to newer versions
424 * while ensuring backwards compatibility. In general, such manipulations should
425 * only be done by designated modules, since most modules that integrate with a
426 * certain library also depend on the API of a certain library version.
427 *
428 * @param $libraries
429 * The JavaScript/CSS libraries provided by $module. Keyed by internal library
430 * name and passed by reference.
431 * @param $module
432 * The name of the module that registered the libraries.
433 *
434 * @see hook_library()
435 */
436 function hook_library_alter(&$libraries, $module) {
437 // Update Farbtastic to version 2.0.
438 if ($module == 'system' && isset($libraries['farbtastic'])) {
439 // Verify existing version is older than the one we are updating to.
440 if (version_compare($libraries['farbtastic']['version'], '2.0', '<')) {
441 // Update the existing Farbtastic to version 2.0.
442 $libraries['farbtastic']['version'] = '2.0';
443 $libraries['farbtastic']['js'] = array(
444 drupal_get_path('module', 'farbtastic_update') . '/farbtastic-2.0.js' => array(),
445 );
446 }
447 }
448 }
449
450 /**
451 * Alter CSS files before they are output on the page.
452 *
453 * @param $css
454 * An array of all CSS items (files and inline CSS) being requested on the page.
455 * @see drupal_add_css()
456 * @see drupal_get_css()
457 */
458 function hook_css_alter(&$css) {
459 // Remove defaults.css file.
460 unset($css[drupal_get_path('module', 'system') . '/defaults.css']);
461 }
462
463 /**
464 * Add elements to a page before it is rendered.
465 *
466 * Use this hook when you want to add elements at the page level. For your
467 * additions to be printed, they have to be placed below a top level array key
468 * of the $page array that has the name of a region of the active theme.
469 *
470 * By default, valid region keys are 'page_top', 'header', 'sidebar_first',
471 * 'content', 'sidebar_second' and 'page_bottom'. To get a list of all regions
472 * of the active theme, use system_region_list($theme). Note that $theme is a
473 * global variable.
474 *
475 * If you want to alter the elements added by other modules or if your module
476 * depends on the elements of other modules, use hook_page_alter() instead which
477 * runs after this hook.
478 *
479 * @param $page
480 * Nested array of renderable elements that make up the page.
481 *
482 * @see hook_page_alter()
483 * @see drupal_render_page()
484 */
485 function hook_page_build(&$page) {
486 if (menu_get_object('node', 1)) {
487 // We are on a node detail page. Append a standard disclaimer to the
488 // content region.
489 $page['content']['disclaimer'] = array(
490 '#markup' => t('Acme, Inc. is not responsible for the contents of this sample code.'),
491 '#weight' => 25,
492 );
493 }
494 }
495
496 /**
497 * Perform alterations before a page is rendered.
498 *
499 * Use this hook when you want to remove or alter elements at the page
500 * level, or add elements at the page level that depend on an other module's
501 * elements (this hook runs after hook_page_build().
502 *
503 * If you are making changes to entities such as forms, menus, or user
504 * profiles, use those objects' native alter hooks instead (hook_form_alter(),
505 * for example).
506 *
507 * The $page array contains top level elements for each block region:
508 * @code
509 * $page['page_top']
510 * $page['header']
511 * $page['sidebar_first']
512 * $page['content']
513 * $page['sidebar_second']
514 * $page['page_bottom']
515 * @endcode
516 *
517 * The 'content' element contains the main content of the current page, and its
518 * structure will vary depending on what module is responsible for building the
519 * page. Some legacy modules may not return structured content at all: their
520 * pre-rendered markup will be located in $page['content']['main']['#markup'].
521 *
522 * Pages built by Drupal's core Node and Blog modules use a standard structure:
523 *
524 * @code
525 * // Node body.
526 * $page['content']['nodes'][$nid]['body']
527 * // Array of links attached to the node (add comments, read more).
528 * $page['content']['nodes'][$nid]['links']
529 * // The node object itself.
530 * $page['content']['nodes'][$nid]['#node']
531 * // The results pager.
532 * $page['content']['pager']
533 * @endcode
534 *
535 * Blocks may be referenced by their module/delta pair within a region:
536 * @code
537 * // The login block in the first sidebar region.
538 * $page['sidebar_first']['user_login']['#block'];
539 * @endcode
540 *
541 * @param $page
542 * Nested array of renderable elements that make up the page.
543 *
544 * @see hook_page_build()
545 * @see drupal_render_page()
546 */
547 function hook_page_alter(&$page) {
548 // Add help text to the user login block.
549 $page['sidebar_first']['user_login']['help'] = array(
550 '#weight' => -10,
551 '#markup' => t('To post comments or add new content, you first have to log in.'),
552 );
553 }
554
555 /**
556 * Perform alterations before a form is rendered.
557 *
558 * One popular use of this hook is to add form elements to the node form. When
559 * altering a node form, the node object retrieved at from $form['#node'].
560 *
561 * Note that instead of hook_form_alter(), which is called for all forms, you
562 * can also use hook_form_FORM_ID_alter() to alter a specific form.
563 *
564 * @param $form
565 * Nested array of form elements that comprise the form.
566 * @param $form_state
567 * A keyed array containing the current state of the form.
568 * @param $form_id
569 * String representing the name of the form itself. Typically this is the
570 * name of the function that generated the form.
571 */
572 function hook_form_alter(&$form, &$form_state, $form_id) {
573 if (isset($form['type']) && $form['type']['#value'] . '_node_settings' == $form_id) {
574 $form['workflow']['upload_' . $form['type']['#value']] = array(
575 '#type' => 'radios',
576 '#title' => t('Attachments'),
577 '#default_value' => variable_get('upload_' . $form['type']['#value'], 1),
578 '#options' => array(t('Disabled'), t('Enabled')),
579 );
580 }
581 }
582
583 /**
584 * Provide a form-specific alteration instead of the global hook_form_alter().
585 *
586 * Modules can implement hook_form_FORM_ID_alter() to modify a specific form,
587 * rather than implementing hook_form_alter() and checking the form ID, or
588 * using long switch statements to alter multiple forms.
589 *
590 * Note that this hook fires before hook_form_alter(). Therefore all
591 * implementations of hook_form_FORM_ID_alter() will run before all implementations
592 * of hook_form_alter(), regardless of the module order.
593 *
594 * @param $form
595 * Nested array of form elements that comprise the form.
596 * @param $form_state
597 * A keyed array containing the current state of the form.
598 *
599 * @see drupal_prepare_form().
600 */
601 function hook_form_FORM_ID_alter(&$form, &$form_state) {
602 // Modification for the form with the given form ID goes here. For example, if
603 // FORM_ID is "user_register_form" this code would run only on the user
604 // registration form.
605
606 // Add a checkbox to registration form about agreeing to terms of use.
607 $form['terms_of_use'] = array(
608 '#type' => 'checkbox',
609 '#title' => t("I agree with the website's terms and conditions."),
610 '#required' => TRUE,
611 );
612 }
613
614 /**
615 * Allow themes to alter the theme-specific settings form.
616 *
617 * With this hook, themes can alter the theme-specific settings form in any way
618 * allowable by Drupal's Forms API, such as adding form elements, changing
619 * default values and removing form elements. See the Forms API documentation on
620 * api.drupal.org for detailed information.
621 *
622 * Note that the base theme's form alterations will be run before any sub-theme
623 * alterations.
624 *
625 * @param $form
626 * Nested array of form elements that comprise the form.
627 * @param $form_state
628 * A keyed array containing the current state of the form.
629 */
630 function hook_form_system_theme_settings_alter(&$form, &$form_state) {
631 // Add a checkbox to toggle the breadcrumb trail.
632 $form['toggle_breadcrumb'] = array(
633 '#type' => 'checkbox',
634 '#title' => t('Display the breadcrumb'),
635 '#default_value' => theme_get_setting('toggle_breadcrumb'),
636 '#description' => t('Show a trail of links from the homepage to the current page.'),
637 );
638 }
639
640 /**
641 * Map form_ids to builder functions.
642 *
643 * This hook allows modules to build multiple forms from a single form "factory"
644 * function but each form will have a different form id for submission,
645 * validation, theming or alteration by other modules.
646 *
647 * The 'callback arguments' will be passed as parameters to the function defined
648 * in 'callback'. In case the code that calls drupal_get_form() also passes
649 * parameters, then the 'callback' function will receive the
650 * 'callback arguments' specified in hook_forms() before those that have been
651 * passed to drupal_get_form().
652 *
653 * See node_forms() for an actual example of how multiple forms share a common
654 * building function.
655 *
656 * @param $form_id
657 * The unique string identifying the desired form.
658 * @param $args
659 * An array containing the original arguments provided to drupal_get_form().
660 * These are always passed to the form builder and do not have to be specified
661 * manually in 'callback arguments'.
662 *
663 * @return
664 * An associative array whose keys define form_ids and whose values are an
665 * associative array defining the following keys:
666 * - callback: The name of the form builder function to invoke.
667 * - callback arguments: (optional) Additional arguments to pass to the
668 * function defined in 'callback', which are prepended to $args.
669 * - wrapper_callback: (optional) The name of a form builder function to
670 * invoke before the form builder defined in 'callback' is invoked. This
671 * wrapper callback may prepopulate the $form array with form elements,
672 * which will then be already contained in the $form that is passed on to
673 * the form builder defined in 'callback'. For example, a wrapper callback
674 * could setup wizard-alike form buttons that are the same for a variety of
675 * forms that belong to the wizard, which all share the same wrapper
676 * callback.
677 */
678 function hook_forms($form_id, $args) {
679 // Simply reroute the (non-existing) $form_id 'mymodule_first_form' to
680 // 'mymodule_main_form'.
681 $forms['mymodule_first_form'] = array(
682 'callback' => 'mymodule_main_form',
683 );
684
685 // Reroute the $form_id and prepend an additional argument that gets passed to
686 // the 'mymodule_main_form' form builder function.
687 $forms['mymodule_second_form'] = array(
688 'callback' => 'mymodule_main_form',
689 'callback arguments' => array('some parameter'),
690 );
691
692 // Reroute the $form_id, but invoke the form builder function
693 // 'mymodule_main_form_wrapper' first, so we can prepopulate the $form array
694 // that is passed to the actual form builder 'mymodule_main_form'.
695 $forms['mymodule_wrapped_form'] = array(
696 'callback' => 'mymodule_main_form',
697 'wrapper_callback' => 'mymodule_main_form_wrapper',
698 );
699
700 return $forms;
701 }
702
703 /**
704 * Perform setup tasks. See also, hook_init.
705 *
706 * This hook is run at the beginning of the page request. It is typically
707 * used to set up global parameters which are needed later in the request.
708 *
709 * Only use this hook if your code must run even for cached page views.This hook
710 * is called before modules or most include files are loaded into memory.
711 * It happens while Drupal is still in bootstrap mode.
712 */
713 function hook_boot() {
714 // we need user_access() in the shutdown function. make sure it gets loaded
715 drupal_load('module', 'user');
716 register_shutdown_function('devel_shutdown');
717 }
718
719 /**
720 * Perform setup tasks. See also, hook_boot.
721 *
722 * This hook is run at the beginning of the page request. It is typically
723 * used to set up global parameters which are needed later in the request.
724 * when this hook is called, all modules are already loaded in memory.
725 *
726 * For example, this hook is a typical place for modules to add CSS or JS
727 * that should be present on every page. This hook is not run on cached
728 * pages - though CSS or JS added this way will be present on a cached page.
729 */
730 function hook_init() {
731 drupal_add_css(drupal_get_path('module', 'book') . '/book.css');
732 }
733
734 /**
735 * Define image toolkits provided by this module.
736 *
737 * The file which includes each toolkit's functions must be declared as part of
738 * the files array in the module .info file so that the registry will find and
739 * parse it.
740 *
741 * The toolkit's functions must be named image_toolkitname_operation().
742 * where the operation may be:
743 * - 'load': Required. See image_gd_load() for usage.
744 * - 'save': Required. See image_gd_save() for usage.
745 * - 'settings': Optional. See image_gd_settings() for usage.
746 * - 'resize': Optional. See image_gd_resize() for usage.
747 * - 'rotate': Optional. See image_gd_rotate() for usage.
748 * - 'crop': Optional. See image_gd_crop() for usage.
749 * - 'desaturate': Optional. See image_gd_desaturate() for usage.
750 *
751 * @return
752 * An array with the toolkit name as keys and sub-arrays with these keys:
753 * - 'title': A string with the toolkit's title.
754 * - 'available': A Boolean value to indicate that the toolkit is operating
755 * properly, e.g. all required libraries exist.
756 *
757 * @see system_image_toolkits()
758 */
759 function hook_image_toolkits() {
760 return array(
761 'working' => array(
762 'title' => t('A toolkit that works.'),
763 'available' => TRUE,
764 ),
765 'broken' => array(
766 'title' => t('A toolkit that is "broken" and will not be listed.'),
767 'available' => FALSE,
768 ),
769 );
770 }
771
772 /**
773 * Alter an email message created with the drupal_mail() function.
774 *
775 * hook_mail_alter() allows modification of email messages created and sent
776 * with drupal_mail(). Usage examples include adding and/or changing message
777 * text, message fields, and message headers.
778 *
779 * Email messages sent using functions other than drupal_mail() will not
780 * invoke hook_mail_alter(). For example, a contributed module directly
781 * calling the drupal_mail_system()->mail() or PHP mail() function
782 * will not invoke this hook. All core modules use drupal_mail() for
783 * messaging, it is best practice but not manditory in contributed modules.
784 *
785 * @param $message
786 * An array containing the message data. Keys in this array include:
787 * - 'id':
788 * The drupal_mail() id of the message. Look at module source code or
789 * drupal_mail() for possible id values.
790 * - 'to':
791 * The address or addresses the message will be sent to. The
792 * formatting of this string must comply with RFC 2822.
793 * - 'from':
794 * The address the message will be marked as being from, which is
795 * either a custom address or the site-wide default email address.
796 * - 'subject':
797 * Subject of the email to be sent. This must not contain any newline
798 * characters, or the email may not be sent properly.
799 * - 'body':
800 * An array of strings containing the message text. The message body is
801 * created by concatenating the individual array strings into a single text
802 * string using "\n\n" as a separator.
803 * - 'headers':
804 * Associative array containing mail headers, such as From, Sender,
805 * MIME-Version, Content-Type, etc.
806 * - 'params':
807 * An array of optional parameters supplied by the caller of drupal_mail()
808 * that is used to build the message before hook_mail_alter() is invoked.
809 * - 'language':
810 * The language object used to build the message before hook_mail_alter()
811 * is invoked.
812 *
813 * @see drupal_mail()
814 */
815 function hook_mail_alter(&$message) {
816 if ($message['id'] == 'modulename_messagekey') {
817 $message['body'][] = "--\nMail sent out from " . variable_get('sitename', t('Drupal'));
818 }
819 }
820
821 /**
822 * Alter the information parsed from module and theme .info files
823 *
824 * This hook is invoked in _system_rebuild_module_data() and in
825 * _system_rebuild_theme_data(). A module may implement this hook in order to
826 * add to or alter the data generated by reading the .info file with
827 * drupal_parse_info_file().
828 *
829 * @param &$info
830 * The .info file contents, passed by reference so that it can be altered.
831 * @param $file
832 * Full information about the module or theme, including $file->name, and
833 * $file->filename
834 * @param $type
835 * Either 'module' or 'theme', depending on the type of .info file that was
836 * passed.
837 */
838 function hook_system_info_alter(&$info, $file, $type) {
839 // Only fill this in if the .info file does not define a 'datestamp'.
840 if (empty($info['datestamp'])) {
841 $info['datestamp'] = filemtime($file->filename);
842 }
843 }
844
845 /**
846 * Define user permissions.
847 *
848 * This hook can supply permissions that the module defines, so that they
849 * can be selected on the user permissions page and used to grant or restrict
850 * access to actions the module performs.
851 *
852 * Permissions are checked using user_access().
853 *
854 * For a detailed usage example, see page_example.module.
855 *
856 * @return
857 * An array of which permission names are the keys and their corresponding
858 * values are descriptions of each permission.
859 * The permission names (keys of the array) must not be wrapped with
860 * the t() function, since the string extractor takes care of
861 * extracting permission names defined in the perm hook for
862 * translation. The permission descriptions (values of the array)
863 * should be wrapped in the t() function so they can be translated.
864 */
865 function hook_permission() {
866 return array(
867 'administer my module' => array(
868 'title' => t('Administer my module'),
869 'description' => t('Perform administration tasks for my module.'),
870 ),
871 );
872 }
873
874 /**
875 * Register a module (or theme's) theme implementations.
876 *
877 * Modules and themes implementing this return an array of arrays. The key
878 * to each sub-array is the internal name of the hook, and the array contains
879 * info about the hook. Each array may contain the following items:
880 *
881 * - variables: (required if "render element" not present) An array of
882 * variables that this theme hook uses. This value allows the theme layer to
883 * properly utilize templates. Each array key represents the name of the
884 * variable and the value will be used as the default value if it is not given
885 * when theme() is called. Template implementations receive these arguments as
886 * variables in the template file. Function implementations are passed this
887 * array data in the $variables parameter.
888 * - render element: (required if "variables" not present) A string that is the
889 * name of the sole renderable element to pass to the theme function. The
890 * string represents the name of the "variable" that will hold the renderable
891 * array inside any optional preprocess or process functions. Cannot be used
892 * with the "variables" item; only one or the other, not both, can be present
893 * in a hook's info array.
894 * - file: The file the implementation resides in. This file will be included
895 * prior to the theme being rendered, to make sure that the function or
896 * preprocess function (as needed) is actually loaded; this makes it possible
897 * to split theme functions out into separate files quite easily.
898 * - path: Override the path of the file to be used. Ordinarily the module or
899 * theme path will be used, but if the file will not be in the default path,
900 * include it here. This path should be relative to the Drupal root
901 * directory.
902 * - template: If specified, this theme implementation is a template, and this
903 * is the template file <b>without an extension</b>. Do not put .tpl.php
904 * on this file; that extension will be added automatically by the default
905 * rendering engine (which is PHPTemplate). If 'path', above, is specified,
906 * the template should also be in this path.
907 * - function: If specified, this will be the function name to invoke for this
908 * implementation. If neither file nor function is specified, a default
909 * function name will be assumed. For example, if a module registers
910 * the 'node' theme hook, 'theme_node' will be assigned to its function.
911 * If the chameleon theme registers the node hook, it will be assigned
912 * 'chameleon_node' as its function.
913 * - pattern: A regular expression pattern to be used to allow this theme
914 * implementation to have a dynamic name. The convention is to use __ to
915 * differentiate the dynamic portion of the theme. For example, to allow
916 * forums to be themed individually, the pattern might be: 'forum__'. Then,
917 * when the forum is themed, call: <code>theme(array('forum__' . $tid, 'forum'),
918 * $forum)</code>.
919 * - preprocess functions: A list of functions used to preprocess this data.
920 * Ordinarily this won't be used; it's automatically filled in. By default,
921 * for a module this will be filled in as template_preprocess_HOOK. For
922 * a theme this will be filled in as phptemplate_preprocess and
923 * phptemplate_preprocess_HOOK as well as themename_preprocess and
924 * themename_preprocess_HOOK.
925 * - override preprocess functions: Set to TRUE when a theme does NOT want the
926 * standard preprocess functions to run. This can be used to give a theme
927 * FULL control over how variables are set. For example, if a theme wants
928 * total control over how certain variables in the page.tpl.php are set,
929 * this can be set to true. Please keep in mind that when this is used
930 * by a theme, that theme becomes responsible for making sure necessary
931 * variables are set.
932 * - type: (automatically derived) Where the theme hook is defined:
933 * 'module', 'theme_engine', or 'theme'.
934 * - theme path: (automatically derived) The directory path of the theme or
935 * module, so that it doesn't need to be looked up.
936 * - theme paths: (automatically derived) An array of template suggestions where
937 * .tpl.php files related to this theme hook may be found.
938 *
939 * The following parameters are all optional.
940 *
941 * @param $existing
942 * An array of existing implementations that may be used for override
943 * purposes. This is primarily useful for themes that may wish to examine
944 * existing implementations to extract data (such as arguments) so that
945 * it may properly register its own, higher priority implementations.
946 * @param $type
947 * What 'type' is being processed. This is primarily useful so that themes
948 * tell if they are the actual theme being called or a parent theme.
949 * May be one of:
950 * - module: A module is being checked for theme implementations.
951 * - base_theme_engine: A theme engine is being checked for a theme which is a parent of the actual theme being used.
952 * - theme_engine: A theme engine is being checked for the actual theme being used.
953 * - base_theme: A base theme is being checked for theme implementations.
954 * - theme: The actual theme in use is being checked.
955 * @param $theme
956 * The actual name of theme that is being being checked (mostly only useful for
957 * theme engine).
958 * @param $path
959 * The directory path of the theme or module, so that it doesn't need to be
960 * looked up.
961 *
962 * @return
963 * A keyed array of theme hooks.
964 */
965 function hook_theme($existing, $type, $theme, $path) {
966 return array(
967 'forum_display' => array(
968 'variables' => array('forums' => NULL, 'topics' => NULL, 'parents' => NULL, 'tid' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL),
969 ),
970 'forum_list' => array(
971 'variables' => array('forums' => NULL, 'parents' => NULL, 'tid' => NULL),
972 ),
973 'forum_topic_list' => array(
974 'variables' => array('tid' => NULL, 'topics' => NULL, 'sortby' => NULL, 'forum_per_page' => NULL),
975 ),
976 'forum_icon' => array(
977 'variables' => array('new_posts' => NULL, 'num_posts' => 0, 'comment_mode' => 0, 'sticky' => 0),
978 ),
979 'status_report' => array(
980 'render element' => 'requirements',
981 'file' => 'system.admin.inc',
982 ),
983 'system_date_time_settings' => array(
984 'render element' => 'form',
985 'file' => 'system.admin.inc',
986 ),
987 );
988 }
989
990 /**
991 * Alter the theme registry information returned from hook_theme().
992 *
993 * The theme registry stores information about all available theme hooks,
994 * including which callback functions those hooks will call when triggered,
995 * what template files are exposed by these hooks, and so on.
996 *
997 * Note that this hook is only executed as the theme cache is re-built.
998 * Changes here will not be visible until the next cache clear.
999 *
1000 * The $theme_registry array is keyed by theme hook name, and contains the
1001 * information returned from hook_theme(), as well as additional properties
1002 * added by _theme_process_registry().
1003 *
1004 * For example:
1005 * @code
1006 * $theme_registry['user_profile'] = array(
1007 * 'variables' => array(
1008 * 'account' => NULL,
1009 * ),
1010 * 'template' => 'modules/user/user-profile',
1011 * 'file' => 'modules/user/user.pages.inc',
1012 * 'type' => 'module',
1013 * 'theme path' => 'modules/user',
1014 * 'theme paths' => array(
1015 * 0 => 'modules/user',
1016 * ),
1017 * 'preprocess functions' => array(
1018 * 0 => 'template_preprocess',
1019 * 1 => 'template_preprocess_user_profile',
1020 * ),
1021 * )
1022 * );
1023 * @endcode
1024 *
1025 * @param $theme_registry
1026 * The entire cache of theme registry information, post-processing.
1027 * @see hook_theme()
1028 * @see _theme_process_registry()
1029 */
1030 function hook_theme_registry_alter(&$theme_registry) {
1031 // Kill the next/previous forum topic navigation links.
1032 foreach ($theme_registry['forum_topic_navigation']['preprocess functions'] as $key => $value) {
1033 if ($value = 'template_preprocess_forum_topic_navigation') {
1034 unset($theme_registry['forum_topic_navigation']['preprocess functions'][$key]);
1035 }
1036 }
1037 }
1038
1039 /**
1040 * Register XML-RPC callbacks.
1041 *
1042 * This hook lets a module register callback functions to be called when
1043 * particular XML-RPC methods are invoked by a client.
1044 *
1045 * @return
1046 * An array which maps XML-RPC methods to Drupal functions. Each array
1047 * element is either a pair of method => function or an array with four
1048 * entries:
1049 * - The XML-RPC method name (for example, module.function).
1050 * - The Drupal callback function (for example, module_function).
1051 * - The method signature is an array of XML-RPC types. The first element
1052 * of this array is the type of return value and then you should write a
1053 * list of the types of the parameters. XML-RPC types are the following
1054 * (See the types at http://www.xmlrpc.com/spec):
1055 * - "boolean": 0 (false) or 1 (true).
1056 * - "double": a floating point number (for example, -12.214).
1057 * - "int": a integer number (for example, -12).
1058 * - "array": an array without keys (for example, array(1, 2, 3)).
1059 * - "struct": an associative array or an object (for example,
1060 * array('one' => 1, 'two' => 2)).
1061 * - "date": when you return a date, then you may either return a
1062 * timestamp (time(), mktime() etc.) or an ISO8601 timestamp. When
1063 * date is specified as an input parameter, then you get an object,
1064 * which is described in the function xmlrpc_date
1065 * - "base64": a string containing binary data, automatically
1066 * encoded/decoded automatically.
1067 * - "string": anything else, typically a string.
1068 * - A descriptive help string, enclosed in a t() function for translation
1069 * purposes.
1070 * Both forms are shown in the example.
1071 */
1072 function hook_xmlrpc() {
1073 return array(
1074 'drupal.login' => 'drupal_login',
1075 array(
1076 'drupal.site.ping',
1077 'drupal_directory_ping',
1078 array('boolean', 'string', 'string', 'string', 'string', 'string'),
1079 t('Handling ping request'))
1080 );
1081 }
1082
1083 /**
1084 * Log an event message
1085 *
1086 * This hook allows modules to route log events to custom destinations, such as
1087 * SMS, Email, pager, syslog, ...etc.
1088 *
1089 * @param $log_entry
1090 * An associative array containing the following keys:
1091 * - type: The type of message for this entry. For contributed modules, this is
1092 * normally the module name. Do not use 'debug', use severity WATCHDOG_DEBUG instead.
1093 * - user: The user object for the user who was logged in when the event happened.
1094 * - request_uri: The Request URI for the page the event happened in.
1095 * - referer: The page that referred the use to the page where the event occurred.
1096 * - ip: The IP address where the request for the page came from.
1097 * - timestamp: The UNIX timetamp of the date/time the event occurred
1098 * - severity: One of the following values as defined in RFC 3164 http://www.faqs.org/rfcs/rfc3164.html
1099 * WATCHDOG_EMERG Emergency: system is unusable
1100 * WATCHDOG_ALERT Alert: action must be taken immediately
1101 * WATCHDOG_CRITICAL Critical: critical conditions
1102 * WATCHDOG_ERROR Error: error conditions
1103 * WATCHDOG_WARNING Warning: warning conditions
1104 * WATCHDOG_NOTICE Notice: normal but significant condition
1105 * WATCHDOG_INFO Informational: informational messages
1106 * WATCHDOG_DEBUG Debug: debug-level messages
1107 * - link: an optional link provided by the module that called the watchdog() function.
1108 * - message: The text of the message to be logged.
1109 */
1110 function hook_watchdog(array $log_entry) {
1111 global $base_url, $language;
1112
1113 $severity_list = array(
1114 WATCHDOG_EMERG => t('Emergency'),
1115 WATCHDOG_ALERT => t('Alert'),
1116 WATCHDOG_CRITICAL => t('Critical'),
1117 WATCHDOG_ERROR => t('Error'),
1118 WATCHDOG_WARNING => t('Warning'),
1119 WATCHDOG_NOTICE => t('Notice'),
1120 WATCHDOG_INFO => t('Info'),
1121 WATCHDOG_DEBUG => t('Debug'),
1122 );
1123
1124 $to = 'someone@example.com';
1125 $params = array();
1126 $params['subject'] = t('[@site_name] @severity_desc: Alert from your web site', array(
1127 '@site_name' => variable_get('site_name', 'Drupal'),
1128 '@severity_desc' => $severity_list[$log_entry['severity']],
1129 ));
1130
1131 $params['message'] = "\nSite: @base_url";
1132 $params['message'] .= "\nSeverity: (@severity) @severity_desc";
1133 $params['message'] .= "\nTimestamp: @timestamp";
1134 $params['message'] .= "\nType: @type";
1135 $params['message'] .= "\nIP Address: @ip";
1136 $params['message'] .= "\nRequest URI: @request_uri";
1137 $params['message'] .= "\nReferrer URI: @referer_uri";
1138 $params['message'] .= "\nUser: (@uid) @name";
1139 $params['message'] .= "\nLink: @link";
1140 $params['message'] .= "\nMessage: \n\n@message";
1141
1142 $params['message'] = t($params['message'], array(
1143 '@base_url' => $base_url,
1144 '@severity' => $log_entry['severity'],
1145 '@severity_desc' => $severity_list[$log_entry['severity']],
1146 '@timestamp' => format_date($log_entry['timestamp']),
1147 '@type' => $log_entry['type'],
1148 '@ip' => $log_entry['ip'],
1149 '@request_uri' => $log_entry['request_uri'],
1150 '@referer_uri' => $log_entry['referer'],
1151 '@uid' => $log_entry['user']->uid,
1152 '@name' => $log_entry['user']->name,
1153 '@link' => strip_tags($log_entry['link']),
1154 '@message' => strip_tags($log_entry['message']),
1155 ));
1156
1157 drupal_mail('emaillog', 'entry', $to, $language, $params);
1158 }
1159
1160 /**
1161 * Prepare a message based on parameters; called from drupal_mail().
1162 *
1163 * @param $key
1164 * An identifier of the mail.
1165 * @param $message
1166 * An array to be filled in. Keys in this array include:
1167 * - 'id':
1168 * An id to identify the mail sent. Look at module source code
1169 * or drupal_mail() for possible id values.
1170 * - 'to':
1171 * The address or addresses the message will be sent to. The
1172 * formatting of this string must comply with RFC 2822.
1173 * - 'subject':
1174 * Subject of the e-mail to be sent. This must not contain any newline
1175 * characters, or the mail may not be sent properly. drupal_mail() sets
1176 * this to an empty string when the hook is invoked.
1177 * - 'body':
1178 * An array of lines containing the message to be sent. Drupal will format
1179 * the correct line endings for you. drupal_mail() sets this to an empty
1180 * array when the hook is invoked.
1181 * - 'from':
1182 * The address the message will be marked as being from, which is
1183 * set by drupal_mail() to either a custom address or the site-wide
1184 * default email address when the hook is invoked.
1185 * - 'headers':
1186 * Associative array containing mail headers, such as From, Sender,
1187 * MIME-Version, Content-Type, etc. drupal_mail() pre-fills
1188 * several headers in this array.
1189 * @param $params
1190 * An array of parameters supplied by the caller of drupal_mail().
1191 */
1192 function hook_mail($key, &$message, $params) {
1193 $account = $params['account'];
1194 $context = $params['context'];
1195 $variables = array(
1196 '%site_name' => variable_get('site_name', 'Drupal'),
1197 '%username' => format_username($account),
1198 );
1199 if ($context['hook'] == 'taxonomy') {
1200 $object = $params['object'];
1201 $vocabulary = taxonomy_vocabulary_load($object->vid);
1202 $variables += array(
1203 '%term_name' => $object->name,
1204 '%term_description' => $object->description,
1205 '%term_id' => $object->tid,
1206 '%vocabulary_name' => $vocabulary->name,
1207 '%vocabulary_description' => $vocabulary->description,
1208 '%vocabulary_id' => $vocabulary->vid,
1209 );
1210 }
1211
1212 // Node-based variable translation is only available if we have a node.
1213 if (isset($params['node'])) {
1214 $node = $params['node'];
1215 $variables += array(
1216 '%uid' => $node->uid,
1217 '%node_url' => url('node/' . $node->nid, array('absolute' => TRUE)),
1218 '%node_type' => node_type_get_name($node),
1219 '%title' => $node->title[FIELD_LANGUAGE_NONE][0]['value'],
1220 '%teaser' => $node->teaser,
1221 '%body' => $node->body,
1222 );
1223 }
1224 $subject = strtr($context['subject'], $variables);
1225 $body = strtr($context['message'], $variables);
1226 $message['subject'] .= str_replace(array("\r", "\n"), '', $subject);
1227 $message['body'][] = drupal_html_to_text($body);
1228 }
1229
1230 /**
1231 * Add a list of cache tables to be cleared.
1232 *
1233 * This hook allows your module to add cache table names to the list of cache
1234 * tables that will be cleared by the Clear button on the Performance page or
1235 * whenever drupal_flush_all_caches is invoked.
1236 *
1237 * @see drupal_flush_all_caches()
1238 *
1239 * @return
1240 * An array of cache table names.
1241 */
1242 function hook_flush_caches() {
1243 return array('cache_example');
1244 }
1245
1246 /**
1247 * Perform necessary actions after modules are installed.
1248 *
1249 * This function differs from hook_install() as it gives all other
1250 * modules a chance to perform actions when a module is installed,
1251 * whereas hook_install() will only be called on the module actually
1252 * being installed.
1253 *
1254 * @see hook_install()
1255 *
1256 * @param $modules
1257 * An array of the installed modules.
1258 */
1259 function hook_modules_installed($modules) {
1260 if (in_array('lousy_module', $modules)) {
1261 variable_set('lousy_module_conflicting_variable', FALSE);
1262 }
1263 }
1264
1265 /**
1266 * Perform necessary actions after modules are enabled.
1267 *
1268 * This function differs from hook_enable() as it gives all other
1269 * modules a chance to perform actions when modules are enabled,
1270 * whereas hook_enable() will only be called on the module actually
1271 * being enabled.
1272 *
1273 * @see hook_enable()
1274 *
1275 * @param $modules
1276 * An array of the enabled modules.
1277 */
1278 function hook_modules_enabled($modules) {
1279 if (in_array('lousy_module', $modules)) {
1280 drupal_set_message(t('mymodule is not compatible with lousy_module'), 'error');
1281 mymodule_disable_functionality();
1282 }
1283 }
1284
1285 /**
1286 * Perform necessary actions after modules are disabled.
1287 *
1288 * This function differs from hook_disable() as it gives all other
1289 * modules a chance to perform actions when modules are disabled,
1290 * whereas hook_disable() will only be called on the module actually
1291 * being disabled.
1292 *
1293 * @see hook_disable()
1294 *
1295 * @param $modules
1296 * An array of the disabled modules.
1297 */
1298 function hook_modules_disabled($modules) {
1299 if (in_array('lousy_module', $modules)) {
1300 mymodule_enable_functionality();
1301 }
1302 }
1303
1304 /**
1305 * Perform necessary actions after modules are uninstalled.
1306 *
1307 * This function differs from hook_uninstall() as it gives all other
1308 * modules a chance to perform actions when a module is uninstalled,
1309 * whereas hook_uninstall() will only be called on the module actually
1310 * being uninstalled.
1311 *
1312 * It is recommended that you implement this module if your module
1313 * stores data that may have been set by other modules.
1314 *
1315 * @see hook_uninstall()
1316 *
1317 * @param $modules
1318 * The name of the uninstalled module.
1319 */
1320 function hook_modules_uninstalled($modules) {
1321 foreach ($modules as $module) {
1322 db_delete('mymodule_table')
1323 ->condition('module', $module)
1324 ->execute();
1325 }
1326 mymodule_cache_rebuild();
1327 }
1328
1329 /**
1330 * Registers PHP stream wrapper implementations associated with a module.
1331 *
1332 * Provide a facility for managing and querying user-defined stream wrappers
1333 * in PHP. PHP's internal stream_get_wrappers() doesn't return the class
1334 * registered to handle a stream, which we need to be able to find the handler
1335 * for class instantiation.
1336 *
1337 * If a module registers a scheme that is already registered with PHP, it will
1338 * be unregistered and replaced with the specified class.
1339 *
1340 * @return
1341 * A nested array, keyed first by scheme name ("public" for "public://"),
1342 * then keyed by the following values:
1343 * - 'name' A short string to name the wrapper.
1344 * - 'class' A string specifying the PHP class that implements the
1345 * DrupalStreamWrapperInterface interface.
1346 * - 'description' A string with a short description of what the wrapper does.
1347 *
1348 * @see file_get_stream_wrappers()
1349 * @see hook_stream_wrappers_alter()
1350 * @see system_stream_wrappers()
1351 */
1352 function hook_stream_wrappers() {
1353 return array(
1354 'public' => array(
1355 'name' => t('Public files'),
1356 'class' => 'DrupalPublicStreamWrapper',
1357 'description' => t('Public local files served by the webserver.'),
1358 ),
1359 'private' => array(
1360 'name' => t('Private files'),
1361 'class' => 'DrupalPrivateStreamWrapper',
1362 'description' => t('Private local files served by Drupal.'),
1363 ),
1364 'temp' => array(
1365 'name' => t('Temporary files'),
1366 'class' => 'DrupalTempStreamWrapper',
1367 'description' => t('Temporary local files for upload and previews.'),
1368 )
1369 );
1370 }
1371
1372 /**
1373 * Alters the list of PHP stream wrapper implementations.
1374 *
1375 * @see file_get_stream_wrappers()
1376 * @see hook_stream_wrappers()
1377 */
1378 function hook_stream_wrappers_alter(&$wrappers) {
1379 // Change the name of private files to reflect the performance.
1380 $wrappers['private']['name'] = t('Slow files');
1381 }
1382
1383 /**
1384 * Load additional information into file objects.
1385 *
1386 * file_load_multiple() calls this hook to allow modules to load
1387 * additional information into each file.
1388 *
1389 * @param $files
1390 * An array of file objects, indexed by fid.
1391 *
1392 * @see file_load_multiple()
1393 * @see upload_file_load()
1394 */
1395 function hook_file_load($files) {
1396 // Add the upload specific data into the file object.
1397 $result = db_query('SELECT * FROM {upload} u WHERE u.fid IN (:fids)', array(':fids' => array_keys($files)))->fetchAll(PDO::FETCH_ASSOC);
1398 foreach ($result as $record) {
1399 foreach ($record as $key => $value) {
1400 $files[$record['fid']]->$key = $value;
1401 }
1402 }
1403 }
1404
1405 /**
1406 * Check that files meet a given criteria.
1407 *
1408 * This hook lets modules perform additional validation on files. They're able
1409 * to report a failure by returning one or more error messages.
1410 *
1411 * @param $file
1412 * The file object being validated.
1413 * @return
1414 * An array of error messages. If there are no problems with the file return
1415 * an empty array.
1416 *
1417 * @see file_validate()
1418 */
1419 function hook_file_validate(&$file) {
1420 $errors = array();
1421
1422 if (empty($file->filename)) {
1423 $errors[] = t("The file's name is empty. Please give a name to the file.");
1424 }
1425 if (strlen($file->filename) > 255) {
1426 $errors[] = t("The file's name exceeds the 255 characters limit. Please rename the file and try again.");
1427 }
1428
1429 return $errors;
1430 }
1431
1432 /**
1433 * Respond to a file being added.
1434 *
1435 * This hook is called when a file has been added to the database. The hook
1436 * doesn't distinguish between files created as a result of a copy or those
1437 * created by an upload.
1438 *
1439 * @param $file
1440 * The file that has just been created.
1441 *
1442 * @see file_save()
1443 */
1444 function hook_file_insert(&$file) {
1445
1446 }
1447
1448 /**
1449 * Respond to a file being updated.
1450 *
1451 * This hook is called when file_save() is called on an existing file.
1452 *
1453 * @param $file
1454 * The file that has just been updated.
1455 *
1456 * @see file_save()
1457 */
1458 function hook_file_update(&$file) {
1459
1460 }
1461
1462 /**
1463 * Respond to a file that has been copied.
1464 *
1465 * @param $file
1466 * The newly copied file object.
1467 * @param $source
1468 * The original file before the copy.
1469 *
1470 * @see file_copy()
1471 */
1472 function hook_file_copy($file, $source) {
1473
1474 }
1475
1476 /**
1477 * Respond to a file that has been moved.
1478 *
1479 * @param $file
1480 * The updated file object after the move.
1481 * @param $source
1482 * The original file object before the move.
1483 *
1484 * @see file_move()
1485 */
1486 function hook_file_move($file, $source) {
1487
1488 }
1489
1490 /**
1491 * Report the number of times a file is referenced by a module.
1492 *
1493 * This hook is called to determine if a files is in use. Multiple modules may
1494 * be referencing the same file and to prevent one from deleting a file used by
1495 * another this hook is called.
1496 *
1497 * @param $file
1498 * The file object being checked for references.
1499 * @return
1500 * If the module uses this file return an array with the module name as the
1501 * key and the value the number of times the file is used.
1502 *
1503 * @see file_delete()
1504 * @see upload_file_references()
1505 */
1506 function hook_file_references($file) {
1507 // If upload.module is still using a file, do not let other modules delete it.
1508 $file_used = (bool) db_query_range('SELECT 1 FROM {upload} WHERE fid = :fid', 0, 1, array(':fid' => $file->fid))->fetchField();
1509 if ($file_used) {
1510 // Return the name of the module and how many references it has to the file.
1511 return array('upload' => $count);
1512 }
1513 }
1514
1515 /**
1516 * Respond to a file being deleted.
1517 *
1518 * @param $file
1519 * The file that has just been deleted.
1520 *
1521 * @see file_delete()
1522 * @see upload_file_delete()
1523 */
1524 function hook_file_delete($file) {
1525 // Delete all information associated with the file.
1526 db_delete('upload')->condition('fid', $file->fid)->execute();
1527 }
1528
1529 /**
1530 * Control access to private file downloads and specify HTTP headers.
1531 *
1532 * This hook allows modules enforce permissions on file downloads when the
1533 * private file download method is selected. Modules can also provide headers
1534 * to specify information like the file's name or MIME type.
1535 *
1536 * @param $uri
1537 * The URI of the file.
1538 * @return
1539 * If the user does not have permission to access the file, return -1. If the
1540 * user has permission, return an array with the appropriate headers. If the
1541 * file is not controlled by the current module, the return value should be
1542 * NULL.
1543 *
1544 * @see file_download()
1545 * @see upload_file_download()
1546 */
1547 function hook_file_download($uri) {
1548 // Check if the file is controlled by the current module.
1549 if (!file_prepare_directory($uri)) {
1550 $uri = FALSE;
1551 }
1552 $result = db_query("SELECT f.* FROM {file} f INNER JOIN {upload} u ON f.fid = u.fid WHERE uri = :uri", array('uri' => $uri));
1553 foreach ($result as $file) {
1554 if (!user_access('view uploaded files')) {
1555 return -1;
1556 }
1557 return array(
1558 'Content-Type' => $file->filemime,
1559 'Content-Length' => $file->filesize,
1560 );
1561 }
1562 }
1563
1564 /**