Completed
Branch models-cleanup/model-relations (b772ed)
by
unknown
56:02 queued 47:06
created
strategies/validation/EE_Email_Validation_Strategy.strategy.php 2 patches
Indentation   +59 added lines, -59 removed lines patch added patch discarded remove patch
@@ -18,72 +18,72 @@
 block discarded – undo
18 18
 {
19 19
 
20 20
 
21
-    /**
22
-     * @param string               $validation_error_message
23
-     */
24
-    public function __construct($validation_error_message = '')
25
-    {
26
-        if (! $validation_error_message) {
27
-            $validation_error_message = esc_html__('Please enter a valid email address.', 'event_espresso');
28
-        }
29
-        parent::__construct($validation_error_message);
30
-    }
21
+	/**
22
+	 * @param string               $validation_error_message
23
+	 */
24
+	public function __construct($validation_error_message = '')
25
+	{
26
+		if (! $validation_error_message) {
27
+			$validation_error_message = esc_html__('Please enter a valid email address.', 'event_espresso');
28
+		}
29
+		parent::__construct($validation_error_message);
30
+	}
31 31
 
32 32
 
33 33
 
34
-    /**
35
-     * just checks the field isn't blank
36
-     *
37
-     * @param $normalized_value
38
-     * @return bool
39
-     * @throws InvalidArgumentException
40
-     * @throws InvalidInterfaceException
41
-     * @throws InvalidDataTypeException
42
-     * @throws EE_Validation_Error
43
-     */
44
-    public function validate($normalized_value)
45
-    {
46
-        if ($normalized_value && ! $this->_validate_email($normalized_value)) {
47
-            throw new EE_Validation_Error($this->get_validation_error_message(), 'required');
48
-        }
49
-        return true;
50
-    }
34
+	/**
35
+	 * just checks the field isn't blank
36
+	 *
37
+	 * @param $normalized_value
38
+	 * @return bool
39
+	 * @throws InvalidArgumentException
40
+	 * @throws InvalidInterfaceException
41
+	 * @throws InvalidDataTypeException
42
+	 * @throws EE_Validation_Error
43
+	 */
44
+	public function validate($normalized_value)
45
+	{
46
+		if ($normalized_value && ! $this->_validate_email($normalized_value)) {
47
+			throw new EE_Validation_Error($this->get_validation_error_message(), 'required');
48
+		}
49
+		return true;
50
+	}
51 51
 
52 52
 
53 53
 
54
-    /**
55
-     * @return array
56
-     */
57
-    public function get_jquery_validation_rule_array()
58
-    {
59
-        return array('email' => true, 'messages' => array('email' => $this->get_validation_error_message()));
60
-    }
54
+	/**
55
+	 * @return array
56
+	 */
57
+	public function get_jquery_validation_rule_array()
58
+	{
59
+		return array('email' => true, 'messages' => array('email' => $this->get_validation_error_message()));
60
+	}
61 61
 
62 62
 
63 63
 
64
-    /**
65
-     * Validate an email address.
66
-     * Provide email address (raw input)
67
-     *
68
-     * @param $email
69
-     * @return bool of whether the email is valid or not
70
-     * @throws InvalidArgumentException
71
-     * @throws InvalidInterfaceException
72
-     * @throws InvalidDataTypeException
73
-     * @throws EE_Validation_Error
74
-     */
75
-    private function _validate_email($email)
76
-    {
77
-        try {
78
-            EmailAddressFactory::create($email);
79
-        } catch (EmailValidationException $e) {
80
-            throw new EE_Validation_Error(
81
-                $e->getMessage(),
82
-                'invalid_email',
83
-                $this->_input,
84
-                $e
85
-            );
86
-        }
87
-        return true;
88
-    }
64
+	/**
65
+	 * Validate an email address.
66
+	 * Provide email address (raw input)
67
+	 *
68
+	 * @param $email
69
+	 * @return bool of whether the email is valid or not
70
+	 * @throws InvalidArgumentException
71
+	 * @throws InvalidInterfaceException
72
+	 * @throws InvalidDataTypeException
73
+	 * @throws EE_Validation_Error
74
+	 */
75
+	private function _validate_email($email)
76
+	{
77
+		try {
78
+			EmailAddressFactory::create($email);
79
+		} catch (EmailValidationException $e) {
80
+			throw new EE_Validation_Error(
81
+				$e->getMessage(),
82
+				'invalid_email',
83
+				$this->_input,
84
+				$e
85
+			);
86
+		}
87
+		return true;
88
+	}
89 89
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -23,7 +23,7 @@
 block discarded – undo
23 23
      */
24 24
     public function __construct($validation_error_message = '')
25 25
     {
26
-        if (! $validation_error_message) {
26
+        if ( ! $validation_error_message) {
27 27
             $validation_error_message = esc_html__('Please enter a valid email address.', 'event_espresso');
28 28
         }
29 29
         parent::__construct($validation_error_message);
Please login to merge, or discard this patch.
core/libraries/messages/messenger/EE_Email_messenger.class.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -456,7 +456,7 @@
 block discarded – undo
456 456
      * be empty
457 457
      *
458 458
      * @since 4.3.1
459
-     * @return array
459
+     * @return string[]
460 460
      */
461 461
     private function _parse_from()
462 462
     {
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -56,7 +56,7 @@  discard block
 block discarded – undo
56 56
             ),
57 57
             '<code>wp_mail</code>'
58 58
         );
59
-        $this->label               = array(
59
+        $this->label = array(
60 60
             'singular' => esc_html__('email', 'event_espresso'),
61 61
             'plural'   => esc_html__('emails', 'event_espresso'),
62 62
         );
@@ -438,7 +438,7 @@  discard block
 block discarded – undo
438 438
             $this->_body(),
439 439
             $this->_headers()
440 440
         );
441
-        if (! $success) {
441
+        if ( ! $success) {
442 442
             EE_Error::add_error(
443 443
                 sprintf(
444 444
                     esc_html__(
@@ -482,8 +482,8 @@  discard block
 block discarded – undo
482 482
         $this->_ensure_has_from_email_address();
483 483
         $from    = $this->_from;
484 484
         $headers = array(
485
-            'From:' . $from,
486
-            'Reply-To:' . $from,
485
+            'From:'.$from,
486
+            'Reply-To:'.$from,
487 487
             'Content-Type:text/html; charset=utf-8',
488 488
         );
489 489
 
@@ -492,8 +492,8 @@  discard block
 block discarded – undo
492 492
          * cover back compat where there may be users who have saved cc values in their db for the newsletter message
493 493
          * type which they are no longer able to change.
494 494
          */
495
-        if (! empty($this->_cc) && ! $this->_incoming_message_type instanceof EE_Newsletter_message_type) {
496
-            $headers[] = 'cc: ' . $this->_cc;
495
+        if ( ! empty($this->_cc) && ! $this->_incoming_message_type instanceof EE_Newsletter_message_type) {
496
+            $headers[] = 'cc: '.$this->_cc;
497 497
         }
498 498
 
499 499
         // but wait!  Header's for the from is NOT reliable because some plugins don't respect From: as set in the
@@ -600,7 +600,7 @@  discard block
 block discarded – undo
600 600
             'from'      => $this->_from,
601 601
             'main_body' => wpautop($this->_content),
602 602
         );
603
-        $body                 = $this->_get_main_template($preview);
603
+        $body = $this->_get_main_template($preview);
604 604
 
605 605
         /**
606 606
          * This filter allows one to bypass the CSSToInlineStyles tool and leave the body untouched.
@@ -610,10 +610,10 @@  discard block
 block discarded – undo
610 610
          */
611 611
         if (apply_filters('FHEE__EE_Email_messenger__apply_CSSInliner ', true, $preview)) {
612 612
             // require CssToInlineStyles library and its dependencies via composer autoloader
613
-            require_once EE_THIRD_PARTY . 'cssinliner/vendor/autoload.php';
613
+            require_once EE_THIRD_PARTY.'cssinliner/vendor/autoload.php';
614 614
 
615 615
             // now if this isn't a preview, let's setup the body so it has inline styles
616
-            if (! $preview || ($preview && defined('DOING_AJAX'))) {
616
+            if ( ! $preview || ($preview && defined('DOING_AJAX'))) {
617 617
                 $style = file_get_contents(
618 618
                     $this->get_variation(
619 619
                         $this->_tmp_pack,
Please login to merge, or discard this patch.
Indentation   +644 added lines, -644 removed lines patch added patch discarded remove patch
@@ -6,648 +6,648 @@
 block discarded – undo
6 6
 class EE_Email_messenger extends EE_messenger
7 7
 {
8 8
 
9
-    /**
10
-     * To field for email
11
-     * @var string
12
-     */
13
-    protected $_to = '';
14
-
15
-
16
-    /**
17
-     * CC field for email.
18
-     * @var string
19
-     */
20
-    protected $_cc = '';
21
-
22
-    /**
23
-     * From field for email
24
-     * @var string
25
-     */
26
-    protected $_from = '';
27
-
28
-
29
-    /**
30
-     * Subject field for email
31
-     * @var string
32
-     */
33
-    protected $_subject = '';
34
-
35
-
36
-    /**
37
-     * Content field for email
38
-     * @var string
39
-     */
40
-    protected $_content = '';
41
-
42
-
43
-    /**
44
-     * constructor
45
-     *
46
-     * @access public
47
-     */
48
-    public function __construct()
49
-    {
50
-        // set name and description properties
51
-        $this->name                = 'email';
52
-        $this->description         = sprintf(
53
-            esc_html__(
54
-                'This messenger delivers messages via email using the built-in %s function included with WordPress',
55
-                'event_espresso'
56
-            ),
57
-            '<code>wp_mail</code>'
58
-        );
59
-        $this->label               = array(
60
-            'singular' => esc_html__('email', 'event_espresso'),
61
-            'plural'   => esc_html__('emails', 'event_espresso'),
62
-        );
63
-        $this->activate_on_install = true;
64
-
65
-        // we're using defaults so let's call parent constructor that will take care of setting up all the other
66
-        // properties
67
-        parent::__construct();
68
-    }
69
-
70
-
71
-    /**
72
-     * see abstract declaration in parent class for details.
73
-     */
74
-    protected function _set_admin_pages()
75
-    {
76
-        $this->admin_registered_pages = array(
77
-            'events_edit' => true,
78
-        );
79
-    }
80
-
81
-
82
-    /**
83
-     * see abstract declaration in parent class for details
84
-     */
85
-    protected function _set_valid_shortcodes()
86
-    {
87
-        // remember by leaving the other fields not set, those fields will inherit the valid shortcodes from the
88
-        // message type.
89
-        $this->_valid_shortcodes = array(
90
-            'to'   => array('email', 'event_author', 'primary_registration_details', 'recipient_details'),
91
-            'cc' => array('email', 'event_author', 'primary_registration_details', 'recipient_details'),
92
-            'from' => array('email', 'event_author', 'primary_registration_details', 'recipient_details'),
93
-        );
94
-    }
95
-
96
-
97
-    /**
98
-     * see abstract declaration in parent class for details
99
-     *
100
-     * @access protected
101
-     * @return void
102
-     */
103
-    protected function _set_validator_config()
104
-    {
105
-        $valid_shortcodes = $this->get_valid_shortcodes();
106
-
107
-        $this->_validator_config = array(
108
-            'to'            => array(
109
-                'shortcodes' => $valid_shortcodes['to'],
110
-                'type'       => 'email',
111
-            ),
112
-            'cc' => array(
113
-                'shortcodes' => $valid_shortcodes['to'],
114
-                'type' => 'email',
115
-            ),
116
-            'from'          => array(
117
-                'shortcodes' => $valid_shortcodes['from'],
118
-                'type'       => 'email',
119
-            ),
120
-            'subject'       => array(
121
-                'shortcodes' => array(
122
-                    'organization',
123
-                    'primary_registration_details',
124
-                    'event_author',
125
-                    'primary_registration_details',
126
-                    'recipient_details',
127
-                ),
128
-            ),
129
-            'content'       => array(
130
-                'shortcodes' => array(
131
-                    'event_list',
132
-                    'attendee_list',
133
-                    'ticket_list',
134
-                    'organization',
135
-                    'primary_registration_details',
136
-                    'primary_registration_list',
137
-                    'event_author',
138
-                    'recipient_details',
139
-                    'recipient_list',
140
-                    'transaction',
141
-                    'messenger',
142
-                ),
143
-            ),
144
-            'attendee_list' => array(
145
-                'shortcodes' => array('attendee', 'event_list', 'ticket_list'),
146
-                'required'   => array('[ATTENDEE_LIST]'),
147
-            ),
148
-            'event_list'    => array(
149
-                'shortcodes' => array(
150
-                    'event',
151
-                    'attendee_list',
152
-                    'ticket_list',
153
-                    'venue',
154
-                    'datetime_list',
155
-                    'attendee',
156
-                    'primary_registration_details',
157
-                    'primary_registration_list',
158
-                    'event_author',
159
-                    'recipient_details',
160
-                    'recipient_list',
161
-                ),
162
-                'required'   => array('[EVENT_LIST]'),
163
-            ),
164
-            'ticket_list'   => array(
165
-                'shortcodes' => array(
166
-                    'event_list',
167
-                    'attendee_list',
168
-                    'ticket',
169
-                    'datetime_list',
170
-                    'primary_registration_details',
171
-                    'recipient_details',
172
-                ),
173
-                'required'   => array('[TICKET_LIST]'),
174
-            ),
175
-            'datetime_list' => array(
176
-                'shortcodes' => array('datetime'),
177
-                'required'   => array('[DATETIME_LIST]'),
178
-            ),
179
-        );
180
-    }
181
-
182
-
183
-    /**
184
-     * @see   parent EE_messenger class for docs
185
-     * @since 4.5.0
186
-     */
187
-    public function do_secondary_messenger_hooks($sending_messenger_name)
188
-    {
189
-        if ($sending_messenger_name === 'html') {
190
-            add_filter('FHEE__EE_Messages_Template_Pack__get_variation', array($this, 'add_email_css'), 10, 8);
191
-        }
192
-    }
193
-
194
-
195
-    public function add_email_css(
196
-        $variation_path,
197
-        $messenger,
198
-        $message_type,
199
-        $type,
200
-        $variation,
201
-        $file_extension,
202
-        $url,
203
-        EE_Messages_Template_Pack $template_pack
204
-    ) {
205
-        // prevent recursion on this callback.
206
-        remove_filter('FHEE__EE_Messages_Template_Pack__get_variation', array($this, 'add_email_css'), 10);
207
-        $variation = $this->get_variation($template_pack, $message_type, $url, 'main', $variation, false);
208
-
209
-        add_filter('FHEE__EE_Messages_Template_Pack__get_variation', array($this, 'add_email_css'), 10, 8);
210
-        return $variation;
211
-    }
212
-
213
-
214
-    /**
215
-     * See parent for details
216
-     *
217
-     * @access protected
218
-     * @return void
219
-     */
220
-    protected function _set_test_settings_fields()
221
-    {
222
-        $this->_test_settings_fields = array(
223
-            'to'      => array(
224
-                'input'      => 'text',
225
-                'label'      => esc_html__('Send a test email to', 'event_espresso'),
226
-                'type'       => 'email',
227
-                'required'   => true,
228
-                'validation' => true,
229
-                'css_class'  => 'large-text',
230
-                'format'     => '%s',
231
-                'default'    => get_bloginfo('admin_email'),
232
-            ),
233
-            'subject' => array(
234
-                'input'      => 'hidden',
235
-                'label'      => '',
236
-                'type'       => 'string',
237
-                'required'   => false,
238
-                'validation' => false,
239
-                'format'     => '%s',
240
-                'value'      => sprintf(__('Test email sent from %s', 'event_espresso'), get_bloginfo('name')),
241
-                'default'    => '',
242
-                'css_class'  => '',
243
-            ),
244
-        );
245
-    }
246
-
247
-
248
-    /**
249
-     * _set_template_fields
250
-     * This sets up the fields that a messenger requires for the message to go out.
251
-     *
252
-     * @access  protected
253
-     * @return void
254
-     */
255
-    protected function _set_template_fields()
256
-    {
257
-        // any extra template fields that are NOT used by the messenger but will get used by a messenger field for
258
-        // shortcode replacement get added to the 'extra' key in an associated array indexed by the messenger field
259
-        // they relate to.  This is important for the Messages_admin to know what fields to display to the user.
260
-        //  Also, notice that the "values" are equal to the field type that messages admin will use to know what
261
-        // kind of field to display. The values ALSO have one index labeled "shortcode".  the values in that array
262
-        // indicate which ACTUAL SHORTCODE (i.e. [SHORTCODE]) is required in order for this extra field to be
263
-        // displayed.  If the required shortcode isn't part of the shortcodes array then the field is not needed and
264
-        // will not be displayed/parsed.
265
-        $this->_template_fields = array(
266
-            'to'      => array(
267
-                'input'      => 'text',
268
-                'label'      => esc_html_x(
269
-                    'To',
270
-                    'Label for the "To" field for email addresses',
271
-                    'event_espresso'
272
-                ),
273
-                'type'       => 'string',
274
-                'required'   => true,
275
-                'validation' => true,
276
-                'css_class'  => 'large-text',
277
-                'format'     => '%s',
278
-            ),
279
-            'cc'      => array(
280
-                'input'      => 'text',
281
-                'label'      => esc_html_x(
282
-                    'CC',
283
-                    'Label for the "Carbon Copy" field used for additional email addresses',
284
-                    'event_espresso'
285
-                ),
286
-                'type'       => 'string',
287
-                'required'   => false,
288
-                'validation' => true,
289
-                'css_class'  => 'large-text',
290
-                'format'     => '%s',
291
-            ),
292
-            'from'    => array(
293
-                'input'      => 'text',
294
-                'label'      => esc_html_x(
295
-                    'From',
296
-                    'Label for the "From" field for email addresses.',
297
-                    'event_espresso'
298
-                ),
299
-                'type'       => 'string',
300
-                'required'   => true,
301
-                'validation' => true,
302
-                'css_class'  => 'large-text',
303
-                'format'     => '%s',
304
-            ),
305
-            'subject' => array(
306
-                'input'      => 'text',
307
-                'label'      => esc_html_x(
308
-                    'Subject',
309
-                    'Label for the "Subject" field (short description of contents) for emails.',
310
-                    'event_espresso'
311
-                ),
312
-                'type'       => 'string',
313
-                'required'   => true,
314
-                'validation' => true,
315
-                'css_class'  => 'large-text',
316
-                'format'     => '%s',
317
-            ),
318
-            'content' => '',
319
-            // left empty b/c it is in the "extra array" but messenger still needs needs to know this is a field.
320
-            'extra'   => array(
321
-                'content' => array(
322
-                    'main'          => array(
323
-                        'input'      => 'wp_editor',
324
-                        'label'      => esc_html__('Main Content', 'event_espresso'),
325
-                        'type'       => 'string',
326
-                        'required'   => true,
327
-                        'validation' => true,
328
-                        'format'     => '%s',
329
-                        'rows'       => '15',
330
-                    ),
331
-                    'event_list'    => array(
332
-                        'input'               => 'wp_editor',
333
-                        'label'               => '[EVENT_LIST]',
334
-                        'type'                => 'string',
335
-                        'required'            => true,
336
-                        'validation'          => true,
337
-                        'format'              => '%s',
338
-                        'rows'                => '15',
339
-                        'shortcodes_required' => array('[EVENT_LIST]'),
340
-                    ),
341
-                    'attendee_list' => array(
342
-                        'input'               => 'textarea',
343
-                        'label'               => '[ATTENDEE_LIST]',
344
-                        'type'                => 'string',
345
-                        'required'            => true,
346
-                        'validation'          => true,
347
-                        'format'              => '%s',
348
-                        'css_class'           => 'large-text',
349
-                        'rows'                => '5',
350
-                        'shortcodes_required' => array('[ATTENDEE_LIST]'),
351
-                    ),
352
-                    'ticket_list'   => array(
353
-                        'input'               => 'textarea',
354
-                        'label'               => '[TICKET_LIST]',
355
-                        'type'                => 'string',
356
-                        'required'            => true,
357
-                        'validation'          => true,
358
-                        'format'              => '%s',
359
-                        'css_class'           => 'large-text',
360
-                        'rows'                => '10',
361
-                        'shortcodes_required' => array('[TICKET_LIST]'),
362
-                    ),
363
-                    'datetime_list' => array(
364
-                        'input'               => 'textarea',
365
-                        'label'               => '[DATETIME_LIST]',
366
-                        'type'                => 'string',
367
-                        'required'            => true,
368
-                        'validation'          => true,
369
-                        'format'              => '%s',
370
-                        'css_class'           => 'large-text',
371
-                        'rows'                => '10',
372
-                        'shortcodes_required' => array('[DATETIME_LIST]'),
373
-                    ),
374
-                ),
375
-            ),
376
-        );
377
-    }
378
-
379
-
380
-    /**
381
-     * See definition of this class in parent
382
-     */
383
-    protected function _set_default_message_types()
384
-    {
385
-        $this->_default_message_types = array(
386
-            'payment',
387
-            'payment_refund',
388
-            'registration',
389
-            'not_approved_registration',
390
-            'pending_approval',
391
-        );
392
-    }
393
-
394
-
395
-    /**
396
-     * @see   definition of this class in parent
397
-     * @since 4.5.0
398
-     */
399
-    protected function _set_valid_message_types()
400
-    {
401
-        $this->_valid_message_types = array(
402
-            'payment',
403
-            'registration',
404
-            'not_approved_registration',
405
-            'declined_registration',
406
-            'cancelled_registration',
407
-            'pending_approval',
408
-            'registration_summary',
409
-            'payment_reminder',
410
-            'payment_declined',
411
-            'payment_refund',
412
-        );
413
-    }
414
-
415
-
416
-    /**
417
-     * setting up admin_settings_fields for messenger.
418
-     */
419
-    protected function _set_admin_settings_fields()
420
-    {
421
-    }
422
-
423
-    /**
424
-     * We just deliver the messages don't kill us!!
425
-     *
426
-     * @return bool|WP_Error true if message delivered, false if it didn't deliver OR bubble up any error object if
427
-     *              present.
428
-     * @throws EE_Error
429
-     * @throws \TijsVerkoyen\CssToInlineStyles\Exception
430
-     */
431
-    protected function _send_message()
432
-    {
433
-        $success = wp_mail(
434
-            $this->_to,
435
-            // some old values for subject may be expecting HTML entities to be decoded in the subject
436
-            // and subjects aren't interpreted as HTML, so there should be no HTML in them
437
-            wp_strip_all_tags(wp_specialchars_decode($this->_subject, ENT_QUOTES)),
438
-            $this->_body(),
439
-            $this->_headers()
440
-        );
441
-        if (! $success) {
442
-            EE_Error::add_error(
443
-                sprintf(
444
-                    esc_html__(
445
-                        'The email did not send successfully.%3$sThe WordPress wp_mail function is used for sending mails but does not give any useful information when an email fails to send.%3$sIt is possible the "to" address (%1$s) or "from" address (%2$s) is invalid.%3$s',
446
-                        'event_espresso'
447
-                    ),
448
-                    $this->_to,
449
-                    $this->_from,
450
-                    '<br />'
451
-                ),
452
-                __FILE__,
453
-                __FUNCTION__,
454
-                __LINE__
455
-            );
456
-        }
457
-        return $success;
458
-    }
459
-
460
-
461
-    /**
462
-     * see parent for definition
463
-     *
464
-     * @return string html body of the message content and the related css.
465
-     * @throws EE_Error
466
-     * @throws \TijsVerkoyen\CssToInlineStyles\Exception
467
-     */
468
-    protected function _preview()
469
-    {
470
-        return $this->_body(true);
471
-    }
472
-
473
-
474
-    /**
475
-     * Setup headers for email
476
-     *
477
-     * @access protected
478
-     * @return string formatted header for email
479
-     */
480
-    protected function _headers()
481
-    {
482
-        $this->_ensure_has_from_email_address();
483
-        $from    = $this->_from;
484
-        $headers = array(
485
-            'From:' . $from,
486
-            'Reply-To:' . $from,
487
-            'Content-Type:text/html; charset=utf-8',
488
-        );
489
-
490
-        /**
491
-         * Second condition added as a result of https://events.codebasehq.com/projects/event-espresso/tickets/11416 to
492
-         * cover back compat where there may be users who have saved cc values in their db for the newsletter message
493
-         * type which they are no longer able to change.
494
-         */
495
-        if (! empty($this->_cc) && ! $this->_incoming_message_type instanceof EE_Newsletter_message_type) {
496
-            $headers[] = 'cc: ' . $this->_cc;
497
-        }
498
-
499
-        // but wait!  Header's for the from is NOT reliable because some plugins don't respect From: as set in the
500
-        // header.
501
-        add_filter('wp_mail_from', array($this, 'set_from_address'), 100);
502
-        add_filter('wp_mail_from_name', array($this, 'set_from_name'), 100);
503
-        return apply_filters('FHEE__EE_Email_messenger___headers', $headers, $this->_incoming_message_type, $this);
504
-    }
505
-
506
-
507
-    /**
508
-     * This simply ensures that the from address is not empty.  If it is, then we use whatever is set as the site email
509
-     * address for the from address to avoid problems with sending emails.
510
-     */
511
-    protected function _ensure_has_from_email_address()
512
-    {
513
-        if (empty($this->_from)) {
514
-            $this->_from = get_bloginfo('admin_email');
515
-        }
516
-    }
517
-
518
-
519
-    /**
520
-     * This simply parses whatever is set as the $_from address and determines if it is in the format {name} <{email}>
521
-     * or just {email} and returns an array with the "from_name" and "from_email" as the values. Note from_name *MAY*
522
-     * be empty
523
-     *
524
-     * @since 4.3.1
525
-     * @return array
526
-     */
527
-    private function _parse_from()
528
-    {
529
-        if (strpos($this->_from, '<') !== false) {
530
-            $from_name = substr($this->_from, 0, strpos($this->_from, '<') - 1);
531
-            $from_name = str_replace('"', '', $from_name);
532
-            $from_name = trim($from_name);
533
-
534
-            $from_email = substr($this->_from, strpos($this->_from, '<') + 1);
535
-            $from_email = str_replace('>', '', $from_email);
536
-            $from_email = trim($from_email);
537
-        } elseif (trim($this->_from) !== '') {
538
-            $from_name  = '';
539
-            $from_email = trim($this->_from);
540
-        } else {
541
-            $from_name = $from_email = '';
542
-        }
543
-        return array($from_name, $from_email);
544
-    }
545
-
546
-
547
-    /**
548
-     * Callback for the wp_mail_from filter.
549
-     *
550
-     * @since 4.3.1
551
-     * @param string $from_email What the original from_email is.
552
-     * @return string
553
-     */
554
-    public function set_from_address($from_email)
555
-    {
556
-        $parsed_from = $this->_parse_from();
557
-        // includes fallback if the parsing failed.
558
-        $from_email = is_array($parsed_from) && ! empty($parsed_from[1])
559
-            ? $parsed_from[1]
560
-            : get_bloginfo('admin_email');
561
-        return $from_email;
562
-    }
563
-
564
-
565
-    /**
566
-     * Callback fro the wp_mail_from_name filter.
567
-     *
568
-     * @since 4.3.1
569
-     * @param string $from_name The original from_name.
570
-     * @return string
571
-     */
572
-    public function set_from_name($from_name)
573
-    {
574
-        $parsed_from = $this->_parse_from();
575
-        if (is_array($parsed_from) && ! empty($parsed_from[0])) {
576
-            $from_name = $parsed_from[0];
577
-        }
578
-
579
-        // if from name is "WordPress" let's sub in the site name instead (more friendly!)
580
-        // but realize the default name is HTML entity-encoded
581
-        $from_name = $from_name == 'WordPress' ? wp_specialchars_decode(get_bloginfo(), ENT_QUOTES) : $from_name;
582
-
583
-        return $from_name;
584
-    }
585
-
586
-
587
-    /**
588
-     * setup body for email
589
-     *
590
-     * @param bool $preview will determine whether this is preview template or not.
591
-     * @return string formatted body for email.
592
-     * @throws EE_Error
593
-     * @throws \TijsVerkoyen\CssToInlineStyles\Exception
594
-     */
595
-    protected function _body($preview = false)
596
-    {
597
-        // setup template args!
598
-        $this->_template_args = array(
599
-            'subject'   => $this->_subject,
600
-            'from'      => $this->_from,
601
-            'main_body' => wpautop($this->_content),
602
-        );
603
-        $body                 = $this->_get_main_template($preview);
604
-
605
-        /**
606
-         * This filter allows one to bypass the CSSToInlineStyles tool and leave the body untouched.
607
-         *
608
-         * @type    bool $preview Indicates whether a preview is being generated or not.
609
-         * @return  bool    true  indicates to use the inliner, false bypasses it.
610
-         */
611
-        if (apply_filters('FHEE__EE_Email_messenger__apply_CSSInliner ', true, $preview)) {
612
-            // require CssToInlineStyles library and its dependencies via composer autoloader
613
-            require_once EE_THIRD_PARTY . 'cssinliner/vendor/autoload.php';
614
-
615
-            // now if this isn't a preview, let's setup the body so it has inline styles
616
-            if (! $preview || ($preview && defined('DOING_AJAX'))) {
617
-                $style = file_get_contents(
618
-                    $this->get_variation(
619
-                        $this->_tmp_pack,
620
-                        $this->_incoming_message_type->name,
621
-                        false,
622
-                        'main',
623
-                        $this->_variation
624
-                    ),
625
-                    true
626
-                );
627
-                $CSS   = new TijsVerkoyen\CssToInlineStyles\CssToInlineStyles($body, $style);
628
-                // for some reason the library has a bracket and new line at the beginning.  This takes care of that.
629
-                $body  = ltrim($CSS->convert(true), ">\n");
630
-                // see https://events.codebasehq.com/projects/event-espresso/tickets/8609
631
-                $body  = ltrim($body, "<?");
632
-            }
633
-        }
634
-        return $body;
635
-    }
636
-
637
-
638
-    /**
639
-     * This just returns any existing test settings that might be saved in the database
640
-     *
641
-     * @access public
642
-     * @return array
643
-     */
644
-    public function get_existing_test_settings()
645
-    {
646
-        $settings = parent::get_existing_test_settings();
647
-        // override subject if present because we always want it to be fresh.
648
-        if (is_array($settings) && ! empty($settings['subject'])) {
649
-            $settings['subject'] = sprintf(__('Test email sent from %s', 'event_espresso'), get_bloginfo('name'));
650
-        }
651
-        return $settings;
652
-    }
9
+	/**
10
+	 * To field for email
11
+	 * @var string
12
+	 */
13
+	protected $_to = '';
14
+
15
+
16
+	/**
17
+	 * CC field for email.
18
+	 * @var string
19
+	 */
20
+	protected $_cc = '';
21
+
22
+	/**
23
+	 * From field for email
24
+	 * @var string
25
+	 */
26
+	protected $_from = '';
27
+
28
+
29
+	/**
30
+	 * Subject field for email
31
+	 * @var string
32
+	 */
33
+	protected $_subject = '';
34
+
35
+
36
+	/**
37
+	 * Content field for email
38
+	 * @var string
39
+	 */
40
+	protected $_content = '';
41
+
42
+
43
+	/**
44
+	 * constructor
45
+	 *
46
+	 * @access public
47
+	 */
48
+	public function __construct()
49
+	{
50
+		// set name and description properties
51
+		$this->name                = 'email';
52
+		$this->description         = sprintf(
53
+			esc_html__(
54
+				'This messenger delivers messages via email using the built-in %s function included with WordPress',
55
+				'event_espresso'
56
+			),
57
+			'<code>wp_mail</code>'
58
+		);
59
+		$this->label               = array(
60
+			'singular' => esc_html__('email', 'event_espresso'),
61
+			'plural'   => esc_html__('emails', 'event_espresso'),
62
+		);
63
+		$this->activate_on_install = true;
64
+
65
+		// we're using defaults so let's call parent constructor that will take care of setting up all the other
66
+		// properties
67
+		parent::__construct();
68
+	}
69
+
70
+
71
+	/**
72
+	 * see abstract declaration in parent class for details.
73
+	 */
74
+	protected function _set_admin_pages()
75
+	{
76
+		$this->admin_registered_pages = array(
77
+			'events_edit' => true,
78
+		);
79
+	}
80
+
81
+
82
+	/**
83
+	 * see abstract declaration in parent class for details
84
+	 */
85
+	protected function _set_valid_shortcodes()
86
+	{
87
+		// remember by leaving the other fields not set, those fields will inherit the valid shortcodes from the
88
+		// message type.
89
+		$this->_valid_shortcodes = array(
90
+			'to'   => array('email', 'event_author', 'primary_registration_details', 'recipient_details'),
91
+			'cc' => array('email', 'event_author', 'primary_registration_details', 'recipient_details'),
92
+			'from' => array('email', 'event_author', 'primary_registration_details', 'recipient_details'),
93
+		);
94
+	}
95
+
96
+
97
+	/**
98
+	 * see abstract declaration in parent class for details
99
+	 *
100
+	 * @access protected
101
+	 * @return void
102
+	 */
103
+	protected function _set_validator_config()
104
+	{
105
+		$valid_shortcodes = $this->get_valid_shortcodes();
106
+
107
+		$this->_validator_config = array(
108
+			'to'            => array(
109
+				'shortcodes' => $valid_shortcodes['to'],
110
+				'type'       => 'email',
111
+			),
112
+			'cc' => array(
113
+				'shortcodes' => $valid_shortcodes['to'],
114
+				'type' => 'email',
115
+			),
116
+			'from'          => array(
117
+				'shortcodes' => $valid_shortcodes['from'],
118
+				'type'       => 'email',
119
+			),
120
+			'subject'       => array(
121
+				'shortcodes' => array(
122
+					'organization',
123
+					'primary_registration_details',
124
+					'event_author',
125
+					'primary_registration_details',
126
+					'recipient_details',
127
+				),
128
+			),
129
+			'content'       => array(
130
+				'shortcodes' => array(
131
+					'event_list',
132
+					'attendee_list',
133
+					'ticket_list',
134
+					'organization',
135
+					'primary_registration_details',
136
+					'primary_registration_list',
137
+					'event_author',
138
+					'recipient_details',
139
+					'recipient_list',
140
+					'transaction',
141
+					'messenger',
142
+				),
143
+			),
144
+			'attendee_list' => array(
145
+				'shortcodes' => array('attendee', 'event_list', 'ticket_list'),
146
+				'required'   => array('[ATTENDEE_LIST]'),
147
+			),
148
+			'event_list'    => array(
149
+				'shortcodes' => array(
150
+					'event',
151
+					'attendee_list',
152
+					'ticket_list',
153
+					'venue',
154
+					'datetime_list',
155
+					'attendee',
156
+					'primary_registration_details',
157
+					'primary_registration_list',
158
+					'event_author',
159
+					'recipient_details',
160
+					'recipient_list',
161
+				),
162
+				'required'   => array('[EVENT_LIST]'),
163
+			),
164
+			'ticket_list'   => array(
165
+				'shortcodes' => array(
166
+					'event_list',
167
+					'attendee_list',
168
+					'ticket',
169
+					'datetime_list',
170
+					'primary_registration_details',
171
+					'recipient_details',
172
+				),
173
+				'required'   => array('[TICKET_LIST]'),
174
+			),
175
+			'datetime_list' => array(
176
+				'shortcodes' => array('datetime'),
177
+				'required'   => array('[DATETIME_LIST]'),
178
+			),
179
+		);
180
+	}
181
+
182
+
183
+	/**
184
+	 * @see   parent EE_messenger class for docs
185
+	 * @since 4.5.0
186
+	 */
187
+	public function do_secondary_messenger_hooks($sending_messenger_name)
188
+	{
189
+		if ($sending_messenger_name === 'html') {
190
+			add_filter('FHEE__EE_Messages_Template_Pack__get_variation', array($this, 'add_email_css'), 10, 8);
191
+		}
192
+	}
193
+
194
+
195
+	public function add_email_css(
196
+		$variation_path,
197
+		$messenger,
198
+		$message_type,
199
+		$type,
200
+		$variation,
201
+		$file_extension,
202
+		$url,
203
+		EE_Messages_Template_Pack $template_pack
204
+	) {
205
+		// prevent recursion on this callback.
206
+		remove_filter('FHEE__EE_Messages_Template_Pack__get_variation', array($this, 'add_email_css'), 10);
207
+		$variation = $this->get_variation($template_pack, $message_type, $url, 'main', $variation, false);
208
+
209
+		add_filter('FHEE__EE_Messages_Template_Pack__get_variation', array($this, 'add_email_css'), 10, 8);
210
+		return $variation;
211
+	}
212
+
213
+
214
+	/**
215
+	 * See parent for details
216
+	 *
217
+	 * @access protected
218
+	 * @return void
219
+	 */
220
+	protected function _set_test_settings_fields()
221
+	{
222
+		$this->_test_settings_fields = array(
223
+			'to'      => array(
224
+				'input'      => 'text',
225
+				'label'      => esc_html__('Send a test email to', 'event_espresso'),
226
+				'type'       => 'email',
227
+				'required'   => true,
228
+				'validation' => true,
229
+				'css_class'  => 'large-text',
230
+				'format'     => '%s',
231
+				'default'    => get_bloginfo('admin_email'),
232
+			),
233
+			'subject' => array(
234
+				'input'      => 'hidden',
235
+				'label'      => '',
236
+				'type'       => 'string',
237
+				'required'   => false,
238
+				'validation' => false,
239
+				'format'     => '%s',
240
+				'value'      => sprintf(__('Test email sent from %s', 'event_espresso'), get_bloginfo('name')),
241
+				'default'    => '',
242
+				'css_class'  => '',
243
+			),
244
+		);
245
+	}
246
+
247
+
248
+	/**
249
+	 * _set_template_fields
250
+	 * This sets up the fields that a messenger requires for the message to go out.
251
+	 *
252
+	 * @access  protected
253
+	 * @return void
254
+	 */
255
+	protected function _set_template_fields()
256
+	{
257
+		// any extra template fields that are NOT used by the messenger but will get used by a messenger field for
258
+		// shortcode replacement get added to the 'extra' key in an associated array indexed by the messenger field
259
+		// they relate to.  This is important for the Messages_admin to know what fields to display to the user.
260
+		//  Also, notice that the "values" are equal to the field type that messages admin will use to know what
261
+		// kind of field to display. The values ALSO have one index labeled "shortcode".  the values in that array
262
+		// indicate which ACTUAL SHORTCODE (i.e. [SHORTCODE]) is required in order for this extra field to be
263
+		// displayed.  If the required shortcode isn't part of the shortcodes array then the field is not needed and
264
+		// will not be displayed/parsed.
265
+		$this->_template_fields = array(
266
+			'to'      => array(
267
+				'input'      => 'text',
268
+				'label'      => esc_html_x(
269
+					'To',
270
+					'Label for the "To" field for email addresses',
271
+					'event_espresso'
272
+				),
273
+				'type'       => 'string',
274
+				'required'   => true,
275
+				'validation' => true,
276
+				'css_class'  => 'large-text',
277
+				'format'     => '%s',
278
+			),
279
+			'cc'      => array(
280
+				'input'      => 'text',
281
+				'label'      => esc_html_x(
282
+					'CC',
283
+					'Label for the "Carbon Copy" field used for additional email addresses',
284
+					'event_espresso'
285
+				),
286
+				'type'       => 'string',
287
+				'required'   => false,
288
+				'validation' => true,
289
+				'css_class'  => 'large-text',
290
+				'format'     => '%s',
291
+			),
292
+			'from'    => array(
293
+				'input'      => 'text',
294
+				'label'      => esc_html_x(
295
+					'From',
296
+					'Label for the "From" field for email addresses.',
297
+					'event_espresso'
298
+				),
299
+				'type'       => 'string',
300
+				'required'   => true,
301
+				'validation' => true,
302
+				'css_class'  => 'large-text',
303
+				'format'     => '%s',
304
+			),
305
+			'subject' => array(
306
+				'input'      => 'text',
307
+				'label'      => esc_html_x(
308
+					'Subject',
309
+					'Label for the "Subject" field (short description of contents) for emails.',
310
+					'event_espresso'
311
+				),
312
+				'type'       => 'string',
313
+				'required'   => true,
314
+				'validation' => true,
315
+				'css_class'  => 'large-text',
316
+				'format'     => '%s',
317
+			),
318
+			'content' => '',
319
+			// left empty b/c it is in the "extra array" but messenger still needs needs to know this is a field.
320
+			'extra'   => array(
321
+				'content' => array(
322
+					'main'          => array(
323
+						'input'      => 'wp_editor',
324
+						'label'      => esc_html__('Main Content', 'event_espresso'),
325
+						'type'       => 'string',
326
+						'required'   => true,
327
+						'validation' => true,
328
+						'format'     => '%s',
329
+						'rows'       => '15',
330
+					),
331
+					'event_list'    => array(
332
+						'input'               => 'wp_editor',
333
+						'label'               => '[EVENT_LIST]',
334
+						'type'                => 'string',
335
+						'required'            => true,
336
+						'validation'          => true,
337
+						'format'              => '%s',
338
+						'rows'                => '15',
339
+						'shortcodes_required' => array('[EVENT_LIST]'),
340
+					),
341
+					'attendee_list' => array(
342
+						'input'               => 'textarea',
343
+						'label'               => '[ATTENDEE_LIST]',
344
+						'type'                => 'string',
345
+						'required'            => true,
346
+						'validation'          => true,
347
+						'format'              => '%s',
348
+						'css_class'           => 'large-text',
349
+						'rows'                => '5',
350
+						'shortcodes_required' => array('[ATTENDEE_LIST]'),
351
+					),
352
+					'ticket_list'   => array(
353
+						'input'               => 'textarea',
354
+						'label'               => '[TICKET_LIST]',
355
+						'type'                => 'string',
356
+						'required'            => true,
357
+						'validation'          => true,
358
+						'format'              => '%s',
359
+						'css_class'           => 'large-text',
360
+						'rows'                => '10',
361
+						'shortcodes_required' => array('[TICKET_LIST]'),
362
+					),
363
+					'datetime_list' => array(
364
+						'input'               => 'textarea',
365
+						'label'               => '[DATETIME_LIST]',
366
+						'type'                => 'string',
367
+						'required'            => true,
368
+						'validation'          => true,
369
+						'format'              => '%s',
370
+						'css_class'           => 'large-text',
371
+						'rows'                => '10',
372
+						'shortcodes_required' => array('[DATETIME_LIST]'),
373
+					),
374
+				),
375
+			),
376
+		);
377
+	}
378
+
379
+
380
+	/**
381
+	 * See definition of this class in parent
382
+	 */
383
+	protected function _set_default_message_types()
384
+	{
385
+		$this->_default_message_types = array(
386
+			'payment',
387
+			'payment_refund',
388
+			'registration',
389
+			'not_approved_registration',
390
+			'pending_approval',
391
+		);
392
+	}
393
+
394
+
395
+	/**
396
+	 * @see   definition of this class in parent
397
+	 * @since 4.5.0
398
+	 */
399
+	protected function _set_valid_message_types()
400
+	{
401
+		$this->_valid_message_types = array(
402
+			'payment',
403
+			'registration',
404
+			'not_approved_registration',
405
+			'declined_registration',
406
+			'cancelled_registration',
407
+			'pending_approval',
408
+			'registration_summary',
409
+			'payment_reminder',
410
+			'payment_declined',
411
+			'payment_refund',
412
+		);
413
+	}
414
+
415
+
416
+	/**
417
+	 * setting up admin_settings_fields for messenger.
418
+	 */
419
+	protected function _set_admin_settings_fields()
420
+	{
421
+	}
422
+
423
+	/**
424
+	 * We just deliver the messages don't kill us!!
425
+	 *
426
+	 * @return bool|WP_Error true if message delivered, false if it didn't deliver OR bubble up any error object if
427
+	 *              present.
428
+	 * @throws EE_Error
429
+	 * @throws \TijsVerkoyen\CssToInlineStyles\Exception
430
+	 */
431
+	protected function _send_message()
432
+	{
433
+		$success = wp_mail(
434
+			$this->_to,
435
+			// some old values for subject may be expecting HTML entities to be decoded in the subject
436
+			// and subjects aren't interpreted as HTML, so there should be no HTML in them
437
+			wp_strip_all_tags(wp_specialchars_decode($this->_subject, ENT_QUOTES)),
438
+			$this->_body(),
439
+			$this->_headers()
440
+		);
441
+		if (! $success) {
442
+			EE_Error::add_error(
443
+				sprintf(
444
+					esc_html__(
445
+						'The email did not send successfully.%3$sThe WordPress wp_mail function is used for sending mails but does not give any useful information when an email fails to send.%3$sIt is possible the "to" address (%1$s) or "from" address (%2$s) is invalid.%3$s',
446
+						'event_espresso'
447
+					),
448
+					$this->_to,
449
+					$this->_from,
450
+					'<br />'
451
+				),
452
+				__FILE__,
453
+				__FUNCTION__,
454
+				__LINE__
455
+			);
456
+		}
457
+		return $success;
458
+	}
459
+
460
+
461
+	/**
462
+	 * see parent for definition
463
+	 *
464
+	 * @return string html body of the message content and the related css.
465
+	 * @throws EE_Error
466
+	 * @throws \TijsVerkoyen\CssToInlineStyles\Exception
467
+	 */
468
+	protected function _preview()
469
+	{
470
+		return $this->_body(true);
471
+	}
472
+
473
+
474
+	/**
475
+	 * Setup headers for email
476
+	 *
477
+	 * @access protected
478
+	 * @return string formatted header for email
479
+	 */
480
+	protected function _headers()
481
+	{
482
+		$this->_ensure_has_from_email_address();
483
+		$from    = $this->_from;
484
+		$headers = array(
485
+			'From:' . $from,
486
+			'Reply-To:' . $from,
487
+			'Content-Type:text/html; charset=utf-8',
488
+		);
489
+
490
+		/**
491
+		 * Second condition added as a result of https://events.codebasehq.com/projects/event-espresso/tickets/11416 to
492
+		 * cover back compat where there may be users who have saved cc values in their db for the newsletter message
493
+		 * type which they are no longer able to change.
494
+		 */
495
+		if (! empty($this->_cc) && ! $this->_incoming_message_type instanceof EE_Newsletter_message_type) {
496
+			$headers[] = 'cc: ' . $this->_cc;
497
+		}
498
+
499
+		// but wait!  Header's for the from is NOT reliable because some plugins don't respect From: as set in the
500
+		// header.
501
+		add_filter('wp_mail_from', array($this, 'set_from_address'), 100);
502
+		add_filter('wp_mail_from_name', array($this, 'set_from_name'), 100);
503
+		return apply_filters('FHEE__EE_Email_messenger___headers', $headers, $this->_incoming_message_type, $this);
504
+	}
505
+
506
+
507
+	/**
508
+	 * This simply ensures that the from address is not empty.  If it is, then we use whatever is set as the site email
509
+	 * address for the from address to avoid problems with sending emails.
510
+	 */
511
+	protected function _ensure_has_from_email_address()
512
+	{
513
+		if (empty($this->_from)) {
514
+			$this->_from = get_bloginfo('admin_email');
515
+		}
516
+	}
517
+
518
+
519
+	/**
520
+	 * This simply parses whatever is set as the $_from address and determines if it is in the format {name} <{email}>
521
+	 * or just {email} and returns an array with the "from_name" and "from_email" as the values. Note from_name *MAY*
522
+	 * be empty
523
+	 *
524
+	 * @since 4.3.1
525
+	 * @return array
526
+	 */
527
+	private function _parse_from()
528
+	{
529
+		if (strpos($this->_from, '<') !== false) {
530
+			$from_name = substr($this->_from, 0, strpos($this->_from, '<') - 1);
531
+			$from_name = str_replace('"', '', $from_name);
532
+			$from_name = trim($from_name);
533
+
534
+			$from_email = substr($this->_from, strpos($this->_from, '<') + 1);
535
+			$from_email = str_replace('>', '', $from_email);
536
+			$from_email = trim($from_email);
537
+		} elseif (trim($this->_from) !== '') {
538
+			$from_name  = '';
539
+			$from_email = trim($this->_from);
540
+		} else {
541
+			$from_name = $from_email = '';
542
+		}
543
+		return array($from_name, $from_email);
544
+	}
545
+
546
+
547
+	/**
548
+	 * Callback for the wp_mail_from filter.
549
+	 *
550
+	 * @since 4.3.1
551
+	 * @param string $from_email What the original from_email is.
552
+	 * @return string
553
+	 */
554
+	public function set_from_address($from_email)
555
+	{
556
+		$parsed_from = $this->_parse_from();
557
+		// includes fallback if the parsing failed.
558
+		$from_email = is_array($parsed_from) && ! empty($parsed_from[1])
559
+			? $parsed_from[1]
560
+			: get_bloginfo('admin_email');
561
+		return $from_email;
562
+	}
563
+
564
+
565
+	/**
566
+	 * Callback fro the wp_mail_from_name filter.
567
+	 *
568
+	 * @since 4.3.1
569
+	 * @param string $from_name The original from_name.
570
+	 * @return string
571
+	 */
572
+	public function set_from_name($from_name)
573
+	{
574
+		$parsed_from = $this->_parse_from();
575
+		if (is_array($parsed_from) && ! empty($parsed_from[0])) {
576
+			$from_name = $parsed_from[0];
577
+		}
578
+
579
+		// if from name is "WordPress" let's sub in the site name instead (more friendly!)
580
+		// but realize the default name is HTML entity-encoded
581
+		$from_name = $from_name == 'WordPress' ? wp_specialchars_decode(get_bloginfo(), ENT_QUOTES) : $from_name;
582
+
583
+		return $from_name;
584
+	}
585
+
586
+
587
+	/**
588
+	 * setup body for email
589
+	 *
590
+	 * @param bool $preview will determine whether this is preview template or not.
591
+	 * @return string formatted body for email.
592
+	 * @throws EE_Error
593
+	 * @throws \TijsVerkoyen\CssToInlineStyles\Exception
594
+	 */
595
+	protected function _body($preview = false)
596
+	{
597
+		// setup template args!
598
+		$this->_template_args = array(
599
+			'subject'   => $this->_subject,
600
+			'from'      => $this->_from,
601
+			'main_body' => wpautop($this->_content),
602
+		);
603
+		$body                 = $this->_get_main_template($preview);
604
+
605
+		/**
606
+		 * This filter allows one to bypass the CSSToInlineStyles tool and leave the body untouched.
607
+		 *
608
+		 * @type    bool $preview Indicates whether a preview is being generated or not.
609
+		 * @return  bool    true  indicates to use the inliner, false bypasses it.
610
+		 */
611
+		if (apply_filters('FHEE__EE_Email_messenger__apply_CSSInliner ', true, $preview)) {
612
+			// require CssToInlineStyles library and its dependencies via composer autoloader
613
+			require_once EE_THIRD_PARTY . 'cssinliner/vendor/autoload.php';
614
+
615
+			// now if this isn't a preview, let's setup the body so it has inline styles
616
+			if (! $preview || ($preview && defined('DOING_AJAX'))) {
617
+				$style = file_get_contents(
618
+					$this->get_variation(
619
+						$this->_tmp_pack,
620
+						$this->_incoming_message_type->name,
621
+						false,
622
+						'main',
623
+						$this->_variation
624
+					),
625
+					true
626
+				);
627
+				$CSS   = new TijsVerkoyen\CssToInlineStyles\CssToInlineStyles($body, $style);
628
+				// for some reason the library has a bracket and new line at the beginning.  This takes care of that.
629
+				$body  = ltrim($CSS->convert(true), ">\n");
630
+				// see https://events.codebasehq.com/projects/event-espresso/tickets/8609
631
+				$body  = ltrim($body, "<?");
632
+			}
633
+		}
634
+		return $body;
635
+	}
636
+
637
+
638
+	/**
639
+	 * This just returns any existing test settings that might be saved in the database
640
+	 *
641
+	 * @access public
642
+	 * @return array
643
+	 */
644
+	public function get_existing_test_settings()
645
+	{
646
+		$settings = parent::get_existing_test_settings();
647
+		// override subject if present because we always want it to be fresh.
648
+		if (is_array($settings) && ! empty($settings['subject'])) {
649
+			$settings['subject'] = sprintf(__('Test email sent from %s', 'event_espresso'), get_bloginfo('name'));
650
+		}
651
+		return $settings;
652
+	}
653 653
 }
Please login to merge, or discard this patch.
core/domain/services/event/EventSpacesCalculator.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -164,7 +164,7 @@
 block discarded – undo
164 164
 
165 165
 
166 166
     /**
167
-     * @param $ticket
167
+     * @param \EE_Base_Class $ticket
168 168
      * @throws DomainException
169 169
      * @throws EE_Error
170 170
      * @throws UnexpectedEntityException
Please login to merge, or discard this patch.
Indentation   +715 added lines, -715 removed lines patch added patch discarded remove patch
@@ -26,719 +26,719 @@
 block discarded – undo
26 26
 class EventSpacesCalculator
27 27
 {
28 28
 
29
-    /**
30
-     * @var EE_Event $event
31
-     */
32
-    private $event;
33
-
34
-    /**
35
-     * @var array $datetime_query_params
36
-     */
37
-    private $datetime_query_params;
38
-
39
-    /**
40
-     * @var EE_Ticket[] $active_tickets
41
-     */
42
-    private $active_tickets = array();
43
-
44
-    /**
45
-     * @var EE_Datetime[] $datetimes
46
-     */
47
-    private $datetimes = array();
48
-
49
-    /**
50
-     * Array of Ticket IDs grouped by Datetime
51
-     *
52
-     * @var array $datetimes
53
-     */
54
-    private $datetime_tickets = array();
55
-
56
-    /**
57
-     * Max spaces for each Datetime (reg limit - previous sold)
58
-     *
59
-     * @var array $datetime_spaces
60
-     */
61
-    private $datetime_spaces = array();
62
-
63
-    /**
64
-     * Array of Datetime IDs grouped by Ticket
65
-     *
66
-     * @var array[] $ticket_datetimes
67
-     */
68
-    private $ticket_datetimes = array();
69
-
70
-    /**
71
-     * maximum ticket quantities for each ticket (adjusted for reg limit)
72
-     *
73
-     * @var array $ticket_quantities
74
-     */
75
-    private $ticket_quantities = array();
76
-
77
-    /**
78
-     * total quantity of sold and reserved for each ticket
79
-     *
80
-     * @var array $tickets_sold
81
-     */
82
-    private $tickets_sold = array();
83
-
84
-    /**
85
-     * total spaces available across all datetimes
86
-     *
87
-     * @var array $total_spaces
88
-     */
89
-    private $total_spaces = array();
90
-
91
-    /**
92
-     * @var boolean $debug
93
-     */
94
-    private $debug = false; // true false
95
-
96
-    /**
97
-     * @var null|int $spaces_remaining
98
-     */
99
-    private $spaces_remaining;
100
-
101
-    /**
102
-     * @var null|int $total_spaces_available
103
-     */
104
-    private $total_spaces_available;
105
-
106
-
107
-    /**
108
-     * EventSpacesCalculator constructor.
109
-     *
110
-     * @param EE_Event $event
111
-     * @param array    $datetime_query_params
112
-     * @throws EE_Error
113
-     */
114
-    public function __construct(EE_Event $event, array $datetime_query_params = array())
115
-    {
116
-        if ($this->debug) {
117
-            \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 1);
118
-            \EEH_Debug_Tools::printr((string) $event->ID(), 'For event', __FILE__, __LINE__);
119
-        }
120
-        $this->event = $event;
121
-        $this->datetime_query_params = $datetime_query_params + array('order_by' => array('DTT_reg_limit' => 'ASC'));
122
-        $this->setHooks();
123
-    }
124
-
125
-
126
-    /**
127
-     * @return void
128
-     */
129
-    private function setHooks()
130
-    {
131
-        add_action('AHEE__EE_Ticket__increase_sold', array($this, 'clearResults'));
132
-        add_action('AHEE__EE_Ticket__decrease_sold', array($this, 'clearResults'));
133
-        add_action('AHEE__EE_Datetime__increase_sold', array($this, 'clearResults'));
134
-        add_action('AHEE__EE_Datetime__decrease_sold', array($this, 'clearResults'));
135
-        add_action('AHEE__EE_Ticket__increase_reserved', array($this, 'clearResults'));
136
-        add_action('AHEE__EE_Ticket__decrease_reserved', array($this, 'clearResults'));
137
-        add_action('AHEE__EE_Datetime__increase_reserved', array($this, 'clearResults'));
138
-        add_action('AHEE__EE_Datetime__decrease_reserved', array($this, 'clearResults'));
139
-    }
140
-
141
-
142
-    /**
143
-     * @return void
144
-     */
145
-    public function clearResults()
146
-    {
147
-        if ($this->debug) {
148
-            \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 1);
149
-        }
150
-        $this->spaces_remaining = null;
151
-        $this->total_spaces_available = null;
152
-    }
153
-
154
-
155
-    /**
156
-     * @return EE_Ticket[]
157
-     * @throws EE_Error
158
-     * @throws InvalidDataTypeException
159
-     * @throws InvalidInterfaceException
160
-     * @throws InvalidArgumentException
161
-     */
162
-    public function getActiveTickets()
163
-    {
164
-        if (empty($this->active_tickets)) {
165
-            $this->active_tickets = $this->event->tickets(
166
-                array(
167
-                    array('TKT_deleted' => false),
168
-                    'order_by' => array('TKT_qty' => 'ASC'),
169
-                )
170
-            );
171
-        }
172
-        return $this->active_tickets;
173
-    }
174
-
175
-
176
-    /**
177
-     * @param EE_Ticket[] $active_tickets
178
-     * @throws EE_Error
179
-     * @throws DomainException
180
-     * @throws UnexpectedEntityException
181
-     */
182
-    public function setActiveTickets(array $active_tickets = array())
183
-    {
184
-        if (! empty($active_tickets)) {
185
-            foreach ($active_tickets as $active_ticket) {
186
-                $this->validateTicket($active_ticket);
187
-            }
188
-            // sort incoming array by ticket quantity (asc)
189
-            usort(
190
-                $active_tickets,
191
-                function (EE_Ticket $a, EE_Ticket $b) {
192
-                    if ($a->qty() === $b->qty()) {
193
-                        return 0;
194
-                    }
195
-                    return ($a->qty() < $b->qty())
196
-                        ? -1
197
-                        : 1;
198
-                }
199
-            );
200
-        }
201
-        $this->active_tickets = $active_tickets;
202
-    }
203
-
204
-
205
-    /**
206
-     * @param $ticket
207
-     * @throws DomainException
208
-     * @throws EE_Error
209
-     * @throws UnexpectedEntityException
210
-     */
211
-    private function validateTicket($ticket)
212
-    {
213
-        if (! $ticket instanceof EE_Ticket) {
214
-            throw new DomainException(
215
-                esc_html__(
216
-                    'Invalid Ticket. Only EE_Ticket objects can be used to calculate event space availability.',
217
-                    'event_espresso'
218
-                )
219
-            );
220
-        }
221
-        if ($ticket->get_event_ID() !== $this->event->ID()) {
222
-            throw new DomainException(
223
-                sprintf(
224
-                    esc_html__(
225
-                        'An EE_Ticket for Event %1$d was supplied while calculating event space availability for Event %2$d.',
226
-                        'event_espresso'
227
-                    ),
228
-                    $ticket->get_event_ID(),
229
-                    $this->event->ID()
230
-                )
231
-            );
232
-        }
233
-    }
234
-
235
-
236
-    /**
237
-     * @return EE_Datetime[]
238
-     */
239
-    public function getDatetimes()
240
-    {
241
-        return $this->datetimes;
242
-    }
243
-
244
-
245
-    /**
246
-     * @param EE_Datetime $datetime
247
-     * @throws EE_Error
248
-     * @throws DomainException
249
-     */
250
-    public function setDatetime(EE_Datetime $datetime)
251
-    {
252
-        if ($datetime->event()->ID() !== $this->event->ID()) {
253
-            throw new DomainException(
254
-                sprintf(
255
-                    esc_html__(
256
-                        'An EE_Datetime for Event %1$d was supplied while calculating event space availability for Event %2$d.',
257
-                        'event_espresso'
258
-                    ),
259
-                    $datetime->event()->ID(),
260
-                    $this->event->ID()
261
-                )
262
-            );
263
-        }
264
-        $this->datetimes[ $datetime->ID() ] = $datetime;
265
-    }
266
-
267
-
268
-    /**
269
-     * calculate spaces remaining based on "saleable" tickets
270
-     *
271
-     * @return float|int
272
-     * @throws EE_Error
273
-     * @throws DomainException
274
-     * @throws UnexpectedEntityException
275
-     * @throws InvalidDataTypeException
276
-     * @throws InvalidInterfaceException
277
-     * @throws InvalidArgumentException
278
-     */
279
-    public function spacesRemaining()
280
-    {
281
-        if ($this->debug) {
282
-            \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
283
-        }
284
-        if ($this->spaces_remaining === null) {
285
-            $this->initialize();
286
-            $this->spaces_remaining = $this->calculate();
287
-        }
288
-        return $this->spaces_remaining;
289
-    }
290
-
291
-
292
-    /**
293
-     * calculates total available spaces for an event with no regard for sold tickets
294
-     *
295
-     * @return int|float
296
-     * @throws EE_Error
297
-     * @throws DomainException
298
-     * @throws UnexpectedEntityException
299
-     * @throws InvalidDataTypeException
300
-     * @throws InvalidInterfaceException
301
-     * @throws InvalidArgumentException
302
-     */
303
-    public function totalSpacesAvailable()
304
-    {
305
-        if ($this->debug) {
306
-            \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
307
-        }
308
-        if ($this->total_spaces_available === null) {
309
-            $this->initialize();
310
-            $this->total_spaces_available = $this->calculate(false);
311
-        }
312
-        return $this->total_spaces_available;
313
-    }
314
-
315
-
316
-    /**
317
-     * Loops through the active tickets for the event
318
-     * and builds a series of data arrays that will be used for calculating
319
-     * the total maximum available spaces, as well as the spaces remaining.
320
-     * Because ticket quantities affect datetime spaces and vice versa,
321
-     * we need to be constantly updating these data arrays as things change,
322
-     * which is the entire reason for their existence.
323
-     *
324
-     * @throws EE_Error
325
-     * @throws DomainException
326
-     * @throws UnexpectedEntityException
327
-     * @throws InvalidDataTypeException
328
-     * @throws InvalidInterfaceException
329
-     * @throws InvalidArgumentException
330
-     */
331
-    private function initialize()
332
-    {
333
-        if ($this->debug) {
334
-            \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
335
-        }
336
-        $this->datetime_tickets = array();
337
-        $this->datetime_spaces = array();
338
-        $this->ticket_datetimes = array();
339
-        $this->ticket_quantities = array();
340
-        $this->tickets_sold = array();
341
-        $this->total_spaces = array();
342
-        $active_tickets = $this->getActiveTickets();
343
-        if (! empty($active_tickets)) {
344
-            foreach ($active_tickets as $ticket) {
345
-                $this->validateTicket($ticket);
346
-                // we need to index our data arrays using strings for the purpose of sorting,
347
-                // but we also need them to be unique, so  we'll just prepend a letter T to the ID
348
-                $ticket_identifier = "T{$ticket->ID()}";
349
-                // to start, we'll just consider the raw qty to be the maximum availability for this ticket,
350
-                // unless the ticket is past its "sell until" date, in which case the qty will be 0
351
-                $max_tickets = $ticket->is_expired() ? 0 : $ticket->qty();
352
-                // but we'll adjust that after looping over each datetime for the ticket and checking reg limits
353
-                $ticket_datetimes = $ticket->datetimes($this->datetime_query_params);
354
-                foreach ($ticket_datetimes as $datetime) {
355
-                    // save all datetimes
356
-                    $this->setDatetime($datetime);
357
-                    $datetime_identifier = "D{$datetime->ID()}";
358
-                    $reg_limit = $datetime->reg_limit();
359
-                    // ticket quantity can not exceed datetime reg limit
360
-                    $max_tickets = min($max_tickets, $reg_limit);
361
-                    // as described earlier, because we need to be able to constantly adjust numbers for things,
362
-                    // we are going to move all of our data into the following arrays:
363
-                    // datetime spaces initially represents the reg limit for each datetime,
364
-                    // but this will get adjusted as tickets are accounted for
365
-                    $this->datetime_spaces[ $datetime_identifier ] = $reg_limit;
366
-                    // just an array of ticket IDs grouped by datetime
367
-                    $this->datetime_tickets[ $datetime_identifier ][] = $ticket_identifier;
368
-                    // and an array of datetime IDs grouped by ticket
369
-                    $this->ticket_datetimes[ $ticket_identifier ][] = $datetime_identifier;
370
-                }
371
-                // total quantity of sold and reserved for each ticket
372
-                $this->tickets_sold[ $ticket_identifier ] = $ticket->sold() + $ticket->reserved();
373
-                // and the maximum ticket quantities for each ticket (adjusted for reg limit)
374
-                $this->ticket_quantities[ $ticket_identifier ] = $max_tickets;
375
-            }
376
-        }
377
-        // sort datetime spaces by reg limit, but maintain our string indexes
378
-        asort($this->datetime_spaces, SORT_NUMERIC);
379
-        // datetime tickets need to be sorted in the SAME order as the above array...
380
-        // so we'll just use array_merge() to take the structure of datetime_spaces
381
-        // but overwrite all of the data with that from datetime_tickets
382
-        $this->datetime_tickets = array_merge(
383
-            $this->datetime_spaces,
384
-            $this->datetime_tickets
385
-        );
386
-        if ($this->debug) {
387
-            \EEH_Debug_Tools::printr($this->datetime_spaces, 'datetime_spaces', __FILE__, __LINE__);
388
-            \EEH_Debug_Tools::printr($this->datetime_tickets, 'datetime_tickets', __FILE__, __LINE__);
389
-            \EEH_Debug_Tools::printr($this->ticket_quantities, 'ticket_quantities', __FILE__, __LINE__);
390
-        }
391
-    }
392
-
393
-
394
-    /**
395
-     * performs calculations on initialized data
396
-     *
397
-     * @param bool $consider_sold
398
-     * @return int|float
399
-     */
400
-    private function calculate($consider_sold = true)
401
-    {
402
-        if ($this->debug) {
403
-            \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
404
-            \EEH_Debug_Tools::printr($consider_sold, '$consider_sold', __FILE__, __LINE__);
405
-        }
406
-        if ($consider_sold) {
407
-            // subtract amounts sold from all ticket quantities and datetime spaces
408
-            $this->adjustTicketQuantitiesDueToSales();
409
-        }
410
-        foreach ($this->datetime_tickets as $datetime_identifier => $tickets) {
411
-            $this->trackAvailableSpacesForDatetimes($datetime_identifier, $tickets);
412
-        }
413
-        // total spaces available is just the sum of the spaces available for each datetime
414
-        $spaces_remaining = array_sum($this->total_spaces);
415
-        if ($this->debug) {
416
-            \EEH_Debug_Tools::printr($this->total_spaces, '$this->total_spaces', __FILE__, __LINE__);
417
-            \EEH_Debug_Tools::printr($this->tickets_sold, '$this->tickets_sold', __FILE__, __LINE__);
418
-            \EEH_Debug_Tools::printr($spaces_remaining, '$spaces_remaining', __FILE__, __LINE__);
419
-        }
420
-        return $spaces_remaining;
421
-    }
422
-
423
-
424
-    /**
425
-     * subtracts amount of  tickets sold from ticket quantities and datetime spaces
426
-     */
427
-    private function adjustTicketQuantitiesDueToSales()
428
-    {
429
-        if ($this->debug) {
430
-            \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
431
-        }
432
-        foreach ($this->tickets_sold as $ticket_identifier => $tickets_sold) {
433
-            if (isset($this->ticket_quantities[ $ticket_identifier ])) {
434
-                $this->ticket_quantities[ $ticket_identifier ] -= $tickets_sold;
435
-                // don't let values go below zero
436
-                $this->ticket_quantities[ $ticket_identifier ] = max(
437
-                    $this->ticket_quantities[ $ticket_identifier ],
438
-                    0
439
-                );
440
-                if ($this->debug) {
441
-                    \EEH_Debug_Tools::printr(
442
-                        "{$tickets_sold} sales for ticket {$ticket_identifier} ",
443
-                        'subtracting',
444
-                        __FILE__,
445
-                        __LINE__
446
-                    );
447
-                }
448
-            }
449
-            if (
450
-                isset($this->ticket_datetimes[ $ticket_identifier ])
451
-                && is_array($this->ticket_datetimes[ $ticket_identifier ])
452
-            ) {
453
-                foreach ($this->ticket_datetimes[ $ticket_identifier ] as $ticket_datetime) {
454
-                    if (isset($this->ticket_quantities[ $ticket_identifier ])) {
455
-                        $this->datetime_spaces[ $ticket_datetime ] -= $tickets_sold;
456
-                        // don't let values go below zero
457
-                        $this->datetime_spaces[ $ticket_datetime ] = max(
458
-                            $this->datetime_spaces[ $ticket_datetime ],
459
-                            0
460
-                        );
461
-                        if ($this->debug) {
462
-                            \EEH_Debug_Tools::printr(
463
-                                "{$tickets_sold} sales for datetime {$ticket_datetime} ",
464
-                                'subtracting',
465
-                                __FILE__,
466
-                                __LINE__
467
-                            );
468
-                        }
469
-                    }
470
-                }
471
-            }
472
-        }
473
-    }
474
-
475
-
476
-    /**
477
-     * @param string $datetime_identifier
478
-     * @param array  $tickets
479
-     */
480
-    private function trackAvailableSpacesForDatetimes($datetime_identifier, array $tickets)
481
-    {
482
-        // make sure a reg limit is set for the datetime
483
-        $reg_limit = isset($this->datetime_spaces[ $datetime_identifier ])
484
-            ? $this->datetime_spaces[ $datetime_identifier ]
485
-            : 0;
486
-        // and bail if it is not
487
-        if (! $reg_limit) {
488
-            if ($this->debug) {
489
-                \EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__);
490
-            }
491
-            return;
492
-        }
493
-        if ($this->debug) {
494
-            \EEH_Debug_Tools::printr($datetime_identifier, '* $datetime_identifier', __FILE__, __LINE__, 1);
495
-            \EEH_Debug_Tools::printr(
496
-                "{$reg_limit}",
497
-                'REG LIMIT',
498
-                __FILE__,
499
-                __LINE__
500
-            );
501
-        }
502
-        // number of allocated spaces always starts at zero
503
-        $spaces_allocated = 0;
504
-        $this->total_spaces[ $datetime_identifier ] = 0;
505
-        foreach ($tickets as $ticket_identifier) {
506
-            $spaces_allocated = $this->calculateAvailableSpacesForTicket(
507
-                $datetime_identifier,
508
-                $reg_limit,
509
-                $ticket_identifier,
510
-                $spaces_allocated
511
-            );
512
-        }
513
-        // spaces can't be negative
514
-        $spaces_allocated = max($spaces_allocated, 0);
515
-        if ($spaces_allocated) {
516
-            // track any non-zero values
517
-            $this->total_spaces[ $datetime_identifier ] += $spaces_allocated;
518
-            if ($this->debug) {
519
-                \EEH_Debug_Tools::printr((string) $spaces_allocated, ' . $spaces_allocated: ', __FILE__, __LINE__);
520
-            }
521
-        } else {
522
-            if ($this->debug) {
523
-                \EEH_Debug_Tools::printr(' ', ' . NO TICKETS AVAILABLE FOR DATETIME', __FILE__, __LINE__);
524
-            }
525
-        }
526
-        if ($this->debug) {
527
-            \EEH_Debug_Tools::printr(
528
-                $this->total_spaces[ $datetime_identifier ],
529
-                '$total_spaces',
530
-                __FILE__,
531
-                __LINE__
532
-            );
533
-            \EEH_Debug_Tools::printr($this->ticket_quantities, '$ticket_quantities', __FILE__, __LINE__);
534
-            \EEH_Debug_Tools::printr($this->datetime_spaces, 'datetime_spaces', __FILE__, __LINE__);
535
-        }
536
-    }
537
-
538
-
539
-    /**
540
-     * @param string $datetime_identifier
541
-     * @param int    $reg_limit
542
-     * @param string $ticket_identifier
543
-     * @param int    $spaces_allocated
544
-     * @return int
545
-     */
546
-    private function calculateAvailableSpacesForTicket(
547
-        $datetime_identifier,
548
-        $reg_limit,
549
-        $ticket_identifier,
550
-        $spaces_allocated
551
-    ) {
552
-        // make sure ticket quantity is set
553
-        $ticket_quantity = isset($this->ticket_quantities[ $ticket_identifier ])
554
-            ? $this->ticket_quantities[ $ticket_identifier ]
555
-            : 0;
556
-        if ($this->debug) {
557
-            \EEH_Debug_Tools::printr("{$spaces_allocated}", '$spaces_allocated', __FILE__, __LINE__);
558
-            \EEH_Debug_Tools::printr(
559
-                "{$ticket_quantity}",
560
-                "ticket $ticket_identifier quantity: ",
561
-                __FILE__,
562
-                __LINE__,
563
-                2
564
-            );
565
-        }
566
-        if ($ticket_quantity) {
567
-            if ($this->debug) {
568
-                \EEH_Debug_Tools::printr(
569
-                    ($spaces_allocated <= $reg_limit)
570
-                        ? 'true'
571
-                        : 'false',
572
-                    ' . spaces_allocated <= reg_limit = ',
573
-                    __FILE__,
574
-                    __LINE__
575
-                );
576
-            }
577
-            // if the datetime is NOT at full capacity yet
578
-            if ($spaces_allocated <= $reg_limit) {
579
-                // then the maximum ticket quantity we can allocate is the lowest value of either:
580
-                //  the number of remaining spaces for the datetime, which is the limit - spaces already taken
581
-                //  or the maximum ticket quantity
582
-                $ticket_quantity = min($reg_limit - $spaces_allocated, $ticket_quantity);
583
-                // adjust the available quantity in our tracking array
584
-                $this->ticket_quantities[ $ticket_identifier ] -= $ticket_quantity;
585
-                // and increment spaces allocated for this datetime
586
-                $spaces_allocated += $ticket_quantity;
587
-                $at_capacity = $spaces_allocated >= $reg_limit;
588
-                if ($this->debug) {
589
-                    \EEH_Debug_Tools::printr(
590
-                        "{$ticket_quantity} {$ticket_identifier} tickets",
591
-                        ' > > allocate ',
592
-                        __FILE__,
593
-                        __LINE__,
594
-                        3
595
-                    );
596
-                    if ($at_capacity) {
597
-                        \EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__, 3);
598
-                    }
599
-                }
600
-                // now adjust all other datetimes that allow access to this ticket
601
-                $this->adjustDatetimes(
602
-                    $datetime_identifier,
603
-                    $ticket_identifier,
604
-                    $ticket_quantity,
605
-                    $at_capacity
606
-                );
607
-            }
608
-        }
609
-        return $spaces_allocated;
610
-    }
611
-
612
-
613
-    /**
614
-     * subtracts ticket amounts from all datetime reg limits
615
-     * that allow access to the ticket specified,
616
-     * because that ticket could be used
617
-     * to attend any of the datetimes it has access to
618
-     *
619
-     * @param string $datetime_identifier
620
-     * @param string $ticket_identifier
621
-     * @param bool   $at_capacity
622
-     * @param int    $ticket_quantity
623
-     */
624
-    private function adjustDatetimes(
625
-        $datetime_identifier,
626
-        $ticket_identifier,
627
-        $ticket_quantity,
628
-        $at_capacity
629
-    ) {
630
-        /** @var array $datetime_tickets */
631
-        foreach ($this->datetime_tickets as $datetime_ID => $datetime_tickets) {
632
-            if ($datetime_ID !== $datetime_identifier || ! is_array($datetime_tickets)) {
633
-                continue;
634
-            }
635
-            $adjusted = $this->adjustDatetimeSpaces(
636
-                $datetime_ID,
637
-                $ticket_identifier,
638
-                $ticket_quantity
639
-            );
640
-            // skip to next ticket if nothing changed
641
-            if (! ($adjusted || $at_capacity)) {
642
-                continue;
643
-            }
644
-            // then all of it's tickets are now unavailable
645
-            foreach ($datetime_tickets as $datetime_ticket) {
646
-                if (
647
-                    ($ticket_identifier === $datetime_ticket || $at_capacity)
648
-                    && isset($this->ticket_quantities[ $datetime_ticket ])
649
-                    && $this->ticket_quantities[ $datetime_ticket ] > 0
650
-                ) {
651
-                    if ($this->debug) {
652
-                        \EEH_Debug_Tools::printr(
653
-                            $datetime_ticket,
654
-                            ' . . . adjust ticket quantities for',
655
-                            __FILE__,
656
-                            __LINE__
657
-                        );
658
-                    }
659
-                    // if this datetime is at full capacity, set any tracked available quantities to zero
660
-                    // otherwise just subtract the ticket quantity
661
-                    $new_quantity = $at_capacity
662
-                        ? 0
663
-                        : $this->ticket_quantities[ $datetime_ticket ] - $ticket_quantity;
664
-                    // don't let ticket quantity go below zero
665
-                    $this->ticket_quantities[ $datetime_ticket ] = max($new_quantity, 0);
666
-                    if ($this->debug) {
667
-                        \EEH_Debug_Tools::printr(
668
-                            $at_capacity
669
-                                ? "0 because Datetime {$datetime_identifier} is at capacity"
670
-                                : "{$this->ticket_quantities[ $datetime_ticket ]}",
671
-                            " . . . . {$datetime_ticket} quantity set to ",
672
-                            __FILE__,
673
-                            __LINE__
674
-                        );
675
-                    }
676
-                }
677
-                // but we also need to adjust spaces for any other datetimes this ticket has access to
678
-                if ($datetime_ticket === $ticket_identifier) {
679
-                    if (
680
-                        isset($this->ticket_datetimes[ $datetime_ticket ])
681
-                        && is_array($this->ticket_datetimes[ $datetime_ticket ])
682
-                    ) {
683
-                        if ($this->debug) {
684
-                            \EEH_Debug_Tools::printr(
685
-                                $datetime_ticket,
686
-                                ' . . adjust other Datetimes for',
687
-                                __FILE__,
688
-                                __LINE__
689
-                            );
690
-                        }
691
-                        foreach ($this->ticket_datetimes[ $datetime_ticket ] as $datetime) {
692
-                            // don't adjust the current datetime twice
693
-                            if ($datetime !== $datetime_identifier) {
694
-                                $this->adjustDatetimeSpaces(
695
-                                    $datetime,
696
-                                    $datetime_ticket,
697
-                                    $ticket_quantity
698
-                                );
699
-                            }
700
-                        }
701
-                    }
702
-                }
703
-            }
704
-        }
705
-    }
706
-
707
-    private function adjustDatetimeSpaces($datetime_identifier, $ticket_identifier, $ticket_quantity = 0)
708
-    {
709
-        // does datetime have spaces available?
710
-        // and does the supplied ticket have access to this datetime ?
711
-        if (
712
-            $this->datetime_spaces[ $datetime_identifier ] > 0
713
-            && isset($this->datetime_spaces[ $datetime_identifier ], $this->datetime_tickets[ $datetime_identifier ])
714
-            && in_array($ticket_identifier, $this->datetime_tickets[ $datetime_identifier ], true)
715
-        ) {
716
-            if ($this->debug) {
717
-                \EEH_Debug_Tools::printr($datetime_identifier, ' . . adjust Datetime Spaces for', __FILE__, __LINE__);
718
-                \EEH_Debug_Tools::printr(
719
-                    "{$this->datetime_spaces[ $datetime_identifier ]}",
720
-                    " . . current  {$datetime_identifier} spaces available",
721
-                    __FILE__,
722
-                    __LINE__
723
-                );
724
-            }
725
-            // then decrement the available spaces for the datetime
726
-            $this->datetime_spaces[ $datetime_identifier ] -= $ticket_quantity;
727
-            // but don't let quantities go below zero
728
-            $this->datetime_spaces[ $datetime_identifier ] = max(
729
-                $this->datetime_spaces[ $datetime_identifier ],
730
-                0
731
-            );
732
-            if ($this->debug) {
733
-                \EEH_Debug_Tools::printr(
734
-                    "{$ticket_quantity}",
735
-                    " . . . {$datetime_identifier} capacity reduced by",
736
-                    __FILE__,
737
-                    __LINE__
738
-                );
739
-            }
740
-            return true;
741
-        }
742
-        return false;
743
-    }
29
+	/**
30
+	 * @var EE_Event $event
31
+	 */
32
+	private $event;
33
+
34
+	/**
35
+	 * @var array $datetime_query_params
36
+	 */
37
+	private $datetime_query_params;
38
+
39
+	/**
40
+	 * @var EE_Ticket[] $active_tickets
41
+	 */
42
+	private $active_tickets = array();
43
+
44
+	/**
45
+	 * @var EE_Datetime[] $datetimes
46
+	 */
47
+	private $datetimes = array();
48
+
49
+	/**
50
+	 * Array of Ticket IDs grouped by Datetime
51
+	 *
52
+	 * @var array $datetimes
53
+	 */
54
+	private $datetime_tickets = array();
55
+
56
+	/**
57
+	 * Max spaces for each Datetime (reg limit - previous sold)
58
+	 *
59
+	 * @var array $datetime_spaces
60
+	 */
61
+	private $datetime_spaces = array();
62
+
63
+	/**
64
+	 * Array of Datetime IDs grouped by Ticket
65
+	 *
66
+	 * @var array[] $ticket_datetimes
67
+	 */
68
+	private $ticket_datetimes = array();
69
+
70
+	/**
71
+	 * maximum ticket quantities for each ticket (adjusted for reg limit)
72
+	 *
73
+	 * @var array $ticket_quantities
74
+	 */
75
+	private $ticket_quantities = array();
76
+
77
+	/**
78
+	 * total quantity of sold and reserved for each ticket
79
+	 *
80
+	 * @var array $tickets_sold
81
+	 */
82
+	private $tickets_sold = array();
83
+
84
+	/**
85
+	 * total spaces available across all datetimes
86
+	 *
87
+	 * @var array $total_spaces
88
+	 */
89
+	private $total_spaces = array();
90
+
91
+	/**
92
+	 * @var boolean $debug
93
+	 */
94
+	private $debug = false; // true false
95
+
96
+	/**
97
+	 * @var null|int $spaces_remaining
98
+	 */
99
+	private $spaces_remaining;
100
+
101
+	/**
102
+	 * @var null|int $total_spaces_available
103
+	 */
104
+	private $total_spaces_available;
105
+
106
+
107
+	/**
108
+	 * EventSpacesCalculator constructor.
109
+	 *
110
+	 * @param EE_Event $event
111
+	 * @param array    $datetime_query_params
112
+	 * @throws EE_Error
113
+	 */
114
+	public function __construct(EE_Event $event, array $datetime_query_params = array())
115
+	{
116
+		if ($this->debug) {
117
+			\EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 1);
118
+			\EEH_Debug_Tools::printr((string) $event->ID(), 'For event', __FILE__, __LINE__);
119
+		}
120
+		$this->event = $event;
121
+		$this->datetime_query_params = $datetime_query_params + array('order_by' => array('DTT_reg_limit' => 'ASC'));
122
+		$this->setHooks();
123
+	}
124
+
125
+
126
+	/**
127
+	 * @return void
128
+	 */
129
+	private function setHooks()
130
+	{
131
+		add_action('AHEE__EE_Ticket__increase_sold', array($this, 'clearResults'));
132
+		add_action('AHEE__EE_Ticket__decrease_sold', array($this, 'clearResults'));
133
+		add_action('AHEE__EE_Datetime__increase_sold', array($this, 'clearResults'));
134
+		add_action('AHEE__EE_Datetime__decrease_sold', array($this, 'clearResults'));
135
+		add_action('AHEE__EE_Ticket__increase_reserved', array($this, 'clearResults'));
136
+		add_action('AHEE__EE_Ticket__decrease_reserved', array($this, 'clearResults'));
137
+		add_action('AHEE__EE_Datetime__increase_reserved', array($this, 'clearResults'));
138
+		add_action('AHEE__EE_Datetime__decrease_reserved', array($this, 'clearResults'));
139
+	}
140
+
141
+
142
+	/**
143
+	 * @return void
144
+	 */
145
+	public function clearResults()
146
+	{
147
+		if ($this->debug) {
148
+			\EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 1);
149
+		}
150
+		$this->spaces_remaining = null;
151
+		$this->total_spaces_available = null;
152
+	}
153
+
154
+
155
+	/**
156
+	 * @return EE_Ticket[]
157
+	 * @throws EE_Error
158
+	 * @throws InvalidDataTypeException
159
+	 * @throws InvalidInterfaceException
160
+	 * @throws InvalidArgumentException
161
+	 */
162
+	public function getActiveTickets()
163
+	{
164
+		if (empty($this->active_tickets)) {
165
+			$this->active_tickets = $this->event->tickets(
166
+				array(
167
+					array('TKT_deleted' => false),
168
+					'order_by' => array('TKT_qty' => 'ASC'),
169
+				)
170
+			);
171
+		}
172
+		return $this->active_tickets;
173
+	}
174
+
175
+
176
+	/**
177
+	 * @param EE_Ticket[] $active_tickets
178
+	 * @throws EE_Error
179
+	 * @throws DomainException
180
+	 * @throws UnexpectedEntityException
181
+	 */
182
+	public function setActiveTickets(array $active_tickets = array())
183
+	{
184
+		if (! empty($active_tickets)) {
185
+			foreach ($active_tickets as $active_ticket) {
186
+				$this->validateTicket($active_ticket);
187
+			}
188
+			// sort incoming array by ticket quantity (asc)
189
+			usort(
190
+				$active_tickets,
191
+				function (EE_Ticket $a, EE_Ticket $b) {
192
+					if ($a->qty() === $b->qty()) {
193
+						return 0;
194
+					}
195
+					return ($a->qty() < $b->qty())
196
+						? -1
197
+						: 1;
198
+				}
199
+			);
200
+		}
201
+		$this->active_tickets = $active_tickets;
202
+	}
203
+
204
+
205
+	/**
206
+	 * @param $ticket
207
+	 * @throws DomainException
208
+	 * @throws EE_Error
209
+	 * @throws UnexpectedEntityException
210
+	 */
211
+	private function validateTicket($ticket)
212
+	{
213
+		if (! $ticket instanceof EE_Ticket) {
214
+			throw new DomainException(
215
+				esc_html__(
216
+					'Invalid Ticket. Only EE_Ticket objects can be used to calculate event space availability.',
217
+					'event_espresso'
218
+				)
219
+			);
220
+		}
221
+		if ($ticket->get_event_ID() !== $this->event->ID()) {
222
+			throw new DomainException(
223
+				sprintf(
224
+					esc_html__(
225
+						'An EE_Ticket for Event %1$d was supplied while calculating event space availability for Event %2$d.',
226
+						'event_espresso'
227
+					),
228
+					$ticket->get_event_ID(),
229
+					$this->event->ID()
230
+				)
231
+			);
232
+		}
233
+	}
234
+
235
+
236
+	/**
237
+	 * @return EE_Datetime[]
238
+	 */
239
+	public function getDatetimes()
240
+	{
241
+		return $this->datetimes;
242
+	}
243
+
244
+
245
+	/**
246
+	 * @param EE_Datetime $datetime
247
+	 * @throws EE_Error
248
+	 * @throws DomainException
249
+	 */
250
+	public function setDatetime(EE_Datetime $datetime)
251
+	{
252
+		if ($datetime->event()->ID() !== $this->event->ID()) {
253
+			throw new DomainException(
254
+				sprintf(
255
+					esc_html__(
256
+						'An EE_Datetime for Event %1$d was supplied while calculating event space availability for Event %2$d.',
257
+						'event_espresso'
258
+					),
259
+					$datetime->event()->ID(),
260
+					$this->event->ID()
261
+				)
262
+			);
263
+		}
264
+		$this->datetimes[ $datetime->ID() ] = $datetime;
265
+	}
266
+
267
+
268
+	/**
269
+	 * calculate spaces remaining based on "saleable" tickets
270
+	 *
271
+	 * @return float|int
272
+	 * @throws EE_Error
273
+	 * @throws DomainException
274
+	 * @throws UnexpectedEntityException
275
+	 * @throws InvalidDataTypeException
276
+	 * @throws InvalidInterfaceException
277
+	 * @throws InvalidArgumentException
278
+	 */
279
+	public function spacesRemaining()
280
+	{
281
+		if ($this->debug) {
282
+			\EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
283
+		}
284
+		if ($this->spaces_remaining === null) {
285
+			$this->initialize();
286
+			$this->spaces_remaining = $this->calculate();
287
+		}
288
+		return $this->spaces_remaining;
289
+	}
290
+
291
+
292
+	/**
293
+	 * calculates total available spaces for an event with no regard for sold tickets
294
+	 *
295
+	 * @return int|float
296
+	 * @throws EE_Error
297
+	 * @throws DomainException
298
+	 * @throws UnexpectedEntityException
299
+	 * @throws InvalidDataTypeException
300
+	 * @throws InvalidInterfaceException
301
+	 * @throws InvalidArgumentException
302
+	 */
303
+	public function totalSpacesAvailable()
304
+	{
305
+		if ($this->debug) {
306
+			\EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
307
+		}
308
+		if ($this->total_spaces_available === null) {
309
+			$this->initialize();
310
+			$this->total_spaces_available = $this->calculate(false);
311
+		}
312
+		return $this->total_spaces_available;
313
+	}
314
+
315
+
316
+	/**
317
+	 * Loops through the active tickets for the event
318
+	 * and builds a series of data arrays that will be used for calculating
319
+	 * the total maximum available spaces, as well as the spaces remaining.
320
+	 * Because ticket quantities affect datetime spaces and vice versa,
321
+	 * we need to be constantly updating these data arrays as things change,
322
+	 * which is the entire reason for their existence.
323
+	 *
324
+	 * @throws EE_Error
325
+	 * @throws DomainException
326
+	 * @throws UnexpectedEntityException
327
+	 * @throws InvalidDataTypeException
328
+	 * @throws InvalidInterfaceException
329
+	 * @throws InvalidArgumentException
330
+	 */
331
+	private function initialize()
332
+	{
333
+		if ($this->debug) {
334
+			\EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
335
+		}
336
+		$this->datetime_tickets = array();
337
+		$this->datetime_spaces = array();
338
+		$this->ticket_datetimes = array();
339
+		$this->ticket_quantities = array();
340
+		$this->tickets_sold = array();
341
+		$this->total_spaces = array();
342
+		$active_tickets = $this->getActiveTickets();
343
+		if (! empty($active_tickets)) {
344
+			foreach ($active_tickets as $ticket) {
345
+				$this->validateTicket($ticket);
346
+				// we need to index our data arrays using strings for the purpose of sorting,
347
+				// but we also need them to be unique, so  we'll just prepend a letter T to the ID
348
+				$ticket_identifier = "T{$ticket->ID()}";
349
+				// to start, we'll just consider the raw qty to be the maximum availability for this ticket,
350
+				// unless the ticket is past its "sell until" date, in which case the qty will be 0
351
+				$max_tickets = $ticket->is_expired() ? 0 : $ticket->qty();
352
+				// but we'll adjust that after looping over each datetime for the ticket and checking reg limits
353
+				$ticket_datetimes = $ticket->datetimes($this->datetime_query_params);
354
+				foreach ($ticket_datetimes as $datetime) {
355
+					// save all datetimes
356
+					$this->setDatetime($datetime);
357
+					$datetime_identifier = "D{$datetime->ID()}";
358
+					$reg_limit = $datetime->reg_limit();
359
+					// ticket quantity can not exceed datetime reg limit
360
+					$max_tickets = min($max_tickets, $reg_limit);
361
+					// as described earlier, because we need to be able to constantly adjust numbers for things,
362
+					// we are going to move all of our data into the following arrays:
363
+					// datetime spaces initially represents the reg limit for each datetime,
364
+					// but this will get adjusted as tickets are accounted for
365
+					$this->datetime_spaces[ $datetime_identifier ] = $reg_limit;
366
+					// just an array of ticket IDs grouped by datetime
367
+					$this->datetime_tickets[ $datetime_identifier ][] = $ticket_identifier;
368
+					// and an array of datetime IDs grouped by ticket
369
+					$this->ticket_datetimes[ $ticket_identifier ][] = $datetime_identifier;
370
+				}
371
+				// total quantity of sold and reserved for each ticket
372
+				$this->tickets_sold[ $ticket_identifier ] = $ticket->sold() + $ticket->reserved();
373
+				// and the maximum ticket quantities for each ticket (adjusted for reg limit)
374
+				$this->ticket_quantities[ $ticket_identifier ] = $max_tickets;
375
+			}
376
+		}
377
+		// sort datetime spaces by reg limit, but maintain our string indexes
378
+		asort($this->datetime_spaces, SORT_NUMERIC);
379
+		// datetime tickets need to be sorted in the SAME order as the above array...
380
+		// so we'll just use array_merge() to take the structure of datetime_spaces
381
+		// but overwrite all of the data with that from datetime_tickets
382
+		$this->datetime_tickets = array_merge(
383
+			$this->datetime_spaces,
384
+			$this->datetime_tickets
385
+		);
386
+		if ($this->debug) {
387
+			\EEH_Debug_Tools::printr($this->datetime_spaces, 'datetime_spaces', __FILE__, __LINE__);
388
+			\EEH_Debug_Tools::printr($this->datetime_tickets, 'datetime_tickets', __FILE__, __LINE__);
389
+			\EEH_Debug_Tools::printr($this->ticket_quantities, 'ticket_quantities', __FILE__, __LINE__);
390
+		}
391
+	}
392
+
393
+
394
+	/**
395
+	 * performs calculations on initialized data
396
+	 *
397
+	 * @param bool $consider_sold
398
+	 * @return int|float
399
+	 */
400
+	private function calculate($consider_sold = true)
401
+	{
402
+		if ($this->debug) {
403
+			\EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
404
+			\EEH_Debug_Tools::printr($consider_sold, '$consider_sold', __FILE__, __LINE__);
405
+		}
406
+		if ($consider_sold) {
407
+			// subtract amounts sold from all ticket quantities and datetime spaces
408
+			$this->adjustTicketQuantitiesDueToSales();
409
+		}
410
+		foreach ($this->datetime_tickets as $datetime_identifier => $tickets) {
411
+			$this->trackAvailableSpacesForDatetimes($datetime_identifier, $tickets);
412
+		}
413
+		// total spaces available is just the sum of the spaces available for each datetime
414
+		$spaces_remaining = array_sum($this->total_spaces);
415
+		if ($this->debug) {
416
+			\EEH_Debug_Tools::printr($this->total_spaces, '$this->total_spaces', __FILE__, __LINE__);
417
+			\EEH_Debug_Tools::printr($this->tickets_sold, '$this->tickets_sold', __FILE__, __LINE__);
418
+			\EEH_Debug_Tools::printr($spaces_remaining, '$spaces_remaining', __FILE__, __LINE__);
419
+		}
420
+		return $spaces_remaining;
421
+	}
422
+
423
+
424
+	/**
425
+	 * subtracts amount of  tickets sold from ticket quantities and datetime spaces
426
+	 */
427
+	private function adjustTicketQuantitiesDueToSales()
428
+	{
429
+		if ($this->debug) {
430
+			\EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
431
+		}
432
+		foreach ($this->tickets_sold as $ticket_identifier => $tickets_sold) {
433
+			if (isset($this->ticket_quantities[ $ticket_identifier ])) {
434
+				$this->ticket_quantities[ $ticket_identifier ] -= $tickets_sold;
435
+				// don't let values go below zero
436
+				$this->ticket_quantities[ $ticket_identifier ] = max(
437
+					$this->ticket_quantities[ $ticket_identifier ],
438
+					0
439
+				);
440
+				if ($this->debug) {
441
+					\EEH_Debug_Tools::printr(
442
+						"{$tickets_sold} sales for ticket {$ticket_identifier} ",
443
+						'subtracting',
444
+						__FILE__,
445
+						__LINE__
446
+					);
447
+				}
448
+			}
449
+			if (
450
+				isset($this->ticket_datetimes[ $ticket_identifier ])
451
+				&& is_array($this->ticket_datetimes[ $ticket_identifier ])
452
+			) {
453
+				foreach ($this->ticket_datetimes[ $ticket_identifier ] as $ticket_datetime) {
454
+					if (isset($this->ticket_quantities[ $ticket_identifier ])) {
455
+						$this->datetime_spaces[ $ticket_datetime ] -= $tickets_sold;
456
+						// don't let values go below zero
457
+						$this->datetime_spaces[ $ticket_datetime ] = max(
458
+							$this->datetime_spaces[ $ticket_datetime ],
459
+							0
460
+						);
461
+						if ($this->debug) {
462
+							\EEH_Debug_Tools::printr(
463
+								"{$tickets_sold} sales for datetime {$ticket_datetime} ",
464
+								'subtracting',
465
+								__FILE__,
466
+								__LINE__
467
+							);
468
+						}
469
+					}
470
+				}
471
+			}
472
+		}
473
+	}
474
+
475
+
476
+	/**
477
+	 * @param string $datetime_identifier
478
+	 * @param array  $tickets
479
+	 */
480
+	private function trackAvailableSpacesForDatetimes($datetime_identifier, array $tickets)
481
+	{
482
+		// make sure a reg limit is set for the datetime
483
+		$reg_limit = isset($this->datetime_spaces[ $datetime_identifier ])
484
+			? $this->datetime_spaces[ $datetime_identifier ]
485
+			: 0;
486
+		// and bail if it is not
487
+		if (! $reg_limit) {
488
+			if ($this->debug) {
489
+				\EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__);
490
+			}
491
+			return;
492
+		}
493
+		if ($this->debug) {
494
+			\EEH_Debug_Tools::printr($datetime_identifier, '* $datetime_identifier', __FILE__, __LINE__, 1);
495
+			\EEH_Debug_Tools::printr(
496
+				"{$reg_limit}",
497
+				'REG LIMIT',
498
+				__FILE__,
499
+				__LINE__
500
+			);
501
+		}
502
+		// number of allocated spaces always starts at zero
503
+		$spaces_allocated = 0;
504
+		$this->total_spaces[ $datetime_identifier ] = 0;
505
+		foreach ($tickets as $ticket_identifier) {
506
+			$spaces_allocated = $this->calculateAvailableSpacesForTicket(
507
+				$datetime_identifier,
508
+				$reg_limit,
509
+				$ticket_identifier,
510
+				$spaces_allocated
511
+			);
512
+		}
513
+		// spaces can't be negative
514
+		$spaces_allocated = max($spaces_allocated, 0);
515
+		if ($spaces_allocated) {
516
+			// track any non-zero values
517
+			$this->total_spaces[ $datetime_identifier ] += $spaces_allocated;
518
+			if ($this->debug) {
519
+				\EEH_Debug_Tools::printr((string) $spaces_allocated, ' . $spaces_allocated: ', __FILE__, __LINE__);
520
+			}
521
+		} else {
522
+			if ($this->debug) {
523
+				\EEH_Debug_Tools::printr(' ', ' . NO TICKETS AVAILABLE FOR DATETIME', __FILE__, __LINE__);
524
+			}
525
+		}
526
+		if ($this->debug) {
527
+			\EEH_Debug_Tools::printr(
528
+				$this->total_spaces[ $datetime_identifier ],
529
+				'$total_spaces',
530
+				__FILE__,
531
+				__LINE__
532
+			);
533
+			\EEH_Debug_Tools::printr($this->ticket_quantities, '$ticket_quantities', __FILE__, __LINE__);
534
+			\EEH_Debug_Tools::printr($this->datetime_spaces, 'datetime_spaces', __FILE__, __LINE__);
535
+		}
536
+	}
537
+
538
+
539
+	/**
540
+	 * @param string $datetime_identifier
541
+	 * @param int    $reg_limit
542
+	 * @param string $ticket_identifier
543
+	 * @param int    $spaces_allocated
544
+	 * @return int
545
+	 */
546
+	private function calculateAvailableSpacesForTicket(
547
+		$datetime_identifier,
548
+		$reg_limit,
549
+		$ticket_identifier,
550
+		$spaces_allocated
551
+	) {
552
+		// make sure ticket quantity is set
553
+		$ticket_quantity = isset($this->ticket_quantities[ $ticket_identifier ])
554
+			? $this->ticket_quantities[ $ticket_identifier ]
555
+			: 0;
556
+		if ($this->debug) {
557
+			\EEH_Debug_Tools::printr("{$spaces_allocated}", '$spaces_allocated', __FILE__, __LINE__);
558
+			\EEH_Debug_Tools::printr(
559
+				"{$ticket_quantity}",
560
+				"ticket $ticket_identifier quantity: ",
561
+				__FILE__,
562
+				__LINE__,
563
+				2
564
+			);
565
+		}
566
+		if ($ticket_quantity) {
567
+			if ($this->debug) {
568
+				\EEH_Debug_Tools::printr(
569
+					($spaces_allocated <= $reg_limit)
570
+						? 'true'
571
+						: 'false',
572
+					' . spaces_allocated <= reg_limit = ',
573
+					__FILE__,
574
+					__LINE__
575
+				);
576
+			}
577
+			// if the datetime is NOT at full capacity yet
578
+			if ($spaces_allocated <= $reg_limit) {
579
+				// then the maximum ticket quantity we can allocate is the lowest value of either:
580
+				//  the number of remaining spaces for the datetime, which is the limit - spaces already taken
581
+				//  or the maximum ticket quantity
582
+				$ticket_quantity = min($reg_limit - $spaces_allocated, $ticket_quantity);
583
+				// adjust the available quantity in our tracking array
584
+				$this->ticket_quantities[ $ticket_identifier ] -= $ticket_quantity;
585
+				// and increment spaces allocated for this datetime
586
+				$spaces_allocated += $ticket_quantity;
587
+				$at_capacity = $spaces_allocated >= $reg_limit;
588
+				if ($this->debug) {
589
+					\EEH_Debug_Tools::printr(
590
+						"{$ticket_quantity} {$ticket_identifier} tickets",
591
+						' > > allocate ',
592
+						__FILE__,
593
+						__LINE__,
594
+						3
595
+					);
596
+					if ($at_capacity) {
597
+						\EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__, 3);
598
+					}
599
+				}
600
+				// now adjust all other datetimes that allow access to this ticket
601
+				$this->adjustDatetimes(
602
+					$datetime_identifier,
603
+					$ticket_identifier,
604
+					$ticket_quantity,
605
+					$at_capacity
606
+				);
607
+			}
608
+		}
609
+		return $spaces_allocated;
610
+	}
611
+
612
+
613
+	/**
614
+	 * subtracts ticket amounts from all datetime reg limits
615
+	 * that allow access to the ticket specified,
616
+	 * because that ticket could be used
617
+	 * to attend any of the datetimes it has access to
618
+	 *
619
+	 * @param string $datetime_identifier
620
+	 * @param string $ticket_identifier
621
+	 * @param bool   $at_capacity
622
+	 * @param int    $ticket_quantity
623
+	 */
624
+	private function adjustDatetimes(
625
+		$datetime_identifier,
626
+		$ticket_identifier,
627
+		$ticket_quantity,
628
+		$at_capacity
629
+	) {
630
+		/** @var array $datetime_tickets */
631
+		foreach ($this->datetime_tickets as $datetime_ID => $datetime_tickets) {
632
+			if ($datetime_ID !== $datetime_identifier || ! is_array($datetime_tickets)) {
633
+				continue;
634
+			}
635
+			$adjusted = $this->adjustDatetimeSpaces(
636
+				$datetime_ID,
637
+				$ticket_identifier,
638
+				$ticket_quantity
639
+			);
640
+			// skip to next ticket if nothing changed
641
+			if (! ($adjusted || $at_capacity)) {
642
+				continue;
643
+			}
644
+			// then all of it's tickets are now unavailable
645
+			foreach ($datetime_tickets as $datetime_ticket) {
646
+				if (
647
+					($ticket_identifier === $datetime_ticket || $at_capacity)
648
+					&& isset($this->ticket_quantities[ $datetime_ticket ])
649
+					&& $this->ticket_quantities[ $datetime_ticket ] > 0
650
+				) {
651
+					if ($this->debug) {
652
+						\EEH_Debug_Tools::printr(
653
+							$datetime_ticket,
654
+							' . . . adjust ticket quantities for',
655
+							__FILE__,
656
+							__LINE__
657
+						);
658
+					}
659
+					// if this datetime is at full capacity, set any tracked available quantities to zero
660
+					// otherwise just subtract the ticket quantity
661
+					$new_quantity = $at_capacity
662
+						? 0
663
+						: $this->ticket_quantities[ $datetime_ticket ] - $ticket_quantity;
664
+					// don't let ticket quantity go below zero
665
+					$this->ticket_quantities[ $datetime_ticket ] = max($new_quantity, 0);
666
+					if ($this->debug) {
667
+						\EEH_Debug_Tools::printr(
668
+							$at_capacity
669
+								? "0 because Datetime {$datetime_identifier} is at capacity"
670
+								: "{$this->ticket_quantities[ $datetime_ticket ]}",
671
+							" . . . . {$datetime_ticket} quantity set to ",
672
+							__FILE__,
673
+							__LINE__
674
+						);
675
+					}
676
+				}
677
+				// but we also need to adjust spaces for any other datetimes this ticket has access to
678
+				if ($datetime_ticket === $ticket_identifier) {
679
+					if (
680
+						isset($this->ticket_datetimes[ $datetime_ticket ])
681
+						&& is_array($this->ticket_datetimes[ $datetime_ticket ])
682
+					) {
683
+						if ($this->debug) {
684
+							\EEH_Debug_Tools::printr(
685
+								$datetime_ticket,
686
+								' . . adjust other Datetimes for',
687
+								__FILE__,
688
+								__LINE__
689
+							);
690
+						}
691
+						foreach ($this->ticket_datetimes[ $datetime_ticket ] as $datetime) {
692
+							// don't adjust the current datetime twice
693
+							if ($datetime !== $datetime_identifier) {
694
+								$this->adjustDatetimeSpaces(
695
+									$datetime,
696
+									$datetime_ticket,
697
+									$ticket_quantity
698
+								);
699
+							}
700
+						}
701
+					}
702
+				}
703
+			}
704
+		}
705
+	}
706
+
707
+	private function adjustDatetimeSpaces($datetime_identifier, $ticket_identifier, $ticket_quantity = 0)
708
+	{
709
+		// does datetime have spaces available?
710
+		// and does the supplied ticket have access to this datetime ?
711
+		if (
712
+			$this->datetime_spaces[ $datetime_identifier ] > 0
713
+			&& isset($this->datetime_spaces[ $datetime_identifier ], $this->datetime_tickets[ $datetime_identifier ])
714
+			&& in_array($ticket_identifier, $this->datetime_tickets[ $datetime_identifier ], true)
715
+		) {
716
+			if ($this->debug) {
717
+				\EEH_Debug_Tools::printr($datetime_identifier, ' . . adjust Datetime Spaces for', __FILE__, __LINE__);
718
+				\EEH_Debug_Tools::printr(
719
+					"{$this->datetime_spaces[ $datetime_identifier ]}",
720
+					" . . current  {$datetime_identifier} spaces available",
721
+					__FILE__,
722
+					__LINE__
723
+				);
724
+			}
725
+			// then decrement the available spaces for the datetime
726
+			$this->datetime_spaces[ $datetime_identifier ] -= $ticket_quantity;
727
+			// but don't let quantities go below zero
728
+			$this->datetime_spaces[ $datetime_identifier ] = max(
729
+				$this->datetime_spaces[ $datetime_identifier ],
730
+				0
731
+			);
732
+			if ($this->debug) {
733
+				\EEH_Debug_Tools::printr(
734
+					"{$ticket_quantity}",
735
+					" . . . {$datetime_identifier} capacity reduced by",
736
+					__FILE__,
737
+					__LINE__
738
+				);
739
+			}
740
+			return true;
741
+		}
742
+		return false;
743
+	}
744 744
 }
Please login to merge, or discard this patch.
Spacing   +46 added lines, -46 removed lines patch added patch discarded remove patch
@@ -181,14 +181,14 @@  discard block
 block discarded – undo
181 181
      */
182 182
     public function setActiveTickets(array $active_tickets = array())
183 183
     {
184
-        if (! empty($active_tickets)) {
184
+        if ( ! empty($active_tickets)) {
185 185
             foreach ($active_tickets as $active_ticket) {
186 186
                 $this->validateTicket($active_ticket);
187 187
             }
188 188
             // sort incoming array by ticket quantity (asc)
189 189
             usort(
190 190
                 $active_tickets,
191
-                function (EE_Ticket $a, EE_Ticket $b) {
191
+                function(EE_Ticket $a, EE_Ticket $b) {
192 192
                     if ($a->qty() === $b->qty()) {
193 193
                         return 0;
194 194
                     }
@@ -210,7 +210,7 @@  discard block
 block discarded – undo
210 210
      */
211 211
     private function validateTicket($ticket)
212 212
     {
213
-        if (! $ticket instanceof EE_Ticket) {
213
+        if ( ! $ticket instanceof EE_Ticket) {
214 214
             throw new DomainException(
215 215
                 esc_html__(
216 216
                     'Invalid Ticket. Only EE_Ticket objects can be used to calculate event space availability.',
@@ -261,7 +261,7 @@  discard block
 block discarded – undo
261 261
                 )
262 262
             );
263 263
         }
264
-        $this->datetimes[ $datetime->ID() ] = $datetime;
264
+        $this->datetimes[$datetime->ID()] = $datetime;
265 265
     }
266 266
 
267 267
 
@@ -340,7 +340,7 @@  discard block
 block discarded – undo
340 340
         $this->tickets_sold = array();
341 341
         $this->total_spaces = array();
342 342
         $active_tickets = $this->getActiveTickets();
343
-        if (! empty($active_tickets)) {
343
+        if ( ! empty($active_tickets)) {
344 344
             foreach ($active_tickets as $ticket) {
345 345
                 $this->validateTicket($ticket);
346 346
                 // we need to index our data arrays using strings for the purpose of sorting,
@@ -362,16 +362,16 @@  discard block
 block discarded – undo
362 362
                     // we are going to move all of our data into the following arrays:
363 363
                     // datetime spaces initially represents the reg limit for each datetime,
364 364
                     // but this will get adjusted as tickets are accounted for
365
-                    $this->datetime_spaces[ $datetime_identifier ] = $reg_limit;
365
+                    $this->datetime_spaces[$datetime_identifier] = $reg_limit;
366 366
                     // just an array of ticket IDs grouped by datetime
367
-                    $this->datetime_tickets[ $datetime_identifier ][] = $ticket_identifier;
367
+                    $this->datetime_tickets[$datetime_identifier][] = $ticket_identifier;
368 368
                     // and an array of datetime IDs grouped by ticket
369
-                    $this->ticket_datetimes[ $ticket_identifier ][] = $datetime_identifier;
369
+                    $this->ticket_datetimes[$ticket_identifier][] = $datetime_identifier;
370 370
                 }
371 371
                 // total quantity of sold and reserved for each ticket
372
-                $this->tickets_sold[ $ticket_identifier ] = $ticket->sold() + $ticket->reserved();
372
+                $this->tickets_sold[$ticket_identifier] = $ticket->sold() + $ticket->reserved();
373 373
                 // and the maximum ticket quantities for each ticket (adjusted for reg limit)
374
-                $this->ticket_quantities[ $ticket_identifier ] = $max_tickets;
374
+                $this->ticket_quantities[$ticket_identifier] = $max_tickets;
375 375
             }
376 376
         }
377 377
         // sort datetime spaces by reg limit, but maintain our string indexes
@@ -430,11 +430,11 @@  discard block
 block discarded – undo
430 430
             \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
431 431
         }
432 432
         foreach ($this->tickets_sold as $ticket_identifier => $tickets_sold) {
433
-            if (isset($this->ticket_quantities[ $ticket_identifier ])) {
434
-                $this->ticket_quantities[ $ticket_identifier ] -= $tickets_sold;
433
+            if (isset($this->ticket_quantities[$ticket_identifier])) {
434
+                $this->ticket_quantities[$ticket_identifier] -= $tickets_sold;
435 435
                 // don't let values go below zero
436
-                $this->ticket_quantities[ $ticket_identifier ] = max(
437
-                    $this->ticket_quantities[ $ticket_identifier ],
436
+                $this->ticket_quantities[$ticket_identifier] = max(
437
+                    $this->ticket_quantities[$ticket_identifier],
438 438
                     0
439 439
                 );
440 440
                 if ($this->debug) {
@@ -447,15 +447,15 @@  discard block
 block discarded – undo
447 447
                 }
448 448
             }
449 449
             if (
450
-                isset($this->ticket_datetimes[ $ticket_identifier ])
451
-                && is_array($this->ticket_datetimes[ $ticket_identifier ])
450
+                isset($this->ticket_datetimes[$ticket_identifier])
451
+                && is_array($this->ticket_datetimes[$ticket_identifier])
452 452
             ) {
453
-                foreach ($this->ticket_datetimes[ $ticket_identifier ] as $ticket_datetime) {
454
-                    if (isset($this->ticket_quantities[ $ticket_identifier ])) {
455
-                        $this->datetime_spaces[ $ticket_datetime ] -= $tickets_sold;
453
+                foreach ($this->ticket_datetimes[$ticket_identifier] as $ticket_datetime) {
454
+                    if (isset($this->ticket_quantities[$ticket_identifier])) {
455
+                        $this->datetime_spaces[$ticket_datetime] -= $tickets_sold;
456 456
                         // don't let values go below zero
457
-                        $this->datetime_spaces[ $ticket_datetime ] = max(
458
-                            $this->datetime_spaces[ $ticket_datetime ],
457
+                        $this->datetime_spaces[$ticket_datetime] = max(
458
+                            $this->datetime_spaces[$ticket_datetime],
459 459
                             0
460 460
                         );
461 461
                         if ($this->debug) {
@@ -480,11 +480,11 @@  discard block
 block discarded – undo
480 480
     private function trackAvailableSpacesForDatetimes($datetime_identifier, array $tickets)
481 481
     {
482 482
         // make sure a reg limit is set for the datetime
483
-        $reg_limit = isset($this->datetime_spaces[ $datetime_identifier ])
484
-            ? $this->datetime_spaces[ $datetime_identifier ]
483
+        $reg_limit = isset($this->datetime_spaces[$datetime_identifier])
484
+            ? $this->datetime_spaces[$datetime_identifier]
485 485
             : 0;
486 486
         // and bail if it is not
487
-        if (! $reg_limit) {
487
+        if ( ! $reg_limit) {
488 488
             if ($this->debug) {
489 489
                 \EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__);
490 490
             }
@@ -501,7 +501,7 @@  discard block
 block discarded – undo
501 501
         }
502 502
         // number of allocated spaces always starts at zero
503 503
         $spaces_allocated = 0;
504
-        $this->total_spaces[ $datetime_identifier ] = 0;
504
+        $this->total_spaces[$datetime_identifier] = 0;
505 505
         foreach ($tickets as $ticket_identifier) {
506 506
             $spaces_allocated = $this->calculateAvailableSpacesForTicket(
507 507
                 $datetime_identifier,
@@ -514,7 +514,7 @@  discard block
 block discarded – undo
514 514
         $spaces_allocated = max($spaces_allocated, 0);
515 515
         if ($spaces_allocated) {
516 516
             // track any non-zero values
517
-            $this->total_spaces[ $datetime_identifier ] += $spaces_allocated;
517
+            $this->total_spaces[$datetime_identifier] += $spaces_allocated;
518 518
             if ($this->debug) {
519 519
                 \EEH_Debug_Tools::printr((string) $spaces_allocated, ' . $spaces_allocated: ', __FILE__, __LINE__);
520 520
             }
@@ -525,7 +525,7 @@  discard block
 block discarded – undo
525 525
         }
526 526
         if ($this->debug) {
527 527
             \EEH_Debug_Tools::printr(
528
-                $this->total_spaces[ $datetime_identifier ],
528
+                $this->total_spaces[$datetime_identifier],
529 529
                 '$total_spaces',
530 530
                 __FILE__,
531 531
                 __LINE__
@@ -550,8 +550,8 @@  discard block
 block discarded – undo
550 550
         $spaces_allocated
551 551
     ) {
552 552
         // make sure ticket quantity is set
553
-        $ticket_quantity = isset($this->ticket_quantities[ $ticket_identifier ])
554
-            ? $this->ticket_quantities[ $ticket_identifier ]
553
+        $ticket_quantity = isset($this->ticket_quantities[$ticket_identifier])
554
+            ? $this->ticket_quantities[$ticket_identifier]
555 555
             : 0;
556 556
         if ($this->debug) {
557 557
             \EEH_Debug_Tools::printr("{$spaces_allocated}", '$spaces_allocated', __FILE__, __LINE__);
@@ -581,7 +581,7 @@  discard block
 block discarded – undo
581 581
                 //  or the maximum ticket quantity
582 582
                 $ticket_quantity = min($reg_limit - $spaces_allocated, $ticket_quantity);
583 583
                 // adjust the available quantity in our tracking array
584
-                $this->ticket_quantities[ $ticket_identifier ] -= $ticket_quantity;
584
+                $this->ticket_quantities[$ticket_identifier] -= $ticket_quantity;
585 585
                 // and increment spaces allocated for this datetime
586 586
                 $spaces_allocated += $ticket_quantity;
587 587
                 $at_capacity = $spaces_allocated >= $reg_limit;
@@ -638,15 +638,15 @@  discard block
 block discarded – undo
638 638
                 $ticket_quantity
639 639
             );
640 640
             // skip to next ticket if nothing changed
641
-            if (! ($adjusted || $at_capacity)) {
641
+            if ( ! ($adjusted || $at_capacity)) {
642 642
                 continue;
643 643
             }
644 644
             // then all of it's tickets are now unavailable
645 645
             foreach ($datetime_tickets as $datetime_ticket) {
646 646
                 if (
647 647
                     ($ticket_identifier === $datetime_ticket || $at_capacity)
648
-                    && isset($this->ticket_quantities[ $datetime_ticket ])
649
-                    && $this->ticket_quantities[ $datetime_ticket ] > 0
648
+                    && isset($this->ticket_quantities[$datetime_ticket])
649
+                    && $this->ticket_quantities[$datetime_ticket] > 0
650 650
                 ) {
651 651
                     if ($this->debug) {
652 652
                         \EEH_Debug_Tools::printr(
@@ -660,14 +660,14 @@  discard block
 block discarded – undo
660 660
                     // otherwise just subtract the ticket quantity
661 661
                     $new_quantity = $at_capacity
662 662
                         ? 0
663
-                        : $this->ticket_quantities[ $datetime_ticket ] - $ticket_quantity;
663
+                        : $this->ticket_quantities[$datetime_ticket] - $ticket_quantity;
664 664
                     // don't let ticket quantity go below zero
665
-                    $this->ticket_quantities[ $datetime_ticket ] = max($new_quantity, 0);
665
+                    $this->ticket_quantities[$datetime_ticket] = max($new_quantity, 0);
666 666
                     if ($this->debug) {
667 667
                         \EEH_Debug_Tools::printr(
668 668
                             $at_capacity
669 669
                                 ? "0 because Datetime {$datetime_identifier} is at capacity"
670
-                                : "{$this->ticket_quantities[ $datetime_ticket ]}",
670
+                                : "{$this->ticket_quantities[$datetime_ticket]}",
671 671
                             " . . . . {$datetime_ticket} quantity set to ",
672 672
                             __FILE__,
673 673
                             __LINE__
@@ -677,8 +677,8 @@  discard block
 block discarded – undo
677 677
                 // but we also need to adjust spaces for any other datetimes this ticket has access to
678 678
                 if ($datetime_ticket === $ticket_identifier) {
679 679
                     if (
680
-                        isset($this->ticket_datetimes[ $datetime_ticket ])
681
-                        && is_array($this->ticket_datetimes[ $datetime_ticket ])
680
+                        isset($this->ticket_datetimes[$datetime_ticket])
681
+                        && is_array($this->ticket_datetimes[$datetime_ticket])
682 682
                     ) {
683 683
                         if ($this->debug) {
684 684
                             \EEH_Debug_Tools::printr(
@@ -688,7 +688,7 @@  discard block
 block discarded – undo
688 688
                                 __LINE__
689 689
                             );
690 690
                         }
691
-                        foreach ($this->ticket_datetimes[ $datetime_ticket ] as $datetime) {
691
+                        foreach ($this->ticket_datetimes[$datetime_ticket] as $datetime) {
692 692
                             // don't adjust the current datetime twice
693 693
                             if ($datetime !== $datetime_identifier) {
694 694
                                 $this->adjustDatetimeSpaces(
@@ -709,24 +709,24 @@  discard block
 block discarded – undo
709 709
         // does datetime have spaces available?
710 710
         // and does the supplied ticket have access to this datetime ?
711 711
         if (
712
-            $this->datetime_spaces[ $datetime_identifier ] > 0
713
-            && isset($this->datetime_spaces[ $datetime_identifier ], $this->datetime_tickets[ $datetime_identifier ])
714
-            && in_array($ticket_identifier, $this->datetime_tickets[ $datetime_identifier ], true)
712
+            $this->datetime_spaces[$datetime_identifier] > 0
713
+            && isset($this->datetime_spaces[$datetime_identifier], $this->datetime_tickets[$datetime_identifier])
714
+            && in_array($ticket_identifier, $this->datetime_tickets[$datetime_identifier], true)
715 715
         ) {
716 716
             if ($this->debug) {
717 717
                 \EEH_Debug_Tools::printr($datetime_identifier, ' . . adjust Datetime Spaces for', __FILE__, __LINE__);
718 718
                 \EEH_Debug_Tools::printr(
719
-                    "{$this->datetime_spaces[ $datetime_identifier ]}",
719
+                    "{$this->datetime_spaces[$datetime_identifier]}",
720 720
                     " . . current  {$datetime_identifier} spaces available",
721 721
                     __FILE__,
722 722
                     __LINE__
723 723
                 );
724 724
             }
725 725
             // then decrement the available spaces for the datetime
726
-            $this->datetime_spaces[ $datetime_identifier ] -= $ticket_quantity;
726
+            $this->datetime_spaces[$datetime_identifier] -= $ticket_quantity;
727 727
             // but don't let quantities go below zero
728
-            $this->datetime_spaces[ $datetime_identifier ] = max(
729
-                $this->datetime_spaces[ $datetime_identifier ],
728
+            $this->datetime_spaces[$datetime_identifier] = max(
729
+                $this->datetime_spaces[$datetime_identifier],
730 730
                 0
731 731
             );
732 732
             if ($this->debug) {
Please login to merge, or discard this patch.
form_sections/strategies/display/EE_Number_Input_Display_Strategy.php 2 patches
Doc Comments   +3 added lines patch added patch discarded remove patch
@@ -64,6 +64,9 @@
 block discarded – undo
64 64
     }
65 65
 
66 66
 
67
+    /**
68
+     * @param string $argument_label
69
+     */
67 70
     private function throwValidationException($argument_label, $argument_value)
68 71
     {
69 72
         throw new InvalidArgumentException(
Please login to merge, or discard this patch.
Indentation   +93 added lines, -93 removed lines patch added patch discarded remove patch
@@ -11,109 +11,109 @@
 block discarded – undo
11 11
 class EE_Number_Input_Display_Strategy extends EE_Display_Strategy_Base
12 12
 {
13 13
 
14
-    /**
15
-     * minimum value for number field
16
-     *
17
-     * @var int|null $min
18
-     */
19
-    protected $min;
14
+	/**
15
+	 * minimum value for number field
16
+	 *
17
+	 * @var int|null $min
18
+	 */
19
+	protected $min;
20 20
 
21
-    /**
22
-     * maximum value for number field
23
-     *
24
-     * @var int|null $max
25
-     */
26
-    protected $max;
21
+	/**
22
+	 * maximum value for number field
23
+	 *
24
+	 * @var int|null $max
25
+	 */
26
+	protected $max;
27 27
 
28 28
 
29
-    /**
30
-     * This is used to set the "step" attribute for the html5 number input.
31
-     * Controls the increments on the input when incrementing or decrementing the value.
32
-     * Note:  Although the step attribute allows for the string "any" to be used, Firefox and Chrome will interpret that
33
-     * to increment by 1.  So although "any" is accepted as a value, it is converted to 1.
34
-     * @var float
35
-     */
36
-    protected $step;
29
+	/**
30
+	 * This is used to set the "step" attribute for the html5 number input.
31
+	 * Controls the increments on the input when incrementing or decrementing the value.
32
+	 * Note:  Although the step attribute allows for the string "any" to be used, Firefox and Chrome will interpret that
33
+	 * to increment by 1.  So although "any" is accepted as a value, it is converted to 1.
34
+	 * @var float
35
+	 */
36
+	protected $step;
37 37
 
38 38
 
39
-    /**
40
-     * EE_Number_Input_Display_Strategy constructor.
41
-     * Null is the default value for the incoming arguments because 0 is a valid value.  So we use null
42
-     * to indicate NOT setting this attribute.
43
-     *
44
-     * @param int|null $min
45
-     * @param int|null $max
46
-     * @param int|null $step
47
-     * @throws InvalidArgumentException
48
-     */
49
-    public function __construct($min = null, $max = null, $step = null)
50
-    {
51
-        $this->min = is_numeric($min) || $min === null
52
-            ? $min
53
-            : $this->throwValidationException('min', $min);
54
-        $this->max = is_numeric($max) || $max === null
55
-            ? $max
56
-            : $this->throwValidationException('max', $max);
57
-        $step = $step === 'any' ? 1 : $step;
58
-        $this->step = is_numeric($step) || $step === null
59
-            ? $step
60
-            : $this->throwValidationException('step', $step);
61
-    }
39
+	/**
40
+	 * EE_Number_Input_Display_Strategy constructor.
41
+	 * Null is the default value for the incoming arguments because 0 is a valid value.  So we use null
42
+	 * to indicate NOT setting this attribute.
43
+	 *
44
+	 * @param int|null $min
45
+	 * @param int|null $max
46
+	 * @param int|null $step
47
+	 * @throws InvalidArgumentException
48
+	 */
49
+	public function __construct($min = null, $max = null, $step = null)
50
+	{
51
+		$this->min = is_numeric($min) || $min === null
52
+			? $min
53
+			: $this->throwValidationException('min', $min);
54
+		$this->max = is_numeric($max) || $max === null
55
+			? $max
56
+			: $this->throwValidationException('max', $max);
57
+		$step = $step === 'any' ? 1 : $step;
58
+		$this->step = is_numeric($step) || $step === null
59
+			? $step
60
+			: $this->throwValidationException('step', $step);
61
+	}
62 62
 
63 63
 
64
-    private function throwValidationException($argument_label, $argument_value)
65
-    {
66
-        throw new InvalidArgumentException(
67
-            sprintf(
68
-                esc_html__(
69
-                    'The %1$s parameter value for %2$s must be numeric or null, %3$s was passed into the constructor.',
70
-                    'event_espresso'
71
-                ),
72
-                $argument_label,
73
-                __CLASS__,
74
-                $argument_value
75
-            )
76
-        );
77
-    }
64
+	private function throwValidationException($argument_label, $argument_value)
65
+	{
66
+		throw new InvalidArgumentException(
67
+			sprintf(
68
+				esc_html__(
69
+					'The %1$s parameter value for %2$s must be numeric or null, %3$s was passed into the constructor.',
70
+					'event_espresso'
71
+				),
72
+				$argument_label,
73
+				__CLASS__,
74
+				$argument_value
75
+			)
76
+		);
77
+	}
78 78
 
79 79
 
80 80
 
81
-    /**
82
-     * @return string of html to display the field
83
-     */
84
-    public function display()
85
-    {
86
-        $input = $this->_opening_tag('input');
87
-        $input .= $this->_attributes_string(
88
-            array_merge(
89
-                $this->_standard_attributes_array(),
90
-                $this->getNumberInputAttributes()
91
-            )
92
-        );
93
-        $input .= $this->_close_tag();
94
-        return $input;
95
-    }
81
+	/**
82
+	 * @return string of html to display the field
83
+	 */
84
+	public function display()
85
+	{
86
+		$input = $this->_opening_tag('input');
87
+		$input .= $this->_attributes_string(
88
+			array_merge(
89
+				$this->_standard_attributes_array(),
90
+				$this->getNumberInputAttributes()
91
+			)
92
+		);
93
+		$input .= $this->_close_tag();
94
+		return $input;
95
+	}
96 96
 
97 97
 
98
-    /**
99
-     * Return the attributes specific to this display strategy
100
-     * @return array
101
-     */
102
-    private function getNumberInputAttributes()
103
-    {
104
-        $attributes = array(
105
-            'type' => 'number',
106
-            'value' => $this->_input->raw_value_in_form()
107
-        );
108
-        if ($this->min !== null) {
109
-            $attributes['min'] = $this->min;
110
-        }
111
-        if ($this->max !== null) {
112
-            $attributes['max'] = $this->max;
113
-        }
114
-        if ($this->step !== null) {
115
-            $attributes['step'] = $this->step;
116
-        }
117
-        return $attributes;
118
-    }
98
+	/**
99
+	 * Return the attributes specific to this display strategy
100
+	 * @return array
101
+	 */
102
+	private function getNumberInputAttributes()
103
+	{
104
+		$attributes = array(
105
+			'type' => 'number',
106
+			'value' => $this->_input->raw_value_in_form()
107
+		);
108
+		if ($this->min !== null) {
109
+			$attributes['min'] = $this->min;
110
+		}
111
+		if ($this->max !== null) {
112
+			$attributes['max'] = $this->max;
113
+		}
114
+		if ($this->step !== null) {
115
+			$attributes['step'] = $this->step;
116
+		}
117
+		return $attributes;
118
+	}
119 119
 }
Please login to merge, or discard this patch.
core/libraries/form_sections/inputs/EE_Float_Input.input.php 1 patch
Indentation   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -11,33 +11,33 @@
 block discarded – undo
11 11
 class EE_Float_Input extends EE_Form_Input_Base
12 12
 {
13 13
 
14
-    /**
15
-     * @param array $input_settings
16
-     * @throws InvalidArgumentException
17
-     */
18
-    public function __construct($input_settings = array())
19
-    {
20
-        $this->_set_display_strategy(
21
-            new EE_Number_Input_Display_Strategy(
22
-                isset($input_settings['min_value'])
23
-                    ? $input_settings['min_value']
24
-                    : null,
25
-                isset($input_settings['max_value'])
26
-                    ? $input_settings['max_value']
27
-                    : null,
28
-                isset($input_settings['step_value'])
29
-                    ? $input_settings['step_value']
30
-                    : null
31
-            )
32
-        );
33
-        $this->_set_normalization_strategy(new EE_Float_Normalization());
34
-        $this->_add_validation_strategy(
35
-            new EE_Float_Validation_Strategy(
36
-                isset($input_settings['validation_error_message'])
37
-                    ? $input_settings['validation_error_message']
38
-                    : null
39
-            )
40
-        );
41
-        parent::__construct($input_settings);
42
-    }
14
+	/**
15
+	 * @param array $input_settings
16
+	 * @throws InvalidArgumentException
17
+	 */
18
+	public function __construct($input_settings = array())
19
+	{
20
+		$this->_set_display_strategy(
21
+			new EE_Number_Input_Display_Strategy(
22
+				isset($input_settings['min_value'])
23
+					? $input_settings['min_value']
24
+					: null,
25
+				isset($input_settings['max_value'])
26
+					? $input_settings['max_value']
27
+					: null,
28
+				isset($input_settings['step_value'])
29
+					? $input_settings['step_value']
30
+					: null
31
+			)
32
+		);
33
+		$this->_set_normalization_strategy(new EE_Float_Normalization());
34
+		$this->_add_validation_strategy(
35
+			new EE_Float_Validation_Strategy(
36
+				isset($input_settings['validation_error_message'])
37
+					? $input_settings['validation_error_message']
38
+					: null
39
+			)
40
+		);
41
+		parent::__construct($input_settings);
42
+	}
43 43
 }
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_List_Table.class.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -152,7 +152,7 @@
 block discarded – undo
152 152
 
153 153
     /**
154 154
      * @param EE_Event $item
155
-     * @return mixed|string
155
+     * @return string
156 156
      * @throws EE_Error
157 157
      */
158 158
     public function column_id(EE_Event $item)
Please login to merge, or discard this patch.
Indentation   +568 added lines, -568 removed lines patch added patch discarded remove patch
@@ -15,572 +15,572 @@
 block discarded – undo
15 15
 class Events_Admin_List_Table extends EE_Admin_List_Table
16 16
 {
17 17
 
18
-    /**
19
-     * @var EE_Datetime
20
-     */
21
-    private $_dtt;
22
-
23
-
24
-    /**
25
-     * Initial setup of data properties for the list table.
26
-     */
27
-    protected function _setup_data()
28
-    {
29
-        $this->_data = $this->_admin_page->get_events($this->_per_page, $this->_current_page);
30
-        $this->_all_data_count = $this->_admin_page->get_events(0, 0, true);
31
-    }
32
-
33
-
34
-    /**
35
-     * Set up of additional properties for the list table.
36
-     */
37
-    protected function _set_properties()
38
-    {
39
-        $this->_wp_list_args = array(
40
-            'singular' => esc_html__('event', 'event_espresso'),
41
-            'plural'   => esc_html__('events', 'event_espresso'),
42
-            'ajax'     => true, // for now
43
-            'screen'   => $this->_admin_page->get_current_screen()->id,
44
-        );
45
-        $this->_columns = array(
46
-            'cb'              => '<input type="checkbox" />',
47
-            'id'              => esc_html__('ID', 'event_espresso'),
48
-            'name'            => esc_html__('Name', 'event_espresso'),
49
-            'author'          => esc_html__('Author', 'event_espresso'),
50
-            'venue'           => esc_html__('Venue', 'event_espresso'),
51
-            'start_date_time' => esc_html__('Event Start', 'event_espresso'),
52
-            'reg_begins'      => esc_html__('On Sale', 'event_espresso'),
53
-            'attendees'       => '<span class="dashicons dashicons-groups ee-icon-color-ee-green ee-icon-size-20">'
54
-                                 . '<span class="screen-reader-text">'
55
-                                 . esc_html__('Approved Registrations', 'event_espresso')
56
-                                 . '</span>'
57
-                                 . '</span>',
58
-            // 'tkts_sold' => esc_html__('Tickets Sold', 'event_espresso'),
59
-            'actions'         => esc_html__('Actions', 'event_espresso'),
60
-        );
61
-        $this->addConditionalColumns();
62
-        $this->_sortable_columns = array(
63
-            'id'              => array('EVT_ID' => true),
64
-            'name'            => array('EVT_name' => false),
65
-            'author'          => array('EVT_wp_user' => false),
66
-            'venue'           => array('Venue.VNU_name' => false),
67
-            'start_date_time' => array('Datetime.DTT_EVT_start' => false),
68
-            'reg_begins'      => array('Datetime.Ticket.TKT_start_date' => false),
69
-        );
70
-
71
-        $this->_primary_column = 'id';
72
-        $this->_hidden_columns = array('author', 'event_category');
73
-    }
74
-
75
-
76
-    /**
77
-     * @return array
78
-     */
79
-    protected function _get_table_filters()
80
-    {
81
-        return array(); // no filters with decaf
82
-    }
83
-
84
-
85
-    /**
86
-     * Setup of views properties.
87
-     *
88
-     * @throws InvalidDataTypeException
89
-     * @throws InvalidInterfaceException
90
-     * @throws InvalidArgumentException
91
-     */
92
-    protected function _add_view_counts()
93
-    {
94
-        $this->_views['all']['count'] = $this->_admin_page->total_events();
95
-        $this->_views['draft']['count'] = $this->_admin_page->total_events_draft();
96
-        if (
97
-            EE_Registry::instance()->CAP->current_user_can(
98
-                'ee_delete_events',
99
-                'espresso_events_trash_events'
100
-            )
101
-        ) {
102
-            $this->_views['trash']['count'] = $this->_admin_page->total_trashed_events();
103
-        }
104
-    }
105
-
106
-
107
-    /**
108
-     * @param EE_Event $item
109
-     * @return string
110
-     * @throws EE_Error
111
-     */
112
-    protected function _get_row_class($item)
113
-    {
114
-        $class = parent::_get_row_class($item);
115
-        // add status class
116
-        $class .= $item instanceof EE_Event
117
-            ? ' ee-status-strip event-status-' . $item->get_active_status()
118
-            : '';
119
-        if ($this->_has_checkbox_column) {
120
-            $class .= ' has-checkbox-column';
121
-        }
122
-        return $class;
123
-    }
124
-
125
-
126
-    /**
127
-     * @param EE_Event $item
128
-     * @return string
129
-     * @throws EE_Error
130
-     */
131
-    public function column_status(EE_Event $item)
132
-    {
133
-        return '<span class="ee-status-strip ee-status-strip-td event-status-'
134
-               . $item->get_active_status()
135
-               . '"></span>';
136
-    }
137
-
138
-
139
-    /**
140
-     * @param  EE_Event $item
141
-     * @return string
142
-     * @throws EE_Error
143
-     */
144
-    public function column_cb($item)
145
-    {
146
-        if (! $item instanceof EE_Event) {
147
-            return '';
148
-        }
149
-        $this->_dtt = $item->primary_datetime(); // set this for use in other columns
150
-        // does event have any attached registrations?
151
-        $regs = $item->count_related('Registration');
152
-        return $regs > 0 && $this->_view === 'trash'
153
-            ? '<span class="ee-lock-icon"></span>'
154
-            : sprintf(
155
-                '<input type="checkbox" name="EVT_IDs[]" value="%s" />',
156
-                $item->ID()
157
-            );
158
-    }
159
-
160
-
161
-    /**
162
-     * @param EE_Event $item
163
-     * @return mixed|string
164
-     * @throws EE_Error
165
-     */
166
-    public function column_id(EE_Event $item)
167
-    {
168
-        $content = $item->ID();
169
-        $content .= '  <span class="show-on-mobile-view-only">' . $item->name() . '</span>';
170
-        return $content;
171
-    }
172
-
173
-
174
-    /**
175
-     * @param EE_Event $item
176
-     * @return string
177
-     * @throws EE_Error
178
-     * @throws InvalidArgumentException
179
-     * @throws InvalidDataTypeException
180
-     * @throws InvalidInterfaceException
181
-     */
182
-    public function column_name(EE_Event $item)
183
-    {
184
-        $edit_query_args = array(
185
-            'action' => 'edit',
186
-            'post'   => $item->ID(),
187
-        );
188
-        $edit_link = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
189
-        $actions = $this->_column_name_action_setup($item);
190
-        $status = ''; // $item->status() !== 'publish' ? ' (' . $item->status() . ')' : '';
191
-        $content = '<strong><a class="row-title" href="'
192
-                   . $edit_link . '">'
193
-                   . $item->name()
194
-                   . '</a></strong>'
195
-                   . $status;
196
-        $content .= '<br><span class="ee-status-text-small">'
197
-                    . EEH_Template::pretty_status(
198
-                        $item->get_active_status(),
199
-                        false,
200
-                        'sentence'
201
-                    )
202
-                    . '</span>';
203
-        $content .= $this->row_actions($actions);
204
-        return $content;
205
-    }
206
-
207
-
208
-    /**
209
-     * Just a method for setting up the actions for the name column
210
-     *
211
-     * @param EE_Event $item
212
-     * @return array array of actions
213
-     * @throws EE_Error
214
-     * @throws InvalidArgumentException
215
-     * @throws InvalidDataTypeException
216
-     * @throws InvalidInterfaceException
217
-     */
218
-    protected function _column_name_action_setup(EE_Event $item)
219
-    {
220
-        // todo: remove when attendees is active
221
-        if (! defined('REG_ADMIN_URL')) {
222
-            define('REG_ADMIN_URL', EVENTS_ADMIN_URL);
223
-        }
224
-        $actions = array();
225
-        $restore_event_link = '';
226
-        $delete_event_link = '';
227
-        $trash_event_link = '';
228
-        if (
229
-            EE_Registry::instance()->CAP->current_user_can(
230
-                'ee_edit_event',
231
-                'espresso_events_edit',
232
-                $item->ID()
233
-            )
234
-        ) {
235
-            $edit_query_args = array(
236
-                'action' => 'edit',
237
-                'post'   => $item->ID(),
238
-            );
239
-            $edit_link = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
240
-            $actions['edit'] = '<a href="' . $edit_link . '"'
241
-                               . ' title="' . esc_attr__('Edit Event', 'event_espresso') . '">'
242
-                               . esc_html__('Edit', 'event_espresso')
243
-                               . '</a>';
244
-        }
245
-        if (
246
-            EE_Registry::instance()->CAP->current_user_can(
247
-                'ee_read_registrations',
248
-                'espresso_registrations_view_registration'
249
-            )
250
-            && EE_Registry::instance()->CAP->current_user_can(
251
-                'ee_read_event',
252
-                'espresso_registrations_view_registration',
253
-                $item->ID()
254
-            )
255
-        ) {
256
-            $attendees_query_args = array(
257
-                'action'   => 'default',
258
-                'event_id' => $item->ID(),
259
-            );
260
-            $attendees_link = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
261
-            $actions['attendees'] = '<a href="' . $attendees_link . '"'
262
-                                    . ' title="' . esc_attr__('View Registrations', 'event_espresso') . '">'
263
-                                    . esc_html__('Registrations', 'event_espresso')
264
-                                    . '</a>';
265
-        }
266
-        if (
267
-            EE_Registry::instance()->CAP->current_user_can(
268
-                'ee_delete_event',
269
-                'espresso_events_trash_event',
270
-                $item->ID()
271
-            )
272
-        ) {
273
-            $trash_event_query_args = array(
274
-                'action' => 'trash_event',
275
-                'EVT_ID' => $item->ID(),
276
-            );
277
-            $trash_event_link = EE_Admin_Page::add_query_args_and_nonce(
278
-                $trash_event_query_args,
279
-                EVENTS_ADMIN_URL
280
-            );
281
-        }
282
-        if (
283
-            EE_Registry::instance()->CAP->current_user_can(
284
-                'ee_delete_event',
285
-                'espresso_events_restore_event',
286
-                $item->ID()
287
-            )
288
-        ) {
289
-            $restore_event_query_args = array(
290
-                'action' => 'restore_event',
291
-                'EVT_ID' => $item->ID(),
292
-            );
293
-            $restore_event_link = EE_Admin_Page::add_query_args_and_nonce(
294
-                $restore_event_query_args,
295
-                EVENTS_ADMIN_URL
296
-            );
297
-        }
298
-        if (
299
-            EE_Registry::instance()->CAP->current_user_can(
300
-                'ee_delete_event',
301
-                'espresso_events_delete_event',
302
-                $item->ID()
303
-            )
304
-        ) {
305
-            $delete_event_query_args = array(
306
-                'action' => 'delete_event',
307
-                'EVT_ID' => $item->ID(),
308
-            );
309
-            $delete_event_link = EE_Admin_Page::add_query_args_and_nonce(
310
-                $delete_event_query_args,
311
-                EVENTS_ADMIN_URL
312
-            );
313
-        }
314
-        $view_link = get_permalink($item->ID());
315
-        $actions['view'] = '<a href="' . $view_link . '"'
316
-                           . ' title="' . esc_attr__('View Event', 'event_espresso') . '">'
317
-                           . esc_html__('View', 'event_espresso')
318
-                           . '</a>';
319
-        if ($item->get('status') === 'trash') {
320
-            if (
321
-                EE_Registry::instance()->CAP->current_user_can(
322
-                    'ee_delete_event',
323
-                    'espresso_events_restore_event',
324
-                    $item->ID()
325
-                )
326
-            ) {
327
-                $actions['restore_from_trash'] = '<a href="' . $restore_event_link . '"'
328
-                                                 . ' title="' . esc_attr__('Restore from Trash', 'event_espresso')
329
-                                                 . '">'
330
-                                                 . esc_html__('Restore from Trash', 'event_espresso')
331
-                                                 . '</a>';
332
-            }
333
-            if (
334
-                $item->count_related('Registration') === 0
335
-                && EE_Registry::instance()->CAP->current_user_can(
336
-                    'ee_delete_event',
337
-                    'espresso_events_delete_event',
338
-                    $item->ID()
339
-                )
340
-            ) {
341
-                $actions['delete'] = '<a href="' . $delete_event_link . '"'
342
-                                     . ' title="' . esc_attr__('Delete Permanently', 'event_espresso') . '">'
343
-                                     . esc_html__('Delete Permanently', 'event_espresso')
344
-                                     . '</a>';
345
-            }
346
-        } else {
347
-            if (
348
-                EE_Registry::instance()->CAP->current_user_can(
349
-                    'ee_delete_event',
350
-                    'espresso_events_trash_event',
351
-                    $item->ID()
352
-                )
353
-            ) {
354
-                $actions['move to trash'] = '<a href="' . $trash_event_link . '"'
355
-                                            . ' title="' . esc_attr__('Trash Event', 'event_espresso') . '">'
356
-                                            . esc_html__('Trash', 'event_espresso')
357
-                                            . '</a>';
358
-            }
359
-        }
360
-        return $actions;
361
-    }
362
-
363
-
364
-    /**
365
-     * @param EE_Event $item
366
-     * @return string
367
-     * @throws EE_Error
368
-     */
369
-    public function column_author(EE_Event $item)
370
-    {
371
-        // user author info
372
-        $event_author = get_userdata($item->wp_user());
373
-        $gravatar = get_avatar($item->wp_user(), '15');
374
-        // filter link
375
-        $query_args = array(
376
-            'action'      => 'default',
377
-            'EVT_wp_user' => $item->wp_user(),
378
-        );
379
-        $filter_url = EE_Admin_Page::add_query_args_and_nonce($query_args, EVENTS_ADMIN_URL);
380
-        return $gravatar . '  <a href="' . $filter_url . '"'
381
-               . ' title="' . esc_attr__('Click to filter events by this author.', 'event_espresso') . '">'
382
-               . $event_author->display_name
383
-               . '</a>';
384
-    }
385
-
386
-
387
-    /**
388
-     * @param EE_Event $event
389
-     * @return string
390
-     * @throws EE_Error
391
-     */
392
-    public function column_event_category(EE_Event $event)
393
-    {
394
-        $event_categories = $event->get_all_event_categories();
395
-        return implode(
396
-            ', ',
397
-            array_map(
398
-                function (EE_Term $category) {
399
-                    return $category->name();
400
-                },
401
-                $event_categories
402
-            )
403
-        );
404
-    }
405
-
406
-
407
-    /**
408
-     * @param EE_Event $item
409
-     * @return string
410
-     * @throws EE_Error
411
-     */
412
-    public function column_venue(EE_Event $item)
413
-    {
414
-        $venue = $item->get_first_related('Venue');
415
-        return ! empty($venue)
416
-            ? $venue->name()
417
-            : '';
418
-    }
419
-
420
-
421
-    /**
422
-     * @param EE_Event $item
423
-     * @return string
424
-     * @throws EE_Error
425
-     */
426
-    public function column_start_date_time(EE_Event $item)
427
-    {
428
-        return $this->_dtt instanceof EE_Datetime
429
-            ? $this->_dtt->get_i18n_datetime('DTT_EVT_start')
430
-            : esc_html__('No Date was saved for this Event', 'event_espresso');
431
-    }
432
-
433
-
434
-    /**
435
-     * @param EE_Event $item
436
-     * @return string
437
-     * @throws EE_Error
438
-     */
439
-    public function column_reg_begins(EE_Event $item)
440
-    {
441
-        $reg_start = $item->get_ticket_with_earliest_start_time();
442
-        return $reg_start instanceof EE_Ticket
443
-            ? $reg_start->get_i18n_datetime('TKT_start_date')
444
-            : esc_html__('No Tickets have been setup for this Event', 'event_espresso');
445
-    }
446
-
447
-
448
-    /**
449
-     * @param EE_Event $item
450
-     * @return int|string
451
-     * @throws EE_Error
452
-     * @throws InvalidArgumentException
453
-     * @throws InvalidDataTypeException
454
-     * @throws InvalidInterfaceException
455
-     */
456
-    public function column_attendees(EE_Event $item)
457
-    {
458
-        $attendees_query_args = array(
459
-            'action'   => 'default',
460
-            'event_id' => $item->ID(),
461
-        );
462
-        $attendees_link = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
463
-        $registered_attendees = EEM_Registration::instance()->get_event_registration_count($item->ID());
464
-        return EE_Registry::instance()->CAP->current_user_can(
465
-            'ee_read_event',
466
-            'espresso_registrations_view_registration',
467
-            $item->ID()
468
-        )
469
-               && EE_Registry::instance()->CAP->current_user_can(
470
-                   'ee_read_registrations',
471
-                   'espresso_registrations_view_registration'
472
-               )
473
-            ? '<a href="' . $attendees_link . '">' . $registered_attendees . '</a>'
474
-            : $registered_attendees;
475
-    }
476
-
477
-
478
-    /**
479
-     * @param EE_Event $item
480
-     * @return float
481
-     * @throws EE_Error
482
-     * @throws InvalidArgumentException
483
-     * @throws InvalidDataTypeException
484
-     * @throws InvalidInterfaceException
485
-     */
486
-    public function column_tkts_sold(EE_Event $item)
487
-    {
488
-        return EEM_Ticket::instance()->sum(array(array('Datetime.EVT_ID' => $item->ID())), 'TKT_sold');
489
-    }
490
-
491
-
492
-    /**
493
-     * @param EE_Event $item
494
-     * @return string
495
-     * @throws EE_Error
496
-     * @throws InvalidArgumentException
497
-     * @throws InvalidDataTypeException
498
-     * @throws InvalidInterfaceException
499
-     */
500
-    public function column_actions(EE_Event $item)
501
-    {
502
-        // todo: remove when attendees is active
503
-        if (! defined('REG_ADMIN_URL')) {
504
-            define('REG_ADMIN_URL', EVENTS_ADMIN_URL);
505
-        }
506
-        $action_links = array();
507
-        $view_link = get_permalink($item->ID());
508
-        $action_links[] = '<a href="' . $view_link . '"'
509
-                          . ' title="' . esc_attr__('View Event', 'event_espresso') . '" target="_blank">';
510
-        $action_links[] = '<div class="dashicons dashicons-search"></div></a>';
511
-        if (
512
-            EE_Registry::instance()->CAP->current_user_can(
513
-                'ee_edit_event',
514
-                'espresso_events_edit',
515
-                $item->ID()
516
-            )
517
-        ) {
518
-            $edit_query_args = array(
519
-                'action' => 'edit',
520
-                'post'   => $item->ID(),
521
-            );
522
-            $edit_link = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
523
-            $action_links[] = '<a href="' . $edit_link . '"'
524
-                              . ' title="' . esc_attr__('Edit Event', 'event_espresso') . '">'
525
-                              . '<div class="ee-icon ee-icon-calendar-edit"></div>'
526
-                              . '</a>';
527
-        }
528
-        if (
529
-            EE_Registry::instance()->CAP->current_user_can(
530
-                'ee_read_registrations',
531
-                'espresso_registrations_view_registration'
532
-            ) && EE_Registry::instance()->CAP->current_user_can(
533
-                'ee_read_event',
534
-                'espresso_registrations_view_registration',
535
-                $item->ID()
536
-            )
537
-        ) {
538
-            $attendees_query_args = array(
539
-                'action'   => 'default',
540
-                'event_id' => $item->ID(),
541
-            );
542
-            $attendees_link = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
543
-            $action_links[] = '<a href="' . $attendees_link . '"'
544
-                              . ' title="' . esc_attr__('View Registrants', 'event_espresso') . '">'
545
-                              . '<div class="dashicons dashicons-groups"></div>'
546
-                              . '</a>';
547
-        }
548
-        $action_links = apply_filters(
549
-            'FHEE__Events_Admin_List_Table__column_actions__action_links',
550
-            $action_links,
551
-            $item
552
-        );
553
-        return $this->_action_string(
554
-            implode("\n\t", $action_links),
555
-            $item,
556
-            'div'
557
-        );
558
-    }
559
-
560
-
561
-    /**
562
-     * Helper for adding columns conditionally
563
-     *
564
-     * @throws EE_Error
565
-     * @throws InvalidArgumentException
566
-     * @throws InvalidDataTypeException
567
-     * @throws InvalidInterfaceException
568
-     */
569
-    private function addConditionalColumns()
570
-    {
571
-        $event_category_count = EEM_Term::instance()->count(
572
-            [['Term_Taxonomy.taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY]]
573
-        );
574
-        if ($event_category_count === 0) {
575
-            return;
576
-        }
577
-        $column_array = [];
578
-        foreach ($this->_columns as $column => $column_label) {
579
-            $column_array[ $column ] = $column_label;
580
-            if ($column === 'venue') {
581
-                $column_array['event_category'] = esc_html__('Event Category', 'event_espresso');
582
-            }
583
-        }
584
-        $this->_columns = $column_array;
585
-    }
18
+	/**
19
+	 * @var EE_Datetime
20
+	 */
21
+	private $_dtt;
22
+
23
+
24
+	/**
25
+	 * Initial setup of data properties for the list table.
26
+	 */
27
+	protected function _setup_data()
28
+	{
29
+		$this->_data = $this->_admin_page->get_events($this->_per_page, $this->_current_page);
30
+		$this->_all_data_count = $this->_admin_page->get_events(0, 0, true);
31
+	}
32
+
33
+
34
+	/**
35
+	 * Set up of additional properties for the list table.
36
+	 */
37
+	protected function _set_properties()
38
+	{
39
+		$this->_wp_list_args = array(
40
+			'singular' => esc_html__('event', 'event_espresso'),
41
+			'plural'   => esc_html__('events', 'event_espresso'),
42
+			'ajax'     => true, // for now
43
+			'screen'   => $this->_admin_page->get_current_screen()->id,
44
+		);
45
+		$this->_columns = array(
46
+			'cb'              => '<input type="checkbox" />',
47
+			'id'              => esc_html__('ID', 'event_espresso'),
48
+			'name'            => esc_html__('Name', 'event_espresso'),
49
+			'author'          => esc_html__('Author', 'event_espresso'),
50
+			'venue'           => esc_html__('Venue', 'event_espresso'),
51
+			'start_date_time' => esc_html__('Event Start', 'event_espresso'),
52
+			'reg_begins'      => esc_html__('On Sale', 'event_espresso'),
53
+			'attendees'       => '<span class="dashicons dashicons-groups ee-icon-color-ee-green ee-icon-size-20">'
54
+								 . '<span class="screen-reader-text">'
55
+								 . esc_html__('Approved Registrations', 'event_espresso')
56
+								 . '</span>'
57
+								 . '</span>',
58
+			// 'tkts_sold' => esc_html__('Tickets Sold', 'event_espresso'),
59
+			'actions'         => esc_html__('Actions', 'event_espresso'),
60
+		);
61
+		$this->addConditionalColumns();
62
+		$this->_sortable_columns = array(
63
+			'id'              => array('EVT_ID' => true),
64
+			'name'            => array('EVT_name' => false),
65
+			'author'          => array('EVT_wp_user' => false),
66
+			'venue'           => array('Venue.VNU_name' => false),
67
+			'start_date_time' => array('Datetime.DTT_EVT_start' => false),
68
+			'reg_begins'      => array('Datetime.Ticket.TKT_start_date' => false),
69
+		);
70
+
71
+		$this->_primary_column = 'id';
72
+		$this->_hidden_columns = array('author', 'event_category');
73
+	}
74
+
75
+
76
+	/**
77
+	 * @return array
78
+	 */
79
+	protected function _get_table_filters()
80
+	{
81
+		return array(); // no filters with decaf
82
+	}
83
+
84
+
85
+	/**
86
+	 * Setup of views properties.
87
+	 *
88
+	 * @throws InvalidDataTypeException
89
+	 * @throws InvalidInterfaceException
90
+	 * @throws InvalidArgumentException
91
+	 */
92
+	protected function _add_view_counts()
93
+	{
94
+		$this->_views['all']['count'] = $this->_admin_page->total_events();
95
+		$this->_views['draft']['count'] = $this->_admin_page->total_events_draft();
96
+		if (
97
+			EE_Registry::instance()->CAP->current_user_can(
98
+				'ee_delete_events',
99
+				'espresso_events_trash_events'
100
+			)
101
+		) {
102
+			$this->_views['trash']['count'] = $this->_admin_page->total_trashed_events();
103
+		}
104
+	}
105
+
106
+
107
+	/**
108
+	 * @param EE_Event $item
109
+	 * @return string
110
+	 * @throws EE_Error
111
+	 */
112
+	protected function _get_row_class($item)
113
+	{
114
+		$class = parent::_get_row_class($item);
115
+		// add status class
116
+		$class .= $item instanceof EE_Event
117
+			? ' ee-status-strip event-status-' . $item->get_active_status()
118
+			: '';
119
+		if ($this->_has_checkbox_column) {
120
+			$class .= ' has-checkbox-column';
121
+		}
122
+		return $class;
123
+	}
124
+
125
+
126
+	/**
127
+	 * @param EE_Event $item
128
+	 * @return string
129
+	 * @throws EE_Error
130
+	 */
131
+	public function column_status(EE_Event $item)
132
+	{
133
+		return '<span class="ee-status-strip ee-status-strip-td event-status-'
134
+			   . $item->get_active_status()
135
+			   . '"></span>';
136
+	}
137
+
138
+
139
+	/**
140
+	 * @param  EE_Event $item
141
+	 * @return string
142
+	 * @throws EE_Error
143
+	 */
144
+	public function column_cb($item)
145
+	{
146
+		if (! $item instanceof EE_Event) {
147
+			return '';
148
+		}
149
+		$this->_dtt = $item->primary_datetime(); // set this for use in other columns
150
+		// does event have any attached registrations?
151
+		$regs = $item->count_related('Registration');
152
+		return $regs > 0 && $this->_view === 'trash'
153
+			? '<span class="ee-lock-icon"></span>'
154
+			: sprintf(
155
+				'<input type="checkbox" name="EVT_IDs[]" value="%s" />',
156
+				$item->ID()
157
+			);
158
+	}
159
+
160
+
161
+	/**
162
+	 * @param EE_Event $item
163
+	 * @return mixed|string
164
+	 * @throws EE_Error
165
+	 */
166
+	public function column_id(EE_Event $item)
167
+	{
168
+		$content = $item->ID();
169
+		$content .= '  <span class="show-on-mobile-view-only">' . $item->name() . '</span>';
170
+		return $content;
171
+	}
172
+
173
+
174
+	/**
175
+	 * @param EE_Event $item
176
+	 * @return string
177
+	 * @throws EE_Error
178
+	 * @throws InvalidArgumentException
179
+	 * @throws InvalidDataTypeException
180
+	 * @throws InvalidInterfaceException
181
+	 */
182
+	public function column_name(EE_Event $item)
183
+	{
184
+		$edit_query_args = array(
185
+			'action' => 'edit',
186
+			'post'   => $item->ID(),
187
+		);
188
+		$edit_link = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
189
+		$actions = $this->_column_name_action_setup($item);
190
+		$status = ''; // $item->status() !== 'publish' ? ' (' . $item->status() . ')' : '';
191
+		$content = '<strong><a class="row-title" href="'
192
+				   . $edit_link . '">'
193
+				   . $item->name()
194
+				   . '</a></strong>'
195
+				   . $status;
196
+		$content .= '<br><span class="ee-status-text-small">'
197
+					. EEH_Template::pretty_status(
198
+						$item->get_active_status(),
199
+						false,
200
+						'sentence'
201
+					)
202
+					. '</span>';
203
+		$content .= $this->row_actions($actions);
204
+		return $content;
205
+	}
206
+
207
+
208
+	/**
209
+	 * Just a method for setting up the actions for the name column
210
+	 *
211
+	 * @param EE_Event $item
212
+	 * @return array array of actions
213
+	 * @throws EE_Error
214
+	 * @throws InvalidArgumentException
215
+	 * @throws InvalidDataTypeException
216
+	 * @throws InvalidInterfaceException
217
+	 */
218
+	protected function _column_name_action_setup(EE_Event $item)
219
+	{
220
+		// todo: remove when attendees is active
221
+		if (! defined('REG_ADMIN_URL')) {
222
+			define('REG_ADMIN_URL', EVENTS_ADMIN_URL);
223
+		}
224
+		$actions = array();
225
+		$restore_event_link = '';
226
+		$delete_event_link = '';
227
+		$trash_event_link = '';
228
+		if (
229
+			EE_Registry::instance()->CAP->current_user_can(
230
+				'ee_edit_event',
231
+				'espresso_events_edit',
232
+				$item->ID()
233
+			)
234
+		) {
235
+			$edit_query_args = array(
236
+				'action' => 'edit',
237
+				'post'   => $item->ID(),
238
+			);
239
+			$edit_link = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
240
+			$actions['edit'] = '<a href="' . $edit_link . '"'
241
+							   . ' title="' . esc_attr__('Edit Event', 'event_espresso') . '">'
242
+							   . esc_html__('Edit', 'event_espresso')
243
+							   . '</a>';
244
+		}
245
+		if (
246
+			EE_Registry::instance()->CAP->current_user_can(
247
+				'ee_read_registrations',
248
+				'espresso_registrations_view_registration'
249
+			)
250
+			&& EE_Registry::instance()->CAP->current_user_can(
251
+				'ee_read_event',
252
+				'espresso_registrations_view_registration',
253
+				$item->ID()
254
+			)
255
+		) {
256
+			$attendees_query_args = array(
257
+				'action'   => 'default',
258
+				'event_id' => $item->ID(),
259
+			);
260
+			$attendees_link = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
261
+			$actions['attendees'] = '<a href="' . $attendees_link . '"'
262
+									. ' title="' . esc_attr__('View Registrations', 'event_espresso') . '">'
263
+									. esc_html__('Registrations', 'event_espresso')
264
+									. '</a>';
265
+		}
266
+		if (
267
+			EE_Registry::instance()->CAP->current_user_can(
268
+				'ee_delete_event',
269
+				'espresso_events_trash_event',
270
+				$item->ID()
271
+			)
272
+		) {
273
+			$trash_event_query_args = array(
274
+				'action' => 'trash_event',
275
+				'EVT_ID' => $item->ID(),
276
+			);
277
+			$trash_event_link = EE_Admin_Page::add_query_args_and_nonce(
278
+				$trash_event_query_args,
279
+				EVENTS_ADMIN_URL
280
+			);
281
+		}
282
+		if (
283
+			EE_Registry::instance()->CAP->current_user_can(
284
+				'ee_delete_event',
285
+				'espresso_events_restore_event',
286
+				$item->ID()
287
+			)
288
+		) {
289
+			$restore_event_query_args = array(
290
+				'action' => 'restore_event',
291
+				'EVT_ID' => $item->ID(),
292
+			);
293
+			$restore_event_link = EE_Admin_Page::add_query_args_and_nonce(
294
+				$restore_event_query_args,
295
+				EVENTS_ADMIN_URL
296
+			);
297
+		}
298
+		if (
299
+			EE_Registry::instance()->CAP->current_user_can(
300
+				'ee_delete_event',
301
+				'espresso_events_delete_event',
302
+				$item->ID()
303
+			)
304
+		) {
305
+			$delete_event_query_args = array(
306
+				'action' => 'delete_event',
307
+				'EVT_ID' => $item->ID(),
308
+			);
309
+			$delete_event_link = EE_Admin_Page::add_query_args_and_nonce(
310
+				$delete_event_query_args,
311
+				EVENTS_ADMIN_URL
312
+			);
313
+		}
314
+		$view_link = get_permalink($item->ID());
315
+		$actions['view'] = '<a href="' . $view_link . '"'
316
+						   . ' title="' . esc_attr__('View Event', 'event_espresso') . '">'
317
+						   . esc_html__('View', 'event_espresso')
318
+						   . '</a>';
319
+		if ($item->get('status') === 'trash') {
320
+			if (
321
+				EE_Registry::instance()->CAP->current_user_can(
322
+					'ee_delete_event',
323
+					'espresso_events_restore_event',
324
+					$item->ID()
325
+				)
326
+			) {
327
+				$actions['restore_from_trash'] = '<a href="' . $restore_event_link . '"'
328
+												 . ' title="' . esc_attr__('Restore from Trash', 'event_espresso')
329
+												 . '">'
330
+												 . esc_html__('Restore from Trash', 'event_espresso')
331
+												 . '</a>';
332
+			}
333
+			if (
334
+				$item->count_related('Registration') === 0
335
+				&& EE_Registry::instance()->CAP->current_user_can(
336
+					'ee_delete_event',
337
+					'espresso_events_delete_event',
338
+					$item->ID()
339
+				)
340
+			) {
341
+				$actions['delete'] = '<a href="' . $delete_event_link . '"'
342
+									 . ' title="' . esc_attr__('Delete Permanently', 'event_espresso') . '">'
343
+									 . esc_html__('Delete Permanently', 'event_espresso')
344
+									 . '</a>';
345
+			}
346
+		} else {
347
+			if (
348
+				EE_Registry::instance()->CAP->current_user_can(
349
+					'ee_delete_event',
350
+					'espresso_events_trash_event',
351
+					$item->ID()
352
+				)
353
+			) {
354
+				$actions['move to trash'] = '<a href="' . $trash_event_link . '"'
355
+											. ' title="' . esc_attr__('Trash Event', 'event_espresso') . '">'
356
+											. esc_html__('Trash', 'event_espresso')
357
+											. '</a>';
358
+			}
359
+		}
360
+		return $actions;
361
+	}
362
+
363
+
364
+	/**
365
+	 * @param EE_Event $item
366
+	 * @return string
367
+	 * @throws EE_Error
368
+	 */
369
+	public function column_author(EE_Event $item)
370
+	{
371
+		// user author info
372
+		$event_author = get_userdata($item->wp_user());
373
+		$gravatar = get_avatar($item->wp_user(), '15');
374
+		// filter link
375
+		$query_args = array(
376
+			'action'      => 'default',
377
+			'EVT_wp_user' => $item->wp_user(),
378
+		);
379
+		$filter_url = EE_Admin_Page::add_query_args_and_nonce($query_args, EVENTS_ADMIN_URL);
380
+		return $gravatar . '  <a href="' . $filter_url . '"'
381
+			   . ' title="' . esc_attr__('Click to filter events by this author.', 'event_espresso') . '">'
382
+			   . $event_author->display_name
383
+			   . '</a>';
384
+	}
385
+
386
+
387
+	/**
388
+	 * @param EE_Event $event
389
+	 * @return string
390
+	 * @throws EE_Error
391
+	 */
392
+	public function column_event_category(EE_Event $event)
393
+	{
394
+		$event_categories = $event->get_all_event_categories();
395
+		return implode(
396
+			', ',
397
+			array_map(
398
+				function (EE_Term $category) {
399
+					return $category->name();
400
+				},
401
+				$event_categories
402
+			)
403
+		);
404
+	}
405
+
406
+
407
+	/**
408
+	 * @param EE_Event $item
409
+	 * @return string
410
+	 * @throws EE_Error
411
+	 */
412
+	public function column_venue(EE_Event $item)
413
+	{
414
+		$venue = $item->get_first_related('Venue');
415
+		return ! empty($venue)
416
+			? $venue->name()
417
+			: '';
418
+	}
419
+
420
+
421
+	/**
422
+	 * @param EE_Event $item
423
+	 * @return string
424
+	 * @throws EE_Error
425
+	 */
426
+	public function column_start_date_time(EE_Event $item)
427
+	{
428
+		return $this->_dtt instanceof EE_Datetime
429
+			? $this->_dtt->get_i18n_datetime('DTT_EVT_start')
430
+			: esc_html__('No Date was saved for this Event', 'event_espresso');
431
+	}
432
+
433
+
434
+	/**
435
+	 * @param EE_Event $item
436
+	 * @return string
437
+	 * @throws EE_Error
438
+	 */
439
+	public function column_reg_begins(EE_Event $item)
440
+	{
441
+		$reg_start = $item->get_ticket_with_earliest_start_time();
442
+		return $reg_start instanceof EE_Ticket
443
+			? $reg_start->get_i18n_datetime('TKT_start_date')
444
+			: esc_html__('No Tickets have been setup for this Event', 'event_espresso');
445
+	}
446
+
447
+
448
+	/**
449
+	 * @param EE_Event $item
450
+	 * @return int|string
451
+	 * @throws EE_Error
452
+	 * @throws InvalidArgumentException
453
+	 * @throws InvalidDataTypeException
454
+	 * @throws InvalidInterfaceException
455
+	 */
456
+	public function column_attendees(EE_Event $item)
457
+	{
458
+		$attendees_query_args = array(
459
+			'action'   => 'default',
460
+			'event_id' => $item->ID(),
461
+		);
462
+		$attendees_link = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
463
+		$registered_attendees = EEM_Registration::instance()->get_event_registration_count($item->ID());
464
+		return EE_Registry::instance()->CAP->current_user_can(
465
+			'ee_read_event',
466
+			'espresso_registrations_view_registration',
467
+			$item->ID()
468
+		)
469
+			   && EE_Registry::instance()->CAP->current_user_can(
470
+				   'ee_read_registrations',
471
+				   'espresso_registrations_view_registration'
472
+			   )
473
+			? '<a href="' . $attendees_link . '">' . $registered_attendees . '</a>'
474
+			: $registered_attendees;
475
+	}
476
+
477
+
478
+	/**
479
+	 * @param EE_Event $item
480
+	 * @return float
481
+	 * @throws EE_Error
482
+	 * @throws InvalidArgumentException
483
+	 * @throws InvalidDataTypeException
484
+	 * @throws InvalidInterfaceException
485
+	 */
486
+	public function column_tkts_sold(EE_Event $item)
487
+	{
488
+		return EEM_Ticket::instance()->sum(array(array('Datetime.EVT_ID' => $item->ID())), 'TKT_sold');
489
+	}
490
+
491
+
492
+	/**
493
+	 * @param EE_Event $item
494
+	 * @return string
495
+	 * @throws EE_Error
496
+	 * @throws InvalidArgumentException
497
+	 * @throws InvalidDataTypeException
498
+	 * @throws InvalidInterfaceException
499
+	 */
500
+	public function column_actions(EE_Event $item)
501
+	{
502
+		// todo: remove when attendees is active
503
+		if (! defined('REG_ADMIN_URL')) {
504
+			define('REG_ADMIN_URL', EVENTS_ADMIN_URL);
505
+		}
506
+		$action_links = array();
507
+		$view_link = get_permalink($item->ID());
508
+		$action_links[] = '<a href="' . $view_link . '"'
509
+						  . ' title="' . esc_attr__('View Event', 'event_espresso') . '" target="_blank">';
510
+		$action_links[] = '<div class="dashicons dashicons-search"></div></a>';
511
+		if (
512
+			EE_Registry::instance()->CAP->current_user_can(
513
+				'ee_edit_event',
514
+				'espresso_events_edit',
515
+				$item->ID()
516
+			)
517
+		) {
518
+			$edit_query_args = array(
519
+				'action' => 'edit',
520
+				'post'   => $item->ID(),
521
+			);
522
+			$edit_link = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
523
+			$action_links[] = '<a href="' . $edit_link . '"'
524
+							  . ' title="' . esc_attr__('Edit Event', 'event_espresso') . '">'
525
+							  . '<div class="ee-icon ee-icon-calendar-edit"></div>'
526
+							  . '</a>';
527
+		}
528
+		if (
529
+			EE_Registry::instance()->CAP->current_user_can(
530
+				'ee_read_registrations',
531
+				'espresso_registrations_view_registration'
532
+			) && EE_Registry::instance()->CAP->current_user_can(
533
+				'ee_read_event',
534
+				'espresso_registrations_view_registration',
535
+				$item->ID()
536
+			)
537
+		) {
538
+			$attendees_query_args = array(
539
+				'action'   => 'default',
540
+				'event_id' => $item->ID(),
541
+			);
542
+			$attendees_link = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
543
+			$action_links[] = '<a href="' . $attendees_link . '"'
544
+							  . ' title="' . esc_attr__('View Registrants', 'event_espresso') . '">'
545
+							  . '<div class="dashicons dashicons-groups"></div>'
546
+							  . '</a>';
547
+		}
548
+		$action_links = apply_filters(
549
+			'FHEE__Events_Admin_List_Table__column_actions__action_links',
550
+			$action_links,
551
+			$item
552
+		);
553
+		return $this->_action_string(
554
+			implode("\n\t", $action_links),
555
+			$item,
556
+			'div'
557
+		);
558
+	}
559
+
560
+
561
+	/**
562
+	 * Helper for adding columns conditionally
563
+	 *
564
+	 * @throws EE_Error
565
+	 * @throws InvalidArgumentException
566
+	 * @throws InvalidDataTypeException
567
+	 * @throws InvalidInterfaceException
568
+	 */
569
+	private function addConditionalColumns()
570
+	{
571
+		$event_category_count = EEM_Term::instance()->count(
572
+			[['Term_Taxonomy.taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY]]
573
+		);
574
+		if ($event_category_count === 0) {
575
+			return;
576
+		}
577
+		$column_array = [];
578
+		foreach ($this->_columns as $column => $column_label) {
579
+			$column_array[ $column ] = $column_label;
580
+			if ($column === 'venue') {
581
+				$column_array['event_category'] = esc_html__('Event Category', 'event_espresso');
582
+			}
583
+		}
584
+		$this->_columns = $column_array;
585
+	}
586 586
 }
Please login to merge, or discard this patch.
Spacing   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -114,7 +114,7 @@  discard block
 block discarded – undo
114 114
         $class = parent::_get_row_class($item);
115 115
         // add status class
116 116
         $class .= $item instanceof EE_Event
117
-            ? ' ee-status-strip event-status-' . $item->get_active_status()
117
+            ? ' ee-status-strip event-status-'.$item->get_active_status()
118 118
             : '';
119 119
         if ($this->_has_checkbox_column) {
120 120
             $class .= ' has-checkbox-column';
@@ -143,7 +143,7 @@  discard block
 block discarded – undo
143 143
      */
144 144
     public function column_cb($item)
145 145
     {
146
-        if (! $item instanceof EE_Event) {
146
+        if ( ! $item instanceof EE_Event) {
147 147
             return '';
148 148
         }
149 149
         $this->_dtt = $item->primary_datetime(); // set this for use in other columns
@@ -166,7 +166,7 @@  discard block
 block discarded – undo
166 166
     public function column_id(EE_Event $item)
167 167
     {
168 168
         $content = $item->ID();
169
-        $content .= '  <span class="show-on-mobile-view-only">' . $item->name() . '</span>';
169
+        $content .= '  <span class="show-on-mobile-view-only">'.$item->name().'</span>';
170 170
         return $content;
171 171
     }
172 172
 
@@ -189,7 +189,7 @@  discard block
 block discarded – undo
189 189
         $actions = $this->_column_name_action_setup($item);
190 190
         $status = ''; // $item->status() !== 'publish' ? ' (' . $item->status() . ')' : '';
191 191
         $content = '<strong><a class="row-title" href="'
192
-                   . $edit_link . '">'
192
+                   . $edit_link.'">'
193 193
                    . $item->name()
194 194
                    . '</a></strong>'
195 195
                    . $status;
@@ -218,7 +218,7 @@  discard block
 block discarded – undo
218 218
     protected function _column_name_action_setup(EE_Event $item)
219 219
     {
220 220
         // todo: remove when attendees is active
221
-        if (! defined('REG_ADMIN_URL')) {
221
+        if ( ! defined('REG_ADMIN_URL')) {
222 222
             define('REG_ADMIN_URL', EVENTS_ADMIN_URL);
223 223
         }
224 224
         $actions = array();
@@ -237,8 +237,8 @@  discard block
 block discarded – undo
237 237
                 'post'   => $item->ID(),
238 238
             );
239 239
             $edit_link = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
240
-            $actions['edit'] = '<a href="' . $edit_link . '"'
241
-                               . ' title="' . esc_attr__('Edit Event', 'event_espresso') . '">'
240
+            $actions['edit'] = '<a href="'.$edit_link.'"'
241
+                               . ' title="'.esc_attr__('Edit Event', 'event_espresso').'">'
242 242
                                . esc_html__('Edit', 'event_espresso')
243 243
                                . '</a>';
244 244
         }
@@ -258,8 +258,8 @@  discard block
 block discarded – undo
258 258
                 'event_id' => $item->ID(),
259 259
             );
260 260
             $attendees_link = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
261
-            $actions['attendees'] = '<a href="' . $attendees_link . '"'
262
-                                    . ' title="' . esc_attr__('View Registrations', 'event_espresso') . '">'
261
+            $actions['attendees'] = '<a href="'.$attendees_link.'"'
262
+                                    . ' title="'.esc_attr__('View Registrations', 'event_espresso').'">'
263 263
                                     . esc_html__('Registrations', 'event_espresso')
264 264
                                     . '</a>';
265 265
         }
@@ -312,8 +312,8 @@  discard block
 block discarded – undo
312 312
             );
313 313
         }
314 314
         $view_link = get_permalink($item->ID());
315
-        $actions['view'] = '<a href="' . $view_link . '"'
316
-                           . ' title="' . esc_attr__('View Event', 'event_espresso') . '">'
315
+        $actions['view'] = '<a href="'.$view_link.'"'
316
+                           . ' title="'.esc_attr__('View Event', 'event_espresso').'">'
317 317
                            . esc_html__('View', 'event_espresso')
318 318
                            . '</a>';
319 319
         if ($item->get('status') === 'trash') {
@@ -324,8 +324,8 @@  discard block
 block discarded – undo
324 324
                     $item->ID()
325 325
                 )
326 326
             ) {
327
-                $actions['restore_from_trash'] = '<a href="' . $restore_event_link . '"'
328
-                                                 . ' title="' . esc_attr__('Restore from Trash', 'event_espresso')
327
+                $actions['restore_from_trash'] = '<a href="'.$restore_event_link.'"'
328
+                                                 . ' title="'.esc_attr__('Restore from Trash', 'event_espresso')
329 329
                                                  . '">'
330 330
                                                  . esc_html__('Restore from Trash', 'event_espresso')
331 331
                                                  . '</a>';
@@ -338,8 +338,8 @@  discard block
 block discarded – undo
338 338
                     $item->ID()
339 339
                 )
340 340
             ) {
341
-                $actions['delete'] = '<a href="' . $delete_event_link . '"'
342
-                                     . ' title="' . esc_attr__('Delete Permanently', 'event_espresso') . '">'
341
+                $actions['delete'] = '<a href="'.$delete_event_link.'"'
342
+                                     . ' title="'.esc_attr__('Delete Permanently', 'event_espresso').'">'
343 343
                                      . esc_html__('Delete Permanently', 'event_espresso')
344 344
                                      . '</a>';
345 345
             }
@@ -351,8 +351,8 @@  discard block
 block discarded – undo
351 351
                     $item->ID()
352 352
                 )
353 353
             ) {
354
-                $actions['move to trash'] = '<a href="' . $trash_event_link . '"'
355
-                                            . ' title="' . esc_attr__('Trash Event', 'event_espresso') . '">'
354
+                $actions['move to trash'] = '<a href="'.$trash_event_link.'"'
355
+                                            . ' title="'.esc_attr__('Trash Event', 'event_espresso').'">'
356 356
                                             . esc_html__('Trash', 'event_espresso')
357 357
                                             . '</a>';
358 358
             }
@@ -377,8 +377,8 @@  discard block
 block discarded – undo
377 377
             'EVT_wp_user' => $item->wp_user(),
378 378
         );
379 379
         $filter_url = EE_Admin_Page::add_query_args_and_nonce($query_args, EVENTS_ADMIN_URL);
380
-        return $gravatar . '  <a href="' . $filter_url . '"'
381
-               . ' title="' . esc_attr__('Click to filter events by this author.', 'event_espresso') . '">'
380
+        return $gravatar.'  <a href="'.$filter_url.'"'
381
+               . ' title="'.esc_attr__('Click to filter events by this author.', 'event_espresso').'">'
382 382
                . $event_author->display_name
383 383
                . '</a>';
384 384
     }
@@ -395,7 +395,7 @@  discard block
 block discarded – undo
395 395
         return implode(
396 396
             ', ',
397 397
             array_map(
398
-                function (EE_Term $category) {
398
+                function(EE_Term $category) {
399 399
                     return $category->name();
400 400
                 },
401 401
                 $event_categories
@@ -470,7 +470,7 @@  discard block
 block discarded – undo
470 470
                    'ee_read_registrations',
471 471
                    'espresso_registrations_view_registration'
472 472
                )
473
-            ? '<a href="' . $attendees_link . '">' . $registered_attendees . '</a>'
473
+            ? '<a href="'.$attendees_link.'">'.$registered_attendees.'</a>'
474 474
             : $registered_attendees;
475 475
     }
476 476
 
@@ -500,13 +500,13 @@  discard block
 block discarded – undo
500 500
     public function column_actions(EE_Event $item)
501 501
     {
502 502
         // todo: remove when attendees is active
503
-        if (! defined('REG_ADMIN_URL')) {
503
+        if ( ! defined('REG_ADMIN_URL')) {
504 504
             define('REG_ADMIN_URL', EVENTS_ADMIN_URL);
505 505
         }
506 506
         $action_links = array();
507 507
         $view_link = get_permalink($item->ID());
508
-        $action_links[] = '<a href="' . $view_link . '"'
509
-                          . ' title="' . esc_attr__('View Event', 'event_espresso') . '" target="_blank">';
508
+        $action_links[] = '<a href="'.$view_link.'"'
509
+                          . ' title="'.esc_attr__('View Event', 'event_espresso').'" target="_blank">';
510 510
         $action_links[] = '<div class="dashicons dashicons-search"></div></a>';
511 511
         if (
512 512
             EE_Registry::instance()->CAP->current_user_can(
@@ -520,8 +520,8 @@  discard block
 block discarded – undo
520 520
                 'post'   => $item->ID(),
521 521
             );
522 522
             $edit_link = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
523
-            $action_links[] = '<a href="' . $edit_link . '"'
524
-                              . ' title="' . esc_attr__('Edit Event', 'event_espresso') . '">'
523
+            $action_links[] = '<a href="'.$edit_link.'"'
524
+                              . ' title="'.esc_attr__('Edit Event', 'event_espresso').'">'
525 525
                               . '<div class="ee-icon ee-icon-calendar-edit"></div>'
526 526
                               . '</a>';
527 527
         }
@@ -540,8 +540,8 @@  discard block
 block discarded – undo
540 540
                 'event_id' => $item->ID(),
541 541
             );
542 542
             $attendees_link = EE_Admin_Page::add_query_args_and_nonce($attendees_query_args, REG_ADMIN_URL);
543
-            $action_links[] = '<a href="' . $attendees_link . '"'
544
-                              . ' title="' . esc_attr__('View Registrants', 'event_espresso') . '">'
543
+            $action_links[] = '<a href="'.$attendees_link.'"'
544
+                              . ' title="'.esc_attr__('View Registrants', 'event_espresso').'">'
545 545
                               . '<div class="dashicons dashicons-groups"></div>'
546 546
                               . '</a>';
547 547
         }
@@ -576,7 +576,7 @@  discard block
 block discarded – undo
576 576
         }
577 577
         $column_array = [];
578 578
         foreach ($this->_columns as $column => $column_label) {
579
-            $column_array[ $column ] = $column_label;
579
+            $column_array[$column] = $column_label;
580 580
             if ($column === 'venue') {
581 581
                 $column_array['event_category'] = esc_html__('Event Category', 'event_espresso');
582 582
             }
Please login to merge, or discard this patch.
core/services/orm/ModelFieldFactory.php 3 patches
Unused Use Statements   -3 removed lines patch added patch discarded remove patch
@@ -33,9 +33,6 @@
 block discarded – undo
33 33
 use EE_WP_Post_Status_Field;
34 34
 use EE_WP_Post_Type_Field;
35 35
 use EE_WP_User_Field;
36
-use EventEspresso\core\exceptions\InvalidDataTypeException;
37
-use EventEspresso\core\exceptions\InvalidInterfaceException;
38
-use EventEspresso\core\services\loaders\LoaderFactory;
39 36
 use EventEspresso\core\services\loaders\LoaderInterface;
40 37
 use InvalidArgumentException;
41 38
 
Please login to merge, or discard this patch.
Doc Comments   +4 added lines, -5 removed lines patch added patch discarded remove patch
@@ -125,7 +125,6 @@  discard block
 block discarded – undo
125 125
     /**
126 126
      * @param string $table_column
127 127
      * @param string $nice_name
128
-     * @param string $timezone_string
129 128
      * @param bool   $nullable
130 129
      * @param string $default_value
131 130
      * @throws EE_Error
@@ -170,7 +169,7 @@  discard block
 block discarded – undo
170 169
      * @param string $table_column
171 170
      * @param string $nice_name
172 171
      * @param bool   $nullable
173
-     * @param null   $default_value
172
+     * @param integer   $default_value
174 173
      * @return EE_DB_Only_Int_Field
175 174
      */
176 175
     public function createDbOnlyIntField($table_column, $nice_name, $nullable, $default_value = null)
@@ -280,7 +279,7 @@  discard block
 block discarded – undo
280 279
      * @param string $table_column
281 280
      * @param string $nice_name
282 281
      * @param bool   $nullable
283
-     * @param null   $default_value
282
+     * @param integer   $default_value
284 283
      * @param string $model_name
285 284
      * @return EE_Foreign_Key_Int_Field
286 285
      */
@@ -297,7 +296,7 @@  discard block
 block discarded – undo
297 296
      * @param string $table_column
298 297
      * @param string $nice_name
299 298
      * @param bool   $nullable
300
-     * @param null   $default_value
299
+     * @param string   $default_value
301 300
      * @param string $model_name
302 301
      * @return EE_Foreign_Key_String_Field
303 302
      */
@@ -533,7 +532,7 @@  discard block
 block discarded – undo
533 532
      * @param string $table_column
534 533
      * @param string $nice_name
535 534
      * @param bool   $nullable
536
-     * @param mixed  $default_value
535
+     * @param string  $default_value
537 536
      * @param array  $values                            If additional stati are to be used other than the default WP
538 537
      *                                                  statuses, then they can be registered via this property. The
539 538
      *                                                  format of the array should be as follows: array(
Please login to merge, or discard this patch.
Indentation   +543 added lines, -543 removed lines patch added patch discarded remove patch
@@ -51,547 +51,547 @@
 block discarded – undo
51 51
 class ModelFieldFactory
52 52
 {
53 53
 
54
-    /**
55
-     * @var LoaderInterface $loader
56
-     */
57
-    private $loader;
58
-
59
-
60
-    /**
61
-     * ModelFieldFactory constructor.
62
-     *
63
-     * @param LoaderInterface $loader
64
-     */
65
-    public function __construct(LoaderInterface $loader)
66
-    {
67
-        $this->loader = $loader;
68
-    }
69
-
70
-
71
-    /**
72
-     * @param string $table_column
73
-     * @param string $nice_name
74
-     * @param bool   $nullable
75
-     * @param null   $default_value
76
-     * @return EE_All_Caps_Text_Field
77
-     */
78
-    public function createAllCapsTextField($table_column, $nice_name, $nullable, $default_value = null)
79
-    {
80
-        return $this->loader->getNew(
81
-            'EE_All_Caps_Text_Field',
82
-            array($table_column, $nice_name, $nullable, $default_value)
83
-        );
84
-    }
85
-
86
-
87
-    /**
88
-     * @param string $table_column
89
-     * @param string $nice_name
90
-     * @param bool   $nullable
91
-     * @param null   $default_value
92
-     * @param string $model_name
93
-     * @return EE_Any_Foreign_Model_Name_Field
94
-     */
95
-    public function createAnyForeignModelNameField(
96
-        $table_column,
97
-        $nice_name,
98
-        $nullable,
99
-        $default_value = null,
100
-        $model_name
101
-    ) {
102
-        return $this->loader->getNew(
103
-            'EE_Any_Foreign_Model_Name_Field',
104
-            array($table_column, $nice_name, $nullable, $default_value, $model_name)
105
-        );
106
-    }
107
-
108
-
109
-    /**
110
-     * @param string $table_column
111
-     * @param string $nice_name
112
-     * @param bool   $nullable
113
-     * @param null   $default_value
114
-     * @return EE_Boolean_Field
115
-     */
116
-    public function createBooleanField($table_column, $nice_name, $nullable, $default_value = null)
117
-    {
118
-        return $this->loader->getNew(
119
-            'EE_Boolean_Field',
120
-            array($table_column, $nice_name, $nullable, $default_value)
121
-        );
122
-    }
123
-
124
-
125
-    /**
126
-     * @param string $table_column
127
-     * @param string $nice_name
128
-     * @param string $timezone_string
129
-     * @param bool   $nullable
130
-     * @param string $default_value
131
-     * @throws EE_Error
132
-     * @throws InvalidArgumentException
133
-     * @return EE_Datetime_Field
134
-     */
135
-    public function createDatetimeField(
136
-        $table_column,
137
-        $nice_name,
138
-        $nullable = false,
139
-        $default_value = EE_Datetime_Field::now
140
-    ) {
141
-        return $this->loader->getNew(
142
-            'EE_Datetime_Field',
143
-            array(
144
-                $table_column,
145
-                $nice_name,
146
-                $nullable,
147
-                $default_value,
148
-            )
149
-        );
150
-    }
151
-
152
-
153
-    /**
154
-     * @param string $table_column
155
-     * @param string $nice_name
156
-     * @param bool   $nullable
157
-     * @param null   $default_value
158
-     * @return EE_DB_Only_Float_Field
159
-     */
160
-    public function createDbOnlyFloatField($table_column, $nice_name, $nullable, $default_value = null)
161
-    {
162
-        return $this->loader->getNew(
163
-            'EE_DB_Only_Float_Field',
164
-            array($table_column, $nice_name, $nullable, $default_value)
165
-        );
166
-    }
167
-
168
-
169
-    /**
170
-     * @param string $table_column
171
-     * @param string $nice_name
172
-     * @param bool   $nullable
173
-     * @param null   $default_value
174
-     * @return EE_DB_Only_Int_Field
175
-     */
176
-    public function createDbOnlyIntField($table_column, $nice_name, $nullable, $default_value = null)
177
-    {
178
-        return $this->loader->getNew(
179
-            'EE_DB_Only_Int_Field',
180
-            array($table_column, $nice_name, $nullable, $default_value)
181
-        );
182
-    }
183
-
184
-
185
-    /**
186
-     * @param string $table_column
187
-     * @param string $nice_name
188
-     * @param bool   $nullable
189
-     * @param null   $default_value
190
-     * @return EE_DB_Only_Text_Field
191
-     */
192
-    public function createDbOnlyTextField($table_column, $nice_name, $nullable, $default_value = null)
193
-    {
194
-        return $this->loader->getNew(
195
-            'EE_DB_Only_Text_Field',
196
-            array($table_column, $nice_name, $nullable, $default_value)
197
-        );
198
-    }
199
-
200
-
201
-    /**
202
-     * @param string $table_column
203
-     * @param string $nice_name
204
-     * @param bool   $nullable
205
-     * @param string $default_value
206
-     * @return EE_Email_Field
207
-     */
208
-    public function createEmailField($table_column, $nice_name, $nullable = true, $default_value = '')
209
-    {
210
-        return $this->loader->getNew(
211
-            'EE_Email_Field',
212
-            array($table_column, $nice_name, $nullable, $default_value)
213
-        );
214
-    }
215
-
216
-
217
-    /**
218
-     * @param string $table_column
219
-     * @param string $nice_name
220
-     * @param bool   $nullable
221
-     * @param null   $default_value
222
-     * @param array  $allowed_enum_values keys are values to be used in the DB,
223
-     *                                    values are how they should be displayed
224
-     * @return EE_Enum_Integer_Field
225
-     */
226
-    public function createEnumIntegerField(
227
-        $table_column,
228
-        $nice_name,
229
-        $nullable,
230
-        $default_value = null,
231
-        array $allowed_enum_values
232
-    ) {
233
-        return $this->loader->getNew(
234
-            'EE_Enum_Integer_Field',
235
-            array($table_column, $nice_name, $nullable, $default_value, $allowed_enum_values)
236
-        );
237
-    }
238
-
239
-
240
-    /**
241
-     * @param string $table_column
242
-     * @param string $nice_name
243
-     * @param bool   $nullable
244
-     * @param null   $default_value
245
-     * @param array  $allowed_enum_values keys are values to be used in the DB,
246
-     *                                    values are how they should be displayed
247
-     * @return EE_Enum_Text_Field
248
-     */
249
-    public function createEnumTextField(
250
-        $table_column,
251
-        $nice_name,
252
-        $nullable,
253
-        $default_value,
254
-        array $allowed_enum_values
255
-    ) {
256
-        return $this->loader->getNew(
257
-            'EE_Enum_Text_Field',
258
-            array($table_column, $nice_name, $nullable, $default_value, $allowed_enum_values)
259
-        );
260
-    }
261
-
262
-
263
-    /**
264
-     * @param string $table_column
265
-     * @param string $nice_name
266
-     * @param bool   $nullable
267
-     * @param null   $default_value
268
-     * @return EE_Float_Field
269
-     */
270
-    public function createFloatField($table_column, $nice_name, $nullable, $default_value = null)
271
-    {
272
-        return $this->loader->getNew(
273
-            'EE_Float_Field',
274
-            array($table_column, $nice_name, $nullable, $default_value)
275
-        );
276
-    }
277
-
278
-
279
-    /**
280
-     * @param string $table_column
281
-     * @param string $nice_name
282
-     * @param bool   $nullable
283
-     * @param null   $default_value
284
-     * @param string $model_name
285
-     * @return EE_Foreign_Key_Int_Field
286
-     */
287
-    public function createForeignKeyIntField($table_column, $nice_name, $nullable, $default_value, $model_name)
288
-    {
289
-        return $this->loader->getNew(
290
-            'EE_Foreign_Key_Int_Field',
291
-            array($table_column, $nice_name, $nullable, $default_value, $model_name)
292
-        );
293
-    }
294
-
295
-
296
-    /**
297
-     * @param string $table_column
298
-     * @param string $nice_name
299
-     * @param bool   $nullable
300
-     * @param null   $default_value
301
-     * @param string $model_name
302
-     * @return EE_Foreign_Key_String_Field
303
-     */
304
-    public function createForeignKeyStringField(
305
-        $table_column,
306
-        $nice_name,
307
-        $nullable,
308
-        $default_value,
309
-        $model_name
310
-    ) {
311
-        return $this->loader->getNew(
312
-            'EE_Foreign_Key_String_Field',
313
-            array($table_column, $nice_name, $nullable, $default_value, $model_name)
314
-        );
315
-    }
316
-
317
-
318
-    /**
319
-     * @param string $table_column
320
-     * @param string $nice_name
321
-     * @param bool   $nullable
322
-     * @param null   $default_value
323
-     * @return EE_Full_HTML_Field
324
-     */
325
-    public function createFullHtmlField($table_column, $nice_name, $nullable, $default_value = null)
326
-    {
327
-        return $this->loader->getNew(
328
-            'EE_Full_HTML_Field',
329
-            array($table_column, $nice_name, $nullable, $default_value)
330
-        );
331
-    }
332
-
333
-
334
-    /**
335
-     * @param string $table_column
336
-     * @param string $nice_name
337
-     * @param bool   $nullable
338
-     * @param null   $default_value
339
-     * @return EE_Infinite_Integer_Field
340
-     */
341
-    public function createInfiniteIntegerField($table_column, $nice_name, $nullable, $default_value = null)
342
-    {
343
-        return $this->loader->getNew(
344
-            'EE_Infinite_Integer_Field',
345
-            array($table_column, $nice_name, $nullable, $default_value)
346
-        );
347
-    }
348
-
349
-
350
-    /**
351
-     * @param string  $table_column
352
-     * @param string  $nice_name
353
-     * @param bool    $nullable
354
-     * @param integer $default_value
355
-     * @return EE_Integer_Field
356
-     */
357
-    public function createIntegerField($table_column, $nice_name, $nullable = false, $default_value = 0)
358
-    {
359
-        return $this->loader->getNew(
360
-            'EE_Integer_Field',
361
-            array($table_column, $nice_name, $nullable, $default_value)
362
-        );
363
-    }
364
-
365
-
366
-    /**
367
-     * @param string $table_column
368
-     * @param string $nice_name
369
-     * @param bool   $nullable
370
-     * @param null   $default_value
371
-     * @return EE_Maybe_Serialized_Simple_HTML_Field
372
-     */
373
-    public function createMaybeSerializedSimpleHtmlField($table_column, $nice_name, $nullable, $default_value = null)
374
-    {
375
-        return $this->loader->getNew(
376
-            'EE_Maybe_Serialized_Simple_HTML_Field',
377
-            array($table_column, $nice_name, $nullable, $default_value)
378
-        );
379
-    }
380
-
381
-
382
-    /**
383
-     * @param string $table_column
384
-     * @param string $nice_name
385
-     * @param bool   $nullable
386
-     * @param null   $default_value
387
-     * @return EE_Maybe_Serialized_Text_Field
388
-     */
389
-    public function createMaybeSerializedTextField($table_column, $nice_name, $nullable, $default_value = null)
390
-    {
391
-        return $this->loader->getNew(
392
-            'EE_Maybe_Serialized_Text_Field',
393
-            array($table_column, $nice_name, $nullable, $default_value)
394
-        );
395
-    }
396
-
397
-
398
-    /**
399
-     * @param string $table_column
400
-     * @param string $nice_name
401
-     * @param bool   $nullable
402
-     * @param null   $default_value
403
-     * @return EE_Money_Field
404
-     */
405
-    public function createMoneyField($table_column, $nice_name, $nullable, $default_value = null)
406
-    {
407
-        return $this->loader->getNew(
408
-            'EE_Money_Field',
409
-            array($table_column, $nice_name, $nullable, $default_value)
410
-        );
411
-    }
412
-
413
-
414
-    /**
415
-     * @param string $table_column
416
-     * @param string $nice_name
417
-     * @param bool   $nullable
418
-     * @param string $default_value
419
-     * @return EE_Plain_Text_Field
420
-     */
421
-    public function createPlainTextField($table_column, $nice_name, $nullable = true, $default_value = '')
422
-    {
423
-        return $this->loader->getNew(
424
-            'EE_Plain_Text_Field',
425
-            array($table_column, $nice_name, $nullable, $default_value)
426
-        );
427
-    }
428
-
429
-
430
-    /**
431
-     * @param string $table_column
432
-     * @param string $nice_name
433
-     * @param bool   $nullable
434
-     * @param null   $default_value
435
-     * @return EE_Post_Content_Field
436
-     */
437
-    public function createPostContentField($table_column, $nice_name, $nullable, $default_value = null)
438
-    {
439
-        return $this->loader->getNew(
440
-            'EE_Post_Content_Field',
441
-            array($table_column, $nice_name, $nullable, $default_value)
442
-        );
443
-    }
444
-
445
-
446
-    /**
447
-     * @param string $table_column
448
-     * @param string $nice_name
449
-     * @return EE_Primary_Key_Int_Field
450
-     */
451
-    public function createPrimaryKeyIntField($table_column, $nice_name)
452
-    {
453
-        return $this->loader->getNew('EE_Primary_Key_Int_Field', array($table_column, $nice_name));
454
-    }
455
-
456
-
457
-    /**
458
-     * @param string $table_column
459
-     * @param string $nice_name
460
-     * @return EE_Primary_Key_String_Field
461
-     */
462
-    public function createPrimaryKeyStringField($table_column, $nice_name)
463
-    {
464
-        return $this->loader->getNew('EE_Primary_Key_String_Field', array($table_column, $nice_name));
465
-    }
466
-
467
-
468
-    /**
469
-     * @param string $table_column
470
-     * @param string $nice_name
471
-     * @param bool   $nullable
472
-     * @param null   $default_value
473
-     * @return EE_Serialized_Text_Field
474
-     */
475
-    public function createSerializedTextField($table_column, $nice_name, $nullable, $default_value = null)
476
-    {
477
-        return $this->loader->getNew(
478
-            'EE_Serialized_Text_Field',
479
-            array($table_column, $nice_name, $nullable, $default_value)
480
-        );
481
-    }
482
-
483
-
484
-    /**
485
-     * @param string $table_column
486
-     * @param string $nice_name
487
-     * @param bool   $nullable
488
-     * @param null   $default_value
489
-     * @return EE_Simple_HTML_Field
490
-     */
491
-    public function createSimpleHtmlField($table_column, $nice_name, $nullable, $default_value = null)
492
-    {
493
-        return $this->loader->getNew(
494
-            'EE_Simple_HTML_Field',
495
-            array($table_column, $nice_name, $nullable, $default_value)
496
-        );
497
-    }
498
-
499
-
500
-    /**
501
-     * @param string $table_column
502
-     * @param string $nice_name
503
-     * @param bool   $nullable
504
-     * @param null   $default_value
505
-     * @return EE_Slug_Field
506
-     */
507
-    public function createSlugField($table_column, $nice_name, $nullable = false, $default_value = null)
508
-    {
509
-        return $this->loader->getNew(
510
-            'EE_Slug_Field',
511
-            array($table_column, $nice_name, $nullable, $default_value)
512
-        );
513
-    }
514
-
515
-
516
-    /**
517
-     * @param string $table_column
518
-     * @param string $nice_name
519
-     * @param bool   $nullable
520
-     * @param null   $default_value
521
-     * @return EE_Trashed_Flag_Field
522
-     */
523
-    public function createTrashedFlagField($table_column, $nice_name, $nullable, $default_value = null)
524
-    {
525
-        return $this->loader->getNew(
526
-            'EE_Trashed_Flag_Field',
527
-            array($table_column, $nice_name, $nullable, $default_value)
528
-        );
529
-    }
530
-
531
-
532
-    /**
533
-     * @param string $table_column
534
-     * @param string $nice_name
535
-     * @param bool   $nullable
536
-     * @param mixed  $default_value
537
-     * @param array  $values                            If additional stati are to be used other than the default WP
538
-     *                                                  statuses, then they can be registered via this property. The
539
-     *                                                  format of the array should be as follows: array(
540
-     *                                                  'status_reference' => array(
541
-     *                                                  'label' => __('Status Reference Label', 'event_espresso'),
542
-     *                                                  'public' => true,                 // whether this status should
543
-     *                                                  be shown on the frontend of the site
544
-     *                                                  'exclude_from_search' => false,   // whether this status should
545
-     *                                                  be excluded from wp searches
546
-     *                                                  'show_in_admin_all_list' => true, // whether this status is
547
-     *                                                  included in queries for the admin "all" view in list table
548
-     *                                                  views.
549
-     *                                                  'show_in_admin_status_list' => true, // show in the list of
550
-     *                                                  statuses with post counts at the top of the admin list tables
551
-     *                                                  (i.e. Status Reference(2) )
552
-     *                                                  'label_count' => _n_noop(
553
-     *                                                  'Status Reference <span class="count">(%s)</span>',
554
-     *                                                  'Status References <span class="count">(%s)</span>'
555
-     *                                                  ),                                   // the text to display on
556
-     *                                                  the admin screen
557
-     *                                                  ( or you won't see your status count ).
558
-     *                                                  )
559
-     *                                                  )
560
-     * @link http://codex.wordpress.org/Function_Reference/register_post_status for more info
561
-     * @return EE_WP_Post_Status_Field
562
-     */
563
-    public function createWpPostStatusField(
564
-        $table_column,
565
-        $nice_name,
566
-        $nullable,
567
-        $default_value = null,
568
-        array $values = array()
569
-    ) {
570
-        return $this->loader->getNew(
571
-            'EE_WP_Post_Status_Field',
572
-            array($table_column, $nice_name, $nullable, $default_value, $values)
573
-        );
574
-    }
575
-
576
-
577
-    /**
578
-     * @param string $post_type
579
-     * @return EE_WP_Post_Type_Field
580
-     */
581
-    public function createWpPostTypeField($post_type)
582
-    {
583
-        return $this->loader->getNew('EE_WP_Post_Type_Field', array($post_type));
584
-    }
585
-
586
-
587
-    /**
588
-     * @param string $table_column
589
-     * @param string $nice_name
590
-     * @param bool   $nullable
591
-     * @return EE_WP_User_Field
592
-     */
593
-    public function createWpUserField($table_column, $nice_name, $nullable)
594
-    {
595
-        return $this->loader->getNew('EE_WP_User_Field', array($table_column, $nice_name, $nullable));
596
-    }
54
+	/**
55
+	 * @var LoaderInterface $loader
56
+	 */
57
+	private $loader;
58
+
59
+
60
+	/**
61
+	 * ModelFieldFactory constructor.
62
+	 *
63
+	 * @param LoaderInterface $loader
64
+	 */
65
+	public function __construct(LoaderInterface $loader)
66
+	{
67
+		$this->loader = $loader;
68
+	}
69
+
70
+
71
+	/**
72
+	 * @param string $table_column
73
+	 * @param string $nice_name
74
+	 * @param bool   $nullable
75
+	 * @param null   $default_value
76
+	 * @return EE_All_Caps_Text_Field
77
+	 */
78
+	public function createAllCapsTextField($table_column, $nice_name, $nullable, $default_value = null)
79
+	{
80
+		return $this->loader->getNew(
81
+			'EE_All_Caps_Text_Field',
82
+			array($table_column, $nice_name, $nullable, $default_value)
83
+		);
84
+	}
85
+
86
+
87
+	/**
88
+	 * @param string $table_column
89
+	 * @param string $nice_name
90
+	 * @param bool   $nullable
91
+	 * @param null   $default_value
92
+	 * @param string $model_name
93
+	 * @return EE_Any_Foreign_Model_Name_Field
94
+	 */
95
+	public function createAnyForeignModelNameField(
96
+		$table_column,
97
+		$nice_name,
98
+		$nullable,
99
+		$default_value = null,
100
+		$model_name
101
+	) {
102
+		return $this->loader->getNew(
103
+			'EE_Any_Foreign_Model_Name_Field',
104
+			array($table_column, $nice_name, $nullable, $default_value, $model_name)
105
+		);
106
+	}
107
+
108
+
109
+	/**
110
+	 * @param string $table_column
111
+	 * @param string $nice_name
112
+	 * @param bool   $nullable
113
+	 * @param null   $default_value
114
+	 * @return EE_Boolean_Field
115
+	 */
116
+	public function createBooleanField($table_column, $nice_name, $nullable, $default_value = null)
117
+	{
118
+		return $this->loader->getNew(
119
+			'EE_Boolean_Field',
120
+			array($table_column, $nice_name, $nullable, $default_value)
121
+		);
122
+	}
123
+
124
+
125
+	/**
126
+	 * @param string $table_column
127
+	 * @param string $nice_name
128
+	 * @param string $timezone_string
129
+	 * @param bool   $nullable
130
+	 * @param string $default_value
131
+	 * @throws EE_Error
132
+	 * @throws InvalidArgumentException
133
+	 * @return EE_Datetime_Field
134
+	 */
135
+	public function createDatetimeField(
136
+		$table_column,
137
+		$nice_name,
138
+		$nullable = false,
139
+		$default_value = EE_Datetime_Field::now
140
+	) {
141
+		return $this->loader->getNew(
142
+			'EE_Datetime_Field',
143
+			array(
144
+				$table_column,
145
+				$nice_name,
146
+				$nullable,
147
+				$default_value,
148
+			)
149
+		);
150
+	}
151
+
152
+
153
+	/**
154
+	 * @param string $table_column
155
+	 * @param string $nice_name
156
+	 * @param bool   $nullable
157
+	 * @param null   $default_value
158
+	 * @return EE_DB_Only_Float_Field
159
+	 */
160
+	public function createDbOnlyFloatField($table_column, $nice_name, $nullable, $default_value = null)
161
+	{
162
+		return $this->loader->getNew(
163
+			'EE_DB_Only_Float_Field',
164
+			array($table_column, $nice_name, $nullable, $default_value)
165
+		);
166
+	}
167
+
168
+
169
+	/**
170
+	 * @param string $table_column
171
+	 * @param string $nice_name
172
+	 * @param bool   $nullable
173
+	 * @param null   $default_value
174
+	 * @return EE_DB_Only_Int_Field
175
+	 */
176
+	public function createDbOnlyIntField($table_column, $nice_name, $nullable, $default_value = null)
177
+	{
178
+		return $this->loader->getNew(
179
+			'EE_DB_Only_Int_Field',
180
+			array($table_column, $nice_name, $nullable, $default_value)
181
+		);
182
+	}
183
+
184
+
185
+	/**
186
+	 * @param string $table_column
187
+	 * @param string $nice_name
188
+	 * @param bool   $nullable
189
+	 * @param null   $default_value
190
+	 * @return EE_DB_Only_Text_Field
191
+	 */
192
+	public function createDbOnlyTextField($table_column, $nice_name, $nullable, $default_value = null)
193
+	{
194
+		return $this->loader->getNew(
195
+			'EE_DB_Only_Text_Field',
196
+			array($table_column, $nice_name, $nullable, $default_value)
197
+		);
198
+	}
199
+
200
+
201
+	/**
202
+	 * @param string $table_column
203
+	 * @param string $nice_name
204
+	 * @param bool   $nullable
205
+	 * @param string $default_value
206
+	 * @return EE_Email_Field
207
+	 */
208
+	public function createEmailField($table_column, $nice_name, $nullable = true, $default_value = '')
209
+	{
210
+		return $this->loader->getNew(
211
+			'EE_Email_Field',
212
+			array($table_column, $nice_name, $nullable, $default_value)
213
+		);
214
+	}
215
+
216
+
217
+	/**
218
+	 * @param string $table_column
219
+	 * @param string $nice_name
220
+	 * @param bool   $nullable
221
+	 * @param null   $default_value
222
+	 * @param array  $allowed_enum_values keys are values to be used in the DB,
223
+	 *                                    values are how they should be displayed
224
+	 * @return EE_Enum_Integer_Field
225
+	 */
226
+	public function createEnumIntegerField(
227
+		$table_column,
228
+		$nice_name,
229
+		$nullable,
230
+		$default_value = null,
231
+		array $allowed_enum_values
232
+	) {
233
+		return $this->loader->getNew(
234
+			'EE_Enum_Integer_Field',
235
+			array($table_column, $nice_name, $nullable, $default_value, $allowed_enum_values)
236
+		);
237
+	}
238
+
239
+
240
+	/**
241
+	 * @param string $table_column
242
+	 * @param string $nice_name
243
+	 * @param bool   $nullable
244
+	 * @param null   $default_value
245
+	 * @param array  $allowed_enum_values keys are values to be used in the DB,
246
+	 *                                    values are how they should be displayed
247
+	 * @return EE_Enum_Text_Field
248
+	 */
249
+	public function createEnumTextField(
250
+		$table_column,
251
+		$nice_name,
252
+		$nullable,
253
+		$default_value,
254
+		array $allowed_enum_values
255
+	) {
256
+		return $this->loader->getNew(
257
+			'EE_Enum_Text_Field',
258
+			array($table_column, $nice_name, $nullable, $default_value, $allowed_enum_values)
259
+		);
260
+	}
261
+
262
+
263
+	/**
264
+	 * @param string $table_column
265
+	 * @param string $nice_name
266
+	 * @param bool   $nullable
267
+	 * @param null   $default_value
268
+	 * @return EE_Float_Field
269
+	 */
270
+	public function createFloatField($table_column, $nice_name, $nullable, $default_value = null)
271
+	{
272
+		return $this->loader->getNew(
273
+			'EE_Float_Field',
274
+			array($table_column, $nice_name, $nullable, $default_value)
275
+		);
276
+	}
277
+
278
+
279
+	/**
280
+	 * @param string $table_column
281
+	 * @param string $nice_name
282
+	 * @param bool   $nullable
283
+	 * @param null   $default_value
284
+	 * @param string $model_name
285
+	 * @return EE_Foreign_Key_Int_Field
286
+	 */
287
+	public function createForeignKeyIntField($table_column, $nice_name, $nullable, $default_value, $model_name)
288
+	{
289
+		return $this->loader->getNew(
290
+			'EE_Foreign_Key_Int_Field',
291
+			array($table_column, $nice_name, $nullable, $default_value, $model_name)
292
+		);
293
+	}
294
+
295
+
296
+	/**
297
+	 * @param string $table_column
298
+	 * @param string $nice_name
299
+	 * @param bool   $nullable
300
+	 * @param null   $default_value
301
+	 * @param string $model_name
302
+	 * @return EE_Foreign_Key_String_Field
303
+	 */
304
+	public function createForeignKeyStringField(
305
+		$table_column,
306
+		$nice_name,
307
+		$nullable,
308
+		$default_value,
309
+		$model_name
310
+	) {
311
+		return $this->loader->getNew(
312
+			'EE_Foreign_Key_String_Field',
313
+			array($table_column, $nice_name, $nullable, $default_value, $model_name)
314
+		);
315
+	}
316
+
317
+
318
+	/**
319
+	 * @param string $table_column
320
+	 * @param string $nice_name
321
+	 * @param bool   $nullable
322
+	 * @param null   $default_value
323
+	 * @return EE_Full_HTML_Field
324
+	 */
325
+	public function createFullHtmlField($table_column, $nice_name, $nullable, $default_value = null)
326
+	{
327
+		return $this->loader->getNew(
328
+			'EE_Full_HTML_Field',
329
+			array($table_column, $nice_name, $nullable, $default_value)
330
+		);
331
+	}
332
+
333
+
334
+	/**
335
+	 * @param string $table_column
336
+	 * @param string $nice_name
337
+	 * @param bool   $nullable
338
+	 * @param null   $default_value
339
+	 * @return EE_Infinite_Integer_Field
340
+	 */
341
+	public function createInfiniteIntegerField($table_column, $nice_name, $nullable, $default_value = null)
342
+	{
343
+		return $this->loader->getNew(
344
+			'EE_Infinite_Integer_Field',
345
+			array($table_column, $nice_name, $nullable, $default_value)
346
+		);
347
+	}
348
+
349
+
350
+	/**
351
+	 * @param string  $table_column
352
+	 * @param string  $nice_name
353
+	 * @param bool    $nullable
354
+	 * @param integer $default_value
355
+	 * @return EE_Integer_Field
356
+	 */
357
+	public function createIntegerField($table_column, $nice_name, $nullable = false, $default_value = 0)
358
+	{
359
+		return $this->loader->getNew(
360
+			'EE_Integer_Field',
361
+			array($table_column, $nice_name, $nullable, $default_value)
362
+		);
363
+	}
364
+
365
+
366
+	/**
367
+	 * @param string $table_column
368
+	 * @param string $nice_name
369
+	 * @param bool   $nullable
370
+	 * @param null   $default_value
371
+	 * @return EE_Maybe_Serialized_Simple_HTML_Field
372
+	 */
373
+	public function createMaybeSerializedSimpleHtmlField($table_column, $nice_name, $nullable, $default_value = null)
374
+	{
375
+		return $this->loader->getNew(
376
+			'EE_Maybe_Serialized_Simple_HTML_Field',
377
+			array($table_column, $nice_name, $nullable, $default_value)
378
+		);
379
+	}
380
+
381
+
382
+	/**
383
+	 * @param string $table_column
384
+	 * @param string $nice_name
385
+	 * @param bool   $nullable
386
+	 * @param null   $default_value
387
+	 * @return EE_Maybe_Serialized_Text_Field
388
+	 */
389
+	public function createMaybeSerializedTextField($table_column, $nice_name, $nullable, $default_value = null)
390
+	{
391
+		return $this->loader->getNew(
392
+			'EE_Maybe_Serialized_Text_Field',
393
+			array($table_column, $nice_name, $nullable, $default_value)
394
+		);
395
+	}
396
+
397
+
398
+	/**
399
+	 * @param string $table_column
400
+	 * @param string $nice_name
401
+	 * @param bool   $nullable
402
+	 * @param null   $default_value
403
+	 * @return EE_Money_Field
404
+	 */
405
+	public function createMoneyField($table_column, $nice_name, $nullable, $default_value = null)
406
+	{
407
+		return $this->loader->getNew(
408
+			'EE_Money_Field',
409
+			array($table_column, $nice_name, $nullable, $default_value)
410
+		);
411
+	}
412
+
413
+
414
+	/**
415
+	 * @param string $table_column
416
+	 * @param string $nice_name
417
+	 * @param bool   $nullable
418
+	 * @param string $default_value
419
+	 * @return EE_Plain_Text_Field
420
+	 */
421
+	public function createPlainTextField($table_column, $nice_name, $nullable = true, $default_value = '')
422
+	{
423
+		return $this->loader->getNew(
424
+			'EE_Plain_Text_Field',
425
+			array($table_column, $nice_name, $nullable, $default_value)
426
+		);
427
+	}
428
+
429
+
430
+	/**
431
+	 * @param string $table_column
432
+	 * @param string $nice_name
433
+	 * @param bool   $nullable
434
+	 * @param null   $default_value
435
+	 * @return EE_Post_Content_Field
436
+	 */
437
+	public function createPostContentField($table_column, $nice_name, $nullable, $default_value = null)
438
+	{
439
+		return $this->loader->getNew(
440
+			'EE_Post_Content_Field',
441
+			array($table_column, $nice_name, $nullable, $default_value)
442
+		);
443
+	}
444
+
445
+
446
+	/**
447
+	 * @param string $table_column
448
+	 * @param string $nice_name
449
+	 * @return EE_Primary_Key_Int_Field
450
+	 */
451
+	public function createPrimaryKeyIntField($table_column, $nice_name)
452
+	{
453
+		return $this->loader->getNew('EE_Primary_Key_Int_Field', array($table_column, $nice_name));
454
+	}
455
+
456
+
457
+	/**
458
+	 * @param string $table_column
459
+	 * @param string $nice_name
460
+	 * @return EE_Primary_Key_String_Field
461
+	 */
462
+	public function createPrimaryKeyStringField($table_column, $nice_name)
463
+	{
464
+		return $this->loader->getNew('EE_Primary_Key_String_Field', array($table_column, $nice_name));
465
+	}
466
+
467
+
468
+	/**
469
+	 * @param string $table_column
470
+	 * @param string $nice_name
471
+	 * @param bool   $nullable
472
+	 * @param null   $default_value
473
+	 * @return EE_Serialized_Text_Field
474
+	 */
475
+	public function createSerializedTextField($table_column, $nice_name, $nullable, $default_value = null)
476
+	{
477
+		return $this->loader->getNew(
478
+			'EE_Serialized_Text_Field',
479
+			array($table_column, $nice_name, $nullable, $default_value)
480
+		);
481
+	}
482
+
483
+
484
+	/**
485
+	 * @param string $table_column
486
+	 * @param string $nice_name
487
+	 * @param bool   $nullable
488
+	 * @param null   $default_value
489
+	 * @return EE_Simple_HTML_Field
490
+	 */
491
+	public function createSimpleHtmlField($table_column, $nice_name, $nullable, $default_value = null)
492
+	{
493
+		return $this->loader->getNew(
494
+			'EE_Simple_HTML_Field',
495
+			array($table_column, $nice_name, $nullable, $default_value)
496
+		);
497
+	}
498
+
499
+
500
+	/**
501
+	 * @param string $table_column
502
+	 * @param string $nice_name
503
+	 * @param bool   $nullable
504
+	 * @param null   $default_value
505
+	 * @return EE_Slug_Field
506
+	 */
507
+	public function createSlugField($table_column, $nice_name, $nullable = false, $default_value = null)
508
+	{
509
+		return $this->loader->getNew(
510
+			'EE_Slug_Field',
511
+			array($table_column, $nice_name, $nullable, $default_value)
512
+		);
513
+	}
514
+
515
+
516
+	/**
517
+	 * @param string $table_column
518
+	 * @param string $nice_name
519
+	 * @param bool   $nullable
520
+	 * @param null   $default_value
521
+	 * @return EE_Trashed_Flag_Field
522
+	 */
523
+	public function createTrashedFlagField($table_column, $nice_name, $nullable, $default_value = null)
524
+	{
525
+		return $this->loader->getNew(
526
+			'EE_Trashed_Flag_Field',
527
+			array($table_column, $nice_name, $nullable, $default_value)
528
+		);
529
+	}
530
+
531
+
532
+	/**
533
+	 * @param string $table_column
534
+	 * @param string $nice_name
535
+	 * @param bool   $nullable
536
+	 * @param mixed  $default_value
537
+	 * @param array  $values                            If additional stati are to be used other than the default WP
538
+	 *                                                  statuses, then they can be registered via this property. The
539
+	 *                                                  format of the array should be as follows: array(
540
+	 *                                                  'status_reference' => array(
541
+	 *                                                  'label' => __('Status Reference Label', 'event_espresso'),
542
+	 *                                                  'public' => true,                 // whether this status should
543
+	 *                                                  be shown on the frontend of the site
544
+	 *                                                  'exclude_from_search' => false,   // whether this status should
545
+	 *                                                  be excluded from wp searches
546
+	 *                                                  'show_in_admin_all_list' => true, // whether this status is
547
+	 *                                                  included in queries for the admin "all" view in list table
548
+	 *                                                  views.
549
+	 *                                                  'show_in_admin_status_list' => true, // show in the list of
550
+	 *                                                  statuses with post counts at the top of the admin list tables
551
+	 *                                                  (i.e. Status Reference(2) )
552
+	 *                                                  'label_count' => _n_noop(
553
+	 *                                                  'Status Reference <span class="count">(%s)</span>',
554
+	 *                                                  'Status References <span class="count">(%s)</span>'
555
+	 *                                                  ),                                   // the text to display on
556
+	 *                                                  the admin screen
557
+	 *                                                  ( or you won't see your status count ).
558
+	 *                                                  )
559
+	 *                                                  )
560
+	 * @link http://codex.wordpress.org/Function_Reference/register_post_status for more info
561
+	 * @return EE_WP_Post_Status_Field
562
+	 */
563
+	public function createWpPostStatusField(
564
+		$table_column,
565
+		$nice_name,
566
+		$nullable,
567
+		$default_value = null,
568
+		array $values = array()
569
+	) {
570
+		return $this->loader->getNew(
571
+			'EE_WP_Post_Status_Field',
572
+			array($table_column, $nice_name, $nullable, $default_value, $values)
573
+		);
574
+	}
575
+
576
+
577
+	/**
578
+	 * @param string $post_type
579
+	 * @return EE_WP_Post_Type_Field
580
+	 */
581
+	public function createWpPostTypeField($post_type)
582
+	{
583
+		return $this->loader->getNew('EE_WP_Post_Type_Field', array($post_type));
584
+	}
585
+
586
+
587
+	/**
588
+	 * @param string $table_column
589
+	 * @param string $nice_name
590
+	 * @param bool   $nullable
591
+	 * @return EE_WP_User_Field
592
+	 */
593
+	public function createWpUserField($table_column, $nice_name, $nullable)
594
+	{
595
+		return $this->loader->getNew('EE_WP_User_Field', array($table_column, $nice_name, $nullable));
596
+	}
597 597
 }
Please login to merge, or discard this patch.
core/EE_Request_Handler.core.php 3 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -275,7 +275,7 @@  discard block
 block discarded – undo
275 275
 
276 276
 
277 277
     /**
278
-     * @param $string
278
+     * @param string $string
279 279
      * @return void
280 280
      */
281 281
     public function add_output($string)
@@ -327,7 +327,7 @@  discard block
 block discarded – undo
327 327
 
328 328
 
329 329
     /**
330
-     * @return    mixed
330
+     * @return    boolean
331 331
      */
332 332
     public function is_espresso_page()
333 333
     {
@@ -389,7 +389,7 @@  discard block
 block discarded – undo
389 389
     /**
390 390
      * remove param
391 391
      *
392
-     * @param $key
392
+     * @param string $key
393 393
      * @return    void
394 394
      */
395 395
     public function un_set($key)
Please login to merge, or discard this patch.
Indentation   +365 added lines, -365 removed lines patch added patch discarded remove patch
@@ -12,369 +12,369 @@
 block discarded – undo
12 12
 final class EE_Request_Handler implements InterminableInterface
13 13
 {
14 14
 
15
-    /**
16
-     * @var EE_Request $request
17
-     */
18
-    private $request;
19
-
20
-    /**
21
-     * @var array $_notice
22
-     */
23
-    private $_notice = array();
24
-
25
-    /**
26
-     * rendered output to be returned to WP
27
-     *
28
-     * @var string $_output
29
-     */
30
-    private $_output = '';
31
-
32
-    /**
33
-     * whether current request is via AJAX
34
-     *
35
-     * @var boolean $ajax
36
-     */
37
-    public $ajax = false;
38
-
39
-    /**
40
-     * whether current request is via AJAX from the frontend of the site
41
-     *
42
-     * @var boolean $front_ajax
43
-     */
44
-    public $front_ajax = false;
45
-
46
-
47
-    /**
48
-     * @param  EE_Request $request
49
-     */
50
-    public function __construct(EE_Request $request)
51
-    {
52
-        $this->request = $request;
53
-        $this->ajax = $this->request->ajax;
54
-        $this->front_ajax = $this->request->front_ajax;
55
-        do_action('AHEE__EE_Request_Handler__construct__complete');
56
-    }
57
-
58
-
59
-    /**
60
-     * @param WP $wp
61
-     * @return void
62
-     * @throws EE_Error
63
-     * @throws ReflectionException
64
-     */
65
-    public function parse_request($wp = null)
66
-    {
67
-        // if somebody forgot to provide us with WP, that's ok because its global
68
-        if (! $wp instanceof WP) {
69
-            global $wp;
70
-        }
71
-        $this->set_request_vars($wp);
72
-    }
73
-
74
-
75
-    /**
76
-     * @param WP $wp
77
-     * @return void
78
-     * @throws EE_Error
79
-     * @throws ReflectionException
80
-     */
81
-    public function set_request_vars($wp = null)
82
-    {
83
-        if (! is_admin()) {
84
-            // set request post_id
85
-            $this->request->set('post_id', $this->get_post_id_from_request($wp));
86
-            // set request post name
87
-            $this->request->set('post_name', $this->get_post_name_from_request($wp));
88
-            // set request post_type
89
-            $this->request->set('post_type', $this->get_post_type_from_request($wp));
90
-            // true or false ? is this page being used by EE ?
91
-            $this->set_espresso_page();
92
-        }
93
-    }
94
-
95
-
96
-    /**
97
-     * @param WP $wp
98
-     * @return int
99
-     */
100
-    public function get_post_id_from_request($wp = null)
101
-    {
102
-        if (! $wp instanceof WP) {
103
-            global $wp;
104
-        }
105
-        $post_id = null;
106
-        if (isset($wp->query_vars['p'])) {
107
-            $post_id = $wp->query_vars['p'];
108
-        }
109
-        if (! $post_id && isset($wp->query_vars['page_id'])) {
110
-            $post_id = $wp->query_vars['page_id'];
111
-        }
112
-        if (! $post_id && $wp->request !== null && is_numeric(basename($wp->request))) {
113
-            $post_id = basename($wp->request);
114
-        }
115
-        return $post_id;
116
-    }
117
-
118
-
119
-    /**
120
-     * @param WP $wp
121
-     * @return string
122
-     */
123
-    public function get_post_name_from_request($wp = null)
124
-    {
125
-        if (! $wp instanceof WP) {
126
-            global $wp;
127
-        }
128
-        $post_name = null;
129
-        if (isset($wp->query_vars['name']) && ! empty($wp->query_vars['name'])) {
130
-            $post_name = $wp->query_vars['name'];
131
-        }
132
-        if (! $post_name && isset($wp->query_vars['pagename']) && ! empty($wp->query_vars['pagename'])) {
133
-            $post_name = $wp->query_vars['pagename'];
134
-        }
135
-        if (! $post_name && $wp->request !== null && ! empty($wp->request)) {
136
-            $possible_post_name = basename($wp->request);
137
-            if (! is_numeric($possible_post_name)) {
138
-                /** @type WPDB $wpdb */
139
-                global $wpdb;
140
-                $SQL =
141
-                    "SELECT ID from {$wpdb->posts} WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash') AND post_name=%s";
142
-                $possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $possible_post_name));
143
-                if ($possible_post_name) {
144
-                    $post_name = $possible_post_name;
145
-                }
146
-            }
147
-        }
148
-        if (! $post_name && $this->get('post_id')) {
149
-            /** @type WPDB $wpdb */
150
-            global $wpdb;
151
-            $SQL =
152
-                "SELECT post_name from {$wpdb->posts} WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash') AND ID=%d";
153
-            $possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $this->get('post_id')));
154
-            if ($possible_post_name) {
155
-                $post_name = $possible_post_name;
156
-            }
157
-        }
158
-        return $post_name;
159
-    }
160
-
161
-
162
-    /**
163
-     * @param WP $wp
164
-     * @return mixed
165
-     */
166
-    public function get_post_type_from_request($wp = null)
167
-    {
168
-        if (! $wp instanceof WP) {
169
-            global $wp;
170
-        }
171
-        return isset($wp->query_vars['post_type'])
172
-            ? $wp->query_vars['post_type']
173
-            : null;
174
-    }
175
-
176
-
177
-    /**
178
-     * Just a helper method for getting the url for the displayed page.
179
-     *
180
-     * @param  WP $wp
181
-     * @return string
182
-     */
183
-    public function get_current_page_permalink($wp = null)
184
-    {
185
-        $post_id = $this->get_post_id_from_request($wp);
186
-        if ($post_id) {
187
-            $current_page_permalink = get_permalink($post_id);
188
-        } else {
189
-            if (! $wp instanceof WP) {
190
-                global $wp;
191
-            }
192
-            if ($wp->request) {
193
-                $current_page_permalink = site_url($wp->request);
194
-            } else {
195
-                $current_page_permalink = esc_url(site_url($_SERVER['REQUEST_URI']));
196
-            }
197
-        }
198
-        return $current_page_permalink;
199
-    }
200
-
201
-
202
-    /**
203
-     * @return bool
204
-     * @throws EE_Error
205
-     * @throws ReflectionException
206
-     */
207
-    public function test_for_espresso_page()
208
-    {
209
-        global $wp;
210
-        /** @type EE_CPT_Strategy $EE_CPT_Strategy */
211
-        $EE_CPT_Strategy = EE_Registry::instance()->load_core('CPT_Strategy');
212
-        $espresso_CPT_taxonomies = $EE_CPT_Strategy->get_CPT_taxonomies();
213
-        if (is_array($espresso_CPT_taxonomies)) {
214
-            foreach ($espresso_CPT_taxonomies as $espresso_CPT_taxonomy => $details) {
215
-                if (isset($wp->query_vars, $wp->query_vars[ $espresso_CPT_taxonomy ])) {
216
-                    return true;
217
-                }
218
-            }
219
-        }
220
-        // load espresso CPT endpoints
221
-        $espresso_CPT_endpoints = $EE_CPT_Strategy->get_CPT_endpoints();
222
-        $post_type_CPT_endpoints = array_flip($espresso_CPT_endpoints);
223
-        $post_types = (array) $this->get('post_type');
224
-        foreach ($post_types as $post_type) {
225
-            // was a post name passed ?
226
-            if (isset($post_type_CPT_endpoints[ $post_type ])) {
227
-                // kk we know this is an espresso page, but is it a specific post ?
228
-                if (! $this->get('post_name')) {
229
-                    // there's no specific post name set, so maybe it's one of our endpoints like www.domain.com/events
230
-                    $post_name = isset($post_type_CPT_endpoints[ $this->get('post_type') ])
231
-                        ? $post_type_CPT_endpoints[ $this->get('post_type') ]
232
-                        : '';
233
-                    // if the post type matches on of our then set the endpoint
234
-                    if ($post_name) {
235
-                        $this->set('post_name', $post_name);
236
-                    }
237
-                }
238
-                return true;
239
-            }
240
-        }
241
-        return false;
242
-    }
243
-
244
-    /**
245
-     * @param $key
246
-     * @param $value
247
-     * @return    void
248
-     */
249
-    public function set_notice($key, $value)
250
-    {
251
-        $this->_notice[ $key ] = $value;
252
-    }
253
-
254
-
255
-    /**
256
-     * @param $key
257
-     * @return    mixed
258
-     */
259
-    public function get_notice($key)
260
-    {
261
-        return isset($this->_notice[ $key ])
262
-            ? $this->_notice[ $key ]
263
-            : null;
264
-    }
265
-
266
-
267
-    /**
268
-     * @param $string
269
-     * @return void
270
-     */
271
-    public function add_output($string)
272
-    {
273
-        $this->_output .= $string;
274
-    }
275
-
276
-
277
-    /**
278
-     * @return string
279
-     */
280
-    public function get_output()
281
-    {
282
-        return $this->_output;
283
-    }
284
-
285
-
286
-    /**
287
-     * @param $item
288
-     * @param $key
289
-     */
290
-    public function sanitize_text_field_for_array_walk(&$item, &$key)
291
-    {
292
-        $item = strpos($item, 'email') !== false
293
-            ? sanitize_email($item)
294
-            : sanitize_text_field($item);
295
-    }
296
-
297
-
298
-    /**
299
-     * @param null|bool $value
300
-     * @return void
301
-     * @throws EE_Error
302
-     * @throws ReflectionException
303
-     */
304
-    public function set_espresso_page($value = null)
305
-    {
306
-        $this->request->set(
307
-            'is_espresso_page',
308
-            ! empty($value)
309
-                ? $value
310
-                : $this->test_for_espresso_page()
311
-        );
312
-    }
313
-
314
-
315
-    /**
316
-     * @return    mixed
317
-     */
318
-    public function is_espresso_page()
319
-    {
320
-        return $this->request->is_set('is_espresso_page');
321
-    }
322
-
323
-
324
-    /**
325
-     * returns contents of $_REQUEST
326
-     *
327
-     * @return array
328
-     */
329
-    public function params()
330
-    {
331
-        return $this->request->params();
332
-    }
333
-
334
-
335
-    /**
336
-     * @param      $key
337
-     * @param      $value
338
-     * @param bool $override_ee
339
-     * @return    void
340
-     */
341
-    public function set($key, $value, $override_ee = false)
342
-    {
343
-        $this->request->set($key, $value, $override_ee);
344
-    }
345
-
346
-
347
-    /**
348
-     * @param      $key
349
-     * @param null $default
350
-     * @return    mixed
351
-     */
352
-    public function get($key, $default = null)
353
-    {
354
-        return $this->request->get($key, $default);
355
-    }
356
-
357
-
358
-    /**
359
-     * check if param exists
360
-     *
361
-     * @param $key
362
-     * @return    boolean
363
-     */
364
-    public function is_set($key)
365
-    {
366
-        return $this->request->is_set($key);
367
-    }
368
-
369
-
370
-    /**
371
-     * remove param
372
-     *
373
-     * @param $key
374
-     * @return    void
375
-     */
376
-    public function un_set($key)
377
-    {
378
-        $this->request->un_set($key);
379
-    }
15
+	/**
16
+	 * @var EE_Request $request
17
+	 */
18
+	private $request;
19
+
20
+	/**
21
+	 * @var array $_notice
22
+	 */
23
+	private $_notice = array();
24
+
25
+	/**
26
+	 * rendered output to be returned to WP
27
+	 *
28
+	 * @var string $_output
29
+	 */
30
+	private $_output = '';
31
+
32
+	/**
33
+	 * whether current request is via AJAX
34
+	 *
35
+	 * @var boolean $ajax
36
+	 */
37
+	public $ajax = false;
38
+
39
+	/**
40
+	 * whether current request is via AJAX from the frontend of the site
41
+	 *
42
+	 * @var boolean $front_ajax
43
+	 */
44
+	public $front_ajax = false;
45
+
46
+
47
+	/**
48
+	 * @param  EE_Request $request
49
+	 */
50
+	public function __construct(EE_Request $request)
51
+	{
52
+		$this->request = $request;
53
+		$this->ajax = $this->request->ajax;
54
+		$this->front_ajax = $this->request->front_ajax;
55
+		do_action('AHEE__EE_Request_Handler__construct__complete');
56
+	}
57
+
58
+
59
+	/**
60
+	 * @param WP $wp
61
+	 * @return void
62
+	 * @throws EE_Error
63
+	 * @throws ReflectionException
64
+	 */
65
+	public function parse_request($wp = null)
66
+	{
67
+		// if somebody forgot to provide us with WP, that's ok because its global
68
+		if (! $wp instanceof WP) {
69
+			global $wp;
70
+		}
71
+		$this->set_request_vars($wp);
72
+	}
73
+
74
+
75
+	/**
76
+	 * @param WP $wp
77
+	 * @return void
78
+	 * @throws EE_Error
79
+	 * @throws ReflectionException
80
+	 */
81
+	public function set_request_vars($wp = null)
82
+	{
83
+		if (! is_admin()) {
84
+			// set request post_id
85
+			$this->request->set('post_id', $this->get_post_id_from_request($wp));
86
+			// set request post name
87
+			$this->request->set('post_name', $this->get_post_name_from_request($wp));
88
+			// set request post_type
89
+			$this->request->set('post_type', $this->get_post_type_from_request($wp));
90
+			// true or false ? is this page being used by EE ?
91
+			$this->set_espresso_page();
92
+		}
93
+	}
94
+
95
+
96
+	/**
97
+	 * @param WP $wp
98
+	 * @return int
99
+	 */
100
+	public function get_post_id_from_request($wp = null)
101
+	{
102
+		if (! $wp instanceof WP) {
103
+			global $wp;
104
+		}
105
+		$post_id = null;
106
+		if (isset($wp->query_vars['p'])) {
107
+			$post_id = $wp->query_vars['p'];
108
+		}
109
+		if (! $post_id && isset($wp->query_vars['page_id'])) {
110
+			$post_id = $wp->query_vars['page_id'];
111
+		}
112
+		if (! $post_id && $wp->request !== null && is_numeric(basename($wp->request))) {
113
+			$post_id = basename($wp->request);
114
+		}
115
+		return $post_id;
116
+	}
117
+
118
+
119
+	/**
120
+	 * @param WP $wp
121
+	 * @return string
122
+	 */
123
+	public function get_post_name_from_request($wp = null)
124
+	{
125
+		if (! $wp instanceof WP) {
126
+			global $wp;
127
+		}
128
+		$post_name = null;
129
+		if (isset($wp->query_vars['name']) && ! empty($wp->query_vars['name'])) {
130
+			$post_name = $wp->query_vars['name'];
131
+		}
132
+		if (! $post_name && isset($wp->query_vars['pagename']) && ! empty($wp->query_vars['pagename'])) {
133
+			$post_name = $wp->query_vars['pagename'];
134
+		}
135
+		if (! $post_name && $wp->request !== null && ! empty($wp->request)) {
136
+			$possible_post_name = basename($wp->request);
137
+			if (! is_numeric($possible_post_name)) {
138
+				/** @type WPDB $wpdb */
139
+				global $wpdb;
140
+				$SQL =
141
+					"SELECT ID from {$wpdb->posts} WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash') AND post_name=%s";
142
+				$possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $possible_post_name));
143
+				if ($possible_post_name) {
144
+					$post_name = $possible_post_name;
145
+				}
146
+			}
147
+		}
148
+		if (! $post_name && $this->get('post_id')) {
149
+			/** @type WPDB $wpdb */
150
+			global $wpdb;
151
+			$SQL =
152
+				"SELECT post_name from {$wpdb->posts} WHERE post_status NOT IN ('auto-draft', 'inherit', 'trash') AND ID=%d";
153
+			$possible_post_name = $wpdb->get_var($wpdb->prepare($SQL, $this->get('post_id')));
154
+			if ($possible_post_name) {
155
+				$post_name = $possible_post_name;
156
+			}
157
+		}
158
+		return $post_name;
159
+	}
160
+
161
+
162
+	/**
163
+	 * @param WP $wp
164
+	 * @return mixed
165
+	 */
166
+	public function get_post_type_from_request($wp = null)
167
+	{
168
+		if (! $wp instanceof WP) {
169
+			global $wp;
170
+		}
171
+		return isset($wp->query_vars['post_type'])
172
+			? $wp->query_vars['post_type']
173
+			: null;
174
+	}
175
+
176
+
177
+	/**
178
+	 * Just a helper method for getting the url for the displayed page.
179
+	 *
180
+	 * @param  WP $wp
181
+	 * @return string
182
+	 */
183
+	public function get_current_page_permalink($wp = null)
184
+	{
185
+		$post_id = $this->get_post_id_from_request($wp);
186
+		if ($post_id) {
187
+			$current_page_permalink = get_permalink($post_id);
188
+		} else {
189
+			if (! $wp instanceof WP) {
190
+				global $wp;
191
+			}
192
+			if ($wp->request) {
193
+				$current_page_permalink = site_url($wp->request);
194
+			} else {
195
+				$current_page_permalink = esc_url(site_url($_SERVER['REQUEST_URI']));
196
+			}
197
+		}
198
+		return $current_page_permalink;
199
+	}
200
+
201
+
202
+	/**
203
+	 * @return bool
204
+	 * @throws EE_Error
205
+	 * @throws ReflectionException
206
+	 */
207
+	public function test_for_espresso_page()
208
+	{
209
+		global $wp;
210
+		/** @type EE_CPT_Strategy $EE_CPT_Strategy */
211
+		$EE_CPT_Strategy = EE_Registry::instance()->load_core('CPT_Strategy');
212
+		$espresso_CPT_taxonomies = $EE_CPT_Strategy->get_CPT_taxonomies();
213
+		if (is_array($espresso_CPT_taxonomies)) {
214
+			foreach ($espresso_CPT_taxonomies as $espresso_CPT_taxonomy => $details) {
215
+				if (isset($wp->query_vars, $wp->query_vars[ $espresso_CPT_taxonomy ])) {
216
+					return true;
217
+				}
218
+			}
219
+		}
220
+		// load espresso CPT endpoints
221
+		$espresso_CPT_endpoints = $EE_CPT_Strategy->get_CPT_endpoints();
222
+		$post_type_CPT_endpoints = array_flip($espresso_CPT_endpoints);
223
+		$post_types = (array) $this->get('post_type');
224
+		foreach ($post_types as $post_type) {
225
+			// was a post name passed ?
226
+			if (isset($post_type_CPT_endpoints[ $post_type ])) {
227
+				// kk we know this is an espresso page, but is it a specific post ?
228
+				if (! $this->get('post_name')) {
229
+					// there's no specific post name set, so maybe it's one of our endpoints like www.domain.com/events
230
+					$post_name = isset($post_type_CPT_endpoints[ $this->get('post_type') ])
231
+						? $post_type_CPT_endpoints[ $this->get('post_type') ]
232
+						: '';
233
+					// if the post type matches on of our then set the endpoint
234
+					if ($post_name) {
235
+						$this->set('post_name', $post_name);
236
+					}
237
+				}
238
+				return true;
239
+			}
240
+		}
241
+		return false;
242
+	}
243
+
244
+	/**
245
+	 * @param $key
246
+	 * @param $value
247
+	 * @return    void
248
+	 */
249
+	public function set_notice($key, $value)
250
+	{
251
+		$this->_notice[ $key ] = $value;
252
+	}
253
+
254
+
255
+	/**
256
+	 * @param $key
257
+	 * @return    mixed
258
+	 */
259
+	public function get_notice($key)
260
+	{
261
+		return isset($this->_notice[ $key ])
262
+			? $this->_notice[ $key ]
263
+			: null;
264
+	}
265
+
266
+
267
+	/**
268
+	 * @param $string
269
+	 * @return void
270
+	 */
271
+	public function add_output($string)
272
+	{
273
+		$this->_output .= $string;
274
+	}
275
+
276
+
277
+	/**
278
+	 * @return string
279
+	 */
280
+	public function get_output()
281
+	{
282
+		return $this->_output;
283
+	}
284
+
285
+
286
+	/**
287
+	 * @param $item
288
+	 * @param $key
289
+	 */
290
+	public function sanitize_text_field_for_array_walk(&$item, &$key)
291
+	{
292
+		$item = strpos($item, 'email') !== false
293
+			? sanitize_email($item)
294
+			: sanitize_text_field($item);
295
+	}
296
+
297
+
298
+	/**
299
+	 * @param null|bool $value
300
+	 * @return void
301
+	 * @throws EE_Error
302
+	 * @throws ReflectionException
303
+	 */
304
+	public function set_espresso_page($value = null)
305
+	{
306
+		$this->request->set(
307
+			'is_espresso_page',
308
+			! empty($value)
309
+				? $value
310
+				: $this->test_for_espresso_page()
311
+		);
312
+	}
313
+
314
+
315
+	/**
316
+	 * @return    mixed
317
+	 */
318
+	public function is_espresso_page()
319
+	{
320
+		return $this->request->is_set('is_espresso_page');
321
+	}
322
+
323
+
324
+	/**
325
+	 * returns contents of $_REQUEST
326
+	 *
327
+	 * @return array
328
+	 */
329
+	public function params()
330
+	{
331
+		return $this->request->params();
332
+	}
333
+
334
+
335
+	/**
336
+	 * @param      $key
337
+	 * @param      $value
338
+	 * @param bool $override_ee
339
+	 * @return    void
340
+	 */
341
+	public function set($key, $value, $override_ee = false)
342
+	{
343
+		$this->request->set($key, $value, $override_ee);
344
+	}
345
+
346
+
347
+	/**
348
+	 * @param      $key
349
+	 * @param null $default
350
+	 * @return    mixed
351
+	 */
352
+	public function get($key, $default = null)
353
+	{
354
+		return $this->request->get($key, $default);
355
+	}
356
+
357
+
358
+	/**
359
+	 * check if param exists
360
+	 *
361
+	 * @param $key
362
+	 * @return    boolean
363
+	 */
364
+	public function is_set($key)
365
+	{
366
+		return $this->request->is_set($key);
367
+	}
368
+
369
+
370
+	/**
371
+	 * remove param
372
+	 *
373
+	 * @param $key
374
+	 * @return    void
375
+	 */
376
+	public function un_set($key)
377
+	{
378
+		$this->request->un_set($key);
379
+	}
380 380
 }
Please login to merge, or discard this patch.
Spacing   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -65,7 +65,7 @@  discard block
 block discarded – undo
65 65
     public function parse_request($wp = null)
66 66
     {
67 67
         // if somebody forgot to provide us with WP, that's ok because its global
68
-        if (! $wp instanceof WP) {
68
+        if ( ! $wp instanceof WP) {
69 69
             global $wp;
70 70
         }
71 71
         $this->set_request_vars($wp);
@@ -80,7 +80,7 @@  discard block
 block discarded – undo
80 80
      */
81 81
     public function set_request_vars($wp = null)
82 82
     {
83
-        if (! is_admin()) {
83
+        if ( ! is_admin()) {
84 84
             // set request post_id
85 85
             $this->request->set('post_id', $this->get_post_id_from_request($wp));
86 86
             // set request post name
@@ -99,17 +99,17 @@  discard block
 block discarded – undo
99 99
      */
100 100
     public function get_post_id_from_request($wp = null)
101 101
     {
102
-        if (! $wp instanceof WP) {
102
+        if ( ! $wp instanceof WP) {
103 103
             global $wp;
104 104
         }
105 105
         $post_id = null;
106 106
         if (isset($wp->query_vars['p'])) {
107 107
             $post_id = $wp->query_vars['p'];
108 108
         }
109
-        if (! $post_id && isset($wp->query_vars['page_id'])) {
109
+        if ( ! $post_id && isset($wp->query_vars['page_id'])) {
110 110
             $post_id = $wp->query_vars['page_id'];
111 111
         }
112
-        if (! $post_id && $wp->request !== null && is_numeric(basename($wp->request))) {
112
+        if ( ! $post_id && $wp->request !== null && is_numeric(basename($wp->request))) {
113 113
             $post_id = basename($wp->request);
114 114
         }
115 115
         return $post_id;
@@ -122,19 +122,19 @@  discard block
 block discarded – undo
122 122
      */
123 123
     public function get_post_name_from_request($wp = null)
124 124
     {
125
-        if (! $wp instanceof WP) {
125
+        if ( ! $wp instanceof WP) {
126 126
             global $wp;
127 127
         }
128 128
         $post_name = null;
129 129
         if (isset($wp->query_vars['name']) && ! empty($wp->query_vars['name'])) {
130 130
             $post_name = $wp->query_vars['name'];
131 131
         }
132
-        if (! $post_name && isset($wp->query_vars['pagename']) && ! empty($wp->query_vars['pagename'])) {
132
+        if ( ! $post_name && isset($wp->query_vars['pagename']) && ! empty($wp->query_vars['pagename'])) {
133 133
             $post_name = $wp->query_vars['pagename'];
134 134
         }
135
-        if (! $post_name && $wp->request !== null && ! empty($wp->request)) {
135
+        if ( ! $post_name && $wp->request !== null && ! empty($wp->request)) {
136 136
             $possible_post_name = basename($wp->request);
137
-            if (! is_numeric($possible_post_name)) {
137
+            if ( ! is_numeric($possible_post_name)) {
138 138
                 /** @type WPDB $wpdb */
139 139
                 global $wpdb;
140 140
                 $SQL =
@@ -145,7 +145,7 @@  discard block
 block discarded – undo
145 145
                 }
146 146
             }
147 147
         }
148
-        if (! $post_name && $this->get('post_id')) {
148
+        if ( ! $post_name && $this->get('post_id')) {
149 149
             /** @type WPDB $wpdb */
150 150
             global $wpdb;
151 151
             $SQL =
@@ -165,7 +165,7 @@  discard block
 block discarded – undo
165 165
      */
166 166
     public function get_post_type_from_request($wp = null)
167 167
     {
168
-        if (! $wp instanceof WP) {
168
+        if ( ! $wp instanceof WP) {
169 169
             global $wp;
170 170
         }
171 171
         return isset($wp->query_vars['post_type'])
@@ -186,7 +186,7 @@  discard block
 block discarded – undo
186 186
         if ($post_id) {
187 187
             $current_page_permalink = get_permalink($post_id);
188 188
         } else {
189
-            if (! $wp instanceof WP) {
189
+            if ( ! $wp instanceof WP) {
190 190
                 global $wp;
191 191
             }
192 192
             if ($wp->request) {
@@ -212,7 +212,7 @@  discard block
 block discarded – undo
212 212
         $espresso_CPT_taxonomies = $EE_CPT_Strategy->get_CPT_taxonomies();
213 213
         if (is_array($espresso_CPT_taxonomies)) {
214 214
             foreach ($espresso_CPT_taxonomies as $espresso_CPT_taxonomy => $details) {
215
-                if (isset($wp->query_vars, $wp->query_vars[ $espresso_CPT_taxonomy ])) {
215
+                if (isset($wp->query_vars, $wp->query_vars[$espresso_CPT_taxonomy])) {
216 216
                     return true;
217 217
                 }
218 218
             }
@@ -223,12 +223,12 @@  discard block
 block discarded – undo
223 223
         $post_types = (array) $this->get('post_type');
224 224
         foreach ($post_types as $post_type) {
225 225
             // was a post name passed ?
226
-            if (isset($post_type_CPT_endpoints[ $post_type ])) {
226
+            if (isset($post_type_CPT_endpoints[$post_type])) {
227 227
                 // kk we know this is an espresso page, but is it a specific post ?
228
-                if (! $this->get('post_name')) {
228
+                if ( ! $this->get('post_name')) {
229 229
                     // there's no specific post name set, so maybe it's one of our endpoints like www.domain.com/events
230
-                    $post_name = isset($post_type_CPT_endpoints[ $this->get('post_type') ])
231
-                        ? $post_type_CPT_endpoints[ $this->get('post_type') ]
230
+                    $post_name = isset($post_type_CPT_endpoints[$this->get('post_type')])
231
+                        ? $post_type_CPT_endpoints[$this->get('post_type')]
232 232
                         : '';
233 233
                     // if the post type matches on of our then set the endpoint
234 234
                     if ($post_name) {
@@ -248,7 +248,7 @@  discard block
 block discarded – undo
248 248
      */
249 249
     public function set_notice($key, $value)
250 250
     {
251
-        $this->_notice[ $key ] = $value;
251
+        $this->_notice[$key] = $value;
252 252
     }
253 253
 
254 254
 
@@ -258,8 +258,8 @@  discard block
 block discarded – undo
258 258
      */
259 259
     public function get_notice($key)
260 260
     {
261
-        return isset($this->_notice[ $key ])
262
-            ? $this->_notice[ $key ]
261
+        return isset($this->_notice[$key])
262
+            ? $this->_notice[$key]
263 263
             : null;
264 264
     }
265 265
 
Please login to merge, or discard this patch.
reg_steps/payment_options/EE_SPCO_Reg_Step_Payment_Options.class.php 3 patches
Doc Comments   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -145,7 +145,7 @@  discard block
 block discarded – undo
145 145
 
146 146
 
147 147
     /**
148
-     * @return null
148
+     * @return EE_Line_Item_Display
149 149
      */
150 150
     public function line_item_display()
151 151
     {
@@ -154,7 +154,7 @@  discard block
 block discarded – undo
154 154
 
155 155
 
156 156
     /**
157
-     * @param null $line_item_display
157
+     * @param EE_Line_Item_Display $line_item_display
158 158
      */
159 159
     public function set_line_item_display($line_item_display)
160 160
     {
@@ -882,7 +882,7 @@  discard block
 block discarded – undo
882 882
      *    _apply_registration_payments_to_amount_owing
883 883
      *
884 884
      * @access protected
885
-     * @param array $registrations
885
+     * @param EE_Base_Class[] $registrations
886 886
      * @throws EE_Error
887 887
      */
888 888
     protected function _apply_registration_payments_to_amount_owing(array $registrations)
@@ -1188,7 +1188,7 @@  discard block
 block discarded – undo
1188 1188
      * get_billing_form_html_for_payment_method
1189 1189
      *
1190 1190
      * @access public
1191
-     * @return string
1191
+     * @return boolean
1192 1192
      * @throws EE_Error
1193 1193
      * @throws InvalidArgumentException
1194 1194
      * @throws ReflectionException
@@ -1255,7 +1255,7 @@  discard block
 block discarded – undo
1255 1255
      *
1256 1256
      * @access private
1257 1257
      * @param EE_Payment_Method $payment_method
1258
-     * @return EE_Billing_Info_Form|EE_Form_Section_HTML
1258
+     * @return EE_Billing_Info_Form
1259 1259
      * @throws EE_Error
1260 1260
      * @throws InvalidArgumentException
1261 1261
      * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
@@ -1364,7 +1364,7 @@  discard block
 block discarded – undo
1364 1364
      * switch_payment_method
1365 1365
      *
1366 1366
      * @access public
1367
-     * @return string
1367
+     * @return boolean
1368 1368
      * @throws EE_Error
1369 1369
      * @throws InvalidArgumentException
1370 1370
      * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
@@ -1643,7 +1643,7 @@  discard block
 block discarded – undo
1643 1643
     /**
1644 1644
      * process_reg_step
1645 1645
      *
1646
-     * @return bool
1646
+     * @return null|boolean
1647 1647
      * @throws EE_Error
1648 1648
      * @throws InvalidArgumentException
1649 1649
      * @throws ReflectionException
@@ -1774,7 +1774,7 @@  discard block
 block discarded – undo
1774 1774
      *    update_reg_step
1775 1775
      *    this is the final step after a user  revisits the site to retry a payment
1776 1776
      *
1777
-     * @return bool
1777
+     * @return null|boolean
1778 1778
      * @throws EE_Error
1779 1779
      * @throws InvalidArgumentException
1780 1780
      * @throws ReflectionException
@@ -2221,7 +2221,7 @@  discard block
 block discarded – undo
2221 2221
      *
2222 2222
      * @access    private
2223 2223
      * @type    EE_Payment_Method $payment_method
2224
-     * @return mixed EE_Payment | boolean
2224
+     * @return EE_Payment|null EE_Payment | boolean
2225 2225
      * @throws EE_Error
2226 2226
      * @throws InvalidArgumentException
2227 2227
      * @throws ReflectionException
@@ -2546,7 +2546,7 @@  discard block
 block discarded – undo
2546 2546
      *        or present the payment options again
2547 2547
      *
2548 2548
      * @access private
2549
-     * @return EE_Payment|FALSE
2549
+     * @return boolean
2550 2550
      * @throws EE_Error
2551 2551
      * @throws InvalidArgumentException
2552 2552
      * @throws ReflectionException
@@ -2686,8 +2686,8 @@  discard block
 block discarded – undo
2686 2686
      * _redirect_wayward_request
2687 2687
      *
2688 2688
      * @access private
2689
-     * @param \EE_Registration|null $primary_registrant
2690
-     * @return bool
2689
+     * @param EE_Registration $primary_registrant
2690
+     * @return false|null
2691 2691
      * @throws EE_Error
2692 2692
      * @throws InvalidArgumentException
2693 2693
      * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
Please login to merge, or discard this patch.
Indentation   +2916 added lines, -2916 removed lines patch added patch discarded remove patch
@@ -12,2921 +12,2921 @@
 block discarded – undo
12 12
 class EE_SPCO_Reg_Step_Payment_Options extends EE_SPCO_Reg_Step
13 13
 {
14 14
 
15
-    /**
16
-     * @access protected
17
-     * @var EE_Line_Item_Display $Line_Item_Display
18
-     */
19
-    protected $line_item_display;
20
-
21
-    /**
22
-     * @access protected
23
-     * @var boolean $handle_IPN_in_this_request
24
-     */
25
-    protected $handle_IPN_in_this_request = false;
26
-
27
-
28
-    /**
29
-     *    set_hooks - for hooking into EE Core, other modules, etc
30
-     *
31
-     * @access    public
32
-     * @return    void
33
-     */
34
-    public static function set_hooks()
35
-    {
36
-        add_filter(
37
-            'FHEE__SPCO__EE_Line_Item_Filter_Collection',
38
-            array('EE_SPCO_Reg_Step_Payment_Options', 'add_spco_line_item_filters')
39
-        );
40
-        add_action(
41
-            'wp_ajax_switch_spco_billing_form',
42
-            array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
43
-        );
44
-        add_action(
45
-            'wp_ajax_nopriv_switch_spco_billing_form',
46
-            array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
47
-        );
48
-        add_action('wp_ajax_save_payer_details', array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details'));
49
-        add_action(
50
-            'wp_ajax_nopriv_save_payer_details',
51
-            array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details')
52
-        );
53
-        add_action(
54
-            'wp_ajax_get_transaction_details_for_gateways',
55
-            array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
56
-        );
57
-        add_action(
58
-            'wp_ajax_nopriv_get_transaction_details_for_gateways',
59
-            array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
60
-        );
61
-        add_filter(
62
-            'FHEE__EED_Recaptcha___bypass_recaptcha__bypass_request_params_array',
63
-            array('EE_SPCO_Reg_Step_Payment_Options', 'bypass_recaptcha_for_load_payment_method'),
64
-            10,
65
-            1
66
-        );
67
-    }
68
-
69
-
70
-    /**
71
-     *    ajax switch_spco_billing_form
72
-     *
73
-     * @throws \EE_Error
74
-     */
75
-    public static function switch_spco_billing_form()
76
-    {
77
-        EED_Single_Page_Checkout::process_ajax_request('switch_payment_method');
78
-    }
79
-
80
-
81
-    /**
82
-     *    ajax save_payer_details
83
-     *
84
-     * @throws \EE_Error
85
-     */
86
-    public static function save_payer_details()
87
-    {
88
-        EED_Single_Page_Checkout::process_ajax_request('save_payer_details_via_ajax');
89
-    }
90
-
91
-
92
-    /**
93
-     *    ajax get_transaction_details
94
-     *
95
-     * @throws \EE_Error
96
-     */
97
-    public static function get_transaction_details()
98
-    {
99
-        EED_Single_Page_Checkout::process_ajax_request('get_transaction_details_for_gateways');
100
-    }
101
-
102
-
103
-    /**
104
-     * bypass_recaptcha_for_load_payment_method
105
-     *
106
-     * @access public
107
-     * @return array
108
-     * @throws InvalidArgumentException
109
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
110
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
111
-     */
112
-    public static function bypass_recaptcha_for_load_payment_method()
113
-    {
114
-        return array(
115
-            'EESID'  => EE_Registry::instance()->SSN->id(),
116
-            'step'   => 'payment_options',
117
-            'action' => 'spco_billing_form',
118
-        );
119
-    }
120
-
121
-
122
-    /**
123
-     *    class constructor
124
-     *
125
-     * @access    public
126
-     * @param    EE_Checkout $checkout
127
-     */
128
-    public function __construct(EE_Checkout $checkout)
129
-    {
130
-        $this->_slug = 'payment_options';
131
-        $this->_name = esc_html__('Payment Options', 'event_espresso');
132
-        $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . '/payment_options_main.template.php';
133
-        $this->checkout = $checkout;
134
-        $this->_reset_success_message();
135
-        $this->set_instructions(
136
-            esc_html__(
137
-                'Please select a method of payment and provide any necessary billing information before proceeding.',
138
-                'event_espresso'
139
-            )
140
-        );
141
-    }
142
-
143
-
144
-    /**
145
-     * @return null
146
-     */
147
-    public function line_item_display()
148
-    {
149
-        return $this->line_item_display;
150
-    }
151
-
152
-
153
-    /**
154
-     * @param null $line_item_display
155
-     */
156
-    public function set_line_item_display($line_item_display)
157
-    {
158
-        $this->line_item_display = $line_item_display;
159
-    }
160
-
161
-
162
-    /**
163
-     * @return boolean
164
-     */
165
-    public function handle_IPN_in_this_request()
166
-    {
167
-        return $this->handle_IPN_in_this_request;
168
-    }
169
-
170
-
171
-    /**
172
-     * @param boolean $handle_IPN_in_this_request
173
-     */
174
-    public function set_handle_IPN_in_this_request($handle_IPN_in_this_request)
175
-    {
176
-        $this->handle_IPN_in_this_request = filter_var($handle_IPN_in_this_request, FILTER_VALIDATE_BOOLEAN);
177
-    }
178
-
179
-
180
-    /**
181
-     * translate_js_strings
182
-     *
183
-     * @return void
184
-     */
185
-    public function translate_js_strings()
186
-    {
187
-        EE_Registry::$i18n_js_strings['no_payment_method'] = esc_html__(
188
-            'Please select a method of payment in order to continue.',
189
-            'event_espresso'
190
-        );
191
-        EE_Registry::$i18n_js_strings['invalid_payment_method'] = esc_html__(
192
-            'A valid method of payment could not be determined. Please refresh the page and try again.',
193
-            'event_espresso'
194
-        );
195
-        EE_Registry::$i18n_js_strings['forwarding_to_offsite'] = esc_html__(
196
-            'Forwarding to Secure Payment Provider.',
197
-            'event_espresso'
198
-        );
199
-    }
200
-
201
-
202
-    /**
203
-     * enqueue_styles_and_scripts
204
-     *
205
-     * @return void
206
-     * @throws EE_Error
207
-     * @throws InvalidArgumentException
208
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
209
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
210
-     */
211
-    public function enqueue_styles_and_scripts()
212
-    {
213
-        $transaction = $this->checkout->transaction;
214
-        // if the transaction isn't set or nothing is owed on it, don't enqueue any JS
215
-        if (! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
216
-            return;
217
-        }
218
-        foreach (
219
-            EEM_Payment_Method::instance()->get_all_for_transaction(
220
-                $transaction,
221
-                EEM_Payment_Method::scope_cart
222
-            ) as $payment_method
223
-        ) {
224
-            $type_obj = $payment_method->type_obj();
225
-            if ($type_obj instanceof EE_PMT_Base) {
226
-                $billing_form = $type_obj->generate_new_billing_form($transaction);
227
-                if ($billing_form instanceof EE_Form_Section_Proper) {
228
-                    $billing_form->enqueue_js();
229
-                }
230
-            }
231
-        }
232
-    }
233
-
234
-
235
-    /**
236
-     * initialize_reg_step
237
-     *
238
-     * @return bool
239
-     * @throws EE_Error
240
-     * @throws InvalidArgumentException
241
-     * @throws ReflectionException
242
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
243
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
244
-     */
245
-    public function initialize_reg_step()
246
-    {
247
-        // TODO: if /when we implement donations, then this will need overriding
248
-        if (
15
+	/**
16
+	 * @access protected
17
+	 * @var EE_Line_Item_Display $Line_Item_Display
18
+	 */
19
+	protected $line_item_display;
20
+
21
+	/**
22
+	 * @access protected
23
+	 * @var boolean $handle_IPN_in_this_request
24
+	 */
25
+	protected $handle_IPN_in_this_request = false;
26
+
27
+
28
+	/**
29
+	 *    set_hooks - for hooking into EE Core, other modules, etc
30
+	 *
31
+	 * @access    public
32
+	 * @return    void
33
+	 */
34
+	public static function set_hooks()
35
+	{
36
+		add_filter(
37
+			'FHEE__SPCO__EE_Line_Item_Filter_Collection',
38
+			array('EE_SPCO_Reg_Step_Payment_Options', 'add_spco_line_item_filters')
39
+		);
40
+		add_action(
41
+			'wp_ajax_switch_spco_billing_form',
42
+			array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
43
+		);
44
+		add_action(
45
+			'wp_ajax_nopriv_switch_spco_billing_form',
46
+			array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
47
+		);
48
+		add_action('wp_ajax_save_payer_details', array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details'));
49
+		add_action(
50
+			'wp_ajax_nopriv_save_payer_details',
51
+			array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details')
52
+		);
53
+		add_action(
54
+			'wp_ajax_get_transaction_details_for_gateways',
55
+			array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
56
+		);
57
+		add_action(
58
+			'wp_ajax_nopriv_get_transaction_details_for_gateways',
59
+			array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
60
+		);
61
+		add_filter(
62
+			'FHEE__EED_Recaptcha___bypass_recaptcha__bypass_request_params_array',
63
+			array('EE_SPCO_Reg_Step_Payment_Options', 'bypass_recaptcha_for_load_payment_method'),
64
+			10,
65
+			1
66
+		);
67
+	}
68
+
69
+
70
+	/**
71
+	 *    ajax switch_spco_billing_form
72
+	 *
73
+	 * @throws \EE_Error
74
+	 */
75
+	public static function switch_spco_billing_form()
76
+	{
77
+		EED_Single_Page_Checkout::process_ajax_request('switch_payment_method');
78
+	}
79
+
80
+
81
+	/**
82
+	 *    ajax save_payer_details
83
+	 *
84
+	 * @throws \EE_Error
85
+	 */
86
+	public static function save_payer_details()
87
+	{
88
+		EED_Single_Page_Checkout::process_ajax_request('save_payer_details_via_ajax');
89
+	}
90
+
91
+
92
+	/**
93
+	 *    ajax get_transaction_details
94
+	 *
95
+	 * @throws \EE_Error
96
+	 */
97
+	public static function get_transaction_details()
98
+	{
99
+		EED_Single_Page_Checkout::process_ajax_request('get_transaction_details_for_gateways');
100
+	}
101
+
102
+
103
+	/**
104
+	 * bypass_recaptcha_for_load_payment_method
105
+	 *
106
+	 * @access public
107
+	 * @return array
108
+	 * @throws InvalidArgumentException
109
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
110
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
111
+	 */
112
+	public static function bypass_recaptcha_for_load_payment_method()
113
+	{
114
+		return array(
115
+			'EESID'  => EE_Registry::instance()->SSN->id(),
116
+			'step'   => 'payment_options',
117
+			'action' => 'spco_billing_form',
118
+		);
119
+	}
120
+
121
+
122
+	/**
123
+	 *    class constructor
124
+	 *
125
+	 * @access    public
126
+	 * @param    EE_Checkout $checkout
127
+	 */
128
+	public function __construct(EE_Checkout $checkout)
129
+	{
130
+		$this->_slug = 'payment_options';
131
+		$this->_name = esc_html__('Payment Options', 'event_espresso');
132
+		$this->_template = SPCO_REG_STEPS_PATH . $this->_slug . '/payment_options_main.template.php';
133
+		$this->checkout = $checkout;
134
+		$this->_reset_success_message();
135
+		$this->set_instructions(
136
+			esc_html__(
137
+				'Please select a method of payment and provide any necessary billing information before proceeding.',
138
+				'event_espresso'
139
+			)
140
+		);
141
+	}
142
+
143
+
144
+	/**
145
+	 * @return null
146
+	 */
147
+	public function line_item_display()
148
+	{
149
+		return $this->line_item_display;
150
+	}
151
+
152
+
153
+	/**
154
+	 * @param null $line_item_display
155
+	 */
156
+	public function set_line_item_display($line_item_display)
157
+	{
158
+		$this->line_item_display = $line_item_display;
159
+	}
160
+
161
+
162
+	/**
163
+	 * @return boolean
164
+	 */
165
+	public function handle_IPN_in_this_request()
166
+	{
167
+		return $this->handle_IPN_in_this_request;
168
+	}
169
+
170
+
171
+	/**
172
+	 * @param boolean $handle_IPN_in_this_request
173
+	 */
174
+	public function set_handle_IPN_in_this_request($handle_IPN_in_this_request)
175
+	{
176
+		$this->handle_IPN_in_this_request = filter_var($handle_IPN_in_this_request, FILTER_VALIDATE_BOOLEAN);
177
+	}
178
+
179
+
180
+	/**
181
+	 * translate_js_strings
182
+	 *
183
+	 * @return void
184
+	 */
185
+	public function translate_js_strings()
186
+	{
187
+		EE_Registry::$i18n_js_strings['no_payment_method'] = esc_html__(
188
+			'Please select a method of payment in order to continue.',
189
+			'event_espresso'
190
+		);
191
+		EE_Registry::$i18n_js_strings['invalid_payment_method'] = esc_html__(
192
+			'A valid method of payment could not be determined. Please refresh the page and try again.',
193
+			'event_espresso'
194
+		);
195
+		EE_Registry::$i18n_js_strings['forwarding_to_offsite'] = esc_html__(
196
+			'Forwarding to Secure Payment Provider.',
197
+			'event_espresso'
198
+		);
199
+	}
200
+
201
+
202
+	/**
203
+	 * enqueue_styles_and_scripts
204
+	 *
205
+	 * @return void
206
+	 * @throws EE_Error
207
+	 * @throws InvalidArgumentException
208
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
209
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
210
+	 */
211
+	public function enqueue_styles_and_scripts()
212
+	{
213
+		$transaction = $this->checkout->transaction;
214
+		// if the transaction isn't set or nothing is owed on it, don't enqueue any JS
215
+		if (! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
216
+			return;
217
+		}
218
+		foreach (
219
+			EEM_Payment_Method::instance()->get_all_for_transaction(
220
+				$transaction,
221
+				EEM_Payment_Method::scope_cart
222
+			) as $payment_method
223
+		) {
224
+			$type_obj = $payment_method->type_obj();
225
+			if ($type_obj instanceof EE_PMT_Base) {
226
+				$billing_form = $type_obj->generate_new_billing_form($transaction);
227
+				if ($billing_form instanceof EE_Form_Section_Proper) {
228
+					$billing_form->enqueue_js();
229
+				}
230
+			}
231
+		}
232
+	}
233
+
234
+
235
+	/**
236
+	 * initialize_reg_step
237
+	 *
238
+	 * @return bool
239
+	 * @throws EE_Error
240
+	 * @throws InvalidArgumentException
241
+	 * @throws ReflectionException
242
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
243
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
244
+	 */
245
+	public function initialize_reg_step()
246
+	{
247
+		// TODO: if /when we implement donations, then this will need overriding
248
+		if (
249 249
 // don't need payment options for:
250
-            // registrations made via the admin
251
-            // completed transactions
252
-            // overpaid transactions
253
-            // $ 0.00 transactions(no payment required)
254
-            ! $this->checkout->payment_required()
255
-            // but do NOT remove if current action being called belongs to this reg step
256
-            && ! is_callable(array($this, $this->checkout->action))
257
-            && ! $this->completed()
258
-        ) {
259
-            // and if so, then we no longer need the Payment Options step
260
-            if ($this->is_current_step()) {
261
-                $this->checkout->generate_reg_form = false;
262
-            }
263
-            $this->checkout->remove_reg_step($this->_slug);
264
-            // DEBUG LOG
265
-            // $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
266
-            return false;
267
-        }
268
-        // load EEM_Payment_Method
269
-        EE_Registry::instance()->load_model('Payment_Method');
270
-        // get all active payment methods
271
-        $this->checkout->available_payment_methods = EEM_Payment_Method::instance()->get_all_for_transaction(
272
-            $this->checkout->transaction,
273
-            EEM_Payment_Method::scope_cart
274
-        );
275
-        return true;
276
-    }
277
-
278
-
279
-    /**
280
-     * @return EE_Form_Section_Proper
281
-     * @throws EE_Error
282
-     * @throws InvalidArgumentException
283
-     * @throws ReflectionException
284
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
285
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
286
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
287
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
288
-     */
289
-    public function generate_reg_form()
290
-    {
291
-        // reset in case someone changes their mind
292
-        $this->_reset_selected_method_of_payment();
293
-        // set some defaults
294
-        $this->checkout->selected_method_of_payment = 'payments_closed';
295
-        $registrations_requiring_payment = array();
296
-        $registrations_for_free_events = array();
297
-        $registrations_requiring_pre_approval = array();
298
-        $sold_out_events = array();
299
-        $insufficient_spaces_available = array();
300
-        $no_payment_required = true;
301
-        // loop thru registrations to gather info
302
-        $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
303
-        $ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
304
-            $registrations,
305
-            $this->checkout->revisit
306
-        );
307
-        foreach ($registrations as $REG_ID => $registration) {
308
-            /** @var $registration EE_Registration */
309
-            // has this registration lost it's space ?
310
-            if (isset($ejected_registrations[ $REG_ID ])) {
311
-                if ($registration->event()->is_sold_out() || $registration->event()->is_sold_out(true)) {
312
-                    $sold_out_events[ $registration->event()->ID() ] = $registration->event();
313
-                } else {
314
-                    $insufficient_spaces_available[ $registration->event()->ID() ] = $registration->event();
315
-                }
316
-                continue;
317
-            }
318
-            // event requires admin approval
319
-            if ($registration->status_ID() === EEM_Registration::status_id_not_approved) {
320
-                // add event to list of events with pre-approval reg status
321
-                $registrations_requiring_pre_approval[ $REG_ID ] = $registration;
322
-                do_action(
323
-                    'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_pre_approval',
324
-                    $registration->event(),
325
-                    $this
326
-                );
327
-                continue;
328
-            }
329
-            if (
330
-                $this->checkout->revisit
331
-                && $registration->status_ID() !== EEM_Registration::status_id_approved
332
-                && (
333
-                    $registration->event()->is_sold_out()
334
-                    || $registration->event()->is_sold_out(true)
335
-                )
336
-            ) {
337
-                // add event to list of events that are sold out
338
-                $sold_out_events[ $registration->event()->ID() ] = $registration->event();
339
-                do_action(
340
-                    'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__sold_out_event',
341
-                    $registration->event(),
342
-                    $this
343
-                );
344
-                continue;
345
-            }
346
-            // are they allowed to pay now and is there monies owing?
347
-            if ($registration->owes_monies_and_can_pay()) {
348
-                $registrations_requiring_payment[ $REG_ID ] = $registration;
349
-                do_action(
350
-                    'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_payment',
351
-                    $registration->event(),
352
-                    $this
353
-                );
354
-            } elseif (
355
-                ! $this->checkout->revisit
356
-                      && $registration->status_ID() !== EEM_Registration::status_id_not_approved
357
-                      && $registration->ticket()->is_free()
358
-            ) {
359
-                $registrations_for_free_events[ $registration->ticket()->ID() ] = $registration;
360
-            }
361
-        }
362
-        $subsections = array();
363
-        // now decide which template to load
364
-        if (! empty($sold_out_events)) {
365
-            $subsections['sold_out_events'] = $this->_sold_out_events($sold_out_events);
366
-        }
367
-        if (! empty($insufficient_spaces_available)) {
368
-            $subsections['insufficient_space'] = $this->_insufficient_spaces_available(
369
-                $insufficient_spaces_available
370
-            );
371
-        }
372
-        if (! empty($registrations_requiring_pre_approval)) {
373
-            $subsections['registrations_requiring_pre_approval'] = $this->_registrations_requiring_pre_approval(
374
-                $registrations_requiring_pre_approval
375
-            );
376
-        }
377
-        if (! empty($registrations_for_free_events)) {
378
-            $subsections['no_payment_required'] = $this->_no_payment_required($registrations_for_free_events);
379
-        }
380
-        if (! empty($registrations_requiring_payment)) {
381
-            if ($this->checkout->amount_owing > 0) {
382
-                // autoload Line_Item_Display classes
383
-                EEH_Autoloader::register_line_item_filter_autoloaders();
384
-                $line_item_filter_processor = new EE_Line_Item_Filter_Processor(
385
-                    apply_filters(
386
-                        'FHEE__SPCO__EE_Line_Item_Filter_Collection',
387
-                        new EE_Line_Item_Filter_Collection()
388
-                    ),
389
-                    $this->checkout->cart->get_grand_total()
390
-                );
391
-                /** @var EE_Line_Item $filtered_line_item_tree */
392
-                $filtered_line_item_tree = $line_item_filter_processor->process();
393
-                EEH_Autoloader::register_line_item_display_autoloaders();
394
-                $this->set_line_item_display(new EE_Line_Item_Display('spco'));
395
-                $subsections['payment_options'] = $this->_display_payment_options(
396
-                    $this->line_item_display->display_line_item(
397
-                        $filtered_line_item_tree,
398
-                        array('registrations' => $registrations)
399
-                    )
400
-                );
401
-                $this->checkout->amount_owing = $filtered_line_item_tree->total();
402
-                $this->_apply_registration_payments_to_amount_owing($registrations);
403
-            }
404
-            $no_payment_required = false;
405
-        } else {
406
-            $this->_hide_reg_step_submit_button_if_revisit();
407
-        }
408
-        $this->_save_selected_method_of_payment();
409
-
410
-        $subsections['default_hidden_inputs'] = $this->reg_step_hidden_inputs();
411
-        $subsections['extra_hidden_inputs'] = $this->_extra_hidden_inputs($no_payment_required);
412
-
413
-        return new EE_Form_Section_Proper(
414
-            array(
415
-                'name'            => $this->reg_form_name(),
416
-                'html_id'         => $this->reg_form_name(),
417
-                'subsections'     => $subsections,
418
-                'layout_strategy' => new EE_No_Layout(),
419
-            )
420
-        );
421
-    }
422
-
423
-
424
-    /**
425
-     * add line item filters required for this reg step
426
-     * these filters are applied via this line in EE_SPCO_Reg_Step_Payment_Options::set_hooks():
427
-     *        add_filter( 'FHEE__SPCO__EE_Line_Item_Filter_Collection', array( 'EE_SPCO_Reg_Step_Payment_Options',
428
-     *        'add_spco_line_item_filters' ) ); so any code that wants to use the same set of filters during the
429
-     *        payment options reg step, can apply these filters via the following: apply_filters(
430
-     *        'FHEE__SPCO__EE_Line_Item_Filter_Collection', new EE_Line_Item_Filter_Collection() ) or to an existing
431
-     *        filter collection by passing that instead of instantiating a new collection
432
-     *
433
-     * @param \EE_Line_Item_Filter_Collection $line_item_filter_collection
434
-     * @return EE_Line_Item_Filter_Collection
435
-     * @throws EE_Error
436
-     * @throws InvalidArgumentException
437
-     * @throws ReflectionException
438
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
439
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
440
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
441
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
442
-     */
443
-    public static function add_spco_line_item_filters(EE_Line_Item_Filter_Collection $line_item_filter_collection)
444
-    {
445
-        if (! EE_Registry::instance()->SSN instanceof EE_Session) {
446
-            return $line_item_filter_collection;
447
-        }
448
-        if (! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
449
-            return $line_item_filter_collection;
450
-        }
451
-        if (! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
452
-            return $line_item_filter_collection;
453
-        }
454
-        $line_item_filter_collection->add(
455
-            new EE_Billable_Line_Item_Filter(
456
-                EE_SPCO_Reg_Step_Payment_Options::remove_ejected_registrations(
457
-                    EE_Registry::instance()->SSN->checkout()->transaction->registrations(
458
-                        EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
459
-                    )
460
-                )
461
-            )
462
-        );
463
-        $line_item_filter_collection->add(new EE_Non_Zero_Line_Item_Filter());
464
-        return $line_item_filter_collection;
465
-    }
466
-
467
-
468
-    /**
469
-     * remove_ejected_registrations
470
-     * if a registrant has lost their potential space at an event due to lack of payment,
471
-     * then this method removes them from the list of registrations being paid for during this request
472
-     *
473
-     * @param \EE_Registration[] $registrations
474
-     * @return EE_Registration[]
475
-     * @throws EE_Error
476
-     * @throws InvalidArgumentException
477
-     * @throws ReflectionException
478
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
479
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
480
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
481
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
482
-     */
483
-    public static function remove_ejected_registrations(array $registrations)
484
-    {
485
-        $ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
486
-            $registrations,
487
-            EE_Registry::instance()->SSN->checkout()->revisit
488
-        );
489
-        foreach ($registrations as $REG_ID => $registration) {
490
-            // has this registration lost it's space ?
491
-            if (isset($ejected_registrations[ $REG_ID ])) {
492
-                unset($registrations[ $REG_ID ]);
493
-                continue;
494
-            }
495
-        }
496
-        return $registrations;
497
-    }
498
-
499
-
500
-    /**
501
-     * find_registrations_that_lost_their_space
502
-     * If a registrant chooses an offline payment method like Invoice,
503
-     * then no space is reserved for them at the event until they fully pay fo that site
504
-     * (unless the event's default reg status is set to APPROVED)
505
-     * if a registrant then later returns to pay, but the number of spaces available has been reduced due to sales,
506
-     * then this method will determine which registrations have lost the ability to complete the reg process.
507
-     *
508
-     * @param \EE_Registration[] $registrations
509
-     * @param bool               $revisit
510
-     * @return array
511
-     * @throws EE_Error
512
-     * @throws InvalidArgumentException
513
-     * @throws ReflectionException
514
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
515
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
516
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
517
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
518
-     */
519
-    public static function find_registrations_that_lost_their_space(array $registrations, $revisit = false)
520
-    {
521
-        // registrations per event
522
-        $event_reg_count = array();
523
-        // spaces left per event
524
-        $event_spaces_remaining = array();
525
-        // tickets left sorted by ID
526
-        $tickets_remaining = array();
527
-        // registrations that have lost their space
528
-        $ejected_registrations = array();
529
-        foreach ($registrations as $REG_ID => $registration) {
530
-            if (
531
-                $registration->status_ID() === EEM_Registration::status_id_approved
532
-                || apply_filters(
533
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options__find_registrations_that_lost_their_space__allow_reg_payment',
534
-                    false,
535
-                    $registration,
536
-                    $revisit
537
-                )
538
-            ) {
539
-                continue;
540
-            }
541
-            $EVT_ID = $registration->event_ID();
542
-            $ticket = $registration->ticket();
543
-            if (! isset($tickets_remaining[ $ticket->ID() ])) {
544
-                $tickets_remaining[ $ticket->ID() ] = $ticket->remaining();
545
-            }
546
-            if ($tickets_remaining[ $ticket->ID() ] > 0) {
547
-                if (! isset($event_reg_count[ $EVT_ID ])) {
548
-                    $event_reg_count[ $EVT_ID ] = 0;
549
-                }
550
-                $event_reg_count[ $EVT_ID ]++;
551
-                if (! isset($event_spaces_remaining[ $EVT_ID ])) {
552
-                    $event_spaces_remaining[ $EVT_ID ] = $registration->event()->spaces_remaining_for_sale();
553
-                }
554
-            }
555
-            if (
556
-                $revisit
557
-                && ($tickets_remaining[ $ticket->ID() ] === 0
558
-                    || $event_reg_count[ $EVT_ID ] > $event_spaces_remaining[ $EVT_ID ]
559
-                )
560
-            ) {
561
-                $ejected_registrations[ $REG_ID ] = $registration->event();
562
-                if ($registration->status_ID() !== EEM_Registration::status_id_wait_list) {
563
-                    /** @type EE_Registration_Processor $registration_processor */
564
-                    $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
565
-                    // at this point, we should have enough details about the registrant to consider the registration
566
-                    // NOT incomplete
567
-                    $registration_processor->manually_update_registration_status(
568
-                        $registration,
569
-                        EEM_Registration::status_id_wait_list
570
-                    );
571
-                }
572
-            }
573
-        }
574
-        return $ejected_registrations;
575
-    }
576
-
577
-
578
-    /**
579
-     * _hide_reg_step_submit_button
580
-     * removes the html for the reg step submit button
581
-     * by replacing it with an empty string via filter callback
582
-     *
583
-     * @return void
584
-     */
585
-    protected function _adjust_registration_status_if_event_old_sold()
586
-    {
587
-    }
588
-
589
-
590
-    /**
591
-     * _hide_reg_step_submit_button
592
-     * removes the html for the reg step submit button
593
-     * by replacing it with an empty string via filter callback
594
-     *
595
-     * @return void
596
-     */
597
-    protected function _hide_reg_step_submit_button_if_revisit()
598
-    {
599
-        if ($this->checkout->revisit) {
600
-            add_filter('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', '__return_empty_string');
601
-        }
602
-    }
603
-
604
-
605
-    /**
606
-     * sold_out_events
607
-     * displays notices regarding events that have sold out since hte registrant first signed up
608
-     *
609
-     * @param \EE_Event[] $sold_out_events_array
610
-     * @return \EE_Form_Section_Proper
611
-     * @throws \EE_Error
612
-     */
613
-    private function _sold_out_events($sold_out_events_array = array())
614
-    {
615
-        // set some defaults
616
-        $this->checkout->selected_method_of_payment = 'events_sold_out';
617
-        $sold_out_events = '';
618
-        foreach ($sold_out_events_array as $sold_out_event) {
619
-            $sold_out_events .= EEH_HTML::li(
620
-                EEH_HTML::span(
621
-                    '  ' . $sold_out_event->name(),
622
-                    '',
623
-                    'dashicons dashicons-marker ee-icon-size-16 pink-text'
624
-                )
625
-            );
626
-        }
627
-        return new EE_Form_Section_Proper(
628
-            array(
629
-                'layout_strategy' => new EE_Template_Layout(
630
-                    array(
631
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
632
-                                                  . $this->_slug
633
-                                                  . '/sold_out_events.template.php',
634
-                        'template_args'        => apply_filters(
635
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
636
-                            array(
637
-                                'sold_out_events'     => $sold_out_events,
638
-                                'sold_out_events_msg' => apply_filters(
639
-                                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__sold_out_events_msg',
640
-                                    sprintf(
641
-                                        esc_html__(
642
-                                            'It appears that the event you were about to make a payment for has sold out since you first registered. If you have already made a partial payment towards this event, please contact the event administrator for a refund.%3$s%3$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%2$s',
643
-                                            'event_espresso'
644
-                                        ),
645
-                                        '<strong>',
646
-                                        '</strong>',
647
-                                        '<br />'
648
-                                    )
649
-                                ),
650
-                            )
651
-                        ),
652
-                    )
653
-                ),
654
-            )
655
-        );
656
-    }
657
-
658
-
659
-    /**
660
-     * _insufficient_spaces_available
661
-     * displays notices regarding events that do not have enough remaining spaces
662
-     * to satisfy the current number of registrations looking to pay
663
-     *
664
-     * @param \EE_Event[] $insufficient_spaces_events_array
665
-     * @return \EE_Form_Section_Proper
666
-     * @throws \EE_Error
667
-     */
668
-    private function _insufficient_spaces_available($insufficient_spaces_events_array = array())
669
-    {
670
-        // set some defaults
671
-        $this->checkout->selected_method_of_payment = 'invoice';
672
-        $insufficient_space_events = '';
673
-        foreach ($insufficient_spaces_events_array as $event) {
674
-            if ($event instanceof EE_Event) {
675
-                $insufficient_space_events .= EEH_HTML::li(
676
-                    EEH_HTML::span(' ' . $event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
677
-                );
678
-            }
679
-        }
680
-        return new EE_Form_Section_Proper(
681
-            array(
682
-                'subsections'     => array(
683
-                    'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
684
-                    'extra_hidden_inputs'   => $this->_extra_hidden_inputs(),
685
-                ),
686
-                'layout_strategy' => new EE_Template_Layout(
687
-                    array(
688
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
689
-                                                  . $this->_slug
690
-                                                  . '/sold_out_events.template.php',
691
-                        'template_args'        => apply_filters(
692
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__template_args',
693
-                            array(
694
-                                'sold_out_events'     => $insufficient_space_events,
695
-                                'sold_out_events_msg' => apply_filters(
696
-                                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__insufficient_space_msg',
697
-                                    esc_html__(
698
-                                        'It appears that the event you were about to make a payment for has sold additional tickets since you first registered, and there are no longer enough spaces left to accommodate your selections. You may continue to pay and secure the available space(s) remaining, or simply cancel if you no longer wish to purchase. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
699
-                                        'event_espresso'
700
-                                    )
701
-                                ),
702
-                            )
703
-                        ),
704
-                    )
705
-                ),
706
-            )
707
-        );
708
-    }
709
-
710
-
711
-    /**
712
-     * registrations_requiring_pre_approval
713
-     *
714
-     * @param array $registrations_requiring_pre_approval
715
-     * @return EE_Form_Section_Proper
716
-     * @throws EE_Error
717
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
718
-     */
719
-    private function _registrations_requiring_pre_approval($registrations_requiring_pre_approval = array())
720
-    {
721
-        $events_requiring_pre_approval = array();
722
-        foreach ($registrations_requiring_pre_approval as $registration) {
723
-            if ($registration instanceof EE_Registration && $registration->event() instanceof EE_Event) {
724
-                $events_requiring_pre_approval[ $registration->event()->ID() ] = EEH_HTML::li(
725
-                    EEH_HTML::span(
726
-                        '',
727
-                        '',
728
-                        'dashicons dashicons-marker ee-icon-size-16 orange-text'
729
-                    )
730
-                    . EEH_HTML::span($registration->event()->name(), '', 'orange-text')
731
-                );
732
-            }
733
-        }
734
-        return new EE_Form_Section_Proper(
735
-            array(
736
-                'layout_strategy' => new EE_Template_Layout(
737
-                    array(
738
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
739
-                                                  . $this->_slug
740
-                                                  . '/events_requiring_pre_approval.template.php', // layout_template
741
-                        'template_args'        => apply_filters(
742
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
743
-                            array(
744
-                                'events_requiring_pre_approval'     => implode('', $events_requiring_pre_approval),
745
-                                'events_requiring_pre_approval_msg' => apply_filters(
746
-                                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___events_requiring_pre_approval__events_requiring_pre_approval_msg',
747
-                                    esc_html__(
748
-                                        'The following events do not require payment at this time and will not be billed during this transaction. Billing will only occur after the attendee has been approved by the event organizer. You will be notified when your registration has been processed. If this is a free event, then no billing will occur.',
749
-                                        'event_espresso'
750
-                                    )
751
-                                ),
752
-                            )
753
-                        ),
754
-                    )
755
-                ),
756
-            )
757
-        );
758
-    }
759
-
760
-
761
-    /**
762
-     * _no_payment_required
763
-     *
764
-     * @param \EE_Event[] $registrations_for_free_events
765
-     * @return \EE_Form_Section_Proper
766
-     * @throws \EE_Error
767
-     */
768
-    private function _no_payment_required($registrations_for_free_events = array())
769
-    {
770
-        // set some defaults
771
-        $this->checkout->selected_method_of_payment = 'no_payment_required';
772
-        // generate no_payment_required form
773
-        return new EE_Form_Section_Proper(
774
-            array(
775
-                'layout_strategy' => new EE_Template_Layout(
776
-                    array(
777
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
778
-                                                  . $this->_slug
779
-                                                  . '/no_payment_required.template.php', // layout_template
780
-                        'template_args'        => apply_filters(
781
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___no_payment_required__template_args',
782
-                            array(
783
-                                'revisit'                       => $this->checkout->revisit,
784
-                                'registrations'                 => array(),
785
-                                'ticket_count'                  => array(),
786
-                                'registrations_for_free_events' => $registrations_for_free_events,
787
-                                'no_payment_required_msg'       => EEH_HTML::p(
788
-                                    esc_html__('This is a free event, so no billing will occur.', 'event_espresso')
789
-                                ),
790
-                            )
791
-                        ),
792
-                    )
793
-                ),
794
-            )
795
-        );
796
-    }
797
-
798
-
799
-    /**
800
-     * _display_payment_options
801
-     *
802
-     * @param string $transaction_details
803
-     * @return EE_Form_Section_Proper
804
-     * @throws EE_Error
805
-     * @throws InvalidArgumentException
806
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
807
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
808
-     */
809
-    private function _display_payment_options($transaction_details = '')
810
-    {
811
-        // has method_of_payment been set by no-js user?
812
-        $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment();
813
-        // build payment options form
814
-        return apply_filters(
815
-            'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__payment_options_form',
816
-            new EE_Form_Section_Proper(
817
-                array(
818
-                    'subsections'     => array(
819
-                        'before_payment_options' => apply_filters(
820
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__before_payment_options',
821
-                            new EE_Form_Section_Proper(
822
-                                array('layout_strategy' => new EE_Div_Per_Section_Layout())
823
-                            )
824
-                        ),
825
-                        'payment_options'        => $this->_setup_payment_options(),
826
-                        'after_payment_options'  => apply_filters(
827
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__after_payment_options',
828
-                            new EE_Form_Section_Proper(
829
-                                array('layout_strategy' => new EE_Div_Per_Section_Layout())
830
-                            )
831
-                        ),
832
-                    ),
833
-                    'layout_strategy' => new EE_Template_Layout(
834
-                        array(
835
-                            'layout_template_file' => $this->_template,
836
-                            'template_args'        => apply_filters(
837
-                                'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__template_args',
838
-                                array(
839
-                                    'reg_count'                 => $this->line_item_display->total_items(),
840
-                                    'transaction_details'       => $transaction_details,
841
-                                    'available_payment_methods' => array(),
842
-                                )
843
-                            ),
844
-                        )
845
-                    ),
846
-                )
847
-            )
848
-        );
849
-    }
850
-
851
-
852
-    /**
853
-     * _extra_hidden_inputs
854
-     *
855
-     * @param bool $no_payment_required
856
-     * @return \EE_Form_Section_Proper
857
-     * @throws \EE_Error
858
-     */
859
-    private function _extra_hidden_inputs($no_payment_required = true)
860
-    {
861
-        return new EE_Form_Section_Proper(
862
-            array(
863
-                'html_id'         => 'ee-' . $this->slug() . '-extra-hidden-inputs',
864
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
865
-                'subsections'     => array(
866
-                    'spco_no_payment_required' => new EE_Hidden_Input(
867
-                        array(
868
-                            'normalization_strategy' => new EE_Boolean_Normalization(),
869
-                            'html_name'              => 'spco_no_payment_required',
870
-                            'html_id'                => 'spco-no-payment-required-payment_options',
871
-                            'default'                => $no_payment_required,
872
-                        )
873
-                    ),
874
-                    'spco_transaction_id'      => new EE_Fixed_Hidden_Input(
875
-                        array(
876
-                            'normalization_strategy' => new EE_Int_Normalization(),
877
-                            'html_name'              => 'spco_transaction_id',
878
-                            'html_id'                => 'spco-transaction-id',
879
-                            'default'                => $this->checkout->transaction->ID(),
880
-                        )
881
-                    ),
882
-                ),
883
-            )
884
-        );
885
-    }
886
-
887
-
888
-    /**
889
-     *    _apply_registration_payments_to_amount_owing
890
-     *
891
-     * @access protected
892
-     * @param array $registrations
893
-     * @throws EE_Error
894
-     */
895
-    protected function _apply_registration_payments_to_amount_owing(array $registrations)
896
-    {
897
-        $payments = array();
898
-        foreach ($registrations as $registration) {
899
-            if ($registration instanceof EE_Registration && $registration->owes_monies_and_can_pay()) {
900
-                $payments += $registration->registration_payments();
901
-            }
902
-        }
903
-        if (! empty($payments)) {
904
-            foreach ($payments as $payment) {
905
-                if ($payment instanceof EE_Registration_Payment) {
906
-                    $this->checkout->amount_owing -= $payment->amount();
907
-                }
908
-            }
909
-        }
910
-    }
911
-
912
-
913
-    /**
914
-     *    _reset_selected_method_of_payment
915
-     *
916
-     * @access    private
917
-     * @param    bool $force_reset
918
-     * @return void
919
-     * @throws InvalidArgumentException
920
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
921
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
922
-     */
923
-    private function _reset_selected_method_of_payment($force_reset = false)
924
-    {
925
-        $reset_payment_method = $force_reset
926
-            ? true
927
-            : sanitize_text_field(EE_Registry::instance()->REQ->get('reset_payment_method', false));
928
-        if ($reset_payment_method) {
929
-            $this->checkout->selected_method_of_payment = null;
930
-            $this->checkout->payment_method = null;
931
-            $this->checkout->billing_form = null;
932
-            $this->_save_selected_method_of_payment();
933
-        }
934
-    }
935
-
936
-
937
-    /**
938
-     * _save_selected_method_of_payment
939
-     * stores the selected_method_of_payment in the session
940
-     * so that it's available for all subsequent requests including AJAX
941
-     *
942
-     * @access        private
943
-     * @param string $selected_method_of_payment
944
-     * @return void
945
-     * @throws InvalidArgumentException
946
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
947
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
948
-     */
949
-    private function _save_selected_method_of_payment($selected_method_of_payment = '')
950
-    {
951
-        $selected_method_of_payment = ! empty($selected_method_of_payment)
952
-            ? $selected_method_of_payment
953
-            : $this->checkout->selected_method_of_payment;
954
-        EE_Registry::instance()->SSN->set_session_data(
955
-            array('selected_method_of_payment' => $selected_method_of_payment)
956
-        );
957
-    }
958
-
959
-
960
-    /**
961
-     * _setup_payment_options
962
-     *
963
-     * @return EE_Form_Section_Proper
964
-     * @throws EE_Error
965
-     * @throws InvalidArgumentException
966
-     * @throws ReflectionException
967
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
968
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
969
-     */
970
-    public function _setup_payment_options()
971
-    {
972
-        // load payment method classes
973
-        $this->checkout->available_payment_methods = $this->_get_available_payment_methods();
974
-        if (empty($this->checkout->available_payment_methods)) {
975
-            EE_Error::add_error(
976
-                apply_filters(
977
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___setup_payment_options__error_message_no_payment_methods',
978
-                    sprintf(
979
-                        esc_html__(
980
-                            'Sorry, you cannot complete your purchase because a payment method is not active.%1$s Please contact %2$s for assistance and provide a description of the problem.',
981
-                            'event_espresso'
982
-                        ),
983
-                        '<br>',
984
-                        EE_Registry::instance()->CFG->organization->get_pretty('email')
985
-                    )
986
-                ),
987
-                __FILE__,
988
-                __FUNCTION__,
989
-                __LINE__
990
-            );
991
-        }
992
-        // switch up header depending on number of available payment methods
993
-        $payment_method_header = count($this->checkout->available_payment_methods) > 1
994
-            ? apply_filters(
995
-                'FHEE__registration_page_payment_options__method_of_payment_hdr',
996
-                esc_html__('Please Select Your Method of Payment', 'event_espresso')
997
-            )
998
-            : apply_filters(
999
-                'FHEE__registration_page_payment_options__method_of_payment_hdr',
1000
-                esc_html__('Method of Payment', 'event_espresso')
1001
-            );
1002
-        $available_payment_methods = array(
1003
-            // display the "Payment Method" header
1004
-            'payment_method_header' => new EE_Form_Section_HTML(
1005
-                apply_filters(
1006
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___setup_payment_options__payment_method_header',
1007
-                    EEH_HTML::h4($payment_method_header, 'method-of-payment-hdr'),
1008
-                    $payment_method_header
1009
-                )
1010
-            ),
1011
-        );
1012
-        // the list of actual payment methods ( invoice, paypal, etc ) in a  ( slug => HTML )  format
1013
-        $available_payment_method_options = array();
1014
-        $default_payment_method_option = array();
1015
-        // additional instructions to be displayed and hidden below payment methods (adding a clearing div to start)
1016
-        $payment_methods_billing_info = array(
1017
-            new EE_Form_Section_HTML(
1018
-                EEH_HTML::div('<br />', '', '', 'clear:both;')
1019
-            ),
1020
-        );
1021
-        // loop through payment methods
1022
-        foreach ($this->checkout->available_payment_methods as $payment_method) {
1023
-            if ($payment_method instanceof EE_Payment_Method) {
1024
-                $payment_method_button = EEH_HTML::img(
1025
-                    $payment_method->button_url(),
1026
-                    $payment_method->name(),
1027
-                    'spco-payment-method-' . $payment_method->slug() . '-btn-img',
1028
-                    'spco-payment-method-btn-img'
1029
-                );
1030
-                // check if any payment methods are set as default
1031
-                // if payment method is already selected OR nothing is selected and this payment method should be
1032
-                // open_by_default
1033
-                if (
1034
-                    ($this->checkout->selected_method_of_payment === $payment_method->slug())
1035
-                    || (! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1036
-                ) {
1037
-                    $this->checkout->selected_method_of_payment = $payment_method->slug();
1038
-                    $this->_save_selected_method_of_payment();
1039
-                    $default_payment_method_option[ $payment_method->slug() ] = $payment_method_button;
1040
-                } else {
1041
-                    $available_payment_method_options[ $payment_method->slug() ] = $payment_method_button;
1042
-                }
1043
-                $payment_methods_billing_info[ $payment_method->slug(
1044
-                ) . '-info' ] = $this->_payment_method_billing_info(
1045
-                    $payment_method
1046
-                );
1047
-            }
1048
-        }
1049
-        // prepend available_payment_method_options with default_payment_method_option so that it appears first in list
1050
-        // of PMs
1051
-        $available_payment_method_options = $default_payment_method_option + $available_payment_method_options;
1052
-        // now generate the actual form  inputs
1053
-        $available_payment_methods['available_payment_methods'] = $this->_available_payment_method_inputs(
1054
-            $available_payment_method_options
1055
-        );
1056
-        $available_payment_methods += $payment_methods_billing_info;
1057
-        // build the available payment methods form
1058
-        return new EE_Form_Section_Proper(
1059
-            array(
1060
-                'html_id'         => 'spco-available-methods-of-payment-dv',
1061
-                'subsections'     => $available_payment_methods,
1062
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1063
-            )
1064
-        );
1065
-    }
1066
-
1067
-
1068
-    /**
1069
-     * _get_available_payment_methods
1070
-     *
1071
-     * @return EE_Payment_Method[]
1072
-     * @throws EE_Error
1073
-     * @throws InvalidArgumentException
1074
-     * @throws ReflectionException
1075
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1076
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1077
-     */
1078
-    protected function _get_available_payment_methods()
1079
-    {
1080
-        if (! empty($this->checkout->available_payment_methods)) {
1081
-            return $this->checkout->available_payment_methods;
1082
-        }
1083
-        $available_payment_methods = array();
1084
-        // load EEM_Payment_Method
1085
-        EE_Registry::instance()->load_model('Payment_Method');
1086
-        /** @type EEM_Payment_Method $EEM_Payment_Method */
1087
-        $EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
1088
-        // get all active payment methods
1089
-        $payment_methods = $EEM_Payment_Method->get_all_for_transaction(
1090
-            $this->checkout->transaction,
1091
-            EEM_Payment_Method::scope_cart
1092
-        );
1093
-        foreach ($payment_methods as $payment_method) {
1094
-            if ($payment_method instanceof EE_Payment_Method) {
1095
-                $available_payment_methods[ $payment_method->slug() ] = $payment_method;
1096
-            }
1097
-        }
1098
-        return $available_payment_methods;
1099
-    }
1100
-
1101
-
1102
-    /**
1103
-     *    _available_payment_method_inputs
1104
-     *
1105
-     * @access    private
1106
-     * @param    array $available_payment_method_options
1107
-     * @return    \EE_Form_Section_Proper
1108
-     */
1109
-    private function _available_payment_method_inputs($available_payment_method_options = array())
1110
-    {
1111
-        // generate inputs
1112
-        return new EE_Form_Section_Proper(
1113
-            array(
1114
-                'html_id'         => 'ee-available-payment-method-inputs',
1115
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1116
-                'subsections'     => array(
1117
-                    '' => new EE_Radio_Button_Input(
1118
-                        $available_payment_method_options,
1119
-                        array(
1120
-                            'html_name'          => 'selected_method_of_payment',
1121
-                            'html_class'         => 'spco-payment-method',
1122
-                            'default'            => $this->checkout->selected_method_of_payment,
1123
-                            'label_size'         => 11,
1124
-                            'enforce_label_size' => true,
1125
-                        )
1126
-                    ),
1127
-                ),
1128
-            )
1129
-        );
1130
-    }
1131
-
1132
-
1133
-    /**
1134
-     *    _payment_method_billing_info
1135
-     *
1136
-     * @access    private
1137
-     * @param    EE_Payment_Method $payment_method
1138
-     * @return EE_Form_Section_Proper
1139
-     * @throws EE_Error
1140
-     * @throws InvalidArgumentException
1141
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1142
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1143
-     */
1144
-    private function _payment_method_billing_info(EE_Payment_Method $payment_method)
1145
-    {
1146
-        $currently_selected = $this->checkout->selected_method_of_payment === $payment_method->slug()
1147
-            ? true
1148
-            : false;
1149
-        // generate the billing form for payment method
1150
-        $billing_form = $currently_selected
1151
-            ? $this->_get_billing_form_for_payment_method($payment_method)
1152
-            : new EE_Form_Section_HTML();
1153
-        $this->checkout->billing_form = $currently_selected
1154
-            ? $billing_form
1155
-            : $this->checkout->billing_form;
1156
-        // it's all in the details
1157
-        $info_html = EEH_HTML::h3(
1158
-            esc_html__('Important information regarding your payment', 'event_espresso'),
1159
-            '',
1160
-            'spco-payment-method-hdr'
1161
-        );
1162
-        // add some info regarding the step, either from what's saved in the admin,
1163
-        // or a default string depending on whether the PM has a billing form or not
1164
-        if ($payment_method->description()) {
1165
-            $payment_method_info = $payment_method->description();
1166
-        } elseif ($billing_form instanceof EE_Billing_Info_Form) {
1167
-            $payment_method_info = sprintf(
1168
-                esc_html__(
1169
-                    'Please provide the following billing information, then click the "%1$s" button below in order to proceed.',
1170
-                    'event_espresso'
1171
-                ),
1172
-                $this->submit_button_text()
1173
-            );
1174
-        } else {
1175
-            $payment_method_info = sprintf(
1176
-                esc_html__('Please click the "%1$s" button below in order to proceed.', 'event_espresso'),
1177
-                $this->submit_button_text()
1178
-            );
1179
-        }
1180
-        $info_html .= EEH_HTML::div(
1181
-            apply_filters(
1182
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options___payment_method_billing_info__payment_method_info',
1183
-                $payment_method_info
1184
-            ),
1185
-            '',
1186
-            'spco-payment-method-desc ee-attention'
1187
-        );
1188
-        return new EE_Form_Section_Proper(
1189
-            array(
1190
-                'html_id'         => 'spco-payment-method-info-' . $payment_method->slug(),
1191
-                'html_class'      => 'spco-payment-method-info-dv',
1192
-                // only display the selected or default PM
1193
-                'html_style'      => $currently_selected ? '' : 'display:none;',
1194
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1195
-                'subsections'     => array(
1196
-                    'info'         => new EE_Form_Section_HTML($info_html),
1197
-                    'billing_form' => $currently_selected ? $billing_form : new EE_Form_Section_HTML(),
1198
-                ),
1199
-            )
1200
-        );
1201
-    }
1202
-
1203
-
1204
-    /**
1205
-     * get_billing_form_html_for_payment_method
1206
-     *
1207
-     * @access public
1208
-     * @return string
1209
-     * @throws EE_Error
1210
-     * @throws InvalidArgumentException
1211
-     * @throws ReflectionException
1212
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1213
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1214
-     */
1215
-    public function get_billing_form_html_for_payment_method()
1216
-    {
1217
-        // how have they chosen to pay?
1218
-        $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1219
-        $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1220
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1221
-            return false;
1222
-        }
1223
-        if (
1224
-            apply_filters(
1225
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1226
-                false
1227
-            )
1228
-        ) {
1229
-            EE_Error::add_success(
1230
-                apply_filters(
1231
-                    'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1232
-                    sprintf(
1233
-                        esc_html__(
1234
-                            'You have selected "%s" as your method of payment. Please note the important payment information below.',
1235
-                            'event_espresso'
1236
-                        ),
1237
-                        $this->checkout->payment_method->name()
1238
-                    )
1239
-                )
1240
-            );
1241
-        }
1242
-        // now generate billing form for selected method of payment
1243
-        $payment_method_billing_form = $this->_get_billing_form_for_payment_method($this->checkout->payment_method);
1244
-        // fill form with attendee info if applicable
1245
-        if (
1246
-            $payment_method_billing_form instanceof EE_Billing_Attendee_Info_Form
1247
-            && $this->checkout->transaction_has_primary_registrant()
1248
-        ) {
1249
-            $payment_method_billing_form->populate_from_attendee(
1250
-                $this->checkout->transaction->primary_registration()->attendee()
1251
-            );
1252
-        }
1253
-        // and debug content
1254
-        if (
1255
-            $payment_method_billing_form instanceof EE_Billing_Info_Form
1256
-            && $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1257
-        ) {
1258
-            $payment_method_billing_form =
1259
-                $this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1260
-                    $payment_method_billing_form
1261
-                );
1262
-        }
1263
-        $billing_info = $payment_method_billing_form instanceof EE_Form_Section_Proper
1264
-            ? $payment_method_billing_form->get_html()
1265
-            : '';
1266
-        $this->checkout->json_response->set_return_data(array('payment_method_info' => $billing_info));
1267
-        // localize validation rules for main form
1268
-        $this->checkout->current_step->reg_form->localize_validation_rules();
1269
-        $this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1270
-        return true;
1271
-    }
1272
-
1273
-
1274
-    /**
1275
-     * _get_billing_form_for_payment_method
1276
-     *
1277
-     * @access private
1278
-     * @param EE_Payment_Method $payment_method
1279
-     * @return EE_Billing_Info_Form|EE_Form_Section_HTML
1280
-     * @throws EE_Error
1281
-     * @throws InvalidArgumentException
1282
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1283
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1284
-     */
1285
-    private function _get_billing_form_for_payment_method(EE_Payment_Method $payment_method)
1286
-    {
1287
-        $billing_form = $payment_method->type_obj()->billing_form(
1288
-            $this->checkout->transaction,
1289
-            array('amount_owing' => $this->checkout->amount_owing)
1290
-        );
1291
-        if ($billing_form instanceof EE_Billing_Info_Form) {
1292
-            if (
1293
-                apply_filters(
1294
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1295
-                    false
1296
-                )
1297
-                && EE_Registry::instance()->REQ->is_set('payment_method')
1298
-            ) {
1299
-                EE_Error::add_success(
1300
-                    apply_filters(
1301
-                        'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1302
-                        sprintf(
1303
-                            esc_html__(
1304
-                                'You have selected "%s" as your method of payment. Please note the important payment information below.',
1305
-                                'event_espresso'
1306
-                            ),
1307
-                            $payment_method->name()
1308
-                        )
1309
-                    )
1310
-                );
1311
-            }
1312
-            return apply_filters(
1313
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options___get_billing_form_for_payment_method__billing_form',
1314
-                $billing_form,
1315
-                $payment_method
1316
-            );
1317
-        }
1318
-        // no actual billing form, so return empty HTML form section
1319
-        return new EE_Form_Section_HTML();
1320
-    }
1321
-
1322
-
1323
-    /**
1324
-     * _get_selected_method_of_payment
1325
-     *
1326
-     * @access private
1327
-     * @param boolean $required whether to throw an error if the "selected_method_of_payment"
1328
-     *                          is not found in the incoming request
1329
-     * @param string  $request_param
1330
-     * @return NULL|string
1331
-     * @throws EE_Error
1332
-     * @throws InvalidArgumentException
1333
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1334
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1335
-     */
1336
-    private function _get_selected_method_of_payment(
1337
-        $required = false,
1338
-        $request_param = 'selected_method_of_payment'
1339
-    ) {
1340
-        // is selected_method_of_payment set in the request ?
1341
-        $selected_method_of_payment = EE_Registry::instance()->REQ->get($request_param, false);
1342
-        if ($selected_method_of_payment) {
1343
-            // sanitize it
1344
-            $selected_method_of_payment = is_array($selected_method_of_payment)
1345
-                ? array_shift($selected_method_of_payment)
1346
-                : $selected_method_of_payment;
1347
-            $selected_method_of_payment = sanitize_text_field($selected_method_of_payment);
1348
-            // store it in the session so that it's available for all subsequent requests including AJAX
1349
-            $this->_save_selected_method_of_payment($selected_method_of_payment);
1350
-        } else {
1351
-            // or is is set in the session ?
1352
-            $selected_method_of_payment = EE_Registry::instance()->SSN->get_session_data(
1353
-                'selected_method_of_payment'
1354
-            );
1355
-        }
1356
-        // do ya really really gotta have it?
1357
-        if (empty($selected_method_of_payment) && $required) {
1358
-            EE_Error::add_error(
1359
-                sprintf(
1360
-                    esc_html__(
1361
-                        'The selected method of payment could not be determined.%sPlease ensure that you have selected one before proceeding.%sIf you continue to experience difficulties, then refresh your browser and try again, or contact %s for assistance.',
1362
-                        'event_espresso'
1363
-                    ),
1364
-                    '<br/>',
1365
-                    '<br/>',
1366
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
1367
-                ),
1368
-                __FILE__,
1369
-                __FUNCTION__,
1370
-                __LINE__
1371
-            );
1372
-            return null;
1373
-        }
1374
-        return $selected_method_of_payment;
1375
-    }
1376
-
1377
-
1378
-
1379
-
1380
-
1381
-
1382
-    /********************************************************************************************************/
1383
-    /***********************************  SWITCH PAYMENT METHOD  ************************************/
1384
-    /********************************************************************************************************/
1385
-    /**
1386
-     * switch_payment_method
1387
-     *
1388
-     * @access public
1389
-     * @return string
1390
-     * @throws EE_Error
1391
-     * @throws InvalidArgumentException
1392
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1393
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1394
-     */
1395
-    public function switch_payment_method()
1396
-    {
1397
-        if (! $this->_verify_payment_method_is_set()) {
1398
-            return false;
1399
-        }
1400
-        if (
1401
-            apply_filters(
1402
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1403
-                false
1404
-            )
1405
-        ) {
1406
-            EE_Error::add_success(
1407
-                apply_filters(
1408
-                    'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1409
-                    sprintf(
1410
-                        esc_html__(
1411
-                            'You have selected "%s" as your method of payment. Please note the important payment information below.',
1412
-                            'event_espresso'
1413
-                        ),
1414
-                        $this->checkout->payment_method->name()
1415
-                    )
1416
-                )
1417
-            );
1418
-        }
1419
-        // generate billing form for selected method of payment if it hasn't been done already
1420
-        if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1421
-            $this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1422
-                $this->checkout->payment_method
1423
-            );
1424
-        }
1425
-        // fill form with attendee info if applicable
1426
-        if (
1427
-            apply_filters(
1428
-                'FHEE__populate_billing_form_fields_from_attendee',
1429
-                (
1430
-                $this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
1431
-                && $this->checkout->transaction_has_primary_registrant()
1432
-                ),
1433
-                $this->checkout->billing_form,
1434
-                $this->checkout->transaction
1435
-            )
1436
-        ) {
1437
-            $this->checkout->billing_form->populate_from_attendee(
1438
-                $this->checkout->transaction->primary_registration()->attendee()
1439
-            );
1440
-        }
1441
-        // and debug content
1442
-        if (
1443
-            $this->checkout->billing_form instanceof EE_Billing_Info_Form
1444
-            && $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1445
-        ) {
1446
-            $this->checkout->billing_form =
1447
-                $this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1448
-                    $this->checkout->billing_form
1449
-                );
1450
-        }
1451
-        // get html and validation rules for form
1452
-        if ($this->checkout->billing_form instanceof EE_Form_Section_Proper) {
1453
-            $this->checkout->json_response->set_return_data(
1454
-                array('payment_method_info' => $this->checkout->billing_form->get_html())
1455
-            );
1456
-            // localize validation rules for main form
1457
-            $this->checkout->billing_form->localize_validation_rules(true);
1458
-            $this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1459
-        } else {
1460
-            $this->checkout->json_response->set_return_data(array('payment_method_info' => ''));
1461
-        }
1462
-        // prevents advancement to next step
1463
-        $this->checkout->continue_reg = false;
1464
-        return true;
1465
-    }
1466
-
1467
-
1468
-    /**
1469
-     * _verify_payment_method_is_set
1470
-     *
1471
-     * @return bool
1472
-     * @throws EE_Error
1473
-     * @throws InvalidArgumentException
1474
-     * @throws ReflectionException
1475
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1476
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1477
-     */
1478
-    protected function _verify_payment_method_is_set()
1479
-    {
1480
-        // generate billing form for selected method of payment if it hasn't been done already
1481
-        if (empty($this->checkout->selected_method_of_payment)) {
1482
-            // how have they chosen to pay?
1483
-            $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1484
-        } else {
1485
-            // choose your own adventure based on method_of_payment
1486
-            switch ($this->checkout->selected_method_of_payment) {
1487
-                case 'events_sold_out':
1488
-                    EE_Error::add_attention(
1489
-                        apply_filters(
1490
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__sold_out_events_msg',
1491
-                            esc_html__(
1492
-                                'It appears that the event you were about to make a payment for has sold out since this form first loaded. Please contact the event administrator if you believe this is an error.',
1493
-                                'event_espresso'
1494
-                            )
1495
-                        ),
1496
-                        __FILE__,
1497
-                        __FUNCTION__,
1498
-                        __LINE__
1499
-                    );
1500
-                    return false;
1501
-                    break;
1502
-                case 'payments_closed':
1503
-                    EE_Error::add_attention(
1504
-                        apply_filters(
1505
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__payments_closed_msg',
1506
-                            esc_html__(
1507
-                                'It appears that the event you were about to make a payment for is not accepting payments at this time. Please contact the event administrator if you believe this is an error.',
1508
-                                'event_espresso'
1509
-                            )
1510
-                        ),
1511
-                        __FILE__,
1512
-                        __FUNCTION__,
1513
-                        __LINE__
1514
-                    );
1515
-                    return false;
1516
-                    break;
1517
-                case 'no_payment_required':
1518
-                    EE_Error::add_attention(
1519
-                        apply_filters(
1520
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__no_payment_required_msg',
1521
-                            esc_html__(
1522
-                                'It appears that the event you were about to make a payment for does not require payment. Please contact the event administrator if you believe this is an error.',
1523
-                                'event_espresso'
1524
-                            )
1525
-                        ),
1526
-                        __FILE__,
1527
-                        __FUNCTION__,
1528
-                        __LINE__
1529
-                    );
1530
-                    return false;
1531
-                    break;
1532
-                default:
1533
-            }
1534
-        }
1535
-        // verify payment method
1536
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1537
-            // get payment method for selected method of payment
1538
-            $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1539
-        }
1540
-        return $this->checkout->payment_method instanceof EE_Payment_Method ? true : false;
1541
-    }
1542
-
1543
-
1544
-
1545
-    /********************************************************************************************************/
1546
-    /***************************************  SAVE PAYER DETAILS  ****************************************/
1547
-    /********************************************************************************************************/
1548
-    /**
1549
-     * save_payer_details_via_ajax
1550
-     *
1551
-     * @return void
1552
-     * @throws EE_Error
1553
-     * @throws InvalidArgumentException
1554
-     * @throws ReflectionException
1555
-     * @throws RuntimeException
1556
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1557
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1558
-     */
1559
-    public function save_payer_details_via_ajax()
1560
-    {
1561
-        if (! $this->_verify_payment_method_is_set()) {
1562
-            return;
1563
-        }
1564
-        // generate billing form for selected method of payment if it hasn't been done already
1565
-        if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1566
-            $this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1567
-                $this->checkout->payment_method
1568
-            );
1569
-        }
1570
-        // generate primary attendee from payer info if applicable
1571
-        if (! $this->checkout->transaction_has_primary_registrant()) {
1572
-            $attendee = $this->_create_attendee_from_request_data();
1573
-            if ($attendee instanceof EE_Attendee) {
1574
-                foreach ($this->checkout->transaction->registrations() as $registration) {
1575
-                    if ($registration->is_primary_registrant()) {
1576
-                        $this->checkout->primary_attendee_obj = $attendee;
1577
-                        $registration->_add_relation_to($attendee, 'Attendee');
1578
-                        $registration->set_attendee_id($attendee->ID());
1579
-                        $registration->update_cache_after_object_save('Attendee', $attendee);
1580
-                    }
1581
-                }
1582
-            }
1583
-        }
1584
-    }
1585
-
1586
-
1587
-    /**
1588
-     * create_attendee_from_request_data
1589
-     * uses info from alternate GET or POST data (such as AJAX) to create a new attendee
1590
-     *
1591
-     * @return EE_Attendee
1592
-     * @throws EE_Error
1593
-     * @throws InvalidArgumentException
1594
-     * @throws ReflectionException
1595
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1596
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1597
-     */
1598
-    protected function _create_attendee_from_request_data()
1599
-    {
1600
-        // get State ID
1601
-        $STA_ID = ! empty($_REQUEST['state']) ? sanitize_text_field($_REQUEST['state']) : '';
1602
-        if (! empty($STA_ID)) {
1603
-            // can we get state object from name ?
1604
-            EE_Registry::instance()->load_model('State');
1605
-            $state = EEM_State::instance()->get_col(array(array('STA_name' => $STA_ID), 'limit' => 1), 'STA_ID');
1606
-            $STA_ID = is_array($state) && ! empty($state) ? reset($state) : $STA_ID;
1607
-        }
1608
-        // get Country ISO
1609
-        $CNT_ISO = ! empty($_REQUEST['country']) ? sanitize_text_field($_REQUEST['country']) : '';
1610
-        if (! empty($CNT_ISO)) {
1611
-            // can we get country object from name ?
1612
-            EE_Registry::instance()->load_model('Country');
1613
-            $country = EEM_Country::instance()->get_col(
1614
-                array(array('CNT_name' => $CNT_ISO), 'limit' => 1),
1615
-                'CNT_ISO'
1616
-            );
1617
-            $CNT_ISO = is_array($country) && ! empty($country) ? reset($country) : $CNT_ISO;
1618
-        }
1619
-        // grab attendee data
1620
-        $attendee_data = array(
1621
-            'ATT_fname'    => ! empty($_REQUEST['first_name']) ? sanitize_text_field($_REQUEST['first_name']) : '',
1622
-            'ATT_lname'    => ! empty($_REQUEST['last_name']) ? sanitize_text_field($_REQUEST['last_name']) : '',
1623
-            'ATT_email'    => ! empty($_REQUEST['email']) ? sanitize_email($_REQUEST['email']) : '',
1624
-            'ATT_address'  => ! empty($_REQUEST['address']) ? sanitize_text_field($_REQUEST['address']) : '',
1625
-            'ATT_address2' => ! empty($_REQUEST['address2']) ? sanitize_text_field($_REQUEST['address2']) : '',
1626
-            'ATT_city'     => ! empty($_REQUEST['city']) ? sanitize_text_field($_REQUEST['city']) : '',
1627
-            'STA_ID'       => $STA_ID,
1628
-            'CNT_ISO'      => $CNT_ISO,
1629
-            'ATT_zip'      => ! empty($_REQUEST['zip']) ? sanitize_text_field($_REQUEST['zip']) : '',
1630
-            'ATT_phone'    => ! empty($_REQUEST['phone']) ? sanitize_text_field($_REQUEST['phone']) : '',
1631
-        );
1632
-        // validate the email address since it is the most important piece of info
1633
-        if (empty($attendee_data['ATT_email']) || $attendee_data['ATT_email'] !== $_REQUEST['email']) {
1634
-            EE_Error::add_error(
1635
-                esc_html__('An invalid email address was submitted.', 'event_espresso'),
1636
-                __FILE__,
1637
-                __FUNCTION__,
1638
-                __LINE__
1639
-            );
1640
-        }
1641
-        // does this attendee already exist in the db ? we're searching using a combination of first name, last name,
1642
-        // AND email address
1643
-        if (
1644
-            ! empty($attendee_data['ATT_fname'])
1645
-            && ! empty($attendee_data['ATT_lname'])
1646
-            && ! empty($attendee_data['ATT_email'])
1647
-        ) {
1648
-            $existing_attendee = EE_Registry::instance()->LIB->EEM_Attendee->find_existing_attendee(
1649
-                array(
1650
-                    'ATT_fname' => $attendee_data['ATT_fname'],
1651
-                    'ATT_lname' => $attendee_data['ATT_lname'],
1652
-                    'ATT_email' => $attendee_data['ATT_email'],
1653
-                )
1654
-            );
1655
-            if ($existing_attendee instanceof EE_Attendee) {
1656
-                return $existing_attendee;
1657
-            }
1658
-        }
1659
-        // no existing attendee? kk let's create a new one
1660
-        // kinda lame, but we need a first and last name to create an attendee, so use the email address if those
1661
-        // don't exist
1662
-        $attendee_data['ATT_fname'] = ! empty($attendee_data['ATT_fname'])
1663
-            ? $attendee_data['ATT_fname']
1664
-            : $attendee_data['ATT_email'];
1665
-        $attendee_data['ATT_lname'] = ! empty($attendee_data['ATT_lname'])
1666
-            ? $attendee_data['ATT_lname']
1667
-            : $attendee_data['ATT_email'];
1668
-        return EE_Attendee::new_instance($attendee_data);
1669
-    }
1670
-
1671
-
1672
-
1673
-    /********************************************************************************************************/
1674
-    /****************************************  PROCESS REG STEP  *****************************************/
1675
-    /********************************************************************************************************/
1676
-    /**
1677
-     * process_reg_step
1678
-     *
1679
-     * @return bool
1680
-     * @throws EE_Error
1681
-     * @throws InvalidArgumentException
1682
-     * @throws ReflectionException
1683
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1684
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1685
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1686
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
1687
-     */
1688
-    public function process_reg_step()
1689
-    {
1690
-        // how have they chosen to pay?
1691
-        $this->checkout->selected_method_of_payment = $this->checkout->transaction->is_free()
1692
-            ? 'no_payment_required'
1693
-            : $this->_get_selected_method_of_payment(true);
1694
-        // choose your own adventure based on method_of_payment
1695
-        switch ($this->checkout->selected_method_of_payment) {
1696
-            case 'events_sold_out':
1697
-                $this->checkout->redirect = true;
1698
-                $this->checkout->redirect_url = $this->checkout->cancel_page_url;
1699
-                $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1700
-                // mark this reg step as completed
1701
-                $this->set_completed();
1702
-                return false;
1703
-                break;
1704
-
1705
-            case 'payments_closed':
1706
-                if (
1707
-                    apply_filters(
1708
-                        'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__payments_closed__display_success',
1709
-                        false
1710
-                    )
1711
-                ) {
1712
-                    EE_Error::add_success(
1713
-                        esc_html__('no payment required at this time.', 'event_espresso'),
1714
-                        __FILE__,
1715
-                        __FUNCTION__,
1716
-                        __LINE__
1717
-                    );
1718
-                }
1719
-                // mark this reg step as completed
1720
-                $this->set_completed();
1721
-                return true;
1722
-                break;
1723
-
1724
-            case 'no_payment_required':
1725
-                if (
1726
-                    apply_filters(
1727
-                        'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__no_payment_required__display_success',
1728
-                        false
1729
-                    )
1730
-                ) {
1731
-                    EE_Error::add_success(
1732
-                        esc_html__('no payment required.', 'event_espresso'),
1733
-                        __FILE__,
1734
-                        __FUNCTION__,
1735
-                        __LINE__
1736
-                    );
1737
-                }
1738
-                // mark this reg step as completed
1739
-                $this->set_completed();
1740
-                return true;
1741
-                break;
1742
-
1743
-            default:
1744
-                $registrations = EE_Registry::instance()->SSN->checkout()->transaction->registrations(
1745
-                    EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
1746
-                );
1747
-                $ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
1748
-                    $registrations,
1749
-                    EE_Registry::instance()->SSN->checkout()->revisit
1750
-                );
1751
-                // calculate difference between the two arrays
1752
-                $registrations = array_diff($registrations, $ejected_registrations);
1753
-                if (empty($registrations)) {
1754
-                    $this->_redirect_because_event_sold_out();
1755
-                    return false;
1756
-                }
1757
-                $payment_successful = $this->_process_payment();
1758
-                if ($payment_successful) {
1759
-                    $this->checkout->continue_reg = true;
1760
-                    $this->_maybe_set_completed($this->checkout->payment_method);
1761
-                } else {
1762
-                    $this->checkout->continue_reg = false;
1763
-                }
1764
-                return $payment_successful;
1765
-        }
1766
-    }
1767
-
1768
-
1769
-    /**
1770
-     * _redirect_because_event_sold_out
1771
-     *
1772
-     * @access protected
1773
-     * @return void
1774
-     */
1775
-    protected function _redirect_because_event_sold_out()
1776
-    {
1777
-        $this->checkout->continue_reg = false;
1778
-        // set redirect URL
1779
-        $this->checkout->redirect_url = add_query_arg(
1780
-            array('e_reg_url_link' => $this->checkout->reg_url_link),
1781
-            $this->checkout->current_step->reg_step_url()
1782
-        );
1783
-        $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1784
-    }
1785
-
1786
-
1787
-    /**
1788
-     * _maybe_set_completed
1789
-     *
1790
-     * @access protected
1791
-     * @param \EE_Payment_Method $payment_method
1792
-     * @return void
1793
-     * @throws \EE_Error
1794
-     */
1795
-    protected function _maybe_set_completed(EE_Payment_Method $payment_method)
1796
-    {
1797
-        switch ($payment_method->type_obj()->payment_occurs()) {
1798
-            case EE_PMT_Base::offsite:
1799
-                break;
1800
-            case EE_PMT_Base::onsite:
1801
-            case EE_PMT_Base::offline:
1802
-                // mark this reg step as completed
1803
-                $this->set_completed();
1804
-                break;
1805
-        }
1806
-    }
1807
-
1808
-
1809
-    /**
1810
-     *    update_reg_step
1811
-     *    this is the final step after a user  revisits the site to retry a payment
1812
-     *
1813
-     * @return bool
1814
-     * @throws EE_Error
1815
-     * @throws InvalidArgumentException
1816
-     * @throws ReflectionException
1817
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1818
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1819
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1820
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
1821
-     */
1822
-    public function update_reg_step()
1823
-    {
1824
-        $success = true;
1825
-        // if payment required
1826
-        if ($this->checkout->transaction->total() > 0) {
1827
-            do_action(
1828
-                'AHEE__EE_Single_Page_Checkout__process_finalize_registration__before_gateway',
1829
-                $this->checkout->transaction
1830
-            );
1831
-            // attempt payment via payment method
1832
-            $success = $this->process_reg_step();
1833
-        }
1834
-        if ($success && ! $this->checkout->redirect) {
1835
-            $this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn(
1836
-                $this->checkout->transaction->ID()
1837
-            );
1838
-            // set return URL
1839
-            $this->checkout->redirect_url = add_query_arg(
1840
-                array('e_reg_url_link' => $this->checkout->reg_url_link),
1841
-                $this->checkout->thank_you_page_url
1842
-            );
1843
-        }
1844
-        return $success;
1845
-    }
1846
-
1847
-
1848
-    /**
1849
-     *    _process_payment
1850
-     *
1851
-     * @access private
1852
-     * @return bool
1853
-     * @throws EE_Error
1854
-     * @throws InvalidArgumentException
1855
-     * @throws ReflectionException
1856
-     * @throws RuntimeException
1857
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1858
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1859
-     */
1860
-    private function _process_payment()
1861
-    {
1862
-        // basically confirm that the event hasn't sold out since they hit the page
1863
-        if (! $this->_last_second_ticket_verifications()) {
1864
-            return false;
1865
-        }
1866
-        // ya gotta make a choice man
1867
-        if (empty($this->checkout->selected_method_of_payment)) {
1868
-            $this->checkout->json_response->set_plz_select_method_of_payment(
1869
-                esc_html__('Please select a method of payment before proceeding.', 'event_espresso')
1870
-            );
1871
-            return false;
1872
-        }
1873
-        // get EE_Payment_Method object
1874
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1875
-            return false;
1876
-        }
1877
-        // setup billing form
1878
-        if ($this->checkout->payment_method->is_on_site()) {
1879
-            $this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1880
-                $this->checkout->payment_method
1881
-            );
1882
-            // bad billing form ?
1883
-            if (! $this->_billing_form_is_valid()) {
1884
-                return false;
1885
-            }
1886
-        }
1887
-        // ensure primary registrant has been fully processed
1888
-        if (! $this->_setup_primary_registrant_prior_to_payment()) {
1889
-            return false;
1890
-        }
1891
-        // if session is close to expiring (under 10 minutes by default)
1892
-        if ((time() - EE_Registry::instance()->SSN->expiration()) < EE_Registry::instance()->SSN->extension()) {
1893
-            // add some time to session expiration so that payment can be completed
1894
-            EE_Registry::instance()->SSN->extend_expiration();
1895
-        }
1896
-        /** @type EE_Transaction_Processor $transaction_processor */
1897
-        // $transaction_processor = EE_Registry::instance()->load_class( 'Transaction_Processor' );
1898
-        // in case a registrant leaves to an Off-Site Gateway and never returns, we want to approve any registrations
1899
-        // for events with a default reg status of Approved
1900
-        // $transaction_processor->toggle_registration_statuses_for_default_approved_events(
1901
-        //      $this->checkout->transaction, $this->checkout->reg_cache_where_params
1902
-        // );
1903
-        // attempt payment
1904
-        $payment = $this->_attempt_payment($this->checkout->payment_method);
1905
-        // process results
1906
-        $payment = $this->_validate_payment($payment);
1907
-        $payment = $this->_post_payment_processing($payment);
1908
-        // verify payment
1909
-        if ($payment instanceof EE_Payment) {
1910
-            // store that for later
1911
-            $this->checkout->payment = $payment;
1912
-            // we can also consider the TXN to not have been failed, so temporarily upgrade it's status to abandoned
1913
-            $this->checkout->transaction->toggle_failed_transaction_status();
1914
-            $payment_status = $payment->status();
1915
-            if (
1916
-                $payment_status === EEM_Payment::status_id_approved
1917
-                || $payment_status === EEM_Payment::status_id_pending
1918
-            ) {
1919
-                return true;
1920
-            } else {
1921
-                return false;
1922
-            }
1923
-        } elseif ($payment === true) {
1924
-            // please note that offline payment methods will NOT make a payment,
1925
-            // but instead just mark themselves as the PMD_ID on the transaction, and return true
1926
-            $this->checkout->payment = $payment;
1927
-            return true;
1928
-        }
1929
-        // where's my money?
1930
-        return false;
1931
-    }
1932
-
1933
-
1934
-    /**
1935
-     * _last_second_ticket_verifications
1936
-     *
1937
-     * @access public
1938
-     * @return bool
1939
-     * @throws EE_Error
1940
-     */
1941
-    protected function _last_second_ticket_verifications()
1942
-    {
1943
-        // don't bother re-validating if not a return visit
1944
-        if (! $this->checkout->revisit) {
1945
-            return true;
1946
-        }
1947
-        $registrations = $this->checkout->transaction->registrations();
1948
-        if (empty($registrations)) {
1949
-            return false;
1950
-        }
1951
-        foreach ($registrations as $registration) {
1952
-            if ($registration instanceof EE_Registration && ! $registration->is_approved()) {
1953
-                $event = $registration->event_obj();
1954
-                if ($event instanceof EE_Event && $event->is_sold_out(true)) {
1955
-                    EE_Error::add_error(
1956
-                        apply_filters(
1957
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___last_second_ticket_verifications__sold_out_events_msg',
1958
-                            sprintf(
1959
-                                esc_html__(
1960
-                                    'It appears that the %1$s event that you were about to make a payment for has sold out since you first registered and/or arrived at this page. Please refresh the page and try again. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
1961
-                                    'event_espresso'
1962
-                                ),
1963
-                                $event->name()
1964
-                            )
1965
-                        ),
1966
-                        __FILE__,
1967
-                        __FUNCTION__,
1968
-                        __LINE__
1969
-                    );
1970
-                    return false;
1971
-                }
1972
-            }
1973
-        }
1974
-        return true;
1975
-    }
1976
-
1977
-
1978
-    /**
1979
-     * redirect_form
1980
-     *
1981
-     * @access public
1982
-     * @return bool
1983
-     * @throws EE_Error
1984
-     * @throws InvalidArgumentException
1985
-     * @throws ReflectionException
1986
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1987
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1988
-     */
1989
-    public function redirect_form()
1990
-    {
1991
-        $payment_method_billing_info = $this->_payment_method_billing_info(
1992
-            $this->_get_payment_method_for_selected_method_of_payment()
1993
-        );
1994
-        $html = $payment_method_billing_info->get_html();
1995
-        $html .= $this->checkout->redirect_form;
1996
-        EE_Registry::instance()->REQ->add_output($html);
1997
-        return true;
1998
-    }
1999
-
2000
-
2001
-    /**
2002
-     * _billing_form_is_valid
2003
-     *
2004
-     * @access private
2005
-     * @return bool
2006
-     * @throws \EE_Error
2007
-     */
2008
-    private function _billing_form_is_valid()
2009
-    {
2010
-        if (! $this->checkout->payment_method->type_obj()->has_billing_form()) {
2011
-            return true;
2012
-        }
2013
-        if ($this->checkout->billing_form instanceof EE_Billing_Info_Form) {
2014
-            if ($this->checkout->billing_form->was_submitted()) {
2015
-                $this->checkout->billing_form->receive_form_submission();
2016
-                if ($this->checkout->billing_form->is_valid()) {
2017
-                    return true;
2018
-                }
2019
-                $validation_errors = $this->checkout->billing_form->get_validation_errors_accumulated();
2020
-                $error_strings = array();
2021
-                foreach ($validation_errors as $validation_error) {
2022
-                    if ($validation_error instanceof EE_Validation_Error) {
2023
-                        $form_section = $validation_error->get_form_section();
2024
-                        if ($form_section instanceof EE_Form_Input_Base) {
2025
-                            $label = $form_section->html_label_text();
2026
-                        } elseif ($form_section instanceof EE_Form_Section_Base) {
2027
-                            $label = $form_section->name();
2028
-                        } else {
2029
-                            $label = esc_html__('Validation Error', 'event_espresso');
2030
-                        }
2031
-                        $error_strings[] = sprintf('%1$s: %2$s', $label, $validation_error->getMessage());
2032
-                    }
2033
-                }
2034
-                EE_Error::add_error(
2035
-                    sprintf(
2036
-                        esc_html__(
2037
-                            'One or more billing form inputs are invalid and require correction before proceeding. %1$s %2$s',
2038
-                            'event_espresso'
2039
-                        ),
2040
-                        '<br/>',
2041
-                        implode('<br/>', $error_strings)
2042
-                    ),
2043
-                    __FILE__,
2044
-                    __FUNCTION__,
2045
-                    __LINE__
2046
-                );
2047
-            } else {
2048
-                EE_Error::add_error(
2049
-                    esc_html__(
2050
-                        'The billing form was not submitted or something prevented it\'s submission.',
2051
-                        'event_espresso'
2052
-                    ),
2053
-                    __FILE__,
2054
-                    __FUNCTION__,
2055
-                    __LINE__
2056
-                );
2057
-            }
2058
-        } else {
2059
-            EE_Error::add_error(
2060
-                esc_html__(
2061
-                    'The submitted billing form is invalid possibly due to a technical reason.',
2062
-                    'event_espresso'
2063
-                ),
2064
-                __FILE__,
2065
-                __FUNCTION__,
2066
-                __LINE__
2067
-            );
2068
-        }
2069
-        return false;
2070
-    }
2071
-
2072
-
2073
-    /**
2074
-     * _setup_primary_registrant_prior_to_payment
2075
-     * ensures that the primary registrant has a valid attendee object created with the critical details populated
2076
-     * (first & last name & email) and that both the transaction object and primary registration object have been saved
2077
-     * plz note that any other registrations will NOT be saved at this point (because they may not have any details
2078
-     * yet)
2079
-     *
2080
-     * @access private
2081
-     * @return bool
2082
-     * @throws EE_Error
2083
-     * @throws InvalidArgumentException
2084
-     * @throws ReflectionException
2085
-     * @throws RuntimeException
2086
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2087
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2088
-     */
2089
-    private function _setup_primary_registrant_prior_to_payment()
2090
-    {
2091
-        // check if transaction has a primary registrant and that it has a related Attendee object
2092
-        // if not, then we need to at least gather some primary registrant data before attempting payment
2093
-        if (
2094
-            $this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
2095
-            && ! $this->checkout->transaction_has_primary_registrant()
2096
-            && ! $this->_capture_primary_registration_data_from_billing_form()
2097
-        ) {
2098
-            return false;
2099
-        }
2100
-        // because saving an object clears it's cache, we need to do the chevy shuffle
2101
-        // grab the primary_registration object
2102
-        $primary_registration = $this->checkout->transaction->primary_registration();
2103
-        // at this point we'll consider a TXN to not have been failed
2104
-        $this->checkout->transaction->toggle_failed_transaction_status();
2105
-        // save the TXN ( which clears cached copy of primary_registration)
2106
-        $this->checkout->transaction->save();
2107
-        // grab TXN ID and save it to the primary_registration
2108
-        $primary_registration->set_transaction_id($this->checkout->transaction->ID());
2109
-        // save what we have so far
2110
-        $primary_registration->save();
2111
-        return true;
2112
-    }
2113
-
2114
-
2115
-    /**
2116
-     * _capture_primary_registration_data_from_billing_form
2117
-     *
2118
-     * @access private
2119
-     * @return bool
2120
-     * @throws EE_Error
2121
-     * @throws InvalidArgumentException
2122
-     * @throws ReflectionException
2123
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2124
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2125
-     */
2126
-    private function _capture_primary_registration_data_from_billing_form()
2127
-    {
2128
-        // convert billing form data into an attendee
2129
-        $this->checkout->primary_attendee_obj = $this->checkout->billing_form->create_attendee_from_billing_form_data();
2130
-        if (! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2131
-            EE_Error::add_error(
2132
-                sprintf(
2133
-                    esc_html__(
2134
-                        'The billing form details could not be used for attendee details due to a technical issue.%sPlease try again or contact %s for assistance.',
2135
-                        'event_espresso'
2136
-                    ),
2137
-                    '<br/>',
2138
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2139
-                ),
2140
-                __FILE__,
2141
-                __FUNCTION__,
2142
-                __LINE__
2143
-            );
2144
-            return false;
2145
-        }
2146
-        $primary_registration = $this->checkout->transaction->primary_registration();
2147
-        if (! $primary_registration instanceof EE_Registration) {
2148
-            EE_Error::add_error(
2149
-                sprintf(
2150
-                    esc_html__(
2151
-                        'The primary registrant for this transaction could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2152
-                        'event_espresso'
2153
-                    ),
2154
-                    '<br/>',
2155
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2156
-                ),
2157
-                __FILE__,
2158
-                __FUNCTION__,
2159
-                __LINE__
2160
-            );
2161
-            return false;
2162
-        }
2163
-        if (
2164
-            ! $primary_registration->_add_relation_to($this->checkout->primary_attendee_obj, 'Attendee')
2165
-              instanceof
2166
-              EE_Attendee
2167
-        ) {
2168
-            EE_Error::add_error(
2169
-                sprintf(
2170
-                    esc_html__(
2171
-                        'The primary registrant could not be associated with this transaction due to a technical issue.%sPlease try again or contact %s for assistance.',
2172
-                        'event_espresso'
2173
-                    ),
2174
-                    '<br/>',
2175
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2176
-                ),
2177
-                __FILE__,
2178
-                __FUNCTION__,
2179
-                __LINE__
2180
-            );
2181
-            return false;
2182
-        }
2183
-        /** @type EE_Registration_Processor $registration_processor */
2184
-        $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
2185
-        // at this point, we should have enough details about the registrant to consider the registration NOT incomplete
2186
-        $registration_processor->toggle_incomplete_registration_status_to_default($primary_registration);
2187
-        return true;
2188
-    }
2189
-
2190
-
2191
-    /**
2192
-     * _get_payment_method_for_selected_method_of_payment
2193
-     * retrieves a valid payment method
2194
-     *
2195
-     * @access public
2196
-     * @return EE_Payment_Method
2197
-     * @throws EE_Error
2198
-     * @throws InvalidArgumentException
2199
-     * @throws ReflectionException
2200
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2201
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2202
-     */
2203
-    private function _get_payment_method_for_selected_method_of_payment()
2204
-    {
2205
-        if ($this->checkout->selected_method_of_payment === 'events_sold_out') {
2206
-            $this->_redirect_because_event_sold_out();
2207
-            return null;
2208
-        }
2209
-        // get EE_Payment_Method object
2210
-        if (isset($this->checkout->available_payment_methods[ $this->checkout->selected_method_of_payment ])) {
2211
-            $payment_method = $this->checkout->available_payment_methods[ $this->checkout->selected_method_of_payment ];
2212
-        } else {
2213
-            // load EEM_Payment_Method
2214
-            EE_Registry::instance()->load_model('Payment_Method');
2215
-            /** @type EEM_Payment_Method $EEM_Payment_Method */
2216
-            $EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
2217
-            $payment_method = $EEM_Payment_Method->get_one_by_slug($this->checkout->selected_method_of_payment);
2218
-        }
2219
-        // verify $payment_method
2220
-        if (! $payment_method instanceof EE_Payment_Method) {
2221
-            // not a payment
2222
-            EE_Error::add_error(
2223
-                sprintf(
2224
-                    esc_html__(
2225
-                        'The selected method of payment could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2226
-                        'event_espresso'
2227
-                    ),
2228
-                    '<br/>',
2229
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2230
-                ),
2231
-                __FILE__,
2232
-                __FUNCTION__,
2233
-                __LINE__
2234
-            );
2235
-            return null;
2236
-        }
2237
-        // and verify it has a valid Payment_Method Type object
2238
-        if (! $payment_method->type_obj() instanceof EE_PMT_Base) {
2239
-            // not a payment
2240
-            EE_Error::add_error(
2241
-                sprintf(
2242
-                    esc_html__(
2243
-                        'A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2244
-                        'event_espresso'
2245
-                    ),
2246
-                    '<br/>',
2247
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2248
-                ),
2249
-                __FILE__,
2250
-                __FUNCTION__,
2251
-                __LINE__
2252
-            );
2253
-            return null;
2254
-        }
2255
-        return $payment_method;
2256
-    }
2257
-
2258
-
2259
-    /**
2260
-     *    _attempt_payment
2261
-     *
2262
-     * @access    private
2263
-     * @type    EE_Payment_Method $payment_method
2264
-     * @return mixed EE_Payment | boolean
2265
-     * @throws EE_Error
2266
-     * @throws InvalidArgumentException
2267
-     * @throws ReflectionException
2268
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2269
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2270
-     */
2271
-    private function _attempt_payment(EE_Payment_Method $payment_method)
2272
-    {
2273
-        $payment = null;
2274
-        $this->checkout->transaction->save();
2275
-        $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2276
-        if (! $payment_processor instanceof EE_Payment_Processor) {
2277
-            return false;
2278
-        }
2279
-        try {
2280
-            $payment_processor->set_revisit($this->checkout->revisit);
2281
-            // generate payment object
2282
-            $payment = $payment_processor->process_payment(
2283
-                $payment_method,
2284
-                $this->checkout->transaction,
2285
-                $this->checkout->amount_owing,
2286
-                $this->checkout->billing_form,
2287
-                $this->_get_return_url($payment_method),
2288
-                'CART',
2289
-                $this->checkout->admin_request,
2290
-                true,
2291
-                $this->reg_step_url()
2292
-            );
2293
-        } catch (Exception $e) {
2294
-            $this->_handle_payment_processor_exception($e);
2295
-        }
2296
-        return $payment;
2297
-    }
2298
-
2299
-
2300
-    /**
2301
-     * _handle_payment_processor_exception
2302
-     *
2303
-     * @access protected
2304
-     * @param \Exception $e
2305
-     * @return void
2306
-     * @throws EE_Error
2307
-     * @throws InvalidArgumentException
2308
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2309
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2310
-     */
2311
-    protected function _handle_payment_processor_exception(Exception $e)
2312
-    {
2313
-        EE_Error::add_error(
2314
-            sprintf(
2315
-                esc_html__(
2316
-                    'The payment could not br processed due to a technical issue.%1$sPlease try again or contact %2$s for assistance.||The following Exception was thrown in %4$s on line %5$s:%1$s%3$s',
2317
-                    'event_espresso'
2318
-                ),
2319
-                '<br/>',
2320
-                EE_Registry::instance()->CFG->organization->get_pretty('email'),
2321
-                $e->getMessage(),
2322
-                $e->getFile(),
2323
-                $e->getLine()
2324
-            ),
2325
-            __FILE__,
2326
-            __FUNCTION__,
2327
-            __LINE__
2328
-        );
2329
-    }
2330
-
2331
-
2332
-    /**
2333
-     * _get_return_url
2334
-     *
2335
-     * @access protected
2336
-     * @param \EE_Payment_Method $payment_method
2337
-     * @return string
2338
-     * @throws \EE_Error
2339
-     */
2340
-    protected function _get_return_url(EE_Payment_Method $payment_method)
2341
-    {
2342
-        $return_url = '';
2343
-        switch ($payment_method->type_obj()->payment_occurs()) {
2344
-            case EE_PMT_Base::offsite:
2345
-                $return_url = add_query_arg(
2346
-                    array(
2347
-                        'action'                     => 'process_gateway_response',
2348
-                        'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2349
-                        'spco_txn'                   => $this->checkout->transaction->ID(),
2350
-                    ),
2351
-                    $this->reg_step_url()
2352
-                );
2353
-                break;
2354
-            case EE_PMT_Base::onsite:
2355
-            case EE_PMT_Base::offline:
2356
-                $return_url = $this->checkout->next_step->reg_step_url();
2357
-                break;
2358
-        }
2359
-        return $return_url;
2360
-    }
2361
-
2362
-
2363
-    /**
2364
-     * _validate_payment
2365
-     *
2366
-     * @access private
2367
-     * @param EE_Payment $payment
2368
-     * @return EE_Payment|FALSE
2369
-     * @throws EE_Error
2370
-     * @throws InvalidArgumentException
2371
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2372
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2373
-     */
2374
-    private function _validate_payment($payment = null)
2375
-    {
2376
-        if ($this->checkout->payment_method->is_off_line()) {
2377
-            return true;
2378
-        }
2379
-        // verify payment object
2380
-        if (! $payment instanceof EE_Payment) {
2381
-            // not a payment
2382
-            EE_Error::add_error(
2383
-                sprintf(
2384
-                    esc_html__(
2385
-                        'A valid payment was not generated due to a technical issue.%1$sPlease try again or contact %2$s for assistance.',
2386
-                        'event_espresso'
2387
-                    ),
2388
-                    '<br/>',
2389
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2390
-                ),
2391
-                __FILE__,
2392
-                __FUNCTION__,
2393
-                __LINE__
2394
-            );
2395
-            return false;
2396
-        }
2397
-        return $payment;
2398
-    }
2399
-
2400
-
2401
-    /**
2402
-     * _post_payment_processing
2403
-     *
2404
-     * @access private
2405
-     * @param EE_Payment|bool $payment
2406
-     * @return bool
2407
-     * @throws EE_Error
2408
-     * @throws InvalidArgumentException
2409
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2410
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2411
-     */
2412
-    private function _post_payment_processing($payment = null)
2413
-    {
2414
-        // Off-Line payment?
2415
-        if ($payment === true) {
2416
-            // $this->_setup_redirect_for_next_step();
2417
-            return true;
2418
-            // On-Site payment?
2419
-        } elseif ($this->checkout->payment_method->is_on_site()) {
2420
-            if (! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2421
-                // $this->_setup_redirect_for_next_step();
2422
-                $this->checkout->continue_reg = false;
2423
-            }
2424
-            // Off-Site payment?
2425
-        } elseif ($this->checkout->payment_method->is_off_site()) {
2426
-            // if a payment object was made and it specifies a redirect url, then we'll setup that redirect info
2427
-            if ($payment instanceof EE_Payment && $payment->redirect_url()) {
2428
-                do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->redirect_url(), '$payment->redirect_url()');
2429
-                $this->checkout->redirect = true;
2430
-                $this->checkout->redirect_form = $payment->redirect_form();
2431
-                $this->checkout->redirect_url = $this->reg_step_url('redirect_form');
2432
-                // set JSON response
2433
-                $this->checkout->json_response->set_redirect_form($this->checkout->redirect_form);
2434
-                // and lastly, let's bump the payment status to pending
2435
-                $payment->set_status(EEM_Payment::status_id_pending);
2436
-                $payment->save();
2437
-            } else {
2438
-                // we couldn't redirect the user. Let's tell them why.
2439
-                $error_message = sprintf(
2440
-                    esc_html__(
2441
-                        'It appears the Off Site Payment Method was not configured properly.%sPlease try again or contact %s for assistance.',
2442
-                        'event_espresso'
2443
-                    ),
2444
-                    '<br/>',
2445
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2446
-                );
2447
-                if ($payment instanceof EE_Payment && $payment->gateway_response()) {
2448
-                    $error_message = $error_message . '<br/>' . $payment->gateway_response();
2449
-                }
2450
-                $this->checkout->continue_reg = false;
2451
-                EE_Error::add_error(
2452
-                    $error_message,
2453
-                    __FILE__,
2454
-                    __FUNCTION__,
2455
-                    __LINE__
2456
-                );
2457
-            }
2458
-        } else {
2459
-            // ummm ya... not Off-Line, not On-Site, not off-Site ????
2460
-            $this->checkout->continue_reg = false;
2461
-            return false;
2462
-        }
2463
-        return $payment;
2464
-    }
2465
-
2466
-
2467
-    /**
2468
-     *    _process_payment_status
2469
-     *
2470
-     * @access private
2471
-     * @type    EE_Payment $payment
2472
-     * @param string       $payment_occurs
2473
-     * @return bool
2474
-     * @throws EE_Error
2475
-     * @throws InvalidArgumentException
2476
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2477
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2478
-     */
2479
-    private function _process_payment_status($payment, $payment_occurs = EE_PMT_Base::offline)
2480
-    {
2481
-        // off-line payment? carry on
2482
-        if ($payment_occurs === EE_PMT_Base::offline) {
2483
-            return true;
2484
-        }
2485
-        // verify payment validity
2486
-        if ($payment instanceof EE_Payment) {
2487
-            do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->status(), '$payment->status()');
2488
-            $msg = $payment->gateway_response();
2489
-            // check results
2490
-            switch ($payment->status()) {
2491
-                // good payment
2492
-                case EEM_Payment::status_id_approved:
2493
-                    EE_Error::add_success(
2494
-                        esc_html__('Your payment was processed successfully.', 'event_espresso'),
2495
-                        __FILE__,
2496
-                        __FUNCTION__,
2497
-                        __LINE__
2498
-                    );
2499
-                    return true;
2500
-                    break;
2501
-                // slow payment
2502
-                case EEM_Payment::status_id_pending:
2503
-                    if (empty($msg)) {
2504
-                        $msg = esc_html__(
2505
-                            'Your payment appears to have been processed successfully, but the Instant Payment Notification has not yet been received. It should arrive shortly.',
2506
-                            'event_espresso'
2507
-                        );
2508
-                    }
2509
-                    EE_Error::add_success($msg, __FILE__, __FUNCTION__, __LINE__);
2510
-                    return true;
2511
-                    break;
2512
-                // don't wanna payment
2513
-                case EEM_Payment::status_id_cancelled:
2514
-                    if (empty($msg)) {
2515
-                        $msg = _n(
2516
-                            'Payment cancelled. Please try again.',
2517
-                            'Payment cancelled. Please try again or select another method of payment.',
2518
-                            count($this->checkout->available_payment_methods),
2519
-                            'event_espresso'
2520
-                        );
2521
-                    }
2522
-                    EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2523
-                    return false;
2524
-                    break;
2525
-                // not enough payment
2526
-                case EEM_Payment::status_id_declined:
2527
-                    if (empty($msg)) {
2528
-                        $msg = _n(
2529
-                            'We\'re sorry but your payment was declined. Please try again.',
2530
-                            'We\'re sorry but your payment was declined. Please try again or select another method of payment.',
2531
-                            count($this->checkout->available_payment_methods),
2532
-                            'event_espresso'
2533
-                        );
2534
-                    }
2535
-                    EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2536
-                    return false;
2537
-                    break;
2538
-                // bad payment
2539
-                case EEM_Payment::status_id_failed:
2540
-                    if (! empty($msg)) {
2541
-                        EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2542
-                        return false;
2543
-                    }
2544
-                    // default to error below
2545
-                    break;
2546
-            }
2547
-        }
2548
-        // off-site payment gateway responses are too unreliable, so let's just assume that
2549
-        // the payment processing is just running slower than the registrant's request
2550
-        if ($payment_occurs === EE_PMT_Base::offsite) {
2551
-            return true;
2552
-        }
2553
-        EE_Error::add_error(
2554
-            sprintf(
2555
-                esc_html__(
2556
-                    'Your payment could not be processed successfully due to a technical issue.%sPlease try again or contact %s for assistance.',
2557
-                    'event_espresso'
2558
-                ),
2559
-                '<br/>',
2560
-                EE_Registry::instance()->CFG->organization->get_pretty('email')
2561
-            ),
2562
-            __FILE__,
2563
-            __FUNCTION__,
2564
-            __LINE__
2565
-        );
2566
-        return false;
2567
-    }
2568
-
2569
-
2570
-
2571
-
2572
-
2573
-
2574
-    /********************************************************************************************************/
2575
-    /**********************************  PROCESS GATEWAY RESPONSE  **********************************/
2576
-    /********************************************************************************************************/
2577
-    /**
2578
-     * process_gateway_response
2579
-     * this is the return point for Off-Site Payment Methods
2580
-     * It will attempt to "handle the IPN" if it appears that this has not already occurred,
2581
-     * otherwise, it will load up the last payment made for the TXN.
2582
-     * If the payment retrieved looks good, it will then either:
2583
-     *    complete the current step and allow advancement to the next reg step
2584
-     *        or present the payment options again
2585
-     *
2586
-     * @access private
2587
-     * @return EE_Payment|FALSE
2588
-     * @throws EE_Error
2589
-     * @throws InvalidArgumentException
2590
-     * @throws ReflectionException
2591
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2592
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2593
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2594
-     */
2595
-    public function process_gateway_response()
2596
-    {
2597
-        $payment = null;
2598
-        // how have they chosen to pay?
2599
-        $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
2600
-        // get EE_Payment_Method object
2601
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2602
-            $this->checkout->continue_reg = false;
2603
-            return false;
2604
-        }
2605
-        if (! $this->checkout->payment_method->is_off_site()) {
2606
-            return false;
2607
-        }
2608
-        $this->_validate_offsite_return();
2609
-        // DEBUG LOG
2610
-        // $this->checkout->log(
2611
-        //     __CLASS__,
2612
-        //     __FUNCTION__,
2613
-        //     __LINE__,
2614
-        //     array(
2615
-        //         'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2616
-        //         'payment_method'             => $this->checkout->payment_method,
2617
-        //     ),
2618
-        //     true
2619
-        // );
2620
-        // verify TXN
2621
-        if ($this->checkout->transaction instanceof EE_Transaction) {
2622
-            $gateway = $this->checkout->payment_method->type_obj()->get_gateway();
2623
-            if (! $gateway instanceof EE_Offsite_Gateway) {
2624
-                $this->checkout->continue_reg = false;
2625
-                return false;
2626
-            }
2627
-            $payment = $this->_process_off_site_payment($gateway);
2628
-            $payment = $this->_process_cancelled_payments($payment);
2629
-            $payment = $this->_validate_payment($payment);
2630
-            // if payment was not declined by the payment gateway or cancelled by the registrant
2631
-            if ($this->_process_payment_status($payment, EE_PMT_Base::offsite)) {
2632
-                // $this->_setup_redirect_for_next_step();
2633
-                // store that for later
2634
-                $this->checkout->payment = $payment;
2635
-                // mark this reg step as completed, as long as gateway doesn't use a separate IPN request,
2636
-                // because we will complete this step during the IPN processing then
2637
-                if ($gateway instanceof EE_Offsite_Gateway && ! $this->handle_IPN_in_this_request()) {
2638
-                    $this->set_completed();
2639
-                }
2640
-                return true;
2641
-            }
2642
-        }
2643
-        // DEBUG LOG
2644
-        // $this->checkout->log(
2645
-        //     __CLASS__,
2646
-        //     __FUNCTION__,
2647
-        //     __LINE__,
2648
-        //     array('payment' => $payment)
2649
-        // );
2650
-        $this->checkout->continue_reg = false;
2651
-        return false;
2652
-    }
2653
-
2654
-
2655
-    /**
2656
-     * _validate_return
2657
-     *
2658
-     * @access private
2659
-     * @return void
2660
-     * @throws EE_Error
2661
-     * @throws InvalidArgumentException
2662
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2663
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2664
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2665
-     */
2666
-    private function _validate_offsite_return()
2667
-    {
2668
-        $TXN_ID = (int) EE_Registry::instance()->REQ->get('spco_txn', 0);
2669
-        if ($TXN_ID !== $this->checkout->transaction->ID()) {
2670
-            // Houston... we might have a problem
2671
-            $invalid_TXN = false;
2672
-            // first gather some info
2673
-            $valid_TXN = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2674
-            $primary_registrant = $valid_TXN instanceof EE_Transaction
2675
-                ? $valid_TXN->primary_registration()
2676
-                : null;
2677
-            // let's start by retrieving the cart for this TXN
2678
-            $cart = $this->checkout->get_cart_for_transaction($this->checkout->transaction);
2679
-            if ($cart instanceof EE_Cart) {
2680
-                // verify that the current cart has tickets
2681
-                $tickets = $cart->get_tickets();
2682
-                if (empty($tickets)) {
2683
-                    $invalid_TXN = true;
2684
-                }
2685
-            } else {
2686
-                $invalid_TXN = true;
2687
-            }
2688
-            $valid_TXN_SID = $primary_registrant instanceof EE_Registration
2689
-                ? $primary_registrant->session_ID()
2690
-                : null;
2691
-            // validate current Session ID and compare against valid TXN session ID
2692
-            if (
2693
-                $invalid_TXN // if this is already true, then skip other checks
2694
-                || EE_Session::instance()->id() === null
2695
-                || (
2696
-                    // WARNING !!!
2697
-                    // this could be PayPal sending back duplicate requests (ya they do that)
2698
-                    // or it **could** mean someone is simply registering AGAIN after having just done so
2699
-                    // so now we need to determine if this current TXN looks valid or not
2700
-                    // and whether this reg step has even been started ?
2701
-                    EE_Session::instance()->id() === $valid_TXN_SID
2702
-                    // really? you're half way through this reg step, but you never started it ?
2703
-                    && $this->checkout->transaction->reg_step_completed($this->slug()) === false
2704
-                )
2705
-            ) {
2706
-                $invalid_TXN = true;
2707
-            }
2708
-            if ($invalid_TXN) {
2709
-                // is the valid TXN completed ?
2710
-                if ($valid_TXN instanceof EE_Transaction) {
2711
-                    // has this step even been started ?
2712
-                    $reg_step_completed = $valid_TXN->reg_step_completed($this->slug());
2713
-                    if ($reg_step_completed !== false && $reg_step_completed !== true) {
2714
-                        // so it **looks** like this is a double request from PayPal
2715
-                        // so let's try to pick up where we left off
2716
-                        $this->checkout->transaction = $valid_TXN;
2717
-                        $this->checkout->refresh_all_entities(true);
2718
-                        return;
2719
-                    }
2720
-                }
2721
-                // you appear to be lost?
2722
-                $this->_redirect_wayward_request($primary_registrant);
2723
-            }
2724
-        }
2725
-    }
2726
-
2727
-
2728
-    /**
2729
-     * _redirect_wayward_request
2730
-     *
2731
-     * @access private
2732
-     * @param \EE_Registration|null $primary_registrant
2733
-     * @return bool
2734
-     * @throws EE_Error
2735
-     * @throws InvalidArgumentException
2736
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2737
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2738
-     */
2739
-    private function _redirect_wayward_request(EE_Registration $primary_registrant)
2740
-    {
2741
-        if (! $primary_registrant instanceof EE_Registration) {
2742
-            // try redirecting based on the current TXN
2743
-            $primary_registrant = $this->checkout->transaction instanceof EE_Transaction
2744
-                ? $this->checkout->transaction->primary_registration()
2745
-                : null;
2746
-        }
2747
-        if (! $primary_registrant instanceof EE_Registration) {
2748
-            EE_Error::add_error(
2749
-                sprintf(
2750
-                    esc_html__(
2751
-                        'Invalid information was received from the Off-Site Payment Processor and your Transaction details could not be retrieved from the database.%1$sPlease try again or contact %2$s for assistance.',
2752
-                        'event_espresso'
2753
-                    ),
2754
-                    '<br/>',
2755
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2756
-                ),
2757
-                __FILE__,
2758
-                __FUNCTION__,
2759
-                __LINE__
2760
-            );
2761
-            return false;
2762
-        }
2763
-        // make sure transaction is not locked
2764
-        $this->checkout->transaction->unlock();
2765
-        wp_safe_redirect(
2766
-            add_query_arg(
2767
-                array(
2768
-                    'e_reg_url_link' => $primary_registrant->reg_url_link(),
2769
-                ),
2770
-                $this->checkout->thank_you_page_url
2771
-            )
2772
-        );
2773
-        exit();
2774
-    }
2775
-
2776
-
2777
-    /**
2778
-     * _process_off_site_payment
2779
-     *
2780
-     * @access private
2781
-     * @param \EE_Offsite_Gateway $gateway
2782
-     * @return EE_Payment
2783
-     * @throws EE_Error
2784
-     * @throws InvalidArgumentException
2785
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2786
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2787
-     */
2788
-    private function _process_off_site_payment(EE_Offsite_Gateway $gateway)
2789
-    {
2790
-        try {
2791
-            $request_data = \EE_Registry::instance()->REQ->params();
2792
-            // if gateway uses_separate_IPN_request, then we don't have to process the IPN manually
2793
-            $this->set_handle_IPN_in_this_request(
2794
-                $gateway->handle_IPN_in_this_request($request_data, false)
2795
-            );
2796
-            if ($this->handle_IPN_in_this_request()) {
2797
-                // get payment details and process results
2798
-                /** @type EE_Payment_Processor $payment_processor */
2799
-                $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2800
-                $payment = $payment_processor->process_ipn(
2801
-                    $request_data,
2802
-                    $this->checkout->transaction,
2803
-                    $this->checkout->payment_method,
2804
-                    true,
2805
-                    false
2806
-                );
2807
-                // $payment_source = 'process_ipn';
2808
-            } else {
2809
-                $payment = $this->checkout->transaction->last_payment();
2810
-                // $payment_source = 'last_payment';
2811
-            }
2812
-        } catch (Exception $e) {
2813
-            // let's just eat the exception and try to move on using any previously set payment info
2814
-            $payment = $this->checkout->transaction->last_payment();
2815
-            // $payment_source = 'last_payment after Exception';
2816
-            // but if we STILL don't have a payment object
2817
-            if (! $payment instanceof EE_Payment) {
2818
-                // then we'll object ! ( not object like a thing... but object like what a lawyer says ! )
2819
-                $this->_handle_payment_processor_exception($e);
2820
-            }
2821
-        }
2822
-        // DEBUG LOG
2823
-        // $this->checkout->log(
2824
-        //     __CLASS__,
2825
-        //     __FUNCTION__,
2826
-        //     __LINE__,
2827
-        //     array(
2828
-        //         'process_ipn_payment' => $payment,
2829
-        //         'payment_source'      => $payment_source,
2830
-        //     )
2831
-        // );
2832
-        return $payment;
2833
-    }
2834
-
2835
-
2836
-    /**
2837
-     * _process_cancelled_payments
2838
-     * just makes sure that the payment status gets updated correctly
2839
-     * so tha tan error isn't generated during payment validation
2840
-     *
2841
-     * @access private
2842
-     * @param EE_Payment $payment
2843
-     * @return EE_Payment | FALSE
2844
-     * @throws \EE_Error
2845
-     */
2846
-    private function _process_cancelled_payments($payment = null)
2847
-    {
2848
-        if (
2849
-            $payment instanceof EE_Payment
2850
-            && isset($_REQUEST['ee_cancel_payment'])
2851
-            && $payment->status() === EEM_Payment::status_id_failed
2852
-        ) {
2853
-            $payment->set_status(EEM_Payment::status_id_cancelled);
2854
-        }
2855
-        return $payment;
2856
-    }
2857
-
2858
-
2859
-    /**
2860
-     *    get_transaction_details_for_gateways
2861
-     *
2862
-     * @access    public
2863
-     * @return int
2864
-     * @throws EE_Error
2865
-     * @throws InvalidArgumentException
2866
-     * @throws ReflectionException
2867
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2868
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2869
-     */
2870
-    public function get_transaction_details_for_gateways()
2871
-    {
2872
-        $txn_details = array();
2873
-        // ya gotta make a choice man
2874
-        if (empty($this->checkout->selected_method_of_payment)) {
2875
-            $txn_details = array(
2876
-                'error' => esc_html__('Please select a method of payment before proceeding.', 'event_espresso'),
2877
-            );
2878
-        }
2879
-        // get EE_Payment_Method object
2880
-        if (
2881
-            empty($txn_details)
2882
-            &&
2883
-            ! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()
2884
-        ) {
2885
-            $txn_details = array(
2886
-                'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2887
-                'error'                      => esc_html__(
2888
-                    'A valid Payment Method could not be determined.',
2889
-                    'event_espresso'
2890
-                ),
2891
-            );
2892
-        }
2893
-        if (empty($txn_details) && $this->checkout->transaction instanceof EE_Transaction) {
2894
-            $return_url = $this->_get_return_url($this->checkout->payment_method);
2895
-            $txn_details = array(
2896
-                'TXN_ID'         => $this->checkout->transaction->ID(),
2897
-                'TXN_timestamp'  => $this->checkout->transaction->datetime(),
2898
-                'TXN_total'      => $this->checkout->transaction->total(),
2899
-                'TXN_paid'       => $this->checkout->transaction->paid(),
2900
-                'TXN_reg_steps'  => $this->checkout->transaction->reg_steps(),
2901
-                'STS_ID'         => $this->checkout->transaction->status_ID(),
2902
-                'PMD_ID'         => $this->checkout->transaction->payment_method_ID(),
2903
-                'payment_amount' => $this->checkout->amount_owing,
2904
-                'return_url'     => $return_url,
2905
-                'cancel_url'     => add_query_arg(array('ee_cancel_payment' => true), $return_url),
2906
-                'notify_url'     => EE_Config::instance()->core->txn_page_url(
2907
-                    array(
2908
-                        'e_reg_url_link'    => $this->checkout->transaction->primary_registration()->reg_url_link(),
2909
-                        'ee_payment_method' => $this->checkout->payment_method->slug(),
2910
-                    )
2911
-                ),
2912
-            );
2913
-        }
2914
-        echo wp_json_encode($txn_details);
2915
-        exit();
2916
-    }
2917
-
2918
-
2919
-    /**
2920
-     *    __sleep
2921
-     * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon
2922
-     * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the
2923
-     * reg form, because if needed, it will be regenerated anyways
2924
-     *
2925
-     * @return array
2926
-     */
2927
-    public function __sleep()
2928
-    {
2929
-        // remove the reg form and the checkout
2930
-        return array_diff(array_keys(get_object_vars($this)), array('reg_form', 'checkout', 'line_item_display'));
2931
-    }
250
+			// registrations made via the admin
251
+			// completed transactions
252
+			// overpaid transactions
253
+			// $ 0.00 transactions(no payment required)
254
+			! $this->checkout->payment_required()
255
+			// but do NOT remove if current action being called belongs to this reg step
256
+			&& ! is_callable(array($this, $this->checkout->action))
257
+			&& ! $this->completed()
258
+		) {
259
+			// and if so, then we no longer need the Payment Options step
260
+			if ($this->is_current_step()) {
261
+				$this->checkout->generate_reg_form = false;
262
+			}
263
+			$this->checkout->remove_reg_step($this->_slug);
264
+			// DEBUG LOG
265
+			// $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
266
+			return false;
267
+		}
268
+		// load EEM_Payment_Method
269
+		EE_Registry::instance()->load_model('Payment_Method');
270
+		// get all active payment methods
271
+		$this->checkout->available_payment_methods = EEM_Payment_Method::instance()->get_all_for_transaction(
272
+			$this->checkout->transaction,
273
+			EEM_Payment_Method::scope_cart
274
+		);
275
+		return true;
276
+	}
277
+
278
+
279
+	/**
280
+	 * @return EE_Form_Section_Proper
281
+	 * @throws EE_Error
282
+	 * @throws InvalidArgumentException
283
+	 * @throws ReflectionException
284
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
285
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
286
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
287
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
288
+	 */
289
+	public function generate_reg_form()
290
+	{
291
+		// reset in case someone changes their mind
292
+		$this->_reset_selected_method_of_payment();
293
+		// set some defaults
294
+		$this->checkout->selected_method_of_payment = 'payments_closed';
295
+		$registrations_requiring_payment = array();
296
+		$registrations_for_free_events = array();
297
+		$registrations_requiring_pre_approval = array();
298
+		$sold_out_events = array();
299
+		$insufficient_spaces_available = array();
300
+		$no_payment_required = true;
301
+		// loop thru registrations to gather info
302
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
303
+		$ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
304
+			$registrations,
305
+			$this->checkout->revisit
306
+		);
307
+		foreach ($registrations as $REG_ID => $registration) {
308
+			/** @var $registration EE_Registration */
309
+			// has this registration lost it's space ?
310
+			if (isset($ejected_registrations[ $REG_ID ])) {
311
+				if ($registration->event()->is_sold_out() || $registration->event()->is_sold_out(true)) {
312
+					$sold_out_events[ $registration->event()->ID() ] = $registration->event();
313
+				} else {
314
+					$insufficient_spaces_available[ $registration->event()->ID() ] = $registration->event();
315
+				}
316
+				continue;
317
+			}
318
+			// event requires admin approval
319
+			if ($registration->status_ID() === EEM_Registration::status_id_not_approved) {
320
+				// add event to list of events with pre-approval reg status
321
+				$registrations_requiring_pre_approval[ $REG_ID ] = $registration;
322
+				do_action(
323
+					'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_pre_approval',
324
+					$registration->event(),
325
+					$this
326
+				);
327
+				continue;
328
+			}
329
+			if (
330
+				$this->checkout->revisit
331
+				&& $registration->status_ID() !== EEM_Registration::status_id_approved
332
+				&& (
333
+					$registration->event()->is_sold_out()
334
+					|| $registration->event()->is_sold_out(true)
335
+				)
336
+			) {
337
+				// add event to list of events that are sold out
338
+				$sold_out_events[ $registration->event()->ID() ] = $registration->event();
339
+				do_action(
340
+					'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__sold_out_event',
341
+					$registration->event(),
342
+					$this
343
+				);
344
+				continue;
345
+			}
346
+			// are they allowed to pay now and is there monies owing?
347
+			if ($registration->owes_monies_and_can_pay()) {
348
+				$registrations_requiring_payment[ $REG_ID ] = $registration;
349
+				do_action(
350
+					'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_payment',
351
+					$registration->event(),
352
+					$this
353
+				);
354
+			} elseif (
355
+				! $this->checkout->revisit
356
+					  && $registration->status_ID() !== EEM_Registration::status_id_not_approved
357
+					  && $registration->ticket()->is_free()
358
+			) {
359
+				$registrations_for_free_events[ $registration->ticket()->ID() ] = $registration;
360
+			}
361
+		}
362
+		$subsections = array();
363
+		// now decide which template to load
364
+		if (! empty($sold_out_events)) {
365
+			$subsections['sold_out_events'] = $this->_sold_out_events($sold_out_events);
366
+		}
367
+		if (! empty($insufficient_spaces_available)) {
368
+			$subsections['insufficient_space'] = $this->_insufficient_spaces_available(
369
+				$insufficient_spaces_available
370
+			);
371
+		}
372
+		if (! empty($registrations_requiring_pre_approval)) {
373
+			$subsections['registrations_requiring_pre_approval'] = $this->_registrations_requiring_pre_approval(
374
+				$registrations_requiring_pre_approval
375
+			);
376
+		}
377
+		if (! empty($registrations_for_free_events)) {
378
+			$subsections['no_payment_required'] = $this->_no_payment_required($registrations_for_free_events);
379
+		}
380
+		if (! empty($registrations_requiring_payment)) {
381
+			if ($this->checkout->amount_owing > 0) {
382
+				// autoload Line_Item_Display classes
383
+				EEH_Autoloader::register_line_item_filter_autoloaders();
384
+				$line_item_filter_processor = new EE_Line_Item_Filter_Processor(
385
+					apply_filters(
386
+						'FHEE__SPCO__EE_Line_Item_Filter_Collection',
387
+						new EE_Line_Item_Filter_Collection()
388
+					),
389
+					$this->checkout->cart->get_grand_total()
390
+				);
391
+				/** @var EE_Line_Item $filtered_line_item_tree */
392
+				$filtered_line_item_tree = $line_item_filter_processor->process();
393
+				EEH_Autoloader::register_line_item_display_autoloaders();
394
+				$this->set_line_item_display(new EE_Line_Item_Display('spco'));
395
+				$subsections['payment_options'] = $this->_display_payment_options(
396
+					$this->line_item_display->display_line_item(
397
+						$filtered_line_item_tree,
398
+						array('registrations' => $registrations)
399
+					)
400
+				);
401
+				$this->checkout->amount_owing = $filtered_line_item_tree->total();
402
+				$this->_apply_registration_payments_to_amount_owing($registrations);
403
+			}
404
+			$no_payment_required = false;
405
+		} else {
406
+			$this->_hide_reg_step_submit_button_if_revisit();
407
+		}
408
+		$this->_save_selected_method_of_payment();
409
+
410
+		$subsections['default_hidden_inputs'] = $this->reg_step_hidden_inputs();
411
+		$subsections['extra_hidden_inputs'] = $this->_extra_hidden_inputs($no_payment_required);
412
+
413
+		return new EE_Form_Section_Proper(
414
+			array(
415
+				'name'            => $this->reg_form_name(),
416
+				'html_id'         => $this->reg_form_name(),
417
+				'subsections'     => $subsections,
418
+				'layout_strategy' => new EE_No_Layout(),
419
+			)
420
+		);
421
+	}
422
+
423
+
424
+	/**
425
+	 * add line item filters required for this reg step
426
+	 * these filters are applied via this line in EE_SPCO_Reg_Step_Payment_Options::set_hooks():
427
+	 *        add_filter( 'FHEE__SPCO__EE_Line_Item_Filter_Collection', array( 'EE_SPCO_Reg_Step_Payment_Options',
428
+	 *        'add_spco_line_item_filters' ) ); so any code that wants to use the same set of filters during the
429
+	 *        payment options reg step, can apply these filters via the following: apply_filters(
430
+	 *        'FHEE__SPCO__EE_Line_Item_Filter_Collection', new EE_Line_Item_Filter_Collection() ) or to an existing
431
+	 *        filter collection by passing that instead of instantiating a new collection
432
+	 *
433
+	 * @param \EE_Line_Item_Filter_Collection $line_item_filter_collection
434
+	 * @return EE_Line_Item_Filter_Collection
435
+	 * @throws EE_Error
436
+	 * @throws InvalidArgumentException
437
+	 * @throws ReflectionException
438
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
439
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
440
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
441
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
442
+	 */
443
+	public static function add_spco_line_item_filters(EE_Line_Item_Filter_Collection $line_item_filter_collection)
444
+	{
445
+		if (! EE_Registry::instance()->SSN instanceof EE_Session) {
446
+			return $line_item_filter_collection;
447
+		}
448
+		if (! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
449
+			return $line_item_filter_collection;
450
+		}
451
+		if (! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
452
+			return $line_item_filter_collection;
453
+		}
454
+		$line_item_filter_collection->add(
455
+			new EE_Billable_Line_Item_Filter(
456
+				EE_SPCO_Reg_Step_Payment_Options::remove_ejected_registrations(
457
+					EE_Registry::instance()->SSN->checkout()->transaction->registrations(
458
+						EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
459
+					)
460
+				)
461
+			)
462
+		);
463
+		$line_item_filter_collection->add(new EE_Non_Zero_Line_Item_Filter());
464
+		return $line_item_filter_collection;
465
+	}
466
+
467
+
468
+	/**
469
+	 * remove_ejected_registrations
470
+	 * if a registrant has lost their potential space at an event due to lack of payment,
471
+	 * then this method removes them from the list of registrations being paid for during this request
472
+	 *
473
+	 * @param \EE_Registration[] $registrations
474
+	 * @return EE_Registration[]
475
+	 * @throws EE_Error
476
+	 * @throws InvalidArgumentException
477
+	 * @throws ReflectionException
478
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
479
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
480
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
481
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
482
+	 */
483
+	public static function remove_ejected_registrations(array $registrations)
484
+	{
485
+		$ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
486
+			$registrations,
487
+			EE_Registry::instance()->SSN->checkout()->revisit
488
+		);
489
+		foreach ($registrations as $REG_ID => $registration) {
490
+			// has this registration lost it's space ?
491
+			if (isset($ejected_registrations[ $REG_ID ])) {
492
+				unset($registrations[ $REG_ID ]);
493
+				continue;
494
+			}
495
+		}
496
+		return $registrations;
497
+	}
498
+
499
+
500
+	/**
501
+	 * find_registrations_that_lost_their_space
502
+	 * If a registrant chooses an offline payment method like Invoice,
503
+	 * then no space is reserved for them at the event until they fully pay fo that site
504
+	 * (unless the event's default reg status is set to APPROVED)
505
+	 * if a registrant then later returns to pay, but the number of spaces available has been reduced due to sales,
506
+	 * then this method will determine which registrations have lost the ability to complete the reg process.
507
+	 *
508
+	 * @param \EE_Registration[] $registrations
509
+	 * @param bool               $revisit
510
+	 * @return array
511
+	 * @throws EE_Error
512
+	 * @throws InvalidArgumentException
513
+	 * @throws ReflectionException
514
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
515
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
516
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
517
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
518
+	 */
519
+	public static function find_registrations_that_lost_their_space(array $registrations, $revisit = false)
520
+	{
521
+		// registrations per event
522
+		$event_reg_count = array();
523
+		// spaces left per event
524
+		$event_spaces_remaining = array();
525
+		// tickets left sorted by ID
526
+		$tickets_remaining = array();
527
+		// registrations that have lost their space
528
+		$ejected_registrations = array();
529
+		foreach ($registrations as $REG_ID => $registration) {
530
+			if (
531
+				$registration->status_ID() === EEM_Registration::status_id_approved
532
+				|| apply_filters(
533
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options__find_registrations_that_lost_their_space__allow_reg_payment',
534
+					false,
535
+					$registration,
536
+					$revisit
537
+				)
538
+			) {
539
+				continue;
540
+			}
541
+			$EVT_ID = $registration->event_ID();
542
+			$ticket = $registration->ticket();
543
+			if (! isset($tickets_remaining[ $ticket->ID() ])) {
544
+				$tickets_remaining[ $ticket->ID() ] = $ticket->remaining();
545
+			}
546
+			if ($tickets_remaining[ $ticket->ID() ] > 0) {
547
+				if (! isset($event_reg_count[ $EVT_ID ])) {
548
+					$event_reg_count[ $EVT_ID ] = 0;
549
+				}
550
+				$event_reg_count[ $EVT_ID ]++;
551
+				if (! isset($event_spaces_remaining[ $EVT_ID ])) {
552
+					$event_spaces_remaining[ $EVT_ID ] = $registration->event()->spaces_remaining_for_sale();
553
+				}
554
+			}
555
+			if (
556
+				$revisit
557
+				&& ($tickets_remaining[ $ticket->ID() ] === 0
558
+					|| $event_reg_count[ $EVT_ID ] > $event_spaces_remaining[ $EVT_ID ]
559
+				)
560
+			) {
561
+				$ejected_registrations[ $REG_ID ] = $registration->event();
562
+				if ($registration->status_ID() !== EEM_Registration::status_id_wait_list) {
563
+					/** @type EE_Registration_Processor $registration_processor */
564
+					$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
565
+					// at this point, we should have enough details about the registrant to consider the registration
566
+					// NOT incomplete
567
+					$registration_processor->manually_update_registration_status(
568
+						$registration,
569
+						EEM_Registration::status_id_wait_list
570
+					);
571
+				}
572
+			}
573
+		}
574
+		return $ejected_registrations;
575
+	}
576
+
577
+
578
+	/**
579
+	 * _hide_reg_step_submit_button
580
+	 * removes the html for the reg step submit button
581
+	 * by replacing it with an empty string via filter callback
582
+	 *
583
+	 * @return void
584
+	 */
585
+	protected function _adjust_registration_status_if_event_old_sold()
586
+	{
587
+	}
588
+
589
+
590
+	/**
591
+	 * _hide_reg_step_submit_button
592
+	 * removes the html for the reg step submit button
593
+	 * by replacing it with an empty string via filter callback
594
+	 *
595
+	 * @return void
596
+	 */
597
+	protected function _hide_reg_step_submit_button_if_revisit()
598
+	{
599
+		if ($this->checkout->revisit) {
600
+			add_filter('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', '__return_empty_string');
601
+		}
602
+	}
603
+
604
+
605
+	/**
606
+	 * sold_out_events
607
+	 * displays notices regarding events that have sold out since hte registrant first signed up
608
+	 *
609
+	 * @param \EE_Event[] $sold_out_events_array
610
+	 * @return \EE_Form_Section_Proper
611
+	 * @throws \EE_Error
612
+	 */
613
+	private function _sold_out_events($sold_out_events_array = array())
614
+	{
615
+		// set some defaults
616
+		$this->checkout->selected_method_of_payment = 'events_sold_out';
617
+		$sold_out_events = '';
618
+		foreach ($sold_out_events_array as $sold_out_event) {
619
+			$sold_out_events .= EEH_HTML::li(
620
+				EEH_HTML::span(
621
+					'  ' . $sold_out_event->name(),
622
+					'',
623
+					'dashicons dashicons-marker ee-icon-size-16 pink-text'
624
+				)
625
+			);
626
+		}
627
+		return new EE_Form_Section_Proper(
628
+			array(
629
+				'layout_strategy' => new EE_Template_Layout(
630
+					array(
631
+						'layout_template_file' => SPCO_REG_STEPS_PATH
632
+												  . $this->_slug
633
+												  . '/sold_out_events.template.php',
634
+						'template_args'        => apply_filters(
635
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
636
+							array(
637
+								'sold_out_events'     => $sold_out_events,
638
+								'sold_out_events_msg' => apply_filters(
639
+									'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__sold_out_events_msg',
640
+									sprintf(
641
+										esc_html__(
642
+											'It appears that the event you were about to make a payment for has sold out since you first registered. If you have already made a partial payment towards this event, please contact the event administrator for a refund.%3$s%3$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%2$s',
643
+											'event_espresso'
644
+										),
645
+										'<strong>',
646
+										'</strong>',
647
+										'<br />'
648
+									)
649
+								),
650
+							)
651
+						),
652
+					)
653
+				),
654
+			)
655
+		);
656
+	}
657
+
658
+
659
+	/**
660
+	 * _insufficient_spaces_available
661
+	 * displays notices regarding events that do not have enough remaining spaces
662
+	 * to satisfy the current number of registrations looking to pay
663
+	 *
664
+	 * @param \EE_Event[] $insufficient_spaces_events_array
665
+	 * @return \EE_Form_Section_Proper
666
+	 * @throws \EE_Error
667
+	 */
668
+	private function _insufficient_spaces_available($insufficient_spaces_events_array = array())
669
+	{
670
+		// set some defaults
671
+		$this->checkout->selected_method_of_payment = 'invoice';
672
+		$insufficient_space_events = '';
673
+		foreach ($insufficient_spaces_events_array as $event) {
674
+			if ($event instanceof EE_Event) {
675
+				$insufficient_space_events .= EEH_HTML::li(
676
+					EEH_HTML::span(' ' . $event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
677
+				);
678
+			}
679
+		}
680
+		return new EE_Form_Section_Proper(
681
+			array(
682
+				'subsections'     => array(
683
+					'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
684
+					'extra_hidden_inputs'   => $this->_extra_hidden_inputs(),
685
+				),
686
+				'layout_strategy' => new EE_Template_Layout(
687
+					array(
688
+						'layout_template_file' => SPCO_REG_STEPS_PATH
689
+												  . $this->_slug
690
+												  . '/sold_out_events.template.php',
691
+						'template_args'        => apply_filters(
692
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__template_args',
693
+							array(
694
+								'sold_out_events'     => $insufficient_space_events,
695
+								'sold_out_events_msg' => apply_filters(
696
+									'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__insufficient_space_msg',
697
+									esc_html__(
698
+										'It appears that the event you were about to make a payment for has sold additional tickets since you first registered, and there are no longer enough spaces left to accommodate your selections. You may continue to pay and secure the available space(s) remaining, or simply cancel if you no longer wish to purchase. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
699
+										'event_espresso'
700
+									)
701
+								),
702
+							)
703
+						),
704
+					)
705
+				),
706
+			)
707
+		);
708
+	}
709
+
710
+
711
+	/**
712
+	 * registrations_requiring_pre_approval
713
+	 *
714
+	 * @param array $registrations_requiring_pre_approval
715
+	 * @return EE_Form_Section_Proper
716
+	 * @throws EE_Error
717
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
718
+	 */
719
+	private function _registrations_requiring_pre_approval($registrations_requiring_pre_approval = array())
720
+	{
721
+		$events_requiring_pre_approval = array();
722
+		foreach ($registrations_requiring_pre_approval as $registration) {
723
+			if ($registration instanceof EE_Registration && $registration->event() instanceof EE_Event) {
724
+				$events_requiring_pre_approval[ $registration->event()->ID() ] = EEH_HTML::li(
725
+					EEH_HTML::span(
726
+						'',
727
+						'',
728
+						'dashicons dashicons-marker ee-icon-size-16 orange-text'
729
+					)
730
+					. EEH_HTML::span($registration->event()->name(), '', 'orange-text')
731
+				);
732
+			}
733
+		}
734
+		return new EE_Form_Section_Proper(
735
+			array(
736
+				'layout_strategy' => new EE_Template_Layout(
737
+					array(
738
+						'layout_template_file' => SPCO_REG_STEPS_PATH
739
+												  . $this->_slug
740
+												  . '/events_requiring_pre_approval.template.php', // layout_template
741
+						'template_args'        => apply_filters(
742
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
743
+							array(
744
+								'events_requiring_pre_approval'     => implode('', $events_requiring_pre_approval),
745
+								'events_requiring_pre_approval_msg' => apply_filters(
746
+									'FHEE__EE_SPCO_Reg_Step_Payment_Options___events_requiring_pre_approval__events_requiring_pre_approval_msg',
747
+									esc_html__(
748
+										'The following events do not require payment at this time and will not be billed during this transaction. Billing will only occur after the attendee has been approved by the event organizer. You will be notified when your registration has been processed. If this is a free event, then no billing will occur.',
749
+										'event_espresso'
750
+									)
751
+								),
752
+							)
753
+						),
754
+					)
755
+				),
756
+			)
757
+		);
758
+	}
759
+
760
+
761
+	/**
762
+	 * _no_payment_required
763
+	 *
764
+	 * @param \EE_Event[] $registrations_for_free_events
765
+	 * @return \EE_Form_Section_Proper
766
+	 * @throws \EE_Error
767
+	 */
768
+	private function _no_payment_required($registrations_for_free_events = array())
769
+	{
770
+		// set some defaults
771
+		$this->checkout->selected_method_of_payment = 'no_payment_required';
772
+		// generate no_payment_required form
773
+		return new EE_Form_Section_Proper(
774
+			array(
775
+				'layout_strategy' => new EE_Template_Layout(
776
+					array(
777
+						'layout_template_file' => SPCO_REG_STEPS_PATH
778
+												  . $this->_slug
779
+												  . '/no_payment_required.template.php', // layout_template
780
+						'template_args'        => apply_filters(
781
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___no_payment_required__template_args',
782
+							array(
783
+								'revisit'                       => $this->checkout->revisit,
784
+								'registrations'                 => array(),
785
+								'ticket_count'                  => array(),
786
+								'registrations_for_free_events' => $registrations_for_free_events,
787
+								'no_payment_required_msg'       => EEH_HTML::p(
788
+									esc_html__('This is a free event, so no billing will occur.', 'event_espresso')
789
+								),
790
+							)
791
+						),
792
+					)
793
+				),
794
+			)
795
+		);
796
+	}
797
+
798
+
799
+	/**
800
+	 * _display_payment_options
801
+	 *
802
+	 * @param string $transaction_details
803
+	 * @return EE_Form_Section_Proper
804
+	 * @throws EE_Error
805
+	 * @throws InvalidArgumentException
806
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
807
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
808
+	 */
809
+	private function _display_payment_options($transaction_details = '')
810
+	{
811
+		// has method_of_payment been set by no-js user?
812
+		$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment();
813
+		// build payment options form
814
+		return apply_filters(
815
+			'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__payment_options_form',
816
+			new EE_Form_Section_Proper(
817
+				array(
818
+					'subsections'     => array(
819
+						'before_payment_options' => apply_filters(
820
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__before_payment_options',
821
+							new EE_Form_Section_Proper(
822
+								array('layout_strategy' => new EE_Div_Per_Section_Layout())
823
+							)
824
+						),
825
+						'payment_options'        => $this->_setup_payment_options(),
826
+						'after_payment_options'  => apply_filters(
827
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__after_payment_options',
828
+							new EE_Form_Section_Proper(
829
+								array('layout_strategy' => new EE_Div_Per_Section_Layout())
830
+							)
831
+						),
832
+					),
833
+					'layout_strategy' => new EE_Template_Layout(
834
+						array(
835
+							'layout_template_file' => $this->_template,
836
+							'template_args'        => apply_filters(
837
+								'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__template_args',
838
+								array(
839
+									'reg_count'                 => $this->line_item_display->total_items(),
840
+									'transaction_details'       => $transaction_details,
841
+									'available_payment_methods' => array(),
842
+								)
843
+							),
844
+						)
845
+					),
846
+				)
847
+			)
848
+		);
849
+	}
850
+
851
+
852
+	/**
853
+	 * _extra_hidden_inputs
854
+	 *
855
+	 * @param bool $no_payment_required
856
+	 * @return \EE_Form_Section_Proper
857
+	 * @throws \EE_Error
858
+	 */
859
+	private function _extra_hidden_inputs($no_payment_required = true)
860
+	{
861
+		return new EE_Form_Section_Proper(
862
+			array(
863
+				'html_id'         => 'ee-' . $this->slug() . '-extra-hidden-inputs',
864
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
865
+				'subsections'     => array(
866
+					'spco_no_payment_required' => new EE_Hidden_Input(
867
+						array(
868
+							'normalization_strategy' => new EE_Boolean_Normalization(),
869
+							'html_name'              => 'spco_no_payment_required',
870
+							'html_id'                => 'spco-no-payment-required-payment_options',
871
+							'default'                => $no_payment_required,
872
+						)
873
+					),
874
+					'spco_transaction_id'      => new EE_Fixed_Hidden_Input(
875
+						array(
876
+							'normalization_strategy' => new EE_Int_Normalization(),
877
+							'html_name'              => 'spco_transaction_id',
878
+							'html_id'                => 'spco-transaction-id',
879
+							'default'                => $this->checkout->transaction->ID(),
880
+						)
881
+					),
882
+				),
883
+			)
884
+		);
885
+	}
886
+
887
+
888
+	/**
889
+	 *    _apply_registration_payments_to_amount_owing
890
+	 *
891
+	 * @access protected
892
+	 * @param array $registrations
893
+	 * @throws EE_Error
894
+	 */
895
+	protected function _apply_registration_payments_to_amount_owing(array $registrations)
896
+	{
897
+		$payments = array();
898
+		foreach ($registrations as $registration) {
899
+			if ($registration instanceof EE_Registration && $registration->owes_monies_and_can_pay()) {
900
+				$payments += $registration->registration_payments();
901
+			}
902
+		}
903
+		if (! empty($payments)) {
904
+			foreach ($payments as $payment) {
905
+				if ($payment instanceof EE_Registration_Payment) {
906
+					$this->checkout->amount_owing -= $payment->amount();
907
+				}
908
+			}
909
+		}
910
+	}
911
+
912
+
913
+	/**
914
+	 *    _reset_selected_method_of_payment
915
+	 *
916
+	 * @access    private
917
+	 * @param    bool $force_reset
918
+	 * @return void
919
+	 * @throws InvalidArgumentException
920
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
921
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
922
+	 */
923
+	private function _reset_selected_method_of_payment($force_reset = false)
924
+	{
925
+		$reset_payment_method = $force_reset
926
+			? true
927
+			: sanitize_text_field(EE_Registry::instance()->REQ->get('reset_payment_method', false));
928
+		if ($reset_payment_method) {
929
+			$this->checkout->selected_method_of_payment = null;
930
+			$this->checkout->payment_method = null;
931
+			$this->checkout->billing_form = null;
932
+			$this->_save_selected_method_of_payment();
933
+		}
934
+	}
935
+
936
+
937
+	/**
938
+	 * _save_selected_method_of_payment
939
+	 * stores the selected_method_of_payment in the session
940
+	 * so that it's available for all subsequent requests including AJAX
941
+	 *
942
+	 * @access        private
943
+	 * @param string $selected_method_of_payment
944
+	 * @return void
945
+	 * @throws InvalidArgumentException
946
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
947
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
948
+	 */
949
+	private function _save_selected_method_of_payment($selected_method_of_payment = '')
950
+	{
951
+		$selected_method_of_payment = ! empty($selected_method_of_payment)
952
+			? $selected_method_of_payment
953
+			: $this->checkout->selected_method_of_payment;
954
+		EE_Registry::instance()->SSN->set_session_data(
955
+			array('selected_method_of_payment' => $selected_method_of_payment)
956
+		);
957
+	}
958
+
959
+
960
+	/**
961
+	 * _setup_payment_options
962
+	 *
963
+	 * @return EE_Form_Section_Proper
964
+	 * @throws EE_Error
965
+	 * @throws InvalidArgumentException
966
+	 * @throws ReflectionException
967
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
968
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
969
+	 */
970
+	public function _setup_payment_options()
971
+	{
972
+		// load payment method classes
973
+		$this->checkout->available_payment_methods = $this->_get_available_payment_methods();
974
+		if (empty($this->checkout->available_payment_methods)) {
975
+			EE_Error::add_error(
976
+				apply_filters(
977
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options___setup_payment_options__error_message_no_payment_methods',
978
+					sprintf(
979
+						esc_html__(
980
+							'Sorry, you cannot complete your purchase because a payment method is not active.%1$s Please contact %2$s for assistance and provide a description of the problem.',
981
+							'event_espresso'
982
+						),
983
+						'<br>',
984
+						EE_Registry::instance()->CFG->organization->get_pretty('email')
985
+					)
986
+				),
987
+				__FILE__,
988
+				__FUNCTION__,
989
+				__LINE__
990
+			);
991
+		}
992
+		// switch up header depending on number of available payment methods
993
+		$payment_method_header = count($this->checkout->available_payment_methods) > 1
994
+			? apply_filters(
995
+				'FHEE__registration_page_payment_options__method_of_payment_hdr',
996
+				esc_html__('Please Select Your Method of Payment', 'event_espresso')
997
+			)
998
+			: apply_filters(
999
+				'FHEE__registration_page_payment_options__method_of_payment_hdr',
1000
+				esc_html__('Method of Payment', 'event_espresso')
1001
+			);
1002
+		$available_payment_methods = array(
1003
+			// display the "Payment Method" header
1004
+			'payment_method_header' => new EE_Form_Section_HTML(
1005
+				apply_filters(
1006
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options___setup_payment_options__payment_method_header',
1007
+					EEH_HTML::h4($payment_method_header, 'method-of-payment-hdr'),
1008
+					$payment_method_header
1009
+				)
1010
+			),
1011
+		);
1012
+		// the list of actual payment methods ( invoice, paypal, etc ) in a  ( slug => HTML )  format
1013
+		$available_payment_method_options = array();
1014
+		$default_payment_method_option = array();
1015
+		// additional instructions to be displayed and hidden below payment methods (adding a clearing div to start)
1016
+		$payment_methods_billing_info = array(
1017
+			new EE_Form_Section_HTML(
1018
+				EEH_HTML::div('<br />', '', '', 'clear:both;')
1019
+			),
1020
+		);
1021
+		// loop through payment methods
1022
+		foreach ($this->checkout->available_payment_methods as $payment_method) {
1023
+			if ($payment_method instanceof EE_Payment_Method) {
1024
+				$payment_method_button = EEH_HTML::img(
1025
+					$payment_method->button_url(),
1026
+					$payment_method->name(),
1027
+					'spco-payment-method-' . $payment_method->slug() . '-btn-img',
1028
+					'spco-payment-method-btn-img'
1029
+				);
1030
+				// check if any payment methods are set as default
1031
+				// if payment method is already selected OR nothing is selected and this payment method should be
1032
+				// open_by_default
1033
+				if (
1034
+					($this->checkout->selected_method_of_payment === $payment_method->slug())
1035
+					|| (! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1036
+				) {
1037
+					$this->checkout->selected_method_of_payment = $payment_method->slug();
1038
+					$this->_save_selected_method_of_payment();
1039
+					$default_payment_method_option[ $payment_method->slug() ] = $payment_method_button;
1040
+				} else {
1041
+					$available_payment_method_options[ $payment_method->slug() ] = $payment_method_button;
1042
+				}
1043
+				$payment_methods_billing_info[ $payment_method->slug(
1044
+				) . '-info' ] = $this->_payment_method_billing_info(
1045
+					$payment_method
1046
+				);
1047
+			}
1048
+		}
1049
+		// prepend available_payment_method_options with default_payment_method_option so that it appears first in list
1050
+		// of PMs
1051
+		$available_payment_method_options = $default_payment_method_option + $available_payment_method_options;
1052
+		// now generate the actual form  inputs
1053
+		$available_payment_methods['available_payment_methods'] = $this->_available_payment_method_inputs(
1054
+			$available_payment_method_options
1055
+		);
1056
+		$available_payment_methods += $payment_methods_billing_info;
1057
+		// build the available payment methods form
1058
+		return new EE_Form_Section_Proper(
1059
+			array(
1060
+				'html_id'         => 'spco-available-methods-of-payment-dv',
1061
+				'subsections'     => $available_payment_methods,
1062
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1063
+			)
1064
+		);
1065
+	}
1066
+
1067
+
1068
+	/**
1069
+	 * _get_available_payment_methods
1070
+	 *
1071
+	 * @return EE_Payment_Method[]
1072
+	 * @throws EE_Error
1073
+	 * @throws InvalidArgumentException
1074
+	 * @throws ReflectionException
1075
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1076
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1077
+	 */
1078
+	protected function _get_available_payment_methods()
1079
+	{
1080
+		if (! empty($this->checkout->available_payment_methods)) {
1081
+			return $this->checkout->available_payment_methods;
1082
+		}
1083
+		$available_payment_methods = array();
1084
+		// load EEM_Payment_Method
1085
+		EE_Registry::instance()->load_model('Payment_Method');
1086
+		/** @type EEM_Payment_Method $EEM_Payment_Method */
1087
+		$EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
1088
+		// get all active payment methods
1089
+		$payment_methods = $EEM_Payment_Method->get_all_for_transaction(
1090
+			$this->checkout->transaction,
1091
+			EEM_Payment_Method::scope_cart
1092
+		);
1093
+		foreach ($payment_methods as $payment_method) {
1094
+			if ($payment_method instanceof EE_Payment_Method) {
1095
+				$available_payment_methods[ $payment_method->slug() ] = $payment_method;
1096
+			}
1097
+		}
1098
+		return $available_payment_methods;
1099
+	}
1100
+
1101
+
1102
+	/**
1103
+	 *    _available_payment_method_inputs
1104
+	 *
1105
+	 * @access    private
1106
+	 * @param    array $available_payment_method_options
1107
+	 * @return    \EE_Form_Section_Proper
1108
+	 */
1109
+	private function _available_payment_method_inputs($available_payment_method_options = array())
1110
+	{
1111
+		// generate inputs
1112
+		return new EE_Form_Section_Proper(
1113
+			array(
1114
+				'html_id'         => 'ee-available-payment-method-inputs',
1115
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1116
+				'subsections'     => array(
1117
+					'' => new EE_Radio_Button_Input(
1118
+						$available_payment_method_options,
1119
+						array(
1120
+							'html_name'          => 'selected_method_of_payment',
1121
+							'html_class'         => 'spco-payment-method',
1122
+							'default'            => $this->checkout->selected_method_of_payment,
1123
+							'label_size'         => 11,
1124
+							'enforce_label_size' => true,
1125
+						)
1126
+					),
1127
+				),
1128
+			)
1129
+		);
1130
+	}
1131
+
1132
+
1133
+	/**
1134
+	 *    _payment_method_billing_info
1135
+	 *
1136
+	 * @access    private
1137
+	 * @param    EE_Payment_Method $payment_method
1138
+	 * @return EE_Form_Section_Proper
1139
+	 * @throws EE_Error
1140
+	 * @throws InvalidArgumentException
1141
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1142
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1143
+	 */
1144
+	private function _payment_method_billing_info(EE_Payment_Method $payment_method)
1145
+	{
1146
+		$currently_selected = $this->checkout->selected_method_of_payment === $payment_method->slug()
1147
+			? true
1148
+			: false;
1149
+		// generate the billing form for payment method
1150
+		$billing_form = $currently_selected
1151
+			? $this->_get_billing_form_for_payment_method($payment_method)
1152
+			: new EE_Form_Section_HTML();
1153
+		$this->checkout->billing_form = $currently_selected
1154
+			? $billing_form
1155
+			: $this->checkout->billing_form;
1156
+		// it's all in the details
1157
+		$info_html = EEH_HTML::h3(
1158
+			esc_html__('Important information regarding your payment', 'event_espresso'),
1159
+			'',
1160
+			'spco-payment-method-hdr'
1161
+		);
1162
+		// add some info regarding the step, either from what's saved in the admin,
1163
+		// or a default string depending on whether the PM has a billing form or not
1164
+		if ($payment_method->description()) {
1165
+			$payment_method_info = $payment_method->description();
1166
+		} elseif ($billing_form instanceof EE_Billing_Info_Form) {
1167
+			$payment_method_info = sprintf(
1168
+				esc_html__(
1169
+					'Please provide the following billing information, then click the "%1$s" button below in order to proceed.',
1170
+					'event_espresso'
1171
+				),
1172
+				$this->submit_button_text()
1173
+			);
1174
+		} else {
1175
+			$payment_method_info = sprintf(
1176
+				esc_html__('Please click the "%1$s" button below in order to proceed.', 'event_espresso'),
1177
+				$this->submit_button_text()
1178
+			);
1179
+		}
1180
+		$info_html .= EEH_HTML::div(
1181
+			apply_filters(
1182
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options___payment_method_billing_info__payment_method_info',
1183
+				$payment_method_info
1184
+			),
1185
+			'',
1186
+			'spco-payment-method-desc ee-attention'
1187
+		);
1188
+		return new EE_Form_Section_Proper(
1189
+			array(
1190
+				'html_id'         => 'spco-payment-method-info-' . $payment_method->slug(),
1191
+				'html_class'      => 'spco-payment-method-info-dv',
1192
+				// only display the selected or default PM
1193
+				'html_style'      => $currently_selected ? '' : 'display:none;',
1194
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1195
+				'subsections'     => array(
1196
+					'info'         => new EE_Form_Section_HTML($info_html),
1197
+					'billing_form' => $currently_selected ? $billing_form : new EE_Form_Section_HTML(),
1198
+				),
1199
+			)
1200
+		);
1201
+	}
1202
+
1203
+
1204
+	/**
1205
+	 * get_billing_form_html_for_payment_method
1206
+	 *
1207
+	 * @access public
1208
+	 * @return string
1209
+	 * @throws EE_Error
1210
+	 * @throws InvalidArgumentException
1211
+	 * @throws ReflectionException
1212
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1213
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1214
+	 */
1215
+	public function get_billing_form_html_for_payment_method()
1216
+	{
1217
+		// how have they chosen to pay?
1218
+		$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1219
+		$this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1220
+		if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1221
+			return false;
1222
+		}
1223
+		if (
1224
+			apply_filters(
1225
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1226
+				false
1227
+			)
1228
+		) {
1229
+			EE_Error::add_success(
1230
+				apply_filters(
1231
+					'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1232
+					sprintf(
1233
+						esc_html__(
1234
+							'You have selected "%s" as your method of payment. Please note the important payment information below.',
1235
+							'event_espresso'
1236
+						),
1237
+						$this->checkout->payment_method->name()
1238
+					)
1239
+				)
1240
+			);
1241
+		}
1242
+		// now generate billing form for selected method of payment
1243
+		$payment_method_billing_form = $this->_get_billing_form_for_payment_method($this->checkout->payment_method);
1244
+		// fill form with attendee info if applicable
1245
+		if (
1246
+			$payment_method_billing_form instanceof EE_Billing_Attendee_Info_Form
1247
+			&& $this->checkout->transaction_has_primary_registrant()
1248
+		) {
1249
+			$payment_method_billing_form->populate_from_attendee(
1250
+				$this->checkout->transaction->primary_registration()->attendee()
1251
+			);
1252
+		}
1253
+		// and debug content
1254
+		if (
1255
+			$payment_method_billing_form instanceof EE_Billing_Info_Form
1256
+			&& $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1257
+		) {
1258
+			$payment_method_billing_form =
1259
+				$this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1260
+					$payment_method_billing_form
1261
+				);
1262
+		}
1263
+		$billing_info = $payment_method_billing_form instanceof EE_Form_Section_Proper
1264
+			? $payment_method_billing_form->get_html()
1265
+			: '';
1266
+		$this->checkout->json_response->set_return_data(array('payment_method_info' => $billing_info));
1267
+		// localize validation rules for main form
1268
+		$this->checkout->current_step->reg_form->localize_validation_rules();
1269
+		$this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1270
+		return true;
1271
+	}
1272
+
1273
+
1274
+	/**
1275
+	 * _get_billing_form_for_payment_method
1276
+	 *
1277
+	 * @access private
1278
+	 * @param EE_Payment_Method $payment_method
1279
+	 * @return EE_Billing_Info_Form|EE_Form_Section_HTML
1280
+	 * @throws EE_Error
1281
+	 * @throws InvalidArgumentException
1282
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1283
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1284
+	 */
1285
+	private function _get_billing_form_for_payment_method(EE_Payment_Method $payment_method)
1286
+	{
1287
+		$billing_form = $payment_method->type_obj()->billing_form(
1288
+			$this->checkout->transaction,
1289
+			array('amount_owing' => $this->checkout->amount_owing)
1290
+		);
1291
+		if ($billing_form instanceof EE_Billing_Info_Form) {
1292
+			if (
1293
+				apply_filters(
1294
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1295
+					false
1296
+				)
1297
+				&& EE_Registry::instance()->REQ->is_set('payment_method')
1298
+			) {
1299
+				EE_Error::add_success(
1300
+					apply_filters(
1301
+						'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1302
+						sprintf(
1303
+							esc_html__(
1304
+								'You have selected "%s" as your method of payment. Please note the important payment information below.',
1305
+								'event_espresso'
1306
+							),
1307
+							$payment_method->name()
1308
+						)
1309
+					)
1310
+				);
1311
+			}
1312
+			return apply_filters(
1313
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options___get_billing_form_for_payment_method__billing_form',
1314
+				$billing_form,
1315
+				$payment_method
1316
+			);
1317
+		}
1318
+		// no actual billing form, so return empty HTML form section
1319
+		return new EE_Form_Section_HTML();
1320
+	}
1321
+
1322
+
1323
+	/**
1324
+	 * _get_selected_method_of_payment
1325
+	 *
1326
+	 * @access private
1327
+	 * @param boolean $required whether to throw an error if the "selected_method_of_payment"
1328
+	 *                          is not found in the incoming request
1329
+	 * @param string  $request_param
1330
+	 * @return NULL|string
1331
+	 * @throws EE_Error
1332
+	 * @throws InvalidArgumentException
1333
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1334
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1335
+	 */
1336
+	private function _get_selected_method_of_payment(
1337
+		$required = false,
1338
+		$request_param = 'selected_method_of_payment'
1339
+	) {
1340
+		// is selected_method_of_payment set in the request ?
1341
+		$selected_method_of_payment = EE_Registry::instance()->REQ->get($request_param, false);
1342
+		if ($selected_method_of_payment) {
1343
+			// sanitize it
1344
+			$selected_method_of_payment = is_array($selected_method_of_payment)
1345
+				? array_shift($selected_method_of_payment)
1346
+				: $selected_method_of_payment;
1347
+			$selected_method_of_payment = sanitize_text_field($selected_method_of_payment);
1348
+			// store it in the session so that it's available for all subsequent requests including AJAX
1349
+			$this->_save_selected_method_of_payment($selected_method_of_payment);
1350
+		} else {
1351
+			// or is is set in the session ?
1352
+			$selected_method_of_payment = EE_Registry::instance()->SSN->get_session_data(
1353
+				'selected_method_of_payment'
1354
+			);
1355
+		}
1356
+		// do ya really really gotta have it?
1357
+		if (empty($selected_method_of_payment) && $required) {
1358
+			EE_Error::add_error(
1359
+				sprintf(
1360
+					esc_html__(
1361
+						'The selected method of payment could not be determined.%sPlease ensure that you have selected one before proceeding.%sIf you continue to experience difficulties, then refresh your browser and try again, or contact %s for assistance.',
1362
+						'event_espresso'
1363
+					),
1364
+					'<br/>',
1365
+					'<br/>',
1366
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
1367
+				),
1368
+				__FILE__,
1369
+				__FUNCTION__,
1370
+				__LINE__
1371
+			);
1372
+			return null;
1373
+		}
1374
+		return $selected_method_of_payment;
1375
+	}
1376
+
1377
+
1378
+
1379
+
1380
+
1381
+
1382
+	/********************************************************************************************************/
1383
+	/***********************************  SWITCH PAYMENT METHOD  ************************************/
1384
+	/********************************************************************************************************/
1385
+	/**
1386
+	 * switch_payment_method
1387
+	 *
1388
+	 * @access public
1389
+	 * @return string
1390
+	 * @throws EE_Error
1391
+	 * @throws InvalidArgumentException
1392
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1393
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1394
+	 */
1395
+	public function switch_payment_method()
1396
+	{
1397
+		if (! $this->_verify_payment_method_is_set()) {
1398
+			return false;
1399
+		}
1400
+		if (
1401
+			apply_filters(
1402
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1403
+				false
1404
+			)
1405
+		) {
1406
+			EE_Error::add_success(
1407
+				apply_filters(
1408
+					'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1409
+					sprintf(
1410
+						esc_html__(
1411
+							'You have selected "%s" as your method of payment. Please note the important payment information below.',
1412
+							'event_espresso'
1413
+						),
1414
+						$this->checkout->payment_method->name()
1415
+					)
1416
+				)
1417
+			);
1418
+		}
1419
+		// generate billing form for selected method of payment if it hasn't been done already
1420
+		if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1421
+			$this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1422
+				$this->checkout->payment_method
1423
+			);
1424
+		}
1425
+		// fill form with attendee info if applicable
1426
+		if (
1427
+			apply_filters(
1428
+				'FHEE__populate_billing_form_fields_from_attendee',
1429
+				(
1430
+				$this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
1431
+				&& $this->checkout->transaction_has_primary_registrant()
1432
+				),
1433
+				$this->checkout->billing_form,
1434
+				$this->checkout->transaction
1435
+			)
1436
+		) {
1437
+			$this->checkout->billing_form->populate_from_attendee(
1438
+				$this->checkout->transaction->primary_registration()->attendee()
1439
+			);
1440
+		}
1441
+		// and debug content
1442
+		if (
1443
+			$this->checkout->billing_form instanceof EE_Billing_Info_Form
1444
+			&& $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1445
+		) {
1446
+			$this->checkout->billing_form =
1447
+				$this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1448
+					$this->checkout->billing_form
1449
+				);
1450
+		}
1451
+		// get html and validation rules for form
1452
+		if ($this->checkout->billing_form instanceof EE_Form_Section_Proper) {
1453
+			$this->checkout->json_response->set_return_data(
1454
+				array('payment_method_info' => $this->checkout->billing_form->get_html())
1455
+			);
1456
+			// localize validation rules for main form
1457
+			$this->checkout->billing_form->localize_validation_rules(true);
1458
+			$this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1459
+		} else {
1460
+			$this->checkout->json_response->set_return_data(array('payment_method_info' => ''));
1461
+		}
1462
+		// prevents advancement to next step
1463
+		$this->checkout->continue_reg = false;
1464
+		return true;
1465
+	}
1466
+
1467
+
1468
+	/**
1469
+	 * _verify_payment_method_is_set
1470
+	 *
1471
+	 * @return bool
1472
+	 * @throws EE_Error
1473
+	 * @throws InvalidArgumentException
1474
+	 * @throws ReflectionException
1475
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1476
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1477
+	 */
1478
+	protected function _verify_payment_method_is_set()
1479
+	{
1480
+		// generate billing form for selected method of payment if it hasn't been done already
1481
+		if (empty($this->checkout->selected_method_of_payment)) {
1482
+			// how have they chosen to pay?
1483
+			$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1484
+		} else {
1485
+			// choose your own adventure based on method_of_payment
1486
+			switch ($this->checkout->selected_method_of_payment) {
1487
+				case 'events_sold_out':
1488
+					EE_Error::add_attention(
1489
+						apply_filters(
1490
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__sold_out_events_msg',
1491
+							esc_html__(
1492
+								'It appears that the event you were about to make a payment for has sold out since this form first loaded. Please contact the event administrator if you believe this is an error.',
1493
+								'event_espresso'
1494
+							)
1495
+						),
1496
+						__FILE__,
1497
+						__FUNCTION__,
1498
+						__LINE__
1499
+					);
1500
+					return false;
1501
+					break;
1502
+				case 'payments_closed':
1503
+					EE_Error::add_attention(
1504
+						apply_filters(
1505
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__payments_closed_msg',
1506
+							esc_html__(
1507
+								'It appears that the event you were about to make a payment for is not accepting payments at this time. Please contact the event administrator if you believe this is an error.',
1508
+								'event_espresso'
1509
+							)
1510
+						),
1511
+						__FILE__,
1512
+						__FUNCTION__,
1513
+						__LINE__
1514
+					);
1515
+					return false;
1516
+					break;
1517
+				case 'no_payment_required':
1518
+					EE_Error::add_attention(
1519
+						apply_filters(
1520
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__no_payment_required_msg',
1521
+							esc_html__(
1522
+								'It appears that the event you were about to make a payment for does not require payment. Please contact the event administrator if you believe this is an error.',
1523
+								'event_espresso'
1524
+							)
1525
+						),
1526
+						__FILE__,
1527
+						__FUNCTION__,
1528
+						__LINE__
1529
+					);
1530
+					return false;
1531
+					break;
1532
+				default:
1533
+			}
1534
+		}
1535
+		// verify payment method
1536
+		if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1537
+			// get payment method for selected method of payment
1538
+			$this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1539
+		}
1540
+		return $this->checkout->payment_method instanceof EE_Payment_Method ? true : false;
1541
+	}
1542
+
1543
+
1544
+
1545
+	/********************************************************************************************************/
1546
+	/***************************************  SAVE PAYER DETAILS  ****************************************/
1547
+	/********************************************************************************************************/
1548
+	/**
1549
+	 * save_payer_details_via_ajax
1550
+	 *
1551
+	 * @return void
1552
+	 * @throws EE_Error
1553
+	 * @throws InvalidArgumentException
1554
+	 * @throws ReflectionException
1555
+	 * @throws RuntimeException
1556
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1557
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1558
+	 */
1559
+	public function save_payer_details_via_ajax()
1560
+	{
1561
+		if (! $this->_verify_payment_method_is_set()) {
1562
+			return;
1563
+		}
1564
+		// generate billing form for selected method of payment if it hasn't been done already
1565
+		if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1566
+			$this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1567
+				$this->checkout->payment_method
1568
+			);
1569
+		}
1570
+		// generate primary attendee from payer info if applicable
1571
+		if (! $this->checkout->transaction_has_primary_registrant()) {
1572
+			$attendee = $this->_create_attendee_from_request_data();
1573
+			if ($attendee instanceof EE_Attendee) {
1574
+				foreach ($this->checkout->transaction->registrations() as $registration) {
1575
+					if ($registration->is_primary_registrant()) {
1576
+						$this->checkout->primary_attendee_obj = $attendee;
1577
+						$registration->_add_relation_to($attendee, 'Attendee');
1578
+						$registration->set_attendee_id($attendee->ID());
1579
+						$registration->update_cache_after_object_save('Attendee', $attendee);
1580
+					}
1581
+				}
1582
+			}
1583
+		}
1584
+	}
1585
+
1586
+
1587
+	/**
1588
+	 * create_attendee_from_request_data
1589
+	 * uses info from alternate GET or POST data (such as AJAX) to create a new attendee
1590
+	 *
1591
+	 * @return EE_Attendee
1592
+	 * @throws EE_Error
1593
+	 * @throws InvalidArgumentException
1594
+	 * @throws ReflectionException
1595
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1596
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1597
+	 */
1598
+	protected function _create_attendee_from_request_data()
1599
+	{
1600
+		// get State ID
1601
+		$STA_ID = ! empty($_REQUEST['state']) ? sanitize_text_field($_REQUEST['state']) : '';
1602
+		if (! empty($STA_ID)) {
1603
+			// can we get state object from name ?
1604
+			EE_Registry::instance()->load_model('State');
1605
+			$state = EEM_State::instance()->get_col(array(array('STA_name' => $STA_ID), 'limit' => 1), 'STA_ID');
1606
+			$STA_ID = is_array($state) && ! empty($state) ? reset($state) : $STA_ID;
1607
+		}
1608
+		// get Country ISO
1609
+		$CNT_ISO = ! empty($_REQUEST['country']) ? sanitize_text_field($_REQUEST['country']) : '';
1610
+		if (! empty($CNT_ISO)) {
1611
+			// can we get country object from name ?
1612
+			EE_Registry::instance()->load_model('Country');
1613
+			$country = EEM_Country::instance()->get_col(
1614
+				array(array('CNT_name' => $CNT_ISO), 'limit' => 1),
1615
+				'CNT_ISO'
1616
+			);
1617
+			$CNT_ISO = is_array($country) && ! empty($country) ? reset($country) : $CNT_ISO;
1618
+		}
1619
+		// grab attendee data
1620
+		$attendee_data = array(
1621
+			'ATT_fname'    => ! empty($_REQUEST['first_name']) ? sanitize_text_field($_REQUEST['first_name']) : '',
1622
+			'ATT_lname'    => ! empty($_REQUEST['last_name']) ? sanitize_text_field($_REQUEST['last_name']) : '',
1623
+			'ATT_email'    => ! empty($_REQUEST['email']) ? sanitize_email($_REQUEST['email']) : '',
1624
+			'ATT_address'  => ! empty($_REQUEST['address']) ? sanitize_text_field($_REQUEST['address']) : '',
1625
+			'ATT_address2' => ! empty($_REQUEST['address2']) ? sanitize_text_field($_REQUEST['address2']) : '',
1626
+			'ATT_city'     => ! empty($_REQUEST['city']) ? sanitize_text_field($_REQUEST['city']) : '',
1627
+			'STA_ID'       => $STA_ID,
1628
+			'CNT_ISO'      => $CNT_ISO,
1629
+			'ATT_zip'      => ! empty($_REQUEST['zip']) ? sanitize_text_field($_REQUEST['zip']) : '',
1630
+			'ATT_phone'    => ! empty($_REQUEST['phone']) ? sanitize_text_field($_REQUEST['phone']) : '',
1631
+		);
1632
+		// validate the email address since it is the most important piece of info
1633
+		if (empty($attendee_data['ATT_email']) || $attendee_data['ATT_email'] !== $_REQUEST['email']) {
1634
+			EE_Error::add_error(
1635
+				esc_html__('An invalid email address was submitted.', 'event_espresso'),
1636
+				__FILE__,
1637
+				__FUNCTION__,
1638
+				__LINE__
1639
+			);
1640
+		}
1641
+		// does this attendee already exist in the db ? we're searching using a combination of first name, last name,
1642
+		// AND email address
1643
+		if (
1644
+			! empty($attendee_data['ATT_fname'])
1645
+			&& ! empty($attendee_data['ATT_lname'])
1646
+			&& ! empty($attendee_data['ATT_email'])
1647
+		) {
1648
+			$existing_attendee = EE_Registry::instance()->LIB->EEM_Attendee->find_existing_attendee(
1649
+				array(
1650
+					'ATT_fname' => $attendee_data['ATT_fname'],
1651
+					'ATT_lname' => $attendee_data['ATT_lname'],
1652
+					'ATT_email' => $attendee_data['ATT_email'],
1653
+				)
1654
+			);
1655
+			if ($existing_attendee instanceof EE_Attendee) {
1656
+				return $existing_attendee;
1657
+			}
1658
+		}
1659
+		// no existing attendee? kk let's create a new one
1660
+		// kinda lame, but we need a first and last name to create an attendee, so use the email address if those
1661
+		// don't exist
1662
+		$attendee_data['ATT_fname'] = ! empty($attendee_data['ATT_fname'])
1663
+			? $attendee_data['ATT_fname']
1664
+			: $attendee_data['ATT_email'];
1665
+		$attendee_data['ATT_lname'] = ! empty($attendee_data['ATT_lname'])
1666
+			? $attendee_data['ATT_lname']
1667
+			: $attendee_data['ATT_email'];
1668
+		return EE_Attendee::new_instance($attendee_data);
1669
+	}
1670
+
1671
+
1672
+
1673
+	/********************************************************************************************************/
1674
+	/****************************************  PROCESS REG STEP  *****************************************/
1675
+	/********************************************************************************************************/
1676
+	/**
1677
+	 * process_reg_step
1678
+	 *
1679
+	 * @return bool
1680
+	 * @throws EE_Error
1681
+	 * @throws InvalidArgumentException
1682
+	 * @throws ReflectionException
1683
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1684
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1685
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1686
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
1687
+	 */
1688
+	public function process_reg_step()
1689
+	{
1690
+		// how have they chosen to pay?
1691
+		$this->checkout->selected_method_of_payment = $this->checkout->transaction->is_free()
1692
+			? 'no_payment_required'
1693
+			: $this->_get_selected_method_of_payment(true);
1694
+		// choose your own adventure based on method_of_payment
1695
+		switch ($this->checkout->selected_method_of_payment) {
1696
+			case 'events_sold_out':
1697
+				$this->checkout->redirect = true;
1698
+				$this->checkout->redirect_url = $this->checkout->cancel_page_url;
1699
+				$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1700
+				// mark this reg step as completed
1701
+				$this->set_completed();
1702
+				return false;
1703
+				break;
1704
+
1705
+			case 'payments_closed':
1706
+				if (
1707
+					apply_filters(
1708
+						'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__payments_closed__display_success',
1709
+						false
1710
+					)
1711
+				) {
1712
+					EE_Error::add_success(
1713
+						esc_html__('no payment required at this time.', 'event_espresso'),
1714
+						__FILE__,
1715
+						__FUNCTION__,
1716
+						__LINE__
1717
+					);
1718
+				}
1719
+				// mark this reg step as completed
1720
+				$this->set_completed();
1721
+				return true;
1722
+				break;
1723
+
1724
+			case 'no_payment_required':
1725
+				if (
1726
+					apply_filters(
1727
+						'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__no_payment_required__display_success',
1728
+						false
1729
+					)
1730
+				) {
1731
+					EE_Error::add_success(
1732
+						esc_html__('no payment required.', 'event_espresso'),
1733
+						__FILE__,
1734
+						__FUNCTION__,
1735
+						__LINE__
1736
+					);
1737
+				}
1738
+				// mark this reg step as completed
1739
+				$this->set_completed();
1740
+				return true;
1741
+				break;
1742
+
1743
+			default:
1744
+				$registrations = EE_Registry::instance()->SSN->checkout()->transaction->registrations(
1745
+					EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
1746
+				);
1747
+				$ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
1748
+					$registrations,
1749
+					EE_Registry::instance()->SSN->checkout()->revisit
1750
+				);
1751
+				// calculate difference between the two arrays
1752
+				$registrations = array_diff($registrations, $ejected_registrations);
1753
+				if (empty($registrations)) {
1754
+					$this->_redirect_because_event_sold_out();
1755
+					return false;
1756
+				}
1757
+				$payment_successful = $this->_process_payment();
1758
+				if ($payment_successful) {
1759
+					$this->checkout->continue_reg = true;
1760
+					$this->_maybe_set_completed($this->checkout->payment_method);
1761
+				} else {
1762
+					$this->checkout->continue_reg = false;
1763
+				}
1764
+				return $payment_successful;
1765
+		}
1766
+	}
1767
+
1768
+
1769
+	/**
1770
+	 * _redirect_because_event_sold_out
1771
+	 *
1772
+	 * @access protected
1773
+	 * @return void
1774
+	 */
1775
+	protected function _redirect_because_event_sold_out()
1776
+	{
1777
+		$this->checkout->continue_reg = false;
1778
+		// set redirect URL
1779
+		$this->checkout->redirect_url = add_query_arg(
1780
+			array('e_reg_url_link' => $this->checkout->reg_url_link),
1781
+			$this->checkout->current_step->reg_step_url()
1782
+		);
1783
+		$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1784
+	}
1785
+
1786
+
1787
+	/**
1788
+	 * _maybe_set_completed
1789
+	 *
1790
+	 * @access protected
1791
+	 * @param \EE_Payment_Method $payment_method
1792
+	 * @return void
1793
+	 * @throws \EE_Error
1794
+	 */
1795
+	protected function _maybe_set_completed(EE_Payment_Method $payment_method)
1796
+	{
1797
+		switch ($payment_method->type_obj()->payment_occurs()) {
1798
+			case EE_PMT_Base::offsite:
1799
+				break;
1800
+			case EE_PMT_Base::onsite:
1801
+			case EE_PMT_Base::offline:
1802
+				// mark this reg step as completed
1803
+				$this->set_completed();
1804
+				break;
1805
+		}
1806
+	}
1807
+
1808
+
1809
+	/**
1810
+	 *    update_reg_step
1811
+	 *    this is the final step after a user  revisits the site to retry a payment
1812
+	 *
1813
+	 * @return bool
1814
+	 * @throws EE_Error
1815
+	 * @throws InvalidArgumentException
1816
+	 * @throws ReflectionException
1817
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1818
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1819
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1820
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
1821
+	 */
1822
+	public function update_reg_step()
1823
+	{
1824
+		$success = true;
1825
+		// if payment required
1826
+		if ($this->checkout->transaction->total() > 0) {
1827
+			do_action(
1828
+				'AHEE__EE_Single_Page_Checkout__process_finalize_registration__before_gateway',
1829
+				$this->checkout->transaction
1830
+			);
1831
+			// attempt payment via payment method
1832
+			$success = $this->process_reg_step();
1833
+		}
1834
+		if ($success && ! $this->checkout->redirect) {
1835
+			$this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn(
1836
+				$this->checkout->transaction->ID()
1837
+			);
1838
+			// set return URL
1839
+			$this->checkout->redirect_url = add_query_arg(
1840
+				array('e_reg_url_link' => $this->checkout->reg_url_link),
1841
+				$this->checkout->thank_you_page_url
1842
+			);
1843
+		}
1844
+		return $success;
1845
+	}
1846
+
1847
+
1848
+	/**
1849
+	 *    _process_payment
1850
+	 *
1851
+	 * @access private
1852
+	 * @return bool
1853
+	 * @throws EE_Error
1854
+	 * @throws InvalidArgumentException
1855
+	 * @throws ReflectionException
1856
+	 * @throws RuntimeException
1857
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1858
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1859
+	 */
1860
+	private function _process_payment()
1861
+	{
1862
+		// basically confirm that the event hasn't sold out since they hit the page
1863
+		if (! $this->_last_second_ticket_verifications()) {
1864
+			return false;
1865
+		}
1866
+		// ya gotta make a choice man
1867
+		if (empty($this->checkout->selected_method_of_payment)) {
1868
+			$this->checkout->json_response->set_plz_select_method_of_payment(
1869
+				esc_html__('Please select a method of payment before proceeding.', 'event_espresso')
1870
+			);
1871
+			return false;
1872
+		}
1873
+		// get EE_Payment_Method object
1874
+		if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1875
+			return false;
1876
+		}
1877
+		// setup billing form
1878
+		if ($this->checkout->payment_method->is_on_site()) {
1879
+			$this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1880
+				$this->checkout->payment_method
1881
+			);
1882
+			// bad billing form ?
1883
+			if (! $this->_billing_form_is_valid()) {
1884
+				return false;
1885
+			}
1886
+		}
1887
+		// ensure primary registrant has been fully processed
1888
+		if (! $this->_setup_primary_registrant_prior_to_payment()) {
1889
+			return false;
1890
+		}
1891
+		// if session is close to expiring (under 10 minutes by default)
1892
+		if ((time() - EE_Registry::instance()->SSN->expiration()) < EE_Registry::instance()->SSN->extension()) {
1893
+			// add some time to session expiration so that payment can be completed
1894
+			EE_Registry::instance()->SSN->extend_expiration();
1895
+		}
1896
+		/** @type EE_Transaction_Processor $transaction_processor */
1897
+		// $transaction_processor = EE_Registry::instance()->load_class( 'Transaction_Processor' );
1898
+		// in case a registrant leaves to an Off-Site Gateway and never returns, we want to approve any registrations
1899
+		// for events with a default reg status of Approved
1900
+		// $transaction_processor->toggle_registration_statuses_for_default_approved_events(
1901
+		//      $this->checkout->transaction, $this->checkout->reg_cache_where_params
1902
+		// );
1903
+		// attempt payment
1904
+		$payment = $this->_attempt_payment($this->checkout->payment_method);
1905
+		// process results
1906
+		$payment = $this->_validate_payment($payment);
1907
+		$payment = $this->_post_payment_processing($payment);
1908
+		// verify payment
1909
+		if ($payment instanceof EE_Payment) {
1910
+			// store that for later
1911
+			$this->checkout->payment = $payment;
1912
+			// we can also consider the TXN to not have been failed, so temporarily upgrade it's status to abandoned
1913
+			$this->checkout->transaction->toggle_failed_transaction_status();
1914
+			$payment_status = $payment->status();
1915
+			if (
1916
+				$payment_status === EEM_Payment::status_id_approved
1917
+				|| $payment_status === EEM_Payment::status_id_pending
1918
+			) {
1919
+				return true;
1920
+			} else {
1921
+				return false;
1922
+			}
1923
+		} elseif ($payment === true) {
1924
+			// please note that offline payment methods will NOT make a payment,
1925
+			// but instead just mark themselves as the PMD_ID on the transaction, and return true
1926
+			$this->checkout->payment = $payment;
1927
+			return true;
1928
+		}
1929
+		// where's my money?
1930
+		return false;
1931
+	}
1932
+
1933
+
1934
+	/**
1935
+	 * _last_second_ticket_verifications
1936
+	 *
1937
+	 * @access public
1938
+	 * @return bool
1939
+	 * @throws EE_Error
1940
+	 */
1941
+	protected function _last_second_ticket_verifications()
1942
+	{
1943
+		// don't bother re-validating if not a return visit
1944
+		if (! $this->checkout->revisit) {
1945
+			return true;
1946
+		}
1947
+		$registrations = $this->checkout->transaction->registrations();
1948
+		if (empty($registrations)) {
1949
+			return false;
1950
+		}
1951
+		foreach ($registrations as $registration) {
1952
+			if ($registration instanceof EE_Registration && ! $registration->is_approved()) {
1953
+				$event = $registration->event_obj();
1954
+				if ($event instanceof EE_Event && $event->is_sold_out(true)) {
1955
+					EE_Error::add_error(
1956
+						apply_filters(
1957
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___last_second_ticket_verifications__sold_out_events_msg',
1958
+							sprintf(
1959
+								esc_html__(
1960
+									'It appears that the %1$s event that you were about to make a payment for has sold out since you first registered and/or arrived at this page. Please refresh the page and try again. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
1961
+									'event_espresso'
1962
+								),
1963
+								$event->name()
1964
+							)
1965
+						),
1966
+						__FILE__,
1967
+						__FUNCTION__,
1968
+						__LINE__
1969
+					);
1970
+					return false;
1971
+				}
1972
+			}
1973
+		}
1974
+		return true;
1975
+	}
1976
+
1977
+
1978
+	/**
1979
+	 * redirect_form
1980
+	 *
1981
+	 * @access public
1982
+	 * @return bool
1983
+	 * @throws EE_Error
1984
+	 * @throws InvalidArgumentException
1985
+	 * @throws ReflectionException
1986
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1987
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1988
+	 */
1989
+	public function redirect_form()
1990
+	{
1991
+		$payment_method_billing_info = $this->_payment_method_billing_info(
1992
+			$this->_get_payment_method_for_selected_method_of_payment()
1993
+		);
1994
+		$html = $payment_method_billing_info->get_html();
1995
+		$html .= $this->checkout->redirect_form;
1996
+		EE_Registry::instance()->REQ->add_output($html);
1997
+		return true;
1998
+	}
1999
+
2000
+
2001
+	/**
2002
+	 * _billing_form_is_valid
2003
+	 *
2004
+	 * @access private
2005
+	 * @return bool
2006
+	 * @throws \EE_Error
2007
+	 */
2008
+	private function _billing_form_is_valid()
2009
+	{
2010
+		if (! $this->checkout->payment_method->type_obj()->has_billing_form()) {
2011
+			return true;
2012
+		}
2013
+		if ($this->checkout->billing_form instanceof EE_Billing_Info_Form) {
2014
+			if ($this->checkout->billing_form->was_submitted()) {
2015
+				$this->checkout->billing_form->receive_form_submission();
2016
+				if ($this->checkout->billing_form->is_valid()) {
2017
+					return true;
2018
+				}
2019
+				$validation_errors = $this->checkout->billing_form->get_validation_errors_accumulated();
2020
+				$error_strings = array();
2021
+				foreach ($validation_errors as $validation_error) {
2022
+					if ($validation_error instanceof EE_Validation_Error) {
2023
+						$form_section = $validation_error->get_form_section();
2024
+						if ($form_section instanceof EE_Form_Input_Base) {
2025
+							$label = $form_section->html_label_text();
2026
+						} elseif ($form_section instanceof EE_Form_Section_Base) {
2027
+							$label = $form_section->name();
2028
+						} else {
2029
+							$label = esc_html__('Validation Error', 'event_espresso');
2030
+						}
2031
+						$error_strings[] = sprintf('%1$s: %2$s', $label, $validation_error->getMessage());
2032
+					}
2033
+				}
2034
+				EE_Error::add_error(
2035
+					sprintf(
2036
+						esc_html__(
2037
+							'One or more billing form inputs are invalid and require correction before proceeding. %1$s %2$s',
2038
+							'event_espresso'
2039
+						),
2040
+						'<br/>',
2041
+						implode('<br/>', $error_strings)
2042
+					),
2043
+					__FILE__,
2044
+					__FUNCTION__,
2045
+					__LINE__
2046
+				);
2047
+			} else {
2048
+				EE_Error::add_error(
2049
+					esc_html__(
2050
+						'The billing form was not submitted or something prevented it\'s submission.',
2051
+						'event_espresso'
2052
+					),
2053
+					__FILE__,
2054
+					__FUNCTION__,
2055
+					__LINE__
2056
+				);
2057
+			}
2058
+		} else {
2059
+			EE_Error::add_error(
2060
+				esc_html__(
2061
+					'The submitted billing form is invalid possibly due to a technical reason.',
2062
+					'event_espresso'
2063
+				),
2064
+				__FILE__,
2065
+				__FUNCTION__,
2066
+				__LINE__
2067
+			);
2068
+		}
2069
+		return false;
2070
+	}
2071
+
2072
+
2073
+	/**
2074
+	 * _setup_primary_registrant_prior_to_payment
2075
+	 * ensures that the primary registrant has a valid attendee object created with the critical details populated
2076
+	 * (first & last name & email) and that both the transaction object and primary registration object have been saved
2077
+	 * plz note that any other registrations will NOT be saved at this point (because they may not have any details
2078
+	 * yet)
2079
+	 *
2080
+	 * @access private
2081
+	 * @return bool
2082
+	 * @throws EE_Error
2083
+	 * @throws InvalidArgumentException
2084
+	 * @throws ReflectionException
2085
+	 * @throws RuntimeException
2086
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2087
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2088
+	 */
2089
+	private function _setup_primary_registrant_prior_to_payment()
2090
+	{
2091
+		// check if transaction has a primary registrant and that it has a related Attendee object
2092
+		// if not, then we need to at least gather some primary registrant data before attempting payment
2093
+		if (
2094
+			$this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
2095
+			&& ! $this->checkout->transaction_has_primary_registrant()
2096
+			&& ! $this->_capture_primary_registration_data_from_billing_form()
2097
+		) {
2098
+			return false;
2099
+		}
2100
+		// because saving an object clears it's cache, we need to do the chevy shuffle
2101
+		// grab the primary_registration object
2102
+		$primary_registration = $this->checkout->transaction->primary_registration();
2103
+		// at this point we'll consider a TXN to not have been failed
2104
+		$this->checkout->transaction->toggle_failed_transaction_status();
2105
+		// save the TXN ( which clears cached copy of primary_registration)
2106
+		$this->checkout->transaction->save();
2107
+		// grab TXN ID and save it to the primary_registration
2108
+		$primary_registration->set_transaction_id($this->checkout->transaction->ID());
2109
+		// save what we have so far
2110
+		$primary_registration->save();
2111
+		return true;
2112
+	}
2113
+
2114
+
2115
+	/**
2116
+	 * _capture_primary_registration_data_from_billing_form
2117
+	 *
2118
+	 * @access private
2119
+	 * @return bool
2120
+	 * @throws EE_Error
2121
+	 * @throws InvalidArgumentException
2122
+	 * @throws ReflectionException
2123
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2124
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2125
+	 */
2126
+	private function _capture_primary_registration_data_from_billing_form()
2127
+	{
2128
+		// convert billing form data into an attendee
2129
+		$this->checkout->primary_attendee_obj = $this->checkout->billing_form->create_attendee_from_billing_form_data();
2130
+		if (! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2131
+			EE_Error::add_error(
2132
+				sprintf(
2133
+					esc_html__(
2134
+						'The billing form details could not be used for attendee details due to a technical issue.%sPlease try again or contact %s for assistance.',
2135
+						'event_espresso'
2136
+					),
2137
+					'<br/>',
2138
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2139
+				),
2140
+				__FILE__,
2141
+				__FUNCTION__,
2142
+				__LINE__
2143
+			);
2144
+			return false;
2145
+		}
2146
+		$primary_registration = $this->checkout->transaction->primary_registration();
2147
+		if (! $primary_registration instanceof EE_Registration) {
2148
+			EE_Error::add_error(
2149
+				sprintf(
2150
+					esc_html__(
2151
+						'The primary registrant for this transaction could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2152
+						'event_espresso'
2153
+					),
2154
+					'<br/>',
2155
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2156
+				),
2157
+				__FILE__,
2158
+				__FUNCTION__,
2159
+				__LINE__
2160
+			);
2161
+			return false;
2162
+		}
2163
+		if (
2164
+			! $primary_registration->_add_relation_to($this->checkout->primary_attendee_obj, 'Attendee')
2165
+			  instanceof
2166
+			  EE_Attendee
2167
+		) {
2168
+			EE_Error::add_error(
2169
+				sprintf(
2170
+					esc_html__(
2171
+						'The primary registrant could not be associated with this transaction due to a technical issue.%sPlease try again or contact %s for assistance.',
2172
+						'event_espresso'
2173
+					),
2174
+					'<br/>',
2175
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2176
+				),
2177
+				__FILE__,
2178
+				__FUNCTION__,
2179
+				__LINE__
2180
+			);
2181
+			return false;
2182
+		}
2183
+		/** @type EE_Registration_Processor $registration_processor */
2184
+		$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
2185
+		// at this point, we should have enough details about the registrant to consider the registration NOT incomplete
2186
+		$registration_processor->toggle_incomplete_registration_status_to_default($primary_registration);
2187
+		return true;
2188
+	}
2189
+
2190
+
2191
+	/**
2192
+	 * _get_payment_method_for_selected_method_of_payment
2193
+	 * retrieves a valid payment method
2194
+	 *
2195
+	 * @access public
2196
+	 * @return EE_Payment_Method
2197
+	 * @throws EE_Error
2198
+	 * @throws InvalidArgumentException
2199
+	 * @throws ReflectionException
2200
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2201
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2202
+	 */
2203
+	private function _get_payment_method_for_selected_method_of_payment()
2204
+	{
2205
+		if ($this->checkout->selected_method_of_payment === 'events_sold_out') {
2206
+			$this->_redirect_because_event_sold_out();
2207
+			return null;
2208
+		}
2209
+		// get EE_Payment_Method object
2210
+		if (isset($this->checkout->available_payment_methods[ $this->checkout->selected_method_of_payment ])) {
2211
+			$payment_method = $this->checkout->available_payment_methods[ $this->checkout->selected_method_of_payment ];
2212
+		} else {
2213
+			// load EEM_Payment_Method
2214
+			EE_Registry::instance()->load_model('Payment_Method');
2215
+			/** @type EEM_Payment_Method $EEM_Payment_Method */
2216
+			$EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
2217
+			$payment_method = $EEM_Payment_Method->get_one_by_slug($this->checkout->selected_method_of_payment);
2218
+		}
2219
+		// verify $payment_method
2220
+		if (! $payment_method instanceof EE_Payment_Method) {
2221
+			// not a payment
2222
+			EE_Error::add_error(
2223
+				sprintf(
2224
+					esc_html__(
2225
+						'The selected method of payment could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2226
+						'event_espresso'
2227
+					),
2228
+					'<br/>',
2229
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2230
+				),
2231
+				__FILE__,
2232
+				__FUNCTION__,
2233
+				__LINE__
2234
+			);
2235
+			return null;
2236
+		}
2237
+		// and verify it has a valid Payment_Method Type object
2238
+		if (! $payment_method->type_obj() instanceof EE_PMT_Base) {
2239
+			// not a payment
2240
+			EE_Error::add_error(
2241
+				sprintf(
2242
+					esc_html__(
2243
+						'A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2244
+						'event_espresso'
2245
+					),
2246
+					'<br/>',
2247
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2248
+				),
2249
+				__FILE__,
2250
+				__FUNCTION__,
2251
+				__LINE__
2252
+			);
2253
+			return null;
2254
+		}
2255
+		return $payment_method;
2256
+	}
2257
+
2258
+
2259
+	/**
2260
+	 *    _attempt_payment
2261
+	 *
2262
+	 * @access    private
2263
+	 * @type    EE_Payment_Method $payment_method
2264
+	 * @return mixed EE_Payment | boolean
2265
+	 * @throws EE_Error
2266
+	 * @throws InvalidArgumentException
2267
+	 * @throws ReflectionException
2268
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2269
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2270
+	 */
2271
+	private function _attempt_payment(EE_Payment_Method $payment_method)
2272
+	{
2273
+		$payment = null;
2274
+		$this->checkout->transaction->save();
2275
+		$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2276
+		if (! $payment_processor instanceof EE_Payment_Processor) {
2277
+			return false;
2278
+		}
2279
+		try {
2280
+			$payment_processor->set_revisit($this->checkout->revisit);
2281
+			// generate payment object
2282
+			$payment = $payment_processor->process_payment(
2283
+				$payment_method,
2284
+				$this->checkout->transaction,
2285
+				$this->checkout->amount_owing,
2286
+				$this->checkout->billing_form,
2287
+				$this->_get_return_url($payment_method),
2288
+				'CART',
2289
+				$this->checkout->admin_request,
2290
+				true,
2291
+				$this->reg_step_url()
2292
+			);
2293
+		} catch (Exception $e) {
2294
+			$this->_handle_payment_processor_exception($e);
2295
+		}
2296
+		return $payment;
2297
+	}
2298
+
2299
+
2300
+	/**
2301
+	 * _handle_payment_processor_exception
2302
+	 *
2303
+	 * @access protected
2304
+	 * @param \Exception $e
2305
+	 * @return void
2306
+	 * @throws EE_Error
2307
+	 * @throws InvalidArgumentException
2308
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2309
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2310
+	 */
2311
+	protected function _handle_payment_processor_exception(Exception $e)
2312
+	{
2313
+		EE_Error::add_error(
2314
+			sprintf(
2315
+				esc_html__(
2316
+					'The payment could not br processed due to a technical issue.%1$sPlease try again or contact %2$s for assistance.||The following Exception was thrown in %4$s on line %5$s:%1$s%3$s',
2317
+					'event_espresso'
2318
+				),
2319
+				'<br/>',
2320
+				EE_Registry::instance()->CFG->organization->get_pretty('email'),
2321
+				$e->getMessage(),
2322
+				$e->getFile(),
2323
+				$e->getLine()
2324
+			),
2325
+			__FILE__,
2326
+			__FUNCTION__,
2327
+			__LINE__
2328
+		);
2329
+	}
2330
+
2331
+
2332
+	/**
2333
+	 * _get_return_url
2334
+	 *
2335
+	 * @access protected
2336
+	 * @param \EE_Payment_Method $payment_method
2337
+	 * @return string
2338
+	 * @throws \EE_Error
2339
+	 */
2340
+	protected function _get_return_url(EE_Payment_Method $payment_method)
2341
+	{
2342
+		$return_url = '';
2343
+		switch ($payment_method->type_obj()->payment_occurs()) {
2344
+			case EE_PMT_Base::offsite:
2345
+				$return_url = add_query_arg(
2346
+					array(
2347
+						'action'                     => 'process_gateway_response',
2348
+						'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2349
+						'spco_txn'                   => $this->checkout->transaction->ID(),
2350
+					),
2351
+					$this->reg_step_url()
2352
+				);
2353
+				break;
2354
+			case EE_PMT_Base::onsite:
2355
+			case EE_PMT_Base::offline:
2356
+				$return_url = $this->checkout->next_step->reg_step_url();
2357
+				break;
2358
+		}
2359
+		return $return_url;
2360
+	}
2361
+
2362
+
2363
+	/**
2364
+	 * _validate_payment
2365
+	 *
2366
+	 * @access private
2367
+	 * @param EE_Payment $payment
2368
+	 * @return EE_Payment|FALSE
2369
+	 * @throws EE_Error
2370
+	 * @throws InvalidArgumentException
2371
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2372
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2373
+	 */
2374
+	private function _validate_payment($payment = null)
2375
+	{
2376
+		if ($this->checkout->payment_method->is_off_line()) {
2377
+			return true;
2378
+		}
2379
+		// verify payment object
2380
+		if (! $payment instanceof EE_Payment) {
2381
+			// not a payment
2382
+			EE_Error::add_error(
2383
+				sprintf(
2384
+					esc_html__(
2385
+						'A valid payment was not generated due to a technical issue.%1$sPlease try again or contact %2$s for assistance.',
2386
+						'event_espresso'
2387
+					),
2388
+					'<br/>',
2389
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2390
+				),
2391
+				__FILE__,
2392
+				__FUNCTION__,
2393
+				__LINE__
2394
+			);
2395
+			return false;
2396
+		}
2397
+		return $payment;
2398
+	}
2399
+
2400
+
2401
+	/**
2402
+	 * _post_payment_processing
2403
+	 *
2404
+	 * @access private
2405
+	 * @param EE_Payment|bool $payment
2406
+	 * @return bool
2407
+	 * @throws EE_Error
2408
+	 * @throws InvalidArgumentException
2409
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2410
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2411
+	 */
2412
+	private function _post_payment_processing($payment = null)
2413
+	{
2414
+		// Off-Line payment?
2415
+		if ($payment === true) {
2416
+			// $this->_setup_redirect_for_next_step();
2417
+			return true;
2418
+			// On-Site payment?
2419
+		} elseif ($this->checkout->payment_method->is_on_site()) {
2420
+			if (! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2421
+				// $this->_setup_redirect_for_next_step();
2422
+				$this->checkout->continue_reg = false;
2423
+			}
2424
+			// Off-Site payment?
2425
+		} elseif ($this->checkout->payment_method->is_off_site()) {
2426
+			// if a payment object was made and it specifies a redirect url, then we'll setup that redirect info
2427
+			if ($payment instanceof EE_Payment && $payment->redirect_url()) {
2428
+				do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->redirect_url(), '$payment->redirect_url()');
2429
+				$this->checkout->redirect = true;
2430
+				$this->checkout->redirect_form = $payment->redirect_form();
2431
+				$this->checkout->redirect_url = $this->reg_step_url('redirect_form');
2432
+				// set JSON response
2433
+				$this->checkout->json_response->set_redirect_form($this->checkout->redirect_form);
2434
+				// and lastly, let's bump the payment status to pending
2435
+				$payment->set_status(EEM_Payment::status_id_pending);
2436
+				$payment->save();
2437
+			} else {
2438
+				// we couldn't redirect the user. Let's tell them why.
2439
+				$error_message = sprintf(
2440
+					esc_html__(
2441
+						'It appears the Off Site Payment Method was not configured properly.%sPlease try again or contact %s for assistance.',
2442
+						'event_espresso'
2443
+					),
2444
+					'<br/>',
2445
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2446
+				);
2447
+				if ($payment instanceof EE_Payment && $payment->gateway_response()) {
2448
+					$error_message = $error_message . '<br/>' . $payment->gateway_response();
2449
+				}
2450
+				$this->checkout->continue_reg = false;
2451
+				EE_Error::add_error(
2452
+					$error_message,
2453
+					__FILE__,
2454
+					__FUNCTION__,
2455
+					__LINE__
2456
+				);
2457
+			}
2458
+		} else {
2459
+			// ummm ya... not Off-Line, not On-Site, not off-Site ????
2460
+			$this->checkout->continue_reg = false;
2461
+			return false;
2462
+		}
2463
+		return $payment;
2464
+	}
2465
+
2466
+
2467
+	/**
2468
+	 *    _process_payment_status
2469
+	 *
2470
+	 * @access private
2471
+	 * @type    EE_Payment $payment
2472
+	 * @param string       $payment_occurs
2473
+	 * @return bool
2474
+	 * @throws EE_Error
2475
+	 * @throws InvalidArgumentException
2476
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2477
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2478
+	 */
2479
+	private function _process_payment_status($payment, $payment_occurs = EE_PMT_Base::offline)
2480
+	{
2481
+		// off-line payment? carry on
2482
+		if ($payment_occurs === EE_PMT_Base::offline) {
2483
+			return true;
2484
+		}
2485
+		// verify payment validity
2486
+		if ($payment instanceof EE_Payment) {
2487
+			do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->status(), '$payment->status()');
2488
+			$msg = $payment->gateway_response();
2489
+			// check results
2490
+			switch ($payment->status()) {
2491
+				// good payment
2492
+				case EEM_Payment::status_id_approved:
2493
+					EE_Error::add_success(
2494
+						esc_html__('Your payment was processed successfully.', 'event_espresso'),
2495
+						__FILE__,
2496
+						__FUNCTION__,
2497
+						__LINE__
2498
+					);
2499
+					return true;
2500
+					break;
2501
+				// slow payment
2502
+				case EEM_Payment::status_id_pending:
2503
+					if (empty($msg)) {
2504
+						$msg = esc_html__(
2505
+							'Your payment appears to have been processed successfully, but the Instant Payment Notification has not yet been received. It should arrive shortly.',
2506
+							'event_espresso'
2507
+						);
2508
+					}
2509
+					EE_Error::add_success($msg, __FILE__, __FUNCTION__, __LINE__);
2510
+					return true;
2511
+					break;
2512
+				// don't wanna payment
2513
+				case EEM_Payment::status_id_cancelled:
2514
+					if (empty($msg)) {
2515
+						$msg = _n(
2516
+							'Payment cancelled. Please try again.',
2517
+							'Payment cancelled. Please try again or select another method of payment.',
2518
+							count($this->checkout->available_payment_methods),
2519
+							'event_espresso'
2520
+						);
2521
+					}
2522
+					EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2523
+					return false;
2524
+					break;
2525
+				// not enough payment
2526
+				case EEM_Payment::status_id_declined:
2527
+					if (empty($msg)) {
2528
+						$msg = _n(
2529
+							'We\'re sorry but your payment was declined. Please try again.',
2530
+							'We\'re sorry but your payment was declined. Please try again or select another method of payment.',
2531
+							count($this->checkout->available_payment_methods),
2532
+							'event_espresso'
2533
+						);
2534
+					}
2535
+					EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2536
+					return false;
2537
+					break;
2538
+				// bad payment
2539
+				case EEM_Payment::status_id_failed:
2540
+					if (! empty($msg)) {
2541
+						EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2542
+						return false;
2543
+					}
2544
+					// default to error below
2545
+					break;
2546
+			}
2547
+		}
2548
+		// off-site payment gateway responses are too unreliable, so let's just assume that
2549
+		// the payment processing is just running slower than the registrant's request
2550
+		if ($payment_occurs === EE_PMT_Base::offsite) {
2551
+			return true;
2552
+		}
2553
+		EE_Error::add_error(
2554
+			sprintf(
2555
+				esc_html__(
2556
+					'Your payment could not be processed successfully due to a technical issue.%sPlease try again or contact %s for assistance.',
2557
+					'event_espresso'
2558
+				),
2559
+				'<br/>',
2560
+				EE_Registry::instance()->CFG->organization->get_pretty('email')
2561
+			),
2562
+			__FILE__,
2563
+			__FUNCTION__,
2564
+			__LINE__
2565
+		);
2566
+		return false;
2567
+	}
2568
+
2569
+
2570
+
2571
+
2572
+
2573
+
2574
+	/********************************************************************************************************/
2575
+	/**********************************  PROCESS GATEWAY RESPONSE  **********************************/
2576
+	/********************************************************************************************************/
2577
+	/**
2578
+	 * process_gateway_response
2579
+	 * this is the return point for Off-Site Payment Methods
2580
+	 * It will attempt to "handle the IPN" if it appears that this has not already occurred,
2581
+	 * otherwise, it will load up the last payment made for the TXN.
2582
+	 * If the payment retrieved looks good, it will then either:
2583
+	 *    complete the current step and allow advancement to the next reg step
2584
+	 *        or present the payment options again
2585
+	 *
2586
+	 * @access private
2587
+	 * @return EE_Payment|FALSE
2588
+	 * @throws EE_Error
2589
+	 * @throws InvalidArgumentException
2590
+	 * @throws ReflectionException
2591
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2592
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2593
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2594
+	 */
2595
+	public function process_gateway_response()
2596
+	{
2597
+		$payment = null;
2598
+		// how have they chosen to pay?
2599
+		$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
2600
+		// get EE_Payment_Method object
2601
+		if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2602
+			$this->checkout->continue_reg = false;
2603
+			return false;
2604
+		}
2605
+		if (! $this->checkout->payment_method->is_off_site()) {
2606
+			return false;
2607
+		}
2608
+		$this->_validate_offsite_return();
2609
+		// DEBUG LOG
2610
+		// $this->checkout->log(
2611
+		//     __CLASS__,
2612
+		//     __FUNCTION__,
2613
+		//     __LINE__,
2614
+		//     array(
2615
+		//         'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2616
+		//         'payment_method'             => $this->checkout->payment_method,
2617
+		//     ),
2618
+		//     true
2619
+		// );
2620
+		// verify TXN
2621
+		if ($this->checkout->transaction instanceof EE_Transaction) {
2622
+			$gateway = $this->checkout->payment_method->type_obj()->get_gateway();
2623
+			if (! $gateway instanceof EE_Offsite_Gateway) {
2624
+				$this->checkout->continue_reg = false;
2625
+				return false;
2626
+			}
2627
+			$payment = $this->_process_off_site_payment($gateway);
2628
+			$payment = $this->_process_cancelled_payments($payment);
2629
+			$payment = $this->_validate_payment($payment);
2630
+			// if payment was not declined by the payment gateway or cancelled by the registrant
2631
+			if ($this->_process_payment_status($payment, EE_PMT_Base::offsite)) {
2632
+				// $this->_setup_redirect_for_next_step();
2633
+				// store that for later
2634
+				$this->checkout->payment = $payment;
2635
+				// mark this reg step as completed, as long as gateway doesn't use a separate IPN request,
2636
+				// because we will complete this step during the IPN processing then
2637
+				if ($gateway instanceof EE_Offsite_Gateway && ! $this->handle_IPN_in_this_request()) {
2638
+					$this->set_completed();
2639
+				}
2640
+				return true;
2641
+			}
2642
+		}
2643
+		// DEBUG LOG
2644
+		// $this->checkout->log(
2645
+		//     __CLASS__,
2646
+		//     __FUNCTION__,
2647
+		//     __LINE__,
2648
+		//     array('payment' => $payment)
2649
+		// );
2650
+		$this->checkout->continue_reg = false;
2651
+		return false;
2652
+	}
2653
+
2654
+
2655
+	/**
2656
+	 * _validate_return
2657
+	 *
2658
+	 * @access private
2659
+	 * @return void
2660
+	 * @throws EE_Error
2661
+	 * @throws InvalidArgumentException
2662
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2663
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2664
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2665
+	 */
2666
+	private function _validate_offsite_return()
2667
+	{
2668
+		$TXN_ID = (int) EE_Registry::instance()->REQ->get('spco_txn', 0);
2669
+		if ($TXN_ID !== $this->checkout->transaction->ID()) {
2670
+			// Houston... we might have a problem
2671
+			$invalid_TXN = false;
2672
+			// first gather some info
2673
+			$valid_TXN = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2674
+			$primary_registrant = $valid_TXN instanceof EE_Transaction
2675
+				? $valid_TXN->primary_registration()
2676
+				: null;
2677
+			// let's start by retrieving the cart for this TXN
2678
+			$cart = $this->checkout->get_cart_for_transaction($this->checkout->transaction);
2679
+			if ($cart instanceof EE_Cart) {
2680
+				// verify that the current cart has tickets
2681
+				$tickets = $cart->get_tickets();
2682
+				if (empty($tickets)) {
2683
+					$invalid_TXN = true;
2684
+				}
2685
+			} else {
2686
+				$invalid_TXN = true;
2687
+			}
2688
+			$valid_TXN_SID = $primary_registrant instanceof EE_Registration
2689
+				? $primary_registrant->session_ID()
2690
+				: null;
2691
+			// validate current Session ID and compare against valid TXN session ID
2692
+			if (
2693
+				$invalid_TXN // if this is already true, then skip other checks
2694
+				|| EE_Session::instance()->id() === null
2695
+				|| (
2696
+					// WARNING !!!
2697
+					// this could be PayPal sending back duplicate requests (ya they do that)
2698
+					// or it **could** mean someone is simply registering AGAIN after having just done so
2699
+					// so now we need to determine if this current TXN looks valid or not
2700
+					// and whether this reg step has even been started ?
2701
+					EE_Session::instance()->id() === $valid_TXN_SID
2702
+					// really? you're half way through this reg step, but you never started it ?
2703
+					&& $this->checkout->transaction->reg_step_completed($this->slug()) === false
2704
+				)
2705
+			) {
2706
+				$invalid_TXN = true;
2707
+			}
2708
+			if ($invalid_TXN) {
2709
+				// is the valid TXN completed ?
2710
+				if ($valid_TXN instanceof EE_Transaction) {
2711
+					// has this step even been started ?
2712
+					$reg_step_completed = $valid_TXN->reg_step_completed($this->slug());
2713
+					if ($reg_step_completed !== false && $reg_step_completed !== true) {
2714
+						// so it **looks** like this is a double request from PayPal
2715
+						// so let's try to pick up where we left off
2716
+						$this->checkout->transaction = $valid_TXN;
2717
+						$this->checkout->refresh_all_entities(true);
2718
+						return;
2719
+					}
2720
+				}
2721
+				// you appear to be lost?
2722
+				$this->_redirect_wayward_request($primary_registrant);
2723
+			}
2724
+		}
2725
+	}
2726
+
2727
+
2728
+	/**
2729
+	 * _redirect_wayward_request
2730
+	 *
2731
+	 * @access private
2732
+	 * @param \EE_Registration|null $primary_registrant
2733
+	 * @return bool
2734
+	 * @throws EE_Error
2735
+	 * @throws InvalidArgumentException
2736
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2737
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2738
+	 */
2739
+	private function _redirect_wayward_request(EE_Registration $primary_registrant)
2740
+	{
2741
+		if (! $primary_registrant instanceof EE_Registration) {
2742
+			// try redirecting based on the current TXN
2743
+			$primary_registrant = $this->checkout->transaction instanceof EE_Transaction
2744
+				? $this->checkout->transaction->primary_registration()
2745
+				: null;
2746
+		}
2747
+		if (! $primary_registrant instanceof EE_Registration) {
2748
+			EE_Error::add_error(
2749
+				sprintf(
2750
+					esc_html__(
2751
+						'Invalid information was received from the Off-Site Payment Processor and your Transaction details could not be retrieved from the database.%1$sPlease try again or contact %2$s for assistance.',
2752
+						'event_espresso'
2753
+					),
2754
+					'<br/>',
2755
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2756
+				),
2757
+				__FILE__,
2758
+				__FUNCTION__,
2759
+				__LINE__
2760
+			);
2761
+			return false;
2762
+		}
2763
+		// make sure transaction is not locked
2764
+		$this->checkout->transaction->unlock();
2765
+		wp_safe_redirect(
2766
+			add_query_arg(
2767
+				array(
2768
+					'e_reg_url_link' => $primary_registrant->reg_url_link(),
2769
+				),
2770
+				$this->checkout->thank_you_page_url
2771
+			)
2772
+		);
2773
+		exit();
2774
+	}
2775
+
2776
+
2777
+	/**
2778
+	 * _process_off_site_payment
2779
+	 *
2780
+	 * @access private
2781
+	 * @param \EE_Offsite_Gateway $gateway
2782
+	 * @return EE_Payment
2783
+	 * @throws EE_Error
2784
+	 * @throws InvalidArgumentException
2785
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2786
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2787
+	 */
2788
+	private function _process_off_site_payment(EE_Offsite_Gateway $gateway)
2789
+	{
2790
+		try {
2791
+			$request_data = \EE_Registry::instance()->REQ->params();
2792
+			// if gateway uses_separate_IPN_request, then we don't have to process the IPN manually
2793
+			$this->set_handle_IPN_in_this_request(
2794
+				$gateway->handle_IPN_in_this_request($request_data, false)
2795
+			);
2796
+			if ($this->handle_IPN_in_this_request()) {
2797
+				// get payment details and process results
2798
+				/** @type EE_Payment_Processor $payment_processor */
2799
+				$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2800
+				$payment = $payment_processor->process_ipn(
2801
+					$request_data,
2802
+					$this->checkout->transaction,
2803
+					$this->checkout->payment_method,
2804
+					true,
2805
+					false
2806
+				);
2807
+				// $payment_source = 'process_ipn';
2808
+			} else {
2809
+				$payment = $this->checkout->transaction->last_payment();
2810
+				// $payment_source = 'last_payment';
2811
+			}
2812
+		} catch (Exception $e) {
2813
+			// let's just eat the exception and try to move on using any previously set payment info
2814
+			$payment = $this->checkout->transaction->last_payment();
2815
+			// $payment_source = 'last_payment after Exception';
2816
+			// but if we STILL don't have a payment object
2817
+			if (! $payment instanceof EE_Payment) {
2818
+				// then we'll object ! ( not object like a thing... but object like what a lawyer says ! )
2819
+				$this->_handle_payment_processor_exception($e);
2820
+			}
2821
+		}
2822
+		// DEBUG LOG
2823
+		// $this->checkout->log(
2824
+		//     __CLASS__,
2825
+		//     __FUNCTION__,
2826
+		//     __LINE__,
2827
+		//     array(
2828
+		//         'process_ipn_payment' => $payment,
2829
+		//         'payment_source'      => $payment_source,
2830
+		//     )
2831
+		// );
2832
+		return $payment;
2833
+	}
2834
+
2835
+
2836
+	/**
2837
+	 * _process_cancelled_payments
2838
+	 * just makes sure that the payment status gets updated correctly
2839
+	 * so tha tan error isn't generated during payment validation
2840
+	 *
2841
+	 * @access private
2842
+	 * @param EE_Payment $payment
2843
+	 * @return EE_Payment | FALSE
2844
+	 * @throws \EE_Error
2845
+	 */
2846
+	private function _process_cancelled_payments($payment = null)
2847
+	{
2848
+		if (
2849
+			$payment instanceof EE_Payment
2850
+			&& isset($_REQUEST['ee_cancel_payment'])
2851
+			&& $payment->status() === EEM_Payment::status_id_failed
2852
+		) {
2853
+			$payment->set_status(EEM_Payment::status_id_cancelled);
2854
+		}
2855
+		return $payment;
2856
+	}
2857
+
2858
+
2859
+	/**
2860
+	 *    get_transaction_details_for_gateways
2861
+	 *
2862
+	 * @access    public
2863
+	 * @return int
2864
+	 * @throws EE_Error
2865
+	 * @throws InvalidArgumentException
2866
+	 * @throws ReflectionException
2867
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2868
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2869
+	 */
2870
+	public function get_transaction_details_for_gateways()
2871
+	{
2872
+		$txn_details = array();
2873
+		// ya gotta make a choice man
2874
+		if (empty($this->checkout->selected_method_of_payment)) {
2875
+			$txn_details = array(
2876
+				'error' => esc_html__('Please select a method of payment before proceeding.', 'event_espresso'),
2877
+			);
2878
+		}
2879
+		// get EE_Payment_Method object
2880
+		if (
2881
+			empty($txn_details)
2882
+			&&
2883
+			! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()
2884
+		) {
2885
+			$txn_details = array(
2886
+				'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2887
+				'error'                      => esc_html__(
2888
+					'A valid Payment Method could not be determined.',
2889
+					'event_espresso'
2890
+				),
2891
+			);
2892
+		}
2893
+		if (empty($txn_details) && $this->checkout->transaction instanceof EE_Transaction) {
2894
+			$return_url = $this->_get_return_url($this->checkout->payment_method);
2895
+			$txn_details = array(
2896
+				'TXN_ID'         => $this->checkout->transaction->ID(),
2897
+				'TXN_timestamp'  => $this->checkout->transaction->datetime(),
2898
+				'TXN_total'      => $this->checkout->transaction->total(),
2899
+				'TXN_paid'       => $this->checkout->transaction->paid(),
2900
+				'TXN_reg_steps'  => $this->checkout->transaction->reg_steps(),
2901
+				'STS_ID'         => $this->checkout->transaction->status_ID(),
2902
+				'PMD_ID'         => $this->checkout->transaction->payment_method_ID(),
2903
+				'payment_amount' => $this->checkout->amount_owing,
2904
+				'return_url'     => $return_url,
2905
+				'cancel_url'     => add_query_arg(array('ee_cancel_payment' => true), $return_url),
2906
+				'notify_url'     => EE_Config::instance()->core->txn_page_url(
2907
+					array(
2908
+						'e_reg_url_link'    => $this->checkout->transaction->primary_registration()->reg_url_link(),
2909
+						'ee_payment_method' => $this->checkout->payment_method->slug(),
2910
+					)
2911
+				),
2912
+			);
2913
+		}
2914
+		echo wp_json_encode($txn_details);
2915
+		exit();
2916
+	}
2917
+
2918
+
2919
+	/**
2920
+	 *    __sleep
2921
+	 * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon
2922
+	 * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the
2923
+	 * reg form, because if needed, it will be regenerated anyways
2924
+	 *
2925
+	 * @return array
2926
+	 */
2927
+	public function __sleep()
2928
+	{
2929
+		// remove the reg form and the checkout
2930
+		return array_diff(array_keys(get_object_vars($this)), array('reg_form', 'checkout', 'line_item_display'));
2931
+	}
2932 2932
 }
Please login to merge, or discard this patch.
Spacing   +74 added lines, -74 removed lines patch added patch discarded remove patch
@@ -129,7 +129,7 @@  discard block
 block discarded – undo
129 129
     {
130 130
         $this->_slug = 'payment_options';
131 131
         $this->_name = esc_html__('Payment Options', 'event_espresso');
132
-        $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . '/payment_options_main.template.php';
132
+        $this->_template = SPCO_REG_STEPS_PATH.$this->_slug.'/payment_options_main.template.php';
133 133
         $this->checkout = $checkout;
134 134
         $this->_reset_success_message();
135 135
         $this->set_instructions(
@@ -212,7 +212,7 @@  discard block
 block discarded – undo
212 212
     {
213 213
         $transaction = $this->checkout->transaction;
214 214
         // if the transaction isn't set or nothing is owed on it, don't enqueue any JS
215
-        if (! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
215
+        if ( ! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
216 216
             return;
217 217
         }
218 218
         foreach (
@@ -307,18 +307,18 @@  discard block
 block discarded – undo
307 307
         foreach ($registrations as $REG_ID => $registration) {
308 308
             /** @var $registration EE_Registration */
309 309
             // has this registration lost it's space ?
310
-            if (isset($ejected_registrations[ $REG_ID ])) {
310
+            if (isset($ejected_registrations[$REG_ID])) {
311 311
                 if ($registration->event()->is_sold_out() || $registration->event()->is_sold_out(true)) {
312
-                    $sold_out_events[ $registration->event()->ID() ] = $registration->event();
312
+                    $sold_out_events[$registration->event()->ID()] = $registration->event();
313 313
                 } else {
314
-                    $insufficient_spaces_available[ $registration->event()->ID() ] = $registration->event();
314
+                    $insufficient_spaces_available[$registration->event()->ID()] = $registration->event();
315 315
                 }
316 316
                 continue;
317 317
             }
318 318
             // event requires admin approval
319 319
             if ($registration->status_ID() === EEM_Registration::status_id_not_approved) {
320 320
                 // add event to list of events with pre-approval reg status
321
-                $registrations_requiring_pre_approval[ $REG_ID ] = $registration;
321
+                $registrations_requiring_pre_approval[$REG_ID] = $registration;
322 322
                 do_action(
323 323
                     'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_pre_approval',
324 324
                     $registration->event(),
@@ -335,7 +335,7 @@  discard block
 block discarded – undo
335 335
                 )
336 336
             ) {
337 337
                 // add event to list of events that are sold out
338
-                $sold_out_events[ $registration->event()->ID() ] = $registration->event();
338
+                $sold_out_events[$registration->event()->ID()] = $registration->event();
339 339
                 do_action(
340 340
                     'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__sold_out_event',
341 341
                     $registration->event(),
@@ -345,7 +345,7 @@  discard block
 block discarded – undo
345 345
             }
346 346
             // are they allowed to pay now and is there monies owing?
347 347
             if ($registration->owes_monies_and_can_pay()) {
348
-                $registrations_requiring_payment[ $REG_ID ] = $registration;
348
+                $registrations_requiring_payment[$REG_ID] = $registration;
349 349
                 do_action(
350 350
                     'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_payment',
351 351
                     $registration->event(),
@@ -356,28 +356,28 @@  discard block
 block discarded – undo
356 356
                       && $registration->status_ID() !== EEM_Registration::status_id_not_approved
357 357
                       && $registration->ticket()->is_free()
358 358
             ) {
359
-                $registrations_for_free_events[ $registration->ticket()->ID() ] = $registration;
359
+                $registrations_for_free_events[$registration->ticket()->ID()] = $registration;
360 360
             }
361 361
         }
362 362
         $subsections = array();
363 363
         // now decide which template to load
364
-        if (! empty($sold_out_events)) {
364
+        if ( ! empty($sold_out_events)) {
365 365
             $subsections['sold_out_events'] = $this->_sold_out_events($sold_out_events);
366 366
         }
367
-        if (! empty($insufficient_spaces_available)) {
367
+        if ( ! empty($insufficient_spaces_available)) {
368 368
             $subsections['insufficient_space'] = $this->_insufficient_spaces_available(
369 369
                 $insufficient_spaces_available
370 370
             );
371 371
         }
372
-        if (! empty($registrations_requiring_pre_approval)) {
372
+        if ( ! empty($registrations_requiring_pre_approval)) {
373 373
             $subsections['registrations_requiring_pre_approval'] = $this->_registrations_requiring_pre_approval(
374 374
                 $registrations_requiring_pre_approval
375 375
             );
376 376
         }
377
-        if (! empty($registrations_for_free_events)) {
377
+        if ( ! empty($registrations_for_free_events)) {
378 378
             $subsections['no_payment_required'] = $this->_no_payment_required($registrations_for_free_events);
379 379
         }
380
-        if (! empty($registrations_requiring_payment)) {
380
+        if ( ! empty($registrations_requiring_payment)) {
381 381
             if ($this->checkout->amount_owing > 0) {
382 382
                 // autoload Line_Item_Display classes
383 383
                 EEH_Autoloader::register_line_item_filter_autoloaders();
@@ -442,13 +442,13 @@  discard block
 block discarded – undo
442 442
      */
443 443
     public static function add_spco_line_item_filters(EE_Line_Item_Filter_Collection $line_item_filter_collection)
444 444
     {
445
-        if (! EE_Registry::instance()->SSN instanceof EE_Session) {
445
+        if ( ! EE_Registry::instance()->SSN instanceof EE_Session) {
446 446
             return $line_item_filter_collection;
447 447
         }
448
-        if (! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
448
+        if ( ! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
449 449
             return $line_item_filter_collection;
450 450
         }
451
-        if (! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
451
+        if ( ! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
452 452
             return $line_item_filter_collection;
453 453
         }
454 454
         $line_item_filter_collection->add(
@@ -488,8 +488,8 @@  discard block
 block discarded – undo
488 488
         );
489 489
         foreach ($registrations as $REG_ID => $registration) {
490 490
             // has this registration lost it's space ?
491
-            if (isset($ejected_registrations[ $REG_ID ])) {
492
-                unset($registrations[ $REG_ID ]);
491
+            if (isset($ejected_registrations[$REG_ID])) {
492
+                unset($registrations[$REG_ID]);
493 493
                 continue;
494 494
             }
495 495
         }
@@ -540,25 +540,25 @@  discard block
 block discarded – undo
540 540
             }
541 541
             $EVT_ID = $registration->event_ID();
542 542
             $ticket = $registration->ticket();
543
-            if (! isset($tickets_remaining[ $ticket->ID() ])) {
544
-                $tickets_remaining[ $ticket->ID() ] = $ticket->remaining();
543
+            if ( ! isset($tickets_remaining[$ticket->ID()])) {
544
+                $tickets_remaining[$ticket->ID()] = $ticket->remaining();
545 545
             }
546
-            if ($tickets_remaining[ $ticket->ID() ] > 0) {
547
-                if (! isset($event_reg_count[ $EVT_ID ])) {
548
-                    $event_reg_count[ $EVT_ID ] = 0;
546
+            if ($tickets_remaining[$ticket->ID()] > 0) {
547
+                if ( ! isset($event_reg_count[$EVT_ID])) {
548
+                    $event_reg_count[$EVT_ID] = 0;
549 549
                 }
550
-                $event_reg_count[ $EVT_ID ]++;
551
-                if (! isset($event_spaces_remaining[ $EVT_ID ])) {
552
-                    $event_spaces_remaining[ $EVT_ID ] = $registration->event()->spaces_remaining_for_sale();
550
+                $event_reg_count[$EVT_ID]++;
551
+                if ( ! isset($event_spaces_remaining[$EVT_ID])) {
552
+                    $event_spaces_remaining[$EVT_ID] = $registration->event()->spaces_remaining_for_sale();
553 553
                 }
554 554
             }
555 555
             if (
556 556
                 $revisit
557
-                && ($tickets_remaining[ $ticket->ID() ] === 0
558
-                    || $event_reg_count[ $EVT_ID ] > $event_spaces_remaining[ $EVT_ID ]
557
+                && ($tickets_remaining[$ticket->ID()] === 0
558
+                    || $event_reg_count[$EVT_ID] > $event_spaces_remaining[$EVT_ID]
559 559
                 )
560 560
             ) {
561
-                $ejected_registrations[ $REG_ID ] = $registration->event();
561
+                $ejected_registrations[$REG_ID] = $registration->event();
562 562
                 if ($registration->status_ID() !== EEM_Registration::status_id_wait_list) {
563 563
                     /** @type EE_Registration_Processor $registration_processor */
564 564
                     $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
@@ -618,7 +618,7 @@  discard block
 block discarded – undo
618 618
         foreach ($sold_out_events_array as $sold_out_event) {
619 619
             $sold_out_events .= EEH_HTML::li(
620 620
                 EEH_HTML::span(
621
-                    '  ' . $sold_out_event->name(),
621
+                    '  '.$sold_out_event->name(),
622 622
                     '',
623 623
                     'dashicons dashicons-marker ee-icon-size-16 pink-text'
624 624
                 )
@@ -673,7 +673,7 @@  discard block
 block discarded – undo
673 673
         foreach ($insufficient_spaces_events_array as $event) {
674 674
             if ($event instanceof EE_Event) {
675 675
                 $insufficient_space_events .= EEH_HTML::li(
676
-                    EEH_HTML::span(' ' . $event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
676
+                    EEH_HTML::span(' '.$event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
677 677
                 );
678 678
             }
679 679
         }
@@ -721,7 +721,7 @@  discard block
 block discarded – undo
721 721
         $events_requiring_pre_approval = array();
722 722
         foreach ($registrations_requiring_pre_approval as $registration) {
723 723
             if ($registration instanceof EE_Registration && $registration->event() instanceof EE_Event) {
724
-                $events_requiring_pre_approval[ $registration->event()->ID() ] = EEH_HTML::li(
724
+                $events_requiring_pre_approval[$registration->event()->ID()] = EEH_HTML::li(
725 725
                     EEH_HTML::span(
726 726
                         '',
727 727
                         '',
@@ -860,7 +860,7 @@  discard block
 block discarded – undo
860 860
     {
861 861
         return new EE_Form_Section_Proper(
862 862
             array(
863
-                'html_id'         => 'ee-' . $this->slug() . '-extra-hidden-inputs',
863
+                'html_id'         => 'ee-'.$this->slug().'-extra-hidden-inputs',
864 864
                 'layout_strategy' => new EE_Div_Per_Section_Layout(),
865 865
                 'subsections'     => array(
866 866
                     'spco_no_payment_required' => new EE_Hidden_Input(
@@ -900,7 +900,7 @@  discard block
 block discarded – undo
900 900
                 $payments += $registration->registration_payments();
901 901
             }
902 902
         }
903
-        if (! empty($payments)) {
903
+        if ( ! empty($payments)) {
904 904
             foreach ($payments as $payment) {
905 905
                 if ($payment instanceof EE_Registration_Payment) {
906 906
                     $this->checkout->amount_owing -= $payment->amount();
@@ -1024,7 +1024,7 @@  discard block
 block discarded – undo
1024 1024
                 $payment_method_button = EEH_HTML::img(
1025 1025
                     $payment_method->button_url(),
1026 1026
                     $payment_method->name(),
1027
-                    'spco-payment-method-' . $payment_method->slug() . '-btn-img',
1027
+                    'spco-payment-method-'.$payment_method->slug().'-btn-img',
1028 1028
                     'spco-payment-method-btn-img'
1029 1029
                 );
1030 1030
                 // check if any payment methods are set as default
@@ -1032,16 +1032,16 @@  discard block
 block discarded – undo
1032 1032
                 // open_by_default
1033 1033
                 if (
1034 1034
                     ($this->checkout->selected_method_of_payment === $payment_method->slug())
1035
-                    || (! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1035
+                    || ( ! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1036 1036
                 ) {
1037 1037
                     $this->checkout->selected_method_of_payment = $payment_method->slug();
1038 1038
                     $this->_save_selected_method_of_payment();
1039
-                    $default_payment_method_option[ $payment_method->slug() ] = $payment_method_button;
1039
+                    $default_payment_method_option[$payment_method->slug()] = $payment_method_button;
1040 1040
                 } else {
1041
-                    $available_payment_method_options[ $payment_method->slug() ] = $payment_method_button;
1041
+                    $available_payment_method_options[$payment_method->slug()] = $payment_method_button;
1042 1042
                 }
1043
-                $payment_methods_billing_info[ $payment_method->slug(
1044
-                ) . '-info' ] = $this->_payment_method_billing_info(
1043
+                $payment_methods_billing_info[$payment_method->slug(
1044
+                ).'-info'] = $this->_payment_method_billing_info(
1045 1045
                     $payment_method
1046 1046
                 );
1047 1047
             }
@@ -1077,7 +1077,7 @@  discard block
 block discarded – undo
1077 1077
      */
1078 1078
     protected function _get_available_payment_methods()
1079 1079
     {
1080
-        if (! empty($this->checkout->available_payment_methods)) {
1080
+        if ( ! empty($this->checkout->available_payment_methods)) {
1081 1081
             return $this->checkout->available_payment_methods;
1082 1082
         }
1083 1083
         $available_payment_methods = array();
@@ -1092,7 +1092,7 @@  discard block
 block discarded – undo
1092 1092
         );
1093 1093
         foreach ($payment_methods as $payment_method) {
1094 1094
             if ($payment_method instanceof EE_Payment_Method) {
1095
-                $available_payment_methods[ $payment_method->slug() ] = $payment_method;
1095
+                $available_payment_methods[$payment_method->slug()] = $payment_method;
1096 1096
             }
1097 1097
         }
1098 1098
         return $available_payment_methods;
@@ -1187,7 +1187,7 @@  discard block
 block discarded – undo
1187 1187
         );
1188 1188
         return new EE_Form_Section_Proper(
1189 1189
             array(
1190
-                'html_id'         => 'spco-payment-method-info-' . $payment_method->slug(),
1190
+                'html_id'         => 'spco-payment-method-info-'.$payment_method->slug(),
1191 1191
                 'html_class'      => 'spco-payment-method-info-dv',
1192 1192
                 // only display the selected or default PM
1193 1193
                 'html_style'      => $currently_selected ? '' : 'display:none;',
@@ -1217,7 +1217,7 @@  discard block
 block discarded – undo
1217 1217
         // how have they chosen to pay?
1218 1218
         $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1219 1219
         $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1220
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1220
+        if ( ! $this->checkout->payment_method instanceof EE_Payment_Method) {
1221 1221
             return false;
1222 1222
         }
1223 1223
         if (
@@ -1394,7 +1394,7 @@  discard block
 block discarded – undo
1394 1394
      */
1395 1395
     public function switch_payment_method()
1396 1396
     {
1397
-        if (! $this->_verify_payment_method_is_set()) {
1397
+        if ( ! $this->_verify_payment_method_is_set()) {
1398 1398
             return false;
1399 1399
         }
1400 1400
         if (
@@ -1533,7 +1533,7 @@  discard block
 block discarded – undo
1533 1533
             }
1534 1534
         }
1535 1535
         // verify payment method
1536
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1536
+        if ( ! $this->checkout->payment_method instanceof EE_Payment_Method) {
1537 1537
             // get payment method for selected method of payment
1538 1538
             $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1539 1539
         }
@@ -1558,7 +1558,7 @@  discard block
 block discarded – undo
1558 1558
      */
1559 1559
     public function save_payer_details_via_ajax()
1560 1560
     {
1561
-        if (! $this->_verify_payment_method_is_set()) {
1561
+        if ( ! $this->_verify_payment_method_is_set()) {
1562 1562
             return;
1563 1563
         }
1564 1564
         // generate billing form for selected method of payment if it hasn't been done already
@@ -1568,7 +1568,7 @@  discard block
 block discarded – undo
1568 1568
             );
1569 1569
         }
1570 1570
         // generate primary attendee from payer info if applicable
1571
-        if (! $this->checkout->transaction_has_primary_registrant()) {
1571
+        if ( ! $this->checkout->transaction_has_primary_registrant()) {
1572 1572
             $attendee = $this->_create_attendee_from_request_data();
1573 1573
             if ($attendee instanceof EE_Attendee) {
1574 1574
                 foreach ($this->checkout->transaction->registrations() as $registration) {
@@ -1599,7 +1599,7 @@  discard block
 block discarded – undo
1599 1599
     {
1600 1600
         // get State ID
1601 1601
         $STA_ID = ! empty($_REQUEST['state']) ? sanitize_text_field($_REQUEST['state']) : '';
1602
-        if (! empty($STA_ID)) {
1602
+        if ( ! empty($STA_ID)) {
1603 1603
             // can we get state object from name ?
1604 1604
             EE_Registry::instance()->load_model('State');
1605 1605
             $state = EEM_State::instance()->get_col(array(array('STA_name' => $STA_ID), 'limit' => 1), 'STA_ID');
@@ -1607,7 +1607,7 @@  discard block
 block discarded – undo
1607 1607
         }
1608 1608
         // get Country ISO
1609 1609
         $CNT_ISO = ! empty($_REQUEST['country']) ? sanitize_text_field($_REQUEST['country']) : '';
1610
-        if (! empty($CNT_ISO)) {
1610
+        if ( ! empty($CNT_ISO)) {
1611 1611
             // can we get country object from name ?
1612 1612
             EE_Registry::instance()->load_model('Country');
1613 1613
             $country = EEM_Country::instance()->get_col(
@@ -1860,7 +1860,7 @@  discard block
 block discarded – undo
1860 1860
     private function _process_payment()
1861 1861
     {
1862 1862
         // basically confirm that the event hasn't sold out since they hit the page
1863
-        if (! $this->_last_second_ticket_verifications()) {
1863
+        if ( ! $this->_last_second_ticket_verifications()) {
1864 1864
             return false;
1865 1865
         }
1866 1866
         // ya gotta make a choice man
@@ -1871,7 +1871,7 @@  discard block
 block discarded – undo
1871 1871
             return false;
1872 1872
         }
1873 1873
         // get EE_Payment_Method object
1874
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1874
+        if ( ! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1875 1875
             return false;
1876 1876
         }
1877 1877
         // setup billing form
@@ -1880,12 +1880,12 @@  discard block
 block discarded – undo
1880 1880
                 $this->checkout->payment_method
1881 1881
             );
1882 1882
             // bad billing form ?
1883
-            if (! $this->_billing_form_is_valid()) {
1883
+            if ( ! $this->_billing_form_is_valid()) {
1884 1884
                 return false;
1885 1885
             }
1886 1886
         }
1887 1887
         // ensure primary registrant has been fully processed
1888
-        if (! $this->_setup_primary_registrant_prior_to_payment()) {
1888
+        if ( ! $this->_setup_primary_registrant_prior_to_payment()) {
1889 1889
             return false;
1890 1890
         }
1891 1891
         // if session is close to expiring (under 10 minutes by default)
@@ -1941,7 +1941,7 @@  discard block
 block discarded – undo
1941 1941
     protected function _last_second_ticket_verifications()
1942 1942
     {
1943 1943
         // don't bother re-validating if not a return visit
1944
-        if (! $this->checkout->revisit) {
1944
+        if ( ! $this->checkout->revisit) {
1945 1945
             return true;
1946 1946
         }
1947 1947
         $registrations = $this->checkout->transaction->registrations();
@@ -2007,7 +2007,7 @@  discard block
 block discarded – undo
2007 2007
      */
2008 2008
     private function _billing_form_is_valid()
2009 2009
     {
2010
-        if (! $this->checkout->payment_method->type_obj()->has_billing_form()) {
2010
+        if ( ! $this->checkout->payment_method->type_obj()->has_billing_form()) {
2011 2011
             return true;
2012 2012
         }
2013 2013
         if ($this->checkout->billing_form instanceof EE_Billing_Info_Form) {
@@ -2127,7 +2127,7 @@  discard block
 block discarded – undo
2127 2127
     {
2128 2128
         // convert billing form data into an attendee
2129 2129
         $this->checkout->primary_attendee_obj = $this->checkout->billing_form->create_attendee_from_billing_form_data();
2130
-        if (! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2130
+        if ( ! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2131 2131
             EE_Error::add_error(
2132 2132
                 sprintf(
2133 2133
                     esc_html__(
@@ -2144,7 +2144,7 @@  discard block
 block discarded – undo
2144 2144
             return false;
2145 2145
         }
2146 2146
         $primary_registration = $this->checkout->transaction->primary_registration();
2147
-        if (! $primary_registration instanceof EE_Registration) {
2147
+        if ( ! $primary_registration instanceof EE_Registration) {
2148 2148
             EE_Error::add_error(
2149 2149
                 sprintf(
2150 2150
                     esc_html__(
@@ -2207,8 +2207,8 @@  discard block
 block discarded – undo
2207 2207
             return null;
2208 2208
         }
2209 2209
         // get EE_Payment_Method object
2210
-        if (isset($this->checkout->available_payment_methods[ $this->checkout->selected_method_of_payment ])) {
2211
-            $payment_method = $this->checkout->available_payment_methods[ $this->checkout->selected_method_of_payment ];
2210
+        if (isset($this->checkout->available_payment_methods[$this->checkout->selected_method_of_payment])) {
2211
+            $payment_method = $this->checkout->available_payment_methods[$this->checkout->selected_method_of_payment];
2212 2212
         } else {
2213 2213
             // load EEM_Payment_Method
2214 2214
             EE_Registry::instance()->load_model('Payment_Method');
@@ -2217,7 +2217,7 @@  discard block
 block discarded – undo
2217 2217
             $payment_method = $EEM_Payment_Method->get_one_by_slug($this->checkout->selected_method_of_payment);
2218 2218
         }
2219 2219
         // verify $payment_method
2220
-        if (! $payment_method instanceof EE_Payment_Method) {
2220
+        if ( ! $payment_method instanceof EE_Payment_Method) {
2221 2221
             // not a payment
2222 2222
             EE_Error::add_error(
2223 2223
                 sprintf(
@@ -2235,7 +2235,7 @@  discard block
 block discarded – undo
2235 2235
             return null;
2236 2236
         }
2237 2237
         // and verify it has a valid Payment_Method Type object
2238
-        if (! $payment_method->type_obj() instanceof EE_PMT_Base) {
2238
+        if ( ! $payment_method->type_obj() instanceof EE_PMT_Base) {
2239 2239
             // not a payment
2240 2240
             EE_Error::add_error(
2241 2241
                 sprintf(
@@ -2273,7 +2273,7 @@  discard block
 block discarded – undo
2273 2273
         $payment = null;
2274 2274
         $this->checkout->transaction->save();
2275 2275
         $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2276
-        if (! $payment_processor instanceof EE_Payment_Processor) {
2276
+        if ( ! $payment_processor instanceof EE_Payment_Processor) {
2277 2277
             return false;
2278 2278
         }
2279 2279
         try {
@@ -2377,7 +2377,7 @@  discard block
 block discarded – undo
2377 2377
             return true;
2378 2378
         }
2379 2379
         // verify payment object
2380
-        if (! $payment instanceof EE_Payment) {
2380
+        if ( ! $payment instanceof EE_Payment) {
2381 2381
             // not a payment
2382 2382
             EE_Error::add_error(
2383 2383
                 sprintf(
@@ -2417,7 +2417,7 @@  discard block
 block discarded – undo
2417 2417
             return true;
2418 2418
             // On-Site payment?
2419 2419
         } elseif ($this->checkout->payment_method->is_on_site()) {
2420
-            if (! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2420
+            if ( ! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2421 2421
                 // $this->_setup_redirect_for_next_step();
2422 2422
                 $this->checkout->continue_reg = false;
2423 2423
             }
@@ -2445,7 +2445,7 @@  discard block
 block discarded – undo
2445 2445
                     EE_Registry::instance()->CFG->organization->get_pretty('email')
2446 2446
                 );
2447 2447
                 if ($payment instanceof EE_Payment && $payment->gateway_response()) {
2448
-                    $error_message = $error_message . '<br/>' . $payment->gateway_response();
2448
+                    $error_message = $error_message.'<br/>'.$payment->gateway_response();
2449 2449
                 }
2450 2450
                 $this->checkout->continue_reg = false;
2451 2451
                 EE_Error::add_error(
@@ -2537,7 +2537,7 @@  discard block
 block discarded – undo
2537 2537
                     break;
2538 2538
                 // bad payment
2539 2539
                 case EEM_Payment::status_id_failed:
2540
-                    if (! empty($msg)) {
2540
+                    if ( ! empty($msg)) {
2541 2541
                         EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2542 2542
                         return false;
2543 2543
                     }
@@ -2598,11 +2598,11 @@  discard block
 block discarded – undo
2598 2598
         // how have they chosen to pay?
2599 2599
         $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
2600 2600
         // get EE_Payment_Method object
2601
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2601
+        if ( ! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2602 2602
             $this->checkout->continue_reg = false;
2603 2603
             return false;
2604 2604
         }
2605
-        if (! $this->checkout->payment_method->is_off_site()) {
2605
+        if ( ! $this->checkout->payment_method->is_off_site()) {
2606 2606
             return false;
2607 2607
         }
2608 2608
         $this->_validate_offsite_return();
@@ -2620,7 +2620,7 @@  discard block
 block discarded – undo
2620 2620
         // verify TXN
2621 2621
         if ($this->checkout->transaction instanceof EE_Transaction) {
2622 2622
             $gateway = $this->checkout->payment_method->type_obj()->get_gateway();
2623
-            if (! $gateway instanceof EE_Offsite_Gateway) {
2623
+            if ( ! $gateway instanceof EE_Offsite_Gateway) {
2624 2624
                 $this->checkout->continue_reg = false;
2625 2625
                 return false;
2626 2626
             }
@@ -2738,13 +2738,13 @@  discard block
 block discarded – undo
2738 2738
      */
2739 2739
     private function _redirect_wayward_request(EE_Registration $primary_registrant)
2740 2740
     {
2741
-        if (! $primary_registrant instanceof EE_Registration) {
2741
+        if ( ! $primary_registrant instanceof EE_Registration) {
2742 2742
             // try redirecting based on the current TXN
2743 2743
             $primary_registrant = $this->checkout->transaction instanceof EE_Transaction
2744 2744
                 ? $this->checkout->transaction->primary_registration()
2745 2745
                 : null;
2746 2746
         }
2747
-        if (! $primary_registrant instanceof EE_Registration) {
2747
+        if ( ! $primary_registrant instanceof EE_Registration) {
2748 2748
             EE_Error::add_error(
2749 2749
                 sprintf(
2750 2750
                     esc_html__(
@@ -2814,7 +2814,7 @@  discard block
 block discarded – undo
2814 2814
             $payment = $this->checkout->transaction->last_payment();
2815 2815
             // $payment_source = 'last_payment after Exception';
2816 2816
             // but if we STILL don't have a payment object
2817
-            if (! $payment instanceof EE_Payment) {
2817
+            if ( ! $payment instanceof EE_Payment) {
2818 2818
                 // then we'll object ! ( not object like a thing... but object like what a lawyer says ! )
2819 2819
                 $this->_handle_payment_processor_exception($e);
2820 2820
             }
Please login to merge, or discard this patch.