PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.13
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.13
6.2.13 6.2.12 6.2.10 6.2.11 6.2.9 6.2.8 6.2.7 6.2.6 6.2.5 6.2.4 6.2.3 6.2.2 3.6.22 3.6.31 3.6.40 3.6.41 3.6.42 3.6.50 3.6.51 3.6.60 3.6.61 3.6.62 3.6.64 3.6.65 3.6.66 All 195 releases
fluentform / database / Migrations / LegacyManagerScopes.php

LegacyManagerScopes.php in Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder 6.2.13, at database/Migrations/LegacyManagerScopes.php

160 lines 5.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentForm\Database\Migrations;
4
5 defined('ABSPATH') or die;
6
7 /**
8 * Temporary compatibility migration for legacy manager scope records.
9 *
10 * Older installs may have "specific forms = yes" with an empty allowed-forms
11 * list, which historically behaved like unrestricted access. The newer scoped
12 * ACL logic treats that state as "no forms allowed", so we normalize those
13 * legacy records once during upgrade.
14 *
15 * This can be removed after a few stable release cycles, once older installs
16 * have had enough time to pass through the one-time normalization.
17 */
18 class LegacyManagerScopes
19 {
20 const BATCH_SIZE = 500;
21 const COMPLETED_OPTION = 'fluentform_empty_manager_scopes_normalized';
22 const CURSOR_OPTION = 'fluentform_empty_manager_scopes_normalization_cursor';
23
24 public static function migrate()
25 {
26 if (get_option(self::COMPLETED_OPTION)) {
27 return;
28 }
29
30 global $wpdb;
31
32 $allowedFormsMetaKey = '_fluent_forms_allowed_forms';
33 $specificFormsMetaKey = '_fluent_forms_has_specific_forms_permission';
34 $lastProcessedUserId = max(0, intval(get_option(self::CURSOR_OPTION, 0)));
35
36 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- One-time upgrade cleanup for legacy manager scope data.
37 $scopedUserIds = $wpdb->get_col($wpdb->prepare(
38 "SELECT user_id
39 FROM {$wpdb->usermeta}
40 WHERE meta_key = %s
41 AND meta_value = %s
42 AND user_id > %d
43 ORDER BY user_id ASC
44 LIMIT %d",
45 $specificFormsMetaKey,
46 'yes',
47 $lastProcessedUserId,
48 self::BATCH_SIZE
49 ));
50
51 if (false === $scopedUserIds) {
52 return;
53 }
54
55 $scopedUserIds = array_values(array_filter(array_map('intval', (array) $scopedUserIds)));
56
57 if (!$scopedUserIds) {
58 self::markComplete();
59 return;
60 }
61
62 if (!self::normalizeLegacyBatch($scopedUserIds, $specificFormsMetaKey, $allowedFormsMetaKey)) {
63 return;
64 }
65
66 $lastProcessedUserId = (int) end($scopedUserIds);
67
68 if (count($scopedUserIds) < self::BATCH_SIZE) {
69 self::markComplete();
70 return;
71 }
72
73 update_option(self::CURSOR_OPTION, $lastProcessedUserId, 'no');
74 }
75
76 protected static function normalizeLegacyBatch($userIds, $specificFormsMetaKey, $allowedFormsMetaKey)
77 {
78 global $wpdb;
79
80 $placeholders = implode(', ', array_fill(0, count($userIds), '%d'));
81
82 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Batched read for one-time upgrade cleanup.
83 $rows = $wpdb->get_results($wpdb->prepare(
84 "SELECT user_id, meta_value
85 FROM {$wpdb->usermeta}
86 WHERE meta_key = %s
87 AND user_id IN ({$placeholders})",
88 array_merge([$allowedFormsMetaKey], $userIds)
89 ));
90
91 if (false === $rows) {
92 return false;
93 }
94
95 $allowedFormsByUser = [];
96
97 foreach ((array) $rows as $row) {
98 $allowedFormsByUser[intval($row->user_id)][] = $row->meta_value;
99 }
100
101 $legacyUserIds = [];
102
103 foreach ($userIds as $userId) {
104 $metaValues = isset($allowedFormsByUser[$userId]) ? $allowedFormsByUser[$userId] : [];
105 $hasAssignedForms = false;
106
107 foreach ($metaValues as $metaValue) {
108 $allowedForms = maybe_unserialize($metaValue);
109 $allowedForms = is_array($allowedForms)
110 ? array_values(array_filter(array_map('intval', $allowedForms)))
111 : [];
112
113 if ($allowedForms) {
114 $hasAssignedForms = true;
115 break;
116 }
117 }
118
119 if (!$hasAssignedForms) {
120 $legacyUserIds[] = $userId;
121 }
122 }
123
124 if (!$legacyUserIds) {
125 return true;
126 }
127
128 $legacyPlaceholders = implode(', ', array_fill(0, count($legacyUserIds), '%d'));
129
130 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Batched meta update for one-time upgrade cleanup.
131 $updated = $wpdb->query($wpdb->prepare(
132 "UPDATE {$wpdb->usermeta}
133 SET meta_value = %s
134 WHERE meta_key = %s
135 AND user_id IN ({$legacyPlaceholders})",
136 array_merge(['no', $specificFormsMetaKey], $legacyUserIds)
137 ));
138
139 if (false === $updated) {
140 return false;
141 }
142
143 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Batched meta delete for one-time upgrade cleanup.
144 $deleted = $wpdb->query($wpdb->prepare(
145 "DELETE FROM {$wpdb->usermeta}
146 WHERE meta_key = %s
147 AND user_id IN ({$legacyPlaceholders})",
148 array_merge([$allowedFormsMetaKey], $legacyUserIds)
149 ));
150
151 return false !== $deleted;
152 }
153
154 protected static function markComplete()
155 {
156 delete_option(self::CURSOR_OPTION);
157 update_option(self::COMPLETED_OPTION, FLUENTFORM_VERSION, 'no');
158 }
159 }
160