includes(); Prefix_Migration::init(); $this->init_hooks(); } /** * Require auxiliary classes and load widget modules automatically. */ private function includes() { require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-module-registry.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-feature-registry.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-dynamic-content.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-layout-schema.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-prefix-migration.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-render.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-save.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-rest.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-global-settings.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-builder-settings.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-role-manager.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-safe-mode.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-performance-settings.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-tools.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-admin-menu.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-custom-code.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-styles-manager.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-page-settings.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-js-manager.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-theme-conditions.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-template-manager.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-frontend-assets.php'; require_once NYXONN_BUILDER_INCLUDES_DIR . 'class-assets-manager.php'; // load base widget class first so other modules can extend it $base_widget = NYXONN_BUILDER_MODULES_DIR . 'widget.php'; if ( file_exists( $base_widget ) ) { require_once $base_widget; } // load every remaining module file (heading, text, image, etc.) foreach ( glob( NYXONN_BUILDER_MODULES_DIR . '*.php' ) as $module ) { if ( $module === $base_widget ) { continue; } require_once $module; } } /** * Attach WordPress hooks. */ private function init_hooks() { add_action( 'init', [ $this, 'register_meta' ] ); add_action( 'init', [ Dynamic_Content::class, 'init' ], 1 ); add_action( 'init', [ Admin_Menu::class, 'init' ] ); add_action( 'init', [ Builder_Settings::class, 'init' ] ); add_action( 'init', [ Role_Manager::class, 'init' ] ); add_action( 'init', [ Safe_Mode::class, 'init' ] ); add_action( 'init', [ Performance_Settings::class, 'init' ] ); add_action( 'init', [ Tools::class, 'init' ] ); add_action( 'init', [ Global_Settings::class, 'init' ] ); add_action( 'init', [ Page_Settings::class, 'init' ] ); add_action( 'init', [ Template_Manager::class, 'init' ] ); add_action( 'init', [ Assets_Manager::class, 'init' ] ); Frontend_Assets::init(); add_action( 'admin_menu', [ $this, 'register_admin_page' ], 5 ); add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_assets' ] ); add_action( 'save_post', [ Save::class, 'clear_on_save' ], 20, 2 ); add_action( 'rest_api_init', [ $this, 'register_rest_routes' ] ); // frontend rendering filter add_filter( 'the_content', [ Render::class, 'render' ], 10 ); // Current admin-AJAX fallback used by the Builder save client. add_action( 'wp_ajax_nyxonn_builder_save', [ Save::class, 'ajax_save' ] ); add_filter( 'page_row_actions', [ $this, 'page_row_actions' ], 10, 2 ); add_filter( 'post_row_actions', [ $this, 'page_row_actions' ], 10, 2 ); // add body class and hide menu when on builder page add_filter( 'admin_body_class', [ $this, 'admin_body_class' ] ); add_filter( 'script_loader_tag', [ $this, 'global_design_module_script_tag' ], 10, 2 ); add_action( 'admin_head', [ $this, 'builder_admin_head' ] ); } /** Ensure the shared-picker admin entry is parsed as an ES module. */ public function global_design_module_script_tag( $tag, $handle ) { if ( 'nyxonn-builder-admin-settings' !== $handle || false !== stripos( $tag, ' type=' ) ) { return $tag; } return preg_replace( '/^ true, 'single' => true, 'type' => 'string', 'sanitize_callback' => [ 'NyxonnBuilder\\Save', 'sanitize_layout' ], 'auth_callback' => function () { return Role_Manager::can_use_builder(); }, ]; register_post_meta( 'page', Save::LAYOUT_META, $args ); register_post_meta( 'post', Save::LAYOUT_META, $args ); register_post_meta( Template_Manager::TEMPLATES_POST_TYPE, Save::LAYOUT_META, $args ); } /** * Register the browser registries before any module registration scripts. */ public static function enqueue_builder_registry_assets() { static $did_enqueue = false; if ( $did_enqueue ) { return; } $did_enqueue = true; wp_enqueue_script( 'nyxonn-builder-feature-registry', NYXONN_BUILDER_ASSETS_URL . 'js/builder/core/FeatureRegistry.js', [], filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/core/FeatureRegistry.js' ), true ); wp_add_inline_script( 'nyxonn-builder-feature-registry', 'window.NyxonnFXFeatureManifest=' . wp_json_encode( Feature_Registry::builder_payload(), JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT ) . ';', 'before' ); wp_enqueue_script( 'nyxonn-builder-extension-registry', NYXONN_BUILDER_ASSETS_URL . 'js/builder/core/ExtensionRegistry.js', [ 'nyxonn-builder-feature-registry' ], filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/core/ExtensionRegistry.js' ), true ); wp_enqueue_script( 'nyxonn-builder-settings-registry', NYXONN_BUILDER_ASSETS_URL . 'js/builder/core/SettingsRegistry.js', [ 'nyxonn-builder-extension-registry' ], filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/core/SettingsRegistry.js' ), true ); wp_add_inline_script( 'nyxonn-builder-extension-registry', 'window.NyxonnFX=window.NyxonnFX||{};window.NyxonnFX.debug=' . wp_json_encode( defined( 'WP_DEBUG' ) && WP_DEBUG ) . ';', 'before' ); wp_enqueue_script( 'nyxonn-builder-style-registry', NYXONN_BUILDER_ASSETS_URL . 'js/builder/core/StyleRegistry.js', [], filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/core/StyleRegistry.js' ), true ); wp_enqueue_script( 'nyxonn-builder-module-registry', NYXONN_BUILDER_ASSETS_URL . 'js/builder/core/ModuleRegistry.js', [ 'nyxonn-builder-settings-registry', 'nyxonn-builder-style-registry' ], filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/core/ModuleRegistry.js' ), true ); wp_enqueue_script( 'nyxonn-builder-dynamic-registry', NYXONN_BUILDER_ASSETS_URL . 'js/builder/core/DynamicRegistry.js', [ 'nyxonn-builder-module-registry' ], filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/core/DynamicRegistry.js' ), true ); wp_enqueue_script( 'nyxonn-builder-registry-bridge', NYXONN_BUILDER_ASSETS_URL . 'js/builder/core/RegistryBridge.js', [ 'nyxonn-builder-dynamic-registry' ], filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/core/RegistryBridge.js' ), true ); } /** * Dependencies for the ES-module editor entry point. * * Add-ons should register a classic module-registration script and return * its handle through nyxonn_fx_builder_module_script_dependencies. * * @return string[] */ public static function get_builder_script_dependencies() { static $dependencies = null; if ( null !== $dependencies ) { return $dependencies; } self::enqueue_builder_registry_assets(); $extension_handles = apply_filters( 'nyxonn_fx_builder_module_script_dependencies', [] ); $dynamic_handles = apply_filters( 'nyxonn_fx_builder_dynamic_provider_script_dependencies', [] ); $registered_handles = []; foreach ( Extension_API::get_builder_assets( 'script' ) as $asset ) { $handle = $asset['handle']; if ( ! wp_script_is( $handle, 'registered' ) ) continue; $registered = wp_scripts()->registered[ $handle ] ?? null; if ( $registered && ! in_array( 'nyxonn-builder-registry-bridge', $registered->deps, true ) ) $registered->deps[] = 'nyxonn-builder-registry-bridge'; $registered_handles[] = $handle; } $extension_handles = is_array( $extension_handles ) ? array_filter( array_map( 'sanitize_key', $extension_handles ) ) : []; $dynamic_handles = is_array( $dynamic_handles ) ? array_filter( array_map( 'sanitize_key', $dynamic_handles ) ) : []; $dependencies = array_values( array_unique( array_merge( [ 'wp-element', 'wp-components', 'wp-data', 'wp-api-fetch', 'nyxonn-builder-registry-bridge' ], $extension_handles, $dynamic_handles, $registered_handles ) ) ); return $dependencies; } /** * Enqueue admin scripts/styles only when necessary. * * @param string $hook Current admin page hook. */ public function enqueue_admin_assets( $hook ) { $page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : ''; $management_pages = [ 'nyxonn-builder', 'nyxonn-builder-pages', 'nyxonn-builder-global-design', 'nyxonn-builder-theme-builder', 'nyxonn-builder-assets', 'nyxonn-builder-role-manager', 'nyxonn-builder-settings', 'nyxonn-builder-upgrade-pro', 'nyxonn-builder-template-conditions', 'nyxonn-builder-templates', 'nyxonn-builder-builder-settings', 'nyxonn-builder-performance', 'nyxonn-builder-integrations', 'nyxonn-builder-tools', ]; $management_pages = apply_filters( 'nyxonn_fx_admin_management_pages', $management_pages ); $management_pages = is_array( $management_pages ) ? array_values( array_unique( array_filter( array_map( 'sanitize_key', $management_pages ) ) ) ) : []; // Load the shared admin design system only on known management pages. // The fullscreen builder is deliberately excluded from this allowlist. if ( in_array( $page, $management_pages, true ) ) { wp_enqueue_style( 'nyxonn-builder-admin-panel', NYXONN_BUILDER_ASSETS_URL . 'css/admin-panel.css', [], filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/css/admin-panel.css' ) ); } if ( 'nyxonn-builder-theme-builder' === $page ) { wp_enqueue_script( 'nyxonn-builder-theme-builder-screen', NYXONN_BUILDER_ASSETS_URL . 'js/theme-builder-screen.js', [], filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/theme-builder-screen.js' ), true ); wp_localize_script( 'nyxonn-builder-theme-builder-screen', 'NyxonnBuilderAdmin', [ 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 'conditionsUrl' => admin_url( 'admin.php?page=nyxonn-builder-template-conditions&template_id=' ), ] ); } // Mount the shared Builder color picker on the PHP-rendered Global Design fields. if ( 'nyxonn-builder-global-design' === $page ) { wp_enqueue_script( 'nyxonn-builder-admin-settings', NYXONN_BUILDER_ASSETS_URL . 'js/admin-settings.js', [ 'wp-element' ], filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/admin-settings.js' ), true ); wp_script_add_data( 'nyxonn-builder-admin-settings', 'type', 'module' ); return; } if ( 'nyxonn-builder-tools' === $page ) { wp_enqueue_script( 'nyxonn-builder-admin-tools', NYXONN_BUILDER_ASSETS_URL . 'js/admin-tools.js', [], filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/admin-tools.js' ), true ); return; } if ( 'nyxonn-builder-assets' === $page ) { wp_enqueue_media(); wp_enqueue_script( 'nyxonn-builder-assets', NYXONN_BUILDER_ASSETS_URL . 'js/assets-manager.js', [ 'media-editor' ], filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/assets-manager.js' ), true ); wp_localize_script( 'nyxonn-builder-assets', 'nyxonnBuilderAssets', [ 'nonce' => wp_create_nonce( 'wp_rest' ), 'apiRoot' => esc_url_raw( rest_url() ), ] ); } // Only enqueue our ES-module app on the canonical hidden Builder route. $is_builder_page = 'nyxonn-builder-editor' === $page; if ( ! $is_builder_page ) { // editor button for block editor (only when block editor is active) if ( $hook === 'post.php' || $hook === 'post-new.php' ) { $post = get_post(); if ( $post && Role_Manager::can_use_builder( $post->ID ) && function_exists( 'use_block_editor_for_post' ) && use_block_editor_for_post( $post ) ) { wp_enqueue_script( 'nyxonn-builder-editor-button', NYXONN_BUILDER_ASSETS_URL . 'js/editor-button.js', [ 'wp-data' ], NYXONN_BUILDER_VERSION, true ); wp_localize_script( 'nyxonn-builder-editor-button', 'nyxonnBuilderEditor', [ 'buttonUrl' => admin_url( 'admin.php?page=nyxonn-builder-editor&nyxonn_builder_enable=1&_wpnonce=' . wp_create_nonce( 'nyxonn_builder_enable' ) . '&post_id=' ), 'postTypes' => array_values( array_unique( array_merge( Builder_Settings::get_enabled_post_types(), [ Template_Manager::TEMPLATES_POST_TYPE ] ) ) ), ] ); } } return; } // ensure media library assets (wp.media, etc.) are available for upload dialogs wp_enqueue_media(); // Preserve the builder's existing icon dependency; management screens // use WordPress Dashicons and make no remote stylesheet request. wp_enqueue_style( 'nyxonn-builder-font-awesome', NYXONN_BUILDER_ASSETS_URL . 'vendor/fontawesome/css/all.min.css', [], filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/vendor/fontawesome/css/all.min.css' ) ); wp_enqueue_style( 'nyxonn-builder-admin', NYXONN_BUILDER_ASSETS_URL . 'css/admin.css', [], filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/css/admin.css' ) ); wp_enqueue_style( 'nyxonn-builder-app', NYXONN_BUILDER_ASSETS_URL . 'css/builder.css', [], filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/css/builder.css' ) ); 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', [], filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/css/frontend.css' ) ); foreach ( Extension_API::get_builder_assets( 'style' ) as $asset ) { if ( wp_style_is( $asset['handle'], 'registered' ) ) wp_enqueue_style( $asset['handle'] ); } wp_enqueue_script( 'nyxonn-builder-frontend', NYXONN_BUILDER_ASSETS_URL . 'js/frontend.js', [ 'jquery' ], filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/frontend.js' ), true ); wp_enqueue_script( 'nyxonn-builder-app', NYXONN_BUILDER_ASSETS_URL . 'js/builder/app.js', self::get_builder_script_dependencies(), filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/app.js' ), true ); // indicate that this file uses ES modules so imports work in the browser wp_script_add_data( 'nyxonn-builder-app', 'type', 'module' ); // Get post ID based on context $post_id = 0; if ( isset( $_GET['post_id'] ) ) { $post_id = isset( $_GET['post_id'] ) ? intval( wp_unslash( $_GET['post_id'] ) ) : 0; } else { $post_id = get_the_ID(); } do_action( 'nyxonn_fx_builder_assets_enqueued', $post_id ); // Only set preview URL if we have a valid post ID $preview_url = ''; $layout_data_b64 = ''; if ( $post_id > 0 ) { $preview_url = esc_url( get_permalink( $post_id ) . '?nx_preview=1' ); $stored_layout = Save::get_layout_for_post( $post_id ); if ( is_string( $stored_layout ) && '' !== $stored_layout ) { $layout_data_b64 = base64_encode( $stored_layout ); } } $assigned_templates = []; $builder_post = $post_id ? get_post( $post_id ) : null; $is_template_post = $builder_post && Template_Manager::TEMPLATES_POST_TYPE === $builder_post->post_type; $exit_url = $is_template_post ? admin_url( 'admin.php?page=nyxonn-builder-theme-builder' ) : ( $post_id ? get_edit_post_link( $post_id, 'raw' ) : admin_url( 'edit.php?post_type=page' ) ); $show_assigned_templates = $builder_post && Template_Manager::TEMPLATES_POST_TYPE !== $builder_post->post_type; if ( $show_assigned_templates ) { $context = Template_Manager::get_context_for_post( $post_id ); $assigned_header = Template_Manager::get_matching_template( 'header', $context ); $assigned_footer = Template_Manager::get_matching_template( 'footer', $context ); if ( $assigned_header ) { $header_rules = Template_Manager::get_template_rules( $assigned_header->ID ); $header_layout = 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' => 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 = Template_Manager::get_template_rules( $assigned_footer->ID ); $footer_layout = 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' => 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', ]; } } 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' => $builder_post ? $builder_post->post_title : '', 'apiRoot' => esc_url_raw( rest_url() ), 'previewUrl' => $preview_url, 'exitUrl' => esc_url_raw( $exit_url ), 'pluginUrl' => esc_url_raw( NYXONN_BUILDER_PLUGIN_URL ), 'pluginPath' => esc_url_raw( NYXONN_BUILDER_PLUGIN_URL . 'assets/js/builder/' ), 'layoutDataB64' => $layout_data_b64, 'assignedTemplates' => $assigned_templates, 'dynamicContent' => Dynamic_Content::get_builder_payload( $post_id ), 'features' => Feature_Registry::builder_payload(), 'disableGoogleFonts' => Performance_Settings::google_fonts_disabled(), 'customFonts' => array_values( array_filter( array_map( static function ( $font ) { return is_array( $font ) ? sanitize_text_field( $font['family'] ?? '' ) : ''; }, 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/components/FeatureGate.js' ), filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/components/PageSettingsModal.js' ), filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/core/DynamicModel.js' ), filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/settings/DynamicControl.js' ), filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/settings/StyleStateFields.js' ), filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/settings/moduleSettingsSchema.js' ), filemtime( NYXONN_BUILDER_PLUGIN_DIR . 'assets/js/builder/utils/fontStore.js' ) ), ] ); } /** * Initialize Global Settings page registration * (Builder page is now handled by Admin_Menu) */ public function register_admin_page() { // Admin_Menu registers the dashboard submenu pages, including Global Settings. } /** * Output the container that our React app will render into. */ /** * Output the root div for flexible React app rendering. * (Now handled by Admin_Menu::builder_page) */ private function builder_page() { // This is now handled by Admin_Menu::builder_page() // Kept for backward compatibility only } /** * Register custom REST routes used by the builder UI. */ public function register_rest_routes() { register_rest_route( 'nyxonn-builder/v1', '/save', [ 'methods' => 'POST', 'callback' => [ Save::class, 'rest_save' ], 'permission_callback' => function ( $request ) { $post_id = intval( $request->get_param( 'post_id' ) ); return Save::can_access_layout( $post_id ); }, ] ); register_rest_route( 'nyxonn-builder/v1', '/layout', [ 'methods' => 'GET', 'callback' => [ Save::class, 'rest_get_layout' ], 'permission_callback' => function ( $request ) { $post_id = intval( $request->get_param( 'post_id' ) ); return Save::can_access_layout( $post_id ); }, ] ); Rest::register_routes(); Global_Settings::register_rest_routes(); } /** * Add a quick "Edit with Nyxonn Builder" link in the pages list. * * @param array $actions * @param WP_Post $post * @return array */ public function page_row_actions( $actions, $post ) { if ( Builder_Settings::can_open_builder( $post ) && Role_Manager::can_use_builder( $post->ID ) ) { $is_enabled = '1' === get_post_meta( $post->ID, Save::ENABLED_META, true ); $url = $is_enabled ? admin_url( 'admin.php?page=nyxonn-builder-editor&post_id=' . $post->ID ) : add_query_arg( [ 'page' => 'nyxonn-builder-editor', 'nyxonn_builder_enable' => 1, 'post_id' => $post->ID, '_wpnonce' => wp_create_nonce( 'nyxonn_builder_enable' ), ], admin_url( 'admin.php' ) ); $actions['nx'] = 'Edit with Nyxonn Builder'; } return $actions; } /** * Add custom body class for the fullscreen builder page. * * @param string $classes * @return string */ public function admin_body_class( $classes ) { $screen = get_current_screen(); if ( $screen && strpos( $screen->id, 'nyxonn-builder-editor' ) !== false ) { $classes .= ' nx-fullscreen-builder'; } return $classes; } /** * Output minimal CSS to hide WP UI on builder page. */ public function builder_admin_head() { $screen = get_current_screen(); if ( $screen && strpos( $screen->id, 'nyxonn-builder-editor' ) !== false ) { } } }