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.