Які дійсні терміни використання current_user_can () та пов'язаних з ними функцій?


10

Під час завантаження ядра ванільної WP встановлюється поточний користувач, $wp-init()який знаходиться після завантаження теми та перед initгаком. Це узгоджується з хорошою практикою функціонування, яка підключається initчи пізніше.

Однак також звичайна практика викликати пов'язані функції, такі як current_user_can() раніше . Це за визначенням, необхідне для плагінів, які працюють з більш ранніми етапами процесу завантаження (приклад мій плагін Перемикача теми буде прикладом).

Документація не пред'являє жодних претензій щодо або проти цієї практики (що я міг знайти).

Однак деякі плагіни, схоже, підключаються до функціональних можливостей користувачів, і очікують, що пост буде 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' );
}

Для швидкої демонстрації вкажіть це у основні визначення current_user_can():

function current_user_can( $capability ) {

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

Хто в цій ситуації "правильний"? Чи є канонічне визначення раніше дозволеного / забороненого використання функцій, пов'язаних з користувачем init?


Відповіді:


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" )предмет стає брекетами, щоб йти з поясом.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.