Me, like @fischi think that filter 'user_has_cap'
is the best choiche for the pourpose, however, I think that is better to the work, regardless the $_GET post or action: WordPress check the meta cabability on a per-post basis, using an additional argument.
In few words, when filtering 'user_has_cap'
for a meta capability (see https://codex.wordpress.org/Function_Reference/map_meta_cap) we have access to the post ID, and using it we can prevent an user edit or delete a specific post.
add_filter( 'user_has_cap', 'no_edit_prending_for_contrib', 9999, 3 );
function no_edit_prending_for_contrib ( $allcaps, $caps, $args ) {
// an arry of action we want to prevent
$prevent = array('edit_posts', 'delete_posts');
// we are not checking for edit a post, do nothing
if ( ! array_intersect( $prevent, (array) $caps ) ) return $allcaps;
// we are not checking for a specific post, do nothing
if ( ! isset( $args[2] ) || ! is_numeric( $args[2] ) ) return $allcaps;
// the user has the capability to edit published posts, do nothing
if ( array_key_exists( 'edit_published_posts', (array) $allcaps ) ) return $allcaps;
// if the post is not a future one, do nothing
if ( get_post_status( $args[2] ) !== 'future' ) return $allcaps;
// if we are here we have to prevent user to edit or delete post
if ( isset($allcaps['edit_posts']) ) unset($allcaps['edit_posts']);
if ( isset($allcaps['delete_posts']) ) unset($allcaps['delete_posts']);
return $allcaps;
}
Using this code the contributors will be still able to see the pending posts, but in read only way, just like the posts published by other users.