PluginProbe
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification / 5.8.0
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification v5.8.0
5.8.0 5.8.1 5.7.0 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 All 41 releases
double-opt-in / core / review.php

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

179 lines 6.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace forge12\contactform7\CF7DoubleOptIn;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit;
7 }
8
9 // Prevent double-registration when Free + Pro are both active
10 if ( ! function_exists( __NAMESPACE__ . '\\f12_cf7_doubleoptin_maybe_show_review_notice' ) ) {
11
12 add_action( 'admin_notices', __NAMESPACE__ . '\\f12_cf7_doubleoptin_maybe_show_review_notice' );
13 add_action( 'admin_init', __NAMESPACE__ . '\\f12_cf7_doubleoptin_handle_review_actions' );
14
15 /**
16 * Confirmed opt-ins a site needs before we ask for a review.
17 *
18 * History: 3 at first — a site that has barely started, asked to vouch for
19 * something it has not seen work yet. Then 25, which small sites rarely
20 * reach: nine ratings in four years, and the count is what wp.org ranks
21 * and visitors weigh. 10 (5.7.1) is past the "does it work at all" stage
22 * and still within reach of a small site's first weeks.
23 */
24 function f12_cf7_doubleoptin_review_threshold(): int {
25 /**
26 * Filter the number of confirmed opt-ins before the review request shows.
27 *
28 * @param int $threshold Default 10.
29 *
30 * @since 5.7.1
31 */
32 return max( 1, (int) apply_filters( 'f12_doi_review_min_confirmed', 10 ) );
33 }
34
35 /**
36 * Whether the review request is due. Pure: every fact comes in.
37 *
38 * @param array{now:int, installedAt:int, confirmed:int, dismissed:bool, remindLater:int, remindCount:int, pagenow:string, page:string} $facts
39 */
40 function f12_cf7_doubleoptin_review_is_due( array $facts ): bool {
41 // Only where someone looks at the plugin: the dashboard, the plugins
42 // screen and the plugin's own pages — not on every admin screen.
43 $onScreen = in_array( $facts['pagenow'], array( 'index.php', 'plugins.php' ), true )
44 || ( $facts['pagenow'] === 'admin.php' && strpos( $facts['page'], 'f12-doi' ) === 0 );
45 if ( ! $onScreen ) {
46 return false;
47 }
48 if ( ( $facts['now'] - $facts['installedAt'] ) < DAY_IN_SECONDS * 10 ) {
49 return false;
50 }
51 if ( $facts['confirmed'] < f12_cf7_doubleoptin_review_threshold() ) {
52 return false;
53 }
54 if ( $facts['dismissed'] ) {
55 return false;
56 }
57 if ( $facts['remindLater'] > 0 && $facts['now'] < $facts['remindLater'] ) {
58 return false;
59 }
60 // Max 2 reminders.
61 return $facts['remindCount'] < 2;
62 }
63
64 /**
65 * Show review notice if conditions are met.
66 */
67 function f12_cf7_doubleoptin_maybe_show_review_notice() {
68 if ( ! current_user_can( 'manage_options' ) ) {
69 return;
70 }
71
72 global $pagenow;
73 $optin_counters = get_option( 'f12_cf7_doubleoptin_telemetry_counters', [] );
74 $confirmed_optins = isset( $optin_counters['confirmed_optins'] ) ? (int) $optin_counters['confirmed_optins'] : 0;
75
76 $due = f12_cf7_doubleoptin_review_is_due(
77 array(
78 'now' => time(),
79 'installedAt' => (int) get_option( 'f12_cf7_doubleoptin_installed_at', time() ),
80 'confirmed' => $confirmed_optins,
81 'dismissed' => (bool) get_option( 'f12_cf7_doubleoptin_review_dismissed', false ),
82 'remindLater' => (int) get_option( 'f12_cf7_doubleoptin_review_remind_later', 0 ),
83 'remindCount' => (int) get_option( 'f12_cf7_doubleoptin_review_remind_count', 0 ),
84 'pagenow' => isset( $pagenow ) ? (string) $pagenow : '',
85 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only: which admin page is open.
86 'page' => isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '',
87 )
88 );
89 if ( ! $due ) {
90 return;
91 }
92
93 // Claim this screen. The credit-link notice runs later on the same hook
94 // and stands down when it sees this — asking a site owner for two
95 // favours at once is how a plugin earns a one-star review, and the
96 // review request is the more valuable of the two.
97 $GLOBALS['f12_doi_review_notice_shown'] = true;
98
99 ?>
100 <div class="notice notice-info is-dismissible f12-cf7-doubleoptin-review-notice">
101 <p>
102 <?php printf(
103 wp_kses(
104 /* translators: %d: number of confirmed opt-ins. */
105 __(
106 '<strong>Double Opt-In for WordPress</strong> has already confirmed <strong>%d email subscriptions</strong>. Would you support us with a quick review?',
107 'double-opt-in'
108 ),
109 array( 'strong' => array() )
110 ),
111 (int) $confirmed_optins
112 ); ?>
113 </p>
114 <p>
115 <a href="https://wordpress.org/support/plugin/double-opt-in/reviews/#new-post"
116 target="_blank"
117 class="button button-primary">
118 <?php _e( 'Leave a review now', 'double-opt-in' ); ?>
119 </a>
120 <?php
121 // The only path out of this notice used to be a public review.
122 // Someone who is unhappy has no other outlet, so the feedback
123 // lands as a one-star rating that nobody can answer. This gives
124 // them somewhere to say it to us instead.
125 ?>
126 <a href="<?php echo esc_url( get_feedback_url( 'review-notice' ) ); ?>"
127 target="_blank"
128 rel="noopener"
129 class="button">
130 <?php esc_html_e( 'Something not working? Tell us', 'double-opt-in' ); ?>
131 </a>
132 <a href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'f12_cf7_doubleoptin_review_remind', '1' ), 'doi_review_action' ) ); ?>"
133 class="button">
134 <?php _e( 'Remind me later', 'double-opt-in' ); ?>
135 </a>
136 <a href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'f12_cf7_doubleoptin_review_dismissed', '1' ), 'doi_review_action' ) ); ?>"
137 class="button">
138 <?php _e( "Don't ask again", 'double-opt-in' ); ?>
139 </a>
140 </p>
141 </div>
142 <?php
143 }
144
145 /**
146 * Handle review notice actions (dismiss / remind later).
147 */
148 function f12_cf7_doubleoptin_handle_review_actions() {
149 if ( ! current_user_can( 'manage_options' ) ) {
150 return;
151 }
152
153 $is_dismiss = isset( $_GET['f12_cf7_doubleoptin_review_dismissed'] );
154 $is_remind = isset( $_GET['f12_cf7_doubleoptin_review_remind'] );
155
156 if ( ! $is_dismiss && ! $is_remind ) {
157 return;
158 }
159
160 if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), 'doi_review_action' ) ) {
161 return;
162 }
163
164 if ( $is_dismiss ) {
165 update_option( 'f12_cf7_doubleoptin_review_dismissed', true );
166 }
167
168 if ( $is_remind ) {
169 $remind_count = (int) get_option( 'f12_cf7_doubleoptin_review_remind_count', 0 );
170 update_option( 'f12_cf7_doubleoptin_review_remind_later', time() + DAY_IN_SECONDS * 7 );
171 update_option( 'f12_cf7_doubleoptin_review_remind_count', $remind_count + 1 );
172 }
173
174 // Redirect to remove query parameters from URL
175 wp_safe_redirect( remove_query_arg( [ 'f12_cf7_doubleoptin_review_dismissed', 'f12_cf7_doubleoptin_review_remind', '_wpnonce' ] ) );
176 exit;
177 }
178 }
179