web-dev-qa-db-fra.com

Autorise le rôle à supprimer des messages mais bloque le wp-admin

J'ai un rôle d'utilisateur personnalisé: Photograph.

Ce rôle ne doit pas pouvoir se connecter au back-office, mais doit être capable de supprimer ses propres publications du front-end.

J'utilise ce code pour empêcher tous les utilisateurs non-administrateurs de se connecter au backoffice avec ceci (function.php):

add_action( 'init', 'blockusers_init' );
function blockusers_init() {
    if ( is_admin() && ! current_user_can( 'administrator' ) &&
         ! ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
        wp_redirect( home_url() );
        exit;
    }
}

Et j'utilise ce code pour supprimer les messages (portfolio.php):

<a href="<?php echo get_delete_post_link( $post->ID ) ?>">Delete post</a>

J'ai essayé quelques autres options, mais je n'ai jamais été en mesure de permettre aux photographes de supprimer leurs publications (ou globalement, car ils ne peuvent de toute façon que voir les leurs).

Je vous remercie !

2
Relisora

En supposant que vous parlez d’un utilisateur personnalisé role nommé "photographe" ", je pense que quelque chose comme ceci devrait ajouter la capacité delete_posts à ce rôle.

function add_delete_cap_to_photog_role() {
    $role = get_role( 'photographer' );

    $role->add_cap( 'delete_posts' );
}
add_action( 'admin_init', 'add_delete_cap_to_photog_role');

Après avoir ajouté les majuscules au rôle, pour résoudre le reste, vous pouvez soit

  1. gardez blockusers_init et fossé get_delete_post_link pour une suppression ajax.
  2. abandonner la fonction blockusers_init et faire une redirection conditionnelle.

Je vais donner quelques idées sur chacun. Je préfère abandonner get_delete_post_link dans cet exemple.

Plusieurs étapes ci-dessous, soyez donc conscient que le code est fourni à titre indicatif uniquement. Réécrire et renommer les choses au besoin.


Ditch get_delete_post_link aka AJAX Supprimer

remplacez la ligne get_delete_post_link par quelque chose comme ceci:

<?php if( current_user_can( 'delete_post' ) ) : ?>
    <a href="#" data-id="<?php the_ID() ?>" data-nonce="<?php echo wp_create_nonce('ajax_delete_post_nonce') ?>" class="delete-post">delete</a>
<?php endif ?>

Mettre en file d'attente des JS

dans le fichier: functions.php

function delete_post_ajax() {
    wp_enqueue_script(  'delete_ajax', get_template_directory_uri() . '/js/my_script.js', array( 'jquery' ), '1.0.0', true );
    wp_localize_script( 'delete_ajax', 'TheAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
}

add_action( 'wp_enqueue_scripts', 'delete_post_ajax' );

onClick pour transmettre les données pour supprimer la méthode

dans le fichier: /js/my_script.js

jQuery( document ).ready( function($) {
    $(document).on( 'click', '.delete-post', function() {
        var id = $(this).data('id');
        var nonce = $(this).data('nonce');
        var post = $(this).parents('.post:first');
        $.ajax({
            type: 'post',
            url: TheAjax.ajaxurl,
            data: {
                action: 'wpse_ajax_delete_post',
                nonce: nonce,
                id: id
            },
            success: function( result ) {
                if( result == 'success' ) {
                    post.fadeOut( function(){
                        post.remove();
                    });
                }
            }
        })
        return false;
    })
})

la méthode de suppression

dans le fichier: functions.php (le hook dont nous avons besoin est juste "wp_ajax" en ajoutant le nom du action dans le fichier js)

add_action( 'wp_ajax_wpse_ajax_delete_post', 'wpse_ajax_delete_post_func' );
function wpse_ajax_delete_post_func(){

    $permission = check_ajax_referer( 'ajax_delete_post_nonce', 'nonce', false );
    if( $permission == false ) {
        echo 'error';
    }
    else {
        wp_delete_post( $_REQUEST['id'] );
        echo 'success';
    }

    die();

}

Pour faire ce qui précède en passant les paramètres uri:

Changer où nous avons échangé get_delete_posts_link pour ceci:

<?php if( current_user_can( 'delete_post' ) ) : ?>
    <?php $nonce = wp_create_nonce('ajax_delete_post_nonce') ?>
    <a href="<?php echo admin_url( 'admin-ajax.php?action=wpse_ajax_delete_post&id=' . get_the_ID() . '&nonce=' . $nonce ) ?>" data-id="<?php the_ID() ?>" data-nonce="<?php echo $nonce ?>" class="delete-post">delete</a>
<?php endif ?>

Voir ceci pour une procédure plus complexe expliquant chaque étape


Ditch blockusers_init (aka redirection conditionnelle)

Ceci définit une redirection sur wp-admin si l'utilisateur n'a pas de limite manage_options, qui est un rôle d'administrateur. Mais d’abord, il pseudo-cache les choses et ajoute un message à l’utilisateur avec quelques css:

Le bit CSS

dans le fichier: functions.php

add_action('admin_head', 'hide_admin_via_css');
function hide_admin_via_css() {
    if (!current_user_can( 'manage_options' )) {
        echo '<style>body * {visibility:hidden !important;} body:before {content:"Give it a second...";}
';
    }
}

Mise en file d'attente du fichier JS

dans le fichier: functions.php

function my_enqueue( $hook ) {
    if (!current_user_can( 'manage_options' )) {
        wp_enqueue_script( 'my_custom_script', get_template_directory_uri() '/js/block-admin.js' );
    }
}
add_action('admin_enqueue_scripts', 'my_enqueue');

Configurez le JS pour qu'il redirige immédiatement

fichier: racine_thème/js/block-admin.js

window.location.href = "/";

OR une redirection temporisée

setTimeout(function () {
   window.location.href = "/";
}, 2000);

Cette approche est venue de clicknathan, et il offre plus de détails ici.

3
hwl

la réponse de hwl est correcte, mais je vais ajouter une vérification si l'utilisateur actuel est l'auteur du message.

<?php
$current_user = wp_get_current_user();
if ( $current_user->ID == $post->post_author ) { ?>
    <a href="<?php echo get_delete_post_link( $post->ID ) ?>">Delete post</a>
<?php } ?>

Étant donné que vous pourriez ajouter la possibilité de 'delete_posts ', ce qui pourrait supprimer n'importe quel message, cela pourrait constituer une sauvegarde. <Ce n'était pas juste.

Ainsi, le lien n'apparaît que sur les messages qu'ils peuvent supprimer, les leurs.

1
socki03

Votre question comporte trois exigences:

  1. Le rôle ne doit pas pouvoir se connecter au serveur
  2. Le rôle doit pouvoir supprimer ses propres publications
  3. Une condition implicite est qu’ils doivent pouvoir supprimer les publications.

Vraisemblablement, vous avez une méthode en place où l'utilisateur peut publier et publier ses publications sans accès au backend. Si tel est le cas, vous pouvez manipuler le rôle en:

  1. Suppression de la capacité read
  2. Ajout de la capacité delete_posts
  3. Ajouter le delete_published_posts capacité

Étant donné que le rôle n'a pas delete_others_posts, ils ne pourront pas supprimer les publications d'autres utilisateurs, même si elles sont publiées.

Les capacités de rôle étant stockées dans la base de données, vous devez les ajouter et les supprimer lors de l'activation du plugin ou du thème. Voici un exemple de plug-in qui ajoute les fonctionnalités requises à l'activation et les supprime en cas de désactivation.

/**
 * Plugin Name: WordPress StackExchange Question 268755
 * Description: Allow subscribers to delete their own posts
 **/

//* On activation, add the capabilities to the subscriber role
register_activation_hook( __FILE__, 'wpse_268755_activation' );
function wpse_268755_activation() {
  $photograph = get_role( 'photograph' );
  $photograph->remove_cap( 'read' );
  $photograph->add_cap( 'delete_posts' );
  $photograph->add_cap( 'delete_published_posts' );
}

//* On deactivation, remove the capabilities from the subscriber role
register_deactivation_hook( __FILE__, 'wpse_268755_deactivation' );
function wpse_268755_deactivation() {
  $photograph = get_role( 'photograph' );
  $photograph->remove_cap( 'delete_posts' );
  $photograph->remove_cap( 'delete_published_posts' );
}

Vous avez ensuite besoin d'un moyen de supprimer réellement le message. Si l'utilisateur avait accès au back-end, vous pouvez utiliser get_delete_post_link.

<a href="<?php echo get_delete_post_link( $post->ID ) ?>">Delete post</a>

Ce que vous devez faire, c’est donc d’écrire du code javascript qui, une fois cliqué sur ce lien, empêche le comportement par défaut et envoie une requête AJAX pour supprimer le message.

1
Nathan Johnson