Added a mod register which allows the system to load advanced modules. This allows for the future build of module versions, prevention of module name conflicts and much more.

This commit is contained in:
Abel Hoogeveen 2015-03-14 15:46:05 +01:00
parent f6f72cc09d
commit 68c68cf91c
5 changed files with 138 additions and 49 deletions

View File

@ -2,6 +2,7 @@
'SITE_URL' => '',
'SITE_DOMAIN' => '',
'SERVER_NAME' => '',
'registers_update_interval' => 3600,
'administrator_mail' => '',
'default_controller' => 'standard',
'default_function' => 'index',

View File

@ -17,6 +17,11 @@ class Module extends Bus {
*/
protected $moduleName = 'placeholder';
/**
* @var String name used in the mod array
*/
protected $linkName = 'placeholder';
/**
* Constructor
*
@ -59,4 +64,22 @@ class Module extends Bus {
if($this->modulePath === null)
$this->modulePath = $modulePath;
}
/**
* Set the link name of the module. The link name is the address in the module array so that the module can self reference.
* @access public
* @param String link name
*/
public function setModuleLinkName($linkName) {
$this->linkName = $linkName;
}
/**
* The name that is required to load itself, eg 'exampleauthor/examplemodulename' or 'techfuze/cms'
* @access public
* @param String module name
*/
public function setModuleName($modName) {
$this->moduleName = $modName;
}
}

View File

@ -11,6 +11,7 @@ class Core {
public $mods;
private $loaded = false;
private $register;
## START/STOP
public function init() {
@ -23,6 +24,12 @@ class Core {
$this->loadStartupFiles();
$this->mods->events->fireEvent('coreStartEvent');
// Mod register exists, check if expired
if ( ( date('U') - $this->mods->config->main->registers_last_update) > $this->mods->config->main->registers_update_interval) {
$this->mods->logger->log("Registers have expired. Updating...", 'Core');
$this->buildModRegister();
$this->mods->events->buildEventRegister();
}
}
public function loadStartupFiles() {
@ -57,69 +64,127 @@ class Core {
}
## MODLOADING
public function loadMod($name) {
public function loadMod($name, $version = null) {
if (!isset($this->mods->$name)) {
$CLASS = $this->loadModule($name);
$this->mods->{strtolower($name)} = &$CLASS;
$this->mods->{strtolower($CLASS[1])} = &$CLASS[0];
}
}
public function getMod($name) {
public function getMod($name, $version = null) {
$CLASS = $this->loadModule($name);
return $CLASS;
return $CLASS[0];
}
private function loadModule($name) {
// Class name
$class_name = ucfirst($name);
// If the mod is in the top mod directory, load it directly
$file = FUZEPATH . "/Core/Mods/class.".$class_name.".php";
if (file_exists($file)) {
$this->mods->logger->log("Loading module '".$class_name."'");
$path = FUZEPATH . "/Core/Mods/class.".$class_name.".php";
require_once($file);
// If not, and a mod config file is found, follow that
} elseif ( file_exists(FUZEPATH . "/Core/Mods/".strtolower($name)."/moduleInfo.php" )) {
// Load the config file
$cfg = (object) require(FUZEPATH . "/Core/Mods/".strtolower($name)."/moduleInfo.php");
// Load the class name and file
$class_file = FUZEPATH . "/Core/Mods/".strtolower($name)."/" . $cfg->module_file;
$class_name = $cfg->module_class;
// Load the dependencies first
$deps = (isset($cfg->dependencies) ? $cfg->dependencies : array());
for ($i=0; $i < count($deps); $i++) {
$this->loadMod($deps[$i]);
}
$path = FUZEPATH . "/Core/Mods/".strtolower($name)."/";
$this->mods->logger->log("Loading Module '".$cfg->name."' v".$cfg->version." made by '".$cfg->author."' : '".$cfg->website."'");
require_once($class_file);
// If no config file found, but a main class is, load that
} elseif ( file_exists(FUZEPATH . "/Core/Mods/".strtolower($name)."/class.".$class_name.".php") ){
$this->mods->logger->log("Loading module '".$class_name."'");
$path = FUZEPATH . "/Core/Mods/".strtolower($name)."/";
require_once(FUZEPATH . "/Core/Mods/".strtolower($name)."/class.".$class_name.".php");
// Otherwise Abort
private function loadModule($name, $version = null) {
// Load the register if not loaded yet
if (!isset($this->mods->config->modregister->register)) {
$this->buildModRegister();
} else {
// MOD NOT FOUND
$this->register = $this->mods->config->modregister->register;
}
// The basic module path
$path = FUZEPATH . "/Core/Mods/";
// Chech if the requested module is set
if (isset($this->register[$name])) {
// Check if the config file is loaded
if (!empty($this->register[$name])) {
// Load the config file
$cfg = (object) $this->register[$name];
// Check if a specific version is requested
if (isset($version)) {
// @TODO: Implement
} else {
// Or load the main version
$file = $cfg->directory . $cfg->module_file;
// Load the dependencies before the module loads
$deps = (isset($cfg->dependencies) ? $cfg->dependencies : array());
for ($i=0; $i < count($deps); $i++) {
$this->loadMod($deps[$i]);
}
// Check if the file exists
if (file_exists($file)) {
// And load it
require_once($file);
$class_name = $cfg->module_class;
$msg = "Loading Module '".ucfirst((isset($cfg->name) ? $cfg->name : $cfg->module_name)) . "'";
$msg .= (isset($cfg->version) ? " version:".$cfg->version : "");
$msg .= (isset($cfg->author) ? " made by ".$cfg->author : "");
$msg .= (isset($cfg->website) ? " from ".$cfg->website: "");
$this->mods->logger->log($msg);
} else {
// Throw Exception if the file does not exist
throw new Exception("Requested mod '".$name."' could not be loaded. Class file not found", 1);
return false;
}
}
} else {
// Throw Exception if the module has an invalid config file
throw new Exception("Requested mod '".$name."' could not be loaded. Invalid config", 1);
return false;
}
} else {
// Throw Exception if the module is not defined
throw new Exception("Requested mod '".$name."' was not found", 1);
return false;
return false;
}
// Create class object
$CLASS = new $class_name($this);
if (method_exists($CLASS, 'setModulePath')) {
$CLASS->setModulePath($path);
$CLASS->setModulePath($cfg->directory);
}
if (method_exists($CLASS, 'setModuleLinkName')) {
$CLASS->setModuleLinkName($cfg->module_name);
}
if (method_exists($CLASS, 'setModuleName')) {
$CLASS->setModuleName($name);
}
$CLASS->onLoad();
return $CLASS;
return array($CLASS, $cfg->module_name);
}
public function buildModRegister() {
$this->mods->logger->newLevel("Building Mod Register", 'Core');
$dir = FUZEPATH . "Core/Mods/";
$mods = array_values(array_diff(scandir($dir), array('..', '.')));
$register = array();
for ($i=0; $i < count($mods); $i++) {
$mod_dir = $dir . $mods[$i] . "/";
if (file_exists($mod_dir . "/moduleInfo.php")) {
$cfg = (object) require($mod_dir . "/moduleInfo.php");
$name = "";
$name .= (!empty($cfg->author) ? strtolower($cfg->author)."/" : "");
$name .= strtolower($cfg->module_name);
// Append directory
$cfg->directory = $mod_dir;
$register[$name] = (array) $cfg;
} else {
// Get the name
$name = $mods[$i];
// Build a dynamic module config
$cfg = new stdClass();
$cfg->module_class = ucfirst($name);
$cfg->module_file = 'class.'.strtolower($name).".php";
$cfg->module_name = $name;
$cfg->dependencies = array();
$cfg->versions = array();
$cfg->directory = $mod_dir;
$register[$name] = (array)$cfg;
}
}
$this->mods->logger->stopLevel();
$this->mods->config->set('modregister', 'register', $register);
$this->mods->config->set('main', 'registers_last_update', date('U'));
}
}

View File

@ -156,9 +156,9 @@ class Events extends Bus{
public function buildEventRegister() {
$this->logger->newLevel("Building Event Register", 'Events');
$dir = FUZEPATH . "/Core/Mods/";
$mods = array_values(array_diff(scandir($dir), array('..', '.')));
for ($i=0; $i < count($mods); $i++) {
$this->core->loadMod($mods[$i]);
$mods = $this->config->modregister->register;
foreach ($mods as $key => $value) {
$this->core->loadMod($key);
}
$event = $this->fireEvent('eventRegisterBuildEvent', '');