942 lines
57 KiB
PHP
942 lines
57 KiB
PHP
<?php
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
class Ansico_CPTax_Admin {
|
|
private static $instance = null;
|
|
private $plugin;
|
|
|
|
public static function instance( $plugin ) {
|
|
if ( null === self::$instance ) {
|
|
self::$instance = new self( $plugin );
|
|
}
|
|
|
|
return self::$instance;
|
|
}
|
|
|
|
public function __construct( $plugin ) {
|
|
$this->plugin = $plugin;
|
|
add_action( 'admin_menu', array( $this, 'admin_menu' ) );
|
|
add_action( 'admin_init', array( $this, 'handle_actions' ) );
|
|
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
|
}
|
|
|
|
public function admin_menu() {
|
|
add_menu_page(
|
|
__( 'Ansico CPT & Taxonomies', 'ansico-cpt-and-taxonomies' ),
|
|
__( 'Ansico CPT', 'ansico-cpt-and-taxonomies' ),
|
|
'manage_options',
|
|
'ansico-cptax',
|
|
array( $this, 'render_cpts_page' ),
|
|
'dashicons-database-add',
|
|
58
|
|
);
|
|
|
|
add_submenu_page(
|
|
'ansico-cptax',
|
|
__( 'Custom Post Types', 'ansico-cpt-and-taxonomies' ),
|
|
__( 'Custom Post Types', 'ansico-cpt-and-taxonomies' ),
|
|
'manage_options',
|
|
'ansico-cptax',
|
|
array( $this, 'render_cpts_page' )
|
|
);
|
|
|
|
add_submenu_page(
|
|
'ansico-cptax',
|
|
__( 'Taxonomies', 'ansico-cpt-and-taxonomies' ),
|
|
__( 'Taxonomies', 'ansico-cpt-and-taxonomies' ),
|
|
'manage_options',
|
|
'ansico-cptax-taxonomies',
|
|
array( $this, 'render_taxonomies_page' )
|
|
);
|
|
|
|
add_submenu_page(
|
|
'ansico-cptax',
|
|
__( 'Tools', 'ansico-cpt-and-taxonomies' ),
|
|
__( 'Tools', 'ansico-cpt-and-taxonomies' ),
|
|
'manage_options',
|
|
'ansico-cptax-tools',
|
|
array( $this, 'render_tools_page' )
|
|
);
|
|
}
|
|
|
|
public function enqueue_assets( $hook_suffix ) {
|
|
if ( false === strpos( $hook_suffix, 'ansico-cptax' ) ) {
|
|
return;
|
|
}
|
|
|
|
wp_enqueue_style(
|
|
'ansico-cptax-admin',
|
|
ANSICO_CPTAX_URL . 'assets/admin.css',
|
|
array(),
|
|
ANSICO_CPTAX_VERSION
|
|
);
|
|
|
|
wp_enqueue_script(
|
|
'ansico-cptax-admin',
|
|
ANSICO_CPTAX_URL . 'assets/admin.js',
|
|
array(),
|
|
ANSICO_CPTAX_VERSION,
|
|
true
|
|
);
|
|
}
|
|
|
|
public function handle_actions() {
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
return;
|
|
}
|
|
|
|
if ( empty( $_POST['ansico_cptax_action'] ) ) {
|
|
return;
|
|
}
|
|
|
|
$action = sanitize_text_field( wp_unslash( $_POST['ansico_cptax_action'] ) );
|
|
|
|
if ( 'export_json' === $action ) {
|
|
check_admin_referer( 'ansico_cptax_export' );
|
|
$this->download_export();
|
|
}
|
|
|
|
check_admin_referer( 'ansico_cptax_save' );
|
|
|
|
if ( 'save_cpt' === $action ) {
|
|
$record = $this->sanitize_cpt_request();
|
|
if ( ! empty( $record['is_override'] ) ) {
|
|
$records = $this->plugin->get_cpt_overrides();
|
|
$records = $this->upsert_by_key( $records, sanitize_key( wp_unslash( $_POST['current_key'] ?? '' ) ), $record, 'key' );
|
|
$this->plugin->save_cpt_overrides( $records );
|
|
} else {
|
|
$records = $this->plugin->get_cpts();
|
|
$records = $this->upsert_by_key( $records, sanitize_key( wp_unslash( $_POST['current_key'] ?? '' ) ), $record, 'key' );
|
|
$this->plugin->save_cpts( $records );
|
|
}
|
|
flush_rewrite_rules();
|
|
wp_safe_redirect( admin_url( 'admin.php?page=ansico-cptax&updated=1' ) );
|
|
exit;
|
|
}
|
|
|
|
if ( 'delete_cpt' === $action ) {
|
|
$key = sanitize_key( wp_unslash( $_POST['key'] ?? '' ) );
|
|
$is_override = ! empty( $_POST['is_override'] );
|
|
$records = $is_override ? $this->plugin->get_cpt_overrides() : $this->plugin->get_cpts();
|
|
$records = array_values( array_filter( $records, function( $cpt ) use ( $key ) {
|
|
return ( $cpt['key'] ?? '' ) !== $key;
|
|
} ) );
|
|
if ( $is_override ) {
|
|
$this->plugin->save_cpt_overrides( $records );
|
|
} else {
|
|
$this->plugin->save_cpts( $records );
|
|
}
|
|
flush_rewrite_rules();
|
|
wp_safe_redirect( admin_url( 'admin.php?page=ansico-cptax&deleted=1' ) );
|
|
exit;
|
|
}
|
|
|
|
if ( 'save_taxonomy' === $action ) {
|
|
$record = $this->sanitize_taxonomy_request();
|
|
if ( ! empty( $record['is_override'] ) ) {
|
|
$records = $this->plugin->get_taxonomy_overrides();
|
|
$records = $this->upsert_by_key( $records, sanitize_key( wp_unslash( $_POST['current_key'] ?? '' ) ), $record, 'key' );
|
|
$this->plugin->save_taxonomy_overrides( $records );
|
|
} else {
|
|
$records = $this->plugin->get_taxonomies();
|
|
$records = $this->upsert_by_key( $records, sanitize_key( wp_unslash( $_POST['current_key'] ?? '' ) ), $record, 'key' );
|
|
$this->plugin->save_taxonomies( $records );
|
|
}
|
|
flush_rewrite_rules();
|
|
wp_safe_redirect( admin_url( 'admin.php?page=ansico-cptax-taxonomies&updated=1' ) );
|
|
exit;
|
|
}
|
|
|
|
if ( 'delete_taxonomy' === $action ) {
|
|
$key = sanitize_key( wp_unslash( $_POST['key'] ?? '' ) );
|
|
$is_override = ! empty( $_POST['is_override'] );
|
|
$records = $is_override ? $this->plugin->get_taxonomy_overrides() : $this->plugin->get_taxonomies();
|
|
$records = array_values( array_filter( $records, function( $taxonomy ) use ( $key ) {
|
|
return ( $taxonomy['key'] ?? '' ) !== $key;
|
|
} ) );
|
|
if ( $is_override ) {
|
|
$this->plugin->save_taxonomy_overrides( $records );
|
|
} else {
|
|
$this->plugin->save_taxonomies( $records );
|
|
}
|
|
flush_rewrite_rules();
|
|
wp_safe_redirect( admin_url( 'admin.php?page=ansico-cptax-taxonomies&deleted=1' ) );
|
|
exit;
|
|
}
|
|
|
|
if ( 'import_json' === $action ) {
|
|
$replace_existing = ! empty( $_POST['replace_existing'] );
|
|
$result = $this->handle_import_json( $replace_existing );
|
|
$status = ! empty( $result['error'] ) ? 'import_error=1' : 'imported=1';
|
|
$message = ! empty( $result['message'] ) ? rawurlencode( $result['message'] ) : '';
|
|
wp_safe_redirect( admin_url( 'admin.php?page=ansico-cptax-tools&' . $status . '&message=' . $message ) );
|
|
exit;
|
|
}
|
|
}
|
|
|
|
private function download_export() {
|
|
$filename = 'ansico-cptax-export-' . gmdate( 'Y-m-d-His' ) . '.json';
|
|
$payload = $this->plugin->get_export_payload();
|
|
|
|
nocache_headers();
|
|
header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) );
|
|
header( 'Content-Disposition: attachment; filename=' . $filename );
|
|
echo wp_json_encode( $payload, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES );
|
|
exit;
|
|
}
|
|
|
|
private function handle_import_json( $replace_existing ) {
|
|
if ( empty( $_FILES['import_file']['tmp_name'] ) ) {
|
|
return array(
|
|
'error' => true,
|
|
'message' => __( 'No JSON file was uploaded.', 'ansico-cpt-and-taxonomies' ),
|
|
);
|
|
}
|
|
|
|
$raw = file_get_contents( $_FILES['import_file']['tmp_name'] ); // phpcs:ignore WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown
|
|
if ( false === $raw || '' === $raw ) {
|
|
return array(
|
|
'error' => true,
|
|
'message' => __( 'The uploaded file could not be read.', 'ansico-cpt-and-taxonomies' ),
|
|
);
|
|
}
|
|
|
|
$payload = json_decode( $raw, true );
|
|
if ( ! is_array( $payload ) ) {
|
|
return array(
|
|
'error' => true,
|
|
'message' => __( 'The uploaded file is not valid JSON.', 'ansico-cpt-and-taxonomies' ),
|
|
);
|
|
}
|
|
|
|
$cpts = $this->normalize_import_records( $payload['cpts'] ?? array(), 'cpt' );
|
|
$taxonomies = $this->normalize_import_records( $payload['taxonomies'] ?? array(), 'taxonomy' );
|
|
$cpt_overrides = $this->normalize_import_records( $payload['cpt_overrides'] ?? array(), 'cpt' );
|
|
$taxonomy_overrides = $this->normalize_import_records( $payload['taxonomy_overrides'] ?? array(), 'taxonomy' );
|
|
|
|
if ( $replace_existing ) {
|
|
$this->plugin->save_cpts( $cpts );
|
|
$this->plugin->save_taxonomies( $taxonomies );
|
|
$this->plugin->save_cpt_overrides( $cpt_overrides );
|
|
$this->plugin->save_taxonomy_overrides( $taxonomy_overrides );
|
|
} else {
|
|
$this->plugin->save_cpts( $this->merge_by_key( $this->plugin->get_cpts(), $cpts ) );
|
|
$this->plugin->save_taxonomies( $this->merge_by_key( $this->plugin->get_taxonomies(), $taxonomies ) );
|
|
$this->plugin->save_cpt_overrides( $this->merge_by_key( $this->plugin->get_cpt_overrides(), $cpt_overrides ) );
|
|
$this->plugin->save_taxonomy_overrides( $this->merge_by_key( $this->plugin->get_taxonomy_overrides(), $taxonomy_overrides ) );
|
|
}
|
|
|
|
flush_rewrite_rules();
|
|
|
|
return array(
|
|
'error' => false,
|
|
'message' => __( 'JSON import completed.', 'ansico-cpt-and-taxonomies' ),
|
|
);
|
|
}
|
|
|
|
private function normalize_import_records( $records, $type ) {
|
|
$normalized = array();
|
|
if ( ! is_array( $records ) ) {
|
|
return $normalized;
|
|
}
|
|
|
|
foreach ( $records as $record ) {
|
|
if ( 'taxonomy' === $type ) {
|
|
$record = $this->plugin->normalize_taxonomy_record( $record );
|
|
} else {
|
|
$record = $this->plugin->normalize_cpt_record( $record );
|
|
}
|
|
|
|
if ( empty( $record['key'] ) ) {
|
|
continue;
|
|
}
|
|
$normalized[] = $record;
|
|
}
|
|
|
|
return $normalized;
|
|
}
|
|
|
|
private function merge_by_key( $existing, $incoming ) {
|
|
foreach ( $incoming as $record ) {
|
|
$existing = $this->upsert_by_key( $existing, $record['key'] ?? '', $record, 'key' );
|
|
}
|
|
|
|
return array_values( $existing );
|
|
}
|
|
|
|
private function upsert_by_key( $records, $current_key, $record, $key_field ) {
|
|
$updated = false;
|
|
foreach ( $records as $index => $existing ) {
|
|
if ( ( $existing[ $key_field ] ?? '' ) === $current_key ) {
|
|
$records[ $index ] = $record;
|
|
$updated = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( ! $updated ) {
|
|
$records[] = $record;
|
|
}
|
|
|
|
return array_values( $records );
|
|
}
|
|
|
|
|
|
private function sanitize_cpt_request() {
|
|
$supports = isset( $_POST['supports'] ) && is_array( $_POST['supports'] ) ? array_map( 'sanitize_key', wp_unslash( $_POST['supports'] ) ) : array();
|
|
$taxonomies = isset( $_POST['taxonomies'] ) && is_array( $_POST['taxonomies'] ) ? array_map( 'sanitize_key', wp_unslash( $_POST['taxonomies'] ) ) : array();
|
|
$custom_fields = $this->sanitize_custom_fields();
|
|
$template_settings = array(
|
|
'single_mode' => sanitize_key( wp_unslash( $_POST['single_mode'] ?? 'plugin' ) ),
|
|
'archive_mode' => sanitize_key( wp_unslash( $_POST['archive_mode'] ?? 'plugin' ) ),
|
|
'single_show_featured' => ! empty( $_POST['single_show_featured'] ) ? 1 : 0,
|
|
'single_show_meta' => ! empty( $_POST['single_show_meta'] ) ? 1 : 0,
|
|
'single_show_terms' => ! empty( $_POST['single_show_terms'] ) ? 1 : 0,
|
|
'single_show_custom_fields' => ! empty( $_POST['single_show_custom_fields'] ) ? 1 : 0,
|
|
'archive_show_featured' => ! empty( $_POST['archive_show_featured'] ) ? 1 : 0,
|
|
'archive_show_excerpt' => ! empty( $_POST['archive_show_excerpt'] ) ? 1 : 0,
|
|
'archive_show_meta' => ! empty( $_POST['archive_show_meta'] ) ? 1 : 0,
|
|
'archive_columns' => absint( wp_unslash( $_POST['archive_columns'] ?? 3 ) ),
|
|
'archive_intro' => sanitize_textarea_field( wp_unslash( $_POST['archive_intro'] ?? '' ) ),
|
|
);
|
|
|
|
return $this->plugin->normalize_cpt_record(
|
|
array(
|
|
'key' => sanitize_key( wp_unslash( $_POST['key'] ?? '' ) ),
|
|
'singular_label' => sanitize_text_field( wp_unslash( $_POST['singular_label'] ?? '' ) ),
|
|
'plural_label' => sanitize_text_field( wp_unslash( $_POST['plural_label'] ?? '' ) ),
|
|
'slug' => sanitize_title( wp_unslash( $_POST['slug'] ?? '' ) ),
|
|
'exclude_from_search' => ! empty( $_POST['exclude_from_search'] ) ? 1 : 0,
|
|
'can_export' => ! empty( $_POST['can_export'] ) ? 1 : 0,
|
|
'supports' => $supports,
|
|
'taxonomies' => $taxonomies,
|
|
'custom_fields' => $custom_fields,
|
|
'template_settings' => $template_settings,
|
|
'is_override' => ! empty( $_POST['is_override'] ) ? 1 : 0,
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
private function sanitize_taxonomy_request() {
|
|
$object_type = isset( $_POST['object_type'] ) && is_array( $_POST['object_type'] ) ? array_map( 'sanitize_key', wp_unslash( $_POST['object_type'] ) ) : array();
|
|
$template_settings = array(
|
|
'archive_mode' => sanitize_key( wp_unslash( $_POST['archive_mode'] ?? 'plugin' ) ),
|
|
'archive_show_featured' => ! empty( $_POST['archive_show_featured'] ) ? 1 : 0,
|
|
'archive_show_excerpt' => ! empty( $_POST['archive_show_excerpt'] ) ? 1 : 0,
|
|
'archive_show_meta' => ! empty( $_POST['archive_show_meta'] ) ? 1 : 0,
|
|
'archive_columns' => absint( wp_unslash( $_POST['archive_columns'] ?? 3 ) ),
|
|
'archive_intro' => sanitize_textarea_field( wp_unslash( $_POST['archive_intro'] ?? '' ) ),
|
|
);
|
|
|
|
return $this->plugin->normalize_taxonomy_record(
|
|
array(
|
|
'key' => sanitize_key( wp_unslash( $_POST['key'] ?? '' ) ),
|
|
'singular_label' => sanitize_text_field( wp_unslash( $_POST['singular_label'] ?? '' ) ),
|
|
'plural_label' => sanitize_text_field( wp_unslash( $_POST['plural_label'] ?? '' ) ),
|
|
'slug' => sanitize_title( wp_unslash( $_POST['slug'] ?? '' ) ),
|
|
'hierarchical' => ! empty( $_POST['hierarchical'] ) ? 1 : 0,
|
|
'object_type' => $object_type,
|
|
'template_settings' => $template_settings,
|
|
'is_override' => ! empty( $_POST['is_override'] ) ? 1 : 0,
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
private function sanitize_custom_fields() {
|
|
$labels = isset( $_POST['field_label'] ) && is_array( $_POST['field_label'] ) ? wp_unslash( $_POST['field_label'] ) : array();
|
|
$keys = isset( $_POST['field_key'] ) && is_array( $_POST['field_key'] ) ? wp_unslash( $_POST['field_key'] ) : array();
|
|
$types = isset( $_POST['field_type'] ) && is_array( $_POST['field_type'] ) ? wp_unslash( $_POST['field_type'] ) : array();
|
|
$descriptions = isset( $_POST['field_description'] ) && is_array( $_POST['field_description'] ) ? wp_unslash( $_POST['field_description'] ) : array();
|
|
$options = isset( $_POST['field_options'] ) && is_array( $_POST['field_options'] ) ? wp_unslash( $_POST['field_options'] ) : array();
|
|
$custom_fields = array();
|
|
|
|
foreach ( $keys as $index => $key ) {
|
|
$key = sanitize_key( $key );
|
|
if ( ! $key ) {
|
|
continue;
|
|
}
|
|
$raw_options = preg_split( '/[
|
|
,]+/', (string) ( $options[ $index ] ?? '' ) );
|
|
$normalized_options = array();
|
|
foreach ( $raw_options as $option ) {
|
|
$option = sanitize_text_field( $option );
|
|
if ( '' !== $option ) {
|
|
$normalized_options[] = $option;
|
|
}
|
|
}
|
|
$custom_fields[] = array(
|
|
'label' => sanitize_text_field( $labels[ $index ] ?? '' ),
|
|
'key' => $key,
|
|
'type' => sanitize_key( $types[ $index ] ?? 'text' ),
|
|
'description' => sanitize_text_field( $descriptions[ $index ] ?? '' ),
|
|
'options' => $normalized_options,
|
|
);
|
|
}
|
|
|
|
return $custom_fields;
|
|
}
|
|
|
|
private function render_page_header( $title, $description, $active_tab ) {
|
|
?>
|
|
<div class="wrap ansico-cptax-wrap">
|
|
<h1><?php echo esc_html( $title ); ?></h1>
|
|
<p class="ansico-cptax-intro"><?php echo esc_html( $description ); ?></p>
|
|
<nav class="nav-tab-wrapper ansico-cptax-tabs">
|
|
<a href="<?php echo esc_url( admin_url( 'admin.php?page=ansico-cptax' ) ); ?>" class="nav-tab <?php echo 'cpts' === $active_tab ? 'nav-tab-active' : ''; ?>"><?php esc_html_e( 'Custom Post Types', 'ansico-cpt-and-taxonomies' ); ?></a>
|
|
<a href="<?php echo esc_url( admin_url( 'admin.php?page=ansico-cptax-taxonomies' ) ); ?>" class="nav-tab <?php echo 'taxonomies' === $active_tab ? 'nav-tab-active' : ''; ?>"><?php esc_html_e( 'Taxonomies', 'ansico-cpt-and-taxonomies' ); ?></a>
|
|
<a href="<?php echo esc_url( admin_url( 'admin.php?page=ansico-cptax-tools' ) ); ?>" class="nav-tab <?php echo 'tools' === $active_tab ? 'nav-tab-active' : ''; ?>"><?php esc_html_e( 'Tools', 'ansico-cpt-and-taxonomies' ); ?></a>
|
|
</nav>
|
|
<?php
|
|
$this->render_notices();
|
|
}
|
|
|
|
private function render_notices() {
|
|
if ( ! empty( $_GET['updated'] ) ) {
|
|
echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__( 'Saved successfully.', 'ansico-cpt-and-taxonomies' ) . '</p></div>';
|
|
}
|
|
if ( ! empty( $_GET['deleted'] ) ) {
|
|
echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__( 'Deleted successfully.', 'ansico-cpt-and-taxonomies' ) . '</p></div>';
|
|
}
|
|
if ( ! empty( $_GET['imported'] ) ) {
|
|
$message = sanitize_text_field( wp_unslash( $_GET['message'] ?? __( 'Import completed.', 'ansico-cpt-and-taxonomies' ) ) );
|
|
echo '<div class="notice notice-success is-dismissible"><p>' . esc_html( $message ) . '</p></div>';
|
|
}
|
|
if ( ! empty( $_GET['import_error'] ) ) {
|
|
$message = sanitize_text_field( wp_unslash( $_GET['message'] ?? __( 'Import failed.', 'ansico-cpt-and-taxonomies' ) ) );
|
|
echo '<div class="notice notice-error is-dismissible"><p>' . esc_html( $message ) . '</p></div>';
|
|
}
|
|
}
|
|
|
|
public function render_cpts_page() {
|
|
$managed = $this->plugin->get_cpts();
|
|
$overrides = $this->plugin->get_cpt_overrides();
|
|
$edit_key = sanitize_key( wp_unslash( $_GET['edit'] ?? '' ) );
|
|
$import_key = sanitize_key( wp_unslash( $_GET['import'] ?? '' ) );
|
|
$editing = null;
|
|
|
|
foreach ( array_merge( $managed, $overrides ) as $record ) {
|
|
if ( $edit_key && ( $record['key'] ?? '' ) === $edit_key ) {
|
|
$editing = $record;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( ! $editing && $import_key ) {
|
|
$all_post_types = $this->plugin->get_editable_post_types();
|
|
if ( isset( $all_post_types[ $import_key ] ) ) {
|
|
$editing = $this->map_post_type_object_to_record( $all_post_types[ $import_key ] );
|
|
$editing['is_override'] = 1;
|
|
}
|
|
}
|
|
|
|
$editing = $editing ?: $this->plugin->normalize_cpt_record( array( 'supports' => array( 'title', 'editor' ) ) );
|
|
$all_taxonomies = $this->plugin->get_editable_taxonomies();
|
|
$all_post_types = $this->plugin->get_editable_post_types();
|
|
$field_types = $this->get_field_types();
|
|
$template_row = $this->get_field_row_template( $field_types );
|
|
|
|
$this->render_page_header(
|
|
__( 'Ansico CPT & Taxonomies', 'ansico-cpt-and-taxonomies' ),
|
|
__( 'Create new custom post types or import existing post types for plugin-based overrides.', 'ansico-cpt-and-taxonomies' ),
|
|
'cpts'
|
|
);
|
|
?>
|
|
<div class="ansico-cptax-grid ansico-cptax-grid--wide">
|
|
<section class="ansico-cptax-card">
|
|
<div class="ansico-cptax-card__header">
|
|
<h2><?php echo $edit_key ? esc_html__( 'Edit Custom Post Type', 'ansico-cpt-and-taxonomies' ) : esc_html__( 'Add Custom Post Type', 'ansico-cpt-and-taxonomies' ); ?></h2>
|
|
<p><?php esc_html_e( 'Define labels, slug, supported features, taxonomies, custom fields, and template behavior.', 'ansico-cpt-and-taxonomies' ); ?></p>
|
|
</div>
|
|
<form method="post">
|
|
<?php wp_nonce_field( 'ansico_cptax_save' ); ?>
|
|
<input type="hidden" name="ansico_cptax_action" value="save_cpt">
|
|
<input type="hidden" name="current_key" value="<?php echo esc_attr( $editing['key'] ?? '' ); ?>">
|
|
<input type="hidden" name="is_override" value="<?php echo ! empty( $editing['is_override'] ) ? '1' : '0'; ?>">
|
|
|
|
<div class="ansico-cptax-form-grid">
|
|
<div>
|
|
<label for="key"><strong><?php esc_html_e( 'Post type key', 'ansico-cpt-and-taxonomies' ); ?></strong></label>
|
|
<input name="key" id="key" type="text" class="regular-text ansico-slug-source" maxlength="20" required value="<?php echo esc_attr( $editing['key'] ?? '' ); ?>" <?php disabled( ! empty( $editing['is_override'] ) ); ?>>
|
|
<p class="description"><?php esc_html_e( 'Lowercase letters, numbers, dashes, and underscores. Max 20 characters for new post types.', 'ansico-cpt-and-taxonomies' ); ?></p>
|
|
</div>
|
|
<div>
|
|
<label for="slug"><strong><?php esc_html_e( 'Slug', 'ansico-cpt-and-taxonomies' ); ?></strong></label>
|
|
<input name="slug" id="slug" type="text" class="regular-text ansico-slug-target" required value="<?php echo esc_attr( $editing['slug'] ?? '' ); ?>">
|
|
<p class="description"><?php esc_html_e( 'Used for front-end URLs and archives.', 'ansico-cpt-and-taxonomies' ); ?></p>
|
|
</div>
|
|
<div>
|
|
<label for="singular_label"><strong><?php esc_html_e( 'Singular label', 'ansico-cpt-and-taxonomies' ); ?></strong></label>
|
|
<input name="singular_label" id="singular_label" type="text" class="regular-text" required value="<?php echo esc_attr( $editing['singular_label'] ?? '' ); ?>">
|
|
</div>
|
|
<div>
|
|
<label for="plural_label"><strong><?php esc_html_e( 'Plural label', 'ansico-cpt-and-taxonomies' ); ?></strong></label>
|
|
<input name="plural_label" id="plural_label" type="text" class="regular-text" required value="<?php echo esc_attr( $editing['plural_label'] ?? '' ); ?>">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ansico-cptax-option-columns">
|
|
<div>
|
|
<h3><?php esc_html_e( 'Visibility', 'ansico-cpt-and-taxonomies' ); ?></h3>
|
|
<label><input type="checkbox" name="exclude_from_search" value="1" <?php checked( ! empty( $editing['exclude_from_search'] ) ); ?>> <?php esc_html_e( 'Exclude from search results', 'ansico-cpt-and-taxonomies' ); ?></label><br>
|
|
<label><input type="checkbox" name="can_export" value="1" <?php checked( ! empty( $editing['can_export'] ) ); ?>> <?php esc_html_e( 'Allow export', 'ansico-cpt-and-taxonomies' ); ?></label>
|
|
</div>
|
|
<div>
|
|
<h3><?php esc_html_e( 'Supports', 'ansico-cpt-and-taxonomies' ); ?></h3>
|
|
<?php foreach ( array( 'title' => 'Title', 'editor' => 'Editor', 'thumbnail' => 'Featured image', 'author' => 'Author', 'comments' => 'Comments' ) as $feature => $label ) : ?>
|
|
<label class="ansico-inline-option"><input type="checkbox" name="supports[]" value="<?php echo esc_attr( $feature ); ?>" <?php checked( in_array( $feature, $editing['supports'] ?? array(), true ) ); ?>> <?php echo esc_html( $label ); ?></label>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ansico-cptax-card ansico-cptax-card--nested">
|
|
<div class="ansico-cptax-card__header">
|
|
<h3><?php esc_html_e( 'Attached taxonomies', 'ansico-cpt-and-taxonomies' ); ?></h3>
|
|
<p><?php esc_html_e( 'Connect categories, tags, or any existing taxonomy to this post type.', 'ansico-cpt-and-taxonomies' ); ?></p>
|
|
</div>
|
|
<div class="ansico-checkbox-grid">
|
|
<?php foreach ( $all_taxonomies as $name => $taxonomy ) : ?>
|
|
<label><input type="checkbox" name="taxonomies[]" value="<?php echo esc_attr( $name ); ?>" <?php checked( in_array( $name, $editing['taxonomies'] ?? array(), true ) ); ?>> <?php echo esc_html( ( $taxonomy->labels->name ?? $name ) . ' (' . $name . ')' ); ?></label>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div class="ansico-cptax-card ansico-cptax-card--nested">
|
|
<div class="ansico-cptax-card__header">
|
|
<h3><?php esc_html_e( 'Template customization', 'ansico-cpt-and-taxonomies' ); ?></h3>
|
|
<p><?php esc_html_e( 'Choose whether the plugin should supply the front-end templates or leave rendering to your theme.', 'ansico-cpt-and-taxonomies' ); ?></p>
|
|
</div>
|
|
<?php $template_settings = $editing['template_settings'] ?? array(); ?>
|
|
<div class="ansico-cptax-form-grid">
|
|
<div>
|
|
<label for="single_mode"><strong><?php esc_html_e( 'Single template source', 'ansico-cpt-and-taxonomies' ); ?></strong></label>
|
|
<select name="single_mode" id="single_mode">
|
|
<option value="plugin" <?php selected( $template_settings['single_mode'] ?? 'plugin', 'plugin' ); ?>><?php esc_html_e( 'Use plugin template', 'ansico-cpt-and-taxonomies' ); ?></option>
|
|
<option value="theme" <?php selected( $template_settings['single_mode'] ?? 'plugin', 'theme' ); ?>><?php esc_html_e( 'Let theme handle it', 'ansico-cpt-and-taxonomies' ); ?></option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label for="archive_mode"><strong><?php esc_html_e( 'Archive template source', 'ansico-cpt-and-taxonomies' ); ?></strong></label>
|
|
<select name="archive_mode" id="archive_mode">
|
|
<option value="plugin" <?php selected( $template_settings['archive_mode'] ?? 'plugin', 'plugin' ); ?>><?php esc_html_e( 'Use plugin template', 'ansico-cpt-and-taxonomies' ); ?></option>
|
|
<option value="theme" <?php selected( $template_settings['archive_mode'] ?? 'plugin', 'theme' ); ?>><?php esc_html_e( 'Let theme handle it', 'ansico-cpt-and-taxonomies' ); ?></option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label for="archive_columns"><strong><?php esc_html_e( 'Archive columns', 'ansico-cpt-and-taxonomies' ); ?></strong></label>
|
|
<select name="archive_columns" id="archive_columns">
|
|
<?php foreach ( array( 1, 2, 3, 4 ) as $columns ) : ?>
|
|
<option value="<?php echo esc_attr( $columns ); ?>" <?php selected( (int) ( $template_settings['archive_columns'] ?? 3 ), $columns ); ?>><?php echo esc_html( $columns ); ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label for="archive_intro"><strong><?php esc_html_e( 'Archive intro text', 'ansico-cpt-and-taxonomies' ); ?></strong></label>
|
|
<textarea name="archive_intro" id="archive_intro" rows="3" class="large-text"><?php echo esc_textarea( $template_settings['archive_intro'] ?? '' ); ?></textarea>
|
|
</div>
|
|
</div>
|
|
<div class="ansico-cptax-option-columns">
|
|
<div>
|
|
<h4><?php esc_html_e( 'Single template elements', 'ansico-cpt-and-taxonomies' ); ?></h4>
|
|
<label class="ansico-inline-option"><input type="checkbox" name="single_show_featured" value="1" <?php checked( ! empty( $template_settings['single_show_featured'] ) ); ?>> <?php esc_html_e( 'Show featured image', 'ansico-cpt-and-taxonomies' ); ?></label>
|
|
<label class="ansico-inline-option"><input type="checkbox" name="single_show_meta" value="1" <?php checked( ! empty( $template_settings['single_show_meta'] ) ); ?>> <?php esc_html_e( 'Show post meta', 'ansico-cpt-and-taxonomies' ); ?></label>
|
|
<label class="ansico-inline-option"><input type="checkbox" name="single_show_terms" value="1" <?php checked( ! empty( $template_settings['single_show_terms'] ) ); ?>> <?php esc_html_e( 'Show attached taxonomy terms', 'ansico-cpt-and-taxonomies' ); ?></label>
|
|
<label class="ansico-inline-option"><input type="checkbox" name="single_show_custom_fields" value="1" <?php checked( ! empty( $template_settings['single_show_custom_fields'] ) ); ?>> <?php esc_html_e( 'Show custom fields section', 'ansico-cpt-and-taxonomies' ); ?></label>
|
|
</div>
|
|
<div>
|
|
<h4><?php esc_html_e( 'Archive template elements', 'ansico-cpt-and-taxonomies' ); ?></h4>
|
|
<label class="ansico-inline-option"><input type="checkbox" name="archive_show_featured" value="1" <?php checked( ! empty( $template_settings['archive_show_featured'] ) ); ?>> <?php esc_html_e( 'Show featured image', 'ansico-cpt-and-taxonomies' ); ?></label>
|
|
<label class="ansico-inline-option"><input type="checkbox" name="archive_show_excerpt" value="1" <?php checked( ! empty( $template_settings['archive_show_excerpt'] ) ); ?>> <?php esc_html_e( 'Show excerpt', 'ansico-cpt-and-taxonomies' ); ?></label>
|
|
<label class="ansico-inline-option"><input type="checkbox" name="archive_show_meta" value="1" <?php checked( ! empty( $template_settings['archive_show_meta'] ) ); ?>> <?php esc_html_e( 'Show post meta', 'ansico-cpt-and-taxonomies' ); ?></label>
|
|
</div>
|
|
</div>
|
|
<p class="description"><?php esc_html_e( 'When set to theme, WordPress can use single-{post_type}.php or archive-{post_type}.php from the active theme.', 'ansico-cpt-and-taxonomies' ); ?></p>
|
|
</div>
|
|
|
|
<div class="ansico-cptax-card ansico-cptax-card--nested">
|
|
<div class="ansico-cptax-card__header ansico-cptax-card__header--spread">
|
|
<div>
|
|
<h3><?php esc_html_e( 'Custom fields', 'ansico-cpt-and-taxonomies' ); ?></h3>
|
|
<p><?php esc_html_e( 'Add simple post meta fields. Select and radio fields accept one option per line or comma separated values.', 'ansico-cpt-and-taxonomies' ); ?></p>
|
|
</div>
|
|
<button type="button" class="button button-secondary" id="ansico-add-field"><?php esc_html_e( 'Add field', 'ansico-cpt-and-taxonomies' ); ?></button>
|
|
</div>
|
|
<div class="ansico-cptax-fields-wrap">
|
|
<table class="widefat striped ansico-cptax-fields-table" id="ansico-fields-table">
|
|
<thead>
|
|
<tr>
|
|
<th><?php esc_html_e( 'Label', 'ansico-cpt-and-taxonomies' ); ?></th>
|
|
<th><?php esc_html_e( 'Key', 'ansico-cpt-and-taxonomies' ); ?></th>
|
|
<th><?php esc_html_e( 'Type', 'ansico-cpt-and-taxonomies' ); ?></th>
|
|
<th><?php esc_html_e( 'Description', 'ansico-cpt-and-taxonomies' ); ?></th>
|
|
<th><?php esc_html_e( 'Options', 'ansico-cpt-and-taxonomies' ); ?></th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if ( ! empty( $editing['custom_fields'] ) ) : ?>
|
|
<?php foreach ( $editing['custom_fields'] as $field ) : ?>
|
|
<?php $this->render_field_row( $field, $field_types ); ?>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
<script type="text/html" id="tmpl-ansico-field-row"><?php echo $template_row; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></script>
|
|
</div>
|
|
</div>
|
|
|
|
<?php submit_button( $edit_key ? __( 'Save Custom Post Type', 'ansico-cpt-and-taxonomies' ) : __( 'Create Custom Post Type', 'ansico-cpt-and-taxonomies' ) ); ?>
|
|
</form>
|
|
</section>
|
|
|
|
<aside class="ansico-cptax-sidebar">
|
|
<section class="ansico-cptax-card">
|
|
<h2><?php esc_html_e( 'Plugin-created post types', 'ansico-cpt-and-taxonomies' ); ?></h2>
|
|
<?php $this->render_cpt_table( $managed, false ); ?>
|
|
</section>
|
|
<section class="ansico-cptax-card">
|
|
<h2><?php esc_html_e( 'Imported / overridden post types', 'ansico-cpt-and-taxonomies' ); ?></h2>
|
|
<?php $this->render_cpt_table( $overrides, true ); ?>
|
|
</section>
|
|
<section class="ansico-cptax-card">
|
|
<h2><?php esc_html_e( 'Available post types to import', 'ansico-cpt-and-taxonomies' ); ?></h2>
|
|
<table class="widefat striped"><thead><tr><th><?php esc_html_e( 'Name', 'ansico-cpt-and-taxonomies' ); ?></th><th><?php esc_html_e( 'Key', 'ansico-cpt-and-taxonomies' ); ?></th><th><?php esc_html_e( 'Action', 'ansico-cpt-and-taxonomies' ); ?></th></tr></thead><tbody>
|
|
<?php foreach ( $all_post_types as $name => $obj ) : ?>
|
|
<?php if ( $this->plugin->get_cpt_by_key( $name ) || $this->plugin->get_cpt_override_by_key( $name ) ) { continue; } ?>
|
|
<tr>
|
|
<td><?php echo esc_html( $obj->labels->name ?? $name ); ?></td>
|
|
<td><code><?php echo esc_html( $name ); ?></code></td>
|
|
<td><a class="button button-small" href="<?php echo esc_url( admin_url( 'admin.php?page=ansico-cptax&import=' . $name ) ); ?>"><?php esc_html_e( 'Import', 'ansico-cpt-and-taxonomies' ); ?></a></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody></table>
|
|
</section>
|
|
</aside>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
public function render_taxonomies_page() {
|
|
$managed = $this->plugin->get_taxonomies();
|
|
$overrides = $this->plugin->get_taxonomy_overrides();
|
|
$edit_key = sanitize_key( wp_unslash( $_GET['edit'] ?? '' ) );
|
|
$import_key = sanitize_key( wp_unslash( $_GET['import'] ?? '' ) );
|
|
$editing = null;
|
|
|
|
foreach ( array_merge( $managed, $overrides ) as $record ) {
|
|
if ( $edit_key && ( $record['key'] ?? '' ) === $edit_key ) {
|
|
$editing = $record;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( ! $editing && $import_key ) {
|
|
$all_taxonomies = $this->plugin->get_editable_taxonomies();
|
|
if ( isset( $all_taxonomies[ $import_key ] ) ) {
|
|
$editing = $this->map_taxonomy_object_to_record( $all_taxonomies[ $import_key ] );
|
|
$editing['is_override'] = 1;
|
|
}
|
|
}
|
|
|
|
$editing = $editing ?: $this->plugin->normalize_taxonomy_record( array( 'object_type' => array( 'post' ) ) );
|
|
$post_types = $this->plugin->get_editable_post_types();
|
|
|
|
$this->render_page_header(
|
|
__( 'Taxonomies', 'ansico-cpt-and-taxonomies' ),
|
|
__( 'Create new taxonomies or import existing ones for plugin-based overrides.', 'ansico-cpt-and-taxonomies' ),
|
|
'taxonomies'
|
|
);
|
|
?>
|
|
<div class="ansico-cptax-grid ansico-cptax-grid--wide">
|
|
<section class="ansico-cptax-card">
|
|
<div class="ansico-cptax-card__header">
|
|
<h2><?php echo $edit_key ? esc_html__( 'Edit Taxonomy', 'ansico-cpt-and-taxonomies' ) : esc_html__( 'Add Taxonomy', 'ansico-cpt-and-taxonomies' ); ?></h2>
|
|
<p><?php esc_html_e( 'Set labels, slug, hierarchy, connected post types, and archive template behavior.', 'ansico-cpt-and-taxonomies' ); ?></p>
|
|
</div>
|
|
<form method="post">
|
|
<?php wp_nonce_field( 'ansico_cptax_save' ); ?>
|
|
<input type="hidden" name="ansico_cptax_action" value="save_taxonomy">
|
|
<input type="hidden" name="current_key" value="<?php echo esc_attr( $editing['key'] ?? '' ); ?>">
|
|
<input type="hidden" name="is_override" value="<?php echo ! empty( $editing['is_override'] ) ? '1' : '0'; ?>">
|
|
|
|
<div class="ansico-cptax-form-grid">
|
|
<div>
|
|
<label for="key"><strong><?php esc_html_e( 'Taxonomy key', 'ansico-cpt-and-taxonomies' ); ?></strong></label>
|
|
<input name="key" id="key" type="text" class="regular-text ansico-slug-source" maxlength="32" required value="<?php echo esc_attr( $editing['key'] ?? '' ); ?>" <?php disabled( ! empty( $editing['is_override'] ) ); ?>>
|
|
</div>
|
|
<div>
|
|
<label for="slug"><strong><?php esc_html_e( 'Slug', 'ansico-cpt-and-taxonomies' ); ?></strong></label>
|
|
<input name="slug" id="slug" type="text" class="regular-text ansico-slug-target" required value="<?php echo esc_attr( $editing['slug'] ?? '' ); ?>">
|
|
</div>
|
|
<div>
|
|
<label for="singular_label"><strong><?php esc_html_e( 'Singular label', 'ansico-cpt-and-taxonomies' ); ?></strong></label>
|
|
<input name="singular_label" id="singular_label" type="text" class="regular-text" required value="<?php echo esc_attr( $editing['singular_label'] ?? '' ); ?>">
|
|
</div>
|
|
<div>
|
|
<label for="plural_label"><strong><?php esc_html_e( 'Plural label', 'ansico-cpt-and-taxonomies' ); ?></strong></label>
|
|
<input name="plural_label" id="plural_label" type="text" class="regular-text" required value="<?php echo esc_attr( $editing['plural_label'] ?? '' ); ?>">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ansico-cptax-card ansico-cptax-card--nested">
|
|
<h3><?php esc_html_e( 'Structure', 'ansico-cpt-and-taxonomies' ); ?></h3>
|
|
<label><input type="checkbox" name="hierarchical" value="1" <?php checked( ! empty( $editing['hierarchical'] ) ); ?>> <?php esc_html_e( 'Hierarchical like categories', 'ansico-cpt-and-taxonomies' ); ?></label>
|
|
<p class="description"><?php esc_html_e( 'Leave unchecked for tag-like behavior.', 'ansico-cpt-and-taxonomies' ); ?></p>
|
|
</div>
|
|
|
|
<div class="ansico-cptax-card ansico-cptax-card--nested">
|
|
<div class="ansico-cptax-card__header">
|
|
<h3><?php esc_html_e( 'Attach to post types', 'ansico-cpt-and-taxonomies' ); ?></h3>
|
|
</div>
|
|
<div class="ansico-checkbox-grid">
|
|
<?php foreach ( $post_types as $post_type ) : ?>
|
|
<label><input type="checkbox" name="object_type[]" value="<?php echo esc_attr( $post_type->name ); ?>" <?php checked( in_array( $post_type->name, $editing['object_type'] ?? array(), true ) ); ?>> <?php echo esc_html( $post_type->labels->name . ' (' . $post_type->name . ')' ); ?></label>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div class="ansico-cptax-card ansico-cptax-card--nested">
|
|
<div class="ansico-cptax-card__header">
|
|
<h3><?php esc_html_e( 'Archive template customization', 'ansico-cpt-and-taxonomies' ); ?></h3>
|
|
<p><?php esc_html_e( 'Control the plugin taxonomy archive layout or hand template rendering back to your theme.', 'ansico-cpt-and-taxonomies' ); ?></p>
|
|
</div>
|
|
<?php $template_settings = $editing['template_settings'] ?? array(); ?>
|
|
<div class="ansico-cptax-form-grid">
|
|
<div>
|
|
<label for="archive_mode"><strong><?php esc_html_e( 'Archive template source', 'ansico-cpt-and-taxonomies' ); ?></strong></label>
|
|
<select name="archive_mode" id="archive_mode">
|
|
<option value="plugin" <?php selected( $template_settings['archive_mode'] ?? 'plugin', 'plugin' ); ?>><?php esc_html_e( 'Use plugin template', 'ansico-cpt-and-taxonomies' ); ?></option>
|
|
<option value="theme" <?php selected( $template_settings['archive_mode'] ?? 'plugin', 'theme' ); ?>><?php esc_html_e( 'Let theme handle it', 'ansico-cpt-and-taxonomies' ); ?></option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label for="archive_columns"><strong><?php esc_html_e( 'Archive columns', 'ansico-cpt-and-taxonomies' ); ?></strong></label>
|
|
<select name="archive_columns" id="archive_columns">
|
|
<?php foreach ( array( 1, 2, 3, 4 ) as $columns ) : ?>
|
|
<option value="<?php echo esc_attr( $columns ); ?>" <?php selected( (int) ( $template_settings['archive_columns'] ?? 3 ), $columns ); ?>><?php echo esc_html( $columns ); ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label for="archive_intro"><strong><?php esc_html_e( 'Archive intro text', 'ansico-cpt-and-taxonomies' ); ?></strong></label>
|
|
<textarea name="archive_intro" id="archive_intro" rows="3" class="large-text"><?php echo esc_textarea( $template_settings['archive_intro'] ?? '' ); ?></textarea>
|
|
</div>
|
|
</div>
|
|
<div class="ansico-cptax-option-columns">
|
|
<div>
|
|
<label class="ansico-inline-option"><input type="checkbox" name="archive_show_featured" value="1" <?php checked( ! empty( $template_settings['archive_show_featured'] ) ); ?>> <?php esc_html_e( 'Show featured image', 'ansico-cpt-and-taxonomies' ); ?></label>
|
|
<label class="ansico-inline-option"><input type="checkbox" name="archive_show_excerpt" value="1" <?php checked( ! empty( $template_settings['archive_show_excerpt'] ) ); ?>> <?php esc_html_e( 'Show excerpt', 'ansico-cpt-and-taxonomies' ); ?></label>
|
|
<label class="ansico-inline-option"><input type="checkbox" name="archive_show_meta" value="1" <?php checked( ! empty( $template_settings['archive_show_meta'] ) ); ?>> <?php esc_html_e( 'Show post meta', 'ansico-cpt-and-taxonomies' ); ?></label>
|
|
</div>
|
|
</div>
|
|
<p class="description"><?php esc_html_e( 'When set to theme, WordPress can use taxonomy-{taxonomy}.php or related archive templates from the active theme.', 'ansico-cpt-and-taxonomies' ); ?></p>
|
|
</div>
|
|
|
|
<?php submit_button( $edit_key ? __( 'Save Taxonomy', 'ansico-cpt-and-taxonomies' ) : __( 'Create Taxonomy', 'ansico-cpt-and-taxonomies' ) ); ?>
|
|
</form>
|
|
</section>
|
|
|
|
<aside class="ansico-cptax-sidebar">
|
|
<section class="ansico-cptax-card">
|
|
<h2><?php esc_html_e( 'Plugin-created taxonomies', 'ansico-cpt-and-taxonomies' ); ?></h2>
|
|
<?php $this->render_taxonomy_table( $managed, false ); ?>
|
|
</section>
|
|
<section class="ansico-cptax-card">
|
|
<h2><?php esc_html_e( 'Imported / overridden taxonomies', 'ansico-cpt-and-taxonomies' ); ?></h2>
|
|
<?php $this->render_taxonomy_table( $overrides, true ); ?>
|
|
</section>
|
|
<section class="ansico-cptax-card">
|
|
<h2><?php esc_html_e( 'Available taxonomies to import', 'ansico-cpt-and-taxonomies' ); ?></h2>
|
|
<table class="widefat striped"><thead><tr><th><?php esc_html_e( 'Name', 'ansico-cpt-and-taxonomies' ); ?></th><th><?php esc_html_e( 'Key', 'ansico-cpt-and-taxonomies' ); ?></th><th><?php esc_html_e( 'Action', 'ansico-cpt-and-taxonomies' ); ?></th></tr></thead><tbody>
|
|
<?php foreach ( $this->plugin->get_editable_taxonomies() as $name => $obj ) : ?>
|
|
<?php if ( $this->plugin->get_taxonomy_by_key( $name ) || $this->plugin->get_taxonomy_override_by_key( $name ) ) { continue; } ?>
|
|
<tr>
|
|
<td><?php echo esc_html( $obj->labels->name ?? $name ); ?></td>
|
|
<td><code><?php echo esc_html( $name ); ?></code></td>
|
|
<td><a class="button button-small" href="<?php echo esc_url( admin_url( 'admin.php?page=ansico-cptax-taxonomies&import=' . $name ) ); ?>"><?php esc_html_e( 'Import', 'ansico-cpt-and-taxonomies' ); ?></a></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody></table>
|
|
</section>
|
|
</aside>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
public function render_tools_page() {
|
|
$payload = $this->plugin->get_export_payload();
|
|
$this->render_page_header(
|
|
__( 'Tools', 'ansico-cpt-and-taxonomies' ),
|
|
__( 'Export or import plugin-managed custom post types, taxonomies, overrides, and custom fields as JSON.', 'ansico-cpt-and-taxonomies' ),
|
|
'tools'
|
|
);
|
|
?>
|
|
<div class="ansico-cptax-grid">
|
|
<section class="ansico-cptax-card">
|
|
<h2><?php esc_html_e( 'Export JSON', 'ansico-cpt-and-taxonomies' ); ?></h2>
|
|
<p><?php esc_html_e( 'Download a JSON snapshot of all plugin-managed registrations and overrides.', 'ansico-cpt-and-taxonomies' ); ?></p>
|
|
<ul class="ansico-cptax-stat-list">
|
|
<li><?php echo esc_html( sprintf( __( '%d custom post types', 'ansico-cpt-and-taxonomies' ), count( $payload['cpts'] ) ) ); ?></li>
|
|
<li><?php echo esc_html( sprintf( __( '%d taxonomies', 'ansico-cpt-and-taxonomies' ), count( $payload['taxonomies'] ) ) ); ?></li>
|
|
<li><?php echo esc_html( sprintf( __( '%d post type overrides', 'ansico-cpt-and-taxonomies' ), count( $payload['cpt_overrides'] ) ) ); ?></li>
|
|
<li><?php echo esc_html( sprintf( __( '%d taxonomy overrides', 'ansico-cpt-and-taxonomies' ), count( $payload['taxonomy_overrides'] ) ) ); ?></li>
|
|
</ul>
|
|
<form method="post">
|
|
<?php wp_nonce_field( 'ansico_cptax_export' ); ?>
|
|
<input type="hidden" name="ansico_cptax_action" value="export_json">
|
|
<?php submit_button( __( 'Download JSON export', 'ansico-cpt-and-taxonomies' ), 'primary', 'submit', false ); ?>
|
|
</form>
|
|
</section>
|
|
<section class="ansico-cptax-card">
|
|
<h2><?php esc_html_e( 'Import JSON', 'ansico-cpt-and-taxonomies' ); ?></h2>
|
|
<p><?php esc_html_e( 'Import a previously exported JSON file. You can merge it with current plugin data or replace everything.', 'ansico-cpt-and-taxonomies' ); ?></p>
|
|
<form method="post" enctype="multipart/form-data">
|
|
<?php wp_nonce_field( 'ansico_cptax_save' ); ?>
|
|
<input type="hidden" name="ansico_cptax_action" value="import_json">
|
|
<p><input type="file" name="import_file" accept="application/json,.json" required></p>
|
|
<p><label><input type="checkbox" name="replace_existing" value="1"> <?php esc_html_e( 'Replace current plugin data instead of merging by key', 'ansico-cpt-and-taxonomies' ); ?></label></p>
|
|
<?php submit_button( __( 'Import JSON', 'ansico-cpt-and-taxonomies' ), 'secondary', 'submit', false ); ?>
|
|
</form>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
private function render_cpt_table( $records, $is_override ) {
|
|
echo '<table class="widefat striped"><thead><tr><th>' . esc_html__( 'Name', 'ansico-cpt-and-taxonomies' ) . '</th><th>' . esc_html__( 'Key', 'ansico-cpt-and-taxonomies' ) . '</th><th>' . esc_html__( 'Slug', 'ansico-cpt-and-taxonomies' ) . '</th><th>' . esc_html__( 'Actions', 'ansico-cpt-and-taxonomies' ) . '</th></tr></thead><tbody>';
|
|
if ( empty( $records ) ) {
|
|
echo '<tr><td colspan="4">' . esc_html__( 'No items found.', 'ansico-cpt-and-taxonomies' ) . '</td></tr>';
|
|
} else {
|
|
foreach ( $records as $cpt ) {
|
|
echo '<tr>';
|
|
echo '<td>' . esc_html( $cpt['plural_label'] ?? $cpt['key'] ) . '</td>';
|
|
echo '<td><code>' . esc_html( $cpt['key'] ?? '' ) . '</code></td>';
|
|
echo '<td>' . esc_html( $cpt['slug'] ?? '' ) . '</td>';
|
|
echo '<td><a class="button button-small" href="' . esc_url( admin_url( 'admin.php?page=ansico-cptax&edit=' . ( $cpt['key'] ?? '' ) ) ) . '">' . esc_html__( 'Edit', 'ansico-cpt-and-taxonomies' ) . '</a> ';
|
|
echo '<form method="post" style="display:inline;">';
|
|
wp_nonce_field( 'ansico_cptax_save' );
|
|
echo '<input type="hidden" name="ansico_cptax_action" value="delete_cpt">';
|
|
echo '<input type="hidden" name="key" value="' . esc_attr( $cpt['key'] ?? '' ) . '">';
|
|
echo '<input type="hidden" name="is_override" value="' . ( $is_override ? '1' : '0' ) . '">';
|
|
submit_button( __( 'Delete', 'ansico-cpt-and-taxonomies' ), 'delete small', '', false, array( 'onclick' => "return confirm('Are you sure?');" ) );
|
|
echo '</form></td>';
|
|
echo '</tr>';
|
|
}
|
|
}
|
|
echo '</tbody></table>';
|
|
}
|
|
|
|
private function render_taxonomy_table( $records, $is_override ) {
|
|
echo '<table class="widefat striped"><thead><tr><th>' . esc_html__( 'Name', 'ansico-cpt-and-taxonomies' ) . '</th><th>' . esc_html__( 'Key', 'ansico-cpt-and-taxonomies' ) . '</th><th>' . esc_html__( 'Slug', 'ansico-cpt-and-taxonomies' ) . '</th><th>' . esc_html__( 'Actions', 'ansico-cpt-and-taxonomies' ) . '</th></tr></thead><tbody>';
|
|
if ( empty( $records ) ) {
|
|
echo '<tr><td colspan="4">' . esc_html__( 'No items found.', 'ansico-cpt-and-taxonomies' ) . '</td></tr>';
|
|
} else {
|
|
foreach ( $records as $taxonomy ) {
|
|
echo '<tr>';
|
|
echo '<td>' . esc_html( $taxonomy['plural_label'] ?? $taxonomy['key'] ) . '</td>';
|
|
echo '<td><code>' . esc_html( $taxonomy['key'] ?? '' ) . '</code></td>';
|
|
echo '<td>' . esc_html( $taxonomy['slug'] ?? '' ) . '</td>';
|
|
echo '<td><a class="button button-small" href="' . esc_url( admin_url( 'admin.php?page=ansico-cptax-taxonomies&edit=' . ( $taxonomy['key'] ?? '' ) ) ) . '">' . esc_html__( 'Edit', 'ansico-cpt-and-taxonomies' ) . '</a> ';
|
|
echo '<form method="post" style="display:inline;">';
|
|
wp_nonce_field( 'ansico_cptax_save' );
|
|
echo '<input type="hidden" name="ansico_cptax_action" value="delete_taxonomy">';
|
|
echo '<input type="hidden" name="key" value="' . esc_attr( $taxonomy['key'] ?? '' ) . '">';
|
|
echo '<input type="hidden" name="is_override" value="' . ( $is_override ? '1' : '0' ) . '">';
|
|
submit_button( __( 'Delete', 'ansico-cpt-and-taxonomies' ), 'delete small', '', false, array( 'onclick' => "return confirm('Are you sure?');" ) );
|
|
echo '</form></td>';
|
|
echo '</tr>';
|
|
}
|
|
}
|
|
echo '</tbody></table>';
|
|
}
|
|
|
|
private function get_field_types() {
|
|
return array(
|
|
'text' => __( 'Text', 'ansico-cpt-and-taxonomies' ),
|
|
'textarea' => __( 'Textarea', 'ansico-cpt-and-taxonomies' ),
|
|
'number' => __( 'Number', 'ansico-cpt-and-taxonomies' ),
|
|
'url' => __( 'URL', 'ansico-cpt-and-taxonomies' ),
|
|
'email' => __( 'Email', 'ansico-cpt-and-taxonomies' ),
|
|
'date' => __( 'Date', 'ansico-cpt-and-taxonomies' ),
|
|
'checkbox' => __( 'Checkbox', 'ansico-cpt-and-taxonomies' ),
|
|
'select' => __( 'Select', 'ansico-cpt-and-taxonomies' ),
|
|
'radio' => __( 'Radio', 'ansico-cpt-and-taxonomies' ),
|
|
);
|
|
}
|
|
|
|
private function render_field_row( $field, $field_types ) {
|
|
echo $this->get_field_row_markup( $field, $field_types ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
}
|
|
|
|
private function get_field_row_template( $field_types ) {
|
|
return str_replace( array( "\n", "\r", "\t" ), '', $this->get_field_row_markup( array(), $field_types ) );
|
|
}
|
|
|
|
private function get_field_row_markup( $field, $field_types ) {
|
|
ob_start();
|
|
?>
|
|
<tr class="ansico-field-row">
|
|
<td><input type="text" class="regular-text" name="field_label[]" value="<?php echo esc_attr( $field['label'] ?? '' ); ?>" placeholder="<?php esc_attr_e( 'Field label', 'ansico-cpt-and-taxonomies' ); ?>"></td>
|
|
<td><input type="text" class="regular-text ansico-field-key" name="field_key[]" value="<?php echo esc_attr( $field['key'] ?? '' ); ?>" placeholder="<?php esc_attr_e( 'field_key', 'ansico-cpt-and-taxonomies' ); ?>"></td>
|
|
<td>
|
|
<select name="field_type[]" class="ansico-field-type">
|
|
<?php foreach ( $field_types as $type_key => $type_label ) : ?>
|
|
<option value="<?php echo esc_attr( $type_key ); ?>" <?php selected( $field['type'] ?? 'text', $type_key ); ?>><?php echo esc_html( $type_label ); ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</td>
|
|
<td><input type="text" class="regular-text" name="field_description[]" value="<?php echo esc_attr( $field['description'] ?? '' ); ?>" placeholder="<?php esc_attr_e( 'Help text shown below the field', 'ansico-cpt-and-taxonomies' ); ?>"></td>
|
|
<td><textarea name="field_options[]" rows="3" class="large-text ansico-field-options" placeholder="<?php esc_attr_e( 'Only for select/radio. One option per line or comma separated.', 'ansico-cpt-and-taxonomies' ); ?>"><?php echo esc_textarea( ! empty( $field['options'] ) && is_array( $field['options'] ) ? implode( "\n", $field['options'] ) : '' ); ?></textarea></td>
|
|
<td><button type="button" class="button-link-delete ansico-remove-field"><?php esc_html_e( 'Remove', 'ansico-cpt-and-taxonomies' ); ?></button></td>
|
|
</tr>
|
|
<?php
|
|
return (string) ob_get_clean();
|
|
}
|
|
|
|
private function map_post_type_object_to_record( $obj ) {
|
|
$supports = array();
|
|
foreach ( array( 'title', 'editor', 'thumbnail', 'author', 'comments' ) as $feature ) {
|
|
if ( post_type_supports( $obj->name, $feature ) ) {
|
|
$supports[] = $feature;
|
|
}
|
|
}
|
|
|
|
$taxonomies = get_object_taxonomies( $obj->name, 'names' );
|
|
|
|
return $this->plugin->normalize_cpt_record(
|
|
array(
|
|
'key' => $obj->name,
|
|
'singular_label' => $obj->labels->singular_name ?? $obj->name,
|
|
'plural_label' => $obj->labels->name ?? $obj->name,
|
|
'slug' => is_array( $obj->rewrite ) && ! empty( $obj->rewrite['slug'] ) ? $obj->rewrite['slug'] : $obj->name,
|
|
'exclude_from_search' => ! empty( $obj->exclude_from_search ) ? 1 : 0,
|
|
'can_export' => ! empty( $obj->can_export ) ? 1 : 0,
|
|
'supports' => $supports,
|
|
'taxonomies' => is_array( $taxonomies ) ? $taxonomies : array(),
|
|
'custom_fields' => array(),
|
|
)
|
|
);
|
|
}
|
|
|
|
private function map_taxonomy_object_to_record( $obj ) {
|
|
return $this->plugin->normalize_taxonomy_record(
|
|
array(
|
|
'key' => $obj->name,
|
|
'singular_label' => $obj->labels->singular_name ?? $obj->name,
|
|
'plural_label' => $obj->labels->name ?? $obj->name,
|
|
'slug' => is_array( $obj->rewrite ) && ! empty( $obj->rewrite['slug'] ) ? $obj->rewrite['slug'] : $obj->name,
|
|
'hierarchical' => ! empty( $obj->hierarchical ) ? 1 : 0,
|
|
'object_type' => is_array( $obj->object_type ) ? $obj->object_type : array(),
|
|
)
|
|
);
|
|
}
|
|
}
|