Page 1 of 1

Creating a "plugin/modular" design

Posted: Mon Feb 05, 2007 10:09 am
by AlexC
Hey,

I'm currently coding an open-source PHP content management system and am in the middle of a complete re-code to increase security, speed and to make it even more customizable.

What would be the best way to include modules (a module in my cms is like a menu, news, poll etc) into the main "core"? Should each module be wrapped in a class, then the core includes the module file and starts the class? Or should it not be wrapped in a class and the module just gets included?

The way my CMS works is that each module gets loaded into different "sectors" of the template file, so for example I could have a sector like {S1} then my php code would be like this:

Code: Select all

$template->assign_tags( array( 'S1' => 'Yay lots of text for the people of the internets to see' ) );
and my CMS would replace S1 with the value. I use ob_start() to catch and store the output of a module currently and then assign the correct sector with the module output, which I don't really like doing as I know there is probably a better way.

If anyone would like to help with the coding and getting it released by late April/early May this year then please contact me!

Posted: Mon Feb 05, 2007 10:12 am
by feyd
"Plugin" and "modular" would tend to lean toward classes.

I would base them on a single main interface, and possibly a second interface (derived from the first) for specific types of modules.

Posted: Mon Feb 05, 2007 10:20 am
by AlexC
Thanks for the quick response!

So what would you suggest the structure of a module should be? If you could do just like a small bit of code that would help me understand better.

Regards,

Posted: Mon Feb 05, 2007 3:55 pm
by AlexC
After doing some research, I've managed to make a new module/plugin system for my CMS:

Code: Select all

class Framework {
		
		var $modules = array();
		
		//---
		// constructor function
		//---
		function Framework() {
			
		}
		
		//---
		// load_module() will load a module into the framework
		// @param object $module_object
		//---
		function load_module( &$module_object ) {			
			if ( !is_object( $module_object ) ) {
				return false;
			}
			$module_name = $module_object->identitfier;
                        $module_object->load_framework_object( &$this ); 
			$this->modules[ $module_name ] = &$module_object;			
		}
		
		//---
		// trigger_event() will trigger an event to all loaded modules or
		// selected modules
		// @param string $event
		// @param mixed $module
		//---
		function trigger_event( $event, $module='' ) {
			if ( empty( $module ) ) {
				// trigger event to all loaded modules
				foreach( $this->modules as $name=>$object ) {
					if ( method_exists( $object, $event ) ) {
						$this->modules[ $name ]->$event();
					}
				}
			} else if ( is_array( $module ) ) {
				// trigger event to a selected number of modules
				foreach( $this->modules as $name=>$object ) {
					if ( in_array( $name, $module ) && method_exists( $object, $event ) ) {
						$this->modules[ $name ]->$event():
					}
				}
			} else {
				// trigger to single module
				if ( method_exists( $this->modules[ $name ], $event ) ) {
					$this->modules[ $name ]->$event();
				}
			}
		}
		
	}
I haven't tested it and just put it together quickly after reading many many observer and other plugin scripts (mainly the oen by d11wtq), but it should allow me to run different events for different modules, or all modules etc - a module would then look like this:

Code: Select all

class module_menu {
	
	var $identitfier = 'menu';
	var $framework_object;
	
	//---
	// load_framework_object() will load the main framework object
	// so that the module can easily access framework functions etc
	//---
	function load_framework_object( &$framework_object ) {
		$this->framework_object = &$framework_object;
	}
	
	//---
	// display_content() main event for all modules
	//---
	function dispaly_content( $foo ) {
		echo $foo;
	}
	
}
I currently have a SQL class which will allow me in the future to support more than just MySQL databases, currently if I wanted to run a query on a database tabel I would do:

Code: Select all

global $libsql;

$query = $libsql->query( " SELECT * FROM {SQL_PREFIX}table WHERE foo='bar' " );
but I remember someone saying to me once "you shouldn't use globals as they can be bad and cause unwanted effects" or something like that anyway :) - so, how could I give modules access to this SQL database "layer" class I've coded without using "global $libsql" ? Would maybe doing this for the $libsql class work?

Code: Select all

class libsql extends Framework {
and then if I wanted to access libsql functions, such as "query" I could do this below, in a module:

Code: Select all

$query = $this->framework_object->query(  " SELECT * FROM {SQL_PREFIX}table WHERE foo='bar' " );
or wouldn't that work?

Regards,

Posted: Tue Feb 06, 2007 10:44 am
by AlexC
What would be the best way to add this SQL class into the core framework class? I've been reading up on OOP and Modular/Plugin design but I can see no logical way to add SQL support, if that makes sense.

Regards,