HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

Plugin inheritance

TiGRTiGR
Currently Vanilla does not support plugin inheritance. If you try to use it, you start getting all kind of bugs (quite unexpected), that spoil everything.

Let's say, I would like to have some common functionality, that could be inherited then. So, you create some abstract class _baseBlahPlugin which extends Gdn_Plugin. You put it somewhere in your plugin dir, carefully naming it not as "default.php" or "*plugin.php", so that plugin manager would not try to load it as plugins.

Then, you create some implementation plugin, _BlahBoxPlugin which extends _base_BlahPlugin, and Boom! you get it broken. Since plugin manager has this magic:
   public function RegisterPlugins() {

      // Loop through all declared classes looking for ones that implement Gdn_iPlugin.
      foreach (get_declared_classes() as $ClassName) {

         // Only register the plugin if it implements the Gdn_IPlugin interface
         if (in_array('Gdn_IPlugin', class_implements($ClassName))) {

            // If this plugin was already indexed, skip it.
            if (array_key_exists($ClassName, $this->RegisteredPlugins))
               continue;

            // Register this plugin's methods
            $this->RegisterPlugin($ClassName);
         }
      }
   }
So, if there is any class loaded that implements Gdn_IPlugin, Vanilla tries to instantiate it as plugin, even if it is abstract. The simple fix looks like this:
            // Register only non abstract classes.
            $Reflection = new ReflectionClass($ClassName);
            if (!$Reflection->isAbstract())
               // Register this plugin's methods
               $this->RegisterPlugin($ClassName);
But the question is - is this a proper way to go? Would such patch be committed?

Currently in my local branch I have AuthCore plugin that does nothing, but holds several core authentication plugin base classes for varions protocols: for openid, oauth2.

So, creating new plugins for such services take only around 30 lines of code, instead of 350 in existing Auth plugins.

Comments

  • LincLinc Admin
    edited August 2011
    Couldn't this be accomplished by creating a normal AuthCore plugin and simply having the others extend the AuthCore plugin and list that as a 'RequiredPlugin' for the others? I don't see why the "hidden" abstract class is needed.
  • I have AuthCore, with very basic functions. Then I have AuthCore_oAuth2 and AuthCore_openid which extend AuthCore. All these classes are located in AuthCore plugin directory. AuthCore_oAuth2 cannot be plugin by itself - it misses getProfile code, which is specific for every service.

    That is, the part of connection process is fetching user data, which is being accomplished not with oAuth API, but with service specific one. Facebook has it's own API, Vkontakte - it's own.

    There just cannot be working oAuth dummy plugin. That's why it is supposed to be abstract.

    But as I said, if I leave it out somewhere in plugin directory Vanilla will attempt to run this plugin. Even if it is not complete.

    And yes, AuthCore is listed as RequiredPlugin in plugins for specific services.

    And I could bear with non abstract class if Vanilla wouldn't have been trying to initiate it.

  • So, if there is any class loaded that implements Gdn_IPlugin, Vanilla tries to instantiate it as plugin, even if it is abstract. The simple fix looks like this:
                // Register only non abstract classes.
                $Reflection = new ReflectionClass($ClassName);
                if (!$Reflection->isAbstract())
                   // Register this plugin's methods
                   $this->RegisterPlugin($ClassName);
    But the question is - is this a proper way to go? Would such patch be committed?
    This seems like a reasonable (and safe) thing to be doing in any case. Why don't you put up a pull request, link it here and pull a dev into the discussion?

    There was an error rendering this rich post.

  • In WordPress, I found a group of plugins that all required 1 core "meta" plugin that provided base functionality for all the other plugins in the group. The meta plugin didn't do anything on its own, it just provided a cleaner way for all the others to work.

    I understand that an abstract class would be the good-and-proper PHP approach, but I'm concerned about creating some corner case of plugin extensibility we need to support from now until the end of time, and wonder if that will be hard to communicate to plugin developers anyway.

    Is it *possible* to create a plugin that simply provides a framework/inheritance for your other plugins and then list that as a RequiredPlugin for the others?
Sign In or Register to comment.