assets = $assets; } /** Relay's screen, optionally at a route such as "#/jobs/": Tools → Relay, or Network Admin → Relay on a network. */ public static function url(string $fragment = ''): string { return (is_multisite() ? network_admin_url('admin.php?page=relay') : admin_url('tools.php?page=relay')) . $fragment; } public function register(): void { add_action(is_multisite() ? 'network_admin_menu' : 'admin_menu', [$this, 'add']); } public function add(): void { $this->hook = is_multisite() ? (string) add_menu_page(__('SiteRelay', 'siterelay'), __('SiteRelay', 'siterelay'), Capability::required(), 'relay', [$this, 'render'], 'dashicons-randomize', 30) : (string) add_management_page(__('SiteRelay', 'siterelay'), __('SiteRelay', 'siterelay'), Capability::required(), 'relay', [$this, 'render']); if ($this->hook !== '') { add_action('load-' . $this->hook, function (): void { add_action('admin_enqueue_scripts', [$this->assets, 'enqueue']); }); } } public function hook(): string { return $this->hook; } public function render(): void { if (!Capability::check()) { wp_die(esc_html__('You do not have permission to use SiteRelay.', 'siterelay')); } if ($this->assets->entry() === null) { // Plain inline markup on purpose: WordPress core JS and notice-manager plugins move `.notice` // elements out of the page, which would leave this screen blank. echo '

' . esc_html__('SiteRelay', 'siterelay') . '

' . '
' . '

' . esc_html__('SiteRelay\'s interface has not been built yet. Run npm run build in the plugin\'s ui folder.', 'siterelay') . '

'; return; } // .wp-header-end tells WordPress where to put other plugins' admin notices: above the app, // never inside the React tree (which would clutter it and can break React's DOM updates). echo '

'; } }