Browse Source

* Move events to a trait
* rename base to reflect that it is abstract
* Add event handling
* Add default events to app, router and response

Nathaniel van Diepen 7 years ago
parent
commit
9397a1811f
6 changed files with 60 additions and 10 deletions
  1. 13 4
      app.class.php
  2. 1 1
      base.abstract.class.php
  3. 0 5
      events.interface.php
  4. 29 0
      events.trait.php
  5. 13 0
      response.class.php
  6. 4 0
      router.class.php

+ 13 - 4
app.class.php

@@ -1,17 +1,18 @@
 <?php
-	require_once('base.class.php');
+	require_once('base.abstract.class.php');
 	require_once('router.class.php');
 	require_once('response.class.php');
 	require_once('request.class.php');
 	require_once('uri.class.php');
-	require_once('events.interface.php');
-	class App extends Base implements Events {
+	require_once('events.trait.php');
+	class App extends Base {
+		use Events;
 		private static $apps = [];
 		private $domains;
 		private $routers;
 		private $router;
 		public $_onerror;
-		public function __construct(string $name, Callable $fn = null){
+		public function __construct(string $name, Callable $fn = null, array $events = null){
 			$this->name = $name;
 			$this->router = new Router();
 			$this->routers = [];
@@ -34,6 +35,11 @@
 					print($o);
 				}
 			};
+			if(!is_null($events)){
+				foreach($events as $name => $handler){
+					$this->on($name, $handler);
+				}
+			}
 			static::$apps[] = $this;
 			if(is_callable($fn)){
 				$fn($this);
@@ -86,6 +92,7 @@
 			}
 			$res = new Response();
 			$req = new Request($url, $headers, $data);
+			$this->fire('handle', $req, $res);
 			$self = $this;
 			$onerror = function($res, $error) use($self){
 				$self->onerror($req, $res, $error);
@@ -109,6 +116,7 @@
 					$self->onerror($req, $res,new Error("Not Found", 404));
 				}
 			}, $onerror);
+			$this->fire('afterhandle', $req, $res);
 			return $res;
 		}
 		public function error(Callable $fn){
@@ -134,6 +142,7 @@
 			return $this;
 		}
 		public function onerror(Request $req, Response $res, $error){
+			$this->fire('error', $error);
 			$fn = $this->_onerror;
 			if(is_callable($fn)){
 				$fn($req, $res, $error);

+ 1 - 1
base.class.php → base.abstract.class.php

@@ -1,5 +1,5 @@
 <?php
-	abstract class Base{
+	abstract class Base {
 		private $data;
 		public function __construct(){
 			$this->data = [];

+ 0 - 5
events.interface.php

@@ -1,5 +0,0 @@
-<?php
-	interface Events {
-		
-	}
-?>

+ 29 - 0
events.trait.php

@@ -0,0 +1,29 @@
+<?php
+	trait Events {
+		private $events = [];
+		public function on(string $name, Callable $fn){
+			if(!isset($this->events[$name])){
+				$this->events[$name] = [];
+			}
+			$this->events[$name][] = $fn;
+			return $this;
+		}
+		public function off(string $name, Callable $fn = null){
+			if(isset($this->events[$name])){
+				$a = $this->events[$name];
+				foreach($a as $k => $f){
+					if(is_null($fn) || $f == $fn){
+						array_splice($a, $k, 1);
+					}
+				}
+			}
+		}
+		public function fire(string $name, ...$args){
+			if(isset($this->events[$name])){
+				foreach($this->events[$name] as $fn){
+					$fn(...$args);
+				}
+			}
+		}
+	}
+?>

+ 13 - 0
response.class.php

@@ -11,12 +11,14 @@
 		}
 		public function clear(){
 			if($this->open){
+				$this->fire('clear');
 				$this->body = '';
 			}
 			return $this;
 		}
 		public function clear_headers(){
 			if($this->open){
+				$this->fire('clear_headers');
 				$this->headers = [];
 			}
 			return $this;
@@ -24,12 +26,14 @@
 		public function clear_header(string $name){
 			foreach($this->headers as $key => $header){
 				if($header[0] == $name){
+					$this->fire('clear_header', $name);
 					array_splice($this->headers, $key, 1);
 				}
 			}
 			return $this;
 		}
 		public function write(string $chunk){
+			$this->fire('write', $chunk);
 			if($this->open){
 				$this->body .= $chunk;
 			}
@@ -43,6 +47,7 @@
 					}
 				});
 			}
+			$this->fire('json', $json);
 			$this->write(json_encode($json));
 			if(json_last_error() != JSON_ERROR_NONE){
 				throw new Exception(json_last_error_msg());
@@ -51,6 +56,7 @@
 		}
 		public function header(string $name, string $value){
 			if($this->open){
+				$this->fire('header', $name, $value);
 				array_push(
 					$this->headers,
 					[
@@ -62,12 +68,14 @@
 			return $this;
 		}
 		public function redirect(string $url){
+			$this->fire('redirect', $url);
 			$this->header('Location',Router::url($url));
 			return $this;
 		}
 		public function end(string $chunk=''){
 			if($this->open){
 				$this->write($chunk);
+				$this->fire('end');
 				$this->open = false;
 			}
 			return $this;
@@ -76,6 +84,7 @@
 			if(!$type){
 				$type = $img->type;
 			}
+			$this->fire('image', $img, $type);
 			$this->clear_header('Content-Type')
 				->header('Content-Type', 'image/'.$type);
 			if(!is_a($img, 'Image')){
@@ -92,19 +101,23 @@
 			if(is_null($code)){
 				return $this->code;
 			}
+			$this->fire('code', $code);
 			$this->code = $code;
 			return $this;
 		}
 		public function shutdown(){
+			$this->fire('beforeshutdown');
 			if($this->open){
 				$this->end();
 			}
+			$this->fire('shutdown');
 			http_response_code($this->code);
 			foreach($this->headers as $k => $header){
 				header("{$header[0]}: $header[1]");
 			}
 			echo $this->body;
 			flush();
+			$this->fire('aftershutdown');
 		}
 	}
 ?>

+ 4 - 0
router.class.php

@@ -2,7 +2,9 @@
 	require_once('path.class.php');
 	require_once('response.class.php');
 	require_once('request.class.php');
+	require_once('events.interface.php');
 	class Router {
+		use Events;
 		private $_paths = [];
 		private $_routers = [];
 		private $_base = '/';
@@ -93,6 +95,7 @@
 				if(!in_array($res,$this->responses)){
 					array_push($this->responses,$res);
 				}
+				$this->fire('handle', $req, $res);
 				$handled = false;
 				foreach($this->_routers as $prefix => $router){
 					$router->handle($path, $req, $res);
@@ -119,6 +122,7 @@
 				}
 				$res->output .= ob_get_contents();
 				ob_end_clean();
+				$this->fire('afterhandle', $req, $res);
 			}
 			return $res;
 		}