flush_rewrite_rules = true; // set flag to flush rewrite rules on next init } public function handle_deactivation() { flush_rewrite_rules(); // flush immediately } public static function init() { if (self::$instance === null) { self::$instance = new self(); } return self::$instance; } public function handle_init() { $post_types = get_option('advset_post_types', []); $nonce = $_POST['_advset_posttype_nonce'] ?? null; if ($nonce && wp_verify_nonce($nonce, 'advset_posttype_nonce') && is_admin() && current_user_can('manage_options')) { // Delete post type via POST only if (!empty($_POST['_advset_posttype_action_delete'])) { $delete_slug = sanitize_key($_POST['_advset_posttype_action_delete'] ?? ''); if (isset($post_types[$delete_slug])) { unset($post_types[$delete_slug]); update_option('advset_post_types', $post_types); $this->flush_rewrite_rules = true; } } // Add post type if (isset($_POST['_advset_posttype_action_save'])) { $type = sanitize_key( $_POST['type'] ?? '' ); $type_result = $this->advset_posttypes_check_type($_POST['type'], $_POST['type_stored']); $type = $type_result['type_available']; if (!$type) { add_action('admin_notices', function() use ($type_result) { echo '

'.__('The post type is not available.', 'advanced-settings').'

'; }); return; } // If type has changed, remove the old type as we are going to add the new type if (!empty($_POST['type_stored']) && $type !== $_POST['type_stored'] && isset($post_types[$_POST['type_stored']])) { unset($post_types[$_POST['type_stored']]); } $labels = [ 'name' => $_POST['label'] ?? '', #'singular_name' => @$singular_name, #'add_new' => @$add_new, #'add_new_item' => @$add_new_item, #'edit_item' => @$edit_item, #'new_item' => @$new_item, #'all_items' => @$all_items, #'view_item' => @$view_item, #'search_items' => @$search_items, #'not_found' => @$not_found, #'not_found_in_trash' => @$not_found_in_trash, #'parent_item_colon' => @$parent_item_colon, #'menu_name' => @$menu_name ]; // These supports are allowed to be added to the post type $supports_allowed = [ 'title', 'editor', 'comments', 'revisions', 'trackbacks', 'author', 'excerpt', 'page-attributes', 'thumbnail', 'custom-fields', 'post-formats', ]; // These taxonomies are allowed to be added to the post type $taxonomies_allowed = [ 'category', 'post_tag', ]; // Get supports that are explicitly set to true // @TODO: Add support for FALSE value for $supports (to allow disabling all supports) $supports = array_intersect(array_keys(array_filter($_POST['supports'] ?? [], function($v) { return Advset_Tristate_Checkbox::post_to_tristate($v) === true; })), $supports_allowed) ?: null; // Get taxonomies that are explicitly set to true $taxonomies = array_intersect(array_keys(array_filter($_POST['taxonomies'] ?? [], function($v) { return Advset_Tristate_Checkbox::post_to_tristate($v) === true; })), $taxonomies_allowed) ?: null; $post_types[$type] = array_filter([ 'labels' => $labels, 'description' => $_POST['description'] ?? null, 'public' => Advset_Tristate_Checkbox::post_to_tristate($_POST['public']), 'hierarchical' => Advset_Tristate_Checkbox::post_to_tristate($_POST['hierarchical']), 'exclude_from_search' => Advset_Tristate_Checkbox::post_to_tristate($_POST['exclude_from_search']), 'publicly_queryable' => Advset_Tristate_Checkbox::post_to_tristate($_POST['publicly_queryable']), 'show_ui' => Advset_Tristate_Checkbox::post_to_tristate($_POST['show_ui']), 'show_in_menu' => Advset_Tristate_Checkbox::post_to_tristate($_POST['show_in_menu']), 'show_in_nav_menus' => Advset_Tristate_Checkbox::post_to_tristate($_POST['show_in_nav_menus']), 'show_in_admin_bar' => Advset_Tristate_Checkbox::post_to_tristate($_POST['show_in_admin_bar']), 'show_in_rest' => Advset_Tristate_Checkbox::post_to_tristate($_POST['show_in_rest']), //'rest_base' => $_POST['rest_base'] ?? null, //'rest_namespace' => $_POST['rest_namespace'] ?? null, //'rest_controller_class' => $_POST['rest_controller_class'] ?? null, //'autosave_rest_controller_class' => $_POST['autosave_rest_controller_class'] ?? null, //'revisions_rest_controller_class' => $_POST['revisions_rest_controller_class'] ?? null, 'late_route_registration' => Advset_Tristate_Checkbox::post_to_tristate($_POST['late_route_registration']), //'menu_position' => !empty($_POST['menu_position']) ? (int)$_POST['menu_position'] : null, //'menu_icon' => $_POST['menu_icon'] ?? null, //'capability_type' => $_POST['capability_type'] ?? null, //'capabilities' => $_POST['capabilities'] ?? null, 'map_meta_cap' => Advset_Tristate_Checkbox::post_to_tristate($_POST['map_meta_cap']), 'supports' => $supports, //'register_meta_box_cb' => $_POST['register_meta_box_cb'] ?? null, 'taxonomies' => $taxonomies, 'has_archive' => Advset_Tristate_Checkbox::post_to_tristate($_POST['has_archive']), //'rewrite' => $_POST['rewrite'] ?? [], 'query_var' => Advset_Tristate_Checkbox::post_to_tristate($_POST['query_var']), 'can_export' => Advset_Tristate_Checkbox::post_to_tristate($_POST['can_export']), //'delete_with_user' => Advset_Tristate_Checkbox::post_to_tristate($_POST['delete_with_user']), //'template' => $_POST['template'] ?? null, //'template_lock' => $_POST['template_lock'] ?? null, ], function($v) { return $v !== null; }); update_option( 'advset_post_types', $post_types ); $this->flush_rewrite_rules = true; } } if (!empty($post_types)) { foreach ($post_types as $post_type => $args) { register_post_type($post_type, $args); if (in_array('thumbnail', $args['supports'] ?? [])) { add_theme_support('post-thumbnails', [$post_type, 'post']); } } } if ($this->flush_rewrite_rules) { flush_rewrite_rules(); $this->flush_rewrite_rules = false; } } public function rest_api_init() { register_rest_route('advset_posttypes/v1', '/check-type', [ 'methods' => 'POST', 'callback' => function($request) { $label_input = $request->get_param('label_input'); $type_input = $request->get_param('type_input'); $type_stored = $request->get_param('type_stored'); $generate_from_label = $request->get_param('generate_from_label'); $type = $generate_from_label && $label_input ? $label_input : $type_input; return $this->advset_posttypes_check_type($type, $type_stored); }, 'args' => [ 'label_input' => [ 'type' => 'string', 'required' => true, ], ], 'permission_callback' => function() { return current_user_can('manage_options'); }, ]); } public function admin_menu() { add_options_page( __('Custom Post Types', 'advanced-settings'), __('Custom Post Types', 'advanced-settings'), 'manage_options', 'advanced-settings-post-types', function() { include ADVSET_DIR.'/feature-setup/features/includes/developer.settings_pages.post_types--admin-post-types.php'; } ); } private function advset_posttypes_check_type($type_input, $type_stored = null) { $type = sanitize_key($type_input); //$type_stored = $type_stored ? '' : $type; $is_valid = !empty($type); $is_taken = $is_valid && post_type_exists($type) && $type !== $type_stored; $alternate_type = null; $alternate_is_taken = $is_taken; for ($i = 1; $alternate_is_taken && $i <= 100; $i++) { $alternate_type = $type . '-' . $i; $alternate_is_taken = post_type_exists($alternate_type) && $alternate_type !== $type_stored; } $type_available = $alternate_is_taken ? null : ($alternate_type ? $alternate_type : $type); return [ 'type' => $type, 'type_stored' => $type_stored, 'is_taken' => $is_taken, 'is_valid' => $is_valid, 'alternate_type' => $alternate_type, 'alternate_is_taken' => $alternate_is_taken, 'type_available' => $type_available, ]; } }