'addifect_design', 'rewrite_slug' => 'addifect_design', 'archive_slug' => false, 'singular_name' => __( 'Addifect Design', 'addifect' ), 'plural_name' => __( 'Addifect Designs', 'addifect' ), 'menu_icon' => 'dashicons-layout', 'public' => false, 'show_in_rest' => false, 'capability_type' => 'addifect_design', 'supports' => array( 'title', 'custom-fields' ), ), ); // 2. Fetch the user-created custom posts from site options $site_options = get_option( 'addifect_site_options', array() ); if ( ! empty( $site_options['custom_posts'] ) && is_array( $site_options['custom_posts'] ) ) { foreach ( $site_options['custom_posts'] as $cp ) { if ( empty( $cp['id'] ) ) { continue; } // Pull the exact labels from your UI. $single_label = ! empty( $cp['labelSingle'] ) ? sanitize_text_field( $cp['labelSingle'] ) : sanitize_text_field( $cp['id'] ); $plural_label = ! empty( $cp['labelPlural'] ) ? sanitize_text_field( $cp['labelPlural'] ) : $single_label; // Pull the exact slugs from your UI (Fallback to ID if left blank). $custom_slug = ! empty( $cp['postTypeSlug'] ) ? sanitize_title( $cp['postTypeSlug'] ) : sanitize_title( $cp['id'] ); $archive_slug = ! empty( $cp['archiveSlug'] ) ? sanitize_title( $cp['archiveSlug'] ) : false; // The safe internal WP post type to prevent conflicts (e.g., 'addifect_cp_vault'). $wp_post_type = 'addifect_cp_' . sanitize_key( $cp['id'] ); // Push the user's custom post type into the registration array. $post_types[] = array( 'type' => $wp_post_type, 'rewrite_slug' => $custom_slug, 'archive_slug' => $archive_slug, // WP accepts a boolean or string for has_archive. 'singular_name' => $single_label, 'plural_name' => $plural_label, 'menu_icon' => 'dashicons-admin-post', 'public' => true, 'show_in_rest' => true, 'capability_type' => 'post', 'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt', 'custom-fields' ), ); } } // 3. Loop through all combined post types and register them foreach ( $post_types as $post_type ) { $labels = array( 'name' => $post_type['plural_name'], 'singular_name' => $post_type['singular_name'], 'menu_name' => $post_type['plural_name'], /* translators: %s: Post type plural name. */ 'all_items' => sprintf( __( 'All %s', 'addifect' ), $post_type['plural_name'] ), 'add_new' => __( 'Add New', 'addifect' ), /* translators: %s: Post type singular name. */ 'add_new_item' => sprintf( __( 'Add New %s', 'addifect' ), $post_type['singular_name'] ), /* translators: %s: Post type singular name. */ 'edit_item' => sprintf( __( 'Edit %s', 'addifect' ), $post_type['singular_name'] ), /* translators: %s: Post type singular name. */ 'new_item' => sprintf( __( 'New %s', 'addifect' ), $post_type['singular_name'] ), /* translators: %s: Post type singular name. */ 'view_item' => sprintf( __( 'View %s', 'addifect' ), $post_type['singular_name'] ), /* translators: %s: Post type plural name. */ 'search_items' => sprintf( __( 'Search %s', 'addifect' ), $post_type['plural_name'] ), 'not_found' => __( 'None found', 'addifect' ), 'not_found_in_trash' => __( 'None found in Trash', 'addifect' ), ); $args = array( 'labels' => $labels, 'public' => $post_type['public'], 'publicly_queryable' => $post_type['public'], 'exclude_from_search' => ! $post_type['public'], 'show_ui' => true, 'show_in_menu' => true, 'show_in_nav_menus' => $post_type['public'], 'has_archive' => $post_type['archive_slug'], 'rewrite' => array( 'slug' => $post_type['rewrite_slug'], 'with_front' => false, ), 'supports' => $post_type['supports'], 'menu_icon' => $post_type['menu_icon'], 'show_in_rest' => $post_type['show_in_rest'], 'capability_type' => $post_type['capability_type'], 'map_meta_cap' => true, ); register_post_type( $post_type['type'], $args ); } } add_action( 'init', 'addifect_register_custom_post_types' );