Setting which theme to use during Drupal 7 cron

Recently I ran into an issue where I had to generate content within a Drupal 7 cron run using node_view(). Normally there wouldn't be much of an issue here except that I was also trying to do some custom work within node.tpl.php in the main theme for the site.

After much frustration, I learned that during cron, the administration theme is used. After some thought, that makes sense and normally would not cause any issues but in my case it caused nothing but pain.

Some research led me to hook_custom_theme for setting theme to use on a particular page. This is instead of global $custom_theme from the Drupal 6 days. In order to get this to work though there are a few steps to follow.

Setting up hook_custom_theme

The custom theme hook needs to be set up so that it sets which theme to use for the cron runs only.

The following code with set the theme when:

  • The theme exists and is enabled
  • Cron is invoked from Admin Menu's cron link
  • Cron is invoked from the system status page
  • Cron is run like normal from command line

Put the following hook in your module's .module file:

/**
 * Implmentation of hook_custom_theme()
 */

function your_module_custom_theme()
{
  if($_GET['q'] == "admin/config/system/cron" ||
    $_GET['q'] == "admin/reports/status/run-cron" ||
    (isset($_GET['cron_key']) && variable_get('cron_key', 'drupal') === $_GET['cron_key'])
  )
  {
    $themes = list_themes();
    if(array_key_exists('your_theme', $themes))
    {
      return 'your_theme';
    }
  }
}

Setting the module weight

The next issue to solve is that, depending on the name of your module, the system module may run after it and set the theme back to the administration theme. To overcome this you need to set the weight of your module to something heavy. I used a weight of 1000 as it would suffice for my personal set up. If 1000 doesn't work, you may need to set it to something higher. Check the weights of modules in the system table to see what weight you need to overcome.

Add the following to your hook_install in your .install file:

/**
 * Implmentation of hook_install()
 */

function your_module_install()
{
  // Set the weight of this module to be heavy so that hook_custom_theme works
  db_update('system')
    ->fields(array('weight' => 1000))
    ->condition('name', 'your_module', '=')
    ->execute();
}

If your module is already enabled, you'll need to add an update function to do the same.

/**
 * Update the weight of <your module> module in the system table
 */

function your_module_update_7001()
{
  db_update('system')
    ->fields(array('weight' => 1000))
    ->condition('name', 'your_module', '=')
    ->execute();
}

That should do it

Refresh your caches, run your table updates and you should be good to go. To test whether or not you're using the correct theme in your module's cron run, add global $theme; to the top of your cron hook and print that out to see what it says. It should be the machine name of your theme.

Most people will never run into this issue but if you're trying to use node_view within hook_cron along with some custom .tpl files, hopefully this just saved your day.

Get in touch if you have any questions or need help! I'm around on Twitter at @grantlucas or just use the contact form here on this site.

Short URL: http://gl2.ca/2o