3

So I am planning a theme that will depend on a plugin (for instance Timber or Themosis). So of course a theme will break if it can't use it's depending plugin's. So I would like a way to stop the user of activating a theme that needs a certain plugin to work and instead show an friendly error message containing the plugin that's needed.

So far I found out how to check if a plugin is installed or not (link), but how to stop the theme from being activated if that's possible at all?

I also found out about the switch_theme and the after_switch_theme actions.

So what I am missing right now is a way to stop the actual activation. Is this possible?

edit: Found this for displaying admin notices/warnings.

3
  • 1
    This seems backwards. Why would you want to prevent a theme from being activated if a plugin is not installed? Why would you not instead show a notice that the theme depends on a given plugin after activation (if the plugin is not in fact installed)? May 5, 2014 at 21:36
  • 2
    Well, I could let the user activate the theme if the plugin it needs is already installed, but not activated and just show a notice. But activating a theme while not having the plugin installed doesn't make sense, cause it wont work and break the website. If someone wanted to activate the theme first and install the plugin later, then yes, he/she would get a annoying warning that he/she can't activate the theme yet. So I would be forcing people to at least first install the plugin. I just think that to take it a step further and force the user to activate it first would be better.
    – Ilyes512
    May 5, 2014 at 22:34
  • @random_user_name: It could be a good mechanism where critical functionality of a theme depends on various plugins being installed. So if Theme B will throw 500 Errors if Plugin A is not present, it is better to check whether Plugin A is present and enabled before Theme B is activated. If you try and hook the event after the theme has been activated, it may never happen because everything is a 500 Error by that point. Would you rather your pilot do a preflight check before they take off, or take off and then do the checks? 22 hours ago

4 Answers 4

8

Using after_switch_theme will activate the theme (which is fine as we want to run the check within the context of the new theme).

If the dependencies are not fulfilled ($missing_dependencies = true;) we're instantly switching back to the theme previously used (passed via after_switch_theme and $oldtheme).

add_action( 'after_switch_theme', 'check_theme_dependencies', 10, 2 );
function check_theme_dependencies( $oldtheme_name, $oldtheme ) {
  if ( $missing_dependencies ) :

    // Update default admin notice: Theme not activated.
    add_filter( 'gettext', 'update_activation_admin_notice', 10, 3 );

    // Custom styling for default admin notice.
    add_action( 'admin_head', 'error_activation_admin_notice' );

    // Switch back to previous theme.
    switch_theme( $oldtheme->stylesheet );
      return false;

  endif;
}

function update_activation_admin_notice( $translated, $original, $domain ) {
    // Strings to translate.
    $strings = array(
        'New theme activated.' => 'Theme not activated.'
    );

    if ( isset( $strings[$original] ) ) {
        // Translate but without running all the filters again.
        $translations = get_translations_for_domain( $domain );
        $translated = $translations->translate( $strings[$original] );
    }

    return $translated;
}

function error_activation_admin_notice() {
  echo '<style>#message2{border-left-color:#dc3232;}</style>';
}

You can use the snippet above within your functions.php, but make sure that after_switch_theme is called before the required dependencies.

Update: There does not seem to be an easy way to prevent the admin notice triggered via the switch_theme function. Overwriting the message via the gettext filter seems to be a good workaround.

Thanks to @alpipego for telling me how to overwrite strings in WordPress Core :)

Further reading: Changing Core WordPress Strings

4
  • Above code works great, however I cannot get wordpress to skip the "New theme activated."-notice. Does anyone have an idea on how to solve that? Right now the output i get is Notice 1: "Theme not activated." Notice 2: "New theme activated." Mar 10, 2016 at 10:15
  • @David Svensson Thank you very much for letting me know. The template file containing this notice is just one big block of code without any hooks, so there does not seem an easy way to get rid of the notice. Nevertheless, I've updated the answer to hide it via CSS as a quick workaround.
    – Sven
    Mar 10, 2016 at 11:27
  • 1
    Yeah I saw the same thing but was hoping I was missing something. Will have to go with a CSS-fix for the time being. Mar 10, 2016 at 15:55
  • @David Svensson I updated the answer once again; I finally found a neat way to fix this :)
    – Sven
    Apr 19, 2016 at 23:06
1

I don't know how to prevent the theme switch (though there may well be a way), however I can think of a workaround.

after_switch_theme passes the old theme name through...

do_action( 'after_switch_theme', $old_theme->get( 'Name' ), $old_theme );

... so you should be able to check for the plugin on that action and then reset to the old theme if the plugin is not active/present. The switch_theme() function will allow you to programatically switch themes. Just pass it a stylesheet slug. I just answered a related question that will problably help with this problem too.

3
  • I knew about the name theme being passed, but didn't think it would come in handy for my problem. What I didn't know (and I take it from you answer it is possible) is that there was a way to activate a theme without the user changing it himself. I think I have enough to produce the answer. I will post it here when I got it! Thanks!
    – Ilyes512
    May 5, 2014 at 22:39
  • @Ilyes512 : see the edit.
    – s_ha_dum
    May 5, 2014 at 22:44
  • github.com/WordPress/WordPress/blob/… I see the hook will even pass a WP_Theme instance. Not sure if I will need it cause I think the first parameter containing the old_theme name should suffes for switch_theme(). The stylesheet name is the slug folder name of the (child) theme. I will try it out tomorrow. It getting late ^^
    – Ilyes512
    May 5, 2014 at 23:25
0

I don't think it'll prevent anyone from activating a theme, but here's a class for attaching plugin dependencies to themes (or to other plugins): https://github.com/thomasgriffin/TGM-Plugin-Activation

At the very least, it adds all the UI notices and nags so that the administrator knows they're missing something. It even adds links to install the missing dependencies. Pretty cool.

-1

Couldn't you just include the plugin with the theme, if it's one you're developing? The disadvantages of this approach include not updating the plugin separately, but if your theme is dependent on a particular version of a particular plugin, it may work just fine, as long as you patch the plugin you require.

1
  • I think I will choose Timber (see the question for the link) for my theme. Timber is a Twig plugin wish also includes other things like routing and the WP loop function. Its available as a plugin. It wouldnt make sense to include it with the theme. It would only mean more work for me as I will probably will have to change all class and function names (if it doesnt use namespaces) as else it will probably produce errors if the user already got the Timber plugin activated.
    – Ilyes512
    May 6, 2014 at 0:36

Your Answer

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

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