昊天SEO

WordPress 初始化核心文件 plugin.php 源码分析

plugin.php 文件位于 wp-includes 目录之下,定义插件 API,无执行代码,主要用于创建动作、过滤、挂载函数等,其部分核心函数如下:

  1. function add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) {
  2.     global $wp_filter, $merged_filters;
  3.     $idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority);
  4.     $wp_filter[$tag][$priority][$idx] = array(‘function’ => $function_to_add, ‘accepted_args’ => $accepted_args);
  5.     unset( $merged_filters[ $tag ] );
  6.     return true;
  7. }

给特定的过滤器(也称挂载点)添加钩子函数(也称挂载函数)或方法;使用这个API可以将一个回调函数绑定(挂载)到过滤器(挂载点)上,插件也可 以使用该函数指定特定的文本添加一个或多个处理函数,以达到过滤或修改文本的目的;该函数并不检查函数或过滤器的存在性,这样有利于性能优化;该函数主要借助于全局变量 $wp_filter 和 $merged_filters;它的第三个可选参数指定多回调函数的过滤顺序,第四个可选参数指定回调函数接收的参数个数;关于过滤钩子详细源码分析及其原理 WordPress 过滤钩子函数 add_filter()、apply_filters() 源码解析

  1. function has_filter($tag, $function_to_check = false) {
  2.     // Don’t reset the internal array pointer
  3.     $wp_filter = $GLOBALS[‘wp_filter’];
  4.  
  5.     $has = ! empty( $wp_filter[ $tag ] );
  6.  
  7.     // Make sure at least one priority has a filter callback
  8.     if ( $has ) {
  9.         $exists = false;
  10.         foreach ( $wp_filter[ $tag ] as $callbacks ) {
  11.             if ( ! empty( $callbacks ) ) {
  12.                 $exists = true;
  13.                 break;
  14.             }
  15.         }
  16.  
  17.         if ( ! $exists ) {
  18.             $has = false;
  19.         }
  20.     }
  21.  
  22.     if ( false === $function_to_check || false === $has )
  23.         return $has;
  24.  
  25.     if ( !$idx = _wp_filter_build_unique_id($tag, $function_to_check, false) )
  26.         return false;
  27.  
  28.     foreach ( (array) array_keys($wp_filter[$tag]) as $priority ) {
  29.         if ( isset($wp_filter[$tag][$priority][$idx]) )
  30.             return $priority;
  31.     }
  32.  
  33.     return false;
  34. }

检查过滤器钩子(挂载点)上是否被挂载函数;

  1. function apply_filters( $tag, $value ) {
  2.     global $wp_filter, $merged_filters, $wp_current_filter;
  3.  
  4.     $args = array();
  5.  
  6.     // Do ‘all’ actions first.
  7.     if ( isset($wp_filter[‘all’]) ) {
  8.         $wp_current_filter[] = $tag;
  9.         $args = func_get_args();
  10.         _wp_call_all_hook($args);
  11.     }
  12.  
  13.     if ( !isset($wp_filter[$tag]) ) {
  14.         if ( isset($wp_filter[‘all’]) )
  15.             array_pop($wp_current_filter);
  16.         return $value;
  17.     }
  18.  
  19.     if ( !isset($wp_filter[‘all’]) )
  20.         $wp_current_filter[] = $tag;
  21.  
  22.     // Sort.
  23.     if ( !isset( $merged_filters[ $tag ] ) ) {
  24.         ksort($wp_filter[$tag]);
  25.         $merged_filters[ $tag ] = true;
  26.     }
  27.  
  28.     reset( $wp_filter[ $tag ] );
  29.  
  30.     if ( empty($args) )
  31.         $args = func_get_args();
  32.  
  33.     do {
  34.         foreach ( (array) current($wp_filter[$tag]) as $the_ )
  35.             if ( !is_null($the_[‘function’]) ){
  36.                 $args[1] = $value;
  37.                 $value = call_user_func_array($the_[‘function’], array_slice($args, 1, (int) $the_[‘accepted_args’]));
  38.             }
  39.  
  40.     } while ( next($wp_filter[$tag]) !== false );
  41.  
  42.     array_pop( $wp_current_filter );
  43.  
  44.     return $value;
  45. }

调用挂载在过滤钩子上的所有函数并返回被处理过的值,若无挂载函数则返回值本身;它也可以被用来创建一个新的过滤钩子,只需要 $tag 参数为一个新的过滤钩子,然后调用这个函数即可;它所记忆的挂载函数源于全局变量 $wp_filter、$merged_filters 和 $wp_current_filter;

  1. function apply_filters_ref_array($tag, $args)

该函数类似于 apply_filters(),不同之处在于它的参数是一个数组;

  1. function remove_filter( $tag, $function_to_remove, $priority = 10 )

删除指定过滤钩子上挂载的指定函数,常用于去除过滤钩上的默认挂载函数;它也是借助于全局变量 $wp_filter 将指定函数从变量中去除;

  1. function remove_all_filters( $tag, $priority = false )

将过滤器上所有挂载函数删除;

  1. function current_filter() {
  2.     global $wp_current_filter;
  3.     return end( $wp_current_filter );
  4. }

检索当前过滤器或动作的名称并以 return 方式返回;

  1. function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
  2.     return add_filter($tag, $function_to_add, $priority, $accepted_args);
  3. }

将函数挂载到一个特定的动作钩子(挂载点)上,它核心代码是使用的 add_filters() 函数,所以它与 add_filters() 函数基本一 样(也是增加全局变量$wp_filter数组中一个元素),只不过是为了在概念上帮助我们区别过滤器和动作;关于动作钩子详细源码分析及其原理见 WordPress 动作钩子函数 add_action()、do_action() 源码解析。

  1. function do_action($tag, $arg = ) {
  2.     global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;
  3.     if ( ! isset($wp_actions[$tag]) )
  4.         $wp_actions[$tag] = 1;
  5.     else
  6.         ++$wp_actions[$tag];
  7.     if ( isset($wp_filter[‘all’]) ) {
  8.         $wp_current_filter[] = $tag;
  9.         $all_args = func_get_args();
  10.         _wp_call_all_hook($all_args);
  11.     }
  12.     if ( !isset($wp_filter[$tag]) ) {
  13.         if ( isset($wp_filter[‘all’]) )
  14.             array_pop($wp_current_filter);
  15.         return;
  16.     }
  17.     if ( !isset($wp_filter[‘all’]) )
  18.         $wp_current_filter[] = $tag;
  19.     $args = array();
  20.     if ( is_array($arg) && 1 == count($arg) && isset($arg[0]) && is_object($arg[0]) ) // array(&$this)
  21.         $args[] =& $arg[0];
  22.     else
  23.         $args[] = $arg;
  24.     for ( $a = 2, $num = func_num_args(); $a < $num; $a++ )
  25.         $args[] = func_get_arg($a);
  26.     if ( !isset( $merged_filters[ $tag ] ) ) {
  27.         ksort($wp_filter[$tag]);
  28.         $merged_filters[ $tag ] = true;
  29.     }
  30.     reset( $wp_filter[ $tag ] );
  31.     do {
  32.         foreach ( (array) current($wp_filter[$tag]) as $the_ )
  33.             if ( !is_null($the_[‘function’]) )
  34.                 call_user_func_array($the_[‘function’], array_slice($args, 0, (int) $the_[‘accepted_args’]));
  35.  
  36.     } while ( next($wp_filter[$tag]) !== false );
  37.     array_pop($wp_current_filter);
  38. }

调用执行挂载在动作钩子上的所有函数,也可以使用该函数新增一个动作钩子;它与 apply_filters() 函数基本相同(代码变量、逻辑、所用函数等均一致),不同之处在于该函数并不返回值,仅仅执行一个函数或方法;

  1. function did_action($tag) {
  2.     global $wp_actions;
  3.     if ( ! isset( $wp_actions[ $tag ] ) )
  4.         return 0;
  5.     return $wp_actions[$tag];
  6. }

获取动作已执行的次数,原理是 do_action() 函数中 $wp_actions[$tag] 变量相关代码,每次执行该变量会记录执行次数;

  1. function do_action_ref_array($tag, $args){}

该函数类似于do_action(),不同之处在于它的参数是一个数组;

  1. function has_action($tag, $function_to_check = false) {
  2.     return has_filter($tag, $function_to_check);
  3. }

检测动作钩子上是否挂载有函数,核心代码是 has_filter(),所以它相当于一个别名;

  1. function remove_action( $tag, $function_to_remove, $priority = 10 ) {
  2.     return remove_filter( $tag, $function_to_remove, $priority );
  3. }

移除指定动作钩子上的函数,核心代码是 remove_filter(),相当于一个别名;

  1. function remove_all_actions($tag, $priority = false) {
  2.     return remove_all_filters($tag, $priority);
  3. }

将动作钩子上所有函数移除,核心代码是 remove_all_filters(),相当于一个别名;

  1. function plugin_basename( $file ) {
  2.     global $wp_plugin_paths;
  3.     foreach ( $wp_plugin_paths as $dir => $realdir ) {
  4.         if ( strpos( $file, $realdir ) === 0 ) {
  5.             $file = $dir . substr( $file, strlen( $realdir ) );
  6.         }
  7.     }
  8.     $file = wp_normalize_path( $file );
  9.     $plugin_dir = wp_normalize_path( WP_PLUGIN_DIR );
  10.     $mu_plugin_dir = wp_normalize_path( WPMU_PLUGIN_DIR );
  11.     $file = preg_replace(‘#^’ . preg_quote($plugin_dir, ‘#’) . ‘/|^’ . preg_quote($mu_plugin_dir, ‘#’) . ‘/#’,,$file); // get relative path from plugins dir
  12.     $file = trim($file, ‘/’);
  13.     return $file;
  14. }

根据插件目录返回文件在 plugins 目录后的路径;

  1. function plugin_dir_path( $file ) {
  2.     return trailingslashit( dirname( $file ) );
  3. }

其核心代码是借助 PHP 函数 dirname(),用于返回路径中的目录部分(不包括文件名部分),参数 $file 为文件的__file__(PHP 常量,返回当前文件路径);

  1. function plugin_dir_url( $file ) {
  2.     return trailingslashit( plugins_url( , $file ) );
  3. }

核心代码是 plugins_url(),用于返回文件的完整 URL(注意跟路径不同,路径是针对服务器文件 系统而言,URL 是跟域名相当的),如:http://www.wpmomo.com/wp-content/plugins/hello-dolly/hello.php;

  1. function register_activation_hook($file, $function) {
  2.     $file = plugin_basename($file);
  3.     add_action(‘activate_’ . $file, $function);
  4. }

为插件设置激活钩子,钩子名格式为 activate_ 后跟 plugin_basename($file);

  1. function register_deactivation_hook($file, $function) {
  2.     $file = plugin_basename($file);
  3.     add_action(‘deactivate_’ . $file, $function);
  4. }

为插件设置失效钩子,钩子名格式为 deactivate_ 后跟 plugin_basename($file);

  1. function register_uninstall_hook( $file, $callback ){}

为插件设置卸载钩子。

本文地址官网    新乡网站建设,seo

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址