PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.14
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.14
6.2.14 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 All 196 releases
← All changes | app/Modules/Logger/DataLogger.php +189 -71 3.6.416.2.14 View file →
@@ -1,7 +1,8 @@
1 1 <?php namespace FluentForm\App\Modules\Logger;
2 2
3 -use FluentForm\App\Databases\Migrations\FormLogs;
3 +use FluentForm\App\Helpers\Helper;
4 +use FluentForm\Database\Migrations\Logs;
4 5 use FluentForm\App\Modules\Form\FormDataParser;
5 6 use FluentForm\App\Modules\Form\FormFieldsParser;
6 7 use FluentForm\Framework\Foundation\Application;
7 8 use FluentForm\Framework\Helpers\ArrayHelper;
@@ -16,12 +17,14 @@
16 17 }
17 18
18 19 public function getLogFilters()
19 20 {
21 + // SECURITY (H-02): unregistered handler; guard it so it is safe if ever wired to an action.
22 + \FluentForm\App\Modules\Acl\Acl::verify('fluentform_settings_manager');
20 23 $statuses = wpFluent()->table('fluentform_logs')
21 - ->select('status')
22 - ->groupBy('status')
23 - ->get();
24 + ->select('status')
25 + ->groupBy('status')
26 + ->get();
24 27 $formattedStatuses = [];
25 28
26 29 foreach ($statuses as $status) {
27 30 $formattedStatuses[] = $status->status;
@@ -36,16 +39,16 @@
36 39 foreach ($apis as $api) {
37 40 $apiStatuses[] = $api->status;
38 41 }
39 42
40 - $components = wpFluent()->table('ff_scheduled_actions')
41 - ->select('action')
42 - ->groupBy('action')
43 + $components = wpFluent()->table('fluentform_logs')
44 + ->select('component')
45 + ->groupBy('component')
43 46 ->get();
44 47
45 48 $formattedComponents = [];
46 49 foreach ($components as $component) {
47 - $formattedComponents[] = $component->action;
50 + $formattedComponents[] = $component->component;
48 51 }
49 52
50 53 $forms = wpFluent()->table('fluentform_logs')
51 54 ->select('fluentform_logs.parent_source_id', 'fluentform_forms.title')
@@ -58,17 +61,18 @@
58 61
59 62 foreach ($forms as $form) {
60 63 $formattedForms[] = [
61 64 'form_id' => $form->parent_source_id,
62 - 'title' => $form->title
63 - ];;
65 + 'title' => $form->title,
66 + ];
67 +
64 68 }
65 69
66 70 wp_send_json_success([
67 - 'available_statuses' => $formattedStatuses,
71 + 'available_statuses' => $formattedStatuses,
68 72 'available_components' => $formattedComponents,
69 - 'available_forms' => $formattedForms,
70 - 'api_statuses' => $apiStatuses
73 + 'available_forms' => $formattedForms,
74 + 'api_statuses' => $apiStatuses,
71 75 ]);
72 76 }
73 77
74 78 public function log($data)
@@ -75,21 +79,34 @@
75 79 {
76 80 if (!$data) {
77 81 return;
78 82 }
83 +
84 + if (isset($data['description'])) {
85 + $data['description'] = wp_kses($data['description'], [
86 + 'br' => [],
87 + 'b' => [],
88 + 'strong' => [],
89 + 'i' => [],
90 + 'em' => [],
91 + 'code' => [],
92 + 'p' => [],
93 + 'a' => ['href' => [], 'title' => [], 'target' => [], 'rel' => []],
94 + ]);
95 + }
96 +
79 97 $data['created_at'] = current_time('mysql');
80 98
81 99 if (!get_option('fluentform_db_fluentform_logs_added')) {
82 - FormLogs::migrate();
100 + Logs::migrate();
83 101 }
84 102
85 - return wpFluent()->table('fluentform_logs')
86 - ->insert($data);
103 + wpFluent()->table('fluentform_logs')->insert($data);
87 104 }
88 105
89 106 public function getLogsByEntry($entry_id, $log_type = 'logs', $sourceType = 'submission_item')
90 107 {
91 - if($log_type == 'logs') {
108 + if ($log_type == 'logs') {
92 109 $logs = wpFluent()->table('fluentform_logs')
93 110 ->where('source_id', $entry_id)
94 111 ->where('source_type', $sourceType)
95 112 ->orderBy('id', 'DESC')
@@ -94,9 +111,20 @@
94 111 ->where('source_type', $sourceType)
95 112 ->orderBy('id', 'DESC')
96 113 ->get();
97 114
98 - $logs = apply_filters('fluentform_entry_logs', $logs, $entry_id);
115 + $logs = apply_filters_deprecated(
116 + 'fluentform_entry_logs',
117 + [
118 + $logs,
119 + $entry_id,
120 + ],
121 + FLUENTFORM_FRAMEWORK_UPGRADE,
122 + 'fluentform/submission_logs',
123 + 'Use fluentform/submission_logs instead of fluentform_entry_logs.'
124 + );
125 +
126 + $logs = apply_filters('fluentform/submission_logs', $logs, $entry_id);
99 127 } else {
100 128 $logs = wpFluent()->table('ff_scheduled_actions')
101 129 ->select([
102 130 'id',
@@ -102,27 +130,39 @@
102 130 'id',
103 131 'action',
104 132 'status',
105 133 'note',
106 - 'created_at'
134 + 'created_at',
107 135 ])
108 136 ->where('origin_id', $entry_id)
109 137 ->orderBy('id', 'DESC')
110 138 ->get();
111 139
112 - $logs = apply_filters('fluentform_entry_api_logs', $logs, $entry_id);
140 + $logs = apply_filters_deprecated(
141 + 'fluentform_entry_api_logs',
142 + [
143 + $logs,
144 + $entry_id,
145 + ],
146 + FLUENTFORM_FRAMEWORK_UPGRADE,
147 + 'fluentform/submission_api_logs',
148 + 'Use fluentform/submission_api_logs instead of fluentform_entry_api_logs.'
149 + );
150 +
151 + $logs = apply_filters('fluentform/submission_api_logs', $logs, $entry_id);
113 152 }
114 153
115 -
116 154 wp_send_json_success([
117 - 'logs' => $logs
155 + 'logs' => $logs,
118 156 ], 200);
119 157 }
120 158
121 159 public function getAllLogs()
122 160 {
123 - $limit = intval($_REQUEST['per_page']);
124 - $pageNumber = intval($_REQUEST['page_number']);
161 + // SECURITY (H-02): unregistered handler; guard it so it is safe if ever wired to an action.
162 + \FluentForm\App\Modules\Acl\Acl::verify('fluentform_settings_manager');
163 + $limit = intval($this->app->request->get('per_page'));
164 + $pageNumber = intval($this->app->request->get('page_number'));
125 165
126 166 $skip = ($pageNumber - 1) * $limit;
127 167
128 168 global $wpdb;
@@ -127,51 +167,72 @@
127 167
128 168 global $wpdb;
129 169 $logsQuery = wpFluent()->table('fluentform_logs')
130 170 ->select([
131 - 'fluentform_logs.*'
171 + 'fluentform_logs.*',
172 + wpFluent()->raw($wpdb->prefix . 'fluentform_forms.title as form_title'),
173 + wpFluent()->raw($wpdb->prefix . 'fluentform_logs.parent_source_id as form_id'),
174 + wpFluent()->raw($wpdb->prefix . 'fluentform_logs.source_id as entry_id'),
132 175 ])
133 - ->select(wpFluent()->raw( $wpdb->prefix.'fluentform_forms.title as form_title' ))
134 - ->join('fluentform_forms', 'fluentform_forms.id', '=', 'fluentform_logs.parent_source_id')
135 - ->orderBy('fluentform_logs.id', 'DESC')
136 - ->whereIn('fluentform_logs.source_type', ['submission_item', 'form_item']);
176 + ->leftJoin('fluentform_forms', 'fluentform_forms.id', '=', 'fluentform_logs.parent_source_id')
177 + ->orderBy('fluentform_logs.id', 'DESC');
178 + // ->whereIn('fluentform_logs.source_type', ['submission_item', 'form_item']);
137 179
138 -
139 - if($parentSourceId = ArrayHelper::get($_REQUEST, 'parent_source_id')) {
180 + if ($parentSourceId = $this->app->request->get('parent_source_id')) {
140 181 $logsQuery = $logsQuery->where('fluentform_logs.parent_source_id', intval($parentSourceId));
141 182 }
142 183
143 - if($status = ArrayHelper::get($_REQUEST, 'status')) {
144 - $logsQuery = $logsQuery->where('fluentform_logs.status', $status);
184 + if ($status = $this->app->request->get('status')) {
185 + $logsQuery = $logsQuery->where('fluentform_logs.status', sanitize_text_field($status));
145 186 }
146 187
147 - if($component = ArrayHelper::get($_REQUEST, 'component')) {
148 - $logsQuery = $logsQuery->where('fluentform_logs.component', $component);
188 + if ($component = $this->app->request->get('component')) {
189 + $logsQuery = $logsQuery->where('fluentform_logs.component', sanitize_text_field($component));
149 190 }
150 191
192 + if ($formId = $this->app->request->get('form_id')) {
193 + $logsQuery = $logsQuery->where('fluentform_forms.id', intval($formId));
194 + }
151 195
152 196 $logsQueryMain = $logsQuery;
153 197
154 - $logs = $logsQuery->offset($skip)
198 + $logs = $logsQuery->offset($skip)
155 199 ->limit($limit)
156 200 ->get();
157 201
158 - $logs = apply_filters('fluentform_all_logs', $logs);
202 + foreach ($logs as $log) {
203 + if ('submission_item' == $log->source_type && $log->entry_id) {
204 + $log->submission_url = admin_url('admin.php?page=fluent_forms&route=entries&form_id=' . $log->form_id . '#/entries/' . $log->entry_id);
205 + }
206 + }
159 207
208 + $logs = apply_filters_deprecated(
209 + 'fluentform_all_logs',
210 + [
211 + $logs,
212 + ],
213 + FLUENTFORM_FRAMEWORK_UPGRADE,
214 + 'fluentform/all_logs',
215 + 'Use fluentform/all_logs instead of fluentform_all_logs.'
216 + );
217 +
218 + $logs = apply_filters('fluentform/all_logs', $logs);
219 +
160 220 $total = $logsQueryMain->count();
161 221
162 222 wp_send_json_success([
163 223 'logs' => $logs,
164 - 'total' => $total
224 + 'total' => $total,
165 225 ], 200);
166 -
167 226 }
168 227
169 228
170 229 public function getApiLogs()
171 230 {
172 - $limit = intval($_REQUEST['per_page']);
173 - $pageNumber = intval($_REQUEST['page_number']);
231 + // SECURITY (H-02): unregistered handler; guard it so it is safe if ever wired to an action.
232 + \FluentForm\App\Modules\Acl\Acl::verify('fluentform_settings_manager');
233 + $limit = intval($this->app->request->get('per_page'));
234 + $pageNumber = intval($this->app->request->get('page_number'));
174 235
175 236 $skip = ($pageNumber - 1) * $limit;
176 237 global $wpdb;
177 238 $logsQuery = wpFluent()->table('ff_scheduled_actions')
@@ -182,23 +243,22 @@
182 243 'ff_scheduled_actions.origin_id',
183 244 'ff_scheduled_actions.status',
184 245 'ff_scheduled_actions.note',
185 246 'ff_scheduled_actions.created_at',
247 + wpFluent()->raw($wpdb->prefix . 'fluentform_forms.title as form_title'),
186 248 ])
187 - ->select(wpFluent()->raw( $wpdb->prefix.'fluentform_forms.title as form_title' ))
188 249 ->join('fluentform_forms', 'fluentform_forms.id', '=', 'ff_scheduled_actions.form_id')
189 250 ->orderBy('ff_scheduled_actions.id', 'DESC');
190 251
191 -
192 - if($formId = ArrayHelper::get($_REQUEST, 'form_id')) {
252 + if ($formId = $this->app->request->get('form_id')) {
193 253 $logsQuery = $logsQuery->where('ff_scheduled_actions.form_id', intval($formId));
194 254 }
195 255
196 - if($status = ArrayHelper::get($_REQUEST, 'status')) {
256 + if ($status = $this->app->request->get('status')) {
197 257 $logsQuery = $logsQuery->where('ff_scheduled_actions.status', $status);
198 258 }
199 259
200 - if($component = ArrayHelper::get($_REQUEST, 'component')) {
260 + if ($component = $this->app->request->get('component')) {
201 261 $logsQuery = $logsQuery->where('ff_scheduled_actions.action', $component);
202 262 }
203 263
204 264 $logsQueryMain = $logsQuery;
@@ -206,12 +266,22 @@
206 266 $logs = $logsQuery->offset($skip)
207 267 ->limit($limit)
208 268 ->get();
209 269
210 - $logs = apply_filters('fluentform_api_all_logs', $logs);
270 + $logs = apply_filters_deprecated(
271 + 'fluentform_api_all_logs',
272 + [
273 + $logs,
274 + ],
275 + FLUENTFORM_FRAMEWORK_UPGRADE,
276 + 'fluentform/api_all_logs',
277 + 'Use fluentform/api_all_logs instead of fluentform_api_all_logs.'
278 + );
211 279
280 + $logs = apply_filters('fluentform/api_all_logs', $logs);
281 +
212 282 foreach ($logs as $log) {
213 - $log->submission_url = admin_url('admin.php?page=fluent_forms&route=entries&form_id='.$log->form_id.'#/entries/'.$log->origin_id);
283 + $log->submission_url = admin_url('admin.php?page=fluent_forms&route=entries&form_id=' . $log->form_id . '#/entries/' . $log->origin_id);
214 284 }
215 285
216 286 $total = $logsQueryMain->count();
217 287
@@ -216,43 +286,42 @@
216 286 $total = $logsQueryMain->count();
217 287
218 288 wp_send_json_success([
219 289 'logs' => $logs,
220 - 'total' => $total
290 + 'total' => $total,
221 291 ], 200);
222 -
223 292 }
224 293
225 294 public function deleteLogsByIds($ids = [])
226 295 {
227 - if(!$ids) {
228 - $ids = wp_unslash($_REQUEST['log_ids']);
296 + if (!$ids) {
297 + $ids = wp_unslash($this->app->request->get('log_ids'));
229 298 }
230 299
231 - if(!$ids) {
300 + if (!$ids) {
232 301 wp_send_json_error([
233 - 'message' => 'No selections found'
302 + 'message' => 'No selections found',
234 303 ], 423);
235 304 }
236 305
237 - wpFluent()->table('fluentform_logs')
306 + wpFluent()->table('fluentform_logs')
238 307 ->whereIn('id', $ids)
239 - ->delete();
308 + ->delete();
240 309
241 310 wp_send_json_success([
242 - 'message' => __('Selected logs successfully deleted', 'fluentform')
311 + 'message' => __('Selected log(s) successfully deleted', 'fluentform'),
243 312 ], 200);
244 313 }
245 314
246 315 public function deleteApiLogsByIds($ids = [])
247 316 {
248 - if(!$ids) {
249 - $ids = wp_unslash($_REQUEST['log_ids']);
317 + if (!$ids) {
318 + $ids = wp_unslash($this->app->request->get('log_ids'));
250 319 }
251 320
252 - if(!$ids) {
321 + if (!$ids) {
253 322 wp_send_json_error([
254 - 'message' => 'No selections found'
323 + 'message' => 'No selections found',
255 324 ], 423);
256 325 }
257 326
258 327 wpFluent()->table('ff_scheduled_actions')
@@ -259,33 +328,35 @@
259 328 ->whereIn('id', $ids)
260 329 ->delete();
261 330
262 331 wp_send_json_success([
263 - 'message' => __('Selected logs successfully deleted', 'fluentform')
332 + 'message' => __('Selected log(s) successfully deleted', 'fluentform'),
264 333 ], 200);
265 334 }
266 335
267 336 public function retryApiAction()
268 337 {
338 + // SECURITY (H-02): unregistered handler; guard it so it is safe if ever wired to an action.
339 + \FluentForm\App\Modules\Acl\Acl::verify('fluentform_settings_manager');
269 340 $logId = $this->app->request->get('log_id');
270 341 $actionFeed = wpFluent()->table('ff_scheduled_actions')
271 342 ->find($logId);
272 343
273 - if(!$actionFeed) {
344 + if (!$actionFeed) {
274 345 wp_send_json_error([
275 - 'message' => 'API log does not exist'
346 + 'message' => 'API log does not exist',
276 347 ], 423);
277 348 }
278 349
279 - if(!$actionFeed->status == 'success') {
350 + if ($actionFeed->status == 'success') {
280 351 wp_send_json_error([
281 - 'message' => 'API log already in success mode'
352 + 'message' => 'API log already in success mode',
282 353 ], 423);
283 354 }
284 355
285 356 $form = wpFluent()->table('fluentform_forms')->find($actionFeed->form_id);
286 357
287 - $feed = maybe_unserialize($actionFeed->data);
358 + $feed = Helper::safeUnserialize($actionFeed->data);
288 359 $feed['scheduled_action_id'] = $actionFeed->id;
289 360
290 361 $submission = wpFluent()->table('fluentform_submissions')->find($actionFeed->origin_id);
291 362 $entry = $this->getEntry($submission, $form);
@@ -290,16 +361,17 @@
290 361 $submission = wpFluent()->table('fluentform_submissions')->find($actionFeed->origin_id);
291 362 $entry = $this->getEntry($submission, $form);
292 363 $formData = json_decode($submission->response, true);
293 364
294 - wpFluent()->table($this->table)
365 + wpFluent()->table('ff_scheduled_actions')
295 366 ->where('id', $actionFeed->id)
296 367 ->update([
297 - 'status' => 'manual_retry',
368 + 'status' => 'manual_retry',
298 369 'retry_count' => $actionFeed->retry_count + 1,
299 - 'updated_at' => current_time('mysql')
370 + 'updated_at' => current_time('mysql'),
300 371 ]);
301 372
373 + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound -- Dynamic hook name from action feed
302 374 do_action($actionFeed->action, $feed, $formData, $entry, $form);
303 375
304 376 /*
305 377 * Hopefully it's done
@@ -308,9 +380,9 @@
308 380 ->find($logId);
309 381
310 382 wp_send_json_success([
311 383 'message' => 'Retry completed',
312 - 'feed' => $actionFeed
384 + 'feed' => $actionFeed,
313 385 ], 200);
314 386 }
315 387
316 388 private function getEntry($submission, $form)
@@ -316,6 +388,52 @@
316 388 private function getEntry($submission, $form)
317 389 {
318 390 $formInputs = FormFieldsParser::getEntryInputs($form, ['admin_label', 'raw']);
319 391 return FormDataParser::parseFormEntry($submission, $form, $formInputs);
392 + }
393 +
394 + public function getApiLogFilters()
395 + {
396 + $apis = wpFluent()->table('ff_scheduled_actions')
397 + ->select('status')
398 + ->groupBy('status')
399 + ->get();
400 +
401 + $apiStatuses = [];
402 + foreach ($apis as $api) {
403 + $apiStatuses[] = $api->status;
404 + }
405 +
406 + $components = wpFluent()->table('ff_scheduled_actions')
407 + ->select('action')
408 + ->groupBy('action')
409 + ->get();
410 +
411 + $formattedComponents = [];
412 + foreach ($components as $component) {
413 + $formattedComponents[] = $component->action;
414 + }
415 +
416 + $forms = wpFluent()->table('ff_scheduled_actions')
417 + ->select('ff_scheduled_actions.form_id', 'fluentform_forms.title')
418 + ->groupBy('ff_scheduled_actions.form_id')
419 + ->orderBy('ff_scheduled_actions.form_id', 'DESC')
420 + ->join('fluentform_forms', 'fluentform_forms.id', '=', 'ff_scheduled_actions.form_id')
421 + ->get();
422 +
423 + $formattedForms = [];
424 +
425 + foreach ($forms as $form) {
426 + $formattedForms[] = [
427 + 'form_id' => $form->form_id,
428 + 'title' => $form->title,
429 + ];
430 +
431 + }
432 +
433 + wp_send_json_success([
434 + 'available_components' => $formattedComponents,
435 + 'available_forms' => $formattedForms,
436 + 'api_statuses' => $apiStatuses,
437 + ]);
320 438 }
321 439 }