It has been quite a while since I worked on Drupal 7, but I'm hitting a snag.

First please understand I only have access to the theme, I cannot create a bunch of custom modules.

Now, I want to add a page, on the URL my.domain.com/authorization, this page should only be available for administrators and I want to provide some custom markup for the "innards" of the page.

Since I know my theme's template.php can implement hook_theme(), I declare my route and template.

function mytheme_theme() {
  return array(
    'authorization' => array(
      'variables' => array('var' => null),
      'template' => 'my_authorization'

I can easily add my markup the my_authorization.tpl.php file, which exists.

However, when I navigate to my URL, I get a Page not found error.

I figured I need to add a MENU_CALLBACK to the menu for my route; I understand I cannot use hook_menu() from a theme, but I can use hook_menu_alter(), so I write this function (which also takes care of my access issue).

function mytheme_menu_alter(&$items) {
  $items['authorization'] = array(
    'title' => t('Authorization'),
    'page callback' => 'page_callback',
    'access callback' => TRUE,

  return $items;

It never hits this function! What have I done wrong?

The page callback exists (it returns a test string) but it is never called, because mytheme_menu_alter() doesn't seem to be invoked.

To be clear, my outcome is simply, for the theme I am working on (only), if the URL is my.domain.com/authorization, and the logged in user is an administrator, display a link on the page (to an oauth endpoint).

  • 2
    Presumably you're clearing the cache from the admin section of the site? Unless you're using mytheme as your admin theme, the alter hook isn't going to be executed. You would need to clear the cache whilst on a page that uses your custom theme, but then obviously when the cache is cleared from a page where your custom theme isn't involved, the new route will be lost. Which should go some way to convincing you that it's a bad idea to try to add routes from the presentation layer. This code simply has to be in a module if you want the behaviour to be consistent and predictable
    – Clive
    Sep 26, 2018 at 12:41
  • 1
    @Clive The hook will never invoked in a theme (to my knowledge)
    – googletorp
    Sep 26, 2018 at 12:52
  • 1
    @googletorp It's invoked fine (all alter hooks are without exception, I just tested to be sure). Adding an item also works fine. Maintaining that item through menu rebuilds, though, is basically impossible. Or in-sensible at least
    – Clive
    Sep 26, 2018 at 12:53
  • Thanks for the comments guys, see my edit above for detail. @Clive when would the menu be rebuilt except via Clear all Caches?
    – Blatant
    Sep 26, 2018 at 15:20

1 Answer 1


I solved this as so (for info).

First a bit more background. This is basically a REST/SOAP Web Service that integrates some business info into some pages on the specific theme, part of the service is an OAuth2 layer that authenticates the server/site with the Web Service.

The Web service is not available in any other theme (indeed there are no other themes), obviously the OAuth requires exchange of secret keys and ID's so should not be exposed to the front of the site (unless the user is an authenticated admin).

My solution, firstly due to the poor coding the previous freelancer put down (he left the API and secret keys exposed, hard coded domains, no "Service Unavailable" messages, ect) I implemented a simple "Service Unavailable, please contact us or come back later" message should the web service be unavailable.

Because all this happens on specific pages of the site, I also put a block under the code that is displayed if the logged in user is an administrator.

Originally I wanted this to be a link to this supposed page that explains the Web Service is not authorized and offer the link to auth it. As this is not possible I skipped this step, shortened the explanation and present the link and explanation under the "Service is Unavailable" message, thus the admin can visit any page with the Web Service on it, see the "Unavailable" message and as an admin initialize the auth process from there.

Definitely the path of least resistance!

That solves the issue, now all that remains is for me to dig into the core for a better understanding of the way the routing table and page callbacks are built. After all, the more you know....

Finally, big thanks to everyone who took the time to stop by, read and/or comment on my query. I and SE appreciate it!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.