Pārlūkot izejas kodu

Add a first draft for hooks

- New Extension->registerHook($hook_name, $hook_function) method to register a new hook
- Only one hook works for the moment: entry_before_insert
- ExtensionManager::callHook will need to evolve based on future hooks

See https://github.com/FreshRSS/FreshRSS/issues/252
Marien Fressinaud 11 gadi atpakaļ
vecāks
revīzija
08546af75f

+ 9 - 2
app/Controllers/feedController.php

@@ -329,9 +329,16 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
 						$id = min(time(), $entry_date) . uSecString();
 					}
 
+					$entry->_id($id);
+					$entry->_isRead($is_read);
+
+					$entry = Minz_ExtensionManager::callHook('entry_before_insert', $entry);
+					if (is_null($entry)) {
+						// An extension has returned a null value, there is nothing to insert.
+						continue;
+					}
+
 					$values = $entry->toArray();
-					$values['id'] = $id;
-					$values['is_read'] = $is_read;
 					$entryDAO->addEntry($values, $prepared_statement);
 				}
 			}

+ 10 - 0
lib/Minz/Extension.php

@@ -153,4 +153,14 @@ class Minz_Extension {
 	public function registerViews() {
 		Minz_View::addBasePathname($this->path);
 	}
+
+	/**
+	 * Register a new hook.
+	 *
+	 * @param $hook_name the hook name (must exist).
+	 * @param $hook_function the function name to call (must be callable).
+	 */
+	public function registerHook($hook_name, $hook_function) {
+		Minz_ExtensionManager::addHook($hook_name, $hook_function, $this);
+	}
 }

+ 55 - 0
lib/Minz/ExtensionManager.php

@@ -2,6 +2,8 @@
 
 /**
  * An extension manager to load extensions present in EXTENSIONS_PATH.
+ *
+ * @todo see coding style for methods!!
  */
 class Minz_ExtensionManager {
 	private static $ext_metaname = 'metadata.json';
@@ -11,6 +13,11 @@ class Minz_ExtensionManager {
 
 	private static $ext_auto_enabled = array();
 
+	private static $hook_list = array(
+		'entry_before_insert' => array(),  // function($entry)
+	);
+	private static $ext_to_hooks = array();
+
 	/**
 	 * Initialize the extension manager by loading extensions in EXTENSIONS_PATH.
 	 *
@@ -131,6 +138,8 @@ class Minz_ExtensionManager {
 				in_array($name, self::$ext_auto_enabled)) {
 			self::enable($ext->getName());
 		}
+
+		self::$ext_to_hooks[$name] = array();
 	}
 
 	/**
@@ -187,4 +196,50 @@ class Minz_ExtensionManager {
 
 		return self::$ext_list[$ext_name];
 	}
+
+	/**
+	 * Add a hook function to a given hook.
+	 *
+	 * The hook name must be a valid one. For the valid list, see self::$hook_list
+	 * array keys.
+	 *
+	 * @param $hook_name the hook name (must exist).
+	 * @param $hook_function the function name to call (must be callable).
+	 * @param $ext the extension which register the hook.
+	 */
+	public static function addHook($hook_name, $hook_function, $ext) {
+		if (isset(self::$hook_list[$hook_name]) && is_callable($hook_function)) {
+			self::$hook_list[$hook_name][] = $hook_function;
+			self::$ext_to_hooks[$ext->getName()][] = $hook_name;
+		}
+	}
+
+	/**
+	 * Call functions related to a given hook.
+	 *
+	 * The hook name must be a valid one. For the valid list, see self::$hook_list
+	 * array keys.
+	 *
+	 * @param $hook_name the hook to call.
+	 * @param additionnal parameters (for signature, please see self::$hook_list comments)
+	 * @todo hook functions will have different signatures. So the $res = func($args);
+	 *       $args = $res; will not work for all of them in the future. We must
+	 *       find a better way to call hooks.
+	 */
+	public static function callHook($hook_name) {
+		$args = func_get_args();
+		unset($args[0]);
+
+		$result = $args;
+		foreach (self::$hook_list[$hook_name] as $function) {
+			$result = call_user_func_array($function, $args);
+
+			if (is_null($result)) {
+				break;
+			}
+
+			$args = $result;
+		}
+		return $result;
+	}
 }