/** * Register a post type. Do not use before init. * * A function for creating or modifying a post type based on the * parameters given. The function will accept an array (second optional * parameter), along with a string for the post type name. * * @since 2.9.0 * @since 3.0.0 The `show_ui` argument is now enforced on the new post screen. * @since 4.4.0 The `show_ui` argument is now enforced on the post type listing screen and post editing screen. * * @global array $wp_post_types List of post types. * @global WP_Rewrite $wp_rewrite Used for default feeds. * @global WP $wp Used to add query vars. * * @param string $post_type Post type key, must not exceed 20 characters. * @param array|string $args { * Array or string of arguments for registering a post type. * * @type string $label Name of the post type shown in the menu. Usually plural. * Default is value of $labels['name']. * @type array $labels An array of labels for this post type. If not set, post * labels are inherited for non-hierarchical types and page * labels for hierarchical ones. {@see get_post_type_labels()}. * @type string $description A short descriptive summary of what the post type is. * Default empty. * @type bool $public Whether a post type is intended for use publicly either via * the admin interface or by front-end users. While the default * settings of $exclude_from_search, $publicly_queryable, $show_ui, * and $show_in_nav_menus are inherited from public, each does not * rely on this relationship and controls a very specific intention. * Default false. * @type bool $hierarchical Whether the post type is hierarchical (e.g. page). Default false. * @type bool $exclude_from_search Whether to exclude posts with this post type from front end search * results. Default is the opposite value of $public. * @type bool $publicly_queryable Whether queries can be performed on the front end for the post type * as part of {@see parse_request()}. Endpoints would include: * * ?post_type={post_type_key} * * ?{post_type_key}={single_post_slug} * * ?{post_type_query_var}={single_post_slug} * If not set, the default is inherited from $public. * @type bool $show_ui Whether to generate and allow a UI for managing this post type in the * admin. Default is value of $public. * @type bool $show_in_menu Where to show the post type in the admin menu. To work, $show_ui * must be true. If true, the post type is shown in its own top level * menu. If false, no menu is shown. If a string of an existing top * level menu (eg. 'tools.php' or 'edit.php?post_type=page'), the post * type will be placed as a sub-menu of that. * Default is value of $show_ui. * @type bool $show_in_nav_menus Makes this post type available for selection in navigation menus. * Default is value $public. * @type bool $show_in_admin_bar Makes this post type available via the admin bar. Default is value * of $show_in_menu. * @type int $menu_position The position in the menu order the post type should appear. To work, * $show_in_menu must be true. Default null (at the bottom). * @type string $menu_icon The url to the icon to be used for this menu. Pass a base64-encoded * SVG using a data URI, which will be colored to match the color scheme * -- this should begin with 'data:image/svg+xml;base64,'. Pass the name * of a Dashicons helper class to use a font icon, e.g. * 'dashicons-chart-pie'. Pass 'none' to leave div.wp-menu-image empty * so an icon can be added via CSS. Defaults to use the posts icon. * @type string $capability_type The string to use to build the read, edit, and delete capabilities. * May be passed as an array to allow for alternative plurals when using * this argument as a base to construct the capabilities, e.g. * array('story', 'stories'). Default 'post'. * @type array $capabilities Array of capabilities for this post type. $capability_type is used * as a base to construct capabilities by default. * {@see get_post_type_capabilities()}. * @type bool $map_meta_cap Whether to use the internal default meta capability handling. * Default false. * @type array $supports An alias for calling {@see add_post_type_support()} directly. * Defaults to array containing 'title' & 'editor'. * @type callable $register_meta_box_cb Provide a callback function that sets up the meta boxes for the * edit form. Do remove_meta_box() and add_meta_box() calls in the * callback. Default null. * @type array $taxonomies An array of taxonomy identifiers that will be registered for the * post type. Taxonomies can be registered later with * {@see register_taxonomy()} or {@see register_taxonomy_for_object_type()}. * Default empty array. * @type bool|string $has_archive Whether there should be post type archives, or if a string, the * archive slug to use. Will generate the proper rewrite rules if * $rewrite is enabled. Default false. * @type bool|array $rewrite { * Triggers the handling of rewrites for this post type. To prevent rewrite, set to false. * Defaults to true, using $post_type as slug. To specify rewrite rules, an array can be * passed with any of these keys: * * @type string $slug Customize the permastruct slug. Defaults to $post_type key. * @type bool $with_front Whether the permastruct should be prepended with WP_Rewrite::$front. * Default true. * @type bool $feeds Whether the feed permastruct should be built for this post type. * Default is value of $has_archive. * @type bool $pages Whether the permastruct should provide for pagination. Default true. * @type const $ep_mask Endpoint mask to assign. If not specified and permalink_epmask is set, * inherits from $permalink_epmask. If not specified and permalink_epmask * is not set, defaults to EP_PERMALINK. * } * @type string|bool $query_var Sets the query_var key for this post type. Defaults to $post_type * key. If false, a post type cannot be loaded at * ?{query_var}={post_slug}. If specified as a string, the query * ?{query_var_string}={post_slug} will be valid. * @type bool $can_export Whether to allow this post type to be exported. Default true. * @type bool $delete_with_user Whether to delete posts of this type when deleting a user. If true, * posts of this type belonging to the user will be moved to trash * when then user is deleted. If false, posts of this type belonging * to the user will *not* be trashed or deleted. If not set (the default), * posts are trashed if post_type_supports('author'). Otherwise posts * are not trashed or deleted. Default null. * @type bool $_builtin FOR INTERNAL USE ONLY! True if this post type is a native or * "built-in" post_type. Default false. * @type string $_edit_link FOR INTERNAL USE ONLY! URL segment to use for edit link of * this post type. Default 'post.php?post=%d'. * } * @return object|WP_Error The registered post type object, or an error object. */ function register_post_type($post_type, $args = array()) { global $wp_post_types, $wp_rewrite, $wp; if (!is_array($wp_post_types)) { $wp_post_types = array(); } // Sanitize post type name $post_type = sanitize_key($post_type); $args = wp_parse_args($args); /** * Filter the arguments for registering a post type. * * @since 4.4.0 * * @param array $args Array of arguments for registering a post type. * @param string $post_type Post type key. */ $args = apply_filters('register_post_type_args', $args, $post_type); $has_edit_link = !empty($args['_edit_link']); // Args prefixed with an underscore are reserved for internal use. $defaults = array('labels' => array(), 'description' => '', 'public' => false, 'hierarchical' => false, 'exclude_from_search' => null, 'publicly_queryable' => null, 'show_ui' => null, 'show_in_menu' => null, 'show_in_nav_menus' => null, 'show_in_admin_bar' => null, 'menu_position' => null, 'menu_icon' => null, 'capability_type' => 'post', 'capabilities' => array(), 'map_meta_cap' => null, 'supports' => array(), 'register_meta_box_cb' => null, 'taxonomies' => array(), 'has_archive' => false, 'rewrite' => true, 'query_var' => true, 'can_export' => true, 'delete_with_user' => null, '_builtin' => false, '_edit_link' => 'post.php?post=%d'); $args = array_merge($defaults, $args); $args = (object) $args; $args->name = $post_type; if (empty($post_type) || strlen($post_type) > 20) { _doing_it_wrong(__FUNCTION__, __('Post type names must be between 1 and 20 characters in length.'), '4.2'); return new WP_Error('post_type_length_invalid', __('Post type names must be between 1 and 20 characters in length.')); } // If not set, default to the setting for public. if (null === $args->publicly_queryable) { $args->publicly_queryable = $args->public; } // If not set, default to the setting for public. if (null === $args->show_ui) { $args->show_ui = $args->public; } // If not set, default to the setting for show_ui. if (null === $args->show_in_menu || !$args->show_ui) { $args->show_in_menu = $args->show_ui; } // If not set, default to the whether the full UI is shown. if (null === $args->show_in_admin_bar) { $args->show_in_admin_bar = (bool) $args->show_in_menu; } // If not set, default to the setting for public. if (null === $args->show_in_nav_menus) { $args->show_in_nav_menus = $args->public; } // If not set, default to true if not public, false if public. if (null === $args->exclude_from_search) { $args->exclude_from_search = !$args->public; } // Back compat with quirky handling in version 3.0. #14122. if (empty($args->capabilities) && null === $args->map_meta_cap && in_array($args->capability_type, array('post', 'page'))) { $args->map_meta_cap = true; } // If not set, default to false. if (null === $args->map_meta_cap) { $args->map_meta_cap = false; } // If there's no specified edit link and no UI, remove the edit link. if (!$args->show_ui && !$has_edit_link) { $args->_edit_link = ''; } $args->cap = get_post_type_capabilities($args); unset($args->capabilities); if (is_array($args->capability_type)) { $args->capability_type = $args->capability_type[0]; } if (!empty($args->supports)) { add_post_type_support($post_type, $args->supports); unset($args->supports); } elseif (false !== $args->supports) { // Add default features add_post_type_support($post_type, array('title', 'editor')); } if (false !== $args->query_var) { if (true === $args->query_var) { $args->query_var = $post_type; } else { $args->query_var = sanitize_title_with_dashes($args->query_var); } if ($wp && is_post_type_viewable($args)) { $wp->add_query_var($args->query_var); } } if (false !== $args->rewrite && (is_admin() || '' != get_option('permalink_structure'))) { if (!is_array($args->rewrite)) { $args->rewrite = array(); } if (empty($args->rewrite['slug'])) { $args->rewrite['slug'] = $post_type; } if (!isset($args->rewrite['with_front'])) { $args->rewrite['with_front'] = true; } if (!isset($args->rewrite['pages'])) { $args->rewrite['pages'] = true; } if (!isset($args->rewrite['feeds']) || !$args->has_archive) { $args->rewrite['feeds'] = (bool) $args->has_archive; } if (!isset($args->rewrite['ep_mask'])) { if (isset($args->permalink_epmask)) { $args->rewrite['ep_mask'] = $args->permalink_epmask; } else { $args->rewrite['ep_mask'] = EP_PERMALINK; } } if ($args->hierarchical) { add_rewrite_tag("%{$post_type}%", '(.+?)', $args->query_var ? "{$args->query_var}=" : "post_type={$post_type}&pagename="); } else { add_rewrite_tag("%{$post_type}%", '([^/]+)', $args->query_var ? "{$args->query_var}=" : "post_type={$post_type}&name="); } if ($args->has_archive) { $archive_slug = $args->has_archive === true ? $args->rewrite['slug'] : $args->has_archive; if ($args->rewrite['with_front']) { $archive_slug = substr($wp_rewrite->front, 1) . $archive_slug; } else { $archive_slug = $wp_rewrite->root . $archive_slug; } add_rewrite_rule("{$archive_slug}/?\$", "index.php?post_type={$post_type}", 'top'); if ($args->rewrite['feeds'] && $wp_rewrite->feeds) { $feeds = '(' . trim(implode('|', $wp_rewrite->feeds)) . ')'; add_rewrite_rule("{$archive_slug}/feed/{$feeds}/?\$", "index.php?post_type={$post_type}" . '&feed=$matches[1]', 'top'); add_rewrite_rule("{$archive_slug}/{$feeds}/?\$", "index.php?post_type={$post_type}" . '&feed=$matches[1]', 'top'); } if ($args->rewrite['pages']) { add_rewrite_rule("{$archive_slug}/{$wp_rewrite->pagination_base}/([0-9]{1,})/?\$", "index.php?post_type={$post_type}" . '&paged=$matches[1]', 'top'); } } $permastruct_args = $args->rewrite; $permastruct_args['feed'] = $permastruct_args['feeds']; add_permastruct($post_type, "{$args->rewrite['slug']}/%{$post_type}%", $permastruct_args); } // Register the post type meta box if a custom callback was specified. if ($args->register_meta_box_cb) { add_action('add_meta_boxes_' . $post_type, $args->register_meta_box_cb, 10, 1); } $args->labels = get_post_type_labels($args); $args->label = $args->labels->name; $wp_post_types[$post_type] = $args; add_action('future_' . $post_type, '_future_post_hook', 5, 2); foreach ($args->taxonomies as $taxonomy) { register_taxonomy_for_object_type($taxonomy, $post_type); } /** * Fires after a post type is registered. * * @since 3.3.0 * * @param string $post_type Post type. * @param object $args Arguments used to register the post type. */ do_action('registered_post_type', $post_type, $args); return $args; }
public function set_own_caps() { global $wp_post_types; $post_types = get_post_types(array(), 'objects'); $_post_types = $this->lib->_get_post_types(); foreach ($post_types as $post_type) { if (!in_array($post_type->name, $_post_types)) { continue; } if ($post_type->name == 'post' || $post_type->capability_type != 'post') { continue; } $wp_post_types[$post_type->name]->capability_type = $post_type->name; $wp_post_types[$post_type->name]->map_meta_cap = true; $cap_object = new stdClass(); $cap_object->capability_type = $wp_post_types[$post_type->name]->capability_type; $cap_object->map_meta_cap = true; $cap_object->capabilities = array(); $create_posts0 = $wp_post_types[$post_type->name]->cap->create_posts; $wp_post_types[$post_type->name]->cap = get_post_type_capabilities($cap_object); if ($post_type->name == 'attachment') { $wp_post_types[$post_type->name]->cap->create_posts = $create_posts0; // restore initial 'upload_files' } } }
/** * Init WooCommerce Memberships user roles * * @since 1.0.0 */ private static function init_user_roles() { global $wp_roles; if (class_exists('WP_Roles') && !isset($wp_roles)) { $wp_roles = new WP_Roles(); } // Allow shop managers and admins to manage membership plans and user memberships if (is_object($wp_roles)) { foreach (array('membership_plan', 'user_membership') as $post_type) { $args = new stdClass(); $args->map_meta_cap = true; $args->capability_type = $post_type; $args->capabilities = array(); foreach (get_post_type_capabilities($args) as $builtin => $mapped) { $wp_roles->add_cap('shop_manager', $mapped); $wp_roles->add_cap('administrator', $mapped); } } $wp_roles->add_cap('shop_manager', 'manage_woocommerce_membership_plans'); $wp_roles->add_cap('administrator', 'manage_woocommerce_membership_plans'); $wp_roles->add_cap('shop_manager', 'manage_woocommerce_user_memberships'); $wp_roles->add_cap('administrator', 'manage_woocommerce_user_memberships'); } }
/** * Register a post type. Do not use before init. * * A function for creating or modifying a post type based on the * parameters given. The function will accept an array (second optional * parameter), along with a string for the post type name. * * Optional $args contents: * * - label - Name of the post type shown in the menu. Usually plural. If not set, labels['name'] will be used. * - description - A short descriptive summary of what the post type is. Defaults to blank. * - public - Whether posts of this type should be shown in the admin UI. Defaults to false. * - exclude_from_search - Whether to exclude posts with this post type from search results. * Defaults to true if the type is not public, false if the type is public. * - publicly_queryable - Whether post_type queries can be performed from the front page. * Defaults to whatever public is set as. * - show_ui - Whether to generate a default UI for managing this post type. Defaults to true * if the type is public, false if the type is not public. * - show_in_menu - Where to show the post type in the admin menu. True for a top level menu, * false for no menu, or can be a top level page like 'tools.php' or 'edit.php?post_type=page'. * show_ui must be true. * - menu_position - The position in the menu order the post type should appear. Defaults to the bottom. * - menu_icon - The url to the icon to be used for this menu. Defaults to use the posts icon. * - capability_type - The string to use to build the read, edit, and delete capabilities. Defaults to 'post'. * May be passed as an array to allow for alternative plurals when using this argument as a base to construct the * capabilities, e.g. array('story', 'stories'). * - capabilities - Array of capabilities for this post type. By default the capability_type is used * as a base to construct capabilities. You can see accepted values in {@link get_post_type_capabilities()}. * - map_meta_cap - Whether to use the internal default meta capability handling. Defaults to false. * - hierarchical - Whether the post type is hierarchical. Defaults to false. * - supports - An alias for calling add_post_type_support() directly. See {@link add_post_type_support()} * for documentation. Defaults to none. * - register_meta_box_cb - Provide a callback function that will be called when setting up the * meta boxes for the edit form. Do remove_meta_box() and add_meta_box() calls in the callback. * - taxonomies - An array of taxonomy identifiers that will be registered for the post type. * Default is no taxonomies. Taxonomies can be registered later with register_taxonomy() or * register_taxonomy_for_object_type(). * - labels - An array of labels for this post type. By default post labels are used for non-hierarchical * types and page labels for hierarchical ones. You can see accepted values in {@link get_post_type_labels()}. * - permalink_epmask - The default rewrite endpoint bitmasks. * - has_archive - True to enable post type archives. Will generate the proper rewrite rules if rewrite is enabled. * - rewrite - false to prevent rewrite. Defaults to true. Use array('slug'=>$slug) to customize permastruct; * default will use $post_type as slug. Other options include 'with_front', 'feeds', and 'pages'. * - query_var - false to prevent queries, or string to value of the query var to use for this post type * - can_export - true allows this post type to be exported. * - show_in_nav_menus - true makes this post type available for selection in navigation menus. * - _builtin - true if this post type is a native or "built-in" post_type. THIS IS FOR INTERNAL USE ONLY! * - _edit_link - URL segement to use for edit link of this post type. THIS IS FOR INTERNAL USE ONLY! * * @since 2.9.0 * @uses $wp_post_types Inserts new post type object into the list * * @param string $post_type Name of the post type. * @param array|string $args See above description. * @return object|WP_Error the registered post type object, or an error object */ function register_post_type($post_type, $args = array()) { global $wp_post_types, $wp_rewrite, $wp; if (!is_array($wp_post_types)) { $wp_post_types = array(); } // Args prefixed with an underscore are reserved for internal use. $defaults = array('labels' => array(), 'description' => '', 'publicly_queryable' => null, 'exclude_from_search' => null, 'capability_type' => 'post', 'capabilities' => array(), 'map_meta_cap' => null, '_builtin' => false, '_edit_link' => 'post.php?post=%d', 'hierarchical' => false, 'public' => false, 'rewrite' => true, 'has_archive' => false, 'query_var' => true, 'supports' => array(), 'register_meta_box_cb' => null, 'taxonomies' => array(), 'show_ui' => null, 'menu_position' => null, 'menu_icon' => null, 'permalink_epmask' => EP_PERMALINK, 'can_export' => true, 'show_in_nav_menus' => null, 'show_in_menu' => null); $args = wp_parse_args($args, $defaults); $args = (object) $args; $post_type = sanitize_key($post_type); $args->name = $post_type; if (strlen($post_type) > 20) { return new WP_Error('post_type_too_long', __('Post types cannot exceed 20 characters in length')); } // If not set, default to the setting for public. if (null === $args->publicly_queryable) { $args->publicly_queryable = $args->public; } // If not set, default to the setting for public. if (null === $args->show_ui) { $args->show_ui = $args->public; } // If not set, default to the setting for show_ui. if (null === $args->show_in_menu || !$args->show_ui) { $args->show_in_menu = $args->show_ui; } // Whether to show this type in nav-menus.php. Defaults to the setting for public. if (null === $args->show_in_nav_menus) { $args->show_in_nav_menus = $args->public; } // If not set, default to true if not public, false if public. if (null === $args->exclude_from_search) { $args->exclude_from_search = !$args->public; } // Back compat with quirky handling in version 3.0. #14122 if (empty($args->capabilities) && null === $args->map_meta_cap && in_array($args->capability_type, array('post', 'page'))) { $args->map_meta_cap = true; } if (null === $args->map_meta_cap) { $args->map_meta_cap = false; } $args->cap = get_post_type_capabilities($args); unset($args->capabilities); if (is_array($args->capability_type)) { $args->capability_type = $args->capability_type[0]; } if (!empty($args->supports)) { add_post_type_support($post_type, $args->supports); unset($args->supports); } else { // Add default features add_post_type_support($post_type, array('title', 'editor')); } if (false !== $args->query_var && !empty($wp)) { if (true === $args->query_var) { $args->query_var = $post_type; } $args->query_var = sanitize_title_with_dashes($args->query_var); $wp->add_query_var($args->query_var); } if (false !== $args->rewrite && '' != get_option('permalink_structure')) { if (!is_array($args->rewrite)) { $args->rewrite = array(); } if (empty($args->rewrite['slug'])) { $args->rewrite['slug'] = $post_type; } if (!isset($args->rewrite['with_front'])) { $args->rewrite['with_front'] = true; } if (!isset($args->rewrite['pages'])) { $args->rewrite['pages'] = true; } if (!isset($args->rewrite['feeds']) || !$args->has_archive) { $args->rewrite['feeds'] = (bool) $args->has_archive; } if ($args->hierarchical) { $wp_rewrite->add_rewrite_tag("%{$post_type}%", '(.+?)', $args->query_var ? "{$args->query_var}=" : "post_type={$post_type}&name="); } else { $wp_rewrite->add_rewrite_tag("%{$post_type}%", '([^/]+)', $args->query_var ? "{$args->query_var}=" : "post_type={$post_type}&name="); } if ($args->has_archive) { $archive_slug = $args->has_archive === true ? $args->rewrite['slug'] : $args->has_archive; $wp_rewrite->add_rule("{$archive_slug}/?\$", "index.php?post_type={$post_type}", 'top'); if ($args->rewrite['feeds'] && $wp_rewrite->feeds) { $feeds = '(' . trim(implode('|', $wp_rewrite->feeds)) . ')'; $wp_rewrite->add_rule("{$archive_slug}/feed/{$feeds}/?\$", "index.php?post_type={$post_type}" . '&feed=$matches[1]', 'top'); $wp_rewrite->add_rule("{$archive_slug}/{$feeds}/?\$", "index.php?post_type={$post_type}" . '&feed=$matches[1]', 'top'); } if ($args->rewrite['pages']) { $wp_rewrite->add_rule("{$archive_slug}/{$wp_rewrite->pagination_base}/([0-9]{1,})/?\$", "index.php?post_type={$post_type}" . '&paged=$matches[1]', 'top'); } } $wp_rewrite->add_permastruct($post_type, "{$args->rewrite['slug']}/%{$post_type}%", $args->rewrite['with_front'], $args->permalink_epmask); } if ($args->register_meta_box_cb) { add_action('add_meta_boxes_' . $post_type, $args->register_meta_box_cb, 10, 1); } $args->labels = get_post_type_labels($args); $args->label = $args->labels->name; $wp_post_types[$post_type] = $args; add_action('future_' . $post_type, '_future_post_hook', 5, 2); foreach ($args->taxonomies as $taxonomy) { register_taxonomy_for_object_type($taxonomy, $post_type); } return $args; }
/** * Restrict access to edit or delete posts based on the post's access restrictions. * * @param array $caps * @param string $cap * @param int $user_id * @param array $args * @return array */ public static function map_meta_cap($caps, $cap, $user_id, $args) { if (isset($args[0])) { if (strpos($cap, 'edit_') === 0 || strpos($cap, 'delete_') === 0) { if ($post_type = get_post_type($args[0])) { $edit_post_type = 'edit_' . $post_type; $delete_post_type = 'delete_' . $post_type; if ($post_type_object = get_post_type_object($post_type)) { if (!isset($post_type_object->capabilities)) { $post_type_object->capabilities = array(); } $caps_object = get_post_type_capabilities($post_type_object); if (isset($caps_object->edit_post)) { $edit_post_type = $caps_object->edit_post; } if (isset($caps_object->delete_post)) { $delete_post_type = $caps_object->delete_post; } } if ($cap === $edit_post_type || $cap === $delete_post_type) { $post_id = null; if (is_numeric($args[0])) { $post_id = $args[0]; } else { if ($args[0] instanceof WP_Post) { $post_id = $post->ID; } } if ($post_id) { if (!self::user_can_read_post($post_id, $user_id)) { $caps[] = 'do_not_allow'; } } } } } } return $caps; }
/** * Register a post type. Do not use before init. * * A simple function for creating or modifying a post type based on the * parameters given. The function will accept an array (second optional * parameter), along with a string for the post type name. * * * Optional $args contents: * * - label - Name of the post type shown in the menu. Usually plural. If not set, labels['name'] will be used. * - description - A short descriptive summary of what the post type is. Defaults to blank. * - public - Whether posts of this type should be shown in the admin UI. Defaults to false. * - exclude_from_search - Whether to exclude posts with this post type from search results. Defaults to true if the type is not public, false if the type is public. * - publicly_queryable - Whether post_type queries can be performed from the front page. Defaults to whatever public is set as. * - show_ui - Whether to generate a default UI for managing this post type. Defaults to true if the type is public, false if the type is not public. * - menu_position - The position in the menu order the post type should appear. Defaults to the bottom. * - menu_icon - The url to the icon to be used for this menu. Defaults to use the posts icon. * - capability_type - The post type to use for checking read, edit, and delete capabilities. Defaults to "post". * - capabilities - Array of capabilities for this post type. You can see accepted values in {@link get_post_type_capabilities()}. By default the capability_type is used to construct capabilities. * - hierarchical - Whether the post type is hierarchical. Defaults to false. * - supports - An alias for calling add_post_type_support() directly. See add_post_type_support() for Documentation. Defaults to none. * - register_meta_box_cb - Provide a callback function that will be called when setting up the meta boxes for the edit form. Do remove_meta_box() and add_meta_box() calls in the callback. * - taxonomies - An array of taxonomy identifiers that will be registered for the post type. Default is no taxonomies. Taxonomies can be registered later with register_taxonomy() or register_taxonomy_for_object_type(). * - labels - An array of labels for this post type. You can see accepted values in {@link get_post_type_labels()}. By default post labels are used for non-hierarchical types and page labels for hierarchical ones. * - permalink_epmask - The default rewrite endpoint bitmasks. * - rewrite - false to prevent rewrite, or array('slug'=>$slug) to customize permastruct; default will use $post_type as slug. * - query_var - false to prevent queries, or string to value of the query var to use for this post type * - can_export - true allows this post type to be exported. * - show_in_nav_menus - true makes this post type available for selection in navigation menus. * - _builtin - true if this post type is a native or "built-in" post_type. THIS IS FOR INTERNAL USE ONLY! * - _edit_link - URL segement to use for edit link of this post type. Set to 'post.php?post=%d'. THIS IS FOR INTERNAL USE ONLY! * * @since 2.9.0 * @uses $wp_post_types Inserts new post type object into the list * * @param string $post_type Name of the post type. * @param array|string $args See above description. * @return object the registered post type object */ function register_post_type($post_type, $args = array()) { global $wp_post_types, $wp_rewrite, $wp; if (!is_array($wp_post_types)) { $wp_post_types = array(); } // Args prefixed with an underscore are reserved for internal use. $defaults = array('labels' => array(), 'description' => '', 'publicly_queryable' => null, 'exclude_from_search' => null, '_builtin' => false, '_edit_link' => 'post.php?post=%d', 'capability_type' => 'post', 'capabilities' => array(), 'hierarchical' => false, 'public' => false, 'rewrite' => true, 'query_var' => true, 'supports' => array(), 'register_meta_box_cb' => null, 'taxonomies' => array(), 'show_ui' => null, 'menu_position' => null, 'menu_icon' => null, 'permalink_epmask' => EP_PERMALINK, 'can_export' => true, 'show_in_nav_menus' => null); $args = wp_parse_args($args, $defaults); $args = (object) $args; $post_type = sanitize_user($post_type, true); $args->name = $post_type; // If not set, default to the setting for public. if (null === $args->publicly_queryable) { $args->publicly_queryable = $args->public; } // If not set, default to the setting for public. if (null === $args->show_ui) { $args->show_ui = $args->public; } // Whether to show this type in nav-menus.php. Defaults to the setting for public. if (null === $args->show_in_nav_menus) { $args->show_in_nav_menus = $args->public; } // If not set, default to true if not public, false if public. if (null === $args->exclude_from_search) { $args->exclude_from_search = !$args->public; } if (empty($args->capability_type)) { $args->capability_type = 'post'; } $args->cap = get_post_type_capabilities($args); unset($args->capabilities); if (!empty($args->supports)) { add_post_type_support($post_type, $args->supports); unset($args->supports); } else { // Add default features add_post_type_support($post_type, array('title', 'editor')); } if (false !== $args->query_var && !empty($wp)) { if (true === $args->query_var) { $args->query_var = $post_type; } $args->query_var = sanitize_title_with_dashes($args->query_var); $wp->add_query_var($args->query_var); } if (false !== $args->rewrite && '' != get_option('permalink_structure')) { if (!is_array($args->rewrite)) { $args->rewrite = array(); } if (!isset($args->rewrite['slug'])) { $args->rewrite['slug'] = $post_type; } if (!isset($args->rewrite['with_front'])) { $args->rewrite['with_front'] = true; } if ($args->hierarchical) { $wp_rewrite->add_rewrite_tag("%{$post_type}%", '(.+?)', $args->query_var ? "{$args->query_var}=" : "post_type={$post_type}&name="); } else { $wp_rewrite->add_rewrite_tag("%{$post_type}%", '([^/]+)', $args->query_var ? "{$args->query_var}=" : "post_type={$post_type}&name="); } $wp_rewrite->add_permastruct($post_type, "{$args->rewrite['slug']}/%{$post_type}%", $args->rewrite['with_front'], $args->permalink_epmask); } if ($args->register_meta_box_cb) { add_action('add_meta_boxes_' . $post_type, $args->register_meta_box_cb, 10, 1); } $args->labels = get_post_type_labels($args); $args->label = $args->labels->name; $wp_post_types[$post_type] = $args; add_action('future_' . $post_type, '_future_post_hook', 5, 2); foreach ($args->taxonomies as $taxonomy) { register_taxonomy_for_object_type($taxonomy, $post_type); } return $args; }
private function get_post_type_capabilities($post_type) { $args = $this->registered_post_type_args[$post_type]; if (is_array($args->capability_type) || $args->capability_type !== 'post') { return $args->cap; } $args->capability_type = $post_type; $args->map_meta_cap = TRUE; $args->capabilities = array(); return get_post_type_capabilities($args); }
/** * Sets post type properties. * * @since 4.6.0 * @access public * * @param array|string $args Array or string of arguments for registering a post type. */ public function set_props($args) { $args = wp_parse_args($args); /** * Filters the arguments for registering a post type. * * @since 4.4.0 * * @param array $args Array of arguments for registering a post type. * @param string $post_type Post type key. */ $args = apply_filters('register_post_type_args', $args, $this->name); $has_edit_link = !empty($args['_edit_link']); // Args prefixed with an underscore are reserved for internal use. $defaults = array('labels' => array(), 'description' => '', 'public' => false, 'hierarchical' => false, 'exclude_from_search' => null, 'publicly_queryable' => null, 'show_ui' => null, 'show_in_menu' => null, 'show_in_nav_menus' => null, 'show_in_admin_bar' => null, 'menu_position' => null, 'menu_icon' => null, 'capability_type' => 'post', 'capabilities' => array(), 'map_meta_cap' => null, 'supports' => array(), 'register_meta_box_cb' => null, 'taxonomies' => array(), 'has_archive' => false, 'rewrite' => true, 'query_var' => true, 'can_export' => true, 'delete_with_user' => null, '_builtin' => false, '_edit_link' => 'post.php?post=%d'); $args = array_merge($defaults, $args); $args['name'] = $this->name; // If not set, default to the setting for public. if (null === $args['publicly_queryable']) { $args['publicly_queryable'] = $args['public']; } // If not set, default to the setting for public. if (null === $args['show_ui']) { $args['show_ui'] = $args['public']; } // If not set, default to the setting for show_ui. if (null === $args['show_in_menu'] || !$args['show_ui']) { $args['show_in_menu'] = $args['show_ui']; } // If not set, default to the whether the full UI is shown. if (null === $args['show_in_admin_bar']) { $args['show_in_admin_bar'] = (bool) $args['show_in_menu']; } // If not set, default to the setting for public. if (null === $args['show_in_nav_menus']) { $args['show_in_nav_menus'] = $args['public']; } // If not set, default to true if not public, false if public. if (null === $args['exclude_from_search']) { $args['exclude_from_search'] = !$args['public']; } // Back compat with quirky handling in version 3.0. #14122. if (empty($args['capabilities']) && null === $args['map_meta_cap'] && in_array($args['capability_type'], array('post', 'page'))) { $args['map_meta_cap'] = true; } // If not set, default to false. if (null === $args['map_meta_cap']) { $args['map_meta_cap'] = false; } // If there's no specified edit link and no UI, remove the edit link. if (!$args['show_ui'] && !$has_edit_link) { $args['_edit_link'] = ''; } $this->cap = get_post_type_capabilities((object) $args); unset($args['capabilities']); if (is_array($args['capability_type'])) { $args['capability_type'] = $args['capability_type'][0]; } if (false !== $args['query_var']) { if (true === $args['query_var']) { $args['query_var'] = $this->name; } else { $args['query_var'] = sanitize_title_with_dashes($args['query_var']); } } if (false !== $args['rewrite'] && (is_admin() || '' != get_option('permalink_structure'))) { if (!is_array($args['rewrite'])) { $args['rewrite'] = array(); } if (empty($args['rewrite']['slug'])) { $args['rewrite']['slug'] = $this->name; } if (!isset($args['rewrite']['with_front'])) { $args['rewrite']['with_front'] = true; } if (!isset($args['rewrite']['pages'])) { $args['rewrite']['pages'] = true; } if (!isset($args['rewrite']['feeds']) || !$args['has_archive']) { $args['rewrite']['feeds'] = (bool) $args['has_archive']; } if (!isset($args['rewrite']['ep_mask'])) { if (isset($args['permalink_epmask'])) { $args['rewrite']['ep_mask'] = $args['permalink_epmask']; } else { $args['rewrite']['ep_mask'] = EP_PERMALINK; } } } foreach ($args as $property_name => $property_value) { $this->{$property_name} = $property_value; } $this->labels = get_post_type_labels($this); $this->label = $this->labels->name; }
/** * Save capability options. * * @param int $post_id * @param mixed $post post data (not used here) */ public static function save_post($post_id = null, $post = null) { if (defined("DOING_AUTOSAVE") && DOING_AUTOSAVE) { } else { $post_type = get_post_type($post_id); $post_type_object = get_post_type_object($post_type); if ($post_type_object && $post_type != 'attachment') { $post_types_option = Groups_Options::get_option(Groups_Post_Access::POST_TYPES, array()); if (!isset($post_types_option[$post_type]['add_meta_box']) || $post_types_option[$post_type]['add_meta_box']) { if (isset($_POST[self::NONCE]) && wp_verify_nonce($_POST[self::NONCE], self::SET_CAPABILITY)) { $post_type = isset($_POST["post_type"]) ? $_POST["post_type"] : null; if ($post_type !== null) { // See http://codex.wordpress.org/Function_Reference/current_user_can 20130119 WP 3.5 // "... Some capability checks (like 'edit_post' or 'delete_page') require this [the post ID] be provided." // If the post ID is not provided, it will throw: // PHP Notice: Undefined offset: 0 in /var/www/groups-forums/wp-includes/capabilities.php on line 1067 $edit_post_type = 'edit_' . $post_type; if ($post_type_object = get_post_type_object($post_type)) { if (!isset($post_type_object->capabilities)) { // get_post_type_capabilities() (WP 3.8) will throw a warning // when trying to merge the missing property otherwise. It's either a // bug or the function's documentation should make it clear that you // have to provide that. $post_type_object->capabilities = array(); } $caps_object = get_post_type_capabilities($post_type_object); if (isset($caps_object->edit_post)) { $edit_post_type = $caps_object->edit_post; } } if (current_user_can($edit_post_type, $post_id)) { // quick-create ? if (current_user_can(GROUPS_ADMINISTER_GROUPS)) { if (!empty($_POST['quick-group-capability'])) { $creator_id = get_current_user_id(); $datetime = date('Y-m-d H:i:s', time()); $name = ucfirst(strtolower(trim($_POST['quick-group-capability']))); if (strlen($name) > 0) { // create or obtain the group if ($group = Groups_Group::read_by_name($name)) { } else { if ($group_id = Groups_Group::create(compact('creator_id', 'datetime', 'name'))) { $group = Groups_Group::read($group_id); } } // create or obtain the capability $name = strtolower($name); if ($capability = Groups_Capability::read_by_capability($name)) { } else { if ($capability_id = Groups_Capability::create(array('capability' => $name))) { $capability = Groups_Capability::read($capability_id); } } if ($group && $capability) { // add the capability to the group if (!Groups_Group_Capability::read($group->group_id, $capability->capability_id)) { Groups_Group_Capability::create(array('group_id' => $group->group_id, 'capability_id' => $capability->capability_id)); } // enable the capability for access restriction $valid_read_caps = Groups_Options::get_option(Groups_Post_Access::READ_POST_CAPABILITIES, array(Groups_Post_Access::READ_POST_CAPABILITY)); if (!in_array($capability->capability, $valid_read_caps)) { $valid_read_caps[] = $capability->capability; } Groups_Options::update_option(Groups_Post_Access::READ_POST_CAPABILITIES, $valid_read_caps); // add the current user to the group Groups_User_Group::create(array('user_id' => get_current_user_id(), 'group_id' => $group->group_id)); // put the capability ID in $_POST[self::CAPABILITY] so it is treated below if (empty($_POST[self::CAPABILITY])) { $_POST[self::CAPABILITY] = array(); } if (!in_array($capability->capability_id, $_POST[self::CAPABILITY])) { $_POST[self::CAPABILITY][] = $capability->capability_id; } } } } } // set if (self::user_can_restrict()) { $valid_read_caps = self::get_valid_read_caps_for_user(); foreach ($valid_read_caps as $valid_read_cap) { if ($capability = Groups_Capability::read_by_capability($valid_read_cap)) { if (!empty($_POST[self::CAPABILITY]) && is_array($_POST[self::CAPABILITY]) && in_array($capability->capability_id, $_POST[self::CAPABILITY])) { Groups_Post_Access::create(array('post_id' => $post_id, 'capability' => $capability->capability)); } else { Groups_Post_Access::delete($post_id, $capability->capability); } } } } // show groups Groups_Options::update_user_option(self::SHOW_GROUPS, !empty($_POST[self::SHOW_GROUPS])); } } } } } } }
/** * Maps rules and settings for post types registered outside of Types. * * @param type $post_type * @param type $args */ function wpcf_access_registered_post_type_hook($post_type, $args) { global $wpcf_access, $wp_post_types; $settings_access = get_option('wpcf-access-types', array()); if (isset($settings_access[$post_type])) { $data = $settings_access[$post_type]; // Mark that will inherit post settings // TODO New types to be added if (!in_array($post_type, array('post', 'page', 'attachment', 'media')) && (empty($wp_post_types[$post_type]->capability_type) || $wp_post_types[$post_type]->capability_type == 'post')) { $wp_post_types[$post_type]->_wpcf_access_inherits_post_cap = 1; } if ($data['mode'] == 'not_managed') { return false; } // Force map meta caps $wp_post_types[$post_type]->capability_type = array(sanitize_title($wp_post_types[$post_type]->labels->singular_name), sanitize_title($wp_post_types[$post_type]->labels->name)); $wp_post_types[$post_type]->map_meta_cap = true; $wp_post_types[$post_type]->capabilities = array(); $wp_post_types[$post_type]->cap = get_post_type_capabilities($wp_post_types[$post_type]); unset($wp_post_types[$post_type]->capabilities); $caps = wpcf_access_types_caps(); $mapped = array(); // Map predefined foreach ($caps as $cap_slug => $cap_spec) { if (isset($data['permissions'][$cap_spec['predefined']])) { $mapped[$cap_slug] = $data['permissions'][$cap_spec['predefined']]; } else { $mapped[$cap_slug] = $cap_spec['predefined']; } } // Set rule settings for post type by pre-defined caps foreach ($args->cap as $cap_slug => $cap_spec) { if (isset($mapped[$cap_slug])) { if (isset($mapped[$cap_slug]['role'])) { $wpcf_access->rules->types[$cap_spec]['role'] = $mapped[$cap_slug]['role']; } else { $wpcf_access->rules->types[$cap_spec]['role'] = 'administrator'; } $wpcf_access->rules->types[$cap_spec]['users'] = isset($mapped[$cap_slug]['users']) ? $mapped[$cap_slug]['users'] : array(); $wpcf_access->rules->types[$cap_spec]['types'][$args->name] = 1; } } // TODO create_posts set manually for now // Monitor WP changes if (!isset($wpcf_access->rules->types['create_posts'])) { $wpcf_access->rules->types['create_posts'] = $wpcf_access->rules->types['edit_posts']; } if (!isset($wpcf_access->rules->types['create_post'])) { $wpcf_access->rules->types['create_post'] = $wpcf_access->rules->types['edit_post']; } } // Check read permissions // Check unlogged user settings $check_read = false; if (isset($settings_access[$post_type])) { $data = $settings_access[$post_type]; $check_read = true; } if ($check_read) { if ($data['mode'] == 'not_managed') { return false; } // Mark post type as hidden if (!empty($data['permissions']['read']['role'])) { wpcf_access_hide_post_type($data['permissions']['read']['role'], $post_type); } else { // Missed setting? Debug that! $wpcf_access->errors['hide_post'][$post_type] = array('data' => $data); } } }
/** * Maps rules and settings for post types registered outside of Types. * * @param type $post_type * @param type $args */ public static function wpcf_access_registered_post_type_hook($post_type, $args) { global $wpcf_access, $wp_post_types; static $_builtin_types = null; $model = TAccess_Loader::get('MODEL/Access'); $settings_access = $model->getAccessTypes(); if (isset($wp_post_types[$post_type])) { // Force map meta caps, if not builtin if (in_array($post_type, array('post', 'page'))) { switch ($post_type) { case 'page': $_sing = 'page'; $_plur = 'pages'; break; case 'post': default: $_sing = 'post'; $_plur = 'posts'; break; } } else { // else use singular/plural names $_sing = sanitize_title($wp_post_types[$post_type]->labels->singular_name); $_plur = sanitize_title($wp_post_types[$post_type]->labels->name); if ($_sing == $_plur) { $_plur = $_plur . '_s'; } } $capability_type = array($_sing, $_plur); // set singular / plural caps based on names or default for builtins $tmp = unserialize(serialize($wp_post_types[$post_type])); $tmp->capability_type = $capability_type; $tmp->map_meta_cap = true; $tmp->capabilities = array(); $tmp->cap = get_post_type_capabilities($tmp); // provide access pointers $wp_post_types[$post_type]->__accessIsCapValid = !self::wpcf_check_cap_conflict(array_values((array) $tmp->cap)); $wp_post_types[$post_type]->__accessIsNameValid = self::wpcf_is_object_valid('type', self::wpcf_object_to_array($tmp)); $wp_post_types[$post_type]->__accessNewCaps = $tmp->cap; if (isset($settings_access[$post_type])) { $data = $settings_access[$post_type]; /*if (null===$_builtin_types) { $_builtin_types=get_post_types(array('_builtin' => true), 'names'); }*/ // Mark that will inherit post settings // TODO New types to be added if (!in_array($post_type, array('post', 'page', 'attachment', 'media')) && (empty($wp_post_types[$post_type]->capability_type) || $wp_post_types[$post_type]->capability_type == 'post')) { $wp_post_types[$post_type]->_wpcf_access_inherits_post_cap = 1; } if ($data['mode'] == 'not_managed' || !$wp_post_types[$post_type]->__accessIsCapValid || !$wp_post_types[$post_type]->__accessIsNameValid) { $settings_access[$post_type]['mode'] = 'not_managed'; $model->updateAccessTypes($settings_access); return false; } $caps = self::wpcf_access_types_caps(); $mapped = array(); // Map predefined foreach ($caps as $cap_slug => $cap_spec) { if (isset($data['permissions'][$cap_spec['predefined']])) { $mapped[$cap_slug] = $data['permissions'][$cap_spec['predefined']]; } else { $mapped[$cap_slug] = $cap_spec['predefined']; } } // set singular / plural caps based on names or default for builtins $wp_post_types[$post_type]->capability_type = $capability_type; $wp_post_types[$post_type]->map_meta_cap = true; $wp_post_types[$post_type]->capabilities = array(); $wp_post_types[$post_type]->cap = get_post_type_capabilities($wp_post_types[$post_type]); //$wp_post_types[$post_type]=$tmp; unset($wp_post_types[$post_type]->capabilities); // Set rule settings for post type by pre-defined caps foreach ($args->cap as $cap_slug => $cap_spec) { if (isset($mapped[$cap_slug])) { if (isset($mapped[$cap_slug]['role'])) { $wpcf_access->rules->types[$cap_spec]['role'] = $mapped[$cap_slug]['role']; } else { $wpcf_access->rules->types[$cap_spec]['role'] = 'administrator'; } $wpcf_access->rules->types[$cap_spec]['users'] = isset($mapped[$cap_slug]['users']) ? $mapped[$cap_slug]['users'] : array(); $wpcf_access->rules->types[$cap_spec]['types'][$post_type] = 1; } } //taccess_log(array($post_type, $args->cap, $mapped, $wpcf_access->rules->types)); // TODO create_posts set manually for now // Monitor WP changes if (!isset($wpcf_access->rules->types['create_posts']) && isset($wpcf_access->rules->types['edit_posts'])) { $wpcf_access->rules->types['create_posts'] = $wpcf_access->rules->types['edit_posts']; } /*if (!isset($wpcf_access->rules->types['create_pages']) && isset($wpcf_access->rules->types['edit_pages'])) { $wpcf_access->rules->types['create_pages'] = $wpcf_access->rules->types['edit_pages']; }*/ if (!isset($wpcf_access->rules->types['create_post']) && isset($wpcf_access->rules->types['edit_post'])) { $wpcf_access->rules->types['create_post'] = $wpcf_access->rules->types['edit_post']; } /*if (!isset($wpcf_access->rules->types['create_page']) && isset($wpcf_access->rules->types['edit_page'])) { $wpcf_access->rules->types['create_page'] = $wpcf_access->rules->types['edit_page']; }*/ // Check frontend read if ($data['mode'] != 'not_managed' && !is_admin()) { // Check read if ($data['mode'] != 'not_managed') { // Set min reading role if (isset($data['permissions']['read']['role'])) { self::set_frontend_read_permissions($data['permissions']['read']['role'], $post_type); } else { // Missed setting? Debug that! $wpcf_access->errors['missing_settings']['read'][] = array('caps' => $caps, 'data' => $data); } } } } } }