So what would a plugin look like? How would it integrate? What would an API allow?

It sounds like having a standard set of hooks, and a simple “installation” method that registers the plugin to get its hooks called (if they exist) could go a long way here. For instance, alt. notification and task voting both seem easily do-able with something like that, so long as there was a way to add fields to the UI in certain places. Hmm... this is starting to sound harder and harder.

The more I think about this, what’s been said on the mailing list, and what Tony has said in his blog, the more I think that a general plugin system is not the right thing for Flyspray. Before anyone goes ballistic or starts ignoring the rest of this comment, let me explain.

I think Tony is right that doing this well would require a somewhat major reworking of the Flyspray code base. Unless we’re going to do a rewrite anyway, that’s not a good solution. If a rewrite is going to be done, I’d say it should probably wait for version 2.0, rather than 1.0.

One of the biggest benefits of Flyspray, IMHO, is that it is simple. Its user interface is simple, it is simple to administer, simple to install, simple to use, and simple to modify. I think that adding a plugin system would more than likely make it _harder_ to modify rather than easier. It would likely also have detrimental effects in the other areas as well.

I think this should probably be a Won’t Implement, but that’s a decision for Tony to make, probably, unless someone has a low-impact way to get an acceptable plugin system working.

In the case that this does get implemented, I think the best way to do it would be as a very simple set of hooks, without any major rewriting. It would not be the best plugin system ever, but it would aim to be the best we can do without a major rewrite and without making the code a big mess. It may require slight modifications to the flyspray code (at the least, to a configuration file or config. info in the database) to add a plugin. The goal would not be that “anyone” can add a plugin, but that someone who knows a little about PHP programming could make a plugin, and write simple instructions (or a script or patchset) for someone to follow to integrate it into their system.

I personally value Flyspray’s current strengths (especially the simplicity!) over the potential of having a plugin system.

i’m really interested in this feature as well as #FS218, so i’d be heappy to help test if/when you need it. as a developer it’s always nice to be able to modify/customize an application without fear of making future upgrades a pain in the neck.

here’s a simple hook system that could be implemented with very little change of existing flyspray code. it’s a variation of the observer pattern with functions.

it’s not a powerful plugin system, but could help to extend flyspray without hacking the code. addtionally, some of flyspray’s core features could be better modularized using observers.

// define global constants for things that can happen in flyspray. // a flyspray function will "broadcast" any events that happens inside it// and any event observer can react to that.// [TO BE ADDED TO EXISTING FLYSPRAY CODE]define('EVENT_SAVED_BUG', 1);
define('EVENT_ADDED_COMMENT', 2);
define('EVENT_CLOSED_BUG', 3);
// [...] // configure Flyspray's Observer classes.//// all classes inside this array will be notified when the events defined above// occur inside flyspray.// someone wanting to add features to the Flyspray would write a class and add // it to this array.// in his class, he can decide if he wants to do something when this event ocurrs,// or not. he will be handed all useful data of from the flyspray context as well.// [TO BE ADDED TO EXISTING FLYSPRAY CODE]$GLOBALS['eventObservers'] = array('myCommentObserver' =>new myCommentObserver());
//// pseudo-existing flyspray code//function addCommentToBug(){// UPDATE flyspray_bugs SET ...// [TO BE ADDED TO EXISTING FLYSPRAY CODE]
notifyObservers(EVENT_ADDED_COMMENT, $commentData)}// [TO BE ADDED TO EXISTING FLYSPRAY CODE]function notifyObservers($eventName, $data){foreach($GLOBALS['eventObservers']as$observer){$observerClass = new$observer;
$observer->notify($eventName, $data);
}}// [TO BE ADDED BY PEOPLE WANTING TO EXTEND FLYSPRAY]class MyCommentObserver
{publicfunction notify($eventName, $eventData){// look at the event and do whatever you like in here.switch($eventName){case EVENT_SAVED_BUG:
echo"The bug with id" . $data['id'] . " was saved!";
case EVENT_ADDED_COMMENT:
echo"The bug with id" . $data['bug_id'] . " was commented on!";
$myLogger->log($data['comment_text']);
break;
default:
// not handled. no need to handle all events}}}

<?php// define global constants for things that can happen in flyspray. // a flyspray function will "broadcast" any events that happens inside it// and any event observer can react to that.// [TO BE ADDED TO EXISTING FLYSPRAY CODE]define('EVENT_SAVED_BUG', 1);
define('EVENT_ADDED_COMMENT', 2);
define('EVENT_CLOSED_BUG', 3);
// [...] // configure Flyspray's Observer classes.//// all classes inside this array will be notified when the events defined above// occur inside flyspray.// someone wanting to add features to the Flyspray would write a class and add // it to this array.// in his class, he can decide if he wants to do something when this event ocurrs,// or not. he will be handed all useful data of from the flyspray context as well.// [TO BE ADDED TO EXISTING FLYSPRAY CODE]$GLOBALS['eventObservers'] = array('myCommentObserver' =>new myCommentObserver());
//// pseudo-existing flyspray code//function addCommentToBug(){// UPDATE flyspray_bugs SET ...// [TO BE ADDED TO EXISTING FLYSPRAY CODE]
notifyObservers(EVENT_ADDED_COMMENT, $commentData)}// [TO BE ADDED TO EXISTING FLYSPRAY CODE]function notifyObservers($eventName, $data){foreach($GLOBALS['eventObservers']as$observer){$observerClass = new$observer;
$observer->notify($eventName, $data);
}}// [TO BE ADDED BY PEOPLE WANTING TO EXTEND FLYSPRAY]class MyCommentObserver
{publicfunction notify($eventName, $eventData){// look at the event and do whatever you like in here.switch($eventName){case EVENT_SAVED_BUG:
echo"The bug with id" . $data['id'] . " was saved!";
case EVENT_ADDED_COMMENT:
echo"The bug with id" . $data['id'] . " was saved!";
$myLogger->log($data['comment_text']);
break;
default:
// not handled. no need to handle all events}}}?>

<?php// define global constants for things that can happen in flyspray. // a flyspray function will "broadcast" any events that happens inside it// and any event observer can react to that.// [TO BE ADDED TO EXISTING FLYSPRAY CODE]define('EVENT_SAVED_BUG', 1);
define('EVENT_ADDED_COMMENT', 2);
define('EVENT_CLOSED_BUG', 3);
// [...] // configure Flyspray's Observer classes.//// all classes inside this array will be notified when the events defined above// occur inside flyspray.// someone wanting to add features to the Flyspray would write a class and add // it to this array.// in his class, he can decide if he wants to do something when this event ocurrs,// or not. he will be handed all useful data of from the flyspray context as well.// [TO BE ADDED TO EXISTING FLYSPRAY CODE]$GLOBALS['eventObservers'] = array('myCommentObserver' =>new myCommentObserver());
//// pseudo-existing flyspray code//function addCommentToBug(){// UPDATE flyspray_bugs SET ...// [TO BE ADDED TO EXISTING FLYSPRAY CODE]$commentData = array('bug_id' =>5, 'comment' =>'A comment on bug 5');
notifyObservers(EVENT_ADDED_COMMENT, $commentData);
}// [TO BE ADDED TO EXISTING FLYSPRAY CODE]function notifyObservers($eventName, $data){foreach($GLOBALS['eventObservers']as$observer){$observer->notify($eventName, $data);
}}// [TO BE ADDED BY PEOPLE WANTING TO EXTEND FLYSPRAY]class MyCommentObserver
{publicfunction notify($eventName, $data){// look at the event and do whatever you like in here.switch($eventName){case EVENT_SAVED_BUG:
echo"The bug with id" . $data['id'] . " was saved!";
break;
case EVENT_ADDED_COMMENT:
echo"The bug with id " . $data['bug_id'] . " was commented on!";
// $myLogger->log($data['comment_text']);break;
default:
// not handled. no need to handle all events}}}
addCommentToBug();
?>

I did not speak out on this yet (only to Tony) so here is my opinion: I think this task should not be implemented (as it is). It adds complexity no one wants and features no one needs. Instead I prefer something more like Phillip suggests: A simple hooks system which makes it possible to execute custom code on certain events. We could for example add a folder where everyone can put PHP scripts like this:

I like the idea of a plugin-system and so I start to develop. I added some lines into the templates, the scripts and include a file called class.plugin.php, which handles everything related to the plugins. I designed a structure for plugins, which is very easy. So the User has just to upload an Archive which includes the patch and then it is installed. After that he can activate,deactivate and remove the plugin. It is easy to handle for the User. The bad thing is that I have to edit all files which can be the target of an plugin. But I would do this if you think it should go this way!? I don’t want to work on a task, which will possibly not implemented.

My personal opionion is that a plugin system is not what we need at this time. Currently Flyspray would need different, much more important improvements. So if you like the extensibility idea, I suggest that you work on FS#218 first. We did not talk much about how the plugin system should work or what kind of plugins there should exist, so you better not rush the implementation. We can probably have a discussion of this task after 0.9.9 or rather 1.0.

But the Question is, why we had to develop something which will be replaced by a plugin-system (if there ever be something like can’t we develop a plugin-system which includes the function discussed in taks 218?

I don’t think that FS#218 should be a plugin. It should be part of the Flyspray core. So FS#218 can be implemented independently from this task. If we create a plugin system later, we can allow plugins to add new task fields too. Besides, FS#218 is more needed than a full plguin system so we should do it first.

Certain integration tasks lend themselves to a plugin system. For example a Joomla! Flyspray component based on the 0.97 version of Flyspray is difficult to upgrade because the authentication code changes (authenticate to Joomla user database) have been made in many of the core flyspray files. Hence any upgrade will over-write these files and authentication will break.

So I guess, as well as being a plugin system to extend functionality of Flyspray it would also be helpful in situations where flypsray is being integrated as a ‘plugin’ to some other system (in this case Joomla!).

I think authentication should at least have the ability/flexibility to interface with other user databases (synchronisation/direct authentication). Single sign-on is a key usability/acceptance factor for many organisations.

I think I can provide a real plugin system, but not for 0.9.9 not for 1.0, maybe in a future release... my idea is something like this...

//a abstract class that mandates all the methods a plugin must implement..
abtract class fsPlugin {
protected function init(){//here the intilitization of the plugin is done}publicfunction perform(){// all the plugin activity including output ..}}

Su..the user creates a plugin...

class MyPlugin extends fsPlugin {//must implement init() and perform() otherwise PHP throws a fatal error.. it may implement other methods//in order to actually create the logic of the plugin...}

the plugings are loaded by just “ticking” them in the admin panel mechanism to not be a mess, and actually work as expected, requires PHP5, that is the reason why it will not be in 0.9.9, not in 1.0 , is just an idea for the future.

JFYI: about the PHP4/PHP5 discussion, PHP4 official support ends on 31 Dec 2007 , Ubuntu has removed PHP4 from their repositories already and SUSE, Redhatand several other vendors does not ship PHP4 anymore.