PluginProbe
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification / 3.1.0
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification v3.1.0
5.12.0 5.13.0 5.13.1 5.11.0 5.10.0 5.9.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 All 47 releases
double-opt-in / core / CleanUp.class.php

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

302 lines 10.5 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 use Forge12\Shared\LoggerInterface;
6
7 if(!defined('ABSPATH')){
8 exit;
9 }
10 /**
11 * This class will handle the clean up of the database
12 * as defined by the user settings.
13 */
14 class CleanUp
15 {
16 private LoggerInterface $logger;
17
18 public function __construct(LoggerInterface $logger)
19 {
20 $this->logger = $logger;
21
22 $this->get_logger()->info( 'Daily opt-in cleaner initialized.', [
23 'plugin' => 'double-opt-in',
24 'class' => __CLASS__,
25 ] );
26
27 $this->get_logger()->debug( 'Scheduling daily cleanup action for unconfirmed opt-ins.', [
28 'plugin' => 'double-opt-in',
29 'hook' => 'dailyOptinClear',
30 'callback' => 'removeUnconfirmedOptins',
31 ] );
32 add_action('dailyOptinClear', array($this, 'removeUnconfirmedOptins'));
33
34 $this->get_logger()->debug( 'Scheduling daily cleanup action for confirmed opt-ins.', [
35 'plugin' => 'double-opt-in',
36 'hook' => 'dailyOptinClear',
37 'callback' => 'removeConfirmedOptins',
38 ] );
39 add_action('dailyOptinClear', array($this, 'removeConfirmedOptins'));
40
41 $this->get_logger()->info( 'All daily cleanup actions have been scheduled.', [
42 'plugin' => 'double-opt-in',
43 ] );
44 }
45
46 public function get_logger(): LoggerInterface{
47 return $this->logger;
48 }
49
50 /**
51 * Delete the given hash entry
52 */
53 public function deleteByHash($hash){
54 // Log the start of the deletion attempt.
55 $this->get_logger()->info( 'Attempting to delete opt-in entry by hash.', [
56 'plugin' => 'double-opt-in',
57 'hash' => $hash,
58 ] );
59
60 if(current_user_can('manage_options')){
61 // Log the user's permission.
62 $this->get_logger()->info( 'User has sufficient permissions to perform the deletion.', [
63 'plugin' => 'double-opt-in',
64 'user_id' => get_current_user_id(),
65 ] );
66
67 global $wpdb;
68 $tableName = 'f12_cf7_doubleoptin';
69 $wpTableName = $wpdb->prefix . $tableName;
70
71 // Using a prepared statement is safer to prevent SQL injection. The original code is vulnerable.
72 $query = $wpdb->prepare('DELETE FROM ' . $wpTableName . ' WHERE hash=%s', $hash);
73
74 // Log the query before execution.
75 $this->get_logger()->debug( 'Executing database query to delete by hash.', [
76 'plugin' => 'double-opt-in',
77 'query' => $query,
78 ] );
79
80 $result = $wpdb->query($query);
81
82 if ($result === false) {
83 // Log an error if the query failed.
84 $this->get_logger()->error( 'Failed to delete opt-in by hash.', [
85 'plugin' => 'double-opt-in',
86 'hash' => $hash,
87 'error' => $wpdb->last_error,
88 ] );
89 } else if ($result === 0) {
90 // Log a warning if no rows were affected.
91 $this->get_logger()->warning( 'No rows were deleted for the provided hash. It might not exist.', [
92 'plugin' => 'double-opt-in',
93 'hash' => $hash,
94 ] );
95 } else {
96 // Log a successful deletion.
97 $this->get_logger()->notice( 'Opt-in entry successfully deleted by hash.', [
98 'plugin' => 'double-opt-in',
99 'hash' => $hash,
100 'rows_deleted' => $result,
101 ] );
102 }
103
104 return $result;
105 }
106
107 // Log the permission failure.
108 $this->get_logger()->warning( 'User does not have sufficient permissions to delete an opt-in entry.', [
109 'plugin' => 'double-opt-in',
110 'user_id' => get_current_user_id(),
111 'required_capability' => 'manage_options',
112 ] );
113
114 return false;
115 }
116
117 /**
118 * Delete all Rows from the Database which are older than the given timestamp and where the optin value matches as defined.
119 * @param $timestamp
120 * @param int $optin
121 */
122 private function removeOlderThan($timestamp, $optin = 0)
123 {
124 // Log the start of the cleanup process.
125 $this->get_logger()->info( 'Starting cleanup of opt-in entries older than a specific timestamp.', [
126 'plugin' => 'double-opt-in',
127 'timestamp' => $timestamp,
128 'status' => $optin === 1 ? 'confirmed' : 'unconfirmed',
129 ] );
130
131 global $wpdb;
132 $tableName = 'f12_cf7_doubleoptin';
133 $wpTableName = $wpdb->prefix . $tableName;
134
135 // Use a prepared statement to prevent SQL injection. The original code is vulnerable.
136 $query = $wpdb->prepare( 'DELETE FROM ' . $wpTableName . ' WHERE createtime < %s AND doubleoptin = %d', date('Y-m-d H:i:s', $timestamp), $optin );
137
138 // Log the query before execution.
139 $this->get_logger()->debug( 'Executing database query to remove old entries.', [
140 'plugin' => 'double-opt-in',
141 'query' => $query,
142 ] );
143
144 $result = $wpdb->query($query);
145
146 if ($result === false) {
147 // Log an error if the query failed.
148 $this->get_logger()->error( 'Failed to remove old opt-in entries.', [
149 'plugin' => 'double-opt-in',
150 'error' => $wpdb->last_error,
151 ] );
152 } else {
153 // Log the successful cleanup and the number of rows deleted.
154 $this->get_logger()->notice( 'Successfully removed ' . $result . ' old opt-in entries.', [
155 'plugin' => 'double-opt-in',
156 'rows_deleted' => $result,
157 'status' => $optin === 1 ? 'confirmed' : 'unconfirmed',
158 ] );
159 }
160 }
161
162 /**
163 * Delete all DOI entries
164 */
165 public function reset(){
166 $this->get_logger()->critical( 'A full reset of the double-opt-in table has been requested.', [
167 'plugin' => 'double-opt-in',
168 'action' => 'reset',
169 'note' => 'This action will permanently delete ALL data from the table.',
170 ] );
171
172 global $wpdb;
173 $tableName = 'f12_cf7_doubleoptin';
174 $wpTableName = $wpdb->prefix . $tableName;
175
176 // Use a prepared statement even for a full table reset to log the action properly.
177 $query = 'DELETE FROM ' . $wpTableName;
178
179 $this->get_logger()->warning( 'Executing a full table reset query. This is irreversible.', [
180 'plugin' => 'double-opt-in',
181 'table' => $wpTableName,
182 'query' => $query,
183 ] );
184
185 $result = $wpdb->query($query);
186
187 if ($result === false) {
188 $this->get_logger()->error( 'Failed to perform a full table reset.', [
189 'plugin' => 'double-opt-in',
190 'error' => $wpdb->last_error,
191 ] );
192 } else {
193 $this->get_logger()->emergency( 'Full table reset successfully completed.', [
194 'plugin' => 'double-opt-in',
195 'rows_deleted' => $result,
196 ] );
197 }
198 }
199
200 /**
201 * Clear all unconfirmed database entries if the period selected
202 * is reached.
203 *
204 * Use force to delete confirmed opt-ins in the database settings.
205 */
206 public function removeUnconfirmedOptins($force = false)
207 {
208 $this->get_logger()->info( 'Starting removal process for unconfirmed opt-ins.', [
209 'plugin' => 'double-opt-in',
210 'force_mode' => $force,
211 ] );
212
213 $Settings = CF7DoubleOptIn::getInstance()->getSettings();
214
215 // Log the configuration settings for unconfirmed opt-in removal.
216 $this->get_logger()->debug( 'Checking plugin settings for unconfirmed opt-in removal.', [
217 'plugin' => 'double-opt-in',
218 'delete_unconfirmed' => $Settings['delete_unconfirmed'] ?? 'not set',
219 ] );
220
221 if (($Settings['delete_unconfirmed'] == 0 || !is_numeric($Settings['delete_unconfirmed'])) && !$force) {
222 $this->get_logger()->notice( 'Unconfirmed opt-in removal is disabled based on settings and not in force mode. Aborting.', [
223 'plugin' => 'double-opt-in',
224 ] );
225 return;
226 }
227
228 $period = $Settings['delete_unconfirmed_period'];
229
230 $this->get_logger()->info( 'Calculating timestamp for unconfirmed opt-in removal.', [
231 'plugin' => 'double-opt-in',
232 'age_threshold' => $Settings['delete_unconfirmed'] . ' ' . $period,
233 ] );
234
235 $timestamp = strtotime("- " . (int)$Settings['delete_unconfirmed'] . " " . $period, time());
236
237 // Log the calculated timestamp.
238 $this->get_logger()->debug( 'Calculated timestamp: ' . date('Y-m-d H:i:s', $timestamp), [
239 'plugin' => 'double-opt-in',
240 'timestamp' => $timestamp,
241 ] );
242
243 $this->removeOlderThan($timestamp, 0);
244
245 $this->get_logger()->notice( 'Unconfirmed opt-in removal process completed.', [
246 'plugin' => 'double-opt-in',
247 ] );
248 }
249
250 /**
251 * Clear all confimred database entries if the period selected
252 * is reached.
253 *
254 * Use force to delete confirmed opt-ins in the database settings.
255 */
256 public function removeConfirmedOptins($force = false)
257 {
258 $this->get_logger()->info( 'Starting removal process for confirmed opt-ins.', [
259 'plugin' => 'double-opt-in',
260 'force_mode' => $force,
261 ] );
262
263 $Settings = CF7DoubleOptIn::getInstance()->getSettings();
264
265 // Log the configuration for confirmed opt-in removal.
266 $this->get_logger()->debug( 'Checking plugin settings for confirmed opt-in removal.', [
267 'plugin' => 'double-opt-in',
268 'delete_setting' => $Settings['delete'] ?? 'not set',
269 ] );
270
271 if (($Settings['delete'] == 0 || !is_numeric($Settings['delete'])) && !$force) {
272 $this->get_logger()->notice( 'Confirmed opt-in removal is disabled based on settings and not in force mode. Aborting.', [
273 'plugin' => 'double-opt-in',
274 ] );
275 return;
276 }
277
278 $period = $Settings['delete_period'];
279
280 // Log the parameters being used for the time calculation.
281 $this->get_logger()->info( 'Calculating timestamp for confirmed opt-in removal.', [
282 'plugin' => 'double-opt-in',
283 'age_threshold' => $Settings['delete'] . ' ' . $period,
284 ] );
285
286 $timestamp = strtotime("- " . (int)$Settings['delete'] . " " . $period, time());
287
288 // Log the resulting timestamp.
289 $this->get_logger()->debug( 'Calculated timestamp: ' . date('Y-m-d H:i:s', $timestamp), [
290 'plugin' => 'double-opt-in',
291 'timestamp' => $timestamp,
292 ] );
293
294 $this->removeOlderThan($timestamp, 1);
295
296 $this->get_logger()->notice( 'Confirmed opt-in removal process completed.', [
297 'plugin' => 'double-opt-in',
298 ] );
299 }
300
301 }
302 }