PluginProbe
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification / 5.5.0
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification v5.5.0
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 3.0.70 3.0.71 All 36 releases
← All changes | OnUpdate.php +233 -34 3.0.715.5.0 View file →
@@ -1,34 +1,233 @@
1 -<?php
2 -
3 -namespace forge12\contactform7\CF7DoubleOptIn;
4 -
5 -if ( ! defined( 'ABSPATH' ) ) {
6 - exit;
7 -}
8 -
9 -function onUpdate() {
10 - // Only run if the version installed not exist or the version is < 1.7
11 - // this will add categories to already existing plugins
12 - if ( version_compare( get_site_option( FORGE12_OPTIN_SLUG . '_version' ), '1.7' ) < 0 ) {
13 - createTableOptinCategories();
14 - createTableOptin();
15 -
16 - update_option( FORGE12_OPTIN_SLUG . '_version', '1.7' );
17 - }
18 -
19 - // Only run if the version installed not exist or the version is < 2.0
20 - // this will add categories to already existing plugins
21 - if ( version_compare( get_site_option( FORGE12_OPTIN_SLUG . '_version' ), '2.0' ) < 0 ) {
22 - createTableOptin();
23 -
24 - update_option( FORGE12_OPTIN_SLUG . '_version', '2.0' );
25 - }
26 -
27 - if ( version_compare( get_site_option( FORGE12_OPTIN_SLUG . '_version' ), '3.0.1' ) < 0 ) {
28 - createTableOptin();
29 -
30 - update_option( FORGE12_OPTIN_SLUG . '_version', '3.0.1' );
31 - }
32 -}
33 -
34 -onUpdate();
1 +<?php
2 +
3 +namespace forge12\contactform7\CF7DoubleOptIn;
4 +
5 +use Forge12\Shared\Logger;
6 +
7 +if ( ! defined( 'ABSPATH' ) ) {
8 + exit;
9 +}
10 +
11 +function onUpdate() {
12 + $logger = Logger::getInstance();
13 +
14 + $logger->info( 'Running onUpdate routine', [
15 + 'plugin' => 'double-opt-in',
16 + 'class' => __CLASS__ ?? null,
17 + 'method' => __FUNCTION__,
18 + ] );
19 +
20 + // Read and write the stored version with the SAME scope. Historically
21 + // the read used get_site_option() (network scope on multisite) while
22 + // every write below uses update_option() (blog scope) — so on a
23 + // network-activated multisite the version never read back, and every
24 + // idempotent block re-ran on each admin load. Blog scope matches the
25 + // per-site tables created in OnActivation.php.
26 + $currentVersion = get_option( FORGE12_OPTIN_SLUG . '_version' );
27 +
28 + if ( version_compare( $currentVersion, '1.7' ) < 0 ) {
29 + $logger->info( 'Updating to version 1.7', [
30 + 'plugin' => 'double-opt-in',
31 + 'current' => $currentVersion,
32 + 'target' => '1.7',
33 + ] );
34 +
35 + createTableOptinCategories();
36 + $logger->debug( 'createTableOptinCategories executed', [
37 + 'plugin' => 'double-opt-in',
38 + ] );
39 +
40 + createTableOptin();
41 + $logger->debug( 'createTableOptin executed', [
42 + 'plugin' => 'double-opt-in',
43 + ] );
44 +
45 + update_option( FORGE12_OPTIN_SLUG . '_version', '1.7' );
46 + $logger->info( 'Version updated to 1.7', [
47 + 'plugin' => 'double-opt-in',
48 + ] );
49 + }
50 +
51 + if ( version_compare( $currentVersion, '2.0' ) < 0 ) {
52 + $logger->info( 'Updating to version 2.0', [
53 + 'plugin' => 'double-opt-in',
54 + 'current' => $currentVersion,
55 + 'target' => '2.0',
56 + ] );
57 +
58 + createTableOptin();
59 + $logger->debug( 'createTableOptin executed', [
60 + 'plugin' => 'double-opt-in',
61 + ] );
62 +
63 + update_option( FORGE12_OPTIN_SLUG . '_version', '2.0' );
64 + $logger->info( 'Version updated to 2.0', [
65 + 'plugin' => 'double-opt-in',
66 + ] );
67 + }
68 +
69 + if ( version_compare( $currentVersion, '3.0.1' ) < 0 ) {
70 + $logger->info( 'Updating to version 3.0.1', [
71 + 'plugin' => 'double-opt-in',
72 + 'current' => $currentVersion,
73 + 'target' => '3.0.1',
74 + ] );
75 +
76 + createTableOptin();
77 + $logger->debug( 'createTableOptin executed', [
78 + 'plugin' => 'double-opt-in',
79 + ] );
80 +
81 + update_option( FORGE12_OPTIN_SLUG . '_version', '3.0.1' );
82 + $logger->info( 'Version updated to 3.0.1', [
83 + 'plugin' => 'double-opt-in',
84 + ] );
85 + }
86 +
87 + if ( version_compare( $currentVersion, '3.2.0' ) < 0 ) {
88 + $logger->info( 'Updating to version 3.2.0', [
89 + 'plugin' => 'double-opt-in',
90 + 'current' => $currentVersion,
91 + 'target' => '3.2.0',
92 + ] );
93 +
94 + createTableOptin();
95 + $logger->debug( 'createTableOptin executed', [
96 + 'plugin' => 'double-opt-in',
97 + ] );
98 +
99 + update_option( FORGE12_OPTIN_SLUG . '_version', '3.2.0' );
100 + $logger->info( 'Version updated to 3.2.0', [
101 + 'plugin' => 'double-opt-in',
102 + ] );
103 + }
104 +
105 + if ( version_compare( $currentVersion, '3.3.0' ) < 0 ) {
106 + $logger->info( 'Updating to version 3.3.0', [
107 + 'plugin' => 'double-opt-in',
108 + 'current' => $currentVersion,
109 + 'target' => '3.3.0',
110 + ] );
111 +
112 + // Migrate Unix timestamps to ISO 8601 format
113 + global $wpdb;
114 + $table = $wpdb->prefix . 'f12_cf7_doubleoptin';
115 + foreach ( [ 'createtime', 'updatetime', 'optouttime' ] as $col ) {
116 + $wpdb->query(
117 + "UPDATE {$table} SET {$col} = FROM_UNIXTIME({$col})
118 + WHERE {$col} REGEXP '^[0-9]+$' AND {$col} != '' AND {$col} != '0'"
119 + );
120 + $logger->debug( "Migrated column {$col} from Unix to ISO 8601", [
121 + 'plugin' => 'double-opt-in',
122 + ] );
123 + }
124 +
125 + update_option( FORGE12_OPTIN_SLUG . '_version', '3.3.0' );
126 + $logger->info( 'Version updated to 3.3.0', [
127 + 'plugin' => 'double-opt-in',
128 + ] );
129 + }
130 +
131 + if ( version_compare( $currentVersion, '3.4.0' ) < 0 ) {
132 + $logger->info( 'Updating to version 3.4.0', [
133 + 'plugin' => 'double-opt-in',
134 + 'current' => $currentVersion,
135 + 'target' => '3.4.0',
136 + ] );
137 +
138 + createTableOptin();
139 + $logger->debug( 'createTableOptin executed (adds reminder columns)', [
140 + 'plugin' => 'double-opt-in',
141 + ] );
142 +
143 + update_option( FORGE12_OPTIN_SLUG . '_version', '3.4.0' );
144 + $logger->info( 'Version updated to 3.4.0', [
145 + 'plugin' => 'double-opt-in',
146 + ] );
147 + }
148 +
149 + if ( version_compare( $currentVersion, '4.2.0' ) < 0 ) {
150 + $logger->info( 'Updating to version 4.2.0', [
151 + 'plugin' => 'double-opt-in',
152 + 'current' => $currentVersion,
153 + 'target' => '4.2.0',
154 + ] );
155 +
156 + createTableAuditLog();
157 + $logger->debug( 'createTableAuditLog executed', [
158 + 'plugin' => 'double-opt-in',
159 + ] );
160 +
161 + update_option( FORGE12_OPTIN_SLUG . '_version', '4.2.0' );
162 + $logger->info( 'Version updated to 4.2.0', [
163 + 'plugin' => 'double-opt-in',
164 + ] );
165 + }
166 +
167 + if ( version_compare( $currentVersion, '5.0.1' ) < 0 ) {
168 + $logger->info( 'Updating to version 5.0.1 (adds consent_field column)', [
169 + 'plugin' => 'double-opt-in',
170 + 'current' => $currentVersion,
171 + 'target' => '5.0.1',
172 + ] );
173 +
174 + // dbDelta detects the new `consent_field` column in
175 + // createTableOptin()'s schema and ALTERs the existing table
176 + // to add it. Existing rows get the column's DEFAULT '' so
177 + // no data migration is needed.
178 + createTableOptin();
179 + $logger->debug( 'createTableOptin executed (adds consent_field column)', [
180 + 'plugin' => 'double-opt-in',
181 + ] );
182 +
183 + update_option( FORGE12_OPTIN_SLUG . '_version', '5.0.1' );
184 + $logger->info( 'Version updated to 5.0.1', [
185 + 'plugin' => 'double-opt-in',
186 + ] );
187 + }
188 +
189 + // Safety net: Ensure both tables always exist regardless of stored version.
190 + // Handles edge cases such as database migrations, manual file uploads, or
191 + // restored backups that are missing the custom tables.
192 + global $wpdb;
193 + $optinTable = $wpdb->prefix . 'f12_cf7_doubleoptin';
194 + $categoryTable = $wpdb->prefix . 'f12_cf7_doubleoptin_categories';
195 +
196 + if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $optinTable ) ) !== $optinTable ) {
197 + $logger->warning( 'OptIn table missing – recreating.', [ 'plugin' => 'double-opt-in', 'table' => $optinTable ] );
198 + createTableOptin();
199 + }
200 +
201 + if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $categoryTable ) ) !== $categoryTable ) {
202 + $logger->warning( 'Categories table missing – recreating.', [ 'plugin' => 'double-opt-in', 'table' => $categoryTable ] );
203 + createTableOptinCategories();
204 + }
205 +
206 + $auditTable = $wpdb->prefix . 'f12_cf7_doubleoptin_audit_log';
207 + if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $auditTable ) ) !== $auditTable ) {
208 + $logger->warning( 'Audit log table missing – recreating.', [ 'plugin' => 'double-opt-in', 'table' => $auditTable ] );
209 + createTableAuditLog();
210 + }
211 +
212 + // Always pin the stored version to the live plugin version. The
213 + // version_compare ladder above only writes the target of the last
214 + // block that ran (e.g. '5.0.1'), so without this line the stored
215 + // version permanently lags FORGE12_OPTIN_VERSION even after the
216 + // upgrade completed — including for releases that ship no schema
217 + // change (e.g. 5.1.0). Unconditional so it self-heals any drift.
218 + if ( defined( 'FORGE12_OPTIN_VERSION' )
219 + && version_compare( (string) $currentVersion, FORGE12_OPTIN_VERSION, '<' ) ) {
220 + update_option( FORGE12_OPTIN_SLUG . '_version', FORGE12_OPTIN_VERSION );
221 + $logger->info( 'Stored version pinned to current plugin version', [
222 + 'plugin' => 'double-opt-in',
223 + 'from' => $currentVersion,
224 + 'to' => FORGE12_OPTIN_VERSION,
225 + ] );
226 + }
227 +
228 + $logger->info( 'onUpdate routine finished', [
229 + 'plugin' => 'double-opt-in',
230 + ] );
231 +}
232 +
233 +onUpdate();