=' ) ) {
return;
}
$fifty_three_minute_tools_core_booted = self::VERSION;
add_action( 'admin_post_fifty_three_minute_tools_activate_plugin', array( self::class, 'handle_activate_plugin' ) );
if ( did_action( 'admin_menu' ) ) {
self::register_parent_menu();
self::register_plugin_submenus();
self::ensure_overview_submenu();
return;
}
add_action( 'admin_menu', array( self::class, 'register_parent_menu' ), 9 );
add_action( 'admin_menu', array( self::class, 'register_plugin_submenus' ), 11 );
add_action( 'admin_menu', array( self::class, 'ensure_overview_submenu' ), 12 );
}
/**
* Add or update the top-level 53mp Tools menu.
*/
public static function register_parent_menu() {
remove_action( 'admin_menu', 'fifty_three_minute_tools_add_parent_menu', 9 );
remove_action( 'admin_menu', 'fifty_three_minute_tools_register_overview_submenu', 10 );
global $menu;
$slug = self::PARENT_SLUG;
$found = false;
foreach ( (array) $menu as $index => $item ) {
if ( isset( $item[2] ) && $slug === $item[2] ) {
$menu[ $index ][0] = __( '53mp Tools', '53mp-fast-bulk-page-creator' );
$menu[ $index ][1] = self::CAPABILITY;
$menu[ $index ][3] = self::overview_title();
$found = true;
break;
}
}
if ( $found ) {
return;
}
add_menu_page(
self::overview_title(),
__( '53mp Tools', '53mp-fast-bulk-page-creator' ),
self::CAPABILITY,
$slug,
array( self::class, 'render_all_plugins' ),
'dashicons-clock',
58
);
}
/**
* Create one submenu for each plugin in the shared registry.
*/
public static function register_plugin_submenus() {
$plugins = apply_filters( 'fifty_three_minute_tools_plugins', array() );
if ( ! is_array( $plugins ) ) {
return;
}
$plugins = self::sort_registered_plugins( $plugins );
$parent = self::PARENT_SLUG;
foreach ( $plugins as $plugin ) {
if ( ! is_array( $plugin ) ) {
continue;
}
$slug = isset( $plugin['menu_slug'] ) ? (string) $plugin['menu_slug'] : '';
if ( '' === $slug || self::PARENT_SLUG === $slug ) {
continue;
}
if ( empty( $plugin['menu_title'] ) || empty( $plugin['callback'] ) || ! is_callable( $plugin['callback'] ) ) {
continue;
}
if ( self::submenu_slug_exists( $parent, $slug ) ) {
continue;
}
$capability = isset( $plugin['capability'] ) ? (string) $plugin['capability'] : '';
if ( '' === $capability ) {
continue;
}
$page_title = isset( $plugin['page_title'] ) && '' !== (string) $plugin['page_title']
? (string) $plugin['page_title']
: (string) $plugin['menu_title'];
add_submenu_page(
$parent,
$page_title,
(string) $plugin['menu_title'],
$capability,
$slug,
$plugin['callback']
);
}
}
/**
* Keep All Plugins as the first submenu and point it at the header table.
*/
public static function ensure_overview_submenu() {
$slug = self::PARENT_SLUG;
$hook = 'toplevel_page_' . $slug;
remove_submenu_page( $slug, $slug );
remove_all_actions( $hook );
add_submenu_page(
$slug,
self::overview_title(),
self::overview_title(),
self::CAPABILITY,
$slug,
array( self::class, 'render_all_plugins' )
);
self::move_submenu_first( $slug );
}
/**
* All Plugins page. Rows come from the WordPress.org plugin directory for DIRECTORY_AUTHOR.
*/
public static function render_all_plugins() {
if ( ! current_user_can( self::CAPABILITY ) ) {
wp_die( esc_html__( 'You do not have permission to access this page.', '53mp-fast-bulk-page-creator' ) );
}
if ( ! function_exists( 'get_plugins' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$plugins = self::directory_plugins();
$registered = self::registry_by_plugin_file();
$can_install = current_user_can( 'install_plugins' );
$can_activate = current_user_can( 'activate_plugins' );
?>
|
|
|
|
|
|
| get_error_message() ); ?> |
|
|
|
|
|
|
|
|
get_error_message() ) );
}
wp_safe_redirect( add_query_arg( '53mp-activated', '1', admin_url( 'admin.php?page=' . self::PARENT_SLUG ) ) );
exit;
}
/**
* Published plugins for DIRECTORY_AUTHOR, from the WordPress.org plugin info API.
*
* @return array|\WP_Error
*/
private static function directory_plugins() {
$cache_key = '53mp_tools_dir_plugins_' . self::DIRECTORY_AUTHOR;
$cached = get_transient( $cache_key );
if ( is_array( $cached ) ) {
return $cached;
}
if ( ! function_exists( 'plugins_api' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
}
$rows = array();
$page = 1;
$pages = 1;
do {
$api = plugins_api(
'query_plugins',
array(
'author' => self::DIRECTORY_AUTHOR,
'per_page' => 100,
'page' => $page,
'fields' => array(
'short_description' => true,
'description' => false,
'sections' => false,
'versions' => false,
'downloaded' => false,
),
)
);
if ( is_wp_error( $api ) ) {
return $api;
}
$batch = ( is_object( $api ) && isset( $api->plugins ) && is_array( $api->plugins ) ) ? $api->plugins : array();
foreach ( $batch as $plugin ) {
$slug = (string) self::plugin_field( $plugin, 'slug' );
if ( '' === $slug ) {
continue;
}
$description = (string) self::plugin_field( $plugin, 'short_description' );
if ( '' === $description ) {
$description = wp_strip_all_tags( (string) self::plugin_field( $plugin, 'description' ) );
}
$rows[] = array(
'slug' => $slug,
'name' => self::normalize_plugin_name( (string) self::plugin_field( $plugin, 'name' ) ),
'description' => html_entity_decode( wp_strip_all_tags( $description ), ENT_QUOTES, 'UTF-8' ),
'version' => (string) self::plugin_field( $plugin, 'version' ),
);
}
if ( is_object( $api ) && isset( $api->info->pages ) ) {
$pages = max( 1, (int) $api->info->pages );
}
++$page;
} while ( $page <= $pages && $page <= 10 );
usort(
$rows,
static function ( $a, $b ) {
return strcasecmp( $a['name'], $b['name'] );
}
);
if ( ! empty( $rows ) ) {
set_transient( $cache_key, $rows, 12 * HOUR_IN_SECONDS );
}
return $rows;
}
/**
* @param object|array $plugin Plugin API record.
* @param string $key Field name.
* @return mixed
*/
private static function plugin_field( $plugin, $key ) {
if ( is_object( $plugin ) && isset( $plugin->{$key} ) ) {
return $plugin->{$key};
}
if ( is_array( $plugin ) && isset( $plugin[ $key ] ) ) {
return $plugin[ $key ];
}
return '';
}
/**
* Match a directory plugin to an installed plugin file.
*
* @param string $slug Directory slug.
* @param string $name Directory plugin name.
* @return string Plugin basename, or empty when it is not installed.
*/
private static function installed_plugin_file( $slug, $name ) {
static $by_slug = null;
static $by_name = null;
if ( null === $by_slug ) {
$by_slug = array();
$by_name = array();
foreach ( get_plugins() as $file => $data ) {
$dir = dirname( $file );
$directory_slug = ( '.' === $dir ) ? basename( $file, '.php' ) : $dir;
$by_slug[ $directory_slug ] = $file;
$plugin_name = isset( $data['Name'] ) ? self::normalize_plugin_name( (string) $data['Name'] ) : '';
if ( '' !== $plugin_name ) {
$by_name[ strtolower( $plugin_name ) ] = $file;
}
}
}
if ( isset( $by_slug[ $slug ] ) ) {
return $by_slug[ $slug ];
}
$key = strtolower( self::normalize_plugin_name( $name ) );
return isset( $by_name[ $key ] ) ? $by_name[ $key ] : '';
}
/**
* Decode directory names so they compare with local plugin headers.
*
* @param string $name Plugin name.
* @return string
*/
private static function normalize_plugin_name( $name ) {
$name = html_entity_decode( wp_strip_all_tags( $name ), ENT_QUOTES, 'UTF-8' );
$name = str_replace( array( '–', '—' ), '-', $name );
return trim( preg_replace( '/\s+/', ' ', $name ) );
}
/**
* @param string $slug Plugin directory slug.
* @return string
*/
private static function install_url( $slug ) {
return wp_nonce_url(
self_admin_url( 'update.php?action=install-plugin&plugin=' . rawurlencode( $slug ) ),
'install-plugin_' . $slug
);
}
/**
* @param string $plugin_file Plugin basename.
* @return string
*/
private static function activate_url( $plugin_file ) {
$url = add_query_arg(
array(
'action' => 'fifty_three_minute_tools_activate_plugin',
'plugin' => $plugin_file,
),
admin_url( 'admin-post.php' )
);
return wp_nonce_url( $url, 'fifty_three_minute_tools_activate_' . $plugin_file );
}
/**
* Settings screen for an installed, active suite plugin.
*
* @param string $plugin_file Plugin basename.
* @param array> $registered Registry keyed by plugin file.
* @return string
*/
private static function settings_url( $plugin_file, $registered ) {
if ( ! isset( $registered[ $plugin_file ] ) || ! is_array( $registered[ $plugin_file ] ) ) {
return '';
}
$registration = $registered[ $plugin_file ];
$menu_slug = isset( $registration['menu_slug'] ) ? (string) $registration['menu_slug'] : '';
$capability = isset( $registration['capability'] ) ? (string) $registration['capability'] : '';
if ( '' === $menu_slug || '' === $capability || ! current_user_can( $capability ) ) {
return '';
}
return admin_url( 'admin.php?page=' . $menu_slug );
}
/**
* Loader version bundled with one installed plugin.
*
* @param string $plugin_file Plugin basename from get_plugins().
* @return string Empty when this plugin does not ship the loader.
*/
private static function bundled_loader_version( $plugin_file ) {
if ( ! defined( 'WP_PLUGIN_DIR' ) ) {
return '';
}
$includes_dir = dirname( WP_PLUGIN_DIR . '/' . $plugin_file ) . '/includes';
if ( function_exists( 'fifty_three_minute_tools_read_bundle_version' ) ) {
$version = fifty_three_minute_tools_read_bundle_version( $includes_dir );
return ( is_string( $version ) && '0.0.0' !== $version ) ? $version : '';
}
$version_file = $includes_dir . '/fifty-three-minute-tools-version.php';
if ( ! is_readable( $version_file ) ) {
return '';
}
$version = include $version_file;
return is_string( $version ) ? $version : '';
}
/**
* Registry entries keyed by plugin basename.
*
* @return array>
*/
private static function registry_by_plugin_file() {
$registered = apply_filters( 'fifty_three_minute_tools_plugins', array() );
$by_file = array();
if ( ! is_array( $registered ) ) {
return $by_file;
}
foreach ( $registered as $entry ) {
if ( ! is_array( $entry ) || empty( $entry['plugin_file'] ) ) {
continue;
}
$by_file[ (string) $entry['plugin_file'] ] = $entry;
}
return $by_file;
}
/**
* Sort by position, then menu title. Missing positions sort after numbered ones.
*
* @param array> $plugins Registered plugins.
* @return array>
*/
private static function sort_registered_plugins( $plugins ) {
uasort(
$plugins,
static function ( $a, $b ) {
$pos_a = ( is_array( $a ) && isset( $a['position'] ) && null !== $a['position'] && '' !== $a['position'] ) ? (int) $a['position'] : 1000;
$pos_b = ( is_array( $b ) && isset( $b['position'] ) && null !== $b['position'] && '' !== $b['position'] ) ? (int) $b['position'] : 1000;
if ( $pos_a !== $pos_b ) {
return ( $pos_a < $pos_b ) ? -1 : 1;
}
$title_a = ( is_array( $a ) && isset( $a['menu_title'] ) ) ? (string) $a['menu_title'] : '';
$title_b = ( is_array( $b ) && isset( $b['menu_title'] ) ) ? (string) $b['menu_title'] : '';
return strcasecmp( $title_a, $title_b );
}
);
return $plugins;
}
/**
* @param string $parent Parent menu slug.
* @param string $slug Submenu slug.
* @return bool
*/
private static function submenu_slug_exists( $parent, $slug ) {
global $submenu;
if ( empty( $submenu[ $parent ] ) || ! is_array( $submenu[ $parent ] ) ) {
return false;
}
foreach ( $submenu[ $parent ] as $item ) {
if ( isset( $item[2] ) && $slug === $item[2] ) {
return true;
}
}
return false;
}
/**
* @param string $slug Parent menu slug.
*/
private static function move_submenu_first( $slug ) {
global $submenu;
if ( empty( $submenu[ $slug ] ) || ! is_array( $submenu[ $slug ] ) ) {
return;
}
$overview = null;
$rest = array();
foreach ( $submenu[ $slug ] as $item ) {
if ( null === $overview && isset( $item[2] ) && $slug === $item[2] ) {
$overview = $item;
continue;
}
$rest[] = $item;
}
if ( null === $overview ) {
return;
}
$submenu[ $slug ] = array_merge( array( $overview ), $rest );
}
}
}
}
namespace {
defined( 'ABSPATH' ) || exit;
if ( ! function_exists( 'fifty_three_minute_tools_menu_slug' ) ) {
/**
* Admin menu slug for the 53mp Tools parent.
*
* @return string
*/
function fifty_three_minute_tools_menu_slug() {
return \FiftyThreeMP\Tools\Core\v1_4_0\Core::parent_slug();
}
}
if ( ! function_exists( 'fifty_three_minute_tools_register_parent_menu' ) ) {
/**
* Register the top-level 53mp Tools admin menu once.
*
* @return string Parent menu slug.
*/
function fifty_three_minute_tools_register_parent_menu() {
\FiftyThreeMP\Tools\Core\v1_4_0\Core::boot();
return \FiftyThreeMP\Tools\Core\v1_4_0\Core::parent_slug();
}
}
\FiftyThreeMP\Tools\Core\v1_4_0\Core::boot();
}