Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

One of my Wordpress themes requires a few third party plugins to run correctly.

Most of the times I used to call functions from third party plugins using conditional statements like

    if(function_exist('plugin_function')) {
             plugin_function() // do something
    }

suppose though I need to use extensively one plugin through many files of my theme... I would like to avoid using many IF conditions... is there a proper way to require certain specific plugin to be installed in WP or even better install them if they're missing before activating the theme?

thanks

share|improve this question
add comment

4 Answers

is_plugin_active() is rather fragile: it will break when either the plugin author renames the main file or when the user renames the plugin's directory or main file. It's better to check if a certain public function exists.

To avoid having to make that check each time you need some of the plugin's functionality, you could show a message in the admin area:

add_action( 'admin_notices', 'my_theme_dependencies' );

function my_theme_dependencies() {
  if( ! function_exists('plugin_function') )
    echo '<div class="error"><p>' . __( 'Warning: The theme needs Plugin X to function', 'my-theme' ) . '</p></div>';
}

Another alternative is to use something like http://tgmpluginactivation.com/

share|improve this answer
    
If the plugin author changes a functions name that you question with function_exists, then a normal user will simply get the message, that he hasn't installed the plugin that another plugin relies on. Problem is, that the user actually will have the plugin installed and then just wonder why it doens't work. Oh, and I'm not going to downvote you for that. –  kaiser Jan 19 '12 at 12:27
    
If you care about votes, then you should upvote the Q itself, as it's a good one. –  kaiser Jan 19 '12 at 12:32
    
If the plugin author changes the function name, he'll receive complaints from a lot more users than if he would change the file name. –  scribu Jan 19 '12 at 13:47
    
And I downvoted your answer because it didn't address the question, IMO. Or would you prefer I downvote covertly, with no explanation offered? –  scribu Jan 19 '12 at 13:50
    
I was just talking about the downvote, not the comment. The comment itself is ok, as this topic is something that needs discussion. I'll add another answer as my thoughts behind that will exceed comment lenght. Please just edit the answer, so we can keep the discussion results in the revisions for everybody to follow. Thanks. –  kaiser Jan 19 '12 at 14:28
show 2 more comments

While this wouldn't prevent the theme from breaking when the plugin is disabled, I would look at this slick article about "How to Display an Admin Notice for Required Themes" plugin. I've never been comfortable with the idea of a theme forcing a plugin to be installed, and so this seems like the next best option.

Another quick thought: I've never tried this, but I wonder if you could figure out some clever way to house multiple hooks in a single conditional. Maybe you could separate out all the conditional functions in a different file and only require it if if( function_exists( 'plugin_function' ) ) returns true (with the understanding that this is an imperfect check.

share|improve this answer
add comment

If you need it only a plugin page, then there's is_plugin_active(). If you need it outside, you better copy/paste the core function to your theme and then reuse it:

if ( ! is_admin() )
{
/**
 * Check whether the plugin is active by checking the active_plugins list.
 *
 * @since 2.5.0
 *
 * @param string $plugin Base plugin path from plugins directory.
 * @return bool True, if in the active plugins list. False, not in the list.
 */
function is_plugin_active( $plugin ) {
    return in_array( $plugin, (array) get_option( 'active_plugins', array() ) ) || is_plugin_active_for_network( $plugin );
}
}

The conditional avoids any errors with double defining the function.

share|improve this answer
    
That doesn't really answer the question. It merely replaces if(function_exist('plugin_function')) with if(is_plugin_active('plugin-file.php')) –  scribu Jan 19 '12 at 11:32
add comment

Note: This answer is just here to make discussion between @scribu and @kaiser easier. Mods: Please don't delete. Users/Readers: Please don't vote. If you want to follow the discussion, take a look at the revision/edit log. If you want to join the discussion, edit the Answer. If the discussion has a result, then it will be marked as such. Thank you.


Scenarios

There are also different scenarios that weight different, where you could have a plugin dependency. (The examples are only fictional). The word "(parent) Plugin" can be exchanged with "Theme" from parent point of view.

  1. (hard) A child plugin that only extends the functionality or alters the display (and similar) of an existing plugin and therefore can't exist without the parent. Example: BuddyPress » BuddyPress-FunkyCommentDisplay
  2. (normal) A plugin that has extended functionality when a child plugin is activated. Example: jQueryAttachmentCarousel » jQuerySlideDeck
  3. (soft) A plugin that just adds a feature. Example: DisneyWonderlandTheme » MickeysSocialLinks

In the following I try to sketch what happens when you update the "other" plugin and the check doesn't work anymore.

  • Ad 1) The plugin couldn't exist without BuddyPress activated » Stuff is completely broken.
  • Ad 2) The plugin couldn't offer the option to switch from Carousel to SlideDeck » Displays wired (I assume that styles are modified to SlideDeck).
  • Ad 3) MickeysSocialLinks disappear.

Check

There are imho three possibilities to check against, if you want to know if a plugin is active:

  • A. Does the folder exist?
  • B. Does the main file - option 'active_plugins' - exist?
  • C. Does a particular function exist?

If I now take my Internal Link Checker Plugin as an example, that offers no public API and isn't meant to get extended, then I'd see no reason (as author) to not change internal function naming on demand or just on will. So if someone would try to piggyback on this plugin, then stuff would simply break (depending on functionality and tightness of bundling) on update. The same goes for file names. I'd have no real reason (aside from that the plugin would get deactivated on update) to not change the filename. The only thing that would hold me back from changing the folder name is that the update check & notification runs against the file name - if it's hosted in the official repo.

So I'd say from weakest (easy to change) to toughest (a lot speak against changing) part of a (parent) plugin would be:

function » main file name » folder


When I said that a function check is less fragile than using is_plugin_active() I assumed that the function in question is one that the plugin author explicitly encourages. The ultimate example of this would be the wp_pagenavi() template tag offered by the WP-PageNavi plugin.

The difficulty in defining dependencies is that there's no standard way to uniquely identify plugins that doesn't involve file names.

More thoughts on the subject:

http://wordpress.org/support/topic/plugin-plugin-dependencies-unreliable-plugin-namingidentifying-scheme


I guess we can so far sum it up in three points:

  • We have talked about slightly different topics
  • We agree that there's no bulletproof way to get around what I thought the topic would be
  • From your understanding of the question, you offered on valid way to go

The (so far) smartest way I can think off, that I've already seen in some (much too less) plugins:

// inside the plugin file:
add_action( 'plugin_custom_hook', 'plugin_trigger' );
// inside some template:
do_action( 'plugin_custom_hook' );

Without thinking too much in detail about it, but I guess you could hook your notice into a check on 'all' filter and check inside current filter if it was triggered when you are on the shutdown hook...?


Using hooks would works well for 'normal' and 'weak' dependencies. The only drawback is that you would still need to use function_exists() or is_plugin_active() if you want to stop if the dependency is not met. Using the 'all' filter for that would be too expensive IMO.

@scibu This was targeted at "your" topic. (I already dropped talking about mine). :)

So basically, if you need a dependency - and you have a nice author - then he could offer a hook instead/as replacement for a template tag. Because the plugin would only hook into it if the hook would be present, or simply do nothing. And on the other side you wouldn't have an error, when the plugins not present.

Here's the tough part (or more of a Q): To write an admin notice to inform the user about the dependancy "You need to install »DisneyWonderLinks«", you could check the array_keys( $GLOBALS['wp_filter']['template_tag_like_hook'] ). I'm not sure if this would work, but afaik the array should be accessible on both (public/admin) sides.


That would not work. Just because a callback is registered to a hook doesn't mean that the hook will be triggered when expected. The only thing that would sort-of-kind-of work is using the 'shutdown' hook, which you mentioned before:

add_action( 'shutdown', function() {
  if ( !did_action( 'template_tag_like_hook' ) )
    echo 'Problem.';
} );

Of course, this would be printed at the very bottom, after the </html> tag, on the front-end (since that's where template tags are normally used), which is not of much use.

You could try to store the message in wp_options and then display it in the admin area, but that would open a whole new can of worms: invalidation, caching plugins etc.

share|improve this answer
    
For the record, this is a rather unorthodox way of using the site's functionality. It reminds me of c2.com/cgi/wiki –  scribu Jan 19 '12 at 15:23
    
Yes, it is. But I had no idea how we could continue the discussion without hiding it from later readers. –  kaiser Jan 19 '12 at 16:27
    
I wouldn't realize that posting the question would have generated quite a discussion :) But it's indeed interesting and I thank you both for your effort and time giving advices and providing some thoughtful debate. I think the advice from scribu (one of the many that is) to use the TGM Activation class could offer a solution to my answer at least from a merely practical point of view, I will look into it. However, I'm still keeping an eye to the whole discussion because also other methods proposed make sense in certain scenarios and is very interesting for me to to read, thanks! –  Fulvio Jan 20 '12 at 17:43
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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