[aur-dev] [PATCH 2/2] Added simple hook framework in preperation to solve FS#30109. Signed-off-by: Mario (xenji) Mueller <mario at xenji.com>

mario at xenji.com mario at xenji.com
Mon Sep 17 08:11:43 EDT 2012


From: "Mario (xenji) Mueller" <mario at xenji.com>

Signed-off-by: Mario (xenji) Mueller <mario at xenji.com>
---
 web/lib/acctfuncs.inc.php |   5 ++
 web/lib/aur.inc.php       |   4 ++
 web/lib/hookdef.php       | 113 ++++++++++++++++++++++++++++++++++++++++++++++
 web/lib/hooks/account.php |   4 ++
 4 files changed, 126 insertions(+)
 create mode 100644 web/lib/hookdef.php
 create mode 100644 web/lib/hooks/account.php

diff --git a/web/lib/acctfuncs.inc.php b/web/lib/acctfuncs.inc.php
index 6f7c98a..0ccd235 100644
--- a/web/lib/acctfuncs.inc.php
+++ b/web/lib/acctfuncs.inc.php
@@ -188,6 +188,11 @@ function process_account_form($UTYPE,$TYPE,$A,$U="",$T="",$S="",$E="",
 			} else {
 				# account created/modified, tell them so.
 				#
+
+                // trigger hook and pass the fully escaped array to it.
+                // see lib/hookdef.php for details.
+                trigger_hook('newAccount', $escaped);
+
 				print __("The account, %s%s%s, has been successfully created.",
 						"<b>", htmlspecialchars($U,ENT_QUOTES), "</b>");
 				print "<p>\n";
diff --git a/web/lib/aur.inc.php b/web/lib/aur.inc.php
index 6dcbb34..50c4bce 100644
--- a/web/lib/aur.inc.php
+++ b/web/lib/aur.inc.php
@@ -11,6 +11,10 @@ include_once('translator.inc.php');
 set_lang();
 
 include_once("config.inc.php");
+
+include_once("hookdef.php");
+include_once("hooks/account.php");
+
 include_once("routing.inc.php");
 include_once("version.inc.php");
 include_once("acctfuncs.inc.php");
diff --git a/web/lib/hookdef.php b/web/lib/hookdef.php
new file mode 100644
index 0000000..19d93d5
--- /dev/null
+++ b/web/lib/hookdef.php
@@ -0,0 +1,113 @@
+<?php
+/*
+ * This hook system is similar to the ones in wordpress or durpal.
+ *
+ * It is meant to be simple and effective, whithout any overengineered stuff.
+ * If you think about making it "better" by creating a OOP version with
+ * interfaces, please take a look at the rest of the system and ask yourself
+ * if this really fits in here.
+ */
+
+// LIST OF EXISTING HOOKS
+/*
+ * USE THIS PATTERN:
+ *
+ * filename.php hookname (payload1, payload2, ...)
+ *
+ * acctfuncs.inc.php newAccount (array($U, $E, $P, $salt, $R, $L, $I, $K))
+ */
+
+/**
+ * Triggers the hook by it's name and passes the given payload to the hook.
+ *
+ * The trigger does not return anything as they must be used in a fire-and-
+ * forget manner.
+ *
+ * The functions for the hooks must follow a naming convention to be triggered
+ * by this function. Keep in mind that the weight goes from 1 (lowest) to
+ * PHP_INT_MAX (highest). The higher the number the earlier it will be executed.
+ *
+ * The pattern is:
+ *
+ * <code>hook_$hookname_$weight_uniqueId</code>
+ *
+ * @example <code>
+ *          function hook_registerUser_15_SendmailOnReg($sUsername) { do something }
+ * // or
+ *          function hook_updatePackage_1_SendmailOnUpdt($sPkgName, $sUsername) {
+ *          do something
+ * }
+ * </code>
+ *
+ * @param string $sHookName The hook name to be triggered
+ * @param mixed  $mPayload  A nullable payload to pass to the hook.
+ *
+ * @return void
+ * @author  xenji <mario at xenji.com>
+ * @since   2012-09-17
+ */
+function trigger_hook($sHookName, $mPayload)
+{
+    error_log('Started ' . __FUNCTION__);
+    $aUserDefFunctions   = get_defined_functions()['user'];
+    error_log('Got defined fncs: ' . implode(', ', $aUserDefFunctions));
+
+    // We just want to process the relevant hooks, no other hooks or fnc.
+    $oFilter = new \CallbackFilterIterator(
+        new \ArrayIterator($aUserDefFunctions),
+        function ($mCurr, $iKey, $oIter) use ($sHookName)
+        {
+            // keep this with three eq. signs, it is needed!
+            if (
+                strpos($mCurr, 'hook_') !== false
+                && strpos(strtolower($mCurr), strtolower($sHookName)) !== false
+            )
+            {
+                error_log('Hookname OK: '. $sHookName . ' in ' . $mCurr);
+                return true;
+            }
+            return false;
+        });
+
+
+    $oHookQueue = new \HookQueue();
+
+    foreach ($oFilter as $sFunction)
+    {
+        // $_ => unused declaration, borrowed from scala's convention
+        list($_, $_, $iWeight, $_) = explode('_', $sFunction);
+        error_log("Inserting $sFunction into Queue with weight $iWeight");
+        $oHookQueue->insert($sFunction, (int)$iWeight);
+    }
+
+    // We just want to have the function name, not the prio
+    $oHookQueue->setExtractFlags(\SplPriorityQueue::EXTR_DATA);
+    if ($oHookQueue->count() > 0)
+    {
+        $oHookQueue->top();
+
+        foreach ($oHookQueue as $sFunction)
+        {
+            call_user_func($sFunction, $mPayload);
+        }
+    }
+}
+
+/**
+ * This is an implementation of the prio queue, which fits perfectly for our
+ * need to sort the hooks in relation to their weight.
+ *
+ * Taken from the example on php.net, because I was too lazy to type the text.
+ *
+ * @see http://php.net/manual/de/class.splpriorityqueue.php
+ * @author xenji <mario at xenji.com>
+ * @since 2012-09-17
+ */
+class HookQueue extends SplPriorityQueue
+{
+    public function compare($priority1, $priority2)
+    {
+        if ($priority1 === $priority2) return 0;
+        return $priority1 < $priority2 ? -1 : 1;
+    }
+}
diff --git a/web/lib/hooks/account.php b/web/lib/hooks/account.php
new file mode 100644
index 0000000..aea57b5
--- /dev/null
+++ b/web/lib/hooks/account.php
@@ -0,0 +1,4 @@
+<?php
+function hook_newAccount_1_SendMailForNewAccount($aAccountData) {
+    // send a mail if you want to...
+}
\ No newline at end of file
-- 
1.7.12



More information about the aur-dev mailing list