Вопрос

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');
Это было полезно?

Решение

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;
}

Другие советы

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;
}

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;
    }

It seems the above solution did not work so well for me (as @slowaways mentioned earlier, with WordPress 5+). So I came up with a new solution. Since I am using ACF, I created a new 'short description' field ('extrait') and made it mandatory. So I can use the validation features of ACF, and update excerpt value on the fly :

/**
 * Set excerpt from ACF field
 */
add_action('acf/save_post', function($post_id) {

  $post_excerpt   = get_field( 'extrait', $post_id );

  if ( ( !empty( $post_id ) ) AND ( $post_excerpt ) ) {

    // Update post options array
    $update_post_excerpt_args = array(
      'ID'          => $post_id,
      'post_excerpt'    => $post_excerpt,
    );

    wp_update_post( $update_post_excerpt_args );

  }

}, 50);

To give credit where credit is due i found this code here : https://gist.github.com/MWDelaney/fd0bed89b891e3ff0850428703786397

Hope this helps.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с wordpress.stackexchange
scroll top