Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I've created a custom post type with 2 custom fields attached to it... When I create a post of this type and fill in the custom fields, the data is, in fact, saved to the db... However, if I trash one of them, then that post's custom fields data is deleted from the database.

I thought trashing was just supposed to basically change the post_status to "trash" so it's out of view unless you actually delete it permanently?

If that's the case, why am I losing my custom fields data when I trash an item?

Here's all the relevant code for the above question:

<?php
add_action('admin_init', 'wpg_add_testimonial_author');
function wpg_add_testimonial_author() {
  add_meta_box('wpg_testimonial_author', __('Author Information', 'quotable'), 'wpg_testimonial_author', 'testimonials', 'side', 'low');
}

function wpg_testimonial_author() {
  global $post;
  $custom = get_post_custom($post->ID);
  $testimonial_author_name = $custom['testimonial_author_name'][0];
  $testimonial_author_link = $custom['testimonial_author_link'][0];
  ?>
  <p>
    <label><?php _e("Author's Name:", 'quotable'); ?></label>
    <input name="testimonial_author_name" value="<?php echo $testimonial_author_name; ?>" />
  </p>
  <p>
    <label><?php _e('Attribution Link:', 'quotable'); ?></label>
    <input name="testimonial_author_link" value="<?php echo $testimonial_author_link; ?>" />
  </p>
  <?php
}

function wpg_save_testimonial_author() {
  global $post;
  if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
    return $post_id;
  }
  if (defined('DOING_AJAX')) {
    return;
  }
  update_post_meta($post->ID, 'testimonial_author_name', $_POST['testimonial_author_name']);
  update_post_meta($post->ID, 'testimonial_author_link', $_POST['testimonial_author_link']);
}
add_action('save_post', 'wpg_save_testimonial_author');

function wpg_row_actions() {
  global $post;
  if($post->post_type == 'page') {
    if(!current_user_can('edit_page')) {
      return;
    }
  }
  else {
    if(!current_user_can('edit_post')) {
      return;
    }
  }
  if($post->post_status == 'trash') {
    $actionLinks  = '<div class="row-actions"><span class="untrash"><a title="'.__('Restore this item', 'quotable').'" href="'.wp_nonce_url(get_admin_url().'post.php?post='.$post->ID.'&action=untrash', 'untrash-'.$post->post_type.'_'.$post->ID).'">'.__('Restore', 'quotable').'</a> | </span>';
    $actionLinks .= '<span class="trash"><a href="'.wp_nonce_url(get_admin_url().'post.php?post='.$post->ID.'&action=delete', 'delete-'.$post->post_type.'_'.$post->ID).'" title="'.__('Delete this item permanently', 'quotable').'" class="submitdelete">'.__('Delete Permanently', 'quotable').'</a></span>';
  }
  else {
    $actionLinks  = '<div class="row-actions"><span class="edit"><a title="'.__('Edit this item', 'quotable').'" href="'.get_admin_url().'post.php?post='.$post->ID.'&action=edit">'.__('Edit', 'quotable').'</a> | </span>';
    $actionLinks .= '<span class="inline hide-if-no-js"><a title="'.__('Edit this item inline', 'quotable').'" class="editinline" href="#">'.__('Quick Edit', 'quotable').'</a> | </span>';
    $actionLinks .= '<span class="trash"><a href="'.wp_nonce_url(get_admin_url().'post.php?post='.$post->ID.'&action=trash', 'trash-'.$post->post_type.'_'.$post->ID).'" title="'.__('Move this item to the Trash', 'quotable').'" class="submitdelete">'._x('Trash', 'verb (ie. trash this post)', 'quotable').'</a></span>';
  }
  return $actionLinks;
}

function wpg_edit_testimonials_columns($columns) {
  $columns = array(
    'cb' => '<input type="checkbox" />',
    'testimonial_author' => __('Author', 'quotable'),
    'testimonial_text' => __('Testimonial', 'quotable'),
    'attribution_link' => __('Attribution Link', 'quotable'),
    'date' => __('Date Added', 'quotable')
  );
  return $columns;
}

function wpg_manage_testimonials_columns($column, $post_id) {
  global $post;
  $custom = get_post_custom($post->ID);
  $testimonial_author_name = $custom['testimonial_author_name'][0];
  $testimonial_author_link = $custom['testimonial_author_link'][0];

  $wpg_row_actions  = wpg_row_actions();

  switch($column) {
    case 'testimonial_author':
      echo $testimonial_author_name.$wpg_row_actions;
    break;

    case 'testimonial_text':
      echo $post->post_content;
    break;

    case 'attribution_link':
      echo $testimonial_author_link;
    break;

    default :
      break;
    }
  }
  add_filter('manage_edit-testimonials_columns', 'wpg_edit_testimonials_columns');
  add_action('manage_testimonials_posts_custom_column', 'wpg_manage_testimonials_columns', 10, 2);

The custom post type doesn't support the "title" portion of posts, so it's not included as one of the columns in the edit posts page. Therefore, I had to hack my own version of the row_actions() function to enable the edit/quick edit/trash links when each post is hovered.

All of the functionality works as it should... Except that the "testimonial author" and "attribution link" values are deleted from the database when moving a post to the trash. No idea why...

share|improve this question
    
I've narrowed it down... I added yet ANOTHER post type with all the exact same attributes as this one, but I didn't include the custom function for adding the "trash" link. Instead I added the "title" as one of the array keys when setting up the custom columns... However, it still deletes the custom field data even when I trash the post using the original trash link. So this leads me to believe it's got to be something to do with my save method for the custom field data. I read somewhere that "save_post" is fired when trashing a post... Any way around this? –  Nero_DCLXVI Oct 25 '11 at 3:30

2 Answers 2

up vote 1 down vote accepted

It seems that the action save_post gets fired when sending a post to the trash... Therefore, my custom metadata save function was being activated with no $_POST data to send thru it.

To circumvent this, I wound up adding a nonce to the save function.

function wpg_testimonial_author() {
  global $post;
  $custom = get_post_custom($post->ID);
  $testimonial_author_name = $custom['testimonial_author_name'][0];
  $testimonial_author_link = $custom['testimonial_author_link'][0];
  ?>
  <p>
    <label><?php _e("Author's Name:", 'quotable'); ?></label>
    <input name="testimonial_author_name" value="<?php echo $testimonial_author_name; ?>" />
  </p>
  <p>
    <label><?php _e('Attribution Link:', 'quotable'); ?></label>
    <input name="testimonial_author_link" value="<?php echo $testimonial_author_link; ?>" />
    <input type="hidden" name="testimonial_author_noncename" id="testimonial_author_noncename" value="<?php echo wp_create_nonce(plugin_basename(__FILE__).$post->ID); ?>" />
  </p>
  <?php
}

function wpg_save_testimonial_author($post_id) {
  global $post;
  if (!wp_verify_nonce($_POST['testimonial_author_noncename'], plugin_basename(__FILE__).$post->ID)) {
    return $post->ID;
  }
  if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
    return $post_id;
  }
  if(defined('DOING_AJAX')) {
    return;
  }
  if(!current_user_can('edit_post')) {
    return $post->ID;
  }
  if($post->post_type == 'revision') {
    return;
  }
  update_post_meta($post->ID, 'testimonial_author_name', $_POST['testimonial_author_name']);
  update_post_meta($post->ID, 'testimonial_author_link', $_POST['testimonial_author_link']);
}
add_action('save_post', 'wpg_save_testimonial_author');

Hopefully this might help someone else later...

share|improve this answer
    
Ah, you've just helped me with a bizarre problem that cost me a few pointless hours..! Much appreciated. –  dunc Dec 25 '11 at 14:57

Wow thank you Nero_DCLXVI. Very helpful. For future people looking to implement this, here's simplified instructions of his solution:

  1. Add this hidden input along with your other custom meta inputs:

<input type="hidden" name="prevent_delete_meta_movetotrash" id="prevent_delete_meta_movetotrash" value="<?php echo wp_create_nonce(plugin_basename(__FILE__).$post->ID); ?>" />

  1. Add this right before your update_post_meta() functions.

if (!wp_verify_nonce($_POST['prevent_delete_meta_movetotrash'], plugin_basename(__FILE__).$post->ID)) { return $post_id; }

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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