slug = $slug; $this->args = wp_parse_args( $args, array( 'render_callback' => null, 'title' => '', 'capability' => 'manage_options', 'menu_title' => '', 'parent_slug' => self::MENU_SLUG, 'enqueue_callback' => null, 'initialize_callback' => null, ) ); if ( empty( $this->args['menu_title'] ) ) { $this->args['menu_title'] = $this->args['title']; } $this->args['title'] = __( 'Site Kit by Google', 'google-site-kit' ) . ' ' . $this->args['title']; } /** * Gets the unique screen slug. * * @since 1.0.0 * * @return string Unique screen slug. */ public function get_slug() { return $this->slug; } /** * Adds the screen to the WordPress admin backend. * * @since 1.0.0 * * @param Context $context Plugin context, used for URL generation. * @return string Hook suffix of the screen, or empty string if not added. */ public function add( Context $context ) { static $menu_slug = null; if ( ! $this->args['title'] ) { return ''; } // A parent slug of null means the screen will not appear in the menu. $parent_slug = null; // If parent slug is provided, use it as parent. if ( ! empty( $this->args['parent_slug'] ) ) { $parent_slug = $this->args['parent_slug']; // If parent slug is 'googlesitekit', append to main Site Kit menu. if ( self::MENU_SLUG === $parent_slug ) { // If this is null, it means no menu has been added yet. if ( null === $menu_slug ) { add_menu_page( $this->args['title'], __( 'Site Kit', 'google-site-kit' ), $this->args['capability'], $this->slug, '', 'data:image/svg+xml;base64,' . Google_Icon::to_base64() ); $menu_slug = $this->slug; /** * An SVG icon file needs to be colored (filled) based on the theme color setting. * * This exists in js as wp.svgPainter() per: * https://github.com/WordPress/WordPress/blob/5.7/wp-admin/js/svg-painter.js * * The downside of the js approach is that we get a brief flash of an unstyled icon * until the JS runs. * * A user can pick a custom Admin Color Scheme, which is only available in admin_init * or later actions. add_menu_page runs on the admin_menu action, which precedes admin_init * per https://codex.wordpress.org/Plugin_API/Action_Reference * * WordPress provides some color schemes out of the box, but they can also be added via * wp_admin_css_color() * * Our workaround is to set the icon and subsequently replace it in current_screen, which is * what we do in the following action. */ add_action( 'current_screen', function () { global $menu, $_wp_admin_css_colors; if ( ! is_array( $menu ) ) { return; } $color_scheme = get_user_option( 'admin_color' ) ?: 'fresh'; // If we're on one of the sitekit pages, use the 'current' color, otherwise use the 'base' color. // @see wp_admin_css_color(). $color_key = false === strpos( get_current_screen()->id, 'googlesitekit' ) ? 'base' : 'current'; if ( empty( $_wp_admin_css_colors[ $color_scheme ]->icon_colors[ $color_key ] ) ) { return; } $color = $_wp_admin_css_colors[ $color_scheme ]->icon_colors[ $color_key ]; foreach ( $menu as &$item ) { if ( 'googlesitekit-dashboard' === $item[2] ) { $item[6] = 'data:image/svg+xml;base64,' . Google_Icon::to_base64( Google_Icon::with_fill( $color ) ); break; } } }, 100 ); } // Set parent slug to actual slug of main Site Kit menu. $parent_slug = $menu_slug; } } // If submenu item or not in menu, use add_submenu_page(). return (string) add_submenu_page( $parent_slug, $this->args['title'], $this->args['menu_title'], $this->args['capability'], $this->slug, function () use ( $context ) { $this->render( $context ); } ); } /** * Runs actions when initializing the screen, before sending headers and generating markup. * * @since 1.0.0 * * @param Context $context Plugin context. */ public function initialize( Context $context ) { if ( ! $this->args['initialize_callback'] ) { return; } call_user_func( $this->args['initialize_callback'], $context ); } /** * Enqueues assets for the screen. * * @since 1.0.0 * * @param Assets $assets Assets instance to rely on for enqueueing assets. */ public function enqueue_assets( Assets $assets ) { // Enqueue base admin screen stylesheet. $assets->enqueue_asset( 'googlesitekit-admin-css' ); $cb = is_callable( $this->args['enqueue_callback'] ) ? $this->args['enqueue_callback'] : function ( Assets $assets ) { $assets->enqueue_asset( $this->slug ); }; call_user_func( $cb, $assets ); } /** * Renders the screen content. * * @since 1.0.0 * * @param Context $context Plugin context. */ private function render( Context $context ) { $cb = is_callable( $this->args['render_callback'] ) ? $this->args['render_callback'] : function () { printf( '
', esc_attr( $this->slug ) ); }; echo '
'; $this->render_noscript_html(); call_user_func( $cb, $context ); echo '
'; } }