Its no longer possible to define dynamic path-specific callbacks in hook_menu because the hook is only invoked once to build the menu tree. There is no two-phase hook_menu, where one could run path-specific code in !may_cache phase as in 4.7/5.x. All such code will be moved (or was move in core) to hook_init().

There are several modules (first and foremost the theme-switching modules, such as sections, taxonomy_theme, mysite, ...) using large case/if..else constructs like <?php if (arg(0) == 'node' && is_numeric(arg(1)) && ... ) { ... } ?> to trigger a callback and/or switch the theme based on the path of the current page.

This patch introduces a new hook_trigger. Modules can implement it and return a structure like the following (from system.module):

<?php
function system_trigger() {
  return array(
    'admin/*' => array(
      'callback' => 'system_trigger_admin',
      'theme' => variable_get('admin_theme', '0'),
    ),
    'node/#/(add|edit)' => array(
      'callback' => 'system_trigger_admin',
      'theme' => variable_get('admin_theme', '0'),
    )
  );
}
?>

The array keys are path 'patterns' that match a specific or wildcarded path, the values contain a 'theme' and a 'callback' field. If the user enters a path matching one of the patterns the theme is switched to the one defined in the 'theme' field and/or the callback specified in the 'callback' field is invoked.

Multiple callbacks for a given path are possible. The path patterns allow wildcards as follows: '*' matches everything, '%' matches everything except a slash '/' (= path component) and '#' matches numbers only. For example 'admin/*' matches every path starting with 'admin/...' and switches the theme to the admin theme. 'node/#/(add|edit)' matches paths like 'node/123/edit' or 'node/321/add', but not 'node/test/edit'. The pattern is tested against the internal Drupal path (e.g. path/node/123) and the aliased path (e.g. path/mytestnode).

All that makes it almost trivial to implement theme-switching modules as you only need to register additional trigger. And it makes it really simple to run code based on the path, e.g. add css/js for certain pages, implement path-based statistics, etc. (there are many possible applications IMO).

With the patch hook_init is now a special trigger that is invoked for every path. This special trigger is auto-registered if hook_init is implemented in a module. What means it does not require a manual entry in the structure returned by hook_trigger (or hook_trigger at all). For modules that dont need path-specific callback, nothing changes, as hook_init() will be called as before.
The patch also allow modules to alter the trigger structure by implementing a hook_trigger_alter.

The code is basically an adapted version of the path-match 'engine' that is used in taxonomy_theme for some time. I first thought, it would be possible to utilize the new menu system for this, but 1. it doesnt allow multiple callbacks, 2. does not allow to have specific regexp patterns, etc. Running path-specific code is needed for several application and atm every module implements its own little version. This patch is a centralized approach to simplify code for these cases and to get rid of large 'arg(x)' constructs. I know I'm late with this. But actually I just started to play with taxonomy_theme to port it to Drupal 6 and realized that it still requires 'ugly' code to work. The patch is a simple, but yet powerful addition, that shouldnt add much overhead in general. I think we will NOT have hundreds of triggers registered and therefore shouldnt get much of a performance penalty.

CommentFileSizeAuthor
trigger.patch8.33 KBprofix898

Comments

chx’s picture

Status: Needs review » Closed (won't fix)

I would heartily recommend reading the new menu system handbook pages especially http://drupal.org/node/103114

chx’s picture

Status: Closed (won't fix) » Needs work

On further consideration, let's change 'page callback' to an array in D7. I do not think we want another complicated wildcard matching for D6 (nor D7).

profix898’s picture

@chx: Please correct if I'm wrong. There are some aspects of the new menu system I dont understand 100% even after reading the handbook pages.

The biggest problem in this context is the 'fitness' idea implemented by the menu system. We can define a menu item for the path 'admin/%' and assign it with a callback function, e.g. myadmin_callback(). However if the user browses to 'admin/abc/def' this callback is no longer invoked in case there is a menu item that better fits the path (e.g. 'admin/abc/%'). What means it is not possible to have the callback invoked for all paths below 'admin/...'. Thats also the reason why we still need code like <?php if (arg(0) == 'node' && is_numeric(arg(1)) && ... ) { ... } ?> in hook_init(). Using the 'trigger' idea this is possible ...
The point is that we need path-specific callbacks (with wildcards) that do not identically match a menu item, but that represent a 'derived' or 'parent' path. Being able to specify multiple callbacks per menu item would be a (first) step forward, but does not solve the problem IMO.

chx’s picture

Status: Needs work » Postponed

Definitely Drupal 7 stuff.

lilou’s picture

Version: 6.x-dev » 7.x-dev
Component: other » menu system
Status: Postponed » Needs work

D7 is now in development.

mitchell’s picture

Title: path-specific callbacks (and theme switching) » theme switching
Project: Drupal core » Rules
Version: 7.x-dev » 6.x-1.x-dev
Component: menu system » Provided module integration
Status: Needs work » Patch (to be ported)

@profix898: what do you think?

fago’s picture

Status: Patch (to be ported) » Needs work

patch to be ported is intended for ports of committed code from other versions, e.g. d7 to d6 or rules to workflow-ng.

mitchell’s picture

Title: theme switching » path-specific callbacks (and theme switching)
Status: Needs work » Fixed

There's a lot going on in this patch, but I'm pretty sure it's fixed now in these two issues:
#442432: Improve textual conditions (starts with, ends with, contains, is equal to, regex)
#417664: Action: switch theme

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

mitchell’s picture

Component: Provided module integration » Provided Module Integrations

Updated component.