Plugin API for Vufind

Details

Description

Maybe it would be a good idea to create a plugin layer to simplify writing extensions for Vufind without modifying the core. In parts this is already possible (e.g. its not so hard to create new RecordDrivers), but a plugin API would allow others to add core functions without touching existing code. Also, it could simplify updates and code exchange.
This API could be modeled on WordPresses API.

Activity

1.) Zend Framework 2 operates using modules. The framework can load multiple modules and merge their configurations together. Each module has its own namespace, and its configuration tells the framework where to find the controllers for various routes. All the VuFind-specific code will be in the VuFind module. Users can plug in a module that loads after the VuFind module and overrides some of its settings. This means that they can point specific routes to their own custom controllers. Because of the namespacing, their controllers can extend the core VuFind controllers and only override or add very targeted behavior. No need to copy-and-paste large amounts of code.

2.) VuFind already has a lot of different plug-in areas: ILS drivers, record drivers, recommendation modules, session handlers, authentication handlers, link resolver drivers. 2.0alpha also adds related record modules for the record view. I also expect to add plug-ins for controlling record tabs (VUFIND-605). In 2.0beta, I plan to extend the configuration for all of these options to recognize fully-qualified, namespaced class names. That way, custom plug-ins can be built either inside or outside the core VuFind module, depending on user preferences. (By default, plug-ins are loaded using a specific namespace within the VuFind core).

3.) I will try to increase the use of dependency injection in VuFind so that deeper behavior can be more easily modified by extending record drivers and/or controllers, injecting modified dependencies, and then calling parent functionality. I can't guarantee that every single aspect of VuFind will be customizable in this fashion, but I hope this will improve over time as code gets refactored. If there are particular areas in need of special customization, feel free to suggest areas of concern.

I hope this will address the vast majority of plug-in use cases. For extreme situations where it is impractical to modify VuFind from the outside, I hope that the transition to Git for version control will make management of custom VuFind instances somewhat easier.

I also realize that this requires different techniques for different types of modifications, and some of these techniques are harder to master than others. However, I think it is probably better to have clear, straightforward APIs for the most common tasks rather than trying to come up with a single, unified API for absolutely everything -- I can't really envision a universal plug-in API that would be easily comprehensible. Also, documentation will play an important role here -- if the wiki includes good tutorials on customizing different aspects of VuFind, that will make a big difference... and I certainly plan to document everything once the design is more stable (which is getting significantly closer now that the move to ZF2 is underway).

Of course, I'm open to suggestions and criticism if anyone sees a better way forward or notices flaws in my current working plan.

Demian Katz
added a comment - 29/Jun/12 7:22 AM - edited I expect to improve this in 2.0beta in a few ways:
1.) Zend Framework 2 operates using modules. The framework can load multiple modules and merge their configurations together. Each module has its own namespace, and its configuration tells the framework where to find the controllers for various routes. All the VuFind-specific code will be in the VuFind module. Users can plug in a module that loads after the VuFind module and overrides some of its settings. This means that they can point specific routes to their own custom controllers. Because of the namespacing, their controllers can extend the core VuFind controllers and only override or add very targeted behavior. No need to copy-and-paste large amounts of code.
2.) VuFind already has a lot of different plug-in areas: ILS drivers, record drivers, recommendation modules, session handlers, authentication handlers, link resolver drivers. 2.0alpha also adds related record modules for the record view. I also expect to add plug-ins for controlling record tabs ( VUFIND-605 ). In 2.0beta, I plan to extend the configuration for all of these options to recognize fully-qualified, namespaced class names. That way, custom plug-ins can be built either inside or outside the core VuFind module, depending on user preferences. (By default, plug-ins are loaded using a specific namespace within the VuFind core).
3.) I will try to increase the use of dependency injection in VuFind so that deeper behavior can be more easily modified by extending record drivers and/or controllers, injecting modified dependencies, and then calling parent functionality. I can't guarantee that every single aspect of VuFind will be customizable in this fashion, but I hope this will improve over time as code gets refactored. If there are particular areas in need of special customization, feel free to suggest areas of concern.
I hope this will address the vast majority of plug-in use cases. For extreme situations where it is impractical to modify VuFind from the outside, I hope that the transition to Git for version control will make management of custom VuFind instances somewhat easier.
I also realize that this requires different techniques for different types of modifications, and some of these techniques are harder to master than others. However, I think it is probably better to have clear, straightforward APIs for the most common tasks rather than trying to come up with a single, unified API for absolutely everything -- I can't really envision a universal plug-in API that would be easily comprehensible. Also, documentation will play an important role here -- if the wiki includes good tutorials on customizing different aspects of VuFind, that will make a big difference... and I certainly plan to document everything once the design is more stable (which is getting significantly closer now that the move to ZF2 is underway).
Of course, I'm open to suggestions and criticism if anyone sees a better way forward or notices flaws in my current working plan.

One more thought -- we could probably add additional integration points using ZF2's event system, allowing users to hook particular events with custom functionality. Perhaps some of the existing plug-in mechanisms can be reimplemented as special cases of a more general event system. I think event-driven hooks need to be a later stage of plug-in implementation, however; I don't want to implement event hooks willy-nilly but would rather come up with a unified plan after the rest of the design is more stable.

Demian Katz
added a comment - 29/Jun/12 10:06 AM One more thought -- we could probably add additional integration points using ZF2's event system, allowing users to hook particular events with custom functionality. Perhaps some of the existing plug-in mechanisms can be reimplemented as special cases of a more general event system. I think event-driven hooks need to be a later stage of plug-in implementation, however; I don't want to implement event hooks willy-nilly but would rather come up with a unified plan after the rest of the design is more stable.

As of 2.0beta, all standard plugins are loaded through ZF2 service locators. Plugins can be added and overridden through module configuration. VuFind has native support for specifying one or more custom modules containing localized code.

I believe this meets the basic requirements for this ticket, so I am closing it.

However, there is still room for improvement -- some of the service locator code should be replaced with more explicit dependency injection, and some of the ideas mentioned here (like using the event system) may still be useful in the future. If action is needed on these things, new, more specific tickets should be opened.

Demian Katz
added a comment - 26/Sep/12 11:36 AM As of 2.0beta, all standard plugins are loaded through ZF2 service locators. Plugins can be added and overridden through module configuration. VuFind has native support for specifying one or more custom modules containing localized code.
I believe this meets the basic requirements for this ticket, so I am closing it.
However, there is still room for improvement -- some of the service locator code should be replaced with more explicit dependency injection, and some of the ideas mentioned here (like using the event system) may still be useful in the future. If action is needed on these things, new, more specific tickets should be opened.