src/admin-pages/class-wp-site-identity-standard-admin-page-registry.php
<?php
/**
* WP_Site_Identity_Standard_Admin_Page_Registry class
*
* @package WPSiteIdentity
* @since 1.0.0
*/
/**
* Class responsible for registering admin pages.
*
* @since 1.0.0
*/
class WP_Site_Identity_Standard_Admin_Page_Registry implements WP_Site_Identity_Admin_Page_Registry {
/**
* Prefix to use for all admin page slugs within WordPress.
*
* @since 1.0.0
* @var string
*/
protected $prefix = '';
/**
* All registered admin pages as `$slug => $instance` pairs.
*
* @since 1.0.0
* @var array
*/
protected $admin_pages = array();
/**
* Factory to create admin page objects.
*
* @since 1.0.0
* @var WP_Site_Identity_Admin_Page_Factory
*/
protected $factory;
/**
* Map for admin page hook suffixes generated by WordPress.
*
* @since 1.0.0
* @var array
*/
protected $hook_suffixes = array();
/**
* Constructor.
*
* Sets the prefix to use for registered admin pages.
*
* @since 1.0.0
*
* @param string $prefix Prefix to use for all admin page slugs within WordPress.
*/
public function __construct( $prefix ) {
$this->prefix = $prefix;
$this->factory = new WP_Site_Identity_Admin_Page_Factory( $this );
}
/**
* Gets all registered admin pages.
*
* @since 1.0.0
*
* @return array Array of `$slug => $instance` pairs.
*/
public function get_all_admin_pages() {
return $this->admin_pages;
}
/**
* Gets a registered admin page instance.
*
* @since 1.0.0
*
* @param string $slug Slug of the admin page.
* @return WP_Site_Identity_Admin_Page Registered admin page.
*
* @throws WP_Site_Identity_Admin_Page_Not_Found_Exception Thrown when a admin page cannot be found.
*/
public function get_admin_page( $slug ) {
if ( ! isset( $this->admin_pages[ $slug ] ) ) {
/* translators: %s: admin page slug */
throw new WP_Site_Identity_Admin_Page_Not_Found_Exception( sprintf( __( 'The admin page with the slug %s could not be found.', 'wp-site-identity' ), $slug ) );
}
return $this->admin_pages[ $slug ];
}
/**
* Checks whether a admin page is registered.
*
* @since 1.0.0
*
* @param string $slug Slug of the admin page.
* @return bool True if the admin page is registered, false otherwise.
*/
public function has_admin_page( $slug ) {
return isset( $this->admin_pages[ $slug ] );
}
/**
* Registers a new admin page.
*
* @since 1.0.0
*
* @param WP_Site_Identity_Admin_Page $admin_page Admin page to register.
*/
public function register_admin_page( WP_Site_Identity_Admin_Page $admin_page ) {
$slug = $admin_page->get_slug();
$this->admin_pages[ $slug ] = $admin_page;
$this->register_in_wp( $admin_page );
}
/**
* Unregisters an existing admin page.
*
* @since 1.0.0
*
* @param WP_Site_Identity_Admin_Page $admin_page Admin page to unregister.
*/
public function unregister_admin_page( WP_Site_Identity_Admin_Page $admin_page ) {
$slug = $admin_page->get_slug();
if ( ! isset( $this->admin_pages[ $slug ] ) ) {
return;
}
$this->unregister_in_wp( $this->admin_pages[ $slug ] );
unset( $this->admin_pages[ $slug ] );
}
/**
* Gets the URL to a registered admin page.
*
* @since 1.0.0
*
* @param WP_Site_Identity_Admin_Page $admin_page Admin page to get the URL for.
* @return string URL to the admin page.
*/
public function get_url_to_admin_page( WP_Site_Identity_Admin_Page $admin_page ) {
$slug = $admin_page->get_slug();
$query_args = array();
$parent_file = 'admin.php';
if ( is_a( $admin_page, 'WP_Site_Identity_Admin_Submenu_Page' ) ) {
$parent_slug = $admin_page->get_parent_slug();
if ( false !== strpos( $parent_slug, '?' ) ) {
list( $base_slug, $query ) = explode( '?', $parent_slug, 2 );
$parent_query_args = explode( '&', $query );
foreach ( $parent_query_args as $parent_query_arg ) {
if ( false === strpos( $parent_query_arg, '=' ) ) {
continue;
}
list( $key, $value ) = explode( '=', $parent_query_arg, 2 );
$query_args[ $key ] = $value;
}
} else {
$base_slug = $parent_slug;
}
if ( '.php' === substr( $base_slug, -4 ) ) {
$parent_file = $parent_slug;
}
}
$query_args['page'] = $this->prefix . $slug;
return add_query_arg( $query_args, admin_url( $parent_file ) );
}
/**
* Gets the factory to create admin page objects.
*
* @since 1.0.0
*
* @return WP_Site_Identity_Admin_Page_Factory Factory to create admin page objects.
*/
public function factory() {
return $this->factory;
}
/**
* Prefixes an admin page slug.
*
* If no slug is given, the prefix is simply returned.
*
* @since 1.0.0
*
* @param string $slug Admin page slug to prefix.
* @return string Prefixed admin page slug.
*/
public function prefix( $slug = '' ) {
return $this->prefix . $slug;
}
/**
* Handles an admin page in WordPress.
*
* @since 1.0.0
* @internal
*/
public function handle_in_wp() {
// This is hooked in here, as there is no dedicated hook that includes $hook_suffix.
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_in_wp' ) );
$hook_suffix = substr( current_action(), strlen( 'load-' ) );
if ( ! isset( $this->hook_suffixes[ $hook_suffix ] ) ) {
return;
}
$admin_page = $this->hook_suffixes[ $hook_suffix ];
$callback = $admin_page->get_handle_callback();
if ( empty( $callback ) ) {
return;
}
call_user_func( $callback, $admin_page );
}
/**
* Enqueues assets for an admin page in WordPress.
*
* @since 1.0.0
* @internal
*
* @param string $hook_suffix Hook suffix for the current page.
*/
public function enqueue_in_wp( $hook_suffix ) {
if ( ! isset( $this->hook_suffixes[ $hook_suffix ] ) ) {
return;
}
$admin_page = $this->hook_suffixes[ $hook_suffix ];
$callback = $admin_page->get_enqueue_callback();
if ( empty( $callback ) ) {
return;
}
call_user_func( $callback, $admin_page );
}
/**
* Renders an admin page in WordPress.
*
* @since 1.0.0
* @internal
*/
public function render_in_wp() {
$hook_suffix = current_action();
if ( ! isset( $this->hook_suffixes[ $hook_suffix ] ) ) {
return;
}
$admin_page = $this->hook_suffixes[ $hook_suffix ];
$callback = $admin_page->get_render_callback();
if ( empty( $callback ) ) {
return;
}
call_user_func( $callback, $admin_page );
}
/**
* Registers a new admin page in WordPress.
*
* @since 1.0.0
*
* @param WP_Site_Identity_Admin_Page $admin_page Admin page to register.
*/
protected function register_in_wp( WP_Site_Identity_Admin_Page $admin_page ) {
$slug = $this->prefix( $admin_page->get_slug() );
$callback = 'add_submenu_page';
$args = array(
null,
$admin_page->get_title(),
$admin_page->get_title(),
$admin_page->get_capability(),
$slug,
array( $this, 'render_in_wp' ),
);
if ( is_a( $admin_page, 'WP_Site_Identity_Admin_Submenu_Page' ) ) {
$args[0] = $admin_page->get_parent_slug();
$args[2] = $admin_page->get_menu_title();
} elseif ( is_a( $admin_page, 'WP_Site_Identity_Admin_Menu_Page' ) ) {
$callback = 'add_menu_page';
$args[2] = $admin_page->get_menu_title();
array_shift( $args );
$args[] = $admin_page->get_icon_url();
$args[] = $admin_page->get_position();
}
$hook_suffix = call_user_func_array( $callback, $args );
add_action( "load-{$hook_suffix}", array( $this, 'handle_in_wp' ) );
$this->hook_suffixes[ $hook_suffix ] = $admin_page;
}
/**
* Unregisters an existing admin page in WordPress.
*
* @since 1.0.0
*
* @param WP_Site_Identity_Admin_Page $admin_page Admin page to unregister.
*/
protected function unregister_in_wp( WP_Site_Identity_Admin_Page $admin_page ) {
$slug = $this->prefix( $admin_page->get_slug() );
$hook_suffix = array_search( $admin_page, $this->hook_suffixes, true );
if ( false !== $hook_suffix ) {
remove_action( "load-{$hook_suffix}", array( $this, 'handle_in_wp' ) );
remove_action( "{$hook_suffix}", array( $this, 'render_in_wp' ) );
unset( $this->hook_suffixes[ $hook_suffix ] );
}
$callback = 'remove_submenu_page';
$args = array(
null,
$slug,
);
if ( is_a( $admin_page, 'WP_Site_Identity_Admin_Submenu_Page' ) ) {
$args[0] = $admin_page->get_parent_slug();
} elseif ( is_a( $admin_page, 'WP_Site_Identity_Admin_Menu_Page' ) ) {
$callback = 'add_menu_page';
array_shift( $args );
}
call_user_func_array( $callback, $args );
}
}