post_types = $post_types; } /** * Set up Settings fields * * @return void */ private function add_setting_fields() { $this->setting_fields['required'] = $this->get_required_fields(); $this->setting_fields['labels'] = $this->get_label_fields(); $this->setting_fields['options'] = $this->get_option_fields(); $this->setting_fields['capabilities'] = $this->get_capabilities_fields(); } /** * Get choices for No/Yes select fields. * * @return array */ private function get_no_yes_choices() { return [ '0' => __( 'No', 'admin-optimizer' ), '1' => __( 'Yes', 'admin-optimizer' ), ]; } /** * Get choices for Yes/No select fields. * * @return array */ private function get_yes_no_choices() { return [ '1' => __( 'Yes', 'admin-optimizer' ), '0' => __( 'No', 'admin-optimizer' ), ]; } /** * Get choices for Default/Yes/No select fields. * * @return array */ private function get_default_yes_no_choices() { return [ '-1' => __( 'Leave it as default', 'admin-optimizer' ), '1' => __( 'Yes', 'admin-optimizer' ), '0' => __( 'No', 'admin-optimizer' ), ]; } /** * Get choices for rewrite options. * * @return array */ private function get_rewrite_choices() { return [ '1' => __( 'Yes', 'admin-optimizer' ), '0' => __( 'No', 'admin-optimizer' ), 'custom' => __( 'Custom', 'admin-optimizer' ), ]; } /** * Get choices for capability mode options. * * @return array */ private function get_capability_mode_choices() { return [ 'post' => __( 'Post', 'admin-optimizer' ), 'custom' => __( 'Custom', 'admin-optimizer' ), ]; } /** * Get the built-in menu icon choices. * * @return array */ private function get_menu_icon_choices() { return [ '' => __( 'Default posts icon', 'admin-optimizer' ), 'dashicons-admin-post' => __( 'Posts', 'admin-optimizer' ), 'dashicons-admin-page' => __( 'Pages', 'admin-optimizer' ), 'dashicons-admin-media' => __( 'Media', 'admin-optimizer' ), 'dashicons-admin-users' => __( 'Users', 'admin-optimizer' ), 'dashicons-admin-comments' => __( 'Comments', 'admin-optimizer' ), 'dashicons-admin-tools' => __( 'Tools', 'admin-optimizer' ), 'dashicons-admin-settings' => __( 'Settings', 'admin-optimizer' ), 'dashicons-portfolio' => __( 'Portfolio', 'admin-optimizer' ), 'dashicons-products' => __( 'Products', 'admin-optimizer' ), 'dashicons-cart' => __( 'Cart', 'admin-optimizer' ), 'dashicons-store' => __( 'Store', 'admin-optimizer' ), 'dashicons-calendar-alt' => __( 'Calendar', 'admin-optimizer' ), 'dashicons-book' => __( 'Book', 'admin-optimizer' ), 'dashicons-category' => __( 'Category', 'admin-optimizer' ), 'dashicons-tag' => __( 'Tag', 'admin-optimizer' ), 'dashicons-location' => __( 'Location', 'admin-optimizer' ), 'dashicons-groups' => __( 'Groups', 'admin-optimizer' ), 'dashicons-chart-pie' => __( 'Pie chart', 'admin-optimizer' ), 'dashicons-chart-bar' => __( 'Bar chart', 'admin-optimizer' ), 'dashicons-chart-line' => __( 'Line chart', 'admin-optimizer' ), 'dashicons-format-gallery' => __( 'Gallery', 'admin-optimizer' ), 'dashicons-format-image' => __( 'Image', 'admin-optimizer' ), 'dashicons-format-video' => __( 'Video', 'admin-optimizer' ), 'dashicons-format-audio' => __( 'Audio', 'admin-optimizer' ), 'dashicons-email' => __( 'Email', 'admin-optimizer' ), 'dashicons-star-filled' => __( 'Star', 'admin-optimizer' ), 'dashicons-heart' => __( 'Heart', 'admin-optimizer' ), 'dashicons-welcome-learn-more' => __( 'Education', 'admin-optimizer' ), 'custom' => __( 'Custom / use your own', 'admin-optimizer' ), 'none' => __( 'No icon', 'admin-optimizer' ), ]; } /** * Get required field definitions. * * @return array */ private function get_required_fields() { $taxonomies_field = $this->get_taxonomies_field(); return [ [ 'id' => 'post-type-name', 'type' => 'text', 'name' => 'posttype[labels][name]', 'key' => 'name', 'key_type' => 'label', 'value' => '', 'label' => __( 'Post Type Name', 'admin-optimizer' ), 'description' => __( 'The name of the custom post type. Usually plural.', 'admin-optimizer' ), 'required' => true, ], [ 'id' => 'post-type-singular-label', 'type' => 'text', 'name' => 'posttype[labels][singular_name]', 'key' => 'singular_name', 'key_type' => 'label', 'value' => '', 'label' => __( 'Singular Label', 'admin-optimizer' ), 'description' => __( 'The singular label of the custom post type.', 'admin-optimizer' ), 'required' => true, ], [ 'id' => 'post-type-slug', 'type' => 'text', 'name' => 'posttype[slug]', 'key' => 'slug', 'key_type' => 'option', 'value' => '', 'label' => __( 'Slug', 'admin-optimizer' ), 'description' => __( 'The "slug" is the URL-friendly version of the name. It is usually all lowercase and contains only letters, numbers, and hyphens.', 'admin-optimizer' ), 'required' => true, ], [ 'id' => 'post-type-description', 'type' => 'textarea', 'name' => 'posttype[description]', 'key' => 'description', 'key_type' => 'option', 'value' => '', 'label' => __( 'Description', 'admin-optimizer' ), 'description' => __( 'Describe what this custom post type is used for.', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-public', 'type' => 'select', 'choices' => $this->get_no_yes_choices(), 'name' => 'posttype[public]', 'key' => 'public', 'key_type' => 'option', 'value' => '', 'label' => __( 'Public', 'admin-optimizer' ), 'description' => __( 'Is this post type intended for use publicly either via the admin interface or by front-end users?', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-hierarchical', 'type' => 'select', 'choices' => $this->get_no_yes_choices(), 'name' => 'posttype[hierarchical]', 'key' => 'hierarchical', 'key_type' => 'option', 'value' => '', 'label' => __( 'Hierarchical', 'admin-optimizer' ), 'description' => __( 'Is this post type hierarchical (e.g. page)?', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-supports', 'type' => 'checkboxes', 'choices' => [ 'title' => __( 'Title', 'admin-optimizer' ), 'editor' => __( 'Editor', 'admin-optimizer' ), 'thumbnail' => __( 'Featured Image', 'admin-optimizer' ), 'excerpt' => __( 'Excerpt', 'admin-optimizer' ), 'trackbacks' => __( 'Trackbacks', 'admin-optimizer' ), 'custom-fields' => __( 'Custom Fields', 'admin-optimizer' ), 'comments' => __( 'Comments', 'admin-optimizer' ), 'revisions' => __( 'Revisions', 'admin-optimizer' ), 'author' => __( 'Author', 'admin-optimizer' ), 'page-attributes' => __( 'Page Attributes', 'admin-optimizer' ), 'post-formats' => __( 'Post Formats', 'admin-optimizer' ), ], 'checked' => [ 'title', 'editor' ], 'name' => 'posttype[supports][]', 'key' => 'supports', 'key_type' => 'supports', 'label' => __( 'Select the features supported by this post type', 'admin-optimizer' ), 'required' => false, ], $taxonomies_field, ]; } /** * Get label field definitions. * * @return array */ private function get_label_fields() { return [ [ 'id' => 'post-type-add-new-label', 'type' => 'text', 'name' => 'posttype[labels][add_new]', 'key' => 'add_new', 'key_type' => 'label', 'value' => '', 'label' => __( 'Add New', 'admin-optimizer' ), 'description' => __( 'Label for adding a new item. Default is \'Add Post\' / \'Add Page\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Add New)', 'admin-optimizer' ), ], [ 'id' => 'post-type-add-new-item-label', 'type' => 'text', 'name' => 'posttype[labels][add_new_item]', 'key' => 'add_new_item', 'key_type' => 'label', 'value' => '', 'label' => __( 'Add New Item', 'admin-optimizer' ), 'description' => __( 'Label for adding a new singular item. Default is \'Add Post\' / \'Add Page\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Add New Book)', 'admin-optimizer' ), ], [ 'id' => 'post-type-edit-item-label', 'type' => 'text', 'name' => 'posttype[labels][edit_item]', 'key' => 'edit_item', 'key_type' => 'label', 'value' => '', 'label' => __( 'Edit Item', 'admin-optimizer' ), 'description' => __( 'Label for editing a new singular item. Default is \'Edit Post\' / \'Edit Page\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Edit Book)', 'admin-optimizer' ), ], [ 'id' => 'post-type-view-item-label', 'type' => 'text', 'name' => 'posttype[labels][view_item]', 'key' => 'view_item', 'key_type' => 'label', 'value' => '', 'label' => __( 'View Item', 'admin-optimizer' ), 'description' => __( 'Label for viewing a singular item. Default is \'View Post\' / \'View Page\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. View Book)', 'admin-optimizer' ), ], [ 'id' => 'post-type-view-items-label', 'type' => 'text', 'name' => 'posttype[labels][view_items]', 'key' => 'view_items', 'key_type' => 'label', 'value' => '', 'label' => __( 'View Items', 'admin-optimizer' ), 'description' => __( 'Label for viewing post type archives. Default is \'View Posts\' / \'View Pages\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. View Books)', 'admin-optimizer' ), ], [ 'id' => 'post-type-search-items-label', 'type' => 'text', 'name' => 'posttype[labels][search_items]', 'key' => 'search_items', 'key_type' => 'label', 'value' => '', 'label' => __( 'Search Items', 'admin-optimizer' ), 'description' => __( 'Label for searching plural items. Default is \'Search Post\' / \'Search Pages\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Search Books)', 'admin-optimizer' ), ], [ 'id' => 'post-type-not-found-label', 'type' => 'text', 'name' => 'posttype[labels][not_found]', 'key' => 'not_found', 'key_type' => 'label', 'value' => '', 'label' => __( 'Not Found', 'admin-optimizer' ), 'description' => __( 'Label used when no items are found. Default is \'No posts found\' / \'No pages found\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. No books found)', 'admin-optimizer' ), ], [ 'id' => 'post-type-not-found-trash-label', 'type' => 'text', 'name' => 'posttype[labels][not_found_in_trash]', 'key' => 'not_found_in_trash', 'key_type' => 'label', 'value' => '', 'label' => __( 'Not Found in Trash', 'admin-optimizer' ), 'description' => __( 'Label used when no items are in the Trash. Default is \'No posts found in Trash\' / \'No pages found in Trash\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. No books found in Trash)', 'admin-optimizer' ), ], [ 'id' => 'post-type-parent-item-colon-label', 'type' => 'text', 'name' => 'posttype[labels][parent_item_colon]', 'key' => 'parent_item_colon', 'key_type' => 'label', 'value' => '', 'label' => __( 'Parent Item', 'admin-optimizer' ), 'description' => __( 'Label used to prefix parents of hierarchical items. Not used on non-hierarchical post types. Default is \'Parent Page:\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Parent Book)', 'admin-optimizer' ), ], [ 'id' => 'post-type-all-items-label', 'type' => 'text', 'name' => 'posttype[labels][all_items]', 'key' => 'all_items', 'key_type' => 'label', 'value' => '', 'label' => __( 'All Items', 'admin-optimizer' ), 'description' => __( 'Label to signify all items in a submenu link. Default is \'All Posts\' / \'All Pages\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. All Books)', 'admin-optimizer' ), ], [ 'id' => 'post-type-archives-label', 'type' => 'text', 'name' => 'posttype[labels][archives]', 'key' => 'archives', 'key_type' => 'label', 'value' => '', 'label' => __( 'Archives', 'admin-optimizer' ), 'description' => __( 'Label for archives in nav menus. Default is \'Post Archives\' / \'Page Archives\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Book Archives)', 'admin-optimizer' ), ], [ 'id' => 'post-type-attributes-label', 'type' => 'text', 'name' => 'posttype[labels][attributes]', 'key' => 'attributes', 'key_type' => 'label', 'value' => '', 'label' => __( 'Attributes', 'admin-optimizer' ), 'description' => __( 'Label for the attributes meta box. Default is \'Post Attributes\' / \'Page Attributes\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Book Attributes)', 'admin-optimizer' ), ], [ 'id' => 'post-type-insert-into-item-label', 'type' => 'text', 'name' => 'posttype[labels][insert_into_item]', 'key' => 'insert_into_item', 'key_type' => 'label', 'value' => '', 'label' => __( 'Insert Into Item', 'admin-optimizer' ), 'description' => __( 'Label for the media frame button. Default is \'Insert into post\' / \'Insert into page\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Insert into book)', 'admin-optimizer' ), ], [ 'id' => 'post-type-uploaded-to-this-item-label', 'type' => 'text', 'name' => 'posttype[labels][uploaded_to_this_item]', 'key' => 'uploaded_to_this_item', 'key_type' => 'label', 'value' => '', 'label' => __( 'Uploaded to this Item', 'admin-optimizer' ), 'description' => __( 'Label for the media frame filter. Default is \'Uploaded to this post\' / \'Uploaded to this page\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Uploaded to this book)', 'admin-optimizer' ), ], [ 'id' => 'post-type-featured-image-label', 'type' => 'text', 'name' => 'posttype[labels][featured_image]', 'key' => 'featured_image', 'key_type' => 'label', 'value' => '', 'label' => __( 'Featured Image', 'admin-optimizer' ), 'description' => __( 'Label for the featured image meta box title. Default is \'Featured image\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Featured image for book)', 'admin-optimizer' ), ], [ 'id' => 'post-type-set-featured-image-label', 'type' => 'text', 'name' => 'posttype[labels][set_featured_image]', 'key' => 'set_featured_image', 'key_type' => 'label', 'value' => '', 'label' => __( 'Set Featured Image', 'admin-optimizer' ), 'description' => __( 'Label for setting the featured image. Default is \'Set Featured image\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Set featured image for book)', 'admin-optimizer' ), ], [ 'id' => 'post-type-remove-featured-image-label', 'type' => 'text', 'name' => 'posttype[labels][remove_featured_image]', 'key' => 'remove_featured_image', 'key_type' => 'label', 'value' => '', 'label' => __( 'Remove Featured Image', 'admin-optimizer' ), 'description' => __( 'Label for setting the featured image. Default is \'Remove featured image\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Remove featured image for book)', 'admin-optimizer' ), ], [ 'id' => 'post-type-use-featured-image-label', 'type' => 'text', 'name' => 'posttype[labels][use_featured_image]', 'key' => 'use_featured_image', 'key_type' => 'label', 'value' => '', 'label' => __( 'Use Featured Image', 'admin-optimizer' ), 'description' => __( 'Label in the media frame for using a featured image. Default is \'Use as featured image\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Use as featured image this book)', 'admin-optimizer' ), ], [ 'id' => 'post-type-menu-name-label', 'type' => 'text', 'name' => 'posttype[labels][menu_name]', 'key' => 'menu_name', 'key_type' => 'label', 'value' => '', 'label' => __( 'Menu Name', 'admin-optimizer' ), 'description' => __( 'Label for the menu name. Default is the same as post type name.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Books)', 'admin-optimizer' ), ], [ 'id' => 'post-type-filter-items-list-label', 'type' => 'text', 'name' => 'posttype[labels][filter_items_list]', 'key' => 'filter_items_list', 'key_type' => 'label', 'value' => '', 'label' => __( 'Filter Items List', 'admin-optimizer' ), 'description' => __( 'Label for the table views hidden heading. Default is \'Filter posts list\' / \'Filter pages list\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Filter books list)', 'admin-optimizer' ), ], [ 'id' => 'post-type-filter-by-date-label', 'type' => 'text', 'name' => 'posttype[labels][filter_by_date]', 'key' => 'filter_by_date', 'key_type' => 'label', 'value' => '', 'label' => __( 'Filter by Date', 'admin-optimizer' ), 'description' => __( 'Label for the date filter in list tables. Default is \'Filter by date\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Filter books by date)', 'admin-optimizer' ), ], [ 'id' => 'post-type-items-list-navigation-label', 'type' => 'text', 'name' => 'posttype[labels][items_list_navigation]', 'key' => 'items_list_navigation', 'key_type' => 'label', 'value' => '', 'label' => __( 'Items List Navigation', 'admin-optimizer' ), 'description' => __( 'Label for the table pagination hidden heading. Default is \'Posts list navigation\' / \'Pages list navigation\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Books list navigation)', 'admin-optimizer' ), ], [ 'id' => 'post-type-items-list-label', 'type' => 'text', 'name' => 'posttype[labels][items_list]', 'key' => 'items_list', 'key_type' => 'label', 'value' => '', 'label' => __( 'Items List', 'admin-optimizer' ), 'description' => __( 'Label for the table hidden heading. Default is \'Posts list\' / \'Pages list\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Books list)', 'admin-optimizer' ), ], [ 'id' => 'post-type-items-published-label', 'type' => 'text', 'name' => 'posttype[labels][item_published]', 'key' => 'item_published', 'key_type' => 'label', 'value' => '', 'label' => __( 'Items Published', 'admin-optimizer' ), 'description' => __( 'Label used when an item is published. Default is \'Post published.\' / \'Page published.\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Books published)', 'admin-optimizer' ), ], [ 'id' => 'post-type-items-published-privately-label', 'type' => 'text', 'name' => 'posttype[labels][item_published_privately]', 'key' => 'item_published_privately', 'key_type' => 'label', 'value' => '', 'label' => __( 'Items Published Privately', 'admin-optimizer' ), 'description' => __( 'Label used when an item is published privately. Default is \'Post published privately.\' / \'Page published privately.\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Books published privately)', 'admin-optimizer' ), ], [ 'id' => 'post-type-items-reverted-to-draft-label', 'type' => 'text', 'name' => 'posttype[labels][item_reverted_to_draft]', 'key' => 'item_reverted_to_draft', 'key_type' => 'label', 'value' => '', 'label' => __( 'Items Reverted to Draft', 'admin-optimizer' ), 'description' => __( 'Label used when an item is switched to a draft. Default is \'Post reverted to draft.\' / \'Page reverted to draft.\'', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Books reverted to draft)', 'admin-optimizer' ), ], [ 'id' => 'post-type-items-trashed-label', 'type' => 'text', 'name' => 'posttype[labels][item_trashed]', 'key' => 'item_trashed', 'key_type' => 'label', 'value' => '', 'label' => __( 'Items Trashed', 'admin-optimizer' ), 'description' => __( 'Label used when an item is moved to Trash. Default is \'Post trashed.\' / \'Page trashed.\'', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Books trashed)', 'admin-optimizer' ), ], [ 'id' => 'post-type-items-scheduled-label', 'type' => 'text', 'name' => 'posttype[labels][item_scheduled]', 'key' => 'item_scheduled', 'key_type' => 'label', 'value' => '', 'label' => __( 'Items Scheduled', 'admin-optimizer' ), 'description' => __( 'Label used when an item is scheduled. Default is \'Post scheduled.\' / \'Page scheduled.\'', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Book scheduled)', 'admin-optimizer' ), ], [ 'id' => 'post-type-items-updated-label', 'type' => 'text', 'name' => 'posttype[labels][item_updated]', 'key' => 'item_updated', 'key_type' => 'label', 'value' => '', 'label' => __( 'Items Updated', 'admin-optimizer' ), 'description' => __( 'Label used when an item is updated. Default is \'Post updated.\' / \'Page updated.\'', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Book updated)', 'admin-optimizer' ), ], [ 'id' => 'post-type-items-link-label', 'type' => 'text', 'name' => 'posttype[labels][item_link]', 'key' => 'item_link', 'key_type' => 'label', 'value' => '', 'label' => __( 'Items Link', 'admin-optimizer' ), 'description' => __( 'Title for a navigation link block variation. Default is \'Post Link\' / \'Page Link\'', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. Book Link)', 'admin-optimizer' ), ], [ 'id' => 'post-type-items-link-description-label', 'type' => 'text', 'name' => 'posttype[labels][item_link_description]', 'key' => 'item_link_description', 'key_type' => 'label', 'value' => '', 'label' => __( 'Items Link Description', 'admin-optimizer' ), 'description' => __( 'Description for a navigation link block variation. Default is \'A link to a post.\' / \'A link to a page.\'', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( '(e.g. A link to a book.)', 'admin-optimizer' ), ], ]; } /** * Build taxonomy field for options settings. * * @return array */ private function get_taxonomies_field() { $taxonomies = get_taxonomies( [ 'public' => true ], 'objects' ); $setting_tax_field = []; foreach ( $taxonomies as $taxonomy ) { if ( 'post_format' === $taxonomy->name || empty( $taxonomy->label ) ) { continue; } $setting_tax_field[ $taxonomy->name ] = $taxonomy->label; } return [ 'id' => 'posttype-taxonomy', 'type' => 'checkboxes', 'choices' => $setting_tax_field, 'checked' => [], 'name' => 'posttype[taxonomies][]', 'key' => 'taxonomies', 'key_type' => 'taxonomies', 'label' => __( 'Taxonomies', 'admin-optimizer' ), 'required' => false, ]; } /** * Get option field definitions. * * @return array */ private function get_option_fields() { return [ [ 'id' => 'posttype-options-message', 'type' => 'html', 'value' => '
' . __( 'The following options are optional. They are safe to leave it as default.', 'admin-optimizer' ) . '
', 'required' => false, ], [ 'id' => 'posttype-exclude-from-search', 'type' => 'select', 'choices' => $this->get_default_yes_no_choices(), 'name' => 'posttype[exclude_from_search]', 'key' => 'exclude_from_search', 'key_type' => 'option', 'value' => '', 'label' => __( 'Exclude from search', 'admin-optimizer' ), 'description' => __( 'Exclude posts with this post type from front end search results? Default is the opposite value of Public', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-publicly-queryable', 'type' => 'select', 'choices' => $this->get_default_yes_no_choices(), 'name' => 'posttype[publicly_queryable]', 'key' => 'publicly_queryable', 'key_type' => 'option', 'value' => '', 'label' => __( 'Publicly queryable', 'admin-optimizer' ), 'description' => __( 'Can queries be performed on the front end for this post type? The default is inherited from Public.', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-show-ui', 'type' => 'select', 'choices' => $this->get_default_yes_no_choices(), 'name' => 'posttype[show_ui]', 'key' => 'show_ui', 'key_type' => 'option', 'value' => '', 'label' => __( 'Show UI', 'admin-optimizer' ), 'description' => __( 'Allow a UI for managing this post type in the admin? The default is inherited from Public.', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-show-in-nav-menu', 'type' => 'select', 'choices' => $this->get_default_yes_no_choices(), 'name' => 'posttype[show_in_nav_menus]', 'key' => 'show_in_nav_menus', 'key_type' => 'option', 'value' => '', 'label' => __( 'Show in Nav Menu', 'admin-optimizer' ), 'description' => __( 'Makes this post type available for selection in navigation menus. The default is the same as Public.', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-show-in-admin-bar', 'type' => 'select', 'choices' => $this->get_default_yes_no_choices(), 'name' => 'posttype[show_in_admin_bar]', 'key' => 'show_in_admin_bar', 'key_type' => 'option', 'value' => '', 'label' => __( 'Show in Admin Bar', 'admin-optimizer' ), 'description' => __( 'Makes this post type available via the admin bar', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-show-in-rest', 'type' => 'select', 'choices' => $this->get_yes_no_choices(), 'name' => 'posttype[show_in_rest]', 'key' => 'show_in_rest', 'key_type' => 'option', 'value' => '', 'label' => __( 'Show in REST API (set to No to use the Classic Editor)', 'admin-optimizer' ), 'description' => __( 'Include the post type in the REST API? Set this to yes for the post type to be available in the block editor.', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-rest-base', 'type' => 'text', 'name' => 'posttype[rest_base]', 'key' => 'rest_base', 'key_type' => 'option', 'value' => '', 'label' => __( 'REST API Base', 'admin-optimizer' ), 'description' => __( 'Change the base URL of REST API route. Default is this post_type slug.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( 'Leave blank if you are not sure.', 'admin-optimizer' ), ], [ 'id' => 'posttype-rest-namespace', 'type' => 'text', 'name' => 'posttype[rest_namespace]', 'key' => 'rest_namespace', 'key_type' => 'option', 'value' => '', 'label' => __( 'REST Namespace', 'admin-optimizer' ), 'description' => __( 'Change the namespace URL of REST API route. Default is "wp/v2".', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( 'Leave blank if you are not sure.', 'admin-optimizer' ), ], [ 'id' => 'posttype-rest-controller-class', 'type' => 'text', 'name' => 'posttype[rest_controller_class]', 'key' => 'rest_controller_class', 'key_type' => 'option', 'value' => '', 'label' => __( 'REST Controller Class', 'admin-optimizer' ), 'description' => __( 'REST API controller class name. Default is \'WP_REST_Posts_Controller\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( 'Leave blank if you are not sure.', 'admin-optimizer' ), ], [ 'id' => 'posttype-autosave-rest-controller-class', 'type' => 'text', 'name' => 'posttype[autosave_rest_controller_class]', 'key' => 'autosave_rest_controller_class', 'key_type' => 'option', 'value' => '', 'label' => __( 'Autosave REST Controller Class', 'admin-optimizer' ), 'description' => __( 'REST API controller class name. Default is \'WP_REST_Autosaves_Controller\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( 'Leave blank if you are not sure.', 'admin-optimizer' ), ], [ 'id' => 'posttype-revisions-rest-controller-class', 'type' => 'text', 'name' => 'posttype[revisions_rest_controller_class]', 'key' => 'revisions_rest_controller_class', 'key_type' => 'option', 'value' => '', 'label' => __( 'Revisions REST Controller Class', 'admin-optimizer' ), 'description' => __( 'REST API controller class name. Default is \'WP_REST_Revisions_Controller\'.', 'admin-optimizer' ), 'required' => false, 'placeholder' => __( 'Leave blank if you are not sure.', 'admin-optimizer' ), ], [ 'id' => 'posttype-menu-position', 'type' => 'number', 'min' => 5, 'max' => 100, 'name' => 'posttype[menu_position]', 'key' => 'menu_position', 'key_type' => 'option', 'value' => '', 'label' => __( 'Menu Position', 'admin-optimizer' ), 'description' => __( 'The position in the menu order the post type should appear. Range between 5-100', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-menu-icon', 'type' => 'menu_icon', 'name' => 'posttype[menu_icon_preset]', 'key' => 'menu_icon', 'key_type' => 'option', 'value' => '', 'label' => __( 'Menu Icon', 'admin-optimizer' ), 'choices' => $this->get_menu_icon_choices(), 'description' => __( 'Paste a base64-encoded SVG data URI. A custom icon takes precedence over the dropdown.', 'admin-optimizer' ), 'required' => false, 'placeholder' => 'data:image/svg+xml;base64,...', ], [ 'id' => 'posttype-custom-supports', 'type' => 'text', 'name' => 'posttype[custom_supports]', 'key' => 'custom_supports', 'key_type' => 'option', 'value' => '', 'label' => __( 'Custom Supports', 'admin-optimizer' ), 'description' => __( 'Add custom supports here', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-register-meta-box-cb', 'type' => 'text', 'name' => 'posttype[register_meta_box_cb]', 'key' => 'register_meta_box_cb', 'key_type' => 'option', 'value' => '', 'label' => __( 'Meta Box Callback', 'admin-optimizer' ), 'description' => __( '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.', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-has-archive', 'type' => 'select', 'choices' => $this->get_no_yes_choices(), 'name' => 'posttype[has_archive]', 'key' => 'has_archive', 'key_type' => 'option', 'value' => '', 'label' => __( 'Has Archive', 'admin-optimizer' ), 'description' => __( 'Are there post type archives for this post type? Default No.', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-rewrite', 'type' => 'select', 'choices' => $this->get_rewrite_choices(), 'name' => 'posttype[do_rewrite]', 'key' => 'rewrite', 'key_type' => 'option', 'value' => '', 'label' => __( 'Rewrite', 'admin-optimizer' ), 'description' => __( 'Triggers the handling of rewrites for this post type. Default Yes.', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-rewrite-slug', 'type' => 'text', 'name' => 'posttype[rewrite][slug]', 'key' => 'slug', 'key_type' => 'rewrite', 'wrapper_class' => 'adminoptim-rewrite-custom-field', 'value' => '', 'label' => __( 'Custom Rewrite Slug', 'admin-optimizer' ), 'description' => __( 'Custom post type slug to use instead of the default.', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-rewrite-with-front', 'type' => 'select', 'choices' => $this->get_yes_no_choices(), 'name' => 'posttype[rewrite][with_front]', 'key' => 'with_front', 'key_type' => 'rewrite', 'wrapper_class' => 'adminoptim-rewrite-custom-field', 'value' => '', 'label' => __( 'With Front', 'admin-optimizer' ), 'description' => __( 'Should the permalink structure be prepended with the front base. (example: if your permalink structure is /blog/, then your permalink will be /blog/books/). Default is Yes.', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-rewrite-feeds', 'type' => 'select', 'choices' => $this->get_yes_no_choices(), 'name' => 'posttype[rewrite][feeds]', 'key' => 'feeds', 'key_type' => 'rewrite', 'wrapper_class' => 'adminoptim-rewrite-custom-field', 'value' => '', 'label' => __( 'Feeds', 'admin-optimizer' ), 'description' => __( 'Whether to generate rewrite rules for feeds for this post type. Default is Yes.', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-can-export', 'type' => 'select', 'choices' => $this->get_yes_no_choices(), 'name' => 'posttype[can_export]', 'key' => 'can_export', 'key_type' => 'option', 'value' => '', 'label' => __( 'Can Export', 'admin-optimizer' ), 'description' => __( 'Whether to allow this post type to be exported. Default Yes.', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-delete-with-user', 'type' => 'select', 'choices' => $this->get_default_yes_no_choices(), 'name' => 'posttype[delete_with_user]', 'key' => 'delete_with_user', 'key_type' => 'option', 'value' => '', 'label' => __( 'Delete with user', 'admin-optimizer' ), 'description' => __( 'Whether to delete posts of this type when deleting a user. If yes, posts of this type belonging to the user will be moved to Trash when the user is deleted. If no, 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 the \'author\' feature. Otherwise posts are not trashed or deleted.', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-query-var', 'type' => 'select', 'choices' => $this->get_yes_no_choices(), 'name' => 'posttype[query_var]', 'key' => 'query_var', 'key_type' => 'option', 'value' => '', 'label' => __( 'Query Var', 'admin-optimizer' ), 'description' => __( 'Sets the query_var key for this post type. Default is true', 'admin-optimizer' ), 'required' => false, ], [ 'id' => 'posttype-custom-query-var', 'type' => 'text', 'name' => 'posttype[custom_query_var]', 'key' => 'custom_query_var', 'key_type' => 'option', 'value' => '', 'label' => __( 'Custom Query Var', 'admin-optimizer' ), 'description' => __( 'Custom query var slug to use instead of the default.', 'admin-optimizer' ), 'required' => false, ], ]; } /** * Get capabilities field definitions. * * @return array */ private function get_capabilities_fields() { $capability_fields = [ 'publish_posts' => __( 'Publish Posts', 'admin-optimizer' ), 'edit_posts' => __( 'Edit Posts', 'admin-optimizer' ), 'edit_others_posts' => __( 'Edit Others Posts', 'admin-optimizer' ), 'edit_published_posts' => __( 'Edit Published Posts', 'admin-optimizer' ), 'edit_private_posts' => __( 'Edit Private Posts', 'admin-optimizer' ), 'read_private_posts' => __( 'Read Private Posts', 'admin-optimizer' ), 'delete_posts' => __( 'Delete Posts', 'admin-optimizer' ), 'delete_private_posts' => __( 'Delete Private Posts', 'admin-optimizer' ), 'delete_published_posts' => __( 'Delete Published Posts', 'admin-optimizer' ), 'delete_others_posts' => __( 'Delete Others Posts', 'admin-optimizer' ), 'edit_post' => __( 'Edit Post', 'admin-optimizer' ), 'read_post' => __( 'Read Post', 'admin-optimizer' ), 'delete_post' => __( 'Delete Post', 'admin-optimizer' ), 'create_posts' => __( 'Create Posts', 'admin-optimizer' ), ]; $fields = [ [ 'id' => 'posttype-capabilities-message', 'type' => 'html', 'value' => '' . __( 'Use custom capabilities only when you need explicit role/capability mappings.', 'admin-optimizer' ) . '
', 'required' => false, ], [ 'id' => 'posttype-capability-type', 'type' => 'select', 'choices' => $this->get_capability_mode_choices(), 'name' => 'posttype[do_capabilities]', 'key' => 'do_capabilities', 'key_type' => 'option', 'value' => 'post', 'label' => __( 'Capability Type', 'admin-optimizer' ), 'description' => __( 'Use default post capabilities or define custom capability mappings.', 'admin-optimizer' ), 'required' => false, ], ]; foreach ( $capability_fields as $capability_key => $capability_label ) { $fields[] = [ 'id' => 'posttype-capability-' . $capability_key, 'type' => 'text', 'name' => 'posttype[capabilities][' . $capability_key . ']', 'key' => $capability_key, 'key_type' => 'capability', 'wrapper_class' => 'adminoptim-capabilities-custom-field', 'value' => '', 'label' => $capability_label, 'description' => sprintf( /* translators: %s capability key. */ __( 'Capability key for "%s". Leave blank to skip.', 'admin-optimizer' ), $capability_key ), 'required' => false, 'placeholder' => $capability_key, ]; } return $fields; } /** * Render Settings page * * @return void */ public function render_settings_page() { $message = ''; $error = false; $action = isset( $_REQUEST['action'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['action'] ) ) : ''; $render_settings = true; $this->add_setting_fields(); if ( ! in_array( $action, [ 'add', 'save-edit', 'edit', 'delete', 'bulk-delete' ], true ) ) { $action = ''; } switch ( $action ) { case 'add': check_admin_referer( 'adminoptim-add-post-type', 'nonce' ); $post_data = isset( $_REQUEST['posttype'] ) ? wp_unslash( $_REQUEST['posttype'] ) : []; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized $response = $this->handle_post_data( $post_data ); if ( is_wp_error( $response ) ) { $error = true; $message = $response->get_error_message(); } else { $message = $response->message; } break; case 'delete': if ( ! isset( $_REQUEST['slug'] ) ) { break; } $slug = sanitize_title_with_dashes( wp_unslash( $_REQUEST['slug'] ), '', 'save' ); check_admin_referer( 'delete-post-type_' . $slug, 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_die( '' . esc_html( 'Sorry, you are not allowed to delete this item.' ) . '
', 403 ); } if ( isset( $this->post_types[ $slug ] ) ) { unset( $this->post_types[ $slug ] ); } update_option( Post_Types::OPTION_NAME, $this->post_types, false ); set_transient( 'adminoptim_post_types_flush_rules', true, 3 * MINUTE_IN_SECONDS ); $message = __( 'Post Type deleted successfully.', 'admin-optimizer' ); break; case 'bulk-delete': check_admin_referer( 'bulk-custom_post_types' ); $slugs = isset( $_REQUEST['slugs'] ) ? wp_unslash( $_REQUEST['slugs'] ) : []; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized if ( ! empty( $slugs ) ) { foreach ( $slugs as $slug ) { $slug = sanitize_title_with_dashes( $slug, '', 'save' ); if ( isset( $this->post_types[ $slug ] ) ) { unset( $this->post_types[ $slug ] ); } else { wp_die( esc_html( 'You attempted to edit a post type that does not exist. Perhaps it was deleted?' ) ); } } update_option( Post_Types::OPTION_NAME, $this->post_types, false ); set_transient( 'adminoptim_post_types_flush_rules', true, 3 * MINUTE_IN_SECONDS ); $message = __( 'Post Type deleted successfully.', 'admin-optimizer' ); } else { wp_die( esc_html__( 'Missing post type slugs.', 'admin-optimizer' ) ); } break; case 'edit': if ( ! isset( $_REQUEST['slug'] ) ) { break; } $post_status_slug = sanitize_title_with_dashes( wp_unslash( $_REQUEST['slug'] ), '', 'save' ); check_admin_referer( 'edit-post-type_' . $post_status_slug, 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_die( '' . esc_html( 'Sorry, you are not allowed to delete this item.' ) . '
', 403 ); } $this->render_edit_page( $post_status_slug ); $render_settings = false; break; case 'save-edit': if ( ! isset( $_REQUEST['slug'] ) ) { wp_die( esc_html( 'You attempted to save a post type with invalid parameters. Please try again!' ) ); } $slug = sanitize_title_with_dashes( wp_unslash( $_REQUEST['slug'] ), '', 'save' ); check_admin_referer( 'save-edit-post-type_' . $slug, 'nonce' ); $post_data = isset( $_REQUEST['posttype'] ) ? wp_unslash( $_REQUEST['posttype'] ) : []; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized if ( empty( $this->post_types[ $slug ] ) ) { wp_die( esc_html( 'You attempted to edit a post type that does not exist. Perhaps it was deleted?' ) ); } $post_data['slug'] = $slug; $response = $this->handle_post_data( $post_data, 'save-edit', $slug ); if ( is_wp_error( $response ) ) { $error = true; $message = $response->get_error_message(); } else { $message = $response->message; } break; } if ( $render_settings ) { $this->render_setting_fields( $message, $error ); } } /** * Render Settings fields * * @param string $message Message. * @param bool $error Post error. * * @return void */ public function render_setting_fields( $message = '', $error = false ) { ?> 'message', 'additional_classes' => [ $class ], 'dismissible' => true, ] ); } ?>