PHP中插件机制实现:mediawiki的钩子机制(fxs_2008) 收藏
2010年02月19日


mediawiki的扩展机制很多,钩子就是其中之一。不过,其钩子机制是通过函数来实现的。

简单地说,钩子机制通过三个方面来实现:

1、注册钩子;
2、放置钩子(事件:event handle);
3、运行钩子;

闲话少说,看体看一下:
一、注册钩子

 如:ArticleDelete


*Define function:    

function fnMyHook( &$article, &$user, &$reason, &$error ) { ... }

*Attach hook:    

$wgHooks['ArticleDelete'][] = 'fnMyHook';


二、钩子句柄
  

      wfRunHooks($event$args = array()) 

这里面就是wfRunHooks('ArticleDelete');放在在适当的位置



三、钩子的运行

/**
 * Because programmers assign to $wgHooks, we need to be very
 * careful about its contents. So, there's a lot more error-checking
 * in here than would normally be necessary.
 */
function wfRunHooks($event$args = array()) {

    global 
$wgHooks;

    
// Return quickly in the most common case
    
if ( !isset( $wgHooks[$event] ) ) {
        return 
true;
    }

    if (!
is_array($wgHooks)) {
        throw new 
MWException("Global hooks array is not an array!\n");
        return 
false;
    }

    if (!
is_array($wgHooks[$event])) {
        throw new 
MWException("Hooks array for event '$event' is not an array!\n");
        return 
false;
    }

    foreach (
$wgHooks[$event] as $index => $hook) {

        
$object null;
        
$method null;
        
$func null;
        
$data null;
        
$have_data false;
        
$closure 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 ) < ) {
                throw new 
MWException("Empty array in hooks for " $event "\n");
            } else if ( 
is_object$hook[0] ) ) {
                
$object $wgHooks[$event][$index][0];
                if ( 
$object instanceof Closure ) {
                    
$closure true;
                    if ( 
count$hook ) > ) {
                        
$data $hook[1];
                        
$have_data true;
                    }
                } else {
                    if ( 
count$hook ) < ) {
                        
$method "on" $event;
                    } else {
                        
$method $hook[1];
                        if ( 
count$hook ) > ) {
                            
$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 {
                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];
            if ( 
$object instanceof Closure ) {
                
$closure true;
            } else {
                
$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 ( 
$closure ) {
            
$callback $object;
            
$func "hook-$event-closure";
        } elseif ( isset( 
$object ) ) {
            
$func get_class$object ) . '::' $method;
            
$callback = array( $object$method );
        } elseif ( 
false !== ( $pos strpos$func'::' ) ) ) {
            
$callback = array( substr$func0$pos ), substr$func$pos ) );
        } 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. */

        
if ( is_string$retval ) ) {
            global 
$wgOut;
            
$wgOut->showFatalError$retval );
            return 
false;
        } elseif( 
$retval === null ) {
            if ( 
$closure ) {
                
$prettyFunc "$event closure";
            } elseif( 
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." );
        } else if ( !
$retval ) {
            return 
false;
        }
    }

    return 
true;
}



就这三下,简单不!注意,其中重要的一个函数,
call_user_func_array();   //php函数

   主要是这个函数起作用。

 

本文永久链接: http://www.zzxj.net/blog/fxs_2008/archive/2010/02/19/117.html

发表于 @ 2010年02月19日 |评论(loading... )|收藏

发表评论 姓  名: