By Chris


2013-11-25 16:14:07 8 Comments

This is proving to be a challenge.

I'm trying to make the excerpt a required field, but only when editing/saving a post in a custom post type.

The following code makes the excerpt a required field for all posts, but doesn't take into account for narrowing its affect to a single custom post type.

function mandatory_excerpt($data) {
  $excerpt = $data['post_excerpt'];

  if (empty($excerpt)) {
    if ($data['post_status'] === 'publish') {
      add_filter('redirect_post_location', 'excerpt_error_message_redirect', '99');
    }

    $data['post_status'] = 'draft';
  }

  return $data;
}

add_filter('wp_insert_post_data', 'mandatory_excerpt');

function excerpt_error_message_redirect($location) {
  remove_filter('redirect_post_location', __FILTER__, '99');
  return add_query_arg('excerpt_required', 1, $location);
}

function excerpt_admin_notice() {
  if (!isset($_GET['excerpt_required'])) return;

  switch (absint($_GET['excerpt_required'])) {
    case 1:
      $message = 'Excerpt is required to publish a post.';
      break;
    default:
      $message = 'Unexpected error';
  }

  echo '<div id="notice" class="error"><p>' . $message . '</p></div>';
}

add_action('admin_notices', 'excerpt_admin_notice');

3 comments

@Jamie 2017-09-26 19:29:01

I don't have enough reputation on this site to comment.

Note that the code you're using doesn't have the appropriate checks for the post status. As a result, your admin dashboard will fill up with lots of Auto Drafts which are usually empty, which will never be cleaned up.

A simple fix is to do something like:

    function mandatory_excerpt($data) {
            if (empty($data['post_excerpt']) && $data['post_type'] != 'custom-post-type' && !isset($_GET['action'])) {

                    if ($data['post_status'] === 'publish') {
                            add_filter('redirect_post_location', 'excerpt_error_message_redirect', '99');
                    }

                    if ($data['post_status'] == 'publish' || $data['post_status'] == 'future' || $data['post_status'] == 'pending') {
                            $data['post_status'] = 'draft';
                    }
            }

            return $data;
    }

@Jelle Wielsma 2016-11-17 16:09:25

The solution to the problem with posts not being able to be removed or even published is adding an extra check to make sure the mandatory_excerpt() function only fires when there is no $_GET['action'] provided. Otherwise, the function will always return an error when removing a post or changing it's publish status.

So the altered function would be:

function mandatory_excerpt($data) {
    if ( 'custom-post-type-here' != $data['post_type'] || $_GET['action'] ) {
        return $data;
    } else {
        $excerpt = $data['post_excerpt'];

        if (empty($excerpt)) {
            if ($data['post_status'] === 'publish') {
                add_filter('redirect_post_location', 'bstcm_excerpt_error_message_redirect', '99');
            }     
            $data['post_status'] = 'draft';
        }
    }     
    return $data;
}

@Chip Bennett 2013-11-25 16:27:04

The code adds a filter to wp_insert_post_data:

add_filter('wp_insert_post_data', 'mandatory_excerpt');

And here's the callback:

function mandatory_excerpt($data) {
  $excerpt = $data['post_excerpt'];

  if (empty($excerpt)) {
    if ($data['post_status'] === 'publish') {
      add_filter('redirect_post_location', 'excerpt_error_message_redirect', '99');
    }

    $data['post_status'] = 'draft';
  }

  return $data;
}

The filter callback is passed $data, which as per the Codex includes the following post data:

'post_author',
'post_date',
'post_date_gmt',
'post_content',
'post_content_filtered',
'post_title',
'post_excerpt',
'post_status',
'post_type',
'comment_status',
'ping_status',
'post_password',
'post_name',
'to_ping',
'pinged',
'post_modified',
'post_modified_gmt',
'post_parent',
'menu_order',
'guid'

Those data include 'post_type', which means you can use that inside the callback:

function mandatory_excerpt($data) {
    if ( 'custom-posttype-slug' != $data['post_type'] ) {
        return $data;
    } else {
        $excerpt = $data['post_excerpt'];

        if (empty($excerpt)) {
            if ($data['post_status'] === 'publish') {
                add_filter('redirect_post_location', 'excerpt_error_message_redirect', '99');
            }     
            $data['post_status'] = 'draft';
        }
    }     
    return $data;
}

@Chris 2013-11-25 16:46:14

Fantastic, Chip! I never thought it would be so easy (when you know how).

@Chris 2013-11-26 08:30:16

One issue I'm having with the above code, is if I try to trash a post with draft status, it remains in draft and does not move to trash.

@Chip Bennett 2013-11-26 12:49:01

That would be a separate question with what the code itself is actually doing.

@emersonthis 2016-06-14 01:40:29

What should excerpt_error_message_redirect be? Is that the name of a function? It's not clear how to actually display the message.

@Slowaways 2019-01-02 22:17:57

The alert message is not displayed in Gutenberg (Wordpress 5).

Related Questions

Sponsored Content

2 Answered Questions

Manual excerpt being ignored on custom post type

1 Answered Questions

How to custom excerpt?

  • 2019-01-04 08:23:45
  • Mike
  • 30 View
  • 0 Score
  • 1 Answer
  • Tags:   excerpt

1 Answered Questions

Writing a custom excerpt function

  • 2016-09-12 23:08:44
  • user1002601
  • 1069 View
  • 2 Score
  • 1 Answer
  • Tags:   excerpt

2 Answered Questions

[SOLVED] Adding [...] string for a custom excerpt function

  • 2013-07-03 16:05:40
  • user1799323
  • 319 View
  • 0 Score
  • 2 Answer
  • Tags:   excerpt

1 Answered Questions

[SOLVED] Excerpt is only getting shown for first post

  • 2011-11-03 14:05:26
  • Corbula
  • 638 View
  • 0 Score
  • 1 Answer
  • Tags:   excerpt

Sponsored Content