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