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