web-dev-qa-db-fra.com

current_user_can ne fonctionne pas toujours correctement

J'ai un thème Wordpress personnalisé qui comprend une section réservée aux membres. Afin d'implémenter cela, j'ai le code suivant en haut de mes pages restreintes.

<?php if ( ! current_user_can ('view_players_area') ) { header('Location: ' . wp_login_url( "http://$_SERVER[HTTP_Host]$_SERVER[REQUEST_URI]" ) ); } ?>

La plupart du temps, cela fonctionne bien, mais de temps en temps, il ne fonctionne tout simplement pas sans raison. Aucun message d'erreur, juste lorsque vous vous connectez, il redirige continuellement vers la page de connexion. A l'origine, j'ai utilisé is_user_logged_in() et j'ai eu un problème similaire, ce qui m'a amené à utiliser ce code.

Si quelqu'un a des suggestions sur ce qui pourrait causer cela, je vous en serai très reconnaissant. Cela me déchire les cheveux, car la zone des membres doit être opérationnelle dans les prochaines semaines.

Cordialement

Ben

Modifier

Suivant les conseils des réponses et de certains utilisateurs du salon de discussion, j'ai modifié mon code afin que la redirection ne soit pas effectuée dans le modèle. Maintenant, dans un functions.php include, j'ai les éléments suivants:

<?php

function redirect_restricted_areas( $query )
{
    if ( !is_admin() && $query->is_main_query() )
    {
          if ( ! current_user_can( 'view_players_area' ) && (
               $query->is_singular ('player-page') ||
               $query->is_post_type_archive ('player-page')
          ) ) 

          header('Location: ' . wp_login_url( "http://$_SERVER[HTTP_Host]$_SERVER[REQUEST_URI]" ) );
    }

}

add_action ( 'pre_get_posts', 'redirect_restricted_areas' );

Malheureusement, bien que ce soit un bon conseil qui simplifie mon code, cela ne résout pas le problème.

Modification ultérieure

Donc, avec un peu de débogage, je peux voir que $ current_user n’est pas toujours défini, mais je ne sais pas pourquoi.

Une autre édition

En enquêtant plus loin, cela semble être quelque chose à voir avec les cookies. Après avoir appris quelques mots sur les cookies d'authentification Wordpress, j'ai remarqué ce qui suit. En utilisant dBug (une version plus jolie de print_r()), j’ai déterminé que, selon PHP, le cookie d’authentification Wordpress n’existait pas. Pourtant, si j’ouvrais l’inspecteur Chrome, je pouvais clairement voir le cookie assis. Je ne sais pas trop quoi en penser, mais si quelqu'un est capable de me diriger dans la bonne direction ...

1
Ben Wainwright

Ne définissez pas header dans un fichier de modèle. Ceux-ci font partie de la requête HTTP elle-même.

A propos de votre problème:

Ajoutez un modèle (quel que soit le fichier requis - voir "Hiérarchie des modèles"). En plus, vous incluez les éléments par défaut tels que get_header(); et ainsi de suite. Pour la partie restreinte, vous utilisez les éléments suivants:

if ( current_user_can( 'view_players_area' ) )
{
    // Code that you want to show to logged in users
    // with a capability of `view_players_area`
}
else
{
    # @link http://queryposts.com/function/wp_login_form/
    wp_login_form();
}
2
kaiser

Vous devez exit() après avoir défini l'en-tête (et je vous recommande d'utiliser wp_redirect()).

Non testé, mais ce qui suit devrait fonctionner. S'il est vraiment vrai que current_user_can() ne fonctionne pas, je désactiverais tout d'abord les autres plug-ins pour éliminer un conflit, puis vérifierais que cet utilisateur dispose vraiment des autorisations que vous pensez avoir.

function redirect_restricted_areas( $query )
{

    //Determine if we're on the log-in page
    global $pagenow;
    $on_login_page = in_array( $pagenow, array( 'wp-login.php', 'wp-register.php' ) );

    //If we're on the front-end and the main query is restricted
    //redirect the user if they do not have permission.
    if ( !$on_login_page && !is_admin() && $query->is_main_query() )
    {
          if ( ! current_user_can( 'view_players_area' ) && (
               $query->is_singular ('player-page') ||
               $query->is_post_type_archive ('player-page')
          ) ) {

            $url = wp_login_url( "http://$_SERVER[HTTP_Host]$_SERVER[REQUEST_URI]" );
            wp_redirect( $url );
            exit();
          }
    }

}
add_action ( 'pre_get_posts', 'redirect_restricted_areas' );
1
Stephen Harris

Mettez ceci en haut du fichier avec votre code:

global $current_user;
if ( !$current_user->ID ) {
    get_currentuserinfo();
}
1
MaximOrlovsky

Vous pouvez essayer d’utiliser wp_redirect(); et le hook after_setup_theme (ne devrait pas toute sortie à ce stade).

Créez des conditions plus gérables avec des renflouements rapides.

Voici mon point de vue, je suppose ...

if(!function_exists('mbe_redirect_restricted_areas')){
    function mbe_redirect_restricted_areas(){

        // Determine login page status.
        global $pagenow;

        // Do nothing on login page.
        if(in_array($pagenow, array(
            'wp-login.php',
            'wp-register.php'
        )){
            return false;
        }

        // Do nothing in admin area.
        if(is_admin()){
            return false;
        }

        // Do nothing if user is logged in and has capability.
        if(is_user_logged_in() && current_user_can('view_players_area')){
            return false;
        }

        // Do nothing if not in player page area.
        if(stripos($_SERVER['REQUEST_URI'], 'player-page') === false){
            return false;
        }

        // Guests and users without capability.
        wp_redirect(wp_login_url("http://{$_SERVER['HTTP_Host']}{$_SERVER['REQUEST_URI']}"));
        exit;

    }
    add_action('after_setup_theme', 'mbe_redirect_restricted_areas');
}
0
Michael Ecklund