Implemented new Event System. Listeners are no longer classes but now are simply callback functions. Also there is now a priority system which decides in which order events are executed.

The core can also not be loaded more then once. A check has been built in. The Model abstract is from now on a system module. No longer a core process.
This commit is contained in:
Abel Hoogeveen 2015-02-11 14:23:27 +01:00
parent 0b1980c32c
commit 4d8b8d5233
7 changed files with 175 additions and 24 deletions

View File

@ -1,5 +1,7 @@
<?php
class Model {
public function onLoad(){}
}
class DatabaseModel extends Bus{
public $fields = array();

View File

@ -0,0 +1,74 @@
<?php
/**
* Class EventPriority
*
* The EventPriority is an "enum" which gives priorities an integer value, the higher the integer value, the lower the
* priority. The available priorities are, from highest to lowest:
*
* EventPriority::MONITOR
* EventPriority::HIGHEST
* EventPriority::HIGH
* EventPriority::NORMAL
* EventPriority::LOW
* EventPriority::LOWEST
*
* @package System\Core
*/
abstract class EventPriority
{
const LOWEST = 5;
const LOW = 4;
const NORMAL = 3;
const HIGH = 2;
const HIGHEST = 1;
const MONITOR = 0;
/**
* Returns the string of the priority based on the integer
* @param $intPriorty
* @return bool|string A bool when the integer isn't a priority. If the integer is a priority, the name is returned
*/
static function getPriority($intPriorty){
switch($intPriorty){
case 5:
return "EventPriority::LOWEST";
case 4:
return "EventPriority::LOW";
case 3:
return "EventPriority::NORMAL";
case 2:
return "EventPriority::HIGH";
case 1:
return "EventPriority::HIGHEST";
case 0:
return "EventPriority::MONITOR";
default:
return false;
}
}
/**
* Returns the highest priority
* This function is needed for the firing of events in the right order,
* @return int
*/
static function getHighestPriority(){
return EventPriority::MONITOR;
}
/**
* Returns the lowest priority
* This function is needed for the firing of events in the right order,
* @return int
*/
static function getLowestPriority(){
return EventPriority::LOWEST;
}
}

View File

@ -10,6 +10,7 @@ if (!defined('FUZESYSPATH')) {
class Core {
public $mods;
private $loaded = false;
## START/STOP
public function init() {
@ -23,11 +24,15 @@ class Core {
}
public function loadStartupFiles() {
if ($this->loaded)
return;
// Load core abstracts
require_once(FUZESYSPATH . "/class.abstract.bus.php");
require_once(FUZESYSPATH . "/class.abstract.model.php");
//require_once(FUZESYSPATH . "/class.abstract.model.php");
require_once(FUZESYSPATH . "/class.abstract.event.php");
require_once(FUZESYSPATH . "/class.abstract.module.php");
require_once(FUZESYSPATH . "/class.abstract.eventPriority.php");
// Load the core classes
require_once(FUZESYSPATH . "/class.config.php");
@ -42,6 +47,8 @@ class Core {
$this->mods->logger = new Logger ($this);
$this->mods->models = new Models ($this);
$this->mods->layout = new Layout ($this);
$this->loaded = true;
}
public function shutdown() {

View File

@ -17,11 +17,62 @@ class Events extends Bus{
$this->listeners = array();
}
/**
* Adds a function as listener
*
* @param mixed callback The callback when the events get fired, see {@link http://php.net/manual/en/language.types.callable.php PHP.net}
* @param String $eventName The name of the event
* @param int $priority The priority, even though integers are valid, please use EventPriority (for example EventPriority::Lowest)
* @see EventPriority
*
* @throws EventException
*/
public function addListener($callback, $eventName, $priority = EventPriority::NORMAL){
if(EventPriority::getPriority($priority) == false)
throw new Exception("Unknown priority " . $priority);
if(!isset($this->listeners[$eventName]))
$this->listeners[$eventName] = array();
if(!isset($this->listeners[$eventName][$priority]))
$this->listeners[$eventName][$priority] = array();
$this->listeners[$eventName][$priority][] = $callback;
}
/**
* Removes a function as listener
*
* @param mixed callback The callback when the events get fired, see {@link http://php.net/manual/en/language.types.callable.php PHP.net}
* @param String $eventName The name of the event
* @param int $priority The priority, even though integers are valid, please use EventPriority (for example EventPriority::Lowest)
* @see EventPriority
*
* @throws EventException
*/
public function removeListener($callback, $eventName, $priority = EventPriority::NORMAL){
if(EventPriority::getPriority($priority) == false)
throw new Exception("Unknown priority " . $priority);
if(!isset($this->listeners[$eventName]))
return;
if(!isset($this->listeners[$eventName][$priority]))
return;
foreach($this->listeners[$eventName][$priority] as $i => $_callback){
if($_callback == $callback) {
unset($this->listeners[$eventName][$priority][$i]);
return;
}
}
}
## EVENTS
public function fireEvent($input) {
if (is_string($input)) {
// STRING
$eventClass = $input;
$eventName = $input;
if(!class_exists($eventClass)){
@ -59,24 +110,43 @@ class Events extends Bus{
if (func_num_args() > 1)
call_user_func_array(array($event, 'init'), array_slice(func_get_args(), 1));
$this->logger->log("Cycling Listeners");
for ($i=0; $i < count($this->listeners); $i++) {
$class = $this->listeners[$i];
if (method_exists($class, 'on'.ucfirst($eventName))) {
$result = $class->{'on'.ucfirst($eventName)}($event);
$event = ($result !== null ? $result : $event);
}
}
$this->logger->log("Checking for Listeners");
//There are listeners for this event
if(isset($this->listeners[$eventName])) {
//Loop from the highest priority to the lowest
for ($priority = EventPriority::getHighestPriority(); $priority <= EventPriority::getLowestPriority(); $priority++) {
//Check for listeners in this priority
if (isset($this->listeners[$eventName][$priority])) {
$listeners = $this->listeners[$eventName][$priority];
$this->logger->newLevel('Found listeners with priority ' . EventPriority::getPriority($priority));
//Fire the event to each listener
foreach ($listeners as $callback) {
if(!is_string($callback[0]))
$this->logger->newLevel('Firing ' . get_class($callback[0]) . '->' . $callback[1]);
else
$this->logger->newLevel('Firing ' . join('->', $callback));
$this->logger->newLevel('');
try {
call_user_func($callback, $event);
} catch (ModuleException $e) {
$this->error->exceptionHandler($e);
}
$this->logger->stopLevel();
$this->logger->stopLevel();
}
$this->logger->stopLevel();
}
}
}
$this->logger->stopLevel();
return $event;
}
public function addListener(&$object) {
if (is_object($object)) {
$this->listeners[] = $object;
}
}
}

View File

@ -67,6 +67,10 @@ class Layout extends Bus {
$this->title = $title;
}
public function getTitle() {
return $this->title;
}
public function view($view = "default", $dir = "") {
// Chech if Smarty is loaded
if (!$this->loaded)

View File

@ -17,7 +17,7 @@ class Logger extends Bus{
set_Exception_handler(array($this, "exceptionHandler"));
error_reporting(false);
}
$this->events->addListener($this);
$this->events->addListener(array($this, 'onCoreShutdownEvent'), 'coreShutdownEvent', EventPriority::LOWEST);
$this->newLevel("Logger Initiated");
}

View File

@ -4,13 +4,6 @@
* @package files
*/
/** Config
*
* This class keeps the config loaded at all times via a singleton class
*
* @name Config
* @package Core
*/
class Models extends Bus{
private $models_array = array();
@ -21,6 +14,7 @@ class Models extends Bus{
}
public function loadModel($name, $directory = null){
$this->core->loadMod('model');
if($directory === null){
$directory = FUZEPATH . "/Application/Models";
}