submenus() as $fragment => $title ) { add_submenu_page( self::SLUG, $title, $title, // Settings save through an administrator-only route; an editor // given access to Transtrix would only reach a form that refuses. '/settings' === $fragment ? 'manage_options' : $capability, '' === $fragment ? self::SLUG : self::SLUG . '#' . $fragment, array( $this, 'render' ) ); } } /** * Core dims image menu icons to 60% and pads them for a 20px glyph; the * logo is a full-colour 24px mark, so undo both. Runs on every admin screen * because the menu does. * * @return void */ public function menu_icon_style(): void { wp_add_inline_style( 'admin-menu', '#toplevel_page_' . self::SLUG . ' .wp-menu-image img{opacity:1;padding-top:5px}' ); } /** * The mount point. Everything else is React. * * @return void */ public function render(): void { if ( ! current_user_can( Settings::capability() ) ) { wp_die( esc_html__( 'You do not have permission to access this page.', 'transtrix' ) ); } echo '
'; } /** * Enqueue the app on its own screen only. * * @param string $hook_suffix Current admin page. * @return void */ public function enqueue( string $hook_suffix ): void { if ( 'toplevel_page_' . self::SLUG !== $hook_suffix ) { return; } $asset_file = TRANSTRIX_PATH . 'dist/admin.asset.php'; if ( ! is_readable( $asset_file ) ) { add_action( 'admin_notices', array( $this, 'build_notice' ) ); return; } $asset = require $asset_file; wp_enqueue_script( self::HANDLE, TRANSTRIX_URL . 'dist/admin.js', isset( $asset['dependencies'] ) ? $asset['dependencies'] : array(), isset( $asset['version'] ) ? $asset['version'] : TRANSTRIX_VERSION, true ); wp_localize_script( self::HANDLE, 'transtrix', array( 'restUrl' => esc_url_raw( rest_url( Controller::NAMESPACE_V1 ) ), 'restNonce' => wp_create_nonce( 'wp_rest' ), 'slug' => self::SLUG, 'textDomain' => 'transtrix', 'adminUrl' => esc_url_raw( admin_url( 'admin.php?page=' . self::SLUG ) ), 'homeUrl' => esc_url_raw( home_url( '/' ) ), 'siteLogo' => esc_url_raw( (string) wp_get_attachment_image_url( (int) get_theme_mod( 'custom_logo' ), 'thumbnail' ) ), 'siteName' => get_bloginfo( 'name' ), 'logosUrl' => esc_url_raw( TRANSTRIX_URL . 'assets/admin/logos/' ), 'wpVersion' => get_bloginfo( 'version' ), 'phpVersion' => PHP_VERSION, 'version' => TRANSTRIX_VERSION, 'maxUpload' => (int) wp_max_upload_size(), 'maxExecution' => (int) ini_get( 'max_execution_time' ), 'canManageOptions' => current_user_can( 'manage_options' ), ) ); wp_set_script_translations( self::HANDLE, 'transtrix', TRANSTRIX_PATH . 'languages' ); // The bundle carries Toastify's and Tippy's stylesheets; the app's own // styling is Emotion, injected at runtime. if ( is_readable( TRANSTRIX_PATH . 'dist/admin.css' ) ) { wp_enqueue_style( self::HANDLE, TRANSTRIX_URL . 'dist/admin.css', array(), isset( $asset['version'] ) ? $asset['version'] : TRANSTRIX_VERSION ); wp_style_add_data( self::HANDLE, 'rtl', 'replace' ); } } /** * Say so when the bundle has not been built, rather than rendering nothing. * * @return void */ public function build_notice(): void { echo '' . esc_html__( 'Transtrix: the admin app has not been built. Run "npm install && npm run build" in the plugin directory.', 'transtrix' ) . '