Was ist der gültige Zeitpunkt für die Verwendung von current_user_can () und verwandten Funktionen?


10

Während des Vanilla WP Core Loads wird der aktuelle Benutzer eingerichtet, $wp-init()der sich nach dem Laden des Themas und vor dem initHook befindet. Dies steht im Einklang mit der guten Praxis, dass Funktionen an initoder später angeschlossen werden.

Es ist jedoch auch üblich, verwandte Funktionen aufzurufen, beispielsweise current_user_can() früher . Es ist per Definition für Plugins erforderlich, die mit früheren Phasen des Ladevorgangs arbeiten (mein Toolbar Theme Switcher-Plugin wäre ein Beispiel).

Die Dokumentation erhebt keine Ansprüche für oder gegen diese Praxis (die ich finden konnte).

Einige Plugins scheinen sich jedoch in benutzerbezogene Funktionen einzubinden und erwarten initjederzeit den Post- Status.

Zum Beispiel wirft bbPress folgenden Hinweis:

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

Zur schnellen Demonstration werfen Sie dies in die Kerndefinition von current_user_can():

function current_user_can( $capability ) {

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

Wer ist in dieser Situation „richtig“? Gibt es eine kanonische Bestimmung über die erlaubte / verbotene Nutzung benutzerbezogener Funktionen vor init?


Antworten:


7

Einzige Voraussetzung dafür current_user_can()ist eine bestehende wp_get_current_user(). Letzteres ist in definiert pluggable.php, sodass Sie es später verwenden können plugins_loaded.

Der _doing_it_wrong()Anruf, den Sie in Ihrer Frage zitieren, ist für sich selbst falsch. Ich vermute, dass Sie das von BuddyPress oder bbPress genommen haben. Beide geraten in eine Rekursion, wenn sie nicht so lange warten. Es gibt andere, bessere Möglichkeiten, um die Rekursion zu verhindern.

In einigen Fällen, z. B. beim Ändern des Gebietsschemas , müssen Sie früher auf das aktuelle Benutzerobjekt zugreifen, sodass das Warten after_setup_themenicht einmal eine Option ist.



2

Wenn Sie die Benutzerfähigkeit vorher überprüfen, besteht die Möglichkeit init, dass Sie für die Einstellung des aktuellen Benutzerobjekts verantwortlich sind.

Wenn Sie nachher auf den Benutzer zugreifen init, sind Sie sicher, dass der Benutzer bereits durch etwas anderes eingerichtet wurde , meistens selbst als Kern.

Aus diesem Grund wird der Zugriff auf den Benutzer nach initals sicher angesehen .

Tatsächlich kann ein früher Zugriff möglicherweise einen Filter beschädigen, auf dem läuft determine_current_user.

Es ist erwähnenswert, dass man ein "zerbrechlicher" Haken ist, denn es besteht die Möglichkeit, dass er niemals ausgeführt wird und nur in steckbaren Funktionen ausgelöst wird.

Es gibt jedoch Fälle (wie @toscho sagte), in denen Sie nicht bis init warten können. In diesen Fällen haben Sie keine Wahl.

Die einzige Möglichkeit, eine Inkompatibilität zu beheben, ist von Fall zu Fall, wenn Sie dies wünschen.

Eine Lösung, die in den meisten Fällen funktioniert (einschließlich bbPress / BuddyPress), besteht darin, die folgende Funktion anstelle von zu verwenden 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 );
}

Dies ermöglicht es, die aktuelle Benutzerfähigkeit frühzeitig zu überprüfen, ohne einen globalen Benutzer festzulegen, sodass sie theoretisch sicher ausgeführt werden kann init.

Das Problem ist, dass, wie oben erwähnt, jeder Code, der steckbare Funktionen überschreibt und keine Feuer determine_current_userauslöst, ihn bricht.


Ich denke, Ihre Funktion hat Variablen ein bisschen durcheinander. :)
Rarst

Ja ... vor dem Abendessen zu schnell getippt: P danke @ialocin für die Korrektur.
gmazzap

Erwähne es nicht. Außerdem sag nicht nur, was los ist, sondern behebe es @Rarst :)
Nicolai

1

Ich bin geneigt zu denken, dass BuddyPress und bbPress etwas anderes überprüfen sollten, bevor sie die _doing_it_wrongNachricht ausgeben

Ich habe beide Routinen geändert, um auch die tatsächliche Einstellung von $ current_user zu überprüfen.

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

Die Hinweise wurden nicht mehr angezeigt.

Das Testen auf did_action( "after_setup_theme" )wird zu den Zahnspangen, die zum Gürtel passen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.