array(
'title' => __( 'Tagwright SEO Dashboard', 'tagwright-seo' ),
'menu_title' => __( 'Dashboard', 'tagwright-seo' ),
'icon' => 'dashboard',
'callback' => array( Dashboard::class, 'render' ),
),
'tagwright-seo-settings' => array(
'title' => __( 'Tagwright SEO Settings', 'tagwright-seo' ),
'menu_title' => __( 'Settings', 'tagwright-seo' ),
'icon' => 'settings',
'callback' => array( Settings_Page::class, 'render' ),
),
'tagwright-seo-tools' => array(
'title' => __( 'Tagwright SEO Tools', 'tagwright-seo' ),
'menu_title' => __( 'Tools', 'tagwright-seo' ),
'icon' => 'tools',
'callback' => array( Tools_Page::class, 'render' ),
),
'tagwright-seo-addons' => array(
'title' => __( 'Tagwright SEO Add-ons', 'tagwright-seo' ),
'menu_title' => __( 'Add-ons', 'tagwright-seo' ),
'icon' => 'addons',
'callback' => array( Addons_Page::class, 'render' ),
),
'tagwright-seo-pro' => array(
'title' => __( 'Tagwright SEO Pro', 'tagwright-seo' ),
'menu_title' => __( 'Tagwright SEO Pro', 'tagwright-seo' ),
'icon' => 'sparkles',
'callback' => array( Pro_Page::class, 'render' ),
),
'tagwright-seo-setup' => array(
'title' => __( 'Tagwright SEO Setup', 'tagwright-seo' ),
'menu_title' => __( 'Setup Wizard', 'tagwright-seo' ),
'icon' => 'sparkles',
'callback' => array( Setup_Wizard::class, 'render' ),
'hidden' => true,
),
);
if ( ! Brand::value( 'upsells', true ) ) {
unset( $pages['tagwright-seo-addons'], $pages['tagwright-seo-pro'] );
}
/**
* Filters the Tagwright SEO admin pages. Add-ons can add a page here
* and it shows up in the menu and in the top navigation.
*
* Each page has title, menu_title, icon, callback and optionally
* hidden and position.
*
* @param array $pages Pages keyed by slug.
*/
return apply_filters( 'tagwright_seo_admin_pages', $pages );
}
/**
* Adds the menu and sub pages.
*
* @return void
*/
public function register_menu() {
$capability = self::capability();
self::$hooks[] = add_menu_page(
__( 'Tagwright SEO', 'tagwright-seo' ),
__( 'Tagwright SEO', 'tagwright-seo' ),
$capability,
'tagwright-seo',
array( Dashboard::class, 'render' ),
$this->menu_icon(),
80
);
foreach ( self::pages() as $slug => $page ) {
self::$hooks[] = add_submenu_page(
! empty( $page['hidden'] ) ? '' : 'tagwright-seo',
$page['title'],
$page['menu_title'],
$capability,
$slug,
$page['callback']
);
}
}
/**
* Whether the current screen belongs to Tagwright SEO.
*
* @return bool
*/
public static function is_plugin_screen() {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Only reading the page slug.
$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';
return '' !== $page && array_key_exists( $page, self::pages() );
}
/**
* Registers and enqueues the design system where it is needed.
*
* @param string $hook Current admin page hook.
* @return void
*/
public function enqueue( $hook ) {
self::register_assets();
$editor_screens = array( 'post.php', 'post-new.php', 'term.php', 'edit-tags.php', 'profile.php', 'user-edit.php', 'edit.php' );
if ( self::is_plugin_screen() || in_array( $hook, $editor_screens, true ) ) {
wp_enqueue_style( 'tagwright-seo-admin' );
wp_enqueue_script( 'tagwright-seo-admin' );
}
if ( self::is_plugin_screen() ) {
wp_enqueue_media();
}
}
/**
* Registers the shared assets so add-ons can depend on the handles.
*
* @return void
*/
public static function register_assets() {
if ( wp_script_is( 'tagwright-seo-admin', 'registered' ) ) {
return;
}
wp_register_style( 'tagwright-seo-admin', TAGWRIGHT_SEO_URL . 'assets/css/admin.css', array(), TAGWRIGHT_SEO_VERSION );
wp_register_script(
'tagwright-seo-admin',
TAGWRIGHT_SEO_URL . 'assets/js/admin.js',
array( 'wp-api-fetch', 'wp-i18n' ),
TAGWRIGHT_SEO_VERSION,
true
);
wp_localize_script(
'tagwright-seo-admin',
'tagwrightSeoAdmin',
array(
'icons' => Icons::all(),
'variables' => Replacer::describe(),
'varLabels' => Replacer::labels(),
'separators' => Replacer::separators(),
'values' => Replacer::static_values(),
'adminUrl' => admin_url(),
'homeUrl' => home_url( '/' ),
'version' => TAGWRIGHT_SEO_VERSION,
)
);
wp_set_script_translations( 'tagwright-seo-admin', 'tagwright-seo' );
}
/**
* Sends the site owner to the setup wizard once after activation.
*
* @return void
*/
public function maybe_redirect_to_wizard() {
if ( ! get_option( Installer::WIZARD_REDIRECT_OPTION ) ) {
return;
}
delete_option( Installer::WIZARD_REDIRECT_OPTION );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Bulk activation check only.
if ( wp_doing_ajax() || is_network_admin() || isset( $_GET['activate-multi'] ) || ! current_user_can( self::capability() ) ) {
return;
}
wp_safe_redirect( admin_url( 'admin.php?page=tagwright-seo-setup' ) );
exit;
}
/**
* Adds quick links on the Plugins screen.
*
* @param string[] $links Existing links.
* @return string[]
*/
public function action_links( $links ) {
array_unshift(
$links,
sprintf( '%s', esc_url( admin_url( 'admin.php?page=tagwright-seo-settings' ) ), esc_html__( 'Settings', 'tagwright-seo' ) ),
sprintf( '%s', esc_url( admin_url( 'admin.php?page=tagwright-seo' ) ), esc_html__( 'Dashboard', 'tagwright-seo' ) )
);
return $links;
}
/**
* Adds a body class on our screens so the shell styles can apply.
*
* @param string $classes Space separated classes.
* @return string
*/
public function body_class( $classes ) {
if ( self::is_plugin_screen() ) {
$classes .= ' tagwright-seo-screen';
}
return $classes;
}
/**
* Friendlier footer on our screens.
*
* @param string $text Footer text.
* @return string
*/
public function footer_text( $text ) {
if ( ! self::is_plugin_screen() || ! Brand::value( 'credits', true ) ) {
return $text;
}
return sprintf(
/* translators: %s: link to the plugin reviews page. */
__( 'Enjoying Tagwright SEO? A %s review helps a lot.', 'tagwright-seo' ),
'★★★★★'
);
}
/**
* Menu icon as an SVG data URI. WordPress recolors the fill to match the
* admin color scheme.
*
* @return string
*/
private function menu_icon() {
$custom = (string) Brand::value( 'menu_icon', '' );
if ( '' !== $custom ) {
return $custom;
}
$svg = '';
return 'data:image/svg+xml;base64,' . base64_encode( $svg ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode -- Standard way to pass a menu icon.
}
}