Background:
I tried both https://wordpress.org/plugins/bainternet-posts-creation-limits and https://wordpress.org/plugins/limit-posts/, but they didn't work for some reason with my custom posts. So I decided to write my own php script, which I put into my child theme's function.php, to limit the number of certain custom posts types that certain users can create.
Structure:
I'm using wordpress 5.4.2 installed on bluehost. I am using geodirectory to create the custom post types (practitioners and organizations) and memberpress to manage permissions.
I decided to filter wp_post_data because all I want to do is change a post's status when first created, depending on how many posts the author has already created. Some suggested wp_insert_post_empty_content, but I think a better use-case is to allow them to create the actual post as a draft first, then ask them to get the proper membership to publish it.
Constraints:
Because another plugin on my site gives privileges to only a particular role, I am giving everyone who is not an admin that particular user role and therefore cannot limit posting privileges by user role. That is why I am using memberpress membership to govern publishing capability.
Issue/What is wrong:
After running the code:
1- All users, instead of just the non-admins with insufficient memberships, cannot save new CPT's. Even the admin cannot save a CPT.
2- Users get this message when they click submit: "You do not have the privileges to perform this action." I wrote a different message to give to a user who has the wrong membership for this action.
Approach:
<?php
//Before a newly created post is saved to the database, filter by membership
add_filter('wp_insert_post_data', 'tml_filter_by_membership', 99, 2);
/**
99 refers to the priority when this filter is executed; 99 indicates that it is one of the last filters executed on this action
2 indicates that we want both arguments given by the filter (because the second one contains sanitized but unmodified data--which is the data we want). Without 2, the function defaults to 1, giving us only slashed post data
*
*/
//filter by membership only acts on non-admin posts of certain post types
function tml_filter_by_membership($data, $postarr)
{
//take only non-admin posts
if (!user_can($postarr['post_author'], 'manage_options'))
{
// continue only if the post type is gd_practitioner or gd_studio
if ($postarr['post_type'] == 'gd_practitioner' || $postarr['post_type'] == 'gd_organization')
{
//Set membership post limits by post_type
$membership_post_limits = tml_set_membership_post_limits_by_post_type();
//Get author's membership
$author_memberships = tml_get_post_author_memberships($postarr);
//Look up the author's post limit for that post type within the membership post limits array
$author_post_limit = tml_get_author_post_limit($author_memberships, $membership_post_limits, $postarr);
//Count author's published posts of the particular post type
$number_of_published_posts_by_author = tml_get_author_published_posts($postarr);
//Compare number of published posts to author's post limit and return $postarr
tml_compare_posts_to_limit($author_post_limit, $number_of_published_posts_by_author, $postarr);
}
}
}
//set membership post limits by post_type
function tml_set_membership_post_limits_by_post_type()
{
$membership_post_limits = Array(
462 => Array(
'gd_practitioner' => 1,
'gd_organization' => 1
) ,
463 => Array(
'gd_practitioner' => 1,
'gd_organization' => 1
) ,
464 => Array(
'gd_practitioner' => 1,
'gd_organization' => 1
) ,
465 => Array(
'gd_practitioner' => 10,
'gd_organization' => 10
) ,
466 => Array(
'gd_practitioner' => 1,
'gd_organization' => 1
) ,
467 => Array(
'gd_practitioner' => 10,
'gd_organization' => 10
) ,
752 => Array(
'gd_practitioner' => 1,
'gd_organization' => 1
) ,
753 => Array(
'gd_practitioner' => 1,
'gd_organization' => 1
) ,
754 => Array(
'gd_practitioner' => 1,
'gd_organization' => 1
)
);
return $membership_post_limits;
}
//Get author's membership
function tml_get_post_author_memberships($postarr)
{
if (class_exists('MeprUser'))
{
$user_id = $postarr['post_author'];
$user = new MeprUser($user_id);
$get_memberships = $user->active_product_subscriptions();
$author_memberships = array_values(array_unique($get_memberships));
return $author_memberships;
}
else
{
return false;
}
}
//Look up the author's post limit for that post type within the membership post limits array, using $postarr to give the post type, and $user_memberships to give the author's memberships
function tml_get_author_post_limit($author_memberships, $membership_post_limits, $postarr)
{
$author_post_limit = 1;
foreach ($author_memberships as $membership)
{
if ($author_post_limit < $membership_post_limits[$membership][$postarr['post_type']])
{
$author_post_limit = $membership_post_limits[$membership][$postarr['post_type']];
}
}
return $author_post_limit;
}
//Count author's published posts of the particular post type
function tml_get_author_published_posts($postarr)
{
$posts = get_posts(array(
'author' => $postarr['post_author'],
'post_type ' => $postarr['post_type'],
'numberposts ' => - 1,
'post_status ' => 'publish'
));
$number_of_published_posts_by_author = count($posts);
return $number_of_published_posts_by_author;
}
/**
//Another option, using count_user_posts function instead
function tml_get_author_published_posts($postarr){
$author= $postarr['post_author'];
$post_type = $postarr['post_type'];
$number_of_published_posts_by_author=count_user_posts($author, $post_type);
return $number_of_published_posts_by_author;
}
*
*/
//Compare number of published posts to author's post limit
function tml_compare_posts_to_limit($author_post_limit, $number_of_published_posts_by_author, $postarr)
{
$message = "";
if ($number_of_published_posts_by_author >= $author_post_limit)
{
$postarr['post_status'] = 'draft';
$message = "You have exceeded the number of listings for your membership";
}
echo "<div> ${message} </div>";
return $postarr;
}