400, 'back_link' => true ]
);
}
// Check if post exists
$post = get_post( $post_id );
if ( ! $post ) {
wp_die( 'Error: Page Not Found', 'Page Not Found', [ 'response' => 404 ] );
}
if ( ! Builder_Settings::can_open_builder( $post ) ) {
wp_die(
esc_html__( 'Nyxonn Builder editing is disabled for this post type. Existing saved layouts remain available on the frontend.', 'nyxonn-builder' ),
esc_html__( 'Builder Unavailable', 'nyxonn-builder' ),
[ 'response' => 403, 'back_link' => true ]
);
}
// Check user permission
if ( ! \NyxonnBuilder\Role_Manager::can_use_builder( $post_id ) ) {
wp_die( 'Sorry, you are not allowed to access this page.', 'Permission Denied', [ 'response' => 403 ] );
}
$data = \NyxonnBuilder\Save::get_layout_for_post( $post_id );
$data_b64 = '';
if ( is_string( $data ) && '' !== $data ) {
$data_b64 = base64_encode( $data );
}
$is_template_post = ! empty( $post ) && \NyxonnBuilder\Template_Manager::TEMPLATES_POST_TYPE === $post->post_type;
$preview_context_id = $is_template_post && isset( $_GET['nx_preview_post_id'] ) ? absint( wp_unslash( $_GET['nx_preview_post_id'] ) ) : 0;
$preview_context = $preview_context_id ? get_post( $preview_context_id ) : null;
if ( $preview_context && ( ! in_array( $preview_context->post_type, [ 'page', 'post' ], true ) || ( ! current_user_can( 'read_post', $preview_context_id ) && ! current_user_can( 'edit_post', $preview_context_id ) ) ) ) {
$preview_context = null;
$preview_context_id = 0;
}
$exit_url = $is_template_post
? admin_url( 'admin.php?page=nyxonn-builder-theme-builder' )
: get_edit_post_link( $post_id, 'raw' );
if ( ! $exit_url ) {
$exit_url = admin_url( 'edit.php?post_type=' . sanitize_key( $post->post_type ) );
}
$assigned_templates = [];
$show_assigned_templates = ! empty( $post ) && \NyxonnBuilder\Template_Manager::TEMPLATES_POST_TYPE !== $post->post_type;
$assigned_header = null;
$assigned_footer = null;
if ( $show_assigned_templates ) {
$context = \NyxonnBuilder\Template_Manager::get_context_for_post( $post_id );
$assigned_header = \NyxonnBuilder\Template_Manager::get_matching_template( 'header', $context );
$assigned_footer = \NyxonnBuilder\Template_Manager::get_matching_template( 'footer', $context );
if ( $assigned_header ) {
$header_rules = \NyxonnBuilder\Template_Manager::get_template_rules( $assigned_header->ID );
$header_layout = \NyxonnBuilder\Save::get_layout_for_post( $assigned_header->ID );
$header_layout = is_string( $header_layout ) ? json_decode( wp_unslash( $header_layout ), true ) : [];
if ( ! is_array( $header_layout ) ) {
$header_layout = [];
}
$assigned_templates[] = [
'id' => intval( $assigned_header->ID ),
'type' => 'header',
'title' => $assigned_header->post_title,
'summary' => \NyxonnBuilder\Template_Manager::get_rules_summary( $header_rules ),
'editUrl' => admin_url( 'admin.php?page=nyxonn-builder-editor&post_id=' . $assigned_header->ID ),
'layout' => $header_layout,
'accentColor' => '#4338ca',
'bgColor' => '#eef2ff',
'borderColor' => '#c7d2fe',
];
}
if ( $assigned_footer ) {
$footer_rules = \NyxonnBuilder\Template_Manager::get_template_rules( $assigned_footer->ID );
$footer_layout = \NyxonnBuilder\Save::get_layout_for_post( $assigned_footer->ID );
$footer_layout = is_string( $footer_layout ) ? json_decode( wp_unslash( $footer_layout ), true ) : [];
if ( ! is_array( $footer_layout ) ) {
$footer_layout = [];
}
$assigned_templates[] = [
'id' => intval( $assigned_footer->ID ),
'type' => 'footer',
'title' => $assigned_footer->post_title,
'summary' => \NyxonnBuilder\Template_Manager::get_rules_summary( $footer_rules ),
'editUrl' => admin_url( 'admin.php?page=nyxonn-builder-editor&post_id=' . $assigned_footer->ID ),
'layout' => $footer_layout,
'accentColor' => '#15803d',
'bgColor' => '#f0fdf4',
'borderColor' => '#bbf7d0',
];
}
}
// Enqueue builder assets
wp_enqueue_media();
wp_enqueue_style( 'nyxonn-builder-admin', NYXONN_BUILDER_ASSETS_URL . 'css/admin.css', [], NYXONN_BUILDER_VERSION );
wp_enqueue_style( 'nyxonn-builder-app', NYXONN_BUILDER_ASSETS_URL . 'css/builder.css', [], NYXONN_BUILDER_VERSION );
wp_enqueue_style( 'nyxonn-builder-dark-ui', NYXONN_BUILDER_ASSETS_URL . 'css/builder-dark.css', [ 'nyxonn-builder-app' ], filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/css/builder-dark.css' ) );
wp_enqueue_style( 'nyxonn-builder-frontend', NYXONN_BUILDER_ASSETS_URL . 'css/frontend.css', [], NYXONN_BUILDER_VERSION );
wp_enqueue_script( 'nyxonn-builder-frontend', NYXONN_BUILDER_ASSETS_URL . 'js/frontend.js', [ 'jquery' ], NYXONN_BUILDER_VERSION, true );
wp_enqueue_script( 'nyxonn-builder-app', NYXONN_BUILDER_ASSETS_URL . 'js/builder/app.js', Builder::get_builder_script_dependencies(), NYXONN_BUILDER_VERSION, true );
wp_script_add_data( 'nyxonn-builder-app', 'type', 'module' );
wp_localize_script(
'nyxonn-builder-app',
'nyxonnBuilderSettings',
[
'nonce' => wp_create_nonce( 'wp_rest' ),
'saveNonce' => wp_create_nonce( 'nyxonn_builder_save_nonce' ),
'ajaxUrl' => esc_url_raw( admin_url( 'admin-ajax.php' ) ),
'postId' => $post_id,
'postTitle' => $post ? $post->post_title : '',
'apiRoot' => esc_url_raw( rest_url() ),
'previewUrl' => esc_url( get_permalink( $post_id ) . '?nx_preview=1' ),
'exitUrl' => esc_url_raw( $exit_url ),
'layoutDataB64' => $data_b64,
'pluginUrl' => esc_url_raw( NYXONN_BUILDER_PLUGIN_URL ),
'pluginPath' => esc_url_raw( NYXONN_BUILDER_PLUGIN_URL . 'assets/js/builder/' ),
'assignedTemplates' => $assigned_templates,
'dynamicContent' => \NyxonnBuilder\Dynamic_Content::get_builder_payload( $post_id ),
'previewContext' => $preview_context ? [ 'id' => $preview_context_id, 'title' => $preview_context->post_title, 'type' => $preview_context->post_type ] : null,
'disableGoogleFonts' => \NyxonnBuilder\Performance_Settings::google_fonts_disabled(),
'customFonts' => array_values( array_filter( array_map( static function ( $font ) {
return is_array( $font ) ? sanitize_text_field( $font['family'] ?? '' ) : '';
}, \NyxonnBuilder\Assets_Manager::get_fonts() ) ) ),
'builderVersion' => (string) max(
filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/app.js' ),
filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/NxApp.js' ),
filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/components/Canvas.js' ),
filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/components/Sidebar.js' ),
filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/components/Toolbar.js' ),
filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/components/SettingsPanel.js' ),
filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/core/DynamicModel.js' ),
filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/utils/fontStore.js' )
),
]
);
// Output the root container
?>
[ 'page', 'post' ], 'post_status' => 'publish', 'posts_per_page' => 20, 's' => $context_search, 'orderby' => 'modified', 'order' => 'DESC', 'no_found_rows' => true ] );
?>
ID ); ?>
Header:
post_title ); ?>
()
Edit
ID ); ?>
Footer:
post_title ); ?>
()
Edit
Loading Nyxonn Builder... Please wait.
\NyxonnBuilder\Template_Manager::TEMPLATES_POST_TYPE,
'posts_per_page' => 1,
'meta_key' => \NyxonnBuilder\Template_Manager::TEMPLATE_TYPE_META,
'meta_value' => $template_type,
] );
if ( ! empty( $existing ) ) {
return $existing[0]->ID;
}
$title = ucfirst( $template_type ) . ' Template';
$post_id = wp_insert_post( [
'post_type' => \NyxonnBuilder\Template_Manager::TEMPLATES_POST_TYPE,
'post_title' => $title,
'post_status' => 'publish',
] );
if ( $post_id ) {
update_post_meta( $post_id, \NyxonnBuilder\Template_Manager::TEMPLATE_TYPE_META, $template_type );
}
return $post_id ?: 0;
}
public static function handle_theme_builder_actions() {
if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) {
return;
}
if ( wp_doing_ajax() ) {
return;
}
if ( ! isset( $_POST['nyxonn_builder_theme_builder_action'] ) ) {
return;
}
$action = sanitize_text_field( wp_unslash( $_POST['nyxonn_builder_theme_builder_action'] ) );
if ( 'create_template' === $action ) {
check_admin_referer( 'nyxonn_builder_create_template', 'nyxonn_builder_create_template_nonce' );
$type = isset( $_POST['template_type'] ) ? sanitize_text_field( wp_unslash( $_POST['template_type'] ) ) : 'header';
$name = isset( $_POST['template_name'] ) ? sanitize_text_field( wp_unslash( $_POST['template_name'] ) ) : '';
// Only header and footer templates are currently consumed by the frontend
// resolver. Other nx_template records belong to the reusable builder library.
$allowed = [ 'header', 'footer' ];
if ( ! in_array( $type, $allowed, true ) ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-theme-builder&error=invalid_type' ) );
exit;
}
if ( '' === $name ) {
$label_map = \NyxonnBuilder\Template_Manager::get_template_types();
$name = ( $label_map[ $type ] ?? ucfirst( $type ) ) . ' Template';
}
$rules = self::get_default_template_rules( $type );
$post_id = wp_insert_post( [
'post_type' => \NyxonnBuilder\Template_Manager::TEMPLATES_POST_TYPE,
'post_title' => $name,
'post_status' => 'publish',
] );
if ( is_wp_error( $post_id ) || ! $post_id ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-theme-builder&error=create_failed' ) );
exit;
}
\NyxonnBuilder\Template_Manager::update_template_rules( $post_id, $type, $rules );
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-editor&post_id=' . intval( $post_id ) ) );
exit;
}
if ( 'save_conditions' === $action ) {
check_admin_referer( 'nyxonn_builder_save_conditions', 'nyxonn_builder_save_conditions_nonce' );
if ( ! Feature_Registry::is_available( 'theme_builder_advanced' ) ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-theme-builder&locked=pro' ) );
exit;
}
$template_id = isset( $_POST['template_id'] ) ? intval( wp_unslash( $_POST['template_id'] ) ) : 0;
if ( ! $template_id || ! current_user_can( 'edit_post', $template_id ) ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-theme-builder&error=invalid_template' ) );
exit;
}
$type = \NyxonnBuilder\Template_Manager::get_template_type( $template_id );
if ( ! in_array( $type, [ 'header', 'footer' ], true ) ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-theme-builder&error=conditions_unsupported' ) );
exit;
}
if ( self::is_protected_default_template( $template_id, $type ) ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-theme-builder&locked=1' ) );
exit;
}
$result = \NyxonnBuilder\Template_Manager::update_template_rules( $template_id, $type, self::get_submitted_template_rules() );
if ( is_wp_error( $result ) ) {
wp_safe_redirect( add_query_arg( 'condition_error', $result->get_error_code(), admin_url( 'admin.php?page=nyxonn-builder-template-conditions&template_id=' . $template_id ) ) );
exit;
}
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-template-conditions&template_id=' . $template_id . '&updated=1' ) );
exit;
}
if ( 'delete_template' === $action ) {
check_admin_referer( 'nyxonn_builder_delete_template', 'nyxonn_builder_delete_template_nonce' );
$template_id = isset( $_POST['template_id'] ) ? intval( wp_unslash( $_POST['template_id'] ) ) : 0;
$redirect_to = isset( $_POST['redirect_to'] ) ? esc_url_raw( wp_unslash( $_POST['redirect_to'] ) ) : admin_url( 'admin.php?page=nyxonn-builder-theme-builder' );
if ( ! $template_id || ! current_user_can( 'delete_post', $template_id ) ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-theme-builder&error=invalid_template' ) );
exit;
}
$template = get_post( $template_id );
if ( ! $template || \NyxonnBuilder\Template_Manager::TEMPLATES_POST_TYPE !== $template->post_type ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-theme-builder&error=invalid_template' ) );
exit;
}
if ( self::is_protected_default_template( $template_id ) ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-theme-builder&locked=1' ) );
exit;
}
wp_trash_post( $template_id );
$redirect_to = add_query_arg(
[
'deleted' => 1,
'item' => rawurlencode( $template->post_title ),
],
$redirect_to
);
wp_safe_redirect( $redirect_to );
exit;
}
if ( 'clear_template_content' === $action ) {
check_admin_referer( 'nyxonn_builder_clear_template_content', 'nyxonn_builder_clear_template_content_nonce' );
$template_id = isset( $_POST['template_id'] ) ? intval( wp_unslash( $_POST['template_id'] ) ) : 0;
$redirect_to = isset( $_POST['redirect_to'] ) ? esc_url_raw( wp_unslash( $_POST['redirect_to'] ) ) : admin_url( 'admin.php?page=nyxonn-builder-theme-builder' );
if ( ! $template_id || ! current_user_can( 'edit_post', $template_id ) ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-theme-builder&error=invalid_template' ) );
exit;
}
$template = get_post( $template_id );
if ( ! $template || \NyxonnBuilder\Template_Manager::TEMPLATES_POST_TYPE !== $template->post_type ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-theme-builder&error=invalid_template' ) );
exit;
}
if ( ! self::is_protected_default_template( $template_id ) ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-theme-builder&error=invalid_template' ) );
exit;
}
self::clear_template_layout( $template_id );
$redirect_to = add_query_arg( 'content_cleared', 1, $redirect_to );
wp_safe_redirect( $redirect_to );
exit;
}
if ( 'restore_template' === $action ) {
check_admin_referer( 'nyxonn_builder_restore_template', 'nyxonn_builder_restore_template_nonce' );
$template_id = isset( $_POST['template_id'] ) ? intval( wp_unslash( $_POST['template_id'] ) ) : 0;
$redirect_to = isset( $_POST['redirect_to'] ) ? esc_url_raw( wp_unslash( $_POST['redirect_to'] ) ) : admin_url( 'admin.php?page=nyxonn-builder-templates' );
if ( ! $template_id || ! current_user_can( 'delete_post', $template_id ) ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-templates&status=trash&error=invalid_template' ) );
exit;
}
$template = get_post( $template_id );
if ( ! $template || \NyxonnBuilder\Template_Manager::TEMPLATES_POST_TYPE !== $template->post_type ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-templates&status=trash&error=invalid_template' ) );
exit;
}
$restored = wp_untrash_post( $template_id );
if ( false === $restored ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-templates&status=trash&error=restore_failed' ) );
exit;
}
$restored_template = get_post( $template_id );
if ( $restored_template && 'publish' !== $restored_template->post_status ) {
wp_update_post( [
'ID' => $template_id,
'post_status' => 'publish',
] );
}
$redirect_to = add_query_arg( 'restored', 1, $redirect_to );
wp_safe_redirect( $redirect_to );
exit;
}
if ( 'delete_template_permanently' === $action ) {
check_admin_referer( 'nyxonn_builder_delete_template_permanently', 'nyxonn_builder_delete_template_permanently_nonce' );
$template_id = isset( $_POST['template_id'] ) ? intval( wp_unslash( $_POST['template_id'] ) ) : 0;
$redirect_to = isset( $_POST['redirect_to'] ) ? esc_url_raw( wp_unslash( $_POST['redirect_to'] ) ) : admin_url( 'admin.php?page=nyxonn-builder-templates&status=trash' );
if ( ! $template_id || ! current_user_can( 'delete_post', $template_id ) ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-templates&status=trash&error=invalid_template' ) );
exit;
}
$template = get_post( $template_id );
if ( ! $template || \NyxonnBuilder\Template_Manager::TEMPLATES_POST_TYPE !== $template->post_type ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-templates&status=trash&error=invalid_template' ) );
exit;
}
wp_delete_post( $template_id, true );
$redirect_to = add_query_arg( 'permanently_deleted', 1, $redirect_to );
wp_safe_redirect( $redirect_to );
exit;
}
if ( 'duplicate_template' === $action ) {
check_admin_referer( 'nyxonn_builder_duplicate_template', 'nyxonn_builder_duplicate_template_nonce' );
$template_id = isset( $_POST['template_id'] ) ? absint( wp_unslash( $_POST['template_id'] ) ) : 0;
$template = $template_id ? get_post( $template_id ) : null;
$type = $template ? \NyxonnBuilder\Template_Manager::get_template_type( $template_id ) : '';
if ( ! $template || \NyxonnBuilder\Template_Manager::TEMPLATES_POST_TYPE !== $template->post_type || ! in_array( $type, [ 'header', 'footer' ], true ) || ! current_user_can( 'edit_post', $template_id ) ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-theme-builder&error=invalid_template' ) );
exit;
}
$copy_id = wp_insert_post( [ 'post_type' => \NyxonnBuilder\Template_Manager::TEMPLATES_POST_TYPE, 'post_status' => 'draft', 'post_title' => sprintf( /* translators: %s: source template title. */ __( '%s (Copy)', 'nyxonn-builder' ), $template->post_title ) ], true );
if ( is_wp_error( $copy_id ) ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-theme-builder&error=duplicate_failed' ) );
exit;
}
$stored = \NyxonnBuilder\Save::store_canonical_layout( $copy_id, \NyxonnBuilder\Save::get_layout_for_post( $template_id ) );
if ( is_wp_error( $stored ) ) {
wp_delete_post( $copy_id, true );
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-theme-builder&error=duplicate_failed' ) );
exit;
}
foreach ( [ '_nyxonn_builder_page_custom_css', '_nyxonn_builder_page_css_enabled' ] as $meta_key ) {
if ( metadata_exists( 'post', $template_id, $meta_key ) ) update_post_meta( $copy_id, $meta_key, get_post_meta( $template_id, $meta_key, true ) );
}
update_post_meta( $copy_id, \NyxonnBuilder\Template_Manager::TEMPLATE_TYPE_META, $type );
update_post_meta( $copy_id, \NyxonnBuilder\Template_Manager::TEMPLATE_RULES_META, [ 'version' => 2, 'priority' => 0, 'conditions' => [] ] );
wp_safe_redirect( add_query_arg( 'duplicated', 1, admin_url( 'admin.php?page=nyxonn-builder-theme-builder' ) ) );
exit;
}
}
public static function ajax_save_template_conditions() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => __( 'Unauthorized', 'nyxonn-builder' ) ], 403 );
}
if ( ! Feature_Registry::is_available( 'theme_builder_advanced' ) ) {
wp_send_json_error( [ 'code' => 'nyxonn_builder_pro_required', 'message' => __( 'Nyxonn Pro is required to edit advanced template conditions. Existing assignments are preserved.', 'nyxonn-builder' ) ], 403 );
}
$template_id = isset( $_POST['template_id'] ) ? intval( wp_unslash( $_POST['template_id'] ) ) : 0;
$nonce = isset( $_POST['nyxonn_builder_save_conditions_nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nyxonn_builder_save_conditions_nonce'] ) ) : '';
if ( ! $template_id || ! wp_verify_nonce( $nonce, 'nyxonn_builder_save_conditions' ) ) {
wp_send_json_error( [ 'message' => __( 'Invalid request.', 'nyxonn-builder' ) ], 400 );
}
$type = \NyxonnBuilder\Template_Manager::get_template_type( $template_id );
if ( ! in_array( $type, [ 'header', 'footer' ], true ) || ! current_user_can( 'edit_post', $template_id ) ) {
wp_send_json_error( [ 'message' => __( 'Conditions are not supported for this template.', 'nyxonn-builder' ) ], 400 );
}
if ( self::is_protected_default_template( $template_id, $type ) ) {
wp_send_json_error( [ 'message' => __( 'Default global header/footer conditions cannot be changed.', 'nyxonn-builder' ) ], 400 );
}
$result = \NyxonnBuilder\Template_Manager::update_template_rules( $template_id, $type, self::get_submitted_template_rules() );
if ( is_wp_error( $result ) ) wp_send_json_error( [ 'message' => $result->get_error_message() ], 400 );
$normalized = \NyxonnBuilder\Template_Manager::get_template_rules( $template_id );
wp_send_json_success( [
'summary' => \NyxonnBuilder\Template_Manager::get_rules_summary( $normalized ),
'is_global' => ! empty( $normalized['all'] ),
] );
}
private static function get_default_template_rules( $type ) {
return [ 'version' => 2, 'priority' => 0, 'conditions' => [ [ 'mode' => 'include', 'target' => 'entire_site' ] ] ];
}
private static function get_submitted_template_rules() {
return [
'version' => 2,
'priority' => isset( $_POST['nyxonn_builder_template_priority'] ) ? intval( wp_unslash( $_POST['nyxonn_builder_template_priority'] ) ) : 0,
'conditions' => isset( $_POST['nx_conditions'] ) && is_array( $_POST['nx_conditions'] ) ? wp_unslash( $_POST['nx_conditions'] ) : [],
];
}
private static function merge_template_rules( $defaults, $submitted ) {
$defaults = is_array( $defaults ) ? $defaults : [];
$submitted = is_array( $submitted ) ? $submitted : [];
return [
'all' => isset( $submitted['all'] ) ? (bool) $submitted['all'] : (bool) ( $defaults['all'] ?? false ),
'include' => ! empty( $submitted['include'] ) ? array_values( $submitted['include'] ) : ( $defaults['include'] ?? [] ),
'exclude' => ! empty( $submitted['exclude'] ) ? array_values( $submitted['exclude'] ) : ( $defaults['exclude'] ?? [] ),
'post_types' => ! empty( $submitted['post_types'] ) ? array_values( $submitted['post_types'] ) : ( $defaults['post_types'] ?? [] ),
'categories' => ! empty( $submitted['categories'] ) ? array_values( $submitted['categories'] ) : ( $defaults['categories'] ?? [] ),
'contexts' => ! empty( $submitted['contexts'] ) ? array_values( $submitted['contexts'] ) : ( $defaults['contexts'] ?? [] ),
];
}
private static function is_protected_default_template( $template_id, $type = '' ) {
$template_id = intval( $template_id );
if ( ! $template_id ) {
return false;
}
if ( '' === $type ) {
$type = \NyxonnBuilder\Template_Manager::get_template_type( $template_id );
}
if ( ! in_array( $type, [ 'header', 'footer' ], true ) ) {
return false;
}
$rules = \NyxonnBuilder\Template_Manager::get_template_rules( $template_id );
return \NyxonnBuilder\Template_Manager::is_locked_global_template( $template_id, $type, $rules );
}
private static function clear_template_layout( $template_id ) {
\NyxonnBuilder\Save::store_canonical_layout( $template_id, [] );
delete_post_meta( $template_id, '_nyxonn_builder_layout' );
}
public static function render_template_conditions() {
$template_id = isset( $_GET['template_id'] ) ? intval( wp_unslash( $_GET['template_id'] ) ) : 0;
$template = $template_id ? get_post( $template_id ) : null;
if ( ! $template || \NyxonnBuilder\Template_Manager::TEMPLATES_POST_TYPE !== $template->post_type ) {
wp_die( esc_html__( 'Template not found.', 'nyxonn-builder' ) );
}
if ( ! current_user_can( 'edit_post', $template_id ) ) {
wp_die( esc_html__( 'You do not have permission to edit this template.', 'nyxonn-builder' ) );
}
$type = \NyxonnBuilder\Template_Manager::get_template_type( $template_id );
if ( ! in_array( $type, [ 'header', 'footer' ], true ) ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-theme-builder&error=conditions_unsupported' ) );
exit;
}
$rules = \NyxonnBuilder\Template_Manager::get_template_rules( $template_id );
$is_protected_default = self::is_protected_default_template( $template_id, $type );
$conditions_available = Feature_Registry::is_available( 'theme_builder_advanced' );
self::render_admin_shell_start(
'nyxonn-builder-theme-builder',
__( 'Template Conditions', 'nyxonn-builder' ),
sprintf( /* translators: %s: template title. */ __( 'Control where “%s†is used.', 'nyxonn-builder' ), $template->post_title )
);
?>
\NyxonnBuilder\Template_Manager::TEMPLATES_POST_TYPE,
'post_status' => $status,
'posts_per_page' => -1,
'orderby' => 'modified',
'order' => 'DESC',
] );
$trash_total = self::count_theme_templates_by_status( 'trash' );
?>
|
|
|
|
ID ); ?>
ID ); ?>
| post_title ); ?> |
ID ) ); ?> |
|
|
405 ] );
}
if ( ! \NyxonnBuilder\Role_Manager::can_use_builder() || ! current_user_can( 'edit_pages' ) ) {
wp_die( esc_html__( 'You do not have permission to create a page with Nyxonn Builder.', 'nyxonn-builder' ), esc_html__( 'Permission Denied', 'nyxonn-builder' ), [ 'response' => 403 ] );
}
check_admin_referer( 'nyxonn_builder_create_page' );
if ( ! Builder_Settings::is_post_type_enabled( 'page' ) ) {
wp_die( esc_html__( 'Page creation is disabled in Nyxonn Builder settings.', 'nyxonn-builder' ), esc_html__( 'Page Creation Disabled', 'nyxonn-builder' ), [ 'response' => 403 ] );
}
$token = isset( $_POST['nyxonn_builder_create_token'] )
? sanitize_text_field( wp_unslash( $_POST['nyxonn_builder_create_token'] ) )
: '';
if ( ! preg_match( '/^[a-f0-9-]{36}$/i', $token ) ) {
wp_die( esc_html__( 'The page creation request is invalid. Reload the dashboard and try again.', 'nyxonn-builder' ), esc_html__( 'Invalid Request', 'nyxonn-builder' ), [ 'response' => 400 ] );
}
// Claim this rendered form token atomically so a double-submit or concurrent
// replay cannot create another draft. A fresh dashboard form gets a fresh token.
$token_hash = hash( 'sha256', get_current_user_id() . '|' . $token );
$request_key = 'nyxonn_builder_create_request_' . substr( $token_hash, 0, 40 );
$claimed = add_option( $request_key, 'processing', '', false );
if ( ! $claimed ) {
$previous_post_id = absint( get_option( $request_key, 0 ) );
$previous_post = $previous_post_id ? get_post( $previous_post_id ) : null;
if ( $previous_post && 'page' === $previous_post->post_type && (int) $previous_post->post_author === get_current_user_id() ) {
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-editor&post_id=' . $previous_post_id ) );
exit;
}
wp_die( esc_html__( 'This page creation request is already being processed. Reload the dashboard before creating another page.', 'nyxonn-builder' ), esc_html__( 'Request Already Processed', 'nyxonn-builder' ), [ 'response' => 409 ] );
}
if ( ! wp_next_scheduled( 'nyxonn_builder_expire_create_request', [ $request_key ] ) ) {
wp_schedule_single_event( time() + DAY_IN_SECONDS, 'nyxonn_builder_expire_create_request', [ $request_key ] );
}
$post_id = self::insert_builder_page();
if ( ! $post_id ) {
delete_option( $request_key );
wp_die( esc_html__( 'The page could not be created.', 'nyxonn-builder' ), esc_html__( 'Page Creation Failed', 'nyxonn-builder' ), [ 'response' => 500 ] );
}
update_option( $request_key, (string) $post_id, false );
wp_safe_redirect( admin_url( 'admin.php?page=nyxonn-builder-editor&post_id=' . absint( $post_id ) ) );
exit;
}
/** Remove an expired idempotency token created for a page request. */
public static function expire_create_request( $request_key ) {
if ( is_string( $request_key ) && preg_match( '/^nyxonn_builder_create_request_[a-f0-9]{40}$/', $request_key ) ) {
delete_option( $request_key );
}
}
private static function insert_builder_page() {
if ( ! \NyxonnBuilder\Role_Manager::can_use_builder() || ! current_user_can( 'edit_pages' ) || ! Builder_Settings::is_post_type_enabled( 'page' ) ) {
return 0;
}
$post_id = wp_insert_post( [
'post_type' => 'page',
'post_title' => __( 'New Nyxonn Builder Page', 'nyxonn-builder' ),
'post_status' => 'draft',
], true );
if ( is_wp_error( $post_id ) || ! $post_id ) {
return 0;
}
update_post_meta( $post_id, '_nyxonn_builder_enabled', '1' );
return intval( $post_id );
}
/**
* Render Dashboard page
*/
public static function render_dashboard() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'You do not have permission to view this page.', 'nyxonn-builder' ) );
}
$recent_pages = self::get_recent_nyxonn_pages();
$is_pro = self::is_pro_extension_registered();
$purchase_url = self::get_pro_purchase_url();
$can_create_page = Builder_Settings::is_post_type_enabled( 'page' );
self::render_admin_shell_start(
'nx',
__( 'Dashboard', 'nyxonn-builder' ),
__( 'Manage your Nyxonn Builder builder and site design.', 'nyxonn-builder' )
);
?>
post_type );
$post_type_label = $post_type_object ? $post_type_object->labels->singular_name : $post->post_type;
?>
-
ID ) && Builder_Settings::can_open_builder( $post ) ) : ?>
ID, 'raw' ); ?>
- labels->singular_name ?? $type; }, $enabled ) ) : __( 'None', 'nyxonn-builder' ) ); ?>
'nyxonn-builder', 'label' => __( 'Dashboard', 'nyxonn-builder' ), 'icon' => 'dashicons-dashboard', 'section' => '', 'order' => 10, 'capability' => 'manage_options' ],
[ 'slug' => 'nyxonn-builder-pages', 'label' => __( 'Pages', 'nyxonn-builder' ), 'icon' => 'dashicons-admin-page', 'section' => __( 'Build', 'nyxonn-builder' ), 'order' => 100, 'capability' => 'manage_options' ],
[ 'slug' => 'nyxonn-builder-builder-settings', 'label' => __( 'Builder Settings', 'nyxonn-builder' ), 'icon' => 'dashicons-admin-generic', 'section' => __( 'Build', 'nyxonn-builder' ), 'order' => 110, 'capability' => 'manage_options' ],
[ 'slug' => 'nyxonn-builder-theme-builder', 'label' => __( 'Theme Builder', 'nyxonn-builder' ), 'icon' => 'dashicons-layout', 'section' => __( 'Build', 'nyxonn-builder' ), 'order' => 120, 'capability' => 'manage_options' ],
[ 'slug' => 'nyxonn-builder-global-design', 'label' => __( 'Global Design', 'nyxonn-builder' ), 'icon' => 'dashicons-art', 'section' => __( 'Design', 'nyxonn-builder' ), 'order' => 200, 'capability' => 'manage_options' ],
[ 'slug' => 'nyxonn-builder-assets', 'label' => __( 'Assets', 'nyxonn-builder' ), 'icon' => 'dashicons-format-image', 'section' => __( 'Design', 'nyxonn-builder' ), 'order' => 210, 'capability' => 'manage_options' ],
[ 'slug' => 'nyxonn-builder-role-manager', 'label' => __( 'Role Manager', 'nyxonn-builder' ), 'icon' => 'dashicons-groups', 'section' => __( 'Site', 'nyxonn-builder' ), 'order' => 310, 'capability' => 'manage_options' ],
[ 'slug' => 'nyxonn-builder-performance', 'label' => __( 'Performance', 'nyxonn-builder' ), 'icon' => 'dashicons-performance', 'section' => __( 'Optimization', 'nyxonn-builder' ), 'order' => 400, 'capability' => 'manage_options' ],
[ 'slug' => 'nyxonn-builder-integrations', 'label' => __( 'Integrations', 'nyxonn-builder' ), 'icon' => 'dashicons-admin-links', 'section' => __( 'System', 'nyxonn-builder' ), 'order' => 500, 'capability' => 'manage_options' ],
[ 'slug' => 'nyxonn-builder-tools', 'label' => __( 'Tools', 'nyxonn-builder' ), 'icon' => 'dashicons-admin-tools', 'section' => __( 'System', 'nyxonn-builder' ), 'order' => 510, 'capability' => 'manage_options' ],
[ 'slug' => 'nyxonn-builder-settings', 'label' => __( 'Settings', 'nyxonn-builder' ), 'icon' => 'dashicons-admin-settings', 'section' => __( 'System', 'nyxonn-builder' ), 'order' => 520, 'capability' => 'manage_options' ],
];
/**
* Filter internal Nyxonn admin navigation items.
*
* Extensions may provide slug, label, section, icon, order, and capability.
*/
$items = apply_filters( 'nyxonn_fx_admin_navigation_items', $items );
$items = is_array( $items ) ? array_merge( $items, Extension_API::get_admin_navigation() ) : Extension_API::get_admin_navigation();
if ( ! is_array( $items ) ) {
return [];
}
$navigation = [];
$seen = [];
foreach ( $items as $item ) {
if ( ! is_array( $item ) ) {
continue;
}
$slug = isset( $item['slug'] ) ? sanitize_key( $item['slug'] ) : '';
$label = isset( $item['label'] ) && is_scalar( $item['label'] ) ? sanitize_text_field( (string) $item['label'] ) : '';
$capability = isset( $item['capability'] ) ? sanitize_key( $item['capability'] ) : 'manage_options';
if ( ! $slug || ! $label || isset( $seen[ $slug ] ) || ! $capability || ! current_user_can( $capability ) ) {
continue;
}
$seen[ $slug ] = true;
$navigation[] = [
'slug' => $slug,
'label' => $label,
'icon' => isset( $item['icon'] ) ? sanitize_html_class( $item['icon'] ) : 'dashicons-admin-generic',
'section' => isset( $item['section'] ) && is_scalar( $item['section'] ) ? sanitize_text_field( (string) $item['section'] ) : '',
'order' => isset( $item['order'] ) && is_numeric( $item['order'] ) ? (float) $item['order'] : 999,
'capability' => $capability,
];
}
usort( $navigation, static function ( $left, $right ) {
return $left['order'] <=> $right['order'];
} );
return $navigation;
}
/** Keep the Nyxonn top-level selected for core and extension-provided routes. */
public static function highlight_parent_menu( $parent_file ) {
$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';
if ( ! $page ) {
return $parent_file;
}
$routes = [ 'nyxonn-builder-editor', 'nyxonn-builder-template-conditions', 'nyxonn-builder-templates', 'nyxonn-builder-upgrade-pro' ];
foreach ( self::get_admin_navigation() as $item ) {
$routes[] = $item['slug'];
}
return in_array( $page, array_unique( $routes ), true ) ? 'nyxonn-builder' : $parent_file;
}
/** Resolve hidden routes to the internal navigation destination that owns them. */
private static function get_admin_navigation_parent_slug( $current_slug ) {
if ( in_array( $current_slug, [ 'nyxonn-builder-template-conditions', 'nyxonn-builder-templates' ], true ) ) {
return 'nyxonn-builder-theme-builder';
}
if ( 'nyxonn-builder-editor' === $current_slug ) {
$post_id = isset( $_GET['post_id'] ) ? absint( $_GET['post_id'] ) : 0;
return $post_id && Template_Manager::TEMPLATES_POST_TYPE === get_post_type( $post_id ) ? 'nyxonn-builder-theme-builder' : 'nyxonn-builder-pages';
}
return $current_slug;
}
/** Query only the five most recently modified Nyxonn-enabled posts/pages. */
private static function get_recent_nyxonn_pages() {
return get_posts( [
'post_type' => [ 'page', 'post' ],
'post_status' => [ 'publish', 'draft', 'pending', 'private' ],
'posts_per_page' => 5,
'orderby' => 'modified',
'order' => 'DESC',
'meta_key' => '_nyxonn_builder_enabled',
'meta_value' => '1',
'no_found_rows' => true,
'ignore_sticky_posts' => true,
] );
}
/** Render vendor-configured support links, or a truthful neutral state. */
private static function render_resource_links() {
$resources = [
__( 'Documentation', 'nyxonn-builder' ) => apply_filters( 'nyxonn_fx_documentation_url', '' ),
__( 'Support', 'nyxonn-builder' ) => apply_filters( 'nyxonn_fx_support_url', '' ),
__( 'Website', 'nyxonn-builder' ) => apply_filters( 'nyxonn_fx_website_url', '' ),
];
$resources = array_filter( array_map( 'esc_url_raw', $resources ) );
if ( empty( $resources ) ) {
echo '' . esc_html__( 'Resource links have not been configured.', 'nyxonn-builder' ) . '
';
return;
}
?>
403 ] );
}
$enabled_post_types = Builder_Settings::get_enabled_post_types();
$supported_post_types = array_keys( Builder_Settings::get_supported_post_types() );
self::render_admin_shell_start(
'nyxonn-builder-pages',
__( 'Pages', 'nyxonn-builder' ),
__( 'Open the Visual Builder for any enabled WordPress content type.', 'nyxonn-builder' )
);
?>
|
|
|
|
$enabled_post_types ?: [ '__nx_none' ],
'posts_per_page' => 20,
'orderby' => 'modified',
'order' => 'DESC'
] );
$existing_posts = get_posts( [
'post_type' => $supported_post_types ?: [ '__nx_none' ],
'posts_per_page' => 20,
'orderby' => 'modified',
'order' => 'DESC',
'meta_key' => Save::ENABLED_META,
'meta_value' => '1',
] );
$posts_by_id = [];
foreach ( array_merge( $enabled_posts, $existing_posts ) as $candidate ) {
$posts_by_id[ $candidate->ID ] = $candidate;
}
$posts = array_values( $posts_by_id );
usort( $posts, static function ( $left, $right ) {
return strcmp( $right->post_modified_gmt, $left->post_modified_gmt );
} );
$posts = array_slice( $posts, 0, 20 );
foreach ( $posts as $post ) {
if ( ! Builder_Settings::can_open_builder( $post ) || ! Role_Manager::can_use_builder( $post->ID ) ) {
continue;
}
$edit_url = admin_url( 'admin.php?page=nyxonn-builder-editor&post_id=' . $post->ID );
?>
| post_title ); ?> |
post_type ) ); ?> |
post_status ) ); ?> |
|
Global Settings
Settings component not available.
';
}
/**
* Render Theme Builder page
*/
private static function render_theme_builder_management() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'You do not have permission to view this page.', 'nyxonn-builder' ) );
}
$status = isset( $_GET['status'] ) ? sanitize_key( wp_unslash( $_GET['status'] ) ) : 'publish';
$status = in_array( $status, [ 'publish', 'trash' ], true ) ? $status : 'publish';
$base_url = admin_url( 'admin.php?page=nyxonn-builder-theme-builder' );
$current_url = 'trash' === $status ? add_query_arg( 'status', 'trash', $base_url ) : $base_url;
$templates = get_posts( [
'post_type' => \NyxonnBuilder\Template_Manager::TEMPLATES_POST_TYPE,
'post_status' => 'trash' === $status ? 'trash' : 'any',
'posts_per_page' => -1,
'orderby' => 'modified',
'order' => 'DESC',
] );
$templates = array_values( array_filter( $templates, static function ( $template ) {
return in_array( \NyxonnBuilder\Template_Manager::get_template_type( $template->ID ), [ 'header', 'footer' ], true );
} ) );
$type_labels = \NyxonnBuilder\Template_Manager::get_template_types();
$trash_total = self::count_theme_templates_by_status( 'trash' );
self::render_admin_shell_start(
'nyxonn-builder-theme-builder',
__( 'Theme Builder', 'nyxonn-builder' ),
__( 'Create and manage reusable site templates with Nyxonn Builder.', 'nyxonn-builder' )
);
?>
| | | | | |
ID );
$resolved_type = \NyxonnBuilder\Template_Manager::PAGE_TEMPLATE_TYPE === $raw_type ? 'page' : $raw_type;
$type_label = $type_labels[ $resolved_type ] ?? ucwords( str_replace( '_', ' ', $raw_type ) );
$supports_conditions = in_array( $raw_type, [ 'header', 'footer' ], true );
$rules = \NyxonnBuilder\Template_Manager::get_template_rules( $template->ID );
$conflicts = 'publish' === $template->post_status ? \NyxonnBuilder\Template_Manager::get_conflicts( $template->ID ) : [];
$protected = self::is_protected_default_template( $template->ID, $raw_type );
?>
| post_title ?: __( '(no title)', 'nyxonn-builder' ) ); ?> |
post_status ); ?>
| label : ucfirst( $template->post_status ) ); ?> |
|
|
|
\NyxonnBuilder\Template_Manager::TEMPLATES_POST_TYPE,
'post_status' => $status,
'posts_per_page' => -1,
'orderby' => 'modified',
'order' => 'DESC',
] );
$trash_total = self::count_theme_templates_by_status( 'trash' );
$grouped = [];
foreach ( array_keys( $types ) as $type_key ) {
$grouped[ $type_key ] = [];
}
foreach ( $templates as $template ) {
$template_type = get_post_meta( $template->ID, \NyxonnBuilder\Template_Manager::TEMPLATE_TYPE_META, true );
if ( \NyxonnBuilder\Template_Manager::PAGE_TEMPLATE_TYPE === $template_type ) {
$template_type = 'page';
}
if ( isset( $grouped[ $template_type ] ) ) {
$grouped[ $template_type ][] = $template;
}
}
foreach ( $grouped as $type_key => $items ) {
usort( $items, function( $a, $b ) {
$a_rules = \NyxonnBuilder\Template_Manager::get_template_rules( $a->ID );
$b_rules = \NyxonnBuilder\Template_Manager::get_template_rules( $b->ID );
if ( ! empty( $a_rules['all'] ) && empty( $b_rules['all'] ) ) return -1;
if ( empty( $a_rules['all'] ) && ! empty( $b_rules['all'] ) ) return 1;
return strtotime( $b->post_modified ) <=> strtotime( $a->post_modified );
} );
$grouped[ $type_key ] = $items;
}
$tab_order = [ 'header', 'footer', 'section', 'single', 'page', 'category', 'archive', '404', 'popup', 'loop' ];
?>
$tab_key ) : ?>
$type_key ) : ?>
ID ); ?>
ID ); ?>
ID, \NyxonnBuilder\Template_Manager::TEMPLATE_TYPE_META, true ); ?>
403 ] );
}
$roles = wp_roles();
self::render_admin_shell_start(
'nyxonn-builder-role-manager',
__( 'Role Manager', 'nyxonn-builder' ),
__( 'Control which WordPress roles can access Nyxonn Builder features.', 'nyxonn-builder' )
);
?>
403 ] );
}
$settings = \NyxonnBuilder\Performance_Settings::get_settings();
$custom_fonts = count( \NyxonnBuilder\Assets_Manager::get_fonts() );
$custom_icons = count( \NyxonnBuilder\Assets_Manager::get_icons() );
$notice = isset( $_GET['nyxonn_builder_notice'] ) ? sanitize_key( wp_unslash( $_GET['nyxonn_builder_notice'] ) ) : '';
self::render_admin_shell_start( 'nyxonn-builder-performance', __( 'Performance', 'nyxonn-builder' ), __( 'Control Nyxonn Builder frontend asset loading and compatibility-safe optimizations.', 'nyxonn-builder' ) );
?>
403 ] );
}
$google_fonts_enabled = ! \NyxonnBuilder\Performance_Settings::google_fonts_disabled();
$font_count = count( \NyxonnBuilder\Assets_Manager::get_fonts() );
$icon_count = count( \NyxonnBuilder\Assets_Manager::get_icons() );
$pro_active = function_exists( 'nyxonn_fx_has_extension' ) && nyxonn_fx_has_extension( 'pro' );
self::render_admin_shell_start(
'nyxonn-builder-integrations',
__( 'Integrations', 'nyxonn-builder' ),
__( 'View integrations and optional extensions available for Nyxonn Builder.', 'nyxonn-builder' )
);
?>
403 ] );
}
$system_info = \NyxonnBuilder\Tools::get_system_information();
$notice = isset( $_GET['nyxonn_builder_notice'] ) ? sanitize_key( wp_unslash( $_GET['nyxonn_builder_notice'] ) ) : '';
self::render_admin_shell_start(
'nyxonn-builder-tools',
__( 'Tools', 'nyxonn-builder' ),
__( 'Maintenance, diagnostics, and support utilities for Nyxonn Builder.', 'nyxonn-builder' )
);
?>
403 ] );
}
$safe_mode = \NyxonnBuilder\Safe_Mode::is_enabled();
$notice = isset( $_GET['nyxonn_builder_notice'] ) ? sanitize_key( wp_unslash( $_GET['nyxonn_builder_notice'] ) ) : '';
self::render_admin_shell_start(
'nyxonn-builder-settings',
__( 'Settings', 'nyxonn-builder' ),
__( 'Configure general Nyxonn Builder plugin behavior.', 'nyxonn-builder' )
);
?>
get_var(
"SELECT COUNT(*) FROM {$wpdb->postmeta}
WHERE meta_key = '_nyxonn_builder_enabled' AND meta_value = '1'"
);
return $count ?: 0;
}
/**
* Helper: Count total modules across all pages
*/
private static function count_total_modules() {
global $wpdb;
$count = $wpdb->get_var(
"SELECT COUNT(*) FROM {$wpdb->postmeta}
WHERE meta_key = '_nyxonn_builder_layout' AND meta_value != ''"
);
return $count ?: 0;
}
/**
* Helper: Count theme templates
*/
private static function count_theme_templates() {
return self::count_theme_templates_by_status( 'publish' );
}
private static function count_theme_templates_by_status( $status ) {
$types = class_exists( '\NyxonnBuilder\Template_Manager' ) ? [ 'header', 'footer' ] : [];
if ( empty( $types ) ) {
return 0;
}
$ids = get_posts( [
'post_type' => \NyxonnBuilder\Template_Manager::TEMPLATES_POST_TYPE,
'post_status' => $status,
'posts_per_page' => -1,
'fields' => 'ids',
'meta_query' => [
[
'key' => \NyxonnBuilder\Template_Manager::TEMPLATE_TYPE_META,
'value' => $types,
'compare' => 'IN',
],
],
] );
return count( $ids );
}
}