<?php
/**
* The abstract class for creating admin components.
*
* @since 5.0.0
*
* @package Shortcodes_Ultimate
* @subpackage Shortcodes_Ultimate/admin
*/
abstract class Shortcodes_Ultimate_Admin {
/**
* The path of the main plugin file.
*
* @since 5.0.0
* @access protected
* @var string $plugin_file The path of the main plugin file.
*/
protected $plugin_file;
/**
* The current version of the plugin.
*
* @since 5.0.0
* @access protected
* @var string $plugin_version The current version of the plugin.
*/
protected $plugin_version;
/**
* The prefix of the plugin.
*
* @since 5.0.8
* @access protected
* @var string $plugin_prefix The prefix of the plugin.
*/
protected $plugin_prefix;
/**
* The URL of the plugin folder.
*
* @since 5.0.0
* @access protected
* @var string $plugin_url The URL of the plugin folder.
*/
protected $plugin_url;
/**
* The path to the plugin folder.
*
* @since 5.1.0
* @access private
* @var string $plugin_path The path to the plugin folder.
*/
private $plugin_path;
/**
* User capability required to access admin pages.
*
* @since 5.0.0
* @access protected
* @var string $capability User capability required to access admin pages.
*/
protected $capability;
/**
* The plugin's pages collection.
*
* @since 5.0.0
* @access protected
* @var array $plugin_menu_pages The plugin's pages collection.
*/
static protected $plugin_menu_pages;
/**
* The hook_suffix of the component menu page.
*
* @since 5.0.0
* @access protected
* @var array $component_hook_suffix The hook_suffix of the component menu page.
*/
protected $component_hook_suffix;
/**
* The URL of the component menu page.
*
* @since 5.0.0
* @access protected
* @var array $component_url The URL of the component menu page.
*/
protected $component_url;
/**
* Component tabs collection.
*
* @since 5.0.0
* @access protected
* @var array $component_tabs Component tabs collection.
*/
protected $component_tabs;
/**
* Initialize the class and set its properties.
*
* @since 5.0.0
* @access protected
* @param string $plugin_file The path of the main plugin file.
* @param string $plugin_version The current version of the plugin.
* @param string $plugin_prefix The prefix of the plugin.
*/
public function __construct( $plugin_file, $plugin_version, $plugin_prefix ) {
$this->plugin_file = $plugin_file;
$this->plugin_version = $plugin_version;
$this->plugin_prefix = $plugin_prefix;
$this->plugin_url = plugin_dir_url( $plugin_file );
$this->plugin_path = plugin_dir_path( $plugin_file );
$this->capability = 'manage_options';
$this->component_url = null;
$this->component_hook_suffix = null;
$this->component_tabs = array();
self::$plugin_menu_pages = (array) self::$plugin_menu_pages;
}
/**
* Register menu pages.
*
* @since 5.0.0
*/
public function add_menu_pages() {}
/**
* Register settings.
*
* @since 5.0.8
*/
public function add_settings() {}
/**
* Enqueue JavaScript(s) and Stylesheet(s) for the component.
*
* @since 5.0.0
*/
public function enqueue_scripts() {}
/**
* Add a top-level menu page.
*
* @since 5.0.0
* @uses add_menu_page
* @access protected
* @param string $page_title The text to be displayed in the title tags of the page when the menu is selected.
* @param string $menu_title The text to be used for the menu.
* @param string $capability The capability required for this menu to be displayed to the user.
* @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu).
* @param callable $function The function to be called to output the content for this page.
* @param string $icon_url The URL to the icon to be used for this menu.
* @param int $position The position in the menu order this one should appear.
*/
final protected function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '', $position = null ) {
$hook_suffix = add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position );
self::$plugin_menu_pages[] = $hook_suffix;
$this->component_hook_suffix = $hook_suffix;
$this->component_url = menu_page_url( $menu_slug, false );
}
/**
* Add a submenu page.
*
* @since 5.0.0
* @uses add_submenu_page
* @access protected
* @param string $parent_slug The slug name for the parent menu (or the file name of a standard WordPress admin page).
* @param string $page_title The text to be displayed in the title tags of the page when the menu is selected.
* @param string $menu_title The text to be used for the menu.
* @param string $capability The capability required for this menu to be displayed to the user.
* @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu).
* @param callable $function The function to be called to output the content for this page.
*/
final protected function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '' ) {
$hook_suffix = add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function );
self::$plugin_menu_pages[] = $hook_suffix;
$this->component_hook_suffix = $hook_suffix;
$this->component_url = menu_page_url( $menu_slug, false );
}
/**
* Common callback for all menu pages.
*
* This method retrieves current page slug from $_GET and loads appropriate
* template.
*
* @since 5.0.0
* @return string Settings pages markup.
*/
public function the_menu_page() {
// Sanitize current page slug
$page = sanitize_title( $_GET['page'], false );
// Replace plugin slug with template prefix
$page = str_replace( $this->plugin_prefix, '', $page );
$this->the_template( 'admin/partials/pages/' . $page );
}
/**
* Display settings section.
*
* @param mixed $args Settings section data.
* @since 5.0.8
*/
public function the_settings_section( $args ) {
$section = str_replace( $this->plugin_prefix, '', $args['id'] );
$this->the_template( 'admin/partials/settings/sections/' . $section, $args );
}
/**
* Display settings field.
*
* @param mixed $args The field data.
* @since 5.0.8
*/
public function the_settings_field( $args ) {
$this->the_template( 'admin/partials/settings/fields/' . $args['type'], $args );
}
/**
* Helper function to check component's menu page hook_suffix
*
* @since 5.0.0
* @return boolean Returns true if current screen is the component's menu page
*/
protected function is_component_page() {
$screen = get_current_screen();
return $screen->id === $this->get_component_hook_suffix();
}
/**
* Retrieve the title of the current admin screen.
*
* @since 5.0.0
* @access protected
* @return string The title of the current admin screen.
*/
protected function get_page_title() {
return sprintf(
'%s › %s',
__( 'Shortcodes Ultimate', 'shortcodes-ultimate' ),
get_admin_page_title()
);
}
/**
* Display the title of the current admin screen.
*
* @since 5.0.0
* @access protected
*/
public function the_page_title() {
echo $this->get_page_title();
}
/**
* Retrieve tabs collection.
*
* @since 5.0.0
* @return array Component tabs collection.
*/
protected function get_tabs() {
return $this->component_tabs;
}
/**
* Retrieve the current tab ID
*
* @since 5.0.0
* @return string Current tab ID
*/
protected function get_current_tab() {
if ( empty( $_GET['tab'] ) ) {
return $this->get_first_tab();
}
if ( ! array_key_exists( $_GET['tab'], $this->get_tabs() ) ) {
return $this->get_first_tab();
}
return sanitize_key( $_GET['tab'] );
}
/**
* Retrieve the ID of the first tab.
*
* @since 5.0.0
* @return string The ID of the first tab.
*/
protected function get_first_tab() {
foreach ( $this->get_tabs() as $tab_id => $tab_title ) {
return $tab_id;
}
}
/**
* Retrieve the tab URL by ID
*
* @param string $tab Tab ID
* @return string The tab's URL
*/
protected function get_tab_url( $tab = null ) {
$url = add_query_arg( 'tab', $tab, $this->get_component_url() );
return esc_url_raw( $url );
}
/**
* Retrieve user capability required to access admin pages.
*
* @since 5.0.0
* @access protected
* @return string User capability required to access admin pages.
*/
protected function get_capability() {
return apply_filters( 'su/admin/capability', $this->capability );
}
/**
* Retrieve the plugin menu pages.
*
* @since 5.0.0
* @access protected
* @return array The plugin menu pages.
*/
protected function get_plugin_menu_pages() {
return self::$plugin_menu_pages;
}
/**
* Retrieve the hook_suffix of the component menu page.
*
* @since 5.0.0
* @return array The hook_suffix of the component menu page.
*/
public function get_component_hook_suffix() {
return $this->component_hook_suffix;
}
/**
* Retrieve the URL of the component menu page.
*
* @since 5.0.0
* @access protected
* @return array The URL of the component menu page.
*/
public function get_component_url() {
return $this->component_url;
}
/**
* Callback function to sanitize checkbox value.
*
* @since 5.0.0
* @param mixed $value String 'on' or null.
* @return string Sanitized checkbox value ('on' or empty string '').
*/
public function sanitize_checkbox( $value ) {
return ! empty( $value ) && 'on' === $value ? 'on' : '';
}
/**
* Callback function to sanitize checkbox-group value.
*
* @since 5.1.0
* @param mixed $value Array with selected checkboxes or null.
* @return string Array with selected checkbox IDs, each sanitized.
*/
public function sanitize_checkbox_group( $value ) {
return array_map( 'sanitize_text_field', array_keys( (array) $value ) );
}
/**
* Callback function to sanitize prefix value.
*
* @since 5.0.1
* @param string $prefix Prefix value.
* @return string Sanitized string.
* @see https://developer.wordpress.org/reference/functions/add_shortcode/ Source of the RegExp.
*/
public function sanitize_prefix( $prefix ) {
return preg_replace( '@[<>&/\[\]\x00-\x20="\']@', '', $prefix );
}
/**
* Utility function to get specified template by it's name.
*
* @since 5.0.0
* @param string $name Template name without extension.
* @param mixed $data Data to be available from within template.
* @return string Template content. Returns empty string if template name is invalid or template file wasn't found.
*/
public function get_template( $name = '', $data = array() ) {
// Validate template name
if ( preg_match( "/^(?!-)[a-z0-9-_]+(?<!-)(\/(?!-)[a-z0-9-_]+(?<!-))*$/", $name ) !== 1 ) {
return '';
}
// The full path to template file
$file = $this->plugin_path . $name . '.php';
// Look for a specified file
if ( file_exists( $file ) ) {
ob_start();
include $file;
$template = ob_get_contents();
ob_end_clean();
}
return isset( $template ) ? $template : '';
}
/**
* Utility function to display specified template by it's name.
*
* @since 5.0.0
* @param string $name Template name (without extension).
* @param mixed $data Template data to be passed to the template.
*/
public function the_template( $name, $data = null ) {
echo $this->get_template( $name, $data );
}
}