Thời gian hợp lệ của việc sử dụng current_user_can () và các hàm liên quan là gì?


10

Trong quá trình tải lõi WP của vanilla, người dùng hiện tại đang được thiết lập $wp-init(), sau khi tải chủ đề và trước khi initmóc. Điều này phù hợp với thực tiễn tốt về chức năng được nối đến inithoặc sau này.

Tuy nhiên, đó cũng là thông lệ để gọi các chức năng liên quan, chẳng hạn như current_user_can() sớm hơn thế. Đó là theo định nghĩa cần thiết cho các plugin hoạt động với các giai đoạn trước của quá trình tải (plugin Thanh công cụ chuyển đổi chủ đề của tôi sẽ là một ví dụ).

Tài liệu làm cho không có yêu cầu cho hoặc chống lại thực tiễn này (mà tôi có thể tìm thấy).

Tuy nhiên, một số plugin dường như liên kết với chức năng liên quan đến người dùng và mong đợi inittrạng thái bài đăng của mọi lúc.

Ví dụ: bbPress ném thông báo sau:

// 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' );
}

Để trình diễn nhanh, hãy đưa điều này vào định nghĩa cốt lõi của current_user_can():

function current_user_can( $capability ) {

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

Ai là người quyền lực trong tình huống này? Có một quyết định chính tắc nào về việc sử dụng được phép / cấm sử dụng các chức năng liên quan đến người dùng trước đây initkhông?


Câu trả lời:


7

Điều kiện tiên quyết duy nhất current_user_can()là có sẵn wp_get_current_user(). Cái sau được định nghĩa trong pluggable.php, vì vậy bạn có thể sử dụng nó sau plugins_loaded.

Cuộc _doing_it_wrong()gọi bạn đang trích dẫn trong câu hỏi của bạn là sai cho chính nó. Tôi đoán là bạn đã lấy nó từ BuddyPress hoặc bbPress. Cả hai đang chạy vào một đệ quy nếu họ không chờ đợi lâu. Có những cách khác, tốt hơn để ngăn chặn sự đệ quy.

Trong một số trường hợp, như thay đổi ngôn ngữ , bạn phải truy cập đối tượng người dùng hiện tại sớm hơn, vì vậy chờ đợi after_setup_themethậm chí không phải là một tùy chọn.



2

Nếu bạn kiểm tra khả năng sử dụng trước khi initphương tiện có khả năng đang bạn là người chịu trách nhiệm cho việc thiết lập các đối tượng người dùng hiện tại.

Nếu bạn truy cập người dùng sau init đó, thì bạn chắc chắn rằng một cái gì đó khác đã thiết lập người dùng, hầu hết các lần cốt lõi.

Đây là lý do tại sao truy cập người dùng sau initđược coi là an toàn .

Trong thực tế, truy cập sớm có thể có thể phá vỡ một số bộ lọc đang chạy determine_current_user.

Điều đáng nói là một cái móc "dễ vỡ", bởi vì có nhiều khả năng nó không bao giờ chạy, chỉ bị sa thải trong các chức năng có thể cắm được.

Tuy nhiên, có những trường hợp (như @toscho đã nói) mà bạn không thể đợi cho đến khi init, trong những trường hợp đó bạn không có lựa chọn nào khác.

Chỉ có cách để giải quyết bất kỳ sự không tương thích là tùy từng trường hợp, nếu bạn có ý chí.

Một giải pháp có thể hoạt động trong hầu hết các trường hợp (bao gồm cả bbPress / BuddyPress) là sử dụng chức năng sau thay vì 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 );
}

Điều này cho phép kiểm tra khả năng người dùng hiện tại sớm mà không cần thiết lập người dùng toàn cầu, vì vậy về lý thuyết an toàn sẽ được chạy trước đó init.

Vấn đề là, như đã nói ở trên, bất kỳ mã nào ghi đè các hàm có thể cắm và không kích hoạt determine_current_usersẽ phá vỡ nó.


Tôi nghĩ rằng chức năng của bạn có các biến tad lộn xộn. :)
Rarst

Có ... gõ quá nhanh trước bữa tối: P cảm ơn @ialocin đã sửa.
gmazzap

Đừng đề cập đến nó. Bên cạnh đó, đừng nói điều gì sai, hãy sửa nó @Rarst :)
Nicolai

1

Tôi có xu hướng nghĩ rằng BuddyPress và bbPress nên kiểm tra cái gì đó khác trước khi đưa ra _doing_it_wrongthông báo

Tôi đã thay đổi cả hai thói quen để kiểm tra cài đặt thực tế của $ current_user.

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

Các thông báo không còn được hiển thị.

Các thử nghiệm để did_action( "after_setup_theme" )trở thành niềng răng đi với vành đai.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.