Completed
Branch FET/11400/gutenberg-block-mana... (713a0a)
by
unknown
45:29 queued 32:15
created
core/libraries/form_sections/form_handlers/FormHandler.php 1 patch
Indentation   +643 added lines, -643 removed lines patch added patch discarded remove patch
@@ -15,7 +15,7 @@  discard block
 block discarded – undo
15 15
 use EventEspresso\core\exceptions\InvalidFormSubmissionException;
16 16
 
17 17
 if (! defined('EVENT_ESPRESSO_VERSION')) {
18
-    exit('No direct script access allowed');
18
+	exit('No direct script access allowed');
19 19
 }
20 20
 
21 21
 
@@ -34,648 +34,648 @@  discard block
 block discarded – undo
34 34
 abstract class FormHandler implements FormHandlerInterface
35 35
 {
36 36
 
37
-    /**
38
-     * will add opening and closing HTML form tags as well as a submit button
39
-     */
40
-    const ADD_FORM_TAGS_AND_SUBMIT = 'add_form_tags_and_submit';
41
-
42
-    /**
43
-     * will add opening and closing HTML form tags but NOT a submit button
44
-     */
45
-    const ADD_FORM_TAGS_ONLY = 'add_form_tags_only';
46
-
47
-    /**
48
-     * will NOT add opening and closing HTML form tags but will add a submit button
49
-     */
50
-    const ADD_FORM_SUBMIT_ONLY = 'add_form_submit_only';
51
-
52
-    /**
53
-     * will NOT add opening and closing HTML form tags NOR a submit button
54
-     */
55
-    const DO_NOT_SETUP_FORM = 'do_not_setup_form';
56
-
57
-    /**
58
-     * if set to false, then this form has no displayable content,
59
-     * and will only be used for processing data sent passed via GET or POST
60
-     * defaults to true ( ie: form has displayable content )
61
-     *
62
-     * @var boolean $displayable
63
-     */
64
-    private $displayable = true;
65
-
66
-    /**
67
-     * @var string $form_name
68
-     */
69
-    private $form_name;
70
-
71
-    /**
72
-     * @var string $admin_name
73
-     */
74
-    private $admin_name;
75
-
76
-    /**
77
-     * @var string $slug
78
-     */
79
-    private $slug;
80
-
81
-    /**
82
-     * @var string $submit_btn_text
83
-     */
84
-    private $submit_btn_text;
85
-
86
-    /**
87
-     * @var string $form_action
88
-     */
89
-    private $form_action;
90
-
91
-    /**
92
-     * form params in key value pairs
93
-     * can be added to form action URL or as hidden inputs
94
-     *
95
-     * @var array $form_args
96
-     */
97
-    private $form_args = array();
98
-
99
-    /**
100
-     * value of one of the string constant above
101
-     *
102
-     * @var string $form_config
103
-     */
104
-    private $form_config;
105
-
106
-    /**
107
-     * whether or not the form was determined to be invalid
108
-     *
109
-     * @var boolean $form_has_errors
110
-     */
111
-    private $form_has_errors;
112
-
113
-    /**
114
-     * the absolute top level form section being used on the page
115
-     *
116
-     * @var EE_Form_Section_Proper $form
117
-     */
118
-    private $form;
119
-
120
-    /**
121
-     * @var EE_Registry $registry
122
-     */
123
-    protected $registry;
124
-
125
-
126
-
127
-    /**
128
-     * Form constructor.
129
-     *
130
-     * @param string      $form_name
131
-     * @param string      $admin_name
132
-     * @param string      $slug
133
-     * @param string      $form_action
134
-     * @param string      $form_config
135
-     * @param EE_Registry $registry
136
-     * @throws InvalidDataTypeException
137
-     * @throws DomainException
138
-     * @throws InvalidArgumentException
139
-     */
140
-    public function __construct(
141
-        $form_name,
142
-        $admin_name,
143
-        $slug,
144
-        $form_action = '',
145
-        $form_config = FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
146
-        EE_Registry $registry
147
-    ) {
148
-        $this->setFormName($form_name);
149
-        $this->setAdminName($admin_name);
150
-        $this->setSlug($slug);
151
-        $this->setFormAction($form_action);
152
-        $this->setFormConfig($form_config);
153
-        $this->setSubmitBtnText(esc_html__('Submit', 'event_espresso'));
154
-        $this->registry = $registry;
155
-    }
156
-
157
-
158
-
159
-    /**
160
-     * @return array
161
-     */
162
-    public static function getFormConfigConstants()
163
-    {
164
-        return array(
165
-            FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
166
-            FormHandler::ADD_FORM_TAGS_ONLY,
167
-            FormHandler::ADD_FORM_SUBMIT_ONLY,
168
-            FormHandler::DO_NOT_SETUP_FORM,
169
-        );
170
-    }
171
-
172
-
173
-
174
-    /**
175
-     * @param bool $for_display
176
-     * @return EE_Form_Section_Proper
177
-     * @throws EE_Error
178
-     * @throws LogicException
179
-     */
180
-    public function form($for_display = false)
181
-    {
182
-        if (! $this->formIsValid()) {
183
-            return null;
184
-        }
185
-        if ($for_display) {
186
-            $form_config = $this->formConfig();
187
-            if (
188
-                $form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
189
-                || $form_config === FormHandler::ADD_FORM_SUBMIT_ONLY
190
-            ) {
191
-                $this->appendSubmitButton();
192
-                $this->clearFormButtonFloats();
193
-            }
194
-        }
195
-        return $this->form;
196
-    }
197
-
198
-
199
-
200
-    /**
201
-     * @return boolean
202
-     * @throws LogicException
203
-     */
204
-    public function formIsValid()
205
-    {
206
-        if ($this->form instanceof EE_Form_Section_Proper) {
207
-            return true;
208
-        }
209
-        $form = apply_filters(
210
-            'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__formIsValid__generated_form_object',
211
-            $this->generate(),
212
-            $this
213
-        );
214
-        if ($this->verifyForm($form)) {
215
-            $this->setForm($form);
216
-        }
217
-        return true;
218
-    }
219
-
220
-
221
-
222
-    /**
223
-     * @param EE_Form_Section_Proper|null $form
224
-     * @return bool
225
-     * @throws LogicException
226
-     */
227
-    public function verifyForm(EE_Form_Section_Proper $form = null)
228
-    {
229
-        $form = $form !== null ? $form : $this->form;
230
-        if ($form instanceof EE_Form_Section_Proper) {
231
-            return true;
232
-        }
233
-        throw new LogicException(
234
-            sprintf(
235
-                esc_html__('The "%1$s" form is invalid or missing. %2$s', 'event_espresso'),
236
-                $this->form_name,
237
-                var_export($form, true)
238
-            )
239
-        );
240
-    }
241
-
242
-
243
-
244
-    /**
245
-     * @param EE_Form_Section_Proper $form
246
-     */
247
-    public function setForm(EE_Form_Section_Proper $form)
248
-    {
249
-        $this->form = $form;
250
-    }
251
-
252
-
253
-
254
-    /**
255
-     * @return boolean
256
-     */
257
-    public function displayable()
258
-    {
259
-        return $this->displayable;
260
-    }
261
-
262
-
263
-
264
-    /**
265
-     * @param boolean $displayable
266
-     */
267
-    public function setDisplayable($displayable = false)
268
-    {
269
-        $this->displayable = filter_var($displayable, FILTER_VALIDATE_BOOLEAN);
270
-    }
271
-
272
-
273
-
274
-    /**
275
-     * a public name for the form that can be displayed on the frontend of a site
276
-     *
277
-     * @return string
278
-     */
279
-    public function formName()
280
-    {
281
-        return $this->form_name;
282
-    }
283
-
284
-
285
-
286
-    /**
287
-     * @param string $form_name
288
-     * @throws InvalidDataTypeException
289
-     */
290
-    public function setFormName($form_name)
291
-    {
292
-        if (! is_string($form_name)) {
293
-            throw new InvalidDataTypeException('$form_name', $form_name, 'string');
294
-        }
295
-        $this->form_name = $form_name;
296
-    }
297
-
298
-
299
-
300
-    /**
301
-     * a public name for the form that can be displayed, but only in the admin
302
-     *
303
-     * @return string
304
-     */
305
-    public function adminName()
306
-    {
307
-        return $this->admin_name;
308
-    }
309
-
310
-
311
-
312
-    /**
313
-     * @param string $admin_name
314
-     * @throws InvalidDataTypeException
315
-     */
316
-    public function setAdminName($admin_name)
317
-    {
318
-        if (! is_string($admin_name)) {
319
-            throw new InvalidDataTypeException('$admin_name', $admin_name, 'string');
320
-        }
321
-        $this->admin_name = $admin_name;
322
-    }
323
-
324
-
325
-
326
-    /**
327
-     * a URL friendly string that can be used for identifying the form
328
-     *
329
-     * @return string
330
-     */
331
-    public function slug()
332
-    {
333
-        return $this->slug;
334
-    }
335
-
336
-
337
-
338
-    /**
339
-     * @param string $slug
340
-     * @throws InvalidDataTypeException
341
-     */
342
-    public function setSlug($slug)
343
-    {
344
-        if (! is_string($slug)) {
345
-            throw new InvalidDataTypeException('$slug', $slug, 'string');
346
-        }
347
-        $this->slug = $slug;
348
-    }
349
-
350
-
351
-
352
-    /**
353
-     * @return string
354
-     */
355
-    public function submitBtnText()
356
-    {
357
-        return $this->submit_btn_text;
358
-    }
359
-
360
-
361
-
362
-    /**
363
-     * @param string $submit_btn_text
364
-     * @throws InvalidDataTypeException
365
-     * @throws InvalidArgumentException
366
-     */
367
-    public function setSubmitBtnText($submit_btn_text)
368
-    {
369
-        if (! is_string($submit_btn_text)) {
370
-            throw new InvalidDataTypeException('$submit_btn_text', $submit_btn_text, 'string');
371
-        }
372
-        if (empty($submit_btn_text)) {
373
-            throw new InvalidArgumentException(
374
-                esc_html__('Can not set Submit button text because an empty string was provided.', 'event_espresso')
375
-            );
376
-        }
377
-        $this->submit_btn_text = $submit_btn_text;
378
-    }
379
-
380
-
381
-
382
-    /**
383
-     * @return string
384
-     */
385
-    public function formAction()
386
-    {
387
-        return ! empty($this->form_args)
388
-            ? add_query_arg($this->form_args, $this->form_action)
389
-            : $this->form_action;
390
-    }
391
-
392
-
393
-
394
-    /**
395
-     * @param string $form_action
396
-     * @throws InvalidDataTypeException
397
-     */
398
-    public function setFormAction($form_action)
399
-    {
400
-        if (! is_string($form_action)) {
401
-            throw new InvalidDataTypeException('$form_action', $form_action, 'string');
402
-        }
403
-        $this->form_action = $form_action;
404
-    }
405
-
406
-
407
-
408
-    /**
409
-     * @param array $form_args
410
-     * @throws InvalidDataTypeException
411
-     * @throws InvalidArgumentException
412
-     */
413
-    public function addFormActionArgs($form_args = array())
414
-    {
415
-        if (is_object($form_args)) {
416
-            throw new InvalidDataTypeException(
417
-                '$form_args',
418
-                $form_args,
419
-                'anything other than an object was expected.'
420
-            );
421
-        }
422
-        if (empty($form_args)) {
423
-            throw new InvalidArgumentException(
424
-                esc_html__('The redirect arguments can not be an empty array.', 'event_espresso')
425
-            );
426
-        }
427
-        $this->form_args = array_merge($this->form_args, $form_args);
428
-    }
429
-
430
-
431
-
432
-    /**
433
-     * @return string
434
-     */
435
-    public function formConfig()
436
-    {
437
-        return $this->form_config;
438
-    }
439
-
440
-
441
-
442
-    /**
443
-     * @param string $form_config
444
-     * @throws DomainException
445
-     */
446
-    public function setFormConfig($form_config)
447
-    {
448
-        if (
449
-        ! in_array(
450
-            $form_config,
451
-            array(
452
-                FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
453
-                FormHandler::ADD_FORM_TAGS_ONLY,
454
-                FormHandler::ADD_FORM_SUBMIT_ONLY,
455
-                FormHandler::DO_NOT_SETUP_FORM,
456
-            ),
457
-            true
458
-        )
459
-        ) {
460
-            throw new DomainException(
461
-                sprintf(
462
-                    esc_html__('"%1$s" is not a valid value for the form config. Please use one of the class constants on \EventEspresso\core\libraries\form_sections\form_handlers\Form',
463
-                        'event_espresso'),
464
-                    $form_config
465
-                )
466
-            );
467
-        }
468
-        $this->form_config = $form_config;
469
-    }
470
-
471
-
472
-
473
-    /**
474
-     * called after the form is instantiated
475
-     * and used for performing any logic that needs to occur early
476
-     * before any of the other methods are called.
477
-     * returns true if everything is ok to proceed,
478
-     * and false if no further form logic should be implemented
479
-     *
480
-     * @return boolean
481
-     */
482
-    public function initialize()
483
-    {
484
-        $this->form_has_errors = EE_Error::has_error(true);
485
-        return true;
486
-    }
487
-
488
-
489
-
490
-    /**
491
-     * used for setting up css and js
492
-     *
493
-     * @return void
494
-     * @throws LogicException
495
-     * @throws EE_Error
496
-     */
497
-    public function enqueueStylesAndScripts()
498
-    {
499
-        $this->form()->enqueue_js();
500
-    }
501
-
502
-
503
-
504
-    /**
505
-     * creates and returns the actual form
506
-     *
507
-     * @return EE_Form_Section_Proper
508
-     */
509
-    abstract public function generate();
510
-
511
-
512
-
513
-    /**
514
-     * creates and returns an EE_Submit_Input labeled "Submit"
515
-     *
516
-     * @param string $text
517
-     * @return EE_Submit_Input
518
-     */
519
-    public function generateSubmitButton($text = '')
520
-    {
521
-        $text = ! empty($text) ? $text : $this->submitBtnText();
522
-        return new EE_Submit_Input(
523
-            array(
524
-                'html_name'             => 'ee-form-submit-' . $this->slug(),
525
-                'html_id'               => 'ee-form-submit-' . $this->slug(),
526
-                'html_class'            => 'ee-form-submit',
527
-                'html_label'            => ' ',
528
-                'other_html_attributes' => ' rel="' . $this->slug() . '"',
529
-                'default'               => $text,
530
-            )
531
-        );
532
-    }
533
-
534
-
535
-
536
-    /**
537
-     * calls generateSubmitButton() and appends it onto the form along with a float clearing div
538
-     *
539
-     * @param string $text
540
-     * @return void
541
-     * @throws EE_Error
542
-     */
543
-    public function appendSubmitButton($text = '')
544
-    {
545
-        if ($this->form->subsection_exists($this->slug() . '-submit-btn')) {
546
-            return;
547
-        }
548
-        $this->form->add_subsections(
549
-            array($this->slug() . '-submit-btn' => $this->generateSubmitButton($text)),
550
-            null,
551
-            false
552
-        );
553
-    }
554
-
555
-
556
-
557
-    /**
558
-     * creates and returns an EE_Submit_Input labeled "Cancel"
559
-     *
560
-     * @param string $text
561
-     * @return EE_Submit_Input
562
-     */
563
-    public function generateCancelButton($text = '')
564
-    {
565
-        $cancel_button = new EE_Submit_Input(
566
-            array(
567
-                'html_name'             => 'ee-form-submit-' . $this->slug(), // YES! Same name as submit !!!
568
-                'html_id'               => 'ee-cancel-form-' . $this->slug(),
569
-                'html_class'            => 'ee-cancel-form',
570
-                'html_label'            => ' ',
571
-                'other_html_attributes' => ' rel="' . $this->slug() . '"',
572
-                'default'               => ! empty($text) ? $text : esc_html__('Cancel', 'event_espresso'),
573
-            )
574
-        );
575
-        $cancel_button->set_button_css_attributes(false);
576
-        return $cancel_button;
577
-    }
578
-
579
-
580
-
581
-    /**
582
-     * appends a float clearing div onto end of form
583
-     *
584
-     * @return void
585
-     * @throws EE_Error
586
-     */
587
-    public function clearFormButtonFloats()
588
-    {
589
-        $this->form->add_subsections(
590
-            array(
591
-                'clear-submit-btn-float' => new EE_Form_Section_HTML(
592
-                    EEH_HTML::div('', '', 'clear-float') . EEH_HTML::divx()
593
-                ),
594
-            ),
595
-            null,
596
-            false
597
-        );
598
-    }
599
-
600
-
601
-    /**
602
-     * takes the generated form and displays it along with ony other non-form HTML that may be required
603
-     * returns a string of HTML that can be directly echoed in a template
604
-     *
605
-     * @return string
606
-     * @throws \InvalidArgumentException
607
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
608
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
609
-     * @throws LogicException
610
-     * @throws EE_Error
611
-     */
612
-    public function display()
613
-    {
614
-        $form_html = apply_filters(
615
-            'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__display__before_form',
616
-            ''
617
-        );
618
-        $form_config = $this->formConfig();
619
-        if (
620
-            $form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
621
-            || $form_config === FormHandler::ADD_FORM_TAGS_ONLY
622
-        ) {
623
-            $form_html .= $this->form()->form_open($this->formAction());
624
-        }
625
-        $form_html .= $this->form(true)->get_html($this->form_has_errors);
626
-        if (
627
-            $form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
628
-            || $form_config === FormHandler::ADD_FORM_TAGS_ONLY
629
-        ) {
630
-            $form_html .= $this->form()->form_close();
631
-        }
632
-        $form_html .= apply_filters(
633
-            'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__display__after_form',
634
-            ''
635
-        );
636
-        return $form_html;
637
-    }
638
-
639
-
640
-    /**
641
-     * handles processing the form submission
642
-     * returns true or false depending on whether the form was processed successfully or not
643
-     *
644
-     * @param array $submitted_form_data
645
-     * @return array
646
-     * @throws \InvalidArgumentException
647
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
648
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
649
-     * @throws EE_Error
650
-     * @throws LogicException
651
-     * @throws InvalidFormSubmissionException
652
-     */
653
-    public function process($submitted_form_data = array())
654
-    {
655
-        if (! $this->form()->was_submitted($submitted_form_data)) {
656
-            throw new InvalidFormSubmissionException($this->form_name);
657
-        }
658
-        $this->form(true)->receive_form_submission($submitted_form_data);
659
-        if (! $this->form()->is_valid()) {
660
-            throw new InvalidFormSubmissionException(
661
-                $this->form_name,
662
-                sprintf(
663
-                    esc_html__(
664
-                        'The "%1$s" form is invalid. Please correct the following errors and resubmit: %2$s %3$s',
665
-                        'event_espresso'
666
-                    ),
667
-                    $this->form_name,
668
-                    '<br />',
669
-                    implode('<br />', $this->form()->get_validation_errors_accumulated())
670
-                )
671
-            );
672
-        }
673
-        return apply_filters(
674
-            'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__process__valid_data',
675
-            $this->form()->valid_data(),
676
-            $this
677
-        );
678
-    }
37
+	/**
38
+	 * will add opening and closing HTML form tags as well as a submit button
39
+	 */
40
+	const ADD_FORM_TAGS_AND_SUBMIT = 'add_form_tags_and_submit';
41
+
42
+	/**
43
+	 * will add opening and closing HTML form tags but NOT a submit button
44
+	 */
45
+	const ADD_FORM_TAGS_ONLY = 'add_form_tags_only';
46
+
47
+	/**
48
+	 * will NOT add opening and closing HTML form tags but will add a submit button
49
+	 */
50
+	const ADD_FORM_SUBMIT_ONLY = 'add_form_submit_only';
51
+
52
+	/**
53
+	 * will NOT add opening and closing HTML form tags NOR a submit button
54
+	 */
55
+	const DO_NOT_SETUP_FORM = 'do_not_setup_form';
56
+
57
+	/**
58
+	 * if set to false, then this form has no displayable content,
59
+	 * and will only be used for processing data sent passed via GET or POST
60
+	 * defaults to true ( ie: form has displayable content )
61
+	 *
62
+	 * @var boolean $displayable
63
+	 */
64
+	private $displayable = true;
65
+
66
+	/**
67
+	 * @var string $form_name
68
+	 */
69
+	private $form_name;
70
+
71
+	/**
72
+	 * @var string $admin_name
73
+	 */
74
+	private $admin_name;
75
+
76
+	/**
77
+	 * @var string $slug
78
+	 */
79
+	private $slug;
80
+
81
+	/**
82
+	 * @var string $submit_btn_text
83
+	 */
84
+	private $submit_btn_text;
85
+
86
+	/**
87
+	 * @var string $form_action
88
+	 */
89
+	private $form_action;
90
+
91
+	/**
92
+	 * form params in key value pairs
93
+	 * can be added to form action URL or as hidden inputs
94
+	 *
95
+	 * @var array $form_args
96
+	 */
97
+	private $form_args = array();
98
+
99
+	/**
100
+	 * value of one of the string constant above
101
+	 *
102
+	 * @var string $form_config
103
+	 */
104
+	private $form_config;
105
+
106
+	/**
107
+	 * whether or not the form was determined to be invalid
108
+	 *
109
+	 * @var boolean $form_has_errors
110
+	 */
111
+	private $form_has_errors;
112
+
113
+	/**
114
+	 * the absolute top level form section being used on the page
115
+	 *
116
+	 * @var EE_Form_Section_Proper $form
117
+	 */
118
+	private $form;
119
+
120
+	/**
121
+	 * @var EE_Registry $registry
122
+	 */
123
+	protected $registry;
124
+
125
+
126
+
127
+	/**
128
+	 * Form constructor.
129
+	 *
130
+	 * @param string      $form_name
131
+	 * @param string      $admin_name
132
+	 * @param string      $slug
133
+	 * @param string      $form_action
134
+	 * @param string      $form_config
135
+	 * @param EE_Registry $registry
136
+	 * @throws InvalidDataTypeException
137
+	 * @throws DomainException
138
+	 * @throws InvalidArgumentException
139
+	 */
140
+	public function __construct(
141
+		$form_name,
142
+		$admin_name,
143
+		$slug,
144
+		$form_action = '',
145
+		$form_config = FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
146
+		EE_Registry $registry
147
+	) {
148
+		$this->setFormName($form_name);
149
+		$this->setAdminName($admin_name);
150
+		$this->setSlug($slug);
151
+		$this->setFormAction($form_action);
152
+		$this->setFormConfig($form_config);
153
+		$this->setSubmitBtnText(esc_html__('Submit', 'event_espresso'));
154
+		$this->registry = $registry;
155
+	}
156
+
157
+
158
+
159
+	/**
160
+	 * @return array
161
+	 */
162
+	public static function getFormConfigConstants()
163
+	{
164
+		return array(
165
+			FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
166
+			FormHandler::ADD_FORM_TAGS_ONLY,
167
+			FormHandler::ADD_FORM_SUBMIT_ONLY,
168
+			FormHandler::DO_NOT_SETUP_FORM,
169
+		);
170
+	}
171
+
172
+
173
+
174
+	/**
175
+	 * @param bool $for_display
176
+	 * @return EE_Form_Section_Proper
177
+	 * @throws EE_Error
178
+	 * @throws LogicException
179
+	 */
180
+	public function form($for_display = false)
181
+	{
182
+		if (! $this->formIsValid()) {
183
+			return null;
184
+		}
185
+		if ($for_display) {
186
+			$form_config = $this->formConfig();
187
+			if (
188
+				$form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
189
+				|| $form_config === FormHandler::ADD_FORM_SUBMIT_ONLY
190
+			) {
191
+				$this->appendSubmitButton();
192
+				$this->clearFormButtonFloats();
193
+			}
194
+		}
195
+		return $this->form;
196
+	}
197
+
198
+
199
+
200
+	/**
201
+	 * @return boolean
202
+	 * @throws LogicException
203
+	 */
204
+	public function formIsValid()
205
+	{
206
+		if ($this->form instanceof EE_Form_Section_Proper) {
207
+			return true;
208
+		}
209
+		$form = apply_filters(
210
+			'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__formIsValid__generated_form_object',
211
+			$this->generate(),
212
+			$this
213
+		);
214
+		if ($this->verifyForm($form)) {
215
+			$this->setForm($form);
216
+		}
217
+		return true;
218
+	}
219
+
220
+
221
+
222
+	/**
223
+	 * @param EE_Form_Section_Proper|null $form
224
+	 * @return bool
225
+	 * @throws LogicException
226
+	 */
227
+	public function verifyForm(EE_Form_Section_Proper $form = null)
228
+	{
229
+		$form = $form !== null ? $form : $this->form;
230
+		if ($form instanceof EE_Form_Section_Proper) {
231
+			return true;
232
+		}
233
+		throw new LogicException(
234
+			sprintf(
235
+				esc_html__('The "%1$s" form is invalid or missing. %2$s', 'event_espresso'),
236
+				$this->form_name,
237
+				var_export($form, true)
238
+			)
239
+		);
240
+	}
241
+
242
+
243
+
244
+	/**
245
+	 * @param EE_Form_Section_Proper $form
246
+	 */
247
+	public function setForm(EE_Form_Section_Proper $form)
248
+	{
249
+		$this->form = $form;
250
+	}
251
+
252
+
253
+
254
+	/**
255
+	 * @return boolean
256
+	 */
257
+	public function displayable()
258
+	{
259
+		return $this->displayable;
260
+	}
261
+
262
+
263
+
264
+	/**
265
+	 * @param boolean $displayable
266
+	 */
267
+	public function setDisplayable($displayable = false)
268
+	{
269
+		$this->displayable = filter_var($displayable, FILTER_VALIDATE_BOOLEAN);
270
+	}
271
+
272
+
273
+
274
+	/**
275
+	 * a public name for the form that can be displayed on the frontend of a site
276
+	 *
277
+	 * @return string
278
+	 */
279
+	public function formName()
280
+	{
281
+		return $this->form_name;
282
+	}
283
+
284
+
285
+
286
+	/**
287
+	 * @param string $form_name
288
+	 * @throws InvalidDataTypeException
289
+	 */
290
+	public function setFormName($form_name)
291
+	{
292
+		if (! is_string($form_name)) {
293
+			throw new InvalidDataTypeException('$form_name', $form_name, 'string');
294
+		}
295
+		$this->form_name = $form_name;
296
+	}
297
+
298
+
299
+
300
+	/**
301
+	 * a public name for the form that can be displayed, but only in the admin
302
+	 *
303
+	 * @return string
304
+	 */
305
+	public function adminName()
306
+	{
307
+		return $this->admin_name;
308
+	}
309
+
310
+
311
+
312
+	/**
313
+	 * @param string $admin_name
314
+	 * @throws InvalidDataTypeException
315
+	 */
316
+	public function setAdminName($admin_name)
317
+	{
318
+		if (! is_string($admin_name)) {
319
+			throw new InvalidDataTypeException('$admin_name', $admin_name, 'string');
320
+		}
321
+		$this->admin_name = $admin_name;
322
+	}
323
+
324
+
325
+
326
+	/**
327
+	 * a URL friendly string that can be used for identifying the form
328
+	 *
329
+	 * @return string
330
+	 */
331
+	public function slug()
332
+	{
333
+		return $this->slug;
334
+	}
335
+
336
+
337
+
338
+	/**
339
+	 * @param string $slug
340
+	 * @throws InvalidDataTypeException
341
+	 */
342
+	public function setSlug($slug)
343
+	{
344
+		if (! is_string($slug)) {
345
+			throw new InvalidDataTypeException('$slug', $slug, 'string');
346
+		}
347
+		$this->slug = $slug;
348
+	}
349
+
350
+
351
+
352
+	/**
353
+	 * @return string
354
+	 */
355
+	public function submitBtnText()
356
+	{
357
+		return $this->submit_btn_text;
358
+	}
359
+
360
+
361
+
362
+	/**
363
+	 * @param string $submit_btn_text
364
+	 * @throws InvalidDataTypeException
365
+	 * @throws InvalidArgumentException
366
+	 */
367
+	public function setSubmitBtnText($submit_btn_text)
368
+	{
369
+		if (! is_string($submit_btn_text)) {
370
+			throw new InvalidDataTypeException('$submit_btn_text', $submit_btn_text, 'string');
371
+		}
372
+		if (empty($submit_btn_text)) {
373
+			throw new InvalidArgumentException(
374
+				esc_html__('Can not set Submit button text because an empty string was provided.', 'event_espresso')
375
+			);
376
+		}
377
+		$this->submit_btn_text = $submit_btn_text;
378
+	}
379
+
380
+
381
+
382
+	/**
383
+	 * @return string
384
+	 */
385
+	public function formAction()
386
+	{
387
+		return ! empty($this->form_args)
388
+			? add_query_arg($this->form_args, $this->form_action)
389
+			: $this->form_action;
390
+	}
391
+
392
+
393
+
394
+	/**
395
+	 * @param string $form_action
396
+	 * @throws InvalidDataTypeException
397
+	 */
398
+	public function setFormAction($form_action)
399
+	{
400
+		if (! is_string($form_action)) {
401
+			throw new InvalidDataTypeException('$form_action', $form_action, 'string');
402
+		}
403
+		$this->form_action = $form_action;
404
+	}
405
+
406
+
407
+
408
+	/**
409
+	 * @param array $form_args
410
+	 * @throws InvalidDataTypeException
411
+	 * @throws InvalidArgumentException
412
+	 */
413
+	public function addFormActionArgs($form_args = array())
414
+	{
415
+		if (is_object($form_args)) {
416
+			throw new InvalidDataTypeException(
417
+				'$form_args',
418
+				$form_args,
419
+				'anything other than an object was expected.'
420
+			);
421
+		}
422
+		if (empty($form_args)) {
423
+			throw new InvalidArgumentException(
424
+				esc_html__('The redirect arguments can not be an empty array.', 'event_espresso')
425
+			);
426
+		}
427
+		$this->form_args = array_merge($this->form_args, $form_args);
428
+	}
429
+
430
+
431
+
432
+	/**
433
+	 * @return string
434
+	 */
435
+	public function formConfig()
436
+	{
437
+		return $this->form_config;
438
+	}
439
+
440
+
441
+
442
+	/**
443
+	 * @param string $form_config
444
+	 * @throws DomainException
445
+	 */
446
+	public function setFormConfig($form_config)
447
+	{
448
+		if (
449
+		! in_array(
450
+			$form_config,
451
+			array(
452
+				FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
453
+				FormHandler::ADD_FORM_TAGS_ONLY,
454
+				FormHandler::ADD_FORM_SUBMIT_ONLY,
455
+				FormHandler::DO_NOT_SETUP_FORM,
456
+			),
457
+			true
458
+		)
459
+		) {
460
+			throw new DomainException(
461
+				sprintf(
462
+					esc_html__('"%1$s" is not a valid value for the form config. Please use one of the class constants on \EventEspresso\core\libraries\form_sections\form_handlers\Form',
463
+						'event_espresso'),
464
+					$form_config
465
+				)
466
+			);
467
+		}
468
+		$this->form_config = $form_config;
469
+	}
470
+
471
+
472
+
473
+	/**
474
+	 * called after the form is instantiated
475
+	 * and used for performing any logic that needs to occur early
476
+	 * before any of the other methods are called.
477
+	 * returns true if everything is ok to proceed,
478
+	 * and false if no further form logic should be implemented
479
+	 *
480
+	 * @return boolean
481
+	 */
482
+	public function initialize()
483
+	{
484
+		$this->form_has_errors = EE_Error::has_error(true);
485
+		return true;
486
+	}
487
+
488
+
489
+
490
+	/**
491
+	 * used for setting up css and js
492
+	 *
493
+	 * @return void
494
+	 * @throws LogicException
495
+	 * @throws EE_Error
496
+	 */
497
+	public function enqueueStylesAndScripts()
498
+	{
499
+		$this->form()->enqueue_js();
500
+	}
501
+
502
+
503
+
504
+	/**
505
+	 * creates and returns the actual form
506
+	 *
507
+	 * @return EE_Form_Section_Proper
508
+	 */
509
+	abstract public function generate();
510
+
511
+
512
+
513
+	/**
514
+	 * creates and returns an EE_Submit_Input labeled "Submit"
515
+	 *
516
+	 * @param string $text
517
+	 * @return EE_Submit_Input
518
+	 */
519
+	public function generateSubmitButton($text = '')
520
+	{
521
+		$text = ! empty($text) ? $text : $this->submitBtnText();
522
+		return new EE_Submit_Input(
523
+			array(
524
+				'html_name'             => 'ee-form-submit-' . $this->slug(),
525
+				'html_id'               => 'ee-form-submit-' . $this->slug(),
526
+				'html_class'            => 'ee-form-submit',
527
+				'html_label'            => '&nbsp;',
528
+				'other_html_attributes' => ' rel="' . $this->slug() . '"',
529
+				'default'               => $text,
530
+			)
531
+		);
532
+	}
533
+
534
+
535
+
536
+	/**
537
+	 * calls generateSubmitButton() and appends it onto the form along with a float clearing div
538
+	 *
539
+	 * @param string $text
540
+	 * @return void
541
+	 * @throws EE_Error
542
+	 */
543
+	public function appendSubmitButton($text = '')
544
+	{
545
+		if ($this->form->subsection_exists($this->slug() . '-submit-btn')) {
546
+			return;
547
+		}
548
+		$this->form->add_subsections(
549
+			array($this->slug() . '-submit-btn' => $this->generateSubmitButton($text)),
550
+			null,
551
+			false
552
+		);
553
+	}
554
+
555
+
556
+
557
+	/**
558
+	 * creates and returns an EE_Submit_Input labeled "Cancel"
559
+	 *
560
+	 * @param string $text
561
+	 * @return EE_Submit_Input
562
+	 */
563
+	public function generateCancelButton($text = '')
564
+	{
565
+		$cancel_button = new EE_Submit_Input(
566
+			array(
567
+				'html_name'             => 'ee-form-submit-' . $this->slug(), // YES! Same name as submit !!!
568
+				'html_id'               => 'ee-cancel-form-' . $this->slug(),
569
+				'html_class'            => 'ee-cancel-form',
570
+				'html_label'            => '&nbsp;',
571
+				'other_html_attributes' => ' rel="' . $this->slug() . '"',
572
+				'default'               => ! empty($text) ? $text : esc_html__('Cancel', 'event_espresso'),
573
+			)
574
+		);
575
+		$cancel_button->set_button_css_attributes(false);
576
+		return $cancel_button;
577
+	}
578
+
579
+
580
+
581
+	/**
582
+	 * appends a float clearing div onto end of form
583
+	 *
584
+	 * @return void
585
+	 * @throws EE_Error
586
+	 */
587
+	public function clearFormButtonFloats()
588
+	{
589
+		$this->form->add_subsections(
590
+			array(
591
+				'clear-submit-btn-float' => new EE_Form_Section_HTML(
592
+					EEH_HTML::div('', '', 'clear-float') . EEH_HTML::divx()
593
+				),
594
+			),
595
+			null,
596
+			false
597
+		);
598
+	}
599
+
600
+
601
+	/**
602
+	 * takes the generated form and displays it along with ony other non-form HTML that may be required
603
+	 * returns a string of HTML that can be directly echoed in a template
604
+	 *
605
+	 * @return string
606
+	 * @throws \InvalidArgumentException
607
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
608
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
609
+	 * @throws LogicException
610
+	 * @throws EE_Error
611
+	 */
612
+	public function display()
613
+	{
614
+		$form_html = apply_filters(
615
+			'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__display__before_form',
616
+			''
617
+		);
618
+		$form_config = $this->formConfig();
619
+		if (
620
+			$form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
621
+			|| $form_config === FormHandler::ADD_FORM_TAGS_ONLY
622
+		) {
623
+			$form_html .= $this->form()->form_open($this->formAction());
624
+		}
625
+		$form_html .= $this->form(true)->get_html($this->form_has_errors);
626
+		if (
627
+			$form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
628
+			|| $form_config === FormHandler::ADD_FORM_TAGS_ONLY
629
+		) {
630
+			$form_html .= $this->form()->form_close();
631
+		}
632
+		$form_html .= apply_filters(
633
+			'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__display__after_form',
634
+			''
635
+		);
636
+		return $form_html;
637
+	}
638
+
639
+
640
+	/**
641
+	 * handles processing the form submission
642
+	 * returns true or false depending on whether the form was processed successfully or not
643
+	 *
644
+	 * @param array $submitted_form_data
645
+	 * @return array
646
+	 * @throws \InvalidArgumentException
647
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
648
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
649
+	 * @throws EE_Error
650
+	 * @throws LogicException
651
+	 * @throws InvalidFormSubmissionException
652
+	 */
653
+	public function process($submitted_form_data = array())
654
+	{
655
+		if (! $this->form()->was_submitted($submitted_form_data)) {
656
+			throw new InvalidFormSubmissionException($this->form_name);
657
+		}
658
+		$this->form(true)->receive_form_submission($submitted_form_data);
659
+		if (! $this->form()->is_valid()) {
660
+			throw new InvalidFormSubmissionException(
661
+				$this->form_name,
662
+				sprintf(
663
+					esc_html__(
664
+						'The "%1$s" form is invalid. Please correct the following errors and resubmit: %2$s %3$s',
665
+						'event_espresso'
666
+					),
667
+					$this->form_name,
668
+					'<br />',
669
+					implode('<br />', $this->form()->get_validation_errors_accumulated())
670
+				)
671
+			);
672
+		}
673
+		return apply_filters(
674
+			'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__process__valid_data',
675
+			$this->form()->valid_data(),
676
+			$this
677
+		);
678
+	}
679 679
 
680 680
 
681 681
 
Please login to merge, or discard this patch.
form_sections/strategies/normalization/EE_Null_Normalization.strategy.php 2 patches
Indentation   +22 added lines, -22 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if (! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 
5 5
 
@@ -15,26 +15,26 @@  discard block
 block discarded – undo
15 15
 class EE_Null_Normalization extends EE_Normalization_Strategy_Base
16 16
 {
17 17
 
18
-    /**
19
-     * @param string $value_to_normalize
20
-     * @return null
21
-     */
22
-    public function normalize($value_to_normalize)
23
-    {
24
-        return null;
25
-    }
26
-
27
-
28
-
29
-    /**
30
-     * In the form input we need some string, so use a blank one.
31
-     *
32
-     * @param string $normalized_value
33
-     * @return string
34
-     */
35
-    public function unnormalize($normalized_value)
36
-    {
37
-        return '';
38
-    }
18
+	/**
19
+	 * @param string $value_to_normalize
20
+	 * @return null
21
+	 */
22
+	public function normalize($value_to_normalize)
23
+	{
24
+		return null;
25
+	}
26
+
27
+
28
+
29
+	/**
30
+	 * In the form input we need some string, so use a blank one.
31
+	 *
32
+	 * @param string $normalized_value
33
+	 * @return string
34
+	 */
35
+	public function unnormalize($normalized_value)
36
+	{
37
+		return '';
38
+	}
39 39
 
40 40
 }
41 41
\ No newline at end of file
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -1,4 +1,4 @@
 block discarded – undo
1
-<?php if (! defined('EVENT_ESPRESSO_VERSION')) {
1
+<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2 2
     exit('No direct script access allowed');
3 3
 }
4 4
 
Please login to merge, or discard this patch.
core/libraries/form_sections/inputs/EE_Form_Input_Base.input.php 2 patches
Indentation   +1171 added lines, -1171 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if (! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 
5 5
 
@@ -16,1174 +16,1174 @@  discard block
 block discarded – undo
16 16
 abstract class EE_Form_Input_Base extends EE_Form_Section_Validatable
17 17
 {
18 18
 
19
-    /**
20
-     * the input's name attribute
21
-     *
22
-     * @var string
23
-     */
24
-    protected $_html_name;
25
-
26
-    /**
27
-     * id for the html label tag
28
-     *
29
-     * @var string
30
-     */
31
-    protected $_html_label_id;
32
-
33
-    /**
34
-     * class for teh html label tag
35
-     *
36
-     * @var string
37
-     */
38
-    protected $_html_label_class;
39
-
40
-    /**
41
-     * any additional html attributes that you may want to add
42
-     *
43
-     * @var string
44
-     */
45
-    protected $_html_other_attributes;
46
-
47
-    /**
48
-     * style for teh html label tag
49
-     *
50
-     * @var string
51
-     */
52
-    protected $_html_label_style;
53
-
54
-    /**
55
-     * text to be placed in the html label
56
-     *
57
-     * @var string
58
-     */
59
-    protected $_html_label_text;
60
-
61
-    /**
62
-     * the full html label. If used, all other html_label_* properties are invalid
63
-     *
64
-     * @var string
65
-     */
66
-    protected $_html_label;
67
-
68
-    /**
69
-     * HTML to use for help text (normally placed below form input), in a span which normally
70
-     * has a class of 'description'
71
-     *
72
-     * @var string
73
-     */
74
-    protected $_html_help_text;
75
-
76
-    /**
77
-     * CSS classes for displaying the help span
78
-     *
79
-     * @var string
80
-     */
81
-    protected $_html_help_class = 'description';
82
-
83
-    /**
84
-     * CSS to put in the style attribute on the help span
85
-     *
86
-     * @var string
87
-     */
88
-    protected $_html_help_style;
89
-
90
-    /**
91
-     * Stores whether or not this input's response is required.
92
-     * Because certain styling elements may also want to know that this
93
-     * input is required etc.
94
-     *
95
-     * @var boolean
96
-     */
97
-    protected $_required;
98
-
99
-    /**
100
-     * css class added to required inputs
101
-     *
102
-     * @var string
103
-     */
104
-    protected $_required_css_class = 'ee-required';
105
-
106
-    /**
107
-     * css styles applied to button type inputs
108
-     *
109
-     * @var string
110
-     */
111
-    protected $_button_css_attributes;
112
-
113
-    /**
114
-     * The raw data submitted for this, like in the $_POST super global.
115
-     * Generally unsafe for usage in client code
116
-     *
117
-     * @var mixed string or array
118
-     */
119
-    protected $_raw_value;
120
-
121
-    /**
122
-     * Value normalized according to the input's normalization strategy.
123
-     * The normalization strategy dictates whether this is a string, int, float,
124
-     * boolean, or array of any of those.
125
-     *
126
-     * @var mixed
127
-     */
128
-    protected $_normalized_value;
129
-
130
-
131
-    /**
132
-     * Normalized default value either initially set on the input, or provided by calling
133
-     * set_default().
134
-     * @var mixed
135
-     */
136
-    protected $_default;
137
-
138
-    /**
139
-     * Strategy used for displaying this field.
140
-     * Child classes must use _get_display_strategy to access it.
141
-     *
142
-     * @var EE_Display_Strategy_Base
143
-     */
144
-    private $_display_strategy;
145
-
146
-    /**
147
-     * Gets all the validation strategies used on this field
148
-     *
149
-     * @var EE_Validation_Strategy_Base[]
150
-     */
151
-    private $_validation_strategies = array();
152
-
153
-    /**
154
-     * The normalization strategy for this field
155
-     *
156
-     * @var EE_Normalization_Strategy_Base
157
-     */
158
-    private $_normalization_strategy;
159
-
160
-    /**
161
-     * Strategy for removing sensitive data after we're done with the form input
162
-     *
163
-     * @var EE_Sensitive_Data_Removal_Base
164
-     */
165
-    protected $_sensitive_data_removal_strategy;
166
-
167
-
168
-
169
-    /**
170
-     * @param array                         $input_args       {
171
-     * @type string                         $html_name        the html name for the input
172
-     * @type string                         $html_label_id    the id attribute to give to the html label tag
173
-     * @type string                         $html_label_class the class attribute to give to the html label tag
174
-     * @type string                         $html_label_style the style attribute to give ot teh label tag
175
-     * @type string                         $html_label_text  the text to put in the label tag
176
-     * @type string                         $html_label       the full html label. If used,
177
-     *                                                        all other html_label_* args are invalid
178
-     * @type string                         $html_help_text   text to put in help element
179
-     * @type string                         $html_help_style  style attribute to give to teh help element
180
-     * @type string                         $html_help_class  class attribute to give to the help element
181
-     * @type string                         $default          default value NORMALIZED (eg, if providing the default
182
-     *       for a Yes_No_Input, you should provide TRUE or FALSE, not '1' or '0')
183
-     * @type EE_Display_Strategy_Base       $display          strategy
184
-     * @type EE_Normalization_Strategy_Base $normalization_strategy
185
-     * @type EE_Validation_Strategy_Base[]  $validation_strategies
186
-     * @type boolean                        $ignore_input special argument which can be used to avoid adding any validation strategies,
187
-     *                                                    and sets the normalization strategy to the Null normalization. This is good
188
-     *                                                    when you want the input to be totally ignored server-side (like when using
189
-     *                                                    React.js form inputs)
190
-     *                                                        }
191
-     */
192
-    public function __construct($input_args = array())
193
-    {
194
-        $input_args = (array)apply_filters('FHEE__EE_Form_Input_Base___construct__input_args', $input_args, $this);
195
-        // the following properties must be cast as arrays
196
-        if (isset($input_args['validation_strategies'])) {
197
-            foreach ((array)$input_args['validation_strategies'] as $validation_strategy) {
198
-                if ($validation_strategy instanceof EE_Validation_Strategy_Base && empty($input_args['ignore_input'])) {
199
-                    $this->_validation_strategies[get_class($validation_strategy)] = $validation_strategy;
200
-                }
201
-            }
202
-            unset($input_args['validation_strategies']);
203
-        }
204
-        if(isset($input_args['ignore_input'])) {
205
-            $this->_validation_strategies = array();
206
-        }
207
-        // loop thru incoming options
208
-        foreach ($input_args as $key => $value) {
209
-            // add underscore to $key to match property names
210
-            $_key = '_' . $key;
211
-            if (property_exists($this, $_key)) {
212
-                $this->{$_key} = $value;
213
-            }
214
-        }
215
-        // ensure that "required" is set correctly
216
-        $this->set_required(
217
-            $this->_required, isset($input_args['required_validation_error_message'])
218
-            ? $input_args['required_validation_error_message']
219
-            : null
220
-        );
221
-        //$this->_html_name_specified = isset( $input_args['html_name'] ) ? TRUE : FALSE;
222
-        $this->_display_strategy->_construct_finalize($this);
223
-        foreach ($this->_validation_strategies as $validation_strategy) {
224
-            $validation_strategy->_construct_finalize($this);
225
-        }
226
-        if (isset($input_args['ignore_input'])) {
227
-            $this->_normalization_strategy = new EE_Null_Normalization();
228
-        }
229
-        if (! $this->_normalization_strategy) {
230
-                $this->_normalization_strategy = new EE_Text_Normalization();
231
-        }
232
-        $this->_normalization_strategy->_construct_finalize($this);
233
-        //at least we can use the normalization strategy to populate the default
234
-        if (isset($input_args['default'])) {
235
-            $this->set_default($input_args['default']);
236
-            unset($input_args['default']);
237
-        }
238
-        if (! $this->_sensitive_data_removal_strategy) {
239
-            $this->_sensitive_data_removal_strategy = new EE_No_Sensitive_Data_Removal();
240
-        }
241
-        $this->_sensitive_data_removal_strategy->_construct_finalize($this);
242
-        parent::__construct($input_args);
243
-    }
244
-
245
-
246
-
247
-    /**
248
-     * Sets the html_name to its default value, if none was specified in teh constructor.
249
-     * Calculation involves using the name and the parent's html_name
250
-     *
251
-     * @throws \EE_Error
252
-     */
253
-    protected function _set_default_html_name_if_empty()
254
-    {
255
-        if (! $this->_html_name) {
256
-            $this->_html_name = $this->name();
257
-            if ($this->_parent_section && $this->_parent_section instanceof EE_Form_Section_Proper) {
258
-                $this->_html_name = $this->_parent_section->html_name_prefix() . "[{$this->name()}]";
259
-            }
260
-        }
261
-    }
262
-
263
-
264
-
265
-    /**
266
-     * @param $parent_form_section
267
-     * @param $name
268
-     * @throws \EE_Error
269
-     */
270
-    public function _construct_finalize($parent_form_section, $name)
271
-    {
272
-        parent::_construct_finalize($parent_form_section, $name);
273
-        if ($this->_html_label === null && $this->_html_label_text === null) {
274
-            $this->_html_label_text = ucwords(str_replace("_", " ", $name));
275
-        }
276
-        do_action('AHEE__EE_Form_Input_Base___construct_finalize__end', $this, $parent_form_section, $name);
277
-    }
278
-
279
-
280
-
281
-    /**
282
-     * Returns the strategy for displaying this form input. If none is set, throws an exception.
283
-     *
284
-     * @return EE_Display_Strategy_Base
285
-     * @throws EE_Error
286
-     */
287
-    protected function _get_display_strategy()
288
-    {
289
-        $this->ensure_construct_finalized_called();
290
-        if (! $this->_display_strategy || ! $this->_display_strategy instanceof EE_Display_Strategy_Base) {
291
-            throw new EE_Error(
292
-                sprintf(
293
-                    __(
294
-                        "Cannot get display strategy for form input with name %s and id %s, because it has not been set in the constructor",
295
-                        "event_espresso"
296
-                    ),
297
-                    $this->html_name(),
298
-                    $this->html_id()
299
-                )
300
-            );
301
-        } else {
302
-            return $this->_display_strategy;
303
-        }
304
-    }
305
-
306
-
307
-
308
-    /**
309
-     * Sets the display strategy.
310
-     *
311
-     * @param EE_Display_Strategy_Base $strategy
312
-     */
313
-    protected function _set_display_strategy(EE_Display_Strategy_Base $strategy)
314
-    {
315
-        $this->_display_strategy = $strategy;
316
-    }
317
-
318
-
319
-
320
-    /**
321
-     * Sets the sanitization strategy
322
-     *
323
-     * @param EE_Normalization_Strategy_Base $strategy
324
-     */
325
-    protected function _set_normalization_strategy(EE_Normalization_Strategy_Base $strategy)
326
-    {
327
-        $this->_normalization_strategy = $strategy;
328
-    }
329
-
330
-
331
-
332
-    /**
333
-     * Gets sensitive_data_removal_strategy
334
-     *
335
-     * @return EE_Sensitive_Data_Removal_Base
336
-     */
337
-    public function get_sensitive_data_removal_strategy()
338
-    {
339
-        return $this->_sensitive_data_removal_strategy;
340
-    }
341
-
342
-
343
-
344
-    /**
345
-     * Sets sensitive_data_removal_strategy
346
-     *
347
-     * @param EE_Sensitive_Data_Removal_Base $sensitive_data_removal_strategy
348
-     * @return boolean
349
-     */
350
-    public function set_sensitive_data_removal_strategy($sensitive_data_removal_strategy)
351
-    {
352
-        $this->_sensitive_data_removal_strategy = $sensitive_data_removal_strategy;
353
-    }
354
-
355
-
356
-
357
-    /**
358
-     * Gets the display strategy for this input
359
-     *
360
-     * @return EE_Display_Strategy_Base
361
-     */
362
-    public function get_display_strategy()
363
-    {
364
-        return $this->_display_strategy;
365
-    }
366
-
367
-
368
-
369
-    /**
370
-     * Overwrites the display strategy
371
-     *
372
-     * @param EE_Display_Strategy_Base $display_strategy
373
-     */
374
-    public function set_display_strategy($display_strategy)
375
-    {
376
-        $this->_display_strategy = $display_strategy;
377
-        $this->_display_strategy->_construct_finalize($this);
378
-    }
379
-
380
-
381
-
382
-    /**
383
-     * Gets the normalization strategy set on this input
384
-     *
385
-     * @return EE_Normalization_Strategy_Base
386
-     */
387
-    public function get_normalization_strategy()
388
-    {
389
-        return $this->_normalization_strategy;
390
-    }
391
-
392
-
393
-
394
-    /**
395
-     * Overwrites the normalization strategy
396
-     *
397
-     * @param EE_Normalization_Strategy_Base $normalization_strategy
398
-     */
399
-    public function set_normalization_strategy($normalization_strategy)
400
-    {
401
-        $this->_normalization_strategy = $normalization_strategy;
402
-        $this->_normalization_strategy->_construct_finalize($this);
403
-    }
404
-
405
-
406
-
407
-    /**
408
-     * Returns all teh validation strategies which apply to this field, numerically indexed
409
-     *
410
-     * @return EE_Validation_Strategy_Base[]
411
-     */
412
-    public function get_validation_strategies()
413
-    {
414
-        return $this->_validation_strategies;
415
-    }
416
-
417
-
418
-
419
-    /**
420
-     * Adds this strategy to the field so it will be used in both JS validation and server-side validation
421
-     *
422
-     * @param EE_Validation_Strategy_Base $validation_strategy
423
-     * @return void
424
-     */
425
-    protected function _add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
426
-    {
427
-        $validation_strategy->_construct_finalize($this);
428
-        $this->_validation_strategies[] = $validation_strategy;
429
-    }
430
-
431
-
432
-
433
-    /**
434
-     * Adds a new validation strategy onto the form input
435
-     *
436
-     * @param EE_Validation_Strategy_Base $validation_strategy
437
-     * @return void
438
-     */
439
-    public function add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
440
-    {
441
-        $this->_add_validation_strategy($validation_strategy);
442
-    }
443
-
444
-
445
-
446
-    /**
447
-     * The classname of the validation strategy to remove
448
-     *
449
-     * @param string $validation_strategy_classname
450
-     */
451
-    public function remove_validation_strategy($validation_strategy_classname)
452
-    {
453
-        foreach ($this->_validation_strategies as $key => $validation_strategy) {
454
-            if (
455
-                $validation_strategy instanceof $validation_strategy_classname
456
-                || is_subclass_of($validation_strategy, $validation_strategy_classname)
457
-            ) {
458
-                unset($this->_validation_strategies[$key]);
459
-            }
460
-        }
461
-    }
462
-
463
-
464
-
465
-    /**
466
-     * returns true if input employs any of the validation strategy defined by the supplied array of classnames
467
-     *
468
-     * @param array $validation_strategy_classnames
469
-     * @return bool
470
-     */
471
-    public function has_validation_strategy($validation_strategy_classnames)
472
-    {
473
-        $validation_strategy_classnames = is_array($validation_strategy_classnames)
474
-            ? $validation_strategy_classnames
475
-            : array($validation_strategy_classnames);
476
-        foreach ($this->_validation_strategies as $key => $validation_strategy) {
477
-            if (in_array($key, $validation_strategy_classnames)) {
478
-                return true;
479
-            }
480
-        }
481
-        return false;
482
-    }
483
-
484
-
485
-
486
-    /**
487
-     * Gets the HTML
488
-     *
489
-     * @return string
490
-     */
491
-    public function get_html()
492
-    {
493
-        return $this->_parent_section->get_html_for_input($this);
494
-    }
495
-
496
-
497
-
498
-    /**
499
-     * Gets the HTML for the input itself (no label or errors) according to the
500
-     * input's display strategy
501
-     * Makes sure the JS and CSS are enqueued for it
502
-     *
503
-     * @return string
504
-     * @throws \EE_Error
505
-     */
506
-    public function get_html_for_input()
507
-    {
508
-        return $this->_form_html_filter
509
-            ? $this->_form_html_filter->filterHtml(
510
-                $this->_get_display_strategy()->display(),
511
-                $this
512
-            )
513
-            : $this->_get_display_strategy()->display();
514
-    }
515
-
516
-
517
-
518
-    /**
519
-     * @return string
520
-     */
521
-    public function html_other_attributes()
522
-    {
523
-        return ! empty($this->_html_other_attributes) ? ' ' . $this->_html_other_attributes : '';
524
-    }
525
-
526
-
527
-
528
-    /**
529
-     * @param string $html_other_attributes
530
-     */
531
-    public function set_html_other_attributes($html_other_attributes)
532
-    {
533
-        $this->_html_other_attributes = $html_other_attributes;
534
-    }
535
-
536
-
537
-
538
-    /**
539
-     * Gets the HTML for displaying the label for this form input
540
-     * according to the form section's layout strategy
541
-     *
542
-     * @return string
543
-     */
544
-    public function get_html_for_label()
545
-    {
546
-        return $this->_parent_section->get_layout_strategy()->display_label($this);
547
-    }
548
-
549
-
550
-
551
-    /**
552
-     * Gets the HTML for displaying the errors section for this form input
553
-     * according to the form section's layout strategy
554
-     *
555
-     * @return string
556
-     */
557
-    public function get_html_for_errors()
558
-    {
559
-        return $this->_parent_section->get_layout_strategy()->display_errors($this);
560
-    }
561
-
562
-
563
-
564
-    /**
565
-     * Gets the HTML for displaying the help text for this form input
566
-     * according to the form section's layout strategy
567
-     *
568
-     * @return string
569
-     */
570
-    public function get_html_for_help()
571
-    {
572
-        return $this->_parent_section->get_layout_strategy()->display_help_text($this);
573
-    }
574
-
575
-
576
-
577
-    /**
578
-     * Validates the input's sanitized value (assumes _sanitize() has already been called)
579
-     * and returns whether or not the form input's submitted value is value
580
-     *
581
-     * @return boolean
582
-     */
583
-    protected function _validate()
584
-    {
585
-        foreach ($this->_validation_strategies as $validation_strategy) {
586
-            if ($validation_strategy instanceof EE_Validation_Strategy_Base) {
587
-                try {
588
-                    $validation_strategy->validate($this->normalized_value());
589
-                } catch (EE_Validation_Error $e) {
590
-                    $this->add_validation_error($e);
591
-                }
592
-            }
593
-        }
594
-        if ($this->get_validation_errors()) {
595
-            return false;
596
-        } else {
597
-            return true;
598
-        }
599
-    }
600
-
601
-
602
-
603
-    /**
604
-     * Performs basic sanitization on this value. But what sanitization can be performed anyways?
605
-     * This value MIGHT be allowed to have tags, so we can't really remove them.
606
-     *
607
-     * @param string $value
608
-     * @return null|string
609
-     */
610
-    private function _sanitize($value)
611
-    {
612
-        return $value !== null ? stripslashes(html_entity_decode(trim($value))) : null;
613
-    }
614
-
615
-
616
-
617
-    /**
618
-     * Picks out the form value that relates to this form input,
619
-     * and stores it as the sanitized value on the form input, and sets the normalized value.
620
-     * Returns whether or not any validation errors occurred
621
-     *
622
-     * @param array $req_data like $_POST
623
-     * @return boolean whether or not there was an error
624
-     * @throws \EE_Error
625
-     */
626
-    protected function _normalize($req_data)
627
-    {
628
-        //any existing validation errors don't apply so clear them
629
-        $this->_validation_errors = array();
630
-        try {
631
-            $raw_input = $this->find_form_data_for_this_section($req_data);
632
-            //super simple sanitization for now
633
-            if (is_array($raw_input)) {
634
-                $raw_value = array();
635
-                foreach ($raw_input as $key => $value) {
636
-                    $raw_value[$key] = $this->_sanitize($value);
637
-                }
638
-                $this->_set_raw_value($raw_value);
639
-            } else {
640
-                $this->_set_raw_value($this->_sanitize($raw_input));
641
-            }
642
-            //we want to mostly leave the input alone in case we need to re-display it to the user
643
-            $this->_set_normalized_value($this->_normalization_strategy->normalize($this->raw_value()));
644
-        } catch (EE_Validation_Error $e) {
645
-            $this->add_validation_error($e);
646
-        }
647
-    }
648
-
649
-
650
-
651
-    /**
652
-     * @return string
653
-     */
654
-    public function html_name()
655
-    {
656
-        $this->_set_default_html_name_if_empty();
657
-        return $this->_html_name;
658
-    }
659
-
660
-
661
-
662
-    /**
663
-     * @return string
664
-     */
665
-    public function html_label_id()
666
-    {
667
-        return ! empty($this->_html_label_id) ? $this->_html_label_id : $this->html_id() . '-lbl';
668
-    }
669
-
670
-
671
-
672
-    /**
673
-     * @return string
674
-     */
675
-    public function html_label_class()
676
-    {
677
-        return $this->_html_label_class;
678
-    }
679
-
680
-
681
-
682
-    /**
683
-     * @return string
684
-     */
685
-    public function html_label_style()
686
-    {
687
-        return $this->_html_label_style;
688
-    }
689
-
690
-
691
-
692
-    /**
693
-     * @return string
694
-     */
695
-    public function html_label_text()
696
-    {
697
-        return $this->_html_label_text;
698
-    }
699
-
700
-
701
-
702
-    /**
703
-     * @return string
704
-     */
705
-    public function html_help_text()
706
-    {
707
-        return $this->_html_help_text;
708
-    }
709
-
710
-
711
-
712
-    /**
713
-     * @return string
714
-     */
715
-    public function html_help_class()
716
-    {
717
-        return $this->_html_help_class;
718
-    }
719
-
720
-
721
-
722
-    /**
723
-     * @return string
724
-     */
725
-    public function html_help_style()
726
-    {
727
-        return $this->_html_style;
728
-    }
729
-
730
-
731
-
732
-    /**
733
-     * returns the raw, UNSAFE, input, almost exactly as the user submitted it.
734
-     * Please note that almost all client code should instead use the normalized_value;
735
-     * or possibly raw_value_in_form (which prepares the string for displaying in an HTML attribute on a tag,
736
-     * mostly by escaping quotes)
737
-     * Note, we do not store the exact original value sent in the user's request because
738
-     * it may have malicious content, and we MIGHT want to store the form input in a transient or something...
739
-     * in which case, we would have stored the malicious content to our database.
740
-     *
741
-     * @return string
742
-     */
743
-    public function raw_value()
744
-    {
745
-        return $this->_raw_value;
746
-    }
747
-
748
-
749
-
750
-    /**
751
-     * Returns a string safe to usage in form inputs when displaying, because
752
-     * it escapes all html entities
753
-     *
754
-     * @return string
755
-     */
756
-    public function raw_value_in_form()
757
-    {
758
-        return htmlentities($this->raw_value(), ENT_QUOTES, 'UTF-8');
759
-    }
760
-
761
-
762
-
763
-    /**
764
-     * returns the value after it's been sanitized, and then converted into it's proper type
765
-     * in PHP. Eg, a string, an int, an array,
766
-     *
767
-     * @return mixed
768
-     */
769
-    public function normalized_value()
770
-    {
771
-        return $this->_normalized_value;
772
-    }
773
-
774
-
775
-
776
-    /**
777
-     * Returns the normalized value is a presentable way. By default this is just
778
-     * the normalized value by itself, but it can be overridden for when that's not
779
-     * the best thing to display
780
-     *
781
-     * @return string
782
-     */
783
-    public function pretty_value()
784
-    {
785
-        return $this->_normalized_value;
786
-    }
787
-
788
-
789
-
790
-    /**
791
-     * When generating the JS for the jquery validation rules like<br>
792
-     * <code>$( "#myform" ).validate({
793
-     * rules: {
794
-     * password: "required",
795
-     * password_again: {
796
-     * equalTo: "#password"
797
-     * }
798
-     * }
799
-     * });</code>
800
-     * if this field had the name 'password_again', it should return
801
-     * <br><code>password_again: {
802
-     * equalTo: "#password"
803
-     * }</code>
804
-     *
805
-     * @return array
806
-     */
807
-    public function get_jquery_validation_rules()
808
-    {
809
-        $jquery_validation_js = array();
810
-        $jquery_validation_rules = array();
811
-        foreach ($this->get_validation_strategies() as $validation_strategy) {
812
-            $jquery_validation_rules = array_replace_recursive(
813
-                $jquery_validation_rules,
814
-                $validation_strategy->get_jquery_validation_rule_array()
815
-            );
816
-        }
817
-        if (! empty($jquery_validation_rules)) {
818
-            foreach ($this->get_display_strategy()->get_html_input_ids(true) as $html_id_with_pound_sign) {
819
-                $jquery_validation_js[$html_id_with_pound_sign] = $jquery_validation_rules;
820
-            }
821
-        }
822
-        return $jquery_validation_js;
823
-    }
824
-
825
-
826
-
827
-    /**
828
-     * Sets the input's default value for use in displaying in the form. Note: value should be
829
-     * normalized (Eg, if providing a default of ra Yes_NO_Input you would provide TRUE or FALSE, not '1' or '0')
830
-     *
831
-     * @param mixed $value
832
-     * @return void
833
-     */
834
-    public function set_default($value)
835
-    {
836
-        $this->_default = $value;
837
-        $this->_set_normalized_value($value);
838
-        $this->_set_raw_value($value);
839
-    }
840
-
841
-
842
-
843
-    /**
844
-     * Sets the normalized value on this input
845
-     *
846
-     * @param mixed $value
847
-     */
848
-    protected function _set_normalized_value($value)
849
-    {
850
-        $this->_normalized_value = $value;
851
-    }
852
-
853
-
854
-
855
-    /**
856
-     * Sets the raw value on this input (ie, exactly as the user submitted it)
857
-     *
858
-     * @param mixed $value
859
-     */
860
-    protected function _set_raw_value($value)
861
-    {
862
-        $this->_raw_value = $this->_normalization_strategy->unnormalize($value);
863
-    }
864
-
865
-
866
-
867
-    /**
868
-     * Sets the HTML label text after it has already been defined
869
-     *
870
-     * @param string $label
871
-     * @return void
872
-     */
873
-    public function set_html_label_text($label)
874
-    {
875
-        $this->_html_label_text = $label;
876
-    }
877
-
878
-
879
-
880
-    /**
881
-     * Sets whether or not this field is required, and adjusts the validation strategy.
882
-     * If you want to use the EE_Conditionally_Required_Validation_Strategy,
883
-     * please add it as a validation strategy using add_validation_strategy as normal
884
-     *
885
-     * @param boolean $required boolean
886
-     * @param null    $required_text
887
-     */
888
-    public function set_required($required = true, $required_text = null)
889
-    {
890
-        $required = filter_var($required, FILTER_VALIDATE_BOOLEAN);
891
-        //whether $required is a string or a boolean, we want to add a required validation strategy
892
-        if ($required) {
893
-            $this->_add_validation_strategy(new EE_Required_Validation_Strategy($required_text));
894
-        } else {
895
-            $this->remove_validation_strategy('EE_Required_Validation_Strategy');
896
-        }
897
-        $this->_required = $required;
898
-    }
899
-
900
-
901
-
902
-    /**
903
-     * Returns whether or not this field is required
904
-     *
905
-     * @return boolean
906
-     */
907
-    public function required()
908
-    {
909
-        return $this->_required;
910
-    }
911
-
912
-
913
-
914
-    /**
915
-     * @param string $required_css_class
916
-     */
917
-    public function set_required_css_class($required_css_class)
918
-    {
919
-        $this->_required_css_class = $required_css_class;
920
-    }
921
-
922
-
923
-
924
-    /**
925
-     * @return string
926
-     */
927
-    public function required_css_class()
928
-    {
929
-        return $this->_required_css_class;
930
-    }
931
-
932
-
933
-
934
-    /**
935
-     * @param bool $add_required
936
-     * @return string
937
-     */
938
-    public function html_class($add_required = false)
939
-    {
940
-        return $add_required && $this->required()
941
-            ? $this->required_css_class() . ' ' . $this->_html_class
942
-            : $this->_html_class;
943
-    }
944
-
945
-
946
-    /**
947
-     * Sets the help text, in case
948
-     *
949
-     * @param string $text
950
-     */
951
-    public function set_html_help_text($text)
952
-    {
953
-        $this->_html_help_text = $text;
954
-    }
955
-
956
-
957
-
958
-    /**
959
-     * Uses the sensitive data removal strategy to remove the sensitive data from this
960
-     * input. If there is any kind of sensitive data removal on this input, we clear
961
-     * out the raw value completely
962
-     *
963
-     * @return void
964
-     */
965
-    public function clean_sensitive_data()
966
-    {
967
-        //if we do ANY kind of sensitive data removal on this, then just clear out the raw value
968
-        //if we need more logic than this we'll make a strategy for it
969
-        if ($this->_sensitive_data_removal_strategy
970
-            && ! $this->_sensitive_data_removal_strategy instanceof EE_No_Sensitive_Data_Removal
971
-        ) {
972
-            $this->_set_raw_value(null);
973
-        }
974
-        //and clean the normalized value according to the appropriate strategy
975
-        $this->_set_normalized_value(
976
-            $this->get_sensitive_data_removal_strategy()->remove_sensitive_data(
977
-                $this->_normalized_value
978
-            )
979
-        );
980
-    }
981
-
982
-
983
-
984
-    /**
985
-     * @param bool   $primary
986
-     * @param string $button_size
987
-     * @param string $other_attributes
988
-     */
989
-    public function set_button_css_attributes($primary = true, $button_size = '', $other_attributes = '')
990
-    {
991
-        $button_css_attributes = 'button';
992
-        $button_css_attributes .= $primary === true ? ' button-primary' : ' button-secondary';
993
-        switch ($button_size) {
994
-            case 'xs' :
995
-            case 'extra-small' :
996
-                $button_css_attributes .= ' button-xs';
997
-                break;
998
-            case 'sm' :
999
-            case 'small' :
1000
-                $button_css_attributes .= ' button-sm';
1001
-                break;
1002
-            case 'lg' :
1003
-            case 'large' :
1004
-                $button_css_attributes .= ' button-lg';
1005
-                break;
1006
-            case 'block' :
1007
-                $button_css_attributes .= ' button-block';
1008
-                break;
1009
-            case 'md' :
1010
-            case 'medium' :
1011
-            default :
1012
-                $button_css_attributes .= '';
1013
-        }
1014
-        $this->_button_css_attributes .= ! empty($other_attributes)
1015
-            ? $button_css_attributes . ' ' . $other_attributes
1016
-            : $button_css_attributes;
1017
-    }
1018
-
1019
-
1020
-
1021
-    /**
1022
-     * @return string
1023
-     */
1024
-    public function button_css_attributes()
1025
-    {
1026
-        if (empty($this->_button_css_attributes)) {
1027
-            $this->set_button_css_attributes();
1028
-        }
1029
-        return $this->_button_css_attributes;
1030
-    }
1031
-
1032
-
1033
-
1034
-    /**
1035
-     * find_form_data_for_this_section
1036
-     * using this section's name and its parents, finds the value of the form data that corresponds to it.
1037
-     * For example, if this form section's HTML name is my_form[subform][form_input_1],
1038
-     * then it's value should be in $_REQUEST at $_REQUEST['my_form']['subform']['form_input_1'].
1039
-     * (If that doesn't exist, we also check for this subsection's name
1040
-     * at the TOP LEVEL of the request data. Eg $_REQUEST['form_input_1'].)
1041
-     * This function finds its value in the form.
1042
-     *
1043
-     * @param array $req_data
1044
-     * @return mixed whatever the raw value of this form section is in the request data
1045
-     * @throws \EE_Error
1046
-     */
1047
-    public function find_form_data_for_this_section($req_data)
1048
-    {
1049
-        // break up the html name by "[]"
1050
-        if (strpos($this->html_name(), '[') !== false) {
1051
-            $before_any_brackets = substr($this->html_name(), 0, strpos($this->html_name(), '['));
1052
-        } else {
1053
-            $before_any_brackets = $this->html_name();
1054
-        }
1055
-        // grab all of the segments
1056
-        preg_match_all('~\[([^]]*)\]~', $this->html_name(), $matches);
1057
-        if (isset($matches[1]) && is_array($matches[1])) {
1058
-            $name_parts = $matches[1];
1059
-            array_unshift($name_parts, $before_any_brackets);
1060
-        } else {
1061
-            $name_parts = array($before_any_brackets);
1062
-        }
1063
-        // now get the value for the input
1064
-        $value = $this->_find_form_data_for_this_section_using_name_parts($name_parts, $req_data);
1065
-        // check if this thing's name is at the TOP level of the request data
1066
-        if ($value === null && isset($req_data[$this->name()])) {
1067
-            $value = $req_data[$this->name()];
1068
-        }
1069
-        return $value;
1070
-    }
1071
-
1072
-
1073
-
1074
-    /**
1075
-     * @param array $html_name_parts
1076
-     * @param array $req_data
1077
-     * @return array | NULL
1078
-     */
1079
-    public function _find_form_data_for_this_section_using_name_parts($html_name_parts, $req_data)
1080
-    {
1081
-        $first_part_to_consider = array_shift($html_name_parts);
1082
-        if (isset($req_data[$first_part_to_consider])) {
1083
-            if (empty($html_name_parts)) {
1084
-                return $req_data[$first_part_to_consider];
1085
-            } else {
1086
-                return $this->_find_form_data_for_this_section_using_name_parts(
1087
-                    $html_name_parts,
1088
-                    $req_data[$first_part_to_consider]
1089
-                );
1090
-            }
1091
-        } else {
1092
-            return null;
1093
-        }
1094
-    }
1095
-
1096
-
1097
-
1098
-    /**
1099
-     * Checks if this form input's data is in the request data
1100
-     *
1101
-     * @param array $req_data like $_POST
1102
-     * @return boolean
1103
-     * @throws \EE_Error
1104
-     */
1105
-    public function form_data_present_in($req_data = null)
1106
-    {
1107
-        if ($req_data === null) {
1108
-            $req_data = $_POST;
1109
-        }
1110
-        $checked_value = $this->find_form_data_for_this_section($req_data);
1111
-        if ($checked_value !== null) {
1112
-            return true;
1113
-        } else {
1114
-            return false;
1115
-        }
1116
-    }
1117
-
1118
-
1119
-
1120
-    /**
1121
-     * Overrides parent to add js data from validation and display strategies
1122
-     *
1123
-     * @param array $form_other_js_data
1124
-     * @return array
1125
-     */
1126
-    public function get_other_js_data($form_other_js_data = array())
1127
-    {
1128
-        $form_other_js_data = $this->get_other_js_data_from_strategies($form_other_js_data);
1129
-        return $form_other_js_data;
1130
-    }
1131
-
1132
-
1133
-
1134
-    /**
1135
-     * Gets other JS data for localization from this input's strategies, like
1136
-     * the validation strategies and the display strategy
1137
-     *
1138
-     * @param array $form_other_js_data
1139
-     * @return array
1140
-     */
1141
-    public function get_other_js_data_from_strategies($form_other_js_data = array())
1142
-    {
1143
-        $form_other_js_data = $this->get_display_strategy()->get_other_js_data($form_other_js_data);
1144
-        foreach ($this->get_validation_strategies() as $validation_strategy) {
1145
-            $form_other_js_data = $validation_strategy->get_other_js_data($form_other_js_data);
1146
-        }
1147
-        return $form_other_js_data;
1148
-    }
1149
-
1150
-
1151
-
1152
-    /**
1153
-     * Override parent because we want to give our strategies an opportunity to enqueue some js and css
1154
-     *
1155
-     * @return void
1156
-     */
1157
-    public function enqueue_js()
1158
-    {
1159
-        //ask our display strategy and validation strategies if they have js to enqueue
1160
-        $this->enqueue_js_from_strategies();
1161
-    }
1162
-
1163
-
1164
-
1165
-    /**
1166
-     * Tells strategies when its ok to enqueue their js and css
1167
-     *
1168
-     * @return void
1169
-     */
1170
-    public function enqueue_js_from_strategies()
1171
-    {
1172
-        $this->get_display_strategy()->enqueue_js();
1173
-        foreach ($this->get_validation_strategies() as $validation_strategy) {
1174
-            $validation_strategy->enqueue_js();
1175
-        }
1176
-    }
1177
-
1178
-
1179
-
1180
-    /**
1181
-     * Gets the default value set on the input (not the current value, which may have been
1182
-     * changed because of a form submission). If no default was set, this us null.
1183
-     * @return mixed
1184
-     */
1185
-    public function get_default()
1186
-    {
1187
-        return $this->_default;
1188
-    }
19
+	/**
20
+	 * the input's name attribute
21
+	 *
22
+	 * @var string
23
+	 */
24
+	protected $_html_name;
25
+
26
+	/**
27
+	 * id for the html label tag
28
+	 *
29
+	 * @var string
30
+	 */
31
+	protected $_html_label_id;
32
+
33
+	/**
34
+	 * class for teh html label tag
35
+	 *
36
+	 * @var string
37
+	 */
38
+	protected $_html_label_class;
39
+
40
+	/**
41
+	 * any additional html attributes that you may want to add
42
+	 *
43
+	 * @var string
44
+	 */
45
+	protected $_html_other_attributes;
46
+
47
+	/**
48
+	 * style for teh html label tag
49
+	 *
50
+	 * @var string
51
+	 */
52
+	protected $_html_label_style;
53
+
54
+	/**
55
+	 * text to be placed in the html label
56
+	 *
57
+	 * @var string
58
+	 */
59
+	protected $_html_label_text;
60
+
61
+	/**
62
+	 * the full html label. If used, all other html_label_* properties are invalid
63
+	 *
64
+	 * @var string
65
+	 */
66
+	protected $_html_label;
67
+
68
+	/**
69
+	 * HTML to use for help text (normally placed below form input), in a span which normally
70
+	 * has a class of 'description'
71
+	 *
72
+	 * @var string
73
+	 */
74
+	protected $_html_help_text;
75
+
76
+	/**
77
+	 * CSS classes for displaying the help span
78
+	 *
79
+	 * @var string
80
+	 */
81
+	protected $_html_help_class = 'description';
82
+
83
+	/**
84
+	 * CSS to put in the style attribute on the help span
85
+	 *
86
+	 * @var string
87
+	 */
88
+	protected $_html_help_style;
89
+
90
+	/**
91
+	 * Stores whether or not this input's response is required.
92
+	 * Because certain styling elements may also want to know that this
93
+	 * input is required etc.
94
+	 *
95
+	 * @var boolean
96
+	 */
97
+	protected $_required;
98
+
99
+	/**
100
+	 * css class added to required inputs
101
+	 *
102
+	 * @var string
103
+	 */
104
+	protected $_required_css_class = 'ee-required';
105
+
106
+	/**
107
+	 * css styles applied to button type inputs
108
+	 *
109
+	 * @var string
110
+	 */
111
+	protected $_button_css_attributes;
112
+
113
+	/**
114
+	 * The raw data submitted for this, like in the $_POST super global.
115
+	 * Generally unsafe for usage in client code
116
+	 *
117
+	 * @var mixed string or array
118
+	 */
119
+	protected $_raw_value;
120
+
121
+	/**
122
+	 * Value normalized according to the input's normalization strategy.
123
+	 * The normalization strategy dictates whether this is a string, int, float,
124
+	 * boolean, or array of any of those.
125
+	 *
126
+	 * @var mixed
127
+	 */
128
+	protected $_normalized_value;
129
+
130
+
131
+	/**
132
+	 * Normalized default value either initially set on the input, or provided by calling
133
+	 * set_default().
134
+	 * @var mixed
135
+	 */
136
+	protected $_default;
137
+
138
+	/**
139
+	 * Strategy used for displaying this field.
140
+	 * Child classes must use _get_display_strategy to access it.
141
+	 *
142
+	 * @var EE_Display_Strategy_Base
143
+	 */
144
+	private $_display_strategy;
145
+
146
+	/**
147
+	 * Gets all the validation strategies used on this field
148
+	 *
149
+	 * @var EE_Validation_Strategy_Base[]
150
+	 */
151
+	private $_validation_strategies = array();
152
+
153
+	/**
154
+	 * The normalization strategy for this field
155
+	 *
156
+	 * @var EE_Normalization_Strategy_Base
157
+	 */
158
+	private $_normalization_strategy;
159
+
160
+	/**
161
+	 * Strategy for removing sensitive data after we're done with the form input
162
+	 *
163
+	 * @var EE_Sensitive_Data_Removal_Base
164
+	 */
165
+	protected $_sensitive_data_removal_strategy;
166
+
167
+
168
+
169
+	/**
170
+	 * @param array                         $input_args       {
171
+	 * @type string                         $html_name        the html name for the input
172
+	 * @type string                         $html_label_id    the id attribute to give to the html label tag
173
+	 * @type string                         $html_label_class the class attribute to give to the html label tag
174
+	 * @type string                         $html_label_style the style attribute to give ot teh label tag
175
+	 * @type string                         $html_label_text  the text to put in the label tag
176
+	 * @type string                         $html_label       the full html label. If used,
177
+	 *                                                        all other html_label_* args are invalid
178
+	 * @type string                         $html_help_text   text to put in help element
179
+	 * @type string                         $html_help_style  style attribute to give to teh help element
180
+	 * @type string                         $html_help_class  class attribute to give to the help element
181
+	 * @type string                         $default          default value NORMALIZED (eg, if providing the default
182
+	 *       for a Yes_No_Input, you should provide TRUE or FALSE, not '1' or '0')
183
+	 * @type EE_Display_Strategy_Base       $display          strategy
184
+	 * @type EE_Normalization_Strategy_Base $normalization_strategy
185
+	 * @type EE_Validation_Strategy_Base[]  $validation_strategies
186
+	 * @type boolean                        $ignore_input special argument which can be used to avoid adding any validation strategies,
187
+	 *                                                    and sets the normalization strategy to the Null normalization. This is good
188
+	 *                                                    when you want the input to be totally ignored server-side (like when using
189
+	 *                                                    React.js form inputs)
190
+	 *                                                        }
191
+	 */
192
+	public function __construct($input_args = array())
193
+	{
194
+		$input_args = (array)apply_filters('FHEE__EE_Form_Input_Base___construct__input_args', $input_args, $this);
195
+		// the following properties must be cast as arrays
196
+		if (isset($input_args['validation_strategies'])) {
197
+			foreach ((array)$input_args['validation_strategies'] as $validation_strategy) {
198
+				if ($validation_strategy instanceof EE_Validation_Strategy_Base && empty($input_args['ignore_input'])) {
199
+					$this->_validation_strategies[get_class($validation_strategy)] = $validation_strategy;
200
+				}
201
+			}
202
+			unset($input_args['validation_strategies']);
203
+		}
204
+		if(isset($input_args['ignore_input'])) {
205
+			$this->_validation_strategies = array();
206
+		}
207
+		// loop thru incoming options
208
+		foreach ($input_args as $key => $value) {
209
+			// add underscore to $key to match property names
210
+			$_key = '_' . $key;
211
+			if (property_exists($this, $_key)) {
212
+				$this->{$_key} = $value;
213
+			}
214
+		}
215
+		// ensure that "required" is set correctly
216
+		$this->set_required(
217
+			$this->_required, isset($input_args['required_validation_error_message'])
218
+			? $input_args['required_validation_error_message']
219
+			: null
220
+		);
221
+		//$this->_html_name_specified = isset( $input_args['html_name'] ) ? TRUE : FALSE;
222
+		$this->_display_strategy->_construct_finalize($this);
223
+		foreach ($this->_validation_strategies as $validation_strategy) {
224
+			$validation_strategy->_construct_finalize($this);
225
+		}
226
+		if (isset($input_args['ignore_input'])) {
227
+			$this->_normalization_strategy = new EE_Null_Normalization();
228
+		}
229
+		if (! $this->_normalization_strategy) {
230
+				$this->_normalization_strategy = new EE_Text_Normalization();
231
+		}
232
+		$this->_normalization_strategy->_construct_finalize($this);
233
+		//at least we can use the normalization strategy to populate the default
234
+		if (isset($input_args['default'])) {
235
+			$this->set_default($input_args['default']);
236
+			unset($input_args['default']);
237
+		}
238
+		if (! $this->_sensitive_data_removal_strategy) {
239
+			$this->_sensitive_data_removal_strategy = new EE_No_Sensitive_Data_Removal();
240
+		}
241
+		$this->_sensitive_data_removal_strategy->_construct_finalize($this);
242
+		parent::__construct($input_args);
243
+	}
244
+
245
+
246
+
247
+	/**
248
+	 * Sets the html_name to its default value, if none was specified in teh constructor.
249
+	 * Calculation involves using the name and the parent's html_name
250
+	 *
251
+	 * @throws \EE_Error
252
+	 */
253
+	protected function _set_default_html_name_if_empty()
254
+	{
255
+		if (! $this->_html_name) {
256
+			$this->_html_name = $this->name();
257
+			if ($this->_parent_section && $this->_parent_section instanceof EE_Form_Section_Proper) {
258
+				$this->_html_name = $this->_parent_section->html_name_prefix() . "[{$this->name()}]";
259
+			}
260
+		}
261
+	}
262
+
263
+
264
+
265
+	/**
266
+	 * @param $parent_form_section
267
+	 * @param $name
268
+	 * @throws \EE_Error
269
+	 */
270
+	public function _construct_finalize($parent_form_section, $name)
271
+	{
272
+		parent::_construct_finalize($parent_form_section, $name);
273
+		if ($this->_html_label === null && $this->_html_label_text === null) {
274
+			$this->_html_label_text = ucwords(str_replace("_", " ", $name));
275
+		}
276
+		do_action('AHEE__EE_Form_Input_Base___construct_finalize__end', $this, $parent_form_section, $name);
277
+	}
278
+
279
+
280
+
281
+	/**
282
+	 * Returns the strategy for displaying this form input. If none is set, throws an exception.
283
+	 *
284
+	 * @return EE_Display_Strategy_Base
285
+	 * @throws EE_Error
286
+	 */
287
+	protected function _get_display_strategy()
288
+	{
289
+		$this->ensure_construct_finalized_called();
290
+		if (! $this->_display_strategy || ! $this->_display_strategy instanceof EE_Display_Strategy_Base) {
291
+			throw new EE_Error(
292
+				sprintf(
293
+					__(
294
+						"Cannot get display strategy for form input with name %s and id %s, because it has not been set in the constructor",
295
+						"event_espresso"
296
+					),
297
+					$this->html_name(),
298
+					$this->html_id()
299
+				)
300
+			);
301
+		} else {
302
+			return $this->_display_strategy;
303
+		}
304
+	}
305
+
306
+
307
+
308
+	/**
309
+	 * Sets the display strategy.
310
+	 *
311
+	 * @param EE_Display_Strategy_Base $strategy
312
+	 */
313
+	protected function _set_display_strategy(EE_Display_Strategy_Base $strategy)
314
+	{
315
+		$this->_display_strategy = $strategy;
316
+	}
317
+
318
+
319
+
320
+	/**
321
+	 * Sets the sanitization strategy
322
+	 *
323
+	 * @param EE_Normalization_Strategy_Base $strategy
324
+	 */
325
+	protected function _set_normalization_strategy(EE_Normalization_Strategy_Base $strategy)
326
+	{
327
+		$this->_normalization_strategy = $strategy;
328
+	}
329
+
330
+
331
+
332
+	/**
333
+	 * Gets sensitive_data_removal_strategy
334
+	 *
335
+	 * @return EE_Sensitive_Data_Removal_Base
336
+	 */
337
+	public function get_sensitive_data_removal_strategy()
338
+	{
339
+		return $this->_sensitive_data_removal_strategy;
340
+	}
341
+
342
+
343
+
344
+	/**
345
+	 * Sets sensitive_data_removal_strategy
346
+	 *
347
+	 * @param EE_Sensitive_Data_Removal_Base $sensitive_data_removal_strategy
348
+	 * @return boolean
349
+	 */
350
+	public function set_sensitive_data_removal_strategy($sensitive_data_removal_strategy)
351
+	{
352
+		$this->_sensitive_data_removal_strategy = $sensitive_data_removal_strategy;
353
+	}
354
+
355
+
356
+
357
+	/**
358
+	 * Gets the display strategy for this input
359
+	 *
360
+	 * @return EE_Display_Strategy_Base
361
+	 */
362
+	public function get_display_strategy()
363
+	{
364
+		return $this->_display_strategy;
365
+	}
366
+
367
+
368
+
369
+	/**
370
+	 * Overwrites the display strategy
371
+	 *
372
+	 * @param EE_Display_Strategy_Base $display_strategy
373
+	 */
374
+	public function set_display_strategy($display_strategy)
375
+	{
376
+		$this->_display_strategy = $display_strategy;
377
+		$this->_display_strategy->_construct_finalize($this);
378
+	}
379
+
380
+
381
+
382
+	/**
383
+	 * Gets the normalization strategy set on this input
384
+	 *
385
+	 * @return EE_Normalization_Strategy_Base
386
+	 */
387
+	public function get_normalization_strategy()
388
+	{
389
+		return $this->_normalization_strategy;
390
+	}
391
+
392
+
393
+
394
+	/**
395
+	 * Overwrites the normalization strategy
396
+	 *
397
+	 * @param EE_Normalization_Strategy_Base $normalization_strategy
398
+	 */
399
+	public function set_normalization_strategy($normalization_strategy)
400
+	{
401
+		$this->_normalization_strategy = $normalization_strategy;
402
+		$this->_normalization_strategy->_construct_finalize($this);
403
+	}
404
+
405
+
406
+
407
+	/**
408
+	 * Returns all teh validation strategies which apply to this field, numerically indexed
409
+	 *
410
+	 * @return EE_Validation_Strategy_Base[]
411
+	 */
412
+	public function get_validation_strategies()
413
+	{
414
+		return $this->_validation_strategies;
415
+	}
416
+
417
+
418
+
419
+	/**
420
+	 * Adds this strategy to the field so it will be used in both JS validation and server-side validation
421
+	 *
422
+	 * @param EE_Validation_Strategy_Base $validation_strategy
423
+	 * @return void
424
+	 */
425
+	protected function _add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
426
+	{
427
+		$validation_strategy->_construct_finalize($this);
428
+		$this->_validation_strategies[] = $validation_strategy;
429
+	}
430
+
431
+
432
+
433
+	/**
434
+	 * Adds a new validation strategy onto the form input
435
+	 *
436
+	 * @param EE_Validation_Strategy_Base $validation_strategy
437
+	 * @return void
438
+	 */
439
+	public function add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
440
+	{
441
+		$this->_add_validation_strategy($validation_strategy);
442
+	}
443
+
444
+
445
+
446
+	/**
447
+	 * The classname of the validation strategy to remove
448
+	 *
449
+	 * @param string $validation_strategy_classname
450
+	 */
451
+	public function remove_validation_strategy($validation_strategy_classname)
452
+	{
453
+		foreach ($this->_validation_strategies as $key => $validation_strategy) {
454
+			if (
455
+				$validation_strategy instanceof $validation_strategy_classname
456
+				|| is_subclass_of($validation_strategy, $validation_strategy_classname)
457
+			) {
458
+				unset($this->_validation_strategies[$key]);
459
+			}
460
+		}
461
+	}
462
+
463
+
464
+
465
+	/**
466
+	 * returns true if input employs any of the validation strategy defined by the supplied array of classnames
467
+	 *
468
+	 * @param array $validation_strategy_classnames
469
+	 * @return bool
470
+	 */
471
+	public function has_validation_strategy($validation_strategy_classnames)
472
+	{
473
+		$validation_strategy_classnames = is_array($validation_strategy_classnames)
474
+			? $validation_strategy_classnames
475
+			: array($validation_strategy_classnames);
476
+		foreach ($this->_validation_strategies as $key => $validation_strategy) {
477
+			if (in_array($key, $validation_strategy_classnames)) {
478
+				return true;
479
+			}
480
+		}
481
+		return false;
482
+	}
483
+
484
+
485
+
486
+	/**
487
+	 * Gets the HTML
488
+	 *
489
+	 * @return string
490
+	 */
491
+	public function get_html()
492
+	{
493
+		return $this->_parent_section->get_html_for_input($this);
494
+	}
495
+
496
+
497
+
498
+	/**
499
+	 * Gets the HTML for the input itself (no label or errors) according to the
500
+	 * input's display strategy
501
+	 * Makes sure the JS and CSS are enqueued for it
502
+	 *
503
+	 * @return string
504
+	 * @throws \EE_Error
505
+	 */
506
+	public function get_html_for_input()
507
+	{
508
+		return $this->_form_html_filter
509
+			? $this->_form_html_filter->filterHtml(
510
+				$this->_get_display_strategy()->display(),
511
+				$this
512
+			)
513
+			: $this->_get_display_strategy()->display();
514
+	}
515
+
516
+
517
+
518
+	/**
519
+	 * @return string
520
+	 */
521
+	public function html_other_attributes()
522
+	{
523
+		return ! empty($this->_html_other_attributes) ? ' ' . $this->_html_other_attributes : '';
524
+	}
525
+
526
+
527
+
528
+	/**
529
+	 * @param string $html_other_attributes
530
+	 */
531
+	public function set_html_other_attributes($html_other_attributes)
532
+	{
533
+		$this->_html_other_attributes = $html_other_attributes;
534
+	}
535
+
536
+
537
+
538
+	/**
539
+	 * Gets the HTML for displaying the label for this form input
540
+	 * according to the form section's layout strategy
541
+	 *
542
+	 * @return string
543
+	 */
544
+	public function get_html_for_label()
545
+	{
546
+		return $this->_parent_section->get_layout_strategy()->display_label($this);
547
+	}
548
+
549
+
550
+
551
+	/**
552
+	 * Gets the HTML for displaying the errors section for this form input
553
+	 * according to the form section's layout strategy
554
+	 *
555
+	 * @return string
556
+	 */
557
+	public function get_html_for_errors()
558
+	{
559
+		return $this->_parent_section->get_layout_strategy()->display_errors($this);
560
+	}
561
+
562
+
563
+
564
+	/**
565
+	 * Gets the HTML for displaying the help text for this form input
566
+	 * according to the form section's layout strategy
567
+	 *
568
+	 * @return string
569
+	 */
570
+	public function get_html_for_help()
571
+	{
572
+		return $this->_parent_section->get_layout_strategy()->display_help_text($this);
573
+	}
574
+
575
+
576
+
577
+	/**
578
+	 * Validates the input's sanitized value (assumes _sanitize() has already been called)
579
+	 * and returns whether or not the form input's submitted value is value
580
+	 *
581
+	 * @return boolean
582
+	 */
583
+	protected function _validate()
584
+	{
585
+		foreach ($this->_validation_strategies as $validation_strategy) {
586
+			if ($validation_strategy instanceof EE_Validation_Strategy_Base) {
587
+				try {
588
+					$validation_strategy->validate($this->normalized_value());
589
+				} catch (EE_Validation_Error $e) {
590
+					$this->add_validation_error($e);
591
+				}
592
+			}
593
+		}
594
+		if ($this->get_validation_errors()) {
595
+			return false;
596
+		} else {
597
+			return true;
598
+		}
599
+	}
600
+
601
+
602
+
603
+	/**
604
+	 * Performs basic sanitization on this value. But what sanitization can be performed anyways?
605
+	 * This value MIGHT be allowed to have tags, so we can't really remove them.
606
+	 *
607
+	 * @param string $value
608
+	 * @return null|string
609
+	 */
610
+	private function _sanitize($value)
611
+	{
612
+		return $value !== null ? stripslashes(html_entity_decode(trim($value))) : null;
613
+	}
614
+
615
+
616
+
617
+	/**
618
+	 * Picks out the form value that relates to this form input,
619
+	 * and stores it as the sanitized value on the form input, and sets the normalized value.
620
+	 * Returns whether or not any validation errors occurred
621
+	 *
622
+	 * @param array $req_data like $_POST
623
+	 * @return boolean whether or not there was an error
624
+	 * @throws \EE_Error
625
+	 */
626
+	protected function _normalize($req_data)
627
+	{
628
+		//any existing validation errors don't apply so clear them
629
+		$this->_validation_errors = array();
630
+		try {
631
+			$raw_input = $this->find_form_data_for_this_section($req_data);
632
+			//super simple sanitization for now
633
+			if (is_array($raw_input)) {
634
+				$raw_value = array();
635
+				foreach ($raw_input as $key => $value) {
636
+					$raw_value[$key] = $this->_sanitize($value);
637
+				}
638
+				$this->_set_raw_value($raw_value);
639
+			} else {
640
+				$this->_set_raw_value($this->_sanitize($raw_input));
641
+			}
642
+			//we want to mostly leave the input alone in case we need to re-display it to the user
643
+			$this->_set_normalized_value($this->_normalization_strategy->normalize($this->raw_value()));
644
+		} catch (EE_Validation_Error $e) {
645
+			$this->add_validation_error($e);
646
+		}
647
+	}
648
+
649
+
650
+
651
+	/**
652
+	 * @return string
653
+	 */
654
+	public function html_name()
655
+	{
656
+		$this->_set_default_html_name_if_empty();
657
+		return $this->_html_name;
658
+	}
659
+
660
+
661
+
662
+	/**
663
+	 * @return string
664
+	 */
665
+	public function html_label_id()
666
+	{
667
+		return ! empty($this->_html_label_id) ? $this->_html_label_id : $this->html_id() . '-lbl';
668
+	}
669
+
670
+
671
+
672
+	/**
673
+	 * @return string
674
+	 */
675
+	public function html_label_class()
676
+	{
677
+		return $this->_html_label_class;
678
+	}
679
+
680
+
681
+
682
+	/**
683
+	 * @return string
684
+	 */
685
+	public function html_label_style()
686
+	{
687
+		return $this->_html_label_style;
688
+	}
689
+
690
+
691
+
692
+	/**
693
+	 * @return string
694
+	 */
695
+	public function html_label_text()
696
+	{
697
+		return $this->_html_label_text;
698
+	}
699
+
700
+
701
+
702
+	/**
703
+	 * @return string
704
+	 */
705
+	public function html_help_text()
706
+	{
707
+		return $this->_html_help_text;
708
+	}
709
+
710
+
711
+
712
+	/**
713
+	 * @return string
714
+	 */
715
+	public function html_help_class()
716
+	{
717
+		return $this->_html_help_class;
718
+	}
719
+
720
+
721
+
722
+	/**
723
+	 * @return string
724
+	 */
725
+	public function html_help_style()
726
+	{
727
+		return $this->_html_style;
728
+	}
729
+
730
+
731
+
732
+	/**
733
+	 * returns the raw, UNSAFE, input, almost exactly as the user submitted it.
734
+	 * Please note that almost all client code should instead use the normalized_value;
735
+	 * or possibly raw_value_in_form (which prepares the string for displaying in an HTML attribute on a tag,
736
+	 * mostly by escaping quotes)
737
+	 * Note, we do not store the exact original value sent in the user's request because
738
+	 * it may have malicious content, and we MIGHT want to store the form input in a transient or something...
739
+	 * in which case, we would have stored the malicious content to our database.
740
+	 *
741
+	 * @return string
742
+	 */
743
+	public function raw_value()
744
+	{
745
+		return $this->_raw_value;
746
+	}
747
+
748
+
749
+
750
+	/**
751
+	 * Returns a string safe to usage in form inputs when displaying, because
752
+	 * it escapes all html entities
753
+	 *
754
+	 * @return string
755
+	 */
756
+	public function raw_value_in_form()
757
+	{
758
+		return htmlentities($this->raw_value(), ENT_QUOTES, 'UTF-8');
759
+	}
760
+
761
+
762
+
763
+	/**
764
+	 * returns the value after it's been sanitized, and then converted into it's proper type
765
+	 * in PHP. Eg, a string, an int, an array,
766
+	 *
767
+	 * @return mixed
768
+	 */
769
+	public function normalized_value()
770
+	{
771
+		return $this->_normalized_value;
772
+	}
773
+
774
+
775
+
776
+	/**
777
+	 * Returns the normalized value is a presentable way. By default this is just
778
+	 * the normalized value by itself, but it can be overridden for when that's not
779
+	 * the best thing to display
780
+	 *
781
+	 * @return string
782
+	 */
783
+	public function pretty_value()
784
+	{
785
+		return $this->_normalized_value;
786
+	}
787
+
788
+
789
+
790
+	/**
791
+	 * When generating the JS for the jquery validation rules like<br>
792
+	 * <code>$( "#myform" ).validate({
793
+	 * rules: {
794
+	 * password: "required",
795
+	 * password_again: {
796
+	 * equalTo: "#password"
797
+	 * }
798
+	 * }
799
+	 * });</code>
800
+	 * if this field had the name 'password_again', it should return
801
+	 * <br><code>password_again: {
802
+	 * equalTo: "#password"
803
+	 * }</code>
804
+	 *
805
+	 * @return array
806
+	 */
807
+	public function get_jquery_validation_rules()
808
+	{
809
+		$jquery_validation_js = array();
810
+		$jquery_validation_rules = array();
811
+		foreach ($this->get_validation_strategies() as $validation_strategy) {
812
+			$jquery_validation_rules = array_replace_recursive(
813
+				$jquery_validation_rules,
814
+				$validation_strategy->get_jquery_validation_rule_array()
815
+			);
816
+		}
817
+		if (! empty($jquery_validation_rules)) {
818
+			foreach ($this->get_display_strategy()->get_html_input_ids(true) as $html_id_with_pound_sign) {
819
+				$jquery_validation_js[$html_id_with_pound_sign] = $jquery_validation_rules;
820
+			}
821
+		}
822
+		return $jquery_validation_js;
823
+	}
824
+
825
+
826
+
827
+	/**
828
+	 * Sets the input's default value for use in displaying in the form. Note: value should be
829
+	 * normalized (Eg, if providing a default of ra Yes_NO_Input you would provide TRUE or FALSE, not '1' or '0')
830
+	 *
831
+	 * @param mixed $value
832
+	 * @return void
833
+	 */
834
+	public function set_default($value)
835
+	{
836
+		$this->_default = $value;
837
+		$this->_set_normalized_value($value);
838
+		$this->_set_raw_value($value);
839
+	}
840
+
841
+
842
+
843
+	/**
844
+	 * Sets the normalized value on this input
845
+	 *
846
+	 * @param mixed $value
847
+	 */
848
+	protected function _set_normalized_value($value)
849
+	{
850
+		$this->_normalized_value = $value;
851
+	}
852
+
853
+
854
+
855
+	/**
856
+	 * Sets the raw value on this input (ie, exactly as the user submitted it)
857
+	 *
858
+	 * @param mixed $value
859
+	 */
860
+	protected function _set_raw_value($value)
861
+	{
862
+		$this->_raw_value = $this->_normalization_strategy->unnormalize($value);
863
+	}
864
+
865
+
866
+
867
+	/**
868
+	 * Sets the HTML label text after it has already been defined
869
+	 *
870
+	 * @param string $label
871
+	 * @return void
872
+	 */
873
+	public function set_html_label_text($label)
874
+	{
875
+		$this->_html_label_text = $label;
876
+	}
877
+
878
+
879
+
880
+	/**
881
+	 * Sets whether or not this field is required, and adjusts the validation strategy.
882
+	 * If you want to use the EE_Conditionally_Required_Validation_Strategy,
883
+	 * please add it as a validation strategy using add_validation_strategy as normal
884
+	 *
885
+	 * @param boolean $required boolean
886
+	 * @param null    $required_text
887
+	 */
888
+	public function set_required($required = true, $required_text = null)
889
+	{
890
+		$required = filter_var($required, FILTER_VALIDATE_BOOLEAN);
891
+		//whether $required is a string or a boolean, we want to add a required validation strategy
892
+		if ($required) {
893
+			$this->_add_validation_strategy(new EE_Required_Validation_Strategy($required_text));
894
+		} else {
895
+			$this->remove_validation_strategy('EE_Required_Validation_Strategy');
896
+		}
897
+		$this->_required = $required;
898
+	}
899
+
900
+
901
+
902
+	/**
903
+	 * Returns whether or not this field is required
904
+	 *
905
+	 * @return boolean
906
+	 */
907
+	public function required()
908
+	{
909
+		return $this->_required;
910
+	}
911
+
912
+
913
+
914
+	/**
915
+	 * @param string $required_css_class
916
+	 */
917
+	public function set_required_css_class($required_css_class)
918
+	{
919
+		$this->_required_css_class = $required_css_class;
920
+	}
921
+
922
+
923
+
924
+	/**
925
+	 * @return string
926
+	 */
927
+	public function required_css_class()
928
+	{
929
+		return $this->_required_css_class;
930
+	}
931
+
932
+
933
+
934
+	/**
935
+	 * @param bool $add_required
936
+	 * @return string
937
+	 */
938
+	public function html_class($add_required = false)
939
+	{
940
+		return $add_required && $this->required()
941
+			? $this->required_css_class() . ' ' . $this->_html_class
942
+			: $this->_html_class;
943
+	}
944
+
945
+
946
+	/**
947
+	 * Sets the help text, in case
948
+	 *
949
+	 * @param string $text
950
+	 */
951
+	public function set_html_help_text($text)
952
+	{
953
+		$this->_html_help_text = $text;
954
+	}
955
+
956
+
957
+
958
+	/**
959
+	 * Uses the sensitive data removal strategy to remove the sensitive data from this
960
+	 * input. If there is any kind of sensitive data removal on this input, we clear
961
+	 * out the raw value completely
962
+	 *
963
+	 * @return void
964
+	 */
965
+	public function clean_sensitive_data()
966
+	{
967
+		//if we do ANY kind of sensitive data removal on this, then just clear out the raw value
968
+		//if we need more logic than this we'll make a strategy for it
969
+		if ($this->_sensitive_data_removal_strategy
970
+			&& ! $this->_sensitive_data_removal_strategy instanceof EE_No_Sensitive_Data_Removal
971
+		) {
972
+			$this->_set_raw_value(null);
973
+		}
974
+		//and clean the normalized value according to the appropriate strategy
975
+		$this->_set_normalized_value(
976
+			$this->get_sensitive_data_removal_strategy()->remove_sensitive_data(
977
+				$this->_normalized_value
978
+			)
979
+		);
980
+	}
981
+
982
+
983
+
984
+	/**
985
+	 * @param bool   $primary
986
+	 * @param string $button_size
987
+	 * @param string $other_attributes
988
+	 */
989
+	public function set_button_css_attributes($primary = true, $button_size = '', $other_attributes = '')
990
+	{
991
+		$button_css_attributes = 'button';
992
+		$button_css_attributes .= $primary === true ? ' button-primary' : ' button-secondary';
993
+		switch ($button_size) {
994
+			case 'xs' :
995
+			case 'extra-small' :
996
+				$button_css_attributes .= ' button-xs';
997
+				break;
998
+			case 'sm' :
999
+			case 'small' :
1000
+				$button_css_attributes .= ' button-sm';
1001
+				break;
1002
+			case 'lg' :
1003
+			case 'large' :
1004
+				$button_css_attributes .= ' button-lg';
1005
+				break;
1006
+			case 'block' :
1007
+				$button_css_attributes .= ' button-block';
1008
+				break;
1009
+			case 'md' :
1010
+			case 'medium' :
1011
+			default :
1012
+				$button_css_attributes .= '';
1013
+		}
1014
+		$this->_button_css_attributes .= ! empty($other_attributes)
1015
+			? $button_css_attributes . ' ' . $other_attributes
1016
+			: $button_css_attributes;
1017
+	}
1018
+
1019
+
1020
+
1021
+	/**
1022
+	 * @return string
1023
+	 */
1024
+	public function button_css_attributes()
1025
+	{
1026
+		if (empty($this->_button_css_attributes)) {
1027
+			$this->set_button_css_attributes();
1028
+		}
1029
+		return $this->_button_css_attributes;
1030
+	}
1031
+
1032
+
1033
+
1034
+	/**
1035
+	 * find_form_data_for_this_section
1036
+	 * using this section's name and its parents, finds the value of the form data that corresponds to it.
1037
+	 * For example, if this form section's HTML name is my_form[subform][form_input_1],
1038
+	 * then it's value should be in $_REQUEST at $_REQUEST['my_form']['subform']['form_input_1'].
1039
+	 * (If that doesn't exist, we also check for this subsection's name
1040
+	 * at the TOP LEVEL of the request data. Eg $_REQUEST['form_input_1'].)
1041
+	 * This function finds its value in the form.
1042
+	 *
1043
+	 * @param array $req_data
1044
+	 * @return mixed whatever the raw value of this form section is in the request data
1045
+	 * @throws \EE_Error
1046
+	 */
1047
+	public function find_form_data_for_this_section($req_data)
1048
+	{
1049
+		// break up the html name by "[]"
1050
+		if (strpos($this->html_name(), '[') !== false) {
1051
+			$before_any_brackets = substr($this->html_name(), 0, strpos($this->html_name(), '['));
1052
+		} else {
1053
+			$before_any_brackets = $this->html_name();
1054
+		}
1055
+		// grab all of the segments
1056
+		preg_match_all('~\[([^]]*)\]~', $this->html_name(), $matches);
1057
+		if (isset($matches[1]) && is_array($matches[1])) {
1058
+			$name_parts = $matches[1];
1059
+			array_unshift($name_parts, $before_any_brackets);
1060
+		} else {
1061
+			$name_parts = array($before_any_brackets);
1062
+		}
1063
+		// now get the value for the input
1064
+		$value = $this->_find_form_data_for_this_section_using_name_parts($name_parts, $req_data);
1065
+		// check if this thing's name is at the TOP level of the request data
1066
+		if ($value === null && isset($req_data[$this->name()])) {
1067
+			$value = $req_data[$this->name()];
1068
+		}
1069
+		return $value;
1070
+	}
1071
+
1072
+
1073
+
1074
+	/**
1075
+	 * @param array $html_name_parts
1076
+	 * @param array $req_data
1077
+	 * @return array | NULL
1078
+	 */
1079
+	public function _find_form_data_for_this_section_using_name_parts($html_name_parts, $req_data)
1080
+	{
1081
+		$first_part_to_consider = array_shift($html_name_parts);
1082
+		if (isset($req_data[$first_part_to_consider])) {
1083
+			if (empty($html_name_parts)) {
1084
+				return $req_data[$first_part_to_consider];
1085
+			} else {
1086
+				return $this->_find_form_data_for_this_section_using_name_parts(
1087
+					$html_name_parts,
1088
+					$req_data[$first_part_to_consider]
1089
+				);
1090
+			}
1091
+		} else {
1092
+			return null;
1093
+		}
1094
+	}
1095
+
1096
+
1097
+
1098
+	/**
1099
+	 * Checks if this form input's data is in the request data
1100
+	 *
1101
+	 * @param array $req_data like $_POST
1102
+	 * @return boolean
1103
+	 * @throws \EE_Error
1104
+	 */
1105
+	public function form_data_present_in($req_data = null)
1106
+	{
1107
+		if ($req_data === null) {
1108
+			$req_data = $_POST;
1109
+		}
1110
+		$checked_value = $this->find_form_data_for_this_section($req_data);
1111
+		if ($checked_value !== null) {
1112
+			return true;
1113
+		} else {
1114
+			return false;
1115
+		}
1116
+	}
1117
+
1118
+
1119
+
1120
+	/**
1121
+	 * Overrides parent to add js data from validation and display strategies
1122
+	 *
1123
+	 * @param array $form_other_js_data
1124
+	 * @return array
1125
+	 */
1126
+	public function get_other_js_data($form_other_js_data = array())
1127
+	{
1128
+		$form_other_js_data = $this->get_other_js_data_from_strategies($form_other_js_data);
1129
+		return $form_other_js_data;
1130
+	}
1131
+
1132
+
1133
+
1134
+	/**
1135
+	 * Gets other JS data for localization from this input's strategies, like
1136
+	 * the validation strategies and the display strategy
1137
+	 *
1138
+	 * @param array $form_other_js_data
1139
+	 * @return array
1140
+	 */
1141
+	public function get_other_js_data_from_strategies($form_other_js_data = array())
1142
+	{
1143
+		$form_other_js_data = $this->get_display_strategy()->get_other_js_data($form_other_js_data);
1144
+		foreach ($this->get_validation_strategies() as $validation_strategy) {
1145
+			$form_other_js_data = $validation_strategy->get_other_js_data($form_other_js_data);
1146
+		}
1147
+		return $form_other_js_data;
1148
+	}
1149
+
1150
+
1151
+
1152
+	/**
1153
+	 * Override parent because we want to give our strategies an opportunity to enqueue some js and css
1154
+	 *
1155
+	 * @return void
1156
+	 */
1157
+	public function enqueue_js()
1158
+	{
1159
+		//ask our display strategy and validation strategies if they have js to enqueue
1160
+		$this->enqueue_js_from_strategies();
1161
+	}
1162
+
1163
+
1164
+
1165
+	/**
1166
+	 * Tells strategies when its ok to enqueue their js and css
1167
+	 *
1168
+	 * @return void
1169
+	 */
1170
+	public function enqueue_js_from_strategies()
1171
+	{
1172
+		$this->get_display_strategy()->enqueue_js();
1173
+		foreach ($this->get_validation_strategies() as $validation_strategy) {
1174
+			$validation_strategy->enqueue_js();
1175
+		}
1176
+	}
1177
+
1178
+
1179
+
1180
+	/**
1181
+	 * Gets the default value set on the input (not the current value, which may have been
1182
+	 * changed because of a form submission). If no default was set, this us null.
1183
+	 * @return mixed
1184
+	 */
1185
+	public function get_default()
1186
+	{
1187
+		return $this->_default;
1188
+	}
1189 1189
 }
Please login to merge, or discard this patch.
Spacing   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -1,4 +1,4 @@  discard block
 block discarded – undo
1
-<?php if (! defined('EVENT_ESPRESSO_VERSION')) {
1
+<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2 2
     exit('No direct script access allowed');
3 3
 }
4 4
 
@@ -191,23 +191,23 @@  discard block
 block discarded – undo
191 191
      */
192 192
     public function __construct($input_args = array())
193 193
     {
194
-        $input_args = (array)apply_filters('FHEE__EE_Form_Input_Base___construct__input_args', $input_args, $this);
194
+        $input_args = (array) apply_filters('FHEE__EE_Form_Input_Base___construct__input_args', $input_args, $this);
195 195
         // the following properties must be cast as arrays
196 196
         if (isset($input_args['validation_strategies'])) {
197
-            foreach ((array)$input_args['validation_strategies'] as $validation_strategy) {
197
+            foreach ((array) $input_args['validation_strategies'] as $validation_strategy) {
198 198
                 if ($validation_strategy instanceof EE_Validation_Strategy_Base && empty($input_args['ignore_input'])) {
199 199
                     $this->_validation_strategies[get_class($validation_strategy)] = $validation_strategy;
200 200
                 }
201 201
             }
202 202
             unset($input_args['validation_strategies']);
203 203
         }
204
-        if(isset($input_args['ignore_input'])) {
204
+        if (isset($input_args['ignore_input'])) {
205 205
             $this->_validation_strategies = array();
206 206
         }
207 207
         // loop thru incoming options
208 208
         foreach ($input_args as $key => $value) {
209 209
             // add underscore to $key to match property names
210
-            $_key = '_' . $key;
210
+            $_key = '_'.$key;
211 211
             if (property_exists($this, $_key)) {
212 212
                 $this->{$_key} = $value;
213 213
             }
@@ -226,7 +226,7 @@  discard block
 block discarded – undo
226 226
         if (isset($input_args['ignore_input'])) {
227 227
             $this->_normalization_strategy = new EE_Null_Normalization();
228 228
         }
229
-        if (! $this->_normalization_strategy) {
229
+        if ( ! $this->_normalization_strategy) {
230 230
                 $this->_normalization_strategy = new EE_Text_Normalization();
231 231
         }
232 232
         $this->_normalization_strategy->_construct_finalize($this);
@@ -235,7 +235,7 @@  discard block
 block discarded – undo
235 235
             $this->set_default($input_args['default']);
236 236
             unset($input_args['default']);
237 237
         }
238
-        if (! $this->_sensitive_data_removal_strategy) {
238
+        if ( ! $this->_sensitive_data_removal_strategy) {
239 239
             $this->_sensitive_data_removal_strategy = new EE_No_Sensitive_Data_Removal();
240 240
         }
241 241
         $this->_sensitive_data_removal_strategy->_construct_finalize($this);
@@ -252,10 +252,10 @@  discard block
 block discarded – undo
252 252
      */
253 253
     protected function _set_default_html_name_if_empty()
254 254
     {
255
-        if (! $this->_html_name) {
255
+        if ( ! $this->_html_name) {
256 256
             $this->_html_name = $this->name();
257 257
             if ($this->_parent_section && $this->_parent_section instanceof EE_Form_Section_Proper) {
258
-                $this->_html_name = $this->_parent_section->html_name_prefix() . "[{$this->name()}]";
258
+                $this->_html_name = $this->_parent_section->html_name_prefix()."[{$this->name()}]";
259 259
             }
260 260
         }
261 261
     }
@@ -287,7 +287,7 @@  discard block
 block discarded – undo
287 287
     protected function _get_display_strategy()
288 288
     {
289 289
         $this->ensure_construct_finalized_called();
290
-        if (! $this->_display_strategy || ! $this->_display_strategy instanceof EE_Display_Strategy_Base) {
290
+        if ( ! $this->_display_strategy || ! $this->_display_strategy instanceof EE_Display_Strategy_Base) {
291 291
             throw new EE_Error(
292 292
                 sprintf(
293 293
                     __(
@@ -520,7 +520,7 @@  discard block
 block discarded – undo
520 520
      */
521 521
     public function html_other_attributes()
522 522
     {
523
-        return ! empty($this->_html_other_attributes) ? ' ' . $this->_html_other_attributes : '';
523
+        return ! empty($this->_html_other_attributes) ? ' '.$this->_html_other_attributes : '';
524 524
     }
525 525
 
526 526
 
@@ -664,7 +664,7 @@  discard block
 block discarded – undo
664 664
      */
665 665
     public function html_label_id()
666 666
     {
667
-        return ! empty($this->_html_label_id) ? $this->_html_label_id : $this->html_id() . '-lbl';
667
+        return ! empty($this->_html_label_id) ? $this->_html_label_id : $this->html_id().'-lbl';
668 668
     }
669 669
 
670 670
 
@@ -814,7 +814,7 @@  discard block
 block discarded – undo
814 814
                 $validation_strategy->get_jquery_validation_rule_array()
815 815
             );
816 816
         }
817
-        if (! empty($jquery_validation_rules)) {
817
+        if ( ! empty($jquery_validation_rules)) {
818 818
             foreach ($this->get_display_strategy()->get_html_input_ids(true) as $html_id_with_pound_sign) {
819 819
                 $jquery_validation_js[$html_id_with_pound_sign] = $jquery_validation_rules;
820 820
             }
@@ -938,7 +938,7 @@  discard block
 block discarded – undo
938 938
     public function html_class($add_required = false)
939 939
     {
940 940
         return $add_required && $this->required()
941
-            ? $this->required_css_class() . ' ' . $this->_html_class
941
+            ? $this->required_css_class().' '.$this->_html_class
942 942
             : $this->_html_class;
943 943
     }
944 944
 
@@ -1012,7 +1012,7 @@  discard block
 block discarded – undo
1012 1012
                 $button_css_attributes .= '';
1013 1013
         }
1014 1014
         $this->_button_css_attributes .= ! empty($other_attributes)
1015
-            ? $button_css_attributes . ' ' . $other_attributes
1015
+            ? $button_css_attributes.' '.$other_attributes
1016 1016
             : $button_css_attributes;
1017 1017
     }
1018 1018
 
Please login to merge, or discard this patch.
core/libraries/form_sections/base/EE_Form_Section_Proper.form.php 3 patches
Doc Comments   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -459,7 +459,7 @@  discard block
 block discarded – undo
459 459
      *                                                      with construction finalize being called later
460 460
      *                                                      (realizing that the subsections' html names
461 461
      *                                                      might not be set yet, etc.)
462
-     * @return EE_Form_Section_Base
462
+     * @return EE_Form_Section_Validatable|null
463 463
      * @throws EE_Error
464 464
      */
465 465
     public function get_subsection($name, $require_construction_to_be_finalized = true)
@@ -1289,7 +1289,6 @@  discard block
 block discarded – undo
1289 1289
     /**
1290 1290
      * Sets the submission error message (aka validation error message for this form section and all sub-sections)
1291 1291
      * @param string                           $form_submission_error_message
1292
-     * @param EE_Form_Section_Validatable $form_section unused
1293 1292
      * @throws EE_Error
1294 1293
      */
1295 1294
     public function set_submission_error_message(
Please login to merge, or discard this patch.
Spacing   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -111,8 +111,8 @@  discard block
 block discarded – undo
111 111
             //AND we are going to make sure they're in that specified order
112 112
             $reordered_subsections = array();
113 113
             foreach ($options_array['include'] as $input_name) {
114
-                if (isset($this->_subsections[ $input_name ])) {
115
-                    $reordered_subsections[ $input_name ] = $this->_subsections[ $input_name ];
114
+                if (isset($this->_subsections[$input_name])) {
115
+                    $reordered_subsections[$input_name] = $this->_subsections[$input_name];
116 116
                 }
117 117
             }
118 118
             $this->_subsections = $reordered_subsections;
@@ -124,7 +124,7 @@  discard block
 block discarded – undo
124 124
         if (isset($options_array['layout_strategy'])) {
125 125
             $this->_layout_strategy = $options_array['layout_strategy'];
126 126
         }
127
-        if (! $this->_layout_strategy) {
127
+        if ( ! $this->_layout_strategy) {
128 128
             $this->_layout_strategy = is_admin() ? new EE_Admin_Two_Column_Layout() : new EE_Two_Column_Layout();
129 129
         }
130 130
         $this->_layout_strategy->_construct_finalize($this);
@@ -277,7 +277,7 @@  discard block
 block discarded – undo
277 277
                 $req_data,
278 278
                 $this
279 279
             );
280
-            $this->cached_request_data = (array)$req_data;
280
+            $this->cached_request_data = (array) $req_data;
281 281
         }
282 282
         return $this->cached_request_data;
283 283
     }
@@ -313,7 +313,7 @@  discard block
 block discarded – undo
313 313
         if ($validate) {
314 314
             $this->_validate();
315 315
             //if it's invalid, we're going to want to re-display so remember what they submitted
316
-            if (! $this->is_valid()) {
316
+            if ( ! $this->is_valid()) {
317 317
                 $this->store_submitted_form_data_in_session();
318 318
             }
319 319
         }
@@ -426,11 +426,11 @@  discard block
 block discarded – undo
426 426
     public function populate_defaults($default_data)
427 427
     {
428 428
         foreach ($this->subsections(false) as $subsection_name => $subsection) {
429
-            if (isset($default_data[ $subsection_name ])) {
429
+            if (isset($default_data[$subsection_name])) {
430 430
                 if ($subsection instanceof EE_Form_Input_Base) {
431
-                    $subsection->set_default($default_data[ $subsection_name ]);
431
+                    $subsection->set_default($default_data[$subsection_name]);
432 432
                 } elseif ($subsection instanceof EE_Form_Section_Proper) {
433
-                    $subsection->populate_defaults($default_data[ $subsection_name ]);
433
+                    $subsection->populate_defaults($default_data[$subsection_name]);
434 434
                 }
435 435
             }
436 436
         }
@@ -445,7 +445,7 @@  discard block
 block discarded – undo
445 445
      */
446 446
     public function subsection_exists($name)
447 447
     {
448
-        return isset($this->_subsections[ $name ]) ? true : false;
448
+        return isset($this->_subsections[$name]) ? true : false;
449 449
     }
450 450
 
451 451
 
@@ -467,7 +467,7 @@  discard block
 block discarded – undo
467 467
         if ($require_construction_to_be_finalized) {
468 468
             $this->ensure_construct_finalized_called();
469 469
         }
470
-        return $this->subsection_exists($name) ? $this->_subsections[ $name ] : null;
470
+        return $this->subsection_exists($name) ? $this->_subsections[$name] : null;
471 471
     }
472 472
 
473 473
 
@@ -482,7 +482,7 @@  discard block
 block discarded – undo
482 482
         $validatable_subsections = array();
483 483
         foreach ($this->subsections() as $name => $obj) {
484 484
             if ($obj instanceof EE_Form_Section_Validatable) {
485
-                $validatable_subsections[ $name ] = $obj;
485
+                $validatable_subsections[$name] = $obj;
486 486
             }
487 487
         }
488 488
         return $validatable_subsections;
@@ -509,7 +509,7 @@  discard block
 block discarded – undo
509 509
             $name,
510 510
             $require_construction_to_be_finalized
511 511
         );
512
-        if (! $subsection instanceof EE_Form_Input_Base) {
512
+        if ( ! $subsection instanceof EE_Form_Input_Base) {
513 513
             throw new EE_Error(
514 514
                 sprintf(
515 515
                     esc_html__(
@@ -546,7 +546,7 @@  discard block
 block discarded – undo
546 546
             $name,
547 547
             $require_construction_to_be_finalized
548 548
         );
549
-        if (! $subsection instanceof EE_Form_Section_Proper) {
549
+        if ( ! $subsection instanceof EE_Form_Section_Proper) {
550 550
             throw new EE_Error(
551 551
                 sprintf(
552 552
                     esc_html__(
@@ -585,8 +585,8 @@  discard block
 block discarded – undo
585 585
      */
586 586
     public function is_valid()
587 587
     {
588
-        if($this->is_valid === null) {
589
-            if (! $this->has_received_submission()) {
588
+        if ($this->is_valid === null) {
589
+            if ( ! $this->has_received_submission()) {
590 590
                 throw new EE_Error(
591 591
                     sprintf(
592 592
                         esc_html__(
@@ -596,14 +596,14 @@  discard block
 block discarded – undo
596 596
                     )
597 597
                 );
598 598
             }
599
-            if (! parent::is_valid()) {
599
+            if ( ! parent::is_valid()) {
600 600
                 $this->is_valid = false;
601 601
             } else {
602 602
                 // ok so no general errors to this entire form section.
603 603
                 // so let's check the subsections, but only set errors if that hasn't been done yet
604 604
                 $this->is_valid = true;
605 605
                 foreach ($this->get_validatable_subsections() as $subsection) {
606
-                    if (! $subsection->is_valid()) {
606
+                    if ( ! $subsection->is_valid()) {
607 607
                         $this->is_valid = false;
608 608
                     }
609 609
                 }
@@ -620,7 +620,7 @@  discard block
 block discarded – undo
620 620
      */
621 621
     protected function _set_default_name_if_empty()
622 622
     {
623
-        if (! $this->_name) {
623
+        if ( ! $this->_name) {
624 624
             $classname    = get_class($this);
625 625
             $default_name = str_replace('EE_', '', $classname);
626 626
             $this->_name  = $default_name;
@@ -710,7 +710,7 @@  discard block
 block discarded – undo
710 710
     {
711 711
         wp_register_script(
712 712
             'ee_form_section_validation',
713
-            EE_GLOBAL_ASSETS_URL . 'scripts' . DS . 'form_section_validation.js',
713
+            EE_GLOBAL_ASSETS_URL.'scripts'.DS.'form_section_validation.js',
714 714
             array('jquery-validate', 'jquery-ui-datepicker', 'jquery-validate-extra-methods'),
715 715
             EVENT_ESPRESSO_VERSION,
716 716
             true
@@ -754,13 +754,13 @@  discard block
 block discarded – undo
754 754
         // we only want to localize vars ONCE for the entire form,
755 755
         // so if the form section doesn't have a parent, then it must be the top dog
756 756
         if ($return_for_subsection || ! $this->parent_section()) {
757
-            EE_Form_Section_Proper::$_js_localization['form_data'][ $this->html_id() ] = array(
757
+            EE_Form_Section_Proper::$_js_localization['form_data'][$this->html_id()] = array(
758 758
                 'form_section_id'  => $this->html_id(true),
759 759
                 'validation_rules' => $this->get_jquery_validation_rules(),
760 760
                 'other_data'       => $this->get_other_js_data(),
761 761
                 'errors'           => $this->subsection_validation_errors_by_html_name(),
762 762
             );
763
-            EE_Form_Section_Proper::$_scripts_localized                                = true;
763
+            EE_Form_Section_Proper::$_scripts_localized = true;
764 764
         }
765 765
     }
766 766
 
@@ -795,7 +795,7 @@  discard block
 block discarded – undo
795 795
         $inputs = array();
796 796
         foreach ($this->subsections() as $subsection) {
797 797
             if ($subsection instanceof EE_Form_Input_Base) {
798
-                $inputs[ $subsection->html_name() ] = $subsection;
798
+                $inputs[$subsection->html_name()] = $subsection;
799 799
             } elseif ($subsection instanceof EE_Form_Section_Proper) {
800 800
                 $inputs += $subsection->inputs_in_subsections();
801 801
             }
@@ -818,7 +818,7 @@  discard block
 block discarded – undo
818 818
         $errors = array();
819 819
         foreach ($inputs as $form_input) {
820 820
             if ($form_input instanceof EE_Form_Input_Base && $form_input->get_validation_errors()) {
821
-                $errors[ $form_input->html_name() ] = $form_input->get_validation_error_string();
821
+                $errors[$form_input->html_name()] = $form_input->get_validation_error_string();
822 822
             }
823 823
         }
824 824
         return $errors;
@@ -841,7 +841,7 @@  discard block
 block discarded – undo
841 841
         $email_validation_level = isset(EE_Registry::instance()->CFG->registration->email_validation_level)
842 842
             ? EE_Registry::instance()->CFG->registration->email_validation_level
843 843
             : 'wp_default';
844
-        EE_Form_Section_Proper::$_js_localization['email_validation_level']   = $email_validation_level;
844
+        EE_Form_Section_Proper::$_js_localization['email_validation_level'] = $email_validation_level;
845 845
         wp_enqueue_script('ee_form_section_validation');
846 846
         wp_localize_script(
847 847
             'ee_form_section_validation',
@@ -858,7 +858,7 @@  discard block
 block discarded – undo
858 858
      */
859 859
     public function ensure_scripts_localized()
860 860
     {
861
-        if (! EE_Form_Section_Proper::$_scripts_localized) {
861
+        if ( ! EE_Form_Section_Proper::$_scripts_localized) {
862 862
             $this->_enqueue_and_localize_form_js();
863 863
         }
864 864
     }
@@ -954,8 +954,8 @@  discard block
 block discarded – undo
954 954
         //reset the cache of whether this form is valid or not- we're re-validating it now
955 955
         $this->is_valid = null;
956 956
         foreach ($this->get_validatable_subsections() as $subsection_name => $subsection) {
957
-            if (method_exists($this, '_validate_' . $subsection_name)) {
958
-                call_user_func_array(array($this, '_validate_' . $subsection_name), array($subsection));
957
+            if (method_exists($this, '_validate_'.$subsection_name)) {
958
+                call_user_func_array(array($this, '_validate_'.$subsection_name), array($subsection));
959 959
             }
960 960
             $subsection->_validate();
961 961
         }
@@ -973,9 +973,9 @@  discard block
 block discarded – undo
973 973
         $inputs = array();
974 974
         foreach ($this->subsections() as $subsection_name => $subsection) {
975 975
             if ($subsection instanceof EE_Form_Section_Proper) {
976
-                $inputs[ $subsection_name ] = $subsection->valid_data();
976
+                $inputs[$subsection_name] = $subsection->valid_data();
977 977
             } elseif ($subsection instanceof EE_Form_Input_Base) {
978
-                $inputs[ $subsection_name ] = $subsection->normalized_value();
978
+                $inputs[$subsection_name] = $subsection->normalized_value();
979 979
             }
980 980
         }
981 981
         return $inputs;
@@ -993,7 +993,7 @@  discard block
 block discarded – undo
993 993
         $inputs = array();
994 994
         foreach ($this->subsections() as $subsection_name => $subsection) {
995 995
             if ($subsection instanceof EE_Form_Input_Base) {
996
-                $inputs[ $subsection_name ] = $subsection;
996
+                $inputs[$subsection_name] = $subsection;
997 997
             }
998 998
         }
999 999
         return $inputs;
@@ -1011,7 +1011,7 @@  discard block
 block discarded – undo
1011 1011
         $form_sections = array();
1012 1012
         foreach ($this->subsections() as $name => $obj) {
1013 1013
             if ($obj instanceof EE_Form_Section_Proper) {
1014
-                $form_sections[ $name ] = $obj;
1014
+                $form_sections[$name] = $obj;
1015 1015
             }
1016 1016
         }
1017 1017
         return $form_sections;
@@ -1118,7 +1118,7 @@  discard block
 block discarded – undo
1118 1118
         $input_values = array();
1119 1119
         foreach ($this->subsections() as $subsection_name => $subsection) {
1120 1120
             if ($subsection instanceof EE_Form_Input_Base) {
1121
-                $input_values[ $subsection_name ] = $pretty
1121
+                $input_values[$subsection_name] = $pretty
1122 1122
                     ? $subsection->pretty_value()
1123 1123
                     : $subsection->normalized_value();
1124 1124
             } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subform_inputs) {
@@ -1130,7 +1130,7 @@  discard block
 block discarded – undo
1130 1130
                 if ($flatten) {
1131 1131
                     $input_values = array_merge($input_values, $subform_input_values);
1132 1132
                 } else {
1133
-                    $input_values[ $subsection_name ] = $subform_input_values;
1133
+                    $input_values[$subsection_name] = $subform_input_values;
1134 1134
                 }
1135 1135
             }
1136 1136
         }
@@ -1158,7 +1158,7 @@  discard block
 block discarded – undo
1158 1158
             if ($subsection instanceof EE_Form_Input_Base) {
1159 1159
                 // is this input part of an array of inputs?
1160 1160
                 if (strpos($subsection->html_name(), '[') !== false) {
1161
-                    $full_input_name  = EEH_Array::convert_array_values_to_keys(
1161
+                    $full_input_name = EEH_Array::convert_array_values_to_keys(
1162 1162
                         explode(
1163 1163
                             '[',
1164 1164
                             str_replace(']', '', $subsection->html_name())
@@ -1167,7 +1167,7 @@  discard block
 block discarded – undo
1167 1167
                     );
1168 1168
                     $submitted_values = array_replace_recursive($submitted_values, $full_input_name);
1169 1169
                 } else {
1170
-                    $submitted_values[ $subsection->html_name() ] = $subsection->raw_value();
1170
+                    $submitted_values[$subsection->html_name()] = $subsection->raw_value();
1171 1171
                 }
1172 1172
             } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subforms) {
1173 1173
                 $subform_input_values = $subsection->submitted_values($include_subforms);
@@ -1202,7 +1202,7 @@  discard block
 block discarded – undo
1202 1202
     public function exclude(array $inputs_to_exclude = array())
1203 1203
     {
1204 1204
         foreach ($inputs_to_exclude as $input_to_exclude_name) {
1205
-            unset($this->_subsections[ $input_to_exclude_name ]);
1205
+            unset($this->_subsections[$input_to_exclude_name]);
1206 1206
         }
1207 1207
     }
1208 1208
 
@@ -1244,7 +1244,7 @@  discard block
 block discarded – undo
1244 1244
     public function add_subsections($new_subsections, $subsection_name_to_target = null, $add_before = true)
1245 1245
     {
1246 1246
         foreach ($new_subsections as $subsection_name => $subsection) {
1247
-            if (! $subsection instanceof EE_Form_Section_Base) {
1247
+            if ( ! $subsection instanceof EE_Form_Section_Base) {
1248 1248
                 EE_Error::add_error(
1249 1249
                     sprintf(
1250 1250
                         esc_html__(
@@ -1256,7 +1256,7 @@  discard block
 block discarded – undo
1256 1256
                         $this->name()
1257 1257
                     )
1258 1258
                 );
1259
-                unset($new_subsections[ $subsection_name ]);
1259
+                unset($new_subsections[$subsection_name]);
1260 1260
             }
1261 1261
         }
1262 1262
         $this->_subsections = EEH_Array::insert_into_array(
@@ -1348,7 +1348,7 @@  discard block
 block discarded – undo
1348 1348
     public function html_name_prefix()
1349 1349
     {
1350 1350
         if ($this->parent_section() instanceof EE_Form_Section_Proper) {
1351
-            return $this->parent_section()->html_name_prefix() . '[' . $this->name() . ']';
1351
+            return $this->parent_section()->html_name_prefix().'['.$this->name().']';
1352 1352
         }
1353 1353
         return $this->name();
1354 1354
     }
@@ -1388,7 +1388,7 @@  discard block
 block discarded – undo
1388 1388
      */
1389 1389
     public function ensure_construct_finalized_called()
1390 1390
     {
1391
-        if (! $this->_construction_finalized) {
1391
+        if ( ! $this->_construction_finalized) {
1392 1392
             $this->_construct_finalize($this->_parent_section, $this->_name);
1393 1393
         }
1394 1394
     }
@@ -1460,7 +1460,7 @@  discard block
 block discarded – undo
1460 1460
                 $form_section = $validation_error->get_form_section();
1461 1461
                 if ($form_section instanceof EE_Form_Input_Base) {
1462 1462
                    $label = $validation_error->get_form_section()->html_label_text();
1463
-                } elseif($form_section instanceof EE_Form_Section_Validatable) {
1463
+                } elseif ($form_section instanceof EE_Form_Section_Validatable) {
1464 1464
                     $label = $validation_error->get_form_section()->name();
1465 1465
                 } else {
1466 1466
                     $label = esc_html__('Unknown', 'event_espresso');
Please login to merge, or discard this patch.
Indentation   +1500 added lines, -1500 removed lines patch added patch discarded remove patch
@@ -14,1505 +14,1505 @@
 block discarded – undo
14 14
 class EE_Form_Section_Proper extends EE_Form_Section_Validatable
15 15
 {
16 16
 
17
-    const SUBMITTED_FORM_DATA_SSN_KEY = 'submitted_form_data';
18
-
19
-    /**
20
-     * Subsections
21
-     *
22
-     * @var EE_Form_Section_Validatable[]
23
-     */
24
-    protected $_subsections = array();
25
-
26
-    /**
27
-     * Strategy for laying out the form
28
-     *
29
-     * @var EE_Form_Section_Layout_Base
30
-     */
31
-    protected $_layout_strategy;
32
-
33
-    /**
34
-     * Whether or not this form has received and validated a form submission yet
35
-     *
36
-     * @var boolean
37
-     */
38
-    protected $_received_submission = false;
39
-
40
-    /**
41
-     * message displayed to users upon successful form submission
42
-     *
43
-     * @var string
44
-     */
45
-    protected $_form_submission_success_message = '';
46
-
47
-    /**
48
-     * message displayed to users upon unsuccessful form submission
49
-     *
50
-     * @var string
51
-     */
52
-    protected $_form_submission_error_message = '';
53
-
54
-    /**
55
-     * @var array like $_REQUEST
56
-     */
57
-    protected $cached_request_data;
58
-
59
-    /**
60
-     * Stores whether this form (and its sub-sections) were found to be valid or not.
61
-     * Starts off as null, but once the form is validated, it set to either true or false
62
-     * @var boolean|null
63
-     */
64
-    protected $is_valid;
65
-
66
-    /**
67
-     * Stores all the data that will localized for form validation
68
-     *
69
-     * @var array
70
-     */
71
-    static protected $_js_localization = array();
72
-
73
-    /**
74
-     * whether or not the form's localized validation JS vars have been set
75
-     *
76
-     * @type boolean
77
-     */
78
-    static protected $_scripts_localized = false;
79
-
80
-
81
-    /**
82
-     * when constructing a proper form section, calls _construct_finalize on children
83
-     * so that they know who their parent is, and what name they've been given.
84
-     *
85
-     * @param array[] $options_array   {
86
-     * @type          $subsections     EE_Form_Section_Validatable[] where keys are the section's name
87
-     * @type          $include         string[] numerically-indexed where values are section names to be included,
88
-     *                                 and in that order. This is handy if you want
89
-     *                                 the subsections to be ordered differently than the default, and if you override
90
-     *                                 which fields are shown
91
-     * @type          $exclude         string[] values are subsections to be excluded. This is handy if you want
92
-     *                                 to remove certain default subsections (note: if you specify BOTH 'include' AND
93
-     *                                 'exclude', the inclusions will be applied first, and the exclusions will exclude
94
-     *                                 items from that list of inclusions)
95
-     * @type          $layout_strategy EE_Form_Section_Layout_Base strategy for laying out the form
96
-     *                                 } @see EE_Form_Section_Validatable::__construct()
97
-     * @throws EE_Error
98
-     */
99
-    public function __construct($options_array = array())
100
-    {
101
-        $options_array = (array) apply_filters(
102
-            'FHEE__EE_Form_Section_Proper___construct__options_array',
103
-            $options_array,
104
-            $this
105
-        );
106
-        //call parent first, as it may be setting the name
107
-        parent::__construct($options_array);
108
-        //if they've included subsections in the constructor, add them now
109
-        if (isset($options_array['include'])) {
110
-            //we are going to make sure we ONLY have those subsections to include
111
-            //AND we are going to make sure they're in that specified order
112
-            $reordered_subsections = array();
113
-            foreach ($options_array['include'] as $input_name) {
114
-                if (isset($this->_subsections[ $input_name ])) {
115
-                    $reordered_subsections[ $input_name ] = $this->_subsections[ $input_name ];
116
-                }
117
-            }
118
-            $this->_subsections = $reordered_subsections;
119
-        }
120
-        if (isset($options_array['exclude'])) {
121
-            $exclude            = $options_array['exclude'];
122
-            $this->_subsections = array_diff_key($this->_subsections, array_flip($exclude));
123
-        }
124
-        if (isset($options_array['layout_strategy'])) {
125
-            $this->_layout_strategy = $options_array['layout_strategy'];
126
-        }
127
-        if (! $this->_layout_strategy) {
128
-            $this->_layout_strategy = is_admin() ? new EE_Admin_Two_Column_Layout() : new EE_Two_Column_Layout();
129
-        }
130
-        $this->_layout_strategy->_construct_finalize($this);
131
-        //ok so we are definitely going to want the forms JS,
132
-        //so enqueue it or remember to enqueue it during wp_enqueue_scripts
133
-        if (did_action('wp_enqueue_scripts') || did_action('admin_enqueue_scripts')) {
134
-            //ok so they've constructed this object after when they should have.
135
-            //just enqueue the generic form scripts and initialize the form immediately in the JS
136
-            EE_Form_Section_Proper::wp_enqueue_scripts(true);
137
-        } else {
138
-            add_action('wp_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
139
-            add_action('admin_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
140
-        }
141
-        add_action('wp_footer', array($this, 'ensure_scripts_localized'), 1);
142
-        /**
143
-         * Gives other plugins a chance to hook in before construct finalize is called.
144
-         * The form probably doesn't yet have a parent form section.
145
-         * Since 4.9.32, when this action was introduced, this is the best place to add a subsection onto a form,
146
-         * assuming you don't care what the form section's name, HTML ID, or HTML name etc are.
147
-         * Also see AHEE__EE_Form_Section_Proper___construct_finalize__end
148
-         *
149
-         * @since 4.9.32
150
-         * @param EE_Form_Section_Proper $this          before __construct is done, but all of its logic,
151
-         *                                              except maybe calling _construct_finalize has been done
152
-         * @param array                  $options_array options passed into the constructor
153
-         */
154
-        do_action(
155
-            'AHEE__EE_Form_Input_Base___construct__before_construct_finalize_called',
156
-            $this,
157
-            $options_array
158
-        );
159
-        if (isset($options_array['name'])) {
160
-            $this->_construct_finalize(null, $options_array['name']);
161
-        }
162
-    }
163
-
164
-
165
-    /**
166
-     * Finishes construction given the parent form section and this form section's name
167
-     *
168
-     * @param EE_Form_Section_Proper $parent_form_section
169
-     * @param string                 $name
170
-     * @throws EE_Error
171
-     */
172
-    public function _construct_finalize($parent_form_section, $name)
173
-    {
174
-        parent::_construct_finalize($parent_form_section, $name);
175
-        $this->_set_default_name_if_empty();
176
-        $this->_set_default_html_id_if_empty();
177
-        foreach ($this->_subsections as $subsection_name => $subsection) {
178
-            if ($subsection instanceof EE_Form_Section_Base) {
179
-                $subsection->_construct_finalize($this, $subsection_name);
180
-            } else {
181
-                throw new EE_Error(
182
-                    sprintf(
183
-                        esc_html__(
184
-                            'Subsection "%s" is not an instanceof EE_Form_Section_Base on form "%s". It is a "%s"',
185
-                            'event_espresso'
186
-                        ),
187
-                        $subsection_name,
188
-                        get_class($this),
189
-                        $subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
190
-                    )
191
-                );
192
-            }
193
-        }
194
-        /**
195
-         * Action performed just after form has been given a name (and HTML ID etc) and is fully constructed.
196
-         * If you have code that should modify the form and needs it and its subsections to have a name, HTML ID
197
-         * (or other attributes derived from the name like the HTML label id, etc), this is where it should be done.
198
-         * This might only happen just before displaying the form, or just before it receives form submission data.
199
-         * If you need to modify the form or its subsections before _construct_finalize is called on it (and we've
200
-         * ensured it has a name, HTML IDs, etc
201
-         *
202
-         * @param EE_Form_Section_Proper      $this
203
-         * @param EE_Form_Section_Proper|null $parent_form_section
204
-         * @param string                      $name
205
-         */
206
-        do_action(
207
-            'AHEE__EE_Form_Section_Proper___construct_finalize__end',
208
-            $this,
209
-            $parent_form_section,
210
-            $name
211
-        );
212
-    }
213
-
214
-
215
-    /**
216
-     * Gets the layout strategy for this form section
217
-     *
218
-     * @return EE_Form_Section_Layout_Base
219
-     */
220
-    public function get_layout_strategy()
221
-    {
222
-        return $this->_layout_strategy;
223
-    }
224
-
225
-
226
-    /**
227
-     * Gets the HTML for a single input for this form section according
228
-     * to the layout strategy
229
-     *
230
-     * @param EE_Form_Input_Base $input
231
-     * @return string
232
-     */
233
-    public function get_html_for_input($input)
234
-    {
235
-        return $this->_layout_strategy->layout_input($input);
236
-    }
237
-
238
-
239
-    /**
240
-     * was_submitted - checks if form inputs are present in request data
241
-     * Basically an alias for form_data_present_in() (which is used by both
242
-     * proper form sections and form inputs)
243
-     *
244
-     * @param null $form_data
245
-     * @return boolean
246
-     * @throws EE_Error
247
-     */
248
-    public function was_submitted($form_data = null)
249
-    {
250
-        return $this->form_data_present_in($form_data);
251
-    }
252
-
253
-    /**
254
-     * Gets the cached request data; but if there is none, or $req_data was set with
255
-     * something different, refresh the cache, and then return it
256
-     * @param null $req_data
257
-     * @return array
258
-     */
259
-    protected function getCachedRequest($req_data = null)
260
-    {
261
-        if ($this->cached_request_data === null
262
-            || (
263
-                $req_data !== null &&
264
-                $req_data !== $this->cached_request_data
265
-            )
266
-        ) {
267
-            $req_data = apply_filters(
268
-                'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
269
-                $req_data,
270
-                $this
271
-            );
272
-            if ($req_data === null) {
273
-                $req_data = array_merge($_GET, $_POST);
274
-            }
275
-            $req_data = apply_filters(
276
-                'FHEE__EE_Form_Section_Proper__receive_form_submission__request_data',
277
-                $req_data,
278
-                $this
279
-            );
280
-            $this->cached_request_data = (array)$req_data;
281
-        }
282
-        return $this->cached_request_data;
283
-    }
284
-
285
-
286
-    /**
287
-     * After the form section is initially created, call this to sanitize the data in the submission
288
-     * which relates to this form section, validate it, and set it as properties on the form.
289
-     *
290
-     * @param array|null $req_data should usually be $_POST (the default).
291
-     *                             However, you CAN supply a different array.
292
-     *                             Consider using set_defaults() instead however.
293
-     *                             (If you rendered the form in the page using echo $form_x->get_html()
294
-     *                             the inputs will have the correct name in the request data for this function
295
-     *                             to find them and populate the form with them.
296
-     *                             If you have a flat form (with only input subsections),
297
-     *                             you can supply a flat array where keys
298
-     *                             are the form input names and values are their values)
299
-     * @param boolean    $validate whether or not to perform validation on this data. Default is,
300
-     *                             of course, to validate that data, and set errors on the invalid values.
301
-     *                             But if the data has already been validated
302
-     *                             (eg you validated the data then stored it in the DB)
303
-     *                             you may want to skip this step.
304
-     * @throws InvalidArgumentException
305
-     * @throws InvalidInterfaceException
306
-     * @throws InvalidDataTypeException
307
-     * @throws EE_Error
308
-     */
309
-    public function receive_form_submission($req_data = null, $validate = true)
310
-    {
311
-        $req_data = $this->getCachedRequest($req_data);
312
-        $this->_normalize($req_data);
313
-        if ($validate) {
314
-            $this->_validate();
315
-            //if it's invalid, we're going to want to re-display so remember what they submitted
316
-            if (! $this->is_valid()) {
317
-                $this->store_submitted_form_data_in_session();
318
-            }
319
-        }
320
-        if ($this->submission_error_message() === '' && ! $this->is_valid()) {
321
-            $this->set_submission_error_message();
322
-        }
323
-        do_action(
324
-            'AHEE__EE_Form_Section_Proper__receive_form_submission__end',
325
-            $req_data,
326
-            $this,
327
-            $validate
328
-        );
329
-    }
330
-
331
-
332
-    /**
333
-     * caches the originally submitted input values in the session
334
-     * so that they can be used to repopulate the form if it failed validation
335
-     *
336
-     * @return boolean whether or not the data was successfully stored in the session
337
-     * @throws InvalidArgumentException
338
-     * @throws InvalidInterfaceException
339
-     * @throws InvalidDataTypeException
340
-     * @throws EE_Error
341
-     */
342
-    protected function store_submitted_form_data_in_session()
343
-    {
344
-        return EE_Registry::instance()->SSN->set_session_data(
345
-            array(
346
-                EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY => $this->submitted_values(true),
347
-            )
348
-        );
349
-    }
350
-
351
-
352
-    /**
353
-     * retrieves the originally submitted input values in the session
354
-     * so that they can be used to repopulate the form if it failed validation
355
-     *
356
-     * @return array
357
-     * @throws InvalidArgumentException
358
-     * @throws InvalidInterfaceException
359
-     * @throws InvalidDataTypeException
360
-     */
361
-    protected function get_submitted_form_data_from_session()
362
-    {
363
-        $session = EE_Registry::instance()->SSN;
364
-        if ($session instanceof EE_Session) {
365
-            return $session->get_session_data(
366
-                EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY
367
-            );
368
-        }
369
-        return array();
370
-    }
371
-
372
-
373
-    /**
374
-     * flushed the originally submitted input values from the session
375
-     *
376
-     * @return boolean whether or not the data was successfully removed from the session
377
-     * @throws InvalidArgumentException
378
-     * @throws InvalidInterfaceException
379
-     * @throws InvalidDataTypeException
380
-     */
381
-    protected function flush_submitted_form_data_from_session()
382
-    {
383
-        return EE_Registry::instance()->SSN->reset_data(
384
-            array(EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY)
385
-        );
386
-    }
387
-
388
-
389
-    /**
390
-     * Populates this form and its subsections with data from the session.
391
-     * (Wrapper for EE_Form_Section_Proper::receive_form_submission, so it shows
392
-     * validation errors when displaying too)
393
-     * Returns true if the form was populated from the session, false otherwise
394
-     *
395
-     * @return boolean
396
-     * @throws InvalidArgumentException
397
-     * @throws InvalidInterfaceException
398
-     * @throws InvalidDataTypeException
399
-     * @throws EE_Error
400
-     */
401
-    public function populate_from_session()
402
-    {
403
-        $form_data_in_session = $this->get_submitted_form_data_from_session();
404
-        if (empty($form_data_in_session)) {
405
-            return false;
406
-        }
407
-        $this->receive_form_submission($form_data_in_session);
408
-        $this->flush_submitted_form_data_from_session();
409
-        if ($this->form_data_present_in($form_data_in_session)) {
410
-            return true;
411
-        }
412
-        return false;
413
-    }
414
-
415
-
416
-    /**
417
-     * Populates the default data for the form, given an array where keys are
418
-     * the input names, and values are their values (preferably normalized to be their
419
-     * proper PHP types, not all strings... although that should be ok too).
420
-     * Proper subsections are sub-arrays, the key being the subsection's name, and
421
-     * the value being an array formatted in teh same way
422
-     *
423
-     * @param array $default_data
424
-     * @throws EE_Error
425
-     */
426
-    public function populate_defaults($default_data)
427
-    {
428
-        foreach ($this->subsections(false) as $subsection_name => $subsection) {
429
-            if (isset($default_data[ $subsection_name ])) {
430
-                if ($subsection instanceof EE_Form_Input_Base) {
431
-                    $subsection->set_default($default_data[ $subsection_name ]);
432
-                } elseif ($subsection instanceof EE_Form_Section_Proper) {
433
-                    $subsection->populate_defaults($default_data[ $subsection_name ]);
434
-                }
435
-            }
436
-        }
437
-    }
438
-
439
-
440
-    /**
441
-     * returns true if subsection exists
442
-     *
443
-     * @param string $name
444
-     * @return boolean
445
-     */
446
-    public function subsection_exists($name)
447
-    {
448
-        return isset($this->_subsections[ $name ]) ? true : false;
449
-    }
450
-
451
-
452
-    /**
453
-     * Gets the subsection specified by its name
454
-     *
455
-     * @param string  $name
456
-     * @param boolean $require_construction_to_be_finalized most client code should leave this as TRUE
457
-     *                                                      so that the inputs will be properly configured.
458
-     *                                                      However, some client code may be ok
459
-     *                                                      with construction finalize being called later
460
-     *                                                      (realizing that the subsections' html names
461
-     *                                                      might not be set yet, etc.)
462
-     * @return EE_Form_Section_Base
463
-     * @throws EE_Error
464
-     */
465
-    public function get_subsection($name, $require_construction_to_be_finalized = true)
466
-    {
467
-        if ($require_construction_to_be_finalized) {
468
-            $this->ensure_construct_finalized_called();
469
-        }
470
-        return $this->subsection_exists($name) ? $this->_subsections[ $name ] : null;
471
-    }
472
-
473
-
474
-    /**
475
-     * Gets all the validatable subsections of this form section
476
-     *
477
-     * @return EE_Form_Section_Validatable[]
478
-     * @throws EE_Error
479
-     */
480
-    public function get_validatable_subsections()
481
-    {
482
-        $validatable_subsections = array();
483
-        foreach ($this->subsections() as $name => $obj) {
484
-            if ($obj instanceof EE_Form_Section_Validatable) {
485
-                $validatable_subsections[ $name ] = $obj;
486
-            }
487
-        }
488
-        return $validatable_subsections;
489
-    }
490
-
491
-
492
-    /**
493
-     * Gets an input by the given name. If not found, or if its not an EE_FOrm_Input_Base child,
494
-     * throw an EE_Error.
495
-     *
496
-     * @param string  $name
497
-     * @param boolean $require_construction_to_be_finalized most client code should
498
-     *                                                      leave this as TRUE so that the inputs will be properly
499
-     *                                                      configured. However, some client code may be ok with
500
-     *                                                      construction finalize being called later
501
-     *                                                      (realizing that the subsections' html names might not be
502
-     *                                                      set yet, etc.)
503
-     * @return EE_Form_Input_Base
504
-     * @throws EE_Error
505
-     */
506
-    public function get_input($name, $require_construction_to_be_finalized = true)
507
-    {
508
-        $subsection = $this->get_subsection(
509
-            $name,
510
-            $require_construction_to_be_finalized
511
-        );
512
-        if (! $subsection instanceof EE_Form_Input_Base) {
513
-            throw new EE_Error(
514
-                sprintf(
515
-                    esc_html__(
516
-                        "Subsection '%s' is not an instanceof EE_Form_Input_Base on form '%s'. It is a '%s'",
517
-                        'event_espresso'
518
-                    ),
519
-                    $name,
520
-                    get_class($this),
521
-                    $subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
522
-                )
523
-            );
524
-        }
525
-        return $subsection;
526
-    }
527
-
528
-
529
-    /**
530
-     * Like get_input(), gets the proper subsection of the form given the name,
531
-     * otherwise throws an EE_Error
532
-     *
533
-     * @param string  $name
534
-     * @param boolean $require_construction_to_be_finalized most client code should
535
-     *                                                      leave this as TRUE so that the inputs will be properly
536
-     *                                                      configured. However, some client code may be ok with
537
-     *                                                      construction finalize being called later
538
-     *                                                      (realizing that the subsections' html names might not be
539
-     *                                                      set yet, etc.)
540
-     * @return EE_Form_Section_Proper
541
-     * @throws EE_Error
542
-     */
543
-    public function get_proper_subsection($name, $require_construction_to_be_finalized = true)
544
-    {
545
-        $subsection = $this->get_subsection(
546
-            $name,
547
-            $require_construction_to_be_finalized
548
-        );
549
-        if (! $subsection instanceof EE_Form_Section_Proper) {
550
-            throw new EE_Error(
551
-                sprintf(
552
-                    esc_html__(
553
-                        "Subsection '%'s is not an instanceof EE_Form_Section_Proper on form '%s'",
554
-                        'event_espresso'
555
-                    ),
556
-                    $name,
557
-                    get_class($this)
558
-                )
559
-            );
560
-        }
561
-        return $subsection;
562
-    }
563
-
564
-
565
-    /**
566
-     * Gets the value of the specified input. Should be called after receive_form_submission()
567
-     * or populate_defaults() on the form, where the normalized value on the input is set.
568
-     *
569
-     * @param string $name
570
-     * @return mixed depending on the input's type and its normalization strategy
571
-     * @throws EE_Error
572
-     */
573
-    public function get_input_value($name)
574
-    {
575
-        $input = $this->get_input($name);
576
-        return $input->normalized_value();
577
-    }
578
-
579
-
580
-    /**
581
-     * Checks if this form section itself is valid, and then checks its subsections
582
-     *
583
-     * @throws EE_Error
584
-     * @return boolean
585
-     */
586
-    public function is_valid()
587
-    {
588
-        if($this->is_valid === null) {
589
-            if (! $this->has_received_submission()) {
590
-                throw new EE_Error(
591
-                    sprintf(
592
-                        esc_html__(
593
-                            'You cannot check if a form is valid before receiving the form submission using receive_form_submission',
594
-                            'event_espresso'
595
-                        )
596
-                    )
597
-                );
598
-            }
599
-            if (! parent::is_valid()) {
600
-                $this->is_valid = false;
601
-            } else {
602
-                // ok so no general errors to this entire form section.
603
-                // so let's check the subsections, but only set errors if that hasn't been done yet
604
-                $this->is_valid = true;
605
-                foreach ($this->get_validatable_subsections() as $subsection) {
606
-                    if (! $subsection->is_valid()) {
607
-                        $this->is_valid = false;
608
-                    }
609
-                }
610
-            }
611
-        }
612
-        return $this->is_valid;
613
-    }
614
-
615
-
616
-    /**
617
-     * gets the default name of this form section if none is specified
618
-     *
619
-     * @return void
620
-     */
621
-    protected function _set_default_name_if_empty()
622
-    {
623
-        if (! $this->_name) {
624
-            $classname    = get_class($this);
625
-            $default_name = str_replace('EE_', '', $classname);
626
-            $this->_name  = $default_name;
627
-        }
628
-    }
629
-
630
-
631
-    /**
632
-     * Returns the HTML for the form, except for the form opening and closing tags
633
-     * (as the form section doesn't know where you necessarily want to send the information to),
634
-     * and except for a submit button. Enqueues JS and CSS; if called early enough we will
635
-     * try to enqueue them in the header, otherwise they'll be enqueued in the footer.
636
-     * Not doing_it_wrong because theoretically this CAN be used properly,
637
-     * provided its used during "wp_enqueue_scripts", or it doesn't need to enqueue
638
-     * any CSS.
639
-     *
640
-     * @throws InvalidArgumentException
641
-     * @throws InvalidInterfaceException
642
-     * @throws InvalidDataTypeException
643
-     * @throws EE_Error
644
-     */
645
-    public function get_html_and_js()
646
-    {
647
-        $this->enqueue_js();
648
-        return $this->get_html();
649
-    }
650
-
651
-
652
-    /**
653
-     * returns HTML for displaying this form section. recursively calls display_section() on all subsections
654
-     *
655
-     * @param bool $display_previously_submitted_data
656
-     * @return string
657
-     * @throws InvalidArgumentException
658
-     * @throws InvalidInterfaceException
659
-     * @throws InvalidDataTypeException
660
-     * @throws EE_Error
661
-     * @throws EE_Error
662
-     * @throws EE_Error
663
-     */
664
-    public function get_html($display_previously_submitted_data = true)
665
-    {
666
-        $this->ensure_construct_finalized_called();
667
-        if ($display_previously_submitted_data) {
668
-            $this->populate_from_session();
669
-        }
670
-        return $this->_form_html_filter
671
-            ? $this->_form_html_filter->filterHtml($this->_layout_strategy->layout_form(), $this)
672
-            : $this->_layout_strategy->layout_form();
673
-    }
674
-
675
-
676
-    /**
677
-     * enqueues JS and CSS for the form.
678
-     * It is preferred to call this before wp_enqueue_scripts so the
679
-     * scripts and styles can be put in the header, but if called later
680
-     * they will be put in the footer (which is OK for JS, but in HTML4 CSS should
681
-     * only be in the header; but in HTML5 its ok in the body.
682
-     * See http://stackoverflow.com/questions/4957446/load-external-css-file-in-body-tag.
683
-     * So if your form enqueues CSS, it's preferred to call this before wp_enqueue_scripts.)
684
-     *
685
-     * @return void
686
-     * @throws EE_Error
687
-     */
688
-    public function enqueue_js()
689
-    {
690
-        $this->_enqueue_and_localize_form_js();
691
-        foreach ($this->subsections() as $subsection) {
692
-            $subsection->enqueue_js();
693
-        }
694
-    }
695
-
696
-
697
-    /**
698
-     * adds a filter so that jquery validate gets enqueued in EE_System::wp_enqueue_scripts().
699
-     * This must be done BEFORE wp_enqueue_scripts() gets called, which is on
700
-     * the wp_enqueue_scripts hook.
701
-     * However, registering the form js and localizing it can happen when we
702
-     * actually output the form (which is preferred, seeing how teh form's fields
703
-     * could change until it's actually outputted)
704
-     *
705
-     * @param boolean $init_form_validation_automatically whether or not we want the form validation
706
-     *                                                    to be triggered automatically or not
707
-     * @return void
708
-     */
709
-    public static function wp_enqueue_scripts($init_form_validation_automatically = true)
710
-    {
711
-        wp_register_script(
712
-            'ee_form_section_validation',
713
-            EE_GLOBAL_ASSETS_URL . 'scripts' . DS . 'form_section_validation.js',
714
-            array('jquery-validate', 'jquery-ui-datepicker', 'jquery-validate-extra-methods'),
715
-            EVENT_ESPRESSO_VERSION,
716
-            true
717
-        );
718
-        wp_localize_script(
719
-            'ee_form_section_validation',
720
-            'ee_form_section_validation_init',
721
-            array('init' => $init_form_validation_automatically ? '1' : '0')
722
-        );
723
-    }
724
-
725
-
726
-    /**
727
-     * gets the variables used by form_section_validation.js.
728
-     * This needs to be called AFTER we've called $this->_enqueue_jquery_validate_script,
729
-     * but before the wordpress hook wp_loaded
730
-     *
731
-     * @throws EE_Error
732
-     */
733
-    public function _enqueue_and_localize_form_js()
734
-    {
735
-        $this->ensure_construct_finalized_called();
736
-        //actually, we don't want to localize just yet. There may be other forms on the page.
737
-        //so we need to add our form section data to a static variable accessible by all form sections
738
-        //and localize it just before the footer
739
-        $this->localize_validation_rules();
740
-        add_action('wp_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'), 2);
741
-        add_action('admin_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'));
742
-    }
743
-
744
-
745
-    /**
746
-     * add our form section data to a static variable accessible by all form sections
747
-     *
748
-     * @param bool $return_for_subsection
749
-     * @return void
750
-     * @throws EE_Error
751
-     */
752
-    public function localize_validation_rules($return_for_subsection = false)
753
-    {
754
-        // we only want to localize vars ONCE for the entire form,
755
-        // so if the form section doesn't have a parent, then it must be the top dog
756
-        if ($return_for_subsection || ! $this->parent_section()) {
757
-            EE_Form_Section_Proper::$_js_localization['form_data'][ $this->html_id() ] = array(
758
-                'form_section_id'  => $this->html_id(true),
759
-                'validation_rules' => $this->get_jquery_validation_rules(),
760
-                'other_data'       => $this->get_other_js_data(),
761
-                'errors'           => $this->subsection_validation_errors_by_html_name(),
762
-            );
763
-            EE_Form_Section_Proper::$_scripts_localized                                = true;
764
-        }
765
-    }
766
-
767
-
768
-    /**
769
-     * Gets an array of extra data that will be useful for client-side javascript.
770
-     * This is primarily data added by inputs and forms in addition to any
771
-     * scripts they might enqueue
772
-     *
773
-     * @param array $form_other_js_data
774
-     * @return array
775
-     * @throws EE_Error
776
-     */
777
-    public function get_other_js_data($form_other_js_data = array())
778
-    {
779
-        foreach ($this->subsections() as $subsection) {
780
-            $form_other_js_data = $subsection->get_other_js_data($form_other_js_data);
781
-        }
782
-        return $form_other_js_data;
783
-    }
784
-
785
-
786
-    /**
787
-     * Gets a flat array of inputs for this form section and its subsections.
788
-     * Keys are their form names, and values are the inputs themselves
789
-     *
790
-     * @return EE_Form_Input_Base
791
-     * @throws EE_Error
792
-     */
793
-    public function inputs_in_subsections()
794
-    {
795
-        $inputs = array();
796
-        foreach ($this->subsections() as $subsection) {
797
-            if ($subsection instanceof EE_Form_Input_Base) {
798
-                $inputs[ $subsection->html_name() ] = $subsection;
799
-            } elseif ($subsection instanceof EE_Form_Section_Proper) {
800
-                $inputs += $subsection->inputs_in_subsections();
801
-            }
802
-        }
803
-        return $inputs;
804
-    }
805
-
806
-
807
-    /**
808
-     * Gets a flat array of all the validation errors.
809
-     * Keys are html names (because those should be unique)
810
-     * and values are a string of all their validation errors
811
-     *
812
-     * @return string[]
813
-     * @throws EE_Error
814
-     */
815
-    public function subsection_validation_errors_by_html_name()
816
-    {
817
-        $inputs = $this->inputs();
818
-        $errors = array();
819
-        foreach ($inputs as $form_input) {
820
-            if ($form_input instanceof EE_Form_Input_Base && $form_input->get_validation_errors()) {
821
-                $errors[ $form_input->html_name() ] = $form_input->get_validation_error_string();
822
-            }
823
-        }
824
-        return $errors;
825
-    }
826
-
827
-
828
-    /**
829
-     * passes all the form data required by the JS to the JS, and enqueues the few required JS files.
830
-     * Should be setup by each form during the _enqueues_and_localize_form_js
831
-     *
832
-     * @throws InvalidArgumentException
833
-     * @throws InvalidInterfaceException
834
-     * @throws InvalidDataTypeException
835
-     */
836
-    public static function localize_script_for_all_forms()
837
-    {
838
-        //allow inputs and stuff to hook in their JS and stuff here
839
-        do_action('AHEE__EE_Form_Section_Proper__localize_script_for_all_forms__begin');
840
-        EE_Form_Section_Proper::$_js_localization['localized_error_messages'] = EE_Form_Section_Proper::_get_localized_error_messages();
841
-        $email_validation_level = isset(EE_Registry::instance()->CFG->registration->email_validation_level)
842
-            ? EE_Registry::instance()->CFG->registration->email_validation_level
843
-            : 'wp_default';
844
-        EE_Form_Section_Proper::$_js_localization['email_validation_level']   = $email_validation_level;
845
-        wp_enqueue_script('ee_form_section_validation');
846
-        wp_localize_script(
847
-            'ee_form_section_validation',
848
-            'ee_form_section_vars',
849
-            EE_Form_Section_Proper::$_js_localization
850
-        );
851
-    }
852
-
853
-
854
-    /**
855
-     * ensure_scripts_localized
856
-     *
857
-     * @throws EE_Error
858
-     */
859
-    public function ensure_scripts_localized()
860
-    {
861
-        if (! EE_Form_Section_Proper::$_scripts_localized) {
862
-            $this->_enqueue_and_localize_form_js();
863
-        }
864
-    }
865
-
866
-
867
-    /**
868
-     * Gets the hard-coded validation error messages to be used in the JS. The convention
869
-     * is that the key here should be the same as the custom validation rule put in the JS file
870
-     *
871
-     * @return array keys are custom validation rules, and values are internationalized strings
872
-     */
873
-    private static function _get_localized_error_messages()
874
-    {
875
-        return array(
876
-            'validUrl' => esc_html__('This is not a valid absolute URL. Eg, http://domain.com/monkey.jpg', 'event_espresso'),
877
-            'regex'    => esc_html__('Please check your input', 'event_espresso'),
878
-        );
879
-    }
880
-
881
-
882
-    /**
883
-     * @return array
884
-     */
885
-    public static function js_localization()
886
-    {
887
-        return self::$_js_localization;
888
-    }
889
-
890
-
891
-    /**
892
-     * @return void
893
-     */
894
-    public static function reset_js_localization()
895
-    {
896
-        self::$_js_localization = array();
897
-    }
898
-
899
-
900
-    /**
901
-     * Gets the JS to put inside the jquery validation rules for subsection of this form section.
902
-     * See parent function for more...
903
-     *
904
-     * @return array
905
-     * @throws EE_Error
906
-     */
907
-    public function get_jquery_validation_rules()
908
-    {
909
-        $jquery_validation_rules = array();
910
-        foreach ($this->get_validatable_subsections() as $subsection) {
911
-            $jquery_validation_rules = array_merge(
912
-                $jquery_validation_rules,
913
-                $subsection->get_jquery_validation_rules()
914
-            );
915
-        }
916
-        return $jquery_validation_rules;
917
-    }
918
-
919
-
920
-    /**
921
-     * Sanitizes all the data and sets the sanitized value of each field
922
-     *
923
-     * @param array $req_data like $_POST
924
-     * @return void
925
-     * @throws EE_Error
926
-     */
927
-    protected function _normalize($req_data)
928
-    {
929
-        $this->_received_submission = true;
930
-        $this->_validation_errors   = array();
931
-        foreach ($this->get_validatable_subsections() as $subsection) {
932
-            try {
933
-                $subsection->_normalize($req_data);
934
-            } catch (EE_Validation_Error $e) {
935
-                $subsection->add_validation_error($e);
936
-            }
937
-        }
938
-    }
939
-
940
-
941
-    /**
942
-     * Performs validation on this form section and its subsections.
943
-     * For each subsection,
944
-     * calls _validate_{subsection_name} on THIS form (if the function exists)
945
-     * and passes it the subsection, then calls _validate on that subsection.
946
-     * If you need to perform validation on the form as a whole (considering multiple)
947
-     * you would be best to override this _validate method,
948
-     * calling parent::_validate() first.
949
-     *
950
-     * @throws EE_Error
951
-     */
952
-    protected function _validate()
953
-    {
954
-        //reset the cache of whether this form is valid or not- we're re-validating it now
955
-        $this->is_valid = null;
956
-        foreach ($this->get_validatable_subsections() as $subsection_name => $subsection) {
957
-            if (method_exists($this, '_validate_' . $subsection_name)) {
958
-                call_user_func_array(array($this, '_validate_' . $subsection_name), array($subsection));
959
-            }
960
-            $subsection->_validate();
961
-        }
962
-    }
963
-
964
-
965
-    /**
966
-     * Gets all the validated inputs for the form section
967
-     *
968
-     * @return array
969
-     * @throws EE_Error
970
-     */
971
-    public function valid_data()
972
-    {
973
-        $inputs = array();
974
-        foreach ($this->subsections() as $subsection_name => $subsection) {
975
-            if ($subsection instanceof EE_Form_Section_Proper) {
976
-                $inputs[ $subsection_name ] = $subsection->valid_data();
977
-            } elseif ($subsection instanceof EE_Form_Input_Base) {
978
-                $inputs[ $subsection_name ] = $subsection->normalized_value();
979
-            }
980
-        }
981
-        return $inputs;
982
-    }
983
-
984
-
985
-    /**
986
-     * Gets all the inputs on this form section
987
-     *
988
-     * @return EE_Form_Input_Base[]
989
-     * @throws EE_Error
990
-     */
991
-    public function inputs()
992
-    {
993
-        $inputs = array();
994
-        foreach ($this->subsections() as $subsection_name => $subsection) {
995
-            if ($subsection instanceof EE_Form_Input_Base) {
996
-                $inputs[ $subsection_name ] = $subsection;
997
-            }
998
-        }
999
-        return $inputs;
1000
-    }
1001
-
1002
-
1003
-    /**
1004
-     * Gets all the subsections which are a proper form
1005
-     *
1006
-     * @return EE_Form_Section_Proper[]
1007
-     * @throws EE_Error
1008
-     */
1009
-    public function subforms()
1010
-    {
1011
-        $form_sections = array();
1012
-        foreach ($this->subsections() as $name => $obj) {
1013
-            if ($obj instanceof EE_Form_Section_Proper) {
1014
-                $form_sections[ $name ] = $obj;
1015
-            }
1016
-        }
1017
-        return $form_sections;
1018
-    }
1019
-
1020
-
1021
-    /**
1022
-     * Gets all the subsections (inputs, proper subsections, or html-only sections).
1023
-     * Consider using inputs() or subforms()
1024
-     * if you only want form inputs or proper form sections.
1025
-     *
1026
-     * @param boolean $require_construction_to_be_finalized most client code should
1027
-     *                                                      leave this as TRUE so that the inputs will be properly
1028
-     *                                                      configured. However, some client code may be ok with
1029
-     *                                                      construction finalize being called later
1030
-     *                                                      (realizing that the subsections' html names might not be
1031
-     *                                                      set yet, etc.)
1032
-     * @return EE_Form_Section_Proper[]
1033
-     * @throws EE_Error
1034
-     */
1035
-    public function subsections($require_construction_to_be_finalized = true)
1036
-    {
1037
-        if ($require_construction_to_be_finalized) {
1038
-            $this->ensure_construct_finalized_called();
1039
-        }
1040
-        return $this->_subsections;
1041
-    }
1042
-
1043
-
1044
-    /**
1045
-     * Returns whether this form has any subforms or inputs
1046
-     * @return bool
1047
-     */
1048
-    public function hasSubsections()
1049
-    {
1050
-        return ! empty($this->_subsections);
1051
-    }
1052
-
1053
-
1054
-    /**
1055
-     * Returns a simple array where keys are input names, and values are their normalized
1056
-     * values. (Similar to calling get_input_value on inputs)
1057
-     *
1058
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1059
-     *                                        or just this forms' direct children inputs
1060
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1061
-     *                                        or allow multidimensional array
1062
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array
1063
-     *                                        with array keys being input names
1064
-     *                                        (regardless of whether they are from a subsection or not),
1065
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1066
-     *                                        where keys are always subsection names and values are either
1067
-     *                                        the input's normalized value, or an array like the top-level array
1068
-     * @throws EE_Error
1069
-     */
1070
-    public function input_values($include_subform_inputs = false, $flatten = false)
1071
-    {
1072
-        return $this->_input_values(false, $include_subform_inputs, $flatten);
1073
-    }
1074
-
1075
-
1076
-    /**
1077
-     * Similar to EE_Form_Section_Proper::input_values(), except this returns the 'display_value'
1078
-     * of each input. On some inputs (especially radio boxes or checkboxes), the value stored
1079
-     * is not necessarily the value we want to display to users. This creates an array
1080
-     * where keys are the input names, and values are their display values
1081
-     *
1082
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1083
-     *                                        or just this forms' direct children inputs
1084
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1085
-     *                                        or allow multidimensional array
1086
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array
1087
-     *                                        with array keys being input names
1088
-     *                                        (regardless of whether they are from a subsection or not),
1089
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1090
-     *                                        where keys are always subsection names and values are either
1091
-     *                                        the input's normalized value, or an array like the top-level array
1092
-     * @throws EE_Error
1093
-     */
1094
-    public function input_pretty_values($include_subform_inputs = false, $flatten = false)
1095
-    {
1096
-        return $this->_input_values(true, $include_subform_inputs, $flatten);
1097
-    }
1098
-
1099
-
1100
-    /**
1101
-     * Gets the input values from the form
1102
-     *
1103
-     * @param boolean $pretty                 Whether to retrieve the pretty value,
1104
-     *                                        or just the normalized value
1105
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1106
-     *                                        or just this forms' direct children inputs
1107
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1108
-     *                                        or allow multidimensional array
1109
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array with array keys being
1110
-     *                                        input names (regardless of whether they are from a subsection or not),
1111
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1112
-     *                                        where keys are always subsection names and values are either
1113
-     *                                        the input's normalized value, or an array like the top-level array
1114
-     * @throws EE_Error
1115
-     */
1116
-    public function _input_values($pretty = false, $include_subform_inputs = false, $flatten = false)
1117
-    {
1118
-        $input_values = array();
1119
-        foreach ($this->subsections() as $subsection_name => $subsection) {
1120
-            if ($subsection instanceof EE_Form_Input_Base) {
1121
-                $input_values[ $subsection_name ] = $pretty
1122
-                    ? $subsection->pretty_value()
1123
-                    : $subsection->normalized_value();
1124
-            } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subform_inputs) {
1125
-                $subform_input_values = $subsection->_input_values(
1126
-                    $pretty,
1127
-                    $include_subform_inputs,
1128
-                    $flatten
1129
-                );
1130
-                if ($flatten) {
1131
-                    $input_values = array_merge($input_values, $subform_input_values);
1132
-                } else {
1133
-                    $input_values[ $subsection_name ] = $subform_input_values;
1134
-                }
1135
-            }
1136
-        }
1137
-        return $input_values;
1138
-    }
1139
-
1140
-
1141
-    /**
1142
-     * Gets the originally submitted input values from the form
1143
-     *
1144
-     * @param boolean $include_subforms  Whether to include inputs from subforms,
1145
-     *                                   or just this forms' direct children inputs
1146
-     * @return array                     if $flatten is TRUE it will always be a 1-dimensional array
1147
-     *                                   with array keys being input names
1148
-     *                                   (regardless of whether they are from a subsection or not),
1149
-     *                                   and if $flatten is FALSE it can be a multidimensional array
1150
-     *                                   where keys are always subsection names and values are either
1151
-     *                                   the input's normalized value, or an array like the top-level array
1152
-     * @throws EE_Error
1153
-     */
1154
-    public function submitted_values($include_subforms = false)
1155
-    {
1156
-        $submitted_values = array();
1157
-        foreach ($this->subsections() as $subsection) {
1158
-            if ($subsection instanceof EE_Form_Input_Base) {
1159
-                // is this input part of an array of inputs?
1160
-                if (strpos($subsection->html_name(), '[') !== false) {
1161
-                    $full_input_name  = EEH_Array::convert_array_values_to_keys(
1162
-                        explode(
1163
-                            '[',
1164
-                            str_replace(']', '', $subsection->html_name())
1165
-                        ),
1166
-                        $subsection->raw_value()
1167
-                    );
1168
-                    $submitted_values = array_replace_recursive($submitted_values, $full_input_name);
1169
-                } else {
1170
-                    $submitted_values[ $subsection->html_name() ] = $subsection->raw_value();
1171
-                }
1172
-            } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subforms) {
1173
-                $subform_input_values = $subsection->submitted_values($include_subforms);
1174
-                $submitted_values     = array_replace_recursive($submitted_values, $subform_input_values);
1175
-            }
1176
-        }
1177
-        return $submitted_values;
1178
-    }
1179
-
1180
-
1181
-    /**
1182
-     * Indicates whether or not this form has received a submission yet
1183
-     * (ie, had receive_form_submission called on it yet)
1184
-     *
1185
-     * @return boolean
1186
-     * @throws EE_Error
1187
-     */
1188
-    public function has_received_submission()
1189
-    {
1190
-        $this->ensure_construct_finalized_called();
1191
-        return $this->_received_submission;
1192
-    }
1193
-
1194
-
1195
-    /**
1196
-     * Equivalent to passing 'exclude' in the constructor's options array.
1197
-     * Removes the listed inputs from the form
1198
-     *
1199
-     * @param array $inputs_to_exclude values are the input names
1200
-     * @return void
1201
-     */
1202
-    public function exclude(array $inputs_to_exclude = array())
1203
-    {
1204
-        foreach ($inputs_to_exclude as $input_to_exclude_name) {
1205
-            unset($this->_subsections[ $input_to_exclude_name ]);
1206
-        }
1207
-    }
1208
-
1209
-
1210
-    /**
1211
-     * @param array $inputs_to_hide
1212
-     * @throws EE_Error
1213
-     */
1214
-    public function hide(array $inputs_to_hide = array())
1215
-    {
1216
-        foreach ($inputs_to_hide as $input_to_hide) {
1217
-            $input = $this->get_input($input_to_hide);
1218
-            $input->set_display_strategy(new EE_Hidden_Display_Strategy());
1219
-        }
1220
-    }
1221
-
1222
-
1223
-    /**
1224
-     * add_subsections
1225
-     * Adds the listed subsections to the form section.
1226
-     * If $subsection_name_to_target is provided,
1227
-     * then new subsections are added before or after that subsection,
1228
-     * otherwise to the start or end of the entire subsections array.
1229
-     *
1230
-     * @param EE_Form_Section_Base[] $new_subsections           array of new form subsections
1231
-     *                                                          where keys are their names
1232
-     * @param string                 $subsection_name_to_target an existing for section that $new_subsections
1233
-     *                                                          should be added before or after
1234
-     *                                                          IF $subsection_name_to_target is null,
1235
-     *                                                          then $new_subsections will be added to
1236
-     *                                                          the beginning or end of the entire subsections array
1237
-     * @param boolean                $add_before                whether to add $new_subsections, before or after
1238
-     *                                                          $subsection_name_to_target,
1239
-     *                                                          or if $subsection_name_to_target is null,
1240
-     *                                                          before or after entire subsections array
1241
-     * @return void
1242
-     * @throws EE_Error
1243
-     */
1244
-    public function add_subsections($new_subsections, $subsection_name_to_target = null, $add_before = true)
1245
-    {
1246
-        foreach ($new_subsections as $subsection_name => $subsection) {
1247
-            if (! $subsection instanceof EE_Form_Section_Base) {
1248
-                EE_Error::add_error(
1249
-                    sprintf(
1250
-                        esc_html__(
1251
-                            "Trying to add a %s as a subsection (it was named '%s') to the form section '%s'. It was removed.",
1252
-                            'event_espresso'
1253
-                        ),
1254
-                        get_class($subsection),
1255
-                        $subsection_name,
1256
-                        $this->name()
1257
-                    )
1258
-                );
1259
-                unset($new_subsections[ $subsection_name ]);
1260
-            }
1261
-        }
1262
-        $this->_subsections = EEH_Array::insert_into_array(
1263
-            $this->_subsections,
1264
-            $new_subsections,
1265
-            $subsection_name_to_target,
1266
-            $add_before
1267
-        );
1268
-        if ($this->_construction_finalized) {
1269
-            foreach ($this->_subsections as $name => $subsection) {
1270
-                $subsection->_construct_finalize($this, $name);
1271
-            }
1272
-        }
1273
-    }
1274
-
1275
-
1276
-    /**
1277
-     * Just gets all validatable subsections to clean their sensitive data
1278
-     *
1279
-     * @throws EE_Error
1280
-     */
1281
-    public function clean_sensitive_data()
1282
-    {
1283
-        foreach ($this->get_validatable_subsections() as $subsection) {
1284
-            $subsection->clean_sensitive_data();
1285
-        }
1286
-    }
1287
-
1288
-
1289
-    /**
1290
-     * Sets the submission error message (aka validation error message for this form section and all sub-sections)
1291
-     * @param string                           $form_submission_error_message
1292
-     * @param EE_Form_Section_Validatable $form_section unused
1293
-     * @throws EE_Error
1294
-     */
1295
-    public function set_submission_error_message(
1296
-        $form_submission_error_message = ''
1297
-    ) {
1298
-        $this->_form_submission_error_message = ! empty($form_submission_error_message)
1299
-            ? $form_submission_error_message
1300
-            : $this->getAllValidationErrorsString();
1301
-    }
1302
-
1303
-
1304
-    /**
1305
-     * Returns the cached error message. A default value is set for this during _validate(),
1306
-     * (called during receive_form_submission) but it can be explicitly set using
1307
-     * set_submission_error_message
1308
-     *
1309
-     * @return string
1310
-     */
1311
-    public function submission_error_message()
1312
-    {
1313
-        return $this->_form_submission_error_message;
1314
-    }
1315
-
1316
-
1317
-    /**
1318
-     * Sets a message to display if the data submitted to the form was valid.
1319
-     * @param string $form_submission_success_message
1320
-     */
1321
-    public function set_submission_success_message($form_submission_success_message = '')
1322
-    {
1323
-        $this->_form_submission_success_message = ! empty($form_submission_success_message)
1324
-            ? $form_submission_success_message
1325
-            : esc_html__('Form submitted successfully', 'event_espresso');
1326
-    }
1327
-
1328
-
1329
-    /**
1330
-     * Gets a message appropriate for display when the form is correctly submitted
1331
-     * @return string
1332
-     */
1333
-    public function submission_success_message()
1334
-    {
1335
-        return $this->_form_submission_success_message;
1336
-    }
1337
-
1338
-
1339
-    /**
1340
-     * Returns the prefix that should be used on child of this form section for
1341
-     * their html names. If this form section itself has a parent, prepends ITS
1342
-     * prefix onto this form section's prefix. Used primarily by
1343
-     * EE_Form_Input_Base::_set_default_html_name_if_empty
1344
-     *
1345
-     * @return string
1346
-     * @throws EE_Error
1347
-     */
1348
-    public function html_name_prefix()
1349
-    {
1350
-        if ($this->parent_section() instanceof EE_Form_Section_Proper) {
1351
-            return $this->parent_section()->html_name_prefix() . '[' . $this->name() . ']';
1352
-        }
1353
-        return $this->name();
1354
-    }
1355
-
1356
-
1357
-    /**
1358
-     * Gets the name, but first checks _construct_finalize has been called. If not,
1359
-     * calls it (assumes there is no parent and that we want the name to be whatever
1360
-     * was set, which is probably nothing, or the classname)
1361
-     *
1362
-     * @return string
1363
-     * @throws EE_Error
1364
-     */
1365
-    public function name()
1366
-    {
1367
-        $this->ensure_construct_finalized_called();
1368
-        return parent::name();
1369
-    }
1370
-
1371
-
1372
-    /**
1373
-     * @return EE_Form_Section_Proper
1374
-     * @throws EE_Error
1375
-     */
1376
-    public function parent_section()
1377
-    {
1378
-        $this->ensure_construct_finalized_called();
1379
-        return parent::parent_section();
1380
-    }
1381
-
1382
-
1383
-    /**
1384
-     * make sure construction finalized was called, otherwise children might not be ready
1385
-     *
1386
-     * @return void
1387
-     * @throws EE_Error
1388
-     */
1389
-    public function ensure_construct_finalized_called()
1390
-    {
1391
-        if (! $this->_construction_finalized) {
1392
-            $this->_construct_finalize($this->_parent_section, $this->_name);
1393
-        }
1394
-    }
1395
-
1396
-
1397
-    /**
1398
-     * Checks if any of this form section's inputs, or any of its children's inputs,
1399
-     * are in teh form data. If any are found, returns true. Else false
1400
-     *
1401
-     * @param array $req_data
1402
-     * @return boolean
1403
-     * @throws EE_Error
1404
-     */
1405
-    public function form_data_present_in($req_data = null)
1406
-    {
1407
-        $req_data = $this->getCachedRequest($req_data);
1408
-        foreach ($this->subsections() as $subsection) {
1409
-            if ($subsection instanceof EE_Form_Input_Base) {
1410
-                if ($subsection->form_data_present_in($req_data)) {
1411
-                    return true;
1412
-                }
1413
-            } elseif ($subsection instanceof EE_Form_Section_Proper) {
1414
-                if ($subsection->form_data_present_in($req_data)) {
1415
-                    return true;
1416
-                }
1417
-            }
1418
-        }
1419
-        return false;
1420
-    }
1421
-
1422
-
1423
-    /**
1424
-     * Gets validation errors for this form section and subsections
1425
-     * Similar to EE_Form_Section_Validatable::get_validation_errors() except this
1426
-     * gets the validation errors for ALL subsection
1427
-     *
1428
-     * @return EE_Validation_Error[]
1429
-     * @throws EE_Error
1430
-     */
1431
-    public function get_validation_errors_accumulated()
1432
-    {
1433
-        $validation_errors = $this->get_validation_errors();
1434
-        foreach ($this->get_validatable_subsections() as $subsection) {
1435
-            if ($subsection instanceof EE_Form_Section_Proper) {
1436
-                $validation_errors_on_this_subsection = $subsection->get_validation_errors_accumulated();
1437
-            } else {
1438
-                $validation_errors_on_this_subsection = $subsection->get_validation_errors();
1439
-            }
1440
-            if ($validation_errors_on_this_subsection) {
1441
-                $validation_errors = array_merge($validation_errors, $validation_errors_on_this_subsection);
1442
-            }
1443
-        }
1444
-        return $validation_errors;
1445
-    }
1446
-
1447
-    /**
1448
-     * Fetch validation errors from children and grandchildren and puts them in a single string.
1449
-     * This traverses the form section tree to generate this, but you probably want to instead use
1450
-     * get_form_submission_error_message() which is usually this message cached (or a custom validation error message)
1451
-     *
1452
-     * @return string
1453
-     * @since $VID:$
1454
-     */
1455
-    protected function getAllValidationErrorsString()
1456
-    {
1457
-        $submission_error_messages = array();
1458
-        // bad, bad, bad registrant
1459
-        foreach ($this->get_validation_errors_accumulated() as $validation_error) {
1460
-            if ($validation_error instanceof EE_Validation_Error) {
1461
-                $form_section = $validation_error->get_form_section();
1462
-                if ($form_section instanceof EE_Form_Input_Base) {
1463
-                   $label = $validation_error->get_form_section()->html_label_text();
1464
-                } elseif($form_section instanceof EE_Form_Section_Validatable) {
1465
-                    $label = $validation_error->get_form_section()->name();
1466
-                } else {
1467
-                    $label = esc_html__('Unknown', 'event_espresso');
1468
-                }
1469
-                $submission_error_messages[] = sprintf(
1470
-                    __('%s : %s', 'event_espresso'),
1471
-                    $label,
1472
-                    $validation_error->getMessage()
1473
-                );
1474
-            }
1475
-        }
1476
-        return implode('<br', $submission_error_messages);
1477
-    }
1478
-
1479
-
1480
-    /**
1481
-     * This isn't just the name of an input, it's a path pointing to an input. The
1482
-     * path is similar to a folder path: slash (/) means to descend into a subsection,
1483
-     * dot-dot-slash (../) means to ascend into the parent section.
1484
-     * After a series of slashes and dot-dot-slashes, there should be the name of an input,
1485
-     * which will be returned.
1486
-     * Eg, if you want the related input to be conditional on a sibling input name 'foobar'
1487
-     * just use 'foobar'. If you want it to be conditional on an aunt/uncle input name
1488
-     * 'baz', use '../baz'. If you want it to be conditional on a cousin input,
1489
-     * the child of 'baz_section' named 'baz_child', use '../baz_section/baz_child'.
1490
-     * Etc
1491
-     *
1492
-     * @param string|false $form_section_path we accept false also because substr( '../', '../' ) = false
1493
-     * @return EE_Form_Section_Base
1494
-     * @throws EE_Error
1495
-     */
1496
-    public function find_section_from_path($form_section_path)
1497
-    {
1498
-        //check if we can find the input from purely going straight up the tree
1499
-        $input = parent::find_section_from_path($form_section_path);
1500
-        if ($input instanceof EE_Form_Section_Base) {
1501
-            return $input;
1502
-        }
1503
-        $next_slash_pos = strpos($form_section_path, '/');
1504
-        if ($next_slash_pos !== false) {
1505
-            $child_section_name = substr($form_section_path, 0, $next_slash_pos);
1506
-            $subpath            = substr($form_section_path, $next_slash_pos + 1);
1507
-        } else {
1508
-            $child_section_name = $form_section_path;
1509
-            $subpath            = '';
1510
-        }
1511
-        $child_section = $this->get_subsection($child_section_name);
1512
-        if ($child_section instanceof EE_Form_Section_Base) {
1513
-            return $child_section->find_section_from_path($subpath);
1514
-        }
1515
-        return null;
1516
-    }
17
+	const SUBMITTED_FORM_DATA_SSN_KEY = 'submitted_form_data';
18
+
19
+	/**
20
+	 * Subsections
21
+	 *
22
+	 * @var EE_Form_Section_Validatable[]
23
+	 */
24
+	protected $_subsections = array();
25
+
26
+	/**
27
+	 * Strategy for laying out the form
28
+	 *
29
+	 * @var EE_Form_Section_Layout_Base
30
+	 */
31
+	protected $_layout_strategy;
32
+
33
+	/**
34
+	 * Whether or not this form has received and validated a form submission yet
35
+	 *
36
+	 * @var boolean
37
+	 */
38
+	protected $_received_submission = false;
39
+
40
+	/**
41
+	 * message displayed to users upon successful form submission
42
+	 *
43
+	 * @var string
44
+	 */
45
+	protected $_form_submission_success_message = '';
46
+
47
+	/**
48
+	 * message displayed to users upon unsuccessful form submission
49
+	 *
50
+	 * @var string
51
+	 */
52
+	protected $_form_submission_error_message = '';
53
+
54
+	/**
55
+	 * @var array like $_REQUEST
56
+	 */
57
+	protected $cached_request_data;
58
+
59
+	/**
60
+	 * Stores whether this form (and its sub-sections) were found to be valid or not.
61
+	 * Starts off as null, but once the form is validated, it set to either true or false
62
+	 * @var boolean|null
63
+	 */
64
+	protected $is_valid;
65
+
66
+	/**
67
+	 * Stores all the data that will localized for form validation
68
+	 *
69
+	 * @var array
70
+	 */
71
+	static protected $_js_localization = array();
72
+
73
+	/**
74
+	 * whether or not the form's localized validation JS vars have been set
75
+	 *
76
+	 * @type boolean
77
+	 */
78
+	static protected $_scripts_localized = false;
79
+
80
+
81
+	/**
82
+	 * when constructing a proper form section, calls _construct_finalize on children
83
+	 * so that they know who their parent is, and what name they've been given.
84
+	 *
85
+	 * @param array[] $options_array   {
86
+	 * @type          $subsections     EE_Form_Section_Validatable[] where keys are the section's name
87
+	 * @type          $include         string[] numerically-indexed where values are section names to be included,
88
+	 *                                 and in that order. This is handy if you want
89
+	 *                                 the subsections to be ordered differently than the default, and if you override
90
+	 *                                 which fields are shown
91
+	 * @type          $exclude         string[] values are subsections to be excluded. This is handy if you want
92
+	 *                                 to remove certain default subsections (note: if you specify BOTH 'include' AND
93
+	 *                                 'exclude', the inclusions will be applied first, and the exclusions will exclude
94
+	 *                                 items from that list of inclusions)
95
+	 * @type          $layout_strategy EE_Form_Section_Layout_Base strategy for laying out the form
96
+	 *                                 } @see EE_Form_Section_Validatable::__construct()
97
+	 * @throws EE_Error
98
+	 */
99
+	public function __construct($options_array = array())
100
+	{
101
+		$options_array = (array) apply_filters(
102
+			'FHEE__EE_Form_Section_Proper___construct__options_array',
103
+			$options_array,
104
+			$this
105
+		);
106
+		//call parent first, as it may be setting the name
107
+		parent::__construct($options_array);
108
+		//if they've included subsections in the constructor, add them now
109
+		if (isset($options_array['include'])) {
110
+			//we are going to make sure we ONLY have those subsections to include
111
+			//AND we are going to make sure they're in that specified order
112
+			$reordered_subsections = array();
113
+			foreach ($options_array['include'] as $input_name) {
114
+				if (isset($this->_subsections[ $input_name ])) {
115
+					$reordered_subsections[ $input_name ] = $this->_subsections[ $input_name ];
116
+				}
117
+			}
118
+			$this->_subsections = $reordered_subsections;
119
+		}
120
+		if (isset($options_array['exclude'])) {
121
+			$exclude            = $options_array['exclude'];
122
+			$this->_subsections = array_diff_key($this->_subsections, array_flip($exclude));
123
+		}
124
+		if (isset($options_array['layout_strategy'])) {
125
+			$this->_layout_strategy = $options_array['layout_strategy'];
126
+		}
127
+		if (! $this->_layout_strategy) {
128
+			$this->_layout_strategy = is_admin() ? new EE_Admin_Two_Column_Layout() : new EE_Two_Column_Layout();
129
+		}
130
+		$this->_layout_strategy->_construct_finalize($this);
131
+		//ok so we are definitely going to want the forms JS,
132
+		//so enqueue it or remember to enqueue it during wp_enqueue_scripts
133
+		if (did_action('wp_enqueue_scripts') || did_action('admin_enqueue_scripts')) {
134
+			//ok so they've constructed this object after when they should have.
135
+			//just enqueue the generic form scripts and initialize the form immediately in the JS
136
+			EE_Form_Section_Proper::wp_enqueue_scripts(true);
137
+		} else {
138
+			add_action('wp_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
139
+			add_action('admin_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
140
+		}
141
+		add_action('wp_footer', array($this, 'ensure_scripts_localized'), 1);
142
+		/**
143
+		 * Gives other plugins a chance to hook in before construct finalize is called.
144
+		 * The form probably doesn't yet have a parent form section.
145
+		 * Since 4.9.32, when this action was introduced, this is the best place to add a subsection onto a form,
146
+		 * assuming you don't care what the form section's name, HTML ID, or HTML name etc are.
147
+		 * Also see AHEE__EE_Form_Section_Proper___construct_finalize__end
148
+		 *
149
+		 * @since 4.9.32
150
+		 * @param EE_Form_Section_Proper $this          before __construct is done, but all of its logic,
151
+		 *                                              except maybe calling _construct_finalize has been done
152
+		 * @param array                  $options_array options passed into the constructor
153
+		 */
154
+		do_action(
155
+			'AHEE__EE_Form_Input_Base___construct__before_construct_finalize_called',
156
+			$this,
157
+			$options_array
158
+		);
159
+		if (isset($options_array['name'])) {
160
+			$this->_construct_finalize(null, $options_array['name']);
161
+		}
162
+	}
163
+
164
+
165
+	/**
166
+	 * Finishes construction given the parent form section and this form section's name
167
+	 *
168
+	 * @param EE_Form_Section_Proper $parent_form_section
169
+	 * @param string                 $name
170
+	 * @throws EE_Error
171
+	 */
172
+	public function _construct_finalize($parent_form_section, $name)
173
+	{
174
+		parent::_construct_finalize($parent_form_section, $name);
175
+		$this->_set_default_name_if_empty();
176
+		$this->_set_default_html_id_if_empty();
177
+		foreach ($this->_subsections as $subsection_name => $subsection) {
178
+			if ($subsection instanceof EE_Form_Section_Base) {
179
+				$subsection->_construct_finalize($this, $subsection_name);
180
+			} else {
181
+				throw new EE_Error(
182
+					sprintf(
183
+						esc_html__(
184
+							'Subsection "%s" is not an instanceof EE_Form_Section_Base on form "%s". It is a "%s"',
185
+							'event_espresso'
186
+						),
187
+						$subsection_name,
188
+						get_class($this),
189
+						$subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
190
+					)
191
+				);
192
+			}
193
+		}
194
+		/**
195
+		 * Action performed just after form has been given a name (and HTML ID etc) and is fully constructed.
196
+		 * If you have code that should modify the form and needs it and its subsections to have a name, HTML ID
197
+		 * (or other attributes derived from the name like the HTML label id, etc), this is where it should be done.
198
+		 * This might only happen just before displaying the form, or just before it receives form submission data.
199
+		 * If you need to modify the form or its subsections before _construct_finalize is called on it (and we've
200
+		 * ensured it has a name, HTML IDs, etc
201
+		 *
202
+		 * @param EE_Form_Section_Proper      $this
203
+		 * @param EE_Form_Section_Proper|null $parent_form_section
204
+		 * @param string                      $name
205
+		 */
206
+		do_action(
207
+			'AHEE__EE_Form_Section_Proper___construct_finalize__end',
208
+			$this,
209
+			$parent_form_section,
210
+			$name
211
+		);
212
+	}
213
+
214
+
215
+	/**
216
+	 * Gets the layout strategy for this form section
217
+	 *
218
+	 * @return EE_Form_Section_Layout_Base
219
+	 */
220
+	public function get_layout_strategy()
221
+	{
222
+		return $this->_layout_strategy;
223
+	}
224
+
225
+
226
+	/**
227
+	 * Gets the HTML for a single input for this form section according
228
+	 * to the layout strategy
229
+	 *
230
+	 * @param EE_Form_Input_Base $input
231
+	 * @return string
232
+	 */
233
+	public function get_html_for_input($input)
234
+	{
235
+		return $this->_layout_strategy->layout_input($input);
236
+	}
237
+
238
+
239
+	/**
240
+	 * was_submitted - checks if form inputs are present in request data
241
+	 * Basically an alias for form_data_present_in() (which is used by both
242
+	 * proper form sections and form inputs)
243
+	 *
244
+	 * @param null $form_data
245
+	 * @return boolean
246
+	 * @throws EE_Error
247
+	 */
248
+	public function was_submitted($form_data = null)
249
+	{
250
+		return $this->form_data_present_in($form_data);
251
+	}
252
+
253
+	/**
254
+	 * Gets the cached request data; but if there is none, or $req_data was set with
255
+	 * something different, refresh the cache, and then return it
256
+	 * @param null $req_data
257
+	 * @return array
258
+	 */
259
+	protected function getCachedRequest($req_data = null)
260
+	{
261
+		if ($this->cached_request_data === null
262
+			|| (
263
+				$req_data !== null &&
264
+				$req_data !== $this->cached_request_data
265
+			)
266
+		) {
267
+			$req_data = apply_filters(
268
+				'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
269
+				$req_data,
270
+				$this
271
+			);
272
+			if ($req_data === null) {
273
+				$req_data = array_merge($_GET, $_POST);
274
+			}
275
+			$req_data = apply_filters(
276
+				'FHEE__EE_Form_Section_Proper__receive_form_submission__request_data',
277
+				$req_data,
278
+				$this
279
+			);
280
+			$this->cached_request_data = (array)$req_data;
281
+		}
282
+		return $this->cached_request_data;
283
+	}
284
+
285
+
286
+	/**
287
+	 * After the form section is initially created, call this to sanitize the data in the submission
288
+	 * which relates to this form section, validate it, and set it as properties on the form.
289
+	 *
290
+	 * @param array|null $req_data should usually be $_POST (the default).
291
+	 *                             However, you CAN supply a different array.
292
+	 *                             Consider using set_defaults() instead however.
293
+	 *                             (If you rendered the form in the page using echo $form_x->get_html()
294
+	 *                             the inputs will have the correct name in the request data for this function
295
+	 *                             to find them and populate the form with them.
296
+	 *                             If you have a flat form (with only input subsections),
297
+	 *                             you can supply a flat array where keys
298
+	 *                             are the form input names and values are their values)
299
+	 * @param boolean    $validate whether or not to perform validation on this data. Default is,
300
+	 *                             of course, to validate that data, and set errors on the invalid values.
301
+	 *                             But if the data has already been validated
302
+	 *                             (eg you validated the data then stored it in the DB)
303
+	 *                             you may want to skip this step.
304
+	 * @throws InvalidArgumentException
305
+	 * @throws InvalidInterfaceException
306
+	 * @throws InvalidDataTypeException
307
+	 * @throws EE_Error
308
+	 */
309
+	public function receive_form_submission($req_data = null, $validate = true)
310
+	{
311
+		$req_data = $this->getCachedRequest($req_data);
312
+		$this->_normalize($req_data);
313
+		if ($validate) {
314
+			$this->_validate();
315
+			//if it's invalid, we're going to want to re-display so remember what they submitted
316
+			if (! $this->is_valid()) {
317
+				$this->store_submitted_form_data_in_session();
318
+			}
319
+		}
320
+		if ($this->submission_error_message() === '' && ! $this->is_valid()) {
321
+			$this->set_submission_error_message();
322
+		}
323
+		do_action(
324
+			'AHEE__EE_Form_Section_Proper__receive_form_submission__end',
325
+			$req_data,
326
+			$this,
327
+			$validate
328
+		);
329
+	}
330
+
331
+
332
+	/**
333
+	 * caches the originally submitted input values in the session
334
+	 * so that they can be used to repopulate the form if it failed validation
335
+	 *
336
+	 * @return boolean whether or not the data was successfully stored in the session
337
+	 * @throws InvalidArgumentException
338
+	 * @throws InvalidInterfaceException
339
+	 * @throws InvalidDataTypeException
340
+	 * @throws EE_Error
341
+	 */
342
+	protected function store_submitted_form_data_in_session()
343
+	{
344
+		return EE_Registry::instance()->SSN->set_session_data(
345
+			array(
346
+				EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY => $this->submitted_values(true),
347
+			)
348
+		);
349
+	}
350
+
351
+
352
+	/**
353
+	 * retrieves the originally submitted input values in the session
354
+	 * so that they can be used to repopulate the form if it failed validation
355
+	 *
356
+	 * @return array
357
+	 * @throws InvalidArgumentException
358
+	 * @throws InvalidInterfaceException
359
+	 * @throws InvalidDataTypeException
360
+	 */
361
+	protected function get_submitted_form_data_from_session()
362
+	{
363
+		$session = EE_Registry::instance()->SSN;
364
+		if ($session instanceof EE_Session) {
365
+			return $session->get_session_data(
366
+				EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY
367
+			);
368
+		}
369
+		return array();
370
+	}
371
+
372
+
373
+	/**
374
+	 * flushed the originally submitted input values from the session
375
+	 *
376
+	 * @return boolean whether or not the data was successfully removed from the session
377
+	 * @throws InvalidArgumentException
378
+	 * @throws InvalidInterfaceException
379
+	 * @throws InvalidDataTypeException
380
+	 */
381
+	protected function flush_submitted_form_data_from_session()
382
+	{
383
+		return EE_Registry::instance()->SSN->reset_data(
384
+			array(EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY)
385
+		);
386
+	}
387
+
388
+
389
+	/**
390
+	 * Populates this form and its subsections with data from the session.
391
+	 * (Wrapper for EE_Form_Section_Proper::receive_form_submission, so it shows
392
+	 * validation errors when displaying too)
393
+	 * Returns true if the form was populated from the session, false otherwise
394
+	 *
395
+	 * @return boolean
396
+	 * @throws InvalidArgumentException
397
+	 * @throws InvalidInterfaceException
398
+	 * @throws InvalidDataTypeException
399
+	 * @throws EE_Error
400
+	 */
401
+	public function populate_from_session()
402
+	{
403
+		$form_data_in_session = $this->get_submitted_form_data_from_session();
404
+		if (empty($form_data_in_session)) {
405
+			return false;
406
+		}
407
+		$this->receive_form_submission($form_data_in_session);
408
+		$this->flush_submitted_form_data_from_session();
409
+		if ($this->form_data_present_in($form_data_in_session)) {
410
+			return true;
411
+		}
412
+		return false;
413
+	}
414
+
415
+
416
+	/**
417
+	 * Populates the default data for the form, given an array where keys are
418
+	 * the input names, and values are their values (preferably normalized to be their
419
+	 * proper PHP types, not all strings... although that should be ok too).
420
+	 * Proper subsections are sub-arrays, the key being the subsection's name, and
421
+	 * the value being an array formatted in teh same way
422
+	 *
423
+	 * @param array $default_data
424
+	 * @throws EE_Error
425
+	 */
426
+	public function populate_defaults($default_data)
427
+	{
428
+		foreach ($this->subsections(false) as $subsection_name => $subsection) {
429
+			if (isset($default_data[ $subsection_name ])) {
430
+				if ($subsection instanceof EE_Form_Input_Base) {
431
+					$subsection->set_default($default_data[ $subsection_name ]);
432
+				} elseif ($subsection instanceof EE_Form_Section_Proper) {
433
+					$subsection->populate_defaults($default_data[ $subsection_name ]);
434
+				}
435
+			}
436
+		}
437
+	}
438
+
439
+
440
+	/**
441
+	 * returns true if subsection exists
442
+	 *
443
+	 * @param string $name
444
+	 * @return boolean
445
+	 */
446
+	public function subsection_exists($name)
447
+	{
448
+		return isset($this->_subsections[ $name ]) ? true : false;
449
+	}
450
+
451
+
452
+	/**
453
+	 * Gets the subsection specified by its name
454
+	 *
455
+	 * @param string  $name
456
+	 * @param boolean $require_construction_to_be_finalized most client code should leave this as TRUE
457
+	 *                                                      so that the inputs will be properly configured.
458
+	 *                                                      However, some client code may be ok
459
+	 *                                                      with construction finalize being called later
460
+	 *                                                      (realizing that the subsections' html names
461
+	 *                                                      might not be set yet, etc.)
462
+	 * @return EE_Form_Section_Base
463
+	 * @throws EE_Error
464
+	 */
465
+	public function get_subsection($name, $require_construction_to_be_finalized = true)
466
+	{
467
+		if ($require_construction_to_be_finalized) {
468
+			$this->ensure_construct_finalized_called();
469
+		}
470
+		return $this->subsection_exists($name) ? $this->_subsections[ $name ] : null;
471
+	}
472
+
473
+
474
+	/**
475
+	 * Gets all the validatable subsections of this form section
476
+	 *
477
+	 * @return EE_Form_Section_Validatable[]
478
+	 * @throws EE_Error
479
+	 */
480
+	public function get_validatable_subsections()
481
+	{
482
+		$validatable_subsections = array();
483
+		foreach ($this->subsections() as $name => $obj) {
484
+			if ($obj instanceof EE_Form_Section_Validatable) {
485
+				$validatable_subsections[ $name ] = $obj;
486
+			}
487
+		}
488
+		return $validatable_subsections;
489
+	}
490
+
491
+
492
+	/**
493
+	 * Gets an input by the given name. If not found, or if its not an EE_FOrm_Input_Base child,
494
+	 * throw an EE_Error.
495
+	 *
496
+	 * @param string  $name
497
+	 * @param boolean $require_construction_to_be_finalized most client code should
498
+	 *                                                      leave this as TRUE so that the inputs will be properly
499
+	 *                                                      configured. However, some client code may be ok with
500
+	 *                                                      construction finalize being called later
501
+	 *                                                      (realizing that the subsections' html names might not be
502
+	 *                                                      set yet, etc.)
503
+	 * @return EE_Form_Input_Base
504
+	 * @throws EE_Error
505
+	 */
506
+	public function get_input($name, $require_construction_to_be_finalized = true)
507
+	{
508
+		$subsection = $this->get_subsection(
509
+			$name,
510
+			$require_construction_to_be_finalized
511
+		);
512
+		if (! $subsection instanceof EE_Form_Input_Base) {
513
+			throw new EE_Error(
514
+				sprintf(
515
+					esc_html__(
516
+						"Subsection '%s' is not an instanceof EE_Form_Input_Base on form '%s'. It is a '%s'",
517
+						'event_espresso'
518
+					),
519
+					$name,
520
+					get_class($this),
521
+					$subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
522
+				)
523
+			);
524
+		}
525
+		return $subsection;
526
+	}
527
+
528
+
529
+	/**
530
+	 * Like get_input(), gets the proper subsection of the form given the name,
531
+	 * otherwise throws an EE_Error
532
+	 *
533
+	 * @param string  $name
534
+	 * @param boolean $require_construction_to_be_finalized most client code should
535
+	 *                                                      leave this as TRUE so that the inputs will be properly
536
+	 *                                                      configured. However, some client code may be ok with
537
+	 *                                                      construction finalize being called later
538
+	 *                                                      (realizing that the subsections' html names might not be
539
+	 *                                                      set yet, etc.)
540
+	 * @return EE_Form_Section_Proper
541
+	 * @throws EE_Error
542
+	 */
543
+	public function get_proper_subsection($name, $require_construction_to_be_finalized = true)
544
+	{
545
+		$subsection = $this->get_subsection(
546
+			$name,
547
+			$require_construction_to_be_finalized
548
+		);
549
+		if (! $subsection instanceof EE_Form_Section_Proper) {
550
+			throw new EE_Error(
551
+				sprintf(
552
+					esc_html__(
553
+						"Subsection '%'s is not an instanceof EE_Form_Section_Proper on form '%s'",
554
+						'event_espresso'
555
+					),
556
+					$name,
557
+					get_class($this)
558
+				)
559
+			);
560
+		}
561
+		return $subsection;
562
+	}
563
+
564
+
565
+	/**
566
+	 * Gets the value of the specified input. Should be called after receive_form_submission()
567
+	 * or populate_defaults() on the form, where the normalized value on the input is set.
568
+	 *
569
+	 * @param string $name
570
+	 * @return mixed depending on the input's type and its normalization strategy
571
+	 * @throws EE_Error
572
+	 */
573
+	public function get_input_value($name)
574
+	{
575
+		$input = $this->get_input($name);
576
+		return $input->normalized_value();
577
+	}
578
+
579
+
580
+	/**
581
+	 * Checks if this form section itself is valid, and then checks its subsections
582
+	 *
583
+	 * @throws EE_Error
584
+	 * @return boolean
585
+	 */
586
+	public function is_valid()
587
+	{
588
+		if($this->is_valid === null) {
589
+			if (! $this->has_received_submission()) {
590
+				throw new EE_Error(
591
+					sprintf(
592
+						esc_html__(
593
+							'You cannot check if a form is valid before receiving the form submission using receive_form_submission',
594
+							'event_espresso'
595
+						)
596
+					)
597
+				);
598
+			}
599
+			if (! parent::is_valid()) {
600
+				$this->is_valid = false;
601
+			} else {
602
+				// ok so no general errors to this entire form section.
603
+				// so let's check the subsections, but only set errors if that hasn't been done yet
604
+				$this->is_valid = true;
605
+				foreach ($this->get_validatable_subsections() as $subsection) {
606
+					if (! $subsection->is_valid()) {
607
+						$this->is_valid = false;
608
+					}
609
+				}
610
+			}
611
+		}
612
+		return $this->is_valid;
613
+	}
614
+
615
+
616
+	/**
617
+	 * gets the default name of this form section if none is specified
618
+	 *
619
+	 * @return void
620
+	 */
621
+	protected function _set_default_name_if_empty()
622
+	{
623
+		if (! $this->_name) {
624
+			$classname    = get_class($this);
625
+			$default_name = str_replace('EE_', '', $classname);
626
+			$this->_name  = $default_name;
627
+		}
628
+	}
629
+
630
+
631
+	/**
632
+	 * Returns the HTML for the form, except for the form opening and closing tags
633
+	 * (as the form section doesn't know where you necessarily want to send the information to),
634
+	 * and except for a submit button. Enqueues JS and CSS; if called early enough we will
635
+	 * try to enqueue them in the header, otherwise they'll be enqueued in the footer.
636
+	 * Not doing_it_wrong because theoretically this CAN be used properly,
637
+	 * provided its used during "wp_enqueue_scripts", or it doesn't need to enqueue
638
+	 * any CSS.
639
+	 *
640
+	 * @throws InvalidArgumentException
641
+	 * @throws InvalidInterfaceException
642
+	 * @throws InvalidDataTypeException
643
+	 * @throws EE_Error
644
+	 */
645
+	public function get_html_and_js()
646
+	{
647
+		$this->enqueue_js();
648
+		return $this->get_html();
649
+	}
650
+
651
+
652
+	/**
653
+	 * returns HTML for displaying this form section. recursively calls display_section() on all subsections
654
+	 *
655
+	 * @param bool $display_previously_submitted_data
656
+	 * @return string
657
+	 * @throws InvalidArgumentException
658
+	 * @throws InvalidInterfaceException
659
+	 * @throws InvalidDataTypeException
660
+	 * @throws EE_Error
661
+	 * @throws EE_Error
662
+	 * @throws EE_Error
663
+	 */
664
+	public function get_html($display_previously_submitted_data = true)
665
+	{
666
+		$this->ensure_construct_finalized_called();
667
+		if ($display_previously_submitted_data) {
668
+			$this->populate_from_session();
669
+		}
670
+		return $this->_form_html_filter
671
+			? $this->_form_html_filter->filterHtml($this->_layout_strategy->layout_form(), $this)
672
+			: $this->_layout_strategy->layout_form();
673
+	}
674
+
675
+
676
+	/**
677
+	 * enqueues JS and CSS for the form.
678
+	 * It is preferred to call this before wp_enqueue_scripts so the
679
+	 * scripts and styles can be put in the header, but if called later
680
+	 * they will be put in the footer (which is OK for JS, but in HTML4 CSS should
681
+	 * only be in the header; but in HTML5 its ok in the body.
682
+	 * See http://stackoverflow.com/questions/4957446/load-external-css-file-in-body-tag.
683
+	 * So if your form enqueues CSS, it's preferred to call this before wp_enqueue_scripts.)
684
+	 *
685
+	 * @return void
686
+	 * @throws EE_Error
687
+	 */
688
+	public function enqueue_js()
689
+	{
690
+		$this->_enqueue_and_localize_form_js();
691
+		foreach ($this->subsections() as $subsection) {
692
+			$subsection->enqueue_js();
693
+		}
694
+	}
695
+
696
+
697
+	/**
698
+	 * adds a filter so that jquery validate gets enqueued in EE_System::wp_enqueue_scripts().
699
+	 * This must be done BEFORE wp_enqueue_scripts() gets called, which is on
700
+	 * the wp_enqueue_scripts hook.
701
+	 * However, registering the form js and localizing it can happen when we
702
+	 * actually output the form (which is preferred, seeing how teh form's fields
703
+	 * could change until it's actually outputted)
704
+	 *
705
+	 * @param boolean $init_form_validation_automatically whether or not we want the form validation
706
+	 *                                                    to be triggered automatically or not
707
+	 * @return void
708
+	 */
709
+	public static function wp_enqueue_scripts($init_form_validation_automatically = true)
710
+	{
711
+		wp_register_script(
712
+			'ee_form_section_validation',
713
+			EE_GLOBAL_ASSETS_URL . 'scripts' . DS . 'form_section_validation.js',
714
+			array('jquery-validate', 'jquery-ui-datepicker', 'jquery-validate-extra-methods'),
715
+			EVENT_ESPRESSO_VERSION,
716
+			true
717
+		);
718
+		wp_localize_script(
719
+			'ee_form_section_validation',
720
+			'ee_form_section_validation_init',
721
+			array('init' => $init_form_validation_automatically ? '1' : '0')
722
+		);
723
+	}
724
+
725
+
726
+	/**
727
+	 * gets the variables used by form_section_validation.js.
728
+	 * This needs to be called AFTER we've called $this->_enqueue_jquery_validate_script,
729
+	 * but before the wordpress hook wp_loaded
730
+	 *
731
+	 * @throws EE_Error
732
+	 */
733
+	public function _enqueue_and_localize_form_js()
734
+	{
735
+		$this->ensure_construct_finalized_called();
736
+		//actually, we don't want to localize just yet. There may be other forms on the page.
737
+		//so we need to add our form section data to a static variable accessible by all form sections
738
+		//and localize it just before the footer
739
+		$this->localize_validation_rules();
740
+		add_action('wp_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'), 2);
741
+		add_action('admin_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'));
742
+	}
743
+
744
+
745
+	/**
746
+	 * add our form section data to a static variable accessible by all form sections
747
+	 *
748
+	 * @param bool $return_for_subsection
749
+	 * @return void
750
+	 * @throws EE_Error
751
+	 */
752
+	public function localize_validation_rules($return_for_subsection = false)
753
+	{
754
+		// we only want to localize vars ONCE for the entire form,
755
+		// so if the form section doesn't have a parent, then it must be the top dog
756
+		if ($return_for_subsection || ! $this->parent_section()) {
757
+			EE_Form_Section_Proper::$_js_localization['form_data'][ $this->html_id() ] = array(
758
+				'form_section_id'  => $this->html_id(true),
759
+				'validation_rules' => $this->get_jquery_validation_rules(),
760
+				'other_data'       => $this->get_other_js_data(),
761
+				'errors'           => $this->subsection_validation_errors_by_html_name(),
762
+			);
763
+			EE_Form_Section_Proper::$_scripts_localized                                = true;
764
+		}
765
+	}
766
+
767
+
768
+	/**
769
+	 * Gets an array of extra data that will be useful for client-side javascript.
770
+	 * This is primarily data added by inputs and forms in addition to any
771
+	 * scripts they might enqueue
772
+	 *
773
+	 * @param array $form_other_js_data
774
+	 * @return array
775
+	 * @throws EE_Error
776
+	 */
777
+	public function get_other_js_data($form_other_js_data = array())
778
+	{
779
+		foreach ($this->subsections() as $subsection) {
780
+			$form_other_js_data = $subsection->get_other_js_data($form_other_js_data);
781
+		}
782
+		return $form_other_js_data;
783
+	}
784
+
785
+
786
+	/**
787
+	 * Gets a flat array of inputs for this form section and its subsections.
788
+	 * Keys are their form names, and values are the inputs themselves
789
+	 *
790
+	 * @return EE_Form_Input_Base
791
+	 * @throws EE_Error
792
+	 */
793
+	public function inputs_in_subsections()
794
+	{
795
+		$inputs = array();
796
+		foreach ($this->subsections() as $subsection) {
797
+			if ($subsection instanceof EE_Form_Input_Base) {
798
+				$inputs[ $subsection->html_name() ] = $subsection;
799
+			} elseif ($subsection instanceof EE_Form_Section_Proper) {
800
+				$inputs += $subsection->inputs_in_subsections();
801
+			}
802
+		}
803
+		return $inputs;
804
+	}
805
+
806
+
807
+	/**
808
+	 * Gets a flat array of all the validation errors.
809
+	 * Keys are html names (because those should be unique)
810
+	 * and values are a string of all their validation errors
811
+	 *
812
+	 * @return string[]
813
+	 * @throws EE_Error
814
+	 */
815
+	public function subsection_validation_errors_by_html_name()
816
+	{
817
+		$inputs = $this->inputs();
818
+		$errors = array();
819
+		foreach ($inputs as $form_input) {
820
+			if ($form_input instanceof EE_Form_Input_Base && $form_input->get_validation_errors()) {
821
+				$errors[ $form_input->html_name() ] = $form_input->get_validation_error_string();
822
+			}
823
+		}
824
+		return $errors;
825
+	}
826
+
827
+
828
+	/**
829
+	 * passes all the form data required by the JS to the JS, and enqueues the few required JS files.
830
+	 * Should be setup by each form during the _enqueues_and_localize_form_js
831
+	 *
832
+	 * @throws InvalidArgumentException
833
+	 * @throws InvalidInterfaceException
834
+	 * @throws InvalidDataTypeException
835
+	 */
836
+	public static function localize_script_for_all_forms()
837
+	{
838
+		//allow inputs and stuff to hook in their JS and stuff here
839
+		do_action('AHEE__EE_Form_Section_Proper__localize_script_for_all_forms__begin');
840
+		EE_Form_Section_Proper::$_js_localization['localized_error_messages'] = EE_Form_Section_Proper::_get_localized_error_messages();
841
+		$email_validation_level = isset(EE_Registry::instance()->CFG->registration->email_validation_level)
842
+			? EE_Registry::instance()->CFG->registration->email_validation_level
843
+			: 'wp_default';
844
+		EE_Form_Section_Proper::$_js_localization['email_validation_level']   = $email_validation_level;
845
+		wp_enqueue_script('ee_form_section_validation');
846
+		wp_localize_script(
847
+			'ee_form_section_validation',
848
+			'ee_form_section_vars',
849
+			EE_Form_Section_Proper::$_js_localization
850
+		);
851
+	}
852
+
853
+
854
+	/**
855
+	 * ensure_scripts_localized
856
+	 *
857
+	 * @throws EE_Error
858
+	 */
859
+	public function ensure_scripts_localized()
860
+	{
861
+		if (! EE_Form_Section_Proper::$_scripts_localized) {
862
+			$this->_enqueue_and_localize_form_js();
863
+		}
864
+	}
865
+
866
+
867
+	/**
868
+	 * Gets the hard-coded validation error messages to be used in the JS. The convention
869
+	 * is that the key here should be the same as the custom validation rule put in the JS file
870
+	 *
871
+	 * @return array keys are custom validation rules, and values are internationalized strings
872
+	 */
873
+	private static function _get_localized_error_messages()
874
+	{
875
+		return array(
876
+			'validUrl' => esc_html__('This is not a valid absolute URL. Eg, http://domain.com/monkey.jpg', 'event_espresso'),
877
+			'regex'    => esc_html__('Please check your input', 'event_espresso'),
878
+		);
879
+	}
880
+
881
+
882
+	/**
883
+	 * @return array
884
+	 */
885
+	public static function js_localization()
886
+	{
887
+		return self::$_js_localization;
888
+	}
889
+
890
+
891
+	/**
892
+	 * @return void
893
+	 */
894
+	public static function reset_js_localization()
895
+	{
896
+		self::$_js_localization = array();
897
+	}
898
+
899
+
900
+	/**
901
+	 * Gets the JS to put inside the jquery validation rules for subsection of this form section.
902
+	 * See parent function for more...
903
+	 *
904
+	 * @return array
905
+	 * @throws EE_Error
906
+	 */
907
+	public function get_jquery_validation_rules()
908
+	{
909
+		$jquery_validation_rules = array();
910
+		foreach ($this->get_validatable_subsections() as $subsection) {
911
+			$jquery_validation_rules = array_merge(
912
+				$jquery_validation_rules,
913
+				$subsection->get_jquery_validation_rules()
914
+			);
915
+		}
916
+		return $jquery_validation_rules;
917
+	}
918
+
919
+
920
+	/**
921
+	 * Sanitizes all the data and sets the sanitized value of each field
922
+	 *
923
+	 * @param array $req_data like $_POST
924
+	 * @return void
925
+	 * @throws EE_Error
926
+	 */
927
+	protected function _normalize($req_data)
928
+	{
929
+		$this->_received_submission = true;
930
+		$this->_validation_errors   = array();
931
+		foreach ($this->get_validatable_subsections() as $subsection) {
932
+			try {
933
+				$subsection->_normalize($req_data);
934
+			} catch (EE_Validation_Error $e) {
935
+				$subsection->add_validation_error($e);
936
+			}
937
+		}
938
+	}
939
+
940
+
941
+	/**
942
+	 * Performs validation on this form section and its subsections.
943
+	 * For each subsection,
944
+	 * calls _validate_{subsection_name} on THIS form (if the function exists)
945
+	 * and passes it the subsection, then calls _validate on that subsection.
946
+	 * If you need to perform validation on the form as a whole (considering multiple)
947
+	 * you would be best to override this _validate method,
948
+	 * calling parent::_validate() first.
949
+	 *
950
+	 * @throws EE_Error
951
+	 */
952
+	protected function _validate()
953
+	{
954
+		//reset the cache of whether this form is valid or not- we're re-validating it now
955
+		$this->is_valid = null;
956
+		foreach ($this->get_validatable_subsections() as $subsection_name => $subsection) {
957
+			if (method_exists($this, '_validate_' . $subsection_name)) {
958
+				call_user_func_array(array($this, '_validate_' . $subsection_name), array($subsection));
959
+			}
960
+			$subsection->_validate();
961
+		}
962
+	}
963
+
964
+
965
+	/**
966
+	 * Gets all the validated inputs for the form section
967
+	 *
968
+	 * @return array
969
+	 * @throws EE_Error
970
+	 */
971
+	public function valid_data()
972
+	{
973
+		$inputs = array();
974
+		foreach ($this->subsections() as $subsection_name => $subsection) {
975
+			if ($subsection instanceof EE_Form_Section_Proper) {
976
+				$inputs[ $subsection_name ] = $subsection->valid_data();
977
+			} elseif ($subsection instanceof EE_Form_Input_Base) {
978
+				$inputs[ $subsection_name ] = $subsection->normalized_value();
979
+			}
980
+		}
981
+		return $inputs;
982
+	}
983
+
984
+
985
+	/**
986
+	 * Gets all the inputs on this form section
987
+	 *
988
+	 * @return EE_Form_Input_Base[]
989
+	 * @throws EE_Error
990
+	 */
991
+	public function inputs()
992
+	{
993
+		$inputs = array();
994
+		foreach ($this->subsections() as $subsection_name => $subsection) {
995
+			if ($subsection instanceof EE_Form_Input_Base) {
996
+				$inputs[ $subsection_name ] = $subsection;
997
+			}
998
+		}
999
+		return $inputs;
1000
+	}
1001
+
1002
+
1003
+	/**
1004
+	 * Gets all the subsections which are a proper form
1005
+	 *
1006
+	 * @return EE_Form_Section_Proper[]
1007
+	 * @throws EE_Error
1008
+	 */
1009
+	public function subforms()
1010
+	{
1011
+		$form_sections = array();
1012
+		foreach ($this->subsections() as $name => $obj) {
1013
+			if ($obj instanceof EE_Form_Section_Proper) {
1014
+				$form_sections[ $name ] = $obj;
1015
+			}
1016
+		}
1017
+		return $form_sections;
1018
+	}
1019
+
1020
+
1021
+	/**
1022
+	 * Gets all the subsections (inputs, proper subsections, or html-only sections).
1023
+	 * Consider using inputs() or subforms()
1024
+	 * if you only want form inputs or proper form sections.
1025
+	 *
1026
+	 * @param boolean $require_construction_to_be_finalized most client code should
1027
+	 *                                                      leave this as TRUE so that the inputs will be properly
1028
+	 *                                                      configured. However, some client code may be ok with
1029
+	 *                                                      construction finalize being called later
1030
+	 *                                                      (realizing that the subsections' html names might not be
1031
+	 *                                                      set yet, etc.)
1032
+	 * @return EE_Form_Section_Proper[]
1033
+	 * @throws EE_Error
1034
+	 */
1035
+	public function subsections($require_construction_to_be_finalized = true)
1036
+	{
1037
+		if ($require_construction_to_be_finalized) {
1038
+			$this->ensure_construct_finalized_called();
1039
+		}
1040
+		return $this->_subsections;
1041
+	}
1042
+
1043
+
1044
+	/**
1045
+	 * Returns whether this form has any subforms or inputs
1046
+	 * @return bool
1047
+	 */
1048
+	public function hasSubsections()
1049
+	{
1050
+		return ! empty($this->_subsections);
1051
+	}
1052
+
1053
+
1054
+	/**
1055
+	 * Returns a simple array where keys are input names, and values are their normalized
1056
+	 * values. (Similar to calling get_input_value on inputs)
1057
+	 *
1058
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1059
+	 *                                        or just this forms' direct children inputs
1060
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1061
+	 *                                        or allow multidimensional array
1062
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array
1063
+	 *                                        with array keys being input names
1064
+	 *                                        (regardless of whether they are from a subsection or not),
1065
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1066
+	 *                                        where keys are always subsection names and values are either
1067
+	 *                                        the input's normalized value, or an array like the top-level array
1068
+	 * @throws EE_Error
1069
+	 */
1070
+	public function input_values($include_subform_inputs = false, $flatten = false)
1071
+	{
1072
+		return $this->_input_values(false, $include_subform_inputs, $flatten);
1073
+	}
1074
+
1075
+
1076
+	/**
1077
+	 * Similar to EE_Form_Section_Proper::input_values(), except this returns the 'display_value'
1078
+	 * of each input. On some inputs (especially radio boxes or checkboxes), the value stored
1079
+	 * is not necessarily the value we want to display to users. This creates an array
1080
+	 * where keys are the input names, and values are their display values
1081
+	 *
1082
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1083
+	 *                                        or just this forms' direct children inputs
1084
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1085
+	 *                                        or allow multidimensional array
1086
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array
1087
+	 *                                        with array keys being input names
1088
+	 *                                        (regardless of whether they are from a subsection or not),
1089
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1090
+	 *                                        where keys are always subsection names and values are either
1091
+	 *                                        the input's normalized value, or an array like the top-level array
1092
+	 * @throws EE_Error
1093
+	 */
1094
+	public function input_pretty_values($include_subform_inputs = false, $flatten = false)
1095
+	{
1096
+		return $this->_input_values(true, $include_subform_inputs, $flatten);
1097
+	}
1098
+
1099
+
1100
+	/**
1101
+	 * Gets the input values from the form
1102
+	 *
1103
+	 * @param boolean $pretty                 Whether to retrieve the pretty value,
1104
+	 *                                        or just the normalized value
1105
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1106
+	 *                                        or just this forms' direct children inputs
1107
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1108
+	 *                                        or allow multidimensional array
1109
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array with array keys being
1110
+	 *                                        input names (regardless of whether they are from a subsection or not),
1111
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1112
+	 *                                        where keys are always subsection names and values are either
1113
+	 *                                        the input's normalized value, or an array like the top-level array
1114
+	 * @throws EE_Error
1115
+	 */
1116
+	public function _input_values($pretty = false, $include_subform_inputs = false, $flatten = false)
1117
+	{
1118
+		$input_values = array();
1119
+		foreach ($this->subsections() as $subsection_name => $subsection) {
1120
+			if ($subsection instanceof EE_Form_Input_Base) {
1121
+				$input_values[ $subsection_name ] = $pretty
1122
+					? $subsection->pretty_value()
1123
+					: $subsection->normalized_value();
1124
+			} elseif ($subsection instanceof EE_Form_Section_Proper && $include_subform_inputs) {
1125
+				$subform_input_values = $subsection->_input_values(
1126
+					$pretty,
1127
+					$include_subform_inputs,
1128
+					$flatten
1129
+				);
1130
+				if ($flatten) {
1131
+					$input_values = array_merge($input_values, $subform_input_values);
1132
+				} else {
1133
+					$input_values[ $subsection_name ] = $subform_input_values;
1134
+				}
1135
+			}
1136
+		}
1137
+		return $input_values;
1138
+	}
1139
+
1140
+
1141
+	/**
1142
+	 * Gets the originally submitted input values from the form
1143
+	 *
1144
+	 * @param boolean $include_subforms  Whether to include inputs from subforms,
1145
+	 *                                   or just this forms' direct children inputs
1146
+	 * @return array                     if $flatten is TRUE it will always be a 1-dimensional array
1147
+	 *                                   with array keys being input names
1148
+	 *                                   (regardless of whether they are from a subsection or not),
1149
+	 *                                   and if $flatten is FALSE it can be a multidimensional array
1150
+	 *                                   where keys are always subsection names and values are either
1151
+	 *                                   the input's normalized value, or an array like the top-level array
1152
+	 * @throws EE_Error
1153
+	 */
1154
+	public function submitted_values($include_subforms = false)
1155
+	{
1156
+		$submitted_values = array();
1157
+		foreach ($this->subsections() as $subsection) {
1158
+			if ($subsection instanceof EE_Form_Input_Base) {
1159
+				// is this input part of an array of inputs?
1160
+				if (strpos($subsection->html_name(), '[') !== false) {
1161
+					$full_input_name  = EEH_Array::convert_array_values_to_keys(
1162
+						explode(
1163
+							'[',
1164
+							str_replace(']', '', $subsection->html_name())
1165
+						),
1166
+						$subsection->raw_value()
1167
+					);
1168
+					$submitted_values = array_replace_recursive($submitted_values, $full_input_name);
1169
+				} else {
1170
+					$submitted_values[ $subsection->html_name() ] = $subsection->raw_value();
1171
+				}
1172
+			} elseif ($subsection instanceof EE_Form_Section_Proper && $include_subforms) {
1173
+				$subform_input_values = $subsection->submitted_values($include_subforms);
1174
+				$submitted_values     = array_replace_recursive($submitted_values, $subform_input_values);
1175
+			}
1176
+		}
1177
+		return $submitted_values;
1178
+	}
1179
+
1180
+
1181
+	/**
1182
+	 * Indicates whether or not this form has received a submission yet
1183
+	 * (ie, had receive_form_submission called on it yet)
1184
+	 *
1185
+	 * @return boolean
1186
+	 * @throws EE_Error
1187
+	 */
1188
+	public function has_received_submission()
1189
+	{
1190
+		$this->ensure_construct_finalized_called();
1191
+		return $this->_received_submission;
1192
+	}
1193
+
1194
+
1195
+	/**
1196
+	 * Equivalent to passing 'exclude' in the constructor's options array.
1197
+	 * Removes the listed inputs from the form
1198
+	 *
1199
+	 * @param array $inputs_to_exclude values are the input names
1200
+	 * @return void
1201
+	 */
1202
+	public function exclude(array $inputs_to_exclude = array())
1203
+	{
1204
+		foreach ($inputs_to_exclude as $input_to_exclude_name) {
1205
+			unset($this->_subsections[ $input_to_exclude_name ]);
1206
+		}
1207
+	}
1208
+
1209
+
1210
+	/**
1211
+	 * @param array $inputs_to_hide
1212
+	 * @throws EE_Error
1213
+	 */
1214
+	public function hide(array $inputs_to_hide = array())
1215
+	{
1216
+		foreach ($inputs_to_hide as $input_to_hide) {
1217
+			$input = $this->get_input($input_to_hide);
1218
+			$input->set_display_strategy(new EE_Hidden_Display_Strategy());
1219
+		}
1220
+	}
1221
+
1222
+
1223
+	/**
1224
+	 * add_subsections
1225
+	 * Adds the listed subsections to the form section.
1226
+	 * If $subsection_name_to_target is provided,
1227
+	 * then new subsections are added before or after that subsection,
1228
+	 * otherwise to the start or end of the entire subsections array.
1229
+	 *
1230
+	 * @param EE_Form_Section_Base[] $new_subsections           array of new form subsections
1231
+	 *                                                          where keys are their names
1232
+	 * @param string                 $subsection_name_to_target an existing for section that $new_subsections
1233
+	 *                                                          should be added before or after
1234
+	 *                                                          IF $subsection_name_to_target is null,
1235
+	 *                                                          then $new_subsections will be added to
1236
+	 *                                                          the beginning or end of the entire subsections array
1237
+	 * @param boolean                $add_before                whether to add $new_subsections, before or after
1238
+	 *                                                          $subsection_name_to_target,
1239
+	 *                                                          or if $subsection_name_to_target is null,
1240
+	 *                                                          before or after entire subsections array
1241
+	 * @return void
1242
+	 * @throws EE_Error
1243
+	 */
1244
+	public function add_subsections($new_subsections, $subsection_name_to_target = null, $add_before = true)
1245
+	{
1246
+		foreach ($new_subsections as $subsection_name => $subsection) {
1247
+			if (! $subsection instanceof EE_Form_Section_Base) {
1248
+				EE_Error::add_error(
1249
+					sprintf(
1250
+						esc_html__(
1251
+							"Trying to add a %s as a subsection (it was named '%s') to the form section '%s'. It was removed.",
1252
+							'event_espresso'
1253
+						),
1254
+						get_class($subsection),
1255
+						$subsection_name,
1256
+						$this->name()
1257
+					)
1258
+				);
1259
+				unset($new_subsections[ $subsection_name ]);
1260
+			}
1261
+		}
1262
+		$this->_subsections = EEH_Array::insert_into_array(
1263
+			$this->_subsections,
1264
+			$new_subsections,
1265
+			$subsection_name_to_target,
1266
+			$add_before
1267
+		);
1268
+		if ($this->_construction_finalized) {
1269
+			foreach ($this->_subsections as $name => $subsection) {
1270
+				$subsection->_construct_finalize($this, $name);
1271
+			}
1272
+		}
1273
+	}
1274
+
1275
+
1276
+	/**
1277
+	 * Just gets all validatable subsections to clean their sensitive data
1278
+	 *
1279
+	 * @throws EE_Error
1280
+	 */
1281
+	public function clean_sensitive_data()
1282
+	{
1283
+		foreach ($this->get_validatable_subsections() as $subsection) {
1284
+			$subsection->clean_sensitive_data();
1285
+		}
1286
+	}
1287
+
1288
+
1289
+	/**
1290
+	 * Sets the submission error message (aka validation error message for this form section and all sub-sections)
1291
+	 * @param string                           $form_submission_error_message
1292
+	 * @param EE_Form_Section_Validatable $form_section unused
1293
+	 * @throws EE_Error
1294
+	 */
1295
+	public function set_submission_error_message(
1296
+		$form_submission_error_message = ''
1297
+	) {
1298
+		$this->_form_submission_error_message = ! empty($form_submission_error_message)
1299
+			? $form_submission_error_message
1300
+			: $this->getAllValidationErrorsString();
1301
+	}
1302
+
1303
+
1304
+	/**
1305
+	 * Returns the cached error message. A default value is set for this during _validate(),
1306
+	 * (called during receive_form_submission) but it can be explicitly set using
1307
+	 * set_submission_error_message
1308
+	 *
1309
+	 * @return string
1310
+	 */
1311
+	public function submission_error_message()
1312
+	{
1313
+		return $this->_form_submission_error_message;
1314
+	}
1315
+
1316
+
1317
+	/**
1318
+	 * Sets a message to display if the data submitted to the form was valid.
1319
+	 * @param string $form_submission_success_message
1320
+	 */
1321
+	public function set_submission_success_message($form_submission_success_message = '')
1322
+	{
1323
+		$this->_form_submission_success_message = ! empty($form_submission_success_message)
1324
+			? $form_submission_success_message
1325
+			: esc_html__('Form submitted successfully', 'event_espresso');
1326
+	}
1327
+
1328
+
1329
+	/**
1330
+	 * Gets a message appropriate for display when the form is correctly submitted
1331
+	 * @return string
1332
+	 */
1333
+	public function submission_success_message()
1334
+	{
1335
+		return $this->_form_submission_success_message;
1336
+	}
1337
+
1338
+
1339
+	/**
1340
+	 * Returns the prefix that should be used on child of this form section for
1341
+	 * their html names. If this form section itself has a parent, prepends ITS
1342
+	 * prefix onto this form section's prefix. Used primarily by
1343
+	 * EE_Form_Input_Base::_set_default_html_name_if_empty
1344
+	 *
1345
+	 * @return string
1346
+	 * @throws EE_Error
1347
+	 */
1348
+	public function html_name_prefix()
1349
+	{
1350
+		if ($this->parent_section() instanceof EE_Form_Section_Proper) {
1351
+			return $this->parent_section()->html_name_prefix() . '[' . $this->name() . ']';
1352
+		}
1353
+		return $this->name();
1354
+	}
1355
+
1356
+
1357
+	/**
1358
+	 * Gets the name, but first checks _construct_finalize has been called. If not,
1359
+	 * calls it (assumes there is no parent and that we want the name to be whatever
1360
+	 * was set, which is probably nothing, or the classname)
1361
+	 *
1362
+	 * @return string
1363
+	 * @throws EE_Error
1364
+	 */
1365
+	public function name()
1366
+	{
1367
+		$this->ensure_construct_finalized_called();
1368
+		return parent::name();
1369
+	}
1370
+
1371
+
1372
+	/**
1373
+	 * @return EE_Form_Section_Proper
1374
+	 * @throws EE_Error
1375
+	 */
1376
+	public function parent_section()
1377
+	{
1378
+		$this->ensure_construct_finalized_called();
1379
+		return parent::parent_section();
1380
+	}
1381
+
1382
+
1383
+	/**
1384
+	 * make sure construction finalized was called, otherwise children might not be ready
1385
+	 *
1386
+	 * @return void
1387
+	 * @throws EE_Error
1388
+	 */
1389
+	public function ensure_construct_finalized_called()
1390
+	{
1391
+		if (! $this->_construction_finalized) {
1392
+			$this->_construct_finalize($this->_parent_section, $this->_name);
1393
+		}
1394
+	}
1395
+
1396
+
1397
+	/**
1398
+	 * Checks if any of this form section's inputs, or any of its children's inputs,
1399
+	 * are in teh form data. If any are found, returns true. Else false
1400
+	 *
1401
+	 * @param array $req_data
1402
+	 * @return boolean
1403
+	 * @throws EE_Error
1404
+	 */
1405
+	public function form_data_present_in($req_data = null)
1406
+	{
1407
+		$req_data = $this->getCachedRequest($req_data);
1408
+		foreach ($this->subsections() as $subsection) {
1409
+			if ($subsection instanceof EE_Form_Input_Base) {
1410
+				if ($subsection->form_data_present_in($req_data)) {
1411
+					return true;
1412
+				}
1413
+			} elseif ($subsection instanceof EE_Form_Section_Proper) {
1414
+				if ($subsection->form_data_present_in($req_data)) {
1415
+					return true;
1416
+				}
1417
+			}
1418
+		}
1419
+		return false;
1420
+	}
1421
+
1422
+
1423
+	/**
1424
+	 * Gets validation errors for this form section and subsections
1425
+	 * Similar to EE_Form_Section_Validatable::get_validation_errors() except this
1426
+	 * gets the validation errors for ALL subsection
1427
+	 *
1428
+	 * @return EE_Validation_Error[]
1429
+	 * @throws EE_Error
1430
+	 */
1431
+	public function get_validation_errors_accumulated()
1432
+	{
1433
+		$validation_errors = $this->get_validation_errors();
1434
+		foreach ($this->get_validatable_subsections() as $subsection) {
1435
+			if ($subsection instanceof EE_Form_Section_Proper) {
1436
+				$validation_errors_on_this_subsection = $subsection->get_validation_errors_accumulated();
1437
+			} else {
1438
+				$validation_errors_on_this_subsection = $subsection->get_validation_errors();
1439
+			}
1440
+			if ($validation_errors_on_this_subsection) {
1441
+				$validation_errors = array_merge($validation_errors, $validation_errors_on_this_subsection);
1442
+			}
1443
+		}
1444
+		return $validation_errors;
1445
+	}
1446
+
1447
+	/**
1448
+	 * Fetch validation errors from children and grandchildren and puts them in a single string.
1449
+	 * This traverses the form section tree to generate this, but you probably want to instead use
1450
+	 * get_form_submission_error_message() which is usually this message cached (or a custom validation error message)
1451
+	 *
1452
+	 * @return string
1453
+	 * @since $VID:$
1454
+	 */
1455
+	protected function getAllValidationErrorsString()
1456
+	{
1457
+		$submission_error_messages = array();
1458
+		// bad, bad, bad registrant
1459
+		foreach ($this->get_validation_errors_accumulated() as $validation_error) {
1460
+			if ($validation_error instanceof EE_Validation_Error) {
1461
+				$form_section = $validation_error->get_form_section();
1462
+				if ($form_section instanceof EE_Form_Input_Base) {
1463
+				   $label = $validation_error->get_form_section()->html_label_text();
1464
+				} elseif($form_section instanceof EE_Form_Section_Validatable) {
1465
+					$label = $validation_error->get_form_section()->name();
1466
+				} else {
1467
+					$label = esc_html__('Unknown', 'event_espresso');
1468
+				}
1469
+				$submission_error_messages[] = sprintf(
1470
+					__('%s : %s', 'event_espresso'),
1471
+					$label,
1472
+					$validation_error->getMessage()
1473
+				);
1474
+			}
1475
+		}
1476
+		return implode('<br', $submission_error_messages);
1477
+	}
1478
+
1479
+
1480
+	/**
1481
+	 * This isn't just the name of an input, it's a path pointing to an input. The
1482
+	 * path is similar to a folder path: slash (/) means to descend into a subsection,
1483
+	 * dot-dot-slash (../) means to ascend into the parent section.
1484
+	 * After a series of slashes and dot-dot-slashes, there should be the name of an input,
1485
+	 * which will be returned.
1486
+	 * Eg, if you want the related input to be conditional on a sibling input name 'foobar'
1487
+	 * just use 'foobar'. If you want it to be conditional on an aunt/uncle input name
1488
+	 * 'baz', use '../baz'. If you want it to be conditional on a cousin input,
1489
+	 * the child of 'baz_section' named 'baz_child', use '../baz_section/baz_child'.
1490
+	 * Etc
1491
+	 *
1492
+	 * @param string|false $form_section_path we accept false also because substr( '../', '../' ) = false
1493
+	 * @return EE_Form_Section_Base
1494
+	 * @throws EE_Error
1495
+	 */
1496
+	public function find_section_from_path($form_section_path)
1497
+	{
1498
+		//check if we can find the input from purely going straight up the tree
1499
+		$input = parent::find_section_from_path($form_section_path);
1500
+		if ($input instanceof EE_Form_Section_Base) {
1501
+			return $input;
1502
+		}
1503
+		$next_slash_pos = strpos($form_section_path, '/');
1504
+		if ($next_slash_pos !== false) {
1505
+			$child_section_name = substr($form_section_path, 0, $next_slash_pos);
1506
+			$subpath            = substr($form_section_path, $next_slash_pos + 1);
1507
+		} else {
1508
+			$child_section_name = $form_section_path;
1509
+			$subpath            = '';
1510
+		}
1511
+		$child_section = $this->get_subsection($child_section_name);
1512
+		if ($child_section instanceof EE_Form_Section_Base) {
1513
+			return $child_section->find_section_from_path($subpath);
1514
+		}
1515
+		return null;
1516
+	}
1517 1517
 }
1518 1518
 
Please login to merge, or discard this patch.
core/libraries/form_sections/base/EE_Form_Section_Validatable.form.php 1 patch
Indentation   +147 added lines, -147 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 if (! defined('EVENT_ESPRESSO_VERSION')) {
3
-    exit('No direct script access allowed');
3
+	exit('No direct script access allowed');
4 4
 }
5 5
 
6 6
 
@@ -35,150 +35,150 @@  discard block
 block discarded – undo
35 35
 abstract class EE_Form_Section_Validatable extends EE_Form_Section_Base
36 36
 {
37 37
 
38
-    /**
39
-     * Array of validation errors in this section. Does not contain validation errors in subsections, however.
40
-     * Those are stored individually on each subsection.
41
-     *
42
-     * @var EE_Validation_Error[]
43
-     */
44
-    protected $_validation_errors = array();
45
-
46
-
47
-
48
-    /**
49
-     * Errors on this form section. Note: EE_Form_Section_Proper
50
-     * has another function for getting all errors in this form section and subsections
51
-     * called get_validation_errors_accumulated
52
-     *
53
-     * @return EE_Validation_Error[]
54
-     */
55
-    public function get_validation_errors()
56
-    {
57
-        return $this->_validation_errors;
58
-    }
59
-
60
-
61
-
62
-    /**
63
-     * returns a comma-separated list of all the validation errors in it.
64
-     * If we want this to be customizable, we may decide to create a strategy for displaying it
65
-     *
66
-     * @return string
67
-     */
68
-    public function get_validation_error_string()
69
-    {
70
-        $validation_error_messages = array();
71
-        if ($this->get_validation_errors()) {
72
-            foreach ($this->get_validation_errors() as $validation_error) {
73
-                if ($validation_error instanceof EE_Validation_Error) {
74
-                    $validation_error_messages[] = $validation_error->getMessage();
75
-                }
76
-            }
77
-        }
78
-        return implode(", ", $validation_error_messages);
79
-    }
80
-
81
-
82
-
83
-    /**
84
-     * Performs validation on this form section (and subsections). Should be called after _normalize()
85
-     *
86
-     * @return boolean of whether or not the form section is valid
87
-     */
88
-    abstract protected function _validate();
89
-
90
-
91
-
92
-    /**
93
-     * Checks if this field has any validation errors
94
-     *
95
-     * @return boolean
96
-     */
97
-    public function is_valid()
98
-    {
99
-        if (count($this->_validation_errors)) {
100
-            return false;
101
-        } else {
102
-            return true;
103
-        }
104
-    }
105
-
106
-
107
-
108
-    /**
109
-     * Sanitizes input for this form section
110
-     *
111
-     * @param array $req_data is the full request data like $_POST
112
-     * @return boolean of whether a normalization error occurred
113
-     */
114
-    abstract protected function _normalize($req_data);
115
-
116
-
117
-
118
-    /**
119
-     * Creates a validation error from the arguments provided, and adds it to the form section's list.
120
-     * If such an EE_Validation_Error object is passed in as the first arg, simply sets this as its form section, and
121
-     * adds it to the list of validation errors of errors
122
-     *
123
-     * @param mixed     $message_or_object  internationalized string describing the validation error; or it could be a
124
-     *                                      proper EE_Validation_Error object
125
-     * @param string    $error_code         a short key which can be used to uniquely identify the error
126
-     * @param Exception $previous_exception if there was an exception that caused the error, that exception
127
-     * @return void
128
-     */
129
-    public function add_validation_error($message_or_object, $error_code = null, $previous_exception = null)
130
-    {
131
-        if ($message_or_object instanceof EE_Validation_Error) {
132
-            $validation_error = $message_or_object;
133
-            $validation_error->set_form_section($this);
134
-        } else {
135
-            $validation_error = new EE_Validation_Error($message_or_object, $error_code, $this, $previous_exception);
136
-        }
137
-        $this->_validation_errors[] = $validation_error;
138
-    }
139
-
140
-
141
-
142
-    /**
143
-     * When generating the JS for the jquery validation rules like<br>
144
-     * <code>$( "#myform" ).validate({
145
-     * rules: {
146
-     * password: "required",
147
-     * password_again: {
148
-     * equalTo: "#password"
149
-     * }
150
-     * }
151
-     * });</code>
152
-     * gets the sections like
153
-     * <br><code>password: "required",
154
-     * password_again: {
155
-     * equalTo: "#password"
156
-     * }</code>
157
-     * except we leave it as a PHP object, and leave wp_localize_script to
158
-     * turn it into a JSON object which can be used by the js
159
-     *
160
-     * @return array
161
-     */
162
-    abstract public function get_jquery_validation_rules();
163
-
164
-
165
-
166
-    /**
167
-     * Checks if this form section's data is present in the req data specified
168
-     *
169
-     * @param array $req_data usually $_POST, if null that's what's used
170
-     * @return boolean
171
-     */
172
-    abstract public function form_data_present_in($req_data = null);
173
-
174
-
175
-
176
-    /**
177
-     * Removes teh sensitive data from this form section (usually done after
178
-     * utilizing the data business function, but before saving it somewhere. Eg,
179
-     * may remove a password from the form after verifying it was correct)
180
-     *
181
-     * @return void
182
-     */
183
-    abstract public function clean_sensitive_data();
38
+	/**
39
+	 * Array of validation errors in this section. Does not contain validation errors in subsections, however.
40
+	 * Those are stored individually on each subsection.
41
+	 *
42
+	 * @var EE_Validation_Error[]
43
+	 */
44
+	protected $_validation_errors = array();
45
+
46
+
47
+
48
+	/**
49
+	 * Errors on this form section. Note: EE_Form_Section_Proper
50
+	 * has another function for getting all errors in this form section and subsections
51
+	 * called get_validation_errors_accumulated
52
+	 *
53
+	 * @return EE_Validation_Error[]
54
+	 */
55
+	public function get_validation_errors()
56
+	{
57
+		return $this->_validation_errors;
58
+	}
59
+
60
+
61
+
62
+	/**
63
+	 * returns a comma-separated list of all the validation errors in it.
64
+	 * If we want this to be customizable, we may decide to create a strategy for displaying it
65
+	 *
66
+	 * @return string
67
+	 */
68
+	public function get_validation_error_string()
69
+	{
70
+		$validation_error_messages = array();
71
+		if ($this->get_validation_errors()) {
72
+			foreach ($this->get_validation_errors() as $validation_error) {
73
+				if ($validation_error instanceof EE_Validation_Error) {
74
+					$validation_error_messages[] = $validation_error->getMessage();
75
+				}
76
+			}
77
+		}
78
+		return implode(", ", $validation_error_messages);
79
+	}
80
+
81
+
82
+
83
+	/**
84
+	 * Performs validation on this form section (and subsections). Should be called after _normalize()
85
+	 *
86
+	 * @return boolean of whether or not the form section is valid
87
+	 */
88
+	abstract protected function _validate();
89
+
90
+
91
+
92
+	/**
93
+	 * Checks if this field has any validation errors
94
+	 *
95
+	 * @return boolean
96
+	 */
97
+	public function is_valid()
98
+	{
99
+		if (count($this->_validation_errors)) {
100
+			return false;
101
+		} else {
102
+			return true;
103
+		}
104
+	}
105
+
106
+
107
+
108
+	/**
109
+	 * Sanitizes input for this form section
110
+	 *
111
+	 * @param array $req_data is the full request data like $_POST
112
+	 * @return boolean of whether a normalization error occurred
113
+	 */
114
+	abstract protected function _normalize($req_data);
115
+
116
+
117
+
118
+	/**
119
+	 * Creates a validation error from the arguments provided, and adds it to the form section's list.
120
+	 * If such an EE_Validation_Error object is passed in as the first arg, simply sets this as its form section, and
121
+	 * adds it to the list of validation errors of errors
122
+	 *
123
+	 * @param mixed     $message_or_object  internationalized string describing the validation error; or it could be a
124
+	 *                                      proper EE_Validation_Error object
125
+	 * @param string    $error_code         a short key which can be used to uniquely identify the error
126
+	 * @param Exception $previous_exception if there was an exception that caused the error, that exception
127
+	 * @return void
128
+	 */
129
+	public function add_validation_error($message_or_object, $error_code = null, $previous_exception = null)
130
+	{
131
+		if ($message_or_object instanceof EE_Validation_Error) {
132
+			$validation_error = $message_or_object;
133
+			$validation_error->set_form_section($this);
134
+		} else {
135
+			$validation_error = new EE_Validation_Error($message_or_object, $error_code, $this, $previous_exception);
136
+		}
137
+		$this->_validation_errors[] = $validation_error;
138
+	}
139
+
140
+
141
+
142
+	/**
143
+	 * When generating the JS for the jquery validation rules like<br>
144
+	 * <code>$( "#myform" ).validate({
145
+	 * rules: {
146
+	 * password: "required",
147
+	 * password_again: {
148
+	 * equalTo: "#password"
149
+	 * }
150
+	 * }
151
+	 * });</code>
152
+	 * gets the sections like
153
+	 * <br><code>password: "required",
154
+	 * password_again: {
155
+	 * equalTo: "#password"
156
+	 * }</code>
157
+	 * except we leave it as a PHP object, and leave wp_localize_script to
158
+	 * turn it into a JSON object which can be used by the js
159
+	 *
160
+	 * @return array
161
+	 */
162
+	abstract public function get_jquery_validation_rules();
163
+
164
+
165
+
166
+	/**
167
+	 * Checks if this form section's data is present in the req data specified
168
+	 *
169
+	 * @param array $req_data usually $_POST, if null that's what's used
170
+	 * @return boolean
171
+	 */
172
+	abstract public function form_data_present_in($req_data = null);
173
+
174
+
175
+
176
+	/**
177
+	 * Removes teh sensitive data from this form section (usually done after
178
+	 * utilizing the data business function, but before saving it somewhere. Eg,
179
+	 * may remove a password from the form after verifying it was correct)
180
+	 *
181
+	 * @return void
182
+	 */
183
+	abstract public function clean_sensitive_data();
184 184
 }
185 185
\ No newline at end of file
Please login to merge, or discard this patch.
modules/single_page_checkout/inc/EE_SPCO_JSON_Response.php 1 patch
Spacing   +40 added lines, -40 removed lines patch added patch discarded remove patch
@@ -107,71 +107,71 @@  discard block
 block discarded – undo
107 107
 	public function __toString() {
108 108
 		$JSON_response = array();
109 109
 		// grab notices
110
-		$notices = EE_Error::get_notices( FALSE );
111
-		$this->set_attention( isset( $notices['attention'] ) ? $notices['attention'] : '' );
112
-		$this->set_errors( isset( $notices['errors'] ) ? $notices['errors'] : '' );
113
-		$this->set_success( isset( $notices['success'] ) ? $notices['success'] : '' );
110
+		$notices = EE_Error::get_notices(FALSE);
111
+		$this->set_attention(isset($notices['attention']) ? $notices['attention'] : '');
112
+		$this->set_errors(isset($notices['errors']) ? $notices['errors'] : '');
113
+		$this->set_success(isset($notices['success']) ? $notices['success'] : '');
114 114
 		// add notices to JSON response, but only if they exist
115
-		if ( $this->attention() ) {
115
+		if ($this->attention()) {
116 116
 			$JSON_response['attention'] = $this->attention();
117 117
 		}
118
-		if ( $this->errors() ) {
118
+		if ($this->errors()) {
119 119
 			$JSON_response['errors'] = $this->errors();
120 120
 		}
121
-		if ( $this->unexpected_errors() ) {
121
+		if ($this->unexpected_errors()) {
122 122
 			$JSON_response['unexpected_errors'] = $this->unexpected_errors();
123 123
 		}
124
-		if ( $this->success() ) {
124
+		if ($this->success()) {
125 125
 			$JSON_response['success'] = $this->success();
126 126
 		}
127 127
 		// but if NO notices are set... at least set the "success" as a key so that the JS knows everything worked
128
-		if ( ! isset( $JSON_response[ 'attention' ] ) && ! isset( $JSON_response[ 'errors' ] ) && ! isset( $JSON_response[ 'success' ] ) ) {
128
+		if ( ! isset($JSON_response['attention']) && ! isset($JSON_response['errors']) && ! isset($JSON_response['success'])) {
129 129
 			$JSON_response['success'] = null;
130 130
 		}
131 131
 		// set redirect_url, IF it exists
132
-		if ( $this->redirect_url() ) {
132
+		if ($this->redirect_url()) {
133 133
 			$JSON_response['redirect_url'] = $this->redirect_url();
134 134
 		}
135 135
 		// set registration_time_limit, IF it exists
136
-		if ( $this->registration_time_limit() ) {
136
+		if ($this->registration_time_limit()) {
137 137
 			$JSON_response['registration_time_limit'] = $this->registration_time_limit();
138 138
 		}
139 139
 		// set payment_amount, IF it exists
140
-		if ( $this->payment_amount() !== null ) {
141
-			$JSON_response[ 'payment_amount' ] = $this->payment_amount();
140
+		if ($this->payment_amount() !== null) {
141
+			$JSON_response['payment_amount'] = $this->payment_amount();
142 142
 		}
143 143
 		// grab generic return data
144 144
 		$return_data = $this->return_data();
145 145
 		// add billing form validation rules
146
-		if ( $this->validation_rules() ) {
146
+		if ($this->validation_rules()) {
147 147
 			$return_data['validation_rules'] = $this->validation_rules();
148 148
 		}
149 149
 		// set reg_step_html, IF it exists
150
-		if ( $this->reg_step_html() ) {
150
+		if ($this->reg_step_html()) {
151 151
 			$return_data['reg_step_html'] = $this->reg_step_html();
152 152
 		}
153 153
 		// set method of payment, IF it exists
154
-		if ( $this->method_of_payment() ) {
154
+		if ($this->method_of_payment()) {
155 155
 			$return_data['method_of_payment'] = $this->method_of_payment();
156 156
 		}
157 157
 		// set "plz_select_method_of_payment" message, IF it exists
158
-		if ( $this->plz_select_method_of_payment() ) {
158
+		if ($this->plz_select_method_of_payment()) {
159 159
 			$return_data['plz_select_method_of_payment'] = $this->plz_select_method_of_payment();
160 160
 		}
161 161
 		// set redirect_form, IF it exists
162
-		if ( $this->redirect_form() ) {
162
+		if ($this->redirect_form()) {
163 163
 			$return_data['redirect_form'] = $this->redirect_form();
164 164
 		}
165 165
 		// and finally, add return_data array to main JSON response array, IF it contains anything
166 166
 		// why did we add some of the above properties to the return data array?
167 167
 		// because it is easier and cleaner in the Javascript to deal with this way
168
-		if ( ! empty( $return_data )) {
168
+		if ( ! empty($return_data)) {
169 169
 			$JSON_response['return_data'] = $return_data;
170 170
 		}
171 171
 		// filter final array
172
-		$JSON_response = apply_filters( 'FHEE__EE_SPCO_JSON_Response___toString__JSON_response', $JSON_response );
172
+		$JSON_response = apply_filters('FHEE__EE_SPCO_JSON_Response___toString__JSON_response', $JSON_response);
173 173
 		// return encoded array
174
-		return wp_json_encode( $JSON_response );
174
+		return wp_json_encode($JSON_response);
175 175
 	}
176 176
 
177 177
 
@@ -179,7 +179,7 @@  discard block
 block discarded – undo
179 179
 	/**
180 180
 	 * @param string $attention
181 181
 	 */
182
-	public function set_attention( $attention ) {
182
+	public function set_attention($attention) {
183 183
 		$this->_attention = $attention;
184 184
 	}
185 185
 
@@ -197,7 +197,7 @@  discard block
 block discarded – undo
197 197
 	/**
198 198
 	 * @param string $errors
199 199
 	 */
200
-	public function set_errors( $errors ) {
200
+	public function set_errors($errors) {
201 201
 		$this->_errors = $errors;
202 202
 	}
203 203
 
@@ -224,7 +224,7 @@  discard block
 block discarded – undo
224 224
 	/**
225 225
 	 * @param string $unexpected_errors
226 226
 	 */
227
-	public function set_unexpected_errors( $unexpected_errors ) {
227
+	public function set_unexpected_errors($unexpected_errors) {
228 228
 		$this->_unexpected_errors = $unexpected_errors;
229 229
 	}
230 230
 
@@ -233,7 +233,7 @@  discard block
 block discarded – undo
233 233
 	/**
234 234
 	 * @param string $success
235 235
 	 */
236
-	public function set_success( $success ) {
236
+	public function set_success($success) {
237 237
 		$this->_success = $success;
238 238
 	}
239 239
 
@@ -251,7 +251,7 @@  discard block
 block discarded – undo
251 251
 	/**
252 252
 	 * @param string $method_of_payment
253 253
 	 */
254
-	public function set_method_of_payment( $method_of_payment ) {
254
+	public function set_method_of_payment($method_of_payment) {
255 255
 		$this->_method_of_payment = $method_of_payment;
256 256
 	}
257 257
 
@@ -278,8 +278,8 @@  discard block
 block discarded – undo
278 278
 	/**
279 279
 	 * @param float $payment_amount
280 280
 	 */
281
-	public function set_payment_amount( $payment_amount ) {
282
-		$this->_payment_amount = (float)$payment_amount;
281
+	public function set_payment_amount($payment_amount) {
282
+		$this->_payment_amount = (float) $payment_amount;
283 283
 	}
284 284
 
285 285
 
@@ -287,7 +287,7 @@  discard block
 block discarded – undo
287 287
 	/**
288 288
 	 * @param string $next_step_html
289 289
 	 */
290
-	public function set_reg_step_html( $next_step_html ) {
290
+	public function set_reg_step_html($next_step_html) {
291 291
 		$this->_reg_step_html = $next_step_html;
292 292
 	}
293 293
 
@@ -305,7 +305,7 @@  discard block
 block discarded – undo
305 305
 	/**
306 306
 	 * @param string $redirect_form
307 307
 	 */
308
-	public function set_redirect_form( $redirect_form ) {
308
+	public function set_redirect_form($redirect_form) {
309 309
 		$this->_redirect_form = $redirect_form;
310 310
 	}
311 311
 
@@ -315,7 +315,7 @@  discard block
 block discarded – undo
315 315
 	 * @return string
316 316
 	 */
317 317
 	public function redirect_form() {
318
-		return ! empty( $this->_redirect_form ) ? $this->_redirect_form : FALSE;
318
+		return ! empty($this->_redirect_form) ? $this->_redirect_form : FALSE;
319 319
 	}
320 320
 
321 321
 
@@ -323,7 +323,7 @@  discard block
 block discarded – undo
323 323
 	/**
324 324
 	 * @param string $plz_select_method_of_payment
325 325
 	 */
326
-	public function set_plz_select_method_of_payment( $plz_select_method_of_payment ) {
326
+	public function set_plz_select_method_of_payment($plz_select_method_of_payment) {
327 327
 		$this->_plz_select_method_of_payment = $plz_select_method_of_payment;
328 328
 	}
329 329
 
@@ -341,7 +341,7 @@  discard block
 block discarded – undo
341 341
 	/**
342 342
 	 * @param string $redirect_url
343 343
 	 */
344
-	public function set_redirect_url( $redirect_url ) {
344
+	public function set_redirect_url($redirect_url) {
345 345
 		$this->_redirect_url = $redirect_url;
346 346
 	}
347 347
 
@@ -368,7 +368,7 @@  discard block
 block discarded – undo
368 368
 	/**
369 369
 	 * @param string $registration_time_limit
370 370
 	 */
371
-	public function set_registration_time_limit( $registration_time_limit ) {
371
+	public function set_registration_time_limit($registration_time_limit) {
372 372
 		$this->_registration_time_limit = $registration_time_limit;
373 373
 	}
374 374
 
@@ -377,8 +377,8 @@  discard block
 block discarded – undo
377 377
 	/**
378 378
 	 * @param array $return_data
379 379
 	 */
380
-	public function set_return_data( $return_data ) {
381
-		$this->_return_data = array_merge( $this->_return_data, $return_data );
380
+	public function set_return_data($return_data) {
381
+		$this->_return_data = array_merge($this->_return_data, $return_data);
382 382
 	}
383 383
 
384 384
 
@@ -395,9 +395,9 @@  discard block
 block discarded – undo
395 395
 	/**
396 396
 	 * @param array $validation_rules
397 397
 	 */
398
-	public function add_validation_rules( $validation_rules = array() ) {
399
-		if ( is_array( $validation_rules ) && ! empty( $validation_rules )) {
400
-			$this->_validation_rules = array_merge( $this->_validation_rules, $validation_rules );
398
+	public function add_validation_rules($validation_rules = array()) {
399
+		if (is_array($validation_rules) && ! empty($validation_rules)) {
400
+			$this->_validation_rules = array_merge($this->_validation_rules, $validation_rules);
401 401
 		}
402 402
 	}
403 403
 
@@ -407,7 +407,7 @@  discard block
 block discarded – undo
407 407
 	 * @return array | bool
408 408
 	 */
409 409
 	public function validation_rules() {
410
-		return ! empty( $this->_validation_rules ) ? $this->_validation_rules : FALSE;
410
+		return ! empty($this->_validation_rules) ? $this->_validation_rules : FALSE;
411 411
 	}
412 412
 
413 413
 
Please login to merge, or discard this patch.
modules/single_page_checkout/EED_Single_Page_Checkout.module.php 2 patches
Spacing   +26 added lines, -26 removed lines patch added patch discarded remove patch
@@ -218,19 +218,19 @@  discard block
 block discarded – undo
218 218
      */
219 219
     public static function set_definitions()
220 220
     {
221
-        if(defined('SPCO_BASE_PATH')) {
221
+        if (defined('SPCO_BASE_PATH')) {
222 222
             return;
223 223
         }
224 224
         define(
225 225
             'SPCO_BASE_PATH',
226
-            rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS
226
+            rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS).DS
227 227
         );
228
-        define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css' . DS);
229
-        define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img' . DS);
230
-        define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js' . DS);
231
-        define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS);
232
-        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS);
233
-        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS);
228
+        define('SPCO_CSS_URL', plugin_dir_url(__FILE__).'css'.DS);
229
+        define('SPCO_IMG_URL', plugin_dir_url(__FILE__).'img'.DS);
230
+        define('SPCO_JS_URL', plugin_dir_url(__FILE__).'js'.DS);
231
+        define('SPCO_INC_PATH', SPCO_BASE_PATH.'inc'.DS);
232
+        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH.'reg_steps'.DS);
233
+        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH.'templates'.DS);
234 234
         EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
235 235
         EE_Registry::$i18n_js_strings['registration_expiration_notice'] = EED_Single_Page_Checkout::getRegistrationExpirationNotice();
236 236
     }
@@ -251,7 +251,7 @@  discard block
 block discarded – undo
251 251
             return;
252 252
         }
253 253
         // filter list of reg_steps
254
-        $reg_steps_to_load = (array)apply_filters(
254
+        $reg_steps_to_load = (array) apply_filters(
255 255
             'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
256 256
             EED_Single_Page_Checkout::get_reg_steps()
257 257
         );
@@ -303,25 +303,25 @@  discard block
 block discarded – undo
303 303
         if (empty($reg_steps)) {
304 304
             $reg_steps = array(
305 305
                 10  => array(
306
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
306
+                    'file_path'  => SPCO_REG_STEPS_PATH.'attendee_information',
307 307
                     'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
308 308
                     'slug'       => 'attendee_information',
309 309
                     'has_hooks'  => false,
310 310
                 ),
311 311
                 20  => array(
312
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'registration_confirmation',
312
+                    'file_path'  => SPCO_REG_STEPS_PATH.'registration_confirmation',
313 313
                     'class_name' => 'EE_SPCO_Reg_Step_Registration_Confirmation',
314 314
                     'slug'       => 'registration_confirmation',
315 315
                     'has_hooks'  => false,
316 316
                 ),
317 317
                 30  => array(
318
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
318
+                    'file_path'  => SPCO_REG_STEPS_PATH.'payment_options',
319 319
                     'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
320 320
                     'slug'       => 'payment_options',
321 321
                     'has_hooks'  => true,
322 322
                 ),
323 323
                 999 => array(
324
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
324
+                    'file_path'  => SPCO_REG_STEPS_PATH.'finalize_registration',
325 325
                     'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
326 326
                     'slug'       => 'finalize_registration',
327 327
                     'has_hooks'  => false,
@@ -505,7 +505,7 @@  discard block
 block discarded – undo
505 505
             // DEBUG LOG
506 506
             //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
507 507
             // get reg form
508
-            if( ! $this->_check_form_submission()) {
508
+            if ( ! $this->_check_form_submission()) {
509 509
                 EED_Single_Page_Checkout::$_initialized = true;
510 510
                 return;
511 511
             }
@@ -546,7 +546,7 @@  discard block
 block discarded – undo
546 546
         );
547 547
         // is session still valid ?
548 548
         if ($clear_session_requested
549
-            || ( EE_Registry::instance()->SSN->expired()
549
+            || (EE_Registry::instance()->SSN->expired()
550 550
               && EE_Registry::instance()->REQ->get('e_reg_url_link', '') === ''
551 551
             )
552 552
         ) {
@@ -555,7 +555,7 @@  discard block
 block discarded – undo
555 555
             // EE_Registry::instance()->SSN->reset_cart();
556 556
             // EE_Registry::instance()->SSN->reset_checkout();
557 557
             // EE_Registry::instance()->SSN->reset_transaction();
558
-            if (! $clear_session_requested) {
558
+            if ( ! $clear_session_requested) {
559 559
                 EE_Error::add_attention(
560 560
                     EE_Registry::$i18n_js_strings['registration_expiration_notice'],
561 561
                     __FILE__, __FUNCTION__, __LINE__
@@ -1114,7 +1114,7 @@  discard block
 block discarded – undo
1114 1114
                     if ( ! $registration instanceof EE_Registration) {
1115 1115
                         throw new InvalidEntityException($registration, 'EE_Registration');
1116 1116
                     }
1117
-                    $registrations[ $registration->ID() ] = $registration;
1117
+                    $registrations[$registration->ID()] = $registration;
1118 1118
                 }
1119 1119
             }
1120 1120
             $registration_processor->fix_reg_final_price_rounding_issue($transaction);
@@ -1375,7 +1375,7 @@  discard block
 block discarded – undo
1375 1375
                         ) {
1376 1376
                             EE_Error::add_success(
1377 1377
                                 $this->checkout->current_step->success_message()
1378
-                                . '<br />' . $this->checkout->next_step->_instructions()
1378
+                                . '<br />'.$this->checkout->next_step->_instructions()
1379 1379
                             );
1380 1380
                         }
1381 1381
                         // pack it up, pack it in...
@@ -1519,7 +1519,7 @@  discard block
 block discarded – undo
1519 1519
         // load css
1520 1520
         wp_register_style(
1521 1521
             'single_page_checkout',
1522
-            SPCO_CSS_URL . 'single_page_checkout.css',
1522
+            SPCO_CSS_URL.'single_page_checkout.css',
1523 1523
             array('espresso_default'),
1524 1524
             EVENT_ESPRESSO_VERSION
1525 1525
         );
@@ -1527,21 +1527,21 @@  discard block
 block discarded – undo
1527 1527
         // load JS
1528 1528
         wp_register_script(
1529 1529
             'jquery_plugin',
1530
-            EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1530
+            EE_THIRD_PARTY_URL.'jquery	.plugin.min.js',
1531 1531
             array('jquery'),
1532 1532
             '1.0.1',
1533 1533
             true
1534 1534
         );
1535 1535
         wp_register_script(
1536 1536
             'jquery_countdown',
1537
-            EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1537
+            EE_THIRD_PARTY_URL.'jquery	.countdown.min.js',
1538 1538
             array('jquery_plugin'),
1539 1539
             '2.0.2',
1540 1540
             true
1541 1541
         );
1542 1542
         wp_register_script(
1543 1543
             'single_page_checkout',
1544
-            SPCO_JS_URL . 'single_page_checkout.js',
1544
+            SPCO_JS_URL.'single_page_checkout.js',
1545 1545
             array('espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown'),
1546 1546
             EVENT_ESPRESSO_VERSION,
1547 1547
             true
@@ -1564,7 +1564,7 @@  discard block
 block discarded – undo
1564 1564
          *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1565 1565
          */
1566 1566
         do_action(
1567
-            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1567
+            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__'.$this->checkout->current_step->slug(),
1568 1568
             $this
1569 1569
         );
1570 1570
     }
@@ -1618,7 +1618,7 @@  discard block
 block discarded – undo
1618 1618
                     'layout_strategy' =>
1619 1619
                         new EE_Template_Layout(
1620 1620
                             array(
1621
-                                'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1621
+                                'layout_template_file' => SPCO_TEMPLATES_PATH.'registration_page_wrapper.template.php',
1622 1622
                                 'template_args'        => array(
1623 1623
                                     'empty_cart'              => $empty_cart,
1624 1624
                                     'revisit'                 => $this->checkout->revisit,
@@ -1692,7 +1692,7 @@  discard block
 block discarded – undo
1692 1692
         ) {
1693 1693
             add_filter(
1694 1694
                 'FHEE__EEH_Template__powered_by_event_espresso__url',
1695
-                function ($url) {
1695
+                function($url) {
1696 1696
                     return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1697 1697
                 }
1698 1698
             );
@@ -1871,7 +1871,7 @@  discard block
 block discarded – undo
1871 1871
             '</h4>',
1872 1872
             '<br />',
1873 1873
             '<p>',
1874
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1874
+            '<a href="'.get_post_type_archive_link('espresso_events').'" title="',
1875 1875
             '">',
1876 1876
             '</a>',
1877 1877
             '</p>'
Please login to merge, or discard this patch.
Indentation   +1844 added lines, -1844 removed lines patch added patch discarded remove patch
@@ -5,7 +5,7 @@  discard block
 block discarded – undo
5 5
 use EventEspresso\core\exceptions\InvalidEntityException;
6 6
 
7 7
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
8
-    exit('No direct script access allowed');
8
+	exit('No direct script access allowed');
9 9
 }
10 10
 
11 11
 
@@ -20,1849 +20,1849 @@  discard block
 block discarded – undo
20 20
 class EED_Single_Page_Checkout extends EED_Module
21 21
 {
22 22
 
23
-    /**
24
-     * $_initialized - has the SPCO controller already been initialized ?
25
-     *
26
-     * @access private
27
-     * @var bool $_initialized
28
-     */
29
-    private static $_initialized = false;
30
-
31
-
32
-    /**
33
-     * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
34
-     *
35
-     * @access private
36
-     * @var bool $_valid_checkout
37
-     */
38
-    private static $_checkout_verified = true;
39
-
40
-    /**
41
-     *    $_reg_steps_array - holds initial array of reg steps
42
-     *
43
-     * @access private
44
-     * @var array $_reg_steps_array
45
-     */
46
-    private static $_reg_steps_array = array();
47
-
48
-    /**
49
-     *    $checkout - EE_Checkout object for handling the properties of the current checkout process
50
-     *
51
-     * @access public
52
-     * @var EE_Checkout $checkout
53
-     */
54
-    public $checkout;
55
-
56
-
57
-
58
-    /**
59
-     * @return EED_Module|EED_Single_Page_Checkout
60
-     */
61
-    public static function instance()
62
-    {
63
-        add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
64
-        return parent::get_instance(__CLASS__);
65
-    }
66
-
67
-
68
-
69
-    /**
70
-     * @return EE_CART
71
-     */
72
-    public function cart()
73
-    {
74
-        return $this->checkout->cart;
75
-    }
76
-
77
-
78
-
79
-    /**
80
-     * @return EE_Transaction
81
-     */
82
-    public function transaction()
83
-    {
84
-        return $this->checkout->transaction;
85
-    }
86
-
87
-
88
-
89
-    /**
90
-     *    set_hooks - for hooking into EE Core, other modules, etc
91
-     *
92
-     * @access    public
93
-     * @return    void
94
-     * @throws EE_Error
95
-     */
96
-    public static function set_hooks()
97
-    {
98
-        EED_Single_Page_Checkout::set_definitions();
99
-    }
100
-
101
-
102
-
103
-    /**
104
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
105
-     *
106
-     * @access    public
107
-     * @return    void
108
-     * @throws EE_Error
109
-     */
110
-    public static function set_hooks_admin()
111
-    {
112
-        EED_Single_Page_Checkout::set_definitions();
113
-        if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
114
-            return;
115
-        }
116
-        // going to start an output buffer in case anything gets accidentally output
117
-        // that might disrupt our JSON response
118
-        ob_start();
119
-        EED_Single_Page_Checkout::load_request_handler();
120
-        EED_Single_Page_Checkout::load_reg_steps();
121
-        // set ajax hooks
122
-        add_action('wp_ajax_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
123
-        add_action('wp_ajax_nopriv_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
124
-        add_action('wp_ajax_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
125
-        add_action('wp_ajax_nopriv_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
126
-        add_action('wp_ajax_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
127
-        add_action('wp_ajax_nopriv_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
128
-    }
129
-
130
-
131
-
132
-    /**
133
-     *    process ajax request
134
-     *
135
-     * @param string $ajax_action
136
-     * @throws EE_Error
137
-     */
138
-    public static function process_ajax_request($ajax_action)
139
-    {
140
-        EE_Registry::instance()->REQ->set('action', $ajax_action);
141
-        EED_Single_Page_Checkout::instance()->_initialize();
142
-    }
143
-
144
-
145
-
146
-    /**
147
-     *    ajax display registration step
148
-     *
149
-     * @throws EE_Error
150
-     */
151
-    public static function display_reg_step()
152
-    {
153
-        EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
154
-    }
155
-
156
-
157
-
158
-    /**
159
-     *    ajax process registration step
160
-     *
161
-     * @throws EE_Error
162
-     */
163
-    public static function process_reg_step()
164
-    {
165
-        EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
166
-    }
167
-
168
-
169
-
170
-    /**
171
-     *    ajax process registration step
172
-     *
173
-     * @throws EE_Error
174
-     */
175
-    public static function update_reg_step()
176
-    {
177
-        EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
178
-    }
179
-
180
-
181
-
182
-    /**
183
-     *   update_checkout
184
-     *
185
-     * @access public
186
-     * @return void
187
-     * @throws EE_Error
188
-     */
189
-    public static function update_checkout()
190
-    {
191
-        EED_Single_Page_Checkout::process_ajax_request('update_checkout');
192
-    }
193
-
194
-
195
-
196
-    /**
197
-     *    load_request_handler
198
-     *
199
-     * @access    public
200
-     * @return    void
201
-     */
202
-    public static function load_request_handler()
203
-    {
204
-        // load core Request_Handler class
205
-        if (EE_Registry::instance()->REQ !== null) {
206
-            EE_Registry::instance()->load_core('Request_Handler');
207
-        }
208
-    }
209
-
210
-
211
-
212
-    /**
213
-     *    set_definitions
214
-     *
215
-     * @access    public
216
-     * @return    void
217
-     * @throws EE_Error
218
-     */
219
-    public static function set_definitions()
220
-    {
221
-        if(defined('SPCO_BASE_PATH')) {
222
-            return;
223
-        }
224
-        define(
225
-            'SPCO_BASE_PATH',
226
-            rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS
227
-        );
228
-        define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css' . DS);
229
-        define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img' . DS);
230
-        define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js' . DS);
231
-        define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS);
232
-        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS);
233
-        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS);
234
-        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
235
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] = EED_Single_Page_Checkout::getRegistrationExpirationNotice();
236
-    }
237
-
238
-
239
-
240
-    /**
241
-     * load_reg_steps
242
-     * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
243
-     *
244
-     * @access    private
245
-     * @throws EE_Error
246
-     */
247
-    public static function load_reg_steps()
248
-    {
249
-        static $reg_steps_loaded = false;
250
-        if ($reg_steps_loaded) {
251
-            return;
252
-        }
253
-        // filter list of reg_steps
254
-        $reg_steps_to_load = (array)apply_filters(
255
-            'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
256
-            EED_Single_Page_Checkout::get_reg_steps()
257
-        );
258
-        // sort by key (order)
259
-        ksort($reg_steps_to_load);
260
-        // loop through folders
261
-        foreach ($reg_steps_to_load as $order => $reg_step) {
262
-            // we need a
263
-            if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
264
-                // copy over to the reg_steps_array
265
-                EED_Single_Page_Checkout::$_reg_steps_array[$order] = $reg_step;
266
-                // register custom key route for each reg step
267
-                // ie: step=>"slug" - this is the entire reason we load the reg steps array now
268
-                EE_Config::register_route(
269
-                    $reg_step['slug'],
270
-                    'EED_Single_Page_Checkout',
271
-                    'run',
272
-                    'step'
273
-                );
274
-                // add AJAX or other hooks
275
-                if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
276
-                    // setup autoloaders if necessary
277
-                    if ( ! class_exists($reg_step['class_name'])) {
278
-                        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
279
-                            $reg_step['file_path'],
280
-                            true
281
-                        );
282
-                    }
283
-                    if (is_callable($reg_step['class_name'], 'set_hooks')) {
284
-                        call_user_func(array($reg_step['class_name'], 'set_hooks'));
285
-                    }
286
-                }
287
-            }
288
-        }
289
-        $reg_steps_loaded = true;
290
-    }
291
-
292
-
293
-
294
-    /**
295
-     *    get_reg_steps
296
-     *
297
-     * @access    public
298
-     * @return    array
299
-     */
300
-    public static function get_reg_steps()
301
-    {
302
-        $reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
303
-        if (empty($reg_steps)) {
304
-            $reg_steps = array(
305
-                10  => array(
306
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
307
-                    'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
308
-                    'slug'       => 'attendee_information',
309
-                    'has_hooks'  => false,
310
-                ),
311
-                20  => array(
312
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'registration_confirmation',
313
-                    'class_name' => 'EE_SPCO_Reg_Step_Registration_Confirmation',
314
-                    'slug'       => 'registration_confirmation',
315
-                    'has_hooks'  => false,
316
-                ),
317
-                30  => array(
318
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
319
-                    'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
320
-                    'slug'       => 'payment_options',
321
-                    'has_hooks'  => true,
322
-                ),
323
-                999 => array(
324
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
325
-                    'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
326
-                    'slug'       => 'finalize_registration',
327
-                    'has_hooks'  => false,
328
-                ),
329
-            );
330
-        }
331
-        return $reg_steps;
332
-    }
333
-
334
-
335
-
336
-    /**
337
-     *    registration_checkout_for_admin
338
-     *
339
-     * @access    public
340
-     * @return    string
341
-     * @throws EE_Error
342
-     */
343
-    public static function registration_checkout_for_admin()
344
-    {
345
-        EED_Single_Page_Checkout::load_request_handler();
346
-        EE_Registry::instance()->REQ->set('step', 'attendee_information');
347
-        EE_Registry::instance()->REQ->set('action', 'display_spco_reg_step');
348
-        EE_Registry::instance()->REQ->set('process_form_submission', false);
349
-        EED_Single_Page_Checkout::instance()->_initialize();
350
-        EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
351
-        return EE_Registry::instance()->REQ->get_output();
352
-    }
353
-
354
-
355
-
356
-    /**
357
-     * process_registration_from_admin
358
-     *
359
-     * @access public
360
-     * @return \EE_Transaction
361
-     * @throws EE_Error
362
-     */
363
-    public static function process_registration_from_admin()
364
-    {
365
-        EED_Single_Page_Checkout::load_request_handler();
366
-        EE_Registry::instance()->REQ->set('step', 'attendee_information');
367
-        EE_Registry::instance()->REQ->set('action', 'process_reg_step');
368
-        EE_Registry::instance()->REQ->set('process_form_submission', true);
369
-        EED_Single_Page_Checkout::instance()->_initialize();
370
-        if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
371
-            $final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
372
-            if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
373
-                EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
374
-                if ($final_reg_step->process_reg_step()) {
375
-                    $final_reg_step->set_completed();
376
-                    EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
377
-                    return EED_Single_Page_Checkout::instance()->checkout->transaction;
378
-                }
379
-            }
380
-        }
381
-        return null;
382
-    }
383
-
384
-
385
-
386
-    /**
387
-     *    run
388
-     *
389
-     * @access    public
390
-     * @param WP_Query $WP_Query
391
-     * @return    void
392
-     * @throws EE_Error
393
-     */
394
-    public function run($WP_Query)
395
-    {
396
-        if (
397
-            $WP_Query instanceof WP_Query
398
-            && $WP_Query->is_main_query()
399
-            && apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
400
-            && $this->_is_reg_checkout()
401
-        ) {
402
-            $this->_initialize();
403
-        }
404
-    }
405
-
406
-
407
-
408
-    /**
409
-     * determines whether current url matches reg page url
410
-     *
411
-     * @return bool
412
-     */
413
-    protected function _is_reg_checkout()
414
-    {
415
-        // get current permalink for reg page without any extra query args
416
-        $reg_page_url = \get_permalink(EE_Config::instance()->core->reg_page_id);
417
-        // get request URI for current request, but without the scheme or host
418
-        $current_request_uri = \EEH_URL::filter_input_server_url('REQUEST_URI');
419
-        $current_request_uri = html_entity_decode($current_request_uri);
420
-        // get array of query args from the current request URI
421
-        $query_args = \EEH_URL::get_query_string($current_request_uri);
422
-        // grab page id if it is set
423
-        $page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
424
-        // and remove the page id from the query args (we will re-add it later)
425
-        unset($query_args['page_id']);
426
-        // now strip all query args from current request URI
427
-        $current_request_uri = remove_query_arg(array_keys($query_args), $current_request_uri);
428
-        // and re-add the page id if it was set
429
-        if ($page_id) {
430
-            $current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
431
-        }
432
-        // remove slashes and ?
433
-        $current_request_uri = trim($current_request_uri, '?/');
434
-        // is current request URI part of the known full reg page URL ?
435
-        return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
436
-    }
437
-
438
-
439
-
440
-    /**
441
-     * @param WP_Query $wp_query
442
-     * @return    void
443
-     * @throws EE_Error
444
-     */
445
-    public static function init($wp_query)
446
-    {
447
-        EED_Single_Page_Checkout::instance()->run($wp_query);
448
-    }
449
-
450
-
451
-
452
-    /**
453
-     *    _initialize - initial module setup
454
-     *
455
-     * @access    private
456
-     * @throws EE_Error
457
-     * @return    void
458
-     */
459
-    private function _initialize()
460
-    {
461
-        // ensure SPCO doesn't run twice
462
-        if (EED_Single_Page_Checkout::$_initialized) {
463
-            return;
464
-        }
465
-        try {
466
-            EED_Single_Page_Checkout::load_reg_steps();
467
-            $this->_verify_session();
468
-            // setup the EE_Checkout object
469
-            $this->checkout = $this->_initialize_checkout();
470
-            // filter checkout
471
-            $this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
472
-            // get the $_GET
473
-            $this->_get_request_vars();
474
-            if ($this->_block_bots()) {
475
-                return;
476
-            }
477
-            // filter continue_reg
478
-            $this->checkout->continue_reg = apply_filters(
479
-                'FHEE__EED_Single_Page_Checkout__init___continue_reg',
480
-                true,
481
-                $this->checkout
482
-            );
483
-            // load the reg steps array
484
-            if ( ! $this->_load_and_instantiate_reg_steps()) {
485
-                EED_Single_Page_Checkout::$_initialized = true;
486
-                return;
487
-            }
488
-            // set the current step
489
-            $this->checkout->set_current_step($this->checkout->step);
490
-            // and the next step
491
-            $this->checkout->set_next_step();
492
-            // verify that everything has been setup correctly
493
-            if ( ! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
494
-                EED_Single_Page_Checkout::$_initialized = true;
495
-                return;
496
-            }
497
-            // lock the transaction
498
-            $this->checkout->transaction->lock();
499
-            // make sure all of our cached objects are added to their respective model entity mappers
500
-            $this->checkout->refresh_all_entities();
501
-            // set amount owing
502
-            $this->checkout->amount_owing = $this->checkout->transaction->remaining();
503
-            // initialize each reg step, which gives them the chance to potentially alter the process
504
-            $this->_initialize_reg_steps();
505
-            // DEBUG LOG
506
-            //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
507
-            // get reg form
508
-            if( ! $this->_check_form_submission()) {
509
-                EED_Single_Page_Checkout::$_initialized = true;
510
-                return;
511
-            }
512
-            // checkout the action!!!
513
-            $this->_process_form_action();
514
-            // add some style and make it dance
515
-            $this->add_styles_and_scripts();
516
-            // kk... SPCO has successfully run
517
-            EED_Single_Page_Checkout::$_initialized = true;
518
-            // set no cache headers and constants
519
-            EE_System::do_not_cache();
520
-            // add anchor
521
-            add_action('loop_start', array($this, 'set_checkout_anchor'), 1);
522
-            // remove transaction lock
523
-            add_action('shutdown', array($this, 'unlock_transaction'), 1);
524
-        } catch (Exception $e) {
525
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
526
-        }
527
-    }
528
-
529
-
530
-
531
-    /**
532
-     *    _verify_session
533
-     * checks that the session is valid and not expired
534
-     *
535
-     * @access    private
536
-     * @throws EE_Error
537
-     */
538
-    private function _verify_session()
539
-    {
540
-        if ( ! EE_Registry::instance()->SSN instanceof EE_Session) {
541
-            throw new EE_Error(__('The EE_Session class could not be loaded.', 'event_espresso'));
542
-        }
543
-        $clear_session_requested = filter_var(
544
-            EE_Registry::instance()->REQ->get('clear_session', false),
545
-            FILTER_VALIDATE_BOOLEAN
546
-        );
547
-        // is session still valid ?
548
-        if ($clear_session_requested
549
-            || ( EE_Registry::instance()->SSN->expired()
550
-              && EE_Registry::instance()->REQ->get('e_reg_url_link', '') === ''
551
-            )
552
-        ) {
553
-            $this->checkout = new EE_Checkout();
554
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
555
-            // EE_Registry::instance()->SSN->reset_cart();
556
-            // EE_Registry::instance()->SSN->reset_checkout();
557
-            // EE_Registry::instance()->SSN->reset_transaction();
558
-            if (! $clear_session_requested) {
559
-                EE_Error::add_attention(
560
-                    EE_Registry::$i18n_js_strings['registration_expiration_notice'],
561
-                    __FILE__, __FUNCTION__, __LINE__
562
-                );
563
-            }
564
-            // EE_Registry::instance()->SSN->reset_expired();
565
-        }
566
-    }
567
-
568
-
569
-
570
-    /**
571
-     *    _initialize_checkout
572
-     * loads and instantiates EE_Checkout
573
-     *
574
-     * @access    private
575
-     * @throws EE_Error
576
-     * @return EE_Checkout
577
-     */
578
-    private function _initialize_checkout()
579
-    {
580
-        // look in session for existing checkout
581
-        /** @type EE_Checkout $checkout */
582
-        $checkout = EE_Registry::instance()->SSN->checkout();
583
-        // verify
584
-        if ( ! $checkout instanceof EE_Checkout) {
585
-            // instantiate EE_Checkout object for handling the properties of the current checkout process
586
-            $checkout = EE_Registry::instance()->load_file(
587
-                SPCO_INC_PATH,
588
-                'EE_Checkout',
589
-                'class', array(),
590
-                false
591
-            );
592
-        } else {
593
-            if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
594
-                $this->unlock_transaction();
595
-                wp_safe_redirect($checkout->redirect_url);
596
-                exit();
597
-            }
598
-        }
599
-        $checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
600
-        // verify again
601
-        if ( ! $checkout instanceof EE_Checkout) {
602
-            throw new EE_Error(__('The EE_Checkout class could not be loaded.', 'event_espresso'));
603
-        }
604
-        // reset anything that needs a clean slate for each request
605
-        $checkout->reset_for_current_request();
606
-        return $checkout;
607
-    }
608
-
609
-
610
-
611
-    /**
612
-     *    _get_request_vars
613
-     *
614
-     * @access    private
615
-     * @return    void
616
-     * @throws EE_Error
617
-     */
618
-    private function _get_request_vars()
619
-    {
620
-        // load classes
621
-        EED_Single_Page_Checkout::load_request_handler();
622
-        //make sure this request is marked as belonging to EE
623
-        EE_Registry::instance()->REQ->set_espresso_page(true);
624
-        // which step is being requested ?
625
-        $this->checkout->step = EE_Registry::instance()->REQ->get('step', $this->_get_first_step());
626
-        // which step is being edited ?
627
-        $this->checkout->edit_step = EE_Registry::instance()->REQ->get('edit_step', '');
628
-        // and what we're doing on the current step
629
-        $this->checkout->action = EE_Registry::instance()->REQ->get('action', 'display_spco_reg_step');
630
-        // timestamp
631
-        $this->checkout->uts = EE_Registry::instance()->REQ->get('uts', 0);
632
-        // returning to edit ?
633
-        $this->checkout->reg_url_link = EE_Registry::instance()->REQ->get('e_reg_url_link', '');
634
-        // add reg url link to registration query params
635
-        if ($this->checkout->reg_url_link && strpos($this->checkout->reg_url_link, '1-') !== 0) {
636
-            $this->checkout->reg_cache_where_params[0]['REG_url_link'] = $this->checkout->reg_url_link;
637
-        }
638
-        // or some other kind of revisit ?
639
-        $this->checkout->revisit = filter_var(
640
-            EE_Registry::instance()->REQ->get('revisit', false),
641
-            FILTER_VALIDATE_BOOLEAN
642
-        );
643
-        // and whether or not to generate a reg form for this request
644
-        $this->checkout->generate_reg_form = filter_var(
645
-            EE_Registry::instance()->REQ->get('generate_reg_form', true),
646
-            FILTER_VALIDATE_BOOLEAN
647
-        );
648
-        // and whether or not to process a reg form submission for this request
649
-        $this->checkout->process_form_submission = filter_var(
650
-            EE_Registry::instance()->REQ->get(
651
-                'process_form_submission',
652
-                $this->checkout->action === 'process_reg_step'
653
-            ),
654
-            FILTER_VALIDATE_BOOLEAN
655
-        );
656
-        $this->checkout->process_form_submission = filter_var(
657
-            $this->checkout->action !== 'display_spco_reg_step'
658
-                ? $this->checkout->process_form_submission
659
-                : false,
660
-            FILTER_VALIDATE_BOOLEAN
661
-        );
662
-        // $this->_display_request_vars();
663
-    }
664
-
665
-
666
-
667
-    /**
668
-     *  _display_request_vars
669
-     *
670
-     * @access    protected
671
-     * @return    void
672
-     */
673
-    protected function _display_request_vars()
674
-    {
675
-        if ( ! WP_DEBUG) {
676
-            return;
677
-        }
678
-        EEH_Debug_Tools::printr($_REQUEST, '$_REQUEST', __FILE__, __LINE__);
679
-        EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
680
-        EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
681
-        EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
682
-        EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
683
-        EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
684
-        EEH_Debug_Tools::printr($this->checkout->generate_reg_form, '$this->checkout->generate_reg_form', __FILE__, __LINE__);
685
-        EEH_Debug_Tools::printr($this->checkout->process_form_submission, '$this->checkout->process_form_submission', __FILE__, __LINE__);
686
-    }
687
-
688
-
689
-
690
-    /**
691
-     * _block_bots
692
-     * checks that the incoming request has either of the following set:
693
-     *  a uts (unix timestamp) which indicates that the request was redirected from the Ticket Selector
694
-     *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
695
-     * so if you're not coming from the Ticket Selector nor returning for a valid IP...
696
-     * then where you coming from man?
697
-     *
698
-     * @return boolean
699
-     */
700
-    private function _block_bots()
701
-    {
702
-        $invalid_checkout_access = EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
703
-        if ($invalid_checkout_access->checkoutAccessIsInvalid($this->checkout)) {
704
-            return true;
705
-        }
706
-        return false;
707
-    }
708
-
709
-
710
-
711
-    /**
712
-     *    _get_first_step
713
-     *  gets slug for first step in $_reg_steps_array
714
-     *
715
-     * @access    private
716
-     * @throws EE_Error
717
-     * @return    string
718
-     */
719
-    private function _get_first_step()
720
-    {
721
-        $first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
722
-        return isset($first_step['slug']) ? $first_step['slug'] : 'attendee_information';
723
-    }
724
-
725
-
726
-
727
-    /**
728
-     *    _load_and_instantiate_reg_steps
729
-     *  instantiates each reg step based on the loaded reg_steps array
730
-     *
731
-     * @access    private
732
-     * @throws EE_Error
733
-     * @return    bool
734
-     */
735
-    private function _load_and_instantiate_reg_steps()
736
-    {
737
-        do_action('AHEE__Single_Page_Checkout___load_and_instantiate_reg_steps__start', $this->checkout);
738
-        // have reg_steps already been instantiated ?
739
-        if (
740
-            empty($this->checkout->reg_steps)
741
-            || apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
742
-        ) {
743
-            // if not, then loop through raw reg steps array
744
-            foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
745
-                if ( ! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
746
-                    return false;
747
-                }
748
-            }
749
-            EE_Registry::instance()->CFG->registration->skip_reg_confirmation = true;
750
-            EE_Registry::instance()->CFG->registration->reg_confirmation_last = true;
751
-            // skip the registration_confirmation page ?
752
-            if (EE_Registry::instance()->CFG->registration->skip_reg_confirmation) {
753
-                // just remove it from the reg steps array
754
-                $this->checkout->remove_reg_step('registration_confirmation', false);
755
-            } else if (
756
-                isset($this->checkout->reg_steps['registration_confirmation'])
757
-                && EE_Registry::instance()->CFG->registration->reg_confirmation_last
758
-            ) {
759
-                // set the order to something big like 100
760
-                $this->checkout->set_reg_step_order('registration_confirmation', 100);
761
-            }
762
-            // filter the array for good luck
763
-            $this->checkout->reg_steps = apply_filters(
764
-                'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
765
-                $this->checkout->reg_steps
766
-            );
767
-            // finally re-sort based on the reg step class order properties
768
-            $this->checkout->sort_reg_steps();
769
-        } else {
770
-            foreach ($this->checkout->reg_steps as $reg_step) {
771
-                // set all current step stati to FALSE
772
-                $reg_step->set_is_current_step(false);
773
-            }
774
-        }
775
-        if (empty($this->checkout->reg_steps)) {
776
-            EE_Error::add_error(
777
-                __('No Reg Steps were loaded..', 'event_espresso'),
778
-                __FILE__, __FUNCTION__, __LINE__
779
-            );
780
-            return false;
781
-        }
782
-        // make reg step details available to JS
783
-        $this->checkout->set_reg_step_JSON_info();
784
-        return true;
785
-    }
786
-
787
-
788
-
789
-    /**
790
-     *     _load_and_instantiate_reg_step
791
-     *
792
-     * @access    private
793
-     * @param array $reg_step
794
-     * @param int   $order
795
-     * @return bool
796
-     */
797
-    private function _load_and_instantiate_reg_step($reg_step = array(), $order = 0)
798
-    {
799
-        // we need a file_path, class_name, and slug to add a reg step
800
-        if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
801
-            // if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
802
-            if (
803
-                $this->checkout->reg_url_link
804
-                && $this->checkout->step !== $reg_step['slug']
805
-                && $reg_step['slug'] !== 'finalize_registration'
806
-                // normally at this point we would NOT load the reg step, but this filter can change that
807
-                && apply_filters(
808
-                    'FHEE__Single_Page_Checkout___load_and_instantiate_reg_step__bypass_reg_step',
809
-                    true,
810
-                    $reg_step,
811
-                    $this->checkout
812
-                )
813
-            ) {
814
-                return true;
815
-            }
816
-            // instantiate step class using file path and class name
817
-            $reg_step_obj = EE_Registry::instance()->load_file(
818
-                $reg_step['file_path'],
819
-                $reg_step['class_name'],
820
-                'class',
821
-                $this->checkout,
822
-                false
823
-            );
824
-            // did we gets the goods ?
825
-            if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
826
-                // set reg step order based on config
827
-                $reg_step_obj->set_order($order);
828
-                // add instantiated reg step object to the master reg steps array
829
-                $this->checkout->add_reg_step($reg_step_obj);
830
-            } else {
831
-                EE_Error::add_error(
832
-                    __('The current step could not be set.', 'event_espresso'),
833
-                    __FILE__, __FUNCTION__, __LINE__
834
-                );
835
-                return false;
836
-            }
837
-        } else {
838
-            if (WP_DEBUG) {
839
-                EE_Error::add_error(
840
-                    sprintf(
841
-                        __(
842
-                            'A registration step could not be loaded. One or more of the following data points is invalid:%4$s%5$sFile Path: %1$s%6$s%5$sClass Name: %2$s%6$s%5$sSlug: %3$s%6$s%7$s',
843
-                            'event_espresso'
844
-                        ),
845
-                        isset($reg_step['file_path']) ? $reg_step['file_path'] : '',
846
-                        isset($reg_step['class_name']) ? $reg_step['class_name'] : '',
847
-                        isset($reg_step['slug']) ? $reg_step['slug'] : '',
848
-                        '<ul>',
849
-                        '<li>',
850
-                        '</li>',
851
-                        '</ul>'
852
-                    ),
853
-                    __FILE__, __FUNCTION__, __LINE__
854
-                );
855
-            }
856
-            return false;
857
-        }
858
-        return true;
859
-    }
860
-
861
-
862
-    /**
863
-     * _verify_transaction_and_get_registrations
864
-     *
865
-     * @access private
866
-     * @return bool
867
-     * @throws InvalidDataTypeException
868
-     * @throws InvalidEntityException
869
-     * @throws EE_Error
870
-     */
871
-    private function _verify_transaction_and_get_registrations()
872
-    {
873
-        // was there already a valid transaction in the checkout from the session ?
874
-        if ( ! $this->checkout->transaction instanceof EE_Transaction) {
875
-            // get transaction from db or session
876
-            $this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
877
-                ? $this->_get_transaction_and_cart_for_previous_visit()
878
-                : $this->_get_cart_for_current_session_and_setup_new_transaction();
879
-            if ( ! $this->checkout->transaction instanceof EE_Transaction) {
880
-                EE_Error::add_error(
881
-                    __('Your Registration and Transaction information could not be retrieved from the db.',
882
-                        'event_espresso'),
883
-                    __FILE__, __FUNCTION__, __LINE__
884
-                );
885
-                $this->checkout->transaction = EE_Transaction::new_instance();
886
-                // add some style and make it dance
887
-                $this->add_styles_and_scripts();
888
-                EED_Single_Page_Checkout::$_initialized = true;
889
-                return false;
890
-            }
891
-            // and the registrations for the transaction
892
-            $this->_get_registrations($this->checkout->transaction);
893
-        }
894
-        return true;
895
-    }
896
-
897
-
898
-
899
-    /**
900
-     * _get_transaction_and_cart_for_previous_visit
901
-     *
902
-     * @access private
903
-     * @return mixed EE_Transaction|NULL
904
-     */
905
-    private function _get_transaction_and_cart_for_previous_visit()
906
-    {
907
-        /** @var $TXN_model EEM_Transaction */
908
-        $TXN_model = EE_Registry::instance()->load_model('Transaction');
909
-        // because the reg_url_link is present in the request,
910
-        // this is a return visit to SPCO, so we'll get the transaction data from the db
911
-        $transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
912
-        // verify transaction
913
-        if ($transaction instanceof EE_Transaction) {
914
-            // and get the cart that was used for that transaction
915
-            $this->checkout->cart = $this->_get_cart_for_transaction($transaction);
916
-            return $transaction;
917
-        }
918
-        EE_Error::add_error(
919
-            __('Your Registration and Transaction information could not be retrieved from the db.', 'event_espresso'),
920
-            __FILE__, __FUNCTION__, __LINE__
921
-        );
922
-        return null;
923
-
924
-    }
925
-
926
-
927
-
928
-    /**
929
-     * _get_cart_for_transaction
930
-     *
931
-     * @access private
932
-     * @param EE_Transaction $transaction
933
-     * @return EE_Cart
934
-     */
935
-    private function _get_cart_for_transaction($transaction)
936
-    {
937
-        return $this->checkout->get_cart_for_transaction($transaction);
938
-    }
939
-
940
-
941
-
942
-    /**
943
-     * get_cart_for_transaction
944
-     *
945
-     * @access public
946
-     * @param EE_Transaction $transaction
947
-     * @return EE_Cart
948
-     */
949
-    public function get_cart_for_transaction(EE_Transaction $transaction)
950
-    {
951
-        return $this->checkout->get_cart_for_transaction($transaction);
952
-    }
953
-
954
-
955
-
956
-    /**
957
-     * _get_transaction_and_cart_for_current_session
958
-     *    generates a new EE_Transaction object and adds it to the $_transaction property.
959
-     *
960
-     * @access private
961
-     * @return EE_Transaction
962
-     * @throws EE_Error
963
-     */
964
-    private function _get_cart_for_current_session_and_setup_new_transaction()
965
-    {
966
-        //  if there's no transaction, then this is the FIRST visit to SPCO
967
-        // so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
968
-        $this->checkout->cart = $this->_get_cart_for_transaction(null);
969
-        // and then create a new transaction
970
-        $transaction = $this->_initialize_transaction();
971
-        // verify transaction
972
-        if ($transaction instanceof EE_Transaction) {
973
-            // save it so that we have an ID for other objects to use
974
-            $transaction->save();
975
-            // and save TXN data to the cart
976
-            $this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
977
-        } else {
978
-            EE_Error::add_error(
979
-                __('A Valid Transaction could not be initialized.', 'event_espresso'),
980
-                __FILE__, __FUNCTION__, __LINE__
981
-            );
982
-        }
983
-        return $transaction;
984
-    }
985
-
986
-
987
-
988
-    /**
989
-     *    generates a new EE_Transaction object and adds it to the $_transaction property.
990
-     *
991
-     * @access private
992
-     * @return mixed EE_Transaction|NULL
993
-     */
994
-    private function _initialize_transaction()
995
-    {
996
-        try {
997
-            // ensure cart totals have been calculated
998
-            $this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
999
-            // grab the cart grand total
1000
-            $cart_total = $this->checkout->cart->get_cart_grand_total();
1001
-            // create new TXN
1002
-            $transaction = EE_Transaction::new_instance(
1003
-                array(
1004
-                    'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
1005
-                    'TXN_total'     => $cart_total > 0 ? $cart_total : 0,
1006
-                    'TXN_paid'      => 0,
1007
-                    'STS_ID'        => EEM_Transaction::failed_status_code,
1008
-                )
1009
-            );
1010
-            // save it so that we have an ID for other objects to use
1011
-            $transaction->save();
1012
-            // set cron job for following up on TXNs after their session has expired
1013
-            EE_Cron_Tasks::schedule_expired_transaction_check(
1014
-                EE_Registry::instance()->SSN->expiration() + 1,
1015
-                $transaction->ID()
1016
-            );
1017
-            return $transaction;
1018
-        } catch (Exception $e) {
1019
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1020
-        }
1021
-        return null;
1022
-    }
1023
-
1024
-
1025
-    /**
1026
-     * _get_registrations
1027
-     *
1028
-     * @access private
1029
-     * @param EE_Transaction $transaction
1030
-     * @return void
1031
-     * @throws InvalidDataTypeException
1032
-     * @throws InvalidEntityException
1033
-     * @throws EE_Error
1034
-     */
1035
-    private function _get_registrations(EE_Transaction $transaction)
1036
-    {
1037
-        // first step: grab the registrants  { : o
1038
-        $registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
1039
-        $this->checkout->total_ticket_count = count($registrations);
1040
-        // verify registrations have been set
1041
-        if (empty($registrations)) {
1042
-            // if no cached registrations, then check the db
1043
-            $registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
1044
-            // still nothing ? well as long as this isn't a revisit
1045
-            if (empty($registrations) && ! $this->checkout->revisit) {
1046
-                // generate new registrations from scratch
1047
-                $registrations = $this->_initialize_registrations($transaction);
1048
-            }
1049
-        }
1050
-        // sort by their original registration order
1051
-        usort($registrations, array('EED_Single_Page_Checkout', 'sort_registrations_by_REG_count'));
1052
-        // then loop thru the array
1053
-        foreach ($registrations as $registration) {
1054
-            // verify each registration
1055
-            if ($registration instanceof EE_Registration) {
1056
-                // we display all attendee info for the primary registrant
1057
-                if ($this->checkout->reg_url_link === $registration->reg_url_link()
1058
-                    && $registration->is_primary_registrant()
1059
-                ) {
1060
-                    $this->checkout->primary_revisit = true;
1061
-                    break;
1062
-                }
1063
-                if ($this->checkout->revisit && $this->checkout->reg_url_link !== $registration->reg_url_link()) {
1064
-                    // but hide info if it doesn't belong to you
1065
-                    $transaction->clear_cache('Registration', $registration->ID());
1066
-                    $this->checkout->total_ticket_count--;
1067
-                }
1068
-                $this->checkout->set_reg_status_updated($registration->ID(), false);
1069
-            }
1070
-        }
1071
-    }
1072
-
1073
-
1074
-    /**
1075
-     *    adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1076
-     *
1077
-     * @access private
1078
-     * @param EE_Transaction $transaction
1079
-     * @return    array
1080
-     * @throws InvalidDataTypeException
1081
-     * @throws InvalidEntityException
1082
-     * @throws EE_Error
1083
-     */
1084
-    private function _initialize_registrations(EE_Transaction $transaction)
1085
-    {
1086
-        $att_nmbr = 0;
1087
-        $registrations = array();
1088
-        if ($transaction instanceof EE_Transaction) {
1089
-            /** @type EE_Registration_Processor $registration_processor */
1090
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1091
-            $this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1092
-            // now let's add the cart items to the $transaction
1093
-            foreach ($this->checkout->cart->get_tickets() as $line_item) {
1094
-                //do the following for each ticket of this type they selected
1095
-                for ($x = 1; $x <= $line_item->quantity(); $x++) {
1096
-                    $att_nmbr++;
1097
-                    /** @var EventEspresso\core\services\commands\registration\CreateRegistrationCommand $CreateRegistrationCommand */
1098
-                    $CreateRegistrationCommand = EE_Registry::instance()->create(
1099
-                        'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1100
-                        array(
1101
-                            $transaction,
1102
-                            $line_item,
1103
-                            $att_nmbr,
1104
-                            $this->checkout->total_ticket_count,
1105
-                        )
1106
-                    );
1107
-                    // override capabilities for frontend registrations
1108
-                    if ( ! is_admin()) {
1109
-                        $CreateRegistrationCommand->setCapCheck(
1110
-                            new PublicCapabilities('', 'create_new_registration')
1111
-                        );
1112
-                    }
1113
-                    $registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1114
-                    if ( ! $registration instanceof EE_Registration) {
1115
-                        throw new InvalidEntityException($registration, 'EE_Registration');
1116
-                    }
1117
-                    $registrations[ $registration->ID() ] = $registration;
1118
-                }
1119
-            }
1120
-            $registration_processor->fix_reg_final_price_rounding_issue($transaction);
1121
-        }
1122
-        return $registrations;
1123
-    }
1124
-
1125
-
1126
-
1127
-    /**
1128
-     * sorts registrations by REG_count
1129
-     *
1130
-     * @access public
1131
-     * @param EE_Registration $reg_A
1132
-     * @param EE_Registration $reg_B
1133
-     * @return int
1134
-     */
1135
-    public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B)
1136
-    {
1137
-        // this shouldn't ever happen within the same TXN, but oh well
1138
-        if ($reg_A->count() === $reg_B->count()) {
1139
-            return 0;
1140
-        }
1141
-        return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1142
-    }
1143
-
1144
-
1145
-
1146
-    /**
1147
-     *    _final_verifications
1148
-     * just makes sure that everything is set up correctly before proceeding
1149
-     *
1150
-     * @access    private
1151
-     * @return    bool
1152
-     * @throws EE_Error
1153
-     */
1154
-    private function _final_verifications()
1155
-    {
1156
-        // filter checkout
1157
-        $this->checkout = apply_filters(
1158
-            'FHEE__EED_Single_Page_Checkout___final_verifications__checkout',
1159
-            $this->checkout
1160
-        );
1161
-        //verify that current step is still set correctly
1162
-        if ( ! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1163
-            EE_Error::add_error(
1164
-                __('We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.', 'event_espresso'),
1165
-                __FILE__,
1166
-                __FUNCTION__,
1167
-                __LINE__
1168
-            );
1169
-            return false;
1170
-        }
1171
-        // if returning to SPCO, then verify that primary registrant is set
1172
-        if ( ! empty($this->checkout->reg_url_link)) {
1173
-            $valid_registrant = $this->checkout->transaction->primary_registration();
1174
-            if ( ! $valid_registrant instanceof EE_Registration) {
1175
-                EE_Error::add_error(
1176
-                    __('We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.', 'event_espresso'),
1177
-                    __FILE__,
1178
-                    __FUNCTION__,
1179
-                    __LINE__
1180
-                );
1181
-                return false;
1182
-            }
1183
-            $valid_registrant = null;
1184
-            foreach (
1185
-                $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params) as $registration
1186
-            ) {
1187
-                if (
1188
-                    $registration instanceof EE_Registration
1189
-                    && $registration->reg_url_link() === $this->checkout->reg_url_link
1190
-                ) {
1191
-                    $valid_registrant = $registration;
1192
-                }
1193
-            }
1194
-            if ( ! $valid_registrant instanceof EE_Registration) {
1195
-                // hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1196
-                if (EED_Single_Page_Checkout::$_checkout_verified) {
1197
-                    // clear the session, mark the checkout as unverified, and try again
1198
-                    EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
1199
-                    EED_Single_Page_Checkout::$_initialized = false;
1200
-                    EED_Single_Page_Checkout::$_checkout_verified = false;
1201
-                    $this->_initialize();
1202
-                    EE_Error::reset_notices();
1203
-                    return false;
1204
-                }
1205
-                EE_Error::add_error(
1206
-                    __(
1207
-                        'We\'re sorry but there appears to be an error with the "reg_url_link" or the transaction itself. Please refresh the page and try again or contact support.',
1208
-                        'event_espresso'
1209
-                    ),
1210
-                    __FILE__,
1211
-                    __FUNCTION__,
1212
-                    __LINE__
1213
-                );
1214
-                return false;
1215
-            }
1216
-        }
1217
-        // now that things have been kinda sufficiently verified,
1218
-        // let's add the checkout to the session so that it's available to other systems
1219
-        EE_Registry::instance()->SSN->set_checkout($this->checkout);
1220
-        return true;
1221
-    }
1222
-
1223
-
1224
-
1225
-    /**
1226
-     *    _initialize_reg_steps
1227
-     * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1228
-     * then loops thru all of the active reg steps and calls the initialize_reg_step() method
1229
-     *
1230
-     * @access    private
1231
-     * @param bool $reinitializing
1232
-     * @throws EE_Error
1233
-     */
1234
-    private function _initialize_reg_steps($reinitializing = false)
1235
-    {
1236
-        $this->checkout->set_reg_step_initiated($this->checkout->current_step);
1237
-        // loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1238
-        foreach ($this->checkout->reg_steps as $reg_step) {
1239
-            if ( ! $reg_step->initialize_reg_step()) {
1240
-                // if not initialized then maybe this step is being removed...
1241
-                if ( ! $reinitializing && $reg_step->is_current_step()) {
1242
-                    // if it was the current step, then we need to start over here
1243
-                    $this->_initialize_reg_steps(true);
1244
-                    return;
1245
-                }
1246
-                continue;
1247
-            }
1248
-            // add css and JS for current step
1249
-            $reg_step->enqueue_styles_and_scripts();
1250
-            // i18n
1251
-            $reg_step->translate_js_strings();
1252
-            if ($reg_step->is_current_step()) {
1253
-                // the text that appears on the reg step form submit button
1254
-                $reg_step->set_submit_button_text();
1255
-            }
1256
-        }
1257
-        // dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1258
-        do_action(
1259
-            "AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}",
1260
-            $this->checkout->current_step
1261
-        );
1262
-    }
1263
-
1264
-
1265
-
1266
-    /**
1267
-     * _check_form_submission
1268
-     *
1269
-     * @access private
1270
-     * @return boolean
1271
-     */
1272
-    private function _check_form_submission()
1273
-    {
1274
-        //does this request require the reg form to be generated ?
1275
-        if ($this->checkout->generate_reg_form) {
1276
-            // ever heard that song by Blue Rodeo ?
1277
-            try {
1278
-                $this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1279
-                // if not displaying a form, then check for form submission
1280
-                if (
1281
-                    $this->checkout->process_form_submission
1282
-                    && $this->checkout->current_step->reg_form->was_submitted()
1283
-                ) {
1284
-                    // clear out any old data in case this step is being run again
1285
-                    $this->checkout->current_step->set_valid_data(array());
1286
-                    // capture submitted form data
1287
-                    $this->checkout->current_step->reg_form->receive_form_submission(
1288
-                        apply_filters(
1289
-                            'FHEE__Single_Page_Checkout___check_form_submission__request_params',
1290
-                            EE_Registry::instance()->REQ->params(),
1291
-                            $this->checkout
1292
-                        )
1293
-                    );
1294
-                    // validate submitted form data
1295
-                    if ( ! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1296
-                        // thou shall not pass !!!
1297
-                        $this->checkout->continue_reg = false;
1298
-                        // any form validation errors?
1299
-                        if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1300
-                            EE_Error::add_error(
1301
-                                $this->checkout->current_step->reg_form->submission_error_message(),
1302
-                                __FILE__, __FUNCTION__, __LINE__
1303
-                            );
1304
-                        }
1305
-                        // well not really... what will happen is
1306
-                        // we'll just get redirected back to redo the current step
1307
-                        $this->go_to_next_step();
1308
-                        return false;
1309
-                    }
1310
-                }
1311
-            } catch (EE_Error $e) {
1312
-                $e->get_error();
1313
-            }
1314
-        }
1315
-        return true;
1316
-    }
1317
-
1318
-
1319
-
1320
-    /**
1321
-     * _process_action
1322
-     *
1323
-     * @access private
1324
-     * @return void
1325
-     * @throws EE_Error
1326
-     */
1327
-    private function _process_form_action()
1328
-    {
1329
-        // what cha wanna do?
1330
-        switch ($this->checkout->action) {
1331
-            // AJAX next step reg form
1332
-            case 'display_spco_reg_step' :
1333
-                $this->checkout->redirect = false;
1334
-                if (EE_Registry::instance()->REQ->ajax) {
1335
-                    $this->checkout->json_response->set_reg_step_html(
1336
-                        $this->checkout->current_step->display_reg_form()
1337
-                    );
1338
-                }
1339
-                break;
1340
-            default :
1341
-                // meh... do one of those other steps first
1342
-                if (
1343
-                    ! empty($this->checkout->action)
1344
-                    && is_callable(array($this->checkout->current_step, $this->checkout->action))
1345
-                ) {
1346
-                    // dynamically creates hook point like:
1347
-                    //   AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1348
-                    do_action(
1349
-                        "AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1350
-                        $this->checkout->current_step
1351
-                    );
1352
-                    // call action on current step
1353
-                    if (call_user_func(array($this->checkout->current_step, $this->checkout->action))) {
1354
-                        // good registrant, you get to proceed
1355
-                        if (
1356
-                            $this->checkout->current_step->success_message() !== ''
1357
-                            && apply_filters(
1358
-                                'FHEE__Single_Page_Checkout___process_form_action__display_success',
1359
-                                false
1360
-                            )
1361
-                        ) {
1362
-                            EE_Error::add_success(
1363
-                                $this->checkout->current_step->success_message()
1364
-                                . '<br />' . $this->checkout->next_step->_instructions()
1365
-                            );
1366
-                        }
1367
-                        // pack it up, pack it in...
1368
-                        $this->_setup_redirect();
1369
-                    }
1370
-                    // dynamically creates hook point like:
1371
-                    //  AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1372
-                    do_action(
1373
-                        "AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1374
-                        $this->checkout->current_step
1375
-                    );
1376
-                } else {
1377
-                    EE_Error::add_error(
1378
-                        sprintf(
1379
-                            __(
1380
-                                'The requested form action "%s" does not exist for the current "%s" registration step.',
1381
-                                'event_espresso'
1382
-                            ),
1383
-                            $this->checkout->action,
1384
-                            $this->checkout->current_step->name()
1385
-                        ),
1386
-                        __FILE__,
1387
-                        __FUNCTION__,
1388
-                        __LINE__
1389
-                    );
1390
-                }
1391
-            // end default
1392
-        }
1393
-        // store our progress so far
1394
-        $this->checkout->stash_transaction_and_checkout();
1395
-        // advance to the next step! If you pass GO, collect $200
1396
-        $this->go_to_next_step();
1397
-    }
1398
-
1399
-
1400
-
1401
-    /**
1402
-     *        add_styles_and_scripts
1403
-     *
1404
-     * @access        public
1405
-     * @return        void
1406
-     */
1407
-    public function add_styles_and_scripts()
1408
-    {
1409
-        // i18n
1410
-        $this->translate_js_strings();
1411
-        if ($this->checkout->admin_request) {
1412
-            add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1413
-        } else {
1414
-            add_action('wp_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1415
-        }
1416
-    }
1417
-
1418
-
1419
-
1420
-    /**
1421
-     *        translate_js_strings
1422
-     *
1423
-     * @access        public
1424
-     * @return        void
1425
-     */
1426
-    public function translate_js_strings()
1427
-    {
1428
-        EE_Registry::$i18n_js_strings['revisit'] = $this->checkout->revisit;
1429
-        EE_Registry::$i18n_js_strings['e_reg_url_link'] = $this->checkout->reg_url_link;
1430
-        EE_Registry::$i18n_js_strings['server_error'] = __(
1431
-            'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1432
-            'event_espresso'
1433
-        );
1434
-        EE_Registry::$i18n_js_strings['invalid_json_response'] = __(
1435
-            'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1436
-            'event_espresso'
1437
-        );
1438
-        EE_Registry::$i18n_js_strings['validation_error'] = __(
1439
-            'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1440
-            'event_espresso'
1441
-        );
1442
-        EE_Registry::$i18n_js_strings['invalid_payment_method'] = __(
1443
-            'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1444
-            'event_espresso'
1445
-        );
1446
-        EE_Registry::$i18n_js_strings['reg_step_error'] = __(
1447
-            'This registration step could not be completed. Please refresh the page and try again.',
1448
-            'event_espresso'
1449
-        );
1450
-        EE_Registry::$i18n_js_strings['invalid_coupon'] = __(
1451
-            'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1452
-            'event_espresso'
1453
-        );
1454
-        EE_Registry::$i18n_js_strings['process_registration'] = sprintf(
1455
-            __(
1456
-                'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1457
-                'event_espresso'
1458
-            ),
1459
-            '<br/>',
1460
-            '<br/>'
1461
-        );
1462
-        EE_Registry::$i18n_js_strings['language'] = get_bloginfo('language');
1463
-        EE_Registry::$i18n_js_strings['EESID'] = EE_Registry::instance()->SSN->id();
1464
-        EE_Registry::$i18n_js_strings['currency'] = EE_Registry::instance()->CFG->currency;
1465
-        EE_Registry::$i18n_js_strings['datepicker_yearRange'] = '-150:+20';
1466
-        EE_Registry::$i18n_js_strings['timer_years'] = __('years', 'event_espresso');
1467
-        EE_Registry::$i18n_js_strings['timer_months'] = __('months', 'event_espresso');
1468
-        EE_Registry::$i18n_js_strings['timer_weeks'] = __('weeks', 'event_espresso');
1469
-        EE_Registry::$i18n_js_strings['timer_days'] = __('days', 'event_espresso');
1470
-        EE_Registry::$i18n_js_strings['timer_hours'] = __('hours', 'event_espresso');
1471
-        EE_Registry::$i18n_js_strings['timer_minutes'] = __('minutes', 'event_espresso');
1472
-        EE_Registry::$i18n_js_strings['timer_seconds'] = __('seconds', 'event_espresso');
1473
-        EE_Registry::$i18n_js_strings['timer_year'] = __('year', 'event_espresso');
1474
-        EE_Registry::$i18n_js_strings['timer_month'] = __('month', 'event_espresso');
1475
-        EE_Registry::$i18n_js_strings['timer_week'] = __('week', 'event_espresso');
1476
-        EE_Registry::$i18n_js_strings['timer_day'] = __('day', 'event_espresso');
1477
-        EE_Registry::$i18n_js_strings['timer_hour'] = __('hour', 'event_espresso');
1478
-        EE_Registry::$i18n_js_strings['timer_minute'] = __('minute', 'event_espresso');
1479
-        EE_Registry::$i18n_js_strings['timer_second'] = __('second', 'event_espresso');
1480
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] = EED_Single_Page_Checkout::getRegistrationExpirationNotice();
1481
-        EE_Registry::$i18n_js_strings['ajax_submit'] = apply_filters(
1482
-            'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit',
1483
-            true
1484
-        );
1485
-        EE_Registry::$i18n_js_strings['session_extension'] = absint(
1486
-            apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1487
-        );
1488
-        EE_Registry::$i18n_js_strings['session_expiration'] = gmdate(
1489
-            'M d, Y H:i:s',
1490
-            EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1491
-        );
1492
-    }
1493
-
1494
-
1495
-
1496
-    /**
1497
-     *    enqueue_styles_and_scripts
1498
-     *
1499
-     * @access        public
1500
-     * @return        void
1501
-     * @throws EE_Error
1502
-     */
1503
-    public function enqueue_styles_and_scripts()
1504
-    {
1505
-        // load css
1506
-        wp_register_style(
1507
-            'single_page_checkout',
1508
-            SPCO_CSS_URL . 'single_page_checkout.css',
1509
-            array('espresso_default'),
1510
-            EVENT_ESPRESSO_VERSION
1511
-        );
1512
-        wp_enqueue_style('single_page_checkout');
1513
-        // load JS
1514
-        wp_register_script(
1515
-            'jquery_plugin',
1516
-            EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1517
-            array('jquery'),
1518
-            '1.0.1',
1519
-            true
1520
-        );
1521
-        wp_register_script(
1522
-            'jquery_countdown',
1523
-            EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1524
-            array('jquery_plugin'),
1525
-            '2.0.2',
1526
-            true
1527
-        );
1528
-        wp_register_script(
1529
-            'single_page_checkout',
1530
-            SPCO_JS_URL . 'single_page_checkout.js',
1531
-            array('espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown'),
1532
-            EVENT_ESPRESSO_VERSION,
1533
-            true
1534
-        );
1535
-        if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1536
-            $this->checkout->registration_form->enqueue_js();
1537
-        }
1538
-        if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1539
-            $this->checkout->current_step->reg_form->enqueue_js();
1540
-        }
1541
-        wp_enqueue_script('single_page_checkout');
1542
-        /**
1543
-         * global action hook for enqueueing styles and scripts with
1544
-         * spco calls.
1545
-         */
1546
-        do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1547
-        /**
1548
-         * dynamic action hook for enqueueing styles and scripts with spco calls.
1549
-         * The hook will end up being something like:
1550
-         *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1551
-         */
1552
-        do_action(
1553
-            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1554
-            $this
1555
-        );
1556
-    }
1557
-
1558
-
1559
-
1560
-    /**
1561
-     *    display the Registration Single Page Checkout Form
1562
-     *
1563
-     * @access    private
1564
-     * @return    void
1565
-     * @throws EE_Error
1566
-     */
1567
-    private function _display_spco_reg_form()
1568
-    {
1569
-        // if registering via the admin, just display the reg form for the current step
1570
-        if ($this->checkout->admin_request) {
1571
-            EE_Registry::instance()->REQ->add_output($this->checkout->current_step->display_reg_form());
1572
-        } else {
1573
-            // add powered by EE msg
1574
-            add_action('AHEE__SPCO__reg_form_footer', array('EED_Single_Page_Checkout', 'display_registration_footer'));
1575
-            $empty_cart = count(
1576
-                $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params)
1577
-            ) < 1;
1578
-            EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1579
-            $cookies_not_set_msg = '';
1580
-            if ($empty_cart) {
1581
-                $cookies_not_set_msg = apply_filters(
1582
-                    'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1583
-                    sprintf(
1584
-                        __(
1585
-                            '%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
1586
-                            'event_espresso'
1587
-                        ),
1588
-                        '<div class="ee-attention hidden" id="ee-cookies-not-set-msg">',
1589
-                        '</div>',
1590
-                        '<h6 class="important-notice">',
1591
-                        '</h6>',
1592
-                        '<p>',
1593
-                        '</p>',
1594
-                        '<br />',
1595
-                        '<a href="http://www.whatarecookies.com/enable.asp" target="_blank">',
1596
-                        '</a>'
1597
-                    )
1598
-                );
1599
-            }
1600
-            $this->checkout->registration_form = new EE_Form_Section_Proper(
1601
-                array(
1602
-                    'name'            => 'single-page-checkout',
1603
-                    'html_id'         => 'ee-single-page-checkout-dv',
1604
-                    'layout_strategy' =>
1605
-                        new EE_Template_Layout(
1606
-                            array(
1607
-                                'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1608
-                                'template_args'        => array(
1609
-                                    'empty_cart'              => $empty_cart,
1610
-                                    'revisit'                 => $this->checkout->revisit,
1611
-                                    'reg_steps'               => $this->checkout->reg_steps,
1612
-                                    'next_step'               => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
1613
-                                        ? $this->checkout->next_step->slug()
1614
-                                        : '',
1615
-                                    'empty_msg'               => apply_filters(
1616
-                                        'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1617
-                                        sprintf(
1618
-                                            __(
1619
-                                                'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1620
-                                                'event_espresso'
1621
-                                            ),
1622
-                                            '<a href="'
1623
-                                            . get_post_type_archive_link('espresso_events')
1624
-                                            . '" title="',
1625
-                                            '">',
1626
-                                            '</a>'
1627
-                                        )
1628
-                                    ),
1629
-                                    'cookies_not_set_msg'     => $cookies_not_set_msg,
1630
-                                    'registration_time_limit' => $this->checkout->get_registration_time_limit(),
1631
-                                    'session_expiration'      => gmdate(
1632
-                                        'M d, Y H:i:s',
1633
-                                        EE_Registry::instance()->SSN->expiration()
1634
-                                        + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1635
-                                    ),
1636
-                                ),
1637
-                            )
1638
-                        ),
1639
-                )
1640
-            );
1641
-            // load template and add to output sent that gets filtered into the_content()
1642
-            EE_Registry::instance()->REQ->add_output($this->checkout->registration_form->get_html());
1643
-        }
1644
-    }
1645
-
1646
-
1647
-
1648
-    /**
1649
-     *    add_extra_finalize_registration_inputs
1650
-     *
1651
-     * @access    public
1652
-     * @param $next_step
1653
-     * @internal  param string $label
1654
-     * @return void
1655
-     */
1656
-    public function add_extra_finalize_registration_inputs($next_step)
1657
-    {
1658
-        if ($next_step === 'finalize_registration') {
1659
-            echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1660
-        }
1661
-    }
1662
-
1663
-
1664
-
1665
-    /**
1666
-     *    display_registration_footer
1667
-     *
1668
-     * @access    public
1669
-     * @return    string
1670
-     */
1671
-    public static function display_registration_footer()
1672
-    {
1673
-        if (
1674
-        apply_filters(
1675
-            'FHEE__EE_Front__Controller__show_reg_footer',
1676
-            EE_Registry::instance()->CFG->admin->show_reg_footer
1677
-        )
1678
-        ) {
1679
-            add_filter(
1680
-                'FHEE__EEH_Template__powered_by_event_espresso__url',
1681
-                function ($url) {
1682
-                    return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1683
-                }
1684
-            );
1685
-            echo apply_filters(
1686
-                'FHEE__EE_Front_Controller__display_registration_footer',
1687
-                \EEH_Template::powered_by_event_espresso(
1688
-                    '',
1689
-                    'espresso-registration-footer-dv',
1690
-                    array('utm_content' => 'registration_checkout')
1691
-                )
1692
-            );
1693
-        }
1694
-        return '';
1695
-    }
1696
-
1697
-
1698
-
1699
-    /**
1700
-     *    unlock_transaction
1701
-     *
1702
-     * @access    public
1703
-     * @return    void
1704
-     * @throws EE_Error
1705
-     */
1706
-    public function unlock_transaction()
1707
-    {
1708
-        if ($this->checkout->transaction instanceof EE_Transaction) {
1709
-            $this->checkout->transaction->unlock();
1710
-        }
1711
-    }
1712
-
1713
-
1714
-
1715
-    /**
1716
-     *        _setup_redirect
1717
-     *
1718
-     * @access    private
1719
-     * @return void
1720
-     */
1721
-    private function _setup_redirect()
1722
-    {
1723
-        if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1724
-            $this->checkout->redirect = true;
1725
-            if (empty($this->checkout->redirect_url)) {
1726
-                $this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1727
-            }
1728
-            $this->checkout->redirect_url = apply_filters(
1729
-                'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1730
-                $this->checkout->redirect_url,
1731
-                $this->checkout
1732
-            );
1733
-        }
1734
-    }
1735
-
1736
-
1737
-
1738
-    /**
1739
-     *   handle ajax message responses and redirects
1740
-     *
1741
-     * @access public
1742
-     * @return void
1743
-     * @throws EE_Error
1744
-     */
1745
-    public function go_to_next_step()
1746
-    {
1747
-        if (EE_Registry::instance()->REQ->ajax) {
1748
-            // capture contents of output buffer we started earlier in the request, and insert into JSON response
1749
-            $this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1750
-        }
1751
-        $this->unlock_transaction();
1752
-        // just return for these conditions
1753
-        if (
1754
-            $this->checkout->admin_request
1755
-            || $this->checkout->action === 'redirect_form'
1756
-            || $this->checkout->action === 'update_checkout'
1757
-        ) {
1758
-            return;
1759
-        }
1760
-        // AJAX response
1761
-        $this->_handle_json_response();
1762
-        // redirect to next step or the Thank You page
1763
-        $this->_handle_html_redirects();
1764
-        // hmmm... must be something wrong, so let's just display the form again !
1765
-        $this->_display_spco_reg_form();
1766
-    }
1767
-
1768
-
1769
-
1770
-    /**
1771
-     *   _handle_json_response
1772
-     *
1773
-     * @access protected
1774
-     * @return void
1775
-     */
1776
-    protected function _handle_json_response()
1777
-    {
1778
-        // if this is an ajax request
1779
-        if (EE_Registry::instance()->REQ->ajax) {
1780
-            // DEBUG LOG
1781
-            //$this->checkout->log(
1782
-            //	__CLASS__, __FUNCTION__, __LINE__,
1783
-            //	array(
1784
-            //		'json_response_redirect_url' => $this->checkout->json_response->redirect_url(),
1785
-            //		'redirect'                   => $this->checkout->redirect,
1786
-            //		'continue_reg'               => $this->checkout->continue_reg,
1787
-            //	)
1788
-            //);
1789
-            $this->checkout->json_response->set_registration_time_limit(
1790
-                $this->checkout->get_registration_time_limit()
1791
-            );
1792
-            $this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1793
-            // just send the ajax (
1794
-            $json_response = apply_filters(
1795
-                'FHEE__EE_Single_Page_Checkout__JSON_response',
1796
-                $this->checkout->json_response
1797
-            );
1798
-            echo $json_response;
1799
-            exit();
1800
-        }
1801
-    }
1802
-
1803
-
1804
-
1805
-    /**
1806
-     *   _handle_redirects
1807
-     *
1808
-     * @access protected
1809
-     * @return void
1810
-     */
1811
-    protected function _handle_html_redirects()
1812
-    {
1813
-        // going somewhere ?
1814
-        if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1815
-            // store notices in a transient
1816
-            EE_Error::get_notices(false, true, true);
1817
-            // DEBUG LOG
1818
-            //$this->checkout->log(
1819
-            //	__CLASS__, __FUNCTION__, __LINE__,
1820
-            //	array(
1821
-            //		'headers_sent' => headers_sent(),
1822
-            //		'redirect_url'     => $this->checkout->redirect_url,
1823
-            //		'headers_list'    => headers_list(),
1824
-            //	)
1825
-            //);
1826
-            wp_safe_redirect($this->checkout->redirect_url);
1827
-            exit();
1828
-        }
1829
-    }
1830
-
1831
-
1832
-
1833
-    /**
1834
-     *   set_checkout_anchor
1835
-     *
1836
-     * @access public
1837
-     * @return void
1838
-     */
1839
-    public function set_checkout_anchor()
1840
-    {
1841
-        echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1842
-    }
1843
-
1844
-    /**
1845
-     *    getRegistrationExpirationNotice
1846
-     *
1847
-     * @since $VID:$
1848
-     * @access    public
1849
-     * @return    string
1850
-     */
1851
-    public static function getRegistrationExpirationNotice()
1852
-    {
1853
-        return sprintf(
1854
-            __('%1$sWe\'re sorry, but your registration time has expired.%2$s%3$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please accept our apologies for any inconvenience this may have caused.%8$s',
1855
-                'event_espresso'),
1856
-            '<h4 class="important-notice">',
1857
-            '</h4>',
1858
-            '<br />',
1859
-            '<p>',
1860
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1861
-            '">',
1862
-            '</a>',
1863
-            '</p>'
1864
-        );
1865
-    }
23
+	/**
24
+	 * $_initialized - has the SPCO controller already been initialized ?
25
+	 *
26
+	 * @access private
27
+	 * @var bool $_initialized
28
+	 */
29
+	private static $_initialized = false;
30
+
31
+
32
+	/**
33
+	 * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
34
+	 *
35
+	 * @access private
36
+	 * @var bool $_valid_checkout
37
+	 */
38
+	private static $_checkout_verified = true;
39
+
40
+	/**
41
+	 *    $_reg_steps_array - holds initial array of reg steps
42
+	 *
43
+	 * @access private
44
+	 * @var array $_reg_steps_array
45
+	 */
46
+	private static $_reg_steps_array = array();
47
+
48
+	/**
49
+	 *    $checkout - EE_Checkout object for handling the properties of the current checkout process
50
+	 *
51
+	 * @access public
52
+	 * @var EE_Checkout $checkout
53
+	 */
54
+	public $checkout;
55
+
56
+
57
+
58
+	/**
59
+	 * @return EED_Module|EED_Single_Page_Checkout
60
+	 */
61
+	public static function instance()
62
+	{
63
+		add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
64
+		return parent::get_instance(__CLASS__);
65
+	}
66
+
67
+
68
+
69
+	/**
70
+	 * @return EE_CART
71
+	 */
72
+	public function cart()
73
+	{
74
+		return $this->checkout->cart;
75
+	}
76
+
77
+
78
+
79
+	/**
80
+	 * @return EE_Transaction
81
+	 */
82
+	public function transaction()
83
+	{
84
+		return $this->checkout->transaction;
85
+	}
86
+
87
+
88
+
89
+	/**
90
+	 *    set_hooks - for hooking into EE Core, other modules, etc
91
+	 *
92
+	 * @access    public
93
+	 * @return    void
94
+	 * @throws EE_Error
95
+	 */
96
+	public static function set_hooks()
97
+	{
98
+		EED_Single_Page_Checkout::set_definitions();
99
+	}
100
+
101
+
102
+
103
+	/**
104
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
105
+	 *
106
+	 * @access    public
107
+	 * @return    void
108
+	 * @throws EE_Error
109
+	 */
110
+	public static function set_hooks_admin()
111
+	{
112
+		EED_Single_Page_Checkout::set_definitions();
113
+		if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
114
+			return;
115
+		}
116
+		// going to start an output buffer in case anything gets accidentally output
117
+		// that might disrupt our JSON response
118
+		ob_start();
119
+		EED_Single_Page_Checkout::load_request_handler();
120
+		EED_Single_Page_Checkout::load_reg_steps();
121
+		// set ajax hooks
122
+		add_action('wp_ajax_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
123
+		add_action('wp_ajax_nopriv_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
124
+		add_action('wp_ajax_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
125
+		add_action('wp_ajax_nopriv_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
126
+		add_action('wp_ajax_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
127
+		add_action('wp_ajax_nopriv_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
128
+	}
129
+
130
+
131
+
132
+	/**
133
+	 *    process ajax request
134
+	 *
135
+	 * @param string $ajax_action
136
+	 * @throws EE_Error
137
+	 */
138
+	public static function process_ajax_request($ajax_action)
139
+	{
140
+		EE_Registry::instance()->REQ->set('action', $ajax_action);
141
+		EED_Single_Page_Checkout::instance()->_initialize();
142
+	}
143
+
144
+
145
+
146
+	/**
147
+	 *    ajax display registration step
148
+	 *
149
+	 * @throws EE_Error
150
+	 */
151
+	public static function display_reg_step()
152
+	{
153
+		EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
154
+	}
155
+
156
+
157
+
158
+	/**
159
+	 *    ajax process registration step
160
+	 *
161
+	 * @throws EE_Error
162
+	 */
163
+	public static function process_reg_step()
164
+	{
165
+		EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
166
+	}
167
+
168
+
169
+
170
+	/**
171
+	 *    ajax process registration step
172
+	 *
173
+	 * @throws EE_Error
174
+	 */
175
+	public static function update_reg_step()
176
+	{
177
+		EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
178
+	}
179
+
180
+
181
+
182
+	/**
183
+	 *   update_checkout
184
+	 *
185
+	 * @access public
186
+	 * @return void
187
+	 * @throws EE_Error
188
+	 */
189
+	public static function update_checkout()
190
+	{
191
+		EED_Single_Page_Checkout::process_ajax_request('update_checkout');
192
+	}
193
+
194
+
195
+
196
+	/**
197
+	 *    load_request_handler
198
+	 *
199
+	 * @access    public
200
+	 * @return    void
201
+	 */
202
+	public static function load_request_handler()
203
+	{
204
+		// load core Request_Handler class
205
+		if (EE_Registry::instance()->REQ !== null) {
206
+			EE_Registry::instance()->load_core('Request_Handler');
207
+		}
208
+	}
209
+
210
+
211
+
212
+	/**
213
+	 *    set_definitions
214
+	 *
215
+	 * @access    public
216
+	 * @return    void
217
+	 * @throws EE_Error
218
+	 */
219
+	public static function set_definitions()
220
+	{
221
+		if(defined('SPCO_BASE_PATH')) {
222
+			return;
223
+		}
224
+		define(
225
+			'SPCO_BASE_PATH',
226
+			rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS
227
+		);
228
+		define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css' . DS);
229
+		define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img' . DS);
230
+		define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js' . DS);
231
+		define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS);
232
+		define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS);
233
+		define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS);
234
+		EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
235
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] = EED_Single_Page_Checkout::getRegistrationExpirationNotice();
236
+	}
237
+
238
+
239
+
240
+	/**
241
+	 * load_reg_steps
242
+	 * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
243
+	 *
244
+	 * @access    private
245
+	 * @throws EE_Error
246
+	 */
247
+	public static function load_reg_steps()
248
+	{
249
+		static $reg_steps_loaded = false;
250
+		if ($reg_steps_loaded) {
251
+			return;
252
+		}
253
+		// filter list of reg_steps
254
+		$reg_steps_to_load = (array)apply_filters(
255
+			'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
256
+			EED_Single_Page_Checkout::get_reg_steps()
257
+		);
258
+		// sort by key (order)
259
+		ksort($reg_steps_to_load);
260
+		// loop through folders
261
+		foreach ($reg_steps_to_load as $order => $reg_step) {
262
+			// we need a
263
+			if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
264
+				// copy over to the reg_steps_array
265
+				EED_Single_Page_Checkout::$_reg_steps_array[$order] = $reg_step;
266
+				// register custom key route for each reg step
267
+				// ie: step=>"slug" - this is the entire reason we load the reg steps array now
268
+				EE_Config::register_route(
269
+					$reg_step['slug'],
270
+					'EED_Single_Page_Checkout',
271
+					'run',
272
+					'step'
273
+				);
274
+				// add AJAX or other hooks
275
+				if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
276
+					// setup autoloaders if necessary
277
+					if ( ! class_exists($reg_step['class_name'])) {
278
+						EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
279
+							$reg_step['file_path'],
280
+							true
281
+						);
282
+					}
283
+					if (is_callable($reg_step['class_name'], 'set_hooks')) {
284
+						call_user_func(array($reg_step['class_name'], 'set_hooks'));
285
+					}
286
+				}
287
+			}
288
+		}
289
+		$reg_steps_loaded = true;
290
+	}
291
+
292
+
293
+
294
+	/**
295
+	 *    get_reg_steps
296
+	 *
297
+	 * @access    public
298
+	 * @return    array
299
+	 */
300
+	public static function get_reg_steps()
301
+	{
302
+		$reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
303
+		if (empty($reg_steps)) {
304
+			$reg_steps = array(
305
+				10  => array(
306
+					'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
307
+					'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
308
+					'slug'       => 'attendee_information',
309
+					'has_hooks'  => false,
310
+				),
311
+				20  => array(
312
+					'file_path'  => SPCO_REG_STEPS_PATH . 'registration_confirmation',
313
+					'class_name' => 'EE_SPCO_Reg_Step_Registration_Confirmation',
314
+					'slug'       => 'registration_confirmation',
315
+					'has_hooks'  => false,
316
+				),
317
+				30  => array(
318
+					'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
319
+					'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
320
+					'slug'       => 'payment_options',
321
+					'has_hooks'  => true,
322
+				),
323
+				999 => array(
324
+					'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
325
+					'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
326
+					'slug'       => 'finalize_registration',
327
+					'has_hooks'  => false,
328
+				),
329
+			);
330
+		}
331
+		return $reg_steps;
332
+	}
333
+
334
+
335
+
336
+	/**
337
+	 *    registration_checkout_for_admin
338
+	 *
339
+	 * @access    public
340
+	 * @return    string
341
+	 * @throws EE_Error
342
+	 */
343
+	public static function registration_checkout_for_admin()
344
+	{
345
+		EED_Single_Page_Checkout::load_request_handler();
346
+		EE_Registry::instance()->REQ->set('step', 'attendee_information');
347
+		EE_Registry::instance()->REQ->set('action', 'display_spco_reg_step');
348
+		EE_Registry::instance()->REQ->set('process_form_submission', false);
349
+		EED_Single_Page_Checkout::instance()->_initialize();
350
+		EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
351
+		return EE_Registry::instance()->REQ->get_output();
352
+	}
353
+
354
+
355
+
356
+	/**
357
+	 * process_registration_from_admin
358
+	 *
359
+	 * @access public
360
+	 * @return \EE_Transaction
361
+	 * @throws EE_Error
362
+	 */
363
+	public static function process_registration_from_admin()
364
+	{
365
+		EED_Single_Page_Checkout::load_request_handler();
366
+		EE_Registry::instance()->REQ->set('step', 'attendee_information');
367
+		EE_Registry::instance()->REQ->set('action', 'process_reg_step');
368
+		EE_Registry::instance()->REQ->set('process_form_submission', true);
369
+		EED_Single_Page_Checkout::instance()->_initialize();
370
+		if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
371
+			$final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
372
+			if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
373
+				EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
374
+				if ($final_reg_step->process_reg_step()) {
375
+					$final_reg_step->set_completed();
376
+					EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
377
+					return EED_Single_Page_Checkout::instance()->checkout->transaction;
378
+				}
379
+			}
380
+		}
381
+		return null;
382
+	}
383
+
384
+
385
+
386
+	/**
387
+	 *    run
388
+	 *
389
+	 * @access    public
390
+	 * @param WP_Query $WP_Query
391
+	 * @return    void
392
+	 * @throws EE_Error
393
+	 */
394
+	public function run($WP_Query)
395
+	{
396
+		if (
397
+			$WP_Query instanceof WP_Query
398
+			&& $WP_Query->is_main_query()
399
+			&& apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
400
+			&& $this->_is_reg_checkout()
401
+		) {
402
+			$this->_initialize();
403
+		}
404
+	}
405
+
406
+
407
+
408
+	/**
409
+	 * determines whether current url matches reg page url
410
+	 *
411
+	 * @return bool
412
+	 */
413
+	protected function _is_reg_checkout()
414
+	{
415
+		// get current permalink for reg page without any extra query args
416
+		$reg_page_url = \get_permalink(EE_Config::instance()->core->reg_page_id);
417
+		// get request URI for current request, but without the scheme or host
418
+		$current_request_uri = \EEH_URL::filter_input_server_url('REQUEST_URI');
419
+		$current_request_uri = html_entity_decode($current_request_uri);
420
+		// get array of query args from the current request URI
421
+		$query_args = \EEH_URL::get_query_string($current_request_uri);
422
+		// grab page id if it is set
423
+		$page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
424
+		// and remove the page id from the query args (we will re-add it later)
425
+		unset($query_args['page_id']);
426
+		// now strip all query args from current request URI
427
+		$current_request_uri = remove_query_arg(array_keys($query_args), $current_request_uri);
428
+		// and re-add the page id if it was set
429
+		if ($page_id) {
430
+			$current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
431
+		}
432
+		// remove slashes and ?
433
+		$current_request_uri = trim($current_request_uri, '?/');
434
+		// is current request URI part of the known full reg page URL ?
435
+		return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
436
+	}
437
+
438
+
439
+
440
+	/**
441
+	 * @param WP_Query $wp_query
442
+	 * @return    void
443
+	 * @throws EE_Error
444
+	 */
445
+	public static function init($wp_query)
446
+	{
447
+		EED_Single_Page_Checkout::instance()->run($wp_query);
448
+	}
449
+
450
+
451
+
452
+	/**
453
+	 *    _initialize - initial module setup
454
+	 *
455
+	 * @access    private
456
+	 * @throws EE_Error
457
+	 * @return    void
458
+	 */
459
+	private function _initialize()
460
+	{
461
+		// ensure SPCO doesn't run twice
462
+		if (EED_Single_Page_Checkout::$_initialized) {
463
+			return;
464
+		}
465
+		try {
466
+			EED_Single_Page_Checkout::load_reg_steps();
467
+			$this->_verify_session();
468
+			// setup the EE_Checkout object
469
+			$this->checkout = $this->_initialize_checkout();
470
+			// filter checkout
471
+			$this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
472
+			// get the $_GET
473
+			$this->_get_request_vars();
474
+			if ($this->_block_bots()) {
475
+				return;
476
+			}
477
+			// filter continue_reg
478
+			$this->checkout->continue_reg = apply_filters(
479
+				'FHEE__EED_Single_Page_Checkout__init___continue_reg',
480
+				true,
481
+				$this->checkout
482
+			);
483
+			// load the reg steps array
484
+			if ( ! $this->_load_and_instantiate_reg_steps()) {
485
+				EED_Single_Page_Checkout::$_initialized = true;
486
+				return;
487
+			}
488
+			// set the current step
489
+			$this->checkout->set_current_step($this->checkout->step);
490
+			// and the next step
491
+			$this->checkout->set_next_step();
492
+			// verify that everything has been setup correctly
493
+			if ( ! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
494
+				EED_Single_Page_Checkout::$_initialized = true;
495
+				return;
496
+			}
497
+			// lock the transaction
498
+			$this->checkout->transaction->lock();
499
+			// make sure all of our cached objects are added to their respective model entity mappers
500
+			$this->checkout->refresh_all_entities();
501
+			// set amount owing
502
+			$this->checkout->amount_owing = $this->checkout->transaction->remaining();
503
+			// initialize each reg step, which gives them the chance to potentially alter the process
504
+			$this->_initialize_reg_steps();
505
+			// DEBUG LOG
506
+			//$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
507
+			// get reg form
508
+			if( ! $this->_check_form_submission()) {
509
+				EED_Single_Page_Checkout::$_initialized = true;
510
+				return;
511
+			}
512
+			// checkout the action!!!
513
+			$this->_process_form_action();
514
+			// add some style and make it dance
515
+			$this->add_styles_and_scripts();
516
+			// kk... SPCO has successfully run
517
+			EED_Single_Page_Checkout::$_initialized = true;
518
+			// set no cache headers and constants
519
+			EE_System::do_not_cache();
520
+			// add anchor
521
+			add_action('loop_start', array($this, 'set_checkout_anchor'), 1);
522
+			// remove transaction lock
523
+			add_action('shutdown', array($this, 'unlock_transaction'), 1);
524
+		} catch (Exception $e) {
525
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
526
+		}
527
+	}
528
+
529
+
530
+
531
+	/**
532
+	 *    _verify_session
533
+	 * checks that the session is valid and not expired
534
+	 *
535
+	 * @access    private
536
+	 * @throws EE_Error
537
+	 */
538
+	private function _verify_session()
539
+	{
540
+		if ( ! EE_Registry::instance()->SSN instanceof EE_Session) {
541
+			throw new EE_Error(__('The EE_Session class could not be loaded.', 'event_espresso'));
542
+		}
543
+		$clear_session_requested = filter_var(
544
+			EE_Registry::instance()->REQ->get('clear_session', false),
545
+			FILTER_VALIDATE_BOOLEAN
546
+		);
547
+		// is session still valid ?
548
+		if ($clear_session_requested
549
+			|| ( EE_Registry::instance()->SSN->expired()
550
+			  && EE_Registry::instance()->REQ->get('e_reg_url_link', '') === ''
551
+			)
552
+		) {
553
+			$this->checkout = new EE_Checkout();
554
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
555
+			// EE_Registry::instance()->SSN->reset_cart();
556
+			// EE_Registry::instance()->SSN->reset_checkout();
557
+			// EE_Registry::instance()->SSN->reset_transaction();
558
+			if (! $clear_session_requested) {
559
+				EE_Error::add_attention(
560
+					EE_Registry::$i18n_js_strings['registration_expiration_notice'],
561
+					__FILE__, __FUNCTION__, __LINE__
562
+				);
563
+			}
564
+			// EE_Registry::instance()->SSN->reset_expired();
565
+		}
566
+	}
567
+
568
+
569
+
570
+	/**
571
+	 *    _initialize_checkout
572
+	 * loads and instantiates EE_Checkout
573
+	 *
574
+	 * @access    private
575
+	 * @throws EE_Error
576
+	 * @return EE_Checkout
577
+	 */
578
+	private function _initialize_checkout()
579
+	{
580
+		// look in session for existing checkout
581
+		/** @type EE_Checkout $checkout */
582
+		$checkout = EE_Registry::instance()->SSN->checkout();
583
+		// verify
584
+		if ( ! $checkout instanceof EE_Checkout) {
585
+			// instantiate EE_Checkout object for handling the properties of the current checkout process
586
+			$checkout = EE_Registry::instance()->load_file(
587
+				SPCO_INC_PATH,
588
+				'EE_Checkout',
589
+				'class', array(),
590
+				false
591
+			);
592
+		} else {
593
+			if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
594
+				$this->unlock_transaction();
595
+				wp_safe_redirect($checkout->redirect_url);
596
+				exit();
597
+			}
598
+		}
599
+		$checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
600
+		// verify again
601
+		if ( ! $checkout instanceof EE_Checkout) {
602
+			throw new EE_Error(__('The EE_Checkout class could not be loaded.', 'event_espresso'));
603
+		}
604
+		// reset anything that needs a clean slate for each request
605
+		$checkout->reset_for_current_request();
606
+		return $checkout;
607
+	}
608
+
609
+
610
+
611
+	/**
612
+	 *    _get_request_vars
613
+	 *
614
+	 * @access    private
615
+	 * @return    void
616
+	 * @throws EE_Error
617
+	 */
618
+	private function _get_request_vars()
619
+	{
620
+		// load classes
621
+		EED_Single_Page_Checkout::load_request_handler();
622
+		//make sure this request is marked as belonging to EE
623
+		EE_Registry::instance()->REQ->set_espresso_page(true);
624
+		// which step is being requested ?
625
+		$this->checkout->step = EE_Registry::instance()->REQ->get('step', $this->_get_first_step());
626
+		// which step is being edited ?
627
+		$this->checkout->edit_step = EE_Registry::instance()->REQ->get('edit_step', '');
628
+		// and what we're doing on the current step
629
+		$this->checkout->action = EE_Registry::instance()->REQ->get('action', 'display_spco_reg_step');
630
+		// timestamp
631
+		$this->checkout->uts = EE_Registry::instance()->REQ->get('uts', 0);
632
+		// returning to edit ?
633
+		$this->checkout->reg_url_link = EE_Registry::instance()->REQ->get('e_reg_url_link', '');
634
+		// add reg url link to registration query params
635
+		if ($this->checkout->reg_url_link && strpos($this->checkout->reg_url_link, '1-') !== 0) {
636
+			$this->checkout->reg_cache_where_params[0]['REG_url_link'] = $this->checkout->reg_url_link;
637
+		}
638
+		// or some other kind of revisit ?
639
+		$this->checkout->revisit = filter_var(
640
+			EE_Registry::instance()->REQ->get('revisit', false),
641
+			FILTER_VALIDATE_BOOLEAN
642
+		);
643
+		// and whether or not to generate a reg form for this request
644
+		$this->checkout->generate_reg_form = filter_var(
645
+			EE_Registry::instance()->REQ->get('generate_reg_form', true),
646
+			FILTER_VALIDATE_BOOLEAN
647
+		);
648
+		// and whether or not to process a reg form submission for this request
649
+		$this->checkout->process_form_submission = filter_var(
650
+			EE_Registry::instance()->REQ->get(
651
+				'process_form_submission',
652
+				$this->checkout->action === 'process_reg_step'
653
+			),
654
+			FILTER_VALIDATE_BOOLEAN
655
+		);
656
+		$this->checkout->process_form_submission = filter_var(
657
+			$this->checkout->action !== 'display_spco_reg_step'
658
+				? $this->checkout->process_form_submission
659
+				: false,
660
+			FILTER_VALIDATE_BOOLEAN
661
+		);
662
+		// $this->_display_request_vars();
663
+	}
664
+
665
+
666
+
667
+	/**
668
+	 *  _display_request_vars
669
+	 *
670
+	 * @access    protected
671
+	 * @return    void
672
+	 */
673
+	protected function _display_request_vars()
674
+	{
675
+		if ( ! WP_DEBUG) {
676
+			return;
677
+		}
678
+		EEH_Debug_Tools::printr($_REQUEST, '$_REQUEST', __FILE__, __LINE__);
679
+		EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
680
+		EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
681
+		EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
682
+		EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
683
+		EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
684
+		EEH_Debug_Tools::printr($this->checkout->generate_reg_form, '$this->checkout->generate_reg_form', __FILE__, __LINE__);
685
+		EEH_Debug_Tools::printr($this->checkout->process_form_submission, '$this->checkout->process_form_submission', __FILE__, __LINE__);
686
+	}
687
+
688
+
689
+
690
+	/**
691
+	 * _block_bots
692
+	 * checks that the incoming request has either of the following set:
693
+	 *  a uts (unix timestamp) which indicates that the request was redirected from the Ticket Selector
694
+	 *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
695
+	 * so if you're not coming from the Ticket Selector nor returning for a valid IP...
696
+	 * then where you coming from man?
697
+	 *
698
+	 * @return boolean
699
+	 */
700
+	private function _block_bots()
701
+	{
702
+		$invalid_checkout_access = EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
703
+		if ($invalid_checkout_access->checkoutAccessIsInvalid($this->checkout)) {
704
+			return true;
705
+		}
706
+		return false;
707
+	}
708
+
709
+
710
+
711
+	/**
712
+	 *    _get_first_step
713
+	 *  gets slug for first step in $_reg_steps_array
714
+	 *
715
+	 * @access    private
716
+	 * @throws EE_Error
717
+	 * @return    string
718
+	 */
719
+	private function _get_first_step()
720
+	{
721
+		$first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
722
+		return isset($first_step['slug']) ? $first_step['slug'] : 'attendee_information';
723
+	}
724
+
725
+
726
+
727
+	/**
728
+	 *    _load_and_instantiate_reg_steps
729
+	 *  instantiates each reg step based on the loaded reg_steps array
730
+	 *
731
+	 * @access    private
732
+	 * @throws EE_Error
733
+	 * @return    bool
734
+	 */
735
+	private function _load_and_instantiate_reg_steps()
736
+	{
737
+		do_action('AHEE__Single_Page_Checkout___load_and_instantiate_reg_steps__start', $this->checkout);
738
+		// have reg_steps already been instantiated ?
739
+		if (
740
+			empty($this->checkout->reg_steps)
741
+			|| apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
742
+		) {
743
+			// if not, then loop through raw reg steps array
744
+			foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
745
+				if ( ! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
746
+					return false;
747
+				}
748
+			}
749
+			EE_Registry::instance()->CFG->registration->skip_reg_confirmation = true;
750
+			EE_Registry::instance()->CFG->registration->reg_confirmation_last = true;
751
+			// skip the registration_confirmation page ?
752
+			if (EE_Registry::instance()->CFG->registration->skip_reg_confirmation) {
753
+				// just remove it from the reg steps array
754
+				$this->checkout->remove_reg_step('registration_confirmation', false);
755
+			} else if (
756
+				isset($this->checkout->reg_steps['registration_confirmation'])
757
+				&& EE_Registry::instance()->CFG->registration->reg_confirmation_last
758
+			) {
759
+				// set the order to something big like 100
760
+				$this->checkout->set_reg_step_order('registration_confirmation', 100);
761
+			}
762
+			// filter the array for good luck
763
+			$this->checkout->reg_steps = apply_filters(
764
+				'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
765
+				$this->checkout->reg_steps
766
+			);
767
+			// finally re-sort based on the reg step class order properties
768
+			$this->checkout->sort_reg_steps();
769
+		} else {
770
+			foreach ($this->checkout->reg_steps as $reg_step) {
771
+				// set all current step stati to FALSE
772
+				$reg_step->set_is_current_step(false);
773
+			}
774
+		}
775
+		if (empty($this->checkout->reg_steps)) {
776
+			EE_Error::add_error(
777
+				__('No Reg Steps were loaded..', 'event_espresso'),
778
+				__FILE__, __FUNCTION__, __LINE__
779
+			);
780
+			return false;
781
+		}
782
+		// make reg step details available to JS
783
+		$this->checkout->set_reg_step_JSON_info();
784
+		return true;
785
+	}
786
+
787
+
788
+
789
+	/**
790
+	 *     _load_and_instantiate_reg_step
791
+	 *
792
+	 * @access    private
793
+	 * @param array $reg_step
794
+	 * @param int   $order
795
+	 * @return bool
796
+	 */
797
+	private function _load_and_instantiate_reg_step($reg_step = array(), $order = 0)
798
+	{
799
+		// we need a file_path, class_name, and slug to add a reg step
800
+		if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
801
+			// if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
802
+			if (
803
+				$this->checkout->reg_url_link
804
+				&& $this->checkout->step !== $reg_step['slug']
805
+				&& $reg_step['slug'] !== 'finalize_registration'
806
+				// normally at this point we would NOT load the reg step, but this filter can change that
807
+				&& apply_filters(
808
+					'FHEE__Single_Page_Checkout___load_and_instantiate_reg_step__bypass_reg_step',
809
+					true,
810
+					$reg_step,
811
+					$this->checkout
812
+				)
813
+			) {
814
+				return true;
815
+			}
816
+			// instantiate step class using file path and class name
817
+			$reg_step_obj = EE_Registry::instance()->load_file(
818
+				$reg_step['file_path'],
819
+				$reg_step['class_name'],
820
+				'class',
821
+				$this->checkout,
822
+				false
823
+			);
824
+			// did we gets the goods ?
825
+			if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
826
+				// set reg step order based on config
827
+				$reg_step_obj->set_order($order);
828
+				// add instantiated reg step object to the master reg steps array
829
+				$this->checkout->add_reg_step($reg_step_obj);
830
+			} else {
831
+				EE_Error::add_error(
832
+					__('The current step could not be set.', 'event_espresso'),
833
+					__FILE__, __FUNCTION__, __LINE__
834
+				);
835
+				return false;
836
+			}
837
+		} else {
838
+			if (WP_DEBUG) {
839
+				EE_Error::add_error(
840
+					sprintf(
841
+						__(
842
+							'A registration step could not be loaded. One or more of the following data points is invalid:%4$s%5$sFile Path: %1$s%6$s%5$sClass Name: %2$s%6$s%5$sSlug: %3$s%6$s%7$s',
843
+							'event_espresso'
844
+						),
845
+						isset($reg_step['file_path']) ? $reg_step['file_path'] : '',
846
+						isset($reg_step['class_name']) ? $reg_step['class_name'] : '',
847
+						isset($reg_step['slug']) ? $reg_step['slug'] : '',
848
+						'<ul>',
849
+						'<li>',
850
+						'</li>',
851
+						'</ul>'
852
+					),
853
+					__FILE__, __FUNCTION__, __LINE__
854
+				);
855
+			}
856
+			return false;
857
+		}
858
+		return true;
859
+	}
860
+
861
+
862
+	/**
863
+	 * _verify_transaction_and_get_registrations
864
+	 *
865
+	 * @access private
866
+	 * @return bool
867
+	 * @throws InvalidDataTypeException
868
+	 * @throws InvalidEntityException
869
+	 * @throws EE_Error
870
+	 */
871
+	private function _verify_transaction_and_get_registrations()
872
+	{
873
+		// was there already a valid transaction in the checkout from the session ?
874
+		if ( ! $this->checkout->transaction instanceof EE_Transaction) {
875
+			// get transaction from db or session
876
+			$this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
877
+				? $this->_get_transaction_and_cart_for_previous_visit()
878
+				: $this->_get_cart_for_current_session_and_setup_new_transaction();
879
+			if ( ! $this->checkout->transaction instanceof EE_Transaction) {
880
+				EE_Error::add_error(
881
+					__('Your Registration and Transaction information could not be retrieved from the db.',
882
+						'event_espresso'),
883
+					__FILE__, __FUNCTION__, __LINE__
884
+				);
885
+				$this->checkout->transaction = EE_Transaction::new_instance();
886
+				// add some style and make it dance
887
+				$this->add_styles_and_scripts();
888
+				EED_Single_Page_Checkout::$_initialized = true;
889
+				return false;
890
+			}
891
+			// and the registrations for the transaction
892
+			$this->_get_registrations($this->checkout->transaction);
893
+		}
894
+		return true;
895
+	}
896
+
897
+
898
+
899
+	/**
900
+	 * _get_transaction_and_cart_for_previous_visit
901
+	 *
902
+	 * @access private
903
+	 * @return mixed EE_Transaction|NULL
904
+	 */
905
+	private function _get_transaction_and_cart_for_previous_visit()
906
+	{
907
+		/** @var $TXN_model EEM_Transaction */
908
+		$TXN_model = EE_Registry::instance()->load_model('Transaction');
909
+		// because the reg_url_link is present in the request,
910
+		// this is a return visit to SPCO, so we'll get the transaction data from the db
911
+		$transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
912
+		// verify transaction
913
+		if ($transaction instanceof EE_Transaction) {
914
+			// and get the cart that was used for that transaction
915
+			$this->checkout->cart = $this->_get_cart_for_transaction($transaction);
916
+			return $transaction;
917
+		}
918
+		EE_Error::add_error(
919
+			__('Your Registration and Transaction information could not be retrieved from the db.', 'event_espresso'),
920
+			__FILE__, __FUNCTION__, __LINE__
921
+		);
922
+		return null;
923
+
924
+	}
925
+
926
+
927
+
928
+	/**
929
+	 * _get_cart_for_transaction
930
+	 *
931
+	 * @access private
932
+	 * @param EE_Transaction $transaction
933
+	 * @return EE_Cart
934
+	 */
935
+	private function _get_cart_for_transaction($transaction)
936
+	{
937
+		return $this->checkout->get_cart_for_transaction($transaction);
938
+	}
939
+
940
+
941
+
942
+	/**
943
+	 * get_cart_for_transaction
944
+	 *
945
+	 * @access public
946
+	 * @param EE_Transaction $transaction
947
+	 * @return EE_Cart
948
+	 */
949
+	public function get_cart_for_transaction(EE_Transaction $transaction)
950
+	{
951
+		return $this->checkout->get_cart_for_transaction($transaction);
952
+	}
953
+
954
+
955
+
956
+	/**
957
+	 * _get_transaction_and_cart_for_current_session
958
+	 *    generates a new EE_Transaction object and adds it to the $_transaction property.
959
+	 *
960
+	 * @access private
961
+	 * @return EE_Transaction
962
+	 * @throws EE_Error
963
+	 */
964
+	private function _get_cart_for_current_session_and_setup_new_transaction()
965
+	{
966
+		//  if there's no transaction, then this is the FIRST visit to SPCO
967
+		// so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
968
+		$this->checkout->cart = $this->_get_cart_for_transaction(null);
969
+		// and then create a new transaction
970
+		$transaction = $this->_initialize_transaction();
971
+		// verify transaction
972
+		if ($transaction instanceof EE_Transaction) {
973
+			// save it so that we have an ID for other objects to use
974
+			$transaction->save();
975
+			// and save TXN data to the cart
976
+			$this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
977
+		} else {
978
+			EE_Error::add_error(
979
+				__('A Valid Transaction could not be initialized.', 'event_espresso'),
980
+				__FILE__, __FUNCTION__, __LINE__
981
+			);
982
+		}
983
+		return $transaction;
984
+	}
985
+
986
+
987
+
988
+	/**
989
+	 *    generates a new EE_Transaction object and adds it to the $_transaction property.
990
+	 *
991
+	 * @access private
992
+	 * @return mixed EE_Transaction|NULL
993
+	 */
994
+	private function _initialize_transaction()
995
+	{
996
+		try {
997
+			// ensure cart totals have been calculated
998
+			$this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
999
+			// grab the cart grand total
1000
+			$cart_total = $this->checkout->cart->get_cart_grand_total();
1001
+			// create new TXN
1002
+			$transaction = EE_Transaction::new_instance(
1003
+				array(
1004
+					'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
1005
+					'TXN_total'     => $cart_total > 0 ? $cart_total : 0,
1006
+					'TXN_paid'      => 0,
1007
+					'STS_ID'        => EEM_Transaction::failed_status_code,
1008
+				)
1009
+			);
1010
+			// save it so that we have an ID for other objects to use
1011
+			$transaction->save();
1012
+			// set cron job for following up on TXNs after their session has expired
1013
+			EE_Cron_Tasks::schedule_expired_transaction_check(
1014
+				EE_Registry::instance()->SSN->expiration() + 1,
1015
+				$transaction->ID()
1016
+			);
1017
+			return $transaction;
1018
+		} catch (Exception $e) {
1019
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1020
+		}
1021
+		return null;
1022
+	}
1023
+
1024
+
1025
+	/**
1026
+	 * _get_registrations
1027
+	 *
1028
+	 * @access private
1029
+	 * @param EE_Transaction $transaction
1030
+	 * @return void
1031
+	 * @throws InvalidDataTypeException
1032
+	 * @throws InvalidEntityException
1033
+	 * @throws EE_Error
1034
+	 */
1035
+	private function _get_registrations(EE_Transaction $transaction)
1036
+	{
1037
+		// first step: grab the registrants  { : o
1038
+		$registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
1039
+		$this->checkout->total_ticket_count = count($registrations);
1040
+		// verify registrations have been set
1041
+		if (empty($registrations)) {
1042
+			// if no cached registrations, then check the db
1043
+			$registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
1044
+			// still nothing ? well as long as this isn't a revisit
1045
+			if (empty($registrations) && ! $this->checkout->revisit) {
1046
+				// generate new registrations from scratch
1047
+				$registrations = $this->_initialize_registrations($transaction);
1048
+			}
1049
+		}
1050
+		// sort by their original registration order
1051
+		usort($registrations, array('EED_Single_Page_Checkout', 'sort_registrations_by_REG_count'));
1052
+		// then loop thru the array
1053
+		foreach ($registrations as $registration) {
1054
+			// verify each registration
1055
+			if ($registration instanceof EE_Registration) {
1056
+				// we display all attendee info for the primary registrant
1057
+				if ($this->checkout->reg_url_link === $registration->reg_url_link()
1058
+					&& $registration->is_primary_registrant()
1059
+				) {
1060
+					$this->checkout->primary_revisit = true;
1061
+					break;
1062
+				}
1063
+				if ($this->checkout->revisit && $this->checkout->reg_url_link !== $registration->reg_url_link()) {
1064
+					// but hide info if it doesn't belong to you
1065
+					$transaction->clear_cache('Registration', $registration->ID());
1066
+					$this->checkout->total_ticket_count--;
1067
+				}
1068
+				$this->checkout->set_reg_status_updated($registration->ID(), false);
1069
+			}
1070
+		}
1071
+	}
1072
+
1073
+
1074
+	/**
1075
+	 *    adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1076
+	 *
1077
+	 * @access private
1078
+	 * @param EE_Transaction $transaction
1079
+	 * @return    array
1080
+	 * @throws InvalidDataTypeException
1081
+	 * @throws InvalidEntityException
1082
+	 * @throws EE_Error
1083
+	 */
1084
+	private function _initialize_registrations(EE_Transaction $transaction)
1085
+	{
1086
+		$att_nmbr = 0;
1087
+		$registrations = array();
1088
+		if ($transaction instanceof EE_Transaction) {
1089
+			/** @type EE_Registration_Processor $registration_processor */
1090
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1091
+			$this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1092
+			// now let's add the cart items to the $transaction
1093
+			foreach ($this->checkout->cart->get_tickets() as $line_item) {
1094
+				//do the following for each ticket of this type they selected
1095
+				for ($x = 1; $x <= $line_item->quantity(); $x++) {
1096
+					$att_nmbr++;
1097
+					/** @var EventEspresso\core\services\commands\registration\CreateRegistrationCommand $CreateRegistrationCommand */
1098
+					$CreateRegistrationCommand = EE_Registry::instance()->create(
1099
+						'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1100
+						array(
1101
+							$transaction,
1102
+							$line_item,
1103
+							$att_nmbr,
1104
+							$this->checkout->total_ticket_count,
1105
+						)
1106
+					);
1107
+					// override capabilities for frontend registrations
1108
+					if ( ! is_admin()) {
1109
+						$CreateRegistrationCommand->setCapCheck(
1110
+							new PublicCapabilities('', 'create_new_registration')
1111
+						);
1112
+					}
1113
+					$registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1114
+					if ( ! $registration instanceof EE_Registration) {
1115
+						throw new InvalidEntityException($registration, 'EE_Registration');
1116
+					}
1117
+					$registrations[ $registration->ID() ] = $registration;
1118
+				}
1119
+			}
1120
+			$registration_processor->fix_reg_final_price_rounding_issue($transaction);
1121
+		}
1122
+		return $registrations;
1123
+	}
1124
+
1125
+
1126
+
1127
+	/**
1128
+	 * sorts registrations by REG_count
1129
+	 *
1130
+	 * @access public
1131
+	 * @param EE_Registration $reg_A
1132
+	 * @param EE_Registration $reg_B
1133
+	 * @return int
1134
+	 */
1135
+	public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B)
1136
+	{
1137
+		// this shouldn't ever happen within the same TXN, but oh well
1138
+		if ($reg_A->count() === $reg_B->count()) {
1139
+			return 0;
1140
+		}
1141
+		return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1142
+	}
1143
+
1144
+
1145
+
1146
+	/**
1147
+	 *    _final_verifications
1148
+	 * just makes sure that everything is set up correctly before proceeding
1149
+	 *
1150
+	 * @access    private
1151
+	 * @return    bool
1152
+	 * @throws EE_Error
1153
+	 */
1154
+	private function _final_verifications()
1155
+	{
1156
+		// filter checkout
1157
+		$this->checkout = apply_filters(
1158
+			'FHEE__EED_Single_Page_Checkout___final_verifications__checkout',
1159
+			$this->checkout
1160
+		);
1161
+		//verify that current step is still set correctly
1162
+		if ( ! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1163
+			EE_Error::add_error(
1164
+				__('We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.', 'event_espresso'),
1165
+				__FILE__,
1166
+				__FUNCTION__,
1167
+				__LINE__
1168
+			);
1169
+			return false;
1170
+		}
1171
+		// if returning to SPCO, then verify that primary registrant is set
1172
+		if ( ! empty($this->checkout->reg_url_link)) {
1173
+			$valid_registrant = $this->checkout->transaction->primary_registration();
1174
+			if ( ! $valid_registrant instanceof EE_Registration) {
1175
+				EE_Error::add_error(
1176
+					__('We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.', 'event_espresso'),
1177
+					__FILE__,
1178
+					__FUNCTION__,
1179
+					__LINE__
1180
+				);
1181
+				return false;
1182
+			}
1183
+			$valid_registrant = null;
1184
+			foreach (
1185
+				$this->checkout->transaction->registrations($this->checkout->reg_cache_where_params) as $registration
1186
+			) {
1187
+				if (
1188
+					$registration instanceof EE_Registration
1189
+					&& $registration->reg_url_link() === $this->checkout->reg_url_link
1190
+				) {
1191
+					$valid_registrant = $registration;
1192
+				}
1193
+			}
1194
+			if ( ! $valid_registrant instanceof EE_Registration) {
1195
+				// hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1196
+				if (EED_Single_Page_Checkout::$_checkout_verified) {
1197
+					// clear the session, mark the checkout as unverified, and try again
1198
+					EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
1199
+					EED_Single_Page_Checkout::$_initialized = false;
1200
+					EED_Single_Page_Checkout::$_checkout_verified = false;
1201
+					$this->_initialize();
1202
+					EE_Error::reset_notices();
1203
+					return false;
1204
+				}
1205
+				EE_Error::add_error(
1206
+					__(
1207
+						'We\'re sorry but there appears to be an error with the "reg_url_link" or the transaction itself. Please refresh the page and try again or contact support.',
1208
+						'event_espresso'
1209
+					),
1210
+					__FILE__,
1211
+					__FUNCTION__,
1212
+					__LINE__
1213
+				);
1214
+				return false;
1215
+			}
1216
+		}
1217
+		// now that things have been kinda sufficiently verified,
1218
+		// let's add the checkout to the session so that it's available to other systems
1219
+		EE_Registry::instance()->SSN->set_checkout($this->checkout);
1220
+		return true;
1221
+	}
1222
+
1223
+
1224
+
1225
+	/**
1226
+	 *    _initialize_reg_steps
1227
+	 * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1228
+	 * then loops thru all of the active reg steps and calls the initialize_reg_step() method
1229
+	 *
1230
+	 * @access    private
1231
+	 * @param bool $reinitializing
1232
+	 * @throws EE_Error
1233
+	 */
1234
+	private function _initialize_reg_steps($reinitializing = false)
1235
+	{
1236
+		$this->checkout->set_reg_step_initiated($this->checkout->current_step);
1237
+		// loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1238
+		foreach ($this->checkout->reg_steps as $reg_step) {
1239
+			if ( ! $reg_step->initialize_reg_step()) {
1240
+				// if not initialized then maybe this step is being removed...
1241
+				if ( ! $reinitializing && $reg_step->is_current_step()) {
1242
+					// if it was the current step, then we need to start over here
1243
+					$this->_initialize_reg_steps(true);
1244
+					return;
1245
+				}
1246
+				continue;
1247
+			}
1248
+			// add css and JS for current step
1249
+			$reg_step->enqueue_styles_and_scripts();
1250
+			// i18n
1251
+			$reg_step->translate_js_strings();
1252
+			if ($reg_step->is_current_step()) {
1253
+				// the text that appears on the reg step form submit button
1254
+				$reg_step->set_submit_button_text();
1255
+			}
1256
+		}
1257
+		// dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1258
+		do_action(
1259
+			"AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}",
1260
+			$this->checkout->current_step
1261
+		);
1262
+	}
1263
+
1264
+
1265
+
1266
+	/**
1267
+	 * _check_form_submission
1268
+	 *
1269
+	 * @access private
1270
+	 * @return boolean
1271
+	 */
1272
+	private function _check_form_submission()
1273
+	{
1274
+		//does this request require the reg form to be generated ?
1275
+		if ($this->checkout->generate_reg_form) {
1276
+			// ever heard that song by Blue Rodeo ?
1277
+			try {
1278
+				$this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1279
+				// if not displaying a form, then check for form submission
1280
+				if (
1281
+					$this->checkout->process_form_submission
1282
+					&& $this->checkout->current_step->reg_form->was_submitted()
1283
+				) {
1284
+					// clear out any old data in case this step is being run again
1285
+					$this->checkout->current_step->set_valid_data(array());
1286
+					// capture submitted form data
1287
+					$this->checkout->current_step->reg_form->receive_form_submission(
1288
+						apply_filters(
1289
+							'FHEE__Single_Page_Checkout___check_form_submission__request_params',
1290
+							EE_Registry::instance()->REQ->params(),
1291
+							$this->checkout
1292
+						)
1293
+					);
1294
+					// validate submitted form data
1295
+					if ( ! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1296
+						// thou shall not pass !!!
1297
+						$this->checkout->continue_reg = false;
1298
+						// any form validation errors?
1299
+						if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1300
+							EE_Error::add_error(
1301
+								$this->checkout->current_step->reg_form->submission_error_message(),
1302
+								__FILE__, __FUNCTION__, __LINE__
1303
+							);
1304
+						}
1305
+						// well not really... what will happen is
1306
+						// we'll just get redirected back to redo the current step
1307
+						$this->go_to_next_step();
1308
+						return false;
1309
+					}
1310
+				}
1311
+			} catch (EE_Error $e) {
1312
+				$e->get_error();
1313
+			}
1314
+		}
1315
+		return true;
1316
+	}
1317
+
1318
+
1319
+
1320
+	/**
1321
+	 * _process_action
1322
+	 *
1323
+	 * @access private
1324
+	 * @return void
1325
+	 * @throws EE_Error
1326
+	 */
1327
+	private function _process_form_action()
1328
+	{
1329
+		// what cha wanna do?
1330
+		switch ($this->checkout->action) {
1331
+			// AJAX next step reg form
1332
+			case 'display_spco_reg_step' :
1333
+				$this->checkout->redirect = false;
1334
+				if (EE_Registry::instance()->REQ->ajax) {
1335
+					$this->checkout->json_response->set_reg_step_html(
1336
+						$this->checkout->current_step->display_reg_form()
1337
+					);
1338
+				}
1339
+				break;
1340
+			default :
1341
+				// meh... do one of those other steps first
1342
+				if (
1343
+					! empty($this->checkout->action)
1344
+					&& is_callable(array($this->checkout->current_step, $this->checkout->action))
1345
+				) {
1346
+					// dynamically creates hook point like:
1347
+					//   AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1348
+					do_action(
1349
+						"AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1350
+						$this->checkout->current_step
1351
+					);
1352
+					// call action on current step
1353
+					if (call_user_func(array($this->checkout->current_step, $this->checkout->action))) {
1354
+						// good registrant, you get to proceed
1355
+						if (
1356
+							$this->checkout->current_step->success_message() !== ''
1357
+							&& apply_filters(
1358
+								'FHEE__Single_Page_Checkout___process_form_action__display_success',
1359
+								false
1360
+							)
1361
+						) {
1362
+							EE_Error::add_success(
1363
+								$this->checkout->current_step->success_message()
1364
+								. '<br />' . $this->checkout->next_step->_instructions()
1365
+							);
1366
+						}
1367
+						// pack it up, pack it in...
1368
+						$this->_setup_redirect();
1369
+					}
1370
+					// dynamically creates hook point like:
1371
+					//  AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1372
+					do_action(
1373
+						"AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1374
+						$this->checkout->current_step
1375
+					);
1376
+				} else {
1377
+					EE_Error::add_error(
1378
+						sprintf(
1379
+							__(
1380
+								'The requested form action "%s" does not exist for the current "%s" registration step.',
1381
+								'event_espresso'
1382
+							),
1383
+							$this->checkout->action,
1384
+							$this->checkout->current_step->name()
1385
+						),
1386
+						__FILE__,
1387
+						__FUNCTION__,
1388
+						__LINE__
1389
+					);
1390
+				}
1391
+			// end default
1392
+		}
1393
+		// store our progress so far
1394
+		$this->checkout->stash_transaction_and_checkout();
1395
+		// advance to the next step! If you pass GO, collect $200
1396
+		$this->go_to_next_step();
1397
+	}
1398
+
1399
+
1400
+
1401
+	/**
1402
+	 *        add_styles_and_scripts
1403
+	 *
1404
+	 * @access        public
1405
+	 * @return        void
1406
+	 */
1407
+	public function add_styles_and_scripts()
1408
+	{
1409
+		// i18n
1410
+		$this->translate_js_strings();
1411
+		if ($this->checkout->admin_request) {
1412
+			add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1413
+		} else {
1414
+			add_action('wp_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1415
+		}
1416
+	}
1417
+
1418
+
1419
+
1420
+	/**
1421
+	 *        translate_js_strings
1422
+	 *
1423
+	 * @access        public
1424
+	 * @return        void
1425
+	 */
1426
+	public function translate_js_strings()
1427
+	{
1428
+		EE_Registry::$i18n_js_strings['revisit'] = $this->checkout->revisit;
1429
+		EE_Registry::$i18n_js_strings['e_reg_url_link'] = $this->checkout->reg_url_link;
1430
+		EE_Registry::$i18n_js_strings['server_error'] = __(
1431
+			'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1432
+			'event_espresso'
1433
+		);
1434
+		EE_Registry::$i18n_js_strings['invalid_json_response'] = __(
1435
+			'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1436
+			'event_espresso'
1437
+		);
1438
+		EE_Registry::$i18n_js_strings['validation_error'] = __(
1439
+			'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1440
+			'event_espresso'
1441
+		);
1442
+		EE_Registry::$i18n_js_strings['invalid_payment_method'] = __(
1443
+			'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1444
+			'event_espresso'
1445
+		);
1446
+		EE_Registry::$i18n_js_strings['reg_step_error'] = __(
1447
+			'This registration step could not be completed. Please refresh the page and try again.',
1448
+			'event_espresso'
1449
+		);
1450
+		EE_Registry::$i18n_js_strings['invalid_coupon'] = __(
1451
+			'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1452
+			'event_espresso'
1453
+		);
1454
+		EE_Registry::$i18n_js_strings['process_registration'] = sprintf(
1455
+			__(
1456
+				'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1457
+				'event_espresso'
1458
+			),
1459
+			'<br/>',
1460
+			'<br/>'
1461
+		);
1462
+		EE_Registry::$i18n_js_strings['language'] = get_bloginfo('language');
1463
+		EE_Registry::$i18n_js_strings['EESID'] = EE_Registry::instance()->SSN->id();
1464
+		EE_Registry::$i18n_js_strings['currency'] = EE_Registry::instance()->CFG->currency;
1465
+		EE_Registry::$i18n_js_strings['datepicker_yearRange'] = '-150:+20';
1466
+		EE_Registry::$i18n_js_strings['timer_years'] = __('years', 'event_espresso');
1467
+		EE_Registry::$i18n_js_strings['timer_months'] = __('months', 'event_espresso');
1468
+		EE_Registry::$i18n_js_strings['timer_weeks'] = __('weeks', 'event_espresso');
1469
+		EE_Registry::$i18n_js_strings['timer_days'] = __('days', 'event_espresso');
1470
+		EE_Registry::$i18n_js_strings['timer_hours'] = __('hours', 'event_espresso');
1471
+		EE_Registry::$i18n_js_strings['timer_minutes'] = __('minutes', 'event_espresso');
1472
+		EE_Registry::$i18n_js_strings['timer_seconds'] = __('seconds', 'event_espresso');
1473
+		EE_Registry::$i18n_js_strings['timer_year'] = __('year', 'event_espresso');
1474
+		EE_Registry::$i18n_js_strings['timer_month'] = __('month', 'event_espresso');
1475
+		EE_Registry::$i18n_js_strings['timer_week'] = __('week', 'event_espresso');
1476
+		EE_Registry::$i18n_js_strings['timer_day'] = __('day', 'event_espresso');
1477
+		EE_Registry::$i18n_js_strings['timer_hour'] = __('hour', 'event_espresso');
1478
+		EE_Registry::$i18n_js_strings['timer_minute'] = __('minute', 'event_espresso');
1479
+		EE_Registry::$i18n_js_strings['timer_second'] = __('second', 'event_espresso');
1480
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] = EED_Single_Page_Checkout::getRegistrationExpirationNotice();
1481
+		EE_Registry::$i18n_js_strings['ajax_submit'] = apply_filters(
1482
+			'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit',
1483
+			true
1484
+		);
1485
+		EE_Registry::$i18n_js_strings['session_extension'] = absint(
1486
+			apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1487
+		);
1488
+		EE_Registry::$i18n_js_strings['session_expiration'] = gmdate(
1489
+			'M d, Y H:i:s',
1490
+			EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1491
+		);
1492
+	}
1493
+
1494
+
1495
+
1496
+	/**
1497
+	 *    enqueue_styles_and_scripts
1498
+	 *
1499
+	 * @access        public
1500
+	 * @return        void
1501
+	 * @throws EE_Error
1502
+	 */
1503
+	public function enqueue_styles_and_scripts()
1504
+	{
1505
+		// load css
1506
+		wp_register_style(
1507
+			'single_page_checkout',
1508
+			SPCO_CSS_URL . 'single_page_checkout.css',
1509
+			array('espresso_default'),
1510
+			EVENT_ESPRESSO_VERSION
1511
+		);
1512
+		wp_enqueue_style('single_page_checkout');
1513
+		// load JS
1514
+		wp_register_script(
1515
+			'jquery_plugin',
1516
+			EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js',
1517
+			array('jquery'),
1518
+			'1.0.1',
1519
+			true
1520
+		);
1521
+		wp_register_script(
1522
+			'jquery_countdown',
1523
+			EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js',
1524
+			array('jquery_plugin'),
1525
+			'2.0.2',
1526
+			true
1527
+		);
1528
+		wp_register_script(
1529
+			'single_page_checkout',
1530
+			SPCO_JS_URL . 'single_page_checkout.js',
1531
+			array('espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown'),
1532
+			EVENT_ESPRESSO_VERSION,
1533
+			true
1534
+		);
1535
+		if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1536
+			$this->checkout->registration_form->enqueue_js();
1537
+		}
1538
+		if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1539
+			$this->checkout->current_step->reg_form->enqueue_js();
1540
+		}
1541
+		wp_enqueue_script('single_page_checkout');
1542
+		/**
1543
+		 * global action hook for enqueueing styles and scripts with
1544
+		 * spco calls.
1545
+		 */
1546
+		do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1547
+		/**
1548
+		 * dynamic action hook for enqueueing styles and scripts with spco calls.
1549
+		 * The hook will end up being something like:
1550
+		 *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1551
+		 */
1552
+		do_action(
1553
+			'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1554
+			$this
1555
+		);
1556
+	}
1557
+
1558
+
1559
+
1560
+	/**
1561
+	 *    display the Registration Single Page Checkout Form
1562
+	 *
1563
+	 * @access    private
1564
+	 * @return    void
1565
+	 * @throws EE_Error
1566
+	 */
1567
+	private function _display_spco_reg_form()
1568
+	{
1569
+		// if registering via the admin, just display the reg form for the current step
1570
+		if ($this->checkout->admin_request) {
1571
+			EE_Registry::instance()->REQ->add_output($this->checkout->current_step->display_reg_form());
1572
+		} else {
1573
+			// add powered by EE msg
1574
+			add_action('AHEE__SPCO__reg_form_footer', array('EED_Single_Page_Checkout', 'display_registration_footer'));
1575
+			$empty_cart = count(
1576
+				$this->checkout->transaction->registrations($this->checkout->reg_cache_where_params)
1577
+			) < 1;
1578
+			EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1579
+			$cookies_not_set_msg = '';
1580
+			if ($empty_cart) {
1581
+				$cookies_not_set_msg = apply_filters(
1582
+					'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1583
+					sprintf(
1584
+						__(
1585
+							'%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
1586
+							'event_espresso'
1587
+						),
1588
+						'<div class="ee-attention hidden" id="ee-cookies-not-set-msg">',
1589
+						'</div>',
1590
+						'<h6 class="important-notice">',
1591
+						'</h6>',
1592
+						'<p>',
1593
+						'</p>',
1594
+						'<br />',
1595
+						'<a href="http://www.whatarecookies.com/enable.asp" target="_blank">',
1596
+						'</a>'
1597
+					)
1598
+				);
1599
+			}
1600
+			$this->checkout->registration_form = new EE_Form_Section_Proper(
1601
+				array(
1602
+					'name'            => 'single-page-checkout',
1603
+					'html_id'         => 'ee-single-page-checkout-dv',
1604
+					'layout_strategy' =>
1605
+						new EE_Template_Layout(
1606
+							array(
1607
+								'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1608
+								'template_args'        => array(
1609
+									'empty_cart'              => $empty_cart,
1610
+									'revisit'                 => $this->checkout->revisit,
1611
+									'reg_steps'               => $this->checkout->reg_steps,
1612
+									'next_step'               => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
1613
+										? $this->checkout->next_step->slug()
1614
+										: '',
1615
+									'empty_msg'               => apply_filters(
1616
+										'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1617
+										sprintf(
1618
+											__(
1619
+												'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1620
+												'event_espresso'
1621
+											),
1622
+											'<a href="'
1623
+											. get_post_type_archive_link('espresso_events')
1624
+											. '" title="',
1625
+											'">',
1626
+											'</a>'
1627
+										)
1628
+									),
1629
+									'cookies_not_set_msg'     => $cookies_not_set_msg,
1630
+									'registration_time_limit' => $this->checkout->get_registration_time_limit(),
1631
+									'session_expiration'      => gmdate(
1632
+										'M d, Y H:i:s',
1633
+										EE_Registry::instance()->SSN->expiration()
1634
+										+ (get_option('gmt_offset') * HOUR_IN_SECONDS)
1635
+									),
1636
+								),
1637
+							)
1638
+						),
1639
+				)
1640
+			);
1641
+			// load template and add to output sent that gets filtered into the_content()
1642
+			EE_Registry::instance()->REQ->add_output($this->checkout->registration_form->get_html());
1643
+		}
1644
+	}
1645
+
1646
+
1647
+
1648
+	/**
1649
+	 *    add_extra_finalize_registration_inputs
1650
+	 *
1651
+	 * @access    public
1652
+	 * @param $next_step
1653
+	 * @internal  param string $label
1654
+	 * @return void
1655
+	 */
1656
+	public function add_extra_finalize_registration_inputs($next_step)
1657
+	{
1658
+		if ($next_step === 'finalize_registration') {
1659
+			echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1660
+		}
1661
+	}
1662
+
1663
+
1664
+
1665
+	/**
1666
+	 *    display_registration_footer
1667
+	 *
1668
+	 * @access    public
1669
+	 * @return    string
1670
+	 */
1671
+	public static function display_registration_footer()
1672
+	{
1673
+		if (
1674
+		apply_filters(
1675
+			'FHEE__EE_Front__Controller__show_reg_footer',
1676
+			EE_Registry::instance()->CFG->admin->show_reg_footer
1677
+		)
1678
+		) {
1679
+			add_filter(
1680
+				'FHEE__EEH_Template__powered_by_event_espresso__url',
1681
+				function ($url) {
1682
+					return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1683
+				}
1684
+			);
1685
+			echo apply_filters(
1686
+				'FHEE__EE_Front_Controller__display_registration_footer',
1687
+				\EEH_Template::powered_by_event_espresso(
1688
+					'',
1689
+					'espresso-registration-footer-dv',
1690
+					array('utm_content' => 'registration_checkout')
1691
+				)
1692
+			);
1693
+		}
1694
+		return '';
1695
+	}
1696
+
1697
+
1698
+
1699
+	/**
1700
+	 *    unlock_transaction
1701
+	 *
1702
+	 * @access    public
1703
+	 * @return    void
1704
+	 * @throws EE_Error
1705
+	 */
1706
+	public function unlock_transaction()
1707
+	{
1708
+		if ($this->checkout->transaction instanceof EE_Transaction) {
1709
+			$this->checkout->transaction->unlock();
1710
+		}
1711
+	}
1712
+
1713
+
1714
+
1715
+	/**
1716
+	 *        _setup_redirect
1717
+	 *
1718
+	 * @access    private
1719
+	 * @return void
1720
+	 */
1721
+	private function _setup_redirect()
1722
+	{
1723
+		if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1724
+			$this->checkout->redirect = true;
1725
+			if (empty($this->checkout->redirect_url)) {
1726
+				$this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1727
+			}
1728
+			$this->checkout->redirect_url = apply_filters(
1729
+				'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1730
+				$this->checkout->redirect_url,
1731
+				$this->checkout
1732
+			);
1733
+		}
1734
+	}
1735
+
1736
+
1737
+
1738
+	/**
1739
+	 *   handle ajax message responses and redirects
1740
+	 *
1741
+	 * @access public
1742
+	 * @return void
1743
+	 * @throws EE_Error
1744
+	 */
1745
+	public function go_to_next_step()
1746
+	{
1747
+		if (EE_Registry::instance()->REQ->ajax) {
1748
+			// capture contents of output buffer we started earlier in the request, and insert into JSON response
1749
+			$this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1750
+		}
1751
+		$this->unlock_transaction();
1752
+		// just return for these conditions
1753
+		if (
1754
+			$this->checkout->admin_request
1755
+			|| $this->checkout->action === 'redirect_form'
1756
+			|| $this->checkout->action === 'update_checkout'
1757
+		) {
1758
+			return;
1759
+		}
1760
+		// AJAX response
1761
+		$this->_handle_json_response();
1762
+		// redirect to next step or the Thank You page
1763
+		$this->_handle_html_redirects();
1764
+		// hmmm... must be something wrong, so let's just display the form again !
1765
+		$this->_display_spco_reg_form();
1766
+	}
1767
+
1768
+
1769
+
1770
+	/**
1771
+	 *   _handle_json_response
1772
+	 *
1773
+	 * @access protected
1774
+	 * @return void
1775
+	 */
1776
+	protected function _handle_json_response()
1777
+	{
1778
+		// if this is an ajax request
1779
+		if (EE_Registry::instance()->REQ->ajax) {
1780
+			// DEBUG LOG
1781
+			//$this->checkout->log(
1782
+			//	__CLASS__, __FUNCTION__, __LINE__,
1783
+			//	array(
1784
+			//		'json_response_redirect_url' => $this->checkout->json_response->redirect_url(),
1785
+			//		'redirect'                   => $this->checkout->redirect,
1786
+			//		'continue_reg'               => $this->checkout->continue_reg,
1787
+			//	)
1788
+			//);
1789
+			$this->checkout->json_response->set_registration_time_limit(
1790
+				$this->checkout->get_registration_time_limit()
1791
+			);
1792
+			$this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1793
+			// just send the ajax (
1794
+			$json_response = apply_filters(
1795
+				'FHEE__EE_Single_Page_Checkout__JSON_response',
1796
+				$this->checkout->json_response
1797
+			);
1798
+			echo $json_response;
1799
+			exit();
1800
+		}
1801
+	}
1802
+
1803
+
1804
+
1805
+	/**
1806
+	 *   _handle_redirects
1807
+	 *
1808
+	 * @access protected
1809
+	 * @return void
1810
+	 */
1811
+	protected function _handle_html_redirects()
1812
+	{
1813
+		// going somewhere ?
1814
+		if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1815
+			// store notices in a transient
1816
+			EE_Error::get_notices(false, true, true);
1817
+			// DEBUG LOG
1818
+			//$this->checkout->log(
1819
+			//	__CLASS__, __FUNCTION__, __LINE__,
1820
+			//	array(
1821
+			//		'headers_sent' => headers_sent(),
1822
+			//		'redirect_url'     => $this->checkout->redirect_url,
1823
+			//		'headers_list'    => headers_list(),
1824
+			//	)
1825
+			//);
1826
+			wp_safe_redirect($this->checkout->redirect_url);
1827
+			exit();
1828
+		}
1829
+	}
1830
+
1831
+
1832
+
1833
+	/**
1834
+	 *   set_checkout_anchor
1835
+	 *
1836
+	 * @access public
1837
+	 * @return void
1838
+	 */
1839
+	public function set_checkout_anchor()
1840
+	{
1841
+		echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1842
+	}
1843
+
1844
+	/**
1845
+	 *    getRegistrationExpirationNotice
1846
+	 *
1847
+	 * @since $VID:$
1848
+	 * @access    public
1849
+	 * @return    string
1850
+	 */
1851
+	public static function getRegistrationExpirationNotice()
1852
+	{
1853
+		return sprintf(
1854
+			__('%1$sWe\'re sorry, but your registration time has expired.%2$s%3$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please accept our apologies for any inconvenience this may have caused.%8$s',
1855
+				'event_espresso'),
1856
+			'<h4 class="important-notice">',
1857
+			'</h4>',
1858
+			'<br />',
1859
+			'<p>',
1860
+			'<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1861
+			'">',
1862
+			'</a>',
1863
+			'</p>'
1864
+		);
1865
+	}
1866 1866
 
1867 1867
 }
1868 1868
 // End of file EED_Single_Page_Checkout.module.php
Please login to merge, or discard this patch.
attendee_information/EE_SPCO_Reg_Step_Attendee_Information.class.php 2 patches
Indentation   +1335 added lines, -1335 removed lines patch added patch discarded remove patch
@@ -17,1343 +17,1343 @@
 block discarded – undo
17 17
 class EE_SPCO_Reg_Step_Attendee_Information extends EE_SPCO_Reg_Step
18 18
 {
19 19
 
20
-    /**
21
-     * @type bool $_print_copy_info
22
-     */
23
-    private $_print_copy_info = false;
24
-
25
-    /**
26
-     * @type array $_attendee_data
27
-     */
28
-    private $_attendee_data = array();
29
-
30
-    /**
31
-     * @type array $_required_questions
32
-     */
33
-    private $_required_questions = array();
34
-
35
-    /**
36
-     * @type array $_registration_answers
37
-     */
38
-    private $_registration_answers = array();
39
-
40
-
41
-    /**
42
-     *    class constructor
43
-     *
44
-     * @access    public
45
-     * @param    EE_Checkout $checkout
46
-     */
47
-    public function __construct(EE_Checkout $checkout)
48
-    {
49
-        $this->_slug     = 'attendee_information';
50
-        $this->_name     = esc_html__('Attendee Information', 'event_espresso');
51
-        $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'attendee_info_main.template.php';
52
-        $this->checkout  = $checkout;
53
-        $this->_reset_success_message();
54
-        $this->set_instructions(
55
-            esc_html__('Please answer the following registration questions before proceeding.', 'event_espresso')
56
-        );
57
-    }
58
-
59
-
60
-    public function translate_js_strings()
61
-    {
62
-        EE_Registry::$i18n_js_strings['required_field']            = esc_html__(
63
-            ' is a required question.',
64
-            'event_espresso'
65
-        );
66
-        EE_Registry::$i18n_js_strings['required_multi_field']      = esc_html__(
67
-            ' is a required question. Please enter a value for at least one of the options.',
68
-            'event_espresso'
69
-        );
70
-        EE_Registry::$i18n_js_strings['answer_required_questions'] = esc_html__(
71
-            'Please answer all required questions correctly before proceeding.',
72
-            'event_espresso'
73
-        );
74
-        EE_Registry::$i18n_js_strings['attendee_info_copied']      = sprintf(
75
-            esc_html__(
76
-                'The attendee information was successfully copied.%sPlease ensure the rest of the registration form is completed before proceeding.',
77
-                'event_espresso'
78
-            ),
79
-            '<br/>'
80
-        );
81
-        EE_Registry::$i18n_js_strings['attendee_info_copy_error']  = esc_html__(
82
-            'An unknown error occurred on the server while attempting to copy the attendee information. Please refresh the page and try again.',
83
-            'event_espresso'
84
-        );
85
-        EE_Registry::$i18n_js_strings['enter_valid_email']         = esc_html__(
86
-            'You must enter a valid email address.',
87
-            'event_espresso'
88
-        );
89
-        EE_Registry::$i18n_js_strings['valid_email_and_questions'] = esc_html__(
90
-            'You must enter a valid email address and answer all other required questions before you can proceed.',
91
-            'event_espresso'
92
-        );
93
-    }
94
-
95
-
96
-    public function enqueue_styles_and_scripts()
97
-    {
98
-    }
99
-
100
-
101
-    /**
102
-     * @return boolean
103
-     */
104
-    public function initialize_reg_step()
105
-    {
106
-        return true;
107
-    }
108
-
109
-
110
-    /**
111
-     * @return EE_Form_Section_Proper
112
-     * @throws EE_Error
113
-     * @throws InvalidArgumentException
114
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
115
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
116
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
117
-     */
118
-    public function generate_reg_form()
119
-    {
120
-        $this->_print_copy_info = false;
121
-        $primary_registrant     = null;
122
-        // autoload Line_Item_Display classes
123
-        EEH_Autoloader::register_line_item_display_autoloaders();
124
-        $Line_Item_Display = new EE_Line_Item_Display();
125
-        // calculate taxes
126
-        $Line_Item_Display->display_line_item(
127
-            $this->checkout->cart->get_grand_total(),
128
-            array('set_tax_rate' => true)
129
-        );
130
-        /** @var $subsections EE_Form_Section_Proper[] */
131
-        $subsections   = array(
132
-            'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
133
-        );
134
-        $template_args = array(
135
-            'revisit'       => $this->checkout->revisit,
136
-            'registrations' => array(),
137
-            'ticket_count'  => array(),
138
-        );
139
-        // grab the saved registrations from the transaction
140
-        $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
141
-        if ($registrations) {
142
-            foreach ($registrations as $registration) {
143
-                // can this registration be processed during this visit ?
144
-                if ($registration instanceof EE_Registration
145
-                    && $this->checkout->visit_allows_processing_of_this_registration($registration)
146
-                ) {
147
-                    $subsections[$registration->reg_url_link()] = $this->_registrations_reg_form($registration);
148
-                    if (! $this->checkout->admin_request) {
149
-                        $template_args['registrations'][$registration->reg_url_link()]    = $registration;
150
-                        $template_args['ticket_count'][$registration->ticket()->ID()]     = isset(
151
-                            $template_args['ticket_count'][$registration->ticket()->ID()]
152
-                        )
153
-                            ? $template_args['ticket_count'][$registration->ticket()->ID()] + 1
154
-                            : 1;
155
-                        $ticket_line_item = EEH_Line_Item::get_line_items_by_object_type_and_IDs(
156
-                            $this->checkout->cart->get_grand_total(),
157
-                            'Ticket',
158
-                            array($registration->ticket()->ID())
159
-                        );
160
-                        $ticket_line_item = is_array($ticket_line_item)
161
-                            ? reset($ticket_line_item)
162
-                            : $ticket_line_item;
163
-                        $template_args['ticket_line_item'][$registration->ticket()->ID()] =
164
-                            $Line_Item_Display->display_line_item($ticket_line_item);
165
-                    }
166
-                    if ($registration->is_primary_registrant()) {
167
-                        $primary_registrant = $registration->reg_url_link();
168
-                    }
169
-                }
170
-            }
171
-            // print_copy_info ?
172
-            if ($primary_registrant && ! $this->checkout->admin_request && count($registrations) > 1) {
173
-                // TODO: add admin option for toggling copy attendee info,
174
-                // then use that value to change $this->_print_copy_info
175
-                $copy_options['spco_copy_attendee_chk'] = $this->_print_copy_info
176
-                    ? $this->_copy_attendee_info_form()
177
-                    : $this->_auto_copy_attendee_info();
178
-                // generate hidden input
179
-                if (isset($subsections[$primary_registrant])
180
-                    && $subsections[$primary_registrant] instanceof EE_Form_Section_Proper
181
-                ) {
182
-                    $subsections[$primary_registrant]->add_subsections(
183
-                        $copy_options,
184
-                        'primary_registrant',
185
-                        false
186
-                    );
187
-                }
188
-            }
189
-        }
190
-
191
-        return new EE_Form_Section_Proper(
192
-            array(
193
-                'name'            => $this->reg_form_name(),
194
-                'html_id'         => $this->reg_form_name(),
195
-                'subsections'     => $subsections,
196
-                'layout_strategy' => $this->checkout->admin_request ?
197
-                    new EE_Div_Per_Section_Layout() :
198
-                    new EE_Template_Layout(
199
-                        array(
200
-                            'layout_template_file' => $this->_template, // layout_template
201
-                            'template_args'        => $template_args,
202
-                        )
203
-                    ),
204
-            )
205
-        );
206
-    }
207
-
208
-
209
-    /**
210
-     * @param EE_Registration $registration
211
-     * @return EE_Form_Section_Base
212
-     * @throws EE_Error
213
-     * @throws InvalidArgumentException
214
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
215
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
216
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
217
-     */
218
-    private function _registrations_reg_form(EE_Registration $registration)
219
-    {
220
-        static $attendee_nmbr = 1;
221
-        $form_args = array();
222
-        // verify that registration has valid event
223
-        if ($registration->event() instanceof EE_Event) {
224
-            $question_groups = $registration->event()->question_groups(
225
-                apply_filters(
226
-                    'FHEE__EE_SPCO_Reg_Step_Attendee_Information___registrations_reg_form__question_groups_query_parameters',
227
-                    array(
228
-                        array(
229
-                            'Event.EVT_ID'                     => $registration->event()->ID(),
230
-                            'Event_Question_Group.EQG_primary' => $registration->count() === 1 ? true : false,
231
-                        ),
232
-                        'order_by' => array('QSG_order' => 'ASC'),
233
-                    ),
234
-                    $registration,
235
-                    $this
236
-                )
237
-            );
238
-            if ($question_groups) {
239
-                // array of params to pass to parent constructor
240
-                $form_args = array(
241
-                    'html_id'         => 'ee-registration-' . $registration->reg_url_link(),
242
-                    'html_class'      => 'ee-reg-form-attendee-dv',
243
-                    'html_style'      => $this->checkout->admin_request
244
-                        ? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;'
245
-                        : '',
246
-                    'subsections'     => array(),
247
-                    'layout_strategy' => new EE_Fieldset_Section_Layout(
248
-                        array(
249
-                            'legend_class' => 'spco-attendee-lgnd smaller-text lt-grey-text',
250
-                            'legend_text'  => sprintf(__('Attendee %d', 'event_espresso'), $attendee_nmbr),
251
-                        )
252
-                    ),
253
-                );
254
-                foreach ($question_groups as $question_group) {
255
-                    if ($question_group instanceof EE_Question_Group) {
256
-                        $form_args['subsections'][$question_group->identifier()] = $this->_question_group_reg_form(
257
-                            $registration,
258
-                            $question_group
259
-                        );
260
-                    }
261
-                }
262
-                // add hidden input
263
-                $form_args['subsections']['additional_attendee_reg_info'] = $this->_additional_attendee_reg_info_input(
264
-                    $registration
265
-                );
266
-                // if we have question groups for additional attendees, then display the copy options
267
-                $this->_print_copy_info = $attendee_nmbr > 1 ? true : $this->_print_copy_info;
268
-                if ($registration->is_primary_registrant()) {
269
-                    // generate hidden input
270
-                    $form_args['subsections']['primary_registrant'] = $this->_additional_primary_registrant_inputs(
271
-                        $registration
272
-                    );
273
-                }
274
-            }
275
-        }
276
-        $attendee_nmbr++;
277
-        return ! empty($form_args) ? new EE_Form_Section_Proper($form_args) : new EE_Form_Section_HTML();
278
-    }
279
-
280
-
281
-    /**
282
-     * _additional_attendee_reg_info_input
283
-     *
284
-     * @access public
285
-     * @param EE_Registration $registration
286
-     * @param bool            $additional_attendee_reg_info
287
-     * @return    EE_Form_Input_Base
288
-     * @throws \EE_Error
289
-     */
290
-    private function _additional_attendee_reg_info_input(
291
-        EE_Registration $registration,
292
-        $additional_attendee_reg_info = true
293
-    ) {
294
-        // generate hidden input
295
-        return new EE_Hidden_Input(
296
-            array(
297
-                'html_id' => 'additional-attendee-reg-info-' . $registration->reg_url_link(),
298
-                'default' => $additional_attendee_reg_info,
299
-            )
300
-        );
301
-    }
302
-
303
-
304
-    /**
305
-     * @param EE_Registration   $registration
306
-     * @param EE_Question_Group $question_group
307
-     * @return EE_Form_Section_Proper
308
-     * @throws EE_Error
309
-     * @throws InvalidArgumentException
310
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
311
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
312
-     */
313
-    private function _question_group_reg_form(EE_Registration $registration, EE_Question_Group $question_group)
314
-    {
315
-        // array of params to pass to parent constructor
316
-        $form_args = array(
317
-            'html_id'         => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-' . $registration->ID(),
318
-            'html_class'      => $this->checkout->admin_request
319
-                ? 'form-table ee-reg-form-qstn-grp-dv'
320
-                : 'ee-reg-form-qstn-grp-dv',
321
-            'html_label_id'   => 'ee-reg-form-qstn-grp-' . $question_group->identifier() .  '-' . $registration->ID() . '-lbl',
322
-            'subsections'     => array(
323
-                'reg_form_qstn_grp_hdr' => $this->_question_group_header($question_group),
324
-            ),
325
-            'layout_strategy' => $this->checkout->admin_request
326
-                ? new EE_Admin_Two_Column_Layout()
327
-                : new EE_Div_Per_Section_Layout(),
328
-        );
329
-        // where params
330
-        $query_params = array('QST_deleted' => 0);
331
-        // don't load admin only questions on the frontend
332
-        if (! $this->checkout->admin_request) {
333
-            $query_params['QST_admin_only'] = array('!=', true);
334
-        }
335
-        $questions = $question_group->get_many_related(
336
-            'Question',
337
-            apply_filters(
338
-                'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__related_questions_query_params',
339
-                array(
340
-                    $query_params,
341
-                    'order_by' => array(
342
-                        'Question_Group_Question.QGQ_order' => 'ASC',
343
-                    ),
344
-                ),
345
-                $question_group,
346
-                $registration,
347
-                $this
348
-            )
349
-        );
350
-        // filter for additional content before questions
351
-        $form_args['subsections']['reg_form_questions_before'] = new EE_Form_Section_HTML(
352
-            apply_filters(
353
-                'FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions',
354
-                '',
355
-                $registration,
356
-                $question_group,
357
-                $this
358
-            )
359
-        );
360
-        // loop thru questions
361
-        foreach ($questions as $question) {
362
-            if ($question instanceof EE_Question) {
363
-                $identifier                            = $question->is_system_question()
364
-                    ? $question->system_ID()
365
-                    : $question->ID();
366
-                $form_args['subsections'][$identifier] = $this->reg_form_question($registration, $question);
367
-            }
368
-        }
369
-        $form_args['subsections'] = apply_filters(
370
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information__question_group_reg_form__subsections_array',
371
-            $form_args['subsections'],
372
-            $registration,
373
-            $question_group,
374
-            $this
375
-        );
376
-        // filter for additional content after questions
377
-        $form_args['subsections']['reg_form_questions_after'] = new EE_Form_Section_HTML(
378
-            apply_filters(
379
-                'FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions',
380
-                '',
381
-                $registration,
382
-                $question_group,
383
-                $this
384
-            )
385
-        );
20
+	/**
21
+	 * @type bool $_print_copy_info
22
+	 */
23
+	private $_print_copy_info = false;
24
+
25
+	/**
26
+	 * @type array $_attendee_data
27
+	 */
28
+	private $_attendee_data = array();
29
+
30
+	/**
31
+	 * @type array $_required_questions
32
+	 */
33
+	private $_required_questions = array();
34
+
35
+	/**
36
+	 * @type array $_registration_answers
37
+	 */
38
+	private $_registration_answers = array();
39
+
40
+
41
+	/**
42
+	 *    class constructor
43
+	 *
44
+	 * @access    public
45
+	 * @param    EE_Checkout $checkout
46
+	 */
47
+	public function __construct(EE_Checkout $checkout)
48
+	{
49
+		$this->_slug     = 'attendee_information';
50
+		$this->_name     = esc_html__('Attendee Information', 'event_espresso');
51
+		$this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'attendee_info_main.template.php';
52
+		$this->checkout  = $checkout;
53
+		$this->_reset_success_message();
54
+		$this->set_instructions(
55
+			esc_html__('Please answer the following registration questions before proceeding.', 'event_espresso')
56
+		);
57
+	}
58
+
59
+
60
+	public function translate_js_strings()
61
+	{
62
+		EE_Registry::$i18n_js_strings['required_field']            = esc_html__(
63
+			' is a required question.',
64
+			'event_espresso'
65
+		);
66
+		EE_Registry::$i18n_js_strings['required_multi_field']      = esc_html__(
67
+			' is a required question. Please enter a value for at least one of the options.',
68
+			'event_espresso'
69
+		);
70
+		EE_Registry::$i18n_js_strings['answer_required_questions'] = esc_html__(
71
+			'Please answer all required questions correctly before proceeding.',
72
+			'event_espresso'
73
+		);
74
+		EE_Registry::$i18n_js_strings['attendee_info_copied']      = sprintf(
75
+			esc_html__(
76
+				'The attendee information was successfully copied.%sPlease ensure the rest of the registration form is completed before proceeding.',
77
+				'event_espresso'
78
+			),
79
+			'<br/>'
80
+		);
81
+		EE_Registry::$i18n_js_strings['attendee_info_copy_error']  = esc_html__(
82
+			'An unknown error occurred on the server while attempting to copy the attendee information. Please refresh the page and try again.',
83
+			'event_espresso'
84
+		);
85
+		EE_Registry::$i18n_js_strings['enter_valid_email']         = esc_html__(
86
+			'You must enter a valid email address.',
87
+			'event_espresso'
88
+		);
89
+		EE_Registry::$i18n_js_strings['valid_email_and_questions'] = esc_html__(
90
+			'You must enter a valid email address and answer all other required questions before you can proceed.',
91
+			'event_espresso'
92
+		);
93
+	}
94
+
95
+
96
+	public function enqueue_styles_and_scripts()
97
+	{
98
+	}
99
+
100
+
101
+	/**
102
+	 * @return boolean
103
+	 */
104
+	public function initialize_reg_step()
105
+	{
106
+		return true;
107
+	}
108
+
109
+
110
+	/**
111
+	 * @return EE_Form_Section_Proper
112
+	 * @throws EE_Error
113
+	 * @throws InvalidArgumentException
114
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
115
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
116
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
117
+	 */
118
+	public function generate_reg_form()
119
+	{
120
+		$this->_print_copy_info = false;
121
+		$primary_registrant     = null;
122
+		// autoload Line_Item_Display classes
123
+		EEH_Autoloader::register_line_item_display_autoloaders();
124
+		$Line_Item_Display = new EE_Line_Item_Display();
125
+		// calculate taxes
126
+		$Line_Item_Display->display_line_item(
127
+			$this->checkout->cart->get_grand_total(),
128
+			array('set_tax_rate' => true)
129
+		);
130
+		/** @var $subsections EE_Form_Section_Proper[] */
131
+		$subsections   = array(
132
+			'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
133
+		);
134
+		$template_args = array(
135
+			'revisit'       => $this->checkout->revisit,
136
+			'registrations' => array(),
137
+			'ticket_count'  => array(),
138
+		);
139
+		// grab the saved registrations from the transaction
140
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
141
+		if ($registrations) {
142
+			foreach ($registrations as $registration) {
143
+				// can this registration be processed during this visit ?
144
+				if ($registration instanceof EE_Registration
145
+					&& $this->checkout->visit_allows_processing_of_this_registration($registration)
146
+				) {
147
+					$subsections[$registration->reg_url_link()] = $this->_registrations_reg_form($registration);
148
+					if (! $this->checkout->admin_request) {
149
+						$template_args['registrations'][$registration->reg_url_link()]    = $registration;
150
+						$template_args['ticket_count'][$registration->ticket()->ID()]     = isset(
151
+							$template_args['ticket_count'][$registration->ticket()->ID()]
152
+						)
153
+							? $template_args['ticket_count'][$registration->ticket()->ID()] + 1
154
+							: 1;
155
+						$ticket_line_item = EEH_Line_Item::get_line_items_by_object_type_and_IDs(
156
+							$this->checkout->cart->get_grand_total(),
157
+							'Ticket',
158
+							array($registration->ticket()->ID())
159
+						);
160
+						$ticket_line_item = is_array($ticket_line_item)
161
+							? reset($ticket_line_item)
162
+							: $ticket_line_item;
163
+						$template_args['ticket_line_item'][$registration->ticket()->ID()] =
164
+							$Line_Item_Display->display_line_item($ticket_line_item);
165
+					}
166
+					if ($registration->is_primary_registrant()) {
167
+						$primary_registrant = $registration->reg_url_link();
168
+					}
169
+				}
170
+			}
171
+			// print_copy_info ?
172
+			if ($primary_registrant && ! $this->checkout->admin_request && count($registrations) > 1) {
173
+				// TODO: add admin option for toggling copy attendee info,
174
+				// then use that value to change $this->_print_copy_info
175
+				$copy_options['spco_copy_attendee_chk'] = $this->_print_copy_info
176
+					? $this->_copy_attendee_info_form()
177
+					: $this->_auto_copy_attendee_info();
178
+				// generate hidden input
179
+				if (isset($subsections[$primary_registrant])
180
+					&& $subsections[$primary_registrant] instanceof EE_Form_Section_Proper
181
+				) {
182
+					$subsections[$primary_registrant]->add_subsections(
183
+						$copy_options,
184
+						'primary_registrant',
185
+						false
186
+					);
187
+				}
188
+			}
189
+		}
190
+
191
+		return new EE_Form_Section_Proper(
192
+			array(
193
+				'name'            => $this->reg_form_name(),
194
+				'html_id'         => $this->reg_form_name(),
195
+				'subsections'     => $subsections,
196
+				'layout_strategy' => $this->checkout->admin_request ?
197
+					new EE_Div_Per_Section_Layout() :
198
+					new EE_Template_Layout(
199
+						array(
200
+							'layout_template_file' => $this->_template, // layout_template
201
+							'template_args'        => $template_args,
202
+						)
203
+					),
204
+			)
205
+		);
206
+	}
207
+
208
+
209
+	/**
210
+	 * @param EE_Registration $registration
211
+	 * @return EE_Form_Section_Base
212
+	 * @throws EE_Error
213
+	 * @throws InvalidArgumentException
214
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
215
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
216
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
217
+	 */
218
+	private function _registrations_reg_form(EE_Registration $registration)
219
+	{
220
+		static $attendee_nmbr = 1;
221
+		$form_args = array();
222
+		// verify that registration has valid event
223
+		if ($registration->event() instanceof EE_Event) {
224
+			$question_groups = $registration->event()->question_groups(
225
+				apply_filters(
226
+					'FHEE__EE_SPCO_Reg_Step_Attendee_Information___registrations_reg_form__question_groups_query_parameters',
227
+					array(
228
+						array(
229
+							'Event.EVT_ID'                     => $registration->event()->ID(),
230
+							'Event_Question_Group.EQG_primary' => $registration->count() === 1 ? true : false,
231
+						),
232
+						'order_by' => array('QSG_order' => 'ASC'),
233
+					),
234
+					$registration,
235
+					$this
236
+				)
237
+			);
238
+			if ($question_groups) {
239
+				// array of params to pass to parent constructor
240
+				$form_args = array(
241
+					'html_id'         => 'ee-registration-' . $registration->reg_url_link(),
242
+					'html_class'      => 'ee-reg-form-attendee-dv',
243
+					'html_style'      => $this->checkout->admin_request
244
+						? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;'
245
+						: '',
246
+					'subsections'     => array(),
247
+					'layout_strategy' => new EE_Fieldset_Section_Layout(
248
+						array(
249
+							'legend_class' => 'spco-attendee-lgnd smaller-text lt-grey-text',
250
+							'legend_text'  => sprintf(__('Attendee %d', 'event_espresso'), $attendee_nmbr),
251
+						)
252
+					),
253
+				);
254
+				foreach ($question_groups as $question_group) {
255
+					if ($question_group instanceof EE_Question_Group) {
256
+						$form_args['subsections'][$question_group->identifier()] = $this->_question_group_reg_form(
257
+							$registration,
258
+							$question_group
259
+						);
260
+					}
261
+				}
262
+				// add hidden input
263
+				$form_args['subsections']['additional_attendee_reg_info'] = $this->_additional_attendee_reg_info_input(
264
+					$registration
265
+				);
266
+				// if we have question groups for additional attendees, then display the copy options
267
+				$this->_print_copy_info = $attendee_nmbr > 1 ? true : $this->_print_copy_info;
268
+				if ($registration->is_primary_registrant()) {
269
+					// generate hidden input
270
+					$form_args['subsections']['primary_registrant'] = $this->_additional_primary_registrant_inputs(
271
+						$registration
272
+					);
273
+				}
274
+			}
275
+		}
276
+		$attendee_nmbr++;
277
+		return ! empty($form_args) ? new EE_Form_Section_Proper($form_args) : new EE_Form_Section_HTML();
278
+	}
279
+
280
+
281
+	/**
282
+	 * _additional_attendee_reg_info_input
283
+	 *
284
+	 * @access public
285
+	 * @param EE_Registration $registration
286
+	 * @param bool            $additional_attendee_reg_info
287
+	 * @return    EE_Form_Input_Base
288
+	 * @throws \EE_Error
289
+	 */
290
+	private function _additional_attendee_reg_info_input(
291
+		EE_Registration $registration,
292
+		$additional_attendee_reg_info = true
293
+	) {
294
+		// generate hidden input
295
+		return new EE_Hidden_Input(
296
+			array(
297
+				'html_id' => 'additional-attendee-reg-info-' . $registration->reg_url_link(),
298
+				'default' => $additional_attendee_reg_info,
299
+			)
300
+		);
301
+	}
302
+
303
+
304
+	/**
305
+	 * @param EE_Registration   $registration
306
+	 * @param EE_Question_Group $question_group
307
+	 * @return EE_Form_Section_Proper
308
+	 * @throws EE_Error
309
+	 * @throws InvalidArgumentException
310
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
311
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
312
+	 */
313
+	private function _question_group_reg_form(EE_Registration $registration, EE_Question_Group $question_group)
314
+	{
315
+		// array of params to pass to parent constructor
316
+		$form_args = array(
317
+			'html_id'         => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-' . $registration->ID(),
318
+			'html_class'      => $this->checkout->admin_request
319
+				? 'form-table ee-reg-form-qstn-grp-dv'
320
+				: 'ee-reg-form-qstn-grp-dv',
321
+			'html_label_id'   => 'ee-reg-form-qstn-grp-' . $question_group->identifier() .  '-' . $registration->ID() . '-lbl',
322
+			'subsections'     => array(
323
+				'reg_form_qstn_grp_hdr' => $this->_question_group_header($question_group),
324
+			),
325
+			'layout_strategy' => $this->checkout->admin_request
326
+				? new EE_Admin_Two_Column_Layout()
327
+				: new EE_Div_Per_Section_Layout(),
328
+		);
329
+		// where params
330
+		$query_params = array('QST_deleted' => 0);
331
+		// don't load admin only questions on the frontend
332
+		if (! $this->checkout->admin_request) {
333
+			$query_params['QST_admin_only'] = array('!=', true);
334
+		}
335
+		$questions = $question_group->get_many_related(
336
+			'Question',
337
+			apply_filters(
338
+				'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__related_questions_query_params',
339
+				array(
340
+					$query_params,
341
+					'order_by' => array(
342
+						'Question_Group_Question.QGQ_order' => 'ASC',
343
+					),
344
+				),
345
+				$question_group,
346
+				$registration,
347
+				$this
348
+			)
349
+		);
350
+		// filter for additional content before questions
351
+		$form_args['subsections']['reg_form_questions_before'] = new EE_Form_Section_HTML(
352
+			apply_filters(
353
+				'FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions',
354
+				'',
355
+				$registration,
356
+				$question_group,
357
+				$this
358
+			)
359
+		);
360
+		// loop thru questions
361
+		foreach ($questions as $question) {
362
+			if ($question instanceof EE_Question) {
363
+				$identifier                            = $question->is_system_question()
364
+					? $question->system_ID()
365
+					: $question->ID();
366
+				$form_args['subsections'][$identifier] = $this->reg_form_question($registration, $question);
367
+			}
368
+		}
369
+		$form_args['subsections'] = apply_filters(
370
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information__question_group_reg_form__subsections_array',
371
+			$form_args['subsections'],
372
+			$registration,
373
+			$question_group,
374
+			$this
375
+		);
376
+		// filter for additional content after questions
377
+		$form_args['subsections']['reg_form_questions_after'] = new EE_Form_Section_HTML(
378
+			apply_filters(
379
+				'FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions',
380
+				'',
381
+				$registration,
382
+				$question_group,
383
+				$this
384
+			)
385
+		);
386 386
 //		d( $form_args );
387
-        $question_group_reg_form = new EE_Form_Section_Proper($form_args);
388
-        return apply_filters(
389
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__question_group_reg_form',
390
-            $question_group_reg_form,
391
-            $registration,
392
-            $question_group,
393
-            $this
394
-        );
395
-    }
396
-
397
-
398
-    /**
399
-     * @access public
400
-     * @param EE_Question_Group $question_group
401
-     * @return    EE_Form_Section_HTML
402
-     */
403
-    private function _question_group_header(EE_Question_Group $question_group)
404
-    {
405
-        $html = '';
406
-        // group_name
407
-        if ($question_group->show_group_name() && $question_group->name() !== '') {
408
-            if ($this->checkout->admin_request) {
409
-                $html .= EEH_HTML::br();
410
-                $html .= EEH_HTML::h3(
411
-                    $question_group->name(),
412
-                    '',
413
-                    'ee-reg-form-qstn-grp-title title',
414
-                    'font-size: 1.3em; padding-left:0;'
415
-                );
416
-            } else {
417
-                $html .= EEH_HTML::h4(
418
-                    $question_group->name(),
419
-                    '',
420
-                    'ee-reg-form-qstn-grp-title section-title'
421
-                );
422
-            }
423
-        }
424
-        // group_desc
425
-        if ($question_group->show_group_desc() && $question_group->desc() !== '') {
426
-            $html .= EEH_HTML::p(
427
-                $question_group->desc(),
428
-                '',
429
-                $this->checkout->admin_request
430
-                    ? 'ee-reg-form-qstn-grp-desc-pg'
431
-                    : 'ee-reg-form-qstn-grp-desc-pg small-text lt-grey-text'
432
-            );
433
-        }
434
-        return new EE_Form_Section_HTML($html);
435
-    }
436
-
437
-
438
-    /**
439
-     * @access public
440
-     * @return    EE_Form_Section_Proper
441
-     * @throws \EE_Error
442
-     */
443
-    private function _copy_attendee_info_form()
444
-    {
445
-        // array of params to pass to parent constructor
446
-        return new EE_Form_Section_Proper(
447
-            array(
448
-                'subsections'     => $this->_copy_attendee_info_inputs(),
449
-                'layout_strategy' => new EE_Template_Layout(
450
-                    array(
451
-                        'layout_template_file'     => SPCO_REG_STEPS_PATH
452
-                                                      . $this->_slug
453
-                                                      . DS
454
-                                                      . 'copy_attendee_info.template.php',
455
-                        'begin_template_file'      => null,
456
-                        'input_template_file'      => null,
457
-                        'subsection_template_file' => null,
458
-                        'end_template_file'        => null,
459
-                    )
460
-                ),
461
-            )
462
-        );
463
-    }
464
-
465
-
466
-    /**
467
-     * _auto_copy_attendee_info
468
-     *
469
-     * @access public
470
-     * @return EE_Form_Section_HTML
471
-     */
472
-    private function _auto_copy_attendee_info()
473
-    {
474
-        return new EE_Form_Section_HTML(
475
-            EEH_Template::locate_template(
476
-                SPCO_REG_STEPS_PATH . $this->_slug . DS . '_auto_copy_attendee_info.template.php',
477
-                apply_filters(
478
-                    'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args',
479
-                    array()
480
-                ),
481
-                true,
482
-                true
483
-            )
484
-        );
485
-    }
486
-
487
-
488
-    /**
489
-     * _copy_attendee_info_inputs
490
-     *
491
-     * @access public
492
-     * @return array
493
-     * @throws \EE_Error
494
-     */
495
-    private function _copy_attendee_info_inputs()
496
-    {
497
-        $copy_attendee_info_inputs = array();
498
-        $prev_ticket               = null;
499
-        // grab the saved registrations from the transaction
500
-        $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
501
-        foreach ($registrations as $registration) {
502
-            // for all  attendees other than the primary attendee
503
-            if ($registration instanceof EE_Registration && ! $registration->is_primary_registrant()) {
504
-                // if this is a new ticket OR if this is the very first additional attendee after the primary attendee
505
-                if ($registration->ticket()->ID() !== $prev_ticket) {
506
-                    $item_name = $registration->ticket()->name();
507
-                    $item_name .= $registration->ticket()->description() !== ''
508
-                        ? ' - ' . $registration->ticket()->description()
509
-                        : '';
510
-                    $copy_attendee_info_inputs['spco_copy_attendee_chk[ticket-' . $registration->ticket()->ID() . ']'] =
511
-                        new EE_Form_Section_HTML(
512
-                            '<h6 class="spco-copy-attendee-event-hdr">' . $item_name . '</h6>'
513
-                        );
514
-                    $prev_ticket = $registration->ticket()->ID();
515
-                }
516
-
517
-                $copy_attendee_info_inputs['spco_copy_attendee_chk[' . $registration->ID() . ']'] =
518
-                    new EE_Checkbox_Multi_Input(
519
-                        array(
520
-                            $registration->ID() => sprintf(
521
-                                esc_html__('Attendee #%s', 'event_espresso'),
522
-                                $registration->count()
523
-                            ),
524
-                        ),
525
-                        array(
526
-                            'html_id'                 => 'spco-copy-attendee-chk-' . $registration->reg_url_link(),
527
-                            'html_class'              => 'spco-copy-attendee-chk ee-do-not-validate',
528
-                            'display_html_label_text' => false,
529
-                        )
530
-                    );
531
-            }
532
-        }
533
-        return $copy_attendee_info_inputs;
534
-    }
535
-
536
-
537
-    /**
538
-     * _additional_primary_registrant_inputs
539
-     *
540
-     * @access public
541
-     * @param EE_Registration $registration
542
-     * @return    EE_Form_Input_Base
543
-     * @throws \EE_Error
544
-     */
545
-    private function _additional_primary_registrant_inputs(EE_Registration $registration)
546
-    {
547
-        // generate hidden input
548
-        return new EE_Hidden_Input(
549
-            array(
550
-                'html_id' => 'primary_registrant',
551
-                'default' => $registration->reg_url_link(),
552
-            )
553
-        );
554
-    }
555
-
556
-
557
-    /**
558
-     * @access public
559
-     * @param EE_Registration $registration
560
-     * @param EE_Question     $question
561
-     * @return EE_Form_Input_Base
562
-     * @throws EE_Error
563
-     * @throws InvalidArgumentException
564
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
565
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
566
-     */
567
-    public function reg_form_question(EE_Registration $registration, EE_Question $question)
568
-    {
569
-
570
-        // if this question was for an attendee detail, then check for that answer
571
-        $answer_value = EEM_Answer::instance()->get_attendee_property_answer_value(
572
-            $registration,
573
-            $question->system_ID()
574
-        );
575
-        $answer       = $answer_value === null
576
-            ? EEM_Answer::instance()->get_one(
577
-                array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
578
-            )
579
-            : null;
580
-        // if NOT returning to edit an existing registration
581
-        // OR if this question is for an attendee property
582
-        // OR we still don't have an EE_Answer object
583
-        if ($answer_value || ! $answer instanceof EE_Answer || ! $registration->reg_url_link()) {
584
-            // create an EE_Answer object for storing everything in
585
-            $answer = EE_Answer::new_instance(array(
586
-                'QST_ID' => $question->ID(),
587
-                'REG_ID' => $registration->ID(),
588
-            ));
589
-        }
590
-        // verify instance
591
-        if ($answer instanceof EE_Answer) {
592
-            if (! empty($answer_value)) {
593
-                $answer->set('ANS_value', $answer_value);
594
-            }
595
-            $answer->cache('Question', $question);
596
-            //remember system ID had a bug where sometimes it could be null
597
-            $answer_cache_id = $question->is_system_question()
598
-                ? $question->system_ID() . '-' . $registration->reg_url_link()
599
-                : $question->ID() . '-' . $registration->reg_url_link();
600
-            $registration->cache('Answer', $answer, $answer_cache_id);
601
-        }
602
-        return $this->_generate_question_input($registration, $question, $answer);
603
-    }
604
-
605
-
606
-    /**
607
-     * @param EE_Registration $registration
608
-     * @param EE_Question     $question
609
-     * @param                 mixed EE_Answer|NULL      $answer
610
-     * @return EE_Form_Input_Base
611
-     * @throws \EE_Error
612
-     */
613
-    private function _generate_question_input(EE_Registration $registration, EE_Question $question, $answer)
614
-    {
615
-        $identifier                             = $question->is_system_question()
616
-            ? $question->system_ID()
617
-            : $question->ID();
618
-        $this->_required_questions[$identifier] = $question->required() ? true : false;
619
-        add_filter(
620
-            'FHEE__EE_Question__generate_form_input__country_options',
621
-            array($this, 'use_cached_countries_for_form_input'),
622
-            10,
623
-            4
624
-        );
625
-        add_filter(
626
-            'FHEE__EE_Question__generate_form_input__state_options',
627
-            array($this, 'use_cached_states_for_form_input'),
628
-            10,
629
-            4
630
-        );
631
-        $input_constructor_args                  = array(
632
-            'html_name'        => 'ee_reg_qstn[' . $registration->ID() . '][' . $identifier . ']',
633
-            'html_id'          => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
634
-            'html_class'       => 'ee-reg-qstn ee-reg-qstn-' . $identifier,
635
-            'html_label_id'    => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
636
-            'html_label_class' => 'ee-reg-qstn',
637
-        );
638
-        $input_constructor_args['html_label_id'] .= '-lbl';
639
-        if ($answer instanceof EE_Answer && $answer->ID()) {
640
-            $input_constructor_args['html_name']     .= '[' . $answer->ID() . ']';
641
-            $input_constructor_args['html_id']       .= '-' . $answer->ID();
642
-            $input_constructor_args['html_label_id'] .= '-' . $answer->ID();
643
-        }
644
-        $form_input = $question->generate_form_input(
645
-            $registration,
646
-            $answer,
647
-            $input_constructor_args
648
-        );
649
-        remove_filter(
650
-            'FHEE__EE_Question__generate_form_input__country_options',
651
-            array($this, 'use_cached_countries_for_form_input')
652
-        );
653
-        remove_filter(
654
-            'FHEE__EE_Question__generate_form_input__state_options',
655
-            array($this, 'use_cached_states_for_form_input')
656
-        );
657
-        return $form_input;
658
-    }
659
-
660
-
661
-    /**
662
-     * Gets the list of countries for the form input
663
-     *
664
-     * @param array|null       $countries_list
665
-     * @param \EE_Question     $question
666
-     * @param \EE_Registration $registration
667
-     * @param \EE_Answer       $answer
668
-     * @return array 2d keys are country IDs, values are their names
669
-     * @throws EE_Error
670
-     * @throws InvalidArgumentException
671
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
672
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
673
-     */
674
-    public function use_cached_countries_for_form_input(
675
-        $countries_list,
676
-        \EE_Question $question = null,
677
-        \EE_Registration $registration = null,
678
-        \EE_Answer $answer = null
679
-    ) {
680
-        $country_options = array('' => '');
681
-        // get possibly cached list of countries
682
-        $countries = $this->checkout->action === 'process_reg_step'
683
-            ? EEM_Country::instance()->get_all_countries()
684
-            : EEM_Country::instance()->get_all_active_countries();
685
-        if (! empty($countries)) {
686
-            foreach ($countries as $country) {
687
-                if ($country instanceof EE_Country) {
688
-                    $country_options[$country->ID()] = $country->name();
689
-                }
690
-            }
691
-        }
692
-        if ($question instanceof EE_Question
693
-            && $registration instanceof EE_Registration) {
694
-            $answer = EEM_Answer::instance()->get_one(
695
-                array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
696
-            );
697
-        } else {
698
-            $answer = EE_Answer::new_instance();
699
-        }
700
-        $country_options = apply_filters(
701
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__country_options',
702
-            $country_options,
703
-            $this,
704
-            $registration,
705
-            $question,
706
-            $answer
707
-        );
708
-        return $country_options;
709
-    }
710
-
711
-
712
-    /**
713
-     * Gets the list of states for the form input
714
-     *
715
-     * @param array|null       $states_list
716
-     * @param \EE_Question     $question
717
-     * @param \EE_Registration $registration
718
-     * @param \EE_Answer       $answer
719
-     * @return array 2d keys are state IDs, values are their names
720
-     * @throws EE_Error
721
-     * @throws InvalidArgumentException
722
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
723
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
724
-     */
725
-    public function use_cached_states_for_form_input(
726
-        $states_list,
727
-        \EE_Question $question = null,
728
-        \EE_Registration $registration = null,
729
-        \EE_Answer $answer = null
730
-    ) {
731
-        $state_options = array('' => array('' => ''));
732
-        $states        = $this->checkout->action === 'process_reg_step'
733
-            ? EEM_State::instance()->get_all_states()
734
-            : EEM_State::instance()->get_all_active_states();
735
-        if (! empty($states)) {
736
-            foreach ($states as $state) {
737
-                if ($state instanceof EE_State) {
738
-                    $state_options[$state->country()->name()][$state->ID()] = $state->name();
739
-                }
740
-            }
741
-        }
742
-        $state_options = apply_filters(
743
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__state_options',
744
-            $state_options,
745
-            $this,
746
-            $registration,
747
-            $question,
748
-            $answer
749
-        );
750
-        return $state_options;
751
-    }
752
-
753
-
754
-
755
-
756
-
757
-
758
-    /********************************************************************************************************/
759
-    /****************************************  PROCESS REG STEP  ****************************************/
760
-    /********************************************************************************************************/
761
-    /**
762
-     * @return bool
763
-     * @throws EE_Error
764
-     * @throws InvalidArgumentException
765
-     * @throws ReflectionException
766
-     * @throws RuntimeException
767
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
768
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
769
-     */
770
-    public function process_reg_step()
771
-    {
772
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
773
-        // grab validated data from form
774
-        $valid_data = $this->checkout->current_step->valid_data();
775
-        // EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ );
776
-        // EEH_Debug_Tools::printr( $valid_data, '$valid_data', __FILE__, __LINE__ );
777
-        // if we don't have any $valid_data then something went TERRIBLY WRONG !!!
778
-        if (empty($valid_data)) {
779
-            EE_Error::add_error(
780
-                esc_html__('No valid question responses were received.', 'event_espresso'),
781
-                __FILE__,
782
-                __FUNCTION__,
783
-                __LINE__
784
-            );
785
-            return false;
786
-        }
787
-        if (! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
788
-            EE_Error::add_error(
789
-                esc_html__(
790
-                    'A valid transaction could not be initiated for processing your registrations.',
791
-                    'event_espresso'
792
-                ),
793
-                __FILE__,
794
-                __FUNCTION__,
795
-                __LINE__
796
-            );
797
-            return false;
798
-        }
799
-        // get cached registrations
800
-        $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
801
-        // verify we got the goods
802
-        if (empty($registrations)) {
803
-            //combine the old translated string with a new one, in order to not break translations
804
-            $error_message = esc_html__( 'Your form data could not be applied to any valid registrations.', 'event_espresso' )
805
-                             . sprintf(
806
-                                 esc_html__('%3$sThis can sometimes happen if too much time has been taken to complete the registration process.%3$sPlease return to the %1$sEvent List%2$s and reselect your tickets. If the problem continues, please contact the site administrator.', 'event_espresso'),
807
-                                 '<a href="' . get_post_type_archive_link('espresso_events') . '" >',
808
-                                 '</a>',
809
-                                 '<br />'
810
-                             );
811
-            EE_Error::add_error(
812
-                $error_message,
813
-                __FILE__,
814
-                __FUNCTION__,
815
-                __LINE__
816
-            );
817
-            return false;
818
-        }
819
-        // extract attendee info from form data and save to model objects
820
-        $registrations_processed = $this->_process_registrations($registrations, $valid_data);
821
-        // if first pass thru SPCO,
822
-        // then let's check processed registrations against the total number of tickets in the cart
823
-        if ($registrations_processed === false) {
824
-            // but return immediately if the previous step exited early due to errors
825
-            return false;
826
-        } elseif (! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
827
-            // generate a correctly translated string for all possible singular/plural combinations
828
-            if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) {
829
-                $error_msg = sprintf(
830
-                    esc_html__(
831
-                        'There was %1$d ticket in the Event Queue, but %2$ds registrations were processed',
832
-                        'event_espresso'
833
-                    ),
834
-                    $this->checkout->total_ticket_count,
835
-                    $registrations_processed
836
-                );
837
-            } elseif ($this->checkout->total_ticket_count !== 1 && $registrations_processed === 1) {
838
-                $error_msg = sprintf(
839
-                    esc_html__(
840
-                        'There was a total of %1$d tickets in the Event Queue, but only %2$ds registration was processed',
841
-                        'event_espresso'
842
-                    ),
843
-                    $this->checkout->total_ticket_count,
844
-                    $registrations_processed
845
-                );
846
-            } else {
847
-                $error_msg = sprintf(
848
-                    esc_html__(
849
-                        'There was a total of %1$d tickets in the Event Queue, but %2$ds registrations were processed',
850
-                        'event_espresso'
851
-                    ),
852
-                    $this->checkout->total_ticket_count,
853
-                    $registrations_processed
854
-                );
855
-            }
856
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
857
-            return false;
858
-        }
859
-        // mark this reg step as completed
860
-        $this->set_completed();
861
-        $this->_set_success_message(
862
-            esc_html__('The Attendee Information Step has been successfully completed.', 'event_espresso')
863
-        );
864
-        //do action in case a plugin wants to do something with the data submitted in step 1.
865
-        //passes EE_Single_Page_Checkout, and it's posted data
866
-        do_action('AHEE__EE_Single_Page_Checkout__process_attendee_information__end', $this, $valid_data);
867
-        return true;
868
-    }
869
-
870
-
871
-    /**
872
-     *    _process_registrations
873
-     *
874
-     * @param EE_Registration[] $registrations
875
-     * @param array             $valid_data
876
-     * @return bool|int
877
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
878
-     * @throws EE_Error
879
-     * @throws InvalidArgumentException
880
-     * @throws ReflectionException
881
-     * @throws RuntimeException
882
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
883
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
884
-     */
885
-    private function _process_registrations($registrations = array(), $valid_data = array())
886
-    {
887
-        // load resources and set some defaults
888
-        EE_Registry::instance()->load_model('Attendee');
889
-        // holder for primary registrant attendee object
890
-        $this->checkout->primary_attendee_obj = null;
891
-        // array for tracking reg form data for the primary registrant
892
-        $primary_registrant = array(
893
-            'line_item_id' => null,
894
-        );
895
-        $copy_primary       = false;
896
-        // reg form sections that do not contain inputs
897
-        $non_input_form_sections = array(
898
-            'primary_registrant',
899
-            'additional_attendee_reg_info',
900
-            'spco_copy_attendee_chk',
901
-        );
902
-        // attendee counter
903
-        $att_nmbr = 0;
904
-        // grab the saved registrations from the transaction
905
-        foreach ($registrations as $registration) {
906
-            // verify EE_Registration object
907
-            if (! $registration instanceof EE_Registration) {
908
-                EE_Error::add_error(
909
-                    esc_html__(
910
-                        'An invalid Registration object was discovered when attempting to process your registration information.',
911
-                        'event_espresso'
912
-                    ),
913
-                    __FILE__,
914
-                    __FUNCTION__,
915
-                    __LINE__
916
-                );
917
-                return false;
918
-            }
919
-            /** @var string $reg_url_link */
920
-            $reg_url_link = $registration->reg_url_link();
921
-            // reg_url_link exists ?
922
-            if (! empty($reg_url_link)) {
923
-                // should this registration be processed during this visit ?
924
-                if ($this->checkout->visit_allows_processing_of_this_registration($registration)) {
925
-                    // if NOT revisiting, then let's save the registration now,
926
-                    // so that we have a REG_ID to use when generating other objects
927
-                    if (! $this->checkout->revisit) {
928
-                        $registration->save();
929
-                    }
930
-                    /**
931
-                     * This allows plugins to trigger a fail on processing of a
932
-                     * registration for any conditions they may have for it to pass.
933
-                     *
934
-                     * @var bool   if true is returned by the plugin then the
935
-                     *            registration processing is halted.
936
-                     */
937
-                    if (apply_filters(
938
-                        'FHEE__EE_SPCO_Reg_Step_Attendee_Information___process_registrations__pre_registration_process',
939
-                        false,
940
-                        $att_nmbr,
941
-                        $registration,
942
-                        $registrations,
943
-                        $valid_data,
944
-                        $this
945
-                    )) {
946
-                        return false;
947
-                    }
948
-
949
-                    // Houston, we have a registration!
950
-                    $att_nmbr++;
951
-                    $this->_attendee_data[$reg_url_link] = array();
952
-                    // grab any existing related answer objects
953
-                    $this->_registration_answers = $registration->answers();
954
-                    // unset( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] );
955
-                    if (isset($valid_data[$reg_url_link])) {
956
-                        // do we need to copy basic info from primary attendee ?
957
-                        $copy_primary = isset($valid_data[$reg_url_link]['additional_attendee_reg_info'])
958
-                                        && absint($valid_data[$reg_url_link]['additional_attendee_reg_info']) === 0
959
-                            ? true
960
-                            : false;
961
-                        // filter form input data for this registration
962
-                        $valid_data[$reg_url_link] = (array)apply_filters(
963
-                            'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item',
964
-                            $valid_data[$reg_url_link]
965
-                        );
966
-                        if (isset($valid_data['primary_attendee'])) {
967
-                            $primary_registrant['line_item_id'] = ! empty($valid_data['primary_attendee'])
968
-                                ? $valid_data['primary_attendee']
969
-                                : false;
970
-                            unset($valid_data['primary_attendee']);
971
-                        }
972
-                        // now loop through our array of valid post data && process attendee reg forms
973
-                        foreach ($valid_data[$reg_url_link] as $form_section => $form_inputs) {
974
-                            if (! in_array($form_section, $non_input_form_sections)) {
975
-                                foreach ($form_inputs as $form_input => $input_value) {
976
-                                    // \EEH_Debug_Tools::printr( $input_value, $form_input, __FILE__, __LINE__ );
977
-                                    // check for critical inputs
978
-                                    if (! $this->_verify_critical_attendee_details_are_set_and_validate_email(
979
-                                        $form_input,
980
-                                        $input_value
981
-                                    )
982
-                                    ) {
983
-                                        return false;
984
-                                    }
985
-                                    // store a bit of data about the primary attendee
986
-                                    if ($att_nmbr === 1
987
-                                        && ! empty($input_value)
988
-                                        && $reg_url_link === $primary_registrant['line_item_id']
989
-                                    ) {
990
-                                        $primary_registrant[$form_input] = $input_value;
991
-                                    } elseif ($copy_primary
992
-                                        && $input_value === null
993
-                                        && isset($primary_registrant[$form_input])
994
-                                    ) {
995
-                                        $input_value = $primary_registrant[$form_input];
996
-                                    }
997
-                                    // now attempt to save the input data
998
-                                    if (! $this->_save_registration_form_input(
999
-                                        $registration,
1000
-                                        $form_input,
1001
-                                        $input_value
1002
-                                    )
1003
-                                    ) {
1004
-                                        EE_Error::add_error(
1005
-                                            sprintf(
1006
-                                                esc_html__(
1007
-                                                    'Unable to save registration form data for the form input: "%1$s" with the submitted value: "%2$s"',
1008
-                                                    'event_espresso'
1009
-                                                ),
1010
-                                                $form_input,
1011
-                                                $input_value
1012
-                                            ),
1013
-                                            __FILE__,
1014
-                                            __FUNCTION__,
1015
-                                            __LINE__
1016
-                                        );
1017
-                                        return false;
1018
-                                    }
1019
-                                }
1020
-                            }
1021
-                        }  // end of foreach ( $valid_data[ $reg_url_link ] as $form_section => $form_inputs )
1022
-                    }
1023
-                    //EEH_Debug_Tools::printr( $this->_attendee_data, '$this->_attendee_data', __FILE__, __LINE__ );
1024
-                    // this registration does not require additional attendee information ?
1025
-                    if ($copy_primary
1026
-                        && $att_nmbr > 1
1027
-                        && $this->checkout->primary_attendee_obj instanceof EE_Attendee
1028
-                    ) {
1029
-                        // just copy the primary registrant
1030
-                        $attendee = $this->checkout->primary_attendee_obj;
1031
-                    } else {
1032
-                        // ensure critical details are set for additional attendees
1033
-                        $this->_attendee_data[$reg_url_link] = $att_nmbr > 1
1034
-                            ? $this->_copy_critical_attendee_details_from_primary_registrant(
1035
-                                $this->_attendee_data[$reg_url_link]
1036
-                            )
1037
-                            : $this->_attendee_data[$reg_url_link];
1038
-                        // execute create attendee command (which may return an existing attendee)
1039
-                        $attendee = EE_Registry::instance()->BUS->execute(
1040
-                            new CreateAttendeeCommand(
1041
-                                $this->_attendee_data[$reg_url_link],
1042
-                                $registration
1043
-                            )
1044
-                        );
1045
-                        // who's #1 ?
1046
-                        if ($att_nmbr === 1) {
1047
-                            $this->checkout->primary_attendee_obj = $attendee;
1048
-                        }
1049
-                    }
1050
-                    // EEH_Debug_Tools::printr( $attendee, '$attendee', __FILE__, __LINE__ );
1051
-                    // add relation to registration, set attendee ID, and cache attendee
1052
-                    $this->_associate_attendee_with_registration($registration, $attendee);
1053
-                    // \EEH_Debug_Tools::printr( $registration, '$registration', __FILE__, __LINE__ );
1054
-                    if (! $registration->attendee() instanceof EE_Attendee) {
1055
-                        EE_Error::add_error(
1056
-                            sprintf(
1057
-                                esc_html__(
1058
-                                    'Registration %s has an invalid or missing Attendee object.',
1059
-                                    'event_espresso'
1060
-                                ),
1061
-                                $reg_url_link
1062
-                            ),
1063
-                            __FILE__,
1064
-                            __FUNCTION__,
1065
-                            __LINE__
1066
-                        );
1067
-                        return false;
1068
-                    }
1069
-                    /** @type EE_Registration_Processor $registration_processor */
1070
-                    $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1071
-                    // at this point, we should have enough details about the registrant to consider the registration
1072
-                    // NOT incomplete
1073
-                    $registration_processor->toggle_incomplete_registration_status_to_default(
1074
-                        $registration,
1075
-                        false,
1076
-                        new Context(
1077
-                            'spco_reg_step_attendee_information_process_registrations',
1078
-                            esc_html__(
1079
-                                'Finished populating registration with details from the registration form after submitting the Attendee Information Reg Step.',
1080
-                                'event_espresso'
1081
-                            )
1082
-                        )
1083
-                    );
1084
-                    // we can also consider the TXN to not have been failed, so temporarily upgrade it's status to
1085
-                    // abandoned
1086
-                    $this->checkout->transaction->toggle_failed_transaction_status();
1087
-                    // if we've gotten this far, then let's save what we have
1088
-                    $registration->save();
1089
-                    // add relation between TXN and registration
1090
-                    $this->_associate_registration_with_transaction($registration);
1091
-                }
1092
-            } else {
1093
-                EE_Error::add_error(
1094
-                    esc_html__(
1095
-                        'An invalid or missing line item ID was encountered while attempting to process the registration form.',
1096
-                        'event_espresso'
1097
-                    ),
1098
-                    __FILE__,
1099
-                    __FUNCTION__,
1100
-                    __LINE__
1101
-                );
1102
-                // remove malformed data
1103
-                unset($valid_data[$reg_url_link]);
1104
-                return false;
1105
-            }
1106
-
1107
-        } // end of foreach ( $this->checkout->transaction->registrations()  as $registration )
1108
-        return $att_nmbr;
1109
-    }
1110
-
1111
-
1112
-    /**
1113
-     *    _save_registration_form_input
1114
-     *
1115
-     * @param EE_Registration $registration
1116
-     * @param string          $form_input
1117
-     * @param string          $input_value
1118
-     * @return bool
1119
-     * @throws EE_Error
1120
-     * @throws InvalidArgumentException
1121
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1122
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1123
-     */
1124
-    private function _save_registration_form_input(
1125
-        EE_Registration $registration,
1126
-        $form_input = '',
1127
-        $input_value = ''
1128
-    ) {
1129
-        // \EEH_Debug_Tools::printr( __FUNCTION__, __CLASS__, __FILE__, __LINE__, 2 );
1130
-        // \EEH_Debug_Tools::printr( $form_input, '$form_input', __FILE__, __LINE__ );
1131
-        // \EEH_Debug_Tools::printr( $input_value, '$input_value', __FILE__, __LINE__ );
1132
-        // allow for plugins to hook in and do their own processing of the form input.
1133
-        // For plugins to bypass normal processing here, they just need to return a boolean value.
1134
-        if (apply_filters(
1135
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___save_registration_form_input',
1136
-            false,
1137
-            $registration,
1138
-            $form_input,
1139
-            $input_value,
1140
-            $this
1141
-        )) {
1142
-            return true;
1143
-        }
1144
-        /*
387
+		$question_group_reg_form = new EE_Form_Section_Proper($form_args);
388
+		return apply_filters(
389
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__question_group_reg_form',
390
+			$question_group_reg_form,
391
+			$registration,
392
+			$question_group,
393
+			$this
394
+		);
395
+	}
396
+
397
+
398
+	/**
399
+	 * @access public
400
+	 * @param EE_Question_Group $question_group
401
+	 * @return    EE_Form_Section_HTML
402
+	 */
403
+	private function _question_group_header(EE_Question_Group $question_group)
404
+	{
405
+		$html = '';
406
+		// group_name
407
+		if ($question_group->show_group_name() && $question_group->name() !== '') {
408
+			if ($this->checkout->admin_request) {
409
+				$html .= EEH_HTML::br();
410
+				$html .= EEH_HTML::h3(
411
+					$question_group->name(),
412
+					'',
413
+					'ee-reg-form-qstn-grp-title title',
414
+					'font-size: 1.3em; padding-left:0;'
415
+				);
416
+			} else {
417
+				$html .= EEH_HTML::h4(
418
+					$question_group->name(),
419
+					'',
420
+					'ee-reg-form-qstn-grp-title section-title'
421
+				);
422
+			}
423
+		}
424
+		// group_desc
425
+		if ($question_group->show_group_desc() && $question_group->desc() !== '') {
426
+			$html .= EEH_HTML::p(
427
+				$question_group->desc(),
428
+				'',
429
+				$this->checkout->admin_request
430
+					? 'ee-reg-form-qstn-grp-desc-pg'
431
+					: 'ee-reg-form-qstn-grp-desc-pg small-text lt-grey-text'
432
+			);
433
+		}
434
+		return new EE_Form_Section_HTML($html);
435
+	}
436
+
437
+
438
+	/**
439
+	 * @access public
440
+	 * @return    EE_Form_Section_Proper
441
+	 * @throws \EE_Error
442
+	 */
443
+	private function _copy_attendee_info_form()
444
+	{
445
+		// array of params to pass to parent constructor
446
+		return new EE_Form_Section_Proper(
447
+			array(
448
+				'subsections'     => $this->_copy_attendee_info_inputs(),
449
+				'layout_strategy' => new EE_Template_Layout(
450
+					array(
451
+						'layout_template_file'     => SPCO_REG_STEPS_PATH
452
+													  . $this->_slug
453
+													  . DS
454
+													  . 'copy_attendee_info.template.php',
455
+						'begin_template_file'      => null,
456
+						'input_template_file'      => null,
457
+						'subsection_template_file' => null,
458
+						'end_template_file'        => null,
459
+					)
460
+				),
461
+			)
462
+		);
463
+	}
464
+
465
+
466
+	/**
467
+	 * _auto_copy_attendee_info
468
+	 *
469
+	 * @access public
470
+	 * @return EE_Form_Section_HTML
471
+	 */
472
+	private function _auto_copy_attendee_info()
473
+	{
474
+		return new EE_Form_Section_HTML(
475
+			EEH_Template::locate_template(
476
+				SPCO_REG_STEPS_PATH . $this->_slug . DS . '_auto_copy_attendee_info.template.php',
477
+				apply_filters(
478
+					'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args',
479
+					array()
480
+				),
481
+				true,
482
+				true
483
+			)
484
+		);
485
+	}
486
+
487
+
488
+	/**
489
+	 * _copy_attendee_info_inputs
490
+	 *
491
+	 * @access public
492
+	 * @return array
493
+	 * @throws \EE_Error
494
+	 */
495
+	private function _copy_attendee_info_inputs()
496
+	{
497
+		$copy_attendee_info_inputs = array();
498
+		$prev_ticket               = null;
499
+		// grab the saved registrations from the transaction
500
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
501
+		foreach ($registrations as $registration) {
502
+			// for all  attendees other than the primary attendee
503
+			if ($registration instanceof EE_Registration && ! $registration->is_primary_registrant()) {
504
+				// if this is a new ticket OR if this is the very first additional attendee after the primary attendee
505
+				if ($registration->ticket()->ID() !== $prev_ticket) {
506
+					$item_name = $registration->ticket()->name();
507
+					$item_name .= $registration->ticket()->description() !== ''
508
+						? ' - ' . $registration->ticket()->description()
509
+						: '';
510
+					$copy_attendee_info_inputs['spco_copy_attendee_chk[ticket-' . $registration->ticket()->ID() . ']'] =
511
+						new EE_Form_Section_HTML(
512
+							'<h6 class="spco-copy-attendee-event-hdr">' . $item_name . '</h6>'
513
+						);
514
+					$prev_ticket = $registration->ticket()->ID();
515
+				}
516
+
517
+				$copy_attendee_info_inputs['spco_copy_attendee_chk[' . $registration->ID() . ']'] =
518
+					new EE_Checkbox_Multi_Input(
519
+						array(
520
+							$registration->ID() => sprintf(
521
+								esc_html__('Attendee #%s', 'event_espresso'),
522
+								$registration->count()
523
+							),
524
+						),
525
+						array(
526
+							'html_id'                 => 'spco-copy-attendee-chk-' . $registration->reg_url_link(),
527
+							'html_class'              => 'spco-copy-attendee-chk ee-do-not-validate',
528
+							'display_html_label_text' => false,
529
+						)
530
+					);
531
+			}
532
+		}
533
+		return $copy_attendee_info_inputs;
534
+	}
535
+
536
+
537
+	/**
538
+	 * _additional_primary_registrant_inputs
539
+	 *
540
+	 * @access public
541
+	 * @param EE_Registration $registration
542
+	 * @return    EE_Form_Input_Base
543
+	 * @throws \EE_Error
544
+	 */
545
+	private function _additional_primary_registrant_inputs(EE_Registration $registration)
546
+	{
547
+		// generate hidden input
548
+		return new EE_Hidden_Input(
549
+			array(
550
+				'html_id' => 'primary_registrant',
551
+				'default' => $registration->reg_url_link(),
552
+			)
553
+		);
554
+	}
555
+
556
+
557
+	/**
558
+	 * @access public
559
+	 * @param EE_Registration $registration
560
+	 * @param EE_Question     $question
561
+	 * @return EE_Form_Input_Base
562
+	 * @throws EE_Error
563
+	 * @throws InvalidArgumentException
564
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
565
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
566
+	 */
567
+	public function reg_form_question(EE_Registration $registration, EE_Question $question)
568
+	{
569
+
570
+		// if this question was for an attendee detail, then check for that answer
571
+		$answer_value = EEM_Answer::instance()->get_attendee_property_answer_value(
572
+			$registration,
573
+			$question->system_ID()
574
+		);
575
+		$answer       = $answer_value === null
576
+			? EEM_Answer::instance()->get_one(
577
+				array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
578
+			)
579
+			: null;
580
+		// if NOT returning to edit an existing registration
581
+		// OR if this question is for an attendee property
582
+		// OR we still don't have an EE_Answer object
583
+		if ($answer_value || ! $answer instanceof EE_Answer || ! $registration->reg_url_link()) {
584
+			// create an EE_Answer object for storing everything in
585
+			$answer = EE_Answer::new_instance(array(
586
+				'QST_ID' => $question->ID(),
587
+				'REG_ID' => $registration->ID(),
588
+			));
589
+		}
590
+		// verify instance
591
+		if ($answer instanceof EE_Answer) {
592
+			if (! empty($answer_value)) {
593
+				$answer->set('ANS_value', $answer_value);
594
+			}
595
+			$answer->cache('Question', $question);
596
+			//remember system ID had a bug where sometimes it could be null
597
+			$answer_cache_id = $question->is_system_question()
598
+				? $question->system_ID() . '-' . $registration->reg_url_link()
599
+				: $question->ID() . '-' . $registration->reg_url_link();
600
+			$registration->cache('Answer', $answer, $answer_cache_id);
601
+		}
602
+		return $this->_generate_question_input($registration, $question, $answer);
603
+	}
604
+
605
+
606
+	/**
607
+	 * @param EE_Registration $registration
608
+	 * @param EE_Question     $question
609
+	 * @param                 mixed EE_Answer|NULL      $answer
610
+	 * @return EE_Form_Input_Base
611
+	 * @throws \EE_Error
612
+	 */
613
+	private function _generate_question_input(EE_Registration $registration, EE_Question $question, $answer)
614
+	{
615
+		$identifier                             = $question->is_system_question()
616
+			? $question->system_ID()
617
+			: $question->ID();
618
+		$this->_required_questions[$identifier] = $question->required() ? true : false;
619
+		add_filter(
620
+			'FHEE__EE_Question__generate_form_input__country_options',
621
+			array($this, 'use_cached_countries_for_form_input'),
622
+			10,
623
+			4
624
+		);
625
+		add_filter(
626
+			'FHEE__EE_Question__generate_form_input__state_options',
627
+			array($this, 'use_cached_states_for_form_input'),
628
+			10,
629
+			4
630
+		);
631
+		$input_constructor_args                  = array(
632
+			'html_name'        => 'ee_reg_qstn[' . $registration->ID() . '][' . $identifier . ']',
633
+			'html_id'          => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
634
+			'html_class'       => 'ee-reg-qstn ee-reg-qstn-' . $identifier,
635
+			'html_label_id'    => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
636
+			'html_label_class' => 'ee-reg-qstn',
637
+		);
638
+		$input_constructor_args['html_label_id'] .= '-lbl';
639
+		if ($answer instanceof EE_Answer && $answer->ID()) {
640
+			$input_constructor_args['html_name']     .= '[' . $answer->ID() . ']';
641
+			$input_constructor_args['html_id']       .= '-' . $answer->ID();
642
+			$input_constructor_args['html_label_id'] .= '-' . $answer->ID();
643
+		}
644
+		$form_input = $question->generate_form_input(
645
+			$registration,
646
+			$answer,
647
+			$input_constructor_args
648
+		);
649
+		remove_filter(
650
+			'FHEE__EE_Question__generate_form_input__country_options',
651
+			array($this, 'use_cached_countries_for_form_input')
652
+		);
653
+		remove_filter(
654
+			'FHEE__EE_Question__generate_form_input__state_options',
655
+			array($this, 'use_cached_states_for_form_input')
656
+		);
657
+		return $form_input;
658
+	}
659
+
660
+
661
+	/**
662
+	 * Gets the list of countries for the form input
663
+	 *
664
+	 * @param array|null       $countries_list
665
+	 * @param \EE_Question     $question
666
+	 * @param \EE_Registration $registration
667
+	 * @param \EE_Answer       $answer
668
+	 * @return array 2d keys are country IDs, values are their names
669
+	 * @throws EE_Error
670
+	 * @throws InvalidArgumentException
671
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
672
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
673
+	 */
674
+	public function use_cached_countries_for_form_input(
675
+		$countries_list,
676
+		\EE_Question $question = null,
677
+		\EE_Registration $registration = null,
678
+		\EE_Answer $answer = null
679
+	) {
680
+		$country_options = array('' => '');
681
+		// get possibly cached list of countries
682
+		$countries = $this->checkout->action === 'process_reg_step'
683
+			? EEM_Country::instance()->get_all_countries()
684
+			: EEM_Country::instance()->get_all_active_countries();
685
+		if (! empty($countries)) {
686
+			foreach ($countries as $country) {
687
+				if ($country instanceof EE_Country) {
688
+					$country_options[$country->ID()] = $country->name();
689
+				}
690
+			}
691
+		}
692
+		if ($question instanceof EE_Question
693
+			&& $registration instanceof EE_Registration) {
694
+			$answer = EEM_Answer::instance()->get_one(
695
+				array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
696
+			);
697
+		} else {
698
+			$answer = EE_Answer::new_instance();
699
+		}
700
+		$country_options = apply_filters(
701
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__country_options',
702
+			$country_options,
703
+			$this,
704
+			$registration,
705
+			$question,
706
+			$answer
707
+		);
708
+		return $country_options;
709
+	}
710
+
711
+
712
+	/**
713
+	 * Gets the list of states for the form input
714
+	 *
715
+	 * @param array|null       $states_list
716
+	 * @param \EE_Question     $question
717
+	 * @param \EE_Registration $registration
718
+	 * @param \EE_Answer       $answer
719
+	 * @return array 2d keys are state IDs, values are their names
720
+	 * @throws EE_Error
721
+	 * @throws InvalidArgumentException
722
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
723
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
724
+	 */
725
+	public function use_cached_states_for_form_input(
726
+		$states_list,
727
+		\EE_Question $question = null,
728
+		\EE_Registration $registration = null,
729
+		\EE_Answer $answer = null
730
+	) {
731
+		$state_options = array('' => array('' => ''));
732
+		$states        = $this->checkout->action === 'process_reg_step'
733
+			? EEM_State::instance()->get_all_states()
734
+			: EEM_State::instance()->get_all_active_states();
735
+		if (! empty($states)) {
736
+			foreach ($states as $state) {
737
+				if ($state instanceof EE_State) {
738
+					$state_options[$state->country()->name()][$state->ID()] = $state->name();
739
+				}
740
+			}
741
+		}
742
+		$state_options = apply_filters(
743
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__state_options',
744
+			$state_options,
745
+			$this,
746
+			$registration,
747
+			$question,
748
+			$answer
749
+		);
750
+		return $state_options;
751
+	}
752
+
753
+
754
+
755
+
756
+
757
+
758
+	/********************************************************************************************************/
759
+	/****************************************  PROCESS REG STEP  ****************************************/
760
+	/********************************************************************************************************/
761
+	/**
762
+	 * @return bool
763
+	 * @throws EE_Error
764
+	 * @throws InvalidArgumentException
765
+	 * @throws ReflectionException
766
+	 * @throws RuntimeException
767
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
768
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
769
+	 */
770
+	public function process_reg_step()
771
+	{
772
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
773
+		// grab validated data from form
774
+		$valid_data = $this->checkout->current_step->valid_data();
775
+		// EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ );
776
+		// EEH_Debug_Tools::printr( $valid_data, '$valid_data', __FILE__, __LINE__ );
777
+		// if we don't have any $valid_data then something went TERRIBLY WRONG !!!
778
+		if (empty($valid_data)) {
779
+			EE_Error::add_error(
780
+				esc_html__('No valid question responses were received.', 'event_espresso'),
781
+				__FILE__,
782
+				__FUNCTION__,
783
+				__LINE__
784
+			);
785
+			return false;
786
+		}
787
+		if (! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
788
+			EE_Error::add_error(
789
+				esc_html__(
790
+					'A valid transaction could not be initiated for processing your registrations.',
791
+					'event_espresso'
792
+				),
793
+				__FILE__,
794
+				__FUNCTION__,
795
+				__LINE__
796
+			);
797
+			return false;
798
+		}
799
+		// get cached registrations
800
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
801
+		// verify we got the goods
802
+		if (empty($registrations)) {
803
+			//combine the old translated string with a new one, in order to not break translations
804
+			$error_message = esc_html__( 'Your form data could not be applied to any valid registrations.', 'event_espresso' )
805
+							 . sprintf(
806
+								 esc_html__('%3$sThis can sometimes happen if too much time has been taken to complete the registration process.%3$sPlease return to the %1$sEvent List%2$s and reselect your tickets. If the problem continues, please contact the site administrator.', 'event_espresso'),
807
+								 '<a href="' . get_post_type_archive_link('espresso_events') . '" >',
808
+								 '</a>',
809
+								 '<br />'
810
+							 );
811
+			EE_Error::add_error(
812
+				$error_message,
813
+				__FILE__,
814
+				__FUNCTION__,
815
+				__LINE__
816
+			);
817
+			return false;
818
+		}
819
+		// extract attendee info from form data and save to model objects
820
+		$registrations_processed = $this->_process_registrations($registrations, $valid_data);
821
+		// if first pass thru SPCO,
822
+		// then let's check processed registrations against the total number of tickets in the cart
823
+		if ($registrations_processed === false) {
824
+			// but return immediately if the previous step exited early due to errors
825
+			return false;
826
+		} elseif (! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
827
+			// generate a correctly translated string for all possible singular/plural combinations
828
+			if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) {
829
+				$error_msg = sprintf(
830
+					esc_html__(
831
+						'There was %1$d ticket in the Event Queue, but %2$ds registrations were processed',
832
+						'event_espresso'
833
+					),
834
+					$this->checkout->total_ticket_count,
835
+					$registrations_processed
836
+				);
837
+			} elseif ($this->checkout->total_ticket_count !== 1 && $registrations_processed === 1) {
838
+				$error_msg = sprintf(
839
+					esc_html__(
840
+						'There was a total of %1$d tickets in the Event Queue, but only %2$ds registration was processed',
841
+						'event_espresso'
842
+					),
843
+					$this->checkout->total_ticket_count,
844
+					$registrations_processed
845
+				);
846
+			} else {
847
+				$error_msg = sprintf(
848
+					esc_html__(
849
+						'There was a total of %1$d tickets in the Event Queue, but %2$ds registrations were processed',
850
+						'event_espresso'
851
+					),
852
+					$this->checkout->total_ticket_count,
853
+					$registrations_processed
854
+				);
855
+			}
856
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
857
+			return false;
858
+		}
859
+		// mark this reg step as completed
860
+		$this->set_completed();
861
+		$this->_set_success_message(
862
+			esc_html__('The Attendee Information Step has been successfully completed.', 'event_espresso')
863
+		);
864
+		//do action in case a plugin wants to do something with the data submitted in step 1.
865
+		//passes EE_Single_Page_Checkout, and it's posted data
866
+		do_action('AHEE__EE_Single_Page_Checkout__process_attendee_information__end', $this, $valid_data);
867
+		return true;
868
+	}
869
+
870
+
871
+	/**
872
+	 *    _process_registrations
873
+	 *
874
+	 * @param EE_Registration[] $registrations
875
+	 * @param array             $valid_data
876
+	 * @return bool|int
877
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
878
+	 * @throws EE_Error
879
+	 * @throws InvalidArgumentException
880
+	 * @throws ReflectionException
881
+	 * @throws RuntimeException
882
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
883
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
884
+	 */
885
+	private function _process_registrations($registrations = array(), $valid_data = array())
886
+	{
887
+		// load resources and set some defaults
888
+		EE_Registry::instance()->load_model('Attendee');
889
+		// holder for primary registrant attendee object
890
+		$this->checkout->primary_attendee_obj = null;
891
+		// array for tracking reg form data for the primary registrant
892
+		$primary_registrant = array(
893
+			'line_item_id' => null,
894
+		);
895
+		$copy_primary       = false;
896
+		// reg form sections that do not contain inputs
897
+		$non_input_form_sections = array(
898
+			'primary_registrant',
899
+			'additional_attendee_reg_info',
900
+			'spco_copy_attendee_chk',
901
+		);
902
+		// attendee counter
903
+		$att_nmbr = 0;
904
+		// grab the saved registrations from the transaction
905
+		foreach ($registrations as $registration) {
906
+			// verify EE_Registration object
907
+			if (! $registration instanceof EE_Registration) {
908
+				EE_Error::add_error(
909
+					esc_html__(
910
+						'An invalid Registration object was discovered when attempting to process your registration information.',
911
+						'event_espresso'
912
+					),
913
+					__FILE__,
914
+					__FUNCTION__,
915
+					__LINE__
916
+				);
917
+				return false;
918
+			}
919
+			/** @var string $reg_url_link */
920
+			$reg_url_link = $registration->reg_url_link();
921
+			// reg_url_link exists ?
922
+			if (! empty($reg_url_link)) {
923
+				// should this registration be processed during this visit ?
924
+				if ($this->checkout->visit_allows_processing_of_this_registration($registration)) {
925
+					// if NOT revisiting, then let's save the registration now,
926
+					// so that we have a REG_ID to use when generating other objects
927
+					if (! $this->checkout->revisit) {
928
+						$registration->save();
929
+					}
930
+					/**
931
+					 * This allows plugins to trigger a fail on processing of a
932
+					 * registration for any conditions they may have for it to pass.
933
+					 *
934
+					 * @var bool   if true is returned by the plugin then the
935
+					 *            registration processing is halted.
936
+					 */
937
+					if (apply_filters(
938
+						'FHEE__EE_SPCO_Reg_Step_Attendee_Information___process_registrations__pre_registration_process',
939
+						false,
940
+						$att_nmbr,
941
+						$registration,
942
+						$registrations,
943
+						$valid_data,
944
+						$this
945
+					)) {
946
+						return false;
947
+					}
948
+
949
+					// Houston, we have a registration!
950
+					$att_nmbr++;
951
+					$this->_attendee_data[$reg_url_link] = array();
952
+					// grab any existing related answer objects
953
+					$this->_registration_answers = $registration->answers();
954
+					// unset( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] );
955
+					if (isset($valid_data[$reg_url_link])) {
956
+						// do we need to copy basic info from primary attendee ?
957
+						$copy_primary = isset($valid_data[$reg_url_link]['additional_attendee_reg_info'])
958
+										&& absint($valid_data[$reg_url_link]['additional_attendee_reg_info']) === 0
959
+							? true
960
+							: false;
961
+						// filter form input data for this registration
962
+						$valid_data[$reg_url_link] = (array)apply_filters(
963
+							'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item',
964
+							$valid_data[$reg_url_link]
965
+						);
966
+						if (isset($valid_data['primary_attendee'])) {
967
+							$primary_registrant['line_item_id'] = ! empty($valid_data['primary_attendee'])
968
+								? $valid_data['primary_attendee']
969
+								: false;
970
+							unset($valid_data['primary_attendee']);
971
+						}
972
+						// now loop through our array of valid post data && process attendee reg forms
973
+						foreach ($valid_data[$reg_url_link] as $form_section => $form_inputs) {
974
+							if (! in_array($form_section, $non_input_form_sections)) {
975
+								foreach ($form_inputs as $form_input => $input_value) {
976
+									// \EEH_Debug_Tools::printr( $input_value, $form_input, __FILE__, __LINE__ );
977
+									// check for critical inputs
978
+									if (! $this->_verify_critical_attendee_details_are_set_and_validate_email(
979
+										$form_input,
980
+										$input_value
981
+									)
982
+									) {
983
+										return false;
984
+									}
985
+									// store a bit of data about the primary attendee
986
+									if ($att_nmbr === 1
987
+										&& ! empty($input_value)
988
+										&& $reg_url_link === $primary_registrant['line_item_id']
989
+									) {
990
+										$primary_registrant[$form_input] = $input_value;
991
+									} elseif ($copy_primary
992
+										&& $input_value === null
993
+										&& isset($primary_registrant[$form_input])
994
+									) {
995
+										$input_value = $primary_registrant[$form_input];
996
+									}
997
+									// now attempt to save the input data
998
+									if (! $this->_save_registration_form_input(
999
+										$registration,
1000
+										$form_input,
1001
+										$input_value
1002
+									)
1003
+									) {
1004
+										EE_Error::add_error(
1005
+											sprintf(
1006
+												esc_html__(
1007
+													'Unable to save registration form data for the form input: "%1$s" with the submitted value: "%2$s"',
1008
+													'event_espresso'
1009
+												),
1010
+												$form_input,
1011
+												$input_value
1012
+											),
1013
+											__FILE__,
1014
+											__FUNCTION__,
1015
+											__LINE__
1016
+										);
1017
+										return false;
1018
+									}
1019
+								}
1020
+							}
1021
+						}  // end of foreach ( $valid_data[ $reg_url_link ] as $form_section => $form_inputs )
1022
+					}
1023
+					//EEH_Debug_Tools::printr( $this->_attendee_data, '$this->_attendee_data', __FILE__, __LINE__ );
1024
+					// this registration does not require additional attendee information ?
1025
+					if ($copy_primary
1026
+						&& $att_nmbr > 1
1027
+						&& $this->checkout->primary_attendee_obj instanceof EE_Attendee
1028
+					) {
1029
+						// just copy the primary registrant
1030
+						$attendee = $this->checkout->primary_attendee_obj;
1031
+					} else {
1032
+						// ensure critical details are set for additional attendees
1033
+						$this->_attendee_data[$reg_url_link] = $att_nmbr > 1
1034
+							? $this->_copy_critical_attendee_details_from_primary_registrant(
1035
+								$this->_attendee_data[$reg_url_link]
1036
+							)
1037
+							: $this->_attendee_data[$reg_url_link];
1038
+						// execute create attendee command (which may return an existing attendee)
1039
+						$attendee = EE_Registry::instance()->BUS->execute(
1040
+							new CreateAttendeeCommand(
1041
+								$this->_attendee_data[$reg_url_link],
1042
+								$registration
1043
+							)
1044
+						);
1045
+						// who's #1 ?
1046
+						if ($att_nmbr === 1) {
1047
+							$this->checkout->primary_attendee_obj = $attendee;
1048
+						}
1049
+					}
1050
+					// EEH_Debug_Tools::printr( $attendee, '$attendee', __FILE__, __LINE__ );
1051
+					// add relation to registration, set attendee ID, and cache attendee
1052
+					$this->_associate_attendee_with_registration($registration, $attendee);
1053
+					// \EEH_Debug_Tools::printr( $registration, '$registration', __FILE__, __LINE__ );
1054
+					if (! $registration->attendee() instanceof EE_Attendee) {
1055
+						EE_Error::add_error(
1056
+							sprintf(
1057
+								esc_html__(
1058
+									'Registration %s has an invalid or missing Attendee object.',
1059
+									'event_espresso'
1060
+								),
1061
+								$reg_url_link
1062
+							),
1063
+							__FILE__,
1064
+							__FUNCTION__,
1065
+							__LINE__
1066
+						);
1067
+						return false;
1068
+					}
1069
+					/** @type EE_Registration_Processor $registration_processor */
1070
+					$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1071
+					// at this point, we should have enough details about the registrant to consider the registration
1072
+					// NOT incomplete
1073
+					$registration_processor->toggle_incomplete_registration_status_to_default(
1074
+						$registration,
1075
+						false,
1076
+						new Context(
1077
+							'spco_reg_step_attendee_information_process_registrations',
1078
+							esc_html__(
1079
+								'Finished populating registration with details from the registration form after submitting the Attendee Information Reg Step.',
1080
+								'event_espresso'
1081
+							)
1082
+						)
1083
+					);
1084
+					// we can also consider the TXN to not have been failed, so temporarily upgrade it's status to
1085
+					// abandoned
1086
+					$this->checkout->transaction->toggle_failed_transaction_status();
1087
+					// if we've gotten this far, then let's save what we have
1088
+					$registration->save();
1089
+					// add relation between TXN and registration
1090
+					$this->_associate_registration_with_transaction($registration);
1091
+				}
1092
+			} else {
1093
+				EE_Error::add_error(
1094
+					esc_html__(
1095
+						'An invalid or missing line item ID was encountered while attempting to process the registration form.',
1096
+						'event_espresso'
1097
+					),
1098
+					__FILE__,
1099
+					__FUNCTION__,
1100
+					__LINE__
1101
+				);
1102
+				// remove malformed data
1103
+				unset($valid_data[$reg_url_link]);
1104
+				return false;
1105
+			}
1106
+
1107
+		} // end of foreach ( $this->checkout->transaction->registrations()  as $registration )
1108
+		return $att_nmbr;
1109
+	}
1110
+
1111
+
1112
+	/**
1113
+	 *    _save_registration_form_input
1114
+	 *
1115
+	 * @param EE_Registration $registration
1116
+	 * @param string          $form_input
1117
+	 * @param string          $input_value
1118
+	 * @return bool
1119
+	 * @throws EE_Error
1120
+	 * @throws InvalidArgumentException
1121
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1122
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1123
+	 */
1124
+	private function _save_registration_form_input(
1125
+		EE_Registration $registration,
1126
+		$form_input = '',
1127
+		$input_value = ''
1128
+	) {
1129
+		// \EEH_Debug_Tools::printr( __FUNCTION__, __CLASS__, __FILE__, __LINE__, 2 );
1130
+		// \EEH_Debug_Tools::printr( $form_input, '$form_input', __FILE__, __LINE__ );
1131
+		// \EEH_Debug_Tools::printr( $input_value, '$input_value', __FILE__, __LINE__ );
1132
+		// allow for plugins to hook in and do their own processing of the form input.
1133
+		// For plugins to bypass normal processing here, they just need to return a boolean value.
1134
+		if (apply_filters(
1135
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___save_registration_form_input',
1136
+			false,
1137
+			$registration,
1138
+			$form_input,
1139
+			$input_value,
1140
+			$this
1141
+		)) {
1142
+			return true;
1143
+		}
1144
+		/*
1145 1145
          * $answer_cache_id is the key used to find the EE_Answer we want
1146 1146
          * @see https://events.codebasehq.com/projects/event-espresso/tickets/10477
1147 1147
          */
1148
-        $answer_cache_id = $this->checkout->reg_url_link
1149
-            ? $form_input . '-' . $registration->reg_url_link()
1150
-            : $form_input;
1151
-        $answer_is_obj   = isset($this->_registration_answers[$answer_cache_id])
1152
-                           && $this->_registration_answers[$answer_cache_id] instanceof EE_Answer
1153
-            ? true
1154
-            : false;
1155
-        //rename form_inputs if they are EE_Attendee properties
1156
-        switch ((string) $form_input) {
1157
-            case 'state':
1158
-            case 'STA_ID':
1159
-                $attendee_property = true;
1160
-                $form_input        = 'STA_ID';
1161
-                break;
1162
-
1163
-            case 'country':
1164
-            case 'CNT_ISO':
1165
-                $attendee_property = true;
1166
-                $form_input        = 'CNT_ISO';
1167
-                break;
1168
-
1169
-            default:
1170
-                $ATT_input = 'ATT_' . $form_input;
1171
-                //EEH_Debug_Tools::printr( $ATT_input, '$ATT_input', __FILE__, __LINE__ );
1172
-                $attendee_property = EEM_Attendee::instance()->has_field($ATT_input) ? true : false;
1173
-                $form_input        = $attendee_property ? 'ATT_' . $form_input : $form_input;
1174
-        }
1175
-        // EEH_Debug_Tools::printr( $answer_cache_id, '$answer_cache_id', __FILE__, __LINE__ );
1176
-        // EEH_Debug_Tools::printr( $attendee_property, '$attendee_property', __FILE__, __LINE__ );
1177
-        // EEH_Debug_Tools::printr( $answer_is_obj, '$answer_is_obj', __FILE__, __LINE__ );
1178
-        // if this form input has a corresponding attendee property
1179
-        if ($attendee_property) {
1180
-            $this->_attendee_data[$registration->reg_url_link()][$form_input] = $input_value;
1181
-            if ($answer_is_obj) {
1182
-                // and delete the corresponding answer since we won't be storing this data in that object
1183
-                $registration->_remove_relation_to($this->_registration_answers[$answer_cache_id], 'Answer');
1184
-                $this->_registration_answers[$answer_cache_id]->delete_permanently();
1185
-            }
1186
-            return true;
1187
-        } elseif ($answer_is_obj) {
1188
-            // save this data to the answer object
1189
-            $this->_registration_answers[$answer_cache_id]->set_value($input_value);
1190
-            $result = $this->_registration_answers[$answer_cache_id]->save();
1191
-            return $result !== false ? true : false;
1192
-        } else {
1193
-            foreach ($this->_registration_answers as $answer) {
1194
-                if ($answer instanceof EE_Answer && $answer->question_ID() === $answer_cache_id) {
1195
-                    $answer->set_value($input_value);
1196
-                    $result = $answer->save();
1197
-                    return $result !== false ? true : false;
1198
-                }
1199
-            }
1200
-        }
1201
-        return false;
1202
-    }
1203
-
1204
-
1205
-    /**
1206
-     *    _verify_critical_attendee_details_are_set
1207
-     *
1208
-     * @param string $form_input
1209
-     * @param string $input_value
1210
-     * @return boolean
1211
-     */
1212
-    private function _verify_critical_attendee_details_are_set_and_validate_email(
1213
-        $form_input = '',
1214
-        $input_value = ''
1215
-    ) {
1216
-        if (empty($input_value)) {
1217
-            // if the form input isn't marked as being required, then just return
1218
-            if (! isset($this->_required_questions[$form_input]) || ! $this->_required_questions[$form_input]) {
1219
-                return true;
1220
-            }
1221
-            switch ($form_input) {
1222
-                case 'fname':
1223
-                    EE_Error::add_error(
1224
-                        esc_html__('First Name is a required value.', 'event_espresso'),
1225
-                        __FILE__,
1226
-                        __FUNCTION__,
1227
-                        __LINE__
1228
-                    );
1229
-                    return false;
1230
-                    break;
1231
-                case 'lname':
1232
-                    EE_Error::add_error(
1233
-                        esc_html__('Last Name is a required value.', 'event_espresso'),
1234
-                        __FILE__,
1235
-                        __FUNCTION__,
1236
-                        __LINE__
1237
-                    );
1238
-                    return false;
1239
-                    break;
1240
-                case 'email':
1241
-                    EE_Error::add_error(
1242
-                        esc_html__('Please enter a valid email address.', 'event_espresso'),
1243
-                        __FILE__,
1244
-                        __FUNCTION__,
1245
-                        __LINE__
1246
-                    );
1247
-                    return false;
1248
-                    break;
1249
-            }
1250
-        }
1251
-        return true;
1252
-    }
1253
-
1254
-
1255
-    /**
1256
-     *    _associate_attendee_with_registration
1257
-     *
1258
-     * @param EE_Registration $registration
1259
-     * @param EE_Attendee     $attendee
1260
-     * @return void
1261
-     * @throws EE_Error
1262
-     * @throws RuntimeException
1263
-     */
1264
-    private function _associate_attendee_with_registration(EE_Registration $registration, EE_Attendee $attendee)
1265
-    {
1266
-        // add relation to attendee
1267
-        $registration->_add_relation_to($attendee, 'Attendee');
1268
-        $registration->set_attendee_id($attendee->ID());
1269
-        $registration->update_cache_after_object_save('Attendee', $attendee);
1270
-    }
1271
-
1272
-
1273
-    /**
1274
-     *    _associate_registration_with_transaction
1275
-     *
1276
-     * @param EE_Registration $registration
1277
-     * @return void
1278
-     * @throws \EE_Error
1279
-     */
1280
-    private function _associate_registration_with_transaction(EE_Registration $registration)
1281
-    {
1282
-        // add relation to registration
1283
-        $this->checkout->transaction->_add_relation_to($registration, 'Registration');
1284
-        $this->checkout->transaction->update_cache_after_object_save('Registration', $registration);
1285
-    }
1286
-
1287
-
1288
-    /**
1289
-     *    _copy_critical_attendee_details_from_primary_registrant
1290
-     *    ensures that all attendees at least have data for first name, last name, and email address
1291
-     *
1292
-     * @param array $attendee_data
1293
-     * @return array
1294
-     * @throws \EE_Error
1295
-     */
1296
-    private function _copy_critical_attendee_details_from_primary_registrant($attendee_data = array())
1297
-    {
1298
-        // bare minimum critical details include first name, last name, email address
1299
-        $critical_attendee_details = array('ATT_fname', 'ATT_lname', 'ATT_email');
1300
-        // add address info to critical details?
1301
-        if (apply_filters(
1302
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information__merge_address_details_with_critical_attendee_details',
1303
-            false
1304
-        )) {
1305
-            $address_details           = array(
1306
-                'ATT_address',
1307
-                'ATT_address2',
1308
-                'ATT_city',
1309
-                'STA_ID',
1310
-                'CNT_ISO',
1311
-                'ATT_zip',
1312
-                'ATT_phone',
1313
-            );
1314
-            $critical_attendee_details = array_merge($critical_attendee_details, $address_details);
1315
-        }
1316
-        foreach ($critical_attendee_details as $critical_attendee_detail) {
1317
-            if (! isset($attendee_data[$critical_attendee_detail])
1318
-                || empty($attendee_data[$critical_attendee_detail])
1319
-            ) {
1320
-                $attendee_data[$critical_attendee_detail] = $this->checkout->primary_attendee_obj->get(
1321
-                    $critical_attendee_detail
1322
-                );
1323
-            }
1324
-        }
1325
-        return $attendee_data;
1326
-    }
1327
-
1328
-
1329
-    /**
1330
-     *    update_reg_step
1331
-     *    this is the final step after a user  revisits the site to edit their attendee information
1332
-     *    this gets called AFTER the process_reg_step() method above
1333
-     *
1334
-     * @return bool
1335
-     * @throws EE_Error
1336
-     * @throws InvalidArgumentException
1337
-     * @throws ReflectionException
1338
-     * @throws RuntimeException
1339
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1340
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1341
-     */
1342
-    public function update_reg_step()
1343
-    {
1344
-        // save everything
1345
-        if ($this->process_reg_step()) {
1346
-            $this->checkout->redirect     = true;
1347
-            $this->checkout->redirect_url = add_query_arg(
1348
-                array(
1349
-                    'e_reg_url_link' => $this->checkout->reg_url_link,
1350
-                    'revisit'        => true,
1351
-                ),
1352
-                $this->checkout->thank_you_page_url
1353
-            );
1354
-            $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1355
-            return true;
1356
-        }
1357
-        return false;
1358
-    }
1148
+		$answer_cache_id = $this->checkout->reg_url_link
1149
+			? $form_input . '-' . $registration->reg_url_link()
1150
+			: $form_input;
1151
+		$answer_is_obj   = isset($this->_registration_answers[$answer_cache_id])
1152
+						   && $this->_registration_answers[$answer_cache_id] instanceof EE_Answer
1153
+			? true
1154
+			: false;
1155
+		//rename form_inputs if they are EE_Attendee properties
1156
+		switch ((string) $form_input) {
1157
+			case 'state':
1158
+			case 'STA_ID':
1159
+				$attendee_property = true;
1160
+				$form_input        = 'STA_ID';
1161
+				break;
1162
+
1163
+			case 'country':
1164
+			case 'CNT_ISO':
1165
+				$attendee_property = true;
1166
+				$form_input        = 'CNT_ISO';
1167
+				break;
1168
+
1169
+			default:
1170
+				$ATT_input = 'ATT_' . $form_input;
1171
+				//EEH_Debug_Tools::printr( $ATT_input, '$ATT_input', __FILE__, __LINE__ );
1172
+				$attendee_property = EEM_Attendee::instance()->has_field($ATT_input) ? true : false;
1173
+				$form_input        = $attendee_property ? 'ATT_' . $form_input : $form_input;
1174
+		}
1175
+		// EEH_Debug_Tools::printr( $answer_cache_id, '$answer_cache_id', __FILE__, __LINE__ );
1176
+		// EEH_Debug_Tools::printr( $attendee_property, '$attendee_property', __FILE__, __LINE__ );
1177
+		// EEH_Debug_Tools::printr( $answer_is_obj, '$answer_is_obj', __FILE__, __LINE__ );
1178
+		// if this form input has a corresponding attendee property
1179
+		if ($attendee_property) {
1180
+			$this->_attendee_data[$registration->reg_url_link()][$form_input] = $input_value;
1181
+			if ($answer_is_obj) {
1182
+				// and delete the corresponding answer since we won't be storing this data in that object
1183
+				$registration->_remove_relation_to($this->_registration_answers[$answer_cache_id], 'Answer');
1184
+				$this->_registration_answers[$answer_cache_id]->delete_permanently();
1185
+			}
1186
+			return true;
1187
+		} elseif ($answer_is_obj) {
1188
+			// save this data to the answer object
1189
+			$this->_registration_answers[$answer_cache_id]->set_value($input_value);
1190
+			$result = $this->_registration_answers[$answer_cache_id]->save();
1191
+			return $result !== false ? true : false;
1192
+		} else {
1193
+			foreach ($this->_registration_answers as $answer) {
1194
+				if ($answer instanceof EE_Answer && $answer->question_ID() === $answer_cache_id) {
1195
+					$answer->set_value($input_value);
1196
+					$result = $answer->save();
1197
+					return $result !== false ? true : false;
1198
+				}
1199
+			}
1200
+		}
1201
+		return false;
1202
+	}
1203
+
1204
+
1205
+	/**
1206
+	 *    _verify_critical_attendee_details_are_set
1207
+	 *
1208
+	 * @param string $form_input
1209
+	 * @param string $input_value
1210
+	 * @return boolean
1211
+	 */
1212
+	private function _verify_critical_attendee_details_are_set_and_validate_email(
1213
+		$form_input = '',
1214
+		$input_value = ''
1215
+	) {
1216
+		if (empty($input_value)) {
1217
+			// if the form input isn't marked as being required, then just return
1218
+			if (! isset($this->_required_questions[$form_input]) || ! $this->_required_questions[$form_input]) {
1219
+				return true;
1220
+			}
1221
+			switch ($form_input) {
1222
+				case 'fname':
1223
+					EE_Error::add_error(
1224
+						esc_html__('First Name is a required value.', 'event_espresso'),
1225
+						__FILE__,
1226
+						__FUNCTION__,
1227
+						__LINE__
1228
+					);
1229
+					return false;
1230
+					break;
1231
+				case 'lname':
1232
+					EE_Error::add_error(
1233
+						esc_html__('Last Name is a required value.', 'event_espresso'),
1234
+						__FILE__,
1235
+						__FUNCTION__,
1236
+						__LINE__
1237
+					);
1238
+					return false;
1239
+					break;
1240
+				case 'email':
1241
+					EE_Error::add_error(
1242
+						esc_html__('Please enter a valid email address.', 'event_espresso'),
1243
+						__FILE__,
1244
+						__FUNCTION__,
1245
+						__LINE__
1246
+					);
1247
+					return false;
1248
+					break;
1249
+			}
1250
+		}
1251
+		return true;
1252
+	}
1253
+
1254
+
1255
+	/**
1256
+	 *    _associate_attendee_with_registration
1257
+	 *
1258
+	 * @param EE_Registration $registration
1259
+	 * @param EE_Attendee     $attendee
1260
+	 * @return void
1261
+	 * @throws EE_Error
1262
+	 * @throws RuntimeException
1263
+	 */
1264
+	private function _associate_attendee_with_registration(EE_Registration $registration, EE_Attendee $attendee)
1265
+	{
1266
+		// add relation to attendee
1267
+		$registration->_add_relation_to($attendee, 'Attendee');
1268
+		$registration->set_attendee_id($attendee->ID());
1269
+		$registration->update_cache_after_object_save('Attendee', $attendee);
1270
+	}
1271
+
1272
+
1273
+	/**
1274
+	 *    _associate_registration_with_transaction
1275
+	 *
1276
+	 * @param EE_Registration $registration
1277
+	 * @return void
1278
+	 * @throws \EE_Error
1279
+	 */
1280
+	private function _associate_registration_with_transaction(EE_Registration $registration)
1281
+	{
1282
+		// add relation to registration
1283
+		$this->checkout->transaction->_add_relation_to($registration, 'Registration');
1284
+		$this->checkout->transaction->update_cache_after_object_save('Registration', $registration);
1285
+	}
1286
+
1287
+
1288
+	/**
1289
+	 *    _copy_critical_attendee_details_from_primary_registrant
1290
+	 *    ensures that all attendees at least have data for first name, last name, and email address
1291
+	 *
1292
+	 * @param array $attendee_data
1293
+	 * @return array
1294
+	 * @throws \EE_Error
1295
+	 */
1296
+	private function _copy_critical_attendee_details_from_primary_registrant($attendee_data = array())
1297
+	{
1298
+		// bare minimum critical details include first name, last name, email address
1299
+		$critical_attendee_details = array('ATT_fname', 'ATT_lname', 'ATT_email');
1300
+		// add address info to critical details?
1301
+		if (apply_filters(
1302
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information__merge_address_details_with_critical_attendee_details',
1303
+			false
1304
+		)) {
1305
+			$address_details           = array(
1306
+				'ATT_address',
1307
+				'ATT_address2',
1308
+				'ATT_city',
1309
+				'STA_ID',
1310
+				'CNT_ISO',
1311
+				'ATT_zip',
1312
+				'ATT_phone',
1313
+			);
1314
+			$critical_attendee_details = array_merge($critical_attendee_details, $address_details);
1315
+		}
1316
+		foreach ($critical_attendee_details as $critical_attendee_detail) {
1317
+			if (! isset($attendee_data[$critical_attendee_detail])
1318
+				|| empty($attendee_data[$critical_attendee_detail])
1319
+			) {
1320
+				$attendee_data[$critical_attendee_detail] = $this->checkout->primary_attendee_obj->get(
1321
+					$critical_attendee_detail
1322
+				);
1323
+			}
1324
+		}
1325
+		return $attendee_data;
1326
+	}
1327
+
1328
+
1329
+	/**
1330
+	 *    update_reg_step
1331
+	 *    this is the final step after a user  revisits the site to edit their attendee information
1332
+	 *    this gets called AFTER the process_reg_step() method above
1333
+	 *
1334
+	 * @return bool
1335
+	 * @throws EE_Error
1336
+	 * @throws InvalidArgumentException
1337
+	 * @throws ReflectionException
1338
+	 * @throws RuntimeException
1339
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1340
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1341
+	 */
1342
+	public function update_reg_step()
1343
+	{
1344
+		// save everything
1345
+		if ($this->process_reg_step()) {
1346
+			$this->checkout->redirect     = true;
1347
+			$this->checkout->redirect_url = add_query_arg(
1348
+				array(
1349
+					'e_reg_url_link' => $this->checkout->reg_url_link,
1350
+					'revisit'        => true,
1351
+				),
1352
+				$this->checkout->thank_you_page_url
1353
+			);
1354
+			$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1355
+			return true;
1356
+		}
1357
+		return false;
1358
+	}
1359 1359
 }
Please login to merge, or discard this patch.
Spacing   +51 added lines, -52 removed lines patch added patch discarded remove patch
@@ -48,7 +48,7 @@  discard block
 block discarded – undo
48 48
     {
49 49
         $this->_slug     = 'attendee_information';
50 50
         $this->_name     = esc_html__('Attendee Information', 'event_espresso');
51
-        $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'attendee_info_main.template.php';
51
+        $this->_template = SPCO_REG_STEPS_PATH.$this->_slug.DS.'attendee_info_main.template.php';
52 52
         $this->checkout  = $checkout;
53 53
         $this->_reset_success_message();
54 54
         $this->set_instructions(
@@ -59,11 +59,11 @@  discard block
 block discarded – undo
59 59
 
60 60
     public function translate_js_strings()
61 61
     {
62
-        EE_Registry::$i18n_js_strings['required_field']            = esc_html__(
62
+        EE_Registry::$i18n_js_strings['required_field'] = esc_html__(
63 63
             ' is a required question.',
64 64
             'event_espresso'
65 65
         );
66
-        EE_Registry::$i18n_js_strings['required_multi_field']      = esc_html__(
66
+        EE_Registry::$i18n_js_strings['required_multi_field'] = esc_html__(
67 67
             ' is a required question. Please enter a value for at least one of the options.',
68 68
             'event_espresso'
69 69
         );
@@ -71,18 +71,18 @@  discard block
 block discarded – undo
71 71
             'Please answer all required questions correctly before proceeding.',
72 72
             'event_espresso'
73 73
         );
74
-        EE_Registry::$i18n_js_strings['attendee_info_copied']      = sprintf(
74
+        EE_Registry::$i18n_js_strings['attendee_info_copied'] = sprintf(
75 75
             esc_html__(
76 76
                 'The attendee information was successfully copied.%sPlease ensure the rest of the registration form is completed before proceeding.',
77 77
                 'event_espresso'
78 78
             ),
79 79
             '<br/>'
80 80
         );
81
-        EE_Registry::$i18n_js_strings['attendee_info_copy_error']  = esc_html__(
81
+        EE_Registry::$i18n_js_strings['attendee_info_copy_error'] = esc_html__(
82 82
             'An unknown error occurred on the server while attempting to copy the attendee information. Please refresh the page and try again.',
83 83
             'event_espresso'
84 84
         );
85
-        EE_Registry::$i18n_js_strings['enter_valid_email']         = esc_html__(
85
+        EE_Registry::$i18n_js_strings['enter_valid_email'] = esc_html__(
86 86
             'You must enter a valid email address.',
87 87
             'event_espresso'
88 88
         );
@@ -145,7 +145,7 @@  discard block
 block discarded – undo
145 145
                     && $this->checkout->visit_allows_processing_of_this_registration($registration)
146 146
                 ) {
147 147
                     $subsections[$registration->reg_url_link()] = $this->_registrations_reg_form($registration);
148
-                    if (! $this->checkout->admin_request) {
148
+                    if ( ! $this->checkout->admin_request) {
149 149
                         $template_args['registrations'][$registration->reg_url_link()]    = $registration;
150 150
                         $template_args['ticket_count'][$registration->ticket()->ID()]     = isset(
151 151
                             $template_args['ticket_count'][$registration->ticket()->ID()]
@@ -194,8 +194,7 @@  discard block
 block discarded – undo
194 194
                 'html_id'         => $this->reg_form_name(),
195 195
                 'subsections'     => $subsections,
196 196
                 'layout_strategy' => $this->checkout->admin_request ?
197
-                    new EE_Div_Per_Section_Layout() :
198
-                    new EE_Template_Layout(
197
+                    new EE_Div_Per_Section_Layout() : new EE_Template_Layout(
199 198
                         array(
200 199
                             'layout_template_file' => $this->_template, // layout_template
201 200
                             'template_args'        => $template_args,
@@ -238,7 +237,7 @@  discard block
 block discarded – undo
238 237
             if ($question_groups) {
239 238
                 // array of params to pass to parent constructor
240 239
                 $form_args = array(
241
-                    'html_id'         => 'ee-registration-' . $registration->reg_url_link(),
240
+                    'html_id'         => 'ee-registration-'.$registration->reg_url_link(),
242 241
                     'html_class'      => 'ee-reg-form-attendee-dv',
243 242
                     'html_style'      => $this->checkout->admin_request
244 243
                         ? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;'
@@ -294,7 +293,7 @@  discard block
 block discarded – undo
294 293
         // generate hidden input
295 294
         return new EE_Hidden_Input(
296 295
             array(
297
-                'html_id' => 'additional-attendee-reg-info-' . $registration->reg_url_link(),
296
+                'html_id' => 'additional-attendee-reg-info-'.$registration->reg_url_link(),
298 297
                 'default' => $additional_attendee_reg_info,
299 298
             )
300 299
         );
@@ -314,11 +313,11 @@  discard block
 block discarded – undo
314 313
     {
315 314
         // array of params to pass to parent constructor
316 315
         $form_args = array(
317
-            'html_id'         => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-' . $registration->ID(),
316
+            'html_id'         => 'ee-reg-form-qstn-grp-'.$question_group->identifier().'-'.$registration->ID(),
318 317
             'html_class'      => $this->checkout->admin_request
319 318
                 ? 'form-table ee-reg-form-qstn-grp-dv'
320 319
                 : 'ee-reg-form-qstn-grp-dv',
321
-            'html_label_id'   => 'ee-reg-form-qstn-grp-' . $question_group->identifier() .  '-' . $registration->ID() . '-lbl',
320
+            'html_label_id'   => 'ee-reg-form-qstn-grp-'.$question_group->identifier().'-'.$registration->ID().'-lbl',
322 321
             'subsections'     => array(
323 322
                 'reg_form_qstn_grp_hdr' => $this->_question_group_header($question_group),
324 323
             ),
@@ -329,7 +328,7 @@  discard block
 block discarded – undo
329 328
         // where params
330 329
         $query_params = array('QST_deleted' => 0);
331 330
         // don't load admin only questions on the frontend
332
-        if (! $this->checkout->admin_request) {
331
+        if ( ! $this->checkout->admin_request) {
333 332
             $query_params['QST_admin_only'] = array('!=', true);
334 333
         }
335 334
         $questions = $question_group->get_many_related(
@@ -473,7 +472,7 @@  discard block
 block discarded – undo
473 472
     {
474 473
         return new EE_Form_Section_HTML(
475 474
             EEH_Template::locate_template(
476
-                SPCO_REG_STEPS_PATH . $this->_slug . DS . '_auto_copy_attendee_info.template.php',
475
+                SPCO_REG_STEPS_PATH.$this->_slug.DS.'_auto_copy_attendee_info.template.php',
477 476
                 apply_filters(
478 477
                     'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args',
479 478
                     array()
@@ -505,16 +504,16 @@  discard block
 block discarded – undo
505 504
                 if ($registration->ticket()->ID() !== $prev_ticket) {
506 505
                     $item_name = $registration->ticket()->name();
507 506
                     $item_name .= $registration->ticket()->description() !== ''
508
-                        ? ' - ' . $registration->ticket()->description()
507
+                        ? ' - '.$registration->ticket()->description()
509 508
                         : '';
510
-                    $copy_attendee_info_inputs['spco_copy_attendee_chk[ticket-' . $registration->ticket()->ID() . ']'] =
509
+                    $copy_attendee_info_inputs['spco_copy_attendee_chk[ticket-'.$registration->ticket()->ID().']'] =
511 510
                         new EE_Form_Section_HTML(
512
-                            '<h6 class="spco-copy-attendee-event-hdr">' . $item_name . '</h6>'
511
+                            '<h6 class="spco-copy-attendee-event-hdr">'.$item_name.'</h6>'
513 512
                         );
514 513
                     $prev_ticket = $registration->ticket()->ID();
515 514
                 }
516 515
 
517
-                $copy_attendee_info_inputs['spco_copy_attendee_chk[' . $registration->ID() . ']'] =
516
+                $copy_attendee_info_inputs['spco_copy_attendee_chk['.$registration->ID().']'] =
518 517
                     new EE_Checkbox_Multi_Input(
519 518
                         array(
520 519
                             $registration->ID() => sprintf(
@@ -523,7 +522,7 @@  discard block
 block discarded – undo
523 522
                             ),
524 523
                         ),
525 524
                         array(
526
-                            'html_id'                 => 'spco-copy-attendee-chk-' . $registration->reg_url_link(),
525
+                            'html_id'                 => 'spco-copy-attendee-chk-'.$registration->reg_url_link(),
527 526
                             'html_class'              => 'spco-copy-attendee-chk ee-do-not-validate',
528 527
                             'display_html_label_text' => false,
529 528
                         )
@@ -572,7 +571,7 @@  discard block
 block discarded – undo
572 571
             $registration,
573 572
             $question->system_ID()
574 573
         );
575
-        $answer       = $answer_value === null
574
+        $answer = $answer_value === null
576 575
             ? EEM_Answer::instance()->get_one(
577 576
                 array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
578 577
             )
@@ -589,14 +588,14 @@  discard block
 block discarded – undo
589 588
         }
590 589
         // verify instance
591 590
         if ($answer instanceof EE_Answer) {
592
-            if (! empty($answer_value)) {
591
+            if ( ! empty($answer_value)) {
593 592
                 $answer->set('ANS_value', $answer_value);
594 593
             }
595 594
             $answer->cache('Question', $question);
596 595
             //remember system ID had a bug where sometimes it could be null
597 596
             $answer_cache_id = $question->is_system_question()
598
-                ? $question->system_ID() . '-' . $registration->reg_url_link()
599
-                : $question->ID() . '-' . $registration->reg_url_link();
597
+                ? $question->system_ID().'-'.$registration->reg_url_link()
598
+                : $question->ID().'-'.$registration->reg_url_link();
600 599
             $registration->cache('Answer', $answer, $answer_cache_id);
601 600
         }
602 601
         return $this->_generate_question_input($registration, $question, $answer);
@@ -628,18 +627,18 @@  discard block
 block discarded – undo
628 627
             10,
629 628
             4
630 629
         );
631
-        $input_constructor_args                  = array(
632
-            'html_name'        => 'ee_reg_qstn[' . $registration->ID() . '][' . $identifier . ']',
633
-            'html_id'          => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
634
-            'html_class'       => 'ee-reg-qstn ee-reg-qstn-' . $identifier,
635
-            'html_label_id'    => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
630
+        $input_constructor_args = array(
631
+            'html_name'        => 'ee_reg_qstn['.$registration->ID().']['.$identifier.']',
632
+            'html_id'          => 'ee_reg_qstn-'.$registration->ID().'-'.$identifier,
633
+            'html_class'       => 'ee-reg-qstn ee-reg-qstn-'.$identifier,
634
+            'html_label_id'    => 'ee_reg_qstn-'.$registration->ID().'-'.$identifier,
636 635
             'html_label_class' => 'ee-reg-qstn',
637 636
         );
638 637
         $input_constructor_args['html_label_id'] .= '-lbl';
639 638
         if ($answer instanceof EE_Answer && $answer->ID()) {
640
-            $input_constructor_args['html_name']     .= '[' . $answer->ID() . ']';
641
-            $input_constructor_args['html_id']       .= '-' . $answer->ID();
642
-            $input_constructor_args['html_label_id'] .= '-' . $answer->ID();
639
+            $input_constructor_args['html_name']     .= '['.$answer->ID().']';
640
+            $input_constructor_args['html_id']       .= '-'.$answer->ID();
641
+            $input_constructor_args['html_label_id'] .= '-'.$answer->ID();
643 642
         }
644 643
         $form_input = $question->generate_form_input(
645 644
             $registration,
@@ -682,7 +681,7 @@  discard block
 block discarded – undo
682 681
         $countries = $this->checkout->action === 'process_reg_step'
683 682
             ? EEM_Country::instance()->get_all_countries()
684 683
             : EEM_Country::instance()->get_all_active_countries();
685
-        if (! empty($countries)) {
684
+        if ( ! empty($countries)) {
686 685
             foreach ($countries as $country) {
687 686
                 if ($country instanceof EE_Country) {
688 687
                     $country_options[$country->ID()] = $country->name();
@@ -732,7 +731,7 @@  discard block
 block discarded – undo
732 731
         $states        = $this->checkout->action === 'process_reg_step'
733 732
             ? EEM_State::instance()->get_all_states()
734 733
             : EEM_State::instance()->get_all_active_states();
735
-        if (! empty($states)) {
734
+        if ( ! empty($states)) {
736 735
             foreach ($states as $state) {
737 736
                 if ($state instanceof EE_State) {
738 737
                     $state_options[$state->country()->name()][$state->ID()] = $state->name();
@@ -784,7 +783,7 @@  discard block
 block discarded – undo
784 783
             );
785 784
             return false;
786 785
         }
787
-        if (! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
786
+        if ( ! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
788 787
             EE_Error::add_error(
789 788
                 esc_html__(
790 789
                     'A valid transaction could not be initiated for processing your registrations.',
@@ -801,10 +800,10 @@  discard block
 block discarded – undo
801 800
         // verify we got the goods
802 801
         if (empty($registrations)) {
803 802
             //combine the old translated string with a new one, in order to not break translations
804
-            $error_message = esc_html__( 'Your form data could not be applied to any valid registrations.', 'event_espresso' )
803
+            $error_message = esc_html__('Your form data could not be applied to any valid registrations.', 'event_espresso')
805 804
                              . sprintf(
806 805
                                  esc_html__('%3$sThis can sometimes happen if too much time has been taken to complete the registration process.%3$sPlease return to the %1$sEvent List%2$s and reselect your tickets. If the problem continues, please contact the site administrator.', 'event_espresso'),
807
-                                 '<a href="' . get_post_type_archive_link('espresso_events') . '" >',
806
+                                 '<a href="'.get_post_type_archive_link('espresso_events').'" >',
808 807
                                  '</a>',
809 808
                                  '<br />'
810 809
                              );
@@ -823,7 +822,7 @@  discard block
 block discarded – undo
823 822
         if ($registrations_processed === false) {
824 823
             // but return immediately if the previous step exited early due to errors
825 824
             return false;
826
-        } elseif (! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
825
+        } elseif ( ! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
827 826
             // generate a correctly translated string for all possible singular/plural combinations
828 827
             if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) {
829 828
                 $error_msg = sprintf(
@@ -904,7 +903,7 @@  discard block
 block discarded – undo
904 903
         // grab the saved registrations from the transaction
905 904
         foreach ($registrations as $registration) {
906 905
             // verify EE_Registration object
907
-            if (! $registration instanceof EE_Registration) {
906
+            if ( ! $registration instanceof EE_Registration) {
908 907
                 EE_Error::add_error(
909 908
                     esc_html__(
910 909
                         'An invalid Registration object was discovered when attempting to process your registration information.',
@@ -919,12 +918,12 @@  discard block
 block discarded – undo
919 918
             /** @var string $reg_url_link */
920 919
             $reg_url_link = $registration->reg_url_link();
921 920
             // reg_url_link exists ?
922
-            if (! empty($reg_url_link)) {
921
+            if ( ! empty($reg_url_link)) {
923 922
                 // should this registration be processed during this visit ?
924 923
                 if ($this->checkout->visit_allows_processing_of_this_registration($registration)) {
925 924
                     // if NOT revisiting, then let's save the registration now,
926 925
                     // so that we have a REG_ID to use when generating other objects
927
-                    if (! $this->checkout->revisit) {
926
+                    if ( ! $this->checkout->revisit) {
928 927
                         $registration->save();
929 928
                     }
930 929
                     /**
@@ -959,7 +958,7 @@  discard block
 block discarded – undo
959 958
                             ? true
960 959
                             : false;
961 960
                         // filter form input data for this registration
962
-                        $valid_data[$reg_url_link] = (array)apply_filters(
961
+                        $valid_data[$reg_url_link] = (array) apply_filters(
963 962
                             'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item',
964 963
                             $valid_data[$reg_url_link]
965 964
                         );
@@ -971,11 +970,11 @@  discard block
 block discarded – undo
971 970
                         }
972 971
                         // now loop through our array of valid post data && process attendee reg forms
973 972
                         foreach ($valid_data[$reg_url_link] as $form_section => $form_inputs) {
974
-                            if (! in_array($form_section, $non_input_form_sections)) {
973
+                            if ( ! in_array($form_section, $non_input_form_sections)) {
975 974
                                 foreach ($form_inputs as $form_input => $input_value) {
976 975
                                     // \EEH_Debug_Tools::printr( $input_value, $form_input, __FILE__, __LINE__ );
977 976
                                     // check for critical inputs
978
-                                    if (! $this->_verify_critical_attendee_details_are_set_and_validate_email(
977
+                                    if ( ! $this->_verify_critical_attendee_details_are_set_and_validate_email(
979 978
                                         $form_input,
980 979
                                         $input_value
981 980
                                     )
@@ -995,7 +994,7 @@  discard block
 block discarded – undo
995 994
                                         $input_value = $primary_registrant[$form_input];
996 995
                                     }
997 996
                                     // now attempt to save the input data
998
-                                    if (! $this->_save_registration_form_input(
997
+                                    if ( ! $this->_save_registration_form_input(
999 998
                                         $registration,
1000 999
                                         $form_input,
1001 1000
                                         $input_value
@@ -1051,7 +1050,7 @@  discard block
 block discarded – undo
1051 1050
                     // add relation to registration, set attendee ID, and cache attendee
1052 1051
                     $this->_associate_attendee_with_registration($registration, $attendee);
1053 1052
                     // \EEH_Debug_Tools::printr( $registration, '$registration', __FILE__, __LINE__ );
1054
-                    if (! $registration->attendee() instanceof EE_Attendee) {
1053
+                    if ( ! $registration->attendee() instanceof EE_Attendee) {
1055 1054
                         EE_Error::add_error(
1056 1055
                             sprintf(
1057 1056
                                 esc_html__(
@@ -1146,7 +1145,7 @@  discard block
 block discarded – undo
1146 1145
          * @see https://events.codebasehq.com/projects/event-espresso/tickets/10477
1147 1146
          */
1148 1147
         $answer_cache_id = $this->checkout->reg_url_link
1149
-            ? $form_input . '-' . $registration->reg_url_link()
1148
+            ? $form_input.'-'.$registration->reg_url_link()
1150 1149
             : $form_input;
1151 1150
         $answer_is_obj   = isset($this->_registration_answers[$answer_cache_id])
1152 1151
                            && $this->_registration_answers[$answer_cache_id] instanceof EE_Answer
@@ -1167,10 +1166,10 @@  discard block
 block discarded – undo
1167 1166
                 break;
1168 1167
 
1169 1168
             default:
1170
-                $ATT_input = 'ATT_' . $form_input;
1169
+                $ATT_input = 'ATT_'.$form_input;
1171 1170
                 //EEH_Debug_Tools::printr( $ATT_input, '$ATT_input', __FILE__, __LINE__ );
1172 1171
                 $attendee_property = EEM_Attendee::instance()->has_field($ATT_input) ? true : false;
1173
-                $form_input        = $attendee_property ? 'ATT_' . $form_input : $form_input;
1172
+                $form_input        = $attendee_property ? 'ATT_'.$form_input : $form_input;
1174 1173
         }
1175 1174
         // EEH_Debug_Tools::printr( $answer_cache_id, '$answer_cache_id', __FILE__, __LINE__ );
1176 1175
         // EEH_Debug_Tools::printr( $attendee_property, '$attendee_property', __FILE__, __LINE__ );
@@ -1215,7 +1214,7 @@  discard block
 block discarded – undo
1215 1214
     ) {
1216 1215
         if (empty($input_value)) {
1217 1216
             // if the form input isn't marked as being required, then just return
1218
-            if (! isset($this->_required_questions[$form_input]) || ! $this->_required_questions[$form_input]) {
1217
+            if ( ! isset($this->_required_questions[$form_input]) || ! $this->_required_questions[$form_input]) {
1219 1218
                 return true;
1220 1219
             }
1221 1220
             switch ($form_input) {
@@ -1302,7 +1301,7 @@  discard block
 block discarded – undo
1302 1301
             'FHEE__EE_SPCO_Reg_Step_Attendee_Information__merge_address_details_with_critical_attendee_details',
1303 1302
             false
1304 1303
         )) {
1305
-            $address_details           = array(
1304
+            $address_details = array(
1306 1305
                 'ATT_address',
1307 1306
                 'ATT_address2',
1308 1307
                 'ATT_city',
@@ -1314,7 +1313,7 @@  discard block
 block discarded – undo
1314 1313
             $critical_attendee_details = array_merge($critical_attendee_details, $address_details);
1315 1314
         }
1316 1315
         foreach ($critical_attendee_details as $critical_attendee_detail) {
1317
-            if (! isset($attendee_data[$critical_attendee_detail])
1316
+            if ( ! isset($attendee_data[$critical_attendee_detail])
1318 1317
                 || empty($attendee_data[$critical_attendee_detail])
1319 1318
             ) {
1320 1319
                 $attendee_data[$critical_attendee_detail] = $this->checkout->primary_attendee_obj->get(
Please login to merge, or discard this patch.
core/services/request/middleware/RecommendedVersions.php 2 patches
Indentation   +175 added lines, -175 removed lines patch added patch discarded remove patch
@@ -23,186 +23,186 @@
 block discarded – undo
23 23
 class RecommendedVersions extends Middleware
24 24
 {
25 25
 
26
-    /**
27
-     * converts a Request to a Response
28
-     *
29
-     * @param RequestInterface $request
30
-     * @param ResponseInterface      $response
31
-     * @return ResponseInterface
32
-     * @throws InvalidDataTypeException
33
-     */
34
-    public function handleRequest(RequestInterface $request, ResponseInterface $response)
35
-    {
36
-        $this->request  = $request;
37
-        $this->response = $response;
38
-        // check required WP version
39
-        if (! $this->minimumWordPressVersionRequired()) {
40
-            $this->request->unSetRequestParam('activate', true);
41
-            add_action('admin_notices', array($this, 'minimum_wp_version_error'), 1);
42
-            $this->response->terminateRequest();
43
-            $this->response->deactivatePlugin();
44
-        }
45
-        // check recommended PHP version
46
-        if (! $this->minimumPhpVersionRecommended()) {
47
-            $this->displayMinimumRecommendedPhpVersionNotice();
48
-        }
49
-        //upcoming required version
50
-        if (! $this->upcomingRequiredPhpVersion()) {
51
-            $this->displayUpcomingRequiredVersion();
52
-        }
53
-        $this->response = $this->processRequestStack($this->request, $this->response);
54
-        return $this->response;
55
-    }
56
-
57
-
58
-    /**
59
-     * Helper method to assess installed wp version against given values.
60
-     * By default this compares the required minimum version of WP for EE against the installed version of WP
61
-     * Note, $wp_version is the first parameter sent into the PHP version_compare function (what is being checked
62
-     * against) so consider that when sending in your values.
63
-     *
64
-     * @param string $version_to_check
65
-     * @param string $operator
66
-     * @return bool
67
-     */
68
-    public static function compareWordPressVersion($version_to_check = EE_MIN_WP_VER_REQUIRED, $operator = '>=')
69
-    {
70
-        global $wp_version;
71
-        return version_compare(
72
-        // first account for wp_version being pre-release
73
-        // (like RC, beta etc) which are usually in the format like 4.7-RC3-39519
74
-            strpos($wp_version, '-') > 0
75
-                ? substr($wp_version, 0, strpos($wp_version, '-'))
76
-                : $wp_version,
77
-            $version_to_check,
78
-            $operator
79
-        );
80
-    }
81
-
82
-
83
-
84
-    /**
85
-     * @return boolean
86
-     */
87
-    private function minimumWordPressVersionRequired()
88
-    {
89
-        return RecommendedVersions::compareWordPressVersion();
90
-    }
91
-
92
-
93
-
94
-    /**
95
-     * @param string $min_version
96
-     * @return boolean
97
-     */
98
-    private function checkPhpVersion($min_version = EE_MIN_PHP_VER_RECOMMENDED)
99
-    {
100
-        return version_compare(PHP_VERSION, $min_version, '>=') ? true : false;
101
-    }
102
-
103
-
104
-
105
-    /**
106
-     * @return boolean
107
-     */
108
-    private function minimumPhpVersionRecommended()
109
-    {
110
-        return $this->checkPhpVersion();
111
-    }
112
-
113
-
114
-
115
-    /**
116
-     * @return void
117
-     */
118
-    public function minimumWpVersionError()
119
-    {
120
-        global $wp_version;
121
-        ?>
26
+	/**
27
+	 * converts a Request to a Response
28
+	 *
29
+	 * @param RequestInterface $request
30
+	 * @param ResponseInterface      $response
31
+	 * @return ResponseInterface
32
+	 * @throws InvalidDataTypeException
33
+	 */
34
+	public function handleRequest(RequestInterface $request, ResponseInterface $response)
35
+	{
36
+		$this->request  = $request;
37
+		$this->response = $response;
38
+		// check required WP version
39
+		if (! $this->minimumWordPressVersionRequired()) {
40
+			$this->request->unSetRequestParam('activate', true);
41
+			add_action('admin_notices', array($this, 'minimum_wp_version_error'), 1);
42
+			$this->response->terminateRequest();
43
+			$this->response->deactivatePlugin();
44
+		}
45
+		// check recommended PHP version
46
+		if (! $this->minimumPhpVersionRecommended()) {
47
+			$this->displayMinimumRecommendedPhpVersionNotice();
48
+		}
49
+		//upcoming required version
50
+		if (! $this->upcomingRequiredPhpVersion()) {
51
+			$this->displayUpcomingRequiredVersion();
52
+		}
53
+		$this->response = $this->processRequestStack($this->request, $this->response);
54
+		return $this->response;
55
+	}
56
+
57
+
58
+	/**
59
+	 * Helper method to assess installed wp version against given values.
60
+	 * By default this compares the required minimum version of WP for EE against the installed version of WP
61
+	 * Note, $wp_version is the first parameter sent into the PHP version_compare function (what is being checked
62
+	 * against) so consider that when sending in your values.
63
+	 *
64
+	 * @param string $version_to_check
65
+	 * @param string $operator
66
+	 * @return bool
67
+	 */
68
+	public static function compareWordPressVersion($version_to_check = EE_MIN_WP_VER_REQUIRED, $operator = '>=')
69
+	{
70
+		global $wp_version;
71
+		return version_compare(
72
+		// first account for wp_version being pre-release
73
+		// (like RC, beta etc) which are usually in the format like 4.7-RC3-39519
74
+			strpos($wp_version, '-') > 0
75
+				? substr($wp_version, 0, strpos($wp_version, '-'))
76
+				: $wp_version,
77
+			$version_to_check,
78
+			$operator
79
+		);
80
+	}
81
+
82
+
83
+
84
+	/**
85
+	 * @return boolean
86
+	 */
87
+	private function minimumWordPressVersionRequired()
88
+	{
89
+		return RecommendedVersions::compareWordPressVersion();
90
+	}
91
+
92
+
93
+
94
+	/**
95
+	 * @param string $min_version
96
+	 * @return boolean
97
+	 */
98
+	private function checkPhpVersion($min_version = EE_MIN_PHP_VER_RECOMMENDED)
99
+	{
100
+		return version_compare(PHP_VERSION, $min_version, '>=') ? true : false;
101
+	}
102
+
103
+
104
+
105
+	/**
106
+	 * @return boolean
107
+	 */
108
+	private function minimumPhpVersionRecommended()
109
+	{
110
+		return $this->checkPhpVersion();
111
+	}
112
+
113
+
114
+
115
+	/**
116
+	 * @return void
117
+	 */
118
+	public function minimumWpVersionError()
119
+	{
120
+		global $wp_version;
121
+		?>
122 122
         <div class="error">
123 123
             <p>
124 124
                 <?php
125
-                printf(
126
-                    __('We\'re sorry, but Event Espresso requires WordPress version %1$s or greater in order to operate. You are currently running version %2$s.%3$sFor information on how to update your version of WordPress, please go to %4$s.',
127
-                        'event_espresso'),
128
-                    EE_MIN_WP_VER_REQUIRED,
129
-                    $wp_version,
130
-                    '<br/>',
131
-                    '<a href="http://codex.wordpress.org/Updating_WordPress">http://codex.wordpress.org/Updating_WordPress</a>'
132
-                );
133
-                ?>
125
+				printf(
126
+					__('We\'re sorry, but Event Espresso requires WordPress version %1$s or greater in order to operate. You are currently running version %2$s.%3$sFor information on how to update your version of WordPress, please go to %4$s.',
127
+						'event_espresso'),
128
+					EE_MIN_WP_VER_REQUIRED,
129
+					$wp_version,
130
+					'<br/>',
131
+					'<a href="http://codex.wordpress.org/Updating_WordPress">http://codex.wordpress.org/Updating_WordPress</a>'
132
+				);
133
+				?>
134 134
             </p>
135 135
         </div>
136 136
         <?php
137
-    }
138
-
139
-
140
-
141
-    /**
142
-     *    _display_minimum_recommended_php_version_notice
143
-     *
144
-     * @access private
145
-     * @return void
146
-     * @throws InvalidDataTypeException
147
-     */
148
-    private function displayMinimumRecommendedPhpVersionNotice()
149
-    {
150
-        if ($this->request->isAdmin()) {
151
-            new PersistentAdminNotice(
152
-                'php_version_' . str_replace('.', '-', EE_MIN_PHP_VER_RECOMMENDED) . '_recommended',
153
-                sprintf(
154
-                    esc_html__(
155
-                        'Event Espresso recommends PHP version %1$s or greater for optimal performance. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
156
-                        'event_espresso'
157
-                    ),
158
-                    EE_MIN_PHP_VER_RECOMMENDED,
159
-                    PHP_VERSION,
160
-                    '<br/>',
161
-                    '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
162
-                )
163
-            );
164
-        }
165
-    }
166
-
167
-
168
-    /**
169
-     * Returns whether the provided php version number is greater than the current version of php installed on the server.
170
-     *
171
-     * @param string $version_required
172
-     * @return bool
173
-     */
174
-    private function upcomingRequiredPhpVersion($version_required = '5.5')
175
-    {
176
-        return $this->checkPhpVersion($version_required);
177
-    }
178
-
179
-
180
-    /**
181
-     *  Sets a notice for an upcoming required version of PHP in the next update of EE core.
182
-     */
183
-    private function displayUpcomingRequiredVersion()
184
-    {
185
-        if ($this->request->isAdmin()
186
-            && apply_filters('FHEE__EE_Recommended_Versions__displayUpcomingRequiredVersion', true, $this->request)
187
-            && current_user_can('update_plugins')
188
-        ) {
189
-            add_action('admin_notices', function ()
190
-            {
191
-                echo '<div class="notice event-espresso-admin-notice notice-warning"><p>'
192
-                     . sprintf(
193
-                         esc_html__(
194
-                             'Please note: The next update of Event Espresso 4 will %1$srequire%2$s PHP 5.4.45 or greater.  Your web server\'s PHP version is %3$s.  You can contact your host and ask them to update your PHP version to at least PHP 5.6.  Please do not update to the new version of Event Espresso 4 until the PHP update is completed. Read about why keeping your server on the latest version of PHP is a good idea %4$shere%5$s',
195
-                             'event_espresso'
196
-                         ),
197
-                         '<strong>',
198
-                         '</strong>',
199
-                         PHP_VERSION,
200
-                         '<a href="https://wordpress.org/support/upgrade-php/">',
201
-                         '</a>'
202
-                     )
203
-                     . '</p></div>';
204
-            });
205
-        }
206
-    }
137
+	}
138
+
139
+
140
+
141
+	/**
142
+	 *    _display_minimum_recommended_php_version_notice
143
+	 *
144
+	 * @access private
145
+	 * @return void
146
+	 * @throws InvalidDataTypeException
147
+	 */
148
+	private function displayMinimumRecommendedPhpVersionNotice()
149
+	{
150
+		if ($this->request->isAdmin()) {
151
+			new PersistentAdminNotice(
152
+				'php_version_' . str_replace('.', '-', EE_MIN_PHP_VER_RECOMMENDED) . '_recommended',
153
+				sprintf(
154
+					esc_html__(
155
+						'Event Espresso recommends PHP version %1$s or greater for optimal performance. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
156
+						'event_espresso'
157
+					),
158
+					EE_MIN_PHP_VER_RECOMMENDED,
159
+					PHP_VERSION,
160
+					'<br/>',
161
+					'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
162
+				)
163
+			);
164
+		}
165
+	}
166
+
167
+
168
+	/**
169
+	 * Returns whether the provided php version number is greater than the current version of php installed on the server.
170
+	 *
171
+	 * @param string $version_required
172
+	 * @return bool
173
+	 */
174
+	private function upcomingRequiredPhpVersion($version_required = '5.5')
175
+	{
176
+		return $this->checkPhpVersion($version_required);
177
+	}
178
+
179
+
180
+	/**
181
+	 *  Sets a notice for an upcoming required version of PHP in the next update of EE core.
182
+	 */
183
+	private function displayUpcomingRequiredVersion()
184
+	{
185
+		if ($this->request->isAdmin()
186
+			&& apply_filters('FHEE__EE_Recommended_Versions__displayUpcomingRequiredVersion', true, $this->request)
187
+			&& current_user_can('update_plugins')
188
+		) {
189
+			add_action('admin_notices', function ()
190
+			{
191
+				echo '<div class="notice event-espresso-admin-notice notice-warning"><p>'
192
+					 . sprintf(
193
+						 esc_html__(
194
+							 'Please note: The next update of Event Espresso 4 will %1$srequire%2$s PHP 5.4.45 or greater.  Your web server\'s PHP version is %3$s.  You can contact your host and ask them to update your PHP version to at least PHP 5.6.  Please do not update to the new version of Event Espresso 4 until the PHP update is completed. Read about why keeping your server on the latest version of PHP is a good idea %4$shere%5$s',
195
+							 'event_espresso'
196
+						 ),
197
+						 '<strong>',
198
+						 '</strong>',
199
+						 PHP_VERSION,
200
+						 '<a href="https://wordpress.org/support/upgrade-php/">',
201
+						 '</a>'
202
+					 )
203
+					 . '</p></div>';
204
+			});
205
+		}
206
+	}
207 207
 }
208 208
 // Location: RecommendedVersions.php
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -36,18 +36,18 @@  discard block
 block discarded – undo
36 36
         $this->request  = $request;
37 37
         $this->response = $response;
38 38
         // check required WP version
39
-        if (! $this->minimumWordPressVersionRequired()) {
39
+        if ( ! $this->minimumWordPressVersionRequired()) {
40 40
             $this->request->unSetRequestParam('activate', true);
41 41
             add_action('admin_notices', array($this, 'minimum_wp_version_error'), 1);
42 42
             $this->response->terminateRequest();
43 43
             $this->response->deactivatePlugin();
44 44
         }
45 45
         // check recommended PHP version
46
-        if (! $this->minimumPhpVersionRecommended()) {
46
+        if ( ! $this->minimumPhpVersionRecommended()) {
47 47
             $this->displayMinimumRecommendedPhpVersionNotice();
48 48
         }
49 49
         //upcoming required version
50
-        if (! $this->upcomingRequiredPhpVersion()) {
50
+        if ( ! $this->upcomingRequiredPhpVersion()) {
51 51
             $this->displayUpcomingRequiredVersion();
52 52
         }
53 53
         $this->response = $this->processRequestStack($this->request, $this->response);
@@ -149,7 +149,7 @@  discard block
 block discarded – undo
149 149
     {
150 150
         if ($this->request->isAdmin()) {
151 151
             new PersistentAdminNotice(
152
-                'php_version_' . str_replace('.', '-', EE_MIN_PHP_VER_RECOMMENDED) . '_recommended',
152
+                'php_version_'.str_replace('.', '-', EE_MIN_PHP_VER_RECOMMENDED).'_recommended',
153 153
                 sprintf(
154 154
                     esc_html__(
155 155
                         'Event Espresso recommends PHP version %1$s or greater for optimal performance. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
@@ -186,7 +186,7 @@  discard block
 block discarded – undo
186 186
             && apply_filters('FHEE__EE_Recommended_Versions__displayUpcomingRequiredVersion', true, $this->request)
187 187
             && current_user_can('update_plugins')
188 188
         ) {
189
-            add_action('admin_notices', function ()
189
+            add_action('admin_notices', function()
190 190
             {
191 191
                 echo '<div class="notice event-espresso-admin-notice notice-warning"><p>'
192 192
                      . sprintf(
Please login to merge, or discard this patch.