0

I have two versions of the same plugin - one is a free version on WordPress.org and the other is a paid upgrade. Both versions use the same function names and so can't be activated at the same time. When someone installs and activates the paid version before deactivating the free version currently a Fatal Error is displayed stating 'Fatal error: Cannot redeclare abc_function() (previously declared in ...)'.

I'm trying to add something to the register_activation_hook for the paid version which either automatically deactivates the free version or displays a wp_die notice asking them to deactivate the free version. I can get these to work, but the problem is that they don't seem to be running early enough and so I get the redeclared function fatal error. This is what I'm using:

function abc_activate() {
    if ( function_exists('abc_function') ) die( "Please deactivate the free version..." );
}
register_activation_hook( __FILE__, 'abc_activate' );

I've also tried attaching the wp_die and deactivate_plugins functions to an admin_init action, but that also doesn't seem to run before the fatal error. Eg:

function abc_warning_message() {
    wp_die( "Please deactivate the free version of the plugin..." );
    deactivate_plugins( 'abc-plugin-name' );
}
add_action( 'admin_init', 'abc_warning_message' );

Does anyone have any idea what I might be doing wrong, or whether it's even possible to call a function before a fatal error is triggered due to the duplicate function names? Worst case scenario I can go through the plugin and rename all of the function names, but I'd love to be able to get this working.

Thanks in advance for any help!

John

  • Don't have the same functions names. Add a class or two (or more) for your paid version. Have the functions check to see if that class exists, and if does, use the premium version of the code, otherwise, execute the free version. That way it degrades gracefully if they deactivate the paid version or you suspend access or whatever. – Andrew Bartel Oct 7 '14 at 21:39
  • Thanks for the suggestion. I want to keep the function names the same between the two versions so that it's easier to maintain. I was able to find a solution based on G.M.'s answer below. – John Oct 9 '14 at 19:27
2

WordPress is not magic. If you add and action hook (register_activation_hook just add an action hook) to WordPress be able to read and run it, have to load your main plugin file, it can't guess its content.

And if WordPress load your main plugin file, it will load all the functions defined there (or in files straight included from there) so you get the fatal error.

If you want to do that, you need to load all your functions after WordPress parsed your main plugin file, both files if both version are activated.

Main plugin file of free plugin should contain only something like this:

add_action( 'plugins_loaded', 'myplugin_require_everything_free', 100 );

function myplugin_require_everything_free() {
  // require all free plugin files here
}

and no more code. (of course on top of file you will have the plugin headers).

Main plugin file in the paid version should contain only something like this:

add_action( 'plugins_loaded', 'myplugin_require_everything_paid', 1 );

function myplugin_require_everything_paid() {

  if ( function_exists( 'myplugin_require_everything_free' ) ) {
     remove_action( 'plugins_loaded', 'myplugin_require_everything_free' );
     deactivate_plugins( 'abc-plugin-name-free' );
  }
  // require all paid plugin files here
}

Both functions run on same hook, when both file have been parsed, but the paid plugin function runs first, because has as an higher priority.

If paid version functions finds that free version is activated, it removes the action free version file added, deactivate free version plugin and only after that loads the files that contain plugin functions.

In this way no conflict may happen...

  • This answer functions, and it's good stuff @G.M, +1. I just feel like it's fundamentally the wrong way to go about it. The functions just shouldn't be named the same thing. Make a class OP, it won't kill you. – Andrew Bartel Oct 8 '14 at 0:36
  • @AndrewBartel Doing OOP code wont save you. In your comment to OP you said "add classes to paid version", but if you add classes, means that paid version need the free one to work (because basic classes are there). But more then often paid versions have to be standalone, so, or all classes are renamed in paid version (unmaintenable solution) or free classes are shipped in paid package too. And problem stay the same: duplicate class names aren't allowed too. Also, having both free and paid version is probably not wanted by dev, so a solution to deactivate the free one is required either way. – gmazzap Oct 8 '14 at 0:51
  • Thanks for the help guys. Moving the plugin code from the main plugin file into another file and using a conditional to include it only if a certain function name didn't already exist solved the problem. The issue I was having before was that all of the code in the main plugin file was running and so the fatal error was flagged straight away. Now I've added the following which works great: if ( function_exists('abc-function') ){ wp_die( "Please deactivate the free version..." ); } else { include dirname( __FILE__ ) .'/abc-plugin-init.php'; } – John Oct 9 '14 at 19:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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