使用current_user_can()和相关函数的有效时间是几点?


10

在香草WP核心加载期间,正在设置当前用户,该用户$wp-init()在主题加载之后,init挂机之前。这与功能挂钩init或以后使用的良好做法是一致的。

但是,调用相关功能(例如current_user_can() 早于此)也是一种常见的做法。从定义上讲,这是与加载过程的早期阶段兼容的插件所必需的(我的Toolbar Theme Switcher插件就是一个示例)。

文档没有主张或反对这种做法(我可以找到)。

但是,某些插件似乎可以与用户相关的功能挂起,并init始终期望后置状态。

例如,bbPress引发以下通知:

// If the current user is being setup before the "init" action has fired,
// strange (and difficult to debug) role/capability issues will occur.
if ( ! did_action( 'after_setup_theme' ) ) {
    _doing_it_wrong( __FUNCTION__, __( 'The current user is being initialized without using $wp->init().', 'bbpress' ), '2.3' );
}

为了快速演示,将其放入core的定义中current_user_can()

function current_user_can( $capability ) {

    if ( ! did_action('after_setup_theme') ) {
        echo wp_debug_backtrace_summary();
    }

在这种情况下谁是“正确的”?之前是否存在关于允许/禁止使用用户相关功能的规范决定init


Answers:


7

唯一的先决条件current_user_can()是存在wp_get_current_user()。后者是在中定义的pluggable.php,因此您可以在之后使用它plugins_loaded

_doing_it_wrong()您在问题中引用的电话本身是错误的。我的猜测是您是从BuddyPress或bbPress那里获得的。如果不等那么久,两者都将递归。还有其他更好的方法可以防止递归。

在某些情况下,例如更改语言环境,您必须更早地访问当前用户对象,因此after_setup_theme甚至无法选择等待。



2

如果您之前检查过用户功能,init则可能由负责当前用户对象的设置。

如果访问用户 init,那么你一定是别的东西已经建立的用户,大部分的时间核心本身。

这就是为什么以后访问用户init被认为是安全的原因

实际上,抢先访问可能会破坏上运行的某些过滤器determine_current_user

值得一提的是,这是一个“脆弱”的钩子,因为它有可能永远不会运行,仅在可插拔函数中被触发。

然而,在一些情况(如@toscho说的),你不能等到初始化,在这些情况下,你别无选择。

解决所有不兼容的唯一方法是视情况而定。

在大多数情况下(包括bbPress / BuddyPress)可能有效的解决方案是使用以下功能代替current_user_can

function compat_current_user_can( $capability )
{
  if ( did_action( 'init' ) ) {
     return current_user_can( $capability );
  }

  $user_id = apply_filters( 'determine_current_user', false );

  return user_can( $user_id, $capability );
}

这允许在不设置全局用户的情况下及早检查当前用户的能力,因此从理论上讲,可以安全地在之前运行init

问题是,如上所述,任何覆盖可插拔功能而不触发的代码都会determine_current_user破坏它。


我认为您的函数的变量有些混乱。:)
拉斯特

是的...晚饭前打得太快了:P感谢@ialocin修复问题。
gmazzap

别说了 除了不只是说出问题是什么,还可以修复@Rarst :)
Nicolai

1

我倾向于认为BuddyPress和bbPress应该在发布_doing_it_wrong消息之前检查其他内容

我更改了两个例程,还检查了$ current_user的实际设置。

global $current_user; 
if ( is_null( $current_user ) ) {
    _doing_it_wrong( ... );
}

通知不再显示。

测试did_action( "after_setup_theme" )成为皮带的支撑。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.