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?

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.

|improve this answer|||||
  • This doesn't seem to work for me. How can I debug an activation hook? Is it stored in the database somewhere? – Yoav Kadosh May 21 '14 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? – Yoav Kadosh May 21 '14 at 0:37
  • @YoavKadosh The $file parameter is always the main plugin file with the plugin headers. – fuxia May 21 '14 at 0:39
  • It's working now! Thank you for answering the question and referring me to the design pattern behind it! – Yoav Kadosh May 21 '14 at 0:55

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.