I have great news, and it blew my mind when I realized how well it worked. In order to explain I will have to convey reason behind my development over the last 2 weeks. To those who don’t know, I have been spear heading an open source project called GneuManager, a project management suite that beings new meaning to modular. The last two weeks I have been putting the finishing touches on the interaction and caching on the back end of the application, let me explain…
A modular application by definition is broken into parts that are possibly interdependent, but aren’t always. PHPBB was the first application I ran into that said it was modular, but a problem existed… One way or another I always felt like I was being shorted because the modules were added in a very unintuitive way. Of course you would drop various files into a directory, images and the like, but you would surely lose consciousness while trying to modify the original files in order to make sure the module is executed properly and that its various parts fall in the proper places, and at the proper time. It would often take more time to find out where to put your code, and that’s even with experience building web applications, than it did to figure out what you wanted to add.
This form of modularity was replaced by what most people today are expecting, drag and drop functionality. Yes it is completely intuitive to think… drop a directory into the modules directory and I’m done. I have successfully installed a new module. Well, GneuManager calls for a new level of modularity; in fact it calls for a level of modularity that has yet to be supplied in any application that I have ever used. One of the features that we made clear to ourselves in the development was that we wanted these modules to be completely separate from the applications core, avoiding the steps of editing the template or forms that are located throughout the applications directories. How have I achieved this? Three parts make up the core…
This object is used to keep track of fairly obvious things. An event consists of a name, preferably in all caps just because that made sense in development, and a function that is tied to it. Events are declared, hooked and executed as necessary, Currently they are a number of default events such as the OUTPUT event which calls the output buffering functions to begin sending the content to the user, and BEGIN_LOAD which is called before any of the modules are loaded, and END_LOAD, which is used to clean and ignore any and all printing handled by the modules. PHP has no function pointers or enclosures, so we turned to its equivalent – call_user_func() – for every action there is an equal and opposite function in PHP. Developers of this application need only execute a couple lines in order to get their functions to be executed in turn.
$gG_EventManager->ExposeEvent("USER_LOGIN"); $gG_EventManager->ExposeEvent("USER_EDIT"); $gG_EventManager->ExposeEvent("USER_LOGOUT"); $gG_EventManager->ExposeEvent("USER_UPDATE"); $gG_EventManager->HookEvent("USER_LOGIN", "User::Login"); $gG_EventManager->HookEvent("USER_LOGOUT", "User::Logout"); $gG_EventManager->HookEvent("USER_UPDATE", "User::Update"); $gG_EventManager->HookEvent("OUTPUT_LOADTABS", "User::LoadTabs");
A close second in craziness is the output manager. Above you may have noticed that I have a hook of the OUTPUT_LOADTABS event. The output manager builds the tabs via this event. It pre-pends the tabs with the Home tab and begins building. Currently the way this orders the tabs is by weight, similar to how drupal handles it, but only 1..10. Using this event Developers can very quickly add to and organize the tabs, but that is not the end of the spectrum. I have also added functionality to allow pages to be included in a similar fashion.
Navigating to ?page=user/edit will trigger that forum to be executed. Obviously this cannot be achieved by allowing the function to be named in the URL because there can be some serious flaws in security.
Here is the simpleton of the application. As yet unfinished, although still very simple, it handles the loading of modules into the system, in a dynamic fashion, and handles the install of any of such modules. It actually is the reason that the above is possible.