cms/drupal/modules/system/system.api.php
changeset 541 e756a8c72c3d
equal deleted inserted replaced
540:07239de796bb 541:e756a8c72c3d
       
     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  */