1: <?php
2:
3: 4: 5:
6: class Quform_Form_Processor
7: {
8: 9: 10:
11: protected $repository;
12:
13: 14: 15:
16: protected $session;
17:
18: 19: 20:
21: protected $uploader;
22:
23: 24: 25:
26: protected $options;
27:
28: 29: 30: 31: 32: 33:
34: public function __construct(
35: Quform_Repository $repository,
36: Quform_Session $session,
37: Quform_Uploader $uploader,
38: Quform_Options $options
39: ) {
40: $this->repository = $repository;
41: $this->session = $session;
42: $this->uploader = $uploader;
43: $this->options = $options;
44: }
45:
46: 47: 48: 49: 50: 51:
52: public function process(Quform_Form $form)
53: {
54:
55: $_POST = wp_unslash($_POST);
56:
57:
58: if ($this->options->get('csrfProtection') && ( ! isset($_POST['quform_csrf_token']) || $this->session->getToken() != $_POST['quform_csrf_token'])) {
59: return apply_filters(
60: 'quform_csrf_failure_response',
61: array(
62: 'type' => 'error',
63: 'error' => array(
64: 'enabled' => true,
65: 'title' => __('An error occurred', 'quform'),
66: 'content' => __('Refresh the page and try again.', 'quform')
67: )
68: ),
69: $form
70: );
71: }
72:
73:
74: $result = apply_filters('quform_pre_process', array(), $form);
75: $result = apply_filters('quform_pre_process_' . $form->getId(), $result, $form);
76:
77: if (is_array($result) && ! empty($result)) {
78: return $result;
79: }
80:
81: $result = $this->checkEntryLimits( $form);
82:
83: if (is_array($result) && ! empty($result)) {
84: return $result;
85: }
86:
87: $result = $this->checkFormSchedule( $form);
88:
89: if (is_array($result) && ! empty($result)) {
90: return $result;
91: }
92:
93: $this->uploader->mergeSessionFiles($form);
94:
95:
96: $form->setValues($_POST, true);
97:
98: $result = apply_filters('quform_post_set_form_values', array(), $form);
99: $result = apply_filters('quform_post_set_form_values_' . $form->getId(), $result, $form);
100:
101: if (is_array($result) && ! empty($result)) {
102: return $result;
103: }
104:
105:
106: $form->calculateElementVisibility();
107:
108: $form->setCurrentPageById((int) $_POST['quform_current_page_id']);
109:
110:
111: $result = apply_filters('quform_pre_validate', array(), $form);
112: $result = apply_filters('quform_pre_validate_' . $form->getId(), $result, $form);
113:
114: if (is_array($result) && ! empty($result)) {
115: return $result;
116: }
117:
118:
119: if ($form->hasPages()) {
120: if (isset($_POST['quform_submit']) && $_POST['quform_submit'] === 'back') {
121:
122: return array('type' => 'page', 'page' => $form->getNextPageId(true));
123: } else {
124:
125: if (($nextPageId = $form->getNextPageId()) !== null) {
126: if ($form->getCurrentPage()->isValid()) {
127: return array('type' => 'page', 'page' => $nextPageId);
128: } else {
129:
130: return array('type' => 'error', 'error' => $form->getGlobalError(), 'errors' => $form->getCurrentPage()->getErrors(), 'page' => $form->getCurrentPage()->getId());
131: }
132: }
133: }
134: }
135:
136:
137: list($valid, $firstErrorPage) = $form->isValid();
138:
139: if ($valid) {
140:
141: $result = apply_filters('quform_post_validate', array(), $form);
142: $result = apply_filters('quform_post_validate_' . $form->getId(), $result, $form);
143:
144: if (is_array($result) && ! empty($result)) {
145: return $result;
146: }
147:
148:
149: $entryId = $this->saveEntry($form);
150: $form->setEntryId($entryId);
151:
152: $result = apply_filters('quform_post_set_entry_id', array(), $form);
153: $result = apply_filters('quform_post_set_entry_id_' . $form->getId(), $result, $form);
154:
155: if (is_array($result) && ! empty($result)) {
156: return $result;
157: }
158:
159:
160: $this->uploader->process($form);
161:
162:
163: $this->saveEntryData($entryId, $form);
164:
165: $result = apply_filters('quform_post_save_entry_data', array(), $form);
166: $result = apply_filters('quform_post_save_entry_data_' . $form->getId(), $result, $form);
167:
168: if (is_array($result) && ! empty($result)) {
169: return $result;
170: }
171:
172:
173: $this->sendNotifications($form);
174:
175:
176: $form->setConfirmation();
177:
178:
179: $this->saveToCustomDatabase($form);
180:
181:
182: if ($this->session->has($form->getSessionKey())) {
183: $this->session->forget($form->getSessionKey());
184: }
185:
186:
187: $result = apply_filters('quform_post_process', array(), $form);
188: $result = apply_filters('quform_post_process_' . $form->getId(), $result, $form);
189:
190: if (is_array($result) && ! empty($result)) {
191: return $result;
192: }
193:
194: $result = array(
195: 'type' => 'success',
196: 'confirmation' => $form->getConfirmation()->getData()
197: );
198: } else {
199: $result = array(
200: 'type' => 'error',
201: 'error' => $form->getGlobalError(),
202: 'errors' => $form->getErrors(),
203: 'page' => $firstErrorPage->getId()
204: );
205: }
206:
207: return $result;
208: }
209:
210: 211: 212: 213: 214: 215:
216: protected function checkEntryLimits(Quform_Form $form) {
217: if ( ! $this->options->get('saveEntries') || ! $form->config('saveEntry')) {
218: return true;
219: }
220:
221: if (apply_filters('quform_bypass_entry_limits', current_user_can('quform_edit_forms'), $form)) {
222: return true;
223: }
224:
225: if ($form->config('oneEntryPerUser')) {
226: $entryExists = false;
227:
228: if ($form->config('oneEntryPer') == 'logged-in-user') {
229: if (is_user_logged_in()) {
230: $entryExists = $this->repository->entryExistsByFormIdAndCreatedBy(
231: $form->getId(),
232: get_current_user_id()
233: );
234: }
235: } elseif ($form->config('oneEntryPer') == 'ip-address') {
236: $entryExists = $this->repository->entryExistsByFormIdAndIpAddress(
237: $form->getId(),
238: Quform::getClientIp()
239: );
240: }
241:
242: $entryExists = apply_filters('quform_one_entry_per_user_entry_exists', $entryExists, $form);
243:
244: if ($entryExists) {
245: return apply_filters('quform_one_entry_per_user_error', array(
246: 'type' => 'error',
247: 'error' => array(
248: 'enabled' => true,
249: 'title' => '',
250: 'content' => $form->getTranslation(
251: 'onlyOneSubmissionAllowed',
252: __('Only one submission is allowed.', 'quform')
253: )
254: )
255: ), $form);
256: }
257: }
258:
259: if ($form->config('limitEntries') && is_numeric($form->config('entryLimit')) && $form->config('entryLimit') > 0) {
260: $entryCount = $this->repository->getEntryCount($form->getId());
261:
262: $entryCount = apply_filters('quform_entry_count', $entryCount, $form);
263: $entryCount = apply_filters('quform_entry_count_' . $form->getId(), $entryCount, $form);
264:
265: if ($entryCount >= $form->config('entryLimit')) {
266: return apply_filters('quform_entry_limit_reached_error', array(
267: 'type' => 'error',
268: 'error' => array(
269: 'enabled' => true,
270: 'title' => '',
271: 'content' => $form->getTranslation(
272: 'thisFormIsCurrentlyClosed',
273: __('This form is currently closed for submissions.', 'quform')
274: )
275: )
276: ), $form);
277: }
278: }
279:
280: return true;
281: }
282:
283: 284: 285: 286: 287: 288:
289: public function checkFormSchedule(Quform_Form $form)
290: {
291: if (
292: ! $form->config('enableSchedule') ||
293: (
294: ! Quform::isNonEmptyString('scheduleStart') &&
295: ! Quform::isNonEmptyString('scheduleEnd')
296: )
297: ) {
298: return true;
299: }
300:
301: if (apply_filters('quform_bypass_form_schedule', current_user_can('quform_edit_forms'), $form)) {
302: return true;
303: }
304:
305: try {
306: $now = new DateTime('now', new DateTimeZone('UTC'));
307:
308: if (Quform::isNonEmptyString($form->config('scheduleStart'))) {
309: $start = DateTime::createFromFormat('Y-m-d H:i:s', $form->config('scheduleStart'));
310:
311: if ($start instanceof DateTime && $now < $start) {
312: return apply_filters('quform_schedule_start_error', array(
313: 'type' => 'error',
314: 'error' => array(
315: 'enabled' => true,
316: 'title' => '',
317: 'content' => $form->getTranslation(
318: 'formIsNotYetOpenForSubmissions',
319: __('This form is not yet open for submissions.', 'quform')
320: )
321: )
322: ), $form);
323: }
324: }
325:
326: if (Quform::isNonEmptyString($form->config('scheduleEnd'))) {
327: $end = DateTime::createFromFormat('Y-m-d H:i:s', $form->config('scheduleEnd'));
328:
329: if ($end instanceof DateTime && $now > $end) {
330: return apply_filters('quform_schedule_end_error', array(
331: 'type' => 'error',
332: 'error' => array(
333: 'enabled' => true,
334: 'title' => '',
335: 'content' => $form->getTranslation(
336: 'formIsNoLongerOpenForSubmissions',
337: __('This form is no longer open for submissions.', 'quform')
338: )
339: )
340: ), $form);
341: }
342: }
343: } catch (Exception $e) {
344:
345: }
346:
347: return true;
348: }
349:
350: 351: 352: 353:
354: protected function sendNotifications(Quform_Form $form)
355: {
356: foreach ($form->getNotifications() as $notification) {
357: if ( ! $notification->config('enabled')) {
358: continue;
359: }
360:
361: if ($notification->config('logicEnabled') && count($notification->config('logicRules'))) {
362: if ($form->checkLogicAction($notification->config('logicAction'), $notification->config('logicMatch'), $notification->config('logicRules'))) {
363: $notification->send();
364: }
365: } else {
366: $notification->send();
367: }
368: }
369:
370: return $this;
371: }
372:
373: 374: 375: 376: 377: 378:
379: protected function saveEntry(Quform_Form $form)
380: {
381: if ( ! $this->options->get('saveEntries') || ! $form->config('saveEntry')) {
382: return null;
383: }
384:
385: $currentTime = Quform::date('Y-m-d H:i:s', null, new DateTimeZone('UTC'));
386:
387: $entry = array(
388: 'form_id' => $form->getId(),
389: 'ip' => $this->options->get('saveIpAddresses') ? Quform::substr(Quform::getClientIp(), 0, 45) : '',
390: 'form_url' => isset($_POST['form_url']) ? Quform::substr($_POST['form_url'], 0, 512) : '',
391: 'referring_url' => isset($_POST['referring_url']) ? Quform::substr($_POST['referring_url'], 0, 512) : '',
392: 'post_id' => is_numeric($postId = Quform::get($_POST, 'post_id')) && $postId > 0 ? (int) $postId : null,
393: 'created_by' => is_user_logged_in() ? (int) Quform::getUserProperty('ID') : null,
394: 'created_at' => $currentTime,
395: 'updated_at' => $currentTime,
396: );
397:
398: $entry = $this->repository->saveEntry($entry);
399:
400: return $entry['id'];
401: }
402:
403: 404: 405: 406: 407: 408:
409: protected function saveEntryData($entryId, Quform_Form $form)
410: {
411: if ( ! ($entryId > 0) || ! $this->options->get('saveEntries') || ! $form->config('saveEntry')) {
412: return;
413: }
414:
415: $data = array();
416:
417: foreach ($form->getRecursiveIterator() as $element) {
418: if ($element->config('saveToDatabase') && ! $element->isConditionallyHidden()) {
419: if ( ! $element->isEmpty()) {
420: $data[$element->getId()] = $element->getValueForStorage();
421: }
422: }
423: }
424:
425: if (count($data)) {
426: $this->repository->saveEntryData($entryId, $data);
427: }
428: }
429:
430: 431: 432: 433: 434:
435: protected function saveToCustomDatabase(Quform_Form $form)
436: {
437: if ( ! $form->config('databaseEnabled') ||
438: ! count($columns = $form->config('databaseColumns')) ||
439: ! Quform::isNonEmptyString($table = $form->config('databaseTable'))
440: ) {
441: return;
442: }
443:
444: $data = array();
445: foreach ($columns as $column) {
446: if ( ! Quform::isNonEmptyString($column['name'])) {
447: continue;
448: }
449:
450: $data[$column['name']] = $form->replaceVariables($column['value']);
451: }
452:
453: if ($form->config('databaseWordpress')) {
454: global $wpdb;
455: $wpdb->insert($table, $data);
456: } else {
457: $customWpdb = new wpdb(
458: $form->config('databaseUsername'),
459: $form->config('databasePassword'),
460: $form->config('databaseDatabase'),
461: $form->config('databaseHost')
462: );
463:
464: $customWpdb->insert($table, $data);
465: }
466: }
467: }
468: