PluginProbe
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification / 5.6.3
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification v5.6.3
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 / src / Repository / FollowUpSchema.php

FollowUpSchema.php in Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification 5.6.3, at src/Repository/FollowUpSchema.php

106 lines 3.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Schema of the follow-up table.
4 *
5 * @package Forge12\DoubleOptIn\Repository
6 * @since 5.6.0
7 */
8
9 declare( strict_types=1 );
10
11 namespace Forge12\DoubleOptIn\Repository;
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 /**
18 * Creates / updates `{prefix}f12_cf7_doubleoptin_followup`.
19 *
20 * Called from the activation hook, the `OnUpdate` ladder and its
21 * "table missing" safety net — the same three places as the other core
22 * tables, so a restored backup or a manual file upload heals itself.
23 *
24 * No form data is stored here. The row references the opt-in by id;
25 * the payload stays in the opt-in row where retention and deletion
26 * already apply to it.
27 */
28 final class FollowUpSchema {
29
30 public const TABLE_NAME = 'f12_cf7_doubleoptin_followup';
31
32 /**
33 * Run dbDelta for the current blog.
34 */
35 public static function install(): void {
36 global $wpdb;
37
38 if ( ! function_exists( 'dbDelta' ) ) {
39 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
40 }
41
42 $table = $wpdb->prefix . self::TABLE_NAME;
43 $charset = $wpdb->get_charset_collate();
44
45 // dbDelta formatting rules: two spaces after PRIMARY KEY, one
46 // column per line, KEY instead of INDEX.
47 $sql = "CREATE TABLE {$table} (
48 id bigint(20) unsigned NOT NULL auto_increment,
49 optin_id bigint(20) unsigned NOT NULL,
50 integration varchar(50) NOT NULL DEFAULT '',
51 action_id varchar(100) NOT NULL,
52 action_kind varchar(20) NOT NULL DEFAULT '',
53 action_label varchar(190) NOT NULL DEFAULT '',
54 config_fingerprint char(64) NOT NULL DEFAULT '',
55 status varchar(24) NOT NULL DEFAULT 'pending',
56 attempts int(11) unsigned NOT NULL DEFAULT 0,
57 budget_attempts int(11) unsigned NOT NULL DEFAULT 0,
58 attempt_id varchar(64) NOT NULL DEFAULT '',
59 attempt_trigger varchar(20) NOT NULL DEFAULT '',
60 started_at datetime DEFAULT NULL,
61 finished_at datetime DEFAULT NULL,
62 next_attempt_at datetime DEFAULT NULL,
63 lease_until datetime DEFAULT NULL,
64 error_code varchar(64) NOT NULL DEFAULT '',
65 retryable tinyint(1) NOT NULL DEFAULT 0,
66 http_status smallint(5) unsigned NOT NULL DEFAULT 0,
67 response_kind varchar(24) NOT NULL DEFAULT '',
68 entry_ref varchar(100) NOT NULL DEFAULT '',
69 evidence varchar(64) NOT NULL DEFAULT '',
70 ticket_hash char(64) DEFAULT NULL,
71 ticket_expires datetime DEFAULT NULL,
72 created_at datetime NOT NULL,
73 updated_at datetime NOT NULL,
74 PRIMARY KEY (id),
75 UNIQUE KEY optin_action (optin_id,action_id),
76 KEY status_next (status,next_attempt_at),
77 KEY status_lease (status,lease_until)
78 ) {$charset};";
79
80 dbDelta( $sql );
81 }
82
83 /**
84 * Whether the table exists and has the newest column. Cheap enough
85 * for the OnUpdate safety net, which runs on every load: one
86 * SHOW COLUMNS … LIKE against a small table.
87 */
88 public static function isCurrent(): bool {
89 global $wpdb;
90 if ( ! self::exists() ) {
91 return false;
92 }
93 $table = $wpdb->prefix . self::TABLE_NAME;
94 return (bool) $wpdb->get_var( $wpdb->prepare( "SHOW COLUMNS FROM {$table} LIKE %s", 'budget_attempts' ) );
95 }
96
97 /**
98 * Whether the table exists on the current blog.
99 */
100 public static function exists(): bool {
101 global $wpdb;
102 $table = $wpdb->prefix . self::TABLE_NAME;
103 return $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ) === $table;
104 }
105 }
106