PluginProbe
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification / 5.6.2
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification v5.6.2
5.6.2 5.6.3 5.6.1 5.6.0 5.5.0 5.4.0 5.3.2 5.3.1 5.1.6 5.1.5 trunk 2.1.5 2.11 2.12 2.13 2.15 3.0.0 3.0.1 3.0.2 3.0.3 3.0.5 3.0.51 3.0.60 3.0.61 3.0.62 All 38 releases
double-opt-in / core / deactivation_survey.php

deactivation_survey.php in Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification 5.6.2, at core/deactivation_survey.php

145 lines 5.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Asks why, on the way out.
4 *
5 * The moment someone deactivates is the one moment they definitely have an
6 * opinion, and it is the last one we get. So we ask — but the rules are strict,
7 * because this pattern is easy to abuse:
8 *
9 * - Deactivation is never blocked or delayed. "Just deactivate" is always one
10 * click away and is the default if anything goes wrong with the dialog.
11 * - Nothing is transmitted from here. Choosing a reason opens the feedback form
12 * in a new tab with that reason pre-selected; the user still decides whether
13 * to send it.
14 * - It appears once. Dismissing it, or deactivating without answering, sets a flag.
15 */
16
17 namespace forge12\contactform7\CF7DoubleOptIn;
18
19 if ( ! defined( 'ABSPATH' ) ) {
20 exit;
21 }
22
23 add_action( 'admin_footer-plugins.php', __NAMESPACE__ . '\render_deactivation_survey' );
24 add_action( 'wp_ajax_f12_doi_dismiss_survey', __NAMESPACE__ . '\dismiss_deactivation_survey' );
25
26 /**
27 * Remember that the dialog has run its course.
28 */
29 function dismiss_deactivation_survey(): void {
30 check_ajax_referer( 'f12_doi_survey' );
31
32 if ( ! current_user_can( 'activate_plugins' ) ) {
33 wp_send_json_error( null, 403 );
34 }
35
36 update_option( 'f12_doi_survey_done', 1, false );
37 wp_send_json_success();
38 }
39
40 /**
41 * The reasons offered, in the order they are shown.
42 *
43 * @return array<string, string> slug => label
44 */
45 function get_deactivation_reasons(): array {
46 return array(
47 'temporary' => __( 'Only switching it off for a moment', 'double-opt-in' ),
48 'not_sending' => __( 'Confirmation emails did not arrive', 'double-opt-in' ),
49 'complicated' => __( 'I could not get it configured', 'double-opt-in' ),
50 'conflict' => __( 'It clashed with another plugin or my theme', 'double-opt-in' ),
51 'form_plugin' => __( 'It did not work with my form plugin', 'double-opt-in' ),
52 'other_plugin' => __( 'I switched to something else', 'double-opt-in' ),
53 );
54 }
55
56 /**
57 * Print the dialog on the plugins screen.
58 */
59 function render_deactivation_survey(): void {
60 if ( ! current_user_can( 'activate_plugins' ) ) {
61 return;
62 }
63
64 if ( (int) get_option( 'f12_doi_survey_done', 0 ) === 1 ) {
65 return;
66 }
67
68 $reasons = get_deactivation_reasons();
69 $feedback = get_feedback_url( 'deactivation' );
70 $nonce = wp_create_nonce( 'f12_doi_survey' );
71 ?>
72 <div id="f12-doi-survey" style="display:none;position:fixed;inset:0;z-index:100000;background:rgba(0,0,0,.6);">
73 <div style="max-width:460px;margin:10vh auto;background:#fff;border-radius:4px;padding:24px;box-shadow:0 4px 24px rgba(0,0,0,.3);">
74 <h2 style="margin-top:0;">
75 <?php esc_html_e( 'Before you go — what went wrong?', 'double-opt-in' ); ?>
76 </h2>
77 <p style="color:#666;">
78 <?php esc_html_e( 'Optional. Picking a reason opens our feedback form; nothing is sent from this page.', 'double-opt-in' ); ?>
79 </p>
80 <ul style="list-style:none;margin:16px 0;padding:0;">
81 <?php foreach ( $reasons as $slug => $label ) : ?>
82 <li style="margin-bottom:8px;">
83 <a href="<?php echo esc_url( add_query_arg( 'reason', $slug, $feedback ) ); ?>"
84 target="_blank" rel="noopener"
85 class="f12-doi-survey-reason"
86 style="display:block;padding:8px 12px;border:1px solid #ddd;border-radius:3px;text-decoration:none;color:#1d2327;">
87 <?php echo esc_html( $label ); ?>
88 </a>
89 </li>
90 <?php endforeach; ?>
91 </ul>
92 <p style="margin-bottom:0;display:flex;gap:8px;align-items:center;">
93 <a href="#" class="button button-primary f12-doi-survey-skip">
94 <?php esc_html_e( 'Just deactivate', 'double-opt-in' ); ?>
95 </a>
96 <a href="#" class="f12-doi-survey-cancel" style="color:#666;">
97 <?php esc_html_e( 'Cancel', 'double-opt-in' ); ?>
98 </a>
99 </p>
100 </div>
101 </div>
102 <script>
103 (function () {
104 var overlay = document.getElementById('f12-doi-survey');
105 var link = document.querySelector('tr[data-slug="double-opt-in"] .deactivate a');
106 if (!overlay || !link) { return; }
107
108 var target = link.href;
109
110 function done() {
111 // Record that we asked, then let the deactivation proceed. A failed
112 // request must never strand the user on this screen, so navigation
113 // happens either way.
114 var body = new FormData();
115 body.append('action', 'f12_doi_dismiss_survey');
116 body.append('_wpnonce', <?php echo wp_json_encode( $nonce ); ?>);
117 fetch(ajaxurl, { method: 'POST', body: body, credentials: 'same-origin' })
118 .catch(function () {})
119 .finally(function () { window.location.href = target; });
120 }
121
122 link.addEventListener('click', function (e) {
123 e.preventDefault();
124 overlay.style.display = 'block';
125 });
126
127 overlay.querySelectorAll('.f12-doi-survey-reason').forEach(function (a) {
128 // The reason opens in a new tab; this one carries on with the deactivation.
129 a.addEventListener('click', function () { setTimeout(done, 150); });
130 });
131
132 overlay.querySelector('.f12-doi-survey-skip').addEventListener('click', function (e) {
133 e.preventDefault();
134 done();
135 });
136
137 overlay.querySelector('.f12-doi-survey-cancel').addEventListener('click', function (e) {
138 e.preventDefault();
139 overlay.style.display = 'none';
140 });
141 })();
142 </script>
143 <?php
144 }
145