Browse Source

implement plugin routing masks, add example plugin

Andrew Dolgov 7 years ago
parent
commit
8dcb2b4762

+ 11 - 3
backend.php

@@ -118,10 +118,18 @@
 
 	$op = str_replace("-", "_", $op);
 
-	if (class_exists($op)) {
-		$handler = new $op($link, $_REQUEST);
+	global $pluginhost;
+	$override = $pluginhost->lookup_handler($op, $method);
 
-		if ($handler && is_subclass_of($handler, 'Handler')) {
+	if (class_exists($op) || $override) {
+
+		if ($override) {
+			$handler = $override;
+		} else {
+			$handler = new $op($link, $_REQUEST);
+		}
+
+		if ($handler && implements_interface($handler, 'IHandler')) {
 			if (validate_csrf($csrf_token) || $handler->csrf_ignore($method)) {
 				if ($handler->before($method)) {
 					if ($method && method_exists($handler, $method)) {

+ 1 - 1
classes/handler.php

@@ -1,5 +1,5 @@
 <?php
-class Handler {
+class Handler implements IHandler {
 	protected $link;
 	protected $args;
 

+ 7 - 0
classes/ihandler.php

@@ -0,0 +1,7 @@
+<?php
+interface IHandler {
+	function csrf_ignore($method);
+	function before($method);
+	function after();
+}
+?>

+ 30 - 1
classes/pluginhost.php

@@ -3,6 +3,7 @@ class PluginHost {
 	private $link;
 	private $hooks = array();
 	private $plugins = array();
+	private $handlers = array();
 
 	const HOOK_ARTICLE_BUTTON = 1;
 	const HOOK_ARTICLE_FILTER = 2;
@@ -62,7 +63,7 @@ class PluginHost {
 
 		foreach ($plugins as $class) {
 			$class = trim($class);
-			$class_file = str_replace("_", "/", strtolower(basename($class)));
+			$class_file = strtolower(basename($class));
 			$file = dirname(__FILE__)."/../plugins/$class_file/$class_file.php";
 
 			if (file_exists($file)) require_once $file;
@@ -75,5 +76,33 @@ class PluginHost {
 		}
 	}
 
+	function add_handler($handler, $method, $sender) {
+		$handler = strtolower($handler);
+		$method = strtolower($method);
+
+		if (!is_array($this->handlers[$handler])) {
+			$this->handlers[$handler] = array();
+		}
+
+		$this->handlers[$handler][$method] = $sender;
+	}
+
+	function del_handler($handler, $method) {
+		$handler = strtolower($handler);
+		$method = strtolower($method);
+
+		unset($this->handlers[$handler][$method]);
+	}
+
+	function lookup_handler($handler, $method) {
+		$handler = strtolower($handler);
+		$method = strtolower($method);
+
+		if (is_array($this->handlers[$handler])) {
+			return $this->handlers[$handler][$method];
+		}
+
+		return false;
+	}
 }
 ?>

+ 4 - 0
include/functions.php

@@ -5576,4 +5576,8 @@
 		return $rc;
 	}
 
+	function implements_interface($class, $interface) {
+		return in_array($interface, class_implements($class));
+	}
+
 ?>

+ 46 - 0
plugins/example_routing/example_routing.php

@@ -0,0 +1,46 @@
+<?php
+class Example_Routing extends Plugin implements IHandler {
+
+	// Demonstrates adding a custom handler and method:
+	// backend.php?op=test&method=example
+	// and masking a system builtin public method:
+	// public.php?op=getUnread
+
+	// Plugin class must implelement IHandler interface and has
+	// a public method of same name as being registered.
+	//
+	// Any system method may be masked by plugins.
+
+	private $link;
+	private $host;
+
+	function __construct($host) {
+		$this->link = $host->get_link();
+		$this->host = $host;
+
+		$host->add_handler("test", "example", $this);
+		$host->add_handler("public", "getunread", $this);
+	}
+
+	function getunread() {
+		print rand(0,100); # yeah right
+	}
+
+	function example() {
+		print "example method called";
+	}
+
+	function csrf_ignore($method) {
+		return true;
+	}
+
+	function before($method) {
+		return true;
+	}
+
+	function after() {
+		return true;
+	}
+
+}
+?>

+ 9 - 2
public.php

@@ -40,9 +40,16 @@
 
 	$method = $_REQUEST["op"];
 
-	$handler = new Handler_Public($link, $_REQUEST);
+	global $pluginhost;
+	$override = $pluginhost->lookup_handler("public", $method);
 
-	if ($handler->before($method)) {
+	if ($override) {
+		$handler = $override;
+	} else {
+		$handler = new Handler_Public($link, $_REQUEST);
+	}
+
+	if (implements_interface($handler, "IHandler") && $handler->before($method)) {
 		if ($method && method_exists($handler, $method)) {
 			$handler->$method();
 		} else if (method_exists($handler, 'index')) {