1: <?php
  2: 
  3:   4:   5: 
  6: class Quform_Form_Controller
  7: {
  8:       9:  10: 
 11:     protected $repository;
 12: 
 13:      14:  15: 
 16:     protected $formFactory;
 17: 
 18:      19:  20: 
 21:     protected $processor;
 22: 
 23:      24:  25: 
 26:     protected $session;
 27: 
 28:      29:  30: 
 31:     protected $uploader;
 32: 
 33:      34:  35:  36:  37: 
 38:     protected $count = 0;
 39: 
 40:      41:  42:  43:  44: 
 45:     protected $uniqueIds = array();
 46: 
 47:      48:  49:  50:  51:  52:  53: 
 54:     public function __construct(Quform_Form_Factory $formFactory, Quform_Repository $repository,
 55:                                 Quform_Form_Processor $processor, Quform_Session $session, Quform_Uploader $uploader)
 56:     {
 57:         $this->formFactory = $formFactory;
 58:         $this->repository = $repository;
 59:         $this->processor = $processor;
 60:         $this->session = $session;
 61:         $this->uploader = $uploader;
 62:     }
 63: 
 64:      65:  66:  67:  68:  69: 
 70:     public function form(array $options = array())
 71:     {
 72:         $options = wp_parse_args($options, array(
 73:             'id' => '',
 74:             'values' => '',
 75:             'content' => '',
 76:             'popup' => false,
 77:             'options' => '',
 78:             'width' => '',
 79:             'show_title' => true,
 80:             'show_description' => true
 81:         ));
 82: 
 83:         $config = $this->repository->getConfig((int) $options['id']);
 84: 
 85:         if ( ! is_array($config)) {
 86:             return;
 87:         }
 88: 
 89:         $this->count++;
 90:         $config['count'] = $this->count;
 91: 
 92:         $processingThisForm = Quform::isPostRequest() && Quform::get($_POST, 'quform_form_id') == $config['id'] && Quform::get($_POST, 'quform_count') == $this->count;
 93: 
 94:         if ($processingThisForm && Quform_Form::isValidUniqueId(Quform::get($_POST, 'quform_form_uid'))) {
 95:             $uniqueId = Quform::get($_POST, 'quform_form_uid');
 96:         } else {
 97:             $uniqueId = $this->generateUniqueId();
 98:         }
 99: 
100:         $config['uniqueId'] = $uniqueId;
101:         $this->uniqueIds[] = $uniqueId;
102: 
103:         if (is_string($options['values'])) {
104:             $options['values'] = join('&', explode('&', $options['values']));
105:         }
106: 
107:         $config['dynamicValues'] = $options['values'];
108: 
109:         $form = $this->formFactory->create($config);
110: 
111:         if ( ! ($form instanceof Quform_Form) || $form->config('trashed')) {
112:             return;
113:         }
114: 
115:         if ( ! $form->isActive()) {
116:             return do_shortcode($form->config('inactiveMessage'));
117:         }
118: 
119:         $output = '';
120: 
121:         if ($processingThisForm) {
122:             $result = $this->processor->process($form);
123: 
124:             if ($result['type'] == 'page') {
125:                 $this->uploader->saveUploadedFilesIntoSession($form);
126:                 $form->setCurrentPageById($result['page']);
127:             } else if ($result['type'] == 'success') {
128:                 $confirmation = $result['confirmation'];
129: 
130:                 switch ($confirmation['type']) {
131:                     case 'message':
132:                         
133:                         $form->setSubmitted(true);
134:                         $form->reset();
135:                         break;
136:                     case 'message-redirect-page':
137:                     case 'message-redirect-url':
138:                         
139:                         $form->setSubmitted(true);
140:                         $output .= sprintf('<meta http-equiv="refresh" content="%d;URL=\'%s\'">', esc_attr($confirmation['redirectDelay']), esc_url($confirmation['redirectUrl']));
141:                         break;
142:                     case 'redirect-page':
143:                     case 'redirect-url':
144:                         $output .= sprintf('<meta http-equiv="refresh" content="0;URL=\'%s\'">', esc_url($confirmation['redirectUrl']));
145:                         break;
146:                     case 'reload':
147:                         $output .= '<meta http-equiv="refresh" content="0">';
148:                         break;
149:                 }
150:             } else if ($result['type'] == 'error') {
151:                 
152:                 if (isset($result['page']) && $form->getCurrentPage()->getId() != $result['page']) {
153:                     $form->setCurrentPageById($result['page']);
154:                 }
155: 
156:                 
157:                 if (isset($result['error']) && is_array($result['error'])) {
158:                     if (isset($result['error']['enabled']) && is_bool($result['error']['enabled'])) {
159:                         $form->setConfig('errorEnabled', $result['error']['enabled']);
160:                     }
161: 
162:                     if (isset($result['error']['title']) && is_string($result['error']['title'])) {
163:                         $form->setConfig('errorTitle', $result['error']['title']);
164:                     }
165: 
166:                     if (isset($result['error']['content']) && is_string($result['error']['content'])) {
167:                         $form->setConfig('errorContent', $result['error']['content']);
168:                     }
169:                 }
170: 
171:                 
172:                 if ($form->config('errorEnabled')) {
173:                     $form->setShowGlobalError(true);
174:                 }
175:             }
176:         }
177: 
178:         $outputOverride = '';
179: 
180:         if (
181:             !apply_filters('quform_bypass_entry_limits', current_user_can('quform_edit_forms'), $form) &&
182:             $form->config('limitEntries') &&
183:             is_numeric($form->config('entryLimit')) &&
184:             $form->config('entryLimit') > 0
185:         ) {
186:             $entryCount = $this->repository->getEntryCount($form->getId());
187: 
188:             $entryCount = apply_filters('quform_entry_count', $entryCount, $form);
189:             $entryCount = apply_filters('quform_entry_count_' . $form->getId(), $entryCount, $form);
190: 
191:             if ($entryCount >= $form->config('entryLimit')) {
192:                 $outputOverride = do_shortcode(shortcode_unautop(wpautop($form->config('entryLimitReachedMessage'))));
193:             }
194:         }
195: 
196:         if (
197:             !apply_filters('quform_bypass_form_schedule', current_user_can('quform_edit_forms'), $form) &&
198:             $form->config('enableSchedule')
199:         ) {
200:             try {
201:                 $now = new DateTime('now', new DateTimeZone('UTC'));
202: 
203:                 if (Quform::isNonEmptyString($form->config('scheduleStart'))) {
204:                     $start = DateTime::createFromFormat('Y-m-d H:i:s', $form->config('scheduleStart'));
205: 
206:                     if ($start instanceof DateTime && $now < $start) {
207:                         $outputOverride = do_shortcode(shortcode_unautop(wpautop($form->config('scheduleStartMessage'))));
208:                     }
209:                 }
210: 
211:                 if (Quform::isNonEmptyString($form->config('scheduleEnd'))) {
212:                     $end = DateTime::createFromFormat('Y-m-d H:i:s', $form->config('scheduleEnd'));
213: 
214:                     if ($end instanceof DateTime && $now > $end) {
215:                         $outputOverride = do_shortcode(shortcode_unautop(wpautop($form->config('scheduleEndMessage'))));
216:                     }
217:                 }
218:             } catch (Exception $e) {
219:                 
220:             }
221:         }
222: 
223:         $output .= $options['popup'] ? $form->renderPopup($options, $outputOverride) : $form->render($options, $outputOverride);
224: 
225:         return $output;
226:     }
227: 
228:     229: 230: 231: 232: 233: 
234:     public function getEntryLimit($formId) {
235:         $config = $this->repository->getConfig($formId);
236: 
237:         if ( ! is_array($config)) {
238:             return '';
239:         }
240: 
241:         $form = $this->formFactory->create($config);
242: 
243:         if ( ! ($form instanceof Quform_Form) || $form->config('trashed')) {
244:             return '';
245:         }
246: 
247:         if ($form->config('limitEntries') && is_numeric($form->config('entryLimit')) && $form->config('entryLimit') > 0) {
248:             return $form->config('entryLimit');
249:         }
250: 
251:         return '∞';
252:     }
253: 
254:     255: 256: 257: 258: 259: 
260:     public function getEntryCount($formId) {
261:         $config = $this->repository->getConfig($formId);
262: 
263:         if ( ! is_array($config)) {
264:             return '';
265:         }
266: 
267:         $form = $this->formFactory->create($config);
268: 
269:         if ( ! ($form instanceof Quform_Form) || $form->config('trashed')) {
270:             return '';
271:         }
272: 
273:         $entryCount = $this->repository->getEntryCount($formId);
274: 
275:         $entryCount = apply_filters('quform_entry_count', $entryCount, $form);
276:         $entryCount = apply_filters('quform_entry_count_' . $form->getId(), $entryCount, $form);
277: 
278:         return $entryCount;
279:     }
280: 
281:     282: 283: 284: 285: 286: 
287:     public function getEntriesRemaining($formId) {
288:         $config = $this->repository->getConfig($formId);
289: 
290:         if ( ! is_array($config)) {
291:             return '';
292:         }
293: 
294:         $form = $this->formFactory->create($config);
295: 
296:         if ( ! ($form instanceof Quform_Form) || $form->config('trashed')) {
297:             return '';
298:         }
299: 
300:         if ($form->config('limitEntries') && is_numeric($form->config('entryLimit')) && $form->config('entryLimit') > 0) {
301:             $entryCount = $this->repository->getEntryCount($formId);
302: 
303:             $entryCount = apply_filters('quform_entry_count', $entryCount, $form);
304:             $entryCount = apply_filters('quform_entry_count_' . $form->getId(), $entryCount, $form);
305: 
306:             $entryLimit = (int) $form->config('entryLimit');
307: 
308:             return $entryCount < $entryLimit ? $entryLimit - $entryCount : 0;
309:         }
310: 
311:         return '∞';
312:     }
313: 
314:     315: 316: 
317:     public function process()
318:     {
319:         if ( ! Quform::isPostRequest() || ! isset($_POST['quform_ajax'])) {
320:             return;
321:         }
322: 
323:         $this->validateProcessRequest();
324:         $this->handleProcessRequest();
325:     }
326: 
327:     328: 329: 
330:     protected function validateProcessRequest()
331:     {
332:         if ( ! isset($_POST['quform_form_id'], $_POST['quform_form_uid']) ||
333:              ! is_numeric($_POST['quform_form_id']) ||
334:              ! Quform_Form::isValidUniqueId($_POST['quform_form_uid'])
335:         ) {
336:             $this->sendEncodedResponse(array(
337:                 'type' => 'error',
338:                 'error' => array(
339:                     'enabled' => true,
340:                     'title' => __('An error occurred', 'quform'),
341:                     'content' => __('Bad request', 'quform')
342:                 )
343:             ));
344:         }
345:     }
346: 
347:     348: 349: 
350:     protected function handleProcessRequest()
351:     {
352:         $config = $this->repository->getConfig((int) $_POST['quform_form_id']);
353: 
354:         if ( ! is_array($config)) {
355:             $this->sendEncodedResponse(array(
356:                 'type' => 'error',
357:                 'error' => array(
358:                     'enabled' => true,
359:                     'title' => __('An error occurred', 'quform'),
360:                     'content' => __('Form not found', 'quform')
361:                 )
362:             ));
363:         }
364: 
365:         $config['uniqueId'] = $_POST['quform_form_uid'];
366: 
367:         $form = $this->formFactory->create($config);
368: 
369:         if ( ! ($form instanceof Quform_Form) || $form->config('trashed')) {
370:             $this->sendEncodedResponse(array(
371:                 'type' => 'error',
372:                 'error' => array(
373:                     'enabled' => true,
374:                     'title' => __('An error occurred', 'quform'),
375:                     'content' => __('Form does not exist', 'quform')
376:                 )
377:             ));
378:         }
379: 
380:         if ( ! $form->isActive()) {
381:             $this->sendEncodedResponse(array(
382:                 'type' => 'error',
383:                 'error' => array(
384:                     'enabled' => true,
385:                     'title' => __('An error occurred', 'quform'),
386:                     'content' => __('Form is not active', 'quform')
387:                 )
388:             ));
389:         }
390: 
391:         $this->sendEncodedResponse($this->processor->process($form));
392:     }
393: 
394:     395: 396: 397: 398: 
399:     protected function generateUniqueId()
400:     {
401:         $uniqueId = Quform_Form::generateUniqueId();
402: 
403:         while (in_array($uniqueId, $this->uniqueIds) || $this->session->has(sprintf('quform-%s', $uniqueId))) {
404:             $uniqueId = Quform_Form::generateUniqueId();
405:         }
406: 
407:         return $uniqueId;
408:     }
409: 
410:     411: 412: 
413:     public function supportPageCaching()
414:     {
415:         $this->validateSupportPageCachingRequest();
416:         $this->handleSupportPageCachingRequest();
417:     }
418: 
419:     420: 421: 
422:     protected function validateSupportPageCachingRequest()
423:     {
424:         if ( ! isset($_GET['forms']) || ! is_array($_GET['forms'])) {
425:             wp_send_json(array('type' => 'error'));
426:         }
427:     }
428: 
429:     430: 431: 
432:     protected function handleSupportPageCachingRequest()
433:     {
434:         $forms = array();
435: 
436:         foreach ($_GET['forms'] as $oldUniqueId) {
437:             $forms[$oldUniqueId] = $this->generateUniqueId();
438:         }
439: 
440:         wp_send_json(array(
441:             'type' => 'success',
442:             'token' => $this->session->getToken(),
443:             'forms' => $forms
444:         ));
445:     }
446: 
447:     448: 449: 450: 451: 452: 453: 454: 455: 
456:     protected function sendEncodedResponse($response)
457:     {
458:         if ( ! headers_sent()) {
459:             header('Content-Type: text/html; charset=' . get_option('blog_charset'));
460:         }
461: 
462:         echo '<textarea>' . Quform::escape(wp_json_encode($response)) . '</textarea>';
463: 
464:         
465:         call_user_func(apply_filters('wp_die_ajax_handler', '_ajax_wp_die_handler'), '');
466:     }
467: }
468: