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 ) ); ?>

PRO
false ] ); ?>
\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' ); ?>

$object ) : ?>

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_status ); ?>
post_title ?: __( '(no title)', 'nyxonn-builder' ) ); ?> 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 ); ?>

post_title ); ?>

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' ) ); ?>

roles as $slug => $data ) : $role = $roles->get_role( $slug ); $protected = ! empty( $data['capabilities']['manage_options'] ); ?>
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' ) ); ?>

$value ) : ?>

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 ); } }