PluginProbe
phpinfo() WP – Site Health, PHP Compatibility & Server Audit / 7.2.5
phpinfo() WP – Site Health, PHP Compatibility & Server Audit v7.2.5
7.2.7 7.2.6 7.2.5 7.2.4 7.2.3 7.2.0 7.2.1 7.2.2 7.1.0 7.0.3 7.0.4 7.0.5 trunk 6.0 7.0.0 7.0.1 7.0.2
phpinfo-wp / includes / class-deactivate-modal.php

class-deactivate-modal.php in phpinfo() WP – Site Health, PHP Compatibility & Server Audit 7.2.5, at includes/class-deactivate-modal.php

146 lines 7.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 defined('ABSPATH') or die('Unauthorized Access');
3
4 /**
5 * Renders a retention modal when the user clicks "Deactivate" on the
6 * phpinfo() WP row in the WordPress Plugins screen. Shows them which
7 * features they'd lose so they don't blindly deactivate a plugin that
8 * was protecting them (PHP EOL warnings, Config Grader, SSL monitor, etc.).
9 *
10 * The modal HTML + JS are injected only on /wp-admin/plugins.php to keep
11 * the rest of the admin clean. The "Deactivate anyway" button just lets
12 * the original deactivate link follow through.
13 *
14 * Free users see the free feature list; Pro users see both.
15 */
16 class Phpinfo_WP_Deactivate_Modal {
17
18 public static function register(): void {
19 add_action('admin_footer-plugins.php', [__CLASS__, 'render']);
20 }
21
22 public static function render(): void {
23 $is_pro = Phpinfo_WP_License::is_valid();
24 $plugin_basename = plugin_basename(PHPINFOWP_DIR . 'phpinfo-wp.php');
25
26 $free_features = [
27 'phpinfo() viewer + .htaccess editor',
28 'PHP EOL Timeline + admin-bar PHP version warning',
29 'Config Grader summary (A–F grade)',
30 'Troubleshooting Mode (per-user safe-mode with one-click undo)',
31 'PHP Compatibility Scanner (catches plugin breakages before PHP upgrades)',
32 'Pre-update PHP-version warnings on the Plugins screen',
33 'Activity Log of every config change',
34 ];
35 $pro_features = [
36 'White-label PDF Audit Report (your branding, hand to clients)',
37 'One-click Config Auto-Fix with rollback',
38 'Security Headers + SSL Certificate monitors',
39 'OPcache Dashboard + PHP Error Log viewer',
40 'Database Health + Autoload bloat detection',
41 'WP-Cron Monitor + orphan-hook purge',
42 'Email Alerts, Weekly Digest, Slack/Discord webhooks',
43 'Multi-site (Network) support',
44 ];
45 ?>
46 <div id="phpinfowp-deactivate-modal" class="phpinfowp-dm" aria-hidden="true" role="dialog" aria-labelledby="phpinfowp-dm-title">
47 <div class="phpinfowp-dm-backdrop"></div>
48 <div class="phpinfowp-dm-dialog" role="document">
49 <button type="button" class="phpinfowp-dm-close" aria-label="Close">&times;</button>
50
51 <div class="phpinfowp-dm-header">
52 <img src="<?php echo esc_url(PHPINFOWP_URL . 'assets/icon-128x128.png'); ?>"
53 alt="" width="48" height="48" class="phpinfowp-dm-logo"
54 onerror="this.style.display='none'">
55 <div>
56 <h2 id="phpinfowp-dm-title" class="phpinfowp-dm-title">Before you deactivate phpinfo() WP…</h2>
57 <p class="phpinfowp-dm-sub"><?php _e('Here\'s what stops working the moment this plugin goes off:', 'phpinfo-wp'); ?></p>
58 </div>
59 </div>
60
61 <div class="phpinfowp-dm-body">
62 <div class="phpinfowp-dm-col">
63 <div class="phpinfowp-dm-col-label"><?php _e('You\'ll lose (Free)', 'phpinfo-wp'); ?></div>
64 <ul class="phpinfowp-dm-list">
65 <?php foreach ($free_features as $f): ?>
66 <li><span class="dashicons dashicons-no-alt phpinfowp-dm-x"></span><?php echo esc_html($f); ?></li>
67 <?php endforeach; ?>
68 </ul>
69 </div>
70 <?php if ($is_pro): ?>
71 <div class="phpinfowp-dm-col phpinfowp-dm-col-pro">
72 <div class="phpinfowp-dm-col-label"><?php _e('You\'ll also lose (Pro)', 'phpinfo-wp'); ?></div>
73 <ul class="phpinfowp-dm-list">
74 <?php foreach ($pro_features as $f): ?>
75 <li><span class="dashicons dashicons-no-alt phpinfowp-dm-x"></span><?php echo esc_html($f); ?></li>
76 <?php endforeach; ?>
77 </ul>
78 </div>
79 <?php endif; ?>
80 </div>
81
82 <div class="phpinfowp-dm-warn">
83 <span class="dashicons dashicons-warning"></span>
84 <div>
85 Deactivating <strong><?php _e('doesn\'t delete', 'phpinfo-wp'); ?></strong> your settings or logs you can re-activate any time.
86 <?php if ($is_pro): ?>
87 Your license stays on this site; Pro features simply pause while the plugin is off.
88 <?php else: ?>
89 But your site will lose the safety net the moment it's off.
90 <?php endif; ?>
91 </div>
92 </div>
93
94 <div class="phpinfowp-dm-actions">
95 <button type="button" class="button button-primary button-large phpinfowp-dm-keep"><?php _e('Keep it active', 'phpinfo-wp'); ?></button>
96 <a href="#" class="phpinfowp-dm-confirm" data-href=""><?php _e('Deactivate anyway ', 'phpinfo-wp'); ?></a>
97 </div>
98 </div>
99 </div>
100
101 <script>
102 (function () {
103 var slug = <?php echo wp_json_encode($plugin_basename); ?>;
104 var modal = document.getElementById('phpinfowp-deactivate-modal');
105 if (!modal) return;
106 var confirmLink = modal.querySelector('.phpinfowp-dm-confirm');
107 var closeBtns = modal.querySelectorAll('.phpinfowp-dm-close, .phpinfowp-dm-keep, .phpinfowp-dm-backdrop');
108
109 function open(url) {
110 confirmLink.setAttribute('href', url);
111 modal.classList.add('is-open');
112 modal.setAttribute('aria-hidden', 'false');
113 document.body.style.overflow = 'hidden';
114 }
115 function close() {
116 modal.classList.remove('is-open');
117 modal.setAttribute('aria-hidden', 'true');
118 document.body.style.overflow = '';
119 }
120 closeBtns.forEach(function (b) { b.addEventListener('click', close); });
121 document.addEventListener('keydown', function (e) {
122 if (e.key === 'Escape' && modal.classList.contains('is-open')) close();
123 });
124
125 // Match WP's deactivate link: tr[data-plugin="…/phpinfo-wp.php"] .deactivate a
126 // The slug differs between standard and must-use installs, so we
127 // also match the action=deactivate URL fragment as a safety net.
128 document.addEventListener('click', function (e) {
129 var a = e.target.closest && e.target.closest('a');
130 if (!a) return;
131 var href = a.getAttribute('href') || '';
132 if (!/action=deactivate/.test(href)) return;
133 var row = a.closest('tr[data-plugin]');
134 var matchesRow = row && row.getAttribute('data-plugin') === slug;
135 var matchesUrl = href.indexOf(encodeURIComponent(slug)) !== -1;
136 if (!matchesRow && !matchesUrl) return;
137 if (a.closest('.phpinfowp-dm')) return;
138 e.preventDefault();
139 open(href);
140 }, true);
141 }());
142 </script>
143 <?php
144 }
145 }
146