+ $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;
+}
+
+/**
+ * Builds an object with all post type capabilities out of a post type object
+ *
+ * Accepted keys of the capabilities array in the post type object:
+ * - edit_post - The meta capability that controls editing a particular object of this post type. Defaults to "edit_ . $capability_type" (edit_post).
+ * - edit_posts - The capability that controls editing objects of this post type as a class. Defaults to "edit_ . $capability_type . s" (edit_posts).
+ * - edit_others_posts - The capability that controls editing objects of this post type that are owned by other users. Defaults to "edit_others_ . $capability_type . s" (edit_others_posts).
+ * - publish_posts - The capability that controls publishing objects of this post type. Defaults to "publish_ . $capability_type . s" (publish_posts).
+ * - read_post - The meta capability that controls reading a particular object of this post type. Defaults to "read_ . $capability_type" (read_post).
+ * - read_private_posts - The capability that controls reading private posts. Defaults to "read_private . $capability_type . s" (read_private_posts).
+ * - delete_post - The meta capability that controls deleting a particular object of this post type. Defaults to "delete_ . $capability_type" (delete_post).
+ *
+ * @since 3.0.0
+ * @param object $args
+ * @return object object with all the capabilities as member variables
+ */
+function get_post_type_capabilities( $args ) {
+ $defaults = array(
+ 'edit_post' => 'edit_' . $args->capability_type,
+ 'edit_posts' => 'edit_' . $args->capability_type . 's',
+ 'edit_others_posts' => 'edit_others_' . $args->capability_type . 's',
+ 'publish_posts' => 'publish_' . $args->capability_type . 's',
+ 'read_post' => 'read_' . $args->capability_type,
+ 'read_private_posts' => 'read_private_' . $args->capability_type . 's',
+ 'delete_post' => 'delete_' . $args->capability_type,
+ );
+ $labels = array_merge( $defaults, $args->capabilities );
+ return (object) $labels;
+}
+
+/**
+ * Builds an object with all post type labels out of a post type object
+ *
+ * Accepted keys of the label array in the post type object:
+ * - name - general name for the post type, usually plural. The same and overriden by $post_type_object->label. Default is Posts/Pages
+ * - singular_name - name for one object of this post type. Default is Post/Page
+ * - add_new - Default is Add New for both hierarchical and non-hierarchical types. When internationalizing this string, please use a {@link http://codex.wordpress.org/I18n_for_WordPress_Developers#Disambiguation_by_context gettext context} matching your post type. Example: <code>_x('Add New', 'product');</code>
+ * - add_new_item - Default is Add New Post/Add New Page
+ * - edit_item - Default is Edit Post/Edit Page
+ * - new_item - Default is New Post/New Page
+ * - view_item - Default is View Post/View Page
+ * - search_items - Default is Search Posts/Search Pages
+ * - not_found - Default is No posts found/No pages found
+ * - not_found_in_trash - Default is No posts found in Trash/No pages found in Trash
+ * - parent_item_colon - This string isn't used on non-hierarchical types. In hierarchical ones the default is Parent Page:
+ *
+ * Above, the first default value is for non-hierarchical post types (like posts) and the second one is for hierarchical post types (like pages.)
+ *
+ * @since 3.0.0
+ * @param object $post_type_object
+ * @return object object with all the labels as member variables
+ */
+function get_post_type_labels( $post_type_object ) {
+ $nohier_vs_hier_defaults = array(
+ 'name' => array( _x('Posts', 'post type general name'), _x('Pages', 'post type general name') ),
+ 'singular_name' => array( _x('Post', 'post type singular name'), _x('Page', 'post type singular name') ),
+ 'add_new' => array( _x('Add New', 'post'), _x('Add New', 'page') ),
+ 'add_new_item' => array( __('Add New Post'), __('Add New Page') ),
+ 'edit_item' => array( __('Edit Post'), __('Edit Page') ),
+ 'new_item' => array( __('New Post'), __('New Page') ),
+ 'view_item' => array( __('View Post'), __('View Page') ),
+ 'search_items' => array( __('Search Posts'), __('Search Pages') ),
+ 'not_found' => array( __('No posts found'), __('No pages found') ),
+ 'not_found_in_trash' => array( __('No posts found in Trash'), __('No pages found in Trash') ),
+ 'parent_item_colon' => array( null, __('Parent Page:') )
+ );
+ return _get_custom_object_labels( $post_type_object, $nohier_vs_hier_defaults );
+}
+
+/**
+ * Builds an object with custom-something object (post type, taxonomy) labels out of a custom-something object
+ *
+ * @access private
+ */
+function _get_custom_object_labels( $object, $nohier_vs_hier_defaults ) {
+
+ if ( isset( $object->label ) && empty( $object->labels['name'] ) )
+ $object->labels['name'] = $object->label;
+
+ if ( !isset( $object->labels['singular_name'] ) && isset( $object->labels['name'] ) )
+ $object->labels['singular_name'] = $object->labels['name'];
+
+ $defaults = array_map( create_function( '$x', $object->hierarchical? 'return $x[1];' : 'return $x[0];' ), $nohier_vs_hier_defaults );
+ $labels = array_merge( $defaults, $object->labels );
+ return (object)$labels;
+}
+
+/**
+ * Register support of certain features for a post type.
+ *
+ * All features are directly associated with a functional area of the edit screen, such as the
+ * editor or a meta box: 'title', 'editor', 'comments', 'revisions', 'trackbacks', 'author',
+ * 'excerpt', 'page-attributes', 'thumbnail', and 'custom-fields'.
+ *
+ * Additionally, the 'revisions' feature dictates whether the post type will store revisions,
+ * and the 'comments' feature dicates whether the comments count will show on the edit screen.
+ *
+ * @since 3.0.0
+ * @param string $post_type The post type for which to add the feature
+ * @param string|array $feature the feature being added, can be an array of feature strings or a single string
+ */
+function add_post_type_support( $post_type, $feature ) {
+ global $_wp_post_type_features;
+
+ $features = (array) $feature;
+ foreach ($features as $feature) {
+ if ( func_num_args() == 2 )
+ $_wp_post_type_features[$post_type][$feature] = true;
+ else
+ $_wp_post_type_features[$post_type][$feature] = array_slice( func_get_args(), 2 );
+ }
+}
+
+/**
+ * Remove support for a feature from a post type.
+ *
+ * @since 3.0.0
+ * @param string $post_type The post type for which to remove the feature
+ * @param string $feature The feature being removed
+ */
+function remove_post_type_support( $post_type, $feature ) {
+ global $_wp_post_type_features;
+
+ if ( !isset($_wp_post_type_features[$post_type]) )
+ return;
+
+ if ( isset($_wp_post_type_features[$post_type][$feature]) )
+ unset($_wp_post_type_features[$post_type][$feature]);
+}
+
+/**
+ * Checks a post type's support for a given feature
+ *
+ * @since 3.0.0
+ * @param string $post_type The post type being checked
+ * @param string $feature the feature being checked
+ * @return boolean
+ */
+
+function post_type_supports( $post_type, $feature ) {
+ global $_wp_post_type_features;
+
+ if ( !isset( $_wp_post_type_features[$post_type][$feature] ) )
+ return false;
+
+ // If no args passed then no extra checks need be performed
+ if ( func_num_args() <= 2 )
+ return true;
+
+ // @todo Allow pluggable arg checking
+ //$args = array_slice( func_get_args(), 2 );
+
+ return true;