1

Is it possible to customize AJAX response when using filters such as check_admin_referer and check_ajax_referer ?

I've done some tweaks (with those filters) to prevent users from deleting some terms that are really important and MUST not be deleted. But it keeps telling me "unknown error" which is far from being clear.

Any hint would be cool.

For now I'm using wp_die( 'This term cannot be deleted' ) and I wonder how to inject this message in AJAX response.

  • In my opinion, there is something wrong if there are users with access to some action they can not perform. I suggest to investigate custom taxonomies and capabilities. In this way you could have users that can completely manage the terms, users that can assign terms but not delete them, and so on. – cybmeta Oct 12 '16 at 14:41
  • Ok but this is not what I want. I already did that. In this case I want only one term to be "undeletable" – JMau Oct 12 '16 at 14:48
  • At-least share your working code that you tried already. and normally I don't can be possible but detect perfectly wp_nonce and action can be possible, I'm not sure but may be you can find some hints on wp-admin/edit-tags.php – Mohammad Limon Oct 12 '16 at 17:18
  • "prevent users from deleting some terms" is not the same that "a term be "undeletable""; anyway, I still see a capabilities problem. Both cases can solved with user capabilities and I tink it is the correst way. – cybmeta Oct 12 '16 at 20:01
2
+50

Wait for WordPress 4.7 on 6th December. It has this almost built-in.

If I got it right, then you'll want to prevent some terms from deletion. I already made a snippet for that which works with WP 4.7

add_filter(
  'user_has_cap',
  function ( $allcaps, $caps, $args ) {
    if ( ! isset( $args[0] ) || 'delete_term' != $args[0] ) {
      // not the deletion process => ignore
      return $allcaps;
    }

    $term = get_term( $args[2] );

    // HERE YOU'LL LIKE TO PUT YOUR LOGIC INSTEAD OF THIS:
    if ( $term->count <= 0 ) {
      return $allcaps;
    }

    // for all other cases => reject deletion
    return [ ];
  },
  10,
  3
);

For more details read https://wp-includes.org/536/capabilities-taxonomies-terms/#Preventnon-empty_categories_from_deletion

| improve this answer | |
1

Another answer is not concerned with AJAX/JAVASCRIPT at all.

Instead, add this code:

add_action( 'pre_delete_term', 'myfunc', 10,2  );
function myfunc($term, $taxonomy){
  //var_dump($term);   var_dump($taxonomy);
  if($taxonomy =='category' && $term==745 ){
     die('not allowed');
  }
}

p.s. change 745 to the desired category id.

| improve this answer | |
0

This is my first answer, hope it helps.

If I understand your question correctly, you are wondering how to send a custom message to the client( i.e. browser) if check_ajax_referrer returns false.

Looking at the code reference you will see the function fires an action called check_ajax_referer, right before it stops code execution, if false. What we will do is use this action to override the outcome of a false nonce result.

function fn_name($action, $result){

    //  check if $result, passed from core function, is false
    //  alternately you can check for action if only needed for a specific ajax request
    //   For example: 
    //       if($action == 'the_action_name' && false === $result)

    if ( false === $result ) {

        //  use built in send function to return json to client,
        //  wp_send_json has wp_die() built-in

        wp_send_json('This term cannot be deleted');
    }

    //  return to core function if true
    return $result;
}

add_action('check_ajax_referer', 'fn_name', 10, 2);

I apologize if this answer is too verbose, I wanted to be as thorough as possible.

| improve this answer | |
  • Hi, thanks for the answer but that's not why I need at all. I want to stop request in particular cases (specific conditions) , in my case $result won't return false. I've alredy tested the send json method with no success :/ – JMau Oct 12 '16 at 14:26
  • Do you mind elaborating on what you mean by "stop request", perhaps go through the whole workflow you are trying to achive. Thank you. – stims Oct 12 '16 at 14:29
  • I'm trying to prevent user from deleting a term that MUST not be deleted. So I used these filters to stop process in /wp-admin/edit-tags.php and it works fine. But the admin notice is always "unknown error". I just want to change that text to tell admin "ok, not this one, you cannot delete it" – JMau Oct 12 '16 at 14:36
  • instead of if ( false === $result ) {} I got if ( $this->is_term_to_block( $term_id ) ), nothing more – JMau Oct 12 '16 at 15:20
0

Every AJAX call has similar stucture:

jQuery.post(ajaxurl,  { 
            action: "something_namee", 
            parameter1: "blabla" ,
            parameter2: "blabla222" ,
            ........ 

in PHP side, you should create an wp_ajax_ action, followed exactly something_namee:

add_action('wp_ajax_something_namee','myfunc123',1);
function myfunc123(){
    //var_dump($_POST);
    if(!EMPTY($_POST['parameter1']) && $_POST['parameter1']==53){
        die("this term id cant be deleted");
    }
}

p.s. just change parameter1 and 53 with the real parameters being called (you can find out what parameters are passed from AJAX by uncommenting var_dump above)

p.s.2. However, I suggest not to be dependent on AJAX calls at all! Because many different things can be done for deleting the categories, so the above method wont help. I will post another answer, which is recommended.

| improve this answer | |
  • ok thanks but remove that one, it can be confusing for anyone who reads – JMau Oct 13 '16 at 12:45
0

I have this in one of my plugins:

/**
 * Prevents deletion of term
 *
 * Applies filter "atf_locks_term_delete_cap" to allow other plugins to filter the capability.
 *
 * @uses Adv_Term_Fields_Locks::get_prevent_msg()
 *
 * @access public
 *
 * @since 0.1.0
 *
 * @param int    $term_id  Term ID.
 * @param string $taxonomy Taxonomy Name.
 *
 * @return mixed int    $term_id If current user can delete the term or term is not locked.
 *               wp_die()  On AJAX calls: If current user can't delete term or user is not detected.
 */
public function maybe_prevent_term_delete( $term_id, $taxonomy )
{
    // If no lock, return term ID
    if ( ! $lock = get_term_meta( $term_id, $this->meta_key, true ) ) {
        return $term_id;
    };

    $cap = apply_filters( "atf_locks_term_delete_cap", "manage_others_term_locks" );
    $user_can_delete = $this->_user_can( $cap, $term_id, $taxonomy, $lock );

    if ( ! $user_can_delete ) :
        if ( defined('DOING_AJAX') && DOING_AJAX ) {
            wp_die( -1 );
        } else {
            $_msg = $this->get_prevent_msg( $action = 'delete' );
            wp_die( $_msg, 403 );
        };
    endif;

    return $term_id;
}

and it's called like so:

add_action( 'pre_delete_term', array( $this, 'maybe_prevent_term_delete' ), 99, 2 );

The pre_delete_filter is called before any term is deleted. To prevent deletion, you can hook into the action similar to how I've done it in my class method above.

The problem is, WP doesn't allow for a way to customize the response. Since it's an ajax call it's only looking for a '1', a '0', or a '-1'.

Check out wp_ajax_delete_tag() in /wp-admin/includes/ajax-actions.php to see what I'm referring to.

| improve this answer | |
0

Every AJAX call uses callback functions to process returning data. Just use the .fail callback:

jQuery.post( ajaxurl,
            { //your data here },
            function( content ) {
               var myContent = JSON.parse(content);
               // success! do something with content
            } ).fail( fucntion( msg ) { alert( msg );
            });

This is how I would pass the AJAX failure message to the user interface.

| improve this answer | |
-2

To send a response to the web page via ajax.

add_action('wp_ajax_my_action','my_function');

function my_function(){
    if( true === $value ){   // make test
       echo 'Is true';       // send string response to web page
       wp_die();             // Finish response
    } else {
       echo 'Is not true';   // send string response to web page
       wp_die();             // Finish response
    }
}

You can also send a json response:

https://codex.wordpress.org/Function_Reference/wp_send_json :Send a JSON response back to an AJAX request, and die().

function my_function(){
    $response_true = array('response'=> 'Success','reason'=>'is true');
    $response_not_true = array('response'=> 'Error','reason'=>'is not true');
    if( true === $value ){   // make test
       wp_send_json($response_true);       // send json response 
   //    wp_die();             // not necessary
    } else {
       wp_send_json($response_not_true);   // send json response 
   //    wp_die();             // not necessary
    }
}
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.