diff --git a/src/Admin/Ide/Ide.php b/src/Admin/Ide/Ide.php deleted file mode 100644 index 81b9eec5e..000000000 --- a/src/Admin/Ide/Ide.php +++ /dev/null @@ -1,581 +0,0 @@ - - - - - - - - - - XML; - } - - /** - * Enqueues custom CSS to set the "GraphQL IDE" menu item icon in the WordPress Admin Bar. - */ - public function enqueue_graphql_ide_menu_icon_css(): void { - if ( $this->user_lacks_capability() ) { - return; - } - - $custom_css = ' - #wp-admin-bar-wpgraphql-ide .ab-icon::before, - #wp-admin-bar-wpgraphql-ide .ab-icon::before { - background-image: url("data:image/svg+xml;base64,' . base64_encode( $this->graphql_logo_svg() ) . '"); - background-size: 100%; - border-radius: 12px; - box-sizing: border-box; - content: ""; - display: inline-block; - height: 24px; - width: 24px; - } - '; - - wp_add_inline_style( 'admin-bar', $custom_css ); - } - - /** - * Renders the container for the dedicated IDE page for the React app to be mounted to. - */ - public function render_dedicated_ide_page(): void { - echo '
'; - } - - /** - * Registers a submenu page for the dedicated GraphQL IDE. - * - * This function checks if the current user has the necessary capabilities - * to access the GraphQL IDE. If the user has the required capabilities, - * it adds a submenu page under a specified parent menu. The submenu page - * is intended to provide access to a dedicated GraphQL IDE within the WordPress - * admin area. - * - * @see add_submenu_page() For more information on adding submenu pages. - * @link https://developer.wordpress.org/reference/functions/add_submenu_page/ - */ - public function register_dedicated_ide_menu(): void { - if ( $this->user_lacks_capability() ) { - return; - } - - // Remove the legacy submenu without affecting the ability to directly link to the legacy IDE (wp-admin/admin.php?page=graphiql-ide) - $graphql_ide_settings = get_option( 'graphql_ide_settings', [] ); - $show_legacy_editor = isset( $graphql_ide_settings['graphql_ide_show_legacy_editor'] ) ? $graphql_ide_settings['graphql_ide_show_legacy_editor'] : 'off'; - - if ( 'off' === $show_legacy_editor ) { - remove_submenu_page( 'graphiql-ide', 'graphiql-ide' ); - } - - add_submenu_page( - 'graphiql-ide', - __( 'GraphQL IDE', 'wpgraphql-ide' ), - __( 'GraphQL IDE', 'wpgraphql-ide' ), - 'manage_options', - 'graphql-ide', - [ $this, 'render_dedicated_ide_page' ] - ); - } - - /** - * Registers the plugin's custom menu item in the WordPress Admin Bar. - * - * @global \WP_Admin_Bar $wp_admin_bar The WordPress Admin Bar instance. - */ - public function register_wpadminbar_menus(): void { - if ( $this->user_lacks_capability() ) { - return; - } - - global $wp_admin_bar; - - $app_context = $this->get_app_context(); - - // Retrieve the settings array - $graphql_ide_settings = get_option( 'graphql_ide_settings', [] ); - - // Get the specific link behavior value, default to 'drawer' if not set - $link_behavior = isset( $graphql_ide_settings['graphql_ide_link_behavior'] ) ? $graphql_ide_settings['graphql_ide_link_behavior'] : 'drawer'; - - if ( 'drawer' === $link_behavior && ! $this->current_screen_is_dedicated_ide_page() ) { - // Drawer Button - $wp_admin_bar->add_node( - [ - 'id' => 'wpgraphql-ide', - 'title' => '
' . $app_context['drawerButtonLabel'] . '
', - 'href' => '#', - ] - ); - } elseif ( 'disabled' !== $link_behavior ) { - // Link to the new dedicated IDE page. - $wp_admin_bar->add_node( - [ - 'id' => 'wpgraphql-ide', - 'title' => '' . $app_context['drawerButtonLabel'], - 'href' => admin_url( 'admin.php?page=graphql-ide' ), - ] - ); - } - } - - /** - * Checks if the current admin page is the new WPGraphQL IDE page. - * - * @return bool True if the current page is the new WPGraphQL IDE page, false otherwise. - */ - public function is_ide_page(): bool { - if ( ! function_exists( 'get_current_screen' ) ) { - return false; - } - - $screen = get_current_screen(); - if ( ! $screen ) { - return false; - } - - return 'graphql_page_graphql-ide' === $screen->id; - } - - /** - * Checks if the current admin page is the legacy GraphiQL IDE page. - * - * @return bool True if the current page is the legacy GraphiQL IDE page, false otherwise. - */ - public function is_legacy_ide_page(): bool { - if ( ! function_exists( 'get_current_screen' ) ) { - return false; - } - - $screen = get_current_screen(); - if ( ! $screen ) { - return false; - } - - return 'toplevel_page_graphiql-ide' === $screen->id; - } - - /** - * Checks if the current user lacks the capability required to load scripts and styles for the GraphQL IDE. - * - * @return bool Whether the user lacks the required capability. - */ - public function user_lacks_capability(): bool { - $capability_required = apply_filters( 'wpgraphqlide_capability_required', 'manage_options' ); - - return ! current_user_can( $capability_required ); - } - - /** - * Determines if the current admin page is a dedicated WPGraphQL IDE page. - * - * This function checks whether the current admin page is exclusively for either the new GraphQL IDE - * or the legacy GraphiQL IDE, distinguishing them from other admin pages where the IDE might be present - * in a drawer. It is designed to help in tailoring the admin interface or enqueuing specific scripts - * and styles on these dedicated IDE pages. - * - * @return bool True if the current page is a dedicated WPGraphQL IDE page, false otherwise. - */ - public function current_screen_is_dedicated_ide_page(): bool { - return $this->is_ide_page() || $this->is_legacy_ide_page(); - } - /** - * Enqueues the React application script and associated styles. - */ - public function enqueue_react_app_with_styles(): void { - if ( $this->is_legacy_ide_page() ) { - return; - } - - if ( ! class_exists( '\WPGraphQL\Router' ) ) { - return; - } - - if ( $this->user_lacks_capability() ) { - return; - } - - // Don't enqueue new styles/scripts on the legacy IDE page - if ( function_exists( 'get_current_screen' ) ) { - $screen = get_current_screen(); - if ( 'toplevel_page_graphiql-ide' === $screen->id ) { - return; - } - } - - $asset_file = include WPGRAPHQL_PLUGIN_DIR . '/src/admin/IDE/build/index.asset.php'; - $render_asset_file = include WPGRAPHQL_PLUGIN_DIR . '/src/admin/IDE/build/render.asset.php'; - $graphql_asset_file = include WPGRAPHQL_PLUGIN_DIR . '/src/admin/IDE/build/graphql.asset.php'; - - $app_context = $this->get_app_context(); - - wp_register_script( - 'graphql', - plugins_url( 'build/graphql.js', __FILE__ ), - $graphql_asset_file['dependencies'], - $graphql_asset_file['version'], - false - ); - - wp_enqueue_script( - 'wpgraphql-ide', - plugins_url( 'build/index.js', __FILE__ ), - array_merge( $asset_file['dependencies'], [ 'graphql' ] ), - $asset_file['version'], - false - ); - - $localized_data = [ - 'nonce' => wp_create_nonce( 'wp_rest' ), - 'graphqlEndpoint' => trailingslashit( site_url() ) . 'index.php?' . \WPGraphQL\Router::$route, - 'rootElementId' => self::WPGRAPHQL_IDE_ROOT_ELEMENT_ID, - 'context' => $app_context, - 'isDedicatedIdePage' => $this->current_screen_is_dedicated_ide_page(), - 'dedicatedIdeBaseUrl' => $this->get_dedicated_ide_base_url(), - ]; - - wp_localize_script( - 'wpgraphql-ide', - 'WPGRAPHQL_IDE_DATA', - $localized_data - ); - - // Extensions looking to extend GraphiQL can hook in here, - // after the window object is established, but before the App renders - do_action( 'wpgraphqlide_enqueue_script', $app_context ); - - wp_enqueue_script( - 'wpgraphql-ide-render', - plugins_url( 'build/render.js', __FILE__ ), - array_merge( $asset_file['dependencies'], [ 'wpgraphql-ide', 'graphql' ] ), - $render_asset_file['version'], - false - ); - - wp_enqueue_style( 'wpgraphql-ide-app', plugins_url( 'build/index.css', __FILE__ ), [], $asset_file['version'] ); - wp_enqueue_style( 'wpgraphql-ide-render', plugins_url( 'build/render.css', __FILE__ ), [], $asset_file['version'] ); - - // Avoid running custom styles through a build process for an improved developer experience. - wp_enqueue_style( 'wpgraphql-ide', plugins_url( 'styles/wpgraphql-ide.css', __FILE__ ), [], $asset_file['version'] ); - } - - /** - * Retrieves the base URL for the dedicated WPGraphQL IDE page. - * - * @return string The URL for the dedicated IDE page within the WordPress admin. - */ - public function get_dedicated_ide_base_url(): string { - return menu_page_url( 'graphql-ide', false ); - } - - /** - * Retrieves the specific header of this plugin. - * - * @param string $key The plugin data key. - * @return string|null The version number of the plugin. Returns an empty string if the version is not found. - */ - public function get_plugin_header( string $key = '' ): ?string { - if ( ! function_exists( 'get_plugin_data' ) ) { - require_once ABSPATH . 'wp-admin/includes/plugin.php'; - } - - if ( empty( $key ) ) { - return null; - } - - $plugin_data = get_plugin_data( __FILE__ ); - - return $plugin_data[ $key ] ?? null; - } - - /** - * Retrieves app context. - * - * @return array The possibly filtered app context array. - */ - public function get_app_context(): array { - $current_user = wp_get_current_user(); - - // Get the avatar URL for the current user. Returns an empty string if no user is logged in. - $avatar_url = $current_user->exists() ? get_avatar_url( $current_user->ID ) : ''; - - return apply_filters( - 'wpgraphqlide_context', - [ - 'pluginVersion' => $this->get_plugin_header( 'Version' ), - 'pluginName' => $this->get_plugin_header( 'Name' ), - 'externalFragments' => apply_filters( 'wpgraphqlide_external_fragments', [] ), - 'avatarUrl' => $avatar_url, - 'drawerButtonLabel' => __( 'GraphQL IDE', 'wpgraphql-ide' ), - ] - ); - } - - /** - * Add styles to hide generic admin notices on the graphiql-ide page - * and play nice with notices added via register_graphql_admin_notice - * - * @param array $notices The array of notices to render - */ - public static function graphql_admin_notices_render_notices( array $notices ): void { - echo ' - - '; - } - - /** - * Add styles to apply top margin to notices added via register_graphql_admin_notice - * - * @param string $notice_slug The slug of the notice - * @param array $notice The notice data - * @param bool $is_dismissable Whether the notice is dismissable - * @param int $count The count of notices - */ - public function graphql_admin_notices_render_notice( string $notice_slug, array $notice, bool $is_dismissable, int $count ): void { - - echo ' - - '; - } - - /** - * Filter to allow graphql admin notices to be displayed on the dedicated IDE page. - * - * @param bool $is_plugin_scoped_page True if the current page is within scope of the plugin's pages. - * @param string $current_page_id The ID of the current admin page. - * @param array $allowed_pages The list of allowed pages. - */ - public function allow_ide_page_for_admin_notices ( bool $is_plugin_scoped_page, string $current_page_id, array $allowed_pages ): bool { - - // If the current page is the dedicated IDE page, we want to allow notices to be displayed. - if ( 'graphql_page_graphql-ide' === $current_page_id ) { - return true; - } - - return $is_plugin_scoped_page; - } - - /** - * Modifies the script tag for specific scripts to add the 'defer' attribute. - * - * This function checks if the script handle matches 'wpgraphql-ide' and, if so, - * adds the 'defer' attribute to the script tag. This allows the script to be executed - * after the HTML document is parsed but before the DOMContentLoaded event. - * - * @param string $tag The HTML `