Completed
Branch BUG-10608-primary-registration... (c40aa6)
by
unknown
65:42 queued 53:47
created
espresso_ticket_selector/EES_Espresso_Ticket_Selector.shortcode.php 1 patch
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -50,8 +50,8 @@  discard block
 block discarded – undo
50 50
 	 * @access    public
51 51
 	 * @param \WP $WP
52 52
 	 */
53
-	public function run( WP $WP ) {
54
-		add_filter( 'FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true' );
53
+	public function run(WP $WP) {
54
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
55 55
 	}
56 56
 
57 57
 
@@ -62,14 +62,14 @@  discard block
 block discarded – undo
62 62
 	 *  @param		array 	$attributes
63 63
 	 *  @return 	string
64 64
 	 */
65
-	public function process_shortcode( $attributes = array() ) {
66
-		extract( $attributes );
67
-		$event_id = isset( $event_id ) ? $event_id : 0;
68
-		$event = EE_Registry::instance()->load_model( 'Event' )->get_one_by_ID( $event_id );
65
+	public function process_shortcode($attributes = array()) {
66
+		extract($attributes);
67
+		$event_id = isset($event_id) ? $event_id : 0;
68
+		$event = EE_Registry::instance()->load_model('Event')->get_one_by_ID($event_id);
69 69
 		ob_start();
70
-		do_action( 'AHEE__EES_Espresso_Ticket_Selector__process_shortcode__begin', $event_id );
71
-		espresso_ticket_selector( $event );
72
-		do_action( 'AHEE__EES_Espresso_Ticket_Selector__process_shortcode__end', $event_id );
70
+		do_action('AHEE__EES_Espresso_Ticket_Selector__process_shortcode__begin', $event_id);
71
+		espresso_ticket_selector($event);
72
+		do_action('AHEE__EES_Espresso_Ticket_Selector__process_shortcode__end', $event_id);
73 73
 		return ob_get_clean();
74 74
 	}
75 75
 
Please login to merge, or discard this patch.
core/libraries/form_sections/base/EE_Form_Section_Proper.form.php 1 patch
Indentation   +1380 added lines, -1380 removed lines patch added patch discarded remove patch
@@ -11,1386 +11,1386 @@
 block discarded – undo
11 11
 class EE_Form_Section_Proper extends EE_Form_Section_Validatable
12 12
 {
13 13
 
14
-    const SUBMITTED_FORM_DATA_SSN_KEY = 'submitted_form_data';
15
-
16
-    /**
17
-     * Subsections
18
-     *
19
-     * @var EE_Form_Section_Validatable[]
20
-     */
21
-    protected $_subsections = array();
22
-
23
-    /**
24
-     * Strategy for laying out the form
25
-     *
26
-     * @var EE_Form_Section_Layout_Base
27
-     */
28
-    protected $_layout_strategy;
29
-
30
-    /**
31
-     * Whether or not this form has received and validated a form submission yet
32
-     *
33
-     * @var boolean
34
-     */
35
-    protected $_received_submission = false;
36
-
37
-    /**
38
-     * message displayed to users upon successful form submission
39
-     *
40
-     * @var string
41
-     */
42
-    protected $_form_submission_success_message = '';
43
-
44
-    /**
45
-     * message displayed to users upon unsuccessful form submission
46
-     *
47
-     * @var string
48
-     */
49
-    protected $_form_submission_error_message = '';
50
-
51
-    /**
52
-     * Stores all the data that will localized for form validation
53
-     *
54
-     * @var array
55
-     */
56
-    static protected $_js_localization = array();
57
-
58
-    /**
59
-     * whether or not the form's localized validation JS vars have been set
60
-     *
61
-     * @type boolean
62
-     */
63
-    static protected $_scripts_localized = false;
64
-
65
-
66
-
67
-    /**
68
-     * when constructing a proper form section, calls _construct_finalize on children
69
-     * so that they know who their parent is, and what name they've been given.
70
-     *
71
-     * @param array $options_array   {
72
-     * @type        $subsections     EE_Form_Section_Validatable[] where keys are the section's name
73
-     * @type        $include         string[] numerically-indexed where values are section names to be included,
74
-     *                               and in that order. This is handy if you want
75
-     *                               the subsections to be ordered differently than the default, and if you override
76
-     *                               which fields are shown
77
-     * @type        $exclude         string[] values are subsections to be excluded. This is handy if you want
78
-     *                               to remove certain default subsections (note: if you specify BOTH 'include' AND
79
-     *                               'exclude', the inclusions will be applied first, and the exclusions will exclude
80
-     *                               items from that list of inclusions)
81
-     * @type        $layout_strategy EE_Form_Section_Layout_Base strategy for laying out the form
82
-     *                               } @see EE_Form_Section_Validatable::__construct()
83
-     * @throws \EE_Error
84
-     */
85
-    public function __construct($options_array = array())
86
-    {
87
-        $options_array = (array)apply_filters('FHEE__EE_Form_Section_Proper___construct__options_array', $options_array,
88
-            $this);
89
-        //call parent first, as it may be setting the name
90
-        parent::__construct($options_array);
91
-        //if they've included subsections in the constructor, add them now
92
-        if (isset($options_array['include'])) {
93
-            //we are going to make sure we ONLY have those subsections to include
94
-            //AND we are going to make sure they're in that specified order
95
-            $reordered_subsections = array();
96
-            foreach ($options_array['include'] as $input_name) {
97
-                if (isset($this->_subsections[$input_name])) {
98
-                    $reordered_subsections[$input_name] = $this->_subsections[$input_name];
99
-                }
100
-            }
101
-            $this->_subsections = $reordered_subsections;
102
-        }
103
-        if (isset($options_array['exclude'])) {
104
-            $exclude = $options_array['exclude'];
105
-            $this->_subsections = array_diff_key($this->_subsections, array_flip($exclude));
106
-        }
107
-        if (isset($options_array['layout_strategy'])) {
108
-            $this->_layout_strategy = $options_array['layout_strategy'];
109
-        }
110
-        if (! $this->_layout_strategy) {
111
-            $this->_layout_strategy = is_admin() ? new EE_Admin_Two_Column_Layout() : new EE_Two_Column_Layout();
112
-        }
113
-        $this->_layout_strategy->_construct_finalize($this);
114
-        //ok so we are definitely going to want the forms JS,
115
-        //so enqueue it or remember to enqueue it during wp_enqueue_scripts
116
-        if (did_action('wp_enqueue_scripts') || did_action('admin_enqueue_scripts')) {
117
-            //ok so they've constructed this object after when they should have.
118
-            //just enqueue the generic form scripts and initialize the form immediately in the JS
119
-            \EE_Form_Section_Proper::wp_enqueue_scripts(true);
120
-        } else {
121
-            add_action('wp_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
122
-            add_action('admin_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
123
-        }
124
-        add_action('wp_footer', array($this, 'ensure_scripts_localized'), 1);
125
-
126
-        /**
127
-         * Gives other plugins a chance to hook in before construct finalize is called. The form probably doesn't
128
-         * yet have a parent form section. Since 4.9.32, when this action was introduced, this is the best place to
129
-         * add a subsection onto a form, assuming you don't care what the form section's name, HTML ID, or HTML name etc are.
130
-         * Also see AHEE__EE_Form_Section_Proper___construct_finalize__end
131
-         * @since 4.9.32
132
-         * @param EE_Form_Section_Proper $this before __construct is done, but all of its logic, except maybe calling
133
-         *                                      _construct_finalize has been done
134
-         * @param array $options_array options passed into the constructor
135
-         */
136
-        do_action('AHEE__EE_Form_Input_Base___construct__before_construct_finalize_called', $this, $options_array);
137
-
138
-        if (isset($options_array['name'])) {
139
-            $this->_construct_finalize(null, $options_array['name']);
140
-        }
141
-    }
142
-
143
-
144
-
145
-    /**
146
-     * Finishes construction given the parent form section and this form section's name
147
-     *
148
-     * @param EE_Form_Section_Proper $parent_form_section
149
-     * @param string                 $name
150
-     * @throws \EE_Error
151
-     */
152
-    public function _construct_finalize($parent_form_section, $name)
153
-    {
154
-        parent::_construct_finalize($parent_form_section, $name);
155
-        $this->_set_default_name_if_empty();
156
-        $this->_set_default_html_id_if_empty();
157
-        foreach ($this->_subsections as $subsection_name => $subsection) {
158
-            if ($subsection instanceof EE_Form_Section_Base) {
159
-                $subsection->_construct_finalize($this, $subsection_name);
160
-            } else {
161
-                throw new EE_Error(
162
-                    sprintf(
163
-                        __('Subsection "%s" is not an instanceof EE_Form_Section_Base on form "%s". It is a "%s"',
164
-                            'event_espresso'),
165
-                        $subsection_name,
166
-                        get_class($this),
167
-                        $subsection ? get_class($subsection) : __('NULL', 'event_espresso')
168
-                    )
169
-                );
170
-            }
171
-        }
172
-        /**
173
-         * Action performed just after form has been given a name (and HTML ID etc) and is fully constructed.
174
-         * If you have code that should modify the form and needs it and its subsections to have a name, HTML ID (or other attributes derived
175
-         * from the name like the HTML label id, etc), this is where it should be done.
176
-         * This might only happen just before displaying the form, or just before it receives form submission data.
177
-         * If you need to modify the form or its subsections before _construct_finalize is called on it (and we've
178
-         * ensured it has a name, HTML IDs, etc
179
-         * @param EE_Form_Section_Proper $this
180
-         * @param EE_Form_Section_Proper|null $parent_form_section
181
-         * @param string $name
182
-         */
183
-        do_action('AHEE__EE_Form_Section_Proper___construct_finalize__end', $this, $parent_form_section, $name);
184
-    }
185
-
186
-
187
-
188
-    /**
189
-     * Gets the layout strategy for this form section
190
-     *
191
-     * @return EE_Form_Section_Layout_Base
192
-     */
193
-    public function get_layout_strategy()
194
-    {
195
-        return $this->_layout_strategy;
196
-    }
197
-
198
-
199
-
200
-    /**
201
-     * Gets the HTML for a single input for this form section according
202
-     * to the layout strategy
203
-     *
204
-     * @param EE_Form_Input_Base $input
205
-     * @return string
206
-     */
207
-    public function get_html_for_input($input)
208
-    {
209
-        return $this->_layout_strategy->layout_input($input);
210
-    }
211
-
212
-
213
-
214
-    /**
215
-     * was_submitted - checks if form inputs are present in request data
216
-     * Basically an alias for form_data_present_in() (which is used by both
217
-     * proper form sections and form inputs)
218
-     *
219
-     * @param null $form_data
220
-     * @return boolean
221
-     */
222
-    public function was_submitted($form_data = null)
223
-    {
224
-        return $this->form_data_present_in($form_data);
225
-    }
226
-
227
-
228
-
229
-    /**
230
-     * After the form section is initially created, call this to sanitize the data in the submission
231
-     * which relates to this form section, validate it, and set it as properties on the form.
232
-     *
233
-     * @param array|null $req_data should usually be $_POST (the default).
234
-     *                             However, you CAN supply a different array.
235
-     *                             Consider using set_defaults() instead however.
236
-     *                             (If you rendered the form in the page using echo $form_x->get_html()
237
-     *                             the inputs will have the correct name in the request data for this function
238
-     *                             to find them and populate the form with them.
239
-     *                             If you have a flat form (with only input subsections),
240
-     *                             you can supply a flat array where keys
241
-     *                             are the form input names and values are their values)
242
-     * @param boolean    $validate whether or not to perform validation on this data. Default is,
243
-     *                             of course, to validate that data, and set errors on the invalid values.
244
-     *                             But if the data has already been validated
245
-     *                             (eg you validated the data then stored it in the DB)
246
-     *                             you may want to skip this step.
247
-     */
248
-    public function receive_form_submission($req_data = null, $validate = true)
249
-    {
250
-        $req_data = apply_filters('FHEE__EE_Form_Section_Proper__receive_form_submission__req_data', $req_data, $this,
251
-            $validate);
252
-        if ($req_data === null) {
253
-            $req_data = array_merge($_GET, $_POST);
254
-        }
255
-        $req_data = apply_filters('FHEE__EE_Form_Section_Proper__receive_form_submission__request_data', $req_data,
256
-            $this);
257
-        $this->_normalize($req_data);
258
-        if ($validate) {
259
-            $this->_validate();
260
-            //if it's invalid, we're going to want to re-display so remember what they submitted
261
-            if (! $this->is_valid()) {
262
-                $this->store_submitted_form_data_in_session();
263
-            }
264
-        }
265
-        do_action('AHEE__EE_Form_Section_Proper__receive_form_submission__end', $req_data, $this, $validate);
266
-    }
267
-
268
-
269
-
270
-    /**
271
-     * caches the originally submitted input values in the session
272
-     * so that they can be used to repopulate the form if it failed validation
273
-     *
274
-     * @return boolean whether or not the data was successfully stored in the session
275
-     */
276
-    protected function store_submitted_form_data_in_session()
277
-    {
278
-        return EE_Registry::instance()->SSN->set_session_data(
279
-            array(
280
-                \EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY => $this->submitted_values(true),
281
-            )
282
-        );
283
-    }
284
-
285
-
286
-
287
-    /**
288
-     * retrieves the originally submitted input values in the session
289
-     * so that they can be used to repopulate the form if it failed validation
290
-     *
291
-     * @return array
292
-     */
293
-    protected function get_submitted_form_data_from_session()
294
-    {
295
-        $session = EE_Registry::instance()->SSN;
296
-        if ($session instanceof EE_Session) {
297
-            return $session->get_session_data(
298
-                \EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY
299
-            );
300
-        } else {
301
-            return array();
302
-        }
303
-    }
304
-
305
-
306
-
307
-    /**
308
-     * flushed the originally submitted input values from the session
309
-     *
310
-     * @return boolean whether or not the data was successfully removed from the session
311
-     */
312
-    protected function flush_submitted_form_data_from_session()
313
-    {
314
-        return EE_Registry::instance()->SSN->reset_data(
315
-            array(\EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY)
316
-        );
317
-    }
318
-
319
-
320
-
321
-    /**
322
-     * Populates this form and its subsections with data from the session.
323
-     * (Wrapper for EE_Form_Section_Proper::receive_form_submission, so it shows
324
-     * validation errors when displaying too)
325
-     * Returns true if the form was populated from the session, false otherwise
326
-     *
327
-     * @return boolean
328
-     */
329
-    public function populate_from_session()
330
-    {
331
-        $form_data_in_session = $this->get_submitted_form_data_from_session();
332
-        if (empty($form_data_in_session)) {
333
-            return false;
334
-        }
335
-        $this->receive_form_submission($form_data_in_session);
336
-        $this->flush_submitted_form_data_from_session();
337
-        if ($this->form_data_present_in($form_data_in_session)) {
338
-            return true;
339
-        } else {
340
-            return false;
341
-        }
342
-    }
343
-
344
-
345
-
346
-    /**
347
-     * Populates the default data for the form, given an array where keys are
348
-     * the input names, and values are their values (preferably normalized to be their
349
-     * proper PHP types, not all strings... although that should be ok too).
350
-     * Proper subsections are sub-arrays, the key being the subsection's name, and
351
-     * the value being an array formatted in teh same way
352
-     *
353
-     * @param array $default_data
354
-     */
355
-    public function populate_defaults($default_data)
356
-    {
357
-        foreach ($this->subsections(false) as $subsection_name => $subsection) {
358
-            if (isset($default_data[$subsection_name])) {
359
-                if ($subsection instanceof EE_Form_Input_Base) {
360
-                    $subsection->set_default($default_data[$subsection_name]);
361
-                } elseif ($subsection instanceof EE_Form_Section_Proper) {
362
-                    $subsection->populate_defaults($default_data[$subsection_name]);
363
-                }
364
-            }
365
-        }
366
-    }
367
-
368
-
369
-
370
-    /**
371
-     * returns true if subsection exists
372
-     *
373
-     * @param string $name
374
-     * @return boolean
375
-     */
376
-    public function subsection_exists($name)
377
-    {
378
-        return isset($this->_subsections[$name]) ? true : false;
379
-    }
380
-
381
-
382
-
383
-    /**
384
-     * Gets the subsection specified by its name
385
-     *
386
-     * @param string  $name
387
-     * @param boolean $require_construction_to_be_finalized most client code should leave this as TRUE
388
-     *                                                      so that the inputs will be properly configured.
389
-     *                                                      However, some client code may be ok
390
-     *                                                      with construction finalize being called later
391
-     *                                                      (realizing that the subsections' html names
392
-     *                                                      might not be set yet, etc.)
393
-     * @return EE_Form_Section_Base
394
-     * @throws \EE_Error
395
-     */
396
-    public function get_subsection($name, $require_construction_to_be_finalized = true)
397
-    {
398
-        if ($require_construction_to_be_finalized) {
399
-            $this->ensure_construct_finalized_called();
400
-        }
401
-        return $this->subsection_exists($name) ? $this->_subsections[$name] : null;
402
-    }
403
-
404
-
405
-
406
-    /**
407
-     * Gets all the validatable subsections of this form section
408
-     *
409
-     * @return EE_Form_Section_Validatable[]
410
-     */
411
-    public function get_validatable_subsections()
412
-    {
413
-        $validatable_subsections = array();
414
-        foreach ($this->subsections() as $name => $obj) {
415
-            if ($obj instanceof EE_Form_Section_Validatable) {
416
-                $validatable_subsections[$name] = $obj;
417
-            }
418
-        }
419
-        return $validatable_subsections;
420
-    }
421
-
422
-
423
-
424
-    /**
425
-     * Gets an input by the given name. If not found, or if its not an EE_FOrm_Input_Base child,
426
-     * throw an EE_Error.
427
-     *
428
-     * @param string  $name
429
-     * @param boolean $require_construction_to_be_finalized most client code should
430
-     *                                                      leave this as TRUE so that the inputs will be properly
431
-     *                                                      configured. However, some client code may be ok with
432
-     *                                                      construction finalize being called later
433
-     *                                                      (realizing that the subsections' html names might not be
434
-     *                                                      set yet, etc.)
435
-     * @return EE_Form_Input_Base
436
-     * @throws EE_Error
437
-     */
438
-    public function get_input($name, $require_construction_to_be_finalized = true)
439
-    {
440
-        $subsection = $this->get_subsection($name, $require_construction_to_be_finalized);
441
-        if (! $subsection instanceof EE_Form_Input_Base) {
442
-            throw new EE_Error(
443
-                sprintf(
444
-                    __(
445
-                        "Subsection '%s' is not an instanceof EE_Form_Input_Base on form '%s'. It is a '%s'",
446
-                        'event_espresso'
447
-                    ),
448
-                    $name,
449
-                    get_class($this),
450
-                    $subsection ? get_class($subsection) : __("NULL", 'event_espresso')
451
-                )
452
-            );
453
-        }
454
-        return $subsection;
455
-    }
456
-
457
-
458
-
459
-    /**
460
-     * Like get_input(), gets the proper subsection of the form given the name,
461
-     * otherwise throws an EE_Error
462
-     *
463
-     * @param string  $name
464
-     * @param boolean $require_construction_to_be_finalized most client code should
465
-     *                                                      leave this as TRUE so that the inputs will be properly
466
-     *                                                      configured. However, some client code may be ok with
467
-     *                                                      construction finalize being called later
468
-     *                                                      (realizing that the subsections' html names might not be
469
-     *                                                      set yet, etc.)
470
-     * @return EE_Form_Section_Proper
471
-     * @throws EE_Error
472
-     */
473
-    public function get_proper_subsection($name, $require_construction_to_be_finalized = true)
474
-    {
475
-        $subsection = $this->get_subsection($name, $require_construction_to_be_finalized);
476
-        if (! $subsection instanceof EE_Form_Section_Proper) {
477
-            throw new EE_Error(
478
-                sprintf(
479
-                    __("Subsection '%'s is not an instanceof EE_Form_Section_Proper on form '%s'", 'event_espresso'),
480
-                    $name,
481
-                    get_class($this)
482
-                )
483
-            );
484
-        }
485
-        return $subsection;
486
-    }
487
-
488
-
489
-
490
-    /**
491
-     * Gets the value of the specified input. Should be called after receive_form_submission()
492
-     * or populate_defaults() on the form, where the normalized value on the input is set.
493
-     *
494
-     * @param string $name
495
-     * @return mixed depending on the input's type and its normalization strategy
496
-     * @throws \EE_Error
497
-     */
498
-    public function get_input_value($name)
499
-    {
500
-        $input = $this->get_input($name);
501
-        return $input->normalized_value();
502
-    }
503
-
504
-
505
-
506
-    /**
507
-     * Checks if this form section itself is valid, and then checks its subsections
508
-     *
509
-     * @throws EE_Error
510
-     * @return boolean
511
-     */
512
-    public function is_valid()
513
-    {
514
-        if (! $this->has_received_submission()) {
515
-            throw new EE_Error(
516
-                sprintf(
517
-                    __(
518
-                        "You cannot check if a form is valid before receiving the form submission using receive_form_submission",
519
-                        "event_espresso"
520
-                    )
521
-                )
522
-            );
523
-        }
524
-        if (! parent::is_valid()) {
525
-            return false;
526
-        }
527
-        // ok so no general errors to this entire form section.
528
-        // so let's check the subsections, but only set errors if that hasn't been done yet
529
-        $set_submission_errors = $this->submission_error_message() === '' ? true : false;
530
-        foreach ($this->get_validatable_subsections() as $subsection) {
531
-            if (! $subsection->is_valid() || $subsection->get_validation_error_string() !== '') {
532
-                if ($set_submission_errors) {
533
-                    $this->set_submission_error_message($subsection->get_validation_error_string());
534
-                }
535
-                return false;
536
-            }
537
-        }
538
-        return true;
539
-    }
540
-
541
-
542
-
543
-    /**
544
-     * gets teh default name of this form section if none is specified
545
-     *
546
-     * @return string
547
-     */
548
-    protected function _set_default_name_if_empty()
549
-    {
550
-        if (! $this->_name) {
551
-            $classname = get_class($this);
552
-            $default_name = str_replace("EE_", "", $classname);
553
-            $this->_name = $default_name;
554
-        }
555
-    }
556
-
557
-
558
-
559
-    /**
560
-     * Returns the HTML for the form, except for the form opening and closing tags
561
-     * (as the form section doesn't know where you necessarily want to send the information to),
562
-     * and except for a submit button. Enqueus JS and CSS; if called early enough we will
563
-     * try to enqueue them in the header, otherwise they'll be enqueued in the footer.
564
-     * Not doing_it_wrong because theoretically this CAN be used properly,
565
-     * provided its used during "wp_enqueue_scripts", or it doesn't need to enqueue
566
-     * any CSS.
567
-     *
568
-     * @throws \EE_Error
569
-     */
570
-    public function get_html_and_js()
571
-    {
572
-        $this->enqueue_js();
573
-        return $this->get_html();
574
-    }
575
-
576
-
577
-
578
-    /**
579
-     * returns HTML for displaying this form section. recursively calls display_section() on all subsections
580
-     *
581
-     * @param bool $display_previously_submitted_data
582
-     * @return string
583
-     */
584
-    public function get_html($display_previously_submitted_data = true)
585
-    {
586
-        $this->ensure_construct_finalized_called();
587
-        if ($display_previously_submitted_data) {
588
-            $this->populate_from_session();
589
-        }
590
-        return $this->_form_html_filter
591
-            ? $this->_form_html_filter->filterHtml($this->_layout_strategy->layout_form(), $this)
592
-            : $this->_layout_strategy->layout_form();
593
-    }
594
-
595
-
596
-
597
-    /**
598
-     * enqueues JS and CSS for the form.
599
-     * It is preferred to call this before wp_enqueue_scripts so the
600
-     * scripts and styles can be put in the header, but if called later
601
-     * they will be put in the footer (which is OK for JS, but in HTML4 CSS should
602
-     * only be in the header; but in HTML5 its ok in the body.
603
-     * See http://stackoverflow.com/questions/4957446/load-external-css-file-in-body-tag.
604
-     * So if your form enqueues CSS, it's preferred to call this before wp_enqueue_scripts.)
605
-     *
606
-     * @return string
607
-     * @throws \EE_Error
608
-     */
609
-    public function enqueue_js()
610
-    {
611
-        $this->_enqueue_and_localize_form_js();
612
-        foreach ($this->subsections() as $subsection) {
613
-            $subsection->enqueue_js();
614
-        }
615
-    }
616
-
617
-
618
-
619
-    /**
620
-     * adds a filter so that jquery validate gets enqueued in EE_System::wp_enqueue_scripts().
621
-     * This must be done BEFORE wp_enqueue_scripts() gets called, which is on
622
-     * the wp_enqueue_scripts hook.
623
-     * However, registering the form js and localizing it can happen when we
624
-     * actually output the form (which is preferred, seeing how teh form's fields
625
-     * could change until it's actually outputted)
626
-     *
627
-     * @param boolean $init_form_validation_automatically whether or not we want the form validation
628
-     *                                                    to be triggered automatically or not
629
-     * @return void
630
-     */
631
-    public static function wp_enqueue_scripts($init_form_validation_automatically = true)
632
-    {
633
-        add_filter('FHEE_load_jquery_validate', '__return_true');
634
-        wp_register_script(
635
-            'ee_form_section_validation',
636
-            EE_GLOBAL_ASSETS_URL . 'scripts' . DS . 'form_section_validation.js',
637
-            array('jquery-validate', 'jquery-ui-datepicker', 'jquery-validate-extra-methods'),
638
-            EVENT_ESPRESSO_VERSION,
639
-            true
640
-        );
641
-        wp_localize_script(
642
-            'ee_form_section_validation',
643
-            'ee_form_section_validation_init',
644
-            array('init' => $init_form_validation_automatically ? true : false)
645
-        );
646
-    }
647
-
648
-
649
-
650
-    /**
651
-     * gets the variables used by form_section_validation.js.
652
-     * This needs to be called AFTER we've called $this->_enqueue_jquery_validate_script,
653
-     * but before the wordpress hook wp_loaded
654
-     *
655
-     * @throws \EE_Error
656
-     */
657
-    public function _enqueue_and_localize_form_js()
658
-    {
659
-        $this->ensure_construct_finalized_called();
660
-        //actually, we don't want to localize just yet. There may be other forms on the page.
661
-        //so we need to add our form section data to a static variable accessible by all form sections
662
-        //and localize it just before the footer
663
-        $this->localize_validation_rules();
664
-        add_action('wp_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'), 2);
665
-        add_action('admin_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'));
666
-    }
667
-
668
-
669
-
670
-    /**
671
-     * add our form section data to a static variable accessible by all form sections
672
-     *
673
-     * @param bool $return_for_subsection
674
-     * @return void
675
-     * @throws \EE_Error
676
-     */
677
-    public function localize_validation_rules($return_for_subsection = false)
678
-    {
679
-        // we only want to localize vars ONCE for the entire form,
680
-        // so if the form section doesn't have a parent, then it must be the top dog
681
-        if ($return_for_subsection || ! $this->parent_section()) {
682
-            EE_Form_Section_Proper::$_js_localization['form_data'][$this->html_id()] = array(
683
-                'form_section_id'  => $this->html_id(true),
684
-                'validation_rules' => $this->get_jquery_validation_rules(),
685
-                'other_data'       => $this->get_other_js_data(),
686
-                'errors'           => $this->subsection_validation_errors_by_html_name(),
687
-            );
688
-            EE_Form_Section_Proper::$_scripts_localized = true;
689
-        }
690
-    }
691
-
692
-
693
-
694
-    /**
695
-     * Gets an array of extra data that will be useful for client-side javascript.
696
-     * This is primarily data added by inputs and forms in addition to any
697
-     * scripts they might enqueue
698
-     *
699
-     * @param array $form_other_js_data
700
-     * @return array
701
-     */
702
-    public function get_other_js_data($form_other_js_data = array())
703
-    {
704
-        foreach ($this->subsections() as $subsection) {
705
-            $form_other_js_data = $subsection->get_other_js_data($form_other_js_data);
706
-        }
707
-        return $form_other_js_data;
708
-    }
709
-
710
-
711
-
712
-    /**
713
-     * Gets a flat array of inputs for this form section and its subsections.
714
-     * Keys are their form names, and values are the inputs themselves
715
-     *
716
-     * @return EE_Form_Input_Base
717
-     */
718
-    public function inputs_in_subsections()
719
-    {
720
-        $inputs = array();
721
-        foreach ($this->subsections() as $subsection) {
722
-            if ($subsection instanceof EE_Form_Input_Base) {
723
-                $inputs[$subsection->html_name()] = $subsection;
724
-            } elseif ($subsection instanceof EE_Form_Section_Proper) {
725
-                $inputs += $subsection->inputs_in_subsections();
726
-            }
727
-        }
728
-        return $inputs;
729
-    }
730
-
731
-
732
-
733
-    /**
734
-     * Gets a flat array of all the validation errors.
735
-     * Keys are html names (because those should be unique)
736
-     * and values are a string of all their validation errors
737
-     *
738
-     * @return string[]
739
-     */
740
-    public function subsection_validation_errors_by_html_name()
741
-    {
742
-        $inputs = $this->inputs();
743
-        $errors = array();
744
-        foreach ($inputs as $form_input) {
745
-            if ($form_input instanceof EE_Form_Input_Base && $form_input->get_validation_errors()) {
746
-                $errors[$form_input->html_name()] = $form_input->get_validation_error_string();
747
-            }
748
-        }
749
-        return $errors;
750
-    }
751
-
752
-
753
-
754
-    /**
755
-     * passes all the form data required by the JS to the JS, and enqueues the few required JS files.
756
-     * Should be setup by each form during the _enqueues_and_localize_form_js
757
-     */
758
-    public static function localize_script_for_all_forms()
759
-    {
760
-        //allow inputs and stuff to hook in their JS and stuff here
761
-        do_action('AHEE__EE_Form_Section_Proper__localize_script_for_all_forms__begin');
762
-        EE_Form_Section_Proper::$_js_localization['localized_error_messages'] = EE_Form_Section_Proper::_get_localized_error_messages();
763
-        $email_validation_level = isset(EE_Registry::instance()->CFG->registration->email_validation_level)
764
-            ? EE_Registry::instance()->CFG->registration->email_validation_level
765
-            : 'wp_default';
766
-        EE_Form_Section_Proper::$_js_localization['email_validation_level'] = $email_validation_level;
767
-        wp_enqueue_script('ee_form_section_validation');
768
-        wp_localize_script(
769
-            'ee_form_section_validation',
770
-            'ee_form_section_vars',
771
-            EE_Form_Section_Proper::$_js_localization
772
-        );
773
-    }
774
-
775
-
776
-
777
-    /**
778
-     * ensure_scripts_localized
779
-     */
780
-    public function ensure_scripts_localized()
781
-    {
782
-        if (! EE_Form_Section_Proper::$_scripts_localized) {
783
-            $this->_enqueue_and_localize_form_js();
784
-        }
785
-    }
786
-
787
-
788
-
789
-    /**
790
-     * Gets the hard-coded validation error messages to be used in the JS. The convention
791
-     * is that the key here should be the same as the custom validation rule put in the JS file
792
-     *
793
-     * @return array keys are custom validation rules, and values are internationalized strings
794
-     */
795
-    private static function _get_localized_error_messages()
796
-    {
797
-        return array(
798
-            'validUrl' => __("This is not a valid absolute URL. Eg, http://domain.com/monkey.jpg", "event_espresso"),
799
-            'regex'    => __('Please check your input', 'event_espresso'),
800
-        );
801
-    }
802
-
803
-
804
-
805
-    /**
806
-     * @return array
807
-     */
808
-    public static function js_localization()
809
-    {
810
-        return self::$_js_localization;
811
-    }
812
-
813
-
814
-
815
-    /**
816
-     * @return array
817
-     */
818
-    public static function reset_js_localization()
819
-    {
820
-        self::$_js_localization = array();
821
-    }
822
-
823
-
824
-
825
-    /**
826
-     * Gets the JS to put inside the jquery validation rules for subsection of this form section.
827
-     * See parent function for more...
828
-     *
829
-     * @return array
830
-     */
831
-    public function get_jquery_validation_rules()
832
-    {
833
-        $jquery_validation_rules = array();
834
-        foreach ($this->get_validatable_subsections() as $subsection) {
835
-            $jquery_validation_rules = array_merge(
836
-                $jquery_validation_rules,
837
-                $subsection->get_jquery_validation_rules()
838
-            );
839
-        }
840
-        return $jquery_validation_rules;
841
-    }
842
-
843
-
844
-
845
-    /**
846
-     * Sanitizes all the data and sets the sanitized value of each field
847
-     *
848
-     * @param array $req_data like $_POST
849
-     * @return void
850
-     */
851
-    protected function _normalize($req_data)
852
-    {
853
-        $this->_received_submission = true;
854
-        $this->_validation_errors = array();
855
-        foreach ($this->get_validatable_subsections() as $subsection) {
856
-            try {
857
-                $subsection->_normalize($req_data);
858
-            } catch (EE_Validation_Error $e) {
859
-                $subsection->add_validation_error($e);
860
-            }
861
-        }
862
-    }
863
-
864
-
865
-
866
-    /**
867
-     * Performs validation on this form section and its subsections.
868
-     * For each subsection,
869
-     * calls _validate_{subsection_name} on THIS form (if the function exists)
870
-     * and passes it the subsection, then calls _validate on that subsection.
871
-     * If you need to perform validation on the form as a whole (considering multiple)
872
-     * you would be best to override this _validate method,
873
-     * calling parent::_validate() first.
874
-     */
875
-    protected function _validate()
876
-    {
877
-        foreach ($this->get_validatable_subsections() as $subsection_name => $subsection) {
878
-            if (method_exists($this, '_validate_' . $subsection_name)) {
879
-                call_user_func_array(array($this, '_validate_' . $subsection_name), array($subsection));
880
-            }
881
-            $subsection->_validate();
882
-        }
883
-    }
884
-
885
-
886
-
887
-    /**
888
-     * Gets all the validated inputs for the form section
889
-     *
890
-     * @return array
891
-     */
892
-    public function valid_data()
893
-    {
894
-        $inputs = array();
895
-        foreach ($this->subsections() as $subsection_name => $subsection) {
896
-            if ($subsection instanceof EE_Form_Section_Proper) {
897
-                $inputs[$subsection_name] = $subsection->valid_data();
898
-            } else if ($subsection instanceof EE_Form_Input_Base) {
899
-                $inputs[$subsection_name] = $subsection->normalized_value();
900
-            }
901
-        }
902
-        return $inputs;
903
-    }
904
-
905
-
906
-
907
-    /**
908
-     * Gets all the inputs on this form section
909
-     *
910
-     * @return EE_Form_Input_Base[]
911
-     */
912
-    public function inputs()
913
-    {
914
-        $inputs = array();
915
-        foreach ($this->subsections() as $subsection_name => $subsection) {
916
-            if ($subsection instanceof EE_Form_Input_Base) {
917
-                $inputs[$subsection_name] = $subsection;
918
-            }
919
-        }
920
-        return $inputs;
921
-    }
922
-
923
-
924
-
925
-    /**
926
-     * Gets all the subsections which are a proper form
927
-     *
928
-     * @return EE_Form_Section_Proper[]
929
-     */
930
-    public function subforms()
931
-    {
932
-        $form_sections = array();
933
-        foreach ($this->subsections() as $name => $obj) {
934
-            if ($obj instanceof EE_Form_Section_Proper) {
935
-                $form_sections[$name] = $obj;
936
-            }
937
-        }
938
-        return $form_sections;
939
-    }
940
-
941
-
942
-
943
-    /**
944
-     * Gets all the subsections (inputs, proper subsections, or html-only sections).
945
-     * Consider using inputs() or subforms()
946
-     * if you only want form inputs or proper form sections.
947
-     *
948
-     * @param boolean $require_construction_to_be_finalized most client code should
949
-     *                                                      leave this as TRUE so that the inputs will be properly
950
-     *                                                      configured. However, some client code may be ok with
951
-     *                                                      construction finalize being called later
952
-     *                                                      (realizing that the subsections' html names might not be
953
-     *                                                      set yet, etc.)
954
-     * @return EE_Form_Section_Proper[]
955
-     */
956
-    public function subsections($require_construction_to_be_finalized = true)
957
-    {
958
-        if ($require_construction_to_be_finalized) {
959
-            $this->ensure_construct_finalized_called();
960
-        }
961
-        return $this->_subsections;
962
-    }
963
-
964
-
965
-
966
-    /**
967
-     * Returns a simple array where keys are input names, and values are their normalized
968
-     * values. (Similar to calling get_input_value on inputs)
969
-     *
970
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
971
-     *                                        or just this forms' direct children inputs
972
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
973
-     *                                        or allow multidimensional array
974
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array
975
-     *                                        with array keys being input names
976
-     *                                        (regardless of whether they are from a subsection or not),
977
-     *                                        and if $flatten is FALSE it can be a multidimensional array
978
-     *                                        where keys are always subsection names and values are either
979
-     *                                        the input's normalized value, or an array like the top-level array
980
-     */
981
-    public function input_values($include_subform_inputs = false, $flatten = false)
982
-    {
983
-        return $this->_input_values(false, $include_subform_inputs, $flatten);
984
-    }
985
-
986
-
987
-
988
-    /**
989
-     * Similar to EE_Form_Section_Proper::input_values(), except this returns the 'display_value'
990
-     * of each input. On some inputs (especially radio boxes or checkboxes), the value stored
991
-     * is not necessarily the value we want to display to users. This creates an array
992
-     * where keys are the input names, and values are their display values
993
-     *
994
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
995
-     *                                        or just this forms' direct children inputs
996
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
997
-     *                                        or allow multidimensional array
998
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array
999
-     *                                        with array keys being input names
1000
-     *                                        (regardless of whether they are from a subsection or not),
1001
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1002
-     *                                        where keys are always subsection names and values are either
1003
-     *                                        the input's normalized value, or an array like the top-level array
1004
-     */
1005
-    public function input_pretty_values($include_subform_inputs = false, $flatten = false)
1006
-    {
1007
-        return $this->_input_values(true, $include_subform_inputs, $flatten);
1008
-    }
1009
-
1010
-
1011
-
1012
-    /**
1013
-     * Gets the input values from the form
1014
-     *
1015
-     * @param boolean $pretty                 Whether to retrieve the pretty value,
1016
-     *                                        or just the normalized value
1017
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1018
-     *                                        or just this forms' direct children inputs
1019
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1020
-     *                                        or allow multidimensional array
1021
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array with array keys being
1022
-     *                                        input names (regardless of whether they are from a subsection or not),
1023
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1024
-     *                                        where keys are always subsection names and values are either
1025
-     *                                        the input's normalized value, or an array like the top-level array
1026
-     */
1027
-    public function _input_values($pretty = false, $include_subform_inputs = false, $flatten = false)
1028
-    {
1029
-        $input_values = array();
1030
-        foreach ($this->subsections() as $subsection_name => $subsection) {
1031
-            if ($subsection instanceof EE_Form_Input_Base) {
1032
-                $input_values[$subsection_name] = $pretty
1033
-                    ? $subsection->pretty_value()
1034
-                    : $subsection->normalized_value();
1035
-            } else if ($subsection instanceof EE_Form_Section_Proper && $include_subform_inputs) {
1036
-                $subform_input_values = $subsection->_input_values($pretty, $include_subform_inputs, $flatten);
1037
-                if ($flatten) {
1038
-                    $input_values = array_merge($input_values, $subform_input_values);
1039
-                } else {
1040
-                    $input_values[$subsection_name] = $subform_input_values;
1041
-                }
1042
-            }
1043
-        }
1044
-        return $input_values;
1045
-    }
1046
-
1047
-
1048
-
1049
-    /**
1050
-     * Gets the originally submitted input values from the form
1051
-     *
1052
-     * @param boolean $include_subforms  Whether to include inputs from subforms,
1053
-     *                                   or just this forms' direct children inputs
1054
-     * @return array                     if $flatten is TRUE it will always be a 1-dimensional array
1055
-     *                                   with array keys being input names
1056
-     *                                   (regardless of whether they are from a subsection or not),
1057
-     *                                   and if $flatten is FALSE it can be a multidimensional array
1058
-     *                                   where keys are always subsection names and values are either
1059
-     *                                   the input's normalized value, or an array like the top-level array
1060
-     */
1061
-    public function submitted_values($include_subforms = false)
1062
-    {
1063
-        $submitted_values = array();
1064
-        foreach ($this->subsections() as $subsection) {
1065
-            if ($subsection instanceof EE_Form_Input_Base) {
1066
-                // is this input part of an array of inputs?
1067
-                if (strpos($subsection->html_name(), '[') !== false) {
1068
-                    $full_input_name = \EEH_Array::convert_array_values_to_keys(
1069
-                        explode('[', str_replace(']', '', $subsection->html_name())),
1070
-                        $subsection->raw_value()
1071
-                    );
1072
-                    $submitted_values = array_replace_recursive($submitted_values, $full_input_name);
1073
-                } else {
1074
-                    $submitted_values[$subsection->html_name()] = $subsection->raw_value();
1075
-                }
1076
-            } else if ($subsection instanceof EE_Form_Section_Proper && $include_subforms) {
1077
-                $subform_input_values = $subsection->submitted_values($include_subforms);
1078
-                $submitted_values = array_replace_recursive($submitted_values, $subform_input_values);
1079
-            }
1080
-        }
1081
-        return $submitted_values;
1082
-    }
1083
-
1084
-
1085
-
1086
-    /**
1087
-     * Indicates whether or not this form has received a submission yet
1088
-     * (ie, had receive_form_submission called on it yet)
1089
-     *
1090
-     * @return boolean
1091
-     * @throws \EE_Error
1092
-     */
1093
-    public function has_received_submission()
1094
-    {
1095
-        $this->ensure_construct_finalized_called();
1096
-        return $this->_received_submission;
1097
-    }
1098
-
1099
-
1100
-
1101
-    /**
1102
-     * Equivalent to passing 'exclude' in the constructor's options array.
1103
-     * Removes the listed inputs from the form
1104
-     *
1105
-     * @param array $inputs_to_exclude values are the input names
1106
-     * @return void
1107
-     */
1108
-    public function exclude(array $inputs_to_exclude = array())
1109
-    {
1110
-        foreach ($inputs_to_exclude as $input_to_exclude_name) {
1111
-            unset($this->_subsections[$input_to_exclude_name]);
1112
-        }
1113
-    }
1114
-
1115
-
1116
-
1117
-    /**
1118
-     * @param array $inputs_to_hide
1119
-     * @throws \EE_Error
1120
-     */
1121
-    public function hide(array $inputs_to_hide = array())
1122
-    {
1123
-        foreach ($inputs_to_hide as $input_to_hide) {
1124
-            $input = $this->get_input($input_to_hide);
1125
-            $input->set_display_strategy(new EE_Hidden_Display_Strategy());
1126
-        }
1127
-    }
1128
-
1129
-
1130
-
1131
-    /**
1132
-     * add_subsections
1133
-     * Adds the listed subsections to the form section.
1134
-     * If $subsection_name_to_target is provided,
1135
-     * then new subsections are added before or after that subsection,
1136
-     * otherwise to the start or end of the entire subsections array.
1137
-     *
1138
-     * @param EE_Form_Section_Base[] $new_subsections           array of new form subsections
1139
-     *                                                          where keys are their names
1140
-     * @param string                 $subsection_name_to_target an existing for section that $new_subsections
1141
-     *                                                          should be added before or after
1142
-     *                                                          IF $subsection_name_to_target is null,
1143
-     *                                                          then $new_subsections will be added to
1144
-     *                                                          the beginning or end of the entire subsections array
1145
-     * @param boolean                $add_before                whether to add $new_subsections, before or after
1146
-     *                                                          $subsection_name_to_target,
1147
-     *                                                          or if $subsection_name_to_target is null,
1148
-     *                                                          before or after entire subsections array
1149
-     * @return void
1150
-     * @throws \EE_Error
1151
-     */
1152
-    public function add_subsections($new_subsections, $subsection_name_to_target = null, $add_before = true)
1153
-    {
1154
-        foreach ($new_subsections as $subsection_name => $subsection) {
1155
-            if (! $subsection instanceof EE_Form_Section_Base) {
1156
-                EE_Error::add_error(
1157
-                    sprintf(
1158
-                        __(
1159
-                            "Trying to add a %s as a subsection (it was named '%s') to the form section '%s'. It was removed.",
1160
-                            "event_espresso"
1161
-                        ),
1162
-                        get_class($subsection),
1163
-                        $subsection_name,
1164
-                        $this->name()
1165
-                    )
1166
-                );
1167
-                unset($new_subsections[$subsection_name]);
1168
-            }
1169
-        }
1170
-        $this->_subsections = EEH_Array::insert_into_array(
1171
-            $this->_subsections,
1172
-            $new_subsections,
1173
-            $subsection_name_to_target,
1174
-            $add_before
1175
-        );
1176
-        if ($this->_construction_finalized) {
1177
-            foreach ($this->_subsections as $name => $subsection) {
1178
-                $subsection->_construct_finalize($this, $name);
1179
-            }
1180
-        }
1181
-    }
1182
-
1183
-
1184
-
1185
-    /**
1186
-     * Just gets all validatable subsections to clean their sensitive data
1187
-     */
1188
-    public function clean_sensitive_data()
1189
-    {
1190
-        foreach ($this->get_validatable_subsections() as $subsection) {
1191
-            $subsection->clean_sensitive_data();
1192
-        }
1193
-    }
1194
-
1195
-
1196
-
1197
-    /**
1198
-     * @param string $form_submission_error_message
1199
-     */
1200
-    public function set_submission_error_message($form_submission_error_message = '')
1201
-    {
1202
-        $this->_form_submission_error_message .= ! empty($form_submission_error_message)
1203
-            ? $form_submission_error_message
1204
-            : __('Form submission failed due to errors', 'event_espresso');
1205
-    }
1206
-
1207
-
1208
-
1209
-    /**
1210
-     * @return string
1211
-     */
1212
-    public function submission_error_message()
1213
-    {
1214
-        return $this->_form_submission_error_message;
1215
-    }
1216
-
1217
-
1218
-
1219
-    /**
1220
-     * @param string $form_submission_success_message
1221
-     */
1222
-    public function set_submission_success_message($form_submission_success_message)
1223
-    {
1224
-        $this->_form_submission_success_message .= ! empty($form_submission_success_message)
1225
-            ? $form_submission_success_message
1226
-            : __('Form submitted successfully', 'event_espresso');
1227
-    }
1228
-
1229
-
1230
-
1231
-    /**
1232
-     * @return string
1233
-     */
1234
-    public function submission_success_message()
1235
-    {
1236
-        return $this->_form_submission_success_message;
1237
-    }
1238
-
1239
-
1240
-
1241
-    /**
1242
-     * Returns the prefix that should be used on child of this form section for
1243
-     * their html names. If this form section itself has a parent, prepends ITS
1244
-     * prefix onto this form section's prefix. Used primarily by
1245
-     * EE_Form_Input_Base::_set_default_html_name_if_empty
1246
-     *
1247
-     * @return string
1248
-     * @throws \EE_Error
1249
-     */
1250
-    public function html_name_prefix()
1251
-    {
1252
-        if ($this->parent_section() instanceof EE_Form_Section_Proper) {
1253
-            return $this->parent_section()->html_name_prefix() . '[' . $this->name() . ']';
1254
-        } else {
1255
-            return $this->name();
1256
-        }
1257
-    }
1258
-
1259
-
1260
-
1261
-    /**
1262
-     * Gets the name, but first checks _construct_finalize has been called. If not,
1263
-     * calls it (assumes there is no parent and that we want the name to be whatever
1264
-     * was set, which is probably nothing, or the classname)
1265
-     *
1266
-     * @return string
1267
-     * @throws \EE_Error
1268
-     */
1269
-    public function name()
1270
-    {
1271
-        $this->ensure_construct_finalized_called();
1272
-        return parent::name();
1273
-    }
1274
-
1275
-
1276
-
1277
-    /**
1278
-     * @return EE_Form_Section_Proper
1279
-     * @throws \EE_Error
1280
-     */
1281
-    public function parent_section()
1282
-    {
1283
-        $this->ensure_construct_finalized_called();
1284
-        return parent::parent_section();
1285
-    }
1286
-
1287
-
1288
-
1289
-    /**
1290
-     * make sure construction finalized was called, otherwise children might not be ready
1291
-     *
1292
-     * @return void
1293
-     * @throws \EE_Error
1294
-     */
1295
-    public function ensure_construct_finalized_called()
1296
-    {
1297
-        if (! $this->_construction_finalized) {
1298
-            $this->_construct_finalize($this->_parent_section, $this->_name);
1299
-        }
1300
-    }
1301
-
1302
-
1303
-
1304
-    /**
1305
-     * Checks if any of this form section's inputs, or any of its children's inputs,
1306
-     * are in teh form data. If any are found, returns true. Else false
1307
-     *
1308
-     * @param array $req_data
1309
-     * @return boolean
1310
-     */
1311
-    public function form_data_present_in($req_data = null)
1312
-    {
1313
-        if ($req_data === null) {
1314
-            $req_data = $_POST;
1315
-        }
1316
-        foreach ($this->subsections() as $subsection) {
1317
-            if ($subsection instanceof EE_Form_Input_Base) {
1318
-                if ($subsection->form_data_present_in($req_data)) {
1319
-                    return true;
1320
-                }
1321
-            } elseif ($subsection instanceof EE_Form_Section_Proper) {
1322
-                if ($subsection->form_data_present_in($req_data)) {
1323
-                    return true;
1324
-                }
1325
-            }
1326
-        }
1327
-        return false;
1328
-    }
1329
-
1330
-
1331
-
1332
-    /**
1333
-     * Gets validation errors for this form section and subsections
1334
-     * Similar to EE_Form_Section_Validatable::get_validation_errors() except this
1335
-     * gets the validation errors for ALL subsection
1336
-     *
1337
-     * @return EE_Validation_Error[]
1338
-     */
1339
-    public function get_validation_errors_accumulated()
1340
-    {
1341
-        $validation_errors = $this->get_validation_errors();
1342
-        foreach ($this->get_validatable_subsections() as $subsection) {
1343
-            if ($subsection instanceof EE_Form_Section_Proper) {
1344
-                $validation_errors_on_this_subsection = $subsection->get_validation_errors_accumulated();
1345
-            } else {
1346
-                $validation_errors_on_this_subsection = $subsection->get_validation_errors();
1347
-            }
1348
-            if ($validation_errors_on_this_subsection) {
1349
-                $validation_errors = array_merge($validation_errors, $validation_errors_on_this_subsection);
1350
-            }
1351
-        }
1352
-        return $validation_errors;
1353
-    }
1354
-
1355
-
1356
-
1357
-    /**
1358
-     * This isn't just the name of an input, it's a path pointing to an input. The
1359
-     * path is similar to a folder path: slash (/) means to descend into a subsection,
1360
-     * dot-dot-slash (../) means to ascend into the parent section.
1361
-     * After a series of slashes and dot-dot-slashes, there should be the name of an input,
1362
-     * which will be returned.
1363
-     * Eg, if you want the related input to be conditional on a sibling input name 'foobar'
1364
-     * just use 'foobar'. If you want it to be conditional on an aunt/uncle input name
1365
-     * 'baz', use '../baz'. If you want it to be conditional on a cousin input,
1366
-     * the child of 'baz_section' named 'baz_child', use '../baz_section/baz_child'.
1367
-     * Etc
1368
-     *
1369
-     * @param string|false $form_section_path we accept false also because substr( '../', '../' ) = false
1370
-     * @return EE_Form_Section_Base
1371
-     */
1372
-    public function find_section_from_path($form_section_path)
1373
-    {
1374
-        //check if we can find the input from purely going straight up the tree
1375
-        $input = parent::find_section_from_path($form_section_path);
1376
-        if ($input instanceof EE_Form_Section_Base) {
1377
-            return $input;
1378
-        }
1379
-        $next_slash_pos = strpos($form_section_path, '/');
1380
-        if ($next_slash_pos !== false) {
1381
-            $child_section_name = substr($form_section_path, 0, $next_slash_pos);
1382
-            $subpath = substr($form_section_path, $next_slash_pos + 1);
1383
-        } else {
1384
-            $child_section_name = $form_section_path;
1385
-            $subpath = '';
1386
-        }
1387
-        $child_section = $this->get_subsection($child_section_name);
1388
-        if ($child_section instanceof EE_Form_Section_Base) {
1389
-            return $child_section->find_section_from_path($subpath);
1390
-        } else {
1391
-            return null;
1392
-        }
1393
-    }
14
+	const SUBMITTED_FORM_DATA_SSN_KEY = 'submitted_form_data';
15
+
16
+	/**
17
+	 * Subsections
18
+	 *
19
+	 * @var EE_Form_Section_Validatable[]
20
+	 */
21
+	protected $_subsections = array();
22
+
23
+	/**
24
+	 * Strategy for laying out the form
25
+	 *
26
+	 * @var EE_Form_Section_Layout_Base
27
+	 */
28
+	protected $_layout_strategy;
29
+
30
+	/**
31
+	 * Whether or not this form has received and validated a form submission yet
32
+	 *
33
+	 * @var boolean
34
+	 */
35
+	protected $_received_submission = false;
36
+
37
+	/**
38
+	 * message displayed to users upon successful form submission
39
+	 *
40
+	 * @var string
41
+	 */
42
+	protected $_form_submission_success_message = '';
43
+
44
+	/**
45
+	 * message displayed to users upon unsuccessful form submission
46
+	 *
47
+	 * @var string
48
+	 */
49
+	protected $_form_submission_error_message = '';
50
+
51
+	/**
52
+	 * Stores all the data that will localized for form validation
53
+	 *
54
+	 * @var array
55
+	 */
56
+	static protected $_js_localization = array();
57
+
58
+	/**
59
+	 * whether or not the form's localized validation JS vars have been set
60
+	 *
61
+	 * @type boolean
62
+	 */
63
+	static protected $_scripts_localized = false;
64
+
65
+
66
+
67
+	/**
68
+	 * when constructing a proper form section, calls _construct_finalize on children
69
+	 * so that they know who their parent is, and what name they've been given.
70
+	 *
71
+	 * @param array $options_array   {
72
+	 * @type        $subsections     EE_Form_Section_Validatable[] where keys are the section's name
73
+	 * @type        $include         string[] numerically-indexed where values are section names to be included,
74
+	 *                               and in that order. This is handy if you want
75
+	 *                               the subsections to be ordered differently than the default, and if you override
76
+	 *                               which fields are shown
77
+	 * @type        $exclude         string[] values are subsections to be excluded. This is handy if you want
78
+	 *                               to remove certain default subsections (note: if you specify BOTH 'include' AND
79
+	 *                               'exclude', the inclusions will be applied first, and the exclusions will exclude
80
+	 *                               items from that list of inclusions)
81
+	 * @type        $layout_strategy EE_Form_Section_Layout_Base strategy for laying out the form
82
+	 *                               } @see EE_Form_Section_Validatable::__construct()
83
+	 * @throws \EE_Error
84
+	 */
85
+	public function __construct($options_array = array())
86
+	{
87
+		$options_array = (array)apply_filters('FHEE__EE_Form_Section_Proper___construct__options_array', $options_array,
88
+			$this);
89
+		//call parent first, as it may be setting the name
90
+		parent::__construct($options_array);
91
+		//if they've included subsections in the constructor, add them now
92
+		if (isset($options_array['include'])) {
93
+			//we are going to make sure we ONLY have those subsections to include
94
+			//AND we are going to make sure they're in that specified order
95
+			$reordered_subsections = array();
96
+			foreach ($options_array['include'] as $input_name) {
97
+				if (isset($this->_subsections[$input_name])) {
98
+					$reordered_subsections[$input_name] = $this->_subsections[$input_name];
99
+				}
100
+			}
101
+			$this->_subsections = $reordered_subsections;
102
+		}
103
+		if (isset($options_array['exclude'])) {
104
+			$exclude = $options_array['exclude'];
105
+			$this->_subsections = array_diff_key($this->_subsections, array_flip($exclude));
106
+		}
107
+		if (isset($options_array['layout_strategy'])) {
108
+			$this->_layout_strategy = $options_array['layout_strategy'];
109
+		}
110
+		if (! $this->_layout_strategy) {
111
+			$this->_layout_strategy = is_admin() ? new EE_Admin_Two_Column_Layout() : new EE_Two_Column_Layout();
112
+		}
113
+		$this->_layout_strategy->_construct_finalize($this);
114
+		//ok so we are definitely going to want the forms JS,
115
+		//so enqueue it or remember to enqueue it during wp_enqueue_scripts
116
+		if (did_action('wp_enqueue_scripts') || did_action('admin_enqueue_scripts')) {
117
+			//ok so they've constructed this object after when they should have.
118
+			//just enqueue the generic form scripts and initialize the form immediately in the JS
119
+			\EE_Form_Section_Proper::wp_enqueue_scripts(true);
120
+		} else {
121
+			add_action('wp_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
122
+			add_action('admin_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
123
+		}
124
+		add_action('wp_footer', array($this, 'ensure_scripts_localized'), 1);
125
+
126
+		/**
127
+		 * Gives other plugins a chance to hook in before construct finalize is called. The form probably doesn't
128
+		 * yet have a parent form section. Since 4.9.32, when this action was introduced, this is the best place to
129
+		 * add a subsection onto a form, assuming you don't care what the form section's name, HTML ID, or HTML name etc are.
130
+		 * Also see AHEE__EE_Form_Section_Proper___construct_finalize__end
131
+		 * @since 4.9.32
132
+		 * @param EE_Form_Section_Proper $this before __construct is done, but all of its logic, except maybe calling
133
+		 *                                      _construct_finalize has been done
134
+		 * @param array $options_array options passed into the constructor
135
+		 */
136
+		do_action('AHEE__EE_Form_Input_Base___construct__before_construct_finalize_called', $this, $options_array);
137
+
138
+		if (isset($options_array['name'])) {
139
+			$this->_construct_finalize(null, $options_array['name']);
140
+		}
141
+	}
142
+
143
+
144
+
145
+	/**
146
+	 * Finishes construction given the parent form section and this form section's name
147
+	 *
148
+	 * @param EE_Form_Section_Proper $parent_form_section
149
+	 * @param string                 $name
150
+	 * @throws \EE_Error
151
+	 */
152
+	public function _construct_finalize($parent_form_section, $name)
153
+	{
154
+		parent::_construct_finalize($parent_form_section, $name);
155
+		$this->_set_default_name_if_empty();
156
+		$this->_set_default_html_id_if_empty();
157
+		foreach ($this->_subsections as $subsection_name => $subsection) {
158
+			if ($subsection instanceof EE_Form_Section_Base) {
159
+				$subsection->_construct_finalize($this, $subsection_name);
160
+			} else {
161
+				throw new EE_Error(
162
+					sprintf(
163
+						__('Subsection "%s" is not an instanceof EE_Form_Section_Base on form "%s". It is a "%s"',
164
+							'event_espresso'),
165
+						$subsection_name,
166
+						get_class($this),
167
+						$subsection ? get_class($subsection) : __('NULL', 'event_espresso')
168
+					)
169
+				);
170
+			}
171
+		}
172
+		/**
173
+		 * Action performed just after form has been given a name (and HTML ID etc) and is fully constructed.
174
+		 * If you have code that should modify the form and needs it and its subsections to have a name, HTML ID (or other attributes derived
175
+		 * from the name like the HTML label id, etc), this is where it should be done.
176
+		 * This might only happen just before displaying the form, or just before it receives form submission data.
177
+		 * If you need to modify the form or its subsections before _construct_finalize is called on it (and we've
178
+		 * ensured it has a name, HTML IDs, etc
179
+		 * @param EE_Form_Section_Proper $this
180
+		 * @param EE_Form_Section_Proper|null $parent_form_section
181
+		 * @param string $name
182
+		 */
183
+		do_action('AHEE__EE_Form_Section_Proper___construct_finalize__end', $this, $parent_form_section, $name);
184
+	}
185
+
186
+
187
+
188
+	/**
189
+	 * Gets the layout strategy for this form section
190
+	 *
191
+	 * @return EE_Form_Section_Layout_Base
192
+	 */
193
+	public function get_layout_strategy()
194
+	{
195
+		return $this->_layout_strategy;
196
+	}
197
+
198
+
199
+
200
+	/**
201
+	 * Gets the HTML for a single input for this form section according
202
+	 * to the layout strategy
203
+	 *
204
+	 * @param EE_Form_Input_Base $input
205
+	 * @return string
206
+	 */
207
+	public function get_html_for_input($input)
208
+	{
209
+		return $this->_layout_strategy->layout_input($input);
210
+	}
211
+
212
+
213
+
214
+	/**
215
+	 * was_submitted - checks if form inputs are present in request data
216
+	 * Basically an alias for form_data_present_in() (which is used by both
217
+	 * proper form sections and form inputs)
218
+	 *
219
+	 * @param null $form_data
220
+	 * @return boolean
221
+	 */
222
+	public function was_submitted($form_data = null)
223
+	{
224
+		return $this->form_data_present_in($form_data);
225
+	}
226
+
227
+
228
+
229
+	/**
230
+	 * After the form section is initially created, call this to sanitize the data in the submission
231
+	 * which relates to this form section, validate it, and set it as properties on the form.
232
+	 *
233
+	 * @param array|null $req_data should usually be $_POST (the default).
234
+	 *                             However, you CAN supply a different array.
235
+	 *                             Consider using set_defaults() instead however.
236
+	 *                             (If you rendered the form in the page using echo $form_x->get_html()
237
+	 *                             the inputs will have the correct name in the request data for this function
238
+	 *                             to find them and populate the form with them.
239
+	 *                             If you have a flat form (with only input subsections),
240
+	 *                             you can supply a flat array where keys
241
+	 *                             are the form input names and values are their values)
242
+	 * @param boolean    $validate whether or not to perform validation on this data. Default is,
243
+	 *                             of course, to validate that data, and set errors on the invalid values.
244
+	 *                             But if the data has already been validated
245
+	 *                             (eg you validated the data then stored it in the DB)
246
+	 *                             you may want to skip this step.
247
+	 */
248
+	public function receive_form_submission($req_data = null, $validate = true)
249
+	{
250
+		$req_data = apply_filters('FHEE__EE_Form_Section_Proper__receive_form_submission__req_data', $req_data, $this,
251
+			$validate);
252
+		if ($req_data === null) {
253
+			$req_data = array_merge($_GET, $_POST);
254
+		}
255
+		$req_data = apply_filters('FHEE__EE_Form_Section_Proper__receive_form_submission__request_data', $req_data,
256
+			$this);
257
+		$this->_normalize($req_data);
258
+		if ($validate) {
259
+			$this->_validate();
260
+			//if it's invalid, we're going to want to re-display so remember what they submitted
261
+			if (! $this->is_valid()) {
262
+				$this->store_submitted_form_data_in_session();
263
+			}
264
+		}
265
+		do_action('AHEE__EE_Form_Section_Proper__receive_form_submission__end', $req_data, $this, $validate);
266
+	}
267
+
268
+
269
+
270
+	/**
271
+	 * caches the originally submitted input values in the session
272
+	 * so that they can be used to repopulate the form if it failed validation
273
+	 *
274
+	 * @return boolean whether or not the data was successfully stored in the session
275
+	 */
276
+	protected function store_submitted_form_data_in_session()
277
+	{
278
+		return EE_Registry::instance()->SSN->set_session_data(
279
+			array(
280
+				\EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY => $this->submitted_values(true),
281
+			)
282
+		);
283
+	}
284
+
285
+
286
+
287
+	/**
288
+	 * retrieves the originally submitted input values in the session
289
+	 * so that they can be used to repopulate the form if it failed validation
290
+	 *
291
+	 * @return array
292
+	 */
293
+	protected function get_submitted_form_data_from_session()
294
+	{
295
+		$session = EE_Registry::instance()->SSN;
296
+		if ($session instanceof EE_Session) {
297
+			return $session->get_session_data(
298
+				\EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY
299
+			);
300
+		} else {
301
+			return array();
302
+		}
303
+	}
304
+
305
+
306
+
307
+	/**
308
+	 * flushed the originally submitted input values from the session
309
+	 *
310
+	 * @return boolean whether or not the data was successfully removed from the session
311
+	 */
312
+	protected function flush_submitted_form_data_from_session()
313
+	{
314
+		return EE_Registry::instance()->SSN->reset_data(
315
+			array(\EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY)
316
+		);
317
+	}
318
+
319
+
320
+
321
+	/**
322
+	 * Populates this form and its subsections with data from the session.
323
+	 * (Wrapper for EE_Form_Section_Proper::receive_form_submission, so it shows
324
+	 * validation errors when displaying too)
325
+	 * Returns true if the form was populated from the session, false otherwise
326
+	 *
327
+	 * @return boolean
328
+	 */
329
+	public function populate_from_session()
330
+	{
331
+		$form_data_in_session = $this->get_submitted_form_data_from_session();
332
+		if (empty($form_data_in_session)) {
333
+			return false;
334
+		}
335
+		$this->receive_form_submission($form_data_in_session);
336
+		$this->flush_submitted_form_data_from_session();
337
+		if ($this->form_data_present_in($form_data_in_session)) {
338
+			return true;
339
+		} else {
340
+			return false;
341
+		}
342
+	}
343
+
344
+
345
+
346
+	/**
347
+	 * Populates the default data for the form, given an array where keys are
348
+	 * the input names, and values are their values (preferably normalized to be their
349
+	 * proper PHP types, not all strings... although that should be ok too).
350
+	 * Proper subsections are sub-arrays, the key being the subsection's name, and
351
+	 * the value being an array formatted in teh same way
352
+	 *
353
+	 * @param array $default_data
354
+	 */
355
+	public function populate_defaults($default_data)
356
+	{
357
+		foreach ($this->subsections(false) as $subsection_name => $subsection) {
358
+			if (isset($default_data[$subsection_name])) {
359
+				if ($subsection instanceof EE_Form_Input_Base) {
360
+					$subsection->set_default($default_data[$subsection_name]);
361
+				} elseif ($subsection instanceof EE_Form_Section_Proper) {
362
+					$subsection->populate_defaults($default_data[$subsection_name]);
363
+				}
364
+			}
365
+		}
366
+	}
367
+
368
+
369
+
370
+	/**
371
+	 * returns true if subsection exists
372
+	 *
373
+	 * @param string $name
374
+	 * @return boolean
375
+	 */
376
+	public function subsection_exists($name)
377
+	{
378
+		return isset($this->_subsections[$name]) ? true : false;
379
+	}
380
+
381
+
382
+
383
+	/**
384
+	 * Gets the subsection specified by its name
385
+	 *
386
+	 * @param string  $name
387
+	 * @param boolean $require_construction_to_be_finalized most client code should leave this as TRUE
388
+	 *                                                      so that the inputs will be properly configured.
389
+	 *                                                      However, some client code may be ok
390
+	 *                                                      with construction finalize being called later
391
+	 *                                                      (realizing that the subsections' html names
392
+	 *                                                      might not be set yet, etc.)
393
+	 * @return EE_Form_Section_Base
394
+	 * @throws \EE_Error
395
+	 */
396
+	public function get_subsection($name, $require_construction_to_be_finalized = true)
397
+	{
398
+		if ($require_construction_to_be_finalized) {
399
+			$this->ensure_construct_finalized_called();
400
+		}
401
+		return $this->subsection_exists($name) ? $this->_subsections[$name] : null;
402
+	}
403
+
404
+
405
+
406
+	/**
407
+	 * Gets all the validatable subsections of this form section
408
+	 *
409
+	 * @return EE_Form_Section_Validatable[]
410
+	 */
411
+	public function get_validatable_subsections()
412
+	{
413
+		$validatable_subsections = array();
414
+		foreach ($this->subsections() as $name => $obj) {
415
+			if ($obj instanceof EE_Form_Section_Validatable) {
416
+				$validatable_subsections[$name] = $obj;
417
+			}
418
+		}
419
+		return $validatable_subsections;
420
+	}
421
+
422
+
423
+
424
+	/**
425
+	 * Gets an input by the given name. If not found, or if its not an EE_FOrm_Input_Base child,
426
+	 * throw an EE_Error.
427
+	 *
428
+	 * @param string  $name
429
+	 * @param boolean $require_construction_to_be_finalized most client code should
430
+	 *                                                      leave this as TRUE so that the inputs will be properly
431
+	 *                                                      configured. However, some client code may be ok with
432
+	 *                                                      construction finalize being called later
433
+	 *                                                      (realizing that the subsections' html names might not be
434
+	 *                                                      set yet, etc.)
435
+	 * @return EE_Form_Input_Base
436
+	 * @throws EE_Error
437
+	 */
438
+	public function get_input($name, $require_construction_to_be_finalized = true)
439
+	{
440
+		$subsection = $this->get_subsection($name, $require_construction_to_be_finalized);
441
+		if (! $subsection instanceof EE_Form_Input_Base) {
442
+			throw new EE_Error(
443
+				sprintf(
444
+					__(
445
+						"Subsection '%s' is not an instanceof EE_Form_Input_Base on form '%s'. It is a '%s'",
446
+						'event_espresso'
447
+					),
448
+					$name,
449
+					get_class($this),
450
+					$subsection ? get_class($subsection) : __("NULL", 'event_espresso')
451
+				)
452
+			);
453
+		}
454
+		return $subsection;
455
+	}
456
+
457
+
458
+
459
+	/**
460
+	 * Like get_input(), gets the proper subsection of the form given the name,
461
+	 * otherwise throws an EE_Error
462
+	 *
463
+	 * @param string  $name
464
+	 * @param boolean $require_construction_to_be_finalized most client code should
465
+	 *                                                      leave this as TRUE so that the inputs will be properly
466
+	 *                                                      configured. However, some client code may be ok with
467
+	 *                                                      construction finalize being called later
468
+	 *                                                      (realizing that the subsections' html names might not be
469
+	 *                                                      set yet, etc.)
470
+	 * @return EE_Form_Section_Proper
471
+	 * @throws EE_Error
472
+	 */
473
+	public function get_proper_subsection($name, $require_construction_to_be_finalized = true)
474
+	{
475
+		$subsection = $this->get_subsection($name, $require_construction_to_be_finalized);
476
+		if (! $subsection instanceof EE_Form_Section_Proper) {
477
+			throw new EE_Error(
478
+				sprintf(
479
+					__("Subsection '%'s is not an instanceof EE_Form_Section_Proper on form '%s'", 'event_espresso'),
480
+					$name,
481
+					get_class($this)
482
+				)
483
+			);
484
+		}
485
+		return $subsection;
486
+	}
487
+
488
+
489
+
490
+	/**
491
+	 * Gets the value of the specified input. Should be called after receive_form_submission()
492
+	 * or populate_defaults() on the form, where the normalized value on the input is set.
493
+	 *
494
+	 * @param string $name
495
+	 * @return mixed depending on the input's type and its normalization strategy
496
+	 * @throws \EE_Error
497
+	 */
498
+	public function get_input_value($name)
499
+	{
500
+		$input = $this->get_input($name);
501
+		return $input->normalized_value();
502
+	}
503
+
504
+
505
+
506
+	/**
507
+	 * Checks if this form section itself is valid, and then checks its subsections
508
+	 *
509
+	 * @throws EE_Error
510
+	 * @return boolean
511
+	 */
512
+	public function is_valid()
513
+	{
514
+		if (! $this->has_received_submission()) {
515
+			throw new EE_Error(
516
+				sprintf(
517
+					__(
518
+						"You cannot check if a form is valid before receiving the form submission using receive_form_submission",
519
+						"event_espresso"
520
+					)
521
+				)
522
+			);
523
+		}
524
+		if (! parent::is_valid()) {
525
+			return false;
526
+		}
527
+		// ok so no general errors to this entire form section.
528
+		// so let's check the subsections, but only set errors if that hasn't been done yet
529
+		$set_submission_errors = $this->submission_error_message() === '' ? true : false;
530
+		foreach ($this->get_validatable_subsections() as $subsection) {
531
+			if (! $subsection->is_valid() || $subsection->get_validation_error_string() !== '') {
532
+				if ($set_submission_errors) {
533
+					$this->set_submission_error_message($subsection->get_validation_error_string());
534
+				}
535
+				return false;
536
+			}
537
+		}
538
+		return true;
539
+	}
540
+
541
+
542
+
543
+	/**
544
+	 * gets teh default name of this form section if none is specified
545
+	 *
546
+	 * @return string
547
+	 */
548
+	protected function _set_default_name_if_empty()
549
+	{
550
+		if (! $this->_name) {
551
+			$classname = get_class($this);
552
+			$default_name = str_replace("EE_", "", $classname);
553
+			$this->_name = $default_name;
554
+		}
555
+	}
556
+
557
+
558
+
559
+	/**
560
+	 * Returns the HTML for the form, except for the form opening and closing tags
561
+	 * (as the form section doesn't know where you necessarily want to send the information to),
562
+	 * and except for a submit button. Enqueus JS and CSS; if called early enough we will
563
+	 * try to enqueue them in the header, otherwise they'll be enqueued in the footer.
564
+	 * Not doing_it_wrong because theoretically this CAN be used properly,
565
+	 * provided its used during "wp_enqueue_scripts", or it doesn't need to enqueue
566
+	 * any CSS.
567
+	 *
568
+	 * @throws \EE_Error
569
+	 */
570
+	public function get_html_and_js()
571
+	{
572
+		$this->enqueue_js();
573
+		return $this->get_html();
574
+	}
575
+
576
+
577
+
578
+	/**
579
+	 * returns HTML for displaying this form section. recursively calls display_section() on all subsections
580
+	 *
581
+	 * @param bool $display_previously_submitted_data
582
+	 * @return string
583
+	 */
584
+	public function get_html($display_previously_submitted_data = true)
585
+	{
586
+		$this->ensure_construct_finalized_called();
587
+		if ($display_previously_submitted_data) {
588
+			$this->populate_from_session();
589
+		}
590
+		return $this->_form_html_filter
591
+			? $this->_form_html_filter->filterHtml($this->_layout_strategy->layout_form(), $this)
592
+			: $this->_layout_strategy->layout_form();
593
+	}
594
+
595
+
596
+
597
+	/**
598
+	 * enqueues JS and CSS for the form.
599
+	 * It is preferred to call this before wp_enqueue_scripts so the
600
+	 * scripts and styles can be put in the header, but if called later
601
+	 * they will be put in the footer (which is OK for JS, but in HTML4 CSS should
602
+	 * only be in the header; but in HTML5 its ok in the body.
603
+	 * See http://stackoverflow.com/questions/4957446/load-external-css-file-in-body-tag.
604
+	 * So if your form enqueues CSS, it's preferred to call this before wp_enqueue_scripts.)
605
+	 *
606
+	 * @return string
607
+	 * @throws \EE_Error
608
+	 */
609
+	public function enqueue_js()
610
+	{
611
+		$this->_enqueue_and_localize_form_js();
612
+		foreach ($this->subsections() as $subsection) {
613
+			$subsection->enqueue_js();
614
+		}
615
+	}
616
+
617
+
618
+
619
+	/**
620
+	 * adds a filter so that jquery validate gets enqueued in EE_System::wp_enqueue_scripts().
621
+	 * This must be done BEFORE wp_enqueue_scripts() gets called, which is on
622
+	 * the wp_enqueue_scripts hook.
623
+	 * However, registering the form js and localizing it can happen when we
624
+	 * actually output the form (which is preferred, seeing how teh form's fields
625
+	 * could change until it's actually outputted)
626
+	 *
627
+	 * @param boolean $init_form_validation_automatically whether or not we want the form validation
628
+	 *                                                    to be triggered automatically or not
629
+	 * @return void
630
+	 */
631
+	public static function wp_enqueue_scripts($init_form_validation_automatically = true)
632
+	{
633
+		add_filter('FHEE_load_jquery_validate', '__return_true');
634
+		wp_register_script(
635
+			'ee_form_section_validation',
636
+			EE_GLOBAL_ASSETS_URL . 'scripts' . DS . 'form_section_validation.js',
637
+			array('jquery-validate', 'jquery-ui-datepicker', 'jquery-validate-extra-methods'),
638
+			EVENT_ESPRESSO_VERSION,
639
+			true
640
+		);
641
+		wp_localize_script(
642
+			'ee_form_section_validation',
643
+			'ee_form_section_validation_init',
644
+			array('init' => $init_form_validation_automatically ? true : false)
645
+		);
646
+	}
647
+
648
+
649
+
650
+	/**
651
+	 * gets the variables used by form_section_validation.js.
652
+	 * This needs to be called AFTER we've called $this->_enqueue_jquery_validate_script,
653
+	 * but before the wordpress hook wp_loaded
654
+	 *
655
+	 * @throws \EE_Error
656
+	 */
657
+	public function _enqueue_and_localize_form_js()
658
+	{
659
+		$this->ensure_construct_finalized_called();
660
+		//actually, we don't want to localize just yet. There may be other forms on the page.
661
+		//so we need to add our form section data to a static variable accessible by all form sections
662
+		//and localize it just before the footer
663
+		$this->localize_validation_rules();
664
+		add_action('wp_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'), 2);
665
+		add_action('admin_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'));
666
+	}
667
+
668
+
669
+
670
+	/**
671
+	 * add our form section data to a static variable accessible by all form sections
672
+	 *
673
+	 * @param bool $return_for_subsection
674
+	 * @return void
675
+	 * @throws \EE_Error
676
+	 */
677
+	public function localize_validation_rules($return_for_subsection = false)
678
+	{
679
+		// we only want to localize vars ONCE for the entire form,
680
+		// so if the form section doesn't have a parent, then it must be the top dog
681
+		if ($return_for_subsection || ! $this->parent_section()) {
682
+			EE_Form_Section_Proper::$_js_localization['form_data'][$this->html_id()] = array(
683
+				'form_section_id'  => $this->html_id(true),
684
+				'validation_rules' => $this->get_jquery_validation_rules(),
685
+				'other_data'       => $this->get_other_js_data(),
686
+				'errors'           => $this->subsection_validation_errors_by_html_name(),
687
+			);
688
+			EE_Form_Section_Proper::$_scripts_localized = true;
689
+		}
690
+	}
691
+
692
+
693
+
694
+	/**
695
+	 * Gets an array of extra data that will be useful for client-side javascript.
696
+	 * This is primarily data added by inputs and forms in addition to any
697
+	 * scripts they might enqueue
698
+	 *
699
+	 * @param array $form_other_js_data
700
+	 * @return array
701
+	 */
702
+	public function get_other_js_data($form_other_js_data = array())
703
+	{
704
+		foreach ($this->subsections() as $subsection) {
705
+			$form_other_js_data = $subsection->get_other_js_data($form_other_js_data);
706
+		}
707
+		return $form_other_js_data;
708
+	}
709
+
710
+
711
+
712
+	/**
713
+	 * Gets a flat array of inputs for this form section and its subsections.
714
+	 * Keys are their form names, and values are the inputs themselves
715
+	 *
716
+	 * @return EE_Form_Input_Base
717
+	 */
718
+	public function inputs_in_subsections()
719
+	{
720
+		$inputs = array();
721
+		foreach ($this->subsections() as $subsection) {
722
+			if ($subsection instanceof EE_Form_Input_Base) {
723
+				$inputs[$subsection->html_name()] = $subsection;
724
+			} elseif ($subsection instanceof EE_Form_Section_Proper) {
725
+				$inputs += $subsection->inputs_in_subsections();
726
+			}
727
+		}
728
+		return $inputs;
729
+	}
730
+
731
+
732
+
733
+	/**
734
+	 * Gets a flat array of all the validation errors.
735
+	 * Keys are html names (because those should be unique)
736
+	 * and values are a string of all their validation errors
737
+	 *
738
+	 * @return string[]
739
+	 */
740
+	public function subsection_validation_errors_by_html_name()
741
+	{
742
+		$inputs = $this->inputs();
743
+		$errors = array();
744
+		foreach ($inputs as $form_input) {
745
+			if ($form_input instanceof EE_Form_Input_Base && $form_input->get_validation_errors()) {
746
+				$errors[$form_input->html_name()] = $form_input->get_validation_error_string();
747
+			}
748
+		}
749
+		return $errors;
750
+	}
751
+
752
+
753
+
754
+	/**
755
+	 * passes all the form data required by the JS to the JS, and enqueues the few required JS files.
756
+	 * Should be setup by each form during the _enqueues_and_localize_form_js
757
+	 */
758
+	public static function localize_script_for_all_forms()
759
+	{
760
+		//allow inputs and stuff to hook in their JS and stuff here
761
+		do_action('AHEE__EE_Form_Section_Proper__localize_script_for_all_forms__begin');
762
+		EE_Form_Section_Proper::$_js_localization['localized_error_messages'] = EE_Form_Section_Proper::_get_localized_error_messages();
763
+		$email_validation_level = isset(EE_Registry::instance()->CFG->registration->email_validation_level)
764
+			? EE_Registry::instance()->CFG->registration->email_validation_level
765
+			: 'wp_default';
766
+		EE_Form_Section_Proper::$_js_localization['email_validation_level'] = $email_validation_level;
767
+		wp_enqueue_script('ee_form_section_validation');
768
+		wp_localize_script(
769
+			'ee_form_section_validation',
770
+			'ee_form_section_vars',
771
+			EE_Form_Section_Proper::$_js_localization
772
+		);
773
+	}
774
+
775
+
776
+
777
+	/**
778
+	 * ensure_scripts_localized
779
+	 */
780
+	public function ensure_scripts_localized()
781
+	{
782
+		if (! EE_Form_Section_Proper::$_scripts_localized) {
783
+			$this->_enqueue_and_localize_form_js();
784
+		}
785
+	}
786
+
787
+
788
+
789
+	/**
790
+	 * Gets the hard-coded validation error messages to be used in the JS. The convention
791
+	 * is that the key here should be the same as the custom validation rule put in the JS file
792
+	 *
793
+	 * @return array keys are custom validation rules, and values are internationalized strings
794
+	 */
795
+	private static function _get_localized_error_messages()
796
+	{
797
+		return array(
798
+			'validUrl' => __("This is not a valid absolute URL. Eg, http://domain.com/monkey.jpg", "event_espresso"),
799
+			'regex'    => __('Please check your input', 'event_espresso'),
800
+		);
801
+	}
802
+
803
+
804
+
805
+	/**
806
+	 * @return array
807
+	 */
808
+	public static function js_localization()
809
+	{
810
+		return self::$_js_localization;
811
+	}
812
+
813
+
814
+
815
+	/**
816
+	 * @return array
817
+	 */
818
+	public static function reset_js_localization()
819
+	{
820
+		self::$_js_localization = array();
821
+	}
822
+
823
+
824
+
825
+	/**
826
+	 * Gets the JS to put inside the jquery validation rules for subsection of this form section.
827
+	 * See parent function for more...
828
+	 *
829
+	 * @return array
830
+	 */
831
+	public function get_jquery_validation_rules()
832
+	{
833
+		$jquery_validation_rules = array();
834
+		foreach ($this->get_validatable_subsections() as $subsection) {
835
+			$jquery_validation_rules = array_merge(
836
+				$jquery_validation_rules,
837
+				$subsection->get_jquery_validation_rules()
838
+			);
839
+		}
840
+		return $jquery_validation_rules;
841
+	}
842
+
843
+
844
+
845
+	/**
846
+	 * Sanitizes all the data and sets the sanitized value of each field
847
+	 *
848
+	 * @param array $req_data like $_POST
849
+	 * @return void
850
+	 */
851
+	protected function _normalize($req_data)
852
+	{
853
+		$this->_received_submission = true;
854
+		$this->_validation_errors = array();
855
+		foreach ($this->get_validatable_subsections() as $subsection) {
856
+			try {
857
+				$subsection->_normalize($req_data);
858
+			} catch (EE_Validation_Error $e) {
859
+				$subsection->add_validation_error($e);
860
+			}
861
+		}
862
+	}
863
+
864
+
865
+
866
+	/**
867
+	 * Performs validation on this form section and its subsections.
868
+	 * For each subsection,
869
+	 * calls _validate_{subsection_name} on THIS form (if the function exists)
870
+	 * and passes it the subsection, then calls _validate on that subsection.
871
+	 * If you need to perform validation on the form as a whole (considering multiple)
872
+	 * you would be best to override this _validate method,
873
+	 * calling parent::_validate() first.
874
+	 */
875
+	protected function _validate()
876
+	{
877
+		foreach ($this->get_validatable_subsections() as $subsection_name => $subsection) {
878
+			if (method_exists($this, '_validate_' . $subsection_name)) {
879
+				call_user_func_array(array($this, '_validate_' . $subsection_name), array($subsection));
880
+			}
881
+			$subsection->_validate();
882
+		}
883
+	}
884
+
885
+
886
+
887
+	/**
888
+	 * Gets all the validated inputs for the form section
889
+	 *
890
+	 * @return array
891
+	 */
892
+	public function valid_data()
893
+	{
894
+		$inputs = array();
895
+		foreach ($this->subsections() as $subsection_name => $subsection) {
896
+			if ($subsection instanceof EE_Form_Section_Proper) {
897
+				$inputs[$subsection_name] = $subsection->valid_data();
898
+			} else if ($subsection instanceof EE_Form_Input_Base) {
899
+				$inputs[$subsection_name] = $subsection->normalized_value();
900
+			}
901
+		}
902
+		return $inputs;
903
+	}
904
+
905
+
906
+
907
+	/**
908
+	 * Gets all the inputs on this form section
909
+	 *
910
+	 * @return EE_Form_Input_Base[]
911
+	 */
912
+	public function inputs()
913
+	{
914
+		$inputs = array();
915
+		foreach ($this->subsections() as $subsection_name => $subsection) {
916
+			if ($subsection instanceof EE_Form_Input_Base) {
917
+				$inputs[$subsection_name] = $subsection;
918
+			}
919
+		}
920
+		return $inputs;
921
+	}
922
+
923
+
924
+
925
+	/**
926
+	 * Gets all the subsections which are a proper form
927
+	 *
928
+	 * @return EE_Form_Section_Proper[]
929
+	 */
930
+	public function subforms()
931
+	{
932
+		$form_sections = array();
933
+		foreach ($this->subsections() as $name => $obj) {
934
+			if ($obj instanceof EE_Form_Section_Proper) {
935
+				$form_sections[$name] = $obj;
936
+			}
937
+		}
938
+		return $form_sections;
939
+	}
940
+
941
+
942
+
943
+	/**
944
+	 * Gets all the subsections (inputs, proper subsections, or html-only sections).
945
+	 * Consider using inputs() or subforms()
946
+	 * if you only want form inputs or proper form sections.
947
+	 *
948
+	 * @param boolean $require_construction_to_be_finalized most client code should
949
+	 *                                                      leave this as TRUE so that the inputs will be properly
950
+	 *                                                      configured. However, some client code may be ok with
951
+	 *                                                      construction finalize being called later
952
+	 *                                                      (realizing that the subsections' html names might not be
953
+	 *                                                      set yet, etc.)
954
+	 * @return EE_Form_Section_Proper[]
955
+	 */
956
+	public function subsections($require_construction_to_be_finalized = true)
957
+	{
958
+		if ($require_construction_to_be_finalized) {
959
+			$this->ensure_construct_finalized_called();
960
+		}
961
+		return $this->_subsections;
962
+	}
963
+
964
+
965
+
966
+	/**
967
+	 * Returns a simple array where keys are input names, and values are their normalized
968
+	 * values. (Similar to calling get_input_value on inputs)
969
+	 *
970
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
971
+	 *                                        or just this forms' direct children inputs
972
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
973
+	 *                                        or allow multidimensional array
974
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array
975
+	 *                                        with array keys being input names
976
+	 *                                        (regardless of whether they are from a subsection or not),
977
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
978
+	 *                                        where keys are always subsection names and values are either
979
+	 *                                        the input's normalized value, or an array like the top-level array
980
+	 */
981
+	public function input_values($include_subform_inputs = false, $flatten = false)
982
+	{
983
+		return $this->_input_values(false, $include_subform_inputs, $flatten);
984
+	}
985
+
986
+
987
+
988
+	/**
989
+	 * Similar to EE_Form_Section_Proper::input_values(), except this returns the 'display_value'
990
+	 * of each input. On some inputs (especially radio boxes or checkboxes), the value stored
991
+	 * is not necessarily the value we want to display to users. This creates an array
992
+	 * where keys are the input names, and values are their display values
993
+	 *
994
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
995
+	 *                                        or just this forms' direct children inputs
996
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
997
+	 *                                        or allow multidimensional array
998
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array
999
+	 *                                        with array keys being input names
1000
+	 *                                        (regardless of whether they are from a subsection or not),
1001
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1002
+	 *                                        where keys are always subsection names and values are either
1003
+	 *                                        the input's normalized value, or an array like the top-level array
1004
+	 */
1005
+	public function input_pretty_values($include_subform_inputs = false, $flatten = false)
1006
+	{
1007
+		return $this->_input_values(true, $include_subform_inputs, $flatten);
1008
+	}
1009
+
1010
+
1011
+
1012
+	/**
1013
+	 * Gets the input values from the form
1014
+	 *
1015
+	 * @param boolean $pretty                 Whether to retrieve the pretty value,
1016
+	 *                                        or just the normalized value
1017
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1018
+	 *                                        or just this forms' direct children inputs
1019
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1020
+	 *                                        or allow multidimensional array
1021
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array with array keys being
1022
+	 *                                        input names (regardless of whether they are from a subsection or not),
1023
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1024
+	 *                                        where keys are always subsection names and values are either
1025
+	 *                                        the input's normalized value, or an array like the top-level array
1026
+	 */
1027
+	public function _input_values($pretty = false, $include_subform_inputs = false, $flatten = false)
1028
+	{
1029
+		$input_values = array();
1030
+		foreach ($this->subsections() as $subsection_name => $subsection) {
1031
+			if ($subsection instanceof EE_Form_Input_Base) {
1032
+				$input_values[$subsection_name] = $pretty
1033
+					? $subsection->pretty_value()
1034
+					: $subsection->normalized_value();
1035
+			} else if ($subsection instanceof EE_Form_Section_Proper && $include_subform_inputs) {
1036
+				$subform_input_values = $subsection->_input_values($pretty, $include_subform_inputs, $flatten);
1037
+				if ($flatten) {
1038
+					$input_values = array_merge($input_values, $subform_input_values);
1039
+				} else {
1040
+					$input_values[$subsection_name] = $subform_input_values;
1041
+				}
1042
+			}
1043
+		}
1044
+		return $input_values;
1045
+	}
1046
+
1047
+
1048
+
1049
+	/**
1050
+	 * Gets the originally submitted input values from the form
1051
+	 *
1052
+	 * @param boolean $include_subforms  Whether to include inputs from subforms,
1053
+	 *                                   or just this forms' direct children inputs
1054
+	 * @return array                     if $flatten is TRUE it will always be a 1-dimensional array
1055
+	 *                                   with array keys being input names
1056
+	 *                                   (regardless of whether they are from a subsection or not),
1057
+	 *                                   and if $flatten is FALSE it can be a multidimensional array
1058
+	 *                                   where keys are always subsection names and values are either
1059
+	 *                                   the input's normalized value, or an array like the top-level array
1060
+	 */
1061
+	public function submitted_values($include_subforms = false)
1062
+	{
1063
+		$submitted_values = array();
1064
+		foreach ($this->subsections() as $subsection) {
1065
+			if ($subsection instanceof EE_Form_Input_Base) {
1066
+				// is this input part of an array of inputs?
1067
+				if (strpos($subsection->html_name(), '[') !== false) {
1068
+					$full_input_name = \EEH_Array::convert_array_values_to_keys(
1069
+						explode('[', str_replace(']', '', $subsection->html_name())),
1070
+						$subsection->raw_value()
1071
+					);
1072
+					$submitted_values = array_replace_recursive($submitted_values, $full_input_name);
1073
+				} else {
1074
+					$submitted_values[$subsection->html_name()] = $subsection->raw_value();
1075
+				}
1076
+			} else if ($subsection instanceof EE_Form_Section_Proper && $include_subforms) {
1077
+				$subform_input_values = $subsection->submitted_values($include_subforms);
1078
+				$submitted_values = array_replace_recursive($submitted_values, $subform_input_values);
1079
+			}
1080
+		}
1081
+		return $submitted_values;
1082
+	}
1083
+
1084
+
1085
+
1086
+	/**
1087
+	 * Indicates whether or not this form has received a submission yet
1088
+	 * (ie, had receive_form_submission called on it yet)
1089
+	 *
1090
+	 * @return boolean
1091
+	 * @throws \EE_Error
1092
+	 */
1093
+	public function has_received_submission()
1094
+	{
1095
+		$this->ensure_construct_finalized_called();
1096
+		return $this->_received_submission;
1097
+	}
1098
+
1099
+
1100
+
1101
+	/**
1102
+	 * Equivalent to passing 'exclude' in the constructor's options array.
1103
+	 * Removes the listed inputs from the form
1104
+	 *
1105
+	 * @param array $inputs_to_exclude values are the input names
1106
+	 * @return void
1107
+	 */
1108
+	public function exclude(array $inputs_to_exclude = array())
1109
+	{
1110
+		foreach ($inputs_to_exclude as $input_to_exclude_name) {
1111
+			unset($this->_subsections[$input_to_exclude_name]);
1112
+		}
1113
+	}
1114
+
1115
+
1116
+
1117
+	/**
1118
+	 * @param array $inputs_to_hide
1119
+	 * @throws \EE_Error
1120
+	 */
1121
+	public function hide(array $inputs_to_hide = array())
1122
+	{
1123
+		foreach ($inputs_to_hide as $input_to_hide) {
1124
+			$input = $this->get_input($input_to_hide);
1125
+			$input->set_display_strategy(new EE_Hidden_Display_Strategy());
1126
+		}
1127
+	}
1128
+
1129
+
1130
+
1131
+	/**
1132
+	 * add_subsections
1133
+	 * Adds the listed subsections to the form section.
1134
+	 * If $subsection_name_to_target is provided,
1135
+	 * then new subsections are added before or after that subsection,
1136
+	 * otherwise to the start or end of the entire subsections array.
1137
+	 *
1138
+	 * @param EE_Form_Section_Base[] $new_subsections           array of new form subsections
1139
+	 *                                                          where keys are their names
1140
+	 * @param string                 $subsection_name_to_target an existing for section that $new_subsections
1141
+	 *                                                          should be added before or after
1142
+	 *                                                          IF $subsection_name_to_target is null,
1143
+	 *                                                          then $new_subsections will be added to
1144
+	 *                                                          the beginning or end of the entire subsections array
1145
+	 * @param boolean                $add_before                whether to add $new_subsections, before or after
1146
+	 *                                                          $subsection_name_to_target,
1147
+	 *                                                          or if $subsection_name_to_target is null,
1148
+	 *                                                          before or after entire subsections array
1149
+	 * @return void
1150
+	 * @throws \EE_Error
1151
+	 */
1152
+	public function add_subsections($new_subsections, $subsection_name_to_target = null, $add_before = true)
1153
+	{
1154
+		foreach ($new_subsections as $subsection_name => $subsection) {
1155
+			if (! $subsection instanceof EE_Form_Section_Base) {
1156
+				EE_Error::add_error(
1157
+					sprintf(
1158
+						__(
1159
+							"Trying to add a %s as a subsection (it was named '%s') to the form section '%s'. It was removed.",
1160
+							"event_espresso"
1161
+						),
1162
+						get_class($subsection),
1163
+						$subsection_name,
1164
+						$this->name()
1165
+					)
1166
+				);
1167
+				unset($new_subsections[$subsection_name]);
1168
+			}
1169
+		}
1170
+		$this->_subsections = EEH_Array::insert_into_array(
1171
+			$this->_subsections,
1172
+			$new_subsections,
1173
+			$subsection_name_to_target,
1174
+			$add_before
1175
+		);
1176
+		if ($this->_construction_finalized) {
1177
+			foreach ($this->_subsections as $name => $subsection) {
1178
+				$subsection->_construct_finalize($this, $name);
1179
+			}
1180
+		}
1181
+	}
1182
+
1183
+
1184
+
1185
+	/**
1186
+	 * Just gets all validatable subsections to clean their sensitive data
1187
+	 */
1188
+	public function clean_sensitive_data()
1189
+	{
1190
+		foreach ($this->get_validatable_subsections() as $subsection) {
1191
+			$subsection->clean_sensitive_data();
1192
+		}
1193
+	}
1194
+
1195
+
1196
+
1197
+	/**
1198
+	 * @param string $form_submission_error_message
1199
+	 */
1200
+	public function set_submission_error_message($form_submission_error_message = '')
1201
+	{
1202
+		$this->_form_submission_error_message .= ! empty($form_submission_error_message)
1203
+			? $form_submission_error_message
1204
+			: __('Form submission failed due to errors', 'event_espresso');
1205
+	}
1206
+
1207
+
1208
+
1209
+	/**
1210
+	 * @return string
1211
+	 */
1212
+	public function submission_error_message()
1213
+	{
1214
+		return $this->_form_submission_error_message;
1215
+	}
1216
+
1217
+
1218
+
1219
+	/**
1220
+	 * @param string $form_submission_success_message
1221
+	 */
1222
+	public function set_submission_success_message($form_submission_success_message)
1223
+	{
1224
+		$this->_form_submission_success_message .= ! empty($form_submission_success_message)
1225
+			? $form_submission_success_message
1226
+			: __('Form submitted successfully', 'event_espresso');
1227
+	}
1228
+
1229
+
1230
+
1231
+	/**
1232
+	 * @return string
1233
+	 */
1234
+	public function submission_success_message()
1235
+	{
1236
+		return $this->_form_submission_success_message;
1237
+	}
1238
+
1239
+
1240
+
1241
+	/**
1242
+	 * Returns the prefix that should be used on child of this form section for
1243
+	 * their html names. If this form section itself has a parent, prepends ITS
1244
+	 * prefix onto this form section's prefix. Used primarily by
1245
+	 * EE_Form_Input_Base::_set_default_html_name_if_empty
1246
+	 *
1247
+	 * @return string
1248
+	 * @throws \EE_Error
1249
+	 */
1250
+	public function html_name_prefix()
1251
+	{
1252
+		if ($this->parent_section() instanceof EE_Form_Section_Proper) {
1253
+			return $this->parent_section()->html_name_prefix() . '[' . $this->name() . ']';
1254
+		} else {
1255
+			return $this->name();
1256
+		}
1257
+	}
1258
+
1259
+
1260
+
1261
+	/**
1262
+	 * Gets the name, but first checks _construct_finalize has been called. If not,
1263
+	 * calls it (assumes there is no parent and that we want the name to be whatever
1264
+	 * was set, which is probably nothing, or the classname)
1265
+	 *
1266
+	 * @return string
1267
+	 * @throws \EE_Error
1268
+	 */
1269
+	public function name()
1270
+	{
1271
+		$this->ensure_construct_finalized_called();
1272
+		return parent::name();
1273
+	}
1274
+
1275
+
1276
+
1277
+	/**
1278
+	 * @return EE_Form_Section_Proper
1279
+	 * @throws \EE_Error
1280
+	 */
1281
+	public function parent_section()
1282
+	{
1283
+		$this->ensure_construct_finalized_called();
1284
+		return parent::parent_section();
1285
+	}
1286
+
1287
+
1288
+
1289
+	/**
1290
+	 * make sure construction finalized was called, otherwise children might not be ready
1291
+	 *
1292
+	 * @return void
1293
+	 * @throws \EE_Error
1294
+	 */
1295
+	public function ensure_construct_finalized_called()
1296
+	{
1297
+		if (! $this->_construction_finalized) {
1298
+			$this->_construct_finalize($this->_parent_section, $this->_name);
1299
+		}
1300
+	}
1301
+
1302
+
1303
+
1304
+	/**
1305
+	 * Checks if any of this form section's inputs, or any of its children's inputs,
1306
+	 * are in teh form data. If any are found, returns true. Else false
1307
+	 *
1308
+	 * @param array $req_data
1309
+	 * @return boolean
1310
+	 */
1311
+	public function form_data_present_in($req_data = null)
1312
+	{
1313
+		if ($req_data === null) {
1314
+			$req_data = $_POST;
1315
+		}
1316
+		foreach ($this->subsections() as $subsection) {
1317
+			if ($subsection instanceof EE_Form_Input_Base) {
1318
+				if ($subsection->form_data_present_in($req_data)) {
1319
+					return true;
1320
+				}
1321
+			} elseif ($subsection instanceof EE_Form_Section_Proper) {
1322
+				if ($subsection->form_data_present_in($req_data)) {
1323
+					return true;
1324
+				}
1325
+			}
1326
+		}
1327
+		return false;
1328
+	}
1329
+
1330
+
1331
+
1332
+	/**
1333
+	 * Gets validation errors for this form section and subsections
1334
+	 * Similar to EE_Form_Section_Validatable::get_validation_errors() except this
1335
+	 * gets the validation errors for ALL subsection
1336
+	 *
1337
+	 * @return EE_Validation_Error[]
1338
+	 */
1339
+	public function get_validation_errors_accumulated()
1340
+	{
1341
+		$validation_errors = $this->get_validation_errors();
1342
+		foreach ($this->get_validatable_subsections() as $subsection) {
1343
+			if ($subsection instanceof EE_Form_Section_Proper) {
1344
+				$validation_errors_on_this_subsection = $subsection->get_validation_errors_accumulated();
1345
+			} else {
1346
+				$validation_errors_on_this_subsection = $subsection->get_validation_errors();
1347
+			}
1348
+			if ($validation_errors_on_this_subsection) {
1349
+				$validation_errors = array_merge($validation_errors, $validation_errors_on_this_subsection);
1350
+			}
1351
+		}
1352
+		return $validation_errors;
1353
+	}
1354
+
1355
+
1356
+
1357
+	/**
1358
+	 * This isn't just the name of an input, it's a path pointing to an input. The
1359
+	 * path is similar to a folder path: slash (/) means to descend into a subsection,
1360
+	 * dot-dot-slash (../) means to ascend into the parent section.
1361
+	 * After a series of slashes and dot-dot-slashes, there should be the name of an input,
1362
+	 * which will be returned.
1363
+	 * Eg, if you want the related input to be conditional on a sibling input name 'foobar'
1364
+	 * just use 'foobar'. If you want it to be conditional on an aunt/uncle input name
1365
+	 * 'baz', use '../baz'. If you want it to be conditional on a cousin input,
1366
+	 * the child of 'baz_section' named 'baz_child', use '../baz_section/baz_child'.
1367
+	 * Etc
1368
+	 *
1369
+	 * @param string|false $form_section_path we accept false also because substr( '../', '../' ) = false
1370
+	 * @return EE_Form_Section_Base
1371
+	 */
1372
+	public function find_section_from_path($form_section_path)
1373
+	{
1374
+		//check if we can find the input from purely going straight up the tree
1375
+		$input = parent::find_section_from_path($form_section_path);
1376
+		if ($input instanceof EE_Form_Section_Base) {
1377
+			return $input;
1378
+		}
1379
+		$next_slash_pos = strpos($form_section_path, '/');
1380
+		if ($next_slash_pos !== false) {
1381
+			$child_section_name = substr($form_section_path, 0, $next_slash_pos);
1382
+			$subpath = substr($form_section_path, $next_slash_pos + 1);
1383
+		} else {
1384
+			$child_section_name = $form_section_path;
1385
+			$subpath = '';
1386
+		}
1387
+		$child_section = $this->get_subsection($child_section_name);
1388
+		if ($child_section instanceof EE_Form_Section_Base) {
1389
+			return $child_section->find_section_from_path($subpath);
1390
+		} else {
1391
+			return null;
1392
+		}
1393
+	}
1394 1394
 
1395 1395
 }
1396 1396
 
Please login to merge, or discard this patch.
core/libraries/form_sections/inputs/EE_Form_Input_Base.input.php 1 patch
Indentation   +1127 added lines, -1127 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,1130 +16,1130 @@  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
-     * Strategy used for displaying this field.
132
-     * Child classes must use _get_display_strategy to access it.
133
-     *
134
-     * @var EE_Display_Strategy_Base
135
-     */
136
-    private $_display_strategy;
137
-
138
-    /**
139
-     * Gets all the validation strategies used on this field
140
-     *
141
-     * @var EE_Validation_Strategy_Base[]
142
-     */
143
-    private $_validation_strategies = array();
144
-
145
-    /**
146
-     * The normalization strategy for this field
147
-     *
148
-     * @var EE_Normalization_Strategy_Base
149
-     */
150
-    private $_normalization_strategy;
151
-
152
-    /**
153
-     * Strategy for removing sensitive data after we're done with the form input
154
-     *
155
-     * @var EE_Sensitive_Data_Removal_Base
156
-     */
157
-    protected $_sensitive_data_removal_strategy;
158
-
159
-
160
-
161
-    /**
162
-     * @param array                         $input_args       {
163
-     * @type string                         $html_name        the html name for the input
164
-     * @type string                         $html_label_id    the id attribute to give to the html label tag
165
-     * @type string                         $html_label_class the class attribute to give to the html label tag
166
-     * @type string                         $html_label_style the style attribute to give ot teh label tag
167
-     * @type string                         $html_label_text  the text to put in the label tag
168
-     * @type string                         $html_label       the full html label. If used,
169
-     *                                                        all other html_label_* args are invalid
170
-     * @type string                         $html_help_text   text to put in help element
171
-     * @type string                         $html_help_style  style attribute to give to teh help element
172
-     * @type string                         $html_help_class  class attribute to give to the help element
173
-     * @type string                         $default          default value NORMALIZED (eg, if providing the default
174
-     *       for a Yes_No_Input, you should provide TRUE or FALSE, not '1' or '0')
175
-     * @type EE_Display_Strategy_Base       $display          strategy
176
-     * @type EE_Normalization_Strategy_Base $normalization_strategy
177
-     * @type EE_Validation_Strategy_Base[]  $validation_strategies
178
-     *                                                        }
179
-     */
180
-    public function __construct($input_args = array())
181
-    {
182
-        $input_args = (array)apply_filters('FHEE__EE_Form_Input_Base___construct__input_args', $input_args, $this);
183
-        // the following properties must be cast as arrays
184
-        if (isset($input_args['validation_strategies'])) {
185
-            foreach ((array)$input_args['validation_strategies'] as $validation_strategy) {
186
-                if ($validation_strategy instanceof EE_Validation_Strategy_Base) {
187
-                    $this->_validation_strategies[get_class($validation_strategy)] = $validation_strategy;
188
-                }
189
-            }
190
-            unset($input_args['validation_strategies']);
191
-        }
192
-        // loop thru incoming options
193
-        foreach ($input_args as $key => $value) {
194
-            // add underscore to $key to match property names
195
-            $_key = '_' . $key;
196
-            if (property_exists($this, $_key)) {
197
-                $this->{$_key} = $value;
198
-            }
199
-        }
200
-        // ensure that "required" is set correctly
201
-        $this->set_required(
202
-            $this->_required, isset($input_args['required_validation_error_message'])
203
-            ? $input_args['required_validation_error_message']
204
-            : null
205
-        );
206
-        //$this->_html_name_specified = isset( $input_args['html_name'] ) ? TRUE : FALSE;
207
-        $this->_display_strategy->_construct_finalize($this);
208
-        foreach ($this->_validation_strategies as $validation_strategy) {
209
-            $validation_strategy->_construct_finalize($this);
210
-        }
211
-        if (! $this->_normalization_strategy) {
212
-            $this->_normalization_strategy = new EE_Text_Normalization();
213
-        }
214
-        $this->_normalization_strategy->_construct_finalize($this);
215
-        //at least we can use the normalization strategy to populate the default
216
-        if (isset($input_args['default'])) {
217
-            $this->set_default($input_args['default']);
218
-        }
219
-        if (! $this->_sensitive_data_removal_strategy) {
220
-            $this->_sensitive_data_removal_strategy = new EE_No_Sensitive_Data_Removal();
221
-        }
222
-        $this->_sensitive_data_removal_strategy->_construct_finalize($this);
223
-        parent::__construct($input_args);
224
-    }
225
-
226
-
227
-
228
-    /**
229
-     * Sets the html_name to its default value, if none was specified in teh constructor.
230
-     * Calculation involves using the name and the parent's html_name
231
-     *
232
-     * @throws \EE_Error
233
-     */
234
-    protected function _set_default_html_name_if_empty()
235
-    {
236
-        if (! $this->_html_name) {
237
-            $this->_html_name = $this->name();
238
-            if ($this->_parent_section && $this->_parent_section instanceof EE_Form_Section_Proper) {
239
-                $this->_html_name = $this->_parent_section->html_name_prefix() . "[{$this->name()}]";
240
-            }
241
-        }
242
-    }
243
-
244
-
245
-
246
-    /**
247
-     * @param $parent_form_section
248
-     * @param $name
249
-     * @throws \EE_Error
250
-     */
251
-    public function _construct_finalize($parent_form_section, $name)
252
-    {
253
-        parent::_construct_finalize($parent_form_section, $name);
254
-        if ($this->_html_label === null && $this->_html_label_text === null) {
255
-            $this->_html_label_text = ucwords(str_replace("_", " ", $name));
256
-        }
257
-        do_action('AHEE__EE_Form_Input_Base___construct_finalize__end', $this, $parent_form_section, $name);
258
-    }
259
-
260
-
261
-
262
-    /**
263
-     * Returns the strategy for displaying this form input. If none is set, throws an exception.
264
-     *
265
-     * @return EE_Display_Strategy_Base
266
-     * @throws EE_Error
267
-     */
268
-    protected function _get_display_strategy()
269
-    {
270
-        $this->ensure_construct_finalized_called();
271
-        if (! $this->_display_strategy || ! $this->_display_strategy instanceof EE_Display_Strategy_Base) {
272
-            throw new EE_Error(
273
-                sprintf(
274
-                    __(
275
-                        "Cannot get display strategy for form input with name %s and id %s, because it has not been set in the constructor",
276
-                        "event_espresso"
277
-                    ),
278
-                    $this->html_name(),
279
-                    $this->html_id()
280
-                )
281
-            );
282
-        } else {
283
-            return $this->_display_strategy;
284
-        }
285
-    }
286
-
287
-
288
-
289
-    /**
290
-     * Sets the display strategy.
291
-     *
292
-     * @param EE_Display_Strategy_Base $strategy
293
-     */
294
-    protected function _set_display_strategy(EE_Display_Strategy_Base $strategy)
295
-    {
296
-        $this->_display_strategy = $strategy;
297
-    }
298
-
299
-
300
-
301
-    /**
302
-     * Sets the sanitization strategy
303
-     *
304
-     * @param EE_Normalization_Strategy_Base $strategy
305
-     */
306
-    protected function _set_normalization_strategy(EE_Normalization_Strategy_Base $strategy)
307
-    {
308
-        $this->_normalization_strategy = $strategy;
309
-    }
310
-
311
-
312
-
313
-    /**
314
-     * Gets sensitive_data_removal_strategy
315
-     *
316
-     * @return EE_Sensitive_Data_Removal_Base
317
-     */
318
-    public function get_sensitive_data_removal_strategy()
319
-    {
320
-        return $this->_sensitive_data_removal_strategy;
321
-    }
322
-
323
-
324
-
325
-    /**
326
-     * Sets sensitive_data_removal_strategy
327
-     *
328
-     * @param EE_Sensitive_Data_Removal_Base $sensitive_data_removal_strategy
329
-     * @return boolean
330
-     */
331
-    public function set_sensitive_data_removal_strategy($sensitive_data_removal_strategy)
332
-    {
333
-        $this->_sensitive_data_removal_strategy = $sensitive_data_removal_strategy;
334
-    }
335
-
336
-
337
-
338
-    /**
339
-     * Gets the display strategy for this input
340
-     *
341
-     * @return EE_Display_Strategy_Base
342
-     */
343
-    public function get_display_strategy()
344
-    {
345
-        return $this->_display_strategy;
346
-    }
347
-
348
-
349
-
350
-    /**
351
-     * Overwrites the display strategy
352
-     *
353
-     * @param EE_Display_Strategy_Base $display_strategy
354
-     */
355
-    public function set_display_strategy($display_strategy)
356
-    {
357
-        $this->_display_strategy = $display_strategy;
358
-        $this->_display_strategy->_construct_finalize($this);
359
-    }
360
-
361
-
362
-
363
-    /**
364
-     * Gets the normalization strategy set on this input
365
-     *
366
-     * @return EE_Normalization_Strategy_Base
367
-     */
368
-    public function get_normalization_strategy()
369
-    {
370
-        return $this->_normalization_strategy;
371
-    }
372
-
373
-
374
-
375
-    /**
376
-     * Overwrites the normalization strategy
377
-     *
378
-     * @param EE_Normalization_Strategy_Base $normalization_strategy
379
-     */
380
-    public function set_normalization_strategy($normalization_strategy)
381
-    {
382
-        $this->_normalization_strategy = $normalization_strategy;
383
-        $this->_normalization_strategy->_construct_finalize($this);
384
-    }
385
-
386
-
387
-
388
-    /**
389
-     * Returns all teh validation strategies which apply to this field, numerically indexed
390
-     *
391
-     * @return EE_Validation_Strategy_Base[]
392
-     */
393
-    public function get_validation_strategies()
394
-    {
395
-        return $this->_validation_strategies;
396
-    }
397
-
398
-
399
-
400
-    /**
401
-     * Adds this strategy to the field so it will be used in both JS validation and server-side validation
402
-     *
403
-     * @param EE_Validation_Strategy_Base $validation_strategy
404
-     * @return void
405
-     */
406
-    protected function _add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
407
-    {
408
-        $validation_strategy->_construct_finalize($this);
409
-        $this->_validation_strategies[] = $validation_strategy;
410
-    }
411
-
412
-
413
-
414
-    /**
415
-     * Adds a new validation strategy onto the form input
416
-     *
417
-     * @param EE_Validation_Strategy_Base $validation_strategy
418
-     * @return void
419
-     */
420
-    public function add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
421
-    {
422
-        $this->_add_validation_strategy($validation_strategy);
423
-    }
424
-
425
-
426
-
427
-    /**
428
-     * The classname of the validation strategy to remove
429
-     *
430
-     * @param string $validation_strategy_classname
431
-     */
432
-    public function remove_validation_strategy($validation_strategy_classname)
433
-    {
434
-        foreach ($this->_validation_strategies as $key => $validation_strategy) {
435
-            if (
436
-                $validation_strategy instanceof $validation_strategy_classname
437
-                || is_subclass_of($validation_strategy, $validation_strategy_classname)
438
-            ) {
439
-                unset($this->_validation_strategies[$key]);
440
-            }
441
-        }
442
-    }
443
-
444
-
445
-
446
-    /**
447
-     * returns true if input employs any of the validation strategy defined by the supplied array of classnames
448
-     *
449
-     * @param array $validation_strategy_classnames
450
-     * @return bool
451
-     */
452
-    public function has_validation_strategy($validation_strategy_classnames)
453
-    {
454
-        $validation_strategy_classnames = is_array($validation_strategy_classnames)
455
-            ? $validation_strategy_classnames
456
-            : array($validation_strategy_classnames);
457
-        foreach ($this->_validation_strategies as $key => $validation_strategy) {
458
-            if (in_array($key, $validation_strategy_classnames)) {
459
-                return true;
460
-            }
461
-        }
462
-        return false;
463
-    }
464
-
465
-
466
-
467
-    /**
468
-     * Gets the HTML
469
-     *
470
-     * @return string
471
-     */
472
-    public function get_html()
473
-    {
474
-        return $this->_parent_section->get_html_for_input($this);
475
-    }
476
-
477
-
478
-
479
-    /**
480
-     * Gets the HTML for the input itself (no label or errors) according to the
481
-     * input's display strategy
482
-     * Makes sure the JS and CSS are enqueued for it
483
-     *
484
-     * @return string
485
-     * @throws \EE_Error
486
-     */
487
-    public function get_html_for_input()
488
-    {
489
-        return $this->_form_html_filter
490
-            ? $this->_form_html_filter->filterHtml(
491
-                $this->_get_display_strategy()->display(),
492
-                $this
493
-            )
494
-            : $this->_get_display_strategy()->display();
495
-    }
496
-
497
-
498
-
499
-    /**
500
-     * @return string
501
-     */
502
-    public function html_other_attributes()
503
-    {
504
-        return ! empty($this->_html_other_attributes) ? ' ' . $this->_html_other_attributes : '';
505
-    }
506
-
507
-
508
-
509
-    /**
510
-     * @param string $html_other_attributes
511
-     */
512
-    public function set_html_other_attributes($html_other_attributes)
513
-    {
514
-        $this->_html_other_attributes = $html_other_attributes;
515
-    }
516
-
517
-
518
-
519
-    /**
520
-     * Gets the HTML for displaying the label for this form input
521
-     * according to the form section's layout strategy
522
-     *
523
-     * @return string
524
-     */
525
-    public function get_html_for_label()
526
-    {
527
-        return $this->_parent_section->get_layout_strategy()->display_label($this);
528
-    }
529
-
530
-
531
-
532
-    /**
533
-     * Gets the HTML for displaying the errors section for this form input
534
-     * according to the form section's layout strategy
535
-     *
536
-     * @return string
537
-     */
538
-    public function get_html_for_errors()
539
-    {
540
-        return $this->_parent_section->get_layout_strategy()->display_errors($this);
541
-    }
542
-
543
-
544
-
545
-    /**
546
-     * Gets the HTML for displaying the help text for this form input
547
-     * according to the form section's layout strategy
548
-     *
549
-     * @return string
550
-     */
551
-    public function get_html_for_help()
552
-    {
553
-        return $this->_parent_section->get_layout_strategy()->display_help_text($this);
554
-    }
555
-
556
-
557
-
558
-    /**
559
-     * Validates the input's sanitized value (assumes _sanitize() has already been called)
560
-     * and returns whether or not the form input's submitted value is value
561
-     *
562
-     * @return boolean
563
-     */
564
-    protected function _validate()
565
-    {
566
-        foreach ($this->_validation_strategies as $validation_strategy) {
567
-            if ($validation_strategy instanceof EE_Validation_Strategy_Base) {
568
-                try {
569
-                    $validation_strategy->validate($this->normalized_value());
570
-                } catch (EE_Validation_Error $e) {
571
-                    $this->add_validation_error($e);
572
-                }
573
-            }
574
-        }
575
-        if ($this->get_validation_errors()) {
576
-            return false;
577
-        } else {
578
-            return true;
579
-        }
580
-    }
581
-
582
-
583
-
584
-    /**
585
-     * Performs basic sanitization on this value. But what sanitization can be performed anyways?
586
-     * This value MIGHT be allowed to have tags, so we can't really remove them.
587
-     *
588
-     * @param string $value
589
-     * @return null|string
590
-     */
591
-    private function _sanitize($value)
592
-    {
593
-        return $value !== null ? stripslashes(html_entity_decode(trim($value))) : null;
594
-    }
595
-
596
-
597
-
598
-    /**
599
-     * Picks out the form value that relates to this form input,
600
-     * and stores it as the sanitized value on the form input, and sets the normalized value.
601
-     * Returns whether or not any validation errors occurred
602
-     *
603
-     * @param array $req_data like $_POST
604
-     * @return boolean whether or not there was an error
605
-     * @throws \EE_Error
606
-     */
607
-    protected function _normalize($req_data)
608
-    {
609
-        //any existing validation errors don't apply so clear them
610
-        $this->_validation_errors = array();
611
-        try {
612
-            $raw_input = $this->find_form_data_for_this_section($req_data);
613
-            //super simple sanitization for now
614
-            if (is_array($raw_input)) {
615
-                $raw_value = array();
616
-                foreach ($raw_input as $key => $value) {
617
-                    $raw_value[$key] = $this->_sanitize($value);
618
-                }
619
-                $this->_set_raw_value($raw_value);
620
-            } else {
621
-                $this->_set_raw_value($this->_sanitize($raw_input));
622
-            }
623
-            //we want to mostly leave the input alone in case we need to re-display it to the user
624
-            $this->_set_normalized_value($this->_normalization_strategy->normalize($this->raw_value()));
625
-        } catch (EE_Validation_Error $e) {
626
-            $this->add_validation_error($e);
627
-        }
628
-    }
629
-
630
-
631
-
632
-    /**
633
-     * @return string
634
-     */
635
-    public function html_name()
636
-    {
637
-        $this->_set_default_html_name_if_empty();
638
-        return $this->_html_name;
639
-    }
640
-
641
-
642
-
643
-    /**
644
-     * @return string
645
-     */
646
-    public function html_label_id()
647
-    {
648
-        return ! empty($this->_html_label_id) ? $this->_html_label_id : $this->_html_id . '-lbl';
649
-    }
650
-
651
-
652
-
653
-    /**
654
-     * @return string
655
-     */
656
-    public function html_label_class()
657
-    {
658
-        return $this->_html_label_class;
659
-    }
660
-
661
-
662
-
663
-    /**
664
-     * @return string
665
-     */
666
-    public function html_label_style()
667
-    {
668
-        return $this->_html_label_style;
669
-    }
670
-
671
-
672
-
673
-    /**
674
-     * @return string
675
-     */
676
-    public function html_label_text()
677
-    {
678
-        return $this->_html_label_text;
679
-    }
680
-
681
-
682
-
683
-    /**
684
-     * @return string
685
-     */
686
-    public function html_help_text()
687
-    {
688
-        return $this->_html_help_text;
689
-    }
690
-
691
-
692
-
693
-    /**
694
-     * @return string
695
-     */
696
-    public function html_help_class()
697
-    {
698
-        return $this->_html_help_class;
699
-    }
700
-
701
-
702
-
703
-    /**
704
-     * @return string
705
-     */
706
-    public function html_help_style()
707
-    {
708
-        return $this->_html_style;
709
-    }
710
-
711
-
712
-
713
-    /**
714
-     * returns the raw, UNSAFE, input, almost exactly as the user submitted it.
715
-     * Please note that almost all client code should instead use the normalized_value;
716
-     * or possibly raw_value_in_form (which prepares the string for displaying in an HTML attribute on a tag,
717
-     * mostly by escaping quotes)
718
-     * Note, we do not store the exact original value sent in the user's request because
719
-     * it may have malicious content, and we MIGHT want to store the form input in a transient or something...
720
-     * in which case, we would have stored the malicious content to our database.
721
-     *
722
-     * @return string
723
-     */
724
-    public function raw_value()
725
-    {
726
-        return $this->_raw_value;
727
-    }
728
-
729
-
730
-
731
-    /**
732
-     * Returns a string safe to usage in form inputs when displaying, because
733
-     * it escapes all html entities
734
-     *
735
-     * @return string
736
-     */
737
-    public function raw_value_in_form()
738
-    {
739
-        return htmlentities($this->raw_value(), ENT_QUOTES, 'UTF-8');
740
-    }
741
-
742
-
743
-
744
-    /**
745
-     * returns the value after it's been sanitized, and then converted into it's proper type
746
-     * in PHP. Eg, a string, an int, an array,
747
-     *
748
-     * @return mixed
749
-     */
750
-    public function normalized_value()
751
-    {
752
-        return $this->_normalized_value;
753
-    }
754
-
755
-
756
-
757
-    /**
758
-     * Returns the normalized value is a presentable way. By default this is just
759
-     * the normalized value by itself, but it can be overridden for when that's not
760
-     * the best thing to display
761
-     *
762
-     * @return string
763
-     */
764
-    public function pretty_value()
765
-    {
766
-        return $this->_normalized_value;
767
-    }
768
-
769
-
770
-
771
-    /**
772
-     * When generating the JS for the jquery validation rules like<br>
773
-     * <code>$( "#myform" ).validate({
774
-     * rules: {
775
-     * password: "required",
776
-     * password_again: {
777
-     * equalTo: "#password"
778
-     * }
779
-     * }
780
-     * });</code>
781
-     * if this field had the name 'password_again', it should return
782
-     * <br><code>password_again: {
783
-     * equalTo: "#password"
784
-     * }</code>
785
-     *
786
-     * @return array
787
-     */
788
-    public function get_jquery_validation_rules()
789
-    {
790
-        $jquery_validation_js = array();
791
-        $jquery_validation_rules = array();
792
-        foreach ($this->get_validation_strategies() as $validation_strategy) {
793
-            $jquery_validation_rules = array_replace_recursive(
794
-                $jquery_validation_rules,
795
-                $validation_strategy->get_jquery_validation_rule_array()
796
-            );
797
-        }
798
-        if (! empty($jquery_validation_rules)) {
799
-            foreach ($this->get_display_strategy()->get_html_input_ids(true) as $html_id_with_pound_sign) {
800
-                $jquery_validation_js[$html_id_with_pound_sign] = $jquery_validation_rules;
801
-            }
802
-        }
803
-        return $jquery_validation_js;
804
-    }
805
-
806
-
807
-
808
-    /**
809
-     * Sets the input's default value for use in displaying in the form. Note: value should be
810
-     * normalized (Eg, if providing a default of ra Yes_NO_Input you would provide TRUE or FALSE, not '1' or '0')
811
-     *
812
-     * @param mixed $value
813
-     * @return void
814
-     */
815
-    public function set_default($value)
816
-    {
817
-        $this->_set_normalized_value($value);
818
-        $this->_set_raw_value($value);
819
-    }
820
-
821
-
822
-
823
-    /**
824
-     * Sets the normalized value on this input
825
-     *
826
-     * @param mixed $value
827
-     */
828
-    protected function _set_normalized_value($value)
829
-    {
830
-        $this->_normalized_value = $value;
831
-    }
832
-
833
-
834
-
835
-    /**
836
-     * Sets the raw value on this input (ie, exactly as the user submitted it)
837
-     *
838
-     * @param mixed $value
839
-     */
840
-    protected function _set_raw_value($value)
841
-    {
842
-        $this->_raw_value = $this->_normalization_strategy->unnormalize($value);
843
-    }
844
-
845
-
846
-
847
-    /**
848
-     * Sets the HTML label text after it has already been defined
849
-     *
850
-     * @param string $label
851
-     * @return void
852
-     */
853
-    public function set_html_label_text($label)
854
-    {
855
-        $this->_html_label_text = $label;
856
-    }
857
-
858
-
859
-
860
-    /**
861
-     * Sets whether or not this field is required, and adjusts the validation strategy.
862
-     * If you want to use the EE_Conditionally_Required_Validation_Strategy,
863
-     * please add it as a validation strategy using add_validation_strategy as normal
864
-     *
865
-     * @param boolean $required boolean
866
-     * @param null    $required_text
867
-     */
868
-    public function set_required($required = true, $required_text = null)
869
-    {
870
-        $required = filter_var($required, FILTER_VALIDATE_BOOLEAN);
871
-        //whether $required is a string or a boolean, we want to add a required validation strategy
872
-        if ($required) {
873
-            $this->_add_validation_strategy(new EE_Required_Validation_Strategy($required_text));
874
-        } else {
875
-            $this->remove_validation_strategy('EE_Required_Validation_Strategy');
876
-        }
877
-        $this->_required = $required;
878
-    }
879
-
880
-
881
-
882
-    /**
883
-     * Returns whether or not this field is required
884
-     *
885
-     * @return boolean
886
-     */
887
-    public function required()
888
-    {
889
-        return $this->_required;
890
-    }
891
-
892
-
893
-
894
-    /**
895
-     * @param string $required_css_class
896
-     */
897
-    public function set_required_css_class($required_css_class)
898
-    {
899
-        $this->_required_css_class = $required_css_class;
900
-    }
901
-
902
-
903
-
904
-    /**
905
-     * @return string
906
-     */
907
-    public function required_css_class()
908
-    {
909
-        return $this->_required_css_class;
910
-    }
911
-
912
-
913
-
914
-    /**
915
-     * Sets the help text, in case
916
-     *
917
-     * @param string $text
918
-     */
919
-    public function set_html_help_text($text)
920
-    {
921
-        $this->_html_help_text = $text;
922
-    }
923
-
924
-
925
-
926
-    /**
927
-     * Uses the sensitive data removal strategy to remove the sensitive data from this
928
-     * input. If there is any kind of sensitive data removal on this input, we clear
929
-     * out the raw value completely
930
-     *
931
-     * @return void
932
-     */
933
-    public function clean_sensitive_data()
934
-    {
935
-        //if we do ANY kind of sensitive data removal on this, then just clear out the raw value
936
-        //if we need more logic than this we'll make a strategy for it
937
-        if ($this->_sensitive_data_removal_strategy
938
-            && ! $this->_sensitive_data_removal_strategy instanceof EE_No_Sensitive_Data_Removal
939
-        ) {
940
-            $this->_set_raw_value(null);
941
-        }
942
-        //and clean the normalized value according to the appropriate strategy
943
-        $this->_set_normalized_value(
944
-            $this->get_sensitive_data_removal_strategy()->remove_sensitive_data(
945
-                $this->_normalized_value
946
-            )
947
-        );
948
-    }
949
-
950
-
951
-
952
-    /**
953
-     * @param bool   $primary
954
-     * @param string $button_size
955
-     * @param string $other_attributes
956
-     */
957
-    public function set_button_css_attributes($primary = true, $button_size = '', $other_attributes = '')
958
-    {
959
-        $button_css_attributes = 'button';
960
-        $button_css_attributes .= $primary === true ? ' button-primary' : ' button-secondary';
961
-        switch ($button_size) {
962
-            case 'xs' :
963
-            case 'extra-small' :
964
-                $button_css_attributes .= ' button-xs';
965
-                break;
966
-            case 'sm' :
967
-            case 'small' :
968
-                $button_css_attributes .= ' button-sm';
969
-                break;
970
-            case 'lg' :
971
-            case 'large' :
972
-                $button_css_attributes .= ' button-lg';
973
-                break;
974
-            case 'block' :
975
-                $button_css_attributes .= ' button-block';
976
-                break;
977
-            case 'md' :
978
-            case 'medium' :
979
-            default :
980
-                $button_css_attributes .= '';
981
-        }
982
-        $this->_button_css_attributes .= ! empty($other_attributes)
983
-            ? $button_css_attributes . ' ' . $other_attributes
984
-            : $button_css_attributes;
985
-    }
986
-
987
-
988
-
989
-    /**
990
-     * @return string
991
-     */
992
-    public function button_css_attributes()
993
-    {
994
-        if (empty($this->_button_css_attributes)) {
995
-            $this->set_button_css_attributes();
996
-        }
997
-        return $this->_button_css_attributes;
998
-    }
999
-
1000
-
1001
-
1002
-    /**
1003
-     * find_form_data_for_this_section
1004
-     * using this section's name and its parents, finds the value of the form data that corresponds to it.
1005
-     * For example, if this form section's HTML name is my_form[subform][form_input_1],
1006
-     * then it's value should be in $_REQUEST at $_REQUEST['my_form']['subform']['form_input_1'].
1007
-     * (If that doesn't exist, we also check for this subsection's name
1008
-     * at the TOP LEVEL of the request data. Eg $_REQUEST['form_input_1'].)
1009
-     * This function finds its value in the form.
1010
-     *
1011
-     * @param array $req_data
1012
-     * @return mixed whatever the raw value of this form section is in the request data
1013
-     * @throws \EE_Error
1014
-     */
1015
-    public function find_form_data_for_this_section($req_data)
1016
-    {
1017
-        // break up the html name by "[]"
1018
-        if (strpos($this->html_name(), '[') !== false) {
1019
-            $before_any_brackets = substr($this->html_name(), 0, strpos($this->html_name(), '['));
1020
-        } else {
1021
-            $before_any_brackets = $this->html_name();
1022
-        }
1023
-        // grab all of the segments
1024
-        preg_match_all('~\[([^]]*)\]~', $this->html_name(), $matches);
1025
-        if (isset($matches[1]) && is_array($matches[1])) {
1026
-            $name_parts = $matches[1];
1027
-            array_unshift($name_parts, $before_any_brackets);
1028
-        } else {
1029
-            $name_parts = array($before_any_brackets);
1030
-        }
1031
-        // now get the value for the input
1032
-        $value = $this->_find_form_data_for_this_section_using_name_parts($name_parts, $req_data);
1033
-        // check if this thing's name is at the TOP level of the request data
1034
-        if ($value === null && isset($req_data[$this->name()])) {
1035
-            $value = $req_data[$this->name()];
1036
-        }
1037
-        return $value;
1038
-    }
1039
-
1040
-
1041
-
1042
-    /**
1043
-     * @param array $html_name_parts
1044
-     * @param array $req_data
1045
-     * @return array | NULL
1046
-     */
1047
-    public function _find_form_data_for_this_section_using_name_parts($html_name_parts, $req_data)
1048
-    {
1049
-        $first_part_to_consider = array_shift($html_name_parts);
1050
-        if (isset($req_data[$first_part_to_consider])) {
1051
-            if (empty($html_name_parts)) {
1052
-                return $req_data[$first_part_to_consider];
1053
-            } else {
1054
-                return $this->_find_form_data_for_this_section_using_name_parts(
1055
-                    $html_name_parts,
1056
-                    $req_data[$first_part_to_consider]
1057
-                );
1058
-            }
1059
-        } else {
1060
-            return null;
1061
-        }
1062
-    }
1063
-
1064
-
1065
-
1066
-    /**
1067
-     * Checks if this form input's data is in the request data
1068
-     *
1069
-     * @param array $req_data like $_POST
1070
-     * @return boolean
1071
-     * @throws \EE_Error
1072
-     */
1073
-    public function form_data_present_in($req_data = null)
1074
-    {
1075
-        if ($req_data === null) {
1076
-            $req_data = $_POST;
1077
-        }
1078
-        $checked_value = $this->find_form_data_for_this_section($req_data);
1079
-        if ($checked_value !== null) {
1080
-            return true;
1081
-        } else {
1082
-            return false;
1083
-        }
1084
-    }
1085
-
1086
-
1087
-
1088
-    /**
1089
-     * Overrides parent to add js data from validation and display strategies
1090
-     *
1091
-     * @param array $form_other_js_data
1092
-     * @return array
1093
-     */
1094
-    public function get_other_js_data($form_other_js_data = array())
1095
-    {
1096
-        $form_other_js_data = $this->get_other_js_data_from_strategies($form_other_js_data);
1097
-        return $form_other_js_data;
1098
-    }
1099
-
1100
-
1101
-
1102
-    /**
1103
-     * Gets other JS data for localization from this input's strategies, like
1104
-     * the validation strategies and the display strategy
1105
-     *
1106
-     * @param array $form_other_js_data
1107
-     * @return array
1108
-     */
1109
-    public function get_other_js_data_from_strategies($form_other_js_data = array())
1110
-    {
1111
-        $form_other_js_data = $this->get_display_strategy()->get_other_js_data($form_other_js_data);
1112
-        foreach ($this->get_validation_strategies() as $validation_strategy) {
1113
-            $form_other_js_data = $validation_strategy->get_other_js_data($form_other_js_data);
1114
-        }
1115
-        return $form_other_js_data;
1116
-    }
1117
-
1118
-
1119
-
1120
-    /**
1121
-     * Override parent because we want to give our strategies an opportunity to enqueue some js and css
1122
-     *
1123
-     * @return void
1124
-     */
1125
-    public function enqueue_js()
1126
-    {
1127
-        //ask our display strategy and validation strategies if they have js to enqueue
1128
-        $this->enqueue_js_from_strategies();
1129
-    }
1130
-
1131
-
1132
-
1133
-    /**
1134
-     * Tells strategies when its ok to enqueue their js and css
1135
-     *
1136
-     * @return void
1137
-     */
1138
-    public function enqueue_js_from_strategies()
1139
-    {
1140
-        $this->get_display_strategy()->enqueue_js();
1141
-        foreach ($this->get_validation_strategies() as $validation_strategy) {
1142
-            $validation_strategy->enqueue_js();
1143
-        }
1144
-    }
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
+	 * Strategy used for displaying this field.
132
+	 * Child classes must use _get_display_strategy to access it.
133
+	 *
134
+	 * @var EE_Display_Strategy_Base
135
+	 */
136
+	private $_display_strategy;
137
+
138
+	/**
139
+	 * Gets all the validation strategies used on this field
140
+	 *
141
+	 * @var EE_Validation_Strategy_Base[]
142
+	 */
143
+	private $_validation_strategies = array();
144
+
145
+	/**
146
+	 * The normalization strategy for this field
147
+	 *
148
+	 * @var EE_Normalization_Strategy_Base
149
+	 */
150
+	private $_normalization_strategy;
151
+
152
+	/**
153
+	 * Strategy for removing sensitive data after we're done with the form input
154
+	 *
155
+	 * @var EE_Sensitive_Data_Removal_Base
156
+	 */
157
+	protected $_sensitive_data_removal_strategy;
158
+
159
+
160
+
161
+	/**
162
+	 * @param array                         $input_args       {
163
+	 * @type string                         $html_name        the html name for the input
164
+	 * @type string                         $html_label_id    the id attribute to give to the html label tag
165
+	 * @type string                         $html_label_class the class attribute to give to the html label tag
166
+	 * @type string                         $html_label_style the style attribute to give ot teh label tag
167
+	 * @type string                         $html_label_text  the text to put in the label tag
168
+	 * @type string                         $html_label       the full html label. If used,
169
+	 *                                                        all other html_label_* args are invalid
170
+	 * @type string                         $html_help_text   text to put in help element
171
+	 * @type string                         $html_help_style  style attribute to give to teh help element
172
+	 * @type string                         $html_help_class  class attribute to give to the help element
173
+	 * @type string                         $default          default value NORMALIZED (eg, if providing the default
174
+	 *       for a Yes_No_Input, you should provide TRUE or FALSE, not '1' or '0')
175
+	 * @type EE_Display_Strategy_Base       $display          strategy
176
+	 * @type EE_Normalization_Strategy_Base $normalization_strategy
177
+	 * @type EE_Validation_Strategy_Base[]  $validation_strategies
178
+	 *                                                        }
179
+	 */
180
+	public function __construct($input_args = array())
181
+	{
182
+		$input_args = (array)apply_filters('FHEE__EE_Form_Input_Base___construct__input_args', $input_args, $this);
183
+		// the following properties must be cast as arrays
184
+		if (isset($input_args['validation_strategies'])) {
185
+			foreach ((array)$input_args['validation_strategies'] as $validation_strategy) {
186
+				if ($validation_strategy instanceof EE_Validation_Strategy_Base) {
187
+					$this->_validation_strategies[get_class($validation_strategy)] = $validation_strategy;
188
+				}
189
+			}
190
+			unset($input_args['validation_strategies']);
191
+		}
192
+		// loop thru incoming options
193
+		foreach ($input_args as $key => $value) {
194
+			// add underscore to $key to match property names
195
+			$_key = '_' . $key;
196
+			if (property_exists($this, $_key)) {
197
+				$this->{$_key} = $value;
198
+			}
199
+		}
200
+		// ensure that "required" is set correctly
201
+		$this->set_required(
202
+			$this->_required, isset($input_args['required_validation_error_message'])
203
+			? $input_args['required_validation_error_message']
204
+			: null
205
+		);
206
+		//$this->_html_name_specified = isset( $input_args['html_name'] ) ? TRUE : FALSE;
207
+		$this->_display_strategy->_construct_finalize($this);
208
+		foreach ($this->_validation_strategies as $validation_strategy) {
209
+			$validation_strategy->_construct_finalize($this);
210
+		}
211
+		if (! $this->_normalization_strategy) {
212
+			$this->_normalization_strategy = new EE_Text_Normalization();
213
+		}
214
+		$this->_normalization_strategy->_construct_finalize($this);
215
+		//at least we can use the normalization strategy to populate the default
216
+		if (isset($input_args['default'])) {
217
+			$this->set_default($input_args['default']);
218
+		}
219
+		if (! $this->_sensitive_data_removal_strategy) {
220
+			$this->_sensitive_data_removal_strategy = new EE_No_Sensitive_Data_Removal();
221
+		}
222
+		$this->_sensitive_data_removal_strategy->_construct_finalize($this);
223
+		parent::__construct($input_args);
224
+	}
225
+
226
+
227
+
228
+	/**
229
+	 * Sets the html_name to its default value, if none was specified in teh constructor.
230
+	 * Calculation involves using the name and the parent's html_name
231
+	 *
232
+	 * @throws \EE_Error
233
+	 */
234
+	protected function _set_default_html_name_if_empty()
235
+	{
236
+		if (! $this->_html_name) {
237
+			$this->_html_name = $this->name();
238
+			if ($this->_parent_section && $this->_parent_section instanceof EE_Form_Section_Proper) {
239
+				$this->_html_name = $this->_parent_section->html_name_prefix() . "[{$this->name()}]";
240
+			}
241
+		}
242
+	}
243
+
244
+
245
+
246
+	/**
247
+	 * @param $parent_form_section
248
+	 * @param $name
249
+	 * @throws \EE_Error
250
+	 */
251
+	public function _construct_finalize($parent_form_section, $name)
252
+	{
253
+		parent::_construct_finalize($parent_form_section, $name);
254
+		if ($this->_html_label === null && $this->_html_label_text === null) {
255
+			$this->_html_label_text = ucwords(str_replace("_", " ", $name));
256
+		}
257
+		do_action('AHEE__EE_Form_Input_Base___construct_finalize__end', $this, $parent_form_section, $name);
258
+	}
259
+
260
+
261
+
262
+	/**
263
+	 * Returns the strategy for displaying this form input. If none is set, throws an exception.
264
+	 *
265
+	 * @return EE_Display_Strategy_Base
266
+	 * @throws EE_Error
267
+	 */
268
+	protected function _get_display_strategy()
269
+	{
270
+		$this->ensure_construct_finalized_called();
271
+		if (! $this->_display_strategy || ! $this->_display_strategy instanceof EE_Display_Strategy_Base) {
272
+			throw new EE_Error(
273
+				sprintf(
274
+					__(
275
+						"Cannot get display strategy for form input with name %s and id %s, because it has not been set in the constructor",
276
+						"event_espresso"
277
+					),
278
+					$this->html_name(),
279
+					$this->html_id()
280
+				)
281
+			);
282
+		} else {
283
+			return $this->_display_strategy;
284
+		}
285
+	}
286
+
287
+
288
+
289
+	/**
290
+	 * Sets the display strategy.
291
+	 *
292
+	 * @param EE_Display_Strategy_Base $strategy
293
+	 */
294
+	protected function _set_display_strategy(EE_Display_Strategy_Base $strategy)
295
+	{
296
+		$this->_display_strategy = $strategy;
297
+	}
298
+
299
+
300
+
301
+	/**
302
+	 * Sets the sanitization strategy
303
+	 *
304
+	 * @param EE_Normalization_Strategy_Base $strategy
305
+	 */
306
+	protected function _set_normalization_strategy(EE_Normalization_Strategy_Base $strategy)
307
+	{
308
+		$this->_normalization_strategy = $strategy;
309
+	}
310
+
311
+
312
+
313
+	/**
314
+	 * Gets sensitive_data_removal_strategy
315
+	 *
316
+	 * @return EE_Sensitive_Data_Removal_Base
317
+	 */
318
+	public function get_sensitive_data_removal_strategy()
319
+	{
320
+		return $this->_sensitive_data_removal_strategy;
321
+	}
322
+
323
+
324
+
325
+	/**
326
+	 * Sets sensitive_data_removal_strategy
327
+	 *
328
+	 * @param EE_Sensitive_Data_Removal_Base $sensitive_data_removal_strategy
329
+	 * @return boolean
330
+	 */
331
+	public function set_sensitive_data_removal_strategy($sensitive_data_removal_strategy)
332
+	{
333
+		$this->_sensitive_data_removal_strategy = $sensitive_data_removal_strategy;
334
+	}
335
+
336
+
337
+
338
+	/**
339
+	 * Gets the display strategy for this input
340
+	 *
341
+	 * @return EE_Display_Strategy_Base
342
+	 */
343
+	public function get_display_strategy()
344
+	{
345
+		return $this->_display_strategy;
346
+	}
347
+
348
+
349
+
350
+	/**
351
+	 * Overwrites the display strategy
352
+	 *
353
+	 * @param EE_Display_Strategy_Base $display_strategy
354
+	 */
355
+	public function set_display_strategy($display_strategy)
356
+	{
357
+		$this->_display_strategy = $display_strategy;
358
+		$this->_display_strategy->_construct_finalize($this);
359
+	}
360
+
361
+
362
+
363
+	/**
364
+	 * Gets the normalization strategy set on this input
365
+	 *
366
+	 * @return EE_Normalization_Strategy_Base
367
+	 */
368
+	public function get_normalization_strategy()
369
+	{
370
+		return $this->_normalization_strategy;
371
+	}
372
+
373
+
374
+
375
+	/**
376
+	 * Overwrites the normalization strategy
377
+	 *
378
+	 * @param EE_Normalization_Strategy_Base $normalization_strategy
379
+	 */
380
+	public function set_normalization_strategy($normalization_strategy)
381
+	{
382
+		$this->_normalization_strategy = $normalization_strategy;
383
+		$this->_normalization_strategy->_construct_finalize($this);
384
+	}
385
+
386
+
387
+
388
+	/**
389
+	 * Returns all teh validation strategies which apply to this field, numerically indexed
390
+	 *
391
+	 * @return EE_Validation_Strategy_Base[]
392
+	 */
393
+	public function get_validation_strategies()
394
+	{
395
+		return $this->_validation_strategies;
396
+	}
397
+
398
+
399
+
400
+	/**
401
+	 * Adds this strategy to the field so it will be used in both JS validation and server-side validation
402
+	 *
403
+	 * @param EE_Validation_Strategy_Base $validation_strategy
404
+	 * @return void
405
+	 */
406
+	protected function _add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
407
+	{
408
+		$validation_strategy->_construct_finalize($this);
409
+		$this->_validation_strategies[] = $validation_strategy;
410
+	}
411
+
412
+
413
+
414
+	/**
415
+	 * Adds a new validation strategy onto the form input
416
+	 *
417
+	 * @param EE_Validation_Strategy_Base $validation_strategy
418
+	 * @return void
419
+	 */
420
+	public function add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
421
+	{
422
+		$this->_add_validation_strategy($validation_strategy);
423
+	}
424
+
425
+
426
+
427
+	/**
428
+	 * The classname of the validation strategy to remove
429
+	 *
430
+	 * @param string $validation_strategy_classname
431
+	 */
432
+	public function remove_validation_strategy($validation_strategy_classname)
433
+	{
434
+		foreach ($this->_validation_strategies as $key => $validation_strategy) {
435
+			if (
436
+				$validation_strategy instanceof $validation_strategy_classname
437
+				|| is_subclass_of($validation_strategy, $validation_strategy_classname)
438
+			) {
439
+				unset($this->_validation_strategies[$key]);
440
+			}
441
+		}
442
+	}
443
+
444
+
445
+
446
+	/**
447
+	 * returns true if input employs any of the validation strategy defined by the supplied array of classnames
448
+	 *
449
+	 * @param array $validation_strategy_classnames
450
+	 * @return bool
451
+	 */
452
+	public function has_validation_strategy($validation_strategy_classnames)
453
+	{
454
+		$validation_strategy_classnames = is_array($validation_strategy_classnames)
455
+			? $validation_strategy_classnames
456
+			: array($validation_strategy_classnames);
457
+		foreach ($this->_validation_strategies as $key => $validation_strategy) {
458
+			if (in_array($key, $validation_strategy_classnames)) {
459
+				return true;
460
+			}
461
+		}
462
+		return false;
463
+	}
464
+
465
+
466
+
467
+	/**
468
+	 * Gets the HTML
469
+	 *
470
+	 * @return string
471
+	 */
472
+	public function get_html()
473
+	{
474
+		return $this->_parent_section->get_html_for_input($this);
475
+	}
476
+
477
+
478
+
479
+	/**
480
+	 * Gets the HTML for the input itself (no label or errors) according to the
481
+	 * input's display strategy
482
+	 * Makes sure the JS and CSS are enqueued for it
483
+	 *
484
+	 * @return string
485
+	 * @throws \EE_Error
486
+	 */
487
+	public function get_html_for_input()
488
+	{
489
+		return $this->_form_html_filter
490
+			? $this->_form_html_filter->filterHtml(
491
+				$this->_get_display_strategy()->display(),
492
+				$this
493
+			)
494
+			: $this->_get_display_strategy()->display();
495
+	}
496
+
497
+
498
+
499
+	/**
500
+	 * @return string
501
+	 */
502
+	public function html_other_attributes()
503
+	{
504
+		return ! empty($this->_html_other_attributes) ? ' ' . $this->_html_other_attributes : '';
505
+	}
506
+
507
+
508
+
509
+	/**
510
+	 * @param string $html_other_attributes
511
+	 */
512
+	public function set_html_other_attributes($html_other_attributes)
513
+	{
514
+		$this->_html_other_attributes = $html_other_attributes;
515
+	}
516
+
517
+
518
+
519
+	/**
520
+	 * Gets the HTML for displaying the label for this form input
521
+	 * according to the form section's layout strategy
522
+	 *
523
+	 * @return string
524
+	 */
525
+	public function get_html_for_label()
526
+	{
527
+		return $this->_parent_section->get_layout_strategy()->display_label($this);
528
+	}
529
+
530
+
531
+
532
+	/**
533
+	 * Gets the HTML for displaying the errors section for this form input
534
+	 * according to the form section's layout strategy
535
+	 *
536
+	 * @return string
537
+	 */
538
+	public function get_html_for_errors()
539
+	{
540
+		return $this->_parent_section->get_layout_strategy()->display_errors($this);
541
+	}
542
+
543
+
544
+
545
+	/**
546
+	 * Gets the HTML for displaying the help text for this form input
547
+	 * according to the form section's layout strategy
548
+	 *
549
+	 * @return string
550
+	 */
551
+	public function get_html_for_help()
552
+	{
553
+		return $this->_parent_section->get_layout_strategy()->display_help_text($this);
554
+	}
555
+
556
+
557
+
558
+	/**
559
+	 * Validates the input's sanitized value (assumes _sanitize() has already been called)
560
+	 * and returns whether or not the form input's submitted value is value
561
+	 *
562
+	 * @return boolean
563
+	 */
564
+	protected function _validate()
565
+	{
566
+		foreach ($this->_validation_strategies as $validation_strategy) {
567
+			if ($validation_strategy instanceof EE_Validation_Strategy_Base) {
568
+				try {
569
+					$validation_strategy->validate($this->normalized_value());
570
+				} catch (EE_Validation_Error $e) {
571
+					$this->add_validation_error($e);
572
+				}
573
+			}
574
+		}
575
+		if ($this->get_validation_errors()) {
576
+			return false;
577
+		} else {
578
+			return true;
579
+		}
580
+	}
581
+
582
+
583
+
584
+	/**
585
+	 * Performs basic sanitization on this value. But what sanitization can be performed anyways?
586
+	 * This value MIGHT be allowed to have tags, so we can't really remove them.
587
+	 *
588
+	 * @param string $value
589
+	 * @return null|string
590
+	 */
591
+	private function _sanitize($value)
592
+	{
593
+		return $value !== null ? stripslashes(html_entity_decode(trim($value))) : null;
594
+	}
595
+
596
+
597
+
598
+	/**
599
+	 * Picks out the form value that relates to this form input,
600
+	 * and stores it as the sanitized value on the form input, and sets the normalized value.
601
+	 * Returns whether or not any validation errors occurred
602
+	 *
603
+	 * @param array $req_data like $_POST
604
+	 * @return boolean whether or not there was an error
605
+	 * @throws \EE_Error
606
+	 */
607
+	protected function _normalize($req_data)
608
+	{
609
+		//any existing validation errors don't apply so clear them
610
+		$this->_validation_errors = array();
611
+		try {
612
+			$raw_input = $this->find_form_data_for_this_section($req_data);
613
+			//super simple sanitization for now
614
+			if (is_array($raw_input)) {
615
+				$raw_value = array();
616
+				foreach ($raw_input as $key => $value) {
617
+					$raw_value[$key] = $this->_sanitize($value);
618
+				}
619
+				$this->_set_raw_value($raw_value);
620
+			} else {
621
+				$this->_set_raw_value($this->_sanitize($raw_input));
622
+			}
623
+			//we want to mostly leave the input alone in case we need to re-display it to the user
624
+			$this->_set_normalized_value($this->_normalization_strategy->normalize($this->raw_value()));
625
+		} catch (EE_Validation_Error $e) {
626
+			$this->add_validation_error($e);
627
+		}
628
+	}
629
+
630
+
631
+
632
+	/**
633
+	 * @return string
634
+	 */
635
+	public function html_name()
636
+	{
637
+		$this->_set_default_html_name_if_empty();
638
+		return $this->_html_name;
639
+	}
640
+
641
+
642
+
643
+	/**
644
+	 * @return string
645
+	 */
646
+	public function html_label_id()
647
+	{
648
+		return ! empty($this->_html_label_id) ? $this->_html_label_id : $this->_html_id . '-lbl';
649
+	}
650
+
651
+
652
+
653
+	/**
654
+	 * @return string
655
+	 */
656
+	public function html_label_class()
657
+	{
658
+		return $this->_html_label_class;
659
+	}
660
+
661
+
662
+
663
+	/**
664
+	 * @return string
665
+	 */
666
+	public function html_label_style()
667
+	{
668
+		return $this->_html_label_style;
669
+	}
670
+
671
+
672
+
673
+	/**
674
+	 * @return string
675
+	 */
676
+	public function html_label_text()
677
+	{
678
+		return $this->_html_label_text;
679
+	}
680
+
681
+
682
+
683
+	/**
684
+	 * @return string
685
+	 */
686
+	public function html_help_text()
687
+	{
688
+		return $this->_html_help_text;
689
+	}
690
+
691
+
692
+
693
+	/**
694
+	 * @return string
695
+	 */
696
+	public function html_help_class()
697
+	{
698
+		return $this->_html_help_class;
699
+	}
700
+
701
+
702
+
703
+	/**
704
+	 * @return string
705
+	 */
706
+	public function html_help_style()
707
+	{
708
+		return $this->_html_style;
709
+	}
710
+
711
+
712
+
713
+	/**
714
+	 * returns the raw, UNSAFE, input, almost exactly as the user submitted it.
715
+	 * Please note that almost all client code should instead use the normalized_value;
716
+	 * or possibly raw_value_in_form (which prepares the string for displaying in an HTML attribute on a tag,
717
+	 * mostly by escaping quotes)
718
+	 * Note, we do not store the exact original value sent in the user's request because
719
+	 * it may have malicious content, and we MIGHT want to store the form input in a transient or something...
720
+	 * in which case, we would have stored the malicious content to our database.
721
+	 *
722
+	 * @return string
723
+	 */
724
+	public function raw_value()
725
+	{
726
+		return $this->_raw_value;
727
+	}
728
+
729
+
730
+
731
+	/**
732
+	 * Returns a string safe to usage in form inputs when displaying, because
733
+	 * it escapes all html entities
734
+	 *
735
+	 * @return string
736
+	 */
737
+	public function raw_value_in_form()
738
+	{
739
+		return htmlentities($this->raw_value(), ENT_QUOTES, 'UTF-8');
740
+	}
741
+
742
+
743
+
744
+	/**
745
+	 * returns the value after it's been sanitized, and then converted into it's proper type
746
+	 * in PHP. Eg, a string, an int, an array,
747
+	 *
748
+	 * @return mixed
749
+	 */
750
+	public function normalized_value()
751
+	{
752
+		return $this->_normalized_value;
753
+	}
754
+
755
+
756
+
757
+	/**
758
+	 * Returns the normalized value is a presentable way. By default this is just
759
+	 * the normalized value by itself, but it can be overridden for when that's not
760
+	 * the best thing to display
761
+	 *
762
+	 * @return string
763
+	 */
764
+	public function pretty_value()
765
+	{
766
+		return $this->_normalized_value;
767
+	}
768
+
769
+
770
+
771
+	/**
772
+	 * When generating the JS for the jquery validation rules like<br>
773
+	 * <code>$( "#myform" ).validate({
774
+	 * rules: {
775
+	 * password: "required",
776
+	 * password_again: {
777
+	 * equalTo: "#password"
778
+	 * }
779
+	 * }
780
+	 * });</code>
781
+	 * if this field had the name 'password_again', it should return
782
+	 * <br><code>password_again: {
783
+	 * equalTo: "#password"
784
+	 * }</code>
785
+	 *
786
+	 * @return array
787
+	 */
788
+	public function get_jquery_validation_rules()
789
+	{
790
+		$jquery_validation_js = array();
791
+		$jquery_validation_rules = array();
792
+		foreach ($this->get_validation_strategies() as $validation_strategy) {
793
+			$jquery_validation_rules = array_replace_recursive(
794
+				$jquery_validation_rules,
795
+				$validation_strategy->get_jquery_validation_rule_array()
796
+			);
797
+		}
798
+		if (! empty($jquery_validation_rules)) {
799
+			foreach ($this->get_display_strategy()->get_html_input_ids(true) as $html_id_with_pound_sign) {
800
+				$jquery_validation_js[$html_id_with_pound_sign] = $jquery_validation_rules;
801
+			}
802
+		}
803
+		return $jquery_validation_js;
804
+	}
805
+
806
+
807
+
808
+	/**
809
+	 * Sets the input's default value for use in displaying in the form. Note: value should be
810
+	 * normalized (Eg, if providing a default of ra Yes_NO_Input you would provide TRUE or FALSE, not '1' or '0')
811
+	 *
812
+	 * @param mixed $value
813
+	 * @return void
814
+	 */
815
+	public function set_default($value)
816
+	{
817
+		$this->_set_normalized_value($value);
818
+		$this->_set_raw_value($value);
819
+	}
820
+
821
+
822
+
823
+	/**
824
+	 * Sets the normalized value on this input
825
+	 *
826
+	 * @param mixed $value
827
+	 */
828
+	protected function _set_normalized_value($value)
829
+	{
830
+		$this->_normalized_value = $value;
831
+	}
832
+
833
+
834
+
835
+	/**
836
+	 * Sets the raw value on this input (ie, exactly as the user submitted it)
837
+	 *
838
+	 * @param mixed $value
839
+	 */
840
+	protected function _set_raw_value($value)
841
+	{
842
+		$this->_raw_value = $this->_normalization_strategy->unnormalize($value);
843
+	}
844
+
845
+
846
+
847
+	/**
848
+	 * Sets the HTML label text after it has already been defined
849
+	 *
850
+	 * @param string $label
851
+	 * @return void
852
+	 */
853
+	public function set_html_label_text($label)
854
+	{
855
+		$this->_html_label_text = $label;
856
+	}
857
+
858
+
859
+
860
+	/**
861
+	 * Sets whether or not this field is required, and adjusts the validation strategy.
862
+	 * If you want to use the EE_Conditionally_Required_Validation_Strategy,
863
+	 * please add it as a validation strategy using add_validation_strategy as normal
864
+	 *
865
+	 * @param boolean $required boolean
866
+	 * @param null    $required_text
867
+	 */
868
+	public function set_required($required = true, $required_text = null)
869
+	{
870
+		$required = filter_var($required, FILTER_VALIDATE_BOOLEAN);
871
+		//whether $required is a string or a boolean, we want to add a required validation strategy
872
+		if ($required) {
873
+			$this->_add_validation_strategy(new EE_Required_Validation_Strategy($required_text));
874
+		} else {
875
+			$this->remove_validation_strategy('EE_Required_Validation_Strategy');
876
+		}
877
+		$this->_required = $required;
878
+	}
879
+
880
+
881
+
882
+	/**
883
+	 * Returns whether or not this field is required
884
+	 *
885
+	 * @return boolean
886
+	 */
887
+	public function required()
888
+	{
889
+		return $this->_required;
890
+	}
891
+
892
+
893
+
894
+	/**
895
+	 * @param string $required_css_class
896
+	 */
897
+	public function set_required_css_class($required_css_class)
898
+	{
899
+		$this->_required_css_class = $required_css_class;
900
+	}
901
+
902
+
903
+
904
+	/**
905
+	 * @return string
906
+	 */
907
+	public function required_css_class()
908
+	{
909
+		return $this->_required_css_class;
910
+	}
911
+
912
+
913
+
914
+	/**
915
+	 * Sets the help text, in case
916
+	 *
917
+	 * @param string $text
918
+	 */
919
+	public function set_html_help_text($text)
920
+	{
921
+		$this->_html_help_text = $text;
922
+	}
923
+
924
+
925
+
926
+	/**
927
+	 * Uses the sensitive data removal strategy to remove the sensitive data from this
928
+	 * input. If there is any kind of sensitive data removal on this input, we clear
929
+	 * out the raw value completely
930
+	 *
931
+	 * @return void
932
+	 */
933
+	public function clean_sensitive_data()
934
+	{
935
+		//if we do ANY kind of sensitive data removal on this, then just clear out the raw value
936
+		//if we need more logic than this we'll make a strategy for it
937
+		if ($this->_sensitive_data_removal_strategy
938
+			&& ! $this->_sensitive_data_removal_strategy instanceof EE_No_Sensitive_Data_Removal
939
+		) {
940
+			$this->_set_raw_value(null);
941
+		}
942
+		//and clean the normalized value according to the appropriate strategy
943
+		$this->_set_normalized_value(
944
+			$this->get_sensitive_data_removal_strategy()->remove_sensitive_data(
945
+				$this->_normalized_value
946
+			)
947
+		);
948
+	}
949
+
950
+
951
+
952
+	/**
953
+	 * @param bool   $primary
954
+	 * @param string $button_size
955
+	 * @param string $other_attributes
956
+	 */
957
+	public function set_button_css_attributes($primary = true, $button_size = '', $other_attributes = '')
958
+	{
959
+		$button_css_attributes = 'button';
960
+		$button_css_attributes .= $primary === true ? ' button-primary' : ' button-secondary';
961
+		switch ($button_size) {
962
+			case 'xs' :
963
+			case 'extra-small' :
964
+				$button_css_attributes .= ' button-xs';
965
+				break;
966
+			case 'sm' :
967
+			case 'small' :
968
+				$button_css_attributes .= ' button-sm';
969
+				break;
970
+			case 'lg' :
971
+			case 'large' :
972
+				$button_css_attributes .= ' button-lg';
973
+				break;
974
+			case 'block' :
975
+				$button_css_attributes .= ' button-block';
976
+				break;
977
+			case 'md' :
978
+			case 'medium' :
979
+			default :
980
+				$button_css_attributes .= '';
981
+		}
982
+		$this->_button_css_attributes .= ! empty($other_attributes)
983
+			? $button_css_attributes . ' ' . $other_attributes
984
+			: $button_css_attributes;
985
+	}
986
+
987
+
988
+
989
+	/**
990
+	 * @return string
991
+	 */
992
+	public function button_css_attributes()
993
+	{
994
+		if (empty($this->_button_css_attributes)) {
995
+			$this->set_button_css_attributes();
996
+		}
997
+		return $this->_button_css_attributes;
998
+	}
999
+
1000
+
1001
+
1002
+	/**
1003
+	 * find_form_data_for_this_section
1004
+	 * using this section's name and its parents, finds the value of the form data that corresponds to it.
1005
+	 * For example, if this form section's HTML name is my_form[subform][form_input_1],
1006
+	 * then it's value should be in $_REQUEST at $_REQUEST['my_form']['subform']['form_input_1'].
1007
+	 * (If that doesn't exist, we also check for this subsection's name
1008
+	 * at the TOP LEVEL of the request data. Eg $_REQUEST['form_input_1'].)
1009
+	 * This function finds its value in the form.
1010
+	 *
1011
+	 * @param array $req_data
1012
+	 * @return mixed whatever the raw value of this form section is in the request data
1013
+	 * @throws \EE_Error
1014
+	 */
1015
+	public function find_form_data_for_this_section($req_data)
1016
+	{
1017
+		// break up the html name by "[]"
1018
+		if (strpos($this->html_name(), '[') !== false) {
1019
+			$before_any_brackets = substr($this->html_name(), 0, strpos($this->html_name(), '['));
1020
+		} else {
1021
+			$before_any_brackets = $this->html_name();
1022
+		}
1023
+		// grab all of the segments
1024
+		preg_match_all('~\[([^]]*)\]~', $this->html_name(), $matches);
1025
+		if (isset($matches[1]) && is_array($matches[1])) {
1026
+			$name_parts = $matches[1];
1027
+			array_unshift($name_parts, $before_any_brackets);
1028
+		} else {
1029
+			$name_parts = array($before_any_brackets);
1030
+		}
1031
+		// now get the value for the input
1032
+		$value = $this->_find_form_data_for_this_section_using_name_parts($name_parts, $req_data);
1033
+		// check if this thing's name is at the TOP level of the request data
1034
+		if ($value === null && isset($req_data[$this->name()])) {
1035
+			$value = $req_data[$this->name()];
1036
+		}
1037
+		return $value;
1038
+	}
1039
+
1040
+
1041
+
1042
+	/**
1043
+	 * @param array $html_name_parts
1044
+	 * @param array $req_data
1045
+	 * @return array | NULL
1046
+	 */
1047
+	public function _find_form_data_for_this_section_using_name_parts($html_name_parts, $req_data)
1048
+	{
1049
+		$first_part_to_consider = array_shift($html_name_parts);
1050
+		if (isset($req_data[$first_part_to_consider])) {
1051
+			if (empty($html_name_parts)) {
1052
+				return $req_data[$first_part_to_consider];
1053
+			} else {
1054
+				return $this->_find_form_data_for_this_section_using_name_parts(
1055
+					$html_name_parts,
1056
+					$req_data[$first_part_to_consider]
1057
+				);
1058
+			}
1059
+		} else {
1060
+			return null;
1061
+		}
1062
+	}
1063
+
1064
+
1065
+
1066
+	/**
1067
+	 * Checks if this form input's data is in the request data
1068
+	 *
1069
+	 * @param array $req_data like $_POST
1070
+	 * @return boolean
1071
+	 * @throws \EE_Error
1072
+	 */
1073
+	public function form_data_present_in($req_data = null)
1074
+	{
1075
+		if ($req_data === null) {
1076
+			$req_data = $_POST;
1077
+		}
1078
+		$checked_value = $this->find_form_data_for_this_section($req_data);
1079
+		if ($checked_value !== null) {
1080
+			return true;
1081
+		} else {
1082
+			return false;
1083
+		}
1084
+	}
1085
+
1086
+
1087
+
1088
+	/**
1089
+	 * Overrides parent to add js data from validation and display strategies
1090
+	 *
1091
+	 * @param array $form_other_js_data
1092
+	 * @return array
1093
+	 */
1094
+	public function get_other_js_data($form_other_js_data = array())
1095
+	{
1096
+		$form_other_js_data = $this->get_other_js_data_from_strategies($form_other_js_data);
1097
+		return $form_other_js_data;
1098
+	}
1099
+
1100
+
1101
+
1102
+	/**
1103
+	 * Gets other JS data for localization from this input's strategies, like
1104
+	 * the validation strategies and the display strategy
1105
+	 *
1106
+	 * @param array $form_other_js_data
1107
+	 * @return array
1108
+	 */
1109
+	public function get_other_js_data_from_strategies($form_other_js_data = array())
1110
+	{
1111
+		$form_other_js_data = $this->get_display_strategy()->get_other_js_data($form_other_js_data);
1112
+		foreach ($this->get_validation_strategies() as $validation_strategy) {
1113
+			$form_other_js_data = $validation_strategy->get_other_js_data($form_other_js_data);
1114
+		}
1115
+		return $form_other_js_data;
1116
+	}
1117
+
1118
+
1119
+
1120
+	/**
1121
+	 * Override parent because we want to give our strategies an opportunity to enqueue some js and css
1122
+	 *
1123
+	 * @return void
1124
+	 */
1125
+	public function enqueue_js()
1126
+	{
1127
+		//ask our display strategy and validation strategies if they have js to enqueue
1128
+		$this->enqueue_js_from_strategies();
1129
+	}
1130
+
1131
+
1132
+
1133
+	/**
1134
+	 * Tells strategies when its ok to enqueue their js and css
1135
+	 *
1136
+	 * @return void
1137
+	 */
1138
+	public function enqueue_js_from_strategies()
1139
+	{
1140
+		$this->get_display_strategy()->enqueue_js();
1141
+		foreach ($this->get_validation_strategies() as $validation_strategy) {
1142
+			$validation_strategy->enqueue_js();
1143
+		}
1144
+	}
1145 1145
 }
Please login to merge, or discard this patch.
core/libraries/form_sections/base/EE_Form_Section_Base.form.php 2 patches
Indentation   +446 added lines, -446 removed lines patch added patch discarded remove patch
@@ -2,7 +2,7 @@  discard block
 block discarded – undo
2 2
 use EventEspresso\core\libraries\form_sections\strategies\filter\FormHtmlFilter;
3 3
 
4 4
 if (! defined('EVENT_ESPRESSO_VERSION')) {
5
-    exit('No direct script access allowed');
5
+	exit('No direct script access allowed');
6 6
 }
7 7
 
8 8
 
@@ -19,462 +19,462 @@  discard block
 block discarded – undo
19 19
 abstract class EE_Form_Section_Base
20 20
 {
21 21
 
22
-    /**
23
-     * the URL the form is submitted to
24
-     *
25
-     * @var string
26
-     */
27
-    protected $_action;
28
-
29
-    /**
30
-     * POST (default) or GET
31
-     *
32
-     * @var string
33
-     */
34
-    protected $_method;
35
-
36
-    /**
37
-     * html_id and html_name are derived from this by default
38
-     *
39
-     * @var string
40
-     */
41
-    protected $_name;
42
-
43
-    /**
44
-     * $_html_id
45
-     * @var string
46
-     */
47
-    protected $_html_id;
48
-
49
-    /**
50
-     * $_html_class
51
-     * @var string
52
-     */
53
-    protected $_html_class;
54
-
55
-    /**
56
-     * $_html_style
57
-     * @var string
58
-     */
59
-    protected $_html_style;
60
-
61
-    /**
62
-     * $_other_html_attributes
63
-     * @var string
64
-     */
65
-    protected $_other_html_attributes;
66
-
67
-    /**
68
-     * The form section of which this form section is a part
69
-     *
70
-     * @var EE_Form_Section_Proper
71
-     */
72
-    protected $_parent_section;
73
-
74
-    /**
75
-     * flag indicating that _construct_finalize has been called.
76
-     * If it hasn't been called and we try to use functions which require it, we call it
77
-     * with no parameters. But normally, _construct_finalize should be called by the instantiating class
78
-     *
79
-     * @var boolean
80
-     */
81
-    protected $_construction_finalized;
82
-
83
-    /**
84
-     * Strategy for parsing the form HTML upon display
85
-     *
86
-     * @var FormHtmlFilter
87
-     */
88
-    protected $_form_html_filter;
89
-
90
-
91
-
92
-    /**
93
-     * @param array $options_array {
94
-     * @type        $name          string the name for this form section, if you want to explicitly define it
95
-     *                             }
96
-     */
97
-    public function __construct($options_array = array())
98
-    {
99
-        // used by display strategies
100
-        // assign incoming values to properties
101
-        foreach ($options_array as $key => $value) {
102
-            $key = '_' . $key;
103
-            if (property_exists($this, $key) && empty($this->{$key})) {
104
-                $this->{$key} = $value;
105
-            }
106
-        }
107
-        // set parser which allows the form section's rendered HTML to be filtered
108
-        if (isset($options_array['form_html_filter']) && $options_array['form_html_filter'] instanceof FormHtmlFilter) {
109
-            $this->_form_html_filter = $options_array['form_html_filter'];
110
-        }
111
-    }
112
-
113
-
114
-
115
-    /**
116
-     * @param $parent_form_section
117
-     * @param $name
118
-     * @throws \EE_Error
119
-     */
120
-    protected function _construct_finalize($parent_form_section, $name)
121
-    {
122
-        $this->_construction_finalized = true;
123
-        $this->_parent_section = $parent_form_section;
124
-        if ($name !== null) {
125
-            $this->_name = $name;
126
-        }
127
-    }
128
-
129
-
130
-
131
-    /**
132
-     * make sure construction finalized was called, otherwise children might not be ready
133
-     *
134
-     * @return void
135
-     * @throws \EE_Error
136
-     */
137
-    public function ensure_construct_finalized_called()
138
-    {
139
-        if (! $this->_construction_finalized) {
140
-            $this->_construct_finalize($this->_parent_section, $this->_name);
141
-        }
142
-    }
143
-
144
-
145
-
146
-    /**
147
-     * @return string
148
-     */
149
-    public function action()
150
-    {
151
-        return $this->_action;
152
-    }
153
-
154
-
155
-
156
-    /**
157
-     * @param string $action
158
-     */
159
-    public function set_action($action)
160
-    {
161
-        $this->_action = $action;
162
-    }
163
-
164
-
165
-
166
-    /**
167
-     * @return string
168
-     */
169
-    public function method()
170
-    {
171
-        return ! empty($this->_method) ? $this->_method : 'POST';
172
-    }
173
-
174
-
175
-
176
-    /**
177
-     * @param string $method
178
-     */
179
-    public function set_method($method)
180
-    {
181
-        switch ($method) {
182
-            case 'get' :
183
-            case 'GET' :
184
-                $this->_method = 'GET';
185
-                break;
186
-            default :
187
-                $this->_method = 'POST';
188
-        }
189
-    }
190
-
191
-
192
-
193
-    /**
194
-     * Sets the html_id to its default value, if none was specified in the constructor.
195
-     * Calculation involves using the name and the parent's html id
196
-     * return void
197
-     *
198
-     * @throws \EE_Error
199
-     */
200
-    protected function _set_default_html_id_if_empty()
201
-    {
202
-        if (! $this->_html_id) {
203
-            if ($this->_parent_section && $this->_parent_section instanceof EE_Form_Section_Proper) {
204
-                $this->_html_id = $this->_parent_section->html_id()
205
-                                  . '-'
206
-                                  . $this->_prep_name_for_html_id($this->name());
207
-            } else {
208
-                $this->_html_id = $this->_prep_name_for_html_id($this->name());
209
-            }
210
-        }
211
-    }
212
-
213
-
214
-
215
-    /**
216
-     * _prep_name_for_html_id
217
-     *
218
-     * @param $name
219
-     * @return string
220
-     */
221
-    private function _prep_name_for_html_id($name)
222
-    {
223
-        return sanitize_key(str_replace(array('&nbsp;', ' ', '_'), '-', $name));
224
-    }
22
+	/**
23
+	 * the URL the form is submitted to
24
+	 *
25
+	 * @var string
26
+	 */
27
+	protected $_action;
28
+
29
+	/**
30
+	 * POST (default) or GET
31
+	 *
32
+	 * @var string
33
+	 */
34
+	protected $_method;
35
+
36
+	/**
37
+	 * html_id and html_name are derived from this by default
38
+	 *
39
+	 * @var string
40
+	 */
41
+	protected $_name;
42
+
43
+	/**
44
+	 * $_html_id
45
+	 * @var string
46
+	 */
47
+	protected $_html_id;
48
+
49
+	/**
50
+	 * $_html_class
51
+	 * @var string
52
+	 */
53
+	protected $_html_class;
54
+
55
+	/**
56
+	 * $_html_style
57
+	 * @var string
58
+	 */
59
+	protected $_html_style;
60
+
61
+	/**
62
+	 * $_other_html_attributes
63
+	 * @var string
64
+	 */
65
+	protected $_other_html_attributes;
66
+
67
+	/**
68
+	 * The form section of which this form section is a part
69
+	 *
70
+	 * @var EE_Form_Section_Proper
71
+	 */
72
+	protected $_parent_section;
73
+
74
+	/**
75
+	 * flag indicating that _construct_finalize has been called.
76
+	 * If it hasn't been called and we try to use functions which require it, we call it
77
+	 * with no parameters. But normally, _construct_finalize should be called by the instantiating class
78
+	 *
79
+	 * @var boolean
80
+	 */
81
+	protected $_construction_finalized;
82
+
83
+	/**
84
+	 * Strategy for parsing the form HTML upon display
85
+	 *
86
+	 * @var FormHtmlFilter
87
+	 */
88
+	protected $_form_html_filter;
89
+
90
+
91
+
92
+	/**
93
+	 * @param array $options_array {
94
+	 * @type        $name          string the name for this form section, if you want to explicitly define it
95
+	 *                             }
96
+	 */
97
+	public function __construct($options_array = array())
98
+	{
99
+		// used by display strategies
100
+		// assign incoming values to properties
101
+		foreach ($options_array as $key => $value) {
102
+			$key = '_' . $key;
103
+			if (property_exists($this, $key) && empty($this->{$key})) {
104
+				$this->{$key} = $value;
105
+			}
106
+		}
107
+		// set parser which allows the form section's rendered HTML to be filtered
108
+		if (isset($options_array['form_html_filter']) && $options_array['form_html_filter'] instanceof FormHtmlFilter) {
109
+			$this->_form_html_filter = $options_array['form_html_filter'];
110
+		}
111
+	}
112
+
113
+
114
+
115
+	/**
116
+	 * @param $parent_form_section
117
+	 * @param $name
118
+	 * @throws \EE_Error
119
+	 */
120
+	protected function _construct_finalize($parent_form_section, $name)
121
+	{
122
+		$this->_construction_finalized = true;
123
+		$this->_parent_section = $parent_form_section;
124
+		if ($name !== null) {
125
+			$this->_name = $name;
126
+		}
127
+	}
128
+
129
+
130
+
131
+	/**
132
+	 * make sure construction finalized was called, otherwise children might not be ready
133
+	 *
134
+	 * @return void
135
+	 * @throws \EE_Error
136
+	 */
137
+	public function ensure_construct_finalized_called()
138
+	{
139
+		if (! $this->_construction_finalized) {
140
+			$this->_construct_finalize($this->_parent_section, $this->_name);
141
+		}
142
+	}
143
+
144
+
145
+
146
+	/**
147
+	 * @return string
148
+	 */
149
+	public function action()
150
+	{
151
+		return $this->_action;
152
+	}
153
+
154
+
155
+
156
+	/**
157
+	 * @param string $action
158
+	 */
159
+	public function set_action($action)
160
+	{
161
+		$this->_action = $action;
162
+	}
163
+
164
+
165
+
166
+	/**
167
+	 * @return string
168
+	 */
169
+	public function method()
170
+	{
171
+		return ! empty($this->_method) ? $this->_method : 'POST';
172
+	}
173
+
174
+
175
+
176
+	/**
177
+	 * @param string $method
178
+	 */
179
+	public function set_method($method)
180
+	{
181
+		switch ($method) {
182
+			case 'get' :
183
+			case 'GET' :
184
+				$this->_method = 'GET';
185
+				break;
186
+			default :
187
+				$this->_method = 'POST';
188
+		}
189
+	}
190
+
191
+
192
+
193
+	/**
194
+	 * Sets the html_id to its default value, if none was specified in the constructor.
195
+	 * Calculation involves using the name and the parent's html id
196
+	 * return void
197
+	 *
198
+	 * @throws \EE_Error
199
+	 */
200
+	protected function _set_default_html_id_if_empty()
201
+	{
202
+		if (! $this->_html_id) {
203
+			if ($this->_parent_section && $this->_parent_section instanceof EE_Form_Section_Proper) {
204
+				$this->_html_id = $this->_parent_section->html_id()
205
+								  . '-'
206
+								  . $this->_prep_name_for_html_id($this->name());
207
+			} else {
208
+				$this->_html_id = $this->_prep_name_for_html_id($this->name());
209
+			}
210
+		}
211
+	}
212
+
213
+
214
+
215
+	/**
216
+	 * _prep_name_for_html_id
217
+	 *
218
+	 * @param $name
219
+	 * @return string
220
+	 */
221
+	private function _prep_name_for_html_id($name)
222
+	{
223
+		return sanitize_key(str_replace(array('&nbsp;', ' ', '_'), '-', $name));
224
+	}
225 225
 
226 226
 
227 227
 
228
-    /**
229
-     * Returns the HTML, JS, and CSS necessary to display this form section on a page.
230
-     * Note however, it's recommended that you instead call enqueue_js on the "wp_enqueue_scripts" action,
231
-     * and call get_html when you want to output the html. Calling get_html_and_js after
232
-     * "wp_enqueue_scripts" has already fired seems to work for now, but is contrary
233
-     * to the instructions on https://developer.wordpress.org/reference/functions/wp_enqueue_script/
234
-     * and so might stop working anytime.
235
-     *
236
-     * @return string
237
-     */
238
-    public function get_html_and_js()
239
-    {
240
-        return $this->get_html();
241
-    }
228
+	/**
229
+	 * Returns the HTML, JS, and CSS necessary to display this form section on a page.
230
+	 * Note however, it's recommended that you instead call enqueue_js on the "wp_enqueue_scripts" action,
231
+	 * and call get_html when you want to output the html. Calling get_html_and_js after
232
+	 * "wp_enqueue_scripts" has already fired seems to work for now, but is contrary
233
+	 * to the instructions on https://developer.wordpress.org/reference/functions/wp_enqueue_script/
234
+	 * and so might stop working anytime.
235
+	 *
236
+	 * @return string
237
+	 */
238
+	public function get_html_and_js()
239
+	{
240
+		return $this->get_html();
241
+	}
242 242
 
243 243
 
244 244
 
245
-    /**
246
-     * Gets the HTML for displaying this form section
247
-     *
248
-     * @return string
249
-     */
250
-    public abstract function get_html();
245
+	/**
246
+	 * Gets the HTML for displaying this form section
247
+	 *
248
+	 * @return string
249
+	 */
250
+	public abstract function get_html();
251 251
 
252 252
 
253 253
 
254
-    /**
255
-     * @param bool $add_pound_sign
256
-     * @return string
257
-     */
258
-    public function html_id($add_pound_sign = false)
259
-    {
260
-        $this->_set_default_html_id_if_empty();
261
-        return $add_pound_sign ? '#' . $this->_html_id : $this->_html_id;
262
-    }
254
+	/**
255
+	 * @param bool $add_pound_sign
256
+	 * @return string
257
+	 */
258
+	public function html_id($add_pound_sign = false)
259
+	{
260
+		$this->_set_default_html_id_if_empty();
261
+		return $add_pound_sign ? '#' . $this->_html_id : $this->_html_id;
262
+	}
263 263
 
264 264
 
265
-
266
-    /**
267
-     * @return string
268
-     */
269
-    public function html_class()
270
-    {
271
-        return $this->_html_class;
272
-    }
273
-
274
-
275
-
276
-    /**
277
-     * @return string
278
-     */
279
-    public function html_style()
280
-    {
281
-        return $this->_html_style;
282
-    }
283
-
284
-
285
-
286
-    /**
287
-     * @param mixed $html_class
288
-     */
289
-    public function set_html_class($html_class)
290
-    {
291
-        $this->_html_class = $html_class;
292
-    }
293
-
294
-
295
-
296
-    /**
297
-     * @param mixed $html_id
298
-     */
299
-    public function set_html_id($html_id)
300
-    {
301
-        $this->_html_id = $html_id;
302
-    }
303
-
304
-
305
-
306
-    /**
307
-     * @param mixed $html_style
308
-     */
309
-    public function set_html_style($html_style)
310
-    {
311
-        $this->_html_style = $html_style;
312
-    }
313
-
314
-
315
-
316
-    /**
317
-     * @param string $other_html_attributes
318
-     */
319
-    public function set_other_html_attributes($other_html_attributes)
320
-    {
321
-        $this->_other_html_attributes = $other_html_attributes;
322
-    }
323
-
324
-
325
-
326
-    /**
327
-     * @return string
328
-     */
329
-    public function other_html_attributes()
330
-    {
331
-        return $this->_other_html_attributes;
332
-    }
333
-
334
-
335
-
336
-    /**
337
-     * Gets the name of the form section. This is not the same as the HTML name.
338
-     *
339
-     * @throws EE_Error
340
-     * @return string
341
-     */
342
-    public function name()
343
-    {
344
-        if (! $this->_construction_finalized) {
345
-            throw new EE_Error(sprintf(__('You cannot use the form section\s name until _construct_finalize has been called on it (when we set the name). It was called on a form section of type \'s\'',
346
-                'event_espresso'), get_class($this)));
347
-        }
348
-        return $this->_name;
349
-    }
350
-
351
-
352
-
353
-    /**
354
-     * Gets the parent section
355
-     *
356
-     * @return EE_Form_Section_Proper
357
-     */
358
-    public function parent_section()
359
-    {
360
-        return $this->_parent_section;
361
-    }
362
-
363
-
364
-
365
-    /**
366
-     * returns HTML for generating the opening form HTML tag (<form>)
367
-     *
368
-     * @param string $action           the URL the form is submitted to
369
-     * @param string $method           POST (default) or GET
370
-     * @param string $other_attributes anything else added to the form open tag, MUST BE VALID HTML
371
-     * @return string
372
-     */
373
-    public function form_open($action = '', $method = '', $other_attributes = '')
374
-    {
375
-        if (! empty($action)) {
376
-            $this->set_action($action);
377
-        }
378
-        if (! empty($method)) {
379
-            $this->set_method($method);
380
-        }
381
-        $html = EEH_HTML::nl(1, 'form') . '<form';
382
-        $html .= $this->html_id() !== '' ? ' id="' . $this->html_id() . '"' : '';
383
-        $html .= ' action="' . $this->action() . '"';
384
-        $html .= ' method="' . $this->method() . '"';
385
-        $html .= $other_attributes . '>';
386
-        return $html;
387
-    }
388
-
389
-
390
-
391
-    /**
392
-     * returns HTML for generating the closing form HTML tag (</form>)
393
-     *
394
-     * @return string
395
-     */
396
-    public function form_close()
397
-    {
398
-        return EEH_HTML::nl(-1, 'form')
399
-               . '</form>'
400
-               . EEH_HTML::nl()
401
-               . '<!-- end of ee-'
402
-               . $this->html_id()
403
-               . '-form -->'
404
-               . EEH_HTML::nl();
405
-    }
406
-
407
-
408
-
409
-    /**
410
-     * enqueues JS (and CSS) for the form (ie immediately call wp_enqueue_script and
411
-     * wp_enqueue_style; the scripts could have optionally been registered earlier)
412
-     * Default does nothing, but child classes can override
413
-     *
414
-     * @return void
415
-     */
416
-    public function enqueue_js()
417
-    {
418
-        //defaults to enqueue NO js or css
419
-    }
420
-
421
-
422
-
423
-    /**
424
-     * Adds any extra data needed by js. Eventually we'll call wp_localize_script
425
-     * with it, and it will be on each form section's 'other_data' property.
426
-     * By default nothing is added, but child classes can extend this method to add something.
427
-     * Eg, if you have an input that will cause a modal dialog to appear,
428
-     * here you could add an entry like 'modal_dialog_inputs' to this array
429
-     * to map between the input's html ID and the modal dialogue's ID, so that
430
-     * your JS code will know where to find the modal dialog when the input is pressed.
431
-     * Eg $form_other_js_data['modal_dialog_inputs']['some-input-id']='modal-dialog-id';
432
-     *
433
-     * @param array $form_other_js_data
434
-     * @return array
435
-     */
436
-    public function get_other_js_data($form_other_js_data = array())
437
-    {
438
-        return $form_other_js_data;
439
-    }
440
-
441
-
442
-
443
-    /**
444
-     * This isn't just the name of an input, it's a path pointing to an input. The
445
-     * path is similar to a folder path: slash (/) means to descend into a subsection,
446
-     * dot-dot-slash (../) means to ascend into the parent section.
447
-     * After a series of slashes and dot-dot-slashes, there should be the name of an input,
448
-     * which will be returned.
449
-     * Eg, if you want the related input to be conditional on a sibling input name 'foobar'
450
-     * just use 'foobar'. If you want it to be conditional on an aunt/uncle input name
451
-     * 'baz', use '../baz'. If you want it to be conditional on a cousin input,
452
-     * the child of 'baz_section' named 'baz_child', use '../baz_section/baz_child'.
453
-     * Etc
454
-     *
455
-     * @param string|false $form_section_path we accept false also because substr( '../', '../' ) = false
456
-     * @return EE_Form_Section_Base
457
-     */
458
-    public function find_section_from_path($form_section_path)
459
-    {
460
-        if (strpos($form_section_path, '/') === 0) {
461
-            $form_section_path = substr($form_section_path, strlen('/'));
462
-        }
463
-        if (empty($form_section_path)) {
464
-            return $this;
465
-        }
466
-        if (strpos($form_section_path, '../') === 0) {
467
-            $parent = $this->parent_section();
468
-            $form_section_path = substr($form_section_path, strlen('../'));
469
-            if ($parent instanceof EE_Form_Section_Base) {
470
-                return $parent->find_section_from_path($form_section_path);
471
-            } elseif (empty($form_section_path)) {
472
-                return $this;
473
-            }
474
-        }
475
-        //couldn't find it using simple parent following
476
-        return null;
477
-    }
265
+
266
+	/**
267
+	 * @return string
268
+	 */
269
+	public function html_class()
270
+	{
271
+		return $this->_html_class;
272
+	}
273
+
274
+
275
+
276
+	/**
277
+	 * @return string
278
+	 */
279
+	public function html_style()
280
+	{
281
+		return $this->_html_style;
282
+	}
283
+
284
+
285
+
286
+	/**
287
+	 * @param mixed $html_class
288
+	 */
289
+	public function set_html_class($html_class)
290
+	{
291
+		$this->_html_class = $html_class;
292
+	}
293
+
294
+
295
+
296
+	/**
297
+	 * @param mixed $html_id
298
+	 */
299
+	public function set_html_id($html_id)
300
+	{
301
+		$this->_html_id = $html_id;
302
+	}
303
+
304
+
305
+
306
+	/**
307
+	 * @param mixed $html_style
308
+	 */
309
+	public function set_html_style($html_style)
310
+	{
311
+		$this->_html_style = $html_style;
312
+	}
313
+
314
+
315
+
316
+	/**
317
+	 * @param string $other_html_attributes
318
+	 */
319
+	public function set_other_html_attributes($other_html_attributes)
320
+	{
321
+		$this->_other_html_attributes = $other_html_attributes;
322
+	}
323
+
324
+
325
+
326
+	/**
327
+	 * @return string
328
+	 */
329
+	public function other_html_attributes()
330
+	{
331
+		return $this->_other_html_attributes;
332
+	}
333
+
334
+
335
+
336
+	/**
337
+	 * Gets the name of the form section. This is not the same as the HTML name.
338
+	 *
339
+	 * @throws EE_Error
340
+	 * @return string
341
+	 */
342
+	public function name()
343
+	{
344
+		if (! $this->_construction_finalized) {
345
+			throw new EE_Error(sprintf(__('You cannot use the form section\s name until _construct_finalize has been called on it (when we set the name). It was called on a form section of type \'s\'',
346
+				'event_espresso'), get_class($this)));
347
+		}
348
+		return $this->_name;
349
+	}
350
+
351
+
352
+
353
+	/**
354
+	 * Gets the parent section
355
+	 *
356
+	 * @return EE_Form_Section_Proper
357
+	 */
358
+	public function parent_section()
359
+	{
360
+		return $this->_parent_section;
361
+	}
362
+
363
+
364
+
365
+	/**
366
+	 * returns HTML for generating the opening form HTML tag (<form>)
367
+	 *
368
+	 * @param string $action           the URL the form is submitted to
369
+	 * @param string $method           POST (default) or GET
370
+	 * @param string $other_attributes anything else added to the form open tag, MUST BE VALID HTML
371
+	 * @return string
372
+	 */
373
+	public function form_open($action = '', $method = '', $other_attributes = '')
374
+	{
375
+		if (! empty($action)) {
376
+			$this->set_action($action);
377
+		}
378
+		if (! empty($method)) {
379
+			$this->set_method($method);
380
+		}
381
+		$html = EEH_HTML::nl(1, 'form') . '<form';
382
+		$html .= $this->html_id() !== '' ? ' id="' . $this->html_id() . '"' : '';
383
+		$html .= ' action="' . $this->action() . '"';
384
+		$html .= ' method="' . $this->method() . '"';
385
+		$html .= $other_attributes . '>';
386
+		return $html;
387
+	}
388
+
389
+
390
+
391
+	/**
392
+	 * returns HTML for generating the closing form HTML tag (</form>)
393
+	 *
394
+	 * @return string
395
+	 */
396
+	public function form_close()
397
+	{
398
+		return EEH_HTML::nl(-1, 'form')
399
+			   . '</form>'
400
+			   . EEH_HTML::nl()
401
+			   . '<!-- end of ee-'
402
+			   . $this->html_id()
403
+			   . '-form -->'
404
+			   . EEH_HTML::nl();
405
+	}
406
+
407
+
408
+
409
+	/**
410
+	 * enqueues JS (and CSS) for the form (ie immediately call wp_enqueue_script and
411
+	 * wp_enqueue_style; the scripts could have optionally been registered earlier)
412
+	 * Default does nothing, but child classes can override
413
+	 *
414
+	 * @return void
415
+	 */
416
+	public function enqueue_js()
417
+	{
418
+		//defaults to enqueue NO js or css
419
+	}
420
+
421
+
422
+
423
+	/**
424
+	 * Adds any extra data needed by js. Eventually we'll call wp_localize_script
425
+	 * with it, and it will be on each form section's 'other_data' property.
426
+	 * By default nothing is added, but child classes can extend this method to add something.
427
+	 * Eg, if you have an input that will cause a modal dialog to appear,
428
+	 * here you could add an entry like 'modal_dialog_inputs' to this array
429
+	 * to map between the input's html ID and the modal dialogue's ID, so that
430
+	 * your JS code will know where to find the modal dialog when the input is pressed.
431
+	 * Eg $form_other_js_data['modal_dialog_inputs']['some-input-id']='modal-dialog-id';
432
+	 *
433
+	 * @param array $form_other_js_data
434
+	 * @return array
435
+	 */
436
+	public function get_other_js_data($form_other_js_data = array())
437
+	{
438
+		return $form_other_js_data;
439
+	}
440
+
441
+
442
+
443
+	/**
444
+	 * This isn't just the name of an input, it's a path pointing to an input. The
445
+	 * path is similar to a folder path: slash (/) means to descend into a subsection,
446
+	 * dot-dot-slash (../) means to ascend into the parent section.
447
+	 * After a series of slashes and dot-dot-slashes, there should be the name of an input,
448
+	 * which will be returned.
449
+	 * Eg, if you want the related input to be conditional on a sibling input name 'foobar'
450
+	 * just use 'foobar'. If you want it to be conditional on an aunt/uncle input name
451
+	 * 'baz', use '../baz'. If you want it to be conditional on a cousin input,
452
+	 * the child of 'baz_section' named 'baz_child', use '../baz_section/baz_child'.
453
+	 * Etc
454
+	 *
455
+	 * @param string|false $form_section_path we accept false also because substr( '../', '../' ) = false
456
+	 * @return EE_Form_Section_Base
457
+	 */
458
+	public function find_section_from_path($form_section_path)
459
+	{
460
+		if (strpos($form_section_path, '/') === 0) {
461
+			$form_section_path = substr($form_section_path, strlen('/'));
462
+		}
463
+		if (empty($form_section_path)) {
464
+			return $this;
465
+		}
466
+		if (strpos($form_section_path, '../') === 0) {
467
+			$parent = $this->parent_section();
468
+			$form_section_path = substr($form_section_path, strlen('../'));
469
+			if ($parent instanceof EE_Form_Section_Base) {
470
+				return $parent->find_section_from_path($form_section_path);
471
+			} elseif (empty($form_section_path)) {
472
+				return $this;
473
+			}
474
+		}
475
+		//couldn't find it using simple parent following
476
+		return null;
477
+	}
478 478
 
479 479
 
480 480
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 use EventEspresso\core\libraries\form_sections\strategies\filter\FormHtmlFilter;
3 3
 
4
-if (! defined('EVENT_ESPRESSO_VERSION')) {
4
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
5 5
     exit('No direct script access allowed');
6 6
 }
7 7
 
@@ -99,7 +99,7 @@  discard block
 block discarded – undo
99 99
         // used by display strategies
100 100
         // assign incoming values to properties
101 101
         foreach ($options_array as $key => $value) {
102
-            $key = '_' . $key;
102
+            $key = '_'.$key;
103 103
             if (property_exists($this, $key) && empty($this->{$key})) {
104 104
                 $this->{$key} = $value;
105 105
             }
@@ -136,7 +136,7 @@  discard block
 block discarded – undo
136 136
      */
137 137
     public function ensure_construct_finalized_called()
138 138
     {
139
-        if (! $this->_construction_finalized) {
139
+        if ( ! $this->_construction_finalized) {
140 140
             $this->_construct_finalize($this->_parent_section, $this->_name);
141 141
         }
142 142
     }
@@ -199,7 +199,7 @@  discard block
 block discarded – undo
199 199
      */
200 200
     protected function _set_default_html_id_if_empty()
201 201
     {
202
-        if (! $this->_html_id) {
202
+        if ( ! $this->_html_id) {
203 203
             if ($this->_parent_section && $this->_parent_section instanceof EE_Form_Section_Proper) {
204 204
                 $this->_html_id = $this->_parent_section->html_id()
205 205
                                   . '-'
@@ -258,7 +258,7 @@  discard block
 block discarded – undo
258 258
     public function html_id($add_pound_sign = false)
259 259
     {
260 260
         $this->_set_default_html_id_if_empty();
261
-        return $add_pound_sign ? '#' . $this->_html_id : $this->_html_id;
261
+        return $add_pound_sign ? '#'.$this->_html_id : $this->_html_id;
262 262
     }
263 263
 
264 264
 
@@ -341,7 +341,7 @@  discard block
 block discarded – undo
341 341
      */
342 342
     public function name()
343 343
     {
344
-        if (! $this->_construction_finalized) {
344
+        if ( ! $this->_construction_finalized) {
345 345
             throw new EE_Error(sprintf(__('You cannot use the form section\s name until _construct_finalize has been called on it (when we set the name). It was called on a form section of type \'s\'',
346 346
                 'event_espresso'), get_class($this)));
347 347
         }
@@ -372,17 +372,17 @@  discard block
 block discarded – undo
372 372
      */
373 373
     public function form_open($action = '', $method = '', $other_attributes = '')
374 374
     {
375
-        if (! empty($action)) {
375
+        if ( ! empty($action)) {
376 376
             $this->set_action($action);
377 377
         }
378
-        if (! empty($method)) {
378
+        if ( ! empty($method)) {
379 379
             $this->set_method($method);
380 380
         }
381
-        $html = EEH_HTML::nl(1, 'form') . '<form';
382
-        $html .= $this->html_id() !== '' ? ' id="' . $this->html_id() . '"' : '';
383
-        $html .= ' action="' . $this->action() . '"';
384
-        $html .= ' method="' . $this->method() . '"';
385
-        $html .= $other_attributes . '>';
381
+        $html = EEH_HTML::nl(1, 'form').'<form';
382
+        $html .= $this->html_id() !== '' ? ' id="'.$this->html_id().'"' : '';
383
+        $html .= ' action="'.$this->action().'"';
384
+        $html .= ' method="'.$this->method().'"';
385
+        $html .= $other_attributes.'>';
386 386
         return $html;
387 387
     }
388 388
 
Please login to merge, or discard this patch.
core/libraries/form_sections/strategies/layout/EE_No_Layout.strategy.php 2 patches
Indentation   +94 added lines, -94 removed lines patch added patch discarded remove patch
@@ -13,110 +13,110 @@
 block discarded – undo
13 13
 {
14 14
 
15 15
 
16
-    /**
17
-     * This is a flag indicating whether to use '<br>' tags after each input in the layout
18
-     * strategy.
19
-     *
20
-     * @var bool
21
-     */
22
-    protected $_use_break_tags = true;
16
+	/**
17
+	 * This is a flag indicating whether to use '<br>' tags after each input in the layout
18
+	 * strategy.
19
+	 *
20
+	 * @var bool
21
+	 */
22
+	protected $_use_break_tags = true;
23 23
 
24 24
 
25
-    /**
26
-     * EE_No_Layout constructor.
27
-     *
28
-     * @param array $options  Currently if this has a 'use_break_tags' key that is used to set the _use_break_tags
29
-     *                        property on the class.
30
-     */
31
-    public function __construct($options = array())
32
-    {
33
-        $this->_use_break_tags = is_array($options) && isset($options['use_break_tags'])
34
-            ? filter_var($options['use_break_tags'], FILTER_VALIDATE_BOOLEAN)
35
-            : $this->_use_break_tags;
36
-        parent::__construct();
37
-    }
25
+	/**
26
+	 * EE_No_Layout constructor.
27
+	 *
28
+	 * @param array $options  Currently if this has a 'use_break_tags' key that is used to set the _use_break_tags
29
+	 *                        property on the class.
30
+	 */
31
+	public function __construct($options = array())
32
+	{
33
+		$this->_use_break_tags = is_array($options) && isset($options['use_break_tags'])
34
+			? filter_var($options['use_break_tags'], FILTER_VALIDATE_BOOLEAN)
35
+			: $this->_use_break_tags;
36
+		parent::__construct();
37
+	}
38 38
 
39
-    /**
40
-     * Add line break at beginning of form
41
-     *
42
-     * @return string
43
-     */
44
-    public function layout_form_begin()
45
-    {
46
-        return EEH_HTML::nl(1);
47
-    }
39
+	/**
40
+	 * Add line break at beginning of form
41
+	 *
42
+	 * @return string
43
+	 */
44
+	public function layout_form_begin()
45
+	{
46
+		return EEH_HTML::nl(1);
47
+	}
48 48
 
49 49
 
50
-    /**
51
-     * Lays out the row for the input, including label and errors
52
-     *
53
-     * @param EE_Form_Input_Base $input
54
-     * @return string
55
-     * @throws \EE_Error
56
-     */
57
-    public function layout_input($input)
58
-    {
59
-        $html = '';
60
-        if ($input instanceof EE_Hidden_Input) {
61
-            $html .= EEH_HTML::nl() . $input->get_html_for_input();
62
-        } else if ($input instanceof EE_Submit_Input) {
63
-            $html .= $this->br();
64
-            $html .= $input->get_html_for_input();
65
-        } else if ($input instanceof EE_Select_Input) {
66
-            $html .= $this->br();
67
-            $html .= EEH_HTML::nl(1) . $input->get_html_for_label();
68
-            $html .= EEH_HTML::nl() . $input->get_html_for_errors();
69
-            $html .= EEH_HTML::nl() . $input->get_html_for_input();
70
-            $html .= EEH_HTML::nl() . $input->get_html_for_help();
71
-            $html .= $this->br();
72
-        } else if ($input instanceof EE_Form_Input_With_Options_Base) {
73
-            $html .= $this->br();
74
-            $html .= EEH_HTML::nl() . $input->get_html_for_errors();
75
-            $html .= EEH_HTML::nl() . $input->get_html_for_input();
76
-            $html .= EEH_HTML::nl() . $input->get_html_for_help();
77
-        } else {
78
-            $html .= $this->br();
79
-            $html .= EEH_HTML::nl(1) . $input->get_html_for_label();
80
-            $html .= EEH_HTML::nl() . $input->get_html_for_errors();
81
-            $html .= EEH_HTML::nl() . $input->get_html_for_input();
82
-            $html .= EEH_HTML::nl() . $input->get_html_for_help();
83
-        }
84
-        $html .= EEH_HTML::nl(-1);
85
-        return $html;
86
-    }
50
+	/**
51
+	 * Lays out the row for the input, including label and errors
52
+	 *
53
+	 * @param EE_Form_Input_Base $input
54
+	 * @return string
55
+	 * @throws \EE_Error
56
+	 */
57
+	public function layout_input($input)
58
+	{
59
+		$html = '';
60
+		if ($input instanceof EE_Hidden_Input) {
61
+			$html .= EEH_HTML::nl() . $input->get_html_for_input();
62
+		} else if ($input instanceof EE_Submit_Input) {
63
+			$html .= $this->br();
64
+			$html .= $input->get_html_for_input();
65
+		} else if ($input instanceof EE_Select_Input) {
66
+			$html .= $this->br();
67
+			$html .= EEH_HTML::nl(1) . $input->get_html_for_label();
68
+			$html .= EEH_HTML::nl() . $input->get_html_for_errors();
69
+			$html .= EEH_HTML::nl() . $input->get_html_for_input();
70
+			$html .= EEH_HTML::nl() . $input->get_html_for_help();
71
+			$html .= $this->br();
72
+		} else if ($input instanceof EE_Form_Input_With_Options_Base) {
73
+			$html .= $this->br();
74
+			$html .= EEH_HTML::nl() . $input->get_html_for_errors();
75
+			$html .= EEH_HTML::nl() . $input->get_html_for_input();
76
+			$html .= EEH_HTML::nl() . $input->get_html_for_help();
77
+		} else {
78
+			$html .= $this->br();
79
+			$html .= EEH_HTML::nl(1) . $input->get_html_for_label();
80
+			$html .= EEH_HTML::nl() . $input->get_html_for_errors();
81
+			$html .= EEH_HTML::nl() . $input->get_html_for_input();
82
+			$html .= EEH_HTML::nl() . $input->get_html_for_help();
83
+		}
84
+		$html .= EEH_HTML::nl(-1);
85
+		return $html;
86
+	}
87 87
 
88 88
 
89
-    /**
90
-     * Lays out a row for the subsection
91
-     *
92
-     * @param EE_Form_Section_Proper $form_section
93
-     * @return string
94
-     */
95
-    public function layout_subsection($form_section)
96
-    {
89
+	/**
90
+	 * Lays out a row for the subsection
91
+	 *
92
+	 * @param EE_Form_Section_Proper $form_section
93
+	 * @return string
94
+	 */
95
+	public function layout_subsection($form_section)
96
+	{
97 97
 //		d( $form_section );
98
-        return EEH_HTML::nl(1) . $form_section->get_html() . EEH_HTML::nl(-1);
99
-    }
98
+		return EEH_HTML::nl(1) . $form_section->get_html() . EEH_HTML::nl(-1);
99
+	}
100 100
 
101 101
 
102
-    /**
103
-     * Add line break at end of form.
104
-     *
105
-     * @return string
106
-     */
107
-    public function layout_form_end()
108
-    {
109
-        return EEH_HTML::nl(-1);
110
-    }
102
+	/**
103
+	 * Add line break at end of form.
104
+	 *
105
+	 * @return string
106
+	 */
107
+	public function layout_form_end()
108
+	{
109
+		return EEH_HTML::nl(-1);
110
+	}
111 111
 
112 112
 
113
-    /**
114
-     * This returns a break tag or an empty string depending on the value of the `_use_break_tags` property.
115
-     *
116
-     * @return string
117
-     */
118
-    protected function br()
119
-    {
120
-        return $this->_use_break_tags ? EEH_HTML::br() : '';
121
-    }
113
+	/**
114
+	 * This returns a break tag or an empty string depending on the value of the `_use_break_tags` property.
115
+	 *
116
+	 * @return string
117
+	 */
118
+	protected function br()
119
+	{
120
+		return $this->_use_break_tags ? EEH_HTML::br() : '';
121
+	}
122 122
 }
123 123
\ No newline at end of file
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -58,28 +58,28 @@  discard block
 block discarded – undo
58 58
     {
59 59
         $html = '';
60 60
         if ($input instanceof EE_Hidden_Input) {
61
-            $html .= EEH_HTML::nl() . $input->get_html_for_input();
61
+            $html .= EEH_HTML::nl().$input->get_html_for_input();
62 62
         } else if ($input instanceof EE_Submit_Input) {
63 63
             $html .= $this->br();
64 64
             $html .= $input->get_html_for_input();
65 65
         } else if ($input instanceof EE_Select_Input) {
66 66
             $html .= $this->br();
67
-            $html .= EEH_HTML::nl(1) . $input->get_html_for_label();
68
-            $html .= EEH_HTML::nl() . $input->get_html_for_errors();
69
-            $html .= EEH_HTML::nl() . $input->get_html_for_input();
70
-            $html .= EEH_HTML::nl() . $input->get_html_for_help();
67
+            $html .= EEH_HTML::nl(1).$input->get_html_for_label();
68
+            $html .= EEH_HTML::nl().$input->get_html_for_errors();
69
+            $html .= EEH_HTML::nl().$input->get_html_for_input();
70
+            $html .= EEH_HTML::nl().$input->get_html_for_help();
71 71
             $html .= $this->br();
72 72
         } else if ($input instanceof EE_Form_Input_With_Options_Base) {
73 73
             $html .= $this->br();
74
-            $html .= EEH_HTML::nl() . $input->get_html_for_errors();
75
-            $html .= EEH_HTML::nl() . $input->get_html_for_input();
76
-            $html .= EEH_HTML::nl() . $input->get_html_for_help();
74
+            $html .= EEH_HTML::nl().$input->get_html_for_errors();
75
+            $html .= EEH_HTML::nl().$input->get_html_for_input();
76
+            $html .= EEH_HTML::nl().$input->get_html_for_help();
77 77
         } else {
78 78
             $html .= $this->br();
79
-            $html .= EEH_HTML::nl(1) . $input->get_html_for_label();
80
-            $html .= EEH_HTML::nl() . $input->get_html_for_errors();
81
-            $html .= EEH_HTML::nl() . $input->get_html_for_input();
82
-            $html .= EEH_HTML::nl() . $input->get_html_for_help();
79
+            $html .= EEH_HTML::nl(1).$input->get_html_for_label();
80
+            $html .= EEH_HTML::nl().$input->get_html_for_errors();
81
+            $html .= EEH_HTML::nl().$input->get_html_for_input();
82
+            $html .= EEH_HTML::nl().$input->get_html_for_help();
83 83
         }
84 84
         $html .= EEH_HTML::nl(-1);
85 85
         return $html;
@@ -95,7 +95,7 @@  discard block
 block discarded – undo
95 95
     public function layout_subsection($form_section)
96 96
     {
97 97
 //		d( $form_section );
98
-        return EEH_HTML::nl(1) . $form_section->get_html() . EEH_HTML::nl(-1);
98
+        return EEH_HTML::nl(1).$form_section->get_html().EEH_HTML::nl(-1);
99 99
     }
100 100
 
101 101
 
Please login to merge, or discard this patch.
core/libraries/form_sections/strategies/filter/FormHtmlFilter.php 1 patch
Indentation   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -18,12 +18,12 @@
 block discarded – undo
18 18
 abstract class FormHtmlFilter
19 19
 {
20 20
 
21
-    /**
22
-     * @param                        $html
23
-     * @param EE_Form_Section_Validatable $form_section
24
-     * @return string
25
-     */
26
-    abstract public function filterHtml($html, EE_Form_Section_Validatable $form_section);
21
+	/**
22
+	 * @param                        $html
23
+	 * @param EE_Form_Section_Validatable $form_section
24
+	 * @return string
25
+	 */
26
+	abstract public function filterHtml($html, EE_Form_Section_Validatable $form_section);
27 27
 
28 28
 }
29 29
 // End of file FormHtmlFilter.php
Please login to merge, or discard this patch.
core/db_models/EEM_Event.model.php 2 patches
Indentation   +745 added lines, -745 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
 require_once(EE_MODELS . 'EEM_CPT_Base.model.php');
5 5
 
@@ -16,750 +16,750 @@  discard block
 block discarded – undo
16 16
 class EEM_Event extends EEM_CPT_Base
17 17
 {
18 18
 
19
-    /**
20
-     * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the
21
-     * event
22
-     */
23
-    const sold_out = 'sold_out';
24
-
25
-    /**
26
-     * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later
27
-     * date)
28
-     */
29
-    const postponed = 'postponed';
30
-
31
-    /**
32
-     * constant used by status(), indicating that the event will no longer occur
33
-     */
34
-    const cancelled = 'cancelled';
35
-
36
-
37
-    /**
38
-     * @var string
39
-     */
40
-    protected static $_default_reg_status;
41
-
42
-
43
-    /**
44
-     * private instance of the Event object
45
-     *
46
-     * @var EEM_Event
47
-     */
48
-    protected static $_instance;
49
-
50
-
51
-
52
-    /**
53
-     *  This function is a singleton method used to instantiate the EEM_Event object
54
-     *
55
-     * @param string $timezone
56
-     * @return EEM_Event
57
-     * @throws \EE_Error
58
-     */
59
-    public static function instance($timezone = null)
60
-    {
61
-        // check if instance of EEM_Event already exists
62
-        if (! self::$_instance instanceof EEM_Event) {
63
-            // instantiate Espresso_model
64
-            self::$_instance = new self($timezone);
65
-        }
66
-        //we might have a timezone set, let set_timezone decide what to do with it
67
-        self::$_instance->set_timezone($timezone);
68
-        // EEM_Event object
69
-        return self::$_instance;
70
-    }
71
-
72
-
73
-
74
-    /**
75
-     * Adds a relationship to Term_Taxonomy for each CPT_Base
76
-     *
77
-     * @param string $timezone
78
-     * @throws \EE_Error
79
-     */
80
-    protected function __construct($timezone = null)
81
-    {
82
-        EE_Registry::instance()->load_model('Registration');
83
-        $this->singular_item = esc_html__('Event', 'event_espresso');
84
-        $this->plural_item = esc_html__('Events', 'event_espresso');
85
-        // to remove Cancelled events from the frontend, copy the following filter to your functions.php file
86
-        // add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
87
-        // to remove Postponed events from the frontend, copy the following filter to your functions.php file
88
-        // add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
89
-        // to remove Sold Out events from the frontend, copy the following filter to your functions.php file
90
-        //	add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
91
-        $this->_custom_stati = apply_filters(
92
-            'AFEE__EEM_Event__construct___custom_stati',
93
-            array(
94
-                EEM_Event::cancelled => array(
95
-                    'label'  => esc_html__('Cancelled', 'event_espresso'),
96
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__cancelled__Public', true),
97
-                ),
98
-                EEM_Event::postponed => array(
99
-                    'label'  => esc_html__('Postponed', 'event_espresso'),
100
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__postponed__Public', true),
101
-                ),
102
-                EEM_Event::sold_out  => array(
103
-                    'label'  => esc_html__('Sold Out', 'event_espresso'),
104
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__sold_out__Public', true),
105
-                ),
106
-            )
107
-        );
108
-        self::$_default_reg_status = empty(self::$_default_reg_status) ? EEM_Registration::status_id_pending_payment
109
-            : self::$_default_reg_status;
110
-        $this->_tables = array(
111
-            'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
112
-            'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
113
-        );
114
-        $this->_fields = array(
115
-            'Event_CPT'  => array(
116
-                'EVT_ID'         => new EE_Primary_Key_Int_Field('ID',
117
-                    esc_html__('Post ID for Event', 'event_espresso')),
118
-                'EVT_name'       => new EE_Plain_Text_Field('post_title', esc_html__('Event Name', 'event_espresso'),
119
-                    false,
120
-                    ''),
121
-                'EVT_desc'       => new EE_Post_Content_Field('post_content',
122
-                    esc_html__('Event Description', 'event_espresso'),
123
-                    false, ''),
124
-                'EVT_slug'       => new EE_Slug_Field('post_name', esc_html__('Event Slug', 'event_espresso'), false,
125
-                    ''),
126
-                'EVT_created'    => new EE_Datetime_Field('post_date',
127
-                    esc_html__('Date/Time Event Created', 'event_espresso'),
128
-                    false, EE_Datetime_Field::now),
129
-                'EVT_short_desc' => new EE_Simple_HTML_Field('post_excerpt',
130
-                    esc_html__('Event Short Description', 'event_espresso'), false, ''),
131
-                'EVT_modified'   => new EE_Datetime_Field('post_modified',
132
-                    esc_html__('Date/Time Event Modified', 'event_espresso'), false, EE_Datetime_Field::now),
133
-                'EVT_wp_user'    => new EE_WP_User_Field('post_author',
134
-                    esc_html__('Event Creator ID', 'event_espresso'),
135
-                    false),
136
-                'parent'         => new EE_Integer_Field('post_parent', esc_html__('Event Parent ID', 'event_espresso'),
137
-                    false,
138
-                    0),
139
-                'EVT_order'      => new EE_Integer_Field('menu_order', esc_html__('Event Menu Order', 'event_espresso'),
140
-                    false,
141
-                    1),
142
-                'post_type'      => new EE_WP_Post_Type_Field('espresso_events'),
143
-                // EE_Plain_Text_Field( 'post_type', esc_html__( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
144
-                'status'         => new EE_WP_Post_Status_Field('post_status',
145
-                    esc_html__('Event Status', 'event_espresso'),
146
-                    false, 'draft', $this->_custom_stati),
147
-            ),
148
-            'Event_Meta' => array(
149
-                'EVTM_ID'                         => new EE_DB_Only_Float_Field('EVTM_ID',
150
-                    esc_html__('Event Meta Row ID', 'event_espresso'), false),
151
-                'EVT_ID_fk'                       => new EE_DB_Only_Int_Field('EVT_ID',
152
-                    esc_html__('Foreign key to Event ID from Event Meta table', 'event_espresso'), false),
153
-                'EVT_display_desc'                => new EE_Boolean_Field('EVT_display_desc',
154
-                    esc_html__('Display Description Flag', 'event_espresso'), false, 1),
155
-                'EVT_display_ticket_selector'     => new EE_Boolean_Field('EVT_display_ticket_selector',
156
-                    esc_html__('Display Ticket Selector Flag', 'event_espresso'), false, 1),
157
-                'EVT_visible_on'                  => new EE_Datetime_Field('EVT_visible_on',
158
-                    esc_html__('Event Visible Date', 'event_espresso'), true, EE_Datetime_Field::now),
159
-                'EVT_additional_limit'            => new EE_Integer_Field('EVT_additional_limit',
160
-                    esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'), true, 10),
161
-                'EVT_default_registration_status' => new EE_Enum_Text_Field(
162
-                    'EVT_default_registration_status',
163
-                    esc_html__('Default Registration Status on this Event', 'event_espresso'), false,
164
-                    EEM_Event::$_default_reg_status, EEM_Registration::reg_status_array()
165
-                ),
166
-                'EVT_member_only'                 => new EE_Boolean_Field('EVT_member_only',
167
-                    esc_html__('Member-Only Event Flag', 'event_espresso'), false, false),
168
-                'EVT_phone'                       => new EE_Plain_Text_Field('EVT_phone',
169
-                    esc_html__('Event Phone Number', 'event_espresso'), false),
170
-                'EVT_allow_overflow'              => new EE_Boolean_Field('EVT_allow_overflow',
171
-                    esc_html__('Allow Overflow on Event', 'event_espresso'), false, false),
172
-                'EVT_timezone_string'             => new EE_Plain_Text_Field('EVT_timezone_string',
173
-                    esc_html__('Timezone (name) for Event times', 'event_espresso'), false),
174
-                'EVT_external_URL'                => new EE_Plain_Text_Field('EVT_external_URL',
175
-                    esc_html__('URL of Event Page if hosted elsewhere', 'event_espresso'), true),
176
-                'EVT_donations'                   => new EE_Boolean_Field('EVT_donations',
177
-                    esc_html__('Accept Donations?', 'event_espresso'), false, false),
178
-            ),
179
-        );
180
-        $this->_model_relations = array(
181
-            'Registration'           => new EE_Has_Many_Relation(),
182
-            'Datetime'               => new EE_Has_Many_Relation(),
183
-            'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
184
-            'Venue'                  => new EE_HABTM_Relation('Event_Venue'),
185
-            'Term_Relationship'      => new EE_Has_Many_Relation(),
186
-            'Term_Taxonomy'          => new EE_HABTM_Relation('Term_Relationship'),
187
-            'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
188
-            'Attendee'               => new EE_HABTM_Relation('Registration'),
189
-            'WP_User'                => new EE_Belongs_To_Relation(),
190
-        );
191
-        //this model is generally available for reading
192
-        $this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Public();
193
-        parent::__construct($timezone);
194
-    }
195
-
196
-
197
-
198
-    /**
199
-     * @param string $default_reg_status
200
-     */
201
-    public static function set_default_reg_status($default_reg_status)
202
-    {
203
-        self::$_default_reg_status = $default_reg_status;
204
-        // if EEM_Event has already been instantiated,
205
-        // then we need to reset the `EVT_default_reg_status` field to use the new default.
206
-        if (self::$_instance instanceof EEM_Event) {
207
-            $default_reg_status = new EE_Enum_Text_Field(
208
-                'EVT_default_registration_status',
209
-                esc_html__('Default Registration Status on this Event', 'event_espresso'),
210
-                false,
211
-                $default_reg_status,
212
-                EEM_Registration::reg_status_array()
213
-            );
214
-            $default_reg_status->_construct_finalize(
215
-                'Event_Meta',
216
-                'EVT_default_registration_status',
217
-                'EEM_Event'
218
-            );
219
-            self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = $default_reg_status;
220
-        }
221
-    }
222
-
223
-
224
-
225
-    /**
226
-     * get_question_groups
227
-     *
228
-     * @return array
229
-     * @throws \EE_Error
230
-     */
231
-    public function get_all_question_groups()
232
-    {
233
-        return EE_Registry::instance()->load_model('Question_Group')->get_all(
234
-            array(
235
-                array('QSG_deleted' => false),
236
-                'order_by' => array('QSG_order' => 'ASC'),
237
-            )
238
-        );
239
-    }
240
-
241
-
242
-
243
-    /**
244
-     * get_question_groups
245
-     *
246
-     * @param int $EVT_ID
247
-     * @return array|bool
248
-     * @throws \EE_Error
249
-     */
250
-    public function get_all_event_question_groups($EVT_ID = 0)
251
-    {
252
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
253
-            EE_Error::add_error(
254
-                esc_html__(
255
-                    'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
256
-                    'event_espresso'
257
-                ),
258
-                __FILE__, __FUNCTION__, __LINE__
259
-            );
260
-            return false;
261
-        }
262
-        return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
263
-            array(
264
-                array('EVT_ID' => $EVT_ID),
265
-            )
266
-        );
267
-    }
268
-
269
-
270
-
271
-    /**
272
-     * get_question_groups
273
-     *
274
-     * @param int     $EVT_ID
275
-     * @param boolean $for_primary_attendee
276
-     * @return array|bool
277
-     * @throws \EE_Error
278
-     */
279
-    public function get_event_question_groups($EVT_ID = 0, $for_primary_attendee = true)
280
-    {
281
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
282
-            EE_Error::add_error(
283
-                esc_html__(
284
-                    'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
285
-                    'event_espresso'
286
-                ),
287
-                __FILE__, __FUNCTION__, __LINE__
288
-            );
289
-            return false;
290
-        }
291
-        return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
292
-            array(
293
-                array(
294
-                    'EVT_ID'      => $EVT_ID,
295
-                    'EQG_primary' => $for_primary_attendee,
296
-                ),
297
-            )
298
-        );
299
-    }
300
-
301
-
302
-
303
-    /**
304
-     * get_question_groups
305
-     *
306
-     * @param int             $EVT_ID
307
-     * @param EE_Registration $registration
308
-     * @return array|bool
309
-     * @throws \EE_Error
310
-     */
311
-    public function get_question_groups_for_event($EVT_ID = 0, EE_Registration $registration)
312
-    {
313
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
314
-            EE_Error::add_error(
315
-                esc_html__(
316
-                    'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
317
-                    'event_espresso'
318
-                ),
319
-                __FILE__, __FUNCTION__, __LINE__
320
-            );
321
-            return false;
322
-        }
323
-        $where_params = array(
324
-            'Event_Question_Group.EVT_ID'      => $EVT_ID,
325
-            'Event_Question_Group.EQG_primary' => $registration->count() === 1 ? true : false,
326
-            'QSG_deleted'                      => false,
327
-        );
328
-        return EE_Registry::instance()->load_model('Question_Group')->get_all(
329
-            array(
330
-                $where_params,
331
-                'order_by' => array('QSG_order' => 'ASC'),
332
-            )
333
-        );
334
-    }
335
-
336
-
337
-
338
-    /**
339
-     * get_question_target_db_column
340
-     *
341
-     * @param string $QSG_IDs csv list of $QSG IDs
342
-     * @return array|bool
343
-     * @throws \EE_Error
344
-     */
345
-    public function get_questions_in_groups($QSG_IDs = '')
346
-    {
347
-        if (empty($QSG_IDs)) {
348
-            EE_Error::add_error(
349
-                esc_html__('An error occurred. No Question Group IDs were received.', 'event_espresso'),
350
-                __FILE__, __FUNCTION__, __LINE__
351
-            );
352
-            return false;
353
-        }
354
-        return EE_Registry::instance()->load_model('Question')->get_all(
355
-            array(
356
-                array(
357
-                    'Question_Group.QSG_ID' => array('IN', $QSG_IDs),
358
-                    'QST_deleted'           => false,
359
-                    'QST_admin_only'        => is_admin(),
360
-                ),
361
-                'order_by' => 'QST_order',
362
-            )
363
-        );
364
-    }
365
-
366
-
367
-
368
-    /**
369
-     * get_options_for_question
370
-     *
371
-     * @param string $QST_IDs csv list of $QST IDs
372
-     * @return array|bool
373
-     * @throws \EE_Error
374
-     */
375
-    public function get_options_for_question($QST_IDs)
376
-    {
377
-        if (empty($QST_IDs)) {
378
-            EE_Error::add_error(
379
-                esc_html__('An error occurred. No Question IDs were received.', 'event_espresso'),
380
-                __FILE__, __FUNCTION__, __LINE__
381
-            );
382
-            return false;
383
-        }
384
-        return EE_Registry::instance()->load_model('Question_Option')->get_all(
385
-            array(
386
-                array(
387
-                    'Question.QST_ID' => array('IN', $QST_IDs),
388
-                    'QSO_deleted'     => false,
389
-                ),
390
-                'order_by' => 'QSO_ID',
391
-            )
392
-        );
393
-    }
394
-
395
-
396
-
397
-
398
-
399
-
400
-
401
-    /**
402
-     * Gets all events that are published
403
-     * and have event start time earlier than now and an event end time later than now
404
-     *
405
-     * @param  array $query_params An array of query params to further filter on
406
-     *                             (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
407
-     * @param bool   $count        whether to return the count or not (default FALSE)
408
-     * @return EE_Event[]|int
409
-     * @throws \EE_Error
410
-     */
411
-    public function get_active_events($query_params, $count = false)
412
-    {
413
-        if (array_key_exists(0, $query_params)) {
414
-            $where_params = $query_params[0];
415
-            unset($query_params[0]);
416
-        } else {
417
-            $where_params = array();
418
-        }
419
-        // if we have count make sure we don't include group by
420
-        if ($count && isset($query_params['group_by'])) {
421
-            unset($query_params['group_by']);
422
-        }
423
-        // let's add specific query_params for active_events
424
-        // keep in mind this will override any sent status in the query AND any date queries.
425
-        $where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
426
-        //if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
427
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
428
-            $where_params['Datetime.DTT_EVT_start******'] = array(
429
-                '<',
430
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
431
-            );
432
-        } else {
433
-            $where_params['Datetime.DTT_EVT_start'] = array(
434
-                '<',
435
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
436
-            );
437
-        }
438
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
439
-            $where_params['Datetime.DTT_EVT_end*****'] = array(
440
-                '>',
441
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
442
-            );
443
-        } else {
444
-            $where_params['Datetime.DTT_EVT_end'] = array(
445
-                '>',
446
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
447
-            );
448
-        }
449
-        $query_params[0] = $where_params;
450
-        // don't use $query_params with count()
451
-        // because we don't want to include additional query clauses like "GROUP BY"
452
-        return $count
453
-            ? $this->count(array($where_params), 'EVT_ID', true)
454
-            : $this->get_all($query_params);
455
-    }
456
-
457
-
458
-
459
-    /**
460
-     * get all events that are published and have an event start time later than now
461
-     *
462
-     * @param  array $query_params An array of query params to further filter on
463
-     *                             (Note that status and DTT_EVT_start will be overridden)
464
-     * @param bool   $count        whether to return the count or not (default FALSE)
465
-     * @return EE_Event[]|int
466
-     * @throws \EE_Error
467
-     */
468
-    public function get_upcoming_events($query_params, $count = false)
469
-    {
470
-        if (array_key_exists(0, $query_params)) {
471
-            $where_params = $query_params[0];
472
-            unset($query_params[0]);
473
-        } else {
474
-            $where_params = array();
475
-        }
476
-        // if we have count make sure we don't include group by
477
-        if ($count && isset($query_params['group_by'])) {
478
-            unset($query_params['group_by']);
479
-        }
480
-        // let's add specific query_params for active_events
481
-        // keep in mind this will override any sent status in the query AND any date queries.
482
-        $where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
483
-        // if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
484
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
485
-            $where_params['Datetime.DTT_EVT_start*****'] = array(
486
-                '>',
487
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
488
-            );
489
-        } else {
490
-            $where_params['Datetime.DTT_EVT_start'] = array(
491
-                '>',
492
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
493
-            );
494
-        }
495
-        $query_params[0] = $where_params;
496
-        // don't use $query_params with count()
497
-        // because we don't want to include additional query clauses like "GROUP BY"
498
-        return $count
499
-            ? $this->count(array($where_params), 'EVT_ID', true)
500
-            : $this->get_all($query_params);
501
-    }
502
-
503
-
504
-
505
-    /**
506
-     * Gets all events that are published
507
-     * and have an event end time later than now
508
-     *
509
-     * @param  array $query_params An array of query params to further filter on
510
-     *                             (note that status and DTT_EVT_end will be overridden)
511
-     * @param bool   $count        whether to return the count or not (default FALSE)
512
-     * @return EE_Event[]|int
513
-     * @throws \EE_Error
514
-     */
515
-    public function get_active_and_upcoming_events($query_params, $count = false)
516
-    {
517
-        if (array_key_exists(0, $query_params)) {
518
-            $where_params = $query_params[0];
519
-            unset($query_params[0]);
520
-        } else {
521
-            $where_params = array();
522
-        }
523
-        // if we have count make sure we don't include group by
524
-        if ($count && isset($query_params['group_by'])) {
525
-            unset($query_params['group_by']);
526
-        }
527
-        // let's add specific query_params for active_events
528
-        // keep in mind this will override any sent status in the query AND any date queries.
529
-        $where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
530
-        // add where params for DTT_EVT_end
531
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
532
-            $where_params['Datetime.DTT_EVT_end*****'] = array(
533
-                '>',
534
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
535
-            );
536
-        } else {
537
-            $where_params['Datetime.DTT_EVT_end'] = array(
538
-                '>',
539
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
540
-            );
541
-        }
542
-        $query_params[0] = $where_params;
543
-        // don't use $query_params with count()
544
-        // because we don't want to include additional query clauses like "GROUP BY"
545
-        return $count
546
-            ? $this->count(array($where_params), 'EVT_ID', true)
547
-            : $this->get_all($query_params);
548
-    }
549
-
550
-
551
-
552
-    /**
553
-     * This only returns events that are expired.
554
-     * They may still be published but all their datetimes have expired.
555
-     *
556
-     * @param  array $query_params An array of query params to further filter on
557
-     *                             (note that status and DTT_EVT_end will be overridden)
558
-     * @param bool   $count        whether to return the count or not (default FALSE)
559
-     * @return EE_Event[]|int
560
-     * @throws \EE_Error
561
-     */
562
-    public function get_expired_events($query_params, $count = false)
563
-    {
564
-        $where_params = isset($query_params[0]) ? $query_params[0] : array();
565
-        // if we have count make sure we don't include group by
566
-        if ($count && isset($query_params['group_by'])) {
567
-            unset($query_params['group_by']);
568
-        }
569
-        // let's add specific query_params for active_events
570
-        // keep in mind this will override any sent status in the query AND any date queries.
571
-        if (isset($where_params['status'])) {
572
-            unset($where_params['status']);
573
-        }
574
-        $exclude_query = $query_params;
575
-        if (isset($exclude_query[0])) {
576
-            unset($exclude_query[0]);
577
-        }
578
-        $exclude_query[0] = array(
579
-            'Datetime.DTT_EVT_end' => array(
580
-                '>',
581
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
582
-            ),
583
-        );
584
-        // first get all events that have datetimes where its not expired.
585
-        $event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
586
-        $event_ids = array_keys($event_ids);
587
-        // if we have any additional query_params, let's add them to the 'AND' condition
588
-        $and_condition = array(
589
-            'Datetime.DTT_EVT_end' => array('<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')),
590
-            'EVT_ID'               => array('NOT IN', $event_ids),
591
-        );
592
-        if (isset($where_params['OR'])) {
593
-            $and_condition['OR'] = $where_params['OR'];
594
-            unset($where_params['OR']);
595
-        }
596
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
597
-            $and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
598
-            unset($where_params['Datetime.DTT_EVT_end']);
599
-        }
600
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
601
-            $and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
602
-            unset($where_params['Datetime.DTT_EVT_start']);
603
-        }
604
-        // merge remaining $where params with the and conditions.
605
-        $where_params['AND'] = array_merge($and_condition, $where_params);
606
-        $query_params[0] = $where_params;
607
-        // don't use $query_params with count()
608
-        // because we don't want to include additional query clauses like "GROUP BY"
609
-        return $count
610
-            ? $this->count(array($where_params), 'EVT_ID', true)
611
-            : $this->get_all($query_params);
612
-    }
613
-
614
-
615
-
616
-    /**
617
-     * This basically just returns the events that do not have the publish status.
618
-     *
619
-     * @param  array   $query_params An array of query params to further filter on
620
-     *                               (note that status will be overwritten)
621
-     * @param  boolean $count        whether to return the count or not (default FALSE)
622
-     * @return EE_Event[]|int
623
-     * @throws \EE_Error
624
-     */
625
-    public function get_inactive_events($query_params, $count = false)
626
-    {
627
-        $where_params = isset($query_params[0]) ? $query_params[0] : array();
628
-        // let's add in specific query_params for inactive events.
629
-        if (isset($where_params['status'])) {
630
-            unset($where_params['status']);
631
-        }
632
-        // if we have count make sure we don't include group by
633
-        if ($count && isset($query_params['group_by'])) {
634
-            unset($query_params['group_by']);
635
-        }
636
-        // if we have any additional query_params, let's add them to the 'AND' condition
637
-        $where_params['AND']['status'] = array('!=', 'publish');
638
-        if (isset($where_params['OR'])) {
639
-            $where_params['AND']['OR'] = $where_params['OR'];
640
-            unset($where_params['OR']);
641
-        }
642
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
643
-            $where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
644
-            unset($where_params['Datetime.DTT_EVT_end']);
645
-        }
646
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
647
-            $where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
648
-            unset($where_params['Datetime.DTT_EVT_start']);
649
-        }
650
-        $query_params[0] = $where_params;
651
-        // don't use $query_params with count()
652
-        // because we don't want to include additional query clauses like "GROUP BY"
653
-        return $count
654
-            ? $this->count(array($where_params), 'EVT_ID', true)
655
-            : $this->get_all($query_params);
656
-    }
657
-
658
-
659
-
660
-    /**
661
-     * This is just injecting into the parent add_relationship_to so we do special handling on price relationships
662
-     * because we don't want to override any existing global default prices but instead insert NEW prices that get
663
-     * attached to the event. See parent for param descriptions
664
-     *
665
-     * @param        $id_or_obj
666
-     * @param        $other_model_id_or_obj
667
-     * @param string $relationName
668
-     * @param array  $where_query
669
-     * @return EE_Base_Class
670
-     * @throws EE_Error
671
-     */
672
-    public function add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query = array())
673
-    {
674
-        if ($relationName === 'Price') {
675
-            //let's get the PRC object for the given ID to make sure that we aren't dealing with a default
676
-            $prc_chk = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
677
-            //if EVT_ID = 0, then this is a default
678
-            if ((int) $prc_chk->get('EVT_ID') === 0) {
679
-                //let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
680
-                $prc_chk->set('PRC_ID', 0);
681
-            }
682
-            //run parent
683
-            return parent::add_relationship_to($id_or_obj, $prc_chk, $relationName, $where_query);
684
-        }
685
-        //otherwise carry on as normal
686
-        return parent::add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query);
687
-    }
688
-
689
-
690
-
691
-    /******************** DEPRECATED METHODS ********************/
692
-
693
-
694
-
695
-    /**
696
-     * _get_question_target_db_column
697
-     *
698
-     * @deprecated as of 4.8.32.rc.001. Instead consider using
699
-     *             EE_Registration_Custom_Questions_Form located in
700
-     *             admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
701
-     * @access     public
702
-     * @param    EE_Registration $registration (so existing answers for registration are included)
703
-     * @param    int             $EVT_ID       so all question groups are included for event (not just answers from
704
-     *                                         registration).
705
-     * @throws EE_Error
706
-     * @return    array
707
-     */
708
-    public function assemble_array_of_groups_questions_and_options(EE_Registration $registration, $EVT_ID = 0)
709
-    {
710
-        if (empty($EVT_ID)) {
711
-            throw new EE_Error(__('An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.',
712
-                'event_espresso'));
713
-        }
714
-        $questions = array();
715
-        // get all question groups for event
716
-        $qgs = $this->get_question_groups_for_event($EVT_ID, $registration);
717
-        if (! empty($qgs)) {
718
-            foreach ($qgs as $qg) {
719
-                $qsts = $qg->questions();
720
-                $questions[$qg->ID()] = $qg->model_field_array();
721
-                $questions[$qg->ID()]['QSG_questions'] = array();
722
-                foreach ($qsts as $qst) {
723
-                    if ($qst->is_system_question()) {
724
-                        continue;
725
-                    }
726
-                    $answer = EEM_Answer::instance()->get_one(array(
727
-                        array(
728
-                            'QST_ID' => $qst->ID(),
729
-                            'REG_ID' => $registration->ID(),
730
-                        ),
731
-                    ));
732
-                    $answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
733
-                    $qst_name = $qstn_id = $qst->ID();
734
-                    $ans_id = $answer->ID();
735
-                    $qst_name = ! empty($ans_id) ? '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
736
-                    $input_name = '';
737
-                    $input_id = sanitize_key($qst->display_text());
738
-                    $input_class = '';
739
-                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()] = $qst->model_field_array();
740
-                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_name'] = 'qstn'
741
-                                                                                           . $input_name
742
-                                                                                           . $qst_name;
743
-                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_id'] = $input_id . '-' . $qstn_id;
744
-                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_class'] = $input_class;
745
-                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_options'] = array();
746
-                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['qst_obj'] = $qst;
747
-                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['ans_obj'] = $answer;
748
-                    //leave responses as-is, don't convert stuff into html entities please!
749
-                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['htmlentities'] = false;
750
-                    if ($qst->type() == 'RADIO_BTN' || $qst->type() == 'CHECKBOX' || $qst->type() == 'DROPDOWN') {
751
-                        $QSOs = $qst->options(true, $answer->value());
752
-                        if (is_array($QSOs)) {
753
-                            foreach ($QSOs as $QSO_ID => $QSO) {
754
-                                $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_options'][$QSO_ID] = $QSO->model_field_array();
755
-                            }
756
-                        }
757
-                    }
758
-                }
759
-            }
760
-        }
761
-        return $questions;
762
-    }
19
+	/**
20
+	 * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the
21
+	 * event
22
+	 */
23
+	const sold_out = 'sold_out';
24
+
25
+	/**
26
+	 * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later
27
+	 * date)
28
+	 */
29
+	const postponed = 'postponed';
30
+
31
+	/**
32
+	 * constant used by status(), indicating that the event will no longer occur
33
+	 */
34
+	const cancelled = 'cancelled';
35
+
36
+
37
+	/**
38
+	 * @var string
39
+	 */
40
+	protected static $_default_reg_status;
41
+
42
+
43
+	/**
44
+	 * private instance of the Event object
45
+	 *
46
+	 * @var EEM_Event
47
+	 */
48
+	protected static $_instance;
49
+
50
+
51
+
52
+	/**
53
+	 *  This function is a singleton method used to instantiate the EEM_Event object
54
+	 *
55
+	 * @param string $timezone
56
+	 * @return EEM_Event
57
+	 * @throws \EE_Error
58
+	 */
59
+	public static function instance($timezone = null)
60
+	{
61
+		// check if instance of EEM_Event already exists
62
+		if (! self::$_instance instanceof EEM_Event) {
63
+			// instantiate Espresso_model
64
+			self::$_instance = new self($timezone);
65
+		}
66
+		//we might have a timezone set, let set_timezone decide what to do with it
67
+		self::$_instance->set_timezone($timezone);
68
+		// EEM_Event object
69
+		return self::$_instance;
70
+	}
71
+
72
+
73
+
74
+	/**
75
+	 * Adds a relationship to Term_Taxonomy for each CPT_Base
76
+	 *
77
+	 * @param string $timezone
78
+	 * @throws \EE_Error
79
+	 */
80
+	protected function __construct($timezone = null)
81
+	{
82
+		EE_Registry::instance()->load_model('Registration');
83
+		$this->singular_item = esc_html__('Event', 'event_espresso');
84
+		$this->plural_item = esc_html__('Events', 'event_espresso');
85
+		// to remove Cancelled events from the frontend, copy the following filter to your functions.php file
86
+		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
87
+		// to remove Postponed events from the frontend, copy the following filter to your functions.php file
88
+		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
89
+		// to remove Sold Out events from the frontend, copy the following filter to your functions.php file
90
+		//	add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
91
+		$this->_custom_stati = apply_filters(
92
+			'AFEE__EEM_Event__construct___custom_stati',
93
+			array(
94
+				EEM_Event::cancelled => array(
95
+					'label'  => esc_html__('Cancelled', 'event_espresso'),
96
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__cancelled__Public', true),
97
+				),
98
+				EEM_Event::postponed => array(
99
+					'label'  => esc_html__('Postponed', 'event_espresso'),
100
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__postponed__Public', true),
101
+				),
102
+				EEM_Event::sold_out  => array(
103
+					'label'  => esc_html__('Sold Out', 'event_espresso'),
104
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__sold_out__Public', true),
105
+				),
106
+			)
107
+		);
108
+		self::$_default_reg_status = empty(self::$_default_reg_status) ? EEM_Registration::status_id_pending_payment
109
+			: self::$_default_reg_status;
110
+		$this->_tables = array(
111
+			'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
112
+			'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
113
+		);
114
+		$this->_fields = array(
115
+			'Event_CPT'  => array(
116
+				'EVT_ID'         => new EE_Primary_Key_Int_Field('ID',
117
+					esc_html__('Post ID for Event', 'event_espresso')),
118
+				'EVT_name'       => new EE_Plain_Text_Field('post_title', esc_html__('Event Name', 'event_espresso'),
119
+					false,
120
+					''),
121
+				'EVT_desc'       => new EE_Post_Content_Field('post_content',
122
+					esc_html__('Event Description', 'event_espresso'),
123
+					false, ''),
124
+				'EVT_slug'       => new EE_Slug_Field('post_name', esc_html__('Event Slug', 'event_espresso'), false,
125
+					''),
126
+				'EVT_created'    => new EE_Datetime_Field('post_date',
127
+					esc_html__('Date/Time Event Created', 'event_espresso'),
128
+					false, EE_Datetime_Field::now),
129
+				'EVT_short_desc' => new EE_Simple_HTML_Field('post_excerpt',
130
+					esc_html__('Event Short Description', 'event_espresso'), false, ''),
131
+				'EVT_modified'   => new EE_Datetime_Field('post_modified',
132
+					esc_html__('Date/Time Event Modified', 'event_espresso'), false, EE_Datetime_Field::now),
133
+				'EVT_wp_user'    => new EE_WP_User_Field('post_author',
134
+					esc_html__('Event Creator ID', 'event_espresso'),
135
+					false),
136
+				'parent'         => new EE_Integer_Field('post_parent', esc_html__('Event Parent ID', 'event_espresso'),
137
+					false,
138
+					0),
139
+				'EVT_order'      => new EE_Integer_Field('menu_order', esc_html__('Event Menu Order', 'event_espresso'),
140
+					false,
141
+					1),
142
+				'post_type'      => new EE_WP_Post_Type_Field('espresso_events'),
143
+				// EE_Plain_Text_Field( 'post_type', esc_html__( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
144
+				'status'         => new EE_WP_Post_Status_Field('post_status',
145
+					esc_html__('Event Status', 'event_espresso'),
146
+					false, 'draft', $this->_custom_stati),
147
+			),
148
+			'Event_Meta' => array(
149
+				'EVTM_ID'                         => new EE_DB_Only_Float_Field('EVTM_ID',
150
+					esc_html__('Event Meta Row ID', 'event_espresso'), false),
151
+				'EVT_ID_fk'                       => new EE_DB_Only_Int_Field('EVT_ID',
152
+					esc_html__('Foreign key to Event ID from Event Meta table', 'event_espresso'), false),
153
+				'EVT_display_desc'                => new EE_Boolean_Field('EVT_display_desc',
154
+					esc_html__('Display Description Flag', 'event_espresso'), false, 1),
155
+				'EVT_display_ticket_selector'     => new EE_Boolean_Field('EVT_display_ticket_selector',
156
+					esc_html__('Display Ticket Selector Flag', 'event_espresso'), false, 1),
157
+				'EVT_visible_on'                  => new EE_Datetime_Field('EVT_visible_on',
158
+					esc_html__('Event Visible Date', 'event_espresso'), true, EE_Datetime_Field::now),
159
+				'EVT_additional_limit'            => new EE_Integer_Field('EVT_additional_limit',
160
+					esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'), true, 10),
161
+				'EVT_default_registration_status' => new EE_Enum_Text_Field(
162
+					'EVT_default_registration_status',
163
+					esc_html__('Default Registration Status on this Event', 'event_espresso'), false,
164
+					EEM_Event::$_default_reg_status, EEM_Registration::reg_status_array()
165
+				),
166
+				'EVT_member_only'                 => new EE_Boolean_Field('EVT_member_only',
167
+					esc_html__('Member-Only Event Flag', 'event_espresso'), false, false),
168
+				'EVT_phone'                       => new EE_Plain_Text_Field('EVT_phone',
169
+					esc_html__('Event Phone Number', 'event_espresso'), false),
170
+				'EVT_allow_overflow'              => new EE_Boolean_Field('EVT_allow_overflow',
171
+					esc_html__('Allow Overflow on Event', 'event_espresso'), false, false),
172
+				'EVT_timezone_string'             => new EE_Plain_Text_Field('EVT_timezone_string',
173
+					esc_html__('Timezone (name) for Event times', 'event_espresso'), false),
174
+				'EVT_external_URL'                => new EE_Plain_Text_Field('EVT_external_URL',
175
+					esc_html__('URL of Event Page if hosted elsewhere', 'event_espresso'), true),
176
+				'EVT_donations'                   => new EE_Boolean_Field('EVT_donations',
177
+					esc_html__('Accept Donations?', 'event_espresso'), false, false),
178
+			),
179
+		);
180
+		$this->_model_relations = array(
181
+			'Registration'           => new EE_Has_Many_Relation(),
182
+			'Datetime'               => new EE_Has_Many_Relation(),
183
+			'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
184
+			'Venue'                  => new EE_HABTM_Relation('Event_Venue'),
185
+			'Term_Relationship'      => new EE_Has_Many_Relation(),
186
+			'Term_Taxonomy'          => new EE_HABTM_Relation('Term_Relationship'),
187
+			'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
188
+			'Attendee'               => new EE_HABTM_Relation('Registration'),
189
+			'WP_User'                => new EE_Belongs_To_Relation(),
190
+		);
191
+		//this model is generally available for reading
192
+		$this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Public();
193
+		parent::__construct($timezone);
194
+	}
195
+
196
+
197
+
198
+	/**
199
+	 * @param string $default_reg_status
200
+	 */
201
+	public static function set_default_reg_status($default_reg_status)
202
+	{
203
+		self::$_default_reg_status = $default_reg_status;
204
+		// if EEM_Event has already been instantiated,
205
+		// then we need to reset the `EVT_default_reg_status` field to use the new default.
206
+		if (self::$_instance instanceof EEM_Event) {
207
+			$default_reg_status = new EE_Enum_Text_Field(
208
+				'EVT_default_registration_status',
209
+				esc_html__('Default Registration Status on this Event', 'event_espresso'),
210
+				false,
211
+				$default_reg_status,
212
+				EEM_Registration::reg_status_array()
213
+			);
214
+			$default_reg_status->_construct_finalize(
215
+				'Event_Meta',
216
+				'EVT_default_registration_status',
217
+				'EEM_Event'
218
+			);
219
+			self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = $default_reg_status;
220
+		}
221
+	}
222
+
223
+
224
+
225
+	/**
226
+	 * get_question_groups
227
+	 *
228
+	 * @return array
229
+	 * @throws \EE_Error
230
+	 */
231
+	public function get_all_question_groups()
232
+	{
233
+		return EE_Registry::instance()->load_model('Question_Group')->get_all(
234
+			array(
235
+				array('QSG_deleted' => false),
236
+				'order_by' => array('QSG_order' => 'ASC'),
237
+			)
238
+		);
239
+	}
240
+
241
+
242
+
243
+	/**
244
+	 * get_question_groups
245
+	 *
246
+	 * @param int $EVT_ID
247
+	 * @return array|bool
248
+	 * @throws \EE_Error
249
+	 */
250
+	public function get_all_event_question_groups($EVT_ID = 0)
251
+	{
252
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
253
+			EE_Error::add_error(
254
+				esc_html__(
255
+					'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
256
+					'event_espresso'
257
+				),
258
+				__FILE__, __FUNCTION__, __LINE__
259
+			);
260
+			return false;
261
+		}
262
+		return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
263
+			array(
264
+				array('EVT_ID' => $EVT_ID),
265
+			)
266
+		);
267
+	}
268
+
269
+
270
+
271
+	/**
272
+	 * get_question_groups
273
+	 *
274
+	 * @param int     $EVT_ID
275
+	 * @param boolean $for_primary_attendee
276
+	 * @return array|bool
277
+	 * @throws \EE_Error
278
+	 */
279
+	public function get_event_question_groups($EVT_ID = 0, $for_primary_attendee = true)
280
+	{
281
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
282
+			EE_Error::add_error(
283
+				esc_html__(
284
+					'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
285
+					'event_espresso'
286
+				),
287
+				__FILE__, __FUNCTION__, __LINE__
288
+			);
289
+			return false;
290
+		}
291
+		return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
292
+			array(
293
+				array(
294
+					'EVT_ID'      => $EVT_ID,
295
+					'EQG_primary' => $for_primary_attendee,
296
+				),
297
+			)
298
+		);
299
+	}
300
+
301
+
302
+
303
+	/**
304
+	 * get_question_groups
305
+	 *
306
+	 * @param int             $EVT_ID
307
+	 * @param EE_Registration $registration
308
+	 * @return array|bool
309
+	 * @throws \EE_Error
310
+	 */
311
+	public function get_question_groups_for_event($EVT_ID = 0, EE_Registration $registration)
312
+	{
313
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
314
+			EE_Error::add_error(
315
+				esc_html__(
316
+					'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
317
+					'event_espresso'
318
+				),
319
+				__FILE__, __FUNCTION__, __LINE__
320
+			);
321
+			return false;
322
+		}
323
+		$where_params = array(
324
+			'Event_Question_Group.EVT_ID'      => $EVT_ID,
325
+			'Event_Question_Group.EQG_primary' => $registration->count() === 1 ? true : false,
326
+			'QSG_deleted'                      => false,
327
+		);
328
+		return EE_Registry::instance()->load_model('Question_Group')->get_all(
329
+			array(
330
+				$where_params,
331
+				'order_by' => array('QSG_order' => 'ASC'),
332
+			)
333
+		);
334
+	}
335
+
336
+
337
+
338
+	/**
339
+	 * get_question_target_db_column
340
+	 *
341
+	 * @param string $QSG_IDs csv list of $QSG IDs
342
+	 * @return array|bool
343
+	 * @throws \EE_Error
344
+	 */
345
+	public function get_questions_in_groups($QSG_IDs = '')
346
+	{
347
+		if (empty($QSG_IDs)) {
348
+			EE_Error::add_error(
349
+				esc_html__('An error occurred. No Question Group IDs were received.', 'event_espresso'),
350
+				__FILE__, __FUNCTION__, __LINE__
351
+			);
352
+			return false;
353
+		}
354
+		return EE_Registry::instance()->load_model('Question')->get_all(
355
+			array(
356
+				array(
357
+					'Question_Group.QSG_ID' => array('IN', $QSG_IDs),
358
+					'QST_deleted'           => false,
359
+					'QST_admin_only'        => is_admin(),
360
+				),
361
+				'order_by' => 'QST_order',
362
+			)
363
+		);
364
+	}
365
+
366
+
367
+
368
+	/**
369
+	 * get_options_for_question
370
+	 *
371
+	 * @param string $QST_IDs csv list of $QST IDs
372
+	 * @return array|bool
373
+	 * @throws \EE_Error
374
+	 */
375
+	public function get_options_for_question($QST_IDs)
376
+	{
377
+		if (empty($QST_IDs)) {
378
+			EE_Error::add_error(
379
+				esc_html__('An error occurred. No Question IDs were received.', 'event_espresso'),
380
+				__FILE__, __FUNCTION__, __LINE__
381
+			);
382
+			return false;
383
+		}
384
+		return EE_Registry::instance()->load_model('Question_Option')->get_all(
385
+			array(
386
+				array(
387
+					'Question.QST_ID' => array('IN', $QST_IDs),
388
+					'QSO_deleted'     => false,
389
+				),
390
+				'order_by' => 'QSO_ID',
391
+			)
392
+		);
393
+	}
394
+
395
+
396
+
397
+
398
+
399
+
400
+
401
+	/**
402
+	 * Gets all events that are published
403
+	 * and have event start time earlier than now and an event end time later than now
404
+	 *
405
+	 * @param  array $query_params An array of query params to further filter on
406
+	 *                             (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
407
+	 * @param bool   $count        whether to return the count or not (default FALSE)
408
+	 * @return EE_Event[]|int
409
+	 * @throws \EE_Error
410
+	 */
411
+	public function get_active_events($query_params, $count = false)
412
+	{
413
+		if (array_key_exists(0, $query_params)) {
414
+			$where_params = $query_params[0];
415
+			unset($query_params[0]);
416
+		} else {
417
+			$where_params = array();
418
+		}
419
+		// if we have count make sure we don't include group by
420
+		if ($count && isset($query_params['group_by'])) {
421
+			unset($query_params['group_by']);
422
+		}
423
+		// let's add specific query_params for active_events
424
+		// keep in mind this will override any sent status in the query AND any date queries.
425
+		$where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
426
+		//if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
427
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
428
+			$where_params['Datetime.DTT_EVT_start******'] = array(
429
+				'<',
430
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
431
+			);
432
+		} else {
433
+			$where_params['Datetime.DTT_EVT_start'] = array(
434
+				'<',
435
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
436
+			);
437
+		}
438
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
439
+			$where_params['Datetime.DTT_EVT_end*****'] = array(
440
+				'>',
441
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
442
+			);
443
+		} else {
444
+			$where_params['Datetime.DTT_EVT_end'] = array(
445
+				'>',
446
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
447
+			);
448
+		}
449
+		$query_params[0] = $where_params;
450
+		// don't use $query_params with count()
451
+		// because we don't want to include additional query clauses like "GROUP BY"
452
+		return $count
453
+			? $this->count(array($where_params), 'EVT_ID', true)
454
+			: $this->get_all($query_params);
455
+	}
456
+
457
+
458
+
459
+	/**
460
+	 * get all events that are published and have an event start time later than now
461
+	 *
462
+	 * @param  array $query_params An array of query params to further filter on
463
+	 *                             (Note that status and DTT_EVT_start will be overridden)
464
+	 * @param bool   $count        whether to return the count or not (default FALSE)
465
+	 * @return EE_Event[]|int
466
+	 * @throws \EE_Error
467
+	 */
468
+	public function get_upcoming_events($query_params, $count = false)
469
+	{
470
+		if (array_key_exists(0, $query_params)) {
471
+			$where_params = $query_params[0];
472
+			unset($query_params[0]);
473
+		} else {
474
+			$where_params = array();
475
+		}
476
+		// if we have count make sure we don't include group by
477
+		if ($count && isset($query_params['group_by'])) {
478
+			unset($query_params['group_by']);
479
+		}
480
+		// let's add specific query_params for active_events
481
+		// keep in mind this will override any sent status in the query AND any date queries.
482
+		$where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
483
+		// if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
484
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
485
+			$where_params['Datetime.DTT_EVT_start*****'] = array(
486
+				'>',
487
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
488
+			);
489
+		} else {
490
+			$where_params['Datetime.DTT_EVT_start'] = array(
491
+				'>',
492
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
493
+			);
494
+		}
495
+		$query_params[0] = $where_params;
496
+		// don't use $query_params with count()
497
+		// because we don't want to include additional query clauses like "GROUP BY"
498
+		return $count
499
+			? $this->count(array($where_params), 'EVT_ID', true)
500
+			: $this->get_all($query_params);
501
+	}
502
+
503
+
504
+
505
+	/**
506
+	 * Gets all events that are published
507
+	 * and have an event end time later than now
508
+	 *
509
+	 * @param  array $query_params An array of query params to further filter on
510
+	 *                             (note that status and DTT_EVT_end will be overridden)
511
+	 * @param bool   $count        whether to return the count or not (default FALSE)
512
+	 * @return EE_Event[]|int
513
+	 * @throws \EE_Error
514
+	 */
515
+	public function get_active_and_upcoming_events($query_params, $count = false)
516
+	{
517
+		if (array_key_exists(0, $query_params)) {
518
+			$where_params = $query_params[0];
519
+			unset($query_params[0]);
520
+		} else {
521
+			$where_params = array();
522
+		}
523
+		// if we have count make sure we don't include group by
524
+		if ($count && isset($query_params['group_by'])) {
525
+			unset($query_params['group_by']);
526
+		}
527
+		// let's add specific query_params for active_events
528
+		// keep in mind this will override any sent status in the query AND any date queries.
529
+		$where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
530
+		// add where params for DTT_EVT_end
531
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
532
+			$where_params['Datetime.DTT_EVT_end*****'] = array(
533
+				'>',
534
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
535
+			);
536
+		} else {
537
+			$where_params['Datetime.DTT_EVT_end'] = array(
538
+				'>',
539
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
540
+			);
541
+		}
542
+		$query_params[0] = $where_params;
543
+		// don't use $query_params with count()
544
+		// because we don't want to include additional query clauses like "GROUP BY"
545
+		return $count
546
+			? $this->count(array($where_params), 'EVT_ID', true)
547
+			: $this->get_all($query_params);
548
+	}
549
+
550
+
551
+
552
+	/**
553
+	 * This only returns events that are expired.
554
+	 * They may still be published but all their datetimes have expired.
555
+	 *
556
+	 * @param  array $query_params An array of query params to further filter on
557
+	 *                             (note that status and DTT_EVT_end will be overridden)
558
+	 * @param bool   $count        whether to return the count or not (default FALSE)
559
+	 * @return EE_Event[]|int
560
+	 * @throws \EE_Error
561
+	 */
562
+	public function get_expired_events($query_params, $count = false)
563
+	{
564
+		$where_params = isset($query_params[0]) ? $query_params[0] : array();
565
+		// if we have count make sure we don't include group by
566
+		if ($count && isset($query_params['group_by'])) {
567
+			unset($query_params['group_by']);
568
+		}
569
+		// let's add specific query_params for active_events
570
+		// keep in mind this will override any sent status in the query AND any date queries.
571
+		if (isset($where_params['status'])) {
572
+			unset($where_params['status']);
573
+		}
574
+		$exclude_query = $query_params;
575
+		if (isset($exclude_query[0])) {
576
+			unset($exclude_query[0]);
577
+		}
578
+		$exclude_query[0] = array(
579
+			'Datetime.DTT_EVT_end' => array(
580
+				'>',
581
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
582
+			),
583
+		);
584
+		// first get all events that have datetimes where its not expired.
585
+		$event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
586
+		$event_ids = array_keys($event_ids);
587
+		// if we have any additional query_params, let's add them to the 'AND' condition
588
+		$and_condition = array(
589
+			'Datetime.DTT_EVT_end' => array('<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')),
590
+			'EVT_ID'               => array('NOT IN', $event_ids),
591
+		);
592
+		if (isset($where_params['OR'])) {
593
+			$and_condition['OR'] = $where_params['OR'];
594
+			unset($where_params['OR']);
595
+		}
596
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
597
+			$and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
598
+			unset($where_params['Datetime.DTT_EVT_end']);
599
+		}
600
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
601
+			$and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
602
+			unset($where_params['Datetime.DTT_EVT_start']);
603
+		}
604
+		// merge remaining $where params with the and conditions.
605
+		$where_params['AND'] = array_merge($and_condition, $where_params);
606
+		$query_params[0] = $where_params;
607
+		// don't use $query_params with count()
608
+		// because we don't want to include additional query clauses like "GROUP BY"
609
+		return $count
610
+			? $this->count(array($where_params), 'EVT_ID', true)
611
+			: $this->get_all($query_params);
612
+	}
613
+
614
+
615
+
616
+	/**
617
+	 * This basically just returns the events that do not have the publish status.
618
+	 *
619
+	 * @param  array   $query_params An array of query params to further filter on
620
+	 *                               (note that status will be overwritten)
621
+	 * @param  boolean $count        whether to return the count or not (default FALSE)
622
+	 * @return EE_Event[]|int
623
+	 * @throws \EE_Error
624
+	 */
625
+	public function get_inactive_events($query_params, $count = false)
626
+	{
627
+		$where_params = isset($query_params[0]) ? $query_params[0] : array();
628
+		// let's add in specific query_params for inactive events.
629
+		if (isset($where_params['status'])) {
630
+			unset($where_params['status']);
631
+		}
632
+		// if we have count make sure we don't include group by
633
+		if ($count && isset($query_params['group_by'])) {
634
+			unset($query_params['group_by']);
635
+		}
636
+		// if we have any additional query_params, let's add them to the 'AND' condition
637
+		$where_params['AND']['status'] = array('!=', 'publish');
638
+		if (isset($where_params['OR'])) {
639
+			$where_params['AND']['OR'] = $where_params['OR'];
640
+			unset($where_params['OR']);
641
+		}
642
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
643
+			$where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
644
+			unset($where_params['Datetime.DTT_EVT_end']);
645
+		}
646
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
647
+			$where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
648
+			unset($where_params['Datetime.DTT_EVT_start']);
649
+		}
650
+		$query_params[0] = $where_params;
651
+		// don't use $query_params with count()
652
+		// because we don't want to include additional query clauses like "GROUP BY"
653
+		return $count
654
+			? $this->count(array($where_params), 'EVT_ID', true)
655
+			: $this->get_all($query_params);
656
+	}
657
+
658
+
659
+
660
+	/**
661
+	 * This is just injecting into the parent add_relationship_to so we do special handling on price relationships
662
+	 * because we don't want to override any existing global default prices but instead insert NEW prices that get
663
+	 * attached to the event. See parent for param descriptions
664
+	 *
665
+	 * @param        $id_or_obj
666
+	 * @param        $other_model_id_or_obj
667
+	 * @param string $relationName
668
+	 * @param array  $where_query
669
+	 * @return EE_Base_Class
670
+	 * @throws EE_Error
671
+	 */
672
+	public function add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query = array())
673
+	{
674
+		if ($relationName === 'Price') {
675
+			//let's get the PRC object for the given ID to make sure that we aren't dealing with a default
676
+			$prc_chk = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
677
+			//if EVT_ID = 0, then this is a default
678
+			if ((int) $prc_chk->get('EVT_ID') === 0) {
679
+				//let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
680
+				$prc_chk->set('PRC_ID', 0);
681
+			}
682
+			//run parent
683
+			return parent::add_relationship_to($id_or_obj, $prc_chk, $relationName, $where_query);
684
+		}
685
+		//otherwise carry on as normal
686
+		return parent::add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query);
687
+	}
688
+
689
+
690
+
691
+	/******************** DEPRECATED METHODS ********************/
692
+
693
+
694
+
695
+	/**
696
+	 * _get_question_target_db_column
697
+	 *
698
+	 * @deprecated as of 4.8.32.rc.001. Instead consider using
699
+	 *             EE_Registration_Custom_Questions_Form located in
700
+	 *             admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
701
+	 * @access     public
702
+	 * @param    EE_Registration $registration (so existing answers for registration are included)
703
+	 * @param    int             $EVT_ID       so all question groups are included for event (not just answers from
704
+	 *                                         registration).
705
+	 * @throws EE_Error
706
+	 * @return    array
707
+	 */
708
+	public function assemble_array_of_groups_questions_and_options(EE_Registration $registration, $EVT_ID = 0)
709
+	{
710
+		if (empty($EVT_ID)) {
711
+			throw new EE_Error(__('An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.',
712
+				'event_espresso'));
713
+		}
714
+		$questions = array();
715
+		// get all question groups for event
716
+		$qgs = $this->get_question_groups_for_event($EVT_ID, $registration);
717
+		if (! empty($qgs)) {
718
+			foreach ($qgs as $qg) {
719
+				$qsts = $qg->questions();
720
+				$questions[$qg->ID()] = $qg->model_field_array();
721
+				$questions[$qg->ID()]['QSG_questions'] = array();
722
+				foreach ($qsts as $qst) {
723
+					if ($qst->is_system_question()) {
724
+						continue;
725
+					}
726
+					$answer = EEM_Answer::instance()->get_one(array(
727
+						array(
728
+							'QST_ID' => $qst->ID(),
729
+							'REG_ID' => $registration->ID(),
730
+						),
731
+					));
732
+					$answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
733
+					$qst_name = $qstn_id = $qst->ID();
734
+					$ans_id = $answer->ID();
735
+					$qst_name = ! empty($ans_id) ? '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
736
+					$input_name = '';
737
+					$input_id = sanitize_key($qst->display_text());
738
+					$input_class = '';
739
+					$questions[$qg->ID()]['QSG_questions'][$qst->ID()] = $qst->model_field_array();
740
+					$questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_name'] = 'qstn'
741
+																						   . $input_name
742
+																						   . $qst_name;
743
+					$questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_id'] = $input_id . '-' . $qstn_id;
744
+					$questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_class'] = $input_class;
745
+					$questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_options'] = array();
746
+					$questions[$qg->ID()]['QSG_questions'][$qst->ID()]['qst_obj'] = $qst;
747
+					$questions[$qg->ID()]['QSG_questions'][$qst->ID()]['ans_obj'] = $answer;
748
+					//leave responses as-is, don't convert stuff into html entities please!
749
+					$questions[$qg->ID()]['QSG_questions'][$qst->ID()]['htmlentities'] = false;
750
+					if ($qst->type() == 'RADIO_BTN' || $qst->type() == 'CHECKBOX' || $qst->type() == 'DROPDOWN') {
751
+						$QSOs = $qst->options(true, $answer->value());
752
+						if (is_array($QSOs)) {
753
+							foreach ($QSOs as $QSO_ID => $QSO) {
754
+								$questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_options'][$QSO_ID] = $QSO->model_field_array();
755
+							}
756
+						}
757
+					}
758
+				}
759
+			}
760
+		}
761
+		return $questions;
762
+	}
763 763
 
764 764
 
765 765
 }
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  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
-require_once(EE_MODELS . 'EEM_CPT_Base.model.php');
4
+require_once(EE_MODELS.'EEM_CPT_Base.model.php');
5 5
 
6 6
 
7 7
 
@@ -59,7 +59,7 @@  discard block
 block discarded – undo
59 59
     public static function instance($timezone = null)
60 60
     {
61 61
         // check if instance of EEM_Event already exists
62
-        if (! self::$_instance instanceof EEM_Event) {
62
+        if ( ! self::$_instance instanceof EEM_Event) {
63 63
             // instantiate Espresso_model
64 64
             self::$_instance = new self($timezone);
65 65
         }
@@ -249,7 +249,7 @@  discard block
 block discarded – undo
249 249
      */
250 250
     public function get_all_event_question_groups($EVT_ID = 0)
251 251
     {
252
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
252
+        if ( ! isset($EVT_ID) || ! absint($EVT_ID)) {
253 253
             EE_Error::add_error(
254 254
                 esc_html__(
255 255
                     'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
@@ -278,7 +278,7 @@  discard block
 block discarded – undo
278 278
      */
279 279
     public function get_event_question_groups($EVT_ID = 0, $for_primary_attendee = true)
280 280
     {
281
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
281
+        if ( ! isset($EVT_ID) || ! absint($EVT_ID)) {
282 282
             EE_Error::add_error(
283 283
                 esc_html__(
284 284
                     'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
@@ -310,7 +310,7 @@  discard block
 block discarded – undo
310 310
      */
311 311
     public function get_question_groups_for_event($EVT_ID = 0, EE_Registration $registration)
312 312
     {
313
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
313
+        if ( ! isset($EVT_ID) || ! absint($EVT_ID)) {
314 314
             EE_Error::add_error(
315 315
                 esc_html__(
316 316
                     'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
@@ -714,7 +714,7 @@  discard block
 block discarded – undo
714 714
         $questions = array();
715 715
         // get all question groups for event
716 716
         $qgs = $this->get_question_groups_for_event($EVT_ID, $registration);
717
-        if (! empty($qgs)) {
717
+        if ( ! empty($qgs)) {
718 718
             foreach ($qgs as $qg) {
719 719
                 $qsts = $qg->questions();
720 720
                 $questions[$qg->ID()] = $qg->model_field_array();
@@ -732,7 +732,7 @@  discard block
 block discarded – undo
732 732
                     $answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
733 733
                     $qst_name = $qstn_id = $qst->ID();
734 734
                     $ans_id = $answer->ID();
735
-                    $qst_name = ! empty($ans_id) ? '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
735
+                    $qst_name = ! empty($ans_id) ? '['.$qst_name.']['.$ans_id.']' : '['.$qst_name.']';
736 736
                     $input_name = '';
737 737
                     $input_id = sanitize_key($qst->display_text());
738 738
                     $input_class = '';
@@ -740,7 +740,7 @@  discard block
 block discarded – undo
740 740
                     $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_name'] = 'qstn'
741 741
                                                                                            . $input_name
742 742
                                                                                            . $qst_name;
743
-                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_id'] = $input_id . '-' . $qstn_id;
743
+                    $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_id'] = $input_id.'-'.$qstn_id;
744 744
                     $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_input_class'] = $input_class;
745 745
                     $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['QST_options'] = array();
746 746
                     $questions[$qg->ID()]['QSG_questions'][$qst->ID()]['qst_obj'] = $qst;
Please login to merge, or discard this patch.
modules/single_page_checkout/EED_Single_Page_Checkout.module.php 1 patch
Indentation   +1712 added lines, -1712 removed lines patch added patch discarded remove patch
@@ -2,7 +2,7 @@  discard block
 block discarded – undo
2 2
 use EventEspresso\core\exceptions\InvalidEntityException;
3 3
 
4 4
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
5
-    exit('No direct script access allowed');
5
+	exit('No direct script access allowed');
6 6
 }
7 7
 
8 8
 
@@ -17,1717 +17,1717 @@  discard block
 block discarded – undo
17 17
 class EED_Single_Page_Checkout extends EED_Module
18 18
 {
19 19
 
20
-    /**
21
-     * $_initialized - has the SPCO controller already been initialized ?
22
-     *
23
-     * @access private
24
-     * @var bool $_initialized
25
-     */
26
-    private static $_initialized = false;
27
-
28
-
29
-    /**
30
-     * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
31
-     *
32
-     * @access private
33
-     * @var bool $_valid_checkout
34
-     */
35
-    private static $_checkout_verified = true;
36
-
37
-    /**
38
-     *    $_reg_steps_array - holds initial array of reg steps
39
-     *
40
-     * @access private
41
-     * @var array $_reg_steps_array
42
-     */
43
-    private static $_reg_steps_array = array();
44
-
45
-    /**
46
-     *    $checkout - EE_Checkout object for handling the properties of the current checkout process
47
-     *
48
-     * @access public
49
-     * @var EE_Checkout $checkout
50
-     */
51
-    public $checkout;
52
-
53
-
54
-
55
-    /**
56
-     * @return EED_Single_Page_Checkout
57
-     */
58
-    public static function instance()
59
-    {
60
-        add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
61
-        return parent::get_instance(__CLASS__);
62
-    }
63
-
64
-
65
-
66
-    /**
67
-     * @return EE_CART
68
-     */
69
-    public function cart()
70
-    {
71
-        return $this->checkout->cart;
72
-    }
73
-
74
-
75
-
76
-    /**
77
-     * @return EE_Transaction
78
-     */
79
-    public function transaction()
80
-    {
81
-        return $this->checkout->transaction;
82
-    }
83
-
84
-
85
-
86
-    /**
87
-     *    set_hooks - for hooking into EE Core, other modules, etc
88
-     *
89
-     * @access    public
90
-     * @return    void
91
-     * @throws \EE_Error
92
-     */
93
-    public static function set_hooks()
94
-    {
95
-        EED_Single_Page_Checkout::set_definitions();
96
-    }
97
-
98
-
99
-
100
-    /**
101
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
102
-     *
103
-     * @access    public
104
-     * @return    void
105
-     * @throws \EE_Error
106
-     */
107
-    public static function set_hooks_admin()
108
-    {
109
-        EED_Single_Page_Checkout::set_definitions();
110
-        if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
111
-            // hook into the top of pre_get_posts to set the reg step routing, which gives other modules or plugins a chance to modify the reg steps, but just before the routes get called
112
-            add_action('pre_get_posts', array('EED_Single_Page_Checkout', 'load_reg_steps'), 1);
113
-            return;
114
-        }
115
-        // going to start an output buffer in case anything gets accidentally output that might disrupt our JSON response
116
-        ob_start();
117
-        EED_Single_Page_Checkout::load_request_handler();
118
-        EED_Single_Page_Checkout::load_reg_steps();
119
-        // set ajax hooks
120
-        add_action('wp_ajax_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
121
-        add_action('wp_ajax_nopriv_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
122
-        add_action('wp_ajax_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
123
-        add_action('wp_ajax_nopriv_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
124
-        add_action('wp_ajax_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
125
-        add_action('wp_ajax_nopriv_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
126
-    }
127
-
128
-
129
-
130
-    /**
131
-     *    process ajax request
132
-     *
133
-     * @param string $ajax_action
134
-     * @throws \EE_Error
135
-     */
136
-    public static function process_ajax_request($ajax_action)
137
-    {
138
-        EE_Registry::instance()->REQ->set('action', $ajax_action);
139
-        EED_Single_Page_Checkout::instance()->_initialize();
140
-    }
141
-
142
-
143
-
144
-    /**
145
-     *    ajax display registration step
146
-     *
147
-     * @throws \EE_Error
148
-     */
149
-    public static function display_reg_step()
150
-    {
151
-        EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
152
-    }
153
-
154
-
155
-
156
-    /**
157
-     *    ajax process registration step
158
-     *
159
-     * @throws \EE_Error
160
-     */
161
-    public static function process_reg_step()
162
-    {
163
-        EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
164
-    }
165
-
166
-
167
-
168
-    /**
169
-     *    ajax process registration step
170
-     *
171
-     * @throws \EE_Error
172
-     */
173
-    public static function update_reg_step()
174
-    {
175
-        EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
176
-    }
177
-
178
-
179
-
180
-    /**
181
-     *   update_checkout
182
-     *
183
-     * @access public
184
-     * @return void
185
-     * @throws \EE_Error
186
-     */
187
-    public static function update_checkout()
188
-    {
189
-        EED_Single_Page_Checkout::process_ajax_request('update_checkout');
190
-    }
191
-
192
-
193
-
194
-    /**
195
-     *    load_request_handler
196
-     *
197
-     * @access    public
198
-     * @return    void
199
-     */
200
-    public static function load_request_handler()
201
-    {
202
-        // load core Request_Handler class
203
-        if ( ! isset(EE_Registry::instance()->REQ)) {
204
-            EE_Registry::instance()->load_core('Request_Handler');
205
-        }
206
-    }
207
-
208
-
209
-
210
-    /**
211
-     *    set_definitions
212
-     *
213
-     * @access    public
214
-     * @return    void
215
-     * @throws \EE_Error
216
-     */
217
-    public static function set_definitions()
218
-    {
219
-        define('SPCO_BASE_PATH', rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS);
220
-        define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css' . DS);
221
-        define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img' . DS);
222
-        define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js' . DS);
223
-        define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS);
224
-        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS);
225
-        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS);
226
-        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
227
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
228
-            __('%1$sWe\'re sorry, but you\'re registration time has expired.%2$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 except our apologies for any inconvenience this may have caused.%8$s',
229
-                'event_espresso'),
230
-            '<h4 class="important-notice">',
231
-            '</h4>',
232
-            '<br />',
233
-            '<p>',
234
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
235
-            '">',
236
-            '</a>',
237
-            '</p>'
238
-        );
239
-    }
240
-
241
-
242
-
243
-    /**
244
-     * load_reg_steps
245
-     * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
246
-     *
247
-     * @access    private
248
-     * @throws EE_Error
249
-     * @return void
250
-     */
251
-    public static function load_reg_steps()
252
-    {
253
-        static $reg_steps_loaded = false;
254
-        if ($reg_steps_loaded) {
255
-            return;
256
-        }
257
-        // filter list of reg_steps
258
-        $reg_steps_to_load = (array)apply_filters(
259
-            'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
260
-            EED_Single_Page_Checkout::get_reg_steps()
261
-        );
262
-        // sort by key (order)
263
-        ksort($reg_steps_to_load);
264
-        // loop through folders
265
-        foreach ($reg_steps_to_load as $order => $reg_step) {
266
-            // we need a
267
-            if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
268
-                // copy over to the reg_steps_array
269
-                EED_Single_Page_Checkout::$_reg_steps_array[$order] = $reg_step;
270
-                // register custom key route for each reg step
271
-                // ie: step=>"slug" - this is the entire reason we load the reg steps array now
272
-                EE_Config::register_route($reg_step['slug'], 'EED_Single_Page_Checkout', 'run', 'step');
273
-                // add AJAX or other hooks
274
-                if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
275
-                    // setup autoloaders if necessary
276
-                    if ( ! class_exists($reg_step['class_name'])) {
277
-                        EEH_Autoloader::register_autoloaders_for_each_file_in_folder($reg_step['file_path'], true);
278
-                    }
279
-                    if (is_callable($reg_step['class_name'], 'set_hooks')) {
280
-                        call_user_func(array($reg_step['class_name'], 'set_hooks'));
281
-                    }
282
-                }
283
-            }
284
-        }
285
-        $reg_steps_loaded = true;
286
-    }
287
-
288
-
289
-
290
-    /**
291
-     *    get_reg_steps
292
-     *
293
-     * @access    public
294
-     * @return    array
295
-     */
296
-    public static function get_reg_steps()
297
-    {
298
-        $reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
299
-        if (empty($reg_steps)) {
300
-            $reg_steps = array(
301
-                10  => array(
302
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
303
-                    'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
304
-                    'slug'       => 'attendee_information',
305
-                    'has_hooks'  => false,
306
-                ),
307
-                20  => array(
308
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'registration_confirmation',
309
-                    'class_name' => 'EE_SPCO_Reg_Step_Registration_Confirmation',
310
-                    'slug'       => 'registration_confirmation',
311
-                    'has_hooks'  => false,
312
-                ),
313
-                30  => array(
314
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
315
-                    'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
316
-                    'slug'       => 'payment_options',
317
-                    'has_hooks'  => true,
318
-                ),
319
-                999 => array(
320
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
321
-                    'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
322
-                    'slug'       => 'finalize_registration',
323
-                    'has_hooks'  => false,
324
-                ),
325
-            );
326
-        }
327
-        return $reg_steps;
328
-    }
329
-
330
-
331
-
332
-    /**
333
-     *    registration_checkout_for_admin
334
-     *
335
-     * @access    public
336
-     * @return    string
337
-     * @throws \EE_Error
338
-     */
339
-    public static function registration_checkout_for_admin()
340
-    {
341
-        EED_Single_Page_Checkout::load_reg_steps();
342
-        EE_Registry::instance()->REQ->set('step', 'attendee_information');
343
-        EE_Registry::instance()->REQ->set('action', 'display_spco_reg_step');
344
-        EE_Registry::instance()->REQ->set('process_form_submission', false);
345
-        EED_Single_Page_Checkout::instance()->_initialize();
346
-        EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
347
-        return EE_Registry::instance()->REQ->get_output();
348
-    }
349
-
350
-
351
-
352
-    /**
353
-     * process_registration_from_admin
354
-     *
355
-     * @access public
356
-     * @return \EE_Transaction
357
-     * @throws \EE_Error
358
-     */
359
-    public static function process_registration_from_admin()
360
-    {
361
-        EED_Single_Page_Checkout::load_reg_steps();
362
-        EE_Registry::instance()->REQ->set('step', 'attendee_information');
363
-        EE_Registry::instance()->REQ->set('action', 'process_reg_step');
364
-        EE_Registry::instance()->REQ->set('process_form_submission', true);
365
-        EED_Single_Page_Checkout::instance()->_initialize();
366
-        if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
367
-            $final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
368
-            if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
369
-                EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
370
-                if ($final_reg_step->process_reg_step()) {
371
-                    $final_reg_step->set_completed();
372
-                    EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
373
-                    return EED_Single_Page_Checkout::instance()->checkout->transaction;
374
-                }
375
-            }
376
-        }
377
-        return null;
378
-    }
379
-
380
-
381
-
382
-    /**
383
-     *    run
384
-     *
385
-     * @access    public
386
-     * @param WP_Query $WP_Query
387
-     * @return    void
388
-     * @throws \EE_Error
389
-     */
390
-    public function run($WP_Query)
391
-    {
392
-        if (
393
-            $WP_Query instanceof WP_Query
394
-            && $WP_Query->is_main_query()
395
-            && apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
396
-            && $this->_is_reg_checkout()
397
-        ) {
398
-            $this->_initialize();
399
-        }
400
-    }
401
-
402
-
403
-
404
-    /**
405
-     * determines whether current url matches reg page url
406
-     *
407
-     * @return bool
408
-     */
409
-    protected function _is_reg_checkout()
410
-    {
411
-        // get current permalink for reg page without any extra query args
412
-        $reg_page_url = \get_permalink(EE_Config::instance()->core->reg_page_id);
413
-        // get request URI for current request, but without the scheme or host
414
-        $current_request_uri = \EEH_URL::filter_input_server_url('REQUEST_URI');
415
-        $current_request_uri = html_entity_decode($current_request_uri);
416
-        // get array of query args from the current request URI
417
-        $query_args = \EEH_URL::get_query_string($current_request_uri);
418
-        // grab page id if it is set
419
-        $page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
420
-        // and remove the page id from the query args (we will re-add it later)
421
-        unset($query_args['page_id']);
422
-        // now strip all query args from current request URI
423
-        $current_request_uri = remove_query_arg(array_keys($query_args), $current_request_uri);
424
-        // and re-add the page id if it was set
425
-        if ($page_id) {
426
-            $current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
427
-        }
428
-        // remove slashes and ?
429
-        $current_request_uri = trim($current_request_uri, '?/');
430
-        // is current request URI part of the known full reg page URL ?
431
-        return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
432
-    }
433
-
434
-
435
-
436
-    /**
437
-     *    run
438
-     *
439
-     * @access    public
440
-     * @param WP_Query $WP_Query
441
-     * @return    void
442
-     * @throws \EE_Error
443
-     */
444
-    public static function init($WP_Query)
445
-    {
446
-        EED_Single_Page_Checkout::instance()->run($WP_Query);
447
-    }
448
-
449
-
450
-
451
-    /**
452
-     *    _initialize - initial module setup
453
-     *
454
-     * @access    private
455
-     * @throws EE_Error
456
-     * @return    void
457
-     */
458
-    private function _initialize()
459
-    {
460
-        // ensure SPCO doesn't run twice
461
-        if (EED_Single_Page_Checkout::$_initialized) {
462
-            return;
463
-        }
464
-        try {
465
-            $this->_verify_session();
466
-            // setup the EE_Checkout object
467
-            $this->checkout = $this->_initialize_checkout();
468
-            // filter checkout
469
-            $this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
470
-            // get the $_GET
471
-            $this->_get_request_vars();
472
-            if ($this->_block_bots()) {
473
-                return;
474
-            }
475
-            // filter continue_reg
476
-            $this->checkout->continue_reg = apply_filters('FHEE__EED_Single_Page_Checkout__init___continue_reg', true, $this->checkout);
477
-            // load the reg steps array
478
-            if ( ! $this->_load_and_instantiate_reg_steps()) {
479
-                EED_Single_Page_Checkout::$_initialized = true;
480
-                return;
481
-            }
482
-            // set the current step
483
-            $this->checkout->set_current_step($this->checkout->step);
484
-            // and the next step
485
-            $this->checkout->set_next_step();
486
-            // verify that everything has been setup correctly
487
-            if ( ! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
488
-                EED_Single_Page_Checkout::$_initialized = true;
489
-                return;
490
-            }
491
-            // lock the transaction
492
-            $this->checkout->transaction->lock();
493
-            // make sure all of our cached objects are added to their respective model entity mappers
494
-            $this->checkout->refresh_all_entities();
495
-            // set amount owing
496
-            $this->checkout->amount_owing = $this->checkout->transaction->remaining();
497
-            // initialize each reg step, which gives them the chance to potentially alter the process
498
-            $this->_initialize_reg_steps();
499
-            // DEBUG LOG
500
-            //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
501
-            // get reg form
502
-            if( ! $this->_check_form_submission()) {
503
-                EED_Single_Page_Checkout::$_initialized = true;
504
-                return;
505
-            }
506
-            // checkout the action!!!
507
-            $this->_process_form_action();
508
-            // add some style and make it dance
509
-            $this->add_styles_and_scripts();
510
-            // kk... SPCO has successfully run
511
-            EED_Single_Page_Checkout::$_initialized = true;
512
-            // set no cache headers and constants
513
-            EE_System::do_not_cache();
514
-            // add anchor
515
-            add_action('loop_start', array($this, 'set_checkout_anchor'), 1);
516
-            // remove transaction lock
517
-            add_action('shutdown', array($this, 'unlock_transaction'), 1);
518
-        } catch (Exception $e) {
519
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
520
-        }
521
-    }
522
-
523
-
524
-
525
-    /**
526
-     *    _verify_session
527
-     * checks that the session is valid and not expired
528
-     *
529
-     * @access    private
530
-     * @throws EE_Error
531
-     */
532
-    private function _verify_session()
533
-    {
534
-        if ( ! EE_Registry::instance()->SSN instanceof EE_Session) {
535
-            throw new EE_Error(__('The EE_Session class could not be loaded.', 'event_espresso'));
536
-        }
537
-        // is session still valid ?
538
-        if (EE_Registry::instance()->SSN->expired() && EE_Registry::instance()->REQ->get('e_reg_url_link', '') === '') {
539
-            $this->checkout = new EE_Checkout();
540
-            EE_Registry::instance()->SSN->reset_cart();
541
-            EE_Registry::instance()->SSN->reset_checkout();
542
-            EE_Registry::instance()->SSN->reset_transaction();
543
-            EE_Error::add_attention(EE_Registry::$i18n_js_strings['registration_expiration_notice'], __FILE__,
544
-                __FUNCTION__, __LINE__);
545
-            EE_Registry::instance()->SSN->reset_expired();
546
-        }
547
-    }
548
-
549
-
550
-
551
-    /**
552
-     *    _initialize_checkout
553
-     * loads and instantiates EE_Checkout
554
-     *
555
-     * @access    private
556
-     * @throws EE_Error
557
-     * @return EE_Checkout
558
-     */
559
-    private function _initialize_checkout()
560
-    {
561
-        // look in session for existing checkout
562
-        /** @type EE_Checkout $checkout */
563
-        $checkout = EE_Registry::instance()->SSN->checkout();
564
-        // verify
565
-        if ( ! $checkout instanceof EE_Checkout) {
566
-            // instantiate EE_Checkout object for handling the properties of the current checkout process
567
-            $checkout = EE_Registry::instance()->load_file(SPCO_INC_PATH, 'EE_Checkout', 'class', array(), false);
568
-        } else {
569
-            if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
570
-                $this->unlock_transaction();
571
-                wp_safe_redirect($checkout->redirect_url);
572
-                exit();
573
-            }
574
-        }
575
-        $checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
576
-        // verify again
577
-        if ( ! $checkout instanceof EE_Checkout) {
578
-            throw new EE_Error(__('The EE_Checkout class could not be loaded.', 'event_espresso'));
579
-        }
580
-        // reset anything that needs a clean slate for each request
581
-        $checkout->reset_for_current_request();
582
-        return $checkout;
583
-    }
584
-
585
-
586
-
587
-    /**
588
-     *    _get_request_vars
589
-     *
590
-     * @access    private
591
-     * @return    void
592
-     * @throws \EE_Error
593
-     */
594
-    private function _get_request_vars()
595
-    {
596
-        // load classes
597
-        EED_Single_Page_Checkout::load_request_handler();
598
-        //make sure this request is marked as belonging to EE
599
-        EE_Registry::instance()->REQ->set_espresso_page(true);
600
-        // which step is being requested ?
601
-        $this->checkout->step = EE_Registry::instance()->REQ->get('step', $this->_get_first_step());
602
-        // which step is being edited ?
603
-        $this->checkout->edit_step = EE_Registry::instance()->REQ->get('edit_step', '');
604
-        // and what we're doing on the current step
605
-        $this->checkout->action = EE_Registry::instance()->REQ->get('action', 'display_spco_reg_step');
606
-        // timestamp
607
-        $this->checkout->uts = EE_Registry::instance()->REQ->get('uts', 0);
608
-        // returning to edit ?
609
-        $this->checkout->reg_url_link = EE_Registry::instance()->REQ->get('e_reg_url_link', '');
610
-        // or some other kind of revisit ?
611
-        $this->checkout->revisit = filter_var(
612
-            EE_Registry::instance()->REQ->get('revisit', false),
613
-            FILTER_VALIDATE_BOOLEAN
614
-        );
615
-        // and whether or not to generate a reg form for this request
616
-        $this->checkout->generate_reg_form = filter_var(
617
-            EE_Registry::instance()->REQ->get('generate_reg_form', true),
618
-            FILTER_VALIDATE_BOOLEAN
619
-        );
620
-        // and whether or not to process a reg form submission for this request
621
-        $this->checkout->process_form_submission = filter_var(
622
-            EE_Registry::instance()->REQ->get(
623
-                'process_form_submission',
624
-                $this->checkout->action === 'process_reg_step'
625
-            ),
626
-            FILTER_VALIDATE_BOOLEAN
627
-        );
628
-        $this->checkout->process_form_submission = filter_var(
629
-            $this->checkout->action !== 'display_spco_reg_step'
630
-                ? $this->checkout->process_form_submission
631
-                : false,
632
-            FILTER_VALIDATE_BOOLEAN
633
-        );
634
-        // $this->_display_request_vars();
635
-    }
636
-
637
-
638
-
639
-    /**
640
-     *  _display_request_vars
641
-     *
642
-     * @access    protected
643
-     * @return    void
644
-     */
645
-    protected function _display_request_vars()
646
-    {
647
-        if ( ! WP_DEBUG) {
648
-            return;
649
-        }
650
-        EEH_Debug_Tools::printr($_REQUEST, '$_REQUEST', __FILE__, __LINE__);
651
-        EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
652
-        EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
653
-        EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
654
-        EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
655
-        EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
656
-        EEH_Debug_Tools::printr($this->checkout->generate_reg_form, '$this->checkout->generate_reg_form', __FILE__, __LINE__);
657
-        EEH_Debug_Tools::printr($this->checkout->process_form_submission, '$this->checkout->process_form_submission', __FILE__, __LINE__);
658
-    }
659
-
660
-
661
-
662
-    /**
663
-     * _block_bots
664
-     * checks that the incoming request has either of the following set:
665
-     *  a uts (unix timestamp) which indicates that the request was redirected from the Ticket Selector
666
-     *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
667
-     * so if you're not coming from the Ticket Selector nor returning for a valid IP...
668
-     * then where you coming from man?
669
-     *
670
-     * @return boolean
671
-     */
672
-    private function _block_bots()
673
-    {
674
-        $invalid_checkout_access = \EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
675
-        if ($invalid_checkout_access->checkoutAccessIsInvalid($this->checkout)) {
676
-            return true;
677
-        }
678
-        return false;
679
-    }
680
-
681
-
682
-
683
-    /**
684
-     *    _get_first_step
685
-     *  gets slug for first step in $_reg_steps_array
686
-     *
687
-     * @access    private
688
-     * @throws EE_Error
689
-     * @return    string
690
-     */
691
-    private function _get_first_step()
692
-    {
693
-        $first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
694
-        return isset($first_step['slug']) ? $first_step['slug'] : 'attendee_information';
695
-    }
696
-
697
-
698
-
699
-    /**
700
-     *    _load_and_instantiate_reg_steps
701
-     *  instantiates each reg step based on the loaded reg_steps array
702
-     *
703
-     * @access    private
704
-     * @throws EE_Error
705
-     * @return    bool
706
-     */
707
-    private function _load_and_instantiate_reg_steps()
708
-    {
709
-        do_action('AHEE__Single_Page_Checkout___load_and_instantiate_reg_steps__start', $this->checkout);
710
-        // have reg_steps already been instantiated ?
711
-        if (
712
-            empty($this->checkout->reg_steps)
713
-            || apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
714
-        ) {
715
-            // if not, then loop through raw reg steps array
716
-            foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
717
-                if ( ! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
718
-                    return false;
719
-                }
720
-            }
721
-            EE_Registry::instance()->CFG->registration->skip_reg_confirmation = true;
722
-            EE_Registry::instance()->CFG->registration->reg_confirmation_last = true;
723
-            // skip the registration_confirmation page ?
724
-            if (EE_Registry::instance()->CFG->registration->skip_reg_confirmation) {
725
-                // just remove it from the reg steps array
726
-                $this->checkout->remove_reg_step('registration_confirmation', false);
727
-            } else if (
728
-                isset($this->checkout->reg_steps['registration_confirmation'])
729
-                && EE_Registry::instance()->CFG->registration->reg_confirmation_last
730
-            ) {
731
-                // set the order to something big like 100
732
-                $this->checkout->set_reg_step_order('registration_confirmation', 100);
733
-            }
734
-            // filter the array for good luck
735
-            $this->checkout->reg_steps = apply_filters(
736
-                'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
737
-                $this->checkout->reg_steps
738
-            );
739
-            // finally re-sort based on the reg step class order properties
740
-            $this->checkout->sort_reg_steps();
741
-        } else {
742
-            foreach ($this->checkout->reg_steps as $reg_step) {
743
-                // set all current step stati to FALSE
744
-                $reg_step->set_is_current_step(false);
745
-            }
746
-        }
747
-        if (empty($this->checkout->reg_steps)) {
748
-            EE_Error::add_error(__('No Reg Steps were loaded..', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
749
-            return false;
750
-        }
751
-        // make reg step details available to JS
752
-        $this->checkout->set_reg_step_JSON_info();
753
-        return true;
754
-    }
755
-
756
-
757
-
758
-    /**
759
-     *     _load_and_instantiate_reg_step
760
-     *
761
-     * @access    private
762
-     * @param array $reg_step
763
-     * @param int   $order
764
-     * @return bool
765
-     */
766
-    private function _load_and_instantiate_reg_step($reg_step = array(), $order = 0)
767
-    {
768
-        // we need a file_path, class_name, and slug to add a reg step
769
-        if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
770
-            // if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
771
-            if (
772
-                $this->checkout->reg_url_link
773
-                && $this->checkout->step !== $reg_step['slug']
774
-                && $reg_step['slug'] !== 'finalize_registration'
775
-                // normally at this point we would NOT load the reg step, but this filter can change that
776
-                && apply_filters(
777
-                    'FHEE__Single_Page_Checkout___load_and_instantiate_reg_step__bypass_reg_step',
778
-                    true,
779
-                    $reg_step,
780
-                    $this->checkout
781
-                )
782
-            ) {
783
-                return true;
784
-            }
785
-            // instantiate step class using file path and class name
786
-            $reg_step_obj = EE_Registry::instance()->load_file(
787
-                $reg_step['file_path'],
788
-                $reg_step['class_name'],
789
-                'class',
790
-                $this->checkout,
791
-                false
792
-            );
793
-            // did we gets the goods ?
794
-            if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
795
-                // set reg step order based on config
796
-                $reg_step_obj->set_order($order);
797
-                // add instantiated reg step object to the master reg steps array
798
-                $this->checkout->add_reg_step($reg_step_obj);
799
-            } else {
800
-                EE_Error::add_error(
801
-                    __('The current step could not be set.', 'event_espresso'),
802
-                    __FILE__, __FUNCTION__, __LINE__
803
-                );
804
-                return false;
805
-            }
806
-        } else {
807
-            if (WP_DEBUG) {
808
-                EE_Error::add_error(
809
-                    sprintf(
810
-                        __('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', 'event_espresso'),
811
-                        isset($reg_step['file_path']) ? $reg_step['file_path'] : '',
812
-                        isset($reg_step['class_name']) ? $reg_step['class_name'] : '',
813
-                        isset($reg_step['slug']) ? $reg_step['slug'] : '',
814
-                        '<ul>',
815
-                        '<li>',
816
-                        '</li>',
817
-                        '</ul>'
818
-                    ),
819
-                    __FILE__, __FUNCTION__, __LINE__
820
-                );
821
-            }
822
-            return false;
823
-        }
824
-        return true;
825
-    }
826
-
827
-
828
-
829
-    /**
830
-     * _verify_transaction_and_get_registrations
831
-     *
832
-     * @access private
833
-     * @return bool
834
-     */
835
-    private function _verify_transaction_and_get_registrations()
836
-    {
837
-        // was there already a valid transaction in the checkout from the session ?
838
-        if ( ! $this->checkout->transaction instanceof EE_Transaction) {
839
-            // get transaction from db or session
840
-            $this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
841
-                ? $this->_get_transaction_and_cart_for_previous_visit()
842
-                : $this->_get_cart_for_current_session_and_setup_new_transaction();
843
-            if ( ! $this->checkout->transaction instanceof EE_Transaction) {
844
-                EE_Error::add_error(
845
-                    __('Your Registration and Transaction information could not be retrieved from the db.',
846
-                        'event_espresso'),
847
-                    __FILE__, __FUNCTION__, __LINE__
848
-                );
849
-                $this->checkout->transaction = EE_Transaction::new_instance();
850
-                // add some style and make it dance
851
-                $this->add_styles_and_scripts();
852
-                EED_Single_Page_Checkout::$_initialized = true;
853
-                return false;
854
-            }
855
-            // and the registrations for the transaction
856
-            $this->_get_registrations($this->checkout->transaction);
857
-        }
858
-        return true;
859
-    }
860
-
861
-
862
-
863
-    /**
864
-     * _get_transaction_and_cart_for_previous_visit
865
-     *
866
-     * @access private
867
-     * @return mixed EE_Transaction|NULL
868
-     */
869
-    private function _get_transaction_and_cart_for_previous_visit()
870
-    {
871
-        /** @var $TXN_model EEM_Transaction */
872
-        $TXN_model = EE_Registry::instance()->load_model('Transaction');
873
-        // because the reg_url_link is present in the request, this is a return visit to SPCO, so we'll get the transaction data from the db
874
-        $transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
875
-        // verify transaction
876
-        if ($transaction instanceof EE_Transaction) {
877
-            // and get the cart that was used for that transaction
878
-            $this->checkout->cart = $this->_get_cart_for_transaction($transaction);
879
-            return $transaction;
880
-        } else {
881
-            EE_Error::add_error(__('Your Registration and Transaction information could not be retrieved from the db.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
882
-            return null;
883
-        }
884
-    }
885
-
886
-
887
-
888
-    /**
889
-     * _get_cart_for_transaction
890
-     *
891
-     * @access private
892
-     * @param EE_Transaction $transaction
893
-     * @return EE_Cart
894
-     */
895
-    private function _get_cart_for_transaction($transaction)
896
-    {
897
-        return $this->checkout->get_cart_for_transaction($transaction);
898
-    }
899
-
900
-
901
-
902
-    /**
903
-     * get_cart_for_transaction
904
-     *
905
-     * @access public
906
-     * @param EE_Transaction $transaction
907
-     * @return EE_Cart
908
-     */
909
-    public function get_cart_for_transaction(EE_Transaction $transaction)
910
-    {
911
-        return $this->checkout->get_cart_for_transaction($transaction);
912
-    }
913
-
914
-
915
-
916
-    /**
917
-     * _get_transaction_and_cart_for_current_session
918
-     *    generates a new EE_Transaction object and adds it to the $_transaction property.
919
-     *
920
-     * @access private
921
-     * @return EE_Transaction
922
-     * @throws \EE_Error
923
-     */
924
-    private function _get_cart_for_current_session_and_setup_new_transaction()
925
-    {
926
-        //  if there's no transaction, then this is the FIRST visit to SPCO
927
-        // so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
928
-        $this->checkout->cart = $this->_get_cart_for_transaction(null);
929
-        // and then create a new transaction
930
-        $transaction = $this->_initialize_transaction();
931
-        // verify transaction
932
-        if ($transaction instanceof EE_Transaction) {
933
-            // save it so that we have an ID for other objects to use
934
-            $transaction->save();
935
-            // and save TXN data to the cart
936
-            $this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
937
-        } else {
938
-            EE_Error::add_error(__('A Valid Transaction could not be initialized.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
939
-        }
940
-        return $transaction;
941
-    }
942
-
943
-
944
-
945
-    /**
946
-     *    generates a new EE_Transaction object and adds it to the $_transaction property.
947
-     *
948
-     * @access private
949
-     * @return mixed EE_Transaction|NULL
950
-     */
951
-    private function _initialize_transaction()
952
-    {
953
-        try {
954
-            // ensure cart totals have been calculated
955
-            $this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
956
-            // grab the cart grand total
957
-            $cart_total = $this->checkout->cart->get_cart_grand_total();
958
-            // create new TXN
959
-            $transaction = EE_Transaction::new_instance(
960
-                array(
961
-                    'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
962
-                    'TXN_total'     => $cart_total > 0 ? $cart_total : 0,
963
-                    'TXN_paid'      => 0,
964
-                    'STS_ID'        => EEM_Transaction::failed_status_code,
965
-                )
966
-            );
967
-            // save it so that we have an ID for other objects to use
968
-            $transaction->save();
969
-            // set cron job for following up on TXNs after their session has expired
970
-            EE_Cron_Tasks::schedule_expired_transaction_check(
971
-                EE_Registry::instance()->SSN->expiration() + 1,
972
-                $transaction->ID()
973
-            );
974
-            return $transaction;
975
-        } catch (Exception $e) {
976
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
977
-        }
978
-        return null;
979
-    }
980
-
981
-
982
-
983
-    /**
984
-     * _get_registrations
985
-     *
986
-     * @access private
987
-     * @param EE_Transaction $transaction
988
-     * @return void
989
-     * @throws \EventEspresso\core\exceptions\InvalidEntityException
990
-     * @throws \EE_Error
991
-     */
992
-    private function _get_registrations(EE_Transaction $transaction)
993
-    {
994
-        // first step: grab the registrants  { : o
995
-        $registrations = $transaction->registrations($this->checkout->reg_cache_where_params, true);
996
-        // verify registrations have been set
997
-        if (empty($registrations)) {
998
-            // if no cached registrations, then check the db
999
-            $registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
1000
-            // still nothing ? well as long as this isn't a revisit
1001
-            if (empty($registrations) && ! $this->checkout->revisit) {
1002
-                // generate new registrations from scratch
1003
-                $registrations = $this->_initialize_registrations($transaction);
1004
-            }
1005
-        }
1006
-        // sort by their original registration order
1007
-        usort($registrations, array('EED_Single_Page_Checkout', 'sort_registrations_by_REG_count'));
1008
-        // then loop thru the array
1009
-        foreach ($registrations as $registration) {
1010
-            // verify each registration
1011
-            if ($registration instanceof EE_Registration) {
1012
-                // we display all attendee info for the primary registrant
1013
-                if ($this->checkout->reg_url_link === $registration->reg_url_link()
1014
-                    && $registration->is_primary_registrant()
1015
-                ) {
1016
-                    $this->checkout->primary_revisit = true;
1017
-                    break;
1018
-                } else if ($this->checkout->revisit
1019
-                           && $this->checkout->reg_url_link !== $registration->reg_url_link()
1020
-                ) {
1021
-                    // but hide info if it doesn't belong to you
1022
-                    $transaction->clear_cache('Registration', $registration->ID());
1023
-                }
1024
-                $this->checkout->set_reg_status_updated($registration->ID(), false);
1025
-            }
1026
-        }
1027
-    }
1028
-
1029
-
1030
-
1031
-    /**
1032
-     *    adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1033
-     *
1034
-     * @access private
1035
-     * @param EE_Transaction $transaction
1036
-     * @return    array
1037
-     * @throws \EventEspresso\core\exceptions\InvalidEntityException
1038
-     * @throws \EE_Error
1039
-     */
1040
-    private function _initialize_registrations(EE_Transaction $transaction)
1041
-    {
1042
-        $att_nmbr = 0;
1043
-        $registrations = array();
1044
-        if ($transaction instanceof EE_Transaction) {
1045
-            /** @type EE_Registration_Processor $registration_processor */
1046
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1047
-            $this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1048
-            // now let's add the cart items to the $transaction
1049
-            foreach ($this->checkout->cart->get_tickets() as $line_item) {
1050
-                //do the following for each ticket of this type they selected
1051
-                for ($x = 1; $x <= $line_item->quantity(); $x++) {
1052
-                    $att_nmbr++;
1053
-                    /** @var EventEspresso\core\services\commands\registration\CreateRegistrationCommand $CreateRegistrationCommand */
1054
-                    $CreateRegistrationCommand = EE_Registry::instance()
1055
-                                                            ->create(
1056
-                                                                'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1057
-                                                                array(
1058
-                                                                    $transaction,
1059
-                                                                    $line_item,
1060
-                                                                    $att_nmbr,
1061
-                                                                    $this->checkout->total_ticket_count,
1062
-                                                                )
1063
-                                                            );
1064
-                    // override capabilities for frontend registrations
1065
-                    if ( ! is_admin()) {
1066
-                        $CreateRegistrationCommand->setCapCheck(
1067
-                            new PublicCapabilities('', 'create_new_registration')
1068
-                        );
1069
-                    }
1070
-                    $registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1071
-                    if ( ! $registration instanceof EE_Registration) {
1072
-                        throw new InvalidEntityException($registration, 'EE_Registration');
1073
-                    }
1074
-                    $registrations[ $registration->ID() ] = $registration;
1075
-                }
1076
-            }
1077
-            $registration_processor->fix_reg_final_price_rounding_issue($transaction);
1078
-        }
1079
-        return $registrations;
1080
-    }
1081
-
1082
-
1083
-
1084
-    /**
1085
-     * sorts registrations by REG_count
1086
-     *
1087
-     * @access public
1088
-     * @param EE_Registration $reg_A
1089
-     * @param EE_Registration $reg_B
1090
-     * @return int
1091
-     */
1092
-    public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B)
1093
-    {
1094
-        // this shouldn't ever happen within the same TXN, but oh well
1095
-        if ($reg_A->count() === $reg_B->count()) {
1096
-            return 0;
1097
-        }
1098
-        return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1099
-    }
1100
-
1101
-
1102
-
1103
-    /**
1104
-     *    _final_verifications
1105
-     * just makes sure that everything is set up correctly before proceeding
1106
-     *
1107
-     * @access    private
1108
-     * @return    bool
1109
-     * @throws \EE_Error
1110
-     */
1111
-    private function _final_verifications()
1112
-    {
1113
-        // filter checkout
1114
-        $this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___final_verifications__checkout', $this->checkout);
1115
-        //verify that current step is still set correctly
1116
-        if ( ! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1117
-            EE_Error::add_error(
1118
-                __('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'),
1119
-                __FILE__,
1120
-                __FUNCTION__,
1121
-                __LINE__
1122
-            );
1123
-            return false;
1124
-        }
1125
-        // if returning to SPCO, then verify that primary registrant is set
1126
-        if ( ! empty($this->checkout->reg_url_link)) {
1127
-            $valid_registrant = $this->checkout->transaction->primary_registration();
1128
-            if ( ! $valid_registrant instanceof EE_Registration) {
1129
-                EE_Error::add_error(
1130
-                    __('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'),
1131
-                    __FILE__,
1132
-                    __FUNCTION__,
1133
-                    __LINE__
1134
-                );
1135
-                return false;
1136
-            }
1137
-            $valid_registrant = null;
1138
-            foreach ($this->checkout->transaction->registrations($this->checkout->reg_cache_where_params) as $registration) {
1139
-                if (
1140
-                    $registration instanceof EE_Registration
1141
-                    && $registration->reg_url_link() === $this->checkout->reg_url_link
1142
-                ) {
1143
-                    $valid_registrant = $registration;
1144
-                }
1145
-            }
1146
-            if ( ! $valid_registrant instanceof EE_Registration) {
1147
-                // hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1148
-                if (EED_Single_Page_Checkout::$_checkout_verified) {
1149
-                    // clear the session, mark the checkout as unverified, and try again
1150
-                    EE_Registry::instance()->SSN->clear_session();
1151
-                    EED_Single_Page_Checkout::$_initialized = false;
1152
-                    EED_Single_Page_Checkout::$_checkout_verified = false;
1153
-                    $this->_initialize();
1154
-                    EE_Error::reset_notices();
1155
-                    return false;
1156
-                }
1157
-                EE_Error::add_error(
1158
-                    __('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.', 'event_espresso'),
1159
-                    __FILE__,
1160
-                    __FUNCTION__,
1161
-                    __LINE__
1162
-                );
1163
-                return false;
1164
-            }
1165
-        }
1166
-        // now that things have been kinda sufficiently verified,
1167
-        // let's add the checkout to the session so that's available other systems
1168
-        EE_Registry::instance()->SSN->set_checkout($this->checkout);
1169
-        return true;
1170
-    }
1171
-
1172
-
1173
-
1174
-    /**
1175
-     *    _initialize_reg_steps
1176
-     * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1177
-     * then loops thru all of the active reg steps and calls the initialize_reg_step() method
1178
-     *
1179
-     * @access    private
1180
-     * @param bool $reinitializing
1181
-     * @throws \EE_Error
1182
-     */
1183
-    private function _initialize_reg_steps($reinitializing = false)
1184
-    {
1185
-        $this->checkout->set_reg_step_initiated($this->checkout->current_step);
1186
-        // loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1187
-        foreach ($this->checkout->reg_steps as $reg_step) {
1188
-            if ( ! $reg_step->initialize_reg_step()) {
1189
-                // if not initialized then maybe this step is being removed...
1190
-                if ( ! $reinitializing && $reg_step->is_current_step()) {
1191
-                    // if it was the current step, then we need to start over here
1192
-                    $this->_initialize_reg_steps(true);
1193
-                    return;
1194
-                }
1195
-                continue;
1196
-            }
1197
-            // add css and JS for current step
1198
-            $reg_step->enqueue_styles_and_scripts();
1199
-            // i18n
1200
-            $reg_step->translate_js_strings();
1201
-            if ($reg_step->is_current_step()) {
1202
-                // the text that appears on the reg step form submit button
1203
-                $reg_step->set_submit_button_text();
1204
-            }
1205
-        }
1206
-        // dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1207
-        do_action("AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}", $this->checkout->current_step);
1208
-    }
1209
-
1210
-
1211
-
1212
-    /**
1213
-     * _check_form_submission
1214
-     *
1215
-     * @access private
1216
-     * @return boolean
1217
-     */
1218
-    private function _check_form_submission()
1219
-    {
1220
-        //does this request require the reg form to be generated ?
1221
-        if ($this->checkout->generate_reg_form) {
1222
-            // ever heard that song by Blue Rodeo ?
1223
-            try {
1224
-                $this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1225
-                // if not displaying a form, then check for form submission
1226
-                if (
1227
-                    $this->checkout->process_form_submission
1228
-                    && $this->checkout->current_step->reg_form->was_submitted()
1229
-                ) {
1230
-                    // clear out any old data in case this step is being run again
1231
-                    $this->checkout->current_step->set_valid_data(array());
1232
-                    // capture submitted form data
1233
-                    $this->checkout->current_step->reg_form->receive_form_submission(
1234
-                        apply_filters('FHEE__Single_Page_Checkout___check_form_submission__request_params', EE_Registry::instance()->REQ->params(), $this->checkout)
1235
-                    );
1236
-                    // validate submitted form data
1237
-                    if ( ! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1238
-                        // thou shall not pass !!!
1239
-                        $this->checkout->continue_reg = false;
1240
-                        // any form validation errors?
1241
-                        if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1242
-                            $submission_error_messages = array();
1243
-                            // bad, bad, bad registrant
1244
-                            foreach ($this->checkout->current_step->reg_form->get_validation_errors_accumulated() as $validation_error) {
1245
-                                if ($validation_error instanceof EE_Validation_Error) {
1246
-                                    $submission_error_messages[] = sprintf(
1247
-                                        __('%s : %s', 'event_espresso'),
1248
-                                        $validation_error->get_form_section()->html_label_text(),
1249
-                                        $validation_error->getMessage()
1250
-                                    );
1251
-                                }
1252
-                            }
1253
-                            EE_Error::add_error(implode('<br />', $submission_error_messages), __FILE__, __FUNCTION__, __LINE__);
1254
-                        }
1255
-                        // well not really... what will happen is we'll just get redirected back to redo the current step
1256
-                        $this->go_to_next_step();
1257
-                        return false;
1258
-                    }
1259
-                }
1260
-            } catch (EE_Error $e) {
1261
-                $e->get_error();
1262
-            }
1263
-        }
1264
-        return true;
1265
-    }
1266
-
1267
-
1268
-
1269
-    /**
1270
-     * _process_action
1271
-     *
1272
-     * @access private
1273
-     * @return void
1274
-     * @throws \EE_Error
1275
-     */
1276
-    private function _process_form_action()
1277
-    {
1278
-        // what cha wanna do?
1279
-        switch ($this->checkout->action) {
1280
-            // AJAX next step reg form
1281
-            case 'display_spco_reg_step' :
1282
-                $this->checkout->redirect = false;
1283
-                if (EE_Registry::instance()->REQ->ajax) {
1284
-                    $this->checkout->json_response->set_reg_step_html($this->checkout->current_step->display_reg_form());
1285
-                }
1286
-                break;
1287
-            default :
1288
-                // meh... do one of those other steps first
1289
-                if ( ! empty($this->checkout->action) && is_callable(array($this->checkout->current_step, $this->checkout->action))) {
1290
-                    // dynamically creates hook point like: AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1291
-                    do_action("AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}", $this->checkout->current_step);
1292
-                    // call action on current step
1293
-                    if (call_user_func(array($this->checkout->current_step, $this->checkout->action))) {
1294
-                        // good registrant, you get to proceed
1295
-                        if (
1296
-                            $this->checkout->current_step->success_message() !== ''
1297
-                            && apply_filters(
1298
-                                'FHEE__Single_Page_Checkout___process_form_action__display_success',
1299
-                                false
1300
-                            )
1301
-                        ) {
1302
-                            EE_Error::add_success(
1303
-                                $this->checkout->current_step->success_message()
1304
-                                . '<br />' . $this->checkout->next_step->_instructions()
1305
-                            );
1306
-                        }
1307
-                        // pack it up, pack it in...
1308
-                        $this->_setup_redirect();
1309
-                    }
1310
-                    // dynamically creates hook point like: AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1311
-                    do_action("AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}", $this->checkout->current_step);
1312
-                } else {
1313
-                    EE_Error::add_error(
1314
-                        sprintf(
1315
-                            __('The requested form action "%s" does not exist for the current "%s" registration step.', 'event_espresso'),
1316
-                            $this->checkout->action,
1317
-                            $this->checkout->current_step->name()
1318
-                        ),
1319
-                        __FILE__,
1320
-                        __FUNCTION__,
1321
-                        __LINE__
1322
-                    );
1323
-                }
1324
-            // end default
1325
-        }
1326
-        // store our progress so far
1327
-        $this->checkout->stash_transaction_and_checkout();
1328
-        // advance to the next step! If you pass GO, collect $200
1329
-        $this->go_to_next_step();
1330
-    }
1331
-
1332
-
1333
-
1334
-    /**
1335
-     *        add_styles_and_scripts
1336
-     *
1337
-     * @access        public
1338
-     * @return        void
1339
-     */
1340
-    public function add_styles_and_scripts()
1341
-    {
1342
-        // i18n
1343
-        $this->translate_js_strings();
1344
-        if ($this->checkout->admin_request) {
1345
-            add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1346
-        } else {
1347
-            add_action('wp_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1348
-        }
1349
-    }
1350
-
1351
-
1352
-
1353
-    /**
1354
-     *        translate_js_strings
1355
-     *
1356
-     * @access        public
1357
-     * @return        void
1358
-     */
1359
-    public function translate_js_strings()
1360
-    {
1361
-        EE_Registry::$i18n_js_strings['revisit'] = $this->checkout->revisit;
1362
-        EE_Registry::$i18n_js_strings['e_reg_url_link'] = $this->checkout->reg_url_link;
1363
-        EE_Registry::$i18n_js_strings['server_error'] = __('An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.', 'event_espresso');
1364
-        EE_Registry::$i18n_js_strings['invalid_json_response'] = __('An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.', 'event_espresso');
1365
-        EE_Registry::$i18n_js_strings['validation_error'] = __('There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.', 'event_espresso');
1366
-        EE_Registry::$i18n_js_strings['invalid_payment_method'] = __('There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.', 'event_espresso');
1367
-        EE_Registry::$i18n_js_strings['reg_step_error'] = __('This registration step could not be completed. Please refresh the page and try again.', 'event_espresso');
1368
-        EE_Registry::$i18n_js_strings['invalid_coupon'] = __('We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.', 'event_espresso');
1369
-        EE_Registry::$i18n_js_strings['process_registration'] = sprintf(
1370
-            __('Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.', 'event_espresso'),
1371
-            '<br/>',
1372
-            '<br/>'
1373
-        );
1374
-        EE_Registry::$i18n_js_strings['language'] = get_bloginfo('language');
1375
-        EE_Registry::$i18n_js_strings['EESID'] = EE_Registry::instance()->SSN->id();
1376
-        EE_Registry::$i18n_js_strings['currency'] = EE_Registry::instance()->CFG->currency;
1377
-        EE_Registry::$i18n_js_strings['datepicker_yearRange'] = '-150:+20';
1378
-        EE_Registry::$i18n_js_strings['timer_years'] = __('years', 'event_espresso');
1379
-        EE_Registry::$i18n_js_strings['timer_months'] = __('months', 'event_espresso');
1380
-        EE_Registry::$i18n_js_strings['timer_weeks'] = __('weeks', 'event_espresso');
1381
-        EE_Registry::$i18n_js_strings['timer_days'] = __('days', 'event_espresso');
1382
-        EE_Registry::$i18n_js_strings['timer_hours'] = __('hours', 'event_espresso');
1383
-        EE_Registry::$i18n_js_strings['timer_minutes'] = __('minutes', 'event_espresso');
1384
-        EE_Registry::$i18n_js_strings['timer_seconds'] = __('seconds', 'event_espresso');
1385
-        EE_Registry::$i18n_js_strings['timer_year'] = __('year', 'event_espresso');
1386
-        EE_Registry::$i18n_js_strings['timer_month'] = __('month', 'event_espresso');
1387
-        EE_Registry::$i18n_js_strings['timer_week'] = __('week', 'event_espresso');
1388
-        EE_Registry::$i18n_js_strings['timer_day'] = __('day', 'event_espresso');
1389
-        EE_Registry::$i18n_js_strings['timer_hour'] = __('hour', 'event_espresso');
1390
-        EE_Registry::$i18n_js_strings['timer_minute'] = __('minute', 'event_espresso');
1391
-        EE_Registry::$i18n_js_strings['timer_second'] = __('second', 'event_espresso');
1392
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
1393
-            __(
1394
-                '%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 except our apologies for any inconvenience this may have caused.%8$s',
1395
-                'event_espresso'
1396
-            ),
1397
-            '<h4 class="important-notice">',
1398
-            '</h4>',
1399
-            '<br />',
1400
-            '<p>',
1401
-            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1402
-            '">',
1403
-            '</a>',
1404
-            '</p>'
1405
-        );
1406
-        EE_Registry::$i18n_js_strings['ajax_submit'] = apply_filters('FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit', true);
1407
-        EE_Registry::$i18n_js_strings['session_extension'] = absint(
1408
-            apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1409
-        );
1410
-        EE_Registry::$i18n_js_strings['session_expiration'] = gmdate(
1411
-            'M d, Y H:i:s', EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1412
-        );
1413
-    }
1414
-
1415
-
1416
-
1417
-    /**
1418
-     *    enqueue_styles_and_scripts
1419
-     *
1420
-     * @access        public
1421
-     * @return        void
1422
-     * @throws \EE_Error
1423
-     */
1424
-    public function enqueue_styles_and_scripts()
1425
-    {
1426
-        // load css
1427
-        wp_register_style('single_page_checkout', SPCO_CSS_URL . 'single_page_checkout.css', array(), EVENT_ESPRESSO_VERSION);
1428
-        wp_enqueue_style('single_page_checkout');
1429
-        // load JS
1430
-        wp_register_script('jquery_plugin', EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js', array('jquery'), '1.0.1', true);
1431
-        wp_register_script('jquery_countdown', EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js', array('jquery_plugin'), '2.0.2', true);
1432
-        wp_register_script('single_page_checkout', SPCO_JS_URL . 'single_page_checkout.js', array('espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown'), EVENT_ESPRESSO_VERSION, true);
1433
-        if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1434
-            $this->checkout->registration_form->enqueue_js();
1435
-        }
1436
-        if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1437
-            $this->checkout->current_step->reg_form->enqueue_js();
1438
-        }
1439
-        wp_enqueue_script('single_page_checkout');
1440
-        /**
1441
-         * global action hook for enqueueing styles and scripts with
1442
-         * spco calls.
1443
-         */
1444
-        do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1445
-        /**
1446
-         * dynamic action hook for enqueueing styles and scripts with spco calls.
1447
-         * The hook will end up being something like AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1448
-         */
1449
-        do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(), $this);
1450
-    }
1451
-
1452
-
1453
-
1454
-    /**
1455
-     *    display the Registration Single Page Checkout Form
1456
-     *
1457
-     * @access    private
1458
-     * @return    void
1459
-     * @throws \EE_Error
1460
-     */
1461
-    private function _display_spco_reg_form()
1462
-    {
1463
-        // if registering via the admin, just display the reg form for the current step
1464
-        if ($this->checkout->admin_request) {
1465
-            EE_Registry::instance()->REQ->add_output($this->checkout->current_step->display_reg_form());
1466
-        } else {
1467
-            // add powered by EE msg
1468
-            add_action('AHEE__SPCO__reg_form_footer', array('EED_Single_Page_Checkout', 'display_registration_footer'));
1469
-            $empty_cart = count($this->checkout->transaction->registrations($this->checkout->reg_cache_where_params)) < 1
1470
-                ? true
1471
-                : false;
1472
-            EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1473
-            $cookies_not_set_msg = '';
1474
-            if ($empty_cart && ! isset($_COOKIE['ee_cookie_test'])) {
1475
-                $cookies_not_set_msg = apply_filters(
1476
-                    'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1477
-                    sprintf(
1478
-                        __(
1479
-                            '%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',
1480
-                            'event_espresso'
1481
-                        ),
1482
-                        '<div class="ee-attention">',
1483
-                        '</div>',
1484
-                        '<h6 class="important-notice">',
1485
-                        '</h6>',
1486
-                        '<p>',
1487
-                        '</p>',
1488
-                        '<br />',
1489
-                        '<a href="http://www.whatarecookies.com/enable.asp" target="_blank">',
1490
-                        '</a>'
1491
-                    )
1492
-                );
1493
-            }
1494
-            $this->checkout->registration_form = new EE_Form_Section_Proper(
1495
-                array(
1496
-                    'name'            => 'single-page-checkout',
1497
-                    'html_id'         => 'ee-single-page-checkout-dv',
1498
-                    'layout_strategy' =>
1499
-                        new EE_Template_Layout(
1500
-                            array(
1501
-                                'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1502
-                                'template_args'        => array(
1503
-                                    'empty_cart'              => $empty_cart,
1504
-                                    'revisit'                 => $this->checkout->revisit,
1505
-                                    'reg_steps'               => $this->checkout->reg_steps,
1506
-                                    'next_step'               => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
1507
-                                        ? $this->checkout->next_step->slug()
1508
-                                        : '',
1509
-                                    'cancel_page_url'         => $this->checkout->cancel_page_url,
1510
-                                    'empty_msg'               => apply_filters(
1511
-                                        'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1512
-                                        sprintf(
1513
-                                            __('You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1514
-                                                'event_espresso'),
1515
-                                            '<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1516
-                                            '">',
1517
-                                            '</a>'
1518
-                                        )
1519
-                                    ),
1520
-                                    'cookies_not_set_msg'     => $cookies_not_set_msg,
1521
-                                    'registration_time_limit' => $this->checkout->get_registration_time_limit(),
1522
-                                    'session_expiration'      =>
1523
-                                        date('M d, Y H:i:s', EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)),
1524
-                                ),
1525
-                            )
1526
-                        ),
1527
-                )
1528
-            );
1529
-            // load template and add to output sent that gets filtered into the_content()
1530
-            EE_Registry::instance()->REQ->add_output($this->checkout->registration_form->get_html());
1531
-        }
1532
-    }
1533
-
1534
-
1535
-
1536
-    /**
1537
-     *    add_extra_finalize_registration_inputs
1538
-     *
1539
-     * @access    public
1540
-     * @param $next_step
1541
-     * @internal  param string $label
1542
-     * @return void
1543
-     */
1544
-    public function add_extra_finalize_registration_inputs($next_step)
1545
-    {
1546
-        if ($next_step === 'finalize_registration') {
1547
-            echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1548
-        }
1549
-    }
1550
-
1551
-
1552
-
1553
-    /**
1554
-     *    display_registration_footer
1555
-     *
1556
-     * @access    public
1557
-     * @return    string
1558
-     */
1559
-    public static function display_registration_footer()
1560
-    {
1561
-        if (
1562
-        apply_filters(
1563
-            'FHEE__EE_Front__Controller__show_reg_footer',
1564
-            EE_Registry::instance()->CFG->admin->show_reg_footer
1565
-        )
1566
-        ) {
1567
-            add_filter(
1568
-                'FHEE__EEH_Template__powered_by_event_espresso__url',
1569
-                function ($url) {
1570
-                    return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1571
-                }
1572
-            );
1573
-            echo apply_filters(
1574
-                'FHEE__EE_Front_Controller__display_registration_footer',
1575
-                \EEH_Template::powered_by_event_espresso(
1576
-                    '',
1577
-                    'espresso-registration-footer-dv',
1578
-                    array('utm_content' => 'registration_checkout')
1579
-                )
1580
-            );
1581
-        }
1582
-        return '';
1583
-    }
1584
-
1585
-
1586
-
1587
-    /**
1588
-     *    unlock_transaction
1589
-     *
1590
-     * @access    public
1591
-     * @return    void
1592
-     * @throws \EE_Error
1593
-     */
1594
-    public function unlock_transaction()
1595
-    {
1596
-        if ($this->checkout->transaction instanceof EE_Transaction) {
1597
-            $this->checkout->transaction->unlock();
1598
-        }
1599
-    }
1600
-
1601
-
1602
-
1603
-    /**
1604
-     *        _setup_redirect
1605
-     *
1606
-     * @access    private
1607
-     * @return void
1608
-     */
1609
-    private function _setup_redirect()
1610
-    {
1611
-        if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1612
-            $this->checkout->redirect = true;
1613
-            if (empty($this->checkout->redirect_url)) {
1614
-                $this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1615
-            }
1616
-            $this->checkout->redirect_url = apply_filters(
1617
-                'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1618
-                $this->checkout->redirect_url,
1619
-                $this->checkout
1620
-            );
1621
-        }
1622
-    }
1623
-
1624
-
1625
-
1626
-    /**
1627
-     *   handle ajax message responses and redirects
1628
-     *
1629
-     * @access public
1630
-     * @return void
1631
-     * @throws \EE_Error
1632
-     */
1633
-    public function go_to_next_step()
1634
-    {
1635
-        if (EE_Registry::instance()->REQ->ajax) {
1636
-            // capture contents of output buffer we started earlier in the request, and insert into JSON response
1637
-            $this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1638
-        }
1639
-        $this->unlock_transaction();
1640
-        // just return for these conditions
1641
-        if (
1642
-            $this->checkout->admin_request
1643
-            || $this->checkout->action === 'redirect_form'
1644
-            || $this->checkout->action === 'update_checkout'
1645
-        ) {
1646
-            return;
1647
-        }
1648
-        // AJAX response
1649
-        $this->_handle_json_response();
1650
-        // redirect to next step or the Thank You page
1651
-        $this->_handle_html_redirects();
1652
-        // hmmm... must be something wrong, so let's just display the form again !
1653
-        $this->_display_spco_reg_form();
1654
-    }
1655
-
1656
-
1657
-
1658
-    /**
1659
-     *   _handle_json_response
1660
-     *
1661
-     * @access protected
1662
-     * @return void
1663
-     */
1664
-    protected function _handle_json_response()
1665
-    {
1666
-        // if this is an ajax request
1667
-        if (EE_Registry::instance()->REQ->ajax) {
1668
-            // DEBUG LOG
1669
-            //$this->checkout->log(
1670
-            //	__CLASS__, __FUNCTION__, __LINE__,
1671
-            //	array(
1672
-            //		'json_response_redirect_url' => $this->checkout->json_response->redirect_url(),
1673
-            //		'redirect'                   => $this->checkout->redirect,
1674
-            //		'continue_reg'               => $this->checkout->continue_reg,
1675
-            //	)
1676
-            //);
1677
-            $this->checkout->json_response->set_registration_time_limit(
1678
-                $this->checkout->get_registration_time_limit()
1679
-            );
1680
-            $this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1681
-            // just send the ajax (
1682
-            $json_response = apply_filters(
1683
-                'FHEE__EE_Single_Page_Checkout__JSON_response',
1684
-                $this->checkout->json_response
1685
-            );
1686
-            echo $json_response;
1687
-            exit();
1688
-        }
1689
-    }
1690
-
1691
-
1692
-
1693
-    /**
1694
-     *   _handle_redirects
1695
-     *
1696
-     * @access protected
1697
-     * @return void
1698
-     */
1699
-    protected function _handle_html_redirects()
1700
-    {
1701
-        // going somewhere ?
1702
-        if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1703
-            // store notices in a transient
1704
-            EE_Error::get_notices(false, true, true);
1705
-            // DEBUG LOG
1706
-            //$this->checkout->log(
1707
-            //	__CLASS__, __FUNCTION__, __LINE__,
1708
-            //	array(
1709
-            //		'headers_sent' => headers_sent(),
1710
-            //		'redirect_url'     => $this->checkout->redirect_url,
1711
-            //		'headers_list'    => headers_list(),
1712
-            //	)
1713
-            //);
1714
-            wp_safe_redirect($this->checkout->redirect_url);
1715
-            exit();
1716
-        }
1717
-    }
1718
-
1719
-
1720
-
1721
-    /**
1722
-     *   set_checkout_anchor
1723
-     *
1724
-     * @access public
1725
-     * @return void
1726
-     */
1727
-    public function set_checkout_anchor()
1728
-    {
1729
-        echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1730
-    }
20
+	/**
21
+	 * $_initialized - has the SPCO controller already been initialized ?
22
+	 *
23
+	 * @access private
24
+	 * @var bool $_initialized
25
+	 */
26
+	private static $_initialized = false;
27
+
28
+
29
+	/**
30
+	 * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
31
+	 *
32
+	 * @access private
33
+	 * @var bool $_valid_checkout
34
+	 */
35
+	private static $_checkout_verified = true;
36
+
37
+	/**
38
+	 *    $_reg_steps_array - holds initial array of reg steps
39
+	 *
40
+	 * @access private
41
+	 * @var array $_reg_steps_array
42
+	 */
43
+	private static $_reg_steps_array = array();
44
+
45
+	/**
46
+	 *    $checkout - EE_Checkout object for handling the properties of the current checkout process
47
+	 *
48
+	 * @access public
49
+	 * @var EE_Checkout $checkout
50
+	 */
51
+	public $checkout;
52
+
53
+
54
+
55
+	/**
56
+	 * @return EED_Single_Page_Checkout
57
+	 */
58
+	public static function instance()
59
+	{
60
+		add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
61
+		return parent::get_instance(__CLASS__);
62
+	}
63
+
64
+
65
+
66
+	/**
67
+	 * @return EE_CART
68
+	 */
69
+	public function cart()
70
+	{
71
+		return $this->checkout->cart;
72
+	}
73
+
74
+
75
+
76
+	/**
77
+	 * @return EE_Transaction
78
+	 */
79
+	public function transaction()
80
+	{
81
+		return $this->checkout->transaction;
82
+	}
83
+
84
+
85
+
86
+	/**
87
+	 *    set_hooks - for hooking into EE Core, other modules, etc
88
+	 *
89
+	 * @access    public
90
+	 * @return    void
91
+	 * @throws \EE_Error
92
+	 */
93
+	public static function set_hooks()
94
+	{
95
+		EED_Single_Page_Checkout::set_definitions();
96
+	}
97
+
98
+
99
+
100
+	/**
101
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
102
+	 *
103
+	 * @access    public
104
+	 * @return    void
105
+	 * @throws \EE_Error
106
+	 */
107
+	public static function set_hooks_admin()
108
+	{
109
+		EED_Single_Page_Checkout::set_definitions();
110
+		if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
111
+			// hook into the top of pre_get_posts to set the reg step routing, which gives other modules or plugins a chance to modify the reg steps, but just before the routes get called
112
+			add_action('pre_get_posts', array('EED_Single_Page_Checkout', 'load_reg_steps'), 1);
113
+			return;
114
+		}
115
+		// going to start an output buffer in case anything gets accidentally output that might disrupt our JSON response
116
+		ob_start();
117
+		EED_Single_Page_Checkout::load_request_handler();
118
+		EED_Single_Page_Checkout::load_reg_steps();
119
+		// set ajax hooks
120
+		add_action('wp_ajax_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
121
+		add_action('wp_ajax_nopriv_process_reg_step', array('EED_Single_Page_Checkout', 'process_reg_step'));
122
+		add_action('wp_ajax_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
123
+		add_action('wp_ajax_nopriv_display_spco_reg_step', array('EED_Single_Page_Checkout', 'display_reg_step'));
124
+		add_action('wp_ajax_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
125
+		add_action('wp_ajax_nopriv_update_reg_step', array('EED_Single_Page_Checkout', 'update_reg_step'));
126
+	}
127
+
128
+
129
+
130
+	/**
131
+	 *    process ajax request
132
+	 *
133
+	 * @param string $ajax_action
134
+	 * @throws \EE_Error
135
+	 */
136
+	public static function process_ajax_request($ajax_action)
137
+	{
138
+		EE_Registry::instance()->REQ->set('action', $ajax_action);
139
+		EED_Single_Page_Checkout::instance()->_initialize();
140
+	}
141
+
142
+
143
+
144
+	/**
145
+	 *    ajax display registration step
146
+	 *
147
+	 * @throws \EE_Error
148
+	 */
149
+	public static function display_reg_step()
150
+	{
151
+		EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
152
+	}
153
+
154
+
155
+
156
+	/**
157
+	 *    ajax process registration step
158
+	 *
159
+	 * @throws \EE_Error
160
+	 */
161
+	public static function process_reg_step()
162
+	{
163
+		EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
164
+	}
165
+
166
+
167
+
168
+	/**
169
+	 *    ajax process registration step
170
+	 *
171
+	 * @throws \EE_Error
172
+	 */
173
+	public static function update_reg_step()
174
+	{
175
+		EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
176
+	}
177
+
178
+
179
+
180
+	/**
181
+	 *   update_checkout
182
+	 *
183
+	 * @access public
184
+	 * @return void
185
+	 * @throws \EE_Error
186
+	 */
187
+	public static function update_checkout()
188
+	{
189
+		EED_Single_Page_Checkout::process_ajax_request('update_checkout');
190
+	}
191
+
192
+
193
+
194
+	/**
195
+	 *    load_request_handler
196
+	 *
197
+	 * @access    public
198
+	 * @return    void
199
+	 */
200
+	public static function load_request_handler()
201
+	{
202
+		// load core Request_Handler class
203
+		if ( ! isset(EE_Registry::instance()->REQ)) {
204
+			EE_Registry::instance()->load_core('Request_Handler');
205
+		}
206
+	}
207
+
208
+
209
+
210
+	/**
211
+	 *    set_definitions
212
+	 *
213
+	 * @access    public
214
+	 * @return    void
215
+	 * @throws \EE_Error
216
+	 */
217
+	public static function set_definitions()
218
+	{
219
+		define('SPCO_BASE_PATH', rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS);
220
+		define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css' . DS);
221
+		define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img' . DS);
222
+		define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js' . DS);
223
+		define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc' . DS);
224
+		define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps' . DS);
225
+		define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates' . DS);
226
+		EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
227
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
228
+			__('%1$sWe\'re sorry, but you\'re registration time has expired.%2$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 except our apologies for any inconvenience this may have caused.%8$s',
229
+				'event_espresso'),
230
+			'<h4 class="important-notice">',
231
+			'</h4>',
232
+			'<br />',
233
+			'<p>',
234
+			'<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
235
+			'">',
236
+			'</a>',
237
+			'</p>'
238
+		);
239
+	}
240
+
241
+
242
+
243
+	/**
244
+	 * load_reg_steps
245
+	 * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
246
+	 *
247
+	 * @access    private
248
+	 * @throws EE_Error
249
+	 * @return void
250
+	 */
251
+	public static function load_reg_steps()
252
+	{
253
+		static $reg_steps_loaded = false;
254
+		if ($reg_steps_loaded) {
255
+			return;
256
+		}
257
+		// filter list of reg_steps
258
+		$reg_steps_to_load = (array)apply_filters(
259
+			'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
260
+			EED_Single_Page_Checkout::get_reg_steps()
261
+		);
262
+		// sort by key (order)
263
+		ksort($reg_steps_to_load);
264
+		// loop through folders
265
+		foreach ($reg_steps_to_load as $order => $reg_step) {
266
+			// we need a
267
+			if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
268
+				// copy over to the reg_steps_array
269
+				EED_Single_Page_Checkout::$_reg_steps_array[$order] = $reg_step;
270
+				// register custom key route for each reg step
271
+				// ie: step=>"slug" - this is the entire reason we load the reg steps array now
272
+				EE_Config::register_route($reg_step['slug'], 'EED_Single_Page_Checkout', 'run', 'step');
273
+				// add AJAX or other hooks
274
+				if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
275
+					// setup autoloaders if necessary
276
+					if ( ! class_exists($reg_step['class_name'])) {
277
+						EEH_Autoloader::register_autoloaders_for_each_file_in_folder($reg_step['file_path'], true);
278
+					}
279
+					if (is_callable($reg_step['class_name'], 'set_hooks')) {
280
+						call_user_func(array($reg_step['class_name'], 'set_hooks'));
281
+					}
282
+				}
283
+			}
284
+		}
285
+		$reg_steps_loaded = true;
286
+	}
287
+
288
+
289
+
290
+	/**
291
+	 *    get_reg_steps
292
+	 *
293
+	 * @access    public
294
+	 * @return    array
295
+	 */
296
+	public static function get_reg_steps()
297
+	{
298
+		$reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
299
+		if (empty($reg_steps)) {
300
+			$reg_steps = array(
301
+				10  => array(
302
+					'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
303
+					'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
304
+					'slug'       => 'attendee_information',
305
+					'has_hooks'  => false,
306
+				),
307
+				20  => array(
308
+					'file_path'  => SPCO_REG_STEPS_PATH . 'registration_confirmation',
309
+					'class_name' => 'EE_SPCO_Reg_Step_Registration_Confirmation',
310
+					'slug'       => 'registration_confirmation',
311
+					'has_hooks'  => false,
312
+				),
313
+				30  => array(
314
+					'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
315
+					'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
316
+					'slug'       => 'payment_options',
317
+					'has_hooks'  => true,
318
+				),
319
+				999 => array(
320
+					'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
321
+					'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
322
+					'slug'       => 'finalize_registration',
323
+					'has_hooks'  => false,
324
+				),
325
+			);
326
+		}
327
+		return $reg_steps;
328
+	}
329
+
330
+
331
+
332
+	/**
333
+	 *    registration_checkout_for_admin
334
+	 *
335
+	 * @access    public
336
+	 * @return    string
337
+	 * @throws \EE_Error
338
+	 */
339
+	public static function registration_checkout_for_admin()
340
+	{
341
+		EED_Single_Page_Checkout::load_reg_steps();
342
+		EE_Registry::instance()->REQ->set('step', 'attendee_information');
343
+		EE_Registry::instance()->REQ->set('action', 'display_spco_reg_step');
344
+		EE_Registry::instance()->REQ->set('process_form_submission', false);
345
+		EED_Single_Page_Checkout::instance()->_initialize();
346
+		EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
347
+		return EE_Registry::instance()->REQ->get_output();
348
+	}
349
+
350
+
351
+
352
+	/**
353
+	 * process_registration_from_admin
354
+	 *
355
+	 * @access public
356
+	 * @return \EE_Transaction
357
+	 * @throws \EE_Error
358
+	 */
359
+	public static function process_registration_from_admin()
360
+	{
361
+		EED_Single_Page_Checkout::load_reg_steps();
362
+		EE_Registry::instance()->REQ->set('step', 'attendee_information');
363
+		EE_Registry::instance()->REQ->set('action', 'process_reg_step');
364
+		EE_Registry::instance()->REQ->set('process_form_submission', true);
365
+		EED_Single_Page_Checkout::instance()->_initialize();
366
+		if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
367
+			$final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
368
+			if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
369
+				EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
370
+				if ($final_reg_step->process_reg_step()) {
371
+					$final_reg_step->set_completed();
372
+					EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
373
+					return EED_Single_Page_Checkout::instance()->checkout->transaction;
374
+				}
375
+			}
376
+		}
377
+		return null;
378
+	}
379
+
380
+
381
+
382
+	/**
383
+	 *    run
384
+	 *
385
+	 * @access    public
386
+	 * @param WP_Query $WP_Query
387
+	 * @return    void
388
+	 * @throws \EE_Error
389
+	 */
390
+	public function run($WP_Query)
391
+	{
392
+		if (
393
+			$WP_Query instanceof WP_Query
394
+			&& $WP_Query->is_main_query()
395
+			&& apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
396
+			&& $this->_is_reg_checkout()
397
+		) {
398
+			$this->_initialize();
399
+		}
400
+	}
401
+
402
+
403
+
404
+	/**
405
+	 * determines whether current url matches reg page url
406
+	 *
407
+	 * @return bool
408
+	 */
409
+	protected function _is_reg_checkout()
410
+	{
411
+		// get current permalink for reg page without any extra query args
412
+		$reg_page_url = \get_permalink(EE_Config::instance()->core->reg_page_id);
413
+		// get request URI for current request, but without the scheme or host
414
+		$current_request_uri = \EEH_URL::filter_input_server_url('REQUEST_URI');
415
+		$current_request_uri = html_entity_decode($current_request_uri);
416
+		// get array of query args from the current request URI
417
+		$query_args = \EEH_URL::get_query_string($current_request_uri);
418
+		// grab page id if it is set
419
+		$page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
420
+		// and remove the page id from the query args (we will re-add it later)
421
+		unset($query_args['page_id']);
422
+		// now strip all query args from current request URI
423
+		$current_request_uri = remove_query_arg(array_keys($query_args), $current_request_uri);
424
+		// and re-add the page id if it was set
425
+		if ($page_id) {
426
+			$current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
427
+		}
428
+		// remove slashes and ?
429
+		$current_request_uri = trim($current_request_uri, '?/');
430
+		// is current request URI part of the known full reg page URL ?
431
+		return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
432
+	}
433
+
434
+
435
+
436
+	/**
437
+	 *    run
438
+	 *
439
+	 * @access    public
440
+	 * @param WP_Query $WP_Query
441
+	 * @return    void
442
+	 * @throws \EE_Error
443
+	 */
444
+	public static function init($WP_Query)
445
+	{
446
+		EED_Single_Page_Checkout::instance()->run($WP_Query);
447
+	}
448
+
449
+
450
+
451
+	/**
452
+	 *    _initialize - initial module setup
453
+	 *
454
+	 * @access    private
455
+	 * @throws EE_Error
456
+	 * @return    void
457
+	 */
458
+	private function _initialize()
459
+	{
460
+		// ensure SPCO doesn't run twice
461
+		if (EED_Single_Page_Checkout::$_initialized) {
462
+			return;
463
+		}
464
+		try {
465
+			$this->_verify_session();
466
+			// setup the EE_Checkout object
467
+			$this->checkout = $this->_initialize_checkout();
468
+			// filter checkout
469
+			$this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
470
+			// get the $_GET
471
+			$this->_get_request_vars();
472
+			if ($this->_block_bots()) {
473
+				return;
474
+			}
475
+			// filter continue_reg
476
+			$this->checkout->continue_reg = apply_filters('FHEE__EED_Single_Page_Checkout__init___continue_reg', true, $this->checkout);
477
+			// load the reg steps array
478
+			if ( ! $this->_load_and_instantiate_reg_steps()) {
479
+				EED_Single_Page_Checkout::$_initialized = true;
480
+				return;
481
+			}
482
+			// set the current step
483
+			$this->checkout->set_current_step($this->checkout->step);
484
+			// and the next step
485
+			$this->checkout->set_next_step();
486
+			// verify that everything has been setup correctly
487
+			if ( ! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
488
+				EED_Single_Page_Checkout::$_initialized = true;
489
+				return;
490
+			}
491
+			// lock the transaction
492
+			$this->checkout->transaction->lock();
493
+			// make sure all of our cached objects are added to their respective model entity mappers
494
+			$this->checkout->refresh_all_entities();
495
+			// set amount owing
496
+			$this->checkout->amount_owing = $this->checkout->transaction->remaining();
497
+			// initialize each reg step, which gives them the chance to potentially alter the process
498
+			$this->_initialize_reg_steps();
499
+			// DEBUG LOG
500
+			//$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
501
+			// get reg form
502
+			if( ! $this->_check_form_submission()) {
503
+				EED_Single_Page_Checkout::$_initialized = true;
504
+				return;
505
+			}
506
+			// checkout the action!!!
507
+			$this->_process_form_action();
508
+			// add some style and make it dance
509
+			$this->add_styles_and_scripts();
510
+			// kk... SPCO has successfully run
511
+			EED_Single_Page_Checkout::$_initialized = true;
512
+			// set no cache headers and constants
513
+			EE_System::do_not_cache();
514
+			// add anchor
515
+			add_action('loop_start', array($this, 'set_checkout_anchor'), 1);
516
+			// remove transaction lock
517
+			add_action('shutdown', array($this, 'unlock_transaction'), 1);
518
+		} catch (Exception $e) {
519
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
520
+		}
521
+	}
522
+
523
+
524
+
525
+	/**
526
+	 *    _verify_session
527
+	 * checks that the session is valid and not expired
528
+	 *
529
+	 * @access    private
530
+	 * @throws EE_Error
531
+	 */
532
+	private function _verify_session()
533
+	{
534
+		if ( ! EE_Registry::instance()->SSN instanceof EE_Session) {
535
+			throw new EE_Error(__('The EE_Session class could not be loaded.', 'event_espresso'));
536
+		}
537
+		// is session still valid ?
538
+		if (EE_Registry::instance()->SSN->expired() && EE_Registry::instance()->REQ->get('e_reg_url_link', '') === '') {
539
+			$this->checkout = new EE_Checkout();
540
+			EE_Registry::instance()->SSN->reset_cart();
541
+			EE_Registry::instance()->SSN->reset_checkout();
542
+			EE_Registry::instance()->SSN->reset_transaction();
543
+			EE_Error::add_attention(EE_Registry::$i18n_js_strings['registration_expiration_notice'], __FILE__,
544
+				__FUNCTION__, __LINE__);
545
+			EE_Registry::instance()->SSN->reset_expired();
546
+		}
547
+	}
548
+
549
+
550
+
551
+	/**
552
+	 *    _initialize_checkout
553
+	 * loads and instantiates EE_Checkout
554
+	 *
555
+	 * @access    private
556
+	 * @throws EE_Error
557
+	 * @return EE_Checkout
558
+	 */
559
+	private function _initialize_checkout()
560
+	{
561
+		// look in session for existing checkout
562
+		/** @type EE_Checkout $checkout */
563
+		$checkout = EE_Registry::instance()->SSN->checkout();
564
+		// verify
565
+		if ( ! $checkout instanceof EE_Checkout) {
566
+			// instantiate EE_Checkout object for handling the properties of the current checkout process
567
+			$checkout = EE_Registry::instance()->load_file(SPCO_INC_PATH, 'EE_Checkout', 'class', array(), false);
568
+		} else {
569
+			if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
570
+				$this->unlock_transaction();
571
+				wp_safe_redirect($checkout->redirect_url);
572
+				exit();
573
+			}
574
+		}
575
+		$checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
576
+		// verify again
577
+		if ( ! $checkout instanceof EE_Checkout) {
578
+			throw new EE_Error(__('The EE_Checkout class could not be loaded.', 'event_espresso'));
579
+		}
580
+		// reset anything that needs a clean slate for each request
581
+		$checkout->reset_for_current_request();
582
+		return $checkout;
583
+	}
584
+
585
+
586
+
587
+	/**
588
+	 *    _get_request_vars
589
+	 *
590
+	 * @access    private
591
+	 * @return    void
592
+	 * @throws \EE_Error
593
+	 */
594
+	private function _get_request_vars()
595
+	{
596
+		// load classes
597
+		EED_Single_Page_Checkout::load_request_handler();
598
+		//make sure this request is marked as belonging to EE
599
+		EE_Registry::instance()->REQ->set_espresso_page(true);
600
+		// which step is being requested ?
601
+		$this->checkout->step = EE_Registry::instance()->REQ->get('step', $this->_get_first_step());
602
+		// which step is being edited ?
603
+		$this->checkout->edit_step = EE_Registry::instance()->REQ->get('edit_step', '');
604
+		// and what we're doing on the current step
605
+		$this->checkout->action = EE_Registry::instance()->REQ->get('action', 'display_spco_reg_step');
606
+		// timestamp
607
+		$this->checkout->uts = EE_Registry::instance()->REQ->get('uts', 0);
608
+		// returning to edit ?
609
+		$this->checkout->reg_url_link = EE_Registry::instance()->REQ->get('e_reg_url_link', '');
610
+		// or some other kind of revisit ?
611
+		$this->checkout->revisit = filter_var(
612
+			EE_Registry::instance()->REQ->get('revisit', false),
613
+			FILTER_VALIDATE_BOOLEAN
614
+		);
615
+		// and whether or not to generate a reg form for this request
616
+		$this->checkout->generate_reg_form = filter_var(
617
+			EE_Registry::instance()->REQ->get('generate_reg_form', true),
618
+			FILTER_VALIDATE_BOOLEAN
619
+		);
620
+		// and whether or not to process a reg form submission for this request
621
+		$this->checkout->process_form_submission = filter_var(
622
+			EE_Registry::instance()->REQ->get(
623
+				'process_form_submission',
624
+				$this->checkout->action === 'process_reg_step'
625
+			),
626
+			FILTER_VALIDATE_BOOLEAN
627
+		);
628
+		$this->checkout->process_form_submission = filter_var(
629
+			$this->checkout->action !== 'display_spco_reg_step'
630
+				? $this->checkout->process_form_submission
631
+				: false,
632
+			FILTER_VALIDATE_BOOLEAN
633
+		);
634
+		// $this->_display_request_vars();
635
+	}
636
+
637
+
638
+
639
+	/**
640
+	 *  _display_request_vars
641
+	 *
642
+	 * @access    protected
643
+	 * @return    void
644
+	 */
645
+	protected function _display_request_vars()
646
+	{
647
+		if ( ! WP_DEBUG) {
648
+			return;
649
+		}
650
+		EEH_Debug_Tools::printr($_REQUEST, '$_REQUEST', __FILE__, __LINE__);
651
+		EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
652
+		EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
653
+		EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
654
+		EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
655
+		EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
656
+		EEH_Debug_Tools::printr($this->checkout->generate_reg_form, '$this->checkout->generate_reg_form', __FILE__, __LINE__);
657
+		EEH_Debug_Tools::printr($this->checkout->process_form_submission, '$this->checkout->process_form_submission', __FILE__, __LINE__);
658
+	}
659
+
660
+
661
+
662
+	/**
663
+	 * _block_bots
664
+	 * checks that the incoming request has either of the following set:
665
+	 *  a uts (unix timestamp) which indicates that the request was redirected from the Ticket Selector
666
+	 *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
667
+	 * so if you're not coming from the Ticket Selector nor returning for a valid IP...
668
+	 * then where you coming from man?
669
+	 *
670
+	 * @return boolean
671
+	 */
672
+	private function _block_bots()
673
+	{
674
+		$invalid_checkout_access = \EED_Invalid_Checkout_Access::getInvalidCheckoutAccess();
675
+		if ($invalid_checkout_access->checkoutAccessIsInvalid($this->checkout)) {
676
+			return true;
677
+		}
678
+		return false;
679
+	}
680
+
681
+
682
+
683
+	/**
684
+	 *    _get_first_step
685
+	 *  gets slug for first step in $_reg_steps_array
686
+	 *
687
+	 * @access    private
688
+	 * @throws EE_Error
689
+	 * @return    string
690
+	 */
691
+	private function _get_first_step()
692
+	{
693
+		$first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
694
+		return isset($first_step['slug']) ? $first_step['slug'] : 'attendee_information';
695
+	}
696
+
697
+
698
+
699
+	/**
700
+	 *    _load_and_instantiate_reg_steps
701
+	 *  instantiates each reg step based on the loaded reg_steps array
702
+	 *
703
+	 * @access    private
704
+	 * @throws EE_Error
705
+	 * @return    bool
706
+	 */
707
+	private function _load_and_instantiate_reg_steps()
708
+	{
709
+		do_action('AHEE__Single_Page_Checkout___load_and_instantiate_reg_steps__start', $this->checkout);
710
+		// have reg_steps already been instantiated ?
711
+		if (
712
+			empty($this->checkout->reg_steps)
713
+			|| apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
714
+		) {
715
+			// if not, then loop through raw reg steps array
716
+			foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
717
+				if ( ! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
718
+					return false;
719
+				}
720
+			}
721
+			EE_Registry::instance()->CFG->registration->skip_reg_confirmation = true;
722
+			EE_Registry::instance()->CFG->registration->reg_confirmation_last = true;
723
+			// skip the registration_confirmation page ?
724
+			if (EE_Registry::instance()->CFG->registration->skip_reg_confirmation) {
725
+				// just remove it from the reg steps array
726
+				$this->checkout->remove_reg_step('registration_confirmation', false);
727
+			} else if (
728
+				isset($this->checkout->reg_steps['registration_confirmation'])
729
+				&& EE_Registry::instance()->CFG->registration->reg_confirmation_last
730
+			) {
731
+				// set the order to something big like 100
732
+				$this->checkout->set_reg_step_order('registration_confirmation', 100);
733
+			}
734
+			// filter the array for good luck
735
+			$this->checkout->reg_steps = apply_filters(
736
+				'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
737
+				$this->checkout->reg_steps
738
+			);
739
+			// finally re-sort based on the reg step class order properties
740
+			$this->checkout->sort_reg_steps();
741
+		} else {
742
+			foreach ($this->checkout->reg_steps as $reg_step) {
743
+				// set all current step stati to FALSE
744
+				$reg_step->set_is_current_step(false);
745
+			}
746
+		}
747
+		if (empty($this->checkout->reg_steps)) {
748
+			EE_Error::add_error(__('No Reg Steps were loaded..', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
749
+			return false;
750
+		}
751
+		// make reg step details available to JS
752
+		$this->checkout->set_reg_step_JSON_info();
753
+		return true;
754
+	}
755
+
756
+
757
+
758
+	/**
759
+	 *     _load_and_instantiate_reg_step
760
+	 *
761
+	 * @access    private
762
+	 * @param array $reg_step
763
+	 * @param int   $order
764
+	 * @return bool
765
+	 */
766
+	private function _load_and_instantiate_reg_step($reg_step = array(), $order = 0)
767
+	{
768
+		// we need a file_path, class_name, and slug to add a reg step
769
+		if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
770
+			// if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
771
+			if (
772
+				$this->checkout->reg_url_link
773
+				&& $this->checkout->step !== $reg_step['slug']
774
+				&& $reg_step['slug'] !== 'finalize_registration'
775
+				// normally at this point we would NOT load the reg step, but this filter can change that
776
+				&& apply_filters(
777
+					'FHEE__Single_Page_Checkout___load_and_instantiate_reg_step__bypass_reg_step',
778
+					true,
779
+					$reg_step,
780
+					$this->checkout
781
+				)
782
+			) {
783
+				return true;
784
+			}
785
+			// instantiate step class using file path and class name
786
+			$reg_step_obj = EE_Registry::instance()->load_file(
787
+				$reg_step['file_path'],
788
+				$reg_step['class_name'],
789
+				'class',
790
+				$this->checkout,
791
+				false
792
+			);
793
+			// did we gets the goods ?
794
+			if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
795
+				// set reg step order based on config
796
+				$reg_step_obj->set_order($order);
797
+				// add instantiated reg step object to the master reg steps array
798
+				$this->checkout->add_reg_step($reg_step_obj);
799
+			} else {
800
+				EE_Error::add_error(
801
+					__('The current step could not be set.', 'event_espresso'),
802
+					__FILE__, __FUNCTION__, __LINE__
803
+				);
804
+				return false;
805
+			}
806
+		} else {
807
+			if (WP_DEBUG) {
808
+				EE_Error::add_error(
809
+					sprintf(
810
+						__('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', 'event_espresso'),
811
+						isset($reg_step['file_path']) ? $reg_step['file_path'] : '',
812
+						isset($reg_step['class_name']) ? $reg_step['class_name'] : '',
813
+						isset($reg_step['slug']) ? $reg_step['slug'] : '',
814
+						'<ul>',
815
+						'<li>',
816
+						'</li>',
817
+						'</ul>'
818
+					),
819
+					__FILE__, __FUNCTION__, __LINE__
820
+				);
821
+			}
822
+			return false;
823
+		}
824
+		return true;
825
+	}
826
+
827
+
828
+
829
+	/**
830
+	 * _verify_transaction_and_get_registrations
831
+	 *
832
+	 * @access private
833
+	 * @return bool
834
+	 */
835
+	private function _verify_transaction_and_get_registrations()
836
+	{
837
+		// was there already a valid transaction in the checkout from the session ?
838
+		if ( ! $this->checkout->transaction instanceof EE_Transaction) {
839
+			// get transaction from db or session
840
+			$this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
841
+				? $this->_get_transaction_and_cart_for_previous_visit()
842
+				: $this->_get_cart_for_current_session_and_setup_new_transaction();
843
+			if ( ! $this->checkout->transaction instanceof EE_Transaction) {
844
+				EE_Error::add_error(
845
+					__('Your Registration and Transaction information could not be retrieved from the db.',
846
+						'event_espresso'),
847
+					__FILE__, __FUNCTION__, __LINE__
848
+				);
849
+				$this->checkout->transaction = EE_Transaction::new_instance();
850
+				// add some style and make it dance
851
+				$this->add_styles_and_scripts();
852
+				EED_Single_Page_Checkout::$_initialized = true;
853
+				return false;
854
+			}
855
+			// and the registrations for the transaction
856
+			$this->_get_registrations($this->checkout->transaction);
857
+		}
858
+		return true;
859
+	}
860
+
861
+
862
+
863
+	/**
864
+	 * _get_transaction_and_cart_for_previous_visit
865
+	 *
866
+	 * @access private
867
+	 * @return mixed EE_Transaction|NULL
868
+	 */
869
+	private function _get_transaction_and_cart_for_previous_visit()
870
+	{
871
+		/** @var $TXN_model EEM_Transaction */
872
+		$TXN_model = EE_Registry::instance()->load_model('Transaction');
873
+		// because the reg_url_link is present in the request, this is a return visit to SPCO, so we'll get the transaction data from the db
874
+		$transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
875
+		// verify transaction
876
+		if ($transaction instanceof EE_Transaction) {
877
+			// and get the cart that was used for that transaction
878
+			$this->checkout->cart = $this->_get_cart_for_transaction($transaction);
879
+			return $transaction;
880
+		} else {
881
+			EE_Error::add_error(__('Your Registration and Transaction information could not be retrieved from the db.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
882
+			return null;
883
+		}
884
+	}
885
+
886
+
887
+
888
+	/**
889
+	 * _get_cart_for_transaction
890
+	 *
891
+	 * @access private
892
+	 * @param EE_Transaction $transaction
893
+	 * @return EE_Cart
894
+	 */
895
+	private function _get_cart_for_transaction($transaction)
896
+	{
897
+		return $this->checkout->get_cart_for_transaction($transaction);
898
+	}
899
+
900
+
901
+
902
+	/**
903
+	 * get_cart_for_transaction
904
+	 *
905
+	 * @access public
906
+	 * @param EE_Transaction $transaction
907
+	 * @return EE_Cart
908
+	 */
909
+	public function get_cart_for_transaction(EE_Transaction $transaction)
910
+	{
911
+		return $this->checkout->get_cart_for_transaction($transaction);
912
+	}
913
+
914
+
915
+
916
+	/**
917
+	 * _get_transaction_and_cart_for_current_session
918
+	 *    generates a new EE_Transaction object and adds it to the $_transaction property.
919
+	 *
920
+	 * @access private
921
+	 * @return EE_Transaction
922
+	 * @throws \EE_Error
923
+	 */
924
+	private function _get_cart_for_current_session_and_setup_new_transaction()
925
+	{
926
+		//  if there's no transaction, then this is the FIRST visit to SPCO
927
+		// so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
928
+		$this->checkout->cart = $this->_get_cart_for_transaction(null);
929
+		// and then create a new transaction
930
+		$transaction = $this->_initialize_transaction();
931
+		// verify transaction
932
+		if ($transaction instanceof EE_Transaction) {
933
+			// save it so that we have an ID for other objects to use
934
+			$transaction->save();
935
+			// and save TXN data to the cart
936
+			$this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
937
+		} else {
938
+			EE_Error::add_error(__('A Valid Transaction could not be initialized.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
939
+		}
940
+		return $transaction;
941
+	}
942
+
943
+
944
+
945
+	/**
946
+	 *    generates a new EE_Transaction object and adds it to the $_transaction property.
947
+	 *
948
+	 * @access private
949
+	 * @return mixed EE_Transaction|NULL
950
+	 */
951
+	private function _initialize_transaction()
952
+	{
953
+		try {
954
+			// ensure cart totals have been calculated
955
+			$this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
956
+			// grab the cart grand total
957
+			$cart_total = $this->checkout->cart->get_cart_grand_total();
958
+			// create new TXN
959
+			$transaction = EE_Transaction::new_instance(
960
+				array(
961
+					'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
962
+					'TXN_total'     => $cart_total > 0 ? $cart_total : 0,
963
+					'TXN_paid'      => 0,
964
+					'STS_ID'        => EEM_Transaction::failed_status_code,
965
+				)
966
+			);
967
+			// save it so that we have an ID for other objects to use
968
+			$transaction->save();
969
+			// set cron job for following up on TXNs after their session has expired
970
+			EE_Cron_Tasks::schedule_expired_transaction_check(
971
+				EE_Registry::instance()->SSN->expiration() + 1,
972
+				$transaction->ID()
973
+			);
974
+			return $transaction;
975
+		} catch (Exception $e) {
976
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
977
+		}
978
+		return null;
979
+	}
980
+
981
+
982
+
983
+	/**
984
+	 * _get_registrations
985
+	 *
986
+	 * @access private
987
+	 * @param EE_Transaction $transaction
988
+	 * @return void
989
+	 * @throws \EventEspresso\core\exceptions\InvalidEntityException
990
+	 * @throws \EE_Error
991
+	 */
992
+	private function _get_registrations(EE_Transaction $transaction)
993
+	{
994
+		// first step: grab the registrants  { : o
995
+		$registrations = $transaction->registrations($this->checkout->reg_cache_where_params, true);
996
+		// verify registrations have been set
997
+		if (empty($registrations)) {
998
+			// if no cached registrations, then check the db
999
+			$registrations = $transaction->registrations($this->checkout->reg_cache_where_params, false);
1000
+			// still nothing ? well as long as this isn't a revisit
1001
+			if (empty($registrations) && ! $this->checkout->revisit) {
1002
+				// generate new registrations from scratch
1003
+				$registrations = $this->_initialize_registrations($transaction);
1004
+			}
1005
+		}
1006
+		// sort by their original registration order
1007
+		usort($registrations, array('EED_Single_Page_Checkout', 'sort_registrations_by_REG_count'));
1008
+		// then loop thru the array
1009
+		foreach ($registrations as $registration) {
1010
+			// verify each registration
1011
+			if ($registration instanceof EE_Registration) {
1012
+				// we display all attendee info for the primary registrant
1013
+				if ($this->checkout->reg_url_link === $registration->reg_url_link()
1014
+					&& $registration->is_primary_registrant()
1015
+				) {
1016
+					$this->checkout->primary_revisit = true;
1017
+					break;
1018
+				} else if ($this->checkout->revisit
1019
+						   && $this->checkout->reg_url_link !== $registration->reg_url_link()
1020
+				) {
1021
+					// but hide info if it doesn't belong to you
1022
+					$transaction->clear_cache('Registration', $registration->ID());
1023
+				}
1024
+				$this->checkout->set_reg_status_updated($registration->ID(), false);
1025
+			}
1026
+		}
1027
+	}
1028
+
1029
+
1030
+
1031
+	/**
1032
+	 *    adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1033
+	 *
1034
+	 * @access private
1035
+	 * @param EE_Transaction $transaction
1036
+	 * @return    array
1037
+	 * @throws \EventEspresso\core\exceptions\InvalidEntityException
1038
+	 * @throws \EE_Error
1039
+	 */
1040
+	private function _initialize_registrations(EE_Transaction $transaction)
1041
+	{
1042
+		$att_nmbr = 0;
1043
+		$registrations = array();
1044
+		if ($transaction instanceof EE_Transaction) {
1045
+			/** @type EE_Registration_Processor $registration_processor */
1046
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1047
+			$this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1048
+			// now let's add the cart items to the $transaction
1049
+			foreach ($this->checkout->cart->get_tickets() as $line_item) {
1050
+				//do the following for each ticket of this type they selected
1051
+				for ($x = 1; $x <= $line_item->quantity(); $x++) {
1052
+					$att_nmbr++;
1053
+					/** @var EventEspresso\core\services\commands\registration\CreateRegistrationCommand $CreateRegistrationCommand */
1054
+					$CreateRegistrationCommand = EE_Registry::instance()
1055
+															->create(
1056
+																'EventEspresso\core\services\commands\registration\CreateRegistrationCommand',
1057
+																array(
1058
+																	$transaction,
1059
+																	$line_item,
1060
+																	$att_nmbr,
1061
+																	$this->checkout->total_ticket_count,
1062
+																)
1063
+															);
1064
+					// override capabilities for frontend registrations
1065
+					if ( ! is_admin()) {
1066
+						$CreateRegistrationCommand->setCapCheck(
1067
+							new PublicCapabilities('', 'create_new_registration')
1068
+						);
1069
+					}
1070
+					$registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1071
+					if ( ! $registration instanceof EE_Registration) {
1072
+						throw new InvalidEntityException($registration, 'EE_Registration');
1073
+					}
1074
+					$registrations[ $registration->ID() ] = $registration;
1075
+				}
1076
+			}
1077
+			$registration_processor->fix_reg_final_price_rounding_issue($transaction);
1078
+		}
1079
+		return $registrations;
1080
+	}
1081
+
1082
+
1083
+
1084
+	/**
1085
+	 * sorts registrations by REG_count
1086
+	 *
1087
+	 * @access public
1088
+	 * @param EE_Registration $reg_A
1089
+	 * @param EE_Registration $reg_B
1090
+	 * @return int
1091
+	 */
1092
+	public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B)
1093
+	{
1094
+		// this shouldn't ever happen within the same TXN, but oh well
1095
+		if ($reg_A->count() === $reg_B->count()) {
1096
+			return 0;
1097
+		}
1098
+		return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1099
+	}
1100
+
1101
+
1102
+
1103
+	/**
1104
+	 *    _final_verifications
1105
+	 * just makes sure that everything is set up correctly before proceeding
1106
+	 *
1107
+	 * @access    private
1108
+	 * @return    bool
1109
+	 * @throws \EE_Error
1110
+	 */
1111
+	private function _final_verifications()
1112
+	{
1113
+		// filter checkout
1114
+		$this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___final_verifications__checkout', $this->checkout);
1115
+		//verify that current step is still set correctly
1116
+		if ( ! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1117
+			EE_Error::add_error(
1118
+				__('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'),
1119
+				__FILE__,
1120
+				__FUNCTION__,
1121
+				__LINE__
1122
+			);
1123
+			return false;
1124
+		}
1125
+		// if returning to SPCO, then verify that primary registrant is set
1126
+		if ( ! empty($this->checkout->reg_url_link)) {
1127
+			$valid_registrant = $this->checkout->transaction->primary_registration();
1128
+			if ( ! $valid_registrant instanceof EE_Registration) {
1129
+				EE_Error::add_error(
1130
+					__('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'),
1131
+					__FILE__,
1132
+					__FUNCTION__,
1133
+					__LINE__
1134
+				);
1135
+				return false;
1136
+			}
1137
+			$valid_registrant = null;
1138
+			foreach ($this->checkout->transaction->registrations($this->checkout->reg_cache_where_params) as $registration) {
1139
+				if (
1140
+					$registration instanceof EE_Registration
1141
+					&& $registration->reg_url_link() === $this->checkout->reg_url_link
1142
+				) {
1143
+					$valid_registrant = $registration;
1144
+				}
1145
+			}
1146
+			if ( ! $valid_registrant instanceof EE_Registration) {
1147
+				// hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1148
+				if (EED_Single_Page_Checkout::$_checkout_verified) {
1149
+					// clear the session, mark the checkout as unverified, and try again
1150
+					EE_Registry::instance()->SSN->clear_session();
1151
+					EED_Single_Page_Checkout::$_initialized = false;
1152
+					EED_Single_Page_Checkout::$_checkout_verified = false;
1153
+					$this->_initialize();
1154
+					EE_Error::reset_notices();
1155
+					return false;
1156
+				}
1157
+				EE_Error::add_error(
1158
+					__('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.', 'event_espresso'),
1159
+					__FILE__,
1160
+					__FUNCTION__,
1161
+					__LINE__
1162
+				);
1163
+				return false;
1164
+			}
1165
+		}
1166
+		// now that things have been kinda sufficiently verified,
1167
+		// let's add the checkout to the session so that's available other systems
1168
+		EE_Registry::instance()->SSN->set_checkout($this->checkout);
1169
+		return true;
1170
+	}
1171
+
1172
+
1173
+
1174
+	/**
1175
+	 *    _initialize_reg_steps
1176
+	 * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1177
+	 * then loops thru all of the active reg steps and calls the initialize_reg_step() method
1178
+	 *
1179
+	 * @access    private
1180
+	 * @param bool $reinitializing
1181
+	 * @throws \EE_Error
1182
+	 */
1183
+	private function _initialize_reg_steps($reinitializing = false)
1184
+	{
1185
+		$this->checkout->set_reg_step_initiated($this->checkout->current_step);
1186
+		// loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1187
+		foreach ($this->checkout->reg_steps as $reg_step) {
1188
+			if ( ! $reg_step->initialize_reg_step()) {
1189
+				// if not initialized then maybe this step is being removed...
1190
+				if ( ! $reinitializing && $reg_step->is_current_step()) {
1191
+					// if it was the current step, then we need to start over here
1192
+					$this->_initialize_reg_steps(true);
1193
+					return;
1194
+				}
1195
+				continue;
1196
+			}
1197
+			// add css and JS for current step
1198
+			$reg_step->enqueue_styles_and_scripts();
1199
+			// i18n
1200
+			$reg_step->translate_js_strings();
1201
+			if ($reg_step->is_current_step()) {
1202
+				// the text that appears on the reg step form submit button
1203
+				$reg_step->set_submit_button_text();
1204
+			}
1205
+		}
1206
+		// dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1207
+		do_action("AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}", $this->checkout->current_step);
1208
+	}
1209
+
1210
+
1211
+
1212
+	/**
1213
+	 * _check_form_submission
1214
+	 *
1215
+	 * @access private
1216
+	 * @return boolean
1217
+	 */
1218
+	private function _check_form_submission()
1219
+	{
1220
+		//does this request require the reg form to be generated ?
1221
+		if ($this->checkout->generate_reg_form) {
1222
+			// ever heard that song by Blue Rodeo ?
1223
+			try {
1224
+				$this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1225
+				// if not displaying a form, then check for form submission
1226
+				if (
1227
+					$this->checkout->process_form_submission
1228
+					&& $this->checkout->current_step->reg_form->was_submitted()
1229
+				) {
1230
+					// clear out any old data in case this step is being run again
1231
+					$this->checkout->current_step->set_valid_data(array());
1232
+					// capture submitted form data
1233
+					$this->checkout->current_step->reg_form->receive_form_submission(
1234
+						apply_filters('FHEE__Single_Page_Checkout___check_form_submission__request_params', EE_Registry::instance()->REQ->params(), $this->checkout)
1235
+					);
1236
+					// validate submitted form data
1237
+					if ( ! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1238
+						// thou shall not pass !!!
1239
+						$this->checkout->continue_reg = false;
1240
+						// any form validation errors?
1241
+						if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1242
+							$submission_error_messages = array();
1243
+							// bad, bad, bad registrant
1244
+							foreach ($this->checkout->current_step->reg_form->get_validation_errors_accumulated() as $validation_error) {
1245
+								if ($validation_error instanceof EE_Validation_Error) {
1246
+									$submission_error_messages[] = sprintf(
1247
+										__('%s : %s', 'event_espresso'),
1248
+										$validation_error->get_form_section()->html_label_text(),
1249
+										$validation_error->getMessage()
1250
+									);
1251
+								}
1252
+							}
1253
+							EE_Error::add_error(implode('<br />', $submission_error_messages), __FILE__, __FUNCTION__, __LINE__);
1254
+						}
1255
+						// well not really... what will happen is we'll just get redirected back to redo the current step
1256
+						$this->go_to_next_step();
1257
+						return false;
1258
+					}
1259
+				}
1260
+			} catch (EE_Error $e) {
1261
+				$e->get_error();
1262
+			}
1263
+		}
1264
+		return true;
1265
+	}
1266
+
1267
+
1268
+
1269
+	/**
1270
+	 * _process_action
1271
+	 *
1272
+	 * @access private
1273
+	 * @return void
1274
+	 * @throws \EE_Error
1275
+	 */
1276
+	private function _process_form_action()
1277
+	{
1278
+		// what cha wanna do?
1279
+		switch ($this->checkout->action) {
1280
+			// AJAX next step reg form
1281
+			case 'display_spco_reg_step' :
1282
+				$this->checkout->redirect = false;
1283
+				if (EE_Registry::instance()->REQ->ajax) {
1284
+					$this->checkout->json_response->set_reg_step_html($this->checkout->current_step->display_reg_form());
1285
+				}
1286
+				break;
1287
+			default :
1288
+				// meh... do one of those other steps first
1289
+				if ( ! empty($this->checkout->action) && is_callable(array($this->checkout->current_step, $this->checkout->action))) {
1290
+					// dynamically creates hook point like: AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1291
+					do_action("AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}", $this->checkout->current_step);
1292
+					// call action on current step
1293
+					if (call_user_func(array($this->checkout->current_step, $this->checkout->action))) {
1294
+						// good registrant, you get to proceed
1295
+						if (
1296
+							$this->checkout->current_step->success_message() !== ''
1297
+							&& apply_filters(
1298
+								'FHEE__Single_Page_Checkout___process_form_action__display_success',
1299
+								false
1300
+							)
1301
+						) {
1302
+							EE_Error::add_success(
1303
+								$this->checkout->current_step->success_message()
1304
+								. '<br />' . $this->checkout->next_step->_instructions()
1305
+							);
1306
+						}
1307
+						// pack it up, pack it in...
1308
+						$this->_setup_redirect();
1309
+					}
1310
+					// dynamically creates hook point like: AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1311
+					do_action("AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}", $this->checkout->current_step);
1312
+				} else {
1313
+					EE_Error::add_error(
1314
+						sprintf(
1315
+							__('The requested form action "%s" does not exist for the current "%s" registration step.', 'event_espresso'),
1316
+							$this->checkout->action,
1317
+							$this->checkout->current_step->name()
1318
+						),
1319
+						__FILE__,
1320
+						__FUNCTION__,
1321
+						__LINE__
1322
+					);
1323
+				}
1324
+			// end default
1325
+		}
1326
+		// store our progress so far
1327
+		$this->checkout->stash_transaction_and_checkout();
1328
+		// advance to the next step! If you pass GO, collect $200
1329
+		$this->go_to_next_step();
1330
+	}
1331
+
1332
+
1333
+
1334
+	/**
1335
+	 *        add_styles_and_scripts
1336
+	 *
1337
+	 * @access        public
1338
+	 * @return        void
1339
+	 */
1340
+	public function add_styles_and_scripts()
1341
+	{
1342
+		// i18n
1343
+		$this->translate_js_strings();
1344
+		if ($this->checkout->admin_request) {
1345
+			add_action('admin_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1346
+		} else {
1347
+			add_action('wp_enqueue_scripts', array($this, 'enqueue_styles_and_scripts'), 10);
1348
+		}
1349
+	}
1350
+
1351
+
1352
+
1353
+	/**
1354
+	 *        translate_js_strings
1355
+	 *
1356
+	 * @access        public
1357
+	 * @return        void
1358
+	 */
1359
+	public function translate_js_strings()
1360
+	{
1361
+		EE_Registry::$i18n_js_strings['revisit'] = $this->checkout->revisit;
1362
+		EE_Registry::$i18n_js_strings['e_reg_url_link'] = $this->checkout->reg_url_link;
1363
+		EE_Registry::$i18n_js_strings['server_error'] = __('An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.', 'event_espresso');
1364
+		EE_Registry::$i18n_js_strings['invalid_json_response'] = __('An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.', 'event_espresso');
1365
+		EE_Registry::$i18n_js_strings['validation_error'] = __('There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.', 'event_espresso');
1366
+		EE_Registry::$i18n_js_strings['invalid_payment_method'] = __('There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.', 'event_espresso');
1367
+		EE_Registry::$i18n_js_strings['reg_step_error'] = __('This registration step could not be completed. Please refresh the page and try again.', 'event_espresso');
1368
+		EE_Registry::$i18n_js_strings['invalid_coupon'] = __('We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.', 'event_espresso');
1369
+		EE_Registry::$i18n_js_strings['process_registration'] = sprintf(
1370
+			__('Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.', 'event_espresso'),
1371
+			'<br/>',
1372
+			'<br/>'
1373
+		);
1374
+		EE_Registry::$i18n_js_strings['language'] = get_bloginfo('language');
1375
+		EE_Registry::$i18n_js_strings['EESID'] = EE_Registry::instance()->SSN->id();
1376
+		EE_Registry::$i18n_js_strings['currency'] = EE_Registry::instance()->CFG->currency;
1377
+		EE_Registry::$i18n_js_strings['datepicker_yearRange'] = '-150:+20';
1378
+		EE_Registry::$i18n_js_strings['timer_years'] = __('years', 'event_espresso');
1379
+		EE_Registry::$i18n_js_strings['timer_months'] = __('months', 'event_espresso');
1380
+		EE_Registry::$i18n_js_strings['timer_weeks'] = __('weeks', 'event_espresso');
1381
+		EE_Registry::$i18n_js_strings['timer_days'] = __('days', 'event_espresso');
1382
+		EE_Registry::$i18n_js_strings['timer_hours'] = __('hours', 'event_espresso');
1383
+		EE_Registry::$i18n_js_strings['timer_minutes'] = __('minutes', 'event_espresso');
1384
+		EE_Registry::$i18n_js_strings['timer_seconds'] = __('seconds', 'event_espresso');
1385
+		EE_Registry::$i18n_js_strings['timer_year'] = __('year', 'event_espresso');
1386
+		EE_Registry::$i18n_js_strings['timer_month'] = __('month', 'event_espresso');
1387
+		EE_Registry::$i18n_js_strings['timer_week'] = __('week', 'event_espresso');
1388
+		EE_Registry::$i18n_js_strings['timer_day'] = __('day', 'event_espresso');
1389
+		EE_Registry::$i18n_js_strings['timer_hour'] = __('hour', 'event_espresso');
1390
+		EE_Registry::$i18n_js_strings['timer_minute'] = __('minute', 'event_espresso');
1391
+		EE_Registry::$i18n_js_strings['timer_second'] = __('second', 'event_espresso');
1392
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] = sprintf(
1393
+			__(
1394
+				'%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 except our apologies for any inconvenience this may have caused.%8$s',
1395
+				'event_espresso'
1396
+			),
1397
+			'<h4 class="important-notice">',
1398
+			'</h4>',
1399
+			'<br />',
1400
+			'<p>',
1401
+			'<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1402
+			'">',
1403
+			'</a>',
1404
+			'</p>'
1405
+		);
1406
+		EE_Registry::$i18n_js_strings['ajax_submit'] = apply_filters('FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit', true);
1407
+		EE_Registry::$i18n_js_strings['session_extension'] = absint(
1408
+			apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1409
+		);
1410
+		EE_Registry::$i18n_js_strings['session_expiration'] = gmdate(
1411
+			'M d, Y H:i:s', EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1412
+		);
1413
+	}
1414
+
1415
+
1416
+
1417
+	/**
1418
+	 *    enqueue_styles_and_scripts
1419
+	 *
1420
+	 * @access        public
1421
+	 * @return        void
1422
+	 * @throws \EE_Error
1423
+	 */
1424
+	public function enqueue_styles_and_scripts()
1425
+	{
1426
+		// load css
1427
+		wp_register_style('single_page_checkout', SPCO_CSS_URL . 'single_page_checkout.css', array(), EVENT_ESPRESSO_VERSION);
1428
+		wp_enqueue_style('single_page_checkout');
1429
+		// load JS
1430
+		wp_register_script('jquery_plugin', EE_THIRD_PARTY_URL . 'jquery	.plugin.min.js', array('jquery'), '1.0.1', true);
1431
+		wp_register_script('jquery_countdown', EE_THIRD_PARTY_URL . 'jquery	.countdown.min.js', array('jquery_plugin'), '2.0.2', true);
1432
+		wp_register_script('single_page_checkout', SPCO_JS_URL . 'single_page_checkout.js', array('espresso_core', 'underscore', 'ee_form_section_validation', 'jquery_countdown'), EVENT_ESPRESSO_VERSION, true);
1433
+		if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1434
+			$this->checkout->registration_form->enqueue_js();
1435
+		}
1436
+		if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1437
+			$this->checkout->current_step->reg_form->enqueue_js();
1438
+		}
1439
+		wp_enqueue_script('single_page_checkout');
1440
+		/**
1441
+		 * global action hook for enqueueing styles and scripts with
1442
+		 * spco calls.
1443
+		 */
1444
+		do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1445
+		/**
1446
+		 * dynamic action hook for enqueueing styles and scripts with spco calls.
1447
+		 * The hook will end up being something like AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1448
+		 */
1449
+		do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(), $this);
1450
+	}
1451
+
1452
+
1453
+
1454
+	/**
1455
+	 *    display the Registration Single Page Checkout Form
1456
+	 *
1457
+	 * @access    private
1458
+	 * @return    void
1459
+	 * @throws \EE_Error
1460
+	 */
1461
+	private function _display_spco_reg_form()
1462
+	{
1463
+		// if registering via the admin, just display the reg form for the current step
1464
+		if ($this->checkout->admin_request) {
1465
+			EE_Registry::instance()->REQ->add_output($this->checkout->current_step->display_reg_form());
1466
+		} else {
1467
+			// add powered by EE msg
1468
+			add_action('AHEE__SPCO__reg_form_footer', array('EED_Single_Page_Checkout', 'display_registration_footer'));
1469
+			$empty_cart = count($this->checkout->transaction->registrations($this->checkout->reg_cache_where_params)) < 1
1470
+				? true
1471
+				: false;
1472
+			EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1473
+			$cookies_not_set_msg = '';
1474
+			if ($empty_cart && ! isset($_COOKIE['ee_cookie_test'])) {
1475
+				$cookies_not_set_msg = apply_filters(
1476
+					'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
1477
+					sprintf(
1478
+						__(
1479
+							'%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',
1480
+							'event_espresso'
1481
+						),
1482
+						'<div class="ee-attention">',
1483
+						'</div>',
1484
+						'<h6 class="important-notice">',
1485
+						'</h6>',
1486
+						'<p>',
1487
+						'</p>',
1488
+						'<br />',
1489
+						'<a href="http://www.whatarecookies.com/enable.asp" target="_blank">',
1490
+						'</a>'
1491
+					)
1492
+				);
1493
+			}
1494
+			$this->checkout->registration_form = new EE_Form_Section_Proper(
1495
+				array(
1496
+					'name'            => 'single-page-checkout',
1497
+					'html_id'         => 'ee-single-page-checkout-dv',
1498
+					'layout_strategy' =>
1499
+						new EE_Template_Layout(
1500
+							array(
1501
+								'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
1502
+								'template_args'        => array(
1503
+									'empty_cart'              => $empty_cart,
1504
+									'revisit'                 => $this->checkout->revisit,
1505
+									'reg_steps'               => $this->checkout->reg_steps,
1506
+									'next_step'               => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
1507
+										? $this->checkout->next_step->slug()
1508
+										: '',
1509
+									'cancel_page_url'         => $this->checkout->cancel_page_url,
1510
+									'empty_msg'               => apply_filters(
1511
+										'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
1512
+										sprintf(
1513
+											__('You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
1514
+												'event_espresso'),
1515
+											'<a href="' . get_post_type_archive_link('espresso_events') . '" title="',
1516
+											'">',
1517
+											'</a>'
1518
+										)
1519
+									),
1520
+									'cookies_not_set_msg'     => $cookies_not_set_msg,
1521
+									'registration_time_limit' => $this->checkout->get_registration_time_limit(),
1522
+									'session_expiration'      =>
1523
+										date('M d, Y H:i:s', EE_Registry::instance()->SSN->expiration() + (get_option('gmt_offset') * HOUR_IN_SECONDS)),
1524
+								),
1525
+							)
1526
+						),
1527
+				)
1528
+			);
1529
+			// load template and add to output sent that gets filtered into the_content()
1530
+			EE_Registry::instance()->REQ->add_output($this->checkout->registration_form->get_html());
1531
+		}
1532
+	}
1533
+
1534
+
1535
+
1536
+	/**
1537
+	 *    add_extra_finalize_registration_inputs
1538
+	 *
1539
+	 * @access    public
1540
+	 * @param $next_step
1541
+	 * @internal  param string $label
1542
+	 * @return void
1543
+	 */
1544
+	public function add_extra_finalize_registration_inputs($next_step)
1545
+	{
1546
+		if ($next_step === 'finalize_registration') {
1547
+			echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1548
+		}
1549
+	}
1550
+
1551
+
1552
+
1553
+	/**
1554
+	 *    display_registration_footer
1555
+	 *
1556
+	 * @access    public
1557
+	 * @return    string
1558
+	 */
1559
+	public static function display_registration_footer()
1560
+	{
1561
+		if (
1562
+		apply_filters(
1563
+			'FHEE__EE_Front__Controller__show_reg_footer',
1564
+			EE_Registry::instance()->CFG->admin->show_reg_footer
1565
+		)
1566
+		) {
1567
+			add_filter(
1568
+				'FHEE__EEH_Template__powered_by_event_espresso__url',
1569
+				function ($url) {
1570
+					return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1571
+				}
1572
+			);
1573
+			echo apply_filters(
1574
+				'FHEE__EE_Front_Controller__display_registration_footer',
1575
+				\EEH_Template::powered_by_event_espresso(
1576
+					'',
1577
+					'espresso-registration-footer-dv',
1578
+					array('utm_content' => 'registration_checkout')
1579
+				)
1580
+			);
1581
+		}
1582
+		return '';
1583
+	}
1584
+
1585
+
1586
+
1587
+	/**
1588
+	 *    unlock_transaction
1589
+	 *
1590
+	 * @access    public
1591
+	 * @return    void
1592
+	 * @throws \EE_Error
1593
+	 */
1594
+	public function unlock_transaction()
1595
+	{
1596
+		if ($this->checkout->transaction instanceof EE_Transaction) {
1597
+			$this->checkout->transaction->unlock();
1598
+		}
1599
+	}
1600
+
1601
+
1602
+
1603
+	/**
1604
+	 *        _setup_redirect
1605
+	 *
1606
+	 * @access    private
1607
+	 * @return void
1608
+	 */
1609
+	private function _setup_redirect()
1610
+	{
1611
+		if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1612
+			$this->checkout->redirect = true;
1613
+			if (empty($this->checkout->redirect_url)) {
1614
+				$this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1615
+			}
1616
+			$this->checkout->redirect_url = apply_filters(
1617
+				'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1618
+				$this->checkout->redirect_url,
1619
+				$this->checkout
1620
+			);
1621
+		}
1622
+	}
1623
+
1624
+
1625
+
1626
+	/**
1627
+	 *   handle ajax message responses and redirects
1628
+	 *
1629
+	 * @access public
1630
+	 * @return void
1631
+	 * @throws \EE_Error
1632
+	 */
1633
+	public function go_to_next_step()
1634
+	{
1635
+		if (EE_Registry::instance()->REQ->ajax) {
1636
+			// capture contents of output buffer we started earlier in the request, and insert into JSON response
1637
+			$this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1638
+		}
1639
+		$this->unlock_transaction();
1640
+		// just return for these conditions
1641
+		if (
1642
+			$this->checkout->admin_request
1643
+			|| $this->checkout->action === 'redirect_form'
1644
+			|| $this->checkout->action === 'update_checkout'
1645
+		) {
1646
+			return;
1647
+		}
1648
+		// AJAX response
1649
+		$this->_handle_json_response();
1650
+		// redirect to next step or the Thank You page
1651
+		$this->_handle_html_redirects();
1652
+		// hmmm... must be something wrong, so let's just display the form again !
1653
+		$this->_display_spco_reg_form();
1654
+	}
1655
+
1656
+
1657
+
1658
+	/**
1659
+	 *   _handle_json_response
1660
+	 *
1661
+	 * @access protected
1662
+	 * @return void
1663
+	 */
1664
+	protected function _handle_json_response()
1665
+	{
1666
+		// if this is an ajax request
1667
+		if (EE_Registry::instance()->REQ->ajax) {
1668
+			// DEBUG LOG
1669
+			//$this->checkout->log(
1670
+			//	__CLASS__, __FUNCTION__, __LINE__,
1671
+			//	array(
1672
+			//		'json_response_redirect_url' => $this->checkout->json_response->redirect_url(),
1673
+			//		'redirect'                   => $this->checkout->redirect,
1674
+			//		'continue_reg'               => $this->checkout->continue_reg,
1675
+			//	)
1676
+			//);
1677
+			$this->checkout->json_response->set_registration_time_limit(
1678
+				$this->checkout->get_registration_time_limit()
1679
+			);
1680
+			$this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1681
+			// just send the ajax (
1682
+			$json_response = apply_filters(
1683
+				'FHEE__EE_Single_Page_Checkout__JSON_response',
1684
+				$this->checkout->json_response
1685
+			);
1686
+			echo $json_response;
1687
+			exit();
1688
+		}
1689
+	}
1690
+
1691
+
1692
+
1693
+	/**
1694
+	 *   _handle_redirects
1695
+	 *
1696
+	 * @access protected
1697
+	 * @return void
1698
+	 */
1699
+	protected function _handle_html_redirects()
1700
+	{
1701
+		// going somewhere ?
1702
+		if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1703
+			// store notices in a transient
1704
+			EE_Error::get_notices(false, true, true);
1705
+			// DEBUG LOG
1706
+			//$this->checkout->log(
1707
+			//	__CLASS__, __FUNCTION__, __LINE__,
1708
+			//	array(
1709
+			//		'headers_sent' => headers_sent(),
1710
+			//		'redirect_url'     => $this->checkout->redirect_url,
1711
+			//		'headers_list'    => headers_list(),
1712
+			//	)
1713
+			//);
1714
+			wp_safe_redirect($this->checkout->redirect_url);
1715
+			exit();
1716
+		}
1717
+	}
1718
+
1719
+
1720
+
1721
+	/**
1722
+	 *   set_checkout_anchor
1723
+	 *
1724
+	 * @access public
1725
+	 * @return void
1726
+	 */
1727
+	public function set_checkout_anchor()
1728
+	{
1729
+		echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1730
+	}
1731 1731
 
1732 1732
 
1733 1733
 
Please login to merge, or discard this patch.
modules/single_page_checkout/inc/EE_SPCO_Reg_Step.class.php 2 patches
Indentation   +616 added lines, -616 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,659 +16,659 @@  discard block
 block discarded – undo
16 16
 abstract class EE_SPCO_Reg_Step
17 17
 {
18 18
 
19
-    /**
20
-     *    $_completed - TRUE if this step has fully completed it's duties
21
-     *
22
-     * @access protected
23
-     * @type bool $_completed
24
-     */
25
-    protected $_completed = false;
26
-
27
-    /**
28
-     *    $_is_current_step - TRUE if this is the current step
29
-     *
30
-     * @access protected
31
-     * @type bool $_is_current_step
32
-     */
33
-    protected $_is_current_step = false;
34
-
35
-    /**
36
-     *    $_order - when the reg step should be run relative to other steps
37
-     *
38
-     * @access protected
39
-     * @type int $_template
40
-     */
41
-    protected $_order = 0;
42
-
43
-    /**
44
-     *    $_slug - URL param for this step
45
-     *
46
-     * @access protected
47
-     * @type string $_slug
48
-     */
49
-    protected $_slug;
50
-
51
-    /**
52
-     *    $_name - Step Name - translatable string
53
-     *
54
-     * @access protected
55
-     * @type string $_slug
56
-     */
57
-    protected $_name;
58
-
59
-    /**
60
-     *    $_submit_button_text - translatable string that appears on this step's submit button
61
-     *
62
-     * @access protected
63
-     * @type string $_slug
64
-     */
65
-    protected $_submit_button_text;
66
-
67
-    /**
68
-     *    $_template - template name
69
-     *
70
-     * @access protected
71
-     * @type string $_template
72
-     */
73
-    protected $_template;
74
-
75
-    /**
76
-     *    $_reg_form_name - the form input name and id attribute
77
-     *
78
-     * @access protected
79
-     * @var string $_reg_form_name
80
-     */
81
-    protected $_reg_form_name;
82
-
83
-    /**
84
-     *    $_success_message - text to display upon successful form submission
85
-     *
86
-     * @access private
87
-     * @var string $_success_message
88
-     */
89
-    protected $_success_message;
90
-
91
-    /**
92
-     *    $_instructions - a brief description of how to complete the reg step. Usually displayed in conjunction with
93
-     *    the previous step's success message.
94
-     *
95
-     * @access private
96
-     * @var string $_instructions
97
-     */
98
-    protected $_instructions;
99
-
100
-    /**
101
-     *    $_valid_data - the normalized and validated data for this step
102
-     *
103
-     * @access public
104
-     * @var array $_valid_data
105
-     */
106
-    protected $_valid_data = array();
107
-
108
-    /**
109
-     *    $reg_form - the registration form for this step
110
-     *
111
-     * @access public
112
-     * @var EE_Form_Section_Proper $reg_form
113
-     */
114
-    public $reg_form;
115
-
116
-    /**
117
-     *    $checkout - EE_Checkout object for handling the properties of the current checkout process
118
-     *
119
-     * @access public
120
-     * @var EE_Checkout $checkout
121
-     */
122
-    public $checkout;
123
-
124
-
125
-
126
-    /**
127
-     * @return void
128
-     */
129
-    abstract public function translate_js_strings();
130
-
131
-
19
+	/**
20
+	 *    $_completed - TRUE if this step has fully completed it's duties
21
+	 *
22
+	 * @access protected
23
+	 * @type bool $_completed
24
+	 */
25
+	protected $_completed = false;
26
+
27
+	/**
28
+	 *    $_is_current_step - TRUE if this is the current step
29
+	 *
30
+	 * @access protected
31
+	 * @type bool $_is_current_step
32
+	 */
33
+	protected $_is_current_step = false;
34
+
35
+	/**
36
+	 *    $_order - when the reg step should be run relative to other steps
37
+	 *
38
+	 * @access protected
39
+	 * @type int $_template
40
+	 */
41
+	protected $_order = 0;
42
+
43
+	/**
44
+	 *    $_slug - URL param for this step
45
+	 *
46
+	 * @access protected
47
+	 * @type string $_slug
48
+	 */
49
+	protected $_slug;
50
+
51
+	/**
52
+	 *    $_name - Step Name - translatable string
53
+	 *
54
+	 * @access protected
55
+	 * @type string $_slug
56
+	 */
57
+	protected $_name;
58
+
59
+	/**
60
+	 *    $_submit_button_text - translatable string that appears on this step's submit button
61
+	 *
62
+	 * @access protected
63
+	 * @type string $_slug
64
+	 */
65
+	protected $_submit_button_text;
66
+
67
+	/**
68
+	 *    $_template - template name
69
+	 *
70
+	 * @access protected
71
+	 * @type string $_template
72
+	 */
73
+	protected $_template;
74
+
75
+	/**
76
+	 *    $_reg_form_name - the form input name and id attribute
77
+	 *
78
+	 * @access protected
79
+	 * @var string $_reg_form_name
80
+	 */
81
+	protected $_reg_form_name;
82
+
83
+	/**
84
+	 *    $_success_message - text to display upon successful form submission
85
+	 *
86
+	 * @access private
87
+	 * @var string $_success_message
88
+	 */
89
+	protected $_success_message;
90
+
91
+	/**
92
+	 *    $_instructions - a brief description of how to complete the reg step. Usually displayed in conjunction with
93
+	 *    the previous step's success message.
94
+	 *
95
+	 * @access private
96
+	 * @var string $_instructions
97
+	 */
98
+	protected $_instructions;
99
+
100
+	/**
101
+	 *    $_valid_data - the normalized and validated data for this step
102
+	 *
103
+	 * @access public
104
+	 * @var array $_valid_data
105
+	 */
106
+	protected $_valid_data = array();
107
+
108
+	/**
109
+	 *    $reg_form - the registration form for this step
110
+	 *
111
+	 * @access public
112
+	 * @var EE_Form_Section_Proper $reg_form
113
+	 */
114
+	public $reg_form;
115
+
116
+	/**
117
+	 *    $checkout - EE_Checkout object for handling the properties of the current checkout process
118
+	 *
119
+	 * @access public
120
+	 * @var EE_Checkout $checkout
121
+	 */
122
+	public $checkout;
123
+
124
+
125
+
126
+	/**
127
+	 * @return void
128
+	 */
129
+	abstract public function translate_js_strings();
130
+
131
+
132 132
 
133
-    /**
134
-     * @return void
135
-     */
136
-    abstract public function enqueue_styles_and_scripts();
137
-
138
-
139
-
140
-    /**
141
-     * @return boolean
142
-     */
143
-    abstract public function initialize_reg_step();
144
-
145
-
146
-
147
-    /**
148
-     * @return string
149
-     */
150
-    abstract public function generate_reg_form();
151
-
152
-
153
-
154
-    /**
155
-     * @return boolean
156
-     */
157
-    abstract public function process_reg_step();
158
-
159
-
160
-
161
-    /**
162
-     * @return boolean
163
-     */
164
-    abstract public function update_reg_step();
165
-
166
-
167
-
168
-    /**
169
-     * @return boolean
170
-     */
171
-    public function completed()
172
-    {
173
-        return $this->_completed;
174
-    }
133
+	/**
134
+	 * @return void
135
+	 */
136
+	abstract public function enqueue_styles_and_scripts();
137
+
138
+
139
+
140
+	/**
141
+	 * @return boolean
142
+	 */
143
+	abstract public function initialize_reg_step();
144
+
145
+
146
+
147
+	/**
148
+	 * @return string
149
+	 */
150
+	abstract public function generate_reg_form();
151
+
152
+
153
+
154
+	/**
155
+	 * @return boolean
156
+	 */
157
+	abstract public function process_reg_step();
158
+
159
+
160
+
161
+	/**
162
+	 * @return boolean
163
+	 */
164
+	abstract public function update_reg_step();
165
+
166
+
167
+
168
+	/**
169
+	 * @return boolean
170
+	 */
171
+	public function completed()
172
+	{
173
+		return $this->_completed;
174
+	}
175 175
 
176 176
 
177 177
 
178
-    /**
179
-     * set_completed - toggles $_completed to TRUE
180
-     */
181
-    public function set_completed()
182
-    {
183
-        // DEBUG LOG
184
-        //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
185
-        $this->_completed = apply_filters('FHEE__EE_SPCO_Reg_Step__set_completed___completed', true, $this);
186
-    }
178
+	/**
179
+	 * set_completed - toggles $_completed to TRUE
180
+	 */
181
+	public function set_completed()
182
+	{
183
+		// DEBUG LOG
184
+		//$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
185
+		$this->_completed = apply_filters('FHEE__EE_SPCO_Reg_Step__set_completed___completed', true, $this);
186
+	}
187 187
 
188 188
 
189 189
 
190
-    /**
191
-     * set_completed - toggles $_completed to FALSE
192
-     */
193
-    public function set_not_completed()
194
-    {
195
-        $this->_completed = false;
196
-    }
190
+	/**
191
+	 * set_completed - toggles $_completed to FALSE
192
+	 */
193
+	public function set_not_completed()
194
+	{
195
+		$this->_completed = false;
196
+	}
197 197
 
198 198
 
199 199
 
200
-    /**
201
-     * @return string
202
-     */
203
-    public function name()
204
-    {
205
-        return $this->_name;
206
-    }
200
+	/**
201
+	 * @return string
202
+	 */
203
+	public function name()
204
+	{
205
+		return $this->_name;
206
+	}
207 207
 
208 208
 
209 209
 
210
-    /**
211
-     * @return string
212
-     */
213
-    public function slug()
214
-    {
215
-        return $this->_slug;
216
-    }
210
+	/**
211
+	 * @return string
212
+	 */
213
+	public function slug()
214
+	{
215
+		return $this->_slug;
216
+	}
217 217
 
218 218
 
219 219
 
220
-    /**
221
-     * submit_button_text
222
-     * the text that appears on the reg step form submit button
223
-     *
224
-     * @return string
225
-     */
226
-    public function submit_button_text()
227
-    {
228
-        return $this->_submit_button_text;
229
-    }
220
+	/**
221
+	 * submit_button_text
222
+	 * the text that appears on the reg step form submit button
223
+	 *
224
+	 * @return string
225
+	 */
226
+	public function submit_button_text()
227
+	{
228
+		return $this->_submit_button_text;
229
+	}
230 230
 
231 231
 
232 232
 
233
-    /**
234
-     * set_submit_button_text
235
-     * sets the text that appears on the reg step form submit button
236
-     *
237
-     * @param string $submit_button_text
238
-     */
239
-    public function set_submit_button_text($submit_button_text = '')
240
-    {
241
-        if (! empty($submit_button_text)) {
242
-            $this->_submit_button_text = $submit_button_text;
243
-        } else if ($this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
244
-            if ($this->checkout->revisit) {
245
-                $this->_submit_button_text = sprintf(__('Update %s', 'event_espresso'),
246
-                    $this->checkout->current_step->name());
247
-            } else {
248
-                $this->_submit_button_text = sprintf(__('Proceed to %s', 'event_espresso'),
249
-                    $this->checkout->next_step->name());
250
-            }
251
-        }
252
-        // filters the submit button text
253
-        $this->_submit_button_text = apply_filters(
254
-            'FHEE__EE_SPCO_Reg_Step__set_submit_button_text___submit_button_text',
255
-            $this->_submit_button_text,
256
-            $this->checkout
257
-        );
258
-    }
233
+	/**
234
+	 * set_submit_button_text
235
+	 * sets the text that appears on the reg step form submit button
236
+	 *
237
+	 * @param string $submit_button_text
238
+	 */
239
+	public function set_submit_button_text($submit_button_text = '')
240
+	{
241
+		if (! empty($submit_button_text)) {
242
+			$this->_submit_button_text = $submit_button_text;
243
+		} else if ($this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
244
+			if ($this->checkout->revisit) {
245
+				$this->_submit_button_text = sprintf(__('Update %s', 'event_espresso'),
246
+					$this->checkout->current_step->name());
247
+			} else {
248
+				$this->_submit_button_text = sprintf(__('Proceed to %s', 'event_espresso'),
249
+					$this->checkout->next_step->name());
250
+			}
251
+		}
252
+		// filters the submit button text
253
+		$this->_submit_button_text = apply_filters(
254
+			'FHEE__EE_SPCO_Reg_Step__set_submit_button_text___submit_button_text',
255
+			$this->_submit_button_text,
256
+			$this->checkout
257
+		);
258
+	}
259 259
 
260 260
 
261 261
 
262
-    /**
263
-     * @param boolean $is_current_step
264
-     */
265
-    public function set_is_current_step($is_current_step)
266
-    {
267
-        $this->_is_current_step = $is_current_step;
268
-    }
262
+	/**
263
+	 * @param boolean $is_current_step
264
+	 */
265
+	public function set_is_current_step($is_current_step)
266
+	{
267
+		$this->_is_current_step = $is_current_step;
268
+	}
269 269
 
270 270
 
271 271
 
272
-    /**
273
-     * @return boolean
274
-     */
275
-    public function is_current_step()
276
-    {
277
-        return $this->_is_current_step;
278
-    }
272
+	/**
273
+	 * @return boolean
274
+	 */
275
+	public function is_current_step()
276
+	{
277
+		return $this->_is_current_step;
278
+	}
279 279
 
280 280
 
281 281
 
282
-    /**
283
-     * @return boolean
284
-     */
285
-    public function is_final_step()
286
-    {
287
-        return $this instanceof EE_SPCO_Reg_Step_Finalize_Registration ? true : false;
288
-    }
282
+	/**
283
+	 * @return boolean
284
+	 */
285
+	public function is_final_step()
286
+	{
287
+		return $this instanceof EE_SPCO_Reg_Step_Finalize_Registration ? true : false;
288
+	}
289 289
 
290 290
 
291 291
 
292
-    /**
293
-     * @param int $order
294
-     */
295
-    public function set_order($order)
296
-    {
297
-        $this->_order = $order;
298
-    }
299
-
300
-
292
+	/**
293
+	 * @param int $order
294
+	 */
295
+	public function set_order($order)
296
+	{
297
+		$this->_order = $order;
298
+	}
299
+
300
+
301 301
 
302
-    /**
303
-     * @return int
304
-     */
305
-    public function order()
306
-    {
307
-        return $this->_order;
308
-    }
309
-
310
-
311
-
312
-    /**
313
-     * @return string
314
-     */
315
-    public function template()
316
-    {
317
-        return $this->_template;
318
-    }
319
-
320
-
321
-
322
-    /**
323
-     * @return string
324
-     */
325
-    public function success_message()
326
-    {
327
-        return $this->_success_message;
328
-    }
302
+	/**
303
+	 * @return int
304
+	 */
305
+	public function order()
306
+	{
307
+		return $this->_order;
308
+	}
309
+
310
+
311
+
312
+	/**
313
+	 * @return string
314
+	 */
315
+	public function template()
316
+	{
317
+		return $this->_template;
318
+	}
319
+
320
+
321
+
322
+	/**
323
+	 * @return string
324
+	 */
325
+	public function success_message()
326
+	{
327
+		return $this->_success_message;
328
+	}
329 329
 
330 330
 
331 331
 
332
-    /**
333
-     * _set_success_message
334
-     *
335
-     * @param string $success_message
336
-     */
337
-    protected function _set_success_message($success_message)
338
-    {
339
-        $this->_success_message = $success_message;
340
-    }
341
-
342
-
343
-
344
-    /**
345
-     * _reset_success_message
346
-     *
347
-     * @return void
348
-     */
349
-    protected function _reset_success_message()
350
-    {
351
-        $this->_success_message = '';
352
-    }
332
+	/**
333
+	 * _set_success_message
334
+	 *
335
+	 * @param string $success_message
336
+	 */
337
+	protected function _set_success_message($success_message)
338
+	{
339
+		$this->_success_message = $success_message;
340
+	}
341
+
342
+
343
+
344
+	/**
345
+	 * _reset_success_message
346
+	 *
347
+	 * @return void
348
+	 */
349
+	protected function _reset_success_message()
350
+	{
351
+		$this->_success_message = '';
352
+	}
353 353
 
354 354
 
355 355
 
356
-    /**
357
-     * @return string
358
-     */
359
-    public function _instructions()
360
-    {
361
-        return $this->_instructions;
362
-    }
363
-
364
-
365
-
366
-    /**
367
-     * @param string $instructions
368
-     */
369
-    public function set_instructions($instructions)
370
-    {
371
-        $this->_instructions = apply_filters(
372
-            'FHEE__EE_SPCO_Reg_Step__set_instructions__instructions',
373
-            $instructions,
374
-            $this
375
-        );
376
-    }
377
-
378
-
379
-
380
-    /**
381
-     * @param array $valid_data
382
-     */
383
-    public function set_valid_data($valid_data)
384
-    {
385
-        $this->_valid_data = $valid_data;
386
-    }
387
-
388
-
389
-
390
-    /**
391
-     * @return array
392
-     */
393
-    public function valid_data()
394
-    {
395
-        if (empty($this->_valid_data)) {
396
-            $this->_valid_data = $this->reg_form->valid_data();
397
-        }
398
-        return $this->_valid_data;
399
-    }
400
-
401
-
402
-
403
-    /**
404
-     * @return string
405
-     */
406
-    public function reg_form_name()
407
-    {
408
-        if (empty($this->_reg_form_name)) {
409
-            $this->set_reg_form_name('ee-spco-' . $this->slug() . '-reg-step-form');
410
-        }
411
-        return $this->_reg_form_name;
412
-    }
413
-
414
-
415
-
416
-    /**
417
-     * @param string $reg_form_name
418
-     */
419
-    protected function set_reg_form_name($reg_form_name)
420
-    {
421
-        $this->_reg_form_name = $reg_form_name;
422
-    }
423
-
424
-
425
-
426
-    /**
427
-     * reg_step_url
428
-     *
429
-     * @param string $action
430
-     * @return string
431
-     */
432
-    public function reg_step_url($action = '')
433
-    {
434
-        $query_args = array('step' => $this->slug());
435
-        if (! empty($action)) {
436
-            $query_args['action'] = $action;
437
-        }
438
-        // final step has no display
439
-        if ($this instanceof EE_SPCO_Reg_Step_Finalize_Registration && $action === 'display_spco_reg_step') {
440
-            $query_args['action'] = 'process_reg_step';
441
-        }
442
-        if ($this->checkout->revisit) {
443
-            $query_args['revisit'] = true;
444
-        }
445
-        if ($this->checkout->reg_url_link) {
446
-            $query_args['e_reg_url_link'] = $this->checkout->reg_url_link;
447
-        }
448
-        return add_query_arg($query_args, $this->checkout->reg_page_base_url);
449
-    }
450
-
451
-
452
-
453
-    /**
454
-     * creates the default hidden inputs section
455
-     *
456
-     * @return EE_Form_Section_Proper
457
-     * @throws \EE_Error
458
-     */
459
-    public function reg_step_hidden_inputs()
460
-    {
461
-        // hidden inputs for admin registrations
462
-        if ($this->checkout->admin_request) {
463
-            return new EE_Form_Section_Proper(
464
-                array(
465
-                    'layout_strategy' => new EE_Div_Per_Section_Layout(),
466
-                    'html_id'         => 'ee-' . $this->slug() . '-hidden-inputs',
467
-                    'subsections'     => array(
468
-                        'next_step' => new EE_Fixed_Hidden_Input(
469
-                            array(
470
-                                'html_name' => 'next_step',
471
-                                'html_id'   => 'spco-' . $this->slug() . '-next-step',
472
-                                'default'   => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
473
-                                    ? $this->checkout->next_step->slug() : '',
474
-                            )
475
-                        ),
476
-                    ),
477
-                )
478
-            );
479
-        } else {
480
-            $default_form_action = apply_filters(
481
-                'FHEE__EE_SPCO_Reg_Step__reg_step_hidden_inputs__default_form_action',
482
-                empty($this->checkout->reg_url_link)
483
-                    ? 'process_reg_step'
484
-                    : 'update_reg_step',
485
-                $this
486
-            );
487
-            // hidden inputs for frontend registrations
488
-            return new EE_Form_Section_Proper(
489
-                array(
490
-                    'layout_strategy' => new EE_Div_Per_Section_Layout(),
491
-                    'html_id'         => 'ee-' . $this->slug() . '-hidden-inputs',
492
-                    'subsections'     => array(
493
-                        'action'         => new EE_Fixed_Hidden_Input(
494
-                            array(
495
-                                'html_name' => 'action',
496
-                                'html_id'   => 'spco-' . $this->slug() . '-action',
497
-                                'default'   => $default_form_action,
498
-                            )
499
-                        ),
500
-                        'next_step'      => new EE_Fixed_Hidden_Input(
501
-                            array(
502
-                                'html_name' => 'next_step',
503
-                                'html_id'   => 'spco-' . $this->slug() . '-next-step',
504
-                                'default'   => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
505
-                                    ? $this->checkout->next_step->slug() : '',
506
-                            )
507
-                        ),
508
-                        'e_reg_url_link' => new EE_Fixed_Hidden_Input(
509
-                            array(
510
-                                'html_name' => 'e_reg_url_link',
511
-                                'html_id'   => 'spco-reg_url_link',
512
-                                'default'   => $this->checkout->reg_url_link,
513
-                            )
514
-                        ),
515
-                        'revisit'        => new EE_Fixed_Hidden_Input(
516
-                            array(
517
-                                'html_name' => 'revisit',
518
-                                'html_id'   => 'spco-revisit',
519
-                                'default'   => $this->checkout->revisit,
520
-                            )
521
-                        ),
522
-                    ),
523
-                )
524
-            );
525
-        }
526
-    }
527
-
528
-
529
-
530
-    /**
531
-     * generate_reg_form_for_actions
532
-     *
533
-     * @param array $actions
534
-     * @return void
535
-     */
536
-    public function generate_reg_form_for_actions($actions = array())
537
-    {
538
-        $actions = array_merge(
539
-            array(
540
-                'generate_reg_form',
541
-                'display_spco_reg_step',
542
-                'process_reg_step',
543
-                'update_reg_step',
544
-            ), $actions
545
-        );
546
-        $this->checkout->generate_reg_form = in_array($this->checkout->action, $actions, true) ? true : false;
547
-    }
548
-
549
-
550
-
551
-    /**
552
-     * @return string
553
-     * @throws \EE_Error
554
-     */
555
-    public function display_reg_form()
556
-    {
557
-        $html = '';
558
-        if ($this->reg_form instanceof EE_Form_Section_Proper) {
559
-            $html .= ! $this->checkout->admin_request ? $this->reg_form->form_open($this->reg_step_url()) : '';
560
-            if (EE_Registry::instance()->REQ->ajax) {
561
-                $this->reg_form->localize_validation_rules();
562
-                $this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
563
-            }
564
-            $html .= $this->reg_form->get_html();
565
-            $html .= ! $this->checkout->admin_request ? $this->reg_step_submit_button() : '';
566
-            $html .= ! $this->checkout->admin_request ? $this->reg_form->form_close() : '';
567
-        }
568
-        return $html;
569
-    }
570
-
571
-
572
-
573
-    /**
574
-     * div_class - returns nothing for current step, but a css class of "hidden" for others
575
-     *
576
-     * @return string
577
-     * @throws \EE_Error
578
-     */
579
-    public function reg_step_submit_button()
580
-    {
581
-        if (! $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
582
-            return '';
583
-        }
584
-        ob_start();
585
-        do_action('AHEE__before_spco_whats_next_buttons', $this->slug(), $this->checkout->next_step->slug(),
586
-            $this->checkout);
587
-        $html = ob_get_clean();
588
-        // generate submit button
589
-        $sbmt_btn = new EE_Submit_Input(array(
590
-            'html_name'             => 'spco-go-to-step-' . $this->checkout->next_step->slug(),
591
-            'html_id'               => 'spco-go-to-step-' . $this->checkout->next_step->slug(),
592
-            'html_class'            => 'spco-next-step-btn',
593
-            'other_html_attributes' => ' rel="' . $this->slug() . '"',
594
-            'default'               => $this->submit_button_text(),
595
-        ));
596
-        $sbmt_btn->set_button_css_attributes(true, 'large');
597
-        $sbmt_btn_html = $sbmt_btn->get_html_for_input();
598
-        $html .= EEH_HTML::div(
599
-            apply_filters('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', $sbmt_btn_html, $this),
600
-            'spco-' . $this->slug() . '-whats-next-buttons-dv',
601
-            'spco-whats-next-buttons'
602
-        );
603
-        return $html;
604
-    }
605
-
606
-
607
-
608
-    /**
609
-     * div_class - returns nothing for current step, but a css class of "hidden" for others
610
-     *
611
-     * @return string
612
-     */
613
-    public function div_class()
614
-    {
615
-        return $this->is_current_step() ? '' : ' hidden';
616
-    }
617
-
618
-
619
-
620
-    /**
621
-     * div_class - returns  a css class of "hidden" for current step, but nothing for others
622
-     *
623
-     * @return string
624
-     */
625
-    public function edit_lnk_url()
626
-    {
627
-        return add_query_arg(array('step' => $this->slug()), $this->checkout->reg_page_base_url);
628
-    }
629
-
630
-
631
-
632
-    /**
633
-     * div_class - returns  a css class of "hidden" for current step, but nothing for others
634
-     *
635
-     * @return string
636
-     */
637
-    public function edit_link_class()
638
-    {
639
-        return $this->is_current_step() ? ' hidden' : '';
640
-    }
641
-
642
-
643
-
644
-    /**
645
-     * update_checkout with changes that have been made to the cart
646
-     *
647
-     * @return void
648
-     * @throws \EE_Error
649
-     */
650
-    public function update_checkout()
651
-    {
652
-        // grab the cart grand total and reset TXN total
653
-        $this->checkout->transaction->set_total($this->checkout->cart->get_cart_grand_total());
654
-        $this->checkout->stash_transaction_and_checkout();
655
-    }
656
-
657
-
658
-
659
-    /**
660
-     *    __sleep
661
-     * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon
662
-     * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the
663
-     * reg form, because if needed, it will be regenerated anyways
664
-     *
665
-     * @return array
666
-     */
667
-    public function __sleep()
668
-    {
669
-        // remove the reg form and the checkout
670
-        return array_diff(array_keys(get_object_vars($this)), array('reg_form', 'checkout'));
671
-    }
356
+	/**
357
+	 * @return string
358
+	 */
359
+	public function _instructions()
360
+	{
361
+		return $this->_instructions;
362
+	}
363
+
364
+
365
+
366
+	/**
367
+	 * @param string $instructions
368
+	 */
369
+	public function set_instructions($instructions)
370
+	{
371
+		$this->_instructions = apply_filters(
372
+			'FHEE__EE_SPCO_Reg_Step__set_instructions__instructions',
373
+			$instructions,
374
+			$this
375
+		);
376
+	}
377
+
378
+
379
+
380
+	/**
381
+	 * @param array $valid_data
382
+	 */
383
+	public function set_valid_data($valid_data)
384
+	{
385
+		$this->_valid_data = $valid_data;
386
+	}
387
+
388
+
389
+
390
+	/**
391
+	 * @return array
392
+	 */
393
+	public function valid_data()
394
+	{
395
+		if (empty($this->_valid_data)) {
396
+			$this->_valid_data = $this->reg_form->valid_data();
397
+		}
398
+		return $this->_valid_data;
399
+	}
400
+
401
+
402
+
403
+	/**
404
+	 * @return string
405
+	 */
406
+	public function reg_form_name()
407
+	{
408
+		if (empty($this->_reg_form_name)) {
409
+			$this->set_reg_form_name('ee-spco-' . $this->slug() . '-reg-step-form');
410
+		}
411
+		return $this->_reg_form_name;
412
+	}
413
+
414
+
415
+
416
+	/**
417
+	 * @param string $reg_form_name
418
+	 */
419
+	protected function set_reg_form_name($reg_form_name)
420
+	{
421
+		$this->_reg_form_name = $reg_form_name;
422
+	}
423
+
424
+
425
+
426
+	/**
427
+	 * reg_step_url
428
+	 *
429
+	 * @param string $action
430
+	 * @return string
431
+	 */
432
+	public function reg_step_url($action = '')
433
+	{
434
+		$query_args = array('step' => $this->slug());
435
+		if (! empty($action)) {
436
+			$query_args['action'] = $action;
437
+		}
438
+		// final step has no display
439
+		if ($this instanceof EE_SPCO_Reg_Step_Finalize_Registration && $action === 'display_spco_reg_step') {
440
+			$query_args['action'] = 'process_reg_step';
441
+		}
442
+		if ($this->checkout->revisit) {
443
+			$query_args['revisit'] = true;
444
+		}
445
+		if ($this->checkout->reg_url_link) {
446
+			$query_args['e_reg_url_link'] = $this->checkout->reg_url_link;
447
+		}
448
+		return add_query_arg($query_args, $this->checkout->reg_page_base_url);
449
+	}
450
+
451
+
452
+
453
+	/**
454
+	 * creates the default hidden inputs section
455
+	 *
456
+	 * @return EE_Form_Section_Proper
457
+	 * @throws \EE_Error
458
+	 */
459
+	public function reg_step_hidden_inputs()
460
+	{
461
+		// hidden inputs for admin registrations
462
+		if ($this->checkout->admin_request) {
463
+			return new EE_Form_Section_Proper(
464
+				array(
465
+					'layout_strategy' => new EE_Div_Per_Section_Layout(),
466
+					'html_id'         => 'ee-' . $this->slug() . '-hidden-inputs',
467
+					'subsections'     => array(
468
+						'next_step' => new EE_Fixed_Hidden_Input(
469
+							array(
470
+								'html_name' => 'next_step',
471
+								'html_id'   => 'spco-' . $this->slug() . '-next-step',
472
+								'default'   => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
473
+									? $this->checkout->next_step->slug() : '',
474
+							)
475
+						),
476
+					),
477
+				)
478
+			);
479
+		} else {
480
+			$default_form_action = apply_filters(
481
+				'FHEE__EE_SPCO_Reg_Step__reg_step_hidden_inputs__default_form_action',
482
+				empty($this->checkout->reg_url_link)
483
+					? 'process_reg_step'
484
+					: 'update_reg_step',
485
+				$this
486
+			);
487
+			// hidden inputs for frontend registrations
488
+			return new EE_Form_Section_Proper(
489
+				array(
490
+					'layout_strategy' => new EE_Div_Per_Section_Layout(),
491
+					'html_id'         => 'ee-' . $this->slug() . '-hidden-inputs',
492
+					'subsections'     => array(
493
+						'action'         => new EE_Fixed_Hidden_Input(
494
+							array(
495
+								'html_name' => 'action',
496
+								'html_id'   => 'spco-' . $this->slug() . '-action',
497
+								'default'   => $default_form_action,
498
+							)
499
+						),
500
+						'next_step'      => new EE_Fixed_Hidden_Input(
501
+							array(
502
+								'html_name' => 'next_step',
503
+								'html_id'   => 'spco-' . $this->slug() . '-next-step',
504
+								'default'   => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
505
+									? $this->checkout->next_step->slug() : '',
506
+							)
507
+						),
508
+						'e_reg_url_link' => new EE_Fixed_Hidden_Input(
509
+							array(
510
+								'html_name' => 'e_reg_url_link',
511
+								'html_id'   => 'spco-reg_url_link',
512
+								'default'   => $this->checkout->reg_url_link,
513
+							)
514
+						),
515
+						'revisit'        => new EE_Fixed_Hidden_Input(
516
+							array(
517
+								'html_name' => 'revisit',
518
+								'html_id'   => 'spco-revisit',
519
+								'default'   => $this->checkout->revisit,
520
+							)
521
+						),
522
+					),
523
+				)
524
+			);
525
+		}
526
+	}
527
+
528
+
529
+
530
+	/**
531
+	 * generate_reg_form_for_actions
532
+	 *
533
+	 * @param array $actions
534
+	 * @return void
535
+	 */
536
+	public function generate_reg_form_for_actions($actions = array())
537
+	{
538
+		$actions = array_merge(
539
+			array(
540
+				'generate_reg_form',
541
+				'display_spco_reg_step',
542
+				'process_reg_step',
543
+				'update_reg_step',
544
+			), $actions
545
+		);
546
+		$this->checkout->generate_reg_form = in_array($this->checkout->action, $actions, true) ? true : false;
547
+	}
548
+
549
+
550
+
551
+	/**
552
+	 * @return string
553
+	 * @throws \EE_Error
554
+	 */
555
+	public function display_reg_form()
556
+	{
557
+		$html = '';
558
+		if ($this->reg_form instanceof EE_Form_Section_Proper) {
559
+			$html .= ! $this->checkout->admin_request ? $this->reg_form->form_open($this->reg_step_url()) : '';
560
+			if (EE_Registry::instance()->REQ->ajax) {
561
+				$this->reg_form->localize_validation_rules();
562
+				$this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
563
+			}
564
+			$html .= $this->reg_form->get_html();
565
+			$html .= ! $this->checkout->admin_request ? $this->reg_step_submit_button() : '';
566
+			$html .= ! $this->checkout->admin_request ? $this->reg_form->form_close() : '';
567
+		}
568
+		return $html;
569
+	}
570
+
571
+
572
+
573
+	/**
574
+	 * div_class - returns nothing for current step, but a css class of "hidden" for others
575
+	 *
576
+	 * @return string
577
+	 * @throws \EE_Error
578
+	 */
579
+	public function reg_step_submit_button()
580
+	{
581
+		if (! $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
582
+			return '';
583
+		}
584
+		ob_start();
585
+		do_action('AHEE__before_spco_whats_next_buttons', $this->slug(), $this->checkout->next_step->slug(),
586
+			$this->checkout);
587
+		$html = ob_get_clean();
588
+		// generate submit button
589
+		$sbmt_btn = new EE_Submit_Input(array(
590
+			'html_name'             => 'spco-go-to-step-' . $this->checkout->next_step->slug(),
591
+			'html_id'               => 'spco-go-to-step-' . $this->checkout->next_step->slug(),
592
+			'html_class'            => 'spco-next-step-btn',
593
+			'other_html_attributes' => ' rel="' . $this->slug() . '"',
594
+			'default'               => $this->submit_button_text(),
595
+		));
596
+		$sbmt_btn->set_button_css_attributes(true, 'large');
597
+		$sbmt_btn_html = $sbmt_btn->get_html_for_input();
598
+		$html .= EEH_HTML::div(
599
+			apply_filters('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', $sbmt_btn_html, $this),
600
+			'spco-' . $this->slug() . '-whats-next-buttons-dv',
601
+			'spco-whats-next-buttons'
602
+		);
603
+		return $html;
604
+	}
605
+
606
+
607
+
608
+	/**
609
+	 * div_class - returns nothing for current step, but a css class of "hidden" for others
610
+	 *
611
+	 * @return string
612
+	 */
613
+	public function div_class()
614
+	{
615
+		return $this->is_current_step() ? '' : ' hidden';
616
+	}
617
+
618
+
619
+
620
+	/**
621
+	 * div_class - returns  a css class of "hidden" for current step, but nothing for others
622
+	 *
623
+	 * @return string
624
+	 */
625
+	public function edit_lnk_url()
626
+	{
627
+		return add_query_arg(array('step' => $this->slug()), $this->checkout->reg_page_base_url);
628
+	}
629
+
630
+
631
+
632
+	/**
633
+	 * div_class - returns  a css class of "hidden" for current step, but nothing for others
634
+	 *
635
+	 * @return string
636
+	 */
637
+	public function edit_link_class()
638
+	{
639
+		return $this->is_current_step() ? ' hidden' : '';
640
+	}
641
+
642
+
643
+
644
+	/**
645
+	 * update_checkout with changes that have been made to the cart
646
+	 *
647
+	 * @return void
648
+	 * @throws \EE_Error
649
+	 */
650
+	public function update_checkout()
651
+	{
652
+		// grab the cart grand total and reset TXN total
653
+		$this->checkout->transaction->set_total($this->checkout->cart->get_cart_grand_total());
654
+		$this->checkout->stash_transaction_and_checkout();
655
+	}
656
+
657
+
658
+
659
+	/**
660
+	 *    __sleep
661
+	 * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon
662
+	 * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the
663
+	 * reg form, because if needed, it will be regenerated anyways
664
+	 *
665
+	 * @return array
666
+	 */
667
+	public function __sleep()
668
+	{
669
+		// remove the reg form and the checkout
670
+		return array_diff(array_keys(get_object_vars($this)), array('reg_form', 'checkout'));
671
+	}
672 672
 
673 673
 
674 674
 
Please login to merge, or discard this patch.
Spacing   +14 added lines, -14 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
 
@@ -238,7 +238,7 @@  discard block
 block discarded – undo
238 238
      */
239 239
     public function set_submit_button_text($submit_button_text = '')
240 240
     {
241
-        if (! empty($submit_button_text)) {
241
+        if ( ! empty($submit_button_text)) {
242 242
             $this->_submit_button_text = $submit_button_text;
243 243
         } else if ($this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
244 244
             if ($this->checkout->revisit) {
@@ -406,7 +406,7 @@  discard block
 block discarded – undo
406 406
     public function reg_form_name()
407 407
     {
408 408
         if (empty($this->_reg_form_name)) {
409
-            $this->set_reg_form_name('ee-spco-' . $this->slug() . '-reg-step-form');
409
+            $this->set_reg_form_name('ee-spco-'.$this->slug().'-reg-step-form');
410 410
         }
411 411
         return $this->_reg_form_name;
412 412
     }
@@ -432,7 +432,7 @@  discard block
 block discarded – undo
432 432
     public function reg_step_url($action = '')
433 433
     {
434 434
         $query_args = array('step' => $this->slug());
435
-        if (! empty($action)) {
435
+        if ( ! empty($action)) {
436 436
             $query_args['action'] = $action;
437 437
         }
438 438
         // final step has no display
@@ -463,12 +463,12 @@  discard block
 block discarded – undo
463 463
             return new EE_Form_Section_Proper(
464 464
                 array(
465 465
                     'layout_strategy' => new EE_Div_Per_Section_Layout(),
466
-                    'html_id'         => 'ee-' . $this->slug() . '-hidden-inputs',
466
+                    'html_id'         => 'ee-'.$this->slug().'-hidden-inputs',
467 467
                     'subsections'     => array(
468 468
                         'next_step' => new EE_Fixed_Hidden_Input(
469 469
                             array(
470 470
                                 'html_name' => 'next_step',
471
-                                'html_id'   => 'spco-' . $this->slug() . '-next-step',
471
+                                'html_id'   => 'spco-'.$this->slug().'-next-step',
472 472
                                 'default'   => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
473 473
                                     ? $this->checkout->next_step->slug() : '',
474 474
                             )
@@ -488,19 +488,19 @@  discard block
 block discarded – undo
488 488
             return new EE_Form_Section_Proper(
489 489
                 array(
490 490
                     'layout_strategy' => new EE_Div_Per_Section_Layout(),
491
-                    'html_id'         => 'ee-' . $this->slug() . '-hidden-inputs',
491
+                    'html_id'         => 'ee-'.$this->slug().'-hidden-inputs',
492 492
                     'subsections'     => array(
493 493
                         'action'         => new EE_Fixed_Hidden_Input(
494 494
                             array(
495 495
                                 'html_name' => 'action',
496
-                                'html_id'   => 'spco-' . $this->slug() . '-action',
496
+                                'html_id'   => 'spco-'.$this->slug().'-action',
497 497
                                 'default'   => $default_form_action,
498 498
                             )
499 499
                         ),
500 500
                         'next_step'      => new EE_Fixed_Hidden_Input(
501 501
                             array(
502 502
                                 'html_name' => 'next_step',
503
-                                'html_id'   => 'spco-' . $this->slug() . '-next-step',
503
+                                'html_id'   => 'spco-'.$this->slug().'-next-step',
504 504
                                 'default'   => $this->checkout->next_step instanceof EE_SPCO_Reg_Step
505 505
                                     ? $this->checkout->next_step->slug() : '',
506 506
                             )
@@ -578,7 +578,7 @@  discard block
 block discarded – undo
578 578
      */
579 579
     public function reg_step_submit_button()
580 580
     {
581
-        if (! $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
581
+        if ( ! $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
582 582
             return '';
583 583
         }
584 584
         ob_start();
@@ -587,17 +587,17 @@  discard block
 block discarded – undo
587 587
         $html = ob_get_clean();
588 588
         // generate submit button
589 589
         $sbmt_btn = new EE_Submit_Input(array(
590
-            'html_name'             => 'spco-go-to-step-' . $this->checkout->next_step->slug(),
591
-            'html_id'               => 'spco-go-to-step-' . $this->checkout->next_step->slug(),
590
+            'html_name'             => 'spco-go-to-step-'.$this->checkout->next_step->slug(),
591
+            'html_id'               => 'spco-go-to-step-'.$this->checkout->next_step->slug(),
592 592
             'html_class'            => 'spco-next-step-btn',
593
-            'other_html_attributes' => ' rel="' . $this->slug() . '"',
593
+            'other_html_attributes' => ' rel="'.$this->slug().'"',
594 594
             'default'               => $this->submit_button_text(),
595 595
         ));
596 596
         $sbmt_btn->set_button_css_attributes(true, 'large');
597 597
         $sbmt_btn_html = $sbmt_btn->get_html_for_input();
598 598
         $html .= EEH_HTML::div(
599 599
             apply_filters('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', $sbmt_btn_html, $this),
600
-            'spco-' . $this->slug() . '-whats-next-buttons-dv',
600
+            'spco-'.$this->slug().'-whats-next-buttons-dv',
601 601
             'spco-whats-next-buttons'
602 602
         );
603 603
         return $html;
Please login to merge, or discard this patch.