如何限制某些用户可以使用php脚本在wordpress中发布的自定义帖子数量?

时间:2020-06-23 作者:Simon Templar

背景:
我两次都试过了https://wordpress.org/plugins/bainternet-posts-creation-limitshttps://wordpress.org/plugins/limit-posts/, 但由于某种原因,它们在我的自定义帖子中不起作用。所以我决定编写自己的php脚本,并将其放入子主题的函数中。php,以限制特定用户可以创建的特定自定义帖子类型的数量。

结构:
我正在使用安装在bluehost上的wordpress 5.4.2。我正在使用GeodDirectory创建自定义帖子类型(从业者和组织),并使用memberpress管理权限
我决定过滤wp\\u post\\u数据,因为我只想在第一次创建帖子时更改帖子的状态,这取决于作者已经创建了多少篇帖子。一些人建议wp\\U insert\\U post\\U empty\\U内容,但我认为一个更好的用例是允许他们先将实际帖子创建为草稿,然后要求他们获得适当的成员资格来发布它。

限制条件:
因为我网站上的另一个插件只给特定角色授予权限,所以我给每个非管理员的人都赋予了该特定用户角色,因此无法按用户角色限制发布权限。这就是为什么我使用memberpress成员资格来管理发布能力。

Issue/What is wrong:
运行代码后:
1-所有用户,而不仅仅是成员资格不足的非管理员,都无法保存新的CPT。即使管理员也无法保存CPT
2-用户单击“提交”时会收到此消息:“提交”;您没有执行此操作的权限"E;我写了一条不同的消息,给这个操作的错误成员身份的用户。

方法:

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

1 个回复
SO网友:Himad

欢迎使用StackExchange!我对您的代码做了一些更改,并在注释中指出了这些更改。我不确定这是否真的会起作用,所以你必须尝试一下,也许你回显消息的方式不会起作用,因为更新后会有一个重定向,所以你必须使用admin_notices 采取行动并找到某种方法在重定向后保留消息,但我认为这是另一个问题的主题,所以我用error_log 通过查看日志,就足以知道这是否按预期工作。

<?php
add_filter(\'wp_insert_post_data\', \'tml_filter_by_membership\', 99, 2);

/* 
When using a filter, the first argument is always the data to be modified and returned. 
Usually you\'ll do your checks to see if you want to modify something, otherwise you\'ll return
the first argument ($data) so other filters can work as well. If you return nothing,
then you will probably break something. Here you should use $data instead of $postarr,
which are the same array but the later ($postarr) is unescaped.
*/
function tml_filter_by_membership($data, $postarr)
{

    /* If you want to take only non-administrator users, don\'t check for capacity, check
 instead for that specific role. */
    if (!in_array(\'administrator\', get_user_by(\'ID\', $data[\'post_author\'])->roles))
    {

        if ($data[\'post_type\'] == \'gd_practitioner\' || $data[\'post_type\'] == \'gd_organization\')
        {

            $membership_post_limits = tml_set_membership_post_limits_by_post_type();

            $author_memberships = tml_get_post_author_memberships($data[\'post_author\']);

            $author_post_limit = tml_get_author_post_limit($author_memberships, $membership_post_limits, $data);

            $number_of_published_posts_by_author = tml_get_author_published_posts($data);
            /* I thought the last function was unnecessary so I just deleted it and moved
 it\'s code in here. */
            if ($number_of_published_posts_by_author >= $author_post_limit)
            {
                $data[\'post_status\'] = \'draft\';
                /* Check yours logs to see if this is actually working. Displaying the
 message is something you can solve afterwards. */
                error_log(\'You have exceeded the number of listings for your membership\');
            }
            /* Return your modified object. Before this, you were using a function which
 returned something, but the return has to be inside the scope of the function linked to
 the filter in order to actually return it. Previously you were returning nothing. */
            return $data;
            
        }
    }

    return $data;
}

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

function tml_get_post_author_memberships($user_id)
{
    if (class_exists(\'MeprUser\'))
    {

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


function tml_get_author_post_limit($author_memberships, $membership_post_limits, $data)
{
    $author_post_limit = 1;
    foreach ($author_memberships as $membership)
    {
        if ($author_post_limit < $membership_post_limits[$membership][$data[\'post_type\']])
        {
            $author_post_limit = $membership_post_limits[$membership][$data[\'post_type\']];
        }
    }
    return $author_post_limit;
}

function tml_get_author_published_posts($data)
{

    return count(get_posts(array(
        \'author\' => $data[\'post_author\'],
        \'post_type \' => $data[\'post_type\'],
        \'numberposts \' => - 1,
        \'post_status \' => \'publish\'
    )));

}