PluginProbe ʕ •ᴥ•ʔ
Media Cleaner: Clean your WordPress! / 7.0.2
Media Cleaner: Clean your WordPress! v7.0.2
7.1.1 7.1.0 7.0.9 7.0.8 trunk 3.6.8 3.6.9 3.7.0 3.8.0 3.9.0 4.0.0 4.0.2 4.0.4 4.0.6 4.0.7 4.1.0 4.2.0 4.2.2 4.2.3 4.2.4 4.2.5 4.4.0 4.4.2 4.4.4 4.4.6 4.4.7 4.4.8 4.5.0 4.5.4 4.5.6 4.5.7 4.5.8 4.6.2 4.6.3 4.8.0 4.8.4 5.0.0 5.0.1 5.1.0 5.1.1 5.1.3 5.2.0 5.2.1 5.2.4 5.4.0 5.4.1 5.4.2 5.4.3 5.4.4 5.4.5 5.4.6 5.4.9 5.5.0 5.5.1 5.5.2 5.5.3 5.5.4 5.5.7 5.5.8 5.6.1 5.6.2 5.6.3 5.6.4 6.0.1 6.0.2 6.0.3 6.0.4 6.0.5 6.0.6 6.0.7 6.0.8 6.0.9 6.1.2 6.1.3 6.1.4 6.1.5 6.1.6 6.1.7 6.1.8 6.1.9 6.2.0 6.2.1 6.2.3 6.2.4 6.2.5 6.2.6 6.2.7 6.2.8 6.3.0 6.3.1 6.3.2 6.3.4 6.3.5 6.3.7 6.3.8 6.3.9 6.4.0 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.4.7 6.4.8 6.4.9 6.5.0 6.5.1 6.5.2 6.5.3 6.5.4 6.5.5 6.5.6 6.5.7 6.5.8 6.5.9 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.6.6 6.6.7 6.6.8 6.6.9 6.7.0 6.7.1 6.7.2 6.7.3 6.7.4 6.7.5 6.7.6 6.7.7 6.7.8 6.7.9 6.8.0 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.8.6 6.8.7 6.8.8 6.8.9 6.9.0 6.9.1 6.9.2 6.9.3 6.9.4 6.9.5 6.9.6 6.9.7 6.9.8 6.9.9 7.0.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.0.6 7.0.7
media-cleaner / common / admin.php
media-cleaner / common Last commit date
admin.php 7 months ago helpers.php 5 months ago issues.php 7 months ago news.php 7 months ago ratings.php 7 months ago releases.txt 2 years ago rest.php 7 months ago
admin.php
336 lines
1 <?php
2
3 if ( !class_exists( 'MeowKit_WPMC_Admin' ) ) {
4
5 class MeowKit_WPMC_Admin {
6 public static $loaded = false;
7 public static $version = '4.0';
8 public static $admin_version = '4.0';
9
10 /**
11 * Storage for instances that need deferred initialization.
12 *
13 * WordPress Loading Sequence Problem:
14 * 1. Load all plugin files
15 * 2. Fire 'plugins_loaded' hook ← Most plugins instantiate Admin here
16 * 3. Load wp-includes/pluggable.php ← current_user_can() defined here
17 * 4. Fire 'init' hook ← Safe to use pluggable functions
18 *
19 * When plugins instantiate during 'plugins_loaded', the pluggable functions
20 * (current_user_can, wp_get_current_user) don't exist yet. This array stores
21 * instances until 'init' when we can safely call those functions.
22 *
23 * @var array
24 */
25 private static $deferred_instances = array();
26
27 public $prefix; // prefix used for actions, filters (mfrh)
28 public $mainfile; // plugin main file (media-file-renamer.php)
29 public $domain; // domain used for translation (media-file-renamer)
30 public $isPro = false;
31
32 // Store constructor params that affect per-instance setup
33 private $disableReview = false;
34
35 public static $logo = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNDYiIHZpZXdCb3g9IjAgMCA2NCA0NiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGlwUGF0aD0idXJsKCNjbGlwMF8zMTBfMjI5KSI+CiAgICA8cGF0aCBkPSJNNjQgMzAuNjQwOEM2NCAyNy43OTg1IDYwLjA4MTYgMjUuODMwMyA1NS44Mjk4IDI1LjgzMDNDNTQuODU5MyAyNS44MzAzIDUzLjkzMTEgMjUuOTMzIDUzLjA3NiAyNi4xMjUzQzQ5Ljg4NjUgMTkuMDc5IDQxLjY1MzkgMTMuMDg1MyAzMi4wMDAyIDEzLjA4NTNDMzAuODMzNyAxMy4wODUzIDI5LjY4ODEgMTMuMTcyNyAyOC41Njk4IDEzLjMzOTJDMjcuMjA2OSAxMC4zMDc2IDIyLjY3NjIgMi40MzQyNiAxMS41OTU0IDAuMDgzMDA2NEMxMS4wNDkxIC0wLjAzMjc0NTYgMTAuNDk0NiAwLjI0MDU3OCAxMC4yNTkgMC43NDY5QzguODU5MTMgMy43NTYwOCA0Ljc0MjQ3IDE0LjQxMTYgMTAuMjQwMyAyNS45OTMxQzkuNTgxNjUgMjUuODg2NCA4Ljg4NzUxIDI1LjgzMDMgOC4xNzAyMiAyNS44MzAzQzMuOTE4MzkgMjUuODMwMyAwIDI3Ljc5ODUgMCAzMC42NDA4QzAgMzMuNDgzIDMuOTE4MzkgMzUuMjI3MiA4LjE3MDIyIDM1LjIyNzJDOC43MTEyNyAzNS4yMjcyIDkuMjM5MjUgMzUuMTk4OCA5Ljc0ODkzIDM1LjE0MzVDOS40MzYwMiAzNS4yNjY0IDkuMTIyNzUgMzUuNDA3NSA4LjgxMTcxIDM1LjU2NzdDNS42OTM4OCAzNy4xNzA3IDMuOTY4OCA0MC4wMzEyIDQuOTU5MDQgNDEuOTU2OEM1Ljk0ODkgNDMuODgyNCA5LjI3OTIgNDQuMTQ0MiAxMi4zOTcgNDIuNTQxMkMxMy4wNDY0IDQyLjIwNzQgMTMuNjM0OCA0MS44MTkgMTQuMTUxNiA0MS4zOTZDMTguMjYyNyA0NC40OTY3IDI0LjcyODMgNDUuOTgwOSAzMS45OTk4IDQ1Ljk4MDlDMzkuMjcxMyA0NS45ODA5IDQ1LjczNyA0NC40OTY3IDQ5Ljg0OCA0MS4zOTZDNTAuMzY0NCA0MS44MTkgNTAuOTUzMyA0Mi4yMDc0IDUxLjYwMjYgNDIuNTQxMkM1NC43MjA0IDQ0LjE0NDIgNTguMDUwMyA0My44ODI0IDU5LjA0MDYgNDEuOTU2OEM2MC4wMzA1IDQwLjAzMTIgNTguMzA1NyAzNy4xNzA3IDU1LjE4NzkgMzUuNTY3N0M1NC44NzYxIDM1LjQwNzUgNTQuNTYyMSAzNS4yNjY3IDU0LjI0ODUgMzUuMTQzNUM1NC43NTg5IDM1LjE5ODggNTUuMjg3NiAzNS4yMjc1IDU1LjgyOTQgMzUuMjI3NUM2MC4wODEyIDM1LjIyNzUgNjMuOTk5NiAzMy40ODM0IDYzLjk5OTYgMzAuNjQxMUw2NCAzMC42NDA4WiIgZmlsbD0id2hpdGUiLz4KICAgIDxwYXRoIGQ9Ik0yMi4yMjkzIDM2Ljc0NDNDMjYuNTkzNSAzNi43NDQzIDMwLjEzMTQgMzMuMjA2NCAzMC4xMzE0IDI4Ljg0MjJDMzAuMTMxNCAyNC40NzggMjYuNTkzNSAyMC45NDAxIDIyLjIyOTMgMjAuOTQwMUMxNy44NjUxIDIwLjk0MDEgMTQuMzI3MSAyNC40NzggMTQuMzI3MSAyOC44NDIyQzE0LjMyNzEgMzMuMjA2NCAxNy44NjUxIDM2Ljc0NDMgMjIuMjI5MyAzNi43NDQzWiIgZmlsbD0iIzAwRTI4RSIvPgogICAgPHBhdGggZD0iTTIyLjI2NTUgMzMuMTM2MUMyMy41MDIyIDMzLjEzNjEgMjQuNTA0NyAzMS4yODA1IDI0LjUwNDcgMjguOTkxNUMyNC41MDQ3IDI2LjcwMjQgMjMuNTAyMiAyNC44NDY4IDIyLjI2NTUgMjQuODQ2OEMyMS4wMjg4IDI0Ljg0NjggMjAuMDI2MiAyNi43MDI0IDIwLjAyNjIgMjguOTkxNUMyMC4wMjYyIDMxLjI4MDUgMjEuMDI4OCAzMy4xMzYxIDIyLjI2NTUgMzMuMTM2MVoiIGZpbGw9IiMzQzZFOEIiLz4KICAgIDxwYXRoIGQ9Ik0zMS45OTk4IDM3LjkxNTZDMzMuNDIzNyAzNy45MTU2IDM0LjU3ODEgMzcuMzQwOSAzNC41NzgxIDM2LjYzMTlDMzQuNTc4MSAzNS45MjI5IDMzLjQyMzcgMzUuMzQ4MSAzMS45OTk4IDM1LjM0ODFDMzAuNTc1OCAzNS4zNDgxIDI5LjQyMTUgMzUuOTIyOSAyOS40MjE1IDM2LjYzMTlDMjkuNDIxNSAzNy4zNDA5IDMwLjU3NTggMzcuOTE1NiAzMS45OTk4IDM3LjkxNTZaIiBmaWxsPSIjRkY5NDkzIi8+CiAgICA8cGF0aCBkPSJNNTQuMjUwMyAzNS4xMDU4QzU0Ljc2IDM1LjE2MTEgNTUuMjg3OSAzNS4xODk0IDU1LjgyOSAzNS4xODk0QzYwLjA4MDggMzUuMTg5NCA2My45OTkyIDMzLjQ0NTMgNjMuOTk5MiAzMC42MDNDNjMuOTk5MiAyNy43NjA4IDYwLjA4MDggMjUuNzkyNiA1NS44MjkgMjUuNzkyNkM1NS4xMTE3IDI1Ljc5MjYgNTQuNDE3NiAyNS44NDkgNTMuNzU4NSAyNS45NTU4QzU5LjI1NjcgMTQuMzc0MiA1NS4xMzk3IDMuNzE4NzIgNTMuNzQwMiAwLjcwOTU0NkM1My41MDQ2IDAuMjAzMjI1IDUyLjk1MDEgLTAuMDcwMDk5MSA1Mi40MDM4IDAuMDQ1NjUyOUM0MS4zMjMgMi4zOTY5MSAzNi43OTIzIDEwLjI3MDcgMzUuNDI5OCAxMy4zMDE1QzM0LjQ1NDEgMTMuMTU2NiAzMy40NTc5IDEzLjA3MTEgMzIuNDQ1MiAxMy4wNTE3QzMxLjI3NDMgMjAuMDMzIDI4Ljk2NTYgNDMuOTM2NSA1NC4zNDM2IDM1LjE0MzlDNTQuMzEyMyAzNS4xMzEyIDU0LjI4MTMgMzUuMTE4MSA1NC4yNDk5IDM1LjEwNThINTQuMjUwM1oiIGZpbGw9IiMyQjlERkYiLz4KICAgIDxwYXRoIGQ9Ik00MS43MzQyIDMzLjEzNjFDNDIuOTcwOSAzMy4xMzYxIDQzLjk3MzUgMzEuMjgwNSA0My45NzM1IDI4Ljk5MTVDNDMuOTczNSAyNi43MDI0IDQyLjk3MDkgMjQuODQ2OCA0MS43MzQyIDI0Ljg0NjhDNDAuNDk3NSAyNC44NDY4IDM5LjQ5NSAyNi43MDI0IDM5LjQ5NSAyOC45OTE1QzM5LjQ5NSAzMS4yODA1IDQwLjQ5NzUgMzMuMTM2MSA0MS43MzQyIDMzLjEzNjFaIiBmaWxsPSIjM0M2RThCIi8+CiAgPC9nPgogIDxkZWZzPgogICAgPGNsaXBQYXRoIGlkPSJjbGlwMF8zMTBfMjI5Ij4KICAgICAgPHJlY3Qgd2lkdGg9IjY0IiBoZWlnaHQ9IjQ1Ljk2MTciIGZpbGw9IndoaXRlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwIDAuMDE5MTY1KSIvPgogICAgPC9jbGlwUGF0aD4KICA8L2RlZnM+Cjwvc3ZnPgo=';
36
37 public function __construct( $prefix, $mainfile, $domain, $isPro = false, $disableReview = false, $freeOnly = false ) {
38
39 // ALWAYS set instance properties first - these are needed regardless of when setup runs
40 $this->prefix = $prefix;
41 $this->mainfile = $mainfile;
42 $this->domain = $domain;
43 $this->isPro = $isPro;
44 $this->disableReview = $disableReview;
45
46 if ( is_admin() ) {
47
48 // Skip AJAX and REST requests to avoid unnecessary processing
49 if ( MeowKit_WPMC_Helpers::is_asynchronous_request() ) {
50 return;
51 }
52
53 // Check if WordPress pluggable functions are available yet.
54 // These are defined in wp-includes/pluggable.php, which WordPress loads
55 // AFTER the 'plugins_loaded' hook but BEFORE the 'init' hook.
56 if ( !function_exists( 'current_user_can' ) || !function_exists( 'wp_get_current_user' ) ) {
57 // Functions don't exist yet - defer admin setup until 'init' hook
58 // This is NORMAL behavior when plugins instantiate on 'plugins_loaded'
59 $this->defer_admin_setup();
60 // Continue to rest of constructor (filters, license checks, etc.)
61 } else {
62 // Functions already exist - safe to run admin setup immediately
63 // This happens when plugins instantiate on 'init' or later
64 $this->run_admin_setup();
65 }
66
67 // License-related admin notices (doesn't require pluggable functions)
68 $license = get_option( $this->prefix . '_license', '' );
69 if ( !empty( $license ) && !$this->isPro ) {
70 add_action( 'admin_notices', [ $this, 'admin_notices_licensed_free' ] );
71 }
72 }
73
74 // ALWAYS register these filters (they work at any time)
75 add_filter( 'plugin_row_meta', [ $this, 'custom_plugin_row_meta' ], 10, 2 );
76 add_filter( 'edd_sl_api_request_verify_ssl', [ $this, 'request_verify_ssl' ], 10, 0 );
77 }
78
79 /**
80 * Defer admin setup until WordPress 'init' hook.
81 *
82 * This method stores the current instance and registers a one-time
83 * 'init' hook callback that will process all deferred instances.
84 *
85 * Why defer? Because we need current_user_can() to check permissions,
86 * and that function doesn't exist until after 'plugins_loaded'.
87 */
88 private function defer_admin_setup() {
89 // Add this instance to the queue for processing on 'init'
90 self::$deferred_instances[] = $this;
91
92 // Register the 'init' hook only once (for the first deferred instance)
93 if ( count( self::$deferred_instances ) === 1 ) {
94 add_action( 'init', array( __CLASS__, 'process_deferred_instances' ) );
95 }
96 }
97
98 /**
99 * Static callback for 'init' hook - processes all deferred instances.
100 *
101 * By the time 'init' fires, WordPress has loaded pluggable.php and
102 * current_user_can() is guaranteed to exist. We process all instances
103 * that were created during 'plugins_loaded' or earlier.
104 *
105 * This is called as a static method because it processes multiple instances.
106 */
107 public static function process_deferred_instances() {
108 // Belt-and-suspenders check: pluggable functions should ALWAYS exist by 'init'
109 // If they somehow don't, log a warning and bail (this should never happen)
110 if ( !function_exists( 'current_user_can' ) || !function_exists( 'wp_get_current_user' ) ) {
111 trigger_error(
112 'MeowKit_WPMC_Admin: Pluggable functions still unavailable on init hook. ' .
113 'This should never happen and indicates a serious WordPress core issue.',
114 E_USER_WARNING
115 );
116 return;
117 }
118
119 // Process each deferred instance's admin setup
120 foreach ( self::$deferred_instances as $instance ) {
121 $instance->run_admin_setup();
122 }
123
124 // Clear the array to free memory (we won't need these references anymore)
125 self::$deferred_instances = array();
126 }
127
128 /**
129 * Run admin setup - both shared (once) and per-instance (each plugin).
130 *
131 * SHARED SETUP (once for all plugins):
132 * - Issues detection
133 * - Meow Apps menu creation
134 * - Admin footer customization
135 *
136 * PER-INSTANCE SETUP (once per plugin):
137 * - Ratings system
138 * - News system
139 *
140 * This method is called either immediately (if pluggable functions exist)
141 * or deferred until 'init' (if they don't). Either way, it's safe to call
142 * current_user_can() here.
143 */
144 private function run_admin_setup() {
145 // SHARED SETUP: Only run once for all Meow Apps plugins
146 if ( !MeowKit_WPMC_Admin::$loaded ) {
147 // Check for potential issues with WordPress install, other plugins, etc.
148 new MeowKit_WPMC_Issues( $this->prefix, $this->mainfile, $this->domain );
149
150 // Create the unified Meow Apps menu (priority 5 to ensure early creation)
151 add_action( 'admin_menu', [ $this, 'admin_menu_start' ], 5 );
152
153 // Customize admin footer on Meow Apps pages
154 $page = isset( $_GET['page'] ) ? sanitize_text_field( $_GET['page'] ) : null;
155 if ( $page === 'meowapps-main-menu' ) {
156 add_filter( 'admin_footer_text', [ $this, 'admin_footer_text' ], 100000, 1 );
157 }
158
159 MeowKit_WPMC_Admin::$loaded = true;
160 }
161
162 // PER-INSTANCE SETUP: Run for each plugin that uses this library
163 // Only admins get ratings prompts and news
164 if ( $this->is_user_admin() ) {
165 if ( !$this->disableReview ) {
166 new MeowKit_WPMC_Ratings( $this->prefix, $this->mainfile, $this->domain );
167 }
168 new MeowKit_WPMC_News( $this->domain );
169 }
170 }
171
172 /**
173 * Check if current user is a site administrator.
174 *
175 * This method is only called from run_admin_setup(), which guarantees
176 * that pluggable functions exist. No error logging needed - if the
177 * functions don't exist, we simply return false as a defensive fallback.
178 *
179 * @return bool True if user can manage options, false otherwise
180 */
181 public function is_user_admin() {
182 // Defensive check (should never fail if called from run_admin_setup)
183 if ( !function_exists( 'current_user_can' ) || !function_exists( 'wp_get_current_user' ) ) {
184 return false;
185 }
186 return current_user_can( 'manage_options' );
187 }
188
189 public function custom_plugin_row_meta( $links, $file ) {
190 $path = pathinfo( $file );
191 $pathName = basename( $path['dirname'] );
192 $thisPath = pathinfo( $this->mainfile );
193 $thisPathName = basename( $thisPath['dirname'] );
194 $isActive = is_plugin_active( $file );
195 if ( !$isActive ) {
196 return $links;
197 }
198 $isIssue = $this->isPro && !$this->is_registered();
199 if ( strpos( $pathName, $thisPathName ) !== false ) {
200 $new_links = [
201 'settings' =>
202 sprintf( __( '<a href="admin.php?page=%s_settings">Settings</a>', $this->domain ), $this->prefix ),
203 'license' =>
204 $this->is_registered() ?
205 ( '<span style="color: #a75bd6;">' . __( 'Pro Version', $this->domain ) . '</span>' ) :
206 ( $isIssue ? ( sprintf( '<span style="color: #ff3434;">' . __( 'License Issue', $this->domain ), $this->prefix ) . '</span>' ) : ( sprintf( '<span>' . __( '<a target="_blank" href="https://meowapps.com">Get the <u>Pro Version</u></a>', $this->domain ), $this->prefix ) . '</span>' ) ),
207 ];
208 $links = array_merge( $new_links, $links );
209 }
210 return $links;
211 }
212
213 public function request_verify_ssl() {
214 return get_option( 'force_sslverify', false );
215 }
216
217 public function nice_name_from_file( $file ) {
218 $info = pathinfo( $file );
219 if ( !empty( $info ) ) {
220 if ( $info['filename'] == 'wplr-sync' ) {
221 return 'WP/LR Sync';
222 }
223 $info['filename'] = str_replace( '-', ' ', $info['filename'] );
224 $file = ucwords( $info['filename'] );
225 }
226 return $file;
227 }
228
229 public function admin_notices_licensed_free() {
230 if ( isset( $_POST[$this->prefix . '_reset_sub'] ) ) {
231 delete_option( $this->prefix . '_pro_serial' );
232 delete_option( $this->prefix . '_license' );
233 return;
234 }
235 $html = '<div class="notice notice-error">';
236 $html .= sprintf(
237 __( '<p>It looks like you are using the free version of the plugin (<b>%s</b>) but a license for the Pro version was also found. The Pro version might have been replaced by the Free version during an update (might be caused by a temporarily issue). If it is the case, <b>please download it again</b> from the <a target="_blank" href="https://meowapps.com">Meow Store</a>. If you wish to continue using the free version and clear this message, click on this button.', $this->domain ),
238 $this->nice_name_from_file( $this->mainfile )
239 );
240 $html .= '<p>
241 <form method="post" action="">
242 <input type="hidden" name="' . $this->prefix . '_reset_sub" value="true">
243 <input type="submit" name="submit" id="submit" class="button" value="'
244 . __( 'Remove the license', $this->domain ) . '">
245 </form>
246 </p>';
247 $html .= '</div>';
248 wp_kses_post( $html );
249 }
250
251 public function admin_menu_start() {
252 // Hide the admin if user doesn't like Meow much
253 if ( get_option( 'meowapps_hide_meowapps', false ) ) {
254 register_setting( 'general', 'meowapps_hide_meowapps' );
255 add_settings_field( 'meowapps_hide_ads', 'Meow Apps Menu', [ $this, 'meowapps_hide_dashboard_callback' ], 'general' );
256 return;
257 }
258
259 // Create standard menu if it does not already exist
260 global $submenu;
261 if ( !isset( $submenu[ 'meowapps-main-menu' ] ) ) {
262 add_menu_page(
263 'Meow Apps',
264 '<img alt="Meow Apps" style="width: 21px; margin-left: -28px; position: absolute; margin-top: 2px;" src="' . MeowKit_WPMC_Admin::$logo . '" />Meow Apps',
265 'manage_options',
266 'meowapps-main-menu',
267 [ $this, 'admin_meow_apps' ],
268 '',
269 82
270 );
271 add_submenu_page(
272 'meowapps-main-menu',
273 __( 'Dashboard', $this->domain ),
274 __( 'Dashboard', $this->domain ),
275 'manage_options',
276 'meowapps-main-menu',
277 [ $this, 'admin_meow_apps' ]
278 );
279 }
280
281 // Add CSS to hide the default icon
282 add_action( 'admin_head', function () {
283 echo '<style>
284 #toplevel_page_meowapps-main-menu .wp-menu-image {
285 display: none;
286 }
287 </style>';
288 } );
289 }
290
291 public function meowapps_hide_dashboard_callback() {
292 $html = '<input type="checkbox" id="meowapps_hide_meowapps" name="meowapps_hide_meowapps" value="1" ' .
293 checked( 1, get_option( 'meowapps_hide_meowapps' ), false ) . '/>';
294 $html .= __( '<label>Hide <b>Meow Apps</b> Menu</label><br /><small>Hide Meow Apps menu and all its components, for a cleaner admin. This option will be reset if a new Meow Apps plugin is installed.<br /><b>Once activated, an option will be added in your General settings to display it again.</b></small>', $this->domain );
295 echo MeowKit_WPMC_Helpers::wp_kses( $html );
296 }
297
298 public function is_registered() {
299 $is_registered = apply_filters( $this->prefix . '_meowapps_is_registered', false, $this->prefix );
300 return $is_registered;
301 }
302
303 public function get_phpinfo() {
304 if ( !$this->is_user_admin() || !function_exists( 'phpinfo' ) ) {
305 return;
306 }
307 ob_start();
308 // phpcs:disable WordPress.PHP.DevelopmentFunctions
309 phpinfo( INFO_GENERAL | INFO_CONFIGURATION | INFO_MODULES );
310 // phpcs:enable
311 $html = ob_get_contents();
312 ob_end_clean();
313 $html = preg_replace( '%^.*<body>(.*)</body>.*$%ms', '$1', $html );
314 return $html;
315 }
316
317 public function admin_meow_apps() {
318 $html = "<div id='meow-common-dashboard'></div>";
319 $html .= "<div style='height: 0; width: 0; overflow: hidden;' id='meow-common-phpinfo'>";
320 $html .= $this->get_phpinfo();
321 $html .= '</div>';
322 $html = preg_replace( "/<img[^>]+\>/i", '', $html );
323 echo wp_kses_post( $html );
324 }
325
326 public function admin_footer_text( $current ) {
327 return sprintf(
328 // translators: %1$s is the version of the interface; %2$s is a file path.
329 __( 'Thanks for using <a href="https://meowapps.com">Meow Apps</a>! This is the Meow Admin %1$s <br /><i>Loaded from %2$s </i>', $this->domain ),
330 MeowKit_WPMC_Admin::$version,
331 __FILE__
332 );
333 }
334 }
335 }
336