From d3c6121c5bbbda715446fdf5e4f9361222772c3e Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 12 Nov 2008 18:06:14 +0000 Subject: [PATCH] Roll back r43377, r43379 "Factored wfInvokeFancyCallback() out of wfRunHooks(). Allows flexible dynamic invocation to be used in other contexts." / "Renamed the new wfInvokeFancyCallback to simply wfInvoke." Breaks existing hooks including core language converters: Notice: Undefined variable: event in /Library/WebServer/Documents/trunk/includes/Hooks.php on line 61 Warning: call_user_func_array(): First argument is expected to be a valid callback, 'ZhConverter::on' was given in /Library/WebServer/Documents/trunk/includes/Hooks.php on line 119 Notice: Undefined variable: args in /Library/WebServer/Documents/trunk/includes/Hooks.php on line 80 Notice: Undefined variable: event in /Library/WebServer/Documents/trunk/includes/Hooks.php on line 61 Detected bug in an extension! Hook ZhConverter::on failed to return a value; should return true to continue hook processing or false to abort. Backtrace: #0 /Library/WebServer/Documents/trunk/includes/Article.php(1684): wfRunHooks('ArticleSaveComp...', Array) #1 /Library/WebServer/Documents/trunk/includes/Article.php(1354): Article->doEdit('Article for spe...', '', 97) #2 /Library/WebServer/Documents/trunk/maintenance/parserTests.inc(998): Article->insertNewArticle('Article for spe...', '', false, false) #3 /Library/WebServer/Documents/trunk/maintenance/parserTests.inc(307): ParserTest->addArticle('Xyzzyx', 'Article for spe...', 5168) #4 /Library/WebServer/Documents/trunk/maintenance/parserTests.inc(273): ParserTest->runFile('/Library/WebSer...') #5 /Library/WebServer/Documents/trunk/maintenance/parserTests.php(73): ParserTest->runTestsFromFiles(Array) #6 {main} --- includes/Hooks.php | 179 ++++++++++++++++++++------------------------- 1 file changed, 78 insertions(+), 101 deletions(-) diff --git a/includes/Hooks.php b/includes/Hooks.php index e4404b0a73..046a149da8 100644 --- a/includes/Hooks.php +++ b/includes/Hooks.php @@ -22,105 +22,6 @@ * @file */ -/* Private */ -function _wfInvokeInternalGoop($hook) { - $object = NULL; - $method = NULL; - $func = NULL; - $data = NULL; - $have_data = false; - - if (is_array($hook)) { - if (count($hook) < 1) { - throw new MWException("Empty array in hooks for " . $event . "\n"); - } else if (is_object($hook[0])) { - $object = $hook[0]; - if (count($hook) < 2) { - $method = "on" . $event; - } else { - $method = $hook[1]; - if (count($hook) > 2) { - $data = $hook[2]; - $have_data = true; - } - } - } else if (is_string($hook[0])) { - $func = $hook[0]; - if (count($hook) > 1) { - $data = $hook[1]; - $have_data = true; - } - } else { - var_dump( $wgHooks ); - throw new MWException("Unknown datatype in hooks for " . $event . "\n"); - } - } else if (is_string($hook)) { # functions look like strings, too - $func = $hook; - } else if (is_object($hook)) { - $object = $hook; - $method = "on" . $event; - } else { - throw new MWException("Unknown datatype in hooks for " . $event . "\n"); - } - - if ( isset( $object ) ) { - $func = get_class( $object ) . '::' . $method; - $callback = array( $object, $method ); - } elseif ( false !== ( $pos = strpos( $func, '::' ) ) ) { - $callback = array( substr( $func, 0, $pos ), substr( $func, $pos + 2 ) ); - } else { - $callback = $func; - } - - return array($callback, $func, $data); -} - -/* Return a string describing the hook for debugging purposes. */ -function wfFormatInvocation($hook) { - list($callback, $func, $data) = _wfInvokeInternalGoop($hook, $args); - - if( is_array( $callback ) ) { - if( is_object( $callback[0] ) ) { - $prettyClass = get_class( $callback[0] ); - } else { - $prettyClass = strval( $callback[0] ); - } - $prettyFunc = $prettyClass . '::' . strval( $callback[1] ); - } else { - $prettyFunc = strval( $callback ); - } - return $prettyFunc; -} - - -/* - * Invoke a function dynamically. - * $hook can be: a function, an object, an array of $function and $data, - * an array of just a function, an array of object and method, or an - * array of object, method, and data. - * If arguments are provided both as part of the hook itself, and when - * calling wfCallFancyCallback, the two arrays are merged. - */ -function wfInvoke($hook, $args = array()) { - list($callback, $func, $data) = _wfInvokeInternalGoop($hook, $args); - - /* We put the first data element on, if needed. */ - if ($data) { - $hook_args = array_merge(array($data), $args); - } else { - $hook_args = $args; - } - - // Run autoloader (workaround for call_user_func_array bug) - is_callable( $callback ); - - /* Call the hook. */ - wfProfileIn( $func ); - $retval = call_user_func_array( $callback, $hook_args ); - wfProfileOut( $func ); - return $retval; -} - /** * Because programmers assign to $wgHooks, we need to be very @@ -147,7 +48,74 @@ function wfRunHooks($event, $args = array()) { foreach ($wgHooks[$event] as $index => $hook) { - $retval = wfInvoke($hook, $args); + $object = NULL; + $method = NULL; + $func = NULL; + $data = NULL; + $have_data = false; + + /* $hook can be: a function, an object, an array of $function and $data, + * an array of just a function, an array of object and method, or an + * array of object, method, and data. + */ + + if (is_array($hook)) { + if (count($hook) < 1) { + throw new MWException("Empty array in hooks for " . $event . "\n"); + } else if (is_object($hook[0])) { + $object = $wgHooks[$event][$index][0]; + if (count($hook) < 2) { + $method = "on" . $event; + } else { + $method = $hook[1]; + if (count($hook) > 2) { + $data = $hook[2]; + $have_data = true; + } + } + } else if (is_string($hook[0])) { + $func = $hook[0]; + if (count($hook) > 1) { + $data = $hook[1]; + $have_data = true; + } + } else { + var_dump( $wgHooks ); + throw new MWException("Unknown datatype in hooks for " . $event . "\n"); + } + } else if (is_string($hook)) { # functions look like strings, too + $func = $hook; + } else if (is_object($hook)) { + $object = $wgHooks[$event][$index]; + $method = "on" . $event; + } else { + throw new MWException("Unknown datatype in hooks for " . $event . "\n"); + } + + /* We put the first data element on, if needed. */ + + if ($have_data) { + $hook_args = array_merge(array($data), $args); + } else { + $hook_args = $args; + } + + if ( isset( $object ) ) { + $func = get_class( $object ) . '::' . $method; + $callback = array( $object, $method ); + } elseif ( false !== ( $pos = strpos( $func, '::' ) ) ) { + $callback = array( substr( $func, 0, $pos ), substr( $func, $pos + 2 ) ); + } else { + $callback = $func; + } + + // Run autoloader (workaround for call_user_func_array bug) + is_callable( $callback ); + + /* Call the hook. */ + wfProfileIn( $func ); + $retval = call_user_func_array( $callback, $hook_args ); + wfProfileOut( $func ); /* String return is an error; false return means stop processing. */ @@ -156,7 +124,16 @@ function wfRunHooks($event, $args = array()) { $wgOut->showFatalError($retval); return false; } elseif( $retval === null ) { - $prettyFunc = wfFormatInvocation($hook); + if( is_array( $callback ) ) { + if( is_object( $callback[0] ) ) { + $prettyClass = get_class( $callback[0] ); + } else { + $prettyClass = strval( $callback[0] ); + } + $prettyFunc = $prettyClass . '::' . strval( $callback[1] ); + } else { + $prettyFunc = strval( $callback ); + } throw new MWException( "Detected bug in an extension! " . "Hook $prettyFunc failed to return a value; " . "should return true to continue hook processing or false to abort." ); -- 2.20.1