Sam,
I think application extensibility is absolutely important. The applications which take off are the ones which can be customized to this degree. People love applications which can be extended because they are not limited and if they want a feature they usually can find it sooner or later. And if they really, really want it they could build it themselves.
To add plugin support to RC I would start documenting what a plugin would be able to do from a functional standpoint. And I would consider how other applications have been built for extensibility. The main one that comes to mind is the Apache Web Server. Much of the functionality that people use is optional. But it is the most widely used web server because it can do so much. And if there is a shortcoming you can quickly overcome it by extending Apache with a module. Apache even allows extensions in different languages like Perl, PHP and Python so you start with C which few developers can do well but open up the extensibility to a very large pool of capable developers. By using JSON as the communications layer there is no reason the backend has to be PHP because JSON has been ported to all of the top programming languages.
For RoundCube I could see some of the existing features broken out into plugins/extensions which come bundled with the installation with a few additional plugins disabled. The core plugins are excellent examples for those who choose to create a custom plugin. And as we add features to RC we make a more rich plugin architecture.
One important point is that the plugin developers who create custom plugins are responsible for testing their own plugins with the RC releases. The core RC team will not be able to test every plugin and should not be expected to support them.
A feature I would want a plugin to be able to do is handle new messages as they are coming in and when messages are moved between folders. From an event-driven standpoint I would like the event to be raised before the action is taken with the option to cancel it, and then again once the action has completed. For the folders, I would have these...
OnMessageMoving(source, cancelEventArgs) - before moving OnMessageMoved(source, eventArgs) - after moved
In each case the source would be the message which is moving and the event args would have a property naming the sourceFolder and destinationFolder. And the cancelEventArgs.cancel property could be set to false to tell the caller not to move the message.
I think this would be a good construct for many of the plugin actions. It is common with event-driven software.
I can easily think of a great way to use this as a plugin. I get emails from my WordPress blog when people post comments with a very specific subject. If I want the comment on my blog deleted I could drag the email to the trash and the plugin would check if it is a blog comment message take the necessary action to delete the comment on my blog. And moving it to my Blog folder could mark a blog comment as approved. Instantly I could have RC integrated with WP. And if the plugin fails to authenticate with my WP blog it could cancel the move and show me a warning. This is something you clearly do not want in the RC core but would be beneficial to many users who also use WP.
That leads to the next point of extensibility. Some plugins will need preferences set. So we would need a way for a plugin to display settings on the preferences screen.
I think we could gradually add more event wrappers to various parts of the interface. With each RC release we can add new wrapper and the plugin developers can add handlers for each of the wrappers if they want to implement some behavior. But a plugin may just use one wrapper for a specific need. We just want to stabilize the initial wrappers so we do not keep changing how they work in later releases and break existing plugins.
Another use for a plugin would be for rendering messages. When I send myself an invite from Google Calendar it sends along an .ics file. Outlook knows how to handle it which I think supported this feature first and Google copied it. I think Apple created the .ics format which MS copied. (wonderful integration!) I would like to use an invitation plugin which can detect this calendar data and do something to the display of the message to integrate with some sort of calendar system that the plugin provides.
For the address book, when I add a new contact a plugin could relay the new contact to another system. A plugin could also handle lookups in a custom user store which we cannot predict for RC. LDAP integration is obvious, but if someone has a custom contact database they could create a plugin to integrate with it. And if one of the core plugins is an LDAP plugin they could use that as a starting point for their own plugin.
Sam,
What we can do is flesh out a proof of concept to present to the team. Once we have put in the work to show a working demo it would be a few steps closer to seeing how it can be implemented with RC.
Brennan
On Thu, 18 Jan 2007 10:02:53 +1100, Sam Bailey cyprix@cyprix.com.au wrote:
I agree with Brennan that a plugin system as he suggests will make things a lot easier to create extensions. As it seems to be decided that a RSS Reader would be considered a bloat, that part of the discussions can now move elsewhere, and I will setup a devel page for it to be done
- if there are any volunteers!! :)
Back to the plugin discussion - what Brennan has suggested seems a lot of work and a major change. As such the roadmap shows it as a 0.3 feature. That leaves me with several questions.
- How are the discussions going along the speeding up the release
cycle, by focusing on the active tickets for each release?
- How long does it seem before the plugin system could be implemented -
are we going to put it off for a while and concentrate on the core features?
- Without a plugin system, how would we go about writing a plugin, such
as this RSS reader?
- Should we set down some basic plugin guidelines or at least the
theory of the system so that we could start a project now, so that there wouldn't be as much to change later?
Sam Bailey (cyprix)
Brennan Stehling wrote:
A while back I suggested breaking up the code to clearly separate the
PHP, Javascript and (X)HTML so that it would be much more flexible. A plugin system would be a good example of that.
What I suggested was an HTML template system where the application loads
largely as static content which uses XHTML and CSS to draw each of the portions of the page with class and id attributes carefully placed to denote important areas, like the toolbar, folders and message box. From there Javascript would use AJAX functions to communicate with the server. On the server PHP would service the Javscript using the JSON protocol for a clean communication layer.
With this architecture you could create a very powerful plugin system.
I would have a Javascript library control all changes on the UI, such as loading messages from the server and placing them into the message box. Consider when the static template loads after you log into the system the following Javascript would run:
function init() { var rcc = new RoundCubeClient(); rcc.LoadFolders(); rcc.LoadMessages(); rcc.StartMonitor(); // polls server for new messages }
In the LoadFolders and LoadMessages method they would run an AJAX
request to get the data necessary to call the following code...
rcc.AddFolder("Inbox"); rcc.AddFolder("Trash"); rcc.AddFolder("Junk"); rcc.AddFolder("Work");
And this RoundCubeClient object would be all static.
This leads into what you could do with a plugin architecture. A plugin
could do a good deal of work with just the Javascript and a little PHP on the server. Modern Javascript techniques show how you can extend Javascript objects with a little inheritance, so consider that a RoundCubeExtension object could be defined as a base class which developers could use a base for inheritance. They could override certain behavior, such as hooks which are fired off by the RoundCubeClient. The client would loop over all configured extensions and run their methods as appropriate. One method that a SpamExtension may run is ProcessMessages() which may loop over all messages and flag messages which match a certain criteria, like a X-Spam-Status header on the message. The client would cal this method after the main method ProcessMessages() on the default client is run.
On the server-side the PHP extensions could provide additional data and
carry out actions on the server. The Ajax requests can make any GET or POST requests of the server. The SpamExtension may look at a message in the Inbox and see the X-Spam-Status is set to Yes and call this function.
rcc.MoveMessage(message, "Junk");
Internally this MoveMessage function would carry out the same action
that happens when we drag a message from the Inbox to the Junk folder, but this would happen with the extension.
The last time I looked the server-side PHP code was emitting a
significant amount of the Javascript and the HTML. If this sort of architecture looks appealing I would like development to start moving in that direction as soon as possible. We already have a lot of this all working, it just needs to be pulled apart a bit into the distinct components.
When it comes to the RSS reader, the Javascript and JSON calls back to
the server do not need to know where the content comes from. We could just implement a message type and allow plugins to handle messages by type. The PHP code on the server has to emit the message in the required JSON format to define the message id, subject, and body of the message. And dealing with folders is another matter. The RSS reader could define folders which it handles itself and when you click on them they are completely handled by the extension.
This may sound pretty complex, but when each piece is built carefully it
will work quite well together and creating new features will be very easy.
Brennan
On Wed, 17 Jan 2007 18:33:37 +0100, Michael Bueker m.bueker@berlin.de
wrote:
Sam Bailey wrote:
- Create as a plugin or as a separate or joint project
According to the roadmap, a plugin API is in planning. I think an RSS reading feature is beyond the scope of roundcube, and I personally
would
consider it to be bloat.
But it seems a perfect model plugin, and many people will probably like the functionality. Even if browser have RSS plugin, you don't usually take your browser everywhere, but you do access roundcube from everywhere. So it has its purpose.
Keep the 2 cents ;)
~Mik
-- I remember 20 years ago when young lady was just getting into email she ask me if a virus could be spread by email. I just laughed and said no, it would never happen. It would require that email readers have the ability to execute code passed to them, and nobody would be stupid enough to write a mail program that would do that.
- Lord Apathy on /.