WordPress:自定义文章类型的功能

15
我正在编写一个插件,用于创建自定义的 post_type。我希望该插件还可以创建一个自定义的用户角色,该角色只能添加/编辑/删除新的 post_type。我尝试了几个插件(Role Scoper、Advanced Access manager),它们允许我重新定义或创建新的角色,但是它们不允许我为新的 post_type 分配特定的权限。例如,我想要允许添加/编辑我的新 post_type,但不允许添加/编辑普通的文章/页面。
据我所知,我可以使用 add_role() 函数添加新的用户角色。该函数的参数之一是一个“capabilities”数组,这些“capabilities”似乎在这里定义。我认为我需要做的是能够添加特定于我的 post_type 的权限。这是否可能?
2个回答

30

自定义文章类型的功能

register_post_type() 函数接受一个$capabilities数组作为其中一个(可选)参数。

它可能看起来像这样:

$capabilities = array(
    'publish_posts' => 'publish_ypts',
    'edit_posts' => 'edit_ypts',
    'edit_others_posts' => 'edit_others_ypts',
    'delete_posts' => 'delete_ypts',
    'delete_others_posts' => 'delete_others_ypts',
    'read_private_posts' => 'read_private_ypts',
    'edit_post' => 'edit_ypt',
    'delete_post' => 'delete_ypt',
    'read_post' => 'read_ypt'
);

"ypt" 代表 "您的文章类型"。

之后,您可以为 WordPress 添加一个新角色,该角色具有这些确切的功能(可能还包括一些标准 WordPress 功能):

add_role(
    'ypt_author',
    'Author of your post type',
    array(
        'publish_ypts' => true,
        'edit_ypts' => true,
        'edit_others_ypts' => true,
        'delete_ypts' => true,
        'delete_others_ypts' => true,
        'read_private_ypts' => true,
        'edit_ypt' => true,
        'delete_ypt' => true,
        'read_ypt' => true,
        // more standard capabilities here
    )
);

使用插件可以实现后者,例如,查看Justin Tadlock的Members插件。

详细示例

为了给您提供更具体的示例:

/* REGISTER POST TYPE */

add_action('init', 'ypt_register');

function ypt_register()
{

    $labels = array(
        'name' => _x('YPTs', 'post type general name'),
        'singular_name' => _x('YPT', 'post type singular name'),
        'add_new' => _x('Add New YPT', 'Team item'),
        'add_new_item' => __('Add a new post of type YPT'),
        'edit_item' => __('Edit YPT'),
        'new_item' => __('New YPT'),
        'view_item' => __('View YPT'),
        'search_items' => __('Search YPTs'),
        'not_found' =>  __('No YPTs found'),
        'not_found_in_trash' => __('No YPTs currently trashed'),
        'parent_item_colon' => ''
    );

    $capabilities = array(
        // this is where the first code block from above goes
    );

    $args = array(
        'labels' => $labels,
        'public' => true,
        'publicly_queryable' => true,
        'show_ui' => true,
        'query_var' => true,
        'rewrite' => true,
        'capability_type' => 'ypt',
        'capabilities' => $capabilities,
        'hierarchical' => false,
        'menu_position' => null,
        'supports' => array( 'title', 'author', 'thumbnail' )
    ); 

    register_post_type( 'ypt' , $args );

    flush_rewrite_rules( false );
}


/* MAP META CAPABILITIES */

add_filter( 'map_meta_cap', 'ypt_map_meta_cap', 10, 4 );

function ypt_map_meta_cap( $caps, $cap, $user_id, $args )
{

    if ( 'edit_ypt' == $cap || 'delete_ypt' == $cap || 'read_ypt' == $cap ) {
        $post = get_post( $args[0] );
        $post_type = get_post_type_object( $post->post_type );
        $caps = array();
    }

    if ( 'edit_ypt' == $cap ) {
        if ( $user_id == $post->post_author )
            $caps[] = $post_type->cap->edit_posts;
        else
            $caps[] = $post_type->cap->edit_others_posts;
    }

    elseif ( 'delete_ypt' == $cap ) {
        if ( $user_id == $post->post_author )
            $caps[] = $post_type->cap->delete_posts;
        else
            $caps[] = $post_type->cap->delete_others_posts;
    }

    elseif ( 'read_ypt' == $cap ) {
        if ( 'private' != $post->post_status )
            $caps[] = 'read';
        elseif ( $user_id == $post->post_author )
            $caps[] = 'read';
        else
            $caps[] = $post_type->cap->read_private_posts;
    }

    return $caps;
}

发布_ypt或任何其他特定于post_type的功能是如何定义的? - emersonthis
@Emerson 我回答的第一部分就是这个定义。$capabilities 数组是你放入 register_post_type() 函数中的参数之一。在其中,你将新的能力映射到常规文章的等效能力上。如果使用 register_post_type() 而没有使用此可选参数,则适用常规能力。如果使用了它,则 pubish_posts 能力不包括您的文章类型 - 作者必须具有 publish_ypt 能力。 - Johannes Pille
@Emerson,请查看我上面的编辑或者我的版本。请注意,由于您显然需要父母和子女,所以'hierarchical'需要设置为true。否则,我的示例同样适用于您的字典条目。 - Johannes Pille
我编辑了我的代码,但我能发现的唯一缺失的是: 'capability_type' => 'dictionary_entry',它仍然不起作用,但我认为可能还有其他我遗漏的东西。 - emersonthis
啊哈。我有几个东西放错了位置!我把能力数组和标签混淆了,而且我也错过了flush_rewrite_rules()。但现在它似乎可以工作了!对于任何跟进的人,我的当前代码在这里:http://pastebin.com/5JtW17gw - emersonthis
显示剩余9条评论

21

现在(WP 3.5+),这变得更加容易了。只需将map_meta_cap参数设置为TRUE,并在注册文章类型时选择一个string(通常是文章类型名称)作为capability_type参数。

一个简单的var_dump( $GLOBALS['wp_post_types']['new_custom_post_type'] ) );会显示以下内容。

[cap] => stdClass Object
(
    [edit_post]      => "edit_{$capability_type}"
    [read_post]      => "read_{$capability_type}"
    [delete_post]        => "delete_{$capability_type}"
    [edit_posts]         => "edit_{$capability_type}s"
    [edit_others_posts]  => "edit_others_{$capability_type}s"
    [publish_posts]      => "publish_{$capability_type}s"
    [read_private_posts]     => "read_private_{$capability_type}s"
        [delete_posts]           => "delete_{$capability_type}s"
        [delete_private_posts]   => "delete_private_{$capability_type}s"
        [delete_published_posts] => "delete_published_{$capability_type}s"
        [delete_others_posts]    => "delete_others_{$capability_type}s"
        [edit_private_posts]     => "edit_private_{$capability_type}s"
        [edit_published_posts]   => "edit_published_{$capability_type}s"
)

更多意图的数组部分是七个其他原始能力,这些能力未经核心检查,但在文章类型注册期间由map_meta_caps()映射。


6
对于那些仍在学习的新手,将map_meta_cap设置为true并将capability_type设置为您的内容类型,将自动生成所需的功能,因此您不必指定它们。 - Ben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接