1

I would like to create a common abstract class to use for every WordPress plugin that I develop. As a part of the class' initiation process, I would like to fire the activation hook which calls an abstract method that will be defined by the child's class.

For example:

abstract class AbstractPlugin extends WP_Plugin {
    public function init() {
        register_activation_hook( __FILE__, array( $this, 'on_activation' ) );
        register_deactivation_hook( __FILE__, array( $this, 'on_deactivation' ) );
    }

    public abstract function on_activation();
    public abstract function on_deactivation();
}

However, the first argument in register_activation_hook should be the path to the file in which the child's class is defined, which is unknown, and even if it is known, it doesn't work.

Is there any way to get around this issue?

1 Answer 1

2

The best way to get around this problem is not creating that abstract class.

Never combine object creation with business logic in the same class. This is called a statically linked dependency and usually a flawed design, because you cannot change it on runtime (for tests or per hooks, for example). Avoid inheritance.

Separation of concerns and dependency injection will solve that.

Example

interface Plugin_Setup_Interface
{
    public function activate( $network_wide );
    public function deactivate( $network_wide );
}

class Plugin_Setup implements Plugin_Setup_Interface
{

    public function activate( $network_wide ) {}

    public function deactivate( $network_wide ) {}
}

class Plugin_Starter
{
    private $plugin_file = '';

    private $setup = NULL;

    public function __construct(
                               $plugin_file,
        Plugin_Setup_Interface $setup = NULL
    )
    {
        $this->plugin_file = $plugin_file;
        $this->setup       = $setup;
    }

    public function init()
    {
        if ( ! is_null( $this->setup ) )
        {
            register_activation_hook(
                $this->plugin_file,
                array ( $this->setup, 'activate' )
            );

            register_deactivation_hook(
                $this->plugin_file,
                array ( $this->setup, 'deactivate' )
            );
        }
    }
}

// call your auto-loader, then …

$start = new Plugin_Starter( __FILE__, new Plugin_Setup() );
$start->init();

Now you can create specialized de/activation routines for every plugin and still reuse the starter class.

4
  • This doesn't seem to work for me. How can I debug an activation hook? Is it stored in the database somewhere? May 21, 2014 at 0:08
  • I think the problem is that my files are separated (each class/interface is in it's own file). Which file should the hook point to? May 21, 2014 at 0:37
  • @YoavKadosh The $file parameter is always the main plugin file with the plugin headers.
    – fuxia
    May 21, 2014 at 0:39
  • It's working now! Thank you for answering the question and referring me to the design pattern behind it! May 21, 2014 at 0:55

Your Answer

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

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