Completed
Branch BUG-10972-prefix-clearfix (829fe7)
by
unknown
21:57 queued 10:57
created
core/libraries/form_sections/inputs/EE_Radio_Button_Input.input.php 1 patch
Indentation   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -15,22 +15,22 @@
 block discarded – undo
15 15
 class EE_Radio_Button_Input extends EE_Form_Input_With_Options_Base
16 16
 {
17 17
 
18
-    /**
19
-     * @param array $answer_options
20
-     * @param array $input_settings
21
-     */
22
-    public function __construct($answer_options, $input_settings = array())
23
-    {
24
-        $this->_set_display_strategy(new EE_Radio_Button_Display_Strategy());
25
-        $this->_add_validation_strategy(
26
-            new EE_Enum_Validation_Strategy(
27
-                isset($input_settings['validation_error_message'])
28
-                    ? $input_settings['validation_error_message']
29
-                    : null
30
-            )
31
-        );
32
-        $this->_multiple_selections = false;
33
-        parent::__construct($answer_options, $input_settings);
34
-    }
18
+	/**
19
+	 * @param array $answer_options
20
+	 * @param array $input_settings
21
+	 */
22
+	public function __construct($answer_options, $input_settings = array())
23
+	{
24
+		$this->_set_display_strategy(new EE_Radio_Button_Display_Strategy());
25
+		$this->_add_validation_strategy(
26
+			new EE_Enum_Validation_Strategy(
27
+				isset($input_settings['validation_error_message'])
28
+					? $input_settings['validation_error_message']
29
+					: null
30
+			)
31
+		);
32
+		$this->_multiple_selections = false;
33
+		parent::__construct($answer_options, $input_settings);
34
+	}
35 35
 
36 36
 }
Please login to merge, or discard this patch.
core/libraries/form_sections/inputs/EE_Datepicker_Input.php 2 patches
Indentation   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -13,47 +13,47 @@
 block discarded – undo
13 13
 class EE_Datepicker_Input extends EE_Form_Input_Base
14 14
 {
15 15
 
16
-    /**
17
-     * @param array $input_settings
18
-     */
19
-    public function __construct($input_settings = array())
20
-    {
21
-        $this->_set_display_strategy(new EE_Text_Input_Display_Strategy('datepicker'));
22
-        $this->_set_normalization_strategy(new EE_Text_Normalization());
23
-        //we could do better for validation, but at least verify its plaintext
24
-        $this->_add_validation_strategy(
25
-            new EE_Plaintext_Validation_Strategy(
26
-                isset($input_settings['validation_error_message'])
27
-                    ? $input_settings['validation_error_message']
28
-                    : null
29
-            )
30
-        );
31
-        parent::__construct($input_settings);
32
-        $this->set_html_class($this->html_class() . ' datepicker');
33
-        // add some style and make it dance
34
-        add_action('wp_enqueue_scripts', array('EE_Datepicker_Input', 'enqueue_styles_and_scripts'));
35
-        add_action('admin_enqueue_scripts', array('EE_Datepicker_Input', 'enqueue_styles_and_scripts'));
36
-    }
37
-
38
-
39
-
40
-    /**
41
-     *    enqueue_styles_and_scripts
42
-     *
43
-     * @access        public
44
-     * @return        void
45
-     */
46
-    public static function enqueue_styles_and_scripts()
47
-    {
48
-        // load css
49
-        wp_register_style(
50
-            'espresso-ui-theme',
51
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
52
-            array(),
53
-            EVENT_ESPRESSO_VERSION
54
-        );
55
-        wp_enqueue_style('espresso-ui-theme');
56
-    }
16
+	/**
17
+	 * @param array $input_settings
18
+	 */
19
+	public function __construct($input_settings = array())
20
+	{
21
+		$this->_set_display_strategy(new EE_Text_Input_Display_Strategy('datepicker'));
22
+		$this->_set_normalization_strategy(new EE_Text_Normalization());
23
+		//we could do better for validation, but at least verify its plaintext
24
+		$this->_add_validation_strategy(
25
+			new EE_Plaintext_Validation_Strategy(
26
+				isset($input_settings['validation_error_message'])
27
+					? $input_settings['validation_error_message']
28
+					: null
29
+			)
30
+		);
31
+		parent::__construct($input_settings);
32
+		$this->set_html_class($this->html_class() . ' datepicker');
33
+		// add some style and make it dance
34
+		add_action('wp_enqueue_scripts', array('EE_Datepicker_Input', 'enqueue_styles_and_scripts'));
35
+		add_action('admin_enqueue_scripts', array('EE_Datepicker_Input', 'enqueue_styles_and_scripts'));
36
+	}
37
+
38
+
39
+
40
+	/**
41
+	 *    enqueue_styles_and_scripts
42
+	 *
43
+	 * @access        public
44
+	 * @return        void
45
+	 */
46
+	public static function enqueue_styles_and_scripts()
47
+	{
48
+		// load css
49
+		wp_register_style(
50
+			'espresso-ui-theme',
51
+			EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
52
+			array(),
53
+			EVENT_ESPRESSO_VERSION
54
+		);
55
+		wp_enqueue_style('espresso-ui-theme');
56
+	}
57 57
 
58 58
 
59 59
 
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -29,7 +29,7 @@  discard block
 block discarded – undo
29 29
             )
30 30
         );
31 31
         parent::__construct($input_settings);
32
-        $this->set_html_class($this->html_class() . ' datepicker');
32
+        $this->set_html_class($this->html_class().' datepicker');
33 33
         // add some style and make it dance
34 34
         add_action('wp_enqueue_scripts', array('EE_Datepicker_Input', 'enqueue_styles_and_scripts'));
35 35
         add_action('admin_enqueue_scripts', array('EE_Datepicker_Input', 'enqueue_styles_and_scripts'));
@@ -48,7 +48,7 @@  discard block
 block discarded – undo
48 48
         // load css
49 49
         wp_register_style(
50 50
             'espresso-ui-theme',
51
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
51
+            EE_GLOBAL_ASSETS_URL.'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
52 52
             array(),
53 53
             EVENT_ESPRESSO_VERSION
54 54
         );
Please login to merge, or discard this patch.
core/db_classes/EE_Registration.class.php 2 patches
Indentation   +1934 added lines, -1934 removed lines patch added patch discarded remove patch
@@ -18,1940 +18,1940 @@
 block discarded – undo
18 18
 {
19 19
 
20 20
 
21
-    /**
22
-     * Used to reference when a registration has never been checked in.
23
-     *
24
-     * @deprecated use \EE_Checkin::status_checked_never instead
25
-     * @type int
26
-     */
27
-    const checkin_status_never = 2;
28
-
29
-    /**
30
-     * Used to reference when a registration has been checked in.
31
-     *
32
-     * @deprecated use \EE_Checkin::status_checked_in instead
33
-     * @type int
34
-     */
35
-    const checkin_status_in = 1;
36
-
37
-
38
-    /**
39
-     * Used to reference when a registration has been checked out.
40
-     *
41
-     * @deprecated use \EE_Checkin::status_checked_out instead
42
-     * @type int
43
-     */
44
-    const checkin_status_out = 0;
45
-
46
-
47
-    /**
48
-     * extra meta key for tracking reg status os trashed registrations
49
-     *
50
-     * @type string
51
-     */
52
-    const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
53
-
54
-
55
-    /**
56
-     * extra meta key for tracking if registration has reserved ticket
57
-     *
58
-     * @type string
59
-     */
60
-    const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
61
-
62
-
63
-    /**
64
-     * @param array  $props_n_values          incoming values
65
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
66
-     *                                        used.)
67
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
68
-     *                                        date_format and the second value is the time format
69
-     * @return EE_Registration
70
-     * @throws EE_Error
71
-     */
72
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
73
-    {
74
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
75
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
76
-    }
77
-
78
-
79
-    /**
80
-     * @param array  $props_n_values  incoming values from the database
81
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
82
-     *                                the website will be used.
83
-     * @return EE_Registration
84
-     */
85
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
86
-    {
87
-        return new self($props_n_values, true, $timezone);
88
-    }
89
-
90
-
91
-    /**
92
-     *        Set Event ID
93
-     *
94
-     * @param        int $EVT_ID Event ID
95
-     * @throws EE_Error
96
-     * @throws RuntimeException
97
-     */
98
-    public function set_event($EVT_ID = 0)
99
-    {
100
-        $this->set('EVT_ID', $EVT_ID);
101
-    }
102
-
103
-
104
-    /**
105
-     * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
106
-     * be routed to internal methods
107
-     *
108
-     * @param string $field_name
109
-     * @param mixed  $field_value
110
-     * @param bool   $use_default
111
-     * @throws EE_Error
112
-     * @throws EntityNotFoundException
113
-     * @throws InvalidArgumentException
114
-     * @throws InvalidDataTypeException
115
-     * @throws InvalidInterfaceException
116
-     * @throws ReflectionException
117
-     * @throws RuntimeException
118
-     */
119
-    public function set($field_name, $field_value, $use_default = false)
120
-    {
121
-        switch ($field_name) {
122
-            case 'REG_code':
123
-                if (! empty($field_value) && $this->reg_code() === null) {
124
-                    $this->set_reg_code($field_value, $use_default);
125
-                }
126
-                break;
127
-            case 'STS_ID':
128
-                $this->set_status($field_value, $use_default);
129
-                break;
130
-            default:
131
-                parent::set($field_name, $field_value, $use_default);
132
-        }
133
-    }
134
-
135
-
136
-    /**
137
-     * Set Status ID
138
-     * updates the registration status and ALSO...
139
-     * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
140
-     * calls release_registration_space() if the reg status changes FROM approved to any other reg status
141
-     *
142
-     * @param string       $new_STS_ID
143
-     * @param boolean      $use_default
144
-     * @param Context|null $context
145
-     * @return bool
146
-     * @throws EE_Error
147
-     * @throws EntityNotFoundException
148
-     * @throws InvalidArgumentException
149
-     * @throws ReflectionException
150
-     * @throws RuntimeException
151
-     * @throws InvalidDataTypeException
152
-     * @throws InvalidInterfaceException
153
-     */
154
-    public function set_status($new_STS_ID = null, $use_default = false, Context $context = null)
155
-    {
156
-        // get current REG_Status
157
-        $old_STS_ID = $this->status_ID();
158
-        // if status has changed
159
-        if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
160
-            && ! empty($old_STS_ID) // and that old status is actually set
161
-            && ! empty($new_STS_ID) // as well as the new status
162
-            && $this->ID() // ensure registration is in the db
163
-        ) {
164
-            // TO approved
165
-            if ($new_STS_ID === EEM_Registration::status_id_approved) {
166
-                // reserve a space by incrementing ticket and datetime sold values
167
-                $this->_reserve_registration_space();
168
-                do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
169
-                // OR FROM  approved
170
-            } elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
171
-                // release a space by decrementing ticket and datetime sold values
172
-                $this->_release_registration_space();
173
-                do_action(
174
-                    'AHEE__EE_Registration__set_status__from_approved',
175
-                    $this,
176
-                    $old_STS_ID,
177
-                    $new_STS_ID,
178
-                    $context
179
-                );
180
-            }
181
-            // update status
182
-            parent::set('STS_ID', $new_STS_ID, $use_default);
183
-            $this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, $context);
184
-            if($this->statusChangeUpdatesTransaction($context)) {
185
-                $this->updateTransactionAfterStatusChange();
186
-            }
187
-            do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
188
-            return true;
189
-        }
190
-        //even though the old value matches the new value, it's still good to
191
-        //allow the parent set method to have a say
192
-        parent::set('STS_ID', $new_STS_ID, $use_default);
193
-        return true;
194
-    }
195
-
196
-
197
-    /**
198
-     * update REGs and TXN when cancelled or declined registrations involved
199
-     *
200
-     * @param string       $new_STS_ID
201
-     * @param string       $old_STS_ID
202
-     * @param Context|null $context
203
-     * @throws EE_Error
204
-     * @throws InvalidArgumentException
205
-     * @throws InvalidDataTypeException
206
-     * @throws InvalidInterfaceException
207
-     * @throws ReflectionException
208
-     */
209
-    private function _update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, Context $context = null)
210
-    {
211
-        // these reg statuses should not be considered in any calculations involving monies owing
212
-        $closed_reg_statuses = EEM_Registration::closed_reg_statuses();
213
-        // true if registration has been cancelled or declined
214
-        $this->updateIfCanceled(
215
-            $closed_reg_statuses,
216
-            $new_STS_ID,
217
-            $old_STS_ID,
218
-            $context
219
-        );
220
-        $this->updateIfDeclined(
221
-            $closed_reg_statuses,
222
-            $new_STS_ID,
223
-            $old_STS_ID,
224
-            $context
225
-        );
226
-    }
227
-
228
-
229
-    /**
230
-     * update REGs and TXN when cancelled or declined registrations involved
231
-     *
232
-     * @param array        $closed_reg_statuses
233
-     * @param string       $new_STS_ID
234
-     * @param string       $old_STS_ID
235
-     * @param Context|null $context
236
-     * @throws EE_Error
237
-     * @throws InvalidArgumentException
238
-     * @throws InvalidDataTypeException
239
-     * @throws InvalidInterfaceException
240
-     * @throws ReflectionException
241
-     */
242
-    private function updateIfCanceled(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, Context $context = null)
243
-    {
244
-        // true if registration has been cancelled or declined
245
-        if (in_array($new_STS_ID, $closed_reg_statuses, true)
246
-            && ! in_array($old_STS_ID, $closed_reg_statuses, true)
247
-        ) {
248
-            /** @type EE_Registration_Processor $registration_processor */
249
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
250
-            /** @type EE_Transaction_Processor $transaction_processor */
251
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
252
-            // cancelled or declined registration
253
-            $registration_processor->update_registration_after_being_canceled_or_declined(
254
-                $this,
255
-                $closed_reg_statuses
256
-            );
257
-            $transaction_processor->update_transaction_after_canceled_or_declined_registration(
258
-                $this,
259
-                $closed_reg_statuses,
260
-                false
261
-            );
262
-            do_action(
263
-                'AHEE__EE_Registration__set_status__canceled_or_declined',
264
-                $this,
265
-                $old_STS_ID,
266
-                $new_STS_ID,
267
-                $context
268
-            );
269
-            return;
270
-        }
271
-    }
272
-
273
-
274
-    /**
275
-     * update REGs and TXN when cancelled or declined registrations involved
276
-     *
277
-     * @param array        $closed_reg_statuses
278
-     * @param string       $new_STS_ID
279
-     * @param string       $old_STS_ID
280
-     * @param Context|null $context
281
-     * @throws EE_Error
282
-     * @throws InvalidArgumentException
283
-     * @throws InvalidDataTypeException
284
-     * @throws InvalidInterfaceException
285
-     * @throws ReflectionException
286
-     */
287
-    private function updateIfDeclined(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, Context $context = null)
288
-    {
289
-        // true if reinstating cancelled or declined registration
290
-        if (in_array($old_STS_ID, $closed_reg_statuses, true)
291
-            && ! in_array($new_STS_ID, $closed_reg_statuses, true)
292
-        ) {
293
-            /** @type EE_Registration_Processor $registration_processor */
294
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
295
-            /** @type EE_Transaction_Processor $transaction_processor */
296
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
297
-            // reinstating cancelled or declined registration
298
-            $registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
299
-                $this,
300
-                $closed_reg_statuses
301
-            );
302
-            $transaction_processor->update_transaction_after_reinstating_canceled_registration(
303
-                $this,
304
-                $closed_reg_statuses,
305
-                false
306
-            );
307
-            do_action(
308
-                'AHEE__EE_Registration__set_status__after_reinstated',
309
-                $this,
310
-                $old_STS_ID,
311
-                $new_STS_ID,
312
-                $context
313
-            );
314
-        }
315
-    }
316
-
317
-
318
-    /**
319
-     * @param Context|null $context
320
-     * @return bool
321
-     */
322
-    private function statusChangeUpdatesTransaction(Context $context = null)
323
-    {
324
-        $contexts_that_do_not_update_transaction = (array) apply_filters(
325
-            'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
326
-            array('spco_reg_step_attendee_information_process_registrations'),
327
-            $context,
328
-            $this
329
-        );
330
-        return ! (
331
-            $context instanceof Context
332
-            && in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
333
-        );
334
-    }
335
-
336
-
337
-    /**
338
-     * @throws EE_Error
339
-     * @throws EntityNotFoundException
340
-     * @throws InvalidArgumentException
341
-     * @throws InvalidDataTypeException
342
-     * @throws InvalidInterfaceException
343
-     * @throws ReflectionException
344
-     * @throws RuntimeException
345
-     */
346
-    private function updateTransactionAfterStatusChange()
347
-    {
348
-        /** @type EE_Transaction_Payments $transaction_payments */
349
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
350
-        $transaction_payments->recalculate_transaction_total($this->transaction(), false);
351
-        $this->transaction()->update_status_based_on_total_paid(true);
352
-    }
353
-
354
-
355
-    /**
356
-     *        get Status ID
357
-     */
358
-    public function status_ID()
359
-    {
360
-        return $this->get('STS_ID');
361
-    }
362
-
363
-
364
-    /**
365
-     * increments this registration's related ticket sold and corresponding datetime sold values
366
-     *
367
-     * @return void
368
-     * @throws EE_Error
369
-     * @throws EntityNotFoundException
370
-     */
371
-    private function _reserve_registration_space()
372
-    {
373
-        // reserved ticket and datetime counts will be decremented as sold counts are incremented
374
-        // so stop tracking that this reg has a ticket reserved
375
-        $this->release_reserved_ticket();
376
-        $ticket = $this->ticket();
377
-        $ticket->increase_sold();
378
-        $ticket->save();
379
-        // possibly set event status to sold out
380
-        $this->event()->perform_sold_out_status_check();
381
-    }
382
-
383
-
384
-    /**
385
-     * Gets the ticket this registration is for
386
-     *
387
-     * @param boolean $include_archived whether to include archived tickets or not.
388
-     * @return EE_Ticket|EE_Base_Class
389
-     * @throws \EE_Error
390
-     */
391
-    public function ticket($include_archived = true)
392
-    {
393
-        $query_params = array();
394
-        if ($include_archived) {
395
-            $query_params['default_where_conditions'] = 'none';
396
-        }
397
-        return $this->get_first_related('Ticket', $query_params);
398
-    }
399
-
400
-
401
-    /**
402
-     * Gets the event this registration is for
403
-     *
404
-     * @return EE_Event
405
-     * @throws EE_Error
406
-     * @throws EntityNotFoundException
407
-     */
408
-    public function event()
409
-    {
410
-        $event = $this->get_first_related('Event');
411
-        if (! $event instanceof \EE_Event) {
412
-            throw new EntityNotFoundException('Event ID', $this->event_ID());
413
-        }
414
-        return $event;
415
-    }
416
-
417
-
418
-    /**
419
-     * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
420
-     * with the author of the event this registration is for.
421
-     *
422
-     * @since 4.5.0
423
-     * @return int
424
-     * @throws EE_Error
425
-     * @throws EntityNotFoundException
426
-     */
427
-    public function wp_user()
428
-    {
429
-        $event = $this->event();
430
-        if ($event instanceof EE_Event) {
431
-            return $event->wp_user();
432
-        }
433
-        return 0;
434
-    }
435
-
436
-
437
-    /**
438
-     * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
439
-     *
440
-     * @return void
441
-     * @throws \EE_Error
442
-     */
443
-    private function _release_registration_space()
444
-    {
445
-        $ticket = $this->ticket();
446
-        $ticket->decrease_sold();
447
-        $ticket->save();
448
-    }
449
-
450
-
451
-    /**
452
-     * tracks this registration's ticket reservation in extra meta
453
-     * and can increment related ticket reserved and corresponding datetime reserved values
454
-     *
455
-     * @param bool $update_ticket if true, will increment ticket and datetime reserved count
456
-     * @return void
457
-     * @throws \EE_Error
458
-     */
459
-    public function reserve_ticket($update_ticket = false)
460
-    {
461
-        if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) === false) {
462
-            // PLZ NOTE: although checking $update_ticket first would be more efficient,
463
-            // we NEED to ALWAYS call update_extra_meta(), which is why that is done first
464
-            if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) && $update_ticket) {
465
-                $ticket = $this->ticket();
466
-                $ticket->increase_reserved();
467
-                $ticket->save();
468
-            }
469
-        }
470
-    }
471
-
472
-
473
-    /**
474
-     * stops tracking this registration's ticket reservation in extra meta
475
-     * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
476
-     *
477
-     * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
478
-     * @return void
479
-     * @throws \EE_Error
480
-     */
481
-    public function release_reserved_ticket($update_ticket = false)
482
-    {
483
-        if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) !== false) {
484
-            // PLZ NOTE: although checking $update_ticket first would be more efficient,
485
-            // we NEED to ALWAYS call delete_extra_meta(), which is why that is done first
486
-            if ($this->delete_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY) && $update_ticket) {
487
-                $ticket = $this->ticket();
488
-                $ticket->decrease_reserved();
489
-                $ticket->save();
490
-            }
491
-        }
492
-    }
493
-
494
-
495
-    /**
496
-     * Set Attendee ID
497
-     *
498
-     * @param        int $ATT_ID Attendee ID
499
-     * @throws EE_Error
500
-     * @throws RuntimeException
501
-     */
502
-    public function set_attendee_id($ATT_ID = 0)
503
-    {
504
-        $this->set('ATT_ID', $ATT_ID);
505
-    }
506
-
507
-
508
-    /**
509
-     *        Set Transaction ID
510
-     *
511
-     * @param        int $TXN_ID Transaction ID
512
-     * @throws EE_Error
513
-     * @throws RuntimeException
514
-     */
515
-    public function set_transaction_id($TXN_ID = 0)
516
-    {
517
-        $this->set('TXN_ID', $TXN_ID);
518
-    }
519
-
520
-
521
-    /**
522
-     *        Set Session
523
-     *
524
-     * @param    string $REG_session PHP Session ID
525
-     * @throws EE_Error
526
-     * @throws RuntimeException
527
-     */
528
-    public function set_session($REG_session = '')
529
-    {
530
-        $this->set('REG_session', $REG_session);
531
-    }
532
-
533
-
534
-    /**
535
-     *        Set Registration URL Link
536
-     *
537
-     * @param    string $REG_url_link Registration URL Link
538
-     * @throws EE_Error
539
-     * @throws RuntimeException
540
-     */
541
-    public function set_reg_url_link($REG_url_link = '')
542
-    {
543
-        $this->set('REG_url_link', $REG_url_link);
544
-    }
545
-
546
-
547
-    /**
548
-     *        Set Attendee Counter
549
-     *
550
-     * @param        int $REG_count Primary Attendee
551
-     * @throws EE_Error
552
-     * @throws RuntimeException
553
-     */
554
-    public function set_count($REG_count = 1)
555
-    {
556
-        $this->set('REG_count', $REG_count);
557
-    }
558
-
559
-
560
-    /**
561
-     *        Set Group Size
562
-     *
563
-     * @param        boolean $REG_group_size Group Registration
564
-     * @throws EE_Error
565
-     * @throws RuntimeException
566
-     */
567
-    public function set_group_size($REG_group_size = false)
568
-    {
569
-        $this->set('REG_group_size', $REG_group_size);
570
-    }
571
-
572
-
573
-    /**
574
-     *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
575
-     *    EEM_Registration::status_id_not_approved
576
-     *
577
-     * @return        boolean
578
-     */
579
-    public function is_not_approved()
580
-    {
581
-        return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
582
-    }
583
-
584
-
585
-    /**
586
-     *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
587
-     *    EEM_Registration::status_id_pending_payment
588
-     *
589
-     * @return        boolean
590
-     */
591
-    public function is_pending_payment()
592
-    {
593
-        return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
594
-    }
595
-
596
-
597
-    /**
598
-     *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
599
-     *
600
-     * @return        boolean
601
-     */
602
-    public function is_approved()
603
-    {
604
-        return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
605
-    }
606
-
607
-
608
-    /**
609
-     *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
610
-     *
611
-     * @return        boolean
612
-     */
613
-    public function is_cancelled()
614
-    {
615
-        return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
616
-    }
617
-
618
-
619
-    /**
620
-     *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
621
-     *
622
-     * @return        boolean
623
-     */
624
-    public function is_declined()
625
-    {
626
-        return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
627
-    }
628
-
629
-
630
-    /**
631
-     *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
632
-     *    EEM_Registration::status_id_incomplete
633
-     *
634
-     * @return        boolean
635
-     */
636
-    public function is_incomplete()
637
-    {
638
-        return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
639
-    }
640
-
641
-
642
-    /**
643
-     *        Set Registration Date
644
-     *
645
-     * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
646
-     *                                                 Date
647
-     * @throws EE_Error
648
-     * @throws RuntimeException
649
-     */
650
-    public function set_reg_date($REG_date = false)
651
-    {
652
-        $this->set('REG_date', $REG_date);
653
-    }
654
-
655
-
656
-    /**
657
-     *    Set final price owing for this registration after all ticket/price modifications
658
-     *
659
-     * @access    public
660
-     * @param    float $REG_final_price
661
-     * @throws EE_Error
662
-     * @throws RuntimeException
663
-     */
664
-    public function set_final_price($REG_final_price = 0.00)
665
-    {
666
-        $this->set('REG_final_price', $REG_final_price);
667
-    }
668
-
669
-
670
-    /**
671
-     *    Set amount paid towards this registration's final price
672
-     *
673
-     * @access    public
674
-     * @param    float $REG_paid
675
-     * @throws EE_Error
676
-     * @throws RuntimeException
677
-     */
678
-    public function set_paid($REG_paid = 0.00)
679
-    {
680
-        $this->set('REG_paid', $REG_paid);
681
-    }
682
-
683
-
684
-    /**
685
-     *        Attendee Is Going
686
-     *
687
-     * @param        boolean $REG_att_is_going Attendee Is Going
688
-     * @throws EE_Error
689
-     * @throws RuntimeException
690
-     */
691
-    public function set_att_is_going($REG_att_is_going = false)
692
-    {
693
-        $this->set('REG_att_is_going', $REG_att_is_going);
694
-    }
695
-
696
-
697
-    /**
698
-     * Gets the related attendee
699
-     *
700
-     * @return EE_Attendee
701
-     * @throws EE_Error
702
-     */
703
-    public function attendee()
704
-    {
705
-        return $this->get_first_related('Attendee');
706
-    }
707
-
708
-
709
-    /**
710
-     *        get Event ID
711
-     */
712
-    public function event_ID()
713
-    {
714
-        return $this->get('EVT_ID');
715
-    }
716
-
717
-
718
-    /**
719
-     *        get Event ID
720
-     */
721
-    public function event_name()
722
-    {
723
-        $event = $this->event_obj();
724
-        if ($event) {
725
-            return $event->name();
726
-        } else {
727
-            return null;
728
-        }
729
-    }
730
-
731
-
732
-    /**
733
-     * Fetches the event this registration is for
734
-     *
735
-     * @return EE_Event
736
-     * @throws EE_Error
737
-     */
738
-    public function event_obj()
739
-    {
740
-        return $this->get_first_related('Event');
741
-    }
742
-
743
-
744
-    /**
745
-     *        get Attendee ID
746
-     */
747
-    public function attendee_ID()
748
-    {
749
-        return $this->get('ATT_ID');
750
-    }
751
-
752
-
753
-    /**
754
-     *        get PHP Session ID
755
-     */
756
-    public function session_ID()
757
-    {
758
-        return $this->get('REG_session');
759
-    }
760
-
761
-
762
-    /**
763
-     * Gets the string which represents the URL trigger for the receipt template in the message template system.
764
-     *
765
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
766
-     * @return string
767
-     */
768
-    public function receipt_url($messenger = 'html')
769
-    {
770
-
771
-        /**
772
-         * The below will be deprecated one version after this.  We check first if there is a custom receipt template
773
-         * already in use on old system.  If there is then we just return the standard url for it.
774
-         *
775
-         * @since 4.5.0
776
-         */
777
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
778
-        $has_custom             = EEH_Template::locate_template(
779
-            $template_relative_path,
780
-            array(),
781
-            true,
782
-            true,
783
-            true
784
-        );
785
-
786
-        if ($has_custom) {
787
-            return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
788
-        }
789
-        return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
790
-    }
791
-
792
-
793
-    /**
794
-     * Gets the string which represents the URL trigger for the invoice template in the message template system.
795
-     *
796
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
797
-     * @return string
798
-     * @throws EE_Error
799
-     */
800
-    public function invoice_url($messenger = 'html')
801
-    {
802
-        /**
803
-         * The below will be deprecated one version after this.  We check first if there is a custom invoice template
804
-         * already in use on old system.  If there is then we just return the standard url for it.
805
-         *
806
-         * @since 4.5.0
807
-         */
808
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
809
-        $has_custom             = EEH_Template::locate_template(
810
-            $template_relative_path,
811
-            array(),
812
-            true,
813
-            true,
814
-            true
815
-        );
816
-
817
-        if ($has_custom) {
818
-            if ($messenger == 'html') {
819
-                return $this->invoice_url('launch');
820
-            }
821
-            $route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
822
-
823
-            $query_args = array('ee' => $route, 'id' => $this->reg_url_link());
824
-            if ($messenger == 'html') {
825
-                $query_args['html'] = true;
826
-            }
827
-            return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
828
-        }
829
-        return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
830
-    }
831
-
832
-
833
-    /**
834
-     * get Registration URL Link
835
-     *
836
-     * @access public
837
-     * @return string
838
-     * @throws \EE_Error
839
-     */
840
-    public function reg_url_link()
841
-    {
842
-        return (string) $this->get('REG_url_link');
843
-    }
844
-
845
-
846
-    /**
847
-     * Echoes out invoice_url()
848
-     *
849
-     * @param string $type 'download','launch', or 'html' (default is 'launch')
850
-     * @return void
851
-     * @throws EE_Error
852
-     */
853
-    public function e_invoice_url($type = 'launch')
854
-    {
855
-        echo $this->invoice_url($type);
856
-    }
857
-
858
-
859
-    /**
860
-     * Echoes out payment_overview_url
861
-     */
862
-    public function e_payment_overview_url()
863
-    {
864
-        echo $this->payment_overview_url();
865
-    }
866
-
867
-
868
-    /**
869
-     * Gets the URL of the thank you page with this registration REG_url_link added as
870
-     * a query parameter
871
-     *
872
-     * @param bool $clear_session Set to true when you want to clear the session on revisiting the
873
-     *                            payment overview url.
874
-     * @return string
875
-     * @throws EE_Error
876
-     */
877
-    public function payment_overview_url($clear_session = false)
878
-    {
879
-        return add_query_arg(array(
880
-            'e_reg_url_link' => $this->reg_url_link(),
881
-            'step'           => 'payment_options',
882
-            'revisit'        => true,
883
-            'clear_session' => (bool) $clear_session
884
-        ), EE_Registry::instance()->CFG->core->reg_page_url());
885
-    }
886
-
887
-
888
-    /**
889
-     * Gets the URL of the thank you page with this registration REG_url_link added as
890
-     * a query parameter
891
-     *
892
-     * @return string
893
-     * @throws EE_Error
894
-     */
895
-    public function edit_attendee_information_url()
896
-    {
897
-        return add_query_arg(array(
898
-            'e_reg_url_link' => $this->reg_url_link(),
899
-            'step'           => 'attendee_information',
900
-            'revisit'        => true,
901
-        ), EE_Registry::instance()->CFG->core->reg_page_url());
902
-    }
903
-
904
-
905
-    /**
906
-     * Simply generates and returns the appropriate admin_url link to edit this registration
907
-     *
908
-     * @return string
909
-     * @throws EE_Error
910
-     */
911
-    public function get_admin_edit_url()
912
-    {
913
-        return EEH_URL::add_query_args_and_nonce(array(
914
-            'page'    => 'espresso_registrations',
915
-            'action'  => 'view_registration',
916
-            '_REG_ID' => $this->ID(),
917
-        ), admin_url('admin.php'));
918
-    }
919
-
920
-
921
-    /**
922
-     *    is_primary_registrant?
923
-     */
924
-    public function is_primary_registrant()
925
-    {
926
-        return $this->get('REG_count') == 1 ? true : false;
927
-    }
928
-
929
-
930
-    /**
931
-     * This returns the primary registration object for this registration group (which may be this object).
932
-     *
933
-     * @return EE_Registration
934
-     * @throws EE_Error
935
-     */
936
-    public function get_primary_registration()
937
-    {
938
-        if ($this->is_primary_registrant()) {
939
-            return $this;
940
-        }
941
-
942
-        //k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
943
-        /** @var EE_Registration $primary_registrant */
944
-        $primary_registrant = EEM_Registration::instance()->get_one(array(
945
-            array(
946
-                'TXN_ID'    => $this->transaction_ID(),
947
-                'REG_count' => 1,
948
-            ),
949
-        ));
950
-        return $primary_registrant;
951
-    }
952
-
953
-
954
-    /**
955
-     *        get  Attendee Number
956
-     *
957
-     * @access        public
958
-     */
959
-    public function count()
960
-    {
961
-        return $this->get('REG_count');
962
-    }
963
-
964
-
965
-    /**
966
-     *        get Group Size
967
-     */
968
-    public function group_size()
969
-    {
970
-        return $this->get('REG_group_size');
971
-    }
972
-
973
-
974
-    /**
975
-     *        get Registration Date
976
-     */
977
-    public function date()
978
-    {
979
-        return $this->get('REG_date');
980
-    }
981
-
982
-
983
-    /**
984
-     * gets a pretty date
985
-     *
986
-     * @param string $date_format
987
-     * @param string $time_format
988
-     * @return string
989
-     * @throws EE_Error
990
-     */
991
-    public function pretty_date($date_format = null, $time_format = null)
992
-    {
993
-        return $this->get_datetime('REG_date', $date_format, $time_format);
994
-    }
995
-
996
-
997
-    /**
998
-     * final_price
999
-     * the registration's share of the transaction total, so that the
1000
-     * sum of all the transaction's REG_final_prices equal the transaction's total
1001
-     *
1002
-     * @return float
1003
-     * @throws EE_Error
1004
-     */
1005
-    public function final_price()
1006
-    {
1007
-        return $this->get('REG_final_price');
1008
-    }
1009
-
1010
-
1011
-    /**
1012
-     * pretty_final_price
1013
-     *  final price as formatted string, with correct decimal places and currency symbol
1014
-     *
1015
-     * @return string
1016
-     * @throws EE_Error
1017
-     */
1018
-    public function pretty_final_price()
1019
-    {
1020
-        return $this->get_pretty('REG_final_price');
1021
-    }
1022
-
1023
-
1024
-    /**
1025
-     * get paid (yeah)
1026
-     *
1027
-     * @return float
1028
-     * @throws EE_Error
1029
-     */
1030
-    public function paid()
1031
-    {
1032
-        return $this->get('REG_paid');
1033
-    }
1034
-
1035
-
1036
-    /**
1037
-     * pretty_paid
1038
-     *
1039
-     * @return float
1040
-     * @throws EE_Error
1041
-     */
1042
-    public function pretty_paid()
1043
-    {
1044
-        return $this->get_pretty('REG_paid');
1045
-    }
1046
-
1047
-
1048
-    /**
1049
-     * owes_monies_and_can_pay
1050
-     * whether or not this registration has monies owing and it's' status allows payment
1051
-     *
1052
-     * @param array $requires_payment
1053
-     * @return bool
1054
-     * @throws EE_Error
1055
-     */
1056
-    public function owes_monies_and_can_pay($requires_payment = array())
1057
-    {
1058
-        // these reg statuses require payment (if event is not free)
1059
-        $requires_payment = ! empty($requires_payment)
1060
-            ? $requires_payment
1061
-            : EEM_Registration::reg_statuses_that_allow_payment();
1062
-        if (in_array($this->status_ID(), $requires_payment) &&
1063
-            $this->final_price() != 0 &&
1064
-            $this->final_price() != $this->paid()
1065
-        ) {
1066
-            return true;
1067
-        } else {
1068
-            return false;
1069
-        }
1070
-    }
1071
-
1072
-
1073
-    /**
1074
-     * Prints out the return value of $this->pretty_status()
1075
-     *
1076
-     * @param bool $show_icons
1077
-     * @return void
1078
-     * @throws EE_Error
1079
-     */
1080
-    public function e_pretty_status($show_icons = false)
1081
-    {
1082
-        echo $this->pretty_status($show_icons);
1083
-    }
1084
-
1085
-
1086
-    /**
1087
-     * Returns a nice version of the status for displaying to customers
1088
-     *
1089
-     * @param bool $show_icons
1090
-     * @return string
1091
-     * @throws EE_Error
1092
-     */
1093
-    public function pretty_status($show_icons = false)
1094
-    {
1095
-        $status = EEM_Status::instance()->localized_status(
1096
-            array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1097
-            false,
1098
-            'sentence'
1099
-        );
1100
-        $icon   = '';
1101
-        switch ($this->status_ID()) {
1102
-            case EEM_Registration::status_id_approved:
1103
-                $icon = $show_icons
1104
-                    ? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1105
-                    : '';
1106
-                break;
1107
-            case EEM_Registration::status_id_pending_payment:
1108
-                $icon = $show_icons
1109
-                    ? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1110
-                    : '';
1111
-                break;
1112
-            case EEM_Registration::status_id_not_approved:
1113
-                $icon = $show_icons
1114
-                    ? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1115
-                    : '';
1116
-                break;
1117
-            case EEM_Registration::status_id_cancelled:
1118
-                $icon = $show_icons
1119
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1120
-                    : '';
1121
-                break;
1122
-            case EEM_Registration::status_id_incomplete:
1123
-                $icon = $show_icons
1124
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1125
-                    : '';
1126
-                break;
1127
-            case EEM_Registration::status_id_declined:
1128
-                $icon = $show_icons
1129
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1130
-                    : '';
1131
-                break;
1132
-            case EEM_Registration::status_id_wait_list:
1133
-                $icon = $show_icons
1134
-                    ? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1135
-                    : '';
1136
-                break;
1137
-        }
1138
-        return $icon . $status[$this->status_ID()];
1139
-    }
1140
-
1141
-
1142
-    /**
1143
-     *        get Attendee Is Going
1144
-     */
1145
-    public function att_is_going()
1146
-    {
1147
-        return $this->get('REG_att_is_going');
1148
-    }
1149
-
1150
-
1151
-    /**
1152
-     * Gets related answers
1153
-     *
1154
-     * @param array $query_params like EEM_Base::get_all
1155
-     * @return EE_Answer[]
1156
-     * @throws EE_Error
1157
-     */
1158
-    public function answers($query_params = null)
1159
-    {
1160
-        return $this->get_many_related('Answer', $query_params);
1161
-    }
1162
-
1163
-
1164
-    /**
1165
-     * Gets the registration's answer value to the specified question
1166
-     * (either the question's ID or a question object)
1167
-     *
1168
-     * @param EE_Question|int $question
1169
-     * @param bool            $pretty_value
1170
-     * @return array|string if pretty_value= true, the result will always be a string
1171
-     * (because the answer might be an array of answer values, so passing pretty_value=true
1172
-     * will convert it into some kind of string)
1173
-     * @throws EE_Error
1174
-     */
1175
-    public function answer_value_to_question($question, $pretty_value = true)
1176
-    {
1177
-        $question_id = EEM_Question::instance()->ensure_is_ID($question);
1178
-        return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1179
-    }
1180
-
1181
-
1182
-    /**
1183
-     * question_groups
1184
-     * returns an array of EE_Question_Group objects for this registration
1185
-     *
1186
-     * @return EE_Question_Group[]
1187
-     * @throws EE_Error
1188
-     * @throws EntityNotFoundException
1189
-     */
1190
-    public function question_groups()
1191
-    {
1192
-        $question_groups = array();
1193
-        if ($this->event() instanceof EE_Event) {
1194
-            $question_groups = $this->event()->question_groups(
1195
-                array(
1196
-                    array(
1197
-                        'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1198
-                    ),
1199
-                    'order_by' => array('QSG_order' => 'ASC'),
1200
-                )
1201
-            );
1202
-        }
1203
-        return $question_groups;
1204
-    }
1205
-
1206
-
1207
-    /**
1208
-     * count_question_groups
1209
-     * returns a count of the number of EE_Question_Group objects for this registration
1210
-     *
1211
-     * @return int
1212
-     * @throws EE_Error
1213
-     * @throws EntityNotFoundException
1214
-     */
1215
-    public function count_question_groups()
1216
-    {
1217
-        $qg_count = 0;
1218
-        if ($this->event() instanceof EE_Event) {
1219
-            $qg_count = $this->event()->count_related(
1220
-                'Question_Group',
1221
-                array(
1222
-                    array(
1223
-                        'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1224
-                    ),
1225
-                )
1226
-            );
1227
-        }
1228
-        return $qg_count;
1229
-    }
1230
-
1231
-
1232
-    /**
1233
-     * Returns the registration date in the 'standard' string format
1234
-     * (function may be improved in the future to allow for different formats and timezones)
1235
-     *
1236
-     * @return string
1237
-     * @throws EE_Error
1238
-     */
1239
-    public function reg_date()
1240
-    {
1241
-        return $this->get_datetime('REG_date');
1242
-    }
1243
-
1244
-
1245
-    /**
1246
-     * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1247
-     * the ticket this registration purchased, or the datetime they have registered
1248
-     * to attend)
1249
-     *
1250
-     * @return EE_Datetime_Ticket
1251
-     * @throws EE_Error
1252
-     */
1253
-    public function datetime_ticket()
1254
-    {
1255
-        return $this->get_first_related('Datetime_Ticket');
1256
-    }
1257
-
1258
-
1259
-    /**
1260
-     * Sets the registration's datetime_ticket.
1261
-     *
1262
-     * @param EE_Datetime_Ticket $datetime_ticket
1263
-     * @return EE_Datetime_Ticket
1264
-     * @throws EE_Error
1265
-     */
1266
-    public function set_datetime_ticket($datetime_ticket)
1267
-    {
1268
-        return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1269
-    }
1270
-
1271
-    /**
1272
-     * Gets deleted
1273
-     *
1274
-     * @return bool
1275
-     * @throws EE_Error
1276
-     */
1277
-    public function deleted()
1278
-    {
1279
-        return $this->get('REG_deleted');
1280
-    }
1281
-
1282
-    /**
1283
-     * Sets deleted
1284
-     *
1285
-     * @param boolean $deleted
1286
-     * @return bool
1287
-     * @throws EE_Error
1288
-     * @throws RuntimeException
1289
-     */
1290
-    public function set_deleted($deleted)
1291
-    {
1292
-        if ($deleted) {
1293
-            $this->delete();
1294
-        } else {
1295
-            $this->restore();
1296
-        }
1297
-    }
1298
-
1299
-
1300
-    /**
1301
-     * Get the status object of this object
1302
-     *
1303
-     * @return EE_Status
1304
-     * @throws EE_Error
1305
-     */
1306
-    public function status_obj()
1307
-    {
1308
-        return $this->get_first_related('Status');
1309
-    }
1310
-
1311
-
1312
-    /**
1313
-     * Returns the number of times this registration has checked into any of the datetimes
1314
-     * its available for
1315
-     *
1316
-     * @return int
1317
-     * @throws EE_Error
1318
-     */
1319
-    public function count_checkins()
1320
-    {
1321
-        return $this->get_model()->count_related($this, 'Checkin');
1322
-    }
1323
-
1324
-
1325
-    /**
1326
-     * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1327
-     * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1328
-     *
1329
-     * @return int
1330
-     * @throws EE_Error
1331
-     */
1332
-    public function count_checkins_not_checkedout()
1333
-    {
1334
-        return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1335
-    }
1336
-
1337
-
1338
-    /**
1339
-     * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1340
-     *
1341
-     * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1342
-     * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1343
-     *                                          consider registration status as well as datetime access.
1344
-     * @return bool
1345
-     * @throws EE_Error
1346
-     */
1347
-    public function can_checkin($DTT_OR_ID, $check_approved = true)
1348
-    {
1349
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1350
-
1351
-        //first check registration status
1352
-        if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1353
-            return false;
1354
-        }
1355
-        //is there a datetime ticket that matches this dtt_ID?
1356
-        if (! (EEM_Datetime_Ticket::instance()->exists(array(
1357
-            array(
1358
-                'TKT_ID' => $this->get('TKT_ID'),
1359
-                'DTT_ID' => $DTT_ID,
1360
-            ),
1361
-        )))
1362
-        ) {
1363
-            return false;
1364
-        }
1365
-
1366
-        //final check is against TKT_uses
1367
-        return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1368
-    }
1369
-
1370
-
1371
-    /**
1372
-     * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1373
-     * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1374
-     * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1375
-     * then return false.  Otherwise return true.
1376
-     *
1377
-     * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1378
-     * @return bool true means can checkin.  false means cannot checkin.
1379
-     * @throws EE_Error
1380
-     */
1381
-    public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1382
-    {
1383
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1384
-
1385
-        if (! $DTT_ID) {
1386
-            return false;
1387
-        }
1388
-
1389
-        $max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1390
-
1391
-        // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1392
-        // check-in or not.
1393
-        if (! $max_uses || $max_uses === EE_INF) {
1394
-            return true;
1395
-        }
1396
-
1397
-        //does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1398
-        //go ahead and toggle.
1399
-        if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1400
-            return true;
1401
-        }
1402
-
1403
-        //made it here so the last check is whether the number of checkins per unique datetime on this registration
1404
-        //disallows further check-ins.
1405
-        $count_unique_dtt_checkins = EEM_Checkin::instance()->count(array(
1406
-            array(
1407
-                'REG_ID' => $this->ID(),
1408
-                'CHK_in' => true,
1409
-            ),
1410
-        ), 'DTT_ID', true);
1411
-        // checkins have already reached their max number of uses
1412
-        // so registrant can NOT checkin
1413
-        if ($count_unique_dtt_checkins >= $max_uses) {
1414
-            EE_Error::add_error(
1415
-                esc_html__(
1416
-                    'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1417
-                    'event_espresso'
1418
-                ),
1419
-                __FILE__,
1420
-                __FUNCTION__,
1421
-                __LINE__
1422
-            );
1423
-            return false;
1424
-        }
1425
-        return true;
1426
-    }
1427
-
1428
-
1429
-    /**
1430
-     * toggle Check-in status for this registration
1431
-     * Check-ins are toggled in the following order:
1432
-     * never checked in -> checked in
1433
-     * checked in -> checked out
1434
-     * checked out -> checked in
1435
-     *
1436
-     * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1437
-     *                      If not included or null, then it is assumed latest datetime is being toggled.
1438
-     * @param bool $verify  If true then can_checkin() is used to verify whether the person
1439
-     *                      can be checked in or not.  Otherwise this forces change in checkin status.
1440
-     * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1441
-     * @throws EE_Error
1442
-     */
1443
-    public function toggle_checkin_status($DTT_ID = null, $verify = false)
1444
-    {
1445
-        if (empty($DTT_ID)) {
1446
-            $datetime = $this->get_latest_related_datetime();
1447
-            $DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1448
-            // verify the registration can checkin for the given DTT_ID
1449
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1450
-            EE_Error::add_error(
1451
-                sprintf(
1452
-                    esc_html__(
1453
-                        'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1454
-                        'event_espresso'
1455
-                    ),
1456
-                    $this->ID(),
1457
-                    $DTT_ID
1458
-                ),
1459
-                __FILE__,
1460
-                __FUNCTION__,
1461
-                __LINE__
1462
-            );
1463
-            return false;
1464
-        }
1465
-        $status_paths = array(
1466
-            EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1467
-            EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1468
-            EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1469
-        );
1470
-        //start by getting the current status so we know what status we'll be changing to.
1471
-        $cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1472
-        $status_to  = $status_paths[$cur_status];
1473
-        // database only records true for checked IN or false for checked OUT
1474
-        // no record ( null ) means checked in NEVER, but we obviously don't save that
1475
-        $new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1476
-        // add relation - note Check-ins are always creating new rows
1477
-        // because we are keeping track of Check-ins over time.
1478
-        // Eventually we'll probably want to show a list table
1479
-        // for the individual Check-ins so that they can be managed.
1480
-        $checkin = EE_Checkin::new_instance(array(
1481
-            'REG_ID' => $this->ID(),
1482
-            'DTT_ID' => $DTT_ID,
1483
-            'CHK_in' => $new_status,
1484
-        ));
1485
-        // if the record could not be saved then return false
1486
-        if ($checkin->save() === 0) {
1487
-            if (WP_DEBUG) {
1488
-                global $wpdb;
1489
-                $error = sprintf(
1490
-                    esc_html__(
1491
-                        'Registration check in update failed because of the following database error: %1$s%2$s',
1492
-                        'event_espresso'
1493
-                    ),
1494
-                    '<br />',
1495
-                    $wpdb->last_error
1496
-                );
1497
-            } else {
1498
-                $error = esc_html__(
1499
-                    'Registration check in update failed because of an unknown database error',
1500
-                    'event_espresso'
1501
-                );
1502
-            }
1503
-            EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1504
-            return false;
1505
-        }
1506
-        return $status_to;
1507
-    }
1508
-
1509
-
1510
-    /**
1511
-     * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1512
-     * "Latest" is defined by the `DTT_EVT_start` column.
1513
-     *
1514
-     * @return EE_Datetime|null
1515
-     * @throws \EE_Error
1516
-     */
1517
-    public function get_latest_related_datetime()
1518
-    {
1519
-        return EEM_Datetime::instance()->get_one(
1520
-            array(
1521
-                array(
1522
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1523
-                ),
1524
-                'order_by' => array('DTT_EVT_start' => 'DESC'),
1525
-            )
1526
-        );
1527
-    }
1528
-
1529
-
1530
-    /**
1531
-     * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1532
-     * "Earliest" is defined by the `DTT_EVT_start` column.
1533
-     *
1534
-     * @throws \EE_Error
1535
-     */
1536
-    public function get_earliest_related_datetime()
1537
-    {
1538
-        return EEM_Datetime::instance()->get_one(
1539
-            array(
1540
-                array(
1541
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1542
-                ),
1543
-                'order_by' => array('DTT_EVT_start' => 'ASC'),
1544
-            )
1545
-        );
1546
-    }
1547
-
1548
-
1549
-    /**
1550
-     * This method simply returns the check-in status for this registration and the given datetime.
1551
-     * If neither the datetime nor the checkin values are provided as arguments,
1552
-     * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1553
-     *
1554
-     * @param  int       $DTT_ID  The ID of the datetime we're checking against
1555
-     *                            (if empty we'll get the primary datetime for
1556
-     *                            this registration (via event) and use it's ID);
1557
-     * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1558
-     * @return int                Integer representing Check-in status.
1559
-     * @throws \EE_Error
1560
-     */
1561
-    public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1562
-    {
1563
-        $checkin_query_params = array(
1564
-            'order_by' => array('CHK_timestamp' => 'DESC'),
1565
-        );
1566
-
1567
-        if ($DTT_ID > 0) {
1568
-            $checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1569
-        }
1570
-
1571
-        //get checkin object (if exists)
1572
-        $checkin = $checkin instanceof EE_Checkin
1573
-            ? $checkin
1574
-            : $this->get_first_related('Checkin', $checkin_query_params);
1575
-        if ($checkin instanceof EE_Checkin) {
1576
-            if ($checkin->get('CHK_in')) {
1577
-                return EE_Checkin::status_checked_in; //checked in
1578
-            }
1579
-            return EE_Checkin::status_checked_out; //had checked in but is now checked out.
1580
-        }
1581
-        return EE_Checkin::status_checked_never; //never been checked in
1582
-    }
1583
-
1584
-
1585
-    /**
1586
-     * This method returns a localized message for the toggled Check-in message.
1587
-     *
1588
-     * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1589
-     *                     then it is assumed Check-in for primary datetime was toggled.
1590
-     * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1591
-     *                     message can be customized with the attendee name.
1592
-     * @return string internationalized message
1593
-     * @throws EE_Error
1594
-     */
1595
-    public function get_checkin_msg($DTT_ID, $error = false)
1596
-    {
1597
-        //let's get the attendee first so we can include the name of the attendee
1598
-        $attendee = $this->get_first_related('Attendee');
1599
-        if ($attendee instanceof EE_Attendee) {
1600
-            if ($error) {
1601
-                return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1602
-            }
1603
-            $cur_status = $this->check_in_status_for_datetime($DTT_ID);
1604
-            //what is the status message going to be?
1605
-            switch ($cur_status) {
1606
-                case EE_Checkin::status_checked_never:
1607
-                    return sprintf(__("%s has been removed from Check-in records", "event_espresso"),
1608
-                        $attendee->full_name());
1609
-                    break;
1610
-                case EE_Checkin::status_checked_in:
1611
-                    return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1612
-                    break;
1613
-                case EE_Checkin::status_checked_out:
1614
-                    return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1615
-                    break;
1616
-            }
1617
-        }
1618
-        return esc_html__("The check-in status could not be determined.", "event_espresso");
1619
-    }
1620
-
1621
-
1622
-    /**
1623
-     * Returns the related EE_Transaction to this registration
1624
-     *
1625
-     * @return EE_Transaction
1626
-     * @throws EE_Error
1627
-     * @throws EntityNotFoundException
1628
-     */
1629
-    public function transaction()
1630
-    {
1631
-        $transaction = $this->get_first_related('Transaction');
1632
-        if (! $transaction instanceof \EE_Transaction) {
1633
-            throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1634
-        }
1635
-        return $transaction;
1636
-    }
1637
-
1638
-
1639
-    /**
1640
-     *        get Registration Code
1641
-     */
1642
-    public function reg_code()
1643
-    {
1644
-        return $this->get('REG_code');
1645
-    }
1646
-
1647
-
1648
-    /**
1649
-     *        get Transaction ID
1650
-     */
1651
-    public function transaction_ID()
1652
-    {
1653
-        return $this->get('TXN_ID');
1654
-    }
1655
-
1656
-
1657
-    /**
1658
-     * @return int
1659
-     * @throws EE_Error
1660
-     */
1661
-    public function ticket_ID()
1662
-    {
1663
-        return $this->get('TKT_ID');
1664
-    }
1665
-
1666
-
1667
-    /**
1668
-     *        Set Registration Code
1669
-     *
1670
-     * @access    public
1671
-     * @param    string  $REG_code Registration Code
1672
-     * @param    boolean $use_default
1673
-     * @throws EE_Error
1674
-     */
1675
-    public function set_reg_code($REG_code, $use_default = false)
1676
-    {
1677
-        if (empty($REG_code)) {
1678
-            EE_Error::add_error(
1679
-                esc_html__('REG_code can not be empty.', 'event_espresso'),
1680
-                __FILE__,
1681
-                __FUNCTION__,
1682
-                __LINE__
1683
-            );
1684
-            return;
1685
-        }
1686
-        if (! $this->reg_code()) {
1687
-            parent::set('REG_code', $REG_code, $use_default);
1688
-        } else {
1689
-            EE_Error::doing_it_wrong(
1690
-                __CLASS__ . '::' . __FUNCTION__,
1691
-                esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1692
-                '4.6.0'
1693
-            );
1694
-        }
1695
-    }
1696
-
1697
-
1698
-    /**
1699
-     * Returns all other registrations in the same group as this registrant who have the same ticket option.
1700
-     * Note, if you want to just get all registrations in the same transaction (group), use:
1701
-     *    $registration->transaction()->registrations();
1702
-     *
1703
-     * @since 4.5.0
1704
-     * @return EE_Registration[] or empty array if this isn't a group registration.
1705
-     * @throws EE_Error
1706
-     */
1707
-    public function get_all_other_registrations_in_group()
1708
-    {
1709
-        if ($this->group_size() < 2) {
1710
-            return array();
1711
-        }
1712
-
1713
-        $query[0] = array(
1714
-            'TXN_ID' => $this->transaction_ID(),
1715
-            'REG_ID' => array('!=', $this->ID()),
1716
-            'TKT_ID' => $this->ticket_ID(),
1717
-        );
1718
-        /** @var EE_Registration[] $registrations */
1719
-        $registrations = $this->get_model()->get_all($query);
1720
-        return $registrations;
1721
-    }
1722
-
1723
-    /**
1724
-     * Return the link to the admin details for the object.
1725
-     *
1726
-     * @return string
1727
-     * @throws EE_Error
1728
-     */
1729
-    public function get_admin_details_link()
1730
-    {
1731
-        EE_Registry::instance()->load_helper('URL');
1732
-        return EEH_URL::add_query_args_and_nonce(
1733
-            array(
1734
-                'page'    => 'espresso_registrations',
1735
-                'action'  => 'view_registration',
1736
-                '_REG_ID' => $this->ID(),
1737
-            ),
1738
-            admin_url('admin.php')
1739
-        );
1740
-    }
1741
-
1742
-    /**
1743
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1744
-     *
1745
-     * @return string
1746
-     * @throws EE_Error
1747
-     */
1748
-    public function get_admin_edit_link()
1749
-    {
1750
-        return $this->get_admin_details_link();
1751
-    }
1752
-
1753
-    /**
1754
-     * Returns the link to a settings page for the object.
1755
-     *
1756
-     * @return string
1757
-     * @throws EE_Error
1758
-     */
1759
-    public function get_admin_settings_link()
1760
-    {
1761
-        return $this->get_admin_details_link();
1762
-    }
1763
-
1764
-    /**
1765
-     * Returns the link to the "overview" for the object (typically the "list table" view).
1766
-     *
1767
-     * @return string
1768
-     */
1769
-    public function get_admin_overview_link()
1770
-    {
1771
-        EE_Registry::instance()->load_helper('URL');
1772
-        return EEH_URL::add_query_args_and_nonce(
1773
-            array(
1774
-                'page' => 'espresso_registrations',
1775
-            ),
1776
-            admin_url('admin.php')
1777
-        );
1778
-    }
1779
-
1780
-
1781
-    /**
1782
-     * @param array $query_params
1783
-     * @return \EE_Registration[]
1784
-     * @throws \EE_Error
1785
-     */
1786
-    public function payments($query_params = array())
1787
-    {
1788
-        return $this->get_many_related('Payment', $query_params);
1789
-    }
1790
-
1791
-
1792
-    /**
1793
-     * @param array $query_params
1794
-     * @return \EE_Registration_Payment[]
1795
-     * @throws \EE_Error
1796
-     */
1797
-    public function registration_payments($query_params = array())
1798
-    {
1799
-        return $this->get_many_related('Registration_Payment', $query_params);
1800
-    }
1801
-
1802
-
1803
-    /**
1804
-     * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1805
-     * Note: if there are no payments on the registration there will be no payment method returned.
1806
-     *
1807
-     * @return EE_Payment_Method|null
1808
-     */
1809
-    public function payment_method()
1810
-    {
1811
-        return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1812
-    }
1813
-
1814
-
1815
-    /**
1816
-     * @return \EE_Line_Item
1817
-     * @throws EntityNotFoundException
1818
-     * @throws \EE_Error
1819
-     */
1820
-    public function ticket_line_item()
1821
-    {
1822
-        $ticket            = $this->ticket();
1823
-        $transaction       = $this->transaction();
1824
-        $line_item         = null;
1825
-        $ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1826
-            $transaction->total_line_item(),
1827
-            'Ticket',
1828
-            array($ticket->ID())
1829
-        );
1830
-        foreach ($ticket_line_items as $ticket_line_item) {
1831
-            if (
1832
-                $ticket_line_item instanceof \EE_Line_Item
1833
-                && $ticket_line_item->OBJ_type() === 'Ticket'
1834
-                && $ticket_line_item->OBJ_ID() === $ticket->ID()
1835
-            ) {
1836
-                $line_item = $ticket_line_item;
1837
-                break;
1838
-            }
1839
-        }
1840
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1841
-            throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1842
-        }
1843
-        return $line_item;
1844
-    }
1845
-
1846
-
1847
-    /**
1848
-     * Soft Deletes this model object.
1849
-     *
1850
-     * @return boolean | int
1851
-     * @throws \RuntimeException
1852
-     * @throws \EE_Error
1853
-     */
1854
-    public function delete()
1855
-    {
1856
-        if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1857
-            $this->set_status(EEM_Registration::status_id_cancelled);
1858
-        }
1859
-        return parent::delete();
1860
-    }
1861
-
1862
-
1863
-    /**
1864
-     * Restores whatever the previous status was on a registration before it was trashed (if possible)
1865
-     *
1866
-     * @throws \EE_Error
1867
-     * @throws \RuntimeException
1868
-     */
1869
-    public function restore()
1870
-    {
1871
-        $previous_status = $this->get_extra_meta(
1872
-            EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1873
-            true,
1874
-            EEM_Registration::status_id_cancelled
1875
-        );
1876
-        if ($previous_status) {
1877
-            $this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1878
-            $this->set_status($previous_status);
1879
-        }
1880
-        return parent::restore();
1881
-    }
1882
-
1883
-
1884
-
1885
-    /*************************** DEPRECATED ***************************/
1886
-
1887
-
1888
-    /**
1889
-     * @deprecated
1890
-     * @since     4.7.0
1891
-     * @access    public
1892
-     */
1893
-    public function price_paid()
1894
-    {
1895
-        EE_Error::doing_it_wrong('EE_Registration::price_paid()',
1896
-            esc_html__('This method is deprecated, please use EE_Registration::final_price() instead.', 'event_espresso'),
1897
-            '4.7.0');
1898
-        return $this->final_price();
1899
-    }
1900
-
1901
-
1902
-    /**
1903
-     * @deprecated
1904
-     * @since     4.7.0
1905
-     * @access    public
1906
-     * @param    float $REG_final_price
1907
-     * @throws EE_Error
1908
-     * @throws RuntimeException
1909
-     */
1910
-    public function set_price_paid($REG_final_price = 0.00)
1911
-    {
1912
-        EE_Error::doing_it_wrong('EE_Registration::set_price_paid()',
1913
-            esc_html__('This method is deprecated, please use EE_Registration::set_final_price() instead.', 'event_espresso'),
1914
-            '4.7.0');
1915
-        $this->set_final_price($REG_final_price);
1916
-    }
1917
-
1918
-
1919
-    /**
1920
-     * @deprecated
1921
-     * @since 4.7.0
1922
-     * @return string
1923
-     * @throws EE_Error
1924
-     */
1925
-    public function pretty_price_paid()
1926
-    {
1927
-        EE_Error::doing_it_wrong('EE_Registration::pretty_price_paid()',
1928
-            esc_html__('This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
1929
-                'event_espresso'), '4.7.0');
1930
-        return $this->pretty_final_price();
1931
-    }
1932
-
1933
-
1934
-    /**
1935
-     * Gets the primary datetime related to this registration via the related Event to this registration
1936
-     *
1937
-     * @deprecated 4.9.17
1938
-     * @return EE_Datetime
1939
-     * @throws EE_Error
1940
-     * @throws EntityNotFoundException
1941
-     */
1942
-    public function get_related_primary_datetime()
1943
-    {
1944
-        EE_Error::doing_it_wrong(
1945
-            __METHOD__,
1946
-            esc_html__(
1947
-                'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
1948
-                'event_espresso'
1949
-            ),
1950
-            '4.9.17',
1951
-            '5.0.0'
1952
-        );
1953
-        return $this->event()->primary_datetime();
1954
-    }
21
+	/**
22
+	 * Used to reference when a registration has never been checked in.
23
+	 *
24
+	 * @deprecated use \EE_Checkin::status_checked_never instead
25
+	 * @type int
26
+	 */
27
+	const checkin_status_never = 2;
28
+
29
+	/**
30
+	 * Used to reference when a registration has been checked in.
31
+	 *
32
+	 * @deprecated use \EE_Checkin::status_checked_in instead
33
+	 * @type int
34
+	 */
35
+	const checkin_status_in = 1;
36
+
37
+
38
+	/**
39
+	 * Used to reference when a registration has been checked out.
40
+	 *
41
+	 * @deprecated use \EE_Checkin::status_checked_out instead
42
+	 * @type int
43
+	 */
44
+	const checkin_status_out = 0;
45
+
46
+
47
+	/**
48
+	 * extra meta key for tracking reg status os trashed registrations
49
+	 *
50
+	 * @type string
51
+	 */
52
+	const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
53
+
54
+
55
+	/**
56
+	 * extra meta key for tracking if registration has reserved ticket
57
+	 *
58
+	 * @type string
59
+	 */
60
+	const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
61
+
62
+
63
+	/**
64
+	 * @param array  $props_n_values          incoming values
65
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
66
+	 *                                        used.)
67
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
68
+	 *                                        date_format and the second value is the time format
69
+	 * @return EE_Registration
70
+	 * @throws EE_Error
71
+	 */
72
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
73
+	{
74
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
75
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
76
+	}
77
+
78
+
79
+	/**
80
+	 * @param array  $props_n_values  incoming values from the database
81
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
82
+	 *                                the website will be used.
83
+	 * @return EE_Registration
84
+	 */
85
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
86
+	{
87
+		return new self($props_n_values, true, $timezone);
88
+	}
89
+
90
+
91
+	/**
92
+	 *        Set Event ID
93
+	 *
94
+	 * @param        int $EVT_ID Event ID
95
+	 * @throws EE_Error
96
+	 * @throws RuntimeException
97
+	 */
98
+	public function set_event($EVT_ID = 0)
99
+	{
100
+		$this->set('EVT_ID', $EVT_ID);
101
+	}
102
+
103
+
104
+	/**
105
+	 * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
106
+	 * be routed to internal methods
107
+	 *
108
+	 * @param string $field_name
109
+	 * @param mixed  $field_value
110
+	 * @param bool   $use_default
111
+	 * @throws EE_Error
112
+	 * @throws EntityNotFoundException
113
+	 * @throws InvalidArgumentException
114
+	 * @throws InvalidDataTypeException
115
+	 * @throws InvalidInterfaceException
116
+	 * @throws ReflectionException
117
+	 * @throws RuntimeException
118
+	 */
119
+	public function set($field_name, $field_value, $use_default = false)
120
+	{
121
+		switch ($field_name) {
122
+			case 'REG_code':
123
+				if (! empty($field_value) && $this->reg_code() === null) {
124
+					$this->set_reg_code($field_value, $use_default);
125
+				}
126
+				break;
127
+			case 'STS_ID':
128
+				$this->set_status($field_value, $use_default);
129
+				break;
130
+			default:
131
+				parent::set($field_name, $field_value, $use_default);
132
+		}
133
+	}
134
+
135
+
136
+	/**
137
+	 * Set Status ID
138
+	 * updates the registration status and ALSO...
139
+	 * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
140
+	 * calls release_registration_space() if the reg status changes FROM approved to any other reg status
141
+	 *
142
+	 * @param string       $new_STS_ID
143
+	 * @param boolean      $use_default
144
+	 * @param Context|null $context
145
+	 * @return bool
146
+	 * @throws EE_Error
147
+	 * @throws EntityNotFoundException
148
+	 * @throws InvalidArgumentException
149
+	 * @throws ReflectionException
150
+	 * @throws RuntimeException
151
+	 * @throws InvalidDataTypeException
152
+	 * @throws InvalidInterfaceException
153
+	 */
154
+	public function set_status($new_STS_ID = null, $use_default = false, Context $context = null)
155
+	{
156
+		// get current REG_Status
157
+		$old_STS_ID = $this->status_ID();
158
+		// if status has changed
159
+		if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
160
+			&& ! empty($old_STS_ID) // and that old status is actually set
161
+			&& ! empty($new_STS_ID) // as well as the new status
162
+			&& $this->ID() // ensure registration is in the db
163
+		) {
164
+			// TO approved
165
+			if ($new_STS_ID === EEM_Registration::status_id_approved) {
166
+				// reserve a space by incrementing ticket and datetime sold values
167
+				$this->_reserve_registration_space();
168
+				do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
169
+				// OR FROM  approved
170
+			} elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
171
+				// release a space by decrementing ticket and datetime sold values
172
+				$this->_release_registration_space();
173
+				do_action(
174
+					'AHEE__EE_Registration__set_status__from_approved',
175
+					$this,
176
+					$old_STS_ID,
177
+					$new_STS_ID,
178
+					$context
179
+				);
180
+			}
181
+			// update status
182
+			parent::set('STS_ID', $new_STS_ID, $use_default);
183
+			$this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, $context);
184
+			if($this->statusChangeUpdatesTransaction($context)) {
185
+				$this->updateTransactionAfterStatusChange();
186
+			}
187
+			do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
188
+			return true;
189
+		}
190
+		//even though the old value matches the new value, it's still good to
191
+		//allow the parent set method to have a say
192
+		parent::set('STS_ID', $new_STS_ID, $use_default);
193
+		return true;
194
+	}
195
+
196
+
197
+	/**
198
+	 * update REGs and TXN when cancelled or declined registrations involved
199
+	 *
200
+	 * @param string       $new_STS_ID
201
+	 * @param string       $old_STS_ID
202
+	 * @param Context|null $context
203
+	 * @throws EE_Error
204
+	 * @throws InvalidArgumentException
205
+	 * @throws InvalidDataTypeException
206
+	 * @throws InvalidInterfaceException
207
+	 * @throws ReflectionException
208
+	 */
209
+	private function _update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, Context $context = null)
210
+	{
211
+		// these reg statuses should not be considered in any calculations involving monies owing
212
+		$closed_reg_statuses = EEM_Registration::closed_reg_statuses();
213
+		// true if registration has been cancelled or declined
214
+		$this->updateIfCanceled(
215
+			$closed_reg_statuses,
216
+			$new_STS_ID,
217
+			$old_STS_ID,
218
+			$context
219
+		);
220
+		$this->updateIfDeclined(
221
+			$closed_reg_statuses,
222
+			$new_STS_ID,
223
+			$old_STS_ID,
224
+			$context
225
+		);
226
+	}
227
+
228
+
229
+	/**
230
+	 * update REGs and TXN when cancelled or declined registrations involved
231
+	 *
232
+	 * @param array        $closed_reg_statuses
233
+	 * @param string       $new_STS_ID
234
+	 * @param string       $old_STS_ID
235
+	 * @param Context|null $context
236
+	 * @throws EE_Error
237
+	 * @throws InvalidArgumentException
238
+	 * @throws InvalidDataTypeException
239
+	 * @throws InvalidInterfaceException
240
+	 * @throws ReflectionException
241
+	 */
242
+	private function updateIfCanceled(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, Context $context = null)
243
+	{
244
+		// true if registration has been cancelled or declined
245
+		if (in_array($new_STS_ID, $closed_reg_statuses, true)
246
+			&& ! in_array($old_STS_ID, $closed_reg_statuses, true)
247
+		) {
248
+			/** @type EE_Registration_Processor $registration_processor */
249
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
250
+			/** @type EE_Transaction_Processor $transaction_processor */
251
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
252
+			// cancelled or declined registration
253
+			$registration_processor->update_registration_after_being_canceled_or_declined(
254
+				$this,
255
+				$closed_reg_statuses
256
+			);
257
+			$transaction_processor->update_transaction_after_canceled_or_declined_registration(
258
+				$this,
259
+				$closed_reg_statuses,
260
+				false
261
+			);
262
+			do_action(
263
+				'AHEE__EE_Registration__set_status__canceled_or_declined',
264
+				$this,
265
+				$old_STS_ID,
266
+				$new_STS_ID,
267
+				$context
268
+			);
269
+			return;
270
+		}
271
+	}
272
+
273
+
274
+	/**
275
+	 * update REGs and TXN when cancelled or declined registrations involved
276
+	 *
277
+	 * @param array        $closed_reg_statuses
278
+	 * @param string       $new_STS_ID
279
+	 * @param string       $old_STS_ID
280
+	 * @param Context|null $context
281
+	 * @throws EE_Error
282
+	 * @throws InvalidArgumentException
283
+	 * @throws InvalidDataTypeException
284
+	 * @throws InvalidInterfaceException
285
+	 * @throws ReflectionException
286
+	 */
287
+	private function updateIfDeclined(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, Context $context = null)
288
+	{
289
+		// true if reinstating cancelled or declined registration
290
+		if (in_array($old_STS_ID, $closed_reg_statuses, true)
291
+			&& ! in_array($new_STS_ID, $closed_reg_statuses, true)
292
+		) {
293
+			/** @type EE_Registration_Processor $registration_processor */
294
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
295
+			/** @type EE_Transaction_Processor $transaction_processor */
296
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
297
+			// reinstating cancelled or declined registration
298
+			$registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
299
+				$this,
300
+				$closed_reg_statuses
301
+			);
302
+			$transaction_processor->update_transaction_after_reinstating_canceled_registration(
303
+				$this,
304
+				$closed_reg_statuses,
305
+				false
306
+			);
307
+			do_action(
308
+				'AHEE__EE_Registration__set_status__after_reinstated',
309
+				$this,
310
+				$old_STS_ID,
311
+				$new_STS_ID,
312
+				$context
313
+			);
314
+		}
315
+	}
316
+
317
+
318
+	/**
319
+	 * @param Context|null $context
320
+	 * @return bool
321
+	 */
322
+	private function statusChangeUpdatesTransaction(Context $context = null)
323
+	{
324
+		$contexts_that_do_not_update_transaction = (array) apply_filters(
325
+			'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
326
+			array('spco_reg_step_attendee_information_process_registrations'),
327
+			$context,
328
+			$this
329
+		);
330
+		return ! (
331
+			$context instanceof Context
332
+			&& in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
333
+		);
334
+	}
335
+
336
+
337
+	/**
338
+	 * @throws EE_Error
339
+	 * @throws EntityNotFoundException
340
+	 * @throws InvalidArgumentException
341
+	 * @throws InvalidDataTypeException
342
+	 * @throws InvalidInterfaceException
343
+	 * @throws ReflectionException
344
+	 * @throws RuntimeException
345
+	 */
346
+	private function updateTransactionAfterStatusChange()
347
+	{
348
+		/** @type EE_Transaction_Payments $transaction_payments */
349
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
350
+		$transaction_payments->recalculate_transaction_total($this->transaction(), false);
351
+		$this->transaction()->update_status_based_on_total_paid(true);
352
+	}
353
+
354
+
355
+	/**
356
+	 *        get Status ID
357
+	 */
358
+	public function status_ID()
359
+	{
360
+		return $this->get('STS_ID');
361
+	}
362
+
363
+
364
+	/**
365
+	 * increments this registration's related ticket sold and corresponding datetime sold values
366
+	 *
367
+	 * @return void
368
+	 * @throws EE_Error
369
+	 * @throws EntityNotFoundException
370
+	 */
371
+	private function _reserve_registration_space()
372
+	{
373
+		// reserved ticket and datetime counts will be decremented as sold counts are incremented
374
+		// so stop tracking that this reg has a ticket reserved
375
+		$this->release_reserved_ticket();
376
+		$ticket = $this->ticket();
377
+		$ticket->increase_sold();
378
+		$ticket->save();
379
+		// possibly set event status to sold out
380
+		$this->event()->perform_sold_out_status_check();
381
+	}
382
+
383
+
384
+	/**
385
+	 * Gets the ticket this registration is for
386
+	 *
387
+	 * @param boolean $include_archived whether to include archived tickets or not.
388
+	 * @return EE_Ticket|EE_Base_Class
389
+	 * @throws \EE_Error
390
+	 */
391
+	public function ticket($include_archived = true)
392
+	{
393
+		$query_params = array();
394
+		if ($include_archived) {
395
+			$query_params['default_where_conditions'] = 'none';
396
+		}
397
+		return $this->get_first_related('Ticket', $query_params);
398
+	}
399
+
400
+
401
+	/**
402
+	 * Gets the event this registration is for
403
+	 *
404
+	 * @return EE_Event
405
+	 * @throws EE_Error
406
+	 * @throws EntityNotFoundException
407
+	 */
408
+	public function event()
409
+	{
410
+		$event = $this->get_first_related('Event');
411
+		if (! $event instanceof \EE_Event) {
412
+			throw new EntityNotFoundException('Event ID', $this->event_ID());
413
+		}
414
+		return $event;
415
+	}
416
+
417
+
418
+	/**
419
+	 * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
420
+	 * with the author of the event this registration is for.
421
+	 *
422
+	 * @since 4.5.0
423
+	 * @return int
424
+	 * @throws EE_Error
425
+	 * @throws EntityNotFoundException
426
+	 */
427
+	public function wp_user()
428
+	{
429
+		$event = $this->event();
430
+		if ($event instanceof EE_Event) {
431
+			return $event->wp_user();
432
+		}
433
+		return 0;
434
+	}
435
+
436
+
437
+	/**
438
+	 * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
439
+	 *
440
+	 * @return void
441
+	 * @throws \EE_Error
442
+	 */
443
+	private function _release_registration_space()
444
+	{
445
+		$ticket = $this->ticket();
446
+		$ticket->decrease_sold();
447
+		$ticket->save();
448
+	}
449
+
450
+
451
+	/**
452
+	 * tracks this registration's ticket reservation in extra meta
453
+	 * and can increment related ticket reserved and corresponding datetime reserved values
454
+	 *
455
+	 * @param bool $update_ticket if true, will increment ticket and datetime reserved count
456
+	 * @return void
457
+	 * @throws \EE_Error
458
+	 */
459
+	public function reserve_ticket($update_ticket = false)
460
+	{
461
+		if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) === false) {
462
+			// PLZ NOTE: although checking $update_ticket first would be more efficient,
463
+			// we NEED to ALWAYS call update_extra_meta(), which is why that is done first
464
+			if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) && $update_ticket) {
465
+				$ticket = $this->ticket();
466
+				$ticket->increase_reserved();
467
+				$ticket->save();
468
+			}
469
+		}
470
+	}
471
+
472
+
473
+	/**
474
+	 * stops tracking this registration's ticket reservation in extra meta
475
+	 * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
476
+	 *
477
+	 * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
478
+	 * @return void
479
+	 * @throws \EE_Error
480
+	 */
481
+	public function release_reserved_ticket($update_ticket = false)
482
+	{
483
+		if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) !== false) {
484
+			// PLZ NOTE: although checking $update_ticket first would be more efficient,
485
+			// we NEED to ALWAYS call delete_extra_meta(), which is why that is done first
486
+			if ($this->delete_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY) && $update_ticket) {
487
+				$ticket = $this->ticket();
488
+				$ticket->decrease_reserved();
489
+				$ticket->save();
490
+			}
491
+		}
492
+	}
493
+
494
+
495
+	/**
496
+	 * Set Attendee ID
497
+	 *
498
+	 * @param        int $ATT_ID Attendee ID
499
+	 * @throws EE_Error
500
+	 * @throws RuntimeException
501
+	 */
502
+	public function set_attendee_id($ATT_ID = 0)
503
+	{
504
+		$this->set('ATT_ID', $ATT_ID);
505
+	}
506
+
507
+
508
+	/**
509
+	 *        Set Transaction ID
510
+	 *
511
+	 * @param        int $TXN_ID Transaction ID
512
+	 * @throws EE_Error
513
+	 * @throws RuntimeException
514
+	 */
515
+	public function set_transaction_id($TXN_ID = 0)
516
+	{
517
+		$this->set('TXN_ID', $TXN_ID);
518
+	}
519
+
520
+
521
+	/**
522
+	 *        Set Session
523
+	 *
524
+	 * @param    string $REG_session PHP Session ID
525
+	 * @throws EE_Error
526
+	 * @throws RuntimeException
527
+	 */
528
+	public function set_session($REG_session = '')
529
+	{
530
+		$this->set('REG_session', $REG_session);
531
+	}
532
+
533
+
534
+	/**
535
+	 *        Set Registration URL Link
536
+	 *
537
+	 * @param    string $REG_url_link Registration URL Link
538
+	 * @throws EE_Error
539
+	 * @throws RuntimeException
540
+	 */
541
+	public function set_reg_url_link($REG_url_link = '')
542
+	{
543
+		$this->set('REG_url_link', $REG_url_link);
544
+	}
545
+
546
+
547
+	/**
548
+	 *        Set Attendee Counter
549
+	 *
550
+	 * @param        int $REG_count Primary Attendee
551
+	 * @throws EE_Error
552
+	 * @throws RuntimeException
553
+	 */
554
+	public function set_count($REG_count = 1)
555
+	{
556
+		$this->set('REG_count', $REG_count);
557
+	}
558
+
559
+
560
+	/**
561
+	 *        Set Group Size
562
+	 *
563
+	 * @param        boolean $REG_group_size Group Registration
564
+	 * @throws EE_Error
565
+	 * @throws RuntimeException
566
+	 */
567
+	public function set_group_size($REG_group_size = false)
568
+	{
569
+		$this->set('REG_group_size', $REG_group_size);
570
+	}
571
+
572
+
573
+	/**
574
+	 *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
575
+	 *    EEM_Registration::status_id_not_approved
576
+	 *
577
+	 * @return        boolean
578
+	 */
579
+	public function is_not_approved()
580
+	{
581
+		return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
582
+	}
583
+
584
+
585
+	/**
586
+	 *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
587
+	 *    EEM_Registration::status_id_pending_payment
588
+	 *
589
+	 * @return        boolean
590
+	 */
591
+	public function is_pending_payment()
592
+	{
593
+		return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
594
+	}
595
+
596
+
597
+	/**
598
+	 *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
599
+	 *
600
+	 * @return        boolean
601
+	 */
602
+	public function is_approved()
603
+	{
604
+		return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
605
+	}
606
+
607
+
608
+	/**
609
+	 *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
610
+	 *
611
+	 * @return        boolean
612
+	 */
613
+	public function is_cancelled()
614
+	{
615
+		return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
616
+	}
617
+
618
+
619
+	/**
620
+	 *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
621
+	 *
622
+	 * @return        boolean
623
+	 */
624
+	public function is_declined()
625
+	{
626
+		return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
627
+	}
628
+
629
+
630
+	/**
631
+	 *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
632
+	 *    EEM_Registration::status_id_incomplete
633
+	 *
634
+	 * @return        boolean
635
+	 */
636
+	public function is_incomplete()
637
+	{
638
+		return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
639
+	}
640
+
641
+
642
+	/**
643
+	 *        Set Registration Date
644
+	 *
645
+	 * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
646
+	 *                                                 Date
647
+	 * @throws EE_Error
648
+	 * @throws RuntimeException
649
+	 */
650
+	public function set_reg_date($REG_date = false)
651
+	{
652
+		$this->set('REG_date', $REG_date);
653
+	}
654
+
655
+
656
+	/**
657
+	 *    Set final price owing for this registration after all ticket/price modifications
658
+	 *
659
+	 * @access    public
660
+	 * @param    float $REG_final_price
661
+	 * @throws EE_Error
662
+	 * @throws RuntimeException
663
+	 */
664
+	public function set_final_price($REG_final_price = 0.00)
665
+	{
666
+		$this->set('REG_final_price', $REG_final_price);
667
+	}
668
+
669
+
670
+	/**
671
+	 *    Set amount paid towards this registration's final price
672
+	 *
673
+	 * @access    public
674
+	 * @param    float $REG_paid
675
+	 * @throws EE_Error
676
+	 * @throws RuntimeException
677
+	 */
678
+	public function set_paid($REG_paid = 0.00)
679
+	{
680
+		$this->set('REG_paid', $REG_paid);
681
+	}
682
+
683
+
684
+	/**
685
+	 *        Attendee Is Going
686
+	 *
687
+	 * @param        boolean $REG_att_is_going Attendee Is Going
688
+	 * @throws EE_Error
689
+	 * @throws RuntimeException
690
+	 */
691
+	public function set_att_is_going($REG_att_is_going = false)
692
+	{
693
+		$this->set('REG_att_is_going', $REG_att_is_going);
694
+	}
695
+
696
+
697
+	/**
698
+	 * Gets the related attendee
699
+	 *
700
+	 * @return EE_Attendee
701
+	 * @throws EE_Error
702
+	 */
703
+	public function attendee()
704
+	{
705
+		return $this->get_first_related('Attendee');
706
+	}
707
+
708
+
709
+	/**
710
+	 *        get Event ID
711
+	 */
712
+	public function event_ID()
713
+	{
714
+		return $this->get('EVT_ID');
715
+	}
716
+
717
+
718
+	/**
719
+	 *        get Event ID
720
+	 */
721
+	public function event_name()
722
+	{
723
+		$event = $this->event_obj();
724
+		if ($event) {
725
+			return $event->name();
726
+		} else {
727
+			return null;
728
+		}
729
+	}
730
+
731
+
732
+	/**
733
+	 * Fetches the event this registration is for
734
+	 *
735
+	 * @return EE_Event
736
+	 * @throws EE_Error
737
+	 */
738
+	public function event_obj()
739
+	{
740
+		return $this->get_first_related('Event');
741
+	}
742
+
743
+
744
+	/**
745
+	 *        get Attendee ID
746
+	 */
747
+	public function attendee_ID()
748
+	{
749
+		return $this->get('ATT_ID');
750
+	}
751
+
752
+
753
+	/**
754
+	 *        get PHP Session ID
755
+	 */
756
+	public function session_ID()
757
+	{
758
+		return $this->get('REG_session');
759
+	}
760
+
761
+
762
+	/**
763
+	 * Gets the string which represents the URL trigger for the receipt template in the message template system.
764
+	 *
765
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
766
+	 * @return string
767
+	 */
768
+	public function receipt_url($messenger = 'html')
769
+	{
770
+
771
+		/**
772
+		 * The below will be deprecated one version after this.  We check first if there is a custom receipt template
773
+		 * already in use on old system.  If there is then we just return the standard url for it.
774
+		 *
775
+		 * @since 4.5.0
776
+		 */
777
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
778
+		$has_custom             = EEH_Template::locate_template(
779
+			$template_relative_path,
780
+			array(),
781
+			true,
782
+			true,
783
+			true
784
+		);
785
+
786
+		if ($has_custom) {
787
+			return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
788
+		}
789
+		return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
790
+	}
791
+
792
+
793
+	/**
794
+	 * Gets the string which represents the URL trigger for the invoice template in the message template system.
795
+	 *
796
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
797
+	 * @return string
798
+	 * @throws EE_Error
799
+	 */
800
+	public function invoice_url($messenger = 'html')
801
+	{
802
+		/**
803
+		 * The below will be deprecated one version after this.  We check first if there is a custom invoice template
804
+		 * already in use on old system.  If there is then we just return the standard url for it.
805
+		 *
806
+		 * @since 4.5.0
807
+		 */
808
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
809
+		$has_custom             = EEH_Template::locate_template(
810
+			$template_relative_path,
811
+			array(),
812
+			true,
813
+			true,
814
+			true
815
+		);
816
+
817
+		if ($has_custom) {
818
+			if ($messenger == 'html') {
819
+				return $this->invoice_url('launch');
820
+			}
821
+			$route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
822
+
823
+			$query_args = array('ee' => $route, 'id' => $this->reg_url_link());
824
+			if ($messenger == 'html') {
825
+				$query_args['html'] = true;
826
+			}
827
+			return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
828
+		}
829
+		return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
830
+	}
831
+
832
+
833
+	/**
834
+	 * get Registration URL Link
835
+	 *
836
+	 * @access public
837
+	 * @return string
838
+	 * @throws \EE_Error
839
+	 */
840
+	public function reg_url_link()
841
+	{
842
+		return (string) $this->get('REG_url_link');
843
+	}
844
+
845
+
846
+	/**
847
+	 * Echoes out invoice_url()
848
+	 *
849
+	 * @param string $type 'download','launch', or 'html' (default is 'launch')
850
+	 * @return void
851
+	 * @throws EE_Error
852
+	 */
853
+	public function e_invoice_url($type = 'launch')
854
+	{
855
+		echo $this->invoice_url($type);
856
+	}
857
+
858
+
859
+	/**
860
+	 * Echoes out payment_overview_url
861
+	 */
862
+	public function e_payment_overview_url()
863
+	{
864
+		echo $this->payment_overview_url();
865
+	}
866
+
867
+
868
+	/**
869
+	 * Gets the URL of the thank you page with this registration REG_url_link added as
870
+	 * a query parameter
871
+	 *
872
+	 * @param bool $clear_session Set to true when you want to clear the session on revisiting the
873
+	 *                            payment overview url.
874
+	 * @return string
875
+	 * @throws EE_Error
876
+	 */
877
+	public function payment_overview_url($clear_session = false)
878
+	{
879
+		return add_query_arg(array(
880
+			'e_reg_url_link' => $this->reg_url_link(),
881
+			'step'           => 'payment_options',
882
+			'revisit'        => true,
883
+			'clear_session' => (bool) $clear_session
884
+		), EE_Registry::instance()->CFG->core->reg_page_url());
885
+	}
886
+
887
+
888
+	/**
889
+	 * Gets the URL of the thank you page with this registration REG_url_link added as
890
+	 * a query parameter
891
+	 *
892
+	 * @return string
893
+	 * @throws EE_Error
894
+	 */
895
+	public function edit_attendee_information_url()
896
+	{
897
+		return add_query_arg(array(
898
+			'e_reg_url_link' => $this->reg_url_link(),
899
+			'step'           => 'attendee_information',
900
+			'revisit'        => true,
901
+		), EE_Registry::instance()->CFG->core->reg_page_url());
902
+	}
903
+
904
+
905
+	/**
906
+	 * Simply generates and returns the appropriate admin_url link to edit this registration
907
+	 *
908
+	 * @return string
909
+	 * @throws EE_Error
910
+	 */
911
+	public function get_admin_edit_url()
912
+	{
913
+		return EEH_URL::add_query_args_and_nonce(array(
914
+			'page'    => 'espresso_registrations',
915
+			'action'  => 'view_registration',
916
+			'_REG_ID' => $this->ID(),
917
+		), admin_url('admin.php'));
918
+	}
919
+
920
+
921
+	/**
922
+	 *    is_primary_registrant?
923
+	 */
924
+	public function is_primary_registrant()
925
+	{
926
+		return $this->get('REG_count') == 1 ? true : false;
927
+	}
928
+
929
+
930
+	/**
931
+	 * This returns the primary registration object for this registration group (which may be this object).
932
+	 *
933
+	 * @return EE_Registration
934
+	 * @throws EE_Error
935
+	 */
936
+	public function get_primary_registration()
937
+	{
938
+		if ($this->is_primary_registrant()) {
939
+			return $this;
940
+		}
941
+
942
+		//k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
943
+		/** @var EE_Registration $primary_registrant */
944
+		$primary_registrant = EEM_Registration::instance()->get_one(array(
945
+			array(
946
+				'TXN_ID'    => $this->transaction_ID(),
947
+				'REG_count' => 1,
948
+			),
949
+		));
950
+		return $primary_registrant;
951
+	}
952
+
953
+
954
+	/**
955
+	 *        get  Attendee Number
956
+	 *
957
+	 * @access        public
958
+	 */
959
+	public function count()
960
+	{
961
+		return $this->get('REG_count');
962
+	}
963
+
964
+
965
+	/**
966
+	 *        get Group Size
967
+	 */
968
+	public function group_size()
969
+	{
970
+		return $this->get('REG_group_size');
971
+	}
972
+
973
+
974
+	/**
975
+	 *        get Registration Date
976
+	 */
977
+	public function date()
978
+	{
979
+		return $this->get('REG_date');
980
+	}
981
+
982
+
983
+	/**
984
+	 * gets a pretty date
985
+	 *
986
+	 * @param string $date_format
987
+	 * @param string $time_format
988
+	 * @return string
989
+	 * @throws EE_Error
990
+	 */
991
+	public function pretty_date($date_format = null, $time_format = null)
992
+	{
993
+		return $this->get_datetime('REG_date', $date_format, $time_format);
994
+	}
995
+
996
+
997
+	/**
998
+	 * final_price
999
+	 * the registration's share of the transaction total, so that the
1000
+	 * sum of all the transaction's REG_final_prices equal the transaction's total
1001
+	 *
1002
+	 * @return float
1003
+	 * @throws EE_Error
1004
+	 */
1005
+	public function final_price()
1006
+	{
1007
+		return $this->get('REG_final_price');
1008
+	}
1009
+
1010
+
1011
+	/**
1012
+	 * pretty_final_price
1013
+	 *  final price as formatted string, with correct decimal places and currency symbol
1014
+	 *
1015
+	 * @return string
1016
+	 * @throws EE_Error
1017
+	 */
1018
+	public function pretty_final_price()
1019
+	{
1020
+		return $this->get_pretty('REG_final_price');
1021
+	}
1022
+
1023
+
1024
+	/**
1025
+	 * get paid (yeah)
1026
+	 *
1027
+	 * @return float
1028
+	 * @throws EE_Error
1029
+	 */
1030
+	public function paid()
1031
+	{
1032
+		return $this->get('REG_paid');
1033
+	}
1034
+
1035
+
1036
+	/**
1037
+	 * pretty_paid
1038
+	 *
1039
+	 * @return float
1040
+	 * @throws EE_Error
1041
+	 */
1042
+	public function pretty_paid()
1043
+	{
1044
+		return $this->get_pretty('REG_paid');
1045
+	}
1046
+
1047
+
1048
+	/**
1049
+	 * owes_monies_and_can_pay
1050
+	 * whether or not this registration has monies owing and it's' status allows payment
1051
+	 *
1052
+	 * @param array $requires_payment
1053
+	 * @return bool
1054
+	 * @throws EE_Error
1055
+	 */
1056
+	public function owes_monies_and_can_pay($requires_payment = array())
1057
+	{
1058
+		// these reg statuses require payment (if event is not free)
1059
+		$requires_payment = ! empty($requires_payment)
1060
+			? $requires_payment
1061
+			: EEM_Registration::reg_statuses_that_allow_payment();
1062
+		if (in_array($this->status_ID(), $requires_payment) &&
1063
+			$this->final_price() != 0 &&
1064
+			$this->final_price() != $this->paid()
1065
+		) {
1066
+			return true;
1067
+		} else {
1068
+			return false;
1069
+		}
1070
+	}
1071
+
1072
+
1073
+	/**
1074
+	 * Prints out the return value of $this->pretty_status()
1075
+	 *
1076
+	 * @param bool $show_icons
1077
+	 * @return void
1078
+	 * @throws EE_Error
1079
+	 */
1080
+	public function e_pretty_status($show_icons = false)
1081
+	{
1082
+		echo $this->pretty_status($show_icons);
1083
+	}
1084
+
1085
+
1086
+	/**
1087
+	 * Returns a nice version of the status for displaying to customers
1088
+	 *
1089
+	 * @param bool $show_icons
1090
+	 * @return string
1091
+	 * @throws EE_Error
1092
+	 */
1093
+	public function pretty_status($show_icons = false)
1094
+	{
1095
+		$status = EEM_Status::instance()->localized_status(
1096
+			array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1097
+			false,
1098
+			'sentence'
1099
+		);
1100
+		$icon   = '';
1101
+		switch ($this->status_ID()) {
1102
+			case EEM_Registration::status_id_approved:
1103
+				$icon = $show_icons
1104
+					? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1105
+					: '';
1106
+				break;
1107
+			case EEM_Registration::status_id_pending_payment:
1108
+				$icon = $show_icons
1109
+					? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1110
+					: '';
1111
+				break;
1112
+			case EEM_Registration::status_id_not_approved:
1113
+				$icon = $show_icons
1114
+					? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1115
+					: '';
1116
+				break;
1117
+			case EEM_Registration::status_id_cancelled:
1118
+				$icon = $show_icons
1119
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1120
+					: '';
1121
+				break;
1122
+			case EEM_Registration::status_id_incomplete:
1123
+				$icon = $show_icons
1124
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1125
+					: '';
1126
+				break;
1127
+			case EEM_Registration::status_id_declined:
1128
+				$icon = $show_icons
1129
+					? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1130
+					: '';
1131
+				break;
1132
+			case EEM_Registration::status_id_wait_list:
1133
+				$icon = $show_icons
1134
+					? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1135
+					: '';
1136
+				break;
1137
+		}
1138
+		return $icon . $status[$this->status_ID()];
1139
+	}
1140
+
1141
+
1142
+	/**
1143
+	 *        get Attendee Is Going
1144
+	 */
1145
+	public function att_is_going()
1146
+	{
1147
+		return $this->get('REG_att_is_going');
1148
+	}
1149
+
1150
+
1151
+	/**
1152
+	 * Gets related answers
1153
+	 *
1154
+	 * @param array $query_params like EEM_Base::get_all
1155
+	 * @return EE_Answer[]
1156
+	 * @throws EE_Error
1157
+	 */
1158
+	public function answers($query_params = null)
1159
+	{
1160
+		return $this->get_many_related('Answer', $query_params);
1161
+	}
1162
+
1163
+
1164
+	/**
1165
+	 * Gets the registration's answer value to the specified question
1166
+	 * (either the question's ID or a question object)
1167
+	 *
1168
+	 * @param EE_Question|int $question
1169
+	 * @param bool            $pretty_value
1170
+	 * @return array|string if pretty_value= true, the result will always be a string
1171
+	 * (because the answer might be an array of answer values, so passing pretty_value=true
1172
+	 * will convert it into some kind of string)
1173
+	 * @throws EE_Error
1174
+	 */
1175
+	public function answer_value_to_question($question, $pretty_value = true)
1176
+	{
1177
+		$question_id = EEM_Question::instance()->ensure_is_ID($question);
1178
+		return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1179
+	}
1180
+
1181
+
1182
+	/**
1183
+	 * question_groups
1184
+	 * returns an array of EE_Question_Group objects for this registration
1185
+	 *
1186
+	 * @return EE_Question_Group[]
1187
+	 * @throws EE_Error
1188
+	 * @throws EntityNotFoundException
1189
+	 */
1190
+	public function question_groups()
1191
+	{
1192
+		$question_groups = array();
1193
+		if ($this->event() instanceof EE_Event) {
1194
+			$question_groups = $this->event()->question_groups(
1195
+				array(
1196
+					array(
1197
+						'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1198
+					),
1199
+					'order_by' => array('QSG_order' => 'ASC'),
1200
+				)
1201
+			);
1202
+		}
1203
+		return $question_groups;
1204
+	}
1205
+
1206
+
1207
+	/**
1208
+	 * count_question_groups
1209
+	 * returns a count of the number of EE_Question_Group objects for this registration
1210
+	 *
1211
+	 * @return int
1212
+	 * @throws EE_Error
1213
+	 * @throws EntityNotFoundException
1214
+	 */
1215
+	public function count_question_groups()
1216
+	{
1217
+		$qg_count = 0;
1218
+		if ($this->event() instanceof EE_Event) {
1219
+			$qg_count = $this->event()->count_related(
1220
+				'Question_Group',
1221
+				array(
1222
+					array(
1223
+						'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1224
+					),
1225
+				)
1226
+			);
1227
+		}
1228
+		return $qg_count;
1229
+	}
1230
+
1231
+
1232
+	/**
1233
+	 * Returns the registration date in the 'standard' string format
1234
+	 * (function may be improved in the future to allow for different formats and timezones)
1235
+	 *
1236
+	 * @return string
1237
+	 * @throws EE_Error
1238
+	 */
1239
+	public function reg_date()
1240
+	{
1241
+		return $this->get_datetime('REG_date');
1242
+	}
1243
+
1244
+
1245
+	/**
1246
+	 * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1247
+	 * the ticket this registration purchased, or the datetime they have registered
1248
+	 * to attend)
1249
+	 *
1250
+	 * @return EE_Datetime_Ticket
1251
+	 * @throws EE_Error
1252
+	 */
1253
+	public function datetime_ticket()
1254
+	{
1255
+		return $this->get_first_related('Datetime_Ticket');
1256
+	}
1257
+
1258
+
1259
+	/**
1260
+	 * Sets the registration's datetime_ticket.
1261
+	 *
1262
+	 * @param EE_Datetime_Ticket $datetime_ticket
1263
+	 * @return EE_Datetime_Ticket
1264
+	 * @throws EE_Error
1265
+	 */
1266
+	public function set_datetime_ticket($datetime_ticket)
1267
+	{
1268
+		return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1269
+	}
1270
+
1271
+	/**
1272
+	 * Gets deleted
1273
+	 *
1274
+	 * @return bool
1275
+	 * @throws EE_Error
1276
+	 */
1277
+	public function deleted()
1278
+	{
1279
+		return $this->get('REG_deleted');
1280
+	}
1281
+
1282
+	/**
1283
+	 * Sets deleted
1284
+	 *
1285
+	 * @param boolean $deleted
1286
+	 * @return bool
1287
+	 * @throws EE_Error
1288
+	 * @throws RuntimeException
1289
+	 */
1290
+	public function set_deleted($deleted)
1291
+	{
1292
+		if ($deleted) {
1293
+			$this->delete();
1294
+		} else {
1295
+			$this->restore();
1296
+		}
1297
+	}
1298
+
1299
+
1300
+	/**
1301
+	 * Get the status object of this object
1302
+	 *
1303
+	 * @return EE_Status
1304
+	 * @throws EE_Error
1305
+	 */
1306
+	public function status_obj()
1307
+	{
1308
+		return $this->get_first_related('Status');
1309
+	}
1310
+
1311
+
1312
+	/**
1313
+	 * Returns the number of times this registration has checked into any of the datetimes
1314
+	 * its available for
1315
+	 *
1316
+	 * @return int
1317
+	 * @throws EE_Error
1318
+	 */
1319
+	public function count_checkins()
1320
+	{
1321
+		return $this->get_model()->count_related($this, 'Checkin');
1322
+	}
1323
+
1324
+
1325
+	/**
1326
+	 * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1327
+	 * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1328
+	 *
1329
+	 * @return int
1330
+	 * @throws EE_Error
1331
+	 */
1332
+	public function count_checkins_not_checkedout()
1333
+	{
1334
+		return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1335
+	}
1336
+
1337
+
1338
+	/**
1339
+	 * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1340
+	 *
1341
+	 * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1342
+	 * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1343
+	 *                                          consider registration status as well as datetime access.
1344
+	 * @return bool
1345
+	 * @throws EE_Error
1346
+	 */
1347
+	public function can_checkin($DTT_OR_ID, $check_approved = true)
1348
+	{
1349
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1350
+
1351
+		//first check registration status
1352
+		if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1353
+			return false;
1354
+		}
1355
+		//is there a datetime ticket that matches this dtt_ID?
1356
+		if (! (EEM_Datetime_Ticket::instance()->exists(array(
1357
+			array(
1358
+				'TKT_ID' => $this->get('TKT_ID'),
1359
+				'DTT_ID' => $DTT_ID,
1360
+			),
1361
+		)))
1362
+		) {
1363
+			return false;
1364
+		}
1365
+
1366
+		//final check is against TKT_uses
1367
+		return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1368
+	}
1369
+
1370
+
1371
+	/**
1372
+	 * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1373
+	 * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1374
+	 * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1375
+	 * then return false.  Otherwise return true.
1376
+	 *
1377
+	 * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1378
+	 * @return bool true means can checkin.  false means cannot checkin.
1379
+	 * @throws EE_Error
1380
+	 */
1381
+	public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1382
+	{
1383
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1384
+
1385
+		if (! $DTT_ID) {
1386
+			return false;
1387
+		}
1388
+
1389
+		$max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1390
+
1391
+		// if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1392
+		// check-in or not.
1393
+		if (! $max_uses || $max_uses === EE_INF) {
1394
+			return true;
1395
+		}
1396
+
1397
+		//does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1398
+		//go ahead and toggle.
1399
+		if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1400
+			return true;
1401
+		}
1402
+
1403
+		//made it here so the last check is whether the number of checkins per unique datetime on this registration
1404
+		//disallows further check-ins.
1405
+		$count_unique_dtt_checkins = EEM_Checkin::instance()->count(array(
1406
+			array(
1407
+				'REG_ID' => $this->ID(),
1408
+				'CHK_in' => true,
1409
+			),
1410
+		), 'DTT_ID', true);
1411
+		// checkins have already reached their max number of uses
1412
+		// so registrant can NOT checkin
1413
+		if ($count_unique_dtt_checkins >= $max_uses) {
1414
+			EE_Error::add_error(
1415
+				esc_html__(
1416
+					'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1417
+					'event_espresso'
1418
+				),
1419
+				__FILE__,
1420
+				__FUNCTION__,
1421
+				__LINE__
1422
+			);
1423
+			return false;
1424
+		}
1425
+		return true;
1426
+	}
1427
+
1428
+
1429
+	/**
1430
+	 * toggle Check-in status for this registration
1431
+	 * Check-ins are toggled in the following order:
1432
+	 * never checked in -> checked in
1433
+	 * checked in -> checked out
1434
+	 * checked out -> checked in
1435
+	 *
1436
+	 * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1437
+	 *                      If not included or null, then it is assumed latest datetime is being toggled.
1438
+	 * @param bool $verify  If true then can_checkin() is used to verify whether the person
1439
+	 *                      can be checked in or not.  Otherwise this forces change in checkin status.
1440
+	 * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1441
+	 * @throws EE_Error
1442
+	 */
1443
+	public function toggle_checkin_status($DTT_ID = null, $verify = false)
1444
+	{
1445
+		if (empty($DTT_ID)) {
1446
+			$datetime = $this->get_latest_related_datetime();
1447
+			$DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1448
+			// verify the registration can checkin for the given DTT_ID
1449
+		} elseif (! $this->can_checkin($DTT_ID, $verify)) {
1450
+			EE_Error::add_error(
1451
+				sprintf(
1452
+					esc_html__(
1453
+						'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1454
+						'event_espresso'
1455
+					),
1456
+					$this->ID(),
1457
+					$DTT_ID
1458
+				),
1459
+				__FILE__,
1460
+				__FUNCTION__,
1461
+				__LINE__
1462
+			);
1463
+			return false;
1464
+		}
1465
+		$status_paths = array(
1466
+			EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1467
+			EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1468
+			EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1469
+		);
1470
+		//start by getting the current status so we know what status we'll be changing to.
1471
+		$cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1472
+		$status_to  = $status_paths[$cur_status];
1473
+		// database only records true for checked IN or false for checked OUT
1474
+		// no record ( null ) means checked in NEVER, but we obviously don't save that
1475
+		$new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1476
+		// add relation - note Check-ins are always creating new rows
1477
+		// because we are keeping track of Check-ins over time.
1478
+		// Eventually we'll probably want to show a list table
1479
+		// for the individual Check-ins so that they can be managed.
1480
+		$checkin = EE_Checkin::new_instance(array(
1481
+			'REG_ID' => $this->ID(),
1482
+			'DTT_ID' => $DTT_ID,
1483
+			'CHK_in' => $new_status,
1484
+		));
1485
+		// if the record could not be saved then return false
1486
+		if ($checkin->save() === 0) {
1487
+			if (WP_DEBUG) {
1488
+				global $wpdb;
1489
+				$error = sprintf(
1490
+					esc_html__(
1491
+						'Registration check in update failed because of the following database error: %1$s%2$s',
1492
+						'event_espresso'
1493
+					),
1494
+					'<br />',
1495
+					$wpdb->last_error
1496
+				);
1497
+			} else {
1498
+				$error = esc_html__(
1499
+					'Registration check in update failed because of an unknown database error',
1500
+					'event_espresso'
1501
+				);
1502
+			}
1503
+			EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1504
+			return false;
1505
+		}
1506
+		return $status_to;
1507
+	}
1508
+
1509
+
1510
+	/**
1511
+	 * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1512
+	 * "Latest" is defined by the `DTT_EVT_start` column.
1513
+	 *
1514
+	 * @return EE_Datetime|null
1515
+	 * @throws \EE_Error
1516
+	 */
1517
+	public function get_latest_related_datetime()
1518
+	{
1519
+		return EEM_Datetime::instance()->get_one(
1520
+			array(
1521
+				array(
1522
+					'Ticket.Registration.REG_ID' => $this->ID(),
1523
+				),
1524
+				'order_by' => array('DTT_EVT_start' => 'DESC'),
1525
+			)
1526
+		);
1527
+	}
1528
+
1529
+
1530
+	/**
1531
+	 * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1532
+	 * "Earliest" is defined by the `DTT_EVT_start` column.
1533
+	 *
1534
+	 * @throws \EE_Error
1535
+	 */
1536
+	public function get_earliest_related_datetime()
1537
+	{
1538
+		return EEM_Datetime::instance()->get_one(
1539
+			array(
1540
+				array(
1541
+					'Ticket.Registration.REG_ID' => $this->ID(),
1542
+				),
1543
+				'order_by' => array('DTT_EVT_start' => 'ASC'),
1544
+			)
1545
+		);
1546
+	}
1547
+
1548
+
1549
+	/**
1550
+	 * This method simply returns the check-in status for this registration and the given datetime.
1551
+	 * If neither the datetime nor the checkin values are provided as arguments,
1552
+	 * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1553
+	 *
1554
+	 * @param  int       $DTT_ID  The ID of the datetime we're checking against
1555
+	 *                            (if empty we'll get the primary datetime for
1556
+	 *                            this registration (via event) and use it's ID);
1557
+	 * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1558
+	 * @return int                Integer representing Check-in status.
1559
+	 * @throws \EE_Error
1560
+	 */
1561
+	public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1562
+	{
1563
+		$checkin_query_params = array(
1564
+			'order_by' => array('CHK_timestamp' => 'DESC'),
1565
+		);
1566
+
1567
+		if ($DTT_ID > 0) {
1568
+			$checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1569
+		}
1570
+
1571
+		//get checkin object (if exists)
1572
+		$checkin = $checkin instanceof EE_Checkin
1573
+			? $checkin
1574
+			: $this->get_first_related('Checkin', $checkin_query_params);
1575
+		if ($checkin instanceof EE_Checkin) {
1576
+			if ($checkin->get('CHK_in')) {
1577
+				return EE_Checkin::status_checked_in; //checked in
1578
+			}
1579
+			return EE_Checkin::status_checked_out; //had checked in but is now checked out.
1580
+		}
1581
+		return EE_Checkin::status_checked_never; //never been checked in
1582
+	}
1583
+
1584
+
1585
+	/**
1586
+	 * This method returns a localized message for the toggled Check-in message.
1587
+	 *
1588
+	 * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1589
+	 *                     then it is assumed Check-in for primary datetime was toggled.
1590
+	 * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1591
+	 *                     message can be customized with the attendee name.
1592
+	 * @return string internationalized message
1593
+	 * @throws EE_Error
1594
+	 */
1595
+	public function get_checkin_msg($DTT_ID, $error = false)
1596
+	{
1597
+		//let's get the attendee first so we can include the name of the attendee
1598
+		$attendee = $this->get_first_related('Attendee');
1599
+		if ($attendee instanceof EE_Attendee) {
1600
+			if ($error) {
1601
+				return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1602
+			}
1603
+			$cur_status = $this->check_in_status_for_datetime($DTT_ID);
1604
+			//what is the status message going to be?
1605
+			switch ($cur_status) {
1606
+				case EE_Checkin::status_checked_never:
1607
+					return sprintf(__("%s has been removed from Check-in records", "event_espresso"),
1608
+						$attendee->full_name());
1609
+					break;
1610
+				case EE_Checkin::status_checked_in:
1611
+					return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1612
+					break;
1613
+				case EE_Checkin::status_checked_out:
1614
+					return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1615
+					break;
1616
+			}
1617
+		}
1618
+		return esc_html__("The check-in status could not be determined.", "event_espresso");
1619
+	}
1620
+
1621
+
1622
+	/**
1623
+	 * Returns the related EE_Transaction to this registration
1624
+	 *
1625
+	 * @return EE_Transaction
1626
+	 * @throws EE_Error
1627
+	 * @throws EntityNotFoundException
1628
+	 */
1629
+	public function transaction()
1630
+	{
1631
+		$transaction = $this->get_first_related('Transaction');
1632
+		if (! $transaction instanceof \EE_Transaction) {
1633
+			throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1634
+		}
1635
+		return $transaction;
1636
+	}
1637
+
1638
+
1639
+	/**
1640
+	 *        get Registration Code
1641
+	 */
1642
+	public function reg_code()
1643
+	{
1644
+		return $this->get('REG_code');
1645
+	}
1646
+
1647
+
1648
+	/**
1649
+	 *        get Transaction ID
1650
+	 */
1651
+	public function transaction_ID()
1652
+	{
1653
+		return $this->get('TXN_ID');
1654
+	}
1655
+
1656
+
1657
+	/**
1658
+	 * @return int
1659
+	 * @throws EE_Error
1660
+	 */
1661
+	public function ticket_ID()
1662
+	{
1663
+		return $this->get('TKT_ID');
1664
+	}
1665
+
1666
+
1667
+	/**
1668
+	 *        Set Registration Code
1669
+	 *
1670
+	 * @access    public
1671
+	 * @param    string  $REG_code Registration Code
1672
+	 * @param    boolean $use_default
1673
+	 * @throws EE_Error
1674
+	 */
1675
+	public function set_reg_code($REG_code, $use_default = false)
1676
+	{
1677
+		if (empty($REG_code)) {
1678
+			EE_Error::add_error(
1679
+				esc_html__('REG_code can not be empty.', 'event_espresso'),
1680
+				__FILE__,
1681
+				__FUNCTION__,
1682
+				__LINE__
1683
+			);
1684
+			return;
1685
+		}
1686
+		if (! $this->reg_code()) {
1687
+			parent::set('REG_code', $REG_code, $use_default);
1688
+		} else {
1689
+			EE_Error::doing_it_wrong(
1690
+				__CLASS__ . '::' . __FUNCTION__,
1691
+				esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1692
+				'4.6.0'
1693
+			);
1694
+		}
1695
+	}
1696
+
1697
+
1698
+	/**
1699
+	 * Returns all other registrations in the same group as this registrant who have the same ticket option.
1700
+	 * Note, if you want to just get all registrations in the same transaction (group), use:
1701
+	 *    $registration->transaction()->registrations();
1702
+	 *
1703
+	 * @since 4.5.0
1704
+	 * @return EE_Registration[] or empty array if this isn't a group registration.
1705
+	 * @throws EE_Error
1706
+	 */
1707
+	public function get_all_other_registrations_in_group()
1708
+	{
1709
+		if ($this->group_size() < 2) {
1710
+			return array();
1711
+		}
1712
+
1713
+		$query[0] = array(
1714
+			'TXN_ID' => $this->transaction_ID(),
1715
+			'REG_ID' => array('!=', $this->ID()),
1716
+			'TKT_ID' => $this->ticket_ID(),
1717
+		);
1718
+		/** @var EE_Registration[] $registrations */
1719
+		$registrations = $this->get_model()->get_all($query);
1720
+		return $registrations;
1721
+	}
1722
+
1723
+	/**
1724
+	 * Return the link to the admin details for the object.
1725
+	 *
1726
+	 * @return string
1727
+	 * @throws EE_Error
1728
+	 */
1729
+	public function get_admin_details_link()
1730
+	{
1731
+		EE_Registry::instance()->load_helper('URL');
1732
+		return EEH_URL::add_query_args_and_nonce(
1733
+			array(
1734
+				'page'    => 'espresso_registrations',
1735
+				'action'  => 'view_registration',
1736
+				'_REG_ID' => $this->ID(),
1737
+			),
1738
+			admin_url('admin.php')
1739
+		);
1740
+	}
1741
+
1742
+	/**
1743
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1744
+	 *
1745
+	 * @return string
1746
+	 * @throws EE_Error
1747
+	 */
1748
+	public function get_admin_edit_link()
1749
+	{
1750
+		return $this->get_admin_details_link();
1751
+	}
1752
+
1753
+	/**
1754
+	 * Returns the link to a settings page for the object.
1755
+	 *
1756
+	 * @return string
1757
+	 * @throws EE_Error
1758
+	 */
1759
+	public function get_admin_settings_link()
1760
+	{
1761
+		return $this->get_admin_details_link();
1762
+	}
1763
+
1764
+	/**
1765
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
1766
+	 *
1767
+	 * @return string
1768
+	 */
1769
+	public function get_admin_overview_link()
1770
+	{
1771
+		EE_Registry::instance()->load_helper('URL');
1772
+		return EEH_URL::add_query_args_and_nonce(
1773
+			array(
1774
+				'page' => 'espresso_registrations',
1775
+			),
1776
+			admin_url('admin.php')
1777
+		);
1778
+	}
1779
+
1780
+
1781
+	/**
1782
+	 * @param array $query_params
1783
+	 * @return \EE_Registration[]
1784
+	 * @throws \EE_Error
1785
+	 */
1786
+	public function payments($query_params = array())
1787
+	{
1788
+		return $this->get_many_related('Payment', $query_params);
1789
+	}
1790
+
1791
+
1792
+	/**
1793
+	 * @param array $query_params
1794
+	 * @return \EE_Registration_Payment[]
1795
+	 * @throws \EE_Error
1796
+	 */
1797
+	public function registration_payments($query_params = array())
1798
+	{
1799
+		return $this->get_many_related('Registration_Payment', $query_params);
1800
+	}
1801
+
1802
+
1803
+	/**
1804
+	 * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1805
+	 * Note: if there are no payments on the registration there will be no payment method returned.
1806
+	 *
1807
+	 * @return EE_Payment_Method|null
1808
+	 */
1809
+	public function payment_method()
1810
+	{
1811
+		return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1812
+	}
1813
+
1814
+
1815
+	/**
1816
+	 * @return \EE_Line_Item
1817
+	 * @throws EntityNotFoundException
1818
+	 * @throws \EE_Error
1819
+	 */
1820
+	public function ticket_line_item()
1821
+	{
1822
+		$ticket            = $this->ticket();
1823
+		$transaction       = $this->transaction();
1824
+		$line_item         = null;
1825
+		$ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1826
+			$transaction->total_line_item(),
1827
+			'Ticket',
1828
+			array($ticket->ID())
1829
+		);
1830
+		foreach ($ticket_line_items as $ticket_line_item) {
1831
+			if (
1832
+				$ticket_line_item instanceof \EE_Line_Item
1833
+				&& $ticket_line_item->OBJ_type() === 'Ticket'
1834
+				&& $ticket_line_item->OBJ_ID() === $ticket->ID()
1835
+			) {
1836
+				$line_item = $ticket_line_item;
1837
+				break;
1838
+			}
1839
+		}
1840
+		if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1841
+			throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1842
+		}
1843
+		return $line_item;
1844
+	}
1845
+
1846
+
1847
+	/**
1848
+	 * Soft Deletes this model object.
1849
+	 *
1850
+	 * @return boolean | int
1851
+	 * @throws \RuntimeException
1852
+	 * @throws \EE_Error
1853
+	 */
1854
+	public function delete()
1855
+	{
1856
+		if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1857
+			$this->set_status(EEM_Registration::status_id_cancelled);
1858
+		}
1859
+		return parent::delete();
1860
+	}
1861
+
1862
+
1863
+	/**
1864
+	 * Restores whatever the previous status was on a registration before it was trashed (if possible)
1865
+	 *
1866
+	 * @throws \EE_Error
1867
+	 * @throws \RuntimeException
1868
+	 */
1869
+	public function restore()
1870
+	{
1871
+		$previous_status = $this->get_extra_meta(
1872
+			EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1873
+			true,
1874
+			EEM_Registration::status_id_cancelled
1875
+		);
1876
+		if ($previous_status) {
1877
+			$this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1878
+			$this->set_status($previous_status);
1879
+		}
1880
+		return parent::restore();
1881
+	}
1882
+
1883
+
1884
+
1885
+	/*************************** DEPRECATED ***************************/
1886
+
1887
+
1888
+	/**
1889
+	 * @deprecated
1890
+	 * @since     4.7.0
1891
+	 * @access    public
1892
+	 */
1893
+	public function price_paid()
1894
+	{
1895
+		EE_Error::doing_it_wrong('EE_Registration::price_paid()',
1896
+			esc_html__('This method is deprecated, please use EE_Registration::final_price() instead.', 'event_espresso'),
1897
+			'4.7.0');
1898
+		return $this->final_price();
1899
+	}
1900
+
1901
+
1902
+	/**
1903
+	 * @deprecated
1904
+	 * @since     4.7.0
1905
+	 * @access    public
1906
+	 * @param    float $REG_final_price
1907
+	 * @throws EE_Error
1908
+	 * @throws RuntimeException
1909
+	 */
1910
+	public function set_price_paid($REG_final_price = 0.00)
1911
+	{
1912
+		EE_Error::doing_it_wrong('EE_Registration::set_price_paid()',
1913
+			esc_html__('This method is deprecated, please use EE_Registration::set_final_price() instead.', 'event_espresso'),
1914
+			'4.7.0');
1915
+		$this->set_final_price($REG_final_price);
1916
+	}
1917
+
1918
+
1919
+	/**
1920
+	 * @deprecated
1921
+	 * @since 4.7.0
1922
+	 * @return string
1923
+	 * @throws EE_Error
1924
+	 */
1925
+	public function pretty_price_paid()
1926
+	{
1927
+		EE_Error::doing_it_wrong('EE_Registration::pretty_price_paid()',
1928
+			esc_html__('This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
1929
+				'event_espresso'), '4.7.0');
1930
+		return $this->pretty_final_price();
1931
+	}
1932
+
1933
+
1934
+	/**
1935
+	 * Gets the primary datetime related to this registration via the related Event to this registration
1936
+	 *
1937
+	 * @deprecated 4.9.17
1938
+	 * @return EE_Datetime
1939
+	 * @throws EE_Error
1940
+	 * @throws EntityNotFoundException
1941
+	 */
1942
+	public function get_related_primary_datetime()
1943
+	{
1944
+		EE_Error::doing_it_wrong(
1945
+			__METHOD__,
1946
+			esc_html__(
1947
+				'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
1948
+				'event_espresso'
1949
+			),
1950
+			'4.9.17',
1951
+			'5.0.0'
1952
+		);
1953
+		return $this->event()->primary_datetime();
1954
+	}
1955 1955
 
1956 1956
 
1957 1957
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -120,7 +120,7 @@  discard block
 block discarded – undo
120 120
     {
121 121
         switch ($field_name) {
122 122
             case 'REG_code':
123
-                if (! empty($field_value) && $this->reg_code() === null) {
123
+                if ( ! empty($field_value) && $this->reg_code() === null) {
124 124
                     $this->set_reg_code($field_value, $use_default);
125 125
                 }
126 126
                 break;
@@ -181,7 +181,7 @@  discard block
 block discarded – undo
181 181
             // update status
182 182
             parent::set('STS_ID', $new_STS_ID, $use_default);
183 183
             $this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, $context);
184
-            if($this->statusChangeUpdatesTransaction($context)) {
184
+            if ($this->statusChangeUpdatesTransaction($context)) {
185 185
                 $this->updateTransactionAfterStatusChange();
186 186
             }
187 187
             do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
@@ -408,7 +408,7 @@  discard block
 block discarded – undo
408 408
     public function event()
409 409
     {
410 410
         $event = $this->get_first_related('Event');
411
-        if (! $event instanceof \EE_Event) {
411
+        if ( ! $event instanceof \EE_Event) {
412 412
             throw new EntityNotFoundException('Event ID', $this->event_ID());
413 413
         }
414 414
         return $event;
@@ -1097,7 +1097,7 @@  discard block
 block discarded – undo
1097 1097
             false,
1098 1098
             'sentence'
1099 1099
         );
1100
-        $icon   = '';
1100
+        $icon = '';
1101 1101
         switch ($this->status_ID()) {
1102 1102
             case EEM_Registration::status_id_approved:
1103 1103
                 $icon = $show_icons
@@ -1135,7 +1135,7 @@  discard block
 block discarded – undo
1135 1135
                     : '';
1136 1136
                 break;
1137 1137
         }
1138
-        return $icon . $status[$this->status_ID()];
1138
+        return $icon.$status[$this->status_ID()];
1139 1139
     }
1140 1140
 
1141 1141
 
@@ -1353,7 +1353,7 @@  discard block
 block discarded – undo
1353 1353
             return false;
1354 1354
         }
1355 1355
         //is there a datetime ticket that matches this dtt_ID?
1356
-        if (! (EEM_Datetime_Ticket::instance()->exists(array(
1356
+        if ( ! (EEM_Datetime_Ticket::instance()->exists(array(
1357 1357
             array(
1358 1358
                 'TKT_ID' => $this->get('TKT_ID'),
1359 1359
                 'DTT_ID' => $DTT_ID,
@@ -1382,7 +1382,7 @@  discard block
 block discarded – undo
1382 1382
     {
1383 1383
         $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1384 1384
 
1385
-        if (! $DTT_ID) {
1385
+        if ( ! $DTT_ID) {
1386 1386
             return false;
1387 1387
         }
1388 1388
 
@@ -1390,7 +1390,7 @@  discard block
 block discarded – undo
1390 1390
 
1391 1391
         // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1392 1392
         // check-in or not.
1393
-        if (! $max_uses || $max_uses === EE_INF) {
1393
+        if ( ! $max_uses || $max_uses === EE_INF) {
1394 1394
             return true;
1395 1395
         }
1396 1396
 
@@ -1446,7 +1446,7 @@  discard block
 block discarded – undo
1446 1446
             $datetime = $this->get_latest_related_datetime();
1447 1447
             $DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1448 1448
             // verify the registration can checkin for the given DTT_ID
1449
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1449
+        } elseif ( ! $this->can_checkin($DTT_ID, $verify)) {
1450 1450
             EE_Error::add_error(
1451 1451
                 sprintf(
1452 1452
                     esc_html__(
@@ -1629,7 +1629,7 @@  discard block
 block discarded – undo
1629 1629
     public function transaction()
1630 1630
     {
1631 1631
         $transaction = $this->get_first_related('Transaction');
1632
-        if (! $transaction instanceof \EE_Transaction) {
1632
+        if ( ! $transaction instanceof \EE_Transaction) {
1633 1633
             throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1634 1634
         }
1635 1635
         return $transaction;
@@ -1683,11 +1683,11 @@  discard block
 block discarded – undo
1683 1683
             );
1684 1684
             return;
1685 1685
         }
1686
-        if (! $this->reg_code()) {
1686
+        if ( ! $this->reg_code()) {
1687 1687
             parent::set('REG_code', $REG_code, $use_default);
1688 1688
         } else {
1689 1689
             EE_Error::doing_it_wrong(
1690
-                __CLASS__ . '::' . __FUNCTION__,
1690
+                __CLASS__.'::'.__FUNCTION__,
1691 1691
                 esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1692 1692
                 '4.6.0'
1693 1693
             );
@@ -1837,7 +1837,7 @@  discard block
 block discarded – undo
1837 1837
                 break;
1838 1838
             }
1839 1839
         }
1840
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1840
+        if ( ! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1841 1841
             throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1842 1842
         }
1843 1843
         return $line_item;
Please login to merge, or discard this patch.
attendee_information/EE_SPCO_Reg_Step_Attendee_Information.class.php 1 patch
Indentation   +1327 added lines, -1327 removed lines patch added patch discarded remove patch
@@ -17,1335 +17,1335 @@
 block discarded – undo
17 17
 class EE_SPCO_Reg_Step_Attendee_Information extends EE_SPCO_Reg_Step
18 18
 {
19 19
 
20
-    /**
21
-     * @type bool $_print_copy_info
22
-     */
23
-    private $_print_copy_info = false;
24
-
25
-    /**
26
-     * @type array $_attendee_data
27
-     */
28
-    private $_attendee_data = array();
29
-
30
-    /**
31
-     * @type array $_required_questions
32
-     */
33
-    private $_required_questions = array();
34
-
35
-    /**
36
-     * @type array $_registration_answers
37
-     */
38
-    private $_registration_answers = array();
39
-
40
-
41
-    /**
42
-     *    class constructor
43
-     *
44
-     * @access    public
45
-     * @param    EE_Checkout $checkout
46
-     */
47
-    public function __construct(EE_Checkout $checkout)
48
-    {
49
-        $this->_slug     = 'attendee_information';
50
-        $this->_name     = esc_html__('Attendee Information', 'event_espresso');
51
-        $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'attendee_info_main.template.php';
52
-        $this->checkout  = $checkout;
53
-        $this->_reset_success_message();
54
-        $this->set_instructions(
55
-            esc_html__('Please answer the following registration questions before proceeding.', 'event_espresso')
56
-        );
57
-    }
58
-
59
-
60
-    public function translate_js_strings()
61
-    {
62
-        EE_Registry::$i18n_js_strings['required_field']            = esc_html__(
63
-            ' is a required question.',
64
-            'event_espresso'
65
-        );
66
-        EE_Registry::$i18n_js_strings['required_multi_field']      = esc_html__(
67
-            ' is a required question. Please enter a value for at least one of the options.',
68
-            'event_espresso'
69
-        );
70
-        EE_Registry::$i18n_js_strings['answer_required_questions'] = esc_html__(
71
-            'Please answer all required questions correctly before proceeding.',
72
-            'event_espresso'
73
-        );
74
-        EE_Registry::$i18n_js_strings['attendee_info_copied']      = sprintf(
75
-            esc_html__(
76
-                'The attendee information was successfully copied.%sPlease ensure the rest of the registration form is completed before proceeding.',
77
-                'event_espresso'
78
-            ),
79
-            '<br/>'
80
-        );
81
-        EE_Registry::$i18n_js_strings['attendee_info_copy_error']  = esc_html__(
82
-            'An unknown error occurred on the server while attempting to copy the attendee information. Please refresh the page and try again.',
83
-            'event_espresso'
84
-        );
85
-        EE_Registry::$i18n_js_strings['enter_valid_email']         = esc_html__(
86
-            'You must enter a valid email address.',
87
-            'event_espresso'
88
-        );
89
-        EE_Registry::$i18n_js_strings['valid_email_and_questions'] = esc_html__(
90
-            'You must enter a valid email address and answer all other required questions before you can proceed.',
91
-            'event_espresso'
92
-        );
93
-    }
94
-
95
-
96
-    public function enqueue_styles_and_scripts()
97
-    {
98
-    }
99
-
100
-
101
-    /**
102
-     * @return boolean
103
-     */
104
-    public function initialize_reg_step()
105
-    {
106
-        return true;
107
-    }
108
-
109
-
110
-    /**
111
-     * @return EE_Form_Section_Proper
112
-     * @throws EE_Error
113
-     * @throws InvalidArgumentException
114
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
115
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
116
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
117
-     */
118
-    public function generate_reg_form()
119
-    {
120
-        $this->_print_copy_info = false;
121
-        $primary_registrant     = null;
122
-        // autoload Line_Item_Display classes
123
-        EEH_Autoloader::register_line_item_display_autoloaders();
124
-        $Line_Item_Display = new EE_Line_Item_Display();
125
-        // calculate taxes
126
-        $Line_Item_Display->display_line_item(
127
-            $this->checkout->cart->get_grand_total(),
128
-            array('set_tax_rate' => true)
129
-        );
130
-        /** @var $subsections EE_Form_Section_Proper[] */
131
-        $subsections   = array(
132
-            'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
133
-        );
134
-        $template_args = array(
135
-            'revisit'       => $this->checkout->revisit,
136
-            'registrations' => array(),
137
-            'ticket_count'  => array(),
138
-        );
139
-        // grab the saved registrations from the transaction
140
-        $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
141
-        if ($registrations) {
142
-            foreach ($registrations as $registration) {
143
-                // can this registration be processed during this visit ?
144
-                if ($registration instanceof EE_Registration
145
-                    && $this->checkout->visit_allows_processing_of_this_registration($registration)
146
-                ) {
147
-                    $subsections[$registration->reg_url_link()] = $this->_registrations_reg_form($registration);
148
-                    if (! $this->checkout->admin_request) {
149
-                        $template_args['registrations'][$registration->reg_url_link()]    = $registration;
150
-                        $template_args['ticket_count'][$registration->ticket()->ID()]     = isset(
151
-                            $template_args['ticket_count'][$registration->ticket()->ID()]
152
-                        )
153
-                            ? $template_args['ticket_count'][$registration->ticket()->ID()] + 1
154
-                            : 1;
155
-                        $ticket_line_item = EEH_Line_Item::get_line_items_by_object_type_and_IDs(
156
-                            $this->checkout->cart->get_grand_total(),
157
-                            'Ticket',
158
-                            array($registration->ticket()->ID())
159
-                        );
160
-                        $ticket_line_item = is_array($ticket_line_item)
161
-                            ? reset($ticket_line_item)
162
-                            : $ticket_line_item;
163
-                        $template_args['ticket_line_item'][$registration->ticket()->ID()] =
164
-                            $Line_Item_Display->display_line_item($ticket_line_item);
165
-                    }
166
-                    if ($registration->is_primary_registrant()) {
167
-                        $primary_registrant = $registration->reg_url_link();
168
-                    }
169
-                }
170
-            }
171
-            // print_copy_info ?
172
-            if ($primary_registrant && ! $this->checkout->admin_request && count($registrations) > 1) {
173
-                // TODO: add admin option for toggling copy attendee info,
174
-                // then use that value to change $this->_print_copy_info
175
-                $copy_options['spco_copy_attendee_chk'] = $this->_print_copy_info
176
-                    ? $this->_copy_attendee_info_form()
177
-                    : $this->_auto_copy_attendee_info();
178
-                // generate hidden input
179
-                if (isset($subsections[$primary_registrant])
180
-                    && $subsections[$primary_registrant] instanceof EE_Form_Section_Proper
181
-                ) {
182
-                    $subsections[$primary_registrant]->add_subsections(
183
-                        $copy_options,
184
-                        'primary_registrant',
185
-                        false
186
-                    );
187
-                }
188
-            }
189
-        }
190
-
191
-        return new EE_Form_Section_Proper(
192
-            array(
193
-                'name'            => $this->reg_form_name(),
194
-                'html_id'         => $this->reg_form_name(),
195
-                'subsections'     => $subsections,
196
-                'layout_strategy' => $this->checkout->admin_request ?
197
-                    new EE_Div_Per_Section_Layout() :
198
-                    new EE_Template_Layout(
199
-                        array(
200
-                            'layout_template_file' => $this->_template, // layout_template
201
-                            'template_args'        => $template_args,
202
-                        )
203
-                    ),
204
-            )
205
-        );
206
-    }
207
-
208
-
209
-    /**
210
-     * @param EE_Registration $registration
211
-     * @return EE_Form_Section_Base
212
-     * @throws EE_Error
213
-     * @throws InvalidArgumentException
214
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
215
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
216
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
217
-     */
218
-    private function _registrations_reg_form(EE_Registration $registration)
219
-    {
220
-        static $attendee_nmbr = 1;
221
-        $form_args = array();
222
-        // verify that registration has valid event
223
-        if ($registration->event() instanceof EE_Event) {
224
-            $question_groups = $registration->event()->question_groups(
225
-                apply_filters(
226
-                    'FHEE__EE_SPCO_Reg_Step_Attendee_Information___registrations_reg_form__question_groups_query_parameters',
227
-                    array(
228
-                        array(
229
-                            'Event.EVT_ID'                     => $registration->event()->ID(),
230
-                            'Event_Question_Group.EQG_primary' => $registration->count() === 1 ? true : false,
231
-                        ),
232
-                        'order_by' => array('QSG_order' => 'ASC'),
233
-                    ),
234
-                    $registration,
235
-                    $this
236
-                )
237
-            );
238
-            if ($question_groups) {
239
-                // array of params to pass to parent constructor
240
-                $form_args = array(
241
-                    'html_id'         => 'ee-registration-' . $registration->reg_url_link(),
242
-                    'html_class'      => 'ee-reg-form-attendee-dv',
243
-                    'html_style'      => $this->checkout->admin_request
244
-                        ? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;'
245
-                        : '',
246
-                    'subsections'     => array(),
247
-                    'layout_strategy' => new EE_Fieldset_Section_Layout(
248
-                        array(
249
-                            'legend_class' => 'spco-attendee-lgnd smaller-text lt-grey-text',
250
-                            'legend_text'  => sprintf(__('Attendee %d', 'event_espresso'), $attendee_nmbr),
251
-                        )
252
-                    ),
253
-                );
254
-                foreach ($question_groups as $question_group) {
255
-                    if ($question_group instanceof EE_Question_Group) {
256
-                        $form_args['subsections'][$question_group->identifier()] = $this->_question_group_reg_form(
257
-                            $registration,
258
-                            $question_group
259
-                        );
260
-                    }
261
-                }
262
-                // add hidden input
263
-                $form_args['subsections']['additional_attendee_reg_info'] = $this->_additional_attendee_reg_info_input(
264
-                    $registration
265
-                );
266
-                // if we have question groups for additional attendees, then display the copy options
267
-                $this->_print_copy_info = $attendee_nmbr > 1 ? true : $this->_print_copy_info;
268
-                if ($registration->is_primary_registrant()) {
269
-                    // generate hidden input
270
-                    $form_args['subsections']['primary_registrant'] = $this->_additional_primary_registrant_inputs(
271
-                        $registration
272
-                    );
273
-                }
274
-            }
275
-        }
276
-        $attendee_nmbr++;
277
-        return ! empty($form_args) ? new EE_Form_Section_Proper($form_args) : new EE_Form_Section_HTML();
278
-    }
279
-
280
-
281
-    /**
282
-     * _additional_attendee_reg_info_input
283
-     *
284
-     * @access public
285
-     * @param EE_Registration $registration
286
-     * @param bool            $additional_attendee_reg_info
287
-     * @return    EE_Form_Input_Base
288
-     * @throws \EE_Error
289
-     */
290
-    private function _additional_attendee_reg_info_input(
291
-        EE_Registration $registration,
292
-        $additional_attendee_reg_info = true
293
-    ) {
294
-        // generate hidden input
295
-        return new EE_Hidden_Input(
296
-            array(
297
-                'html_id' => 'additional-attendee-reg-info-' . $registration->reg_url_link(),
298
-                'default' => $additional_attendee_reg_info,
299
-            )
300
-        );
301
-    }
302
-
303
-
304
-    /**
305
-     * @param EE_Registration   $registration
306
-     * @param EE_Question_Group $question_group
307
-     * @return EE_Form_Section_Proper
308
-     * @throws EE_Error
309
-     * @throws InvalidArgumentException
310
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
311
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
312
-     */
313
-    private function _question_group_reg_form(EE_Registration $registration, EE_Question_Group $question_group)
314
-    {
315
-        // array of params to pass to parent constructor
316
-        $form_args = array(
317
-            'html_id'         => 'ee-reg-form-qstn-grp-' . $question_group->identifier(),
318
-            'html_class'      => $this->checkout->admin_request
319
-                ? 'form-table ee-reg-form-qstn-grp-dv'
320
-                : 'ee-reg-form-qstn-grp-dv',
321
-            'html_label_id'   => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-lbl',
322
-            'subsections'     => array(
323
-                'reg_form_qstn_grp_hdr' => $this->_question_group_header($question_group),
324
-            ),
325
-            'layout_strategy' => $this->checkout->admin_request
326
-                ? new EE_Admin_Two_Column_Layout()
327
-                : new EE_Div_Per_Section_Layout(),
328
-        );
329
-        // where params
330
-        $query_params = array('QST_deleted' => 0);
331
-        // don't load admin only questions on the frontend
332
-        if (! $this->checkout->admin_request) {
333
-            $query_params['QST_admin_only'] = array('!=', true);
334
-        }
335
-        $questions = $question_group->get_many_related(
336
-            'Question',
337
-            apply_filters(
338
-                'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__related_questions_query_params',
339
-                array(
340
-                    $query_params,
341
-                    'order_by' => array(
342
-                        'Question_Group_Question.QGQ_order' => 'ASC',
343
-                    ),
344
-                ),
345
-                $question_group,
346
-                $registration,
347
-                $this
348
-            )
349
-        );
350
-        // filter for additional content before questions
351
-        $form_args['subsections']['reg_form_questions_before'] = new EE_Form_Section_HTML(
352
-            apply_filters(
353
-                'FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions',
354
-                '',
355
-                $registration,
356
-                $question_group,
357
-                $this
358
-            )
359
-        );
360
-        // loop thru questions
361
-        foreach ($questions as $question) {
362
-            if ($question instanceof EE_Question) {
363
-                $identifier                            = $question->is_system_question()
364
-                    ? $question->system_ID()
365
-                    : $question->ID();
366
-                $form_args['subsections'][$identifier] = $this->reg_form_question($registration, $question);
367
-            }
368
-        }
369
-        $form_args['subsections'] = apply_filters(
370
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information__question_group_reg_form__subsections_array',
371
-            $form_args['subsections'],
372
-            $registration,
373
-            $question_group,
374
-            $this
375
-        );
376
-        // filter for additional content after questions
377
-        $form_args['subsections']['reg_form_questions_after'] = new EE_Form_Section_HTML(
378
-            apply_filters(
379
-                'FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions',
380
-                '',
381
-                $registration,
382
-                $question_group,
383
-                $this
384
-            )
385
-        );
20
+	/**
21
+	 * @type bool $_print_copy_info
22
+	 */
23
+	private $_print_copy_info = false;
24
+
25
+	/**
26
+	 * @type array $_attendee_data
27
+	 */
28
+	private $_attendee_data = array();
29
+
30
+	/**
31
+	 * @type array $_required_questions
32
+	 */
33
+	private $_required_questions = array();
34
+
35
+	/**
36
+	 * @type array $_registration_answers
37
+	 */
38
+	private $_registration_answers = array();
39
+
40
+
41
+	/**
42
+	 *    class constructor
43
+	 *
44
+	 * @access    public
45
+	 * @param    EE_Checkout $checkout
46
+	 */
47
+	public function __construct(EE_Checkout $checkout)
48
+	{
49
+		$this->_slug     = 'attendee_information';
50
+		$this->_name     = esc_html__('Attendee Information', 'event_espresso');
51
+		$this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'attendee_info_main.template.php';
52
+		$this->checkout  = $checkout;
53
+		$this->_reset_success_message();
54
+		$this->set_instructions(
55
+			esc_html__('Please answer the following registration questions before proceeding.', 'event_espresso')
56
+		);
57
+	}
58
+
59
+
60
+	public function translate_js_strings()
61
+	{
62
+		EE_Registry::$i18n_js_strings['required_field']            = esc_html__(
63
+			' is a required question.',
64
+			'event_espresso'
65
+		);
66
+		EE_Registry::$i18n_js_strings['required_multi_field']      = esc_html__(
67
+			' is a required question. Please enter a value for at least one of the options.',
68
+			'event_espresso'
69
+		);
70
+		EE_Registry::$i18n_js_strings['answer_required_questions'] = esc_html__(
71
+			'Please answer all required questions correctly before proceeding.',
72
+			'event_espresso'
73
+		);
74
+		EE_Registry::$i18n_js_strings['attendee_info_copied']      = sprintf(
75
+			esc_html__(
76
+				'The attendee information was successfully copied.%sPlease ensure the rest of the registration form is completed before proceeding.',
77
+				'event_espresso'
78
+			),
79
+			'<br/>'
80
+		);
81
+		EE_Registry::$i18n_js_strings['attendee_info_copy_error']  = esc_html__(
82
+			'An unknown error occurred on the server while attempting to copy the attendee information. Please refresh the page and try again.',
83
+			'event_espresso'
84
+		);
85
+		EE_Registry::$i18n_js_strings['enter_valid_email']         = esc_html__(
86
+			'You must enter a valid email address.',
87
+			'event_espresso'
88
+		);
89
+		EE_Registry::$i18n_js_strings['valid_email_and_questions'] = esc_html__(
90
+			'You must enter a valid email address and answer all other required questions before you can proceed.',
91
+			'event_espresso'
92
+		);
93
+	}
94
+
95
+
96
+	public function enqueue_styles_and_scripts()
97
+	{
98
+	}
99
+
100
+
101
+	/**
102
+	 * @return boolean
103
+	 */
104
+	public function initialize_reg_step()
105
+	{
106
+		return true;
107
+	}
108
+
109
+
110
+	/**
111
+	 * @return EE_Form_Section_Proper
112
+	 * @throws EE_Error
113
+	 * @throws InvalidArgumentException
114
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
115
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
116
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
117
+	 */
118
+	public function generate_reg_form()
119
+	{
120
+		$this->_print_copy_info = false;
121
+		$primary_registrant     = null;
122
+		// autoload Line_Item_Display classes
123
+		EEH_Autoloader::register_line_item_display_autoloaders();
124
+		$Line_Item_Display = new EE_Line_Item_Display();
125
+		// calculate taxes
126
+		$Line_Item_Display->display_line_item(
127
+			$this->checkout->cart->get_grand_total(),
128
+			array('set_tax_rate' => true)
129
+		);
130
+		/** @var $subsections EE_Form_Section_Proper[] */
131
+		$subsections   = array(
132
+			'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
133
+		);
134
+		$template_args = array(
135
+			'revisit'       => $this->checkout->revisit,
136
+			'registrations' => array(),
137
+			'ticket_count'  => array(),
138
+		);
139
+		// grab the saved registrations from the transaction
140
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
141
+		if ($registrations) {
142
+			foreach ($registrations as $registration) {
143
+				// can this registration be processed during this visit ?
144
+				if ($registration instanceof EE_Registration
145
+					&& $this->checkout->visit_allows_processing_of_this_registration($registration)
146
+				) {
147
+					$subsections[$registration->reg_url_link()] = $this->_registrations_reg_form($registration);
148
+					if (! $this->checkout->admin_request) {
149
+						$template_args['registrations'][$registration->reg_url_link()]    = $registration;
150
+						$template_args['ticket_count'][$registration->ticket()->ID()]     = isset(
151
+							$template_args['ticket_count'][$registration->ticket()->ID()]
152
+						)
153
+							? $template_args['ticket_count'][$registration->ticket()->ID()] + 1
154
+							: 1;
155
+						$ticket_line_item = EEH_Line_Item::get_line_items_by_object_type_and_IDs(
156
+							$this->checkout->cart->get_grand_total(),
157
+							'Ticket',
158
+							array($registration->ticket()->ID())
159
+						);
160
+						$ticket_line_item = is_array($ticket_line_item)
161
+							? reset($ticket_line_item)
162
+							: $ticket_line_item;
163
+						$template_args['ticket_line_item'][$registration->ticket()->ID()] =
164
+							$Line_Item_Display->display_line_item($ticket_line_item);
165
+					}
166
+					if ($registration->is_primary_registrant()) {
167
+						$primary_registrant = $registration->reg_url_link();
168
+					}
169
+				}
170
+			}
171
+			// print_copy_info ?
172
+			if ($primary_registrant && ! $this->checkout->admin_request && count($registrations) > 1) {
173
+				// TODO: add admin option for toggling copy attendee info,
174
+				// then use that value to change $this->_print_copy_info
175
+				$copy_options['spco_copy_attendee_chk'] = $this->_print_copy_info
176
+					? $this->_copy_attendee_info_form()
177
+					: $this->_auto_copy_attendee_info();
178
+				// generate hidden input
179
+				if (isset($subsections[$primary_registrant])
180
+					&& $subsections[$primary_registrant] instanceof EE_Form_Section_Proper
181
+				) {
182
+					$subsections[$primary_registrant]->add_subsections(
183
+						$copy_options,
184
+						'primary_registrant',
185
+						false
186
+					);
187
+				}
188
+			}
189
+		}
190
+
191
+		return new EE_Form_Section_Proper(
192
+			array(
193
+				'name'            => $this->reg_form_name(),
194
+				'html_id'         => $this->reg_form_name(),
195
+				'subsections'     => $subsections,
196
+				'layout_strategy' => $this->checkout->admin_request ?
197
+					new EE_Div_Per_Section_Layout() :
198
+					new EE_Template_Layout(
199
+						array(
200
+							'layout_template_file' => $this->_template, // layout_template
201
+							'template_args'        => $template_args,
202
+						)
203
+					),
204
+			)
205
+		);
206
+	}
207
+
208
+
209
+	/**
210
+	 * @param EE_Registration $registration
211
+	 * @return EE_Form_Section_Base
212
+	 * @throws EE_Error
213
+	 * @throws InvalidArgumentException
214
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
215
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
216
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
217
+	 */
218
+	private function _registrations_reg_form(EE_Registration $registration)
219
+	{
220
+		static $attendee_nmbr = 1;
221
+		$form_args = array();
222
+		// verify that registration has valid event
223
+		if ($registration->event() instanceof EE_Event) {
224
+			$question_groups = $registration->event()->question_groups(
225
+				apply_filters(
226
+					'FHEE__EE_SPCO_Reg_Step_Attendee_Information___registrations_reg_form__question_groups_query_parameters',
227
+					array(
228
+						array(
229
+							'Event.EVT_ID'                     => $registration->event()->ID(),
230
+							'Event_Question_Group.EQG_primary' => $registration->count() === 1 ? true : false,
231
+						),
232
+						'order_by' => array('QSG_order' => 'ASC'),
233
+					),
234
+					$registration,
235
+					$this
236
+				)
237
+			);
238
+			if ($question_groups) {
239
+				// array of params to pass to parent constructor
240
+				$form_args = array(
241
+					'html_id'         => 'ee-registration-' . $registration->reg_url_link(),
242
+					'html_class'      => 'ee-reg-form-attendee-dv',
243
+					'html_style'      => $this->checkout->admin_request
244
+						? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;'
245
+						: '',
246
+					'subsections'     => array(),
247
+					'layout_strategy' => new EE_Fieldset_Section_Layout(
248
+						array(
249
+							'legend_class' => 'spco-attendee-lgnd smaller-text lt-grey-text',
250
+							'legend_text'  => sprintf(__('Attendee %d', 'event_espresso'), $attendee_nmbr),
251
+						)
252
+					),
253
+				);
254
+				foreach ($question_groups as $question_group) {
255
+					if ($question_group instanceof EE_Question_Group) {
256
+						$form_args['subsections'][$question_group->identifier()] = $this->_question_group_reg_form(
257
+							$registration,
258
+							$question_group
259
+						);
260
+					}
261
+				}
262
+				// add hidden input
263
+				$form_args['subsections']['additional_attendee_reg_info'] = $this->_additional_attendee_reg_info_input(
264
+					$registration
265
+				);
266
+				// if we have question groups for additional attendees, then display the copy options
267
+				$this->_print_copy_info = $attendee_nmbr > 1 ? true : $this->_print_copy_info;
268
+				if ($registration->is_primary_registrant()) {
269
+					// generate hidden input
270
+					$form_args['subsections']['primary_registrant'] = $this->_additional_primary_registrant_inputs(
271
+						$registration
272
+					);
273
+				}
274
+			}
275
+		}
276
+		$attendee_nmbr++;
277
+		return ! empty($form_args) ? new EE_Form_Section_Proper($form_args) : new EE_Form_Section_HTML();
278
+	}
279
+
280
+
281
+	/**
282
+	 * _additional_attendee_reg_info_input
283
+	 *
284
+	 * @access public
285
+	 * @param EE_Registration $registration
286
+	 * @param bool            $additional_attendee_reg_info
287
+	 * @return    EE_Form_Input_Base
288
+	 * @throws \EE_Error
289
+	 */
290
+	private function _additional_attendee_reg_info_input(
291
+		EE_Registration $registration,
292
+		$additional_attendee_reg_info = true
293
+	) {
294
+		// generate hidden input
295
+		return new EE_Hidden_Input(
296
+			array(
297
+				'html_id' => 'additional-attendee-reg-info-' . $registration->reg_url_link(),
298
+				'default' => $additional_attendee_reg_info,
299
+			)
300
+		);
301
+	}
302
+
303
+
304
+	/**
305
+	 * @param EE_Registration   $registration
306
+	 * @param EE_Question_Group $question_group
307
+	 * @return EE_Form_Section_Proper
308
+	 * @throws EE_Error
309
+	 * @throws InvalidArgumentException
310
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
311
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
312
+	 */
313
+	private function _question_group_reg_form(EE_Registration $registration, EE_Question_Group $question_group)
314
+	{
315
+		// array of params to pass to parent constructor
316
+		$form_args = array(
317
+			'html_id'         => 'ee-reg-form-qstn-grp-' . $question_group->identifier(),
318
+			'html_class'      => $this->checkout->admin_request
319
+				? 'form-table ee-reg-form-qstn-grp-dv'
320
+				: 'ee-reg-form-qstn-grp-dv',
321
+			'html_label_id'   => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-lbl',
322
+			'subsections'     => array(
323
+				'reg_form_qstn_grp_hdr' => $this->_question_group_header($question_group),
324
+			),
325
+			'layout_strategy' => $this->checkout->admin_request
326
+				? new EE_Admin_Two_Column_Layout()
327
+				: new EE_Div_Per_Section_Layout(),
328
+		);
329
+		// where params
330
+		$query_params = array('QST_deleted' => 0);
331
+		// don't load admin only questions on the frontend
332
+		if (! $this->checkout->admin_request) {
333
+			$query_params['QST_admin_only'] = array('!=', true);
334
+		}
335
+		$questions = $question_group->get_many_related(
336
+			'Question',
337
+			apply_filters(
338
+				'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__related_questions_query_params',
339
+				array(
340
+					$query_params,
341
+					'order_by' => array(
342
+						'Question_Group_Question.QGQ_order' => 'ASC',
343
+					),
344
+				),
345
+				$question_group,
346
+				$registration,
347
+				$this
348
+			)
349
+		);
350
+		// filter for additional content before questions
351
+		$form_args['subsections']['reg_form_questions_before'] = new EE_Form_Section_HTML(
352
+			apply_filters(
353
+				'FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions',
354
+				'',
355
+				$registration,
356
+				$question_group,
357
+				$this
358
+			)
359
+		);
360
+		// loop thru questions
361
+		foreach ($questions as $question) {
362
+			if ($question instanceof EE_Question) {
363
+				$identifier                            = $question->is_system_question()
364
+					? $question->system_ID()
365
+					: $question->ID();
366
+				$form_args['subsections'][$identifier] = $this->reg_form_question($registration, $question);
367
+			}
368
+		}
369
+		$form_args['subsections'] = apply_filters(
370
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information__question_group_reg_form__subsections_array',
371
+			$form_args['subsections'],
372
+			$registration,
373
+			$question_group,
374
+			$this
375
+		);
376
+		// filter for additional content after questions
377
+		$form_args['subsections']['reg_form_questions_after'] = new EE_Form_Section_HTML(
378
+			apply_filters(
379
+				'FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions',
380
+				'',
381
+				$registration,
382
+				$question_group,
383
+				$this
384
+			)
385
+		);
386 386
 //		d( $form_args );
387
-        $question_group_reg_form = new EE_Form_Section_Proper($form_args);
388
-        return apply_filters(
389
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__question_group_reg_form',
390
-            $question_group_reg_form,
391
-            $registration,
392
-            $question_group,
393
-            $this
394
-        );
395
-    }
396
-
397
-
398
-    /**
399
-     * @access public
400
-     * @param EE_Question_Group $question_group
401
-     * @return    EE_Form_Section_HTML
402
-     */
403
-    private function _question_group_header(EE_Question_Group $question_group)
404
-    {
405
-        $html = '';
406
-        // group_name
407
-        if ($question_group->show_group_name() && $question_group->name() !== '') {
408
-            if ($this->checkout->admin_request) {
409
-                $html .= EEH_HTML::br();
410
-                $html .= EEH_HTML::h3(
411
-                    $question_group->name(),
412
-                    '',
413
-                    'ee-reg-form-qstn-grp-title title',
414
-                    'font-size: 1.3em; padding-left:0;'
415
-                );
416
-            } else {
417
-                $html .= EEH_HTML::h4(
418
-                    $question_group->name(),
419
-                    '',
420
-                    'ee-reg-form-qstn-grp-title section-title'
421
-                );
422
-            }
423
-        }
424
-        // group_desc
425
-        if ($question_group->show_group_desc() && $question_group->desc() !== '') {
426
-            $html .= EEH_HTML::p(
427
-                $question_group->desc(),
428
-                '',
429
-                $this->checkout->admin_request
430
-                    ? 'ee-reg-form-qstn-grp-desc-pg'
431
-                    : 'ee-reg-form-qstn-grp-desc-pg small-text lt-grey-text'
432
-            );
433
-        }
434
-        return new EE_Form_Section_HTML($html);
435
-    }
436
-
437
-
438
-    /**
439
-     * @access public
440
-     * @return    EE_Form_Section_Proper
441
-     * @throws \EE_Error
442
-     */
443
-    private function _copy_attendee_info_form()
444
-    {
445
-        // array of params to pass to parent constructor
446
-        return new EE_Form_Section_Proper(
447
-            array(
448
-                'subsections'     => $this->_copy_attendee_info_inputs(),
449
-                'layout_strategy' => new EE_Template_Layout(
450
-                    array(
451
-                        'layout_template_file'     => SPCO_REG_STEPS_PATH
452
-                                                      . $this->_slug
453
-                                                      . DS
454
-                                                      . 'copy_attendee_info.template.php',
455
-                        'begin_template_file'      => null,
456
-                        'input_template_file'      => null,
457
-                        'subsection_template_file' => null,
458
-                        'end_template_file'        => null,
459
-                    )
460
-                ),
461
-            )
462
-        );
463
-    }
464
-
465
-
466
-    /**
467
-     * _auto_copy_attendee_info
468
-     *
469
-     * @access public
470
-     * @return EE_Form_Section_HTML
471
-     */
472
-    private function _auto_copy_attendee_info()
473
-    {
474
-        return new EE_Form_Section_HTML(
475
-            EEH_Template::locate_template(
476
-                SPCO_REG_STEPS_PATH . $this->_slug . DS . '_auto_copy_attendee_info.template.php',
477
-                apply_filters(
478
-                    'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args',
479
-                    array()
480
-                ),
481
-                true,
482
-                true
483
-            )
484
-        );
485
-    }
486
-
487
-
488
-    /**
489
-     * _copy_attendee_info_inputs
490
-     *
491
-     * @access public
492
-     * @return array
493
-     * @throws \EE_Error
494
-     */
495
-    private function _copy_attendee_info_inputs()
496
-    {
497
-        $copy_attendee_info_inputs = array();
498
-        $prev_ticket               = null;
499
-        // grab the saved registrations from the transaction
500
-        $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
501
-        foreach ($registrations as $registration) {
502
-            // for all  attendees other than the primary attendee
503
-            if ($registration instanceof EE_Registration && ! $registration->is_primary_registrant()) {
504
-                // if this is a new ticket OR if this is the very first additional attendee after the primary attendee
505
-                if ($registration->ticket()->ID() !== $prev_ticket) {
506
-                    $item_name = $registration->ticket()->name();
507
-                    $item_name .= $registration->ticket()->description() !== ''
508
-                        ? ' - ' . $registration->ticket()->description()
509
-                        : '';
510
-                    $copy_attendee_info_inputs['spco_copy_attendee_chk[ticket-' . $registration->ticket()->ID() . ']'] =
511
-                        new EE_Form_Section_HTML(
512
-                            '<h6 class="spco-copy-attendee-event-hdr">' . $item_name . '</h6>'
513
-                        );
514
-                    $prev_ticket = $registration->ticket()->ID();
515
-                }
516
-
517
-                $copy_attendee_info_inputs['spco_copy_attendee_chk[' . $registration->ID() . ']'] =
518
-                    new EE_Checkbox_Multi_Input(
519
-                        array(
520
-                            $registration->ID() => sprintf(
521
-                                esc_html__('Attendee #%s', 'event_espresso'),
522
-                                $registration->count()
523
-                            ),
524
-                        ),
525
-                        array(
526
-                            'html_id'                 => 'spco-copy-attendee-chk-' . $registration->reg_url_link(),
527
-                            'html_class'              => 'spco-copy-attendee-chk ee-do-not-validate',
528
-                            'display_html_label_text' => false,
529
-                        )
530
-                    );
531
-            }
532
-        }
533
-        return $copy_attendee_info_inputs;
534
-    }
535
-
536
-
537
-    /**
538
-     * _additional_primary_registrant_inputs
539
-     *
540
-     * @access public
541
-     * @param EE_Registration $registration
542
-     * @return    EE_Form_Input_Base
543
-     * @throws \EE_Error
544
-     */
545
-    private function _additional_primary_registrant_inputs(EE_Registration $registration)
546
-    {
547
-        // generate hidden input
548
-        return new EE_Hidden_Input(
549
-            array(
550
-                'html_id' => 'primary_registrant',
551
-                'default' => $registration->reg_url_link(),
552
-            )
553
-        );
554
-    }
555
-
556
-
557
-    /**
558
-     * @access public
559
-     * @param EE_Registration $registration
560
-     * @param EE_Question     $question
561
-     * @return EE_Form_Input_Base
562
-     * @throws EE_Error
563
-     * @throws InvalidArgumentException
564
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
565
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
566
-     */
567
-    public function reg_form_question(EE_Registration $registration, EE_Question $question)
568
-    {
569
-
570
-        // if this question was for an attendee detail, then check for that answer
571
-        $answer_value = EEM_Answer::instance()->get_attendee_property_answer_value(
572
-            $registration,
573
-            $question->system_ID()
574
-        );
575
-        $answer       = $answer_value === null
576
-            ? EEM_Answer::instance()->get_one(
577
-                array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
578
-            )
579
-            : null;
580
-        // if NOT returning to edit an existing registration
581
-        // OR if this question is for an attendee property
582
-        // OR we still don't have an EE_Answer object
583
-        if ($answer_value || ! $answer instanceof EE_Answer || ! $registration->reg_url_link()) {
584
-            // create an EE_Answer object for storing everything in
585
-            $answer = EE_Answer::new_instance(array(
586
-                'QST_ID' => $question->ID(),
587
-                'REG_ID' => $registration->ID(),
588
-            ));
589
-        }
590
-        // verify instance
591
-        if ($answer instanceof EE_Answer) {
592
-            if (! empty($answer_value)) {
593
-                $answer->set('ANS_value', $answer_value);
594
-            }
595
-            $answer->cache('Question', $question);
596
-            //remember system ID had a bug where sometimes it could be null
597
-            $answer_cache_id = $question->is_system_question()
598
-                ? $question->system_ID() . '-' . $registration->reg_url_link()
599
-                : $question->ID() . '-' . $registration->reg_url_link();
600
-            $registration->cache('Answer', $answer, $answer_cache_id);
601
-        }
602
-        return $this->_generate_question_input($registration, $question, $answer);
603
-    }
604
-
605
-
606
-    /**
607
-     * @param EE_Registration $registration
608
-     * @param EE_Question     $question
609
-     * @param                 mixed EE_Answer|NULL      $answer
610
-     * @return EE_Form_Input_Base
611
-     * @throws \EE_Error
612
-     */
613
-    private function _generate_question_input(EE_Registration $registration, EE_Question $question, $answer)
614
-    {
615
-        $identifier                             = $question->is_system_question()
616
-            ? $question->system_ID()
617
-            : $question->ID();
618
-        $this->_required_questions[$identifier] = $question->required() ? true : false;
619
-        add_filter(
620
-            'FHEE__EE_Question__generate_form_input__country_options',
621
-            array($this, 'use_cached_countries_for_form_input'),
622
-            10,
623
-            4
624
-        );
625
-        add_filter(
626
-            'FHEE__EE_Question__generate_form_input__state_options',
627
-            array($this, 'use_cached_states_for_form_input'),
628
-            10,
629
-            4
630
-        );
631
-        $input_constructor_args                  = array(
632
-            'html_name'        => 'ee_reg_qstn[' . $registration->ID() . '][' . $identifier . ']',
633
-            'html_id'          => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
634
-            'html_class'       => 'ee-reg-qstn ee-reg-qstn-' . $identifier,
635
-            'html_label_id'    => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
636
-            'html_label_class' => 'ee-reg-qstn',
637
-        );
638
-        $input_constructor_args['html_label_id'] .= '-lbl';
639
-        if ($answer instanceof EE_Answer && $answer->ID()) {
640
-            $input_constructor_args['html_name']     .= '[' . $answer->ID() . ']';
641
-            $input_constructor_args['html_id']       .= '-' . $answer->ID();
642
-            $input_constructor_args['html_label_id'] .= '-' . $answer->ID();
643
-        }
644
-        $form_input = $question->generate_form_input(
645
-            $registration,
646
-            $answer,
647
-            $input_constructor_args
648
-        );
649
-        remove_filter(
650
-            'FHEE__EE_Question__generate_form_input__country_options',
651
-            array($this, 'use_cached_countries_for_form_input')
652
-        );
653
-        remove_filter(
654
-            'FHEE__EE_Question__generate_form_input__state_options',
655
-            array($this, 'use_cached_states_for_form_input')
656
-        );
657
-        return $form_input;
658
-    }
659
-
660
-
661
-    /**
662
-     * Gets the list of countries for the form input
663
-     *
664
-     * @param array|null       $countries_list
665
-     * @param \EE_Question     $question
666
-     * @param \EE_Registration $registration
667
-     * @param \EE_Answer       $answer
668
-     * @return array 2d keys are country IDs, values are their names
669
-     * @throws EE_Error
670
-     * @throws InvalidArgumentException
671
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
672
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
673
-     */
674
-    public function use_cached_countries_for_form_input(
675
-        $countries_list,
676
-        \EE_Question $question = null,
677
-        \EE_Registration $registration = null,
678
-        \EE_Answer $answer = null
679
-    ) {
680
-        $country_options = array('' => '');
681
-        // get possibly cached list of countries
682
-        $countries = $this->checkout->action === 'process_reg_step'
683
-            ? EEM_Country::instance()->get_all_countries()
684
-            : EEM_Country::instance()->get_all_active_countries();
685
-        if (! empty($countries)) {
686
-            foreach ($countries as $country) {
687
-                if ($country instanceof EE_Country) {
688
-                    $country_options[$country->ID()] = $country->name();
689
-                }
690
-            }
691
-        }
692
-        if ($question instanceof EE_Question
693
-            && $registration instanceof EE_Registration) {
694
-            $answer = EEM_Answer::instance()->get_one(
695
-                array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
696
-            );
697
-        } else {
698
-            $answer = EE_Answer::new_instance();
699
-        }
700
-        $country_options = apply_filters(
701
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__country_options',
702
-            $country_options,
703
-            $this,
704
-            $registration,
705
-            $question,
706
-            $answer
707
-        );
708
-        return $country_options;
709
-    }
710
-
711
-
712
-    /**
713
-     * Gets the list of states for the form input
714
-     *
715
-     * @param array|null       $states_list
716
-     * @param \EE_Question     $question
717
-     * @param \EE_Registration $registration
718
-     * @param \EE_Answer       $answer
719
-     * @return array 2d keys are state IDs, values are their names
720
-     * @throws EE_Error
721
-     * @throws InvalidArgumentException
722
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
723
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
724
-     */
725
-    public function use_cached_states_for_form_input(
726
-        $states_list,
727
-        \EE_Question $question = null,
728
-        \EE_Registration $registration = null,
729
-        \EE_Answer $answer = null
730
-    ) {
731
-        $state_options = array('' => array('' => ''));
732
-        $states        = $this->checkout->action === 'process_reg_step'
733
-            ? EEM_State::instance()->get_all_states()
734
-            : EEM_State::instance()->get_all_active_states();
735
-        if (! empty($states)) {
736
-            foreach ($states as $state) {
737
-                if ($state instanceof EE_State) {
738
-                    $state_options[$state->country()->name()][$state->ID()] = $state->name();
739
-                }
740
-            }
741
-        }
742
-        $state_options = apply_filters(
743
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__state_options',
744
-            $state_options,
745
-            $this,
746
-            $registration,
747
-            $question,
748
-            $answer
749
-        );
750
-        return $state_options;
751
-    }
752
-
753
-
754
-
755
-
756
-
757
-
758
-    /********************************************************************************************************/
759
-    /****************************************  PROCESS REG STEP  ****************************************/
760
-    /********************************************************************************************************/
761
-    /**
762
-     * @return bool
763
-     * @throws EE_Error
764
-     * @throws InvalidArgumentException
765
-     * @throws ReflectionException
766
-     * @throws RuntimeException
767
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
768
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
769
-     */
770
-    public function process_reg_step()
771
-    {
772
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
773
-        // grab validated data from form
774
-        $valid_data = $this->checkout->current_step->valid_data();
775
-        // EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ );
776
-        // EEH_Debug_Tools::printr( $valid_data, '$valid_data', __FILE__, __LINE__ );
777
-        // if we don't have any $valid_data then something went TERRIBLY WRONG !!!
778
-        if (empty($valid_data)) {
779
-            EE_Error::add_error(
780
-                esc_html__('No valid question responses were received.', 'event_espresso'),
781
-                __FILE__,
782
-                __FUNCTION__,
783
-                __LINE__
784
-            );
785
-            return false;
786
-        }
787
-        if (! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
788
-            EE_Error::add_error(
789
-                esc_html__(
790
-                    'A valid transaction could not be initiated for processing your registrations.',
791
-                    'event_espresso'
792
-                ),
793
-                __FILE__,
794
-                __FUNCTION__,
795
-                __LINE__
796
-            );
797
-            return false;
798
-        }
799
-        // get cached registrations
800
-        $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
801
-        // verify we got the goods
802
-        if (empty($registrations)) {
803
-            EE_Error::add_error(
804
-                esc_html__('Your form data could not be applied to any valid registrations.', 'event_espresso'),
805
-                __FILE__,
806
-                __FUNCTION__,
807
-                __LINE__
808
-            );
809
-            return false;
810
-        }
811
-        // extract attendee info from form data and save to model objects
812
-        $registrations_processed = $this->_process_registrations($registrations, $valid_data);
813
-        // if first pass thru SPCO,
814
-        // then let's check processed registrations against the total number of tickets in the cart
815
-        if ($registrations_processed === false) {
816
-            // but return immediately if the previous step exited early due to errors
817
-            return false;
818
-        } elseif (! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
819
-            // generate a correctly translated string for all possible singular/plural combinations
820
-            if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) {
821
-                $error_msg = sprintf(
822
-                    esc_html__(
823
-                        'There was %1$d ticket in the Event Queue, but %2$ds registrations were processed',
824
-                        'event_espresso'
825
-                    ),
826
-                    $this->checkout->total_ticket_count,
827
-                    $registrations_processed
828
-                );
829
-            } elseif ($this->checkout->total_ticket_count !== 1 && $registrations_processed === 1) {
830
-                $error_msg = sprintf(
831
-                    esc_html__(
832
-                        'There was a total of %1$d tickets in the Event Queue, but only %2$ds registration was processed',
833
-                        'event_espresso'
834
-                    ),
835
-                    $this->checkout->total_ticket_count,
836
-                    $registrations_processed
837
-                );
838
-            } else {
839
-                $error_msg = sprintf(
840
-                    esc_html__(
841
-                        'There was a total of %1$d tickets in the Event Queue, but %2$ds registrations were processed',
842
-                        'event_espresso'
843
-                    ),
844
-                    $this->checkout->total_ticket_count,
845
-                    $registrations_processed
846
-                );
847
-            }
848
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
849
-            return false;
850
-        }
851
-        // mark this reg step as completed
852
-        $this->set_completed();
853
-        $this->_set_success_message(
854
-            esc_html__('The Attendee Information Step has been successfully completed.', 'event_espresso')
855
-        );
856
-        //do action in case a plugin wants to do something with the data submitted in step 1.
857
-        //passes EE_Single_Page_Checkout, and it's posted data
858
-        do_action('AHEE__EE_Single_Page_Checkout__process_attendee_information__end', $this, $valid_data);
859
-        return true;
860
-    }
861
-
862
-
863
-    /**
864
-     *    _process_registrations
865
-     *
866
-     * @param EE_Registration[] $registrations
867
-     * @param array             $valid_data
868
-     * @return bool|int
869
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
870
-     * @throws EE_Error
871
-     * @throws InvalidArgumentException
872
-     * @throws ReflectionException
873
-     * @throws RuntimeException
874
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
875
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
876
-     */
877
-    private function _process_registrations($registrations = array(), $valid_data = array())
878
-    {
879
-        // load resources and set some defaults
880
-        EE_Registry::instance()->load_model('Attendee');
881
-        // holder for primary registrant attendee object
882
-        $this->checkout->primary_attendee_obj = null;
883
-        // array for tracking reg form data for the primary registrant
884
-        $primary_registrant = array(
885
-            'line_item_id' => null,
886
-        );
887
-        $copy_primary       = false;
888
-        // reg form sections that do not contain inputs
889
-        $non_input_form_sections = array(
890
-            'primary_registrant',
891
-            'additional_attendee_reg_info',
892
-            'spco_copy_attendee_chk',
893
-        );
894
-        // attendee counter
895
-        $att_nmbr = 0;
896
-        // grab the saved registrations from the transaction
897
-        foreach ($registrations as $registration) {
898
-            // verify EE_Registration object
899
-            if (! $registration instanceof EE_Registration) {
900
-                EE_Error::add_error(
901
-                    esc_html__(
902
-                        'An invalid Registration object was discovered when attempting to process your registration information.',
903
-                        'event_espresso'
904
-                    ),
905
-                    __FILE__,
906
-                    __FUNCTION__,
907
-                    __LINE__
908
-                );
909
-                return false;
910
-            }
911
-            /** @var string $reg_url_link */
912
-            $reg_url_link = $registration->reg_url_link();
913
-            // reg_url_link exists ?
914
-            if (! empty($reg_url_link)) {
915
-                // should this registration be processed during this visit ?
916
-                if ($this->checkout->visit_allows_processing_of_this_registration($registration)) {
917
-                    // if NOT revisiting, then let's save the registration now,
918
-                    // so that we have a REG_ID to use when generating other objects
919
-                    if (! $this->checkout->revisit) {
920
-                        $registration->save();
921
-                    }
922
-                    /**
923
-                     * This allows plugins to trigger a fail on processing of a
924
-                     * registration for any conditions they may have for it to pass.
925
-                     *
926
-                     * @var bool   if true is returned by the plugin then the
927
-                     *            registration processing is halted.
928
-                     */
929
-                    if (apply_filters(
930
-                        'FHEE__EE_SPCO_Reg_Step_Attendee_Information___process_registrations__pre_registration_process',
931
-                        false,
932
-                        $att_nmbr,
933
-                        $registration,
934
-                        $registrations,
935
-                        $valid_data,
936
-                        $this
937
-                    )) {
938
-                        return false;
939
-                    }
940
-
941
-                    // Houston, we have a registration!
942
-                    $att_nmbr++;
943
-                    $this->_attendee_data[$reg_url_link] = array();
944
-                    // grab any existing related answer objects
945
-                    $this->_registration_answers = $registration->answers();
946
-                    // unset( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] );
947
-                    if (isset($valid_data[$reg_url_link])) {
948
-                        // do we need to copy basic info from primary attendee ?
949
-                        $copy_primary = isset($valid_data[$reg_url_link]['additional_attendee_reg_info'])
950
-                                        && absint($valid_data[$reg_url_link]['additional_attendee_reg_info']) === 0
951
-                            ? true
952
-                            : false;
953
-                        // filter form input data for this registration
954
-                        $valid_data[$reg_url_link] = (array)apply_filters(
955
-                            'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item',
956
-                            $valid_data[$reg_url_link]
957
-                        );
958
-                        if (isset($valid_data['primary_attendee'])) {
959
-                            $primary_registrant['line_item_id'] = ! empty($valid_data['primary_attendee'])
960
-                                ? $valid_data['primary_attendee']
961
-                                : false;
962
-                            unset($valid_data['primary_attendee']);
963
-                        }
964
-                        // now loop through our array of valid post data && process attendee reg forms
965
-                        foreach ($valid_data[$reg_url_link] as $form_section => $form_inputs) {
966
-                            if (! in_array($form_section, $non_input_form_sections)) {
967
-                                foreach ($form_inputs as $form_input => $input_value) {
968
-                                    // \EEH_Debug_Tools::printr( $input_value, $form_input, __FILE__, __LINE__ );
969
-                                    // check for critical inputs
970
-                                    if (! $this->_verify_critical_attendee_details_are_set_and_validate_email(
971
-                                        $form_input,
972
-                                        $input_value
973
-                                    )
974
-                                    ) {
975
-                                        return false;
976
-                                    }
977
-                                    // store a bit of data about the primary attendee
978
-                                    if ($att_nmbr === 1
979
-                                        && ! empty($input_value)
980
-                                        && $reg_url_link === $primary_registrant['line_item_id']
981
-                                    ) {
982
-                                        $primary_registrant[$form_input] = $input_value;
983
-                                    } elseif ($copy_primary
984
-                                        && $input_value === null
985
-                                        && isset($primary_registrant[$form_input])
986
-                                    ) {
987
-                                        $input_value = $primary_registrant[$form_input];
988
-                                    }
989
-                                    // now attempt to save the input data
990
-                                    if (! $this->_save_registration_form_input(
991
-                                        $registration,
992
-                                        $form_input,
993
-                                        $input_value
994
-                                    )
995
-                                    ) {
996
-                                        EE_Error::add_error(
997
-                                            sprintf(
998
-                                                esc_html__(
999
-                                                    'Unable to save registration form data for the form input: "%1$s" with the submitted value: "%2$s"',
1000
-                                                    'event_espresso'
1001
-                                                ),
1002
-                                                $form_input,
1003
-                                                $input_value
1004
-                                            ),
1005
-                                            __FILE__,
1006
-                                            __FUNCTION__,
1007
-                                            __LINE__
1008
-                                        );
1009
-                                        return false;
1010
-                                    }
1011
-                                }
1012
-                            }
1013
-                        }  // end of foreach ( $valid_data[ $reg_url_link ] as $form_section => $form_inputs )
1014
-                    }
1015
-                    //EEH_Debug_Tools::printr( $this->_attendee_data, '$this->_attendee_data', __FILE__, __LINE__ );
1016
-                    // this registration does not require additional attendee information ?
1017
-                    if ($copy_primary
1018
-                        && $att_nmbr > 1
1019
-                        && $this->checkout->primary_attendee_obj instanceof EE_Attendee
1020
-                    ) {
1021
-                        // just copy the primary registrant
1022
-                        $attendee = $this->checkout->primary_attendee_obj;
1023
-                    } else {
1024
-                        // ensure critical details are set for additional attendees
1025
-                        $this->_attendee_data[$reg_url_link] = $att_nmbr > 1
1026
-                            ? $this->_copy_critical_attendee_details_from_primary_registrant(
1027
-                                $this->_attendee_data[$reg_url_link]
1028
-                            )
1029
-                            : $this->_attendee_data[$reg_url_link];
1030
-                        // execute create attendee command (which may return an existing attendee)
1031
-                        $attendee = EE_Registry::instance()->BUS->execute(
1032
-                            new CreateAttendeeCommand(
1033
-                                $this->_attendee_data[$reg_url_link],
1034
-                                $registration
1035
-                            )
1036
-                        );
1037
-                        // who's #1 ?
1038
-                        if ($att_nmbr === 1) {
1039
-                            $this->checkout->primary_attendee_obj = $attendee;
1040
-                        }
1041
-                    }
1042
-                    // EEH_Debug_Tools::printr( $attendee, '$attendee', __FILE__, __LINE__ );
1043
-                    // add relation to registration, set attendee ID, and cache attendee
1044
-                    $this->_associate_attendee_with_registration($registration, $attendee);
1045
-                    // \EEH_Debug_Tools::printr( $registration, '$registration', __FILE__, __LINE__ );
1046
-                    if (! $registration->attendee() instanceof EE_Attendee) {
1047
-                        EE_Error::add_error(
1048
-                            sprintf(
1049
-                                esc_html__(
1050
-                                    'Registration %s has an invalid or missing Attendee object.',
1051
-                                    'event_espresso'
1052
-                                ),
1053
-                                $reg_url_link
1054
-                            ),
1055
-                            __FILE__,
1056
-                            __FUNCTION__,
1057
-                            __LINE__
1058
-                        );
1059
-                        return false;
1060
-                    }
1061
-                    /** @type EE_Registration_Processor $registration_processor */
1062
-                    $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1063
-                    // at this point, we should have enough details about the registrant to consider the registration
1064
-                    // NOT incomplete
1065
-                    $registration_processor->toggle_incomplete_registration_status_to_default(
1066
-                        $registration,
1067
-                        false,
1068
-                        new Context(
1069
-                            'spco_reg_step_attendee_information_process_registrations',
1070
-                            esc_html__(
1071
-                                'Finished populating registration with details from the registration form after submitting the Attendee Information Reg Step.',
1072
-                                'event_espresso'
1073
-                            )
1074
-                        )
1075
-                    );
1076
-                    // we can also consider the TXN to not have been failed, so temporarily upgrade it's status to
1077
-                    // abandoned
1078
-                    $this->checkout->transaction->toggle_failed_transaction_status();
1079
-                    // if we've gotten this far, then let's save what we have
1080
-                    $registration->save();
1081
-                    // add relation between TXN and registration
1082
-                    $this->_associate_registration_with_transaction($registration);
1083
-                }
1084
-            } else {
1085
-                EE_Error::add_error(
1086
-                    esc_html__(
1087
-                        'An invalid or missing line item ID was encountered while attempting to process the registration form.',
1088
-                        'event_espresso'
1089
-                    ),
1090
-                    __FILE__,
1091
-                    __FUNCTION__,
1092
-                    __LINE__
1093
-                );
1094
-                // remove malformed data
1095
-                unset($valid_data[$reg_url_link]);
1096
-                return false;
1097
-            }
1098
-
1099
-        } // end of foreach ( $this->checkout->transaction->registrations()  as $registration )
1100
-        return $att_nmbr;
1101
-    }
1102
-
1103
-
1104
-    /**
1105
-     *    _save_registration_form_input
1106
-     *
1107
-     * @param EE_Registration $registration
1108
-     * @param string          $form_input
1109
-     * @param string          $input_value
1110
-     * @return bool
1111
-     * @throws EE_Error
1112
-     * @throws InvalidArgumentException
1113
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1114
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1115
-     */
1116
-    private function _save_registration_form_input(
1117
-        EE_Registration $registration,
1118
-        $form_input = '',
1119
-        $input_value = ''
1120
-    ) {
1121
-        // \EEH_Debug_Tools::printr( __FUNCTION__, __CLASS__, __FILE__, __LINE__, 2 );
1122
-        // \EEH_Debug_Tools::printr( $form_input, '$form_input', __FILE__, __LINE__ );
1123
-        // \EEH_Debug_Tools::printr( $input_value, '$input_value', __FILE__, __LINE__ );
1124
-        // allow for plugins to hook in and do their own processing of the form input.
1125
-        // For plugins to bypass normal processing here, they just need to return a boolean value.
1126
-        if (apply_filters(
1127
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___save_registration_form_input',
1128
-            false,
1129
-            $registration,
1130
-            $form_input,
1131
-            $input_value,
1132
-            $this
1133
-        )) {
1134
-            return true;
1135
-        }
1136
-        /*
387
+		$question_group_reg_form = new EE_Form_Section_Proper($form_args);
388
+		return apply_filters(
389
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__question_group_reg_form',
390
+			$question_group_reg_form,
391
+			$registration,
392
+			$question_group,
393
+			$this
394
+		);
395
+	}
396
+
397
+
398
+	/**
399
+	 * @access public
400
+	 * @param EE_Question_Group $question_group
401
+	 * @return    EE_Form_Section_HTML
402
+	 */
403
+	private function _question_group_header(EE_Question_Group $question_group)
404
+	{
405
+		$html = '';
406
+		// group_name
407
+		if ($question_group->show_group_name() && $question_group->name() !== '') {
408
+			if ($this->checkout->admin_request) {
409
+				$html .= EEH_HTML::br();
410
+				$html .= EEH_HTML::h3(
411
+					$question_group->name(),
412
+					'',
413
+					'ee-reg-form-qstn-grp-title title',
414
+					'font-size: 1.3em; padding-left:0;'
415
+				);
416
+			} else {
417
+				$html .= EEH_HTML::h4(
418
+					$question_group->name(),
419
+					'',
420
+					'ee-reg-form-qstn-grp-title section-title'
421
+				);
422
+			}
423
+		}
424
+		// group_desc
425
+		if ($question_group->show_group_desc() && $question_group->desc() !== '') {
426
+			$html .= EEH_HTML::p(
427
+				$question_group->desc(),
428
+				'',
429
+				$this->checkout->admin_request
430
+					? 'ee-reg-form-qstn-grp-desc-pg'
431
+					: 'ee-reg-form-qstn-grp-desc-pg small-text lt-grey-text'
432
+			);
433
+		}
434
+		return new EE_Form_Section_HTML($html);
435
+	}
436
+
437
+
438
+	/**
439
+	 * @access public
440
+	 * @return    EE_Form_Section_Proper
441
+	 * @throws \EE_Error
442
+	 */
443
+	private function _copy_attendee_info_form()
444
+	{
445
+		// array of params to pass to parent constructor
446
+		return new EE_Form_Section_Proper(
447
+			array(
448
+				'subsections'     => $this->_copy_attendee_info_inputs(),
449
+				'layout_strategy' => new EE_Template_Layout(
450
+					array(
451
+						'layout_template_file'     => SPCO_REG_STEPS_PATH
452
+													  . $this->_slug
453
+													  . DS
454
+													  . 'copy_attendee_info.template.php',
455
+						'begin_template_file'      => null,
456
+						'input_template_file'      => null,
457
+						'subsection_template_file' => null,
458
+						'end_template_file'        => null,
459
+					)
460
+				),
461
+			)
462
+		);
463
+	}
464
+
465
+
466
+	/**
467
+	 * _auto_copy_attendee_info
468
+	 *
469
+	 * @access public
470
+	 * @return EE_Form_Section_HTML
471
+	 */
472
+	private function _auto_copy_attendee_info()
473
+	{
474
+		return new EE_Form_Section_HTML(
475
+			EEH_Template::locate_template(
476
+				SPCO_REG_STEPS_PATH . $this->_slug . DS . '_auto_copy_attendee_info.template.php',
477
+				apply_filters(
478
+					'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args',
479
+					array()
480
+				),
481
+				true,
482
+				true
483
+			)
484
+		);
485
+	}
486
+
487
+
488
+	/**
489
+	 * _copy_attendee_info_inputs
490
+	 *
491
+	 * @access public
492
+	 * @return array
493
+	 * @throws \EE_Error
494
+	 */
495
+	private function _copy_attendee_info_inputs()
496
+	{
497
+		$copy_attendee_info_inputs = array();
498
+		$prev_ticket               = null;
499
+		// grab the saved registrations from the transaction
500
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
501
+		foreach ($registrations as $registration) {
502
+			// for all  attendees other than the primary attendee
503
+			if ($registration instanceof EE_Registration && ! $registration->is_primary_registrant()) {
504
+				// if this is a new ticket OR if this is the very first additional attendee after the primary attendee
505
+				if ($registration->ticket()->ID() !== $prev_ticket) {
506
+					$item_name = $registration->ticket()->name();
507
+					$item_name .= $registration->ticket()->description() !== ''
508
+						? ' - ' . $registration->ticket()->description()
509
+						: '';
510
+					$copy_attendee_info_inputs['spco_copy_attendee_chk[ticket-' . $registration->ticket()->ID() . ']'] =
511
+						new EE_Form_Section_HTML(
512
+							'<h6 class="spco-copy-attendee-event-hdr">' . $item_name . '</h6>'
513
+						);
514
+					$prev_ticket = $registration->ticket()->ID();
515
+				}
516
+
517
+				$copy_attendee_info_inputs['spco_copy_attendee_chk[' . $registration->ID() . ']'] =
518
+					new EE_Checkbox_Multi_Input(
519
+						array(
520
+							$registration->ID() => sprintf(
521
+								esc_html__('Attendee #%s', 'event_espresso'),
522
+								$registration->count()
523
+							),
524
+						),
525
+						array(
526
+							'html_id'                 => 'spco-copy-attendee-chk-' . $registration->reg_url_link(),
527
+							'html_class'              => 'spco-copy-attendee-chk ee-do-not-validate',
528
+							'display_html_label_text' => false,
529
+						)
530
+					);
531
+			}
532
+		}
533
+		return $copy_attendee_info_inputs;
534
+	}
535
+
536
+
537
+	/**
538
+	 * _additional_primary_registrant_inputs
539
+	 *
540
+	 * @access public
541
+	 * @param EE_Registration $registration
542
+	 * @return    EE_Form_Input_Base
543
+	 * @throws \EE_Error
544
+	 */
545
+	private function _additional_primary_registrant_inputs(EE_Registration $registration)
546
+	{
547
+		// generate hidden input
548
+		return new EE_Hidden_Input(
549
+			array(
550
+				'html_id' => 'primary_registrant',
551
+				'default' => $registration->reg_url_link(),
552
+			)
553
+		);
554
+	}
555
+
556
+
557
+	/**
558
+	 * @access public
559
+	 * @param EE_Registration $registration
560
+	 * @param EE_Question     $question
561
+	 * @return EE_Form_Input_Base
562
+	 * @throws EE_Error
563
+	 * @throws InvalidArgumentException
564
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
565
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
566
+	 */
567
+	public function reg_form_question(EE_Registration $registration, EE_Question $question)
568
+	{
569
+
570
+		// if this question was for an attendee detail, then check for that answer
571
+		$answer_value = EEM_Answer::instance()->get_attendee_property_answer_value(
572
+			$registration,
573
+			$question->system_ID()
574
+		);
575
+		$answer       = $answer_value === null
576
+			? EEM_Answer::instance()->get_one(
577
+				array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
578
+			)
579
+			: null;
580
+		// if NOT returning to edit an existing registration
581
+		// OR if this question is for an attendee property
582
+		// OR we still don't have an EE_Answer object
583
+		if ($answer_value || ! $answer instanceof EE_Answer || ! $registration->reg_url_link()) {
584
+			// create an EE_Answer object for storing everything in
585
+			$answer = EE_Answer::new_instance(array(
586
+				'QST_ID' => $question->ID(),
587
+				'REG_ID' => $registration->ID(),
588
+			));
589
+		}
590
+		// verify instance
591
+		if ($answer instanceof EE_Answer) {
592
+			if (! empty($answer_value)) {
593
+				$answer->set('ANS_value', $answer_value);
594
+			}
595
+			$answer->cache('Question', $question);
596
+			//remember system ID had a bug where sometimes it could be null
597
+			$answer_cache_id = $question->is_system_question()
598
+				? $question->system_ID() . '-' . $registration->reg_url_link()
599
+				: $question->ID() . '-' . $registration->reg_url_link();
600
+			$registration->cache('Answer', $answer, $answer_cache_id);
601
+		}
602
+		return $this->_generate_question_input($registration, $question, $answer);
603
+	}
604
+
605
+
606
+	/**
607
+	 * @param EE_Registration $registration
608
+	 * @param EE_Question     $question
609
+	 * @param                 mixed EE_Answer|NULL      $answer
610
+	 * @return EE_Form_Input_Base
611
+	 * @throws \EE_Error
612
+	 */
613
+	private function _generate_question_input(EE_Registration $registration, EE_Question $question, $answer)
614
+	{
615
+		$identifier                             = $question->is_system_question()
616
+			? $question->system_ID()
617
+			: $question->ID();
618
+		$this->_required_questions[$identifier] = $question->required() ? true : false;
619
+		add_filter(
620
+			'FHEE__EE_Question__generate_form_input__country_options',
621
+			array($this, 'use_cached_countries_for_form_input'),
622
+			10,
623
+			4
624
+		);
625
+		add_filter(
626
+			'FHEE__EE_Question__generate_form_input__state_options',
627
+			array($this, 'use_cached_states_for_form_input'),
628
+			10,
629
+			4
630
+		);
631
+		$input_constructor_args                  = array(
632
+			'html_name'        => 'ee_reg_qstn[' . $registration->ID() . '][' . $identifier . ']',
633
+			'html_id'          => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
634
+			'html_class'       => 'ee-reg-qstn ee-reg-qstn-' . $identifier,
635
+			'html_label_id'    => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier,
636
+			'html_label_class' => 'ee-reg-qstn',
637
+		);
638
+		$input_constructor_args['html_label_id'] .= '-lbl';
639
+		if ($answer instanceof EE_Answer && $answer->ID()) {
640
+			$input_constructor_args['html_name']     .= '[' . $answer->ID() . ']';
641
+			$input_constructor_args['html_id']       .= '-' . $answer->ID();
642
+			$input_constructor_args['html_label_id'] .= '-' . $answer->ID();
643
+		}
644
+		$form_input = $question->generate_form_input(
645
+			$registration,
646
+			$answer,
647
+			$input_constructor_args
648
+		);
649
+		remove_filter(
650
+			'FHEE__EE_Question__generate_form_input__country_options',
651
+			array($this, 'use_cached_countries_for_form_input')
652
+		);
653
+		remove_filter(
654
+			'FHEE__EE_Question__generate_form_input__state_options',
655
+			array($this, 'use_cached_states_for_form_input')
656
+		);
657
+		return $form_input;
658
+	}
659
+
660
+
661
+	/**
662
+	 * Gets the list of countries for the form input
663
+	 *
664
+	 * @param array|null       $countries_list
665
+	 * @param \EE_Question     $question
666
+	 * @param \EE_Registration $registration
667
+	 * @param \EE_Answer       $answer
668
+	 * @return array 2d keys are country IDs, values are their names
669
+	 * @throws EE_Error
670
+	 * @throws InvalidArgumentException
671
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
672
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
673
+	 */
674
+	public function use_cached_countries_for_form_input(
675
+		$countries_list,
676
+		\EE_Question $question = null,
677
+		\EE_Registration $registration = null,
678
+		\EE_Answer $answer = null
679
+	) {
680
+		$country_options = array('' => '');
681
+		// get possibly cached list of countries
682
+		$countries = $this->checkout->action === 'process_reg_step'
683
+			? EEM_Country::instance()->get_all_countries()
684
+			: EEM_Country::instance()->get_all_active_countries();
685
+		if (! empty($countries)) {
686
+			foreach ($countries as $country) {
687
+				if ($country instanceof EE_Country) {
688
+					$country_options[$country->ID()] = $country->name();
689
+				}
690
+			}
691
+		}
692
+		if ($question instanceof EE_Question
693
+			&& $registration instanceof EE_Registration) {
694
+			$answer = EEM_Answer::instance()->get_one(
695
+				array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID()))
696
+			);
697
+		} else {
698
+			$answer = EE_Answer::new_instance();
699
+		}
700
+		$country_options = apply_filters(
701
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__country_options',
702
+			$country_options,
703
+			$this,
704
+			$registration,
705
+			$question,
706
+			$answer
707
+		);
708
+		return $country_options;
709
+	}
710
+
711
+
712
+	/**
713
+	 * Gets the list of states for the form input
714
+	 *
715
+	 * @param array|null       $states_list
716
+	 * @param \EE_Question     $question
717
+	 * @param \EE_Registration $registration
718
+	 * @param \EE_Answer       $answer
719
+	 * @return array 2d keys are state IDs, values are their names
720
+	 * @throws EE_Error
721
+	 * @throws InvalidArgumentException
722
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
723
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
724
+	 */
725
+	public function use_cached_states_for_form_input(
726
+		$states_list,
727
+		\EE_Question $question = null,
728
+		\EE_Registration $registration = null,
729
+		\EE_Answer $answer = null
730
+	) {
731
+		$state_options = array('' => array('' => ''));
732
+		$states        = $this->checkout->action === 'process_reg_step'
733
+			? EEM_State::instance()->get_all_states()
734
+			: EEM_State::instance()->get_all_active_states();
735
+		if (! empty($states)) {
736
+			foreach ($states as $state) {
737
+				if ($state instanceof EE_State) {
738
+					$state_options[$state->country()->name()][$state->ID()] = $state->name();
739
+				}
740
+			}
741
+		}
742
+		$state_options = apply_filters(
743
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__state_options',
744
+			$state_options,
745
+			$this,
746
+			$registration,
747
+			$question,
748
+			$answer
749
+		);
750
+		return $state_options;
751
+	}
752
+
753
+
754
+
755
+
756
+
757
+
758
+	/********************************************************************************************************/
759
+	/****************************************  PROCESS REG STEP  ****************************************/
760
+	/********************************************************************************************************/
761
+	/**
762
+	 * @return bool
763
+	 * @throws EE_Error
764
+	 * @throws InvalidArgumentException
765
+	 * @throws ReflectionException
766
+	 * @throws RuntimeException
767
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
768
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
769
+	 */
770
+	public function process_reg_step()
771
+	{
772
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
773
+		// grab validated data from form
774
+		$valid_data = $this->checkout->current_step->valid_data();
775
+		// EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ );
776
+		// EEH_Debug_Tools::printr( $valid_data, '$valid_data', __FILE__, __LINE__ );
777
+		// if we don't have any $valid_data then something went TERRIBLY WRONG !!!
778
+		if (empty($valid_data)) {
779
+			EE_Error::add_error(
780
+				esc_html__('No valid question responses were received.', 'event_espresso'),
781
+				__FILE__,
782
+				__FUNCTION__,
783
+				__LINE__
784
+			);
785
+			return false;
786
+		}
787
+		if (! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) {
788
+			EE_Error::add_error(
789
+				esc_html__(
790
+					'A valid transaction could not be initiated for processing your registrations.',
791
+					'event_espresso'
792
+				),
793
+				__FILE__,
794
+				__FUNCTION__,
795
+				__LINE__
796
+			);
797
+			return false;
798
+		}
799
+		// get cached registrations
800
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
801
+		// verify we got the goods
802
+		if (empty($registrations)) {
803
+			EE_Error::add_error(
804
+				esc_html__('Your form data could not be applied to any valid registrations.', 'event_espresso'),
805
+				__FILE__,
806
+				__FUNCTION__,
807
+				__LINE__
808
+			);
809
+			return false;
810
+		}
811
+		// extract attendee info from form data and save to model objects
812
+		$registrations_processed = $this->_process_registrations($registrations, $valid_data);
813
+		// if first pass thru SPCO,
814
+		// then let's check processed registrations against the total number of tickets in the cart
815
+		if ($registrations_processed === false) {
816
+			// but return immediately if the previous step exited early due to errors
817
+			return false;
818
+		} elseif (! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) {
819
+			// generate a correctly translated string for all possible singular/plural combinations
820
+			if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) {
821
+				$error_msg = sprintf(
822
+					esc_html__(
823
+						'There was %1$d ticket in the Event Queue, but %2$ds registrations were processed',
824
+						'event_espresso'
825
+					),
826
+					$this->checkout->total_ticket_count,
827
+					$registrations_processed
828
+				);
829
+			} elseif ($this->checkout->total_ticket_count !== 1 && $registrations_processed === 1) {
830
+				$error_msg = sprintf(
831
+					esc_html__(
832
+						'There was a total of %1$d tickets in the Event Queue, but only %2$ds registration was processed',
833
+						'event_espresso'
834
+					),
835
+					$this->checkout->total_ticket_count,
836
+					$registrations_processed
837
+				);
838
+			} else {
839
+				$error_msg = sprintf(
840
+					esc_html__(
841
+						'There was a total of %1$d tickets in the Event Queue, but %2$ds registrations were processed',
842
+						'event_espresso'
843
+					),
844
+					$this->checkout->total_ticket_count,
845
+					$registrations_processed
846
+				);
847
+			}
848
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
849
+			return false;
850
+		}
851
+		// mark this reg step as completed
852
+		$this->set_completed();
853
+		$this->_set_success_message(
854
+			esc_html__('The Attendee Information Step has been successfully completed.', 'event_espresso')
855
+		);
856
+		//do action in case a plugin wants to do something with the data submitted in step 1.
857
+		//passes EE_Single_Page_Checkout, and it's posted data
858
+		do_action('AHEE__EE_Single_Page_Checkout__process_attendee_information__end', $this, $valid_data);
859
+		return true;
860
+	}
861
+
862
+
863
+	/**
864
+	 *    _process_registrations
865
+	 *
866
+	 * @param EE_Registration[] $registrations
867
+	 * @param array             $valid_data
868
+	 * @return bool|int
869
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
870
+	 * @throws EE_Error
871
+	 * @throws InvalidArgumentException
872
+	 * @throws ReflectionException
873
+	 * @throws RuntimeException
874
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
875
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
876
+	 */
877
+	private function _process_registrations($registrations = array(), $valid_data = array())
878
+	{
879
+		// load resources and set some defaults
880
+		EE_Registry::instance()->load_model('Attendee');
881
+		// holder for primary registrant attendee object
882
+		$this->checkout->primary_attendee_obj = null;
883
+		// array for tracking reg form data for the primary registrant
884
+		$primary_registrant = array(
885
+			'line_item_id' => null,
886
+		);
887
+		$copy_primary       = false;
888
+		// reg form sections that do not contain inputs
889
+		$non_input_form_sections = array(
890
+			'primary_registrant',
891
+			'additional_attendee_reg_info',
892
+			'spco_copy_attendee_chk',
893
+		);
894
+		// attendee counter
895
+		$att_nmbr = 0;
896
+		// grab the saved registrations from the transaction
897
+		foreach ($registrations as $registration) {
898
+			// verify EE_Registration object
899
+			if (! $registration instanceof EE_Registration) {
900
+				EE_Error::add_error(
901
+					esc_html__(
902
+						'An invalid Registration object was discovered when attempting to process your registration information.',
903
+						'event_espresso'
904
+					),
905
+					__FILE__,
906
+					__FUNCTION__,
907
+					__LINE__
908
+				);
909
+				return false;
910
+			}
911
+			/** @var string $reg_url_link */
912
+			$reg_url_link = $registration->reg_url_link();
913
+			// reg_url_link exists ?
914
+			if (! empty($reg_url_link)) {
915
+				// should this registration be processed during this visit ?
916
+				if ($this->checkout->visit_allows_processing_of_this_registration($registration)) {
917
+					// if NOT revisiting, then let's save the registration now,
918
+					// so that we have a REG_ID to use when generating other objects
919
+					if (! $this->checkout->revisit) {
920
+						$registration->save();
921
+					}
922
+					/**
923
+					 * This allows plugins to trigger a fail on processing of a
924
+					 * registration for any conditions they may have for it to pass.
925
+					 *
926
+					 * @var bool   if true is returned by the plugin then the
927
+					 *            registration processing is halted.
928
+					 */
929
+					if (apply_filters(
930
+						'FHEE__EE_SPCO_Reg_Step_Attendee_Information___process_registrations__pre_registration_process',
931
+						false,
932
+						$att_nmbr,
933
+						$registration,
934
+						$registrations,
935
+						$valid_data,
936
+						$this
937
+					)) {
938
+						return false;
939
+					}
940
+
941
+					// Houston, we have a registration!
942
+					$att_nmbr++;
943
+					$this->_attendee_data[$reg_url_link] = array();
944
+					// grab any existing related answer objects
945
+					$this->_registration_answers = $registration->answers();
946
+					// unset( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] );
947
+					if (isset($valid_data[$reg_url_link])) {
948
+						// do we need to copy basic info from primary attendee ?
949
+						$copy_primary = isset($valid_data[$reg_url_link]['additional_attendee_reg_info'])
950
+										&& absint($valid_data[$reg_url_link]['additional_attendee_reg_info']) === 0
951
+							? true
952
+							: false;
953
+						// filter form input data for this registration
954
+						$valid_data[$reg_url_link] = (array)apply_filters(
955
+							'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item',
956
+							$valid_data[$reg_url_link]
957
+						);
958
+						if (isset($valid_data['primary_attendee'])) {
959
+							$primary_registrant['line_item_id'] = ! empty($valid_data['primary_attendee'])
960
+								? $valid_data['primary_attendee']
961
+								: false;
962
+							unset($valid_data['primary_attendee']);
963
+						}
964
+						// now loop through our array of valid post data && process attendee reg forms
965
+						foreach ($valid_data[$reg_url_link] as $form_section => $form_inputs) {
966
+							if (! in_array($form_section, $non_input_form_sections)) {
967
+								foreach ($form_inputs as $form_input => $input_value) {
968
+									// \EEH_Debug_Tools::printr( $input_value, $form_input, __FILE__, __LINE__ );
969
+									// check for critical inputs
970
+									if (! $this->_verify_critical_attendee_details_are_set_and_validate_email(
971
+										$form_input,
972
+										$input_value
973
+									)
974
+									) {
975
+										return false;
976
+									}
977
+									// store a bit of data about the primary attendee
978
+									if ($att_nmbr === 1
979
+										&& ! empty($input_value)
980
+										&& $reg_url_link === $primary_registrant['line_item_id']
981
+									) {
982
+										$primary_registrant[$form_input] = $input_value;
983
+									} elseif ($copy_primary
984
+										&& $input_value === null
985
+										&& isset($primary_registrant[$form_input])
986
+									) {
987
+										$input_value = $primary_registrant[$form_input];
988
+									}
989
+									// now attempt to save the input data
990
+									if (! $this->_save_registration_form_input(
991
+										$registration,
992
+										$form_input,
993
+										$input_value
994
+									)
995
+									) {
996
+										EE_Error::add_error(
997
+											sprintf(
998
+												esc_html__(
999
+													'Unable to save registration form data for the form input: "%1$s" with the submitted value: "%2$s"',
1000
+													'event_espresso'
1001
+												),
1002
+												$form_input,
1003
+												$input_value
1004
+											),
1005
+											__FILE__,
1006
+											__FUNCTION__,
1007
+											__LINE__
1008
+										);
1009
+										return false;
1010
+									}
1011
+								}
1012
+							}
1013
+						}  // end of foreach ( $valid_data[ $reg_url_link ] as $form_section => $form_inputs )
1014
+					}
1015
+					//EEH_Debug_Tools::printr( $this->_attendee_data, '$this->_attendee_data', __FILE__, __LINE__ );
1016
+					// this registration does not require additional attendee information ?
1017
+					if ($copy_primary
1018
+						&& $att_nmbr > 1
1019
+						&& $this->checkout->primary_attendee_obj instanceof EE_Attendee
1020
+					) {
1021
+						// just copy the primary registrant
1022
+						$attendee = $this->checkout->primary_attendee_obj;
1023
+					} else {
1024
+						// ensure critical details are set for additional attendees
1025
+						$this->_attendee_data[$reg_url_link] = $att_nmbr > 1
1026
+							? $this->_copy_critical_attendee_details_from_primary_registrant(
1027
+								$this->_attendee_data[$reg_url_link]
1028
+							)
1029
+							: $this->_attendee_data[$reg_url_link];
1030
+						// execute create attendee command (which may return an existing attendee)
1031
+						$attendee = EE_Registry::instance()->BUS->execute(
1032
+							new CreateAttendeeCommand(
1033
+								$this->_attendee_data[$reg_url_link],
1034
+								$registration
1035
+							)
1036
+						);
1037
+						// who's #1 ?
1038
+						if ($att_nmbr === 1) {
1039
+							$this->checkout->primary_attendee_obj = $attendee;
1040
+						}
1041
+					}
1042
+					// EEH_Debug_Tools::printr( $attendee, '$attendee', __FILE__, __LINE__ );
1043
+					// add relation to registration, set attendee ID, and cache attendee
1044
+					$this->_associate_attendee_with_registration($registration, $attendee);
1045
+					// \EEH_Debug_Tools::printr( $registration, '$registration', __FILE__, __LINE__ );
1046
+					if (! $registration->attendee() instanceof EE_Attendee) {
1047
+						EE_Error::add_error(
1048
+							sprintf(
1049
+								esc_html__(
1050
+									'Registration %s has an invalid or missing Attendee object.',
1051
+									'event_espresso'
1052
+								),
1053
+								$reg_url_link
1054
+							),
1055
+							__FILE__,
1056
+							__FUNCTION__,
1057
+							__LINE__
1058
+						);
1059
+						return false;
1060
+					}
1061
+					/** @type EE_Registration_Processor $registration_processor */
1062
+					$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
1063
+					// at this point, we should have enough details about the registrant to consider the registration
1064
+					// NOT incomplete
1065
+					$registration_processor->toggle_incomplete_registration_status_to_default(
1066
+						$registration,
1067
+						false,
1068
+						new Context(
1069
+							'spco_reg_step_attendee_information_process_registrations',
1070
+							esc_html__(
1071
+								'Finished populating registration with details from the registration form after submitting the Attendee Information Reg Step.',
1072
+								'event_espresso'
1073
+							)
1074
+						)
1075
+					);
1076
+					// we can also consider the TXN to not have been failed, so temporarily upgrade it's status to
1077
+					// abandoned
1078
+					$this->checkout->transaction->toggle_failed_transaction_status();
1079
+					// if we've gotten this far, then let's save what we have
1080
+					$registration->save();
1081
+					// add relation between TXN and registration
1082
+					$this->_associate_registration_with_transaction($registration);
1083
+				}
1084
+			} else {
1085
+				EE_Error::add_error(
1086
+					esc_html__(
1087
+						'An invalid or missing line item ID was encountered while attempting to process the registration form.',
1088
+						'event_espresso'
1089
+					),
1090
+					__FILE__,
1091
+					__FUNCTION__,
1092
+					__LINE__
1093
+				);
1094
+				// remove malformed data
1095
+				unset($valid_data[$reg_url_link]);
1096
+				return false;
1097
+			}
1098
+
1099
+		} // end of foreach ( $this->checkout->transaction->registrations()  as $registration )
1100
+		return $att_nmbr;
1101
+	}
1102
+
1103
+
1104
+	/**
1105
+	 *    _save_registration_form_input
1106
+	 *
1107
+	 * @param EE_Registration $registration
1108
+	 * @param string          $form_input
1109
+	 * @param string          $input_value
1110
+	 * @return bool
1111
+	 * @throws EE_Error
1112
+	 * @throws InvalidArgumentException
1113
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1114
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1115
+	 */
1116
+	private function _save_registration_form_input(
1117
+		EE_Registration $registration,
1118
+		$form_input = '',
1119
+		$input_value = ''
1120
+	) {
1121
+		// \EEH_Debug_Tools::printr( __FUNCTION__, __CLASS__, __FILE__, __LINE__, 2 );
1122
+		// \EEH_Debug_Tools::printr( $form_input, '$form_input', __FILE__, __LINE__ );
1123
+		// \EEH_Debug_Tools::printr( $input_value, '$input_value', __FILE__, __LINE__ );
1124
+		// allow for plugins to hook in and do their own processing of the form input.
1125
+		// For plugins to bypass normal processing here, they just need to return a boolean value.
1126
+		if (apply_filters(
1127
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___save_registration_form_input',
1128
+			false,
1129
+			$registration,
1130
+			$form_input,
1131
+			$input_value,
1132
+			$this
1133
+		)) {
1134
+			return true;
1135
+		}
1136
+		/*
1137 1137
          * $answer_cache_id is the key used to find the EE_Answer we want
1138 1138
          * @see https://events.codebasehq.com/projects/event-espresso/tickets/10477
1139 1139
          */
1140
-        $answer_cache_id = $this->checkout->reg_url_link
1141
-            ? $form_input . '-' . $registration->reg_url_link()
1142
-            : $form_input;
1143
-        $answer_is_obj   = isset($this->_registration_answers[$answer_cache_id])
1144
-                           && $this->_registration_answers[$answer_cache_id] instanceof EE_Answer
1145
-            ? true
1146
-            : false;
1147
-        //rename form_inputs if they are EE_Attendee properties
1148
-        switch ((string) $form_input) {
1149
-            case 'state':
1150
-            case 'STA_ID':
1151
-                $attendee_property = true;
1152
-                $form_input        = 'STA_ID';
1153
-                break;
1154
-
1155
-            case 'country':
1156
-            case 'CNT_ISO':
1157
-                $attendee_property = true;
1158
-                $form_input        = 'CNT_ISO';
1159
-                break;
1160
-
1161
-            default:
1162
-                $ATT_input = 'ATT_' . $form_input;
1163
-                //EEH_Debug_Tools::printr( $ATT_input, '$ATT_input', __FILE__, __LINE__ );
1164
-                $attendee_property = EEM_Attendee::instance()->has_field($ATT_input) ? true : false;
1165
-                $form_input        = $attendee_property ? 'ATT_' . $form_input : $form_input;
1166
-        }
1167
-        // EEH_Debug_Tools::printr( $answer_cache_id, '$answer_cache_id', __FILE__, __LINE__ );
1168
-        // EEH_Debug_Tools::printr( $attendee_property, '$attendee_property', __FILE__, __LINE__ );
1169
-        // EEH_Debug_Tools::printr( $answer_is_obj, '$answer_is_obj', __FILE__, __LINE__ );
1170
-        // if this form input has a corresponding attendee property
1171
-        if ($attendee_property) {
1172
-            $this->_attendee_data[$registration->reg_url_link()][$form_input] = $input_value;
1173
-            if ($answer_is_obj) {
1174
-                // and delete the corresponding answer since we won't be storing this data in that object
1175
-                $registration->_remove_relation_to($this->_registration_answers[$answer_cache_id], 'Answer');
1176
-                $this->_registration_answers[$answer_cache_id]->delete_permanently();
1177
-            }
1178
-            return true;
1179
-        } elseif ($answer_is_obj) {
1180
-            // save this data to the answer object
1181
-            $this->_registration_answers[$answer_cache_id]->set_value($input_value);
1182
-            $result = $this->_registration_answers[$answer_cache_id]->save();
1183
-            return $result !== false ? true : false;
1184
-        } else {
1185
-            foreach ($this->_registration_answers as $answer) {
1186
-                if ($answer instanceof EE_Answer && $answer->question_ID() === $answer_cache_id) {
1187
-                    $answer->set_value($input_value);
1188
-                    $result = $answer->save();
1189
-                    return $result !== false ? true : false;
1190
-                }
1191
-            }
1192
-        }
1193
-        return false;
1194
-    }
1195
-
1196
-
1197
-    /**
1198
-     *    _verify_critical_attendee_details_are_set
1199
-     *
1200
-     * @param string $form_input
1201
-     * @param string $input_value
1202
-     * @return boolean
1203
-     */
1204
-    private function _verify_critical_attendee_details_are_set_and_validate_email(
1205
-        $form_input = '',
1206
-        $input_value = ''
1207
-    ) {
1208
-        if (empty($input_value)) {
1209
-            // if the form input isn't marked as being required, then just return
1210
-            if (! isset($this->_required_questions[$form_input]) || ! $this->_required_questions[$form_input]) {
1211
-                return true;
1212
-            }
1213
-            switch ($form_input) {
1214
-                case 'fname':
1215
-                    EE_Error::add_error(
1216
-                        esc_html__('First Name is a required value.', 'event_espresso'),
1217
-                        __FILE__,
1218
-                        __FUNCTION__,
1219
-                        __LINE__
1220
-                    );
1221
-                    return false;
1222
-                    break;
1223
-                case 'lname':
1224
-                    EE_Error::add_error(
1225
-                        esc_html__('Last Name is a required value.', 'event_espresso'),
1226
-                        __FILE__,
1227
-                        __FUNCTION__,
1228
-                        __LINE__
1229
-                    );
1230
-                    return false;
1231
-                    break;
1232
-                case 'email':
1233
-                    EE_Error::add_error(
1234
-                        esc_html__('Please enter a valid email address.', 'event_espresso'),
1235
-                        __FILE__,
1236
-                        __FUNCTION__,
1237
-                        __LINE__
1238
-                    );
1239
-                    return false;
1240
-                    break;
1241
-            }
1242
-        }
1243
-        return true;
1244
-    }
1245
-
1246
-
1247
-    /**
1248
-     *    _associate_attendee_with_registration
1249
-     *
1250
-     * @param EE_Registration $registration
1251
-     * @param EE_Attendee     $attendee
1252
-     * @return void
1253
-     * @throws EE_Error
1254
-     * @throws RuntimeException
1255
-     */
1256
-    private function _associate_attendee_with_registration(EE_Registration $registration, EE_Attendee $attendee)
1257
-    {
1258
-        // add relation to attendee
1259
-        $registration->_add_relation_to($attendee, 'Attendee');
1260
-        $registration->set_attendee_id($attendee->ID());
1261
-        $registration->update_cache_after_object_save('Attendee', $attendee);
1262
-    }
1263
-
1264
-
1265
-    /**
1266
-     *    _associate_registration_with_transaction
1267
-     *
1268
-     * @param EE_Registration $registration
1269
-     * @return void
1270
-     * @throws \EE_Error
1271
-     */
1272
-    private function _associate_registration_with_transaction(EE_Registration $registration)
1273
-    {
1274
-        // add relation to registration
1275
-        $this->checkout->transaction->_add_relation_to($registration, 'Registration');
1276
-        $this->checkout->transaction->update_cache_after_object_save('Registration', $registration);
1277
-    }
1278
-
1279
-
1280
-    /**
1281
-     *    _copy_critical_attendee_details_from_primary_registrant
1282
-     *    ensures that all attendees at least have data for first name, last name, and email address
1283
-     *
1284
-     * @param array $attendee_data
1285
-     * @return array
1286
-     * @throws \EE_Error
1287
-     */
1288
-    private function _copy_critical_attendee_details_from_primary_registrant($attendee_data = array())
1289
-    {
1290
-        // bare minimum critical details include first name, last name, email address
1291
-        $critical_attendee_details = array('ATT_fname', 'ATT_lname', 'ATT_email');
1292
-        // add address info to critical details?
1293
-        if (apply_filters(
1294
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information__merge_address_details_with_critical_attendee_details',
1295
-            false
1296
-        )) {
1297
-            $address_details           = array(
1298
-                'ATT_address',
1299
-                'ATT_address2',
1300
-                'ATT_city',
1301
-                'STA_ID',
1302
-                'CNT_ISO',
1303
-                'ATT_zip',
1304
-                'ATT_phone',
1305
-            );
1306
-            $critical_attendee_details = array_merge($critical_attendee_details, $address_details);
1307
-        }
1308
-        foreach ($critical_attendee_details as $critical_attendee_detail) {
1309
-            if (! isset($attendee_data[$critical_attendee_detail])
1310
-                || empty($attendee_data[$critical_attendee_detail])
1311
-            ) {
1312
-                $attendee_data[$critical_attendee_detail] = $this->checkout->primary_attendee_obj->get(
1313
-                    $critical_attendee_detail
1314
-                );
1315
-            }
1316
-        }
1317
-        return $attendee_data;
1318
-    }
1319
-
1320
-
1321
-    /**
1322
-     *    update_reg_step
1323
-     *    this is the final step after a user  revisits the site to edit their attendee information
1324
-     *    this gets called AFTER the process_reg_step() method above
1325
-     *
1326
-     * @return bool
1327
-     * @throws EE_Error
1328
-     * @throws InvalidArgumentException
1329
-     * @throws ReflectionException
1330
-     * @throws RuntimeException
1331
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1332
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1333
-     */
1334
-    public function update_reg_step()
1335
-    {
1336
-        // save everything
1337
-        if ($this->process_reg_step()) {
1338
-            $this->checkout->redirect     = true;
1339
-            $this->checkout->redirect_url = add_query_arg(
1340
-                array(
1341
-                    'e_reg_url_link' => $this->checkout->reg_url_link,
1342
-                    'revisit'        => true,
1343
-                ),
1344
-                $this->checkout->thank_you_page_url
1345
-            );
1346
-            $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1347
-            return true;
1348
-        }
1349
-        return false;
1350
-    }
1140
+		$answer_cache_id = $this->checkout->reg_url_link
1141
+			? $form_input . '-' . $registration->reg_url_link()
1142
+			: $form_input;
1143
+		$answer_is_obj   = isset($this->_registration_answers[$answer_cache_id])
1144
+						   && $this->_registration_answers[$answer_cache_id] instanceof EE_Answer
1145
+			? true
1146
+			: false;
1147
+		//rename form_inputs if they are EE_Attendee properties
1148
+		switch ((string) $form_input) {
1149
+			case 'state':
1150
+			case 'STA_ID':
1151
+				$attendee_property = true;
1152
+				$form_input        = 'STA_ID';
1153
+				break;
1154
+
1155
+			case 'country':
1156
+			case 'CNT_ISO':
1157
+				$attendee_property = true;
1158
+				$form_input        = 'CNT_ISO';
1159
+				break;
1160
+
1161
+			default:
1162
+				$ATT_input = 'ATT_' . $form_input;
1163
+				//EEH_Debug_Tools::printr( $ATT_input, '$ATT_input', __FILE__, __LINE__ );
1164
+				$attendee_property = EEM_Attendee::instance()->has_field($ATT_input) ? true : false;
1165
+				$form_input        = $attendee_property ? 'ATT_' . $form_input : $form_input;
1166
+		}
1167
+		// EEH_Debug_Tools::printr( $answer_cache_id, '$answer_cache_id', __FILE__, __LINE__ );
1168
+		// EEH_Debug_Tools::printr( $attendee_property, '$attendee_property', __FILE__, __LINE__ );
1169
+		// EEH_Debug_Tools::printr( $answer_is_obj, '$answer_is_obj', __FILE__, __LINE__ );
1170
+		// if this form input has a corresponding attendee property
1171
+		if ($attendee_property) {
1172
+			$this->_attendee_data[$registration->reg_url_link()][$form_input] = $input_value;
1173
+			if ($answer_is_obj) {
1174
+				// and delete the corresponding answer since we won't be storing this data in that object
1175
+				$registration->_remove_relation_to($this->_registration_answers[$answer_cache_id], 'Answer');
1176
+				$this->_registration_answers[$answer_cache_id]->delete_permanently();
1177
+			}
1178
+			return true;
1179
+		} elseif ($answer_is_obj) {
1180
+			// save this data to the answer object
1181
+			$this->_registration_answers[$answer_cache_id]->set_value($input_value);
1182
+			$result = $this->_registration_answers[$answer_cache_id]->save();
1183
+			return $result !== false ? true : false;
1184
+		} else {
1185
+			foreach ($this->_registration_answers as $answer) {
1186
+				if ($answer instanceof EE_Answer && $answer->question_ID() === $answer_cache_id) {
1187
+					$answer->set_value($input_value);
1188
+					$result = $answer->save();
1189
+					return $result !== false ? true : false;
1190
+				}
1191
+			}
1192
+		}
1193
+		return false;
1194
+	}
1195
+
1196
+
1197
+	/**
1198
+	 *    _verify_critical_attendee_details_are_set
1199
+	 *
1200
+	 * @param string $form_input
1201
+	 * @param string $input_value
1202
+	 * @return boolean
1203
+	 */
1204
+	private function _verify_critical_attendee_details_are_set_and_validate_email(
1205
+		$form_input = '',
1206
+		$input_value = ''
1207
+	) {
1208
+		if (empty($input_value)) {
1209
+			// if the form input isn't marked as being required, then just return
1210
+			if (! isset($this->_required_questions[$form_input]) || ! $this->_required_questions[$form_input]) {
1211
+				return true;
1212
+			}
1213
+			switch ($form_input) {
1214
+				case 'fname':
1215
+					EE_Error::add_error(
1216
+						esc_html__('First Name is a required value.', 'event_espresso'),
1217
+						__FILE__,
1218
+						__FUNCTION__,
1219
+						__LINE__
1220
+					);
1221
+					return false;
1222
+					break;
1223
+				case 'lname':
1224
+					EE_Error::add_error(
1225
+						esc_html__('Last Name is a required value.', 'event_espresso'),
1226
+						__FILE__,
1227
+						__FUNCTION__,
1228
+						__LINE__
1229
+					);
1230
+					return false;
1231
+					break;
1232
+				case 'email':
1233
+					EE_Error::add_error(
1234
+						esc_html__('Please enter a valid email address.', 'event_espresso'),
1235
+						__FILE__,
1236
+						__FUNCTION__,
1237
+						__LINE__
1238
+					);
1239
+					return false;
1240
+					break;
1241
+			}
1242
+		}
1243
+		return true;
1244
+	}
1245
+
1246
+
1247
+	/**
1248
+	 *    _associate_attendee_with_registration
1249
+	 *
1250
+	 * @param EE_Registration $registration
1251
+	 * @param EE_Attendee     $attendee
1252
+	 * @return void
1253
+	 * @throws EE_Error
1254
+	 * @throws RuntimeException
1255
+	 */
1256
+	private function _associate_attendee_with_registration(EE_Registration $registration, EE_Attendee $attendee)
1257
+	{
1258
+		// add relation to attendee
1259
+		$registration->_add_relation_to($attendee, 'Attendee');
1260
+		$registration->set_attendee_id($attendee->ID());
1261
+		$registration->update_cache_after_object_save('Attendee', $attendee);
1262
+	}
1263
+
1264
+
1265
+	/**
1266
+	 *    _associate_registration_with_transaction
1267
+	 *
1268
+	 * @param EE_Registration $registration
1269
+	 * @return void
1270
+	 * @throws \EE_Error
1271
+	 */
1272
+	private function _associate_registration_with_transaction(EE_Registration $registration)
1273
+	{
1274
+		// add relation to registration
1275
+		$this->checkout->transaction->_add_relation_to($registration, 'Registration');
1276
+		$this->checkout->transaction->update_cache_after_object_save('Registration', $registration);
1277
+	}
1278
+
1279
+
1280
+	/**
1281
+	 *    _copy_critical_attendee_details_from_primary_registrant
1282
+	 *    ensures that all attendees at least have data for first name, last name, and email address
1283
+	 *
1284
+	 * @param array $attendee_data
1285
+	 * @return array
1286
+	 * @throws \EE_Error
1287
+	 */
1288
+	private function _copy_critical_attendee_details_from_primary_registrant($attendee_data = array())
1289
+	{
1290
+		// bare minimum critical details include first name, last name, email address
1291
+		$critical_attendee_details = array('ATT_fname', 'ATT_lname', 'ATT_email');
1292
+		// add address info to critical details?
1293
+		if (apply_filters(
1294
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information__merge_address_details_with_critical_attendee_details',
1295
+			false
1296
+		)) {
1297
+			$address_details           = array(
1298
+				'ATT_address',
1299
+				'ATT_address2',
1300
+				'ATT_city',
1301
+				'STA_ID',
1302
+				'CNT_ISO',
1303
+				'ATT_zip',
1304
+				'ATT_phone',
1305
+			);
1306
+			$critical_attendee_details = array_merge($critical_attendee_details, $address_details);
1307
+		}
1308
+		foreach ($critical_attendee_details as $critical_attendee_detail) {
1309
+			if (! isset($attendee_data[$critical_attendee_detail])
1310
+				|| empty($attendee_data[$critical_attendee_detail])
1311
+			) {
1312
+				$attendee_data[$critical_attendee_detail] = $this->checkout->primary_attendee_obj->get(
1313
+					$critical_attendee_detail
1314
+				);
1315
+			}
1316
+		}
1317
+		return $attendee_data;
1318
+	}
1319
+
1320
+
1321
+	/**
1322
+	 *    update_reg_step
1323
+	 *    this is the final step after a user  revisits the site to edit their attendee information
1324
+	 *    this gets called AFTER the process_reg_step() method above
1325
+	 *
1326
+	 * @return bool
1327
+	 * @throws EE_Error
1328
+	 * @throws InvalidArgumentException
1329
+	 * @throws ReflectionException
1330
+	 * @throws RuntimeException
1331
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1332
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1333
+	 */
1334
+	public function update_reg_step()
1335
+	{
1336
+		// save everything
1337
+		if ($this->process_reg_step()) {
1338
+			$this->checkout->redirect     = true;
1339
+			$this->checkout->redirect_url = add_query_arg(
1340
+				array(
1341
+					'e_reg_url_link' => $this->checkout->reg_url_link,
1342
+					'revisit'        => true,
1343
+				),
1344
+				$this->checkout->thank_you_page_url
1345
+			);
1346
+			$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1347
+			return true;
1348
+		}
1349
+		return false;
1350
+	}
1351 1351
 }
Please login to merge, or discard this patch.
admin/extend/registrations/Extend_Registrations_Admin_Page.core.php 1 patch
Indentation   +1181 added lines, -1181 removed lines patch added patch discarded remove patch
@@ -3,7 +3,7 @@  discard block
 block discarded – undo
3 3
 use EventEspresso\ui\browser\checkins\entities\CheckinStatusDashicon;
4 4
 
5 5
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
6
-    exit('NO direct script access allowed');
6
+	exit('NO direct script access allowed');
7 7
 }
8 8
 
9 9
 
@@ -20,1186 +20,1186 @@  discard block
 block discarded – undo
20 20
 {
21 21
 
22 22
 
23
-    /**
24
-     * This is used to hold the reports template data which is setup early in the request.
25
-     *
26
-     * @type array
27
-     */
28
-    protected $_reports_template_data = array();
29
-
30
-
31
-
32
-    /**
33
-     * Extend_Registrations_Admin_Page constructor.
34
-     *
35
-     * @param bool $routing
36
-     */
37
-    public function __construct($routing = true)
38
-    {
39
-        parent::__construct($routing);
40
-        if ( ! defined('REG_CAF_TEMPLATE_PATH')) {
41
-            define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/templates/');
42
-            define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/assets/');
43
-            define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registrations/assets/');
44
-        }
45
-    }
46
-
47
-
48
-
49
-    protected function _extend_page_config()
50
-    {
51
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'registrations';
52
-        $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
53
-            ? $this->_req_data['_REG_ID']
54
-            : 0;
55
-        // $att_id = ! empty( $this->_req_data['ATT_ID'] ) ? ! is_array( $this->_req_data['ATT_ID'] ) : 0;
56
-        // $att_id = ! empty( $this->_req_data['post'] ) && ! is_array( $this->_req_data['post'] )
57
-        // 	? $this->_req_data['post'] : $att_id;
58
-        $new_page_routes = array(
59
-            'reports'                  => array(
60
-                'func'       => '_registration_reports',
61
-                'capability' => 'ee_read_registrations',
62
-            ),
63
-            'registration_checkins'    => array(
64
-                'func'       => '_registration_checkin_list_table',
65
-                'capability' => 'ee_read_checkins',
66
-            ),
67
-            'newsletter_selected_send' => array(
68
-                'func'       => '_newsletter_selected_send',
69
-                'noheader'   => true,
70
-                'capability' => 'ee_send_message',
71
-            ),
72
-            'delete_checkin_rows'      => array(
73
-                'func'       => '_delete_checkin_rows',
74
-                'noheader'   => true,
75
-                'capability' => 'ee_delete_checkins',
76
-            ),
77
-            'delete_checkin_row'       => array(
78
-                'func'       => '_delete_checkin_row',
79
-                'noheader'   => true,
80
-                'capability' => 'ee_delete_checkin',
81
-                'obj_id'     => $reg_id,
82
-            ),
83
-            'toggle_checkin_status'    => array(
84
-                'func'       => '_toggle_checkin_status',
85
-                'noheader'   => true,
86
-                'capability' => 'ee_edit_checkin',
87
-                'obj_id'     => $reg_id,
88
-            ),
89
-            'toggle_checkin_status_bulk' => array(
90
-                'func' => '_toggle_checkin_status',
91
-                'noheader' => true,
92
-                'capability' => 'ee_edit_checkins'
93
-            ),
94
-            'event_registrations'      => array(
95
-                'func'       => '_event_registrations_list_table',
96
-                'capability' => 'ee_read_checkins',
97
-            ),
98
-            'registrations_checkin_report' => array(
99
-                'func'       => '_registrations_checkin_report',
100
-                'noheader'   => true,
101
-                'capability' => 'ee_read_registrations',
102
-            ),
103
-        );
104
-        $this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
105
-        $new_page_config = array(
106
-            'reports'               => array(
107
-                'nav'           => array(
108
-                    'label' => __('Reports', 'event_espresso'),
109
-                    'order' => 30,
110
-                ),
111
-                'help_tabs'     => array(
112
-                    'registrations_reports_help_tab' => array(
113
-                        'title'    => __('Registration Reports', 'event_espresso'),
114
-                        'filename' => 'registrations_reports',
115
-                    ),
116
-                ),
117
-                /*'help_tour' => array( 'Registration_Reports_Help_Tour' ),*/
118
-                'require_nonce' => false,
119
-            ),
120
-            'event_registrations'   => array(
121
-                'nav'           => array(
122
-                    'label'      => __('Event Check-In', 'event_espresso'),
123
-                    'order'      => 10,
124
-                    'persistent' => true,
125
-                ),
126
-                'help_tabs'     => array(
127
-                    'registrations_event_checkin_help_tab'                       => array(
128
-                        'title'    => __('Registrations Event Check-In', 'event_espresso'),
129
-                        'filename' => 'registrations_event_checkin',
130
-                    ),
131
-                    'registrations_event_checkin_table_column_headings_help_tab' => array(
132
-                        'title'    => __('Event Check-In Table Column Headings', 'event_espresso'),
133
-                        'filename' => 'registrations_event_checkin_table_column_headings',
134
-                    ),
135
-                    'registrations_event_checkin_filters_help_tab'               => array(
136
-                        'title'    => __('Event Check-In Filters', 'event_espresso'),
137
-                        'filename' => 'registrations_event_checkin_filters',
138
-                    ),
139
-                    'registrations_event_checkin_views_help_tab'                 => array(
140
-                        'title'    => __('Event Check-In Views', 'event_espresso'),
141
-                        'filename' => 'registrations_event_checkin_views',
142
-                    ),
143
-                    'registrations_event_checkin_other_help_tab'                 => array(
144
-                        'title'    => __('Event Check-In Other', 'event_espresso'),
145
-                        'filename' => 'registrations_event_checkin_other',
146
-                    ),
147
-                ),
148
-                'help_tour'     => array('Event_Checkin_Help_Tour'),
149
-                'qtips'         => array('Registration_List_Table_Tips'),
150
-                'list_table'    => 'EE_Event_Registrations_List_Table',
151
-                'metaboxes'     => array(),
152
-                'require_nonce' => false,
153
-            ),
154
-            'registration_checkins' => array(
155
-                'nav'           => array(
156
-                    'label'      => __('Check-In Records', 'event_espresso'),
157
-                    'order'      => 15,
158
-                    'persistent' => false,
159
-                ),
160
-                'list_table'    => 'EE_Registration_CheckIn_List_Table',
161
-                //'help_tour' => array( 'Checkin_Toggle_View_Help_Tour' ),
162
-                'metaboxes'     => array(),
163
-                'require_nonce' => false,
164
-            ),
165
-        );
166
-        $this->_page_config = array_merge($this->_page_config, $new_page_config);
167
-        $this->_page_config['contact_list']['list_table'] = 'Extend_EE_Attendee_Contact_List_Table';
168
-        $this->_page_config['default']['list_table'] = 'Extend_EE_Registrations_List_Table';
169
-    }
170
-
171
-
172
-
173
-    protected function _ajax_hooks()
174
-    {
175
-        parent::_ajax_hooks();
176
-        add_action('wp_ajax_get_newsletter_form_content', array($this, 'get_newsletter_form_content'));
177
-    }
178
-
179
-
180
-
181
-    public function load_scripts_styles()
182
-    {
183
-        parent::load_scripts_styles();
184
-        //if newsletter message type is active then let's add filter and load js for it.
185
-        if (EEH_MSG_Template::is_mt_active('newsletter')) {
186
-            //enqueue newsletter js
187
-            wp_enqueue_script(
188
-                'ee-newsletter-trigger',
189
-                REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.js',
190
-                array('ee-dialog'),
191
-                EVENT_ESPRESSO_VERSION,
192
-                true
193
-            );
194
-            wp_enqueue_style(
195
-                'ee-newsletter-trigger-css',
196
-                REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.css',
197
-                array(),
198
-                EVENT_ESPRESSO_VERSION
199
-            );
200
-            //hook in buttons for newsletter message type trigger.
201
-            add_action(
202
-                'AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons',
203
-                array($this, 'add_newsletter_action_buttons'),
204
-                10
205
-            );
206
-        }
207
-    }
208
-
209
-
210
-
211
-    public function load_scripts_styles_reports()
212
-    {
213
-        wp_register_script(
214
-            'ee-reg-reports-js',
215
-            REG_CAF_ASSETS_URL . 'ee-registration-admin-reports.js',
216
-            array('google-charts'),
217
-            EVENT_ESPRESSO_VERSION,
218
-            true
219
-        );
220
-        wp_enqueue_script('ee-reg-reports-js');
221
-        $this->_registration_reports_js_setup();
222
-    }
223
-
224
-
225
-
226
-    protected function _add_screen_options_event_registrations()
227
-    {
228
-        $this->_per_page_screen_option();
229
-    }
230
-
231
-
232
-
233
-    protected function _add_screen_options_registration_checkins()
234
-    {
235
-        $page_title = $this->_admin_page_title;
236
-        $this->_admin_page_title = __('Check-In Records', 'event_espresso');
237
-        $this->_per_page_screen_option();
238
-        $this->_admin_page_title = $page_title;
239
-    }
240
-
241
-
242
-
243
-    protected function _set_list_table_views_event_registrations()
244
-    {
245
-        $this->_views = array(
246
-            'all' => array(
247
-                'slug'        => 'all',
248
-                'label'       => __('All', 'event_espresso'),
249
-                'count'       => 0,
250
-                'bulk_action' => ! isset($this->_req_data['event_id'])
251
-                    ? array()
252
-                    : array(
253
-                        'toggle_checkin_status_bulk' => __('Toggle Check-In', 'event_espresso'),
254
-                    ),
255
-            ),
256
-        );
257
-    }
258
-
259
-
260
-
261
-    protected function _set_list_table_views_registration_checkins()
262
-    {
263
-        $this->_views = array(
264
-            'all' => array(
265
-                'slug'        => 'all',
266
-                'label'       => __('All', 'event_espresso'),
267
-                'count'       => 0,
268
-                'bulk_action' => array('delete_checkin_rows' => __('Delete Check-In Rows', 'event_espresso')),
269
-            ),
270
-        );
271
-    }
272
-
273
-
274
-
275
-    /**
276
-     * callback for ajax action.
277
-     *
278
-     * @since 4.3.0
279
-     * @return void (JSON)
280
-     * @throws \EE_Error
281
-     */
282
-    public function get_newsletter_form_content()
283
-    {
284
-        //do a nonce check cause we're not coming in from an normal route here.
285
-        $nonce = isset($this->_req_data['get_newsletter_form_content_nonce']) ? sanitize_text_field(
286
-            $this->_req_data['get_newsletter_form_content_nonce']
287
-        ) : '';
288
-        $nonce_ref = 'get_newsletter_form_content_nonce';
289
-        $this->_verify_nonce($nonce, $nonce_ref);
290
-        //let's get the mtp for the incoming MTP_ ID
291
-        if ( ! isset($this->_req_data['GRP_ID'])) {
292
-            EE_Error::add_error(
293
-                __(
294
-                    'There must be something broken with the js or html structure because the required data for getting a message template group is not present (need an GRP_ID).',
295
-                    'event_espresso'
296
-                ),
297
-                __FILE__,
298
-                __FUNCTION__,
299
-                __LINE__
300
-            );
301
-            $this->_template_args['success'] = false;
302
-            $this->_template_args['error'] = true;
303
-            $this->_return_json();
304
-        }
305
-        $MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID($this->_req_data['GRP_ID']);
306
-        if ( ! $MTPG instanceof EE_Message_Template_Group) {
307
-            EE_Error::add_error(
308
-                sprintf(
309
-                    __(
310
-                        'The GRP_ID given (%d) does not appear to have a corresponding row in the database.',
311
-                        'event_espresso'
312
-                    ),
313
-                    $this->_req_data['GRP_ID']
314
-                ),
315
-                __FILE__,
316
-                __FUNCTION__,
317
-                __LINE__
318
-            );
319
-            $this->_template_args['success'] = false;
320
-            $this->_template_args['error'] = true;
321
-            $this->_return_json();
322
-        }
323
-        $MTPs = $MTPG->context_templates();
324
-        $MTPs = $MTPs['attendee'];
325
-        $template_fields = array();
326
-        /** @var EE_Message_Template $MTP */
327
-        foreach ($MTPs as $MTP) {
328
-            $field = $MTP->get('MTP_template_field');
329
-            if ($field === 'content') {
330
-                $content = $MTP->get('MTP_content');
331
-                if ( ! empty($content['newsletter_content'])) {
332
-                    $template_fields['newsletter_content'] = $content['newsletter_content'];
333
-                }
334
-                continue;
335
-            }
336
-            $template_fields[$MTP->get('MTP_template_field')] = $MTP->get('MTP_content');
337
-        }
338
-        $this->_template_args['success'] = true;
339
-        $this->_template_args['error'] = false;
340
-        $this->_template_args['data'] = array(
341
-            'batch_message_from'    => isset($template_fields['from'])
342
-                ? $template_fields['from']
343
-                : '',
344
-            'batch_message_subject' => isset($template_fields['subject'])
345
-                ? $template_fields['subject']
346
-                : '',
347
-            'batch_message_content' => isset($template_fields['newsletter_content'])
348
-                ? $template_fields['newsletter_content']
349
-                : '',
350
-        );
351
-        $this->_return_json();
352
-    }
353
-
354
-
355
-
356
-    /**
357
-     * callback for AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons action
358
-     *
359
-     * @since 4.3.0
360
-     * @param EE_Admin_List_Table $list_table
361
-     * @return void
362
-     */
363
-    public function add_newsletter_action_buttons(EE_Admin_List_Table $list_table)
364
-    {
365
-        if ( ! EE_Registry::instance()->CAP->current_user_can(
366
-            'ee_send_message',
367
-            'espresso_registrations_newsletter_selected_send'
368
-        )
369
-        ) {
370
-            return;
371
-        }
372
-        $routes_to_add_to = array(
373
-            'contact_list',
374
-            'event_registrations',
375
-            'default',
376
-        );
377
-        if ($this->_current_page === 'espresso_registrations' && in_array($this->_req_action, $routes_to_add_to)) {
378
-            if (($this->_req_action === 'event_registrations' && empty($this->_req_data['event_id']))
379
-                || (isset($this->_req_data['status']) && $this->_req_data['status'] === 'trash')
380
-            ) {
381
-                echo '';
382
-            } else {
383
-                $button_text = sprintf(
384
-                    __('Send Batch Message (%s selected)', 'event_espresso'),
385
-                    '<span class="send-selected-newsletter-count">0</span>'
386
-                );
387
-                echo '<button id="selected-batch-send-trigger" class="button secondary-button"><span class="dashicons dashicons-email "></span>'
388
-                     . $button_text
389
-                     . '</button>';
390
-                add_action('admin_footer', array($this, 'newsletter_send_form_skeleton'));
391
-            }
392
-        }
393
-    }
394
-
395
-
396
-
397
-    public function newsletter_send_form_skeleton()
398
-    {
399
-        $list_table = $this->_list_table_object;
400
-        $codes = array();
401
-        //need to templates for the newsletter message type for the template selector.
402
-        $values[] = array('text' => __('Select Template to Use', 'event_espresso'), 'id' => 0);
403
-        $mtps = EEM_Message_Template_Group::instance()->get_all(
404
-            array(array('MTP_message_type' => 'newsletter', 'MTP_messenger' => 'email'))
405
-        );
406
-        foreach ($mtps as $mtp) {
407
-            $name = $mtp->name();
408
-            $values[] = array(
409
-                'text' => empty($name) ? __('Global', 'event_espresso') : $name,
410
-                'id'   => $mtp->ID(),
411
-            );
412
-        }
413
-        //need to get a list of shortcodes that are available for the newsletter message type.
414
-        $shortcodes = EEH_MSG_Template::get_shortcodes('newsletter', 'email', array(), 'attendee', false);
415
-        foreach ($shortcodes as $field => $shortcode_array) {
416
-            $codes[$field] = implode(', ', array_keys($shortcode_array));
417
-        }
418
-        $shortcodes = $codes;
419
-        $form_template = REG_CAF_TEMPLATE_PATH . 'newsletter-send-form.template.php';
420
-        $form_template_args = array(
421
-            'form_action'       => admin_url('admin.php?page=espresso_registrations'),
422
-            'form_route'        => 'newsletter_selected_send',
423
-            'form_nonce_name'   => 'newsletter_selected_send_nonce',
424
-            'form_nonce'        => wp_create_nonce('newsletter_selected_send_nonce'),
425
-            'redirect_back_to'  => $this->_req_action,
426
-            'ajax_nonce'        => wp_create_nonce('get_newsletter_form_content_nonce'),
427
-            'template_selector' => EEH_Form_Fields::select_input('newsletter_mtp_selected', $values),
428
-            'shortcodes'        => $shortcodes,
429
-            'id_type'           => $list_table instanceof EE_Attendee_Contact_List_Table ? 'contact' : 'registration',
430
-        );
431
-        EEH_Template::display_template($form_template, $form_template_args);
432
-    }
433
-
434
-
435
-
436
-    /**
437
-     * Handles sending selected registrations/contacts a newsletter.
438
-     *
439
-     * @since  4.3.0
440
-     * @return void
441
-     * @throws \EE_Error
442
-     */
443
-    protected function _newsletter_selected_send()
444
-    {
445
-        $success = true;
446
-        //first we need to make sure we have a GRP_ID so we know what template we're sending and updating!
447
-        if (empty($this->_req_data['newsletter_mtp_selected'])) {
448
-            EE_Error::add_error(
449
-                __(
450
-                    'In order to send a message, a Message Template GRP_ID is needed. It was not provided so messages were not sent.',
451
-                    'event_espresso'
452
-                ),
453
-                __FILE__,
454
-                __FUNCTION__,
455
-                __LINE__
456
-            );
457
-            $success = false;
458
-        }
459
-        if ($success) {
460
-            //update Message template in case there are any changes
461
-            $Message_Template_Group = EEM_Message_Template_Group::instance()->get_one_by_ID(
462
-                $this->_req_data['newsletter_mtp_selected']
463
-            );
464
-            $Message_Templates = $Message_Template_Group instanceof EE_Message_Template_Group
465
-                ? $Message_Template_Group->context_templates()
466
-                : array();
467
-            if (empty($Message_Templates)) {
468
-                EE_Error::add_error(
469
-                    __(
470
-                        'Unable to retrieve message template fields from the db. Messages not sent.',
471
-                        'event_espresso'
472
-                    ),
473
-                    __FILE__,
474
-                    __FUNCTION__,
475
-                    __LINE__
476
-                );
477
-            }
478
-            //let's just update the specific fields
479
-            foreach ($Message_Templates['attendee'] as $Message_Template) {
480
-                if ($Message_Template instanceof EE_Message_Template) {
481
-                    $field = $Message_Template->get('MTP_template_field');
482
-                    $content = $Message_Template->get('MTP_content');
483
-                    $new_content = $content;
484
-                    switch ($field) {
485
-                        case 'from' :
486
-                            $new_content = ! empty($this->_req_data['batch_message']['from'])
487
-                                ? $this->_req_data['batch_message']['from']
488
-                                : $content;
489
-                            break;
490
-                        case 'subject' :
491
-                            $new_content = ! empty($this->_req_data['batch_message']['subject'])
492
-                                ? $this->_req_data['batch_message']['subject']
493
-                                : $content;
494
-                            break;
495
-                        case 'content' :
496
-                            $new_content = $content;
497
-                            $new_content['newsletter_content'] = ! empty($this->_req_data['batch_message']['content'])
498
-                                ? $this->_req_data['batch_message']['content']
499
-                                : $content['newsletter_content'];
500
-                            break;
501
-                        default :
502
-                            //continue the foreach loop, we don't want to set $new_content nor save.
503
-                            continue 2;
504
-                    }
505
-                    $Message_Template->set('MTP_content', $new_content);
506
-                    $Message_Template->save();
507
-                }
508
-            }
509
-            //great fields are updated!  now let's make sure we just have contact objects (EE_Attendee).
510
-            $id_type = ! empty($this->_req_data['batch_message']['id_type'])
511
-                ? $this->_req_data['batch_message']['id_type']
512
-                : 'registration';
513
-            //id_type will affect how we assemble the ids.
514
-            $ids = ! empty($this->_req_data['batch_message']['ids'])
515
-                ? json_decode(stripslashes($this->_req_data['batch_message']['ids']))
516
-                : array();
517
-            $registrations_used_for_contact_data = array();
518
-            //using switch because eventually we'll have other contexts that will be used for generating messages.
519
-            switch ($id_type) {
520
-                case 'registration' :
521
-                    $registrations_used_for_contact_data = EEM_Registration::instance()->get_all(
522
-                        array(
523
-                            array(
524
-                                'REG_ID' => array('IN', $ids),
525
-                            ),
526
-                        )
527
-                    );
528
-                    break;
529
-                case 'contact' :
530
-                    $registrations_used_for_contact_data = EEM_Registration::instance()
531
-                                                                           ->get_latest_registration_for_each_of_given_contacts($ids);
532
-                    break;
533
-            }
534
-            do_action_ref_array(
535
-                'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations',
536
-                array(
537
-                    $registrations_used_for_contact_data,
538
-                    $Message_Template_Group->ID()
539
-                )
540
-            );
541
-            //kept for backward compat, internally we no longer use this action.
542
-            //@deprecated 4.8.36.rc.002
543
-            $contacts = $id_type === 'registration'
544
-                ? EEM_Attendee::instance()->get_array_of_contacts_from_reg_ids($ids)
545
-                : EEM_Attendee::instance()->get_all(array(array('ATT_ID' => array('in', $ids))));
546
-            do_action_ref_array(
547
-                'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send',
548
-                array(
549
-                    $contacts,
550
-                    $Message_Template_Group->ID()
551
-                )
552
-            );
553
-        }
554
-        $query_args = array(
555
-            'action' => ! empty($this->_req_data['redirect_back_to'])
556
-                ? $this->_req_data['redirect_back_to']
557
-                : 'default',
558
-        );
559
-        $this->_redirect_after_action(false, '', '', $query_args, true);
560
-    }
561
-
562
-
563
-
564
-    /**
565
-     * This is called when javascript is being enqueued to setup the various data needed for the reports js.
566
-     * Also $this->{$_reports_template_data} property is set for later usage by the _registration_reports method.
567
-     */
568
-    protected function _registration_reports_js_setup()
569
-    {
570
-        $this->_reports_template_data['admin_reports'][] = $this->_registrations_per_day_report();
571
-        $this->_reports_template_data['admin_reports'][] = $this->_registrations_per_event_report();
572
-    }
573
-
574
-
575
-
576
-    /**
577
-     *        generates Business Reports regarding Registrations
578
-     *
579
-     * @access protected
580
-     * @return void
581
-     */
582
-    protected function _registration_reports()
583
-    {
584
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_reports.template.php';
585
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
586
-            $template_path,
587
-            $this->_reports_template_data,
588
-            true
589
-        );
590
-        // the final template wrapper
591
-        $this->display_admin_page_with_no_sidebar();
592
-    }
593
-
594
-
595
-
596
-    /**
597
-     * Generates Business Report showing total registrations per day.
598
-     *
599
-     * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
600
-     * @return string
601
-     */
602
-    private function _registrations_per_day_report($period = '-1 month')
603
-    {
604
-        $report_ID = 'reg-admin-registrations-per-day-report-dv';
605
-        $results = EEM_Registration::instance()->get_registrations_per_day_and_per_status_report($period);
606
-        $results = (array)$results;
607
-        $regs = array();
608
-        $subtitle = '';
609
-        if ($results) {
610
-            $column_titles = array();
611
-            $tracker = 0;
612
-            foreach ($results as $result) {
613
-                $report_column_values = array();
614
-                foreach ($result as $property_name => $property_value) {
615
-                    $property_value = $property_name === 'Registration_REG_date' ? $property_value
616
-                        : (int)$property_value;
617
-                    $report_column_values[] = $property_value;
618
-                    if ($tracker === 0) {
619
-                        if ($property_name === 'Registration_REG_date') {
620
-                            $column_titles[] = __('Date (only days with registrations are shown)', 'event_espresso');
621
-                        } else {
622
-                            $column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
623
-                        }
624
-                    }
625
-                }
626
-                $tracker++;
627
-                $regs[] = $report_column_values;
628
-            }
629
-            //make sure the column_titles is pushed to the beginning of the array
630
-            array_unshift($regs, $column_titles);
631
-            //setup the date range.
632
-            $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
633
-            $beginning_date = new DateTime("now " . $period, $DateTimeZone);
634
-            $ending_date = new DateTime("now", $DateTimeZone);
635
-            $subtitle = sprintf(
636
-                _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
637
-                $beginning_date->format('Y-m-d'),
638
-                $ending_date->format('Y-m-d')
639
-            );
640
-        }
641
-        $report_title = __('Total Registrations per Day', 'event_espresso');
642
-        $report_params = array(
643
-            'title'     => $report_title,
644
-            'subtitle'  => $subtitle,
645
-            'id'        => $report_ID,
646
-            'regs'      => $regs,
647
-            'noResults' => empty($regs),
648
-            'noRegsMsg' => sprintf(
649
-                __(
650
-                    '%sThere are currently no registration records in the last month for this report.%s',
651
-                    'event_espresso'
652
-                ),
653
-                '<h2>' . $report_title . '</h2><p>',
654
-                '</p>'
655
-            ),
656
-        );
657
-        wp_localize_script('ee-reg-reports-js', 'regPerDay', $report_params);
658
-        return $report_ID;
659
-    }
660
-
661
-
662
-
663
-    /**
664
-     * Generates Business Report showing total registrations per event.
665
-     *
666
-     * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
667
-     * @return string
668
-     */
669
-    private function _registrations_per_event_report($period = '-1 month')
670
-    {
671
-        $report_ID = 'reg-admin-registrations-per-event-report-dv';
672
-        $results = EEM_Registration::instance()->get_registrations_per_event_and_per_status_report($period);
673
-        $results = (array)$results;
674
-        $regs = array();
675
-        $subtitle = '';
676
-        if ($results) {
677
-            $column_titles = array();
678
-            $tracker = 0;
679
-            foreach ($results as $result) {
680
-                $report_column_values = array();
681
-                foreach ($result as $property_name => $property_value) {
682
-                    $property_value = $property_name === 'Registration_Event' ? wp_trim_words(
683
-                        $property_value,
684
-                        4,
685
-                        '...'
686
-                    ) : (int)$property_value;
687
-                    $report_column_values[] = $property_value;
688
-                    if ($tracker === 0) {
689
-                        if ($property_name === 'Registration_Event') {
690
-                            $column_titles[] = __('Event', 'event_espresso');
691
-                        } else {
692
-                            $column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
693
-                        }
694
-                    }
695
-                }
696
-                $tracker++;
697
-                $regs[] = $report_column_values;
698
-            }
699
-            //make sure the column_titles is pushed to the beginning of the array
700
-            array_unshift($regs, $column_titles);
701
-            //setup the date range.
702
-            $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
703
-            $beginning_date = new DateTime("now " . $period, $DateTimeZone);
704
-            $ending_date = new DateTime("now", $DateTimeZone);
705
-            $subtitle = sprintf(
706
-                _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
707
-                $beginning_date->format('Y-m-d'),
708
-                $ending_date->format('Y-m-d')
709
-            );
710
-        }
711
-        $report_title = __('Total Registrations per Event', 'event_espresso');
712
-        $report_params = array(
713
-            'title'     => $report_title,
714
-            'subtitle'  => $subtitle,
715
-            'id'        => $report_ID,
716
-            'regs'      => $regs,
717
-            'noResults' => empty($regs),
718
-            'noRegsMsg' => sprintf(
719
-                __(
720
-                    '%sThere are currently no registration records in the last month for this report.%s',
721
-                    'event_espresso'
722
-                ),
723
-                '<h2>' . $report_title . '</h2><p>',
724
-                '</p>'
725
-            ),
726
-        );
727
-        wp_localize_script('ee-reg-reports-js', 'regPerEvent', $report_params);
728
-        return $report_ID;
729
-    }
730
-
731
-
732
-
733
-    /**
734
-     * generates HTML for the Registration Check-in list table (showing all Check-ins for a specific registration)
735
-     *
736
-     * @access protected
737
-     * @return void
738
-     * @throws \EE_Error
739
-     */
740
-    protected function _registration_checkin_list_table()
741
-    {
742
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
743
-        $reg_id = isset($this->_req_data['_REGID']) ? $this->_req_data['_REGID'] : null;
744
-        /** @var EE_Registration $registration */
745
-        $registration = EEM_Registration::instance()->get_one_by_ID($reg_id);
746
-        $attendee = $registration->attendee();
747
-        $this->_admin_page_title .= $this->get_action_link_or_button(
748
-            'new_registration',
749
-            'add-registrant',
750
-            array('event_id' => $registration->event_ID()),
751
-            'add-new-h2'
752
-        );
753
-        $checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
754
-        $checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
755
-        $legend_items = array(
756
-            'checkin'  => array(
757
-                'class' => $checked_in->cssClasses(),
758
-                'desc'  => $checked_in->legendLabel(),
759
-            ),
760
-            'checkout' => array(
761
-                'class' => $checked_out->cssClasses(),
762
-                'desc'  => $checked_out->legendLabel(),
763
-            ),
764
-        );
765
-        $this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
766
-        $dtt_id = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
767
-        /** @var EE_Datetime $datetime */
768
-        $datetime = EEM_Datetime::instance()->get_one_by_ID($dtt_id);
769
-        $datetime_label = '';
770
-        if ($datetime instanceof EE_Datetime) {
771
-            $datetime_label = $datetime->get_dtt_display_name(true);
772
-            $datetime_label .= ! empty($datetime_label)
773
-                ? ' (' . $datetime->get_dtt_display_name() . ')'
774
-                : $datetime->get_dtt_display_name();
775
-        }
776
-        $datetime_link = ! empty($dtt_id) && $registration instanceof EE_Registration
777
-            ? EE_Admin_Page::add_query_args_and_nonce(
778
-                array(
779
-                    'action'   => 'event_registrations',
780
-                    'event_id' => $registration->event_ID(),
781
-                    'DTT_ID'   => $dtt_id,
782
-                ),
783
-                $this->_admin_base_url
784
-            )
785
-            : '';
786
-        $datetime_link = ! empty($datetime_link)
787
-            ? '<a href="' . $datetime_link . '">'
788
-              . '<span id="checkin-dtt">'
789
-              . $datetime_label
790
-              . '</span></a>'
791
-            : $datetime_label;
792
-        $attendee_name = $attendee instanceof EE_Attendee
793
-            ? $attendee->full_name()
794
-            : '';
795
-        $attendee_link = $attendee instanceof EE_Attendee
796
-            ? $attendee->get_admin_details_link()
797
-            : '';
798
-        $attendee_link = ! empty($attendee_link)
799
-            ? '<a href="' . $attendee->get_admin_details_link() . '"'
800
-              . ' title="' . esc_html__('Click for attendee details', 'event_espresso') . '">'
801
-              . '<span id="checkin-attendee-name">'
802
-              . $attendee_name
803
-              . '</span></a>'
804
-            : '';
805
-        $event_link = $registration->event() instanceof EE_Event
806
-            ? $registration->event()->get_admin_details_link()
807
-            : '';
808
-        $event_link = ! empty($event_link)
809
-            ? '<a href="' . $event_link . '"'
810
-              . ' title="' . esc_html__('Click here to edit event.', 'event_espresso') . '">'
811
-              . '<span id="checkin-event-name">'
812
-              . $registration->event_name()
813
-              . '</span>'
814
-              . '</a>'
815
-            : '';
816
-        $this->_template_args['before_list_table'] = ! empty($reg_id) && ! empty($dtt_id)
817
-            ? '<h2>' . sprintf(
818
-                esc_html__('Displaying check in records for %1$s for %2$s at the event, %3$s', 'event_espresso'),
819
-                $attendee_link,
820
-                $datetime_link,
821
-                $event_link
822
-            ) . '</h2>'
823
-            : '';
824
-        $this->_template_args['list_table_hidden_fields'] = ! empty($reg_id)
825
-            ? '<input type="hidden" name="_REGID" value="' . $reg_id . '">' : '';
826
-        $this->_template_args['list_table_hidden_fields'] .= ! empty($dtt_id)
827
-            ? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : '';
828
-        $this->display_admin_list_table_page_with_no_sidebar();
829
-    }
830
-
831
-
832
-
833
-    /**
834
-     * toggle the Check-in status for the given registration (coming from ajax)
835
-     *
836
-     * @return void (JSON)
837
-     */
838
-    public function toggle_checkin_status()
839
-    {
840
-        //first make sure we have the necessary data
841
-        if ( ! isset($this->_req_data['_regid'])) {
842
-            EE_Error::add_error(
843
-                __(
844
-                    'There must be something broken with the html structure because the required data for toggling the Check-in status is not being sent via ajax',
845
-                    'event_espresso'
846
-                ),
847
-                __FILE__,
848
-                __FUNCTION__,
849
-                __LINE__
850
-            );
851
-            $this->_template_args['success'] = false;
852
-            $this->_template_args['error'] = true;
853
-            $this->_return_json();
854
-        };
855
-        //do a nonce check cause we're not coming in from an normal route here.
856
-        $nonce = isset($this->_req_data['checkinnonce']) ? sanitize_text_field($this->_req_data['checkinnonce'])
857
-            : '';
858
-        $nonce_ref = 'checkin_nonce';
859
-        $this->_verify_nonce($nonce, $nonce_ref);
860
-        //beautiful! Made it this far so let's get the status.
861
-        $new_status = new CheckinStatusDashicon($this->_toggle_checkin_status());
862
-        //setup new class to return via ajax
863
-        $this->_template_args['admin_page_content'] = 'clickable trigger-checkin ' . $new_status->cssClasses();
864
-        $this->_template_args['success'] = true;
865
-        $this->_return_json();
866
-    }
867
-
868
-
869
-
870
-    /**
871
-     * handles toggling the checkin status for the registration,
872
-     *
873
-     * @access protected
874
-     * @return int|void
875
-     */
876
-    protected function _toggle_checkin_status()
877
-    {
878
-        //first let's get the query args out of the way for the redirect
879
-        $query_args = array(
880
-            'action'   => 'event_registrations',
881
-            'event_id' => isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null,
882
-            'DTT_ID'   => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null,
883
-        );
884
-        $new_status = false;
885
-        // bulk action check in toggle
886
-        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
887
-            // cycle thru checkboxes
888
-            while (list($REG_ID, $value) = each($this->_req_data['checkbox'])) {
889
-                $DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
890
-                $new_status = $this->_toggle_checkin($REG_ID, $DTT_ID);
891
-            }
892
-        } elseif (isset($this->_req_data['_regid'])) {
893
-            //coming from ajax request
894
-            $DTT_ID = isset($this->_req_data['dttid']) ? $this->_req_data['dttid'] : null;
895
-            $query_args['DTT_ID'] = $DTT_ID;
896
-            $new_status = $this->_toggle_checkin($this->_req_data['_regid'], $DTT_ID);
897
-        } else {
898
-            EE_Error::add_error(
899
-                __('Missing some required data to toggle the Check-in', 'event_espresso'),
900
-                __FILE__,
901
-                __FUNCTION__,
902
-                __LINE__
903
-            );
904
-        }
905
-        if (defined('DOING_AJAX')) {
906
-            return $new_status;
907
-        }
908
-        $this->_redirect_after_action(false, '', '', $query_args, true);
909
-    }
910
-
911
-
912
-
913
-    /**
914
-     * This is toggles a single Check-in for the given registration and datetime.
915
-     *
916
-     * @param  int $REG_ID The registration we're toggling
917
-     * @param  int $DTT_ID The datetime we're toggling
918
-     * @return int            The new status toggled to.
919
-     * @throws \EE_Error
920
-     */
921
-    private function _toggle_checkin($REG_ID, $DTT_ID)
922
-    {
923
-        /** @var EE_Registration $REG */
924
-        $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
925
-        $new_status = $REG->toggle_checkin_status($DTT_ID);
926
-        if ($new_status !== false) {
927
-            EE_Error::add_success($REG->get_checkin_msg($DTT_ID));
928
-        } else {
929
-            EE_Error::add_error($REG->get_checkin_msg($DTT_ID, true), __FILE__, __FUNCTION__, __LINE__);
930
-            $new_status = false;
931
-        }
932
-        return $new_status;
933
-    }
934
-
935
-
936
-
937
-    /**
938
-     * Takes care of deleting multiple EE_Checkin table rows
939
-     *
940
-     * @access protected
941
-     * @return void
942
-     * @throws \EE_Error
943
-     */
944
-    protected function _delete_checkin_rows()
945
-    {
946
-        $query_args = array(
947
-            'action' => 'registration_checkins',
948
-            'DTT_ID' => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
949
-            '_REGID' => isset($this->_req_data['_REGID']) ? $this->_req_data['_REGID'] : 0,
950
-        );
951
-        $errors = 0;
952
-        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
953
-            while (list($CHK_ID, $value) = each($this->_req_data['checkbox'])) {
954
-                if ( ! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) {
955
-                    $errors++;
956
-                }
957
-            }
958
-        } else {
959
-            EE_Error::add_error(
960
-                __(
961
-                    'So, something went wrong with the bulk delete because there was no data received for instructions on WHAT to delete!',
962
-                    'event_espresso'
963
-                ),
964
-                __FILE__,
965
-                __FUNCTION__,
966
-                __LINE__
967
-            );
968
-            $this->_redirect_after_action(false, '', '', $query_args, true);
969
-        }
970
-        if ($errors > 0) {
971
-            EE_Error::add_error(
972
-                sprintf(__('There were %d records that did not delete successfully', 'event_espresso'), $errors),
973
-                __FILE__,
974
-                __FUNCTION__,
975
-                __LINE__
976
-            );
977
-        } else {
978
-            EE_Error::add_success(__('Records were successfully deleted', 'event_espresso'));
979
-        }
980
-        $this->_redirect_after_action(false, '', '', $query_args, true);
981
-    }
982
-
983
-
984
-
985
-    /**
986
-     * Deletes a single EE_Checkin row
987
-     *
988
-     * @return void
989
-     * @throws \EE_Error
990
-     */
991
-    protected function _delete_checkin_row()
992
-    {
993
-        $query_args = array(
994
-            'action' => 'registration_checkins',
995
-            'DTT_ID' => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
996
-            '_REGID' => isset($this->_req_data['_REGID']) ? $this->_req_data['_REGID'] : 0,
997
-        );
998
-        if ( ! empty($this->_req_data['CHK_ID'])) {
999
-            if ( ! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
1000
-                EE_Error::add_error(
1001
-                    __('Something went wrong and this check-in record was not deleted', 'event_espresso'),
1002
-                    __FILE__,
1003
-                    __FUNCTION__,
1004
-                    __LINE__
1005
-                );
1006
-            } else {
1007
-                EE_Error::add_success(__('Check-In record successfully deleted', 'event_espresso'));
1008
-            }
1009
-        } else {
1010
-            EE_Error::add_error(
1011
-                __(
1012
-                    'In order to delete a Check-in record, there must be a Check-In ID available. There is not. It is not your fault, there is just a gremlin living in the code',
1013
-                    'event_espresso'
1014
-                ),
1015
-                __FILE__,
1016
-                __FUNCTION__,
1017
-                __LINE__
1018
-            );
1019
-        }
1020
-        $this->_redirect_after_action(false, '', '', $query_args, true);
1021
-    }
1022
-
1023
-
1024
-
1025
-    /**
1026
-     *        generates HTML for the Event Registrations List Table
1027
-     *
1028
-     * @access protected
1029
-     * @return void
1030
-     * @throws \EE_Error
1031
-     */
1032
-    protected function _event_registrations_list_table()
1033
-    {
1034
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1035
-        $this->_admin_page_title .= isset($this->_req_data['event_id'])
1036
-            ? $this->get_action_link_or_button(
1037
-                'new_registration',
1038
-                'add-registrant',
1039
-                array('event_id' => $this->_req_data['event_id']),
1040
-                'add-new-h2',
1041
-                '',
1042
-                false
1043
-            )
1044
-            : '';
1045
-        $checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
1046
-        $checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
1047
-        $checked_never = new CheckinStatusDashicon(EE_Checkin::status_checked_never);
1048
-        $legend_items = array(
1049
-            'star-icon'        => array(
1050
-                'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
1051
-                'desc'  => __('This Registrant is the Primary Registrant', 'event_espresso'),
1052
-            ),
1053
-            'checkin'          => array(
1054
-                'class' => $checked_in->cssClasses(),
1055
-                'desc'  => $checked_in->legendLabel(),
1056
-            ),
1057
-            'checkout'         => array(
1058
-                'class' => $checked_out->cssClasses(),
1059
-                'desc'  => $checked_out->legendLabel(),
1060
-            ),
1061
-            'nocheckinrecord'  => array(
1062
-                'class' => $checked_never->cssClasses(),
1063
-                'desc'  => $checked_never->legendLabel(),
1064
-            ),
1065
-            'view_details'     => array(
1066
-                'class' => 'dashicons dashicons-search',
1067
-                'desc'  => __('View All Check-in Records for this Registrant', 'event_espresso'),
1068
-            ),
1069
-            'approved_status'  => array(
1070
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1071
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'),
1072
-            ),
1073
-            'cancelled_status' => array(
1074
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1075
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'),
1076
-            ),
1077
-            'declined_status'  => array(
1078
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1079
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'),
1080
-            ),
1081
-            'not_approved'     => array(
1082
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1083
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'),
1084
-            ),
1085
-            'pending_status'   => array(
1086
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1087
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'),
1088
-            ),
1089
-            'wait_list'        => array(
1090
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1091
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'),
1092
-            ),
1093
-        );
1094
-        $this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
1095
-        $event_id = isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null;
1096
-        $this->_template_args['before_list_table'] = ! empty($event_id)
1097
-            ? '<h2>' . sprintf(
1098
-                __('Viewing Registrations for Event: %s', 'event_espresso'),
1099
-                EEM_Event::instance()->get_one_by_ID($event_id)->get('EVT_name')
1100
-            ) . '</h2>'
1101
-            : '';
1102
-        //need to get the number of datetimes on the event and set default datetime_id if there is only one datetime on the event.
1103
-        /** @var EE_Event $event */
1104
-        $event = EEM_Event::instance()->get_one_by_ID($event_id);
1105
-        $DTT_ID = ! empty($this->_req_data['DTT_ID']) ? absint($this->_req_data['DTT_ID']) : 0;
1106
-        $datetime = null;
1107
-        if ($event instanceof EE_Event) {
1108
-            $datetimes_on_event = $event->datetimes();
1109
-            if (count($datetimes_on_event) === 1) {
1110
-                $datetime = reset($datetimes_on_event);
1111
-            }
1112
-        }
1113
-        $datetime = $datetime instanceof EE_Datetime ? $datetime : EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1114
-        if ($datetime instanceof EE_Datetime && $this->_template_args['before_list_table'] !== '') {
1115
-            $this->_template_args['before_list_table'] = substr($this->_template_args['before_list_table'], 0, -5);
1116
-            $this->_template_args['before_list_table'] .= ' &nbsp;<span class="drk-grey-text">';
1117
-            $this->_template_args['before_list_table'] .= '<span class="dashicons dashicons-calendar"></span>';
1118
-            $this->_template_args['before_list_table'] .= $datetime->name();
1119
-            $this->_template_args['before_list_table'] .= ' ( ' . $datetime->date_and_time_range() . ' )';
1120
-            $this->_template_args['before_list_table'] .= '</span></h2>';
1121
-        }
1122
-        //if no datetime, then we're on the initial view, so let's give some helpful instructions on what the status column
1123
-        //represents
1124
-        if ( ! $datetime instanceof EE_Datetime) {
1125
-            $this->_template_args['before_list_table'] .= '<br><p class="description">'
1126
-                                                          . __('In this view, the check-in status represents the latest check-in record for the registration in that row.',
1127
-                    'event_espresso')
1128
-                                                          . '</p>';
1129
-        }
1130
-        $this->display_admin_list_table_page_with_no_sidebar();
1131
-    }
1132
-
1133
-    /**
1134
-     * Download the registrations check-in report (same as the normal registration report, but with different where
1135
-     * conditions)
1136
-     *
1137
-     * @return void ends the request by a redirect or download
1138
-     */
1139
-    public function _registrations_checkin_report()
1140
-    {
1141
-        $this->_registrations_report_base('_get_checkin_query_params_from_request');
1142
-    }
1143
-
1144
-    /**
1145
-     * Gets the query params from the request, plus adds a where condition for the registration status,
1146
-     * because on the checkin page we only ever want to see approved and pending-approval registrations
1147
-     *
1148
-     * @param array     $request
1149
-     * @param int  $per_page
1150
-     * @param bool $count
1151
-     * @return array
1152
-     */
1153
-    protected function _get_checkin_query_params_from_request(
1154
-        $request,
1155
-        $per_page = 10,
1156
-        $count = false
1157
-    ) {
1158
-        $query_params = $this->_get_registration_query_parameters($request, $per_page, $count);
1159
-        //unlike the regular registrations list table,
1160
-        $status_ids_array = apply_filters(
1161
-            'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array',
1162
-            array(EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved)
1163
-        );
1164
-        $query_params[0]['STS_ID'] = array('IN', $status_ids_array);
1165
-        return $query_params;
1166
-    }
1167
-
1168
-
1169
-
1170
-
1171
-    /**
1172
-     * Gets registrations for an event
1173
-     *
1174
-     * @param int    $per_page
1175
-     * @param bool   $count whether to return count or data.
1176
-     * @param bool   $trash
1177
-     * @param string $orderby
1178
-     * @return EE_Registration[]|int
1179
-     * @throws \EE_Error
1180
-     */
1181
-    public function get_event_attendees($per_page = 10, $count = false, $trash = false, $orderby = 'ATT_fname')
1182
-    {
1183
-        //normalize some request params that get setup by the parent `get_registrations` method.
1184
-        $request = $this->_req_data;
1185
-        $request['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : $orderby;
1186
-        $request['order'] =  ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'ASC';
1187
-        if($trash){
1188
-            $request['status'] = 'trash';
1189
-        }
1190
-        $query_params = $this->_get_checkin_query_params_from_request( $request, $per_page, $count );
1191
-        /**
1192
-         * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1193
-         * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1194
-         * @see EEM_Base::get_all()
1195
-         */
1196
-        $query_params['group_by'] = '';
1197
-
1198
-        return $count
1199
-            ? EEM_Registration::instance()->count($query_params)
1200
-            /** @type EE_Registration[] */
1201
-            : EEM_Registration::instance()->get_all($query_params);
1202
-    }
23
+	/**
24
+	 * This is used to hold the reports template data which is setup early in the request.
25
+	 *
26
+	 * @type array
27
+	 */
28
+	protected $_reports_template_data = array();
29
+
30
+
31
+
32
+	/**
33
+	 * Extend_Registrations_Admin_Page constructor.
34
+	 *
35
+	 * @param bool $routing
36
+	 */
37
+	public function __construct($routing = true)
38
+	{
39
+		parent::__construct($routing);
40
+		if ( ! defined('REG_CAF_TEMPLATE_PATH')) {
41
+			define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/templates/');
42
+			define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/assets/');
43
+			define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registrations/assets/');
44
+		}
45
+	}
46
+
47
+
48
+
49
+	protected function _extend_page_config()
50
+	{
51
+		$this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'registrations';
52
+		$reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
53
+			? $this->_req_data['_REG_ID']
54
+			: 0;
55
+		// $att_id = ! empty( $this->_req_data['ATT_ID'] ) ? ! is_array( $this->_req_data['ATT_ID'] ) : 0;
56
+		// $att_id = ! empty( $this->_req_data['post'] ) && ! is_array( $this->_req_data['post'] )
57
+		// 	? $this->_req_data['post'] : $att_id;
58
+		$new_page_routes = array(
59
+			'reports'                  => array(
60
+				'func'       => '_registration_reports',
61
+				'capability' => 'ee_read_registrations',
62
+			),
63
+			'registration_checkins'    => array(
64
+				'func'       => '_registration_checkin_list_table',
65
+				'capability' => 'ee_read_checkins',
66
+			),
67
+			'newsletter_selected_send' => array(
68
+				'func'       => '_newsletter_selected_send',
69
+				'noheader'   => true,
70
+				'capability' => 'ee_send_message',
71
+			),
72
+			'delete_checkin_rows'      => array(
73
+				'func'       => '_delete_checkin_rows',
74
+				'noheader'   => true,
75
+				'capability' => 'ee_delete_checkins',
76
+			),
77
+			'delete_checkin_row'       => array(
78
+				'func'       => '_delete_checkin_row',
79
+				'noheader'   => true,
80
+				'capability' => 'ee_delete_checkin',
81
+				'obj_id'     => $reg_id,
82
+			),
83
+			'toggle_checkin_status'    => array(
84
+				'func'       => '_toggle_checkin_status',
85
+				'noheader'   => true,
86
+				'capability' => 'ee_edit_checkin',
87
+				'obj_id'     => $reg_id,
88
+			),
89
+			'toggle_checkin_status_bulk' => array(
90
+				'func' => '_toggle_checkin_status',
91
+				'noheader' => true,
92
+				'capability' => 'ee_edit_checkins'
93
+			),
94
+			'event_registrations'      => array(
95
+				'func'       => '_event_registrations_list_table',
96
+				'capability' => 'ee_read_checkins',
97
+			),
98
+			'registrations_checkin_report' => array(
99
+				'func'       => '_registrations_checkin_report',
100
+				'noheader'   => true,
101
+				'capability' => 'ee_read_registrations',
102
+			),
103
+		);
104
+		$this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
105
+		$new_page_config = array(
106
+			'reports'               => array(
107
+				'nav'           => array(
108
+					'label' => __('Reports', 'event_espresso'),
109
+					'order' => 30,
110
+				),
111
+				'help_tabs'     => array(
112
+					'registrations_reports_help_tab' => array(
113
+						'title'    => __('Registration Reports', 'event_espresso'),
114
+						'filename' => 'registrations_reports',
115
+					),
116
+				),
117
+				/*'help_tour' => array( 'Registration_Reports_Help_Tour' ),*/
118
+				'require_nonce' => false,
119
+			),
120
+			'event_registrations'   => array(
121
+				'nav'           => array(
122
+					'label'      => __('Event Check-In', 'event_espresso'),
123
+					'order'      => 10,
124
+					'persistent' => true,
125
+				),
126
+				'help_tabs'     => array(
127
+					'registrations_event_checkin_help_tab'                       => array(
128
+						'title'    => __('Registrations Event Check-In', 'event_espresso'),
129
+						'filename' => 'registrations_event_checkin',
130
+					),
131
+					'registrations_event_checkin_table_column_headings_help_tab' => array(
132
+						'title'    => __('Event Check-In Table Column Headings', 'event_espresso'),
133
+						'filename' => 'registrations_event_checkin_table_column_headings',
134
+					),
135
+					'registrations_event_checkin_filters_help_tab'               => array(
136
+						'title'    => __('Event Check-In Filters', 'event_espresso'),
137
+						'filename' => 'registrations_event_checkin_filters',
138
+					),
139
+					'registrations_event_checkin_views_help_tab'                 => array(
140
+						'title'    => __('Event Check-In Views', 'event_espresso'),
141
+						'filename' => 'registrations_event_checkin_views',
142
+					),
143
+					'registrations_event_checkin_other_help_tab'                 => array(
144
+						'title'    => __('Event Check-In Other', 'event_espresso'),
145
+						'filename' => 'registrations_event_checkin_other',
146
+					),
147
+				),
148
+				'help_tour'     => array('Event_Checkin_Help_Tour'),
149
+				'qtips'         => array('Registration_List_Table_Tips'),
150
+				'list_table'    => 'EE_Event_Registrations_List_Table',
151
+				'metaboxes'     => array(),
152
+				'require_nonce' => false,
153
+			),
154
+			'registration_checkins' => array(
155
+				'nav'           => array(
156
+					'label'      => __('Check-In Records', 'event_espresso'),
157
+					'order'      => 15,
158
+					'persistent' => false,
159
+				),
160
+				'list_table'    => 'EE_Registration_CheckIn_List_Table',
161
+				//'help_tour' => array( 'Checkin_Toggle_View_Help_Tour' ),
162
+				'metaboxes'     => array(),
163
+				'require_nonce' => false,
164
+			),
165
+		);
166
+		$this->_page_config = array_merge($this->_page_config, $new_page_config);
167
+		$this->_page_config['contact_list']['list_table'] = 'Extend_EE_Attendee_Contact_List_Table';
168
+		$this->_page_config['default']['list_table'] = 'Extend_EE_Registrations_List_Table';
169
+	}
170
+
171
+
172
+
173
+	protected function _ajax_hooks()
174
+	{
175
+		parent::_ajax_hooks();
176
+		add_action('wp_ajax_get_newsletter_form_content', array($this, 'get_newsletter_form_content'));
177
+	}
178
+
179
+
180
+
181
+	public function load_scripts_styles()
182
+	{
183
+		parent::load_scripts_styles();
184
+		//if newsletter message type is active then let's add filter and load js for it.
185
+		if (EEH_MSG_Template::is_mt_active('newsletter')) {
186
+			//enqueue newsletter js
187
+			wp_enqueue_script(
188
+				'ee-newsletter-trigger',
189
+				REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.js',
190
+				array('ee-dialog'),
191
+				EVENT_ESPRESSO_VERSION,
192
+				true
193
+			);
194
+			wp_enqueue_style(
195
+				'ee-newsletter-trigger-css',
196
+				REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.css',
197
+				array(),
198
+				EVENT_ESPRESSO_VERSION
199
+			);
200
+			//hook in buttons for newsletter message type trigger.
201
+			add_action(
202
+				'AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons',
203
+				array($this, 'add_newsletter_action_buttons'),
204
+				10
205
+			);
206
+		}
207
+	}
208
+
209
+
210
+
211
+	public function load_scripts_styles_reports()
212
+	{
213
+		wp_register_script(
214
+			'ee-reg-reports-js',
215
+			REG_CAF_ASSETS_URL . 'ee-registration-admin-reports.js',
216
+			array('google-charts'),
217
+			EVENT_ESPRESSO_VERSION,
218
+			true
219
+		);
220
+		wp_enqueue_script('ee-reg-reports-js');
221
+		$this->_registration_reports_js_setup();
222
+	}
223
+
224
+
225
+
226
+	protected function _add_screen_options_event_registrations()
227
+	{
228
+		$this->_per_page_screen_option();
229
+	}
230
+
231
+
232
+
233
+	protected function _add_screen_options_registration_checkins()
234
+	{
235
+		$page_title = $this->_admin_page_title;
236
+		$this->_admin_page_title = __('Check-In Records', 'event_espresso');
237
+		$this->_per_page_screen_option();
238
+		$this->_admin_page_title = $page_title;
239
+	}
240
+
241
+
242
+
243
+	protected function _set_list_table_views_event_registrations()
244
+	{
245
+		$this->_views = array(
246
+			'all' => array(
247
+				'slug'        => 'all',
248
+				'label'       => __('All', 'event_espresso'),
249
+				'count'       => 0,
250
+				'bulk_action' => ! isset($this->_req_data['event_id'])
251
+					? array()
252
+					: array(
253
+						'toggle_checkin_status_bulk' => __('Toggle Check-In', 'event_espresso'),
254
+					),
255
+			),
256
+		);
257
+	}
258
+
259
+
260
+
261
+	protected function _set_list_table_views_registration_checkins()
262
+	{
263
+		$this->_views = array(
264
+			'all' => array(
265
+				'slug'        => 'all',
266
+				'label'       => __('All', 'event_espresso'),
267
+				'count'       => 0,
268
+				'bulk_action' => array('delete_checkin_rows' => __('Delete Check-In Rows', 'event_espresso')),
269
+			),
270
+		);
271
+	}
272
+
273
+
274
+
275
+	/**
276
+	 * callback for ajax action.
277
+	 *
278
+	 * @since 4.3.0
279
+	 * @return void (JSON)
280
+	 * @throws \EE_Error
281
+	 */
282
+	public function get_newsletter_form_content()
283
+	{
284
+		//do a nonce check cause we're not coming in from an normal route here.
285
+		$nonce = isset($this->_req_data['get_newsletter_form_content_nonce']) ? sanitize_text_field(
286
+			$this->_req_data['get_newsletter_form_content_nonce']
287
+		) : '';
288
+		$nonce_ref = 'get_newsletter_form_content_nonce';
289
+		$this->_verify_nonce($nonce, $nonce_ref);
290
+		//let's get the mtp for the incoming MTP_ ID
291
+		if ( ! isset($this->_req_data['GRP_ID'])) {
292
+			EE_Error::add_error(
293
+				__(
294
+					'There must be something broken with the js or html structure because the required data for getting a message template group is not present (need an GRP_ID).',
295
+					'event_espresso'
296
+				),
297
+				__FILE__,
298
+				__FUNCTION__,
299
+				__LINE__
300
+			);
301
+			$this->_template_args['success'] = false;
302
+			$this->_template_args['error'] = true;
303
+			$this->_return_json();
304
+		}
305
+		$MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID($this->_req_data['GRP_ID']);
306
+		if ( ! $MTPG instanceof EE_Message_Template_Group) {
307
+			EE_Error::add_error(
308
+				sprintf(
309
+					__(
310
+						'The GRP_ID given (%d) does not appear to have a corresponding row in the database.',
311
+						'event_espresso'
312
+					),
313
+					$this->_req_data['GRP_ID']
314
+				),
315
+				__FILE__,
316
+				__FUNCTION__,
317
+				__LINE__
318
+			);
319
+			$this->_template_args['success'] = false;
320
+			$this->_template_args['error'] = true;
321
+			$this->_return_json();
322
+		}
323
+		$MTPs = $MTPG->context_templates();
324
+		$MTPs = $MTPs['attendee'];
325
+		$template_fields = array();
326
+		/** @var EE_Message_Template $MTP */
327
+		foreach ($MTPs as $MTP) {
328
+			$field = $MTP->get('MTP_template_field');
329
+			if ($field === 'content') {
330
+				$content = $MTP->get('MTP_content');
331
+				if ( ! empty($content['newsletter_content'])) {
332
+					$template_fields['newsletter_content'] = $content['newsletter_content'];
333
+				}
334
+				continue;
335
+			}
336
+			$template_fields[$MTP->get('MTP_template_field')] = $MTP->get('MTP_content');
337
+		}
338
+		$this->_template_args['success'] = true;
339
+		$this->_template_args['error'] = false;
340
+		$this->_template_args['data'] = array(
341
+			'batch_message_from'    => isset($template_fields['from'])
342
+				? $template_fields['from']
343
+				: '',
344
+			'batch_message_subject' => isset($template_fields['subject'])
345
+				? $template_fields['subject']
346
+				: '',
347
+			'batch_message_content' => isset($template_fields['newsletter_content'])
348
+				? $template_fields['newsletter_content']
349
+				: '',
350
+		);
351
+		$this->_return_json();
352
+	}
353
+
354
+
355
+
356
+	/**
357
+	 * callback for AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons action
358
+	 *
359
+	 * @since 4.3.0
360
+	 * @param EE_Admin_List_Table $list_table
361
+	 * @return void
362
+	 */
363
+	public function add_newsletter_action_buttons(EE_Admin_List_Table $list_table)
364
+	{
365
+		if ( ! EE_Registry::instance()->CAP->current_user_can(
366
+			'ee_send_message',
367
+			'espresso_registrations_newsletter_selected_send'
368
+		)
369
+		) {
370
+			return;
371
+		}
372
+		$routes_to_add_to = array(
373
+			'contact_list',
374
+			'event_registrations',
375
+			'default',
376
+		);
377
+		if ($this->_current_page === 'espresso_registrations' && in_array($this->_req_action, $routes_to_add_to)) {
378
+			if (($this->_req_action === 'event_registrations' && empty($this->_req_data['event_id']))
379
+				|| (isset($this->_req_data['status']) && $this->_req_data['status'] === 'trash')
380
+			) {
381
+				echo '';
382
+			} else {
383
+				$button_text = sprintf(
384
+					__('Send Batch Message (%s selected)', 'event_espresso'),
385
+					'<span class="send-selected-newsletter-count">0</span>'
386
+				);
387
+				echo '<button id="selected-batch-send-trigger" class="button secondary-button"><span class="dashicons dashicons-email "></span>'
388
+					 . $button_text
389
+					 . '</button>';
390
+				add_action('admin_footer', array($this, 'newsletter_send_form_skeleton'));
391
+			}
392
+		}
393
+	}
394
+
395
+
396
+
397
+	public function newsletter_send_form_skeleton()
398
+	{
399
+		$list_table = $this->_list_table_object;
400
+		$codes = array();
401
+		//need to templates for the newsletter message type for the template selector.
402
+		$values[] = array('text' => __('Select Template to Use', 'event_espresso'), 'id' => 0);
403
+		$mtps = EEM_Message_Template_Group::instance()->get_all(
404
+			array(array('MTP_message_type' => 'newsletter', 'MTP_messenger' => 'email'))
405
+		);
406
+		foreach ($mtps as $mtp) {
407
+			$name = $mtp->name();
408
+			$values[] = array(
409
+				'text' => empty($name) ? __('Global', 'event_espresso') : $name,
410
+				'id'   => $mtp->ID(),
411
+			);
412
+		}
413
+		//need to get a list of shortcodes that are available for the newsletter message type.
414
+		$shortcodes = EEH_MSG_Template::get_shortcodes('newsletter', 'email', array(), 'attendee', false);
415
+		foreach ($shortcodes as $field => $shortcode_array) {
416
+			$codes[$field] = implode(', ', array_keys($shortcode_array));
417
+		}
418
+		$shortcodes = $codes;
419
+		$form_template = REG_CAF_TEMPLATE_PATH . 'newsletter-send-form.template.php';
420
+		$form_template_args = array(
421
+			'form_action'       => admin_url('admin.php?page=espresso_registrations'),
422
+			'form_route'        => 'newsletter_selected_send',
423
+			'form_nonce_name'   => 'newsletter_selected_send_nonce',
424
+			'form_nonce'        => wp_create_nonce('newsletter_selected_send_nonce'),
425
+			'redirect_back_to'  => $this->_req_action,
426
+			'ajax_nonce'        => wp_create_nonce('get_newsletter_form_content_nonce'),
427
+			'template_selector' => EEH_Form_Fields::select_input('newsletter_mtp_selected', $values),
428
+			'shortcodes'        => $shortcodes,
429
+			'id_type'           => $list_table instanceof EE_Attendee_Contact_List_Table ? 'contact' : 'registration',
430
+		);
431
+		EEH_Template::display_template($form_template, $form_template_args);
432
+	}
433
+
434
+
435
+
436
+	/**
437
+	 * Handles sending selected registrations/contacts a newsletter.
438
+	 *
439
+	 * @since  4.3.0
440
+	 * @return void
441
+	 * @throws \EE_Error
442
+	 */
443
+	protected function _newsletter_selected_send()
444
+	{
445
+		$success = true;
446
+		//first we need to make sure we have a GRP_ID so we know what template we're sending and updating!
447
+		if (empty($this->_req_data['newsletter_mtp_selected'])) {
448
+			EE_Error::add_error(
449
+				__(
450
+					'In order to send a message, a Message Template GRP_ID is needed. It was not provided so messages were not sent.',
451
+					'event_espresso'
452
+				),
453
+				__FILE__,
454
+				__FUNCTION__,
455
+				__LINE__
456
+			);
457
+			$success = false;
458
+		}
459
+		if ($success) {
460
+			//update Message template in case there are any changes
461
+			$Message_Template_Group = EEM_Message_Template_Group::instance()->get_one_by_ID(
462
+				$this->_req_data['newsletter_mtp_selected']
463
+			);
464
+			$Message_Templates = $Message_Template_Group instanceof EE_Message_Template_Group
465
+				? $Message_Template_Group->context_templates()
466
+				: array();
467
+			if (empty($Message_Templates)) {
468
+				EE_Error::add_error(
469
+					__(
470
+						'Unable to retrieve message template fields from the db. Messages not sent.',
471
+						'event_espresso'
472
+					),
473
+					__FILE__,
474
+					__FUNCTION__,
475
+					__LINE__
476
+				);
477
+			}
478
+			//let's just update the specific fields
479
+			foreach ($Message_Templates['attendee'] as $Message_Template) {
480
+				if ($Message_Template instanceof EE_Message_Template) {
481
+					$field = $Message_Template->get('MTP_template_field');
482
+					$content = $Message_Template->get('MTP_content');
483
+					$new_content = $content;
484
+					switch ($field) {
485
+						case 'from' :
486
+							$new_content = ! empty($this->_req_data['batch_message']['from'])
487
+								? $this->_req_data['batch_message']['from']
488
+								: $content;
489
+							break;
490
+						case 'subject' :
491
+							$new_content = ! empty($this->_req_data['batch_message']['subject'])
492
+								? $this->_req_data['batch_message']['subject']
493
+								: $content;
494
+							break;
495
+						case 'content' :
496
+							$new_content = $content;
497
+							$new_content['newsletter_content'] = ! empty($this->_req_data['batch_message']['content'])
498
+								? $this->_req_data['batch_message']['content']
499
+								: $content['newsletter_content'];
500
+							break;
501
+						default :
502
+							//continue the foreach loop, we don't want to set $new_content nor save.
503
+							continue 2;
504
+					}
505
+					$Message_Template->set('MTP_content', $new_content);
506
+					$Message_Template->save();
507
+				}
508
+			}
509
+			//great fields are updated!  now let's make sure we just have contact objects (EE_Attendee).
510
+			$id_type = ! empty($this->_req_data['batch_message']['id_type'])
511
+				? $this->_req_data['batch_message']['id_type']
512
+				: 'registration';
513
+			//id_type will affect how we assemble the ids.
514
+			$ids = ! empty($this->_req_data['batch_message']['ids'])
515
+				? json_decode(stripslashes($this->_req_data['batch_message']['ids']))
516
+				: array();
517
+			$registrations_used_for_contact_data = array();
518
+			//using switch because eventually we'll have other contexts that will be used for generating messages.
519
+			switch ($id_type) {
520
+				case 'registration' :
521
+					$registrations_used_for_contact_data = EEM_Registration::instance()->get_all(
522
+						array(
523
+							array(
524
+								'REG_ID' => array('IN', $ids),
525
+							),
526
+						)
527
+					);
528
+					break;
529
+				case 'contact' :
530
+					$registrations_used_for_contact_data = EEM_Registration::instance()
531
+																		   ->get_latest_registration_for_each_of_given_contacts($ids);
532
+					break;
533
+			}
534
+			do_action_ref_array(
535
+				'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations',
536
+				array(
537
+					$registrations_used_for_contact_data,
538
+					$Message_Template_Group->ID()
539
+				)
540
+			);
541
+			//kept for backward compat, internally we no longer use this action.
542
+			//@deprecated 4.8.36.rc.002
543
+			$contacts = $id_type === 'registration'
544
+				? EEM_Attendee::instance()->get_array_of_contacts_from_reg_ids($ids)
545
+				: EEM_Attendee::instance()->get_all(array(array('ATT_ID' => array('in', $ids))));
546
+			do_action_ref_array(
547
+				'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send',
548
+				array(
549
+					$contacts,
550
+					$Message_Template_Group->ID()
551
+				)
552
+			);
553
+		}
554
+		$query_args = array(
555
+			'action' => ! empty($this->_req_data['redirect_back_to'])
556
+				? $this->_req_data['redirect_back_to']
557
+				: 'default',
558
+		);
559
+		$this->_redirect_after_action(false, '', '', $query_args, true);
560
+	}
561
+
562
+
563
+
564
+	/**
565
+	 * This is called when javascript is being enqueued to setup the various data needed for the reports js.
566
+	 * Also $this->{$_reports_template_data} property is set for later usage by the _registration_reports method.
567
+	 */
568
+	protected function _registration_reports_js_setup()
569
+	{
570
+		$this->_reports_template_data['admin_reports'][] = $this->_registrations_per_day_report();
571
+		$this->_reports_template_data['admin_reports'][] = $this->_registrations_per_event_report();
572
+	}
573
+
574
+
575
+
576
+	/**
577
+	 *        generates Business Reports regarding Registrations
578
+	 *
579
+	 * @access protected
580
+	 * @return void
581
+	 */
582
+	protected function _registration_reports()
583
+	{
584
+		$template_path = EE_ADMIN_TEMPLATE . 'admin_reports.template.php';
585
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
586
+			$template_path,
587
+			$this->_reports_template_data,
588
+			true
589
+		);
590
+		// the final template wrapper
591
+		$this->display_admin_page_with_no_sidebar();
592
+	}
593
+
594
+
595
+
596
+	/**
597
+	 * Generates Business Report showing total registrations per day.
598
+	 *
599
+	 * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
600
+	 * @return string
601
+	 */
602
+	private function _registrations_per_day_report($period = '-1 month')
603
+	{
604
+		$report_ID = 'reg-admin-registrations-per-day-report-dv';
605
+		$results = EEM_Registration::instance()->get_registrations_per_day_and_per_status_report($period);
606
+		$results = (array)$results;
607
+		$regs = array();
608
+		$subtitle = '';
609
+		if ($results) {
610
+			$column_titles = array();
611
+			$tracker = 0;
612
+			foreach ($results as $result) {
613
+				$report_column_values = array();
614
+				foreach ($result as $property_name => $property_value) {
615
+					$property_value = $property_name === 'Registration_REG_date' ? $property_value
616
+						: (int)$property_value;
617
+					$report_column_values[] = $property_value;
618
+					if ($tracker === 0) {
619
+						if ($property_name === 'Registration_REG_date') {
620
+							$column_titles[] = __('Date (only days with registrations are shown)', 'event_espresso');
621
+						} else {
622
+							$column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
623
+						}
624
+					}
625
+				}
626
+				$tracker++;
627
+				$regs[] = $report_column_values;
628
+			}
629
+			//make sure the column_titles is pushed to the beginning of the array
630
+			array_unshift($regs, $column_titles);
631
+			//setup the date range.
632
+			$DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
633
+			$beginning_date = new DateTime("now " . $period, $DateTimeZone);
634
+			$ending_date = new DateTime("now", $DateTimeZone);
635
+			$subtitle = sprintf(
636
+				_x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
637
+				$beginning_date->format('Y-m-d'),
638
+				$ending_date->format('Y-m-d')
639
+			);
640
+		}
641
+		$report_title = __('Total Registrations per Day', 'event_espresso');
642
+		$report_params = array(
643
+			'title'     => $report_title,
644
+			'subtitle'  => $subtitle,
645
+			'id'        => $report_ID,
646
+			'regs'      => $regs,
647
+			'noResults' => empty($regs),
648
+			'noRegsMsg' => sprintf(
649
+				__(
650
+					'%sThere are currently no registration records in the last month for this report.%s',
651
+					'event_espresso'
652
+				),
653
+				'<h2>' . $report_title . '</h2><p>',
654
+				'</p>'
655
+			),
656
+		);
657
+		wp_localize_script('ee-reg-reports-js', 'regPerDay', $report_params);
658
+		return $report_ID;
659
+	}
660
+
661
+
662
+
663
+	/**
664
+	 * Generates Business Report showing total registrations per event.
665
+	 *
666
+	 * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
667
+	 * @return string
668
+	 */
669
+	private function _registrations_per_event_report($period = '-1 month')
670
+	{
671
+		$report_ID = 'reg-admin-registrations-per-event-report-dv';
672
+		$results = EEM_Registration::instance()->get_registrations_per_event_and_per_status_report($period);
673
+		$results = (array)$results;
674
+		$regs = array();
675
+		$subtitle = '';
676
+		if ($results) {
677
+			$column_titles = array();
678
+			$tracker = 0;
679
+			foreach ($results as $result) {
680
+				$report_column_values = array();
681
+				foreach ($result as $property_name => $property_value) {
682
+					$property_value = $property_name === 'Registration_Event' ? wp_trim_words(
683
+						$property_value,
684
+						4,
685
+						'...'
686
+					) : (int)$property_value;
687
+					$report_column_values[] = $property_value;
688
+					if ($tracker === 0) {
689
+						if ($property_name === 'Registration_Event') {
690
+							$column_titles[] = __('Event', 'event_espresso');
691
+						} else {
692
+							$column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
693
+						}
694
+					}
695
+				}
696
+				$tracker++;
697
+				$regs[] = $report_column_values;
698
+			}
699
+			//make sure the column_titles is pushed to the beginning of the array
700
+			array_unshift($regs, $column_titles);
701
+			//setup the date range.
702
+			$DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
703
+			$beginning_date = new DateTime("now " . $period, $DateTimeZone);
704
+			$ending_date = new DateTime("now", $DateTimeZone);
705
+			$subtitle = sprintf(
706
+				_x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
707
+				$beginning_date->format('Y-m-d'),
708
+				$ending_date->format('Y-m-d')
709
+			);
710
+		}
711
+		$report_title = __('Total Registrations per Event', 'event_espresso');
712
+		$report_params = array(
713
+			'title'     => $report_title,
714
+			'subtitle'  => $subtitle,
715
+			'id'        => $report_ID,
716
+			'regs'      => $regs,
717
+			'noResults' => empty($regs),
718
+			'noRegsMsg' => sprintf(
719
+				__(
720
+					'%sThere are currently no registration records in the last month for this report.%s',
721
+					'event_espresso'
722
+				),
723
+				'<h2>' . $report_title . '</h2><p>',
724
+				'</p>'
725
+			),
726
+		);
727
+		wp_localize_script('ee-reg-reports-js', 'regPerEvent', $report_params);
728
+		return $report_ID;
729
+	}
730
+
731
+
732
+
733
+	/**
734
+	 * generates HTML for the Registration Check-in list table (showing all Check-ins for a specific registration)
735
+	 *
736
+	 * @access protected
737
+	 * @return void
738
+	 * @throws \EE_Error
739
+	 */
740
+	protected function _registration_checkin_list_table()
741
+	{
742
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
743
+		$reg_id = isset($this->_req_data['_REGID']) ? $this->_req_data['_REGID'] : null;
744
+		/** @var EE_Registration $registration */
745
+		$registration = EEM_Registration::instance()->get_one_by_ID($reg_id);
746
+		$attendee = $registration->attendee();
747
+		$this->_admin_page_title .= $this->get_action_link_or_button(
748
+			'new_registration',
749
+			'add-registrant',
750
+			array('event_id' => $registration->event_ID()),
751
+			'add-new-h2'
752
+		);
753
+		$checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
754
+		$checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
755
+		$legend_items = array(
756
+			'checkin'  => array(
757
+				'class' => $checked_in->cssClasses(),
758
+				'desc'  => $checked_in->legendLabel(),
759
+			),
760
+			'checkout' => array(
761
+				'class' => $checked_out->cssClasses(),
762
+				'desc'  => $checked_out->legendLabel(),
763
+			),
764
+		);
765
+		$this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
766
+		$dtt_id = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
767
+		/** @var EE_Datetime $datetime */
768
+		$datetime = EEM_Datetime::instance()->get_one_by_ID($dtt_id);
769
+		$datetime_label = '';
770
+		if ($datetime instanceof EE_Datetime) {
771
+			$datetime_label = $datetime->get_dtt_display_name(true);
772
+			$datetime_label .= ! empty($datetime_label)
773
+				? ' (' . $datetime->get_dtt_display_name() . ')'
774
+				: $datetime->get_dtt_display_name();
775
+		}
776
+		$datetime_link = ! empty($dtt_id) && $registration instanceof EE_Registration
777
+			? EE_Admin_Page::add_query_args_and_nonce(
778
+				array(
779
+					'action'   => 'event_registrations',
780
+					'event_id' => $registration->event_ID(),
781
+					'DTT_ID'   => $dtt_id,
782
+				),
783
+				$this->_admin_base_url
784
+			)
785
+			: '';
786
+		$datetime_link = ! empty($datetime_link)
787
+			? '<a href="' . $datetime_link . '">'
788
+			  . '<span id="checkin-dtt">'
789
+			  . $datetime_label
790
+			  . '</span></a>'
791
+			: $datetime_label;
792
+		$attendee_name = $attendee instanceof EE_Attendee
793
+			? $attendee->full_name()
794
+			: '';
795
+		$attendee_link = $attendee instanceof EE_Attendee
796
+			? $attendee->get_admin_details_link()
797
+			: '';
798
+		$attendee_link = ! empty($attendee_link)
799
+			? '<a href="' . $attendee->get_admin_details_link() . '"'
800
+			  . ' title="' . esc_html__('Click for attendee details', 'event_espresso') . '">'
801
+			  . '<span id="checkin-attendee-name">'
802
+			  . $attendee_name
803
+			  . '</span></a>'
804
+			: '';
805
+		$event_link = $registration->event() instanceof EE_Event
806
+			? $registration->event()->get_admin_details_link()
807
+			: '';
808
+		$event_link = ! empty($event_link)
809
+			? '<a href="' . $event_link . '"'
810
+			  . ' title="' . esc_html__('Click here to edit event.', 'event_espresso') . '">'
811
+			  . '<span id="checkin-event-name">'
812
+			  . $registration->event_name()
813
+			  . '</span>'
814
+			  . '</a>'
815
+			: '';
816
+		$this->_template_args['before_list_table'] = ! empty($reg_id) && ! empty($dtt_id)
817
+			? '<h2>' . sprintf(
818
+				esc_html__('Displaying check in records for %1$s for %2$s at the event, %3$s', 'event_espresso'),
819
+				$attendee_link,
820
+				$datetime_link,
821
+				$event_link
822
+			) . '</h2>'
823
+			: '';
824
+		$this->_template_args['list_table_hidden_fields'] = ! empty($reg_id)
825
+			? '<input type="hidden" name="_REGID" value="' . $reg_id . '">' : '';
826
+		$this->_template_args['list_table_hidden_fields'] .= ! empty($dtt_id)
827
+			? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : '';
828
+		$this->display_admin_list_table_page_with_no_sidebar();
829
+	}
830
+
831
+
832
+
833
+	/**
834
+	 * toggle the Check-in status for the given registration (coming from ajax)
835
+	 *
836
+	 * @return void (JSON)
837
+	 */
838
+	public function toggle_checkin_status()
839
+	{
840
+		//first make sure we have the necessary data
841
+		if ( ! isset($this->_req_data['_regid'])) {
842
+			EE_Error::add_error(
843
+				__(
844
+					'There must be something broken with the html structure because the required data for toggling the Check-in status is not being sent via ajax',
845
+					'event_espresso'
846
+				),
847
+				__FILE__,
848
+				__FUNCTION__,
849
+				__LINE__
850
+			);
851
+			$this->_template_args['success'] = false;
852
+			$this->_template_args['error'] = true;
853
+			$this->_return_json();
854
+		};
855
+		//do a nonce check cause we're not coming in from an normal route here.
856
+		$nonce = isset($this->_req_data['checkinnonce']) ? sanitize_text_field($this->_req_data['checkinnonce'])
857
+			: '';
858
+		$nonce_ref = 'checkin_nonce';
859
+		$this->_verify_nonce($nonce, $nonce_ref);
860
+		//beautiful! Made it this far so let's get the status.
861
+		$new_status = new CheckinStatusDashicon($this->_toggle_checkin_status());
862
+		//setup new class to return via ajax
863
+		$this->_template_args['admin_page_content'] = 'clickable trigger-checkin ' . $new_status->cssClasses();
864
+		$this->_template_args['success'] = true;
865
+		$this->_return_json();
866
+	}
867
+
868
+
869
+
870
+	/**
871
+	 * handles toggling the checkin status for the registration,
872
+	 *
873
+	 * @access protected
874
+	 * @return int|void
875
+	 */
876
+	protected function _toggle_checkin_status()
877
+	{
878
+		//first let's get the query args out of the way for the redirect
879
+		$query_args = array(
880
+			'action'   => 'event_registrations',
881
+			'event_id' => isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null,
882
+			'DTT_ID'   => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null,
883
+		);
884
+		$new_status = false;
885
+		// bulk action check in toggle
886
+		if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
887
+			// cycle thru checkboxes
888
+			while (list($REG_ID, $value) = each($this->_req_data['checkbox'])) {
889
+				$DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
890
+				$new_status = $this->_toggle_checkin($REG_ID, $DTT_ID);
891
+			}
892
+		} elseif (isset($this->_req_data['_regid'])) {
893
+			//coming from ajax request
894
+			$DTT_ID = isset($this->_req_data['dttid']) ? $this->_req_data['dttid'] : null;
895
+			$query_args['DTT_ID'] = $DTT_ID;
896
+			$new_status = $this->_toggle_checkin($this->_req_data['_regid'], $DTT_ID);
897
+		} else {
898
+			EE_Error::add_error(
899
+				__('Missing some required data to toggle the Check-in', 'event_espresso'),
900
+				__FILE__,
901
+				__FUNCTION__,
902
+				__LINE__
903
+			);
904
+		}
905
+		if (defined('DOING_AJAX')) {
906
+			return $new_status;
907
+		}
908
+		$this->_redirect_after_action(false, '', '', $query_args, true);
909
+	}
910
+
911
+
912
+
913
+	/**
914
+	 * This is toggles a single Check-in for the given registration and datetime.
915
+	 *
916
+	 * @param  int $REG_ID The registration we're toggling
917
+	 * @param  int $DTT_ID The datetime we're toggling
918
+	 * @return int            The new status toggled to.
919
+	 * @throws \EE_Error
920
+	 */
921
+	private function _toggle_checkin($REG_ID, $DTT_ID)
922
+	{
923
+		/** @var EE_Registration $REG */
924
+		$REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
925
+		$new_status = $REG->toggle_checkin_status($DTT_ID);
926
+		if ($new_status !== false) {
927
+			EE_Error::add_success($REG->get_checkin_msg($DTT_ID));
928
+		} else {
929
+			EE_Error::add_error($REG->get_checkin_msg($DTT_ID, true), __FILE__, __FUNCTION__, __LINE__);
930
+			$new_status = false;
931
+		}
932
+		return $new_status;
933
+	}
934
+
935
+
936
+
937
+	/**
938
+	 * Takes care of deleting multiple EE_Checkin table rows
939
+	 *
940
+	 * @access protected
941
+	 * @return void
942
+	 * @throws \EE_Error
943
+	 */
944
+	protected function _delete_checkin_rows()
945
+	{
946
+		$query_args = array(
947
+			'action' => 'registration_checkins',
948
+			'DTT_ID' => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
949
+			'_REGID' => isset($this->_req_data['_REGID']) ? $this->_req_data['_REGID'] : 0,
950
+		);
951
+		$errors = 0;
952
+		if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
953
+			while (list($CHK_ID, $value) = each($this->_req_data['checkbox'])) {
954
+				if ( ! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) {
955
+					$errors++;
956
+				}
957
+			}
958
+		} else {
959
+			EE_Error::add_error(
960
+				__(
961
+					'So, something went wrong with the bulk delete because there was no data received for instructions on WHAT to delete!',
962
+					'event_espresso'
963
+				),
964
+				__FILE__,
965
+				__FUNCTION__,
966
+				__LINE__
967
+			);
968
+			$this->_redirect_after_action(false, '', '', $query_args, true);
969
+		}
970
+		if ($errors > 0) {
971
+			EE_Error::add_error(
972
+				sprintf(__('There were %d records that did not delete successfully', 'event_espresso'), $errors),
973
+				__FILE__,
974
+				__FUNCTION__,
975
+				__LINE__
976
+			);
977
+		} else {
978
+			EE_Error::add_success(__('Records were successfully deleted', 'event_espresso'));
979
+		}
980
+		$this->_redirect_after_action(false, '', '', $query_args, true);
981
+	}
982
+
983
+
984
+
985
+	/**
986
+	 * Deletes a single EE_Checkin row
987
+	 *
988
+	 * @return void
989
+	 * @throws \EE_Error
990
+	 */
991
+	protected function _delete_checkin_row()
992
+	{
993
+		$query_args = array(
994
+			'action' => 'registration_checkins',
995
+			'DTT_ID' => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
996
+			'_REGID' => isset($this->_req_data['_REGID']) ? $this->_req_data['_REGID'] : 0,
997
+		);
998
+		if ( ! empty($this->_req_data['CHK_ID'])) {
999
+			if ( ! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
1000
+				EE_Error::add_error(
1001
+					__('Something went wrong and this check-in record was not deleted', 'event_espresso'),
1002
+					__FILE__,
1003
+					__FUNCTION__,
1004
+					__LINE__
1005
+				);
1006
+			} else {
1007
+				EE_Error::add_success(__('Check-In record successfully deleted', 'event_espresso'));
1008
+			}
1009
+		} else {
1010
+			EE_Error::add_error(
1011
+				__(
1012
+					'In order to delete a Check-in record, there must be a Check-In ID available. There is not. It is not your fault, there is just a gremlin living in the code',
1013
+					'event_espresso'
1014
+				),
1015
+				__FILE__,
1016
+				__FUNCTION__,
1017
+				__LINE__
1018
+			);
1019
+		}
1020
+		$this->_redirect_after_action(false, '', '', $query_args, true);
1021
+	}
1022
+
1023
+
1024
+
1025
+	/**
1026
+	 *        generates HTML for the Event Registrations List Table
1027
+	 *
1028
+	 * @access protected
1029
+	 * @return void
1030
+	 * @throws \EE_Error
1031
+	 */
1032
+	protected function _event_registrations_list_table()
1033
+	{
1034
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1035
+		$this->_admin_page_title .= isset($this->_req_data['event_id'])
1036
+			? $this->get_action_link_or_button(
1037
+				'new_registration',
1038
+				'add-registrant',
1039
+				array('event_id' => $this->_req_data['event_id']),
1040
+				'add-new-h2',
1041
+				'',
1042
+				false
1043
+			)
1044
+			: '';
1045
+		$checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
1046
+		$checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
1047
+		$checked_never = new CheckinStatusDashicon(EE_Checkin::status_checked_never);
1048
+		$legend_items = array(
1049
+			'star-icon'        => array(
1050
+				'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
1051
+				'desc'  => __('This Registrant is the Primary Registrant', 'event_espresso'),
1052
+			),
1053
+			'checkin'          => array(
1054
+				'class' => $checked_in->cssClasses(),
1055
+				'desc'  => $checked_in->legendLabel(),
1056
+			),
1057
+			'checkout'         => array(
1058
+				'class' => $checked_out->cssClasses(),
1059
+				'desc'  => $checked_out->legendLabel(),
1060
+			),
1061
+			'nocheckinrecord'  => array(
1062
+				'class' => $checked_never->cssClasses(),
1063
+				'desc'  => $checked_never->legendLabel(),
1064
+			),
1065
+			'view_details'     => array(
1066
+				'class' => 'dashicons dashicons-search',
1067
+				'desc'  => __('View All Check-in Records for this Registrant', 'event_espresso'),
1068
+			),
1069
+			'approved_status'  => array(
1070
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1071
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'),
1072
+			),
1073
+			'cancelled_status' => array(
1074
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1075
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'),
1076
+			),
1077
+			'declined_status'  => array(
1078
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1079
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'),
1080
+			),
1081
+			'not_approved'     => array(
1082
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1083
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'),
1084
+			),
1085
+			'pending_status'   => array(
1086
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1087
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'),
1088
+			),
1089
+			'wait_list'        => array(
1090
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1091
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'),
1092
+			),
1093
+		);
1094
+		$this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
1095
+		$event_id = isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null;
1096
+		$this->_template_args['before_list_table'] = ! empty($event_id)
1097
+			? '<h2>' . sprintf(
1098
+				__('Viewing Registrations for Event: %s', 'event_espresso'),
1099
+				EEM_Event::instance()->get_one_by_ID($event_id)->get('EVT_name')
1100
+			) . '</h2>'
1101
+			: '';
1102
+		//need to get the number of datetimes on the event and set default datetime_id if there is only one datetime on the event.
1103
+		/** @var EE_Event $event */
1104
+		$event = EEM_Event::instance()->get_one_by_ID($event_id);
1105
+		$DTT_ID = ! empty($this->_req_data['DTT_ID']) ? absint($this->_req_data['DTT_ID']) : 0;
1106
+		$datetime = null;
1107
+		if ($event instanceof EE_Event) {
1108
+			$datetimes_on_event = $event->datetimes();
1109
+			if (count($datetimes_on_event) === 1) {
1110
+				$datetime = reset($datetimes_on_event);
1111
+			}
1112
+		}
1113
+		$datetime = $datetime instanceof EE_Datetime ? $datetime : EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1114
+		if ($datetime instanceof EE_Datetime && $this->_template_args['before_list_table'] !== '') {
1115
+			$this->_template_args['before_list_table'] = substr($this->_template_args['before_list_table'], 0, -5);
1116
+			$this->_template_args['before_list_table'] .= ' &nbsp;<span class="drk-grey-text">';
1117
+			$this->_template_args['before_list_table'] .= '<span class="dashicons dashicons-calendar"></span>';
1118
+			$this->_template_args['before_list_table'] .= $datetime->name();
1119
+			$this->_template_args['before_list_table'] .= ' ( ' . $datetime->date_and_time_range() . ' )';
1120
+			$this->_template_args['before_list_table'] .= '</span></h2>';
1121
+		}
1122
+		//if no datetime, then we're on the initial view, so let's give some helpful instructions on what the status column
1123
+		//represents
1124
+		if ( ! $datetime instanceof EE_Datetime) {
1125
+			$this->_template_args['before_list_table'] .= '<br><p class="description">'
1126
+														  . __('In this view, the check-in status represents the latest check-in record for the registration in that row.',
1127
+					'event_espresso')
1128
+														  . '</p>';
1129
+		}
1130
+		$this->display_admin_list_table_page_with_no_sidebar();
1131
+	}
1132
+
1133
+	/**
1134
+	 * Download the registrations check-in report (same as the normal registration report, but with different where
1135
+	 * conditions)
1136
+	 *
1137
+	 * @return void ends the request by a redirect or download
1138
+	 */
1139
+	public function _registrations_checkin_report()
1140
+	{
1141
+		$this->_registrations_report_base('_get_checkin_query_params_from_request');
1142
+	}
1143
+
1144
+	/**
1145
+	 * Gets the query params from the request, plus adds a where condition for the registration status,
1146
+	 * because on the checkin page we only ever want to see approved and pending-approval registrations
1147
+	 *
1148
+	 * @param array     $request
1149
+	 * @param int  $per_page
1150
+	 * @param bool $count
1151
+	 * @return array
1152
+	 */
1153
+	protected function _get_checkin_query_params_from_request(
1154
+		$request,
1155
+		$per_page = 10,
1156
+		$count = false
1157
+	) {
1158
+		$query_params = $this->_get_registration_query_parameters($request, $per_page, $count);
1159
+		//unlike the regular registrations list table,
1160
+		$status_ids_array = apply_filters(
1161
+			'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array',
1162
+			array(EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved)
1163
+		);
1164
+		$query_params[0]['STS_ID'] = array('IN', $status_ids_array);
1165
+		return $query_params;
1166
+	}
1167
+
1168
+
1169
+
1170
+
1171
+	/**
1172
+	 * Gets registrations for an event
1173
+	 *
1174
+	 * @param int    $per_page
1175
+	 * @param bool   $count whether to return count or data.
1176
+	 * @param bool   $trash
1177
+	 * @param string $orderby
1178
+	 * @return EE_Registration[]|int
1179
+	 * @throws \EE_Error
1180
+	 */
1181
+	public function get_event_attendees($per_page = 10, $count = false, $trash = false, $orderby = 'ATT_fname')
1182
+	{
1183
+		//normalize some request params that get setup by the parent `get_registrations` method.
1184
+		$request = $this->_req_data;
1185
+		$request['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : $orderby;
1186
+		$request['order'] =  ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'ASC';
1187
+		if($trash){
1188
+			$request['status'] = 'trash';
1189
+		}
1190
+		$query_params = $this->_get_checkin_query_params_from_request( $request, $per_page, $count );
1191
+		/**
1192
+		 * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1193
+		 * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1194
+		 * @see EEM_Base::get_all()
1195
+		 */
1196
+		$query_params['group_by'] = '';
1197
+
1198
+		return $count
1199
+			? EEM_Registration::instance()->count($query_params)
1200
+			/** @type EE_Registration[] */
1201
+			: EEM_Registration::instance()->get_all($query_params);
1202
+	}
1203 1203
 
1204 1204
 
1205 1205
 } //end class Registrations Admin Page
Please login to merge, or discard this patch.
public/Espresso_Arabica_2014/loop-espresso_event_attendees.php 3 patches
Indentation   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -22,15 +22,15 @@  discard block
 block discarded – undo
22 22
 
23 23
 <div class="event-attendees">
24 24
     <?php do_action_ref_array(
25
-        'AHEE__loop-espresso_event_attendees__before',
26
-        array(
27
-            $contacts,
28
-            $event,
29
-            $datetime,
30
-            $ticket,
31
-            $show_gravatar,
32
-        )
33
-    ); ?>
25
+		'AHEE__loop-espresso_event_attendees__before',
26
+		array(
27
+			$contacts,
28
+			$event,
29
+			$datetime,
30
+			$ticket,
31
+			$show_gravatar,
32
+		)
33
+	); ?>
34 34
 	<?php if ( $contacts ) : ?>
35 35
 		<ul class="event-attendees-list">
36 36
 			<?php foreach( $contacts as $contact ) :
@@ -47,13 +47,13 @@  discard block
 block discarded – undo
47 47
 		<p><?php echo $no_attendees_message; ?></p>
48 48
 	<?php endif; ?>
49 49
     <?php do_action_ref_array(
50
-        'AHEE__loop-espresso_event_attendees__after',
51
-        array(
52
-            $contacts,
53
-            $event,
54
-            $datetime,
55
-            $ticket,
56
-            $show_gravatar,
57
-        )
58
-    ); ?>
50
+		'AHEE__loop-espresso_event_attendees__after',
51
+		array(
52
+			$contacts,
53
+			$event,
54
+			$datetime,
55
+			$ticket,
56
+			$show_gravatar,
57
+		)
58
+	); ?>
59 59
 </div>
60 60
\ No newline at end of file
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -15,7 +15,7 @@  discard block
 block discarded – undo
15 15
  * @type bool       $show_gravatar  whether to show gravatar or not.
16 16
  */
17 17
 
18
-$no_attendees_message =  apply_filters( 'FHEE__loop-espresso_attendees-shortcode__template__no_attendees_message', __('No Attendees Yet', 'event_espresso' ) );
18
+$no_attendees_message = apply_filters('FHEE__loop-espresso_attendees-shortcode__template__no_attendees_message', __('No Attendees Yet', 'event_espresso'));
19 19
 
20 20
 
21 21
 ?>
@@ -31,16 +31,16 @@  discard block
 block discarded – undo
31 31
             $show_gravatar,
32 32
         )
33 33
     ); ?>
34
-	<?php if ( $contacts ) : ?>
34
+	<?php if ($contacts) : ?>
35 35
 		<ul class="event-attendees-list">
36
-			<?php foreach( $contacts as $contact ) :
37
-				EEH_Template::get_template_part( 'content', 'espresso_event_attendees', array( 
36
+			<?php foreach ($contacts as $contact) :
37
+				EEH_Template::get_template_part('content', 'espresso_event_attendees', array( 
38 38
 					'contact'       => $contact, 
39 39
 					'event'         => $event,
40 40
 					'datetime'      => $datetime,
41 41
 					'ticket'        => $ticket,
42 42
 					'show_gravatar' => $show_gravatar 
43
-				) );
43
+				));
44 44
 				endforeach; ?>
45 45
 		</ul>
46 46
 	<?php else : ?>
Please login to merge, or discard this patch.
Braces   +5 added lines, -2 removed lines patch added patch discarded remove patch
@@ -43,8 +43,11 @@
 block discarded – undo
43 43
 				) );
44 44
 				endforeach; ?>
45 45
 		</ul>
46
-	<?php else : ?>
47
-		<p><?php echo $no_attendees_message; ?></p>
46
+	<?php else {
47
+	: ?>
48
+		<p><?php echo $no_attendees_message;
49
+}
50
+?></p>
48 51
 	<?php endif; ?>
49 52
     <?php do_action_ref_array(
50 53
         'AHEE__loop-espresso_event_attendees__after',
Please login to merge, or discard this patch.
modules/ticket_sales_monitor/EED_Ticket_Sales_Monitor.module.php 3 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -309,7 +309,7 @@  discard block
 block discarded – undo
309 309
      *
310 310
      * @param    EE_Ticket $ticket
311 311
      * @param int          $quantity
312
-     * @return bool
312
+     * @return integer
313 313
      * @throws EE_Error
314 314
      */
315 315
     protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
@@ -326,7 +326,7 @@  discard block
 block discarded – undo
326 326
     /**
327 327
      * @param  EE_Ticket $ticket
328 328
      * @param  int       $quantity
329
-     * @return bool
329
+     * @return integer
330 330
      * @throws EE_Error
331 331
      */
332 332
     protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
Please login to merge, or discard this patch.
Spacing   +51 added lines, -51 removed lines patch added patch discarded remove patch
@@ -2,7 +2,7 @@  discard block
 block discarded – undo
2 2
 
3 3
 use EventEspresso\core\exceptions\UnexpectedEntityException;
4 4
 
5
-if (! defined('EVENT_ESPRESSO_VERSION')) {
5
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
6 6
     exit('No direct script access allowed');
7 7
 }
8 8
 
@@ -22,7 +22,7 @@  discard block
 block discarded – undo
22 22
 class EED_Ticket_Sales_Monitor extends EED_Module
23 23
 {
24 24
 
25
-    const debug = false;    //	true false
25
+    const debug = false; //	true false
26 26
 
27 27
     /**
28 28
      * an array of raw ticket data from EED_Ticket_Selector
@@ -199,7 +199,7 @@  discard block
 block discarded – undo
199 199
             /** @var EE_Line_Item $total_line_item */
200 200
             $ticket_line_items = EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total($total_line_item);
201 201
             foreach ($ticket_line_items as $ticket_line_item) {
202
-                if (! $ticket_line_item instanceof EE_Line_Item) {
202
+                if ( ! $ticket_line_item instanceof EE_Line_Item) {
203 203
                     continue;
204 204
                 }
205 205
                 if ($total_line_item->timestamp(true) <= $expired) {
@@ -209,7 +209,7 @@  discard block
 block discarded – undo
209 209
                 }
210 210
             }
211 211
         }
212
-        if (! empty($expired_ticket_IDs)) {
212
+        if ( ! empty($expired_ticket_IDs)) {
213 213
             EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
214 214
                 \EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
215 215
                 $valid_ticket_line_items
@@ -245,8 +245,8 @@  discard block
 block discarded – undo
245 245
             $qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
246 246
         }
247 247
         if (self::debug) {
248
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '()';
249
-            echo '<br /><br /><b> RETURNED QTY: ' . $qty . '</b>';
248
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'()';
249
+            echo '<br /><br /><b> RETURNED QTY: '.$qty.'</b>';
250 250
         }
251 251
         return $qty;
252 252
     }
@@ -265,36 +265,36 @@  discard block
 block discarded – undo
265 265
     protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
266 266
     {
267 267
         if (self::debug) {
268
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
268
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
269 269
         }
270
-        if (! $ticket instanceof EE_Ticket) {
270
+        if ( ! $ticket instanceof EE_Ticket) {
271 271
             return 0;
272 272
         }
273 273
         if (self::debug) {
274
-            echo '<br /><b> . ticket->ID: ' . $ticket->ID() . '</b>';
275
-            echo '<br /> . original ticket->reserved: ' . $ticket->reserved();
274
+            echo '<br /><b> . ticket->ID: '.$ticket->ID().'</b>';
275
+            echo '<br /> . original ticket->reserved: '.$ticket->reserved();
276 276
         }
277 277
         $ticket->refresh_from_db();
278 278
         // first let's determine the ticket availability based on sales
279 279
         $available = $ticket->qty('saleable');
280 280
         if (self::debug) {
281
-            echo '<br /> . . . ticket->qty: ' . $ticket->qty();
282
-            echo '<br /> . . . ticket->sold: ' . $ticket->sold();
283
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
284
-            echo '<br /> . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
285
-            echo '<br /> . . . available: ' . $available;
281
+            echo '<br /> . . . ticket->qty: '.$ticket->qty();
282
+            echo '<br /> . . . ticket->sold: '.$ticket->sold();
283
+            echo '<br /> . . . ticket->reserved: '.$ticket->reserved();
284
+            echo '<br /> . . . ticket->qty(saleable): '.$ticket->qty('saleable');
285
+            echo '<br /> . . . available: '.$available;
286 286
         }
287 287
         if ($available < 1) {
288 288
             $this->_ticket_sold_out($ticket);
289 289
             return 0;
290 290
         }
291 291
         if (self::debug) {
292
-            echo '<br /> . . . qty: ' . $qty;
292
+            echo '<br /> . . . qty: '.$qty;
293 293
         }
294 294
         if ($available < $qty) {
295 295
             $qty = $available;
296 296
             if (self::debug) {
297
-                echo '<br /> . . . QTY ADJUSTED: ' . $qty;
297
+                echo '<br /> . . . QTY ADJUSTED: '.$qty;
298 298
             }
299 299
             $this->_ticket_quantity_decremented($ticket);
300 300
         }
@@ -315,7 +315,7 @@  discard block
 block discarded – undo
315 315
     protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
316 316
     {
317 317
         if (self::debug) {
318
-            echo '<br /><br /> . . . INCREASE RESERVED: ' . $quantity;
318
+            echo '<br /><br /> . . . INCREASE RESERVED: '.$quantity;
319 319
         }
320 320
         $ticket->increase_reserved($quantity);
321 321
         return $ticket->save();
@@ -332,12 +332,12 @@  discard block
 block discarded – undo
332 332
     protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
333 333
     {
334 334
         if (self::debug) {
335
-            echo '<br /> . . . ticket->ID: ' . $ticket->ID();
336
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
335
+            echo '<br /> . . . ticket->ID: '.$ticket->ID();
336
+            echo '<br /> . . . ticket->reserved: '.$ticket->reserved();
337 337
         }
338 338
         $ticket->decrease_reserved($quantity);
339 339
         if (self::debug) {
340
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
340
+            echo '<br /> . . . ticket->reserved: '.$ticket->reserved();
341 341
         }
342 342
         return $ticket->save() ? 1 : 0;
343 343
     }
@@ -355,8 +355,8 @@  discard block
 block discarded – undo
355 355
     protected function _ticket_sold_out(EE_Ticket $ticket)
356 356
     {
357 357
         if (self::debug) {
358
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
359
-            echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
358
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
359
+            echo '<br /> . . ticket->name: '.$this->_get_ticket_and_event_name($ticket);
360 360
         }
361 361
         $this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
362 362
     }
@@ -374,8 +374,8 @@  discard block
 block discarded – undo
374 374
     protected function _ticket_quantity_decremented(EE_Ticket $ticket)
375 375
     {
376 376
         if (self::debug) {
377
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
378
-            echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
377
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
378
+            echo '<br /> . . ticket->name: '.$this->_get_ticket_and_event_name($ticket);
379 379
         }
380 380
         $this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
381 381
     }
@@ -481,18 +481,18 @@  discard block
 block discarded – undo
481 481
     protected function _post_notices()
482 482
     {
483 483
         if (self::debug) {
484
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
484
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
485 485
         }
486 486
         $refresh_msg    = '';
487 487
         $none_added_msg = '';
488 488
         if (defined('DOING_AJAX') && DOING_AJAX) {
489
-            $refresh_msg    = __(
489
+            $refresh_msg = __(
490 490
                 'Please refresh the page to view updated ticket quantities.',
491 491
                 'event_espresso'
492 492
             );
493 493
             $none_added_msg = __('No tickets were added for the event.', 'event_espresso');
494 494
         }
495
-        if (! empty($this->sold_out_tickets)) {
495
+        if ( ! empty($this->sold_out_tickets)) {
496 496
             EE_Error::add_attention(
497 497
                 sprintf(
498 498
                     apply_filters(
@@ -515,7 +515,7 @@  discard block
 block discarded – undo
515 515
             // and reset the cart
516 516
             EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
517 517
         }
518
-        if (! empty($this->decremented_tickets)) {
518
+        if ( ! empty($this->decremented_tickets)) {
519 519
             EE_Error::add_attention(
520 520
                 sprintf(
521 521
                     apply_filters(
@@ -553,8 +553,8 @@  discard block
 block discarded – undo
553 553
     protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
554 554
     {
555 555
         if (self::debug) {
556
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
557
-            echo '<br /> . transaction->ID: ' . $transaction->ID();
556
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
557
+            echo '<br /> . transaction->ID: '.$transaction->ID();
558 558
         }
559 559
         // check if 'finalize_registration' step has been completed...
560 560
         $finalized = $transaction->reg_step_completed('finalize_registration');
@@ -566,13 +566,13 @@  discard block
 block discarded – undo
566 566
                 __LINE__,
567 567
                 array('finalized' => $finalized),
568 568
                 false,
569
-                'EE_Transaction: ' . $transaction->ID()
569
+                'EE_Transaction: '.$transaction->ID()
570 570
             );
571 571
         }
572 572
         // how many tickets were released
573 573
         $count = 0;
574 574
         if (self::debug) {
575
-            echo '<br /> . . . finalized: ' . $finalized;
575
+            echo '<br /> . . . finalized: '.$finalized;
576 576
         }
577 577
         $release_tickets_with_TXN_status = array(
578 578
             EEM_Transaction::failed_status_code,
@@ -580,10 +580,10 @@  discard block
 block discarded – undo
580 580
             EEM_Transaction::incomplete_status_code,
581 581
         );
582 582
         // if the session is getting cleared BEFORE the TXN has been finalized
583
-        if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
583
+        if ( ! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
584 584
             // let's cancel any reserved tickets
585 585
             $registrations = $transaction->registrations();
586
-            if (! empty($registrations)) {
586
+            if ( ! empty($registrations)) {
587 587
                 foreach ($registrations as $registration) {
588 588
                     if ($registration instanceof EE_Registration) {
589 589
                         $count += $this->_release_reserved_ticket_for_registration($registration, $transaction);
@@ -611,10 +611,10 @@  discard block
 block discarded – undo
611 611
     ) {
612 612
         $STS_ID = $transaction->status_ID();
613 613
         if (self::debug) {
614
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
615
-            echo '<br /> . . registration->ID: ' . $registration->ID();
616
-            echo '<br /> . . registration->status_ID: ' . $registration->status_ID();
617
-            echo '<br /> . . transaction->status_ID(): ' . $STS_ID;
614
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
615
+            echo '<br /> . . registration->ID: '.$registration->ID();
616
+            echo '<br /> . . registration->status_ID: '.$registration->status_ID();
617
+            echo '<br /> . . transaction->status_ID(): '.$STS_ID;
618 618
         }
619 619
         if (
620 620
             // release Tickets for Failed Transactions and Abandoned Transactions
@@ -654,7 +654,7 @@  discard block
 block discarded – undo
654 654
     public static function session_cart_reset(EE_Session $session)
655 655
     {
656 656
         if (self::debug) {
657
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
657
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
658 658
         }
659 659
         $cart = $session->cart();
660 660
         if ($cart instanceof EE_Cart) {
@@ -686,7 +686,7 @@  discard block
 block discarded – undo
686 686
     protected function _session_cart_reset(EE_Cart $cart)
687 687
     {
688 688
         if (self::debug) {
689
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
689
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
690 690
         }
691 691
         EE_Registry::instance()->load_helper('Line_Item');
692 692
         $ticket_line_items = $cart->get_tickets();
@@ -695,17 +695,17 @@  discard block
 block discarded – undo
695 695
         }
696 696
         foreach ($ticket_line_items as $ticket_line_item) {
697 697
             if (self::debug) {
698
-                echo '<br /> . ticket_line_item->ID(): ' . $ticket_line_item->ID();
698
+                echo '<br /> . ticket_line_item->ID(): '.$ticket_line_item->ID();
699 699
             }
700 700
             if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
701 701
                 if (self::debug) {
702
-                    echo '<br /> . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
702
+                    echo '<br /> . . ticket_line_item->OBJ_ID(): '.$ticket_line_item->OBJ_ID();
703 703
                 }
704 704
                 $ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
705 705
                 if ($ticket instanceof EE_Ticket) {
706 706
                     if (self::debug) {
707
-                        echo '<br /> . . ticket->ID(): ' . $ticket->ID();
708
-                        echo '<br /> . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
707
+                        echo '<br /> . . ticket->ID(): '.$ticket->ID();
708
+                        echo '<br /> . . ticket_line_item->quantity(): '.$ticket_line_item->quantity();
709 709
                     }
710 710
                     $this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
711 711
                 }
@@ -751,7 +751,7 @@  discard block
 block discarded – undo
751 751
     protected function _session_checkout_reset(EE_Checkout $checkout)
752 752
     {
753 753
         if (self::debug) {
754
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
754
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
755 755
         }
756 756
         // we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
757 757
         if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
@@ -801,7 +801,7 @@  discard block
 block discarded – undo
801 801
                     __LINE__,
802 802
                     array($transaction),
803 803
                     false,
804
-                    'EE_Transaction: ' . $transaction->ID()
804
+                    'EE_Transaction: '.$transaction->ID()
805 805
                 );
806 806
             }
807 807
             return;
@@ -818,7 +818,7 @@  discard block
 block discarded – undo
818 818
                         __LINE__,
819 819
                         array($payment),
820 820
                         false,
821
-                        'EE_Transaction: ' . $transaction->ID()
821
+                        'EE_Transaction: '.$transaction->ID()
822 822
                     );
823 823
                 }
824 824
                 return;
@@ -874,7 +874,7 @@  discard block
 block discarded – undo
874 874
             /** @var EE_Transaction $transaction_in_progress */
875 875
             $total_line_item = $transaction_in_progress->total_line_item();
876 876
             // $transaction_in_progress->line
877
-            if (! $total_line_item instanceof EE_Line_Item) {
877
+            if ( ! $total_line_item instanceof EE_Line_Item) {
878 878
                 throw new DomainException(
879 879
                     esc_html__(
880 880
                         'Transaction does not have a valid Total Line Item associated with it.',
@@ -931,7 +931,7 @@  discard block
 block discarded – undo
931 931
     ) {
932 932
         $total_tickets_released = 0;
933 933
         foreach ($tickets_with_reservations as $ticket_with_reservations) {
934
-            if (! $ticket_with_reservations instanceof EE_Ticket) {
934
+            if ( ! $ticket_with_reservations instanceof EE_Ticket) {
935 935
                 continue;
936 936
             }
937 937
             $reserved_qty = $ticket_with_reservations->reserved();
@@ -971,7 +971,7 @@  discard block
 block discarded – undo
971 971
         global $wpdb;
972 972
         return $wpdb->query(
973 973
             $wpdb->prepare(
974
-                'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
974
+                'DELETE FROM '.EEM_Line_Item::instance()->table().'
975 975
                 WHERE TXN_ID = 0 AND LIN_timestamp <= %s',
976 976
                 // use GMT time because that's what LIN_timestamps are in
977 977
                 date('Y-m-d H:i:s', time() - EE_Registry::instance()->SSN->lifespan())
Please login to merge, or discard this patch.
Indentation   +956 added lines, -956 removed lines patch added patch discarded remove patch
@@ -3,7 +3,7 @@  discard block
 block discarded – undo
3 3
 use EventEspresso\core\exceptions\UnexpectedEntityException;
4 4
 
5 5
 if (! defined('EVENT_ESPRESSO_VERSION')) {
6
-    exit('No direct script access allowed');
6
+	exit('No direct script access allowed');
7 7
 }
8 8
 
9 9
 
@@ -22,962 +22,962 @@  discard block
 block discarded – undo
22 22
 class EED_Ticket_Sales_Monitor extends EED_Module
23 23
 {
24 24
 
25
-    const debug = false;    //	true false
26
-
27
-    /**
28
-     * an array of raw ticket data from EED_Ticket_Selector
29
-     *
30
-     * @var array $ticket_selections
31
-     */
32
-    protected $ticket_selections = array();
33
-
34
-    /**
35
-     * the raw ticket data from EED_Ticket_Selector is organized in rows
36
-     * according to how they are displayed in the actual Ticket_Selector
37
-     * this tracks the current row being processed
38
-     *
39
-     * @var int $current_row
40
-     */
41
-    protected $current_row = 0;
42
-
43
-    /**
44
-     * an array for tracking names of tickets that have sold out
45
-     *
46
-     * @var array $sold_out_tickets
47
-     */
48
-    protected $sold_out_tickets = array();
49
-
50
-    /**
51
-     * an array for tracking names of tickets that have had their quantities reduced
52
-     *
53
-     * @var array $decremented_tickets
54
-     */
55
-    protected $decremented_tickets = array();
56
-
57
-
58
-
59
-    /**
60
-     * set_hooks - for hooking into EE Core, other modules, etc
61
-     *
62
-     * @return    void
63
-     */
64
-    public static function set_hooks()
65
-    {
66
-        // release tickets for expired carts
67
-        add_action(
68
-            'EED_Ticket_Selector__process_ticket_selections__before',
69
-            array('EED_Ticket_Sales_Monitor', 'release_tickets_for_expired_carts'),
70
-            1
71
-        );
72
-        // check ticket reserves AFTER MER does it's check (hence priority 20)
73
-        add_filter(
74
-            'FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty',
75
-            array('EED_Ticket_Sales_Monitor', 'validate_ticket_sale'),
76
-            20,
77
-            3
78
-        );
79
-        // add notices for sold out tickets
80
-        add_action(
81
-            'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
82
-            array('EED_Ticket_Sales_Monitor', 'post_notices'),
83
-            10
84
-        );
85
-        // handle ticket quantities adjusted in cart
86
-        //add_action(
87
-        //	'FHEE__EED_Multi_Event_Registration__adjust_line_item_quantity__line_item_quantity_updated',
88
-        //	array( 'EED_Ticket_Sales_Monitor', 'ticket_quantity_updated' ),
89
-        //	10, 2
90
-        //);
91
-        // handle tickets deleted from cart
92
-        add_action(
93
-            'FHEE__EED_Multi_Event_Registration__delete_ticket__ticket_removed_from_cart',
94
-            array('EED_Ticket_Sales_Monitor', 'ticket_removed_from_cart'),
95
-            10,
96
-            2
97
-        );
98
-        // handle emptied carts
99
-        add_action(
100
-            'AHEE__EE_Session__reset_cart__before_reset',
101
-            array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
102
-            10,
103
-            1
104
-        );
105
-        add_action(
106
-            'AHEE__EED_Multi_Event_Registration__empty_event_cart__before_delete_cart',
107
-            array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
108
-            10,
109
-            1
110
-        );
111
-        // handle cancelled registrations
112
-        add_action(
113
-            'AHEE__EE_Session__reset_checkout__before_reset',
114
-            array('EED_Ticket_Sales_Monitor', 'session_checkout_reset'),
115
-            10,
116
-            1
117
-        );
118
-        // cron tasks
119
-        add_action(
120
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
121
-            array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
122
-            10,
123
-            1
124
-        );
125
-        add_action(
126
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
127
-            array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
128
-            10,
129
-            1
130
-        );
131
-        add_action(
132
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
133
-            array('EED_Ticket_Sales_Monitor', 'process_failed_transactions'),
134
-            10,
135
-            1
136
-        );
137
-    }
138
-
139
-
140
-
141
-    /**
142
-     * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
143
-     *
144
-     * @return void
145
-     */
146
-    public static function set_hooks_admin()
147
-    {
148
-        EED_Ticket_Sales_Monitor::set_hooks();
149
-    }
150
-
151
-
152
-
153
-    /**
154
-     * @return EED_Ticket_Sales_Monitor|EED_Module
155
-     */
156
-    public static function instance()
157
-    {
158
-        return parent::get_instance(__CLASS__);
159
-    }
160
-
161
-
162
-
163
-    /**
164
-     * @param WP_Query $WP_Query
165
-     * @return    void
166
-     */
167
-    public function run($WP_Query)
168
-    {
169
-    }
170
-
171
-
172
-
173
-    /********************************** PRE_TICKET_SALES  **********************************/
174
-
175
-
176
-
177
-    /**
178
-     * Retrieves grand totals from the line items that have no TXN ID
179
-     * and timestamps less than the current time minus the session lifespan.
180
-     * These are carts that have been abandoned before the "registrant" even attempted to checkout.
181
-     * We're going to release the tickets for these line items before attempting to add more to the cart.
182
-     *
183
-     * @return void
184
-     * @throws EE_Error
185
-     * @throws InvalidArgumentException
186
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
187
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
188
-     */
189
-    public static function release_tickets_for_expired_carts()
190
-    {
191
-        $expired_ticket_IDs      = array();
192
-        $valid_ticket_line_items = array();
193
-        $total_line_items        = EEM_Line_Item::instance()->get_total_line_items_with_no_transaction();
194
-        if (empty($total_line_items)) {
195
-            return;
196
-        }
197
-        $expired = current_time('timestamp') - EE_Registry::instance()->SSN->lifespan();
198
-        foreach ($total_line_items as $total_line_item) {
199
-            /** @var EE_Line_Item $total_line_item */
200
-            $ticket_line_items = EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total($total_line_item);
201
-            foreach ($ticket_line_items as $ticket_line_item) {
202
-                if (! $ticket_line_item instanceof EE_Line_Item) {
203
-                    continue;
204
-                }
205
-                if ($total_line_item->timestamp(true) <= $expired) {
206
-                    $expired_ticket_IDs[$ticket_line_item->OBJ_ID()] = $ticket_line_item->OBJ_ID();
207
-                } else {
208
-                    $valid_ticket_line_items[$ticket_line_item->OBJ_ID()] = $ticket_line_item;
209
-                }
210
-            }
211
-        }
212
-        if (! empty($expired_ticket_IDs)) {
213
-            EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
214
-                \EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
215
-                $valid_ticket_line_items
216
-            );
217
-            // let's get rid of expired line items so that they can't interfere with tracking
218
-            add_action(
219
-                'shutdown',
220
-                array('EED_Ticket_Sales_Monitor', 'clear_expired_line_items_with_no_transaction'),
221
-                999
222
-            );
223
-        }
224
-    }
225
-
226
-
227
-
228
-    /********************************** VALIDATE_TICKET_SALE  **********************************/
229
-
230
-
231
-
232
-    /**
233
-     * callback for 'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data'
234
-     *
235
-     * @param int       $qty
236
-     * @param EE_Ticket $ticket
237
-     * @return bool
238
-     * @throws UnexpectedEntityException
239
-     * @throws EE_Error
240
-     */
241
-    public static function validate_ticket_sale($qty = 1, EE_Ticket $ticket)
242
-    {
243
-        $qty = absint($qty);
244
-        if ($qty > 0) {
245
-            $qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
246
-        }
247
-        if (self::debug) {
248
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '()';
249
-            echo '<br /><br /><b> RETURNED QTY: ' . $qty . '</b>';
250
-        }
251
-        return $qty;
252
-    }
253
-
254
-
255
-
256
-    /**
257
-     * checks whether an individual ticket is available for purchase based on datetime, and ticket details
258
-     *
259
-     * @param   EE_Ticket $ticket
260
-     * @param int         $qty
261
-     * @return int
262
-     * @throws UnexpectedEntityException
263
-     * @throws EE_Error
264
-     */
265
-    protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
266
-    {
267
-        if (self::debug) {
268
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
269
-        }
270
-        if (! $ticket instanceof EE_Ticket) {
271
-            return 0;
272
-        }
273
-        if (self::debug) {
274
-            echo '<br /><b> . ticket->ID: ' . $ticket->ID() . '</b>';
275
-            echo '<br /> . original ticket->reserved: ' . $ticket->reserved();
276
-        }
277
-        $ticket->refresh_from_db();
278
-        // first let's determine the ticket availability based on sales
279
-        $available = $ticket->qty('saleable');
280
-        if (self::debug) {
281
-            echo '<br /> . . . ticket->qty: ' . $ticket->qty();
282
-            echo '<br /> . . . ticket->sold: ' . $ticket->sold();
283
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
284
-            echo '<br /> . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
285
-            echo '<br /> . . . available: ' . $available;
286
-        }
287
-        if ($available < 1) {
288
-            $this->_ticket_sold_out($ticket);
289
-            return 0;
290
-        }
291
-        if (self::debug) {
292
-            echo '<br /> . . . qty: ' . $qty;
293
-        }
294
-        if ($available < $qty) {
295
-            $qty = $available;
296
-            if (self::debug) {
297
-                echo '<br /> . . . QTY ADJUSTED: ' . $qty;
298
-            }
299
-            $this->_ticket_quantity_decremented($ticket);
300
-        }
301
-        $this->_reserve_ticket($ticket, $qty);
302
-        return $qty;
303
-    }
304
-
305
-
306
-
307
-    /**
308
-     * increments ticket reserved based on quantity passed
309
-     *
310
-     * @param    EE_Ticket $ticket
311
-     * @param int          $quantity
312
-     * @return bool
313
-     * @throws EE_Error
314
-     */
315
-    protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
316
-    {
317
-        if (self::debug) {
318
-            echo '<br /><br /> . . . INCREASE RESERVED: ' . $quantity;
319
-        }
320
-        $ticket->increase_reserved($quantity);
321
-        return $ticket->save();
322
-    }
323
-
324
-
325
-
326
-    /**
327
-     * @param  EE_Ticket $ticket
328
-     * @param  int       $quantity
329
-     * @return bool
330
-     * @throws EE_Error
331
-     */
332
-    protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
333
-    {
334
-        if (self::debug) {
335
-            echo '<br /> . . . ticket->ID: ' . $ticket->ID();
336
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
337
-        }
338
-        $ticket->decrease_reserved($quantity);
339
-        if (self::debug) {
340
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
341
-        }
342
-        return $ticket->save() ? 1 : 0;
343
-    }
344
-
345
-
346
-
347
-    /**
348
-     * removes quantities within the ticket selector based on zero ticket availability
349
-     *
350
-     * @param    EE_Ticket $ticket
351
-     * @return    void
352
-     * @throws UnexpectedEntityException
353
-     * @throws EE_Error
354
-     */
355
-    protected function _ticket_sold_out(EE_Ticket $ticket)
356
-    {
357
-        if (self::debug) {
358
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
359
-            echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
360
-        }
361
-        $this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
362
-    }
363
-
364
-
365
-
366
-    /**
367
-     * adjusts quantities within the ticket selector based on decreased ticket availability
368
-     *
369
-     * @param    EE_Ticket $ticket
370
-     * @return void
371
-     * @throws UnexpectedEntityException
372
-     * @throws EE_Error
373
-     */
374
-    protected function _ticket_quantity_decremented(EE_Ticket $ticket)
375
-    {
376
-        if (self::debug) {
377
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
378
-            echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
379
-        }
380
-        $this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
381
-    }
382
-
383
-
384
-
385
-    /**
386
-     * builds string out of ticket and event name
387
-     *
388
-     * @param    EE_Ticket $ticket
389
-     * @return string
390
-     * @throws UnexpectedEntityException
391
-     * @throws EE_Error
392
-     */
393
-    protected function _get_ticket_and_event_name(EE_Ticket $ticket)
394
-    {
395
-        $event = $ticket->get_related_event();
396
-        if ($event instanceof EE_Event) {
397
-            $ticket_name = sprintf(
398
-                _x('%1$s for %2$s', 'ticket name for event name', 'event_espresso'),
399
-                $ticket->name(),
400
-                $event->name()
401
-            );
402
-        } else {
403
-            $ticket_name = $ticket->name();
404
-        }
405
-        return $ticket_name;
406
-    }
407
-
408
-
409
-
410
-    /********************************** EVENT CART  **********************************/
411
-
412
-
413
-
414
-    /**
415
-     * releases or reserves ticket(s) based on quantity passed
416
-     *
417
-     * @param  EE_Line_Item $line_item
418
-     * @param  int          $quantity
419
-     * @return void
420
-     * @throws EE_Error
421
-     * @throws InvalidArgumentException
422
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
423
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
424
-     */
425
-    public static function ticket_quantity_updated(EE_Line_Item $line_item, $quantity = 1)
426
-    {
427
-        $ticket = EEM_Ticket::instance()->get_one_by_ID(absint($line_item->OBJ_ID()));
428
-        if ($ticket instanceof EE_Ticket) {
429
-            if ($quantity > 0) {
430
-                EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
431
-            } else {
432
-                EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
433
-            }
434
-        }
435
-    }
436
-
437
-
438
-
439
-    /**
440
-     * releases reserved ticket(s) based on quantity passed
441
-     *
442
-     * @param  EE_Ticket $ticket
443
-     * @param  int       $quantity
444
-     * @return void
445
-     * @throws EE_Error
446
-     */
447
-    public static function ticket_removed_from_cart(EE_Ticket $ticket, $quantity = 1)
448
-    {
449
-        EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
450
-    }
451
-
452
-
453
-
454
-    /********************************** POST_NOTICES  **********************************/
455
-
456
-
457
-
458
-    /**
459
-     * @return void
460
-     * @throws EE_Error
461
-     * @throws InvalidArgumentException
462
-     * @throws ReflectionException
463
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
464
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
465
-     */
466
-    public static function post_notices()
467
-    {
468
-        EED_Ticket_Sales_Monitor::instance()->_post_notices();
469
-    }
470
-
471
-
472
-
473
-    /**
474
-     * @return void
475
-     * @throws EE_Error
476
-     * @throws InvalidArgumentException
477
-     * @throws ReflectionException
478
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
479
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
480
-     */
481
-    protected function _post_notices()
482
-    {
483
-        if (self::debug) {
484
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
485
-        }
486
-        $refresh_msg    = '';
487
-        $none_added_msg = '';
488
-        if (defined('DOING_AJAX') && DOING_AJAX) {
489
-            $refresh_msg    = __(
490
-                'Please refresh the page to view updated ticket quantities.',
491
-                'event_espresso'
492
-            );
493
-            $none_added_msg = __('No tickets were added for the event.', 'event_espresso');
494
-        }
495
-        if (! empty($this->sold_out_tickets)) {
496
-            EE_Error::add_attention(
497
-                sprintf(
498
-                    apply_filters(
499
-                        'FHEE__EED_Ticket_Sales_Monitor___post_notices__sold_out_tickets_notice',
500
-                        __(
501
-                            'We\'re sorry...%1$sThe following items have sold out since you first viewed this page, and can no longer be registered for:%1$s%1$s%2$s%1$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.%1$s%1$s%3$s%1$s%4$s%1$s',
502
-                            'event_espresso'
503
-                        )
504
-                    ),
505
-                    '<br />',
506
-                    implode('<br />', $this->sold_out_tickets),
507
-                    $none_added_msg,
508
-                    $refresh_msg
509
-                )
510
-            );
511
-            // alter code flow in the Ticket Selector for better UX
512
-            add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', '__return_true');
513
-            add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__success', '__return_false');
514
-            $this->sold_out_tickets = array();
515
-            // and reset the cart
516
-            EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
517
-        }
518
-        if (! empty($this->decremented_tickets)) {
519
-            EE_Error::add_attention(
520
-                sprintf(
521
-                    apply_filters(
522
-                        'FHEE__EED_Ticket_Sales_Monitor___ticket_quantity_decremented__notice',
523
-                        __(
524
-                            'We\'re sorry...%1$sDue to sales that have occurred since you first viewed the last page, the following items have had their quantities adjusted to match the current available amount:%1$s%1$s%2$s%1$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.%1$s%1$s%3$s%1$s%4$s%1$s',
525
-                            'event_espresso'
526
-                        )
527
-                    ),
528
-                    '<br />',
529
-                    implode('<br />', $this->decremented_tickets),
530
-                    $none_added_msg,
531
-                    $refresh_msg
532
-                )
533
-            );
534
-            $this->decremented_tickets = array();
535
-        }
536
-    }
537
-
538
-
539
-
540
-    /********************************** RELEASE_ALL_RESERVED_TICKETS_FOR_TRANSACTION  **********************************/
541
-
542
-
543
-
544
-    /**
545
-     * releases reserved tickets for all registrations of an EE_Transaction
546
-     * by default, will NOT release tickets for finalized transactions
547
-     *
548
-     * @param    EE_Transaction $transaction
549
-     * @return int
550
-     * @throws EE_Error
551
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
552
-     */
553
-    protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
554
-    {
555
-        if (self::debug) {
556
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
557
-            echo '<br /> . transaction->ID: ' . $transaction->ID();
558
-        }
559
-        // check if 'finalize_registration' step has been completed...
560
-        $finalized = $transaction->reg_step_completed('finalize_registration');
561
-        if (self::debug) {
562
-            // DEBUG LOG
563
-            EEH_Debug_Tools::log(
564
-                __CLASS__,
565
-                __FUNCTION__,
566
-                __LINE__,
567
-                array('finalized' => $finalized),
568
-                false,
569
-                'EE_Transaction: ' . $transaction->ID()
570
-            );
571
-        }
572
-        // how many tickets were released
573
-        $count = 0;
574
-        if (self::debug) {
575
-            echo '<br /> . . . finalized: ' . $finalized;
576
-        }
577
-        $release_tickets_with_TXN_status = array(
578
-            EEM_Transaction::failed_status_code,
579
-            EEM_Transaction::abandoned_status_code,
580
-            EEM_Transaction::incomplete_status_code,
581
-        );
582
-        // if the session is getting cleared BEFORE the TXN has been finalized
583
-        if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
584
-            // let's cancel any reserved tickets
585
-            $registrations = $transaction->registrations();
586
-            if (! empty($registrations)) {
587
-                foreach ($registrations as $registration) {
588
-                    if ($registration instanceof EE_Registration) {
589
-                        $count += $this->_release_reserved_ticket_for_registration($registration, $transaction);
590
-                    }
591
-                }
592
-            }
593
-        }
594
-        return $count;
595
-    }
596
-
597
-
598
-
599
-    /**
600
-     * releases reserved tickets for an EE_Registration
601
-     * by default, will NOT release tickets for APPROVED registrations
602
-     *
603
-     * @param    EE_Registration $registration
604
-     * @param    EE_Transaction  $transaction
605
-     * @return    int
606
-     * @throws    EE_Error
607
-     */
608
-    protected function _release_reserved_ticket_for_registration(
609
-        EE_Registration $registration,
610
-        EE_Transaction $transaction
611
-    ) {
612
-        $STS_ID = $transaction->status_ID();
613
-        if (self::debug) {
614
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
615
-            echo '<br /> . . registration->ID: ' . $registration->ID();
616
-            echo '<br /> . . registration->status_ID: ' . $registration->status_ID();
617
-            echo '<br /> . . transaction->status_ID(): ' . $STS_ID;
618
-        }
619
-        if (
620
-            // release Tickets for Failed Transactions and Abandoned Transactions
621
-            $STS_ID === EEM_Transaction::failed_status_code
622
-            || $STS_ID === EEM_Transaction::abandoned_status_code
623
-            || (
624
-                // also release Tickets for Incomplete Transactions, but ONLY if the Registrations are NOT Approved
625
-                $STS_ID === EEM_Transaction::incomplete_status_code
626
-                && $registration->status_ID() !== EEM_Registration::status_id_approved
627
-            )
628
-        ) {
629
-            $ticket = $registration->ticket();
630
-            if ($ticket instanceof EE_Ticket) {
631
-                return $this->_release_reserved_ticket($ticket);
632
-            }
633
-        }
634
-        return 0;
635
-    }
636
-
637
-
638
-
639
-    /********************************** SESSION_CART_RESET  **********************************/
640
-
641
-
642
-
643
-    /**
644
-     * callback hooked into 'AHEE__EE_Session__reset_cart__before_reset'
645
-     *
646
-     * @param    EE_Session $session
647
-     * @return void
648
-     * @throws EE_Error
649
-     * @throws InvalidArgumentException
650
-     * @throws ReflectionException
651
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
652
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
653
-     */
654
-    public static function session_cart_reset(EE_Session $session)
655
-    {
656
-        if (self::debug) {
657
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
658
-        }
659
-        $cart = $session->cart();
660
-        if ($cart instanceof EE_Cart) {
661
-            if (self::debug) {
662
-                echo '<br /><br /> cart instance of EE_Cart: ';
663
-            }
664
-            EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart);
665
-        } else {
666
-            if (self::debug) {
667
-                echo '<br /><br /> invalid EE_Cart: ';
668
-                var_export($cart, true);
669
-            }
670
-        }
671
-    }
672
-
673
-
674
-
675
-    /**
676
-     * releases reserved tickets in the EE_Cart
677
-     *
678
-     * @param    EE_Cart $cart
679
-     * @return void
680
-     * @throws EE_Error
681
-     * @throws InvalidArgumentException
682
-     * @throws ReflectionException
683
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
684
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
685
-     */
686
-    protected function _session_cart_reset(EE_Cart $cart)
687
-    {
688
-        if (self::debug) {
689
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
690
-        }
691
-        EE_Registry::instance()->load_helper('Line_Item');
692
-        $ticket_line_items = $cart->get_tickets();
693
-        if (empty($ticket_line_items)) {
694
-            return;
695
-        }
696
-        foreach ($ticket_line_items as $ticket_line_item) {
697
-            if (self::debug) {
698
-                echo '<br /> . ticket_line_item->ID(): ' . $ticket_line_item->ID();
699
-            }
700
-            if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
701
-                if (self::debug) {
702
-                    echo '<br /> . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
703
-                }
704
-                $ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
705
-                if ($ticket instanceof EE_Ticket) {
706
-                    if (self::debug) {
707
-                        echo '<br /> . . ticket->ID(): ' . $ticket->ID();
708
-                        echo '<br /> . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
709
-                    }
710
-                    $this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
711
-                }
712
-            }
713
-        }
714
-        if (self::debug) {
715
-            echo '<br /><br /> RESET COMPLETED ';
716
-        }
717
-    }
718
-
719
-
720
-
721
-    /********************************** SESSION_CHECKOUT_RESET  **********************************/
722
-
723
-
724
-
725
-    /**
726
-     * callback hooked into 'AHEE__EE_Session__reset_checkout__before_reset'
727
-     *
728
-     * @param    EE_Session $session
729
-     * @return void
730
-     * @throws EE_Error
731
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
732
-     */
733
-    public static function session_checkout_reset(EE_Session $session)
734
-    {
735
-        $checkout = $session->checkout();
736
-        if ($checkout instanceof EE_Checkout) {
737
-            EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
738
-        }
739
-    }
740
-
741
-
742
-
743
-    /**
744
-     * releases reserved tickets for the EE_Checkout->transaction
745
-     *
746
-     * @param    EE_Checkout $checkout
747
-     * @return void
748
-     * @throws EE_Error
749
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
750
-     */
751
-    protected function _session_checkout_reset(EE_Checkout $checkout)
752
-    {
753
-        if (self::debug) {
754
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
755
-        }
756
-        // we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
757
-        if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
758
-            return;
759
-        }
760
-        $this->_release_all_reserved_tickets_for_transaction($checkout->transaction);
761
-    }
762
-
763
-
764
-
765
-    /********************************** SESSION_EXPIRED_RESET  **********************************/
766
-
767
-
768
-
769
-    /**
770
-     * @param    EE_Session $session
771
-     * @return    void
772
-     */
773
-    public static function session_expired_reset(EE_Session $session)
774
-    {
775
-    }
776
-
777
-
778
-
779
-    /********************************** PROCESS_ABANDONED_TRANSACTIONS  **********************************/
780
-
781
-
782
-
783
-    /**
784
-     * releases reserved tickets for all registrations of an ABANDONED EE_Transaction
785
-     * by default, will NOT release tickets for free transactions, or any that have received a payment
786
-     *
787
-     * @param    EE_Transaction $transaction
788
-     * @return void
789
-     * @throws EE_Error
790
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
791
-     */
792
-    public static function process_abandoned_transactions(EE_Transaction $transaction)
793
-    {
794
-        // is this TXN free or has any money been paid towards this TXN? If so, then leave it alone
795
-        if ($transaction->is_free() || $transaction->paid() > 0) {
796
-            if (self::debug) {
797
-                // DEBUG LOG
798
-                EEH_Debug_Tools::log(
799
-                    __CLASS__,
800
-                    __FUNCTION__,
801
-                    __LINE__,
802
-                    array($transaction),
803
-                    false,
804
-                    'EE_Transaction: ' . $transaction->ID()
805
-                );
806
-            }
807
-            return;
808
-        }
809
-        // have their been any successful payments made ?
810
-        $payments = $transaction->payments();
811
-        foreach ($payments as $payment) {
812
-            if ($payment instanceof EE_Payment && $payment->status() === EEM_Payment::status_id_approved) {
813
-                if (self::debug) {
814
-                    // DEBUG LOG
815
-                    EEH_Debug_Tools::log(
816
-                        __CLASS__,
817
-                        __FUNCTION__,
818
-                        __LINE__,
819
-                        array($payment),
820
-                        false,
821
-                        'EE_Transaction: ' . $transaction->ID()
822
-                    );
823
-                }
824
-                return;
825
-            }
826
-        }
827
-        // since you haven't even attempted to pay for your ticket...
828
-        EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
829
-    }
830
-
831
-
832
-
833
-    /********************************** PROCESS_FAILED_TRANSACTIONS  **********************************/
834
-
835
-
836
-
837
-    /**
838
-     * releases reserved tickets for absolutely ALL registrations of a FAILED EE_Transaction
839
-     *
840
-     * @param    EE_Transaction $transaction
841
-     * @return void
842
-     * @throws EE_Error
843
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
844
-     */
845
-    public static function process_failed_transactions(EE_Transaction $transaction)
846
-    {
847
-        // since you haven't even attempted to pay for your ticket...
848
-        EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
849
-    }
850
-
851
-
852
-
853
-    /********************************** RESET RESERVATION COUNTS  *********************************/
854
-    /**
855
-     * Resets all ticket and datetime reserved counts to zero
856
-     * Tickets that are currently associated with a Transaction that is in progress
857
-     *
858
-     * @throws \EE_Error
859
-     * @throws \DomainException
860
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
861
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
862
-     * @throws \InvalidArgumentException
863
-     */
864
-    public static function reset_reservation_counts()
865
-    {
866
-        /** @var EE_Line_Item[] $valid_reserved_tickets */
867
-        $valid_reserved_tickets   = array();
868
-        $transactions_in_progress = EEM_Transaction::instance()->get_transactions_in_progress();
869
-        foreach ($transactions_in_progress as $transaction_in_progress) {
870
-            // if this TXN has been fully completed, then skip it
871
-            if ($transaction_in_progress->reg_step_completed('finalize_registration')) {
872
-                continue;
873
-            }
874
-            /** @var EE_Transaction $transaction_in_progress */
875
-            $total_line_item = $transaction_in_progress->total_line_item();
876
-            // $transaction_in_progress->line
877
-            if (! $total_line_item instanceof EE_Line_Item) {
878
-                throw new DomainException(
879
-                    esc_html__(
880
-                        'Transaction does not have a valid Total Line Item associated with it.',
881
-                        'event_espresso'
882
-                    )
883
-                );
884
-            }
885
-            $valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
886
-                $total_line_item
887
-            );
888
-        }
889
-        $total_line_items = EEM_Line_Item::instance()->get_total_line_items_for_active_carts();
890
-        foreach ($total_line_items as $total_line_item) {
891
-            $valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
892
-                $total_line_item
893
-            );
894
-        }
895
-        return EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
896
-            EEM_Ticket::instance()->get_tickets_with_reservations(),
897
-            $valid_reserved_tickets
898
-        );
899
-    }
900
-
901
-
902
-
903
-    /**
904
-     * @param EE_Line_Item $total_line_item
905
-     * @return EE_Line_Item[]
906
-     */
907
-    private static function get_ticket_line_items_for_grand_total(EE_Line_Item $total_line_item)
908
-    {
909
-        /** @var EE_Line_Item[] $valid_reserved_tickets */
910
-        $valid_reserved_tickets = array();
911
-        $ticket_line_items      = EEH_Line_Item::get_ticket_line_items($total_line_item);
912
-        foreach ($ticket_line_items as $ticket_line_item) {
913
-            if ($ticket_line_item instanceof EE_Line_Item) {
914
-                $valid_reserved_tickets[] = $ticket_line_item;
915
-            }
916
-        }
917
-        return $valid_reserved_tickets;
918
-    }
919
-
920
-
921
-
922
-    /**
923
-     * @param EE_Ticket[]    $tickets_with_reservations
924
-     * @param EE_Line_Item[] $valid_reserved_ticket_line_items
925
-     * @return int
926
-     * @throws \EE_Error
927
-     */
928
-    private static function release_reservations_for_tickets(
929
-        array $tickets_with_reservations,
930
-        $valid_reserved_ticket_line_items = array()
931
-    ) {
932
-        $total_tickets_released = 0;
933
-        foreach ($tickets_with_reservations as $ticket_with_reservations) {
934
-            if (! $ticket_with_reservations instanceof EE_Ticket) {
935
-                continue;
936
-            }
937
-            $reserved_qty = $ticket_with_reservations->reserved();
938
-            foreach ($valid_reserved_ticket_line_items as $valid_reserved_ticket_line_item) {
939
-                if (
940
-                    $valid_reserved_ticket_line_item instanceof EE_Line_Item
941
-                    && $valid_reserved_ticket_line_item->OBJ_ID() === $ticket_with_reservations->ID()
942
-                ) {
943
-                    $reserved_qty -= $valid_reserved_ticket_line_item->quantity();
944
-                }
945
-            }
946
-            if ($reserved_qty > 0) {
947
-                $ticket_with_reservations->decrease_reserved($reserved_qty);
948
-                $ticket_with_reservations->save();
949
-                $total_tickets_released += $reserved_qty;
950
-            }
951
-        }
952
-        return $total_tickets_released;
953
-    }
954
-
955
-
956
-
957
-    /********************************** SHUTDOWN  **********************************/
958
-
959
-
960
-
961
-    /**
962
-     * @return false|int
963
-     * @throws EE_Error
964
-     * @throws InvalidArgumentException
965
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
966
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
967
-     */
968
-    public static function clear_expired_line_items_with_no_transaction()
969
-    {
970
-        /** @type WPDB $wpdb */
971
-        global $wpdb;
972
-        return $wpdb->query(
973
-            $wpdb->prepare(
974
-                'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
25
+	const debug = false;    //	true false
26
+
27
+	/**
28
+	 * an array of raw ticket data from EED_Ticket_Selector
29
+	 *
30
+	 * @var array $ticket_selections
31
+	 */
32
+	protected $ticket_selections = array();
33
+
34
+	/**
35
+	 * the raw ticket data from EED_Ticket_Selector is organized in rows
36
+	 * according to how they are displayed in the actual Ticket_Selector
37
+	 * this tracks the current row being processed
38
+	 *
39
+	 * @var int $current_row
40
+	 */
41
+	protected $current_row = 0;
42
+
43
+	/**
44
+	 * an array for tracking names of tickets that have sold out
45
+	 *
46
+	 * @var array $sold_out_tickets
47
+	 */
48
+	protected $sold_out_tickets = array();
49
+
50
+	/**
51
+	 * an array for tracking names of tickets that have had their quantities reduced
52
+	 *
53
+	 * @var array $decremented_tickets
54
+	 */
55
+	protected $decremented_tickets = array();
56
+
57
+
58
+
59
+	/**
60
+	 * set_hooks - for hooking into EE Core, other modules, etc
61
+	 *
62
+	 * @return    void
63
+	 */
64
+	public static function set_hooks()
65
+	{
66
+		// release tickets for expired carts
67
+		add_action(
68
+			'EED_Ticket_Selector__process_ticket_selections__before',
69
+			array('EED_Ticket_Sales_Monitor', 'release_tickets_for_expired_carts'),
70
+			1
71
+		);
72
+		// check ticket reserves AFTER MER does it's check (hence priority 20)
73
+		add_filter(
74
+			'FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty',
75
+			array('EED_Ticket_Sales_Monitor', 'validate_ticket_sale'),
76
+			20,
77
+			3
78
+		);
79
+		// add notices for sold out tickets
80
+		add_action(
81
+			'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
82
+			array('EED_Ticket_Sales_Monitor', 'post_notices'),
83
+			10
84
+		);
85
+		// handle ticket quantities adjusted in cart
86
+		//add_action(
87
+		//	'FHEE__EED_Multi_Event_Registration__adjust_line_item_quantity__line_item_quantity_updated',
88
+		//	array( 'EED_Ticket_Sales_Monitor', 'ticket_quantity_updated' ),
89
+		//	10, 2
90
+		//);
91
+		// handle tickets deleted from cart
92
+		add_action(
93
+			'FHEE__EED_Multi_Event_Registration__delete_ticket__ticket_removed_from_cart',
94
+			array('EED_Ticket_Sales_Monitor', 'ticket_removed_from_cart'),
95
+			10,
96
+			2
97
+		);
98
+		// handle emptied carts
99
+		add_action(
100
+			'AHEE__EE_Session__reset_cart__before_reset',
101
+			array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
102
+			10,
103
+			1
104
+		);
105
+		add_action(
106
+			'AHEE__EED_Multi_Event_Registration__empty_event_cart__before_delete_cart',
107
+			array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
108
+			10,
109
+			1
110
+		);
111
+		// handle cancelled registrations
112
+		add_action(
113
+			'AHEE__EE_Session__reset_checkout__before_reset',
114
+			array('EED_Ticket_Sales_Monitor', 'session_checkout_reset'),
115
+			10,
116
+			1
117
+		);
118
+		// cron tasks
119
+		add_action(
120
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
121
+			array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
122
+			10,
123
+			1
124
+		);
125
+		add_action(
126
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
127
+			array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
128
+			10,
129
+			1
130
+		);
131
+		add_action(
132
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
133
+			array('EED_Ticket_Sales_Monitor', 'process_failed_transactions'),
134
+			10,
135
+			1
136
+		);
137
+	}
138
+
139
+
140
+
141
+	/**
142
+	 * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
143
+	 *
144
+	 * @return void
145
+	 */
146
+	public static function set_hooks_admin()
147
+	{
148
+		EED_Ticket_Sales_Monitor::set_hooks();
149
+	}
150
+
151
+
152
+
153
+	/**
154
+	 * @return EED_Ticket_Sales_Monitor|EED_Module
155
+	 */
156
+	public static function instance()
157
+	{
158
+		return parent::get_instance(__CLASS__);
159
+	}
160
+
161
+
162
+
163
+	/**
164
+	 * @param WP_Query $WP_Query
165
+	 * @return    void
166
+	 */
167
+	public function run($WP_Query)
168
+	{
169
+	}
170
+
171
+
172
+
173
+	/********************************** PRE_TICKET_SALES  **********************************/
174
+
175
+
176
+
177
+	/**
178
+	 * Retrieves grand totals from the line items that have no TXN ID
179
+	 * and timestamps less than the current time minus the session lifespan.
180
+	 * These are carts that have been abandoned before the "registrant" even attempted to checkout.
181
+	 * We're going to release the tickets for these line items before attempting to add more to the cart.
182
+	 *
183
+	 * @return void
184
+	 * @throws EE_Error
185
+	 * @throws InvalidArgumentException
186
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
187
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
188
+	 */
189
+	public static function release_tickets_for_expired_carts()
190
+	{
191
+		$expired_ticket_IDs      = array();
192
+		$valid_ticket_line_items = array();
193
+		$total_line_items        = EEM_Line_Item::instance()->get_total_line_items_with_no_transaction();
194
+		if (empty($total_line_items)) {
195
+			return;
196
+		}
197
+		$expired = current_time('timestamp') - EE_Registry::instance()->SSN->lifespan();
198
+		foreach ($total_line_items as $total_line_item) {
199
+			/** @var EE_Line_Item $total_line_item */
200
+			$ticket_line_items = EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total($total_line_item);
201
+			foreach ($ticket_line_items as $ticket_line_item) {
202
+				if (! $ticket_line_item instanceof EE_Line_Item) {
203
+					continue;
204
+				}
205
+				if ($total_line_item->timestamp(true) <= $expired) {
206
+					$expired_ticket_IDs[$ticket_line_item->OBJ_ID()] = $ticket_line_item->OBJ_ID();
207
+				} else {
208
+					$valid_ticket_line_items[$ticket_line_item->OBJ_ID()] = $ticket_line_item;
209
+				}
210
+			}
211
+		}
212
+		if (! empty($expired_ticket_IDs)) {
213
+			EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
214
+				\EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
215
+				$valid_ticket_line_items
216
+			);
217
+			// let's get rid of expired line items so that they can't interfere with tracking
218
+			add_action(
219
+				'shutdown',
220
+				array('EED_Ticket_Sales_Monitor', 'clear_expired_line_items_with_no_transaction'),
221
+				999
222
+			);
223
+		}
224
+	}
225
+
226
+
227
+
228
+	/********************************** VALIDATE_TICKET_SALE  **********************************/
229
+
230
+
231
+
232
+	/**
233
+	 * callback for 'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data'
234
+	 *
235
+	 * @param int       $qty
236
+	 * @param EE_Ticket $ticket
237
+	 * @return bool
238
+	 * @throws UnexpectedEntityException
239
+	 * @throws EE_Error
240
+	 */
241
+	public static function validate_ticket_sale($qty = 1, EE_Ticket $ticket)
242
+	{
243
+		$qty = absint($qty);
244
+		if ($qty > 0) {
245
+			$qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
246
+		}
247
+		if (self::debug) {
248
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '()';
249
+			echo '<br /><br /><b> RETURNED QTY: ' . $qty . '</b>';
250
+		}
251
+		return $qty;
252
+	}
253
+
254
+
255
+
256
+	/**
257
+	 * checks whether an individual ticket is available for purchase based on datetime, and ticket details
258
+	 *
259
+	 * @param   EE_Ticket $ticket
260
+	 * @param int         $qty
261
+	 * @return int
262
+	 * @throws UnexpectedEntityException
263
+	 * @throws EE_Error
264
+	 */
265
+	protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
266
+	{
267
+		if (self::debug) {
268
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
269
+		}
270
+		if (! $ticket instanceof EE_Ticket) {
271
+			return 0;
272
+		}
273
+		if (self::debug) {
274
+			echo '<br /><b> . ticket->ID: ' . $ticket->ID() . '</b>';
275
+			echo '<br /> . original ticket->reserved: ' . $ticket->reserved();
276
+		}
277
+		$ticket->refresh_from_db();
278
+		// first let's determine the ticket availability based on sales
279
+		$available = $ticket->qty('saleable');
280
+		if (self::debug) {
281
+			echo '<br /> . . . ticket->qty: ' . $ticket->qty();
282
+			echo '<br /> . . . ticket->sold: ' . $ticket->sold();
283
+			echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
284
+			echo '<br /> . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
285
+			echo '<br /> . . . available: ' . $available;
286
+		}
287
+		if ($available < 1) {
288
+			$this->_ticket_sold_out($ticket);
289
+			return 0;
290
+		}
291
+		if (self::debug) {
292
+			echo '<br /> . . . qty: ' . $qty;
293
+		}
294
+		if ($available < $qty) {
295
+			$qty = $available;
296
+			if (self::debug) {
297
+				echo '<br /> . . . QTY ADJUSTED: ' . $qty;
298
+			}
299
+			$this->_ticket_quantity_decremented($ticket);
300
+		}
301
+		$this->_reserve_ticket($ticket, $qty);
302
+		return $qty;
303
+	}
304
+
305
+
306
+
307
+	/**
308
+	 * increments ticket reserved based on quantity passed
309
+	 *
310
+	 * @param    EE_Ticket $ticket
311
+	 * @param int          $quantity
312
+	 * @return bool
313
+	 * @throws EE_Error
314
+	 */
315
+	protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
316
+	{
317
+		if (self::debug) {
318
+			echo '<br /><br /> . . . INCREASE RESERVED: ' . $quantity;
319
+		}
320
+		$ticket->increase_reserved($quantity);
321
+		return $ticket->save();
322
+	}
323
+
324
+
325
+
326
+	/**
327
+	 * @param  EE_Ticket $ticket
328
+	 * @param  int       $quantity
329
+	 * @return bool
330
+	 * @throws EE_Error
331
+	 */
332
+	protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
333
+	{
334
+		if (self::debug) {
335
+			echo '<br /> . . . ticket->ID: ' . $ticket->ID();
336
+			echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
337
+		}
338
+		$ticket->decrease_reserved($quantity);
339
+		if (self::debug) {
340
+			echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
341
+		}
342
+		return $ticket->save() ? 1 : 0;
343
+	}
344
+
345
+
346
+
347
+	/**
348
+	 * removes quantities within the ticket selector based on zero ticket availability
349
+	 *
350
+	 * @param    EE_Ticket $ticket
351
+	 * @return    void
352
+	 * @throws UnexpectedEntityException
353
+	 * @throws EE_Error
354
+	 */
355
+	protected function _ticket_sold_out(EE_Ticket $ticket)
356
+	{
357
+		if (self::debug) {
358
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
359
+			echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
360
+		}
361
+		$this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
362
+	}
363
+
364
+
365
+
366
+	/**
367
+	 * adjusts quantities within the ticket selector based on decreased ticket availability
368
+	 *
369
+	 * @param    EE_Ticket $ticket
370
+	 * @return void
371
+	 * @throws UnexpectedEntityException
372
+	 * @throws EE_Error
373
+	 */
374
+	protected function _ticket_quantity_decremented(EE_Ticket $ticket)
375
+	{
376
+		if (self::debug) {
377
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
378
+			echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
379
+		}
380
+		$this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
381
+	}
382
+
383
+
384
+
385
+	/**
386
+	 * builds string out of ticket and event name
387
+	 *
388
+	 * @param    EE_Ticket $ticket
389
+	 * @return string
390
+	 * @throws UnexpectedEntityException
391
+	 * @throws EE_Error
392
+	 */
393
+	protected function _get_ticket_and_event_name(EE_Ticket $ticket)
394
+	{
395
+		$event = $ticket->get_related_event();
396
+		if ($event instanceof EE_Event) {
397
+			$ticket_name = sprintf(
398
+				_x('%1$s for %2$s', 'ticket name for event name', 'event_espresso'),
399
+				$ticket->name(),
400
+				$event->name()
401
+			);
402
+		} else {
403
+			$ticket_name = $ticket->name();
404
+		}
405
+		return $ticket_name;
406
+	}
407
+
408
+
409
+
410
+	/********************************** EVENT CART  **********************************/
411
+
412
+
413
+
414
+	/**
415
+	 * releases or reserves ticket(s) based on quantity passed
416
+	 *
417
+	 * @param  EE_Line_Item $line_item
418
+	 * @param  int          $quantity
419
+	 * @return void
420
+	 * @throws EE_Error
421
+	 * @throws InvalidArgumentException
422
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
423
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
424
+	 */
425
+	public static function ticket_quantity_updated(EE_Line_Item $line_item, $quantity = 1)
426
+	{
427
+		$ticket = EEM_Ticket::instance()->get_one_by_ID(absint($line_item->OBJ_ID()));
428
+		if ($ticket instanceof EE_Ticket) {
429
+			if ($quantity > 0) {
430
+				EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
431
+			} else {
432
+				EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
433
+			}
434
+		}
435
+	}
436
+
437
+
438
+
439
+	/**
440
+	 * releases reserved ticket(s) based on quantity passed
441
+	 *
442
+	 * @param  EE_Ticket $ticket
443
+	 * @param  int       $quantity
444
+	 * @return void
445
+	 * @throws EE_Error
446
+	 */
447
+	public static function ticket_removed_from_cart(EE_Ticket $ticket, $quantity = 1)
448
+	{
449
+		EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
450
+	}
451
+
452
+
453
+
454
+	/********************************** POST_NOTICES  **********************************/
455
+
456
+
457
+
458
+	/**
459
+	 * @return void
460
+	 * @throws EE_Error
461
+	 * @throws InvalidArgumentException
462
+	 * @throws ReflectionException
463
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
464
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
465
+	 */
466
+	public static function post_notices()
467
+	{
468
+		EED_Ticket_Sales_Monitor::instance()->_post_notices();
469
+	}
470
+
471
+
472
+
473
+	/**
474
+	 * @return void
475
+	 * @throws EE_Error
476
+	 * @throws InvalidArgumentException
477
+	 * @throws ReflectionException
478
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
479
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
480
+	 */
481
+	protected function _post_notices()
482
+	{
483
+		if (self::debug) {
484
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
485
+		}
486
+		$refresh_msg    = '';
487
+		$none_added_msg = '';
488
+		if (defined('DOING_AJAX') && DOING_AJAX) {
489
+			$refresh_msg    = __(
490
+				'Please refresh the page to view updated ticket quantities.',
491
+				'event_espresso'
492
+			);
493
+			$none_added_msg = __('No tickets were added for the event.', 'event_espresso');
494
+		}
495
+		if (! empty($this->sold_out_tickets)) {
496
+			EE_Error::add_attention(
497
+				sprintf(
498
+					apply_filters(
499
+						'FHEE__EED_Ticket_Sales_Monitor___post_notices__sold_out_tickets_notice',
500
+						__(
501
+							'We\'re sorry...%1$sThe following items have sold out since you first viewed this page, and can no longer be registered for:%1$s%1$s%2$s%1$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.%1$s%1$s%3$s%1$s%4$s%1$s',
502
+							'event_espresso'
503
+						)
504
+					),
505
+					'<br />',
506
+					implode('<br />', $this->sold_out_tickets),
507
+					$none_added_msg,
508
+					$refresh_msg
509
+				)
510
+			);
511
+			// alter code flow in the Ticket Selector for better UX
512
+			add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', '__return_true');
513
+			add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__success', '__return_false');
514
+			$this->sold_out_tickets = array();
515
+			// and reset the cart
516
+			EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
517
+		}
518
+		if (! empty($this->decremented_tickets)) {
519
+			EE_Error::add_attention(
520
+				sprintf(
521
+					apply_filters(
522
+						'FHEE__EED_Ticket_Sales_Monitor___ticket_quantity_decremented__notice',
523
+						__(
524
+							'We\'re sorry...%1$sDue to sales that have occurred since you first viewed the last page, the following items have had their quantities adjusted to match the current available amount:%1$s%1$s%2$s%1$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.%1$s%1$s%3$s%1$s%4$s%1$s',
525
+							'event_espresso'
526
+						)
527
+					),
528
+					'<br />',
529
+					implode('<br />', $this->decremented_tickets),
530
+					$none_added_msg,
531
+					$refresh_msg
532
+				)
533
+			);
534
+			$this->decremented_tickets = array();
535
+		}
536
+	}
537
+
538
+
539
+
540
+	/********************************** RELEASE_ALL_RESERVED_TICKETS_FOR_TRANSACTION  **********************************/
541
+
542
+
543
+
544
+	/**
545
+	 * releases reserved tickets for all registrations of an EE_Transaction
546
+	 * by default, will NOT release tickets for finalized transactions
547
+	 *
548
+	 * @param    EE_Transaction $transaction
549
+	 * @return int
550
+	 * @throws EE_Error
551
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
552
+	 */
553
+	protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
554
+	{
555
+		if (self::debug) {
556
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
557
+			echo '<br /> . transaction->ID: ' . $transaction->ID();
558
+		}
559
+		// check if 'finalize_registration' step has been completed...
560
+		$finalized = $transaction->reg_step_completed('finalize_registration');
561
+		if (self::debug) {
562
+			// DEBUG LOG
563
+			EEH_Debug_Tools::log(
564
+				__CLASS__,
565
+				__FUNCTION__,
566
+				__LINE__,
567
+				array('finalized' => $finalized),
568
+				false,
569
+				'EE_Transaction: ' . $transaction->ID()
570
+			);
571
+		}
572
+		// how many tickets were released
573
+		$count = 0;
574
+		if (self::debug) {
575
+			echo '<br /> . . . finalized: ' . $finalized;
576
+		}
577
+		$release_tickets_with_TXN_status = array(
578
+			EEM_Transaction::failed_status_code,
579
+			EEM_Transaction::abandoned_status_code,
580
+			EEM_Transaction::incomplete_status_code,
581
+		);
582
+		// if the session is getting cleared BEFORE the TXN has been finalized
583
+		if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
584
+			// let's cancel any reserved tickets
585
+			$registrations = $transaction->registrations();
586
+			if (! empty($registrations)) {
587
+				foreach ($registrations as $registration) {
588
+					if ($registration instanceof EE_Registration) {
589
+						$count += $this->_release_reserved_ticket_for_registration($registration, $transaction);
590
+					}
591
+				}
592
+			}
593
+		}
594
+		return $count;
595
+	}
596
+
597
+
598
+
599
+	/**
600
+	 * releases reserved tickets for an EE_Registration
601
+	 * by default, will NOT release tickets for APPROVED registrations
602
+	 *
603
+	 * @param    EE_Registration $registration
604
+	 * @param    EE_Transaction  $transaction
605
+	 * @return    int
606
+	 * @throws    EE_Error
607
+	 */
608
+	protected function _release_reserved_ticket_for_registration(
609
+		EE_Registration $registration,
610
+		EE_Transaction $transaction
611
+	) {
612
+		$STS_ID = $transaction->status_ID();
613
+		if (self::debug) {
614
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
615
+			echo '<br /> . . registration->ID: ' . $registration->ID();
616
+			echo '<br /> . . registration->status_ID: ' . $registration->status_ID();
617
+			echo '<br /> . . transaction->status_ID(): ' . $STS_ID;
618
+		}
619
+		if (
620
+			// release Tickets for Failed Transactions and Abandoned Transactions
621
+			$STS_ID === EEM_Transaction::failed_status_code
622
+			|| $STS_ID === EEM_Transaction::abandoned_status_code
623
+			|| (
624
+				// also release Tickets for Incomplete Transactions, but ONLY if the Registrations are NOT Approved
625
+				$STS_ID === EEM_Transaction::incomplete_status_code
626
+				&& $registration->status_ID() !== EEM_Registration::status_id_approved
627
+			)
628
+		) {
629
+			$ticket = $registration->ticket();
630
+			if ($ticket instanceof EE_Ticket) {
631
+				return $this->_release_reserved_ticket($ticket);
632
+			}
633
+		}
634
+		return 0;
635
+	}
636
+
637
+
638
+
639
+	/********************************** SESSION_CART_RESET  **********************************/
640
+
641
+
642
+
643
+	/**
644
+	 * callback hooked into 'AHEE__EE_Session__reset_cart__before_reset'
645
+	 *
646
+	 * @param    EE_Session $session
647
+	 * @return void
648
+	 * @throws EE_Error
649
+	 * @throws InvalidArgumentException
650
+	 * @throws ReflectionException
651
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
652
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
653
+	 */
654
+	public static function session_cart_reset(EE_Session $session)
655
+	{
656
+		if (self::debug) {
657
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
658
+		}
659
+		$cart = $session->cart();
660
+		if ($cart instanceof EE_Cart) {
661
+			if (self::debug) {
662
+				echo '<br /><br /> cart instance of EE_Cart: ';
663
+			}
664
+			EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart);
665
+		} else {
666
+			if (self::debug) {
667
+				echo '<br /><br /> invalid EE_Cart: ';
668
+				var_export($cart, true);
669
+			}
670
+		}
671
+	}
672
+
673
+
674
+
675
+	/**
676
+	 * releases reserved tickets in the EE_Cart
677
+	 *
678
+	 * @param    EE_Cart $cart
679
+	 * @return void
680
+	 * @throws EE_Error
681
+	 * @throws InvalidArgumentException
682
+	 * @throws ReflectionException
683
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
684
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
685
+	 */
686
+	protected function _session_cart_reset(EE_Cart $cart)
687
+	{
688
+		if (self::debug) {
689
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
690
+		}
691
+		EE_Registry::instance()->load_helper('Line_Item');
692
+		$ticket_line_items = $cart->get_tickets();
693
+		if (empty($ticket_line_items)) {
694
+			return;
695
+		}
696
+		foreach ($ticket_line_items as $ticket_line_item) {
697
+			if (self::debug) {
698
+				echo '<br /> . ticket_line_item->ID(): ' . $ticket_line_item->ID();
699
+			}
700
+			if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
701
+				if (self::debug) {
702
+					echo '<br /> . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
703
+				}
704
+				$ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
705
+				if ($ticket instanceof EE_Ticket) {
706
+					if (self::debug) {
707
+						echo '<br /> . . ticket->ID(): ' . $ticket->ID();
708
+						echo '<br /> . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
709
+					}
710
+					$this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
711
+				}
712
+			}
713
+		}
714
+		if (self::debug) {
715
+			echo '<br /><br /> RESET COMPLETED ';
716
+		}
717
+	}
718
+
719
+
720
+
721
+	/********************************** SESSION_CHECKOUT_RESET  **********************************/
722
+
723
+
724
+
725
+	/**
726
+	 * callback hooked into 'AHEE__EE_Session__reset_checkout__before_reset'
727
+	 *
728
+	 * @param    EE_Session $session
729
+	 * @return void
730
+	 * @throws EE_Error
731
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
732
+	 */
733
+	public static function session_checkout_reset(EE_Session $session)
734
+	{
735
+		$checkout = $session->checkout();
736
+		if ($checkout instanceof EE_Checkout) {
737
+			EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
738
+		}
739
+	}
740
+
741
+
742
+
743
+	/**
744
+	 * releases reserved tickets for the EE_Checkout->transaction
745
+	 *
746
+	 * @param    EE_Checkout $checkout
747
+	 * @return void
748
+	 * @throws EE_Error
749
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
750
+	 */
751
+	protected function _session_checkout_reset(EE_Checkout $checkout)
752
+	{
753
+		if (self::debug) {
754
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
755
+		}
756
+		// we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
757
+		if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
758
+			return;
759
+		}
760
+		$this->_release_all_reserved_tickets_for_transaction($checkout->transaction);
761
+	}
762
+
763
+
764
+
765
+	/********************************** SESSION_EXPIRED_RESET  **********************************/
766
+
767
+
768
+
769
+	/**
770
+	 * @param    EE_Session $session
771
+	 * @return    void
772
+	 */
773
+	public static function session_expired_reset(EE_Session $session)
774
+	{
775
+	}
776
+
777
+
778
+
779
+	/********************************** PROCESS_ABANDONED_TRANSACTIONS  **********************************/
780
+
781
+
782
+
783
+	/**
784
+	 * releases reserved tickets for all registrations of an ABANDONED EE_Transaction
785
+	 * by default, will NOT release tickets for free transactions, or any that have received a payment
786
+	 *
787
+	 * @param    EE_Transaction $transaction
788
+	 * @return void
789
+	 * @throws EE_Error
790
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
791
+	 */
792
+	public static function process_abandoned_transactions(EE_Transaction $transaction)
793
+	{
794
+		// is this TXN free or has any money been paid towards this TXN? If so, then leave it alone
795
+		if ($transaction->is_free() || $transaction->paid() > 0) {
796
+			if (self::debug) {
797
+				// DEBUG LOG
798
+				EEH_Debug_Tools::log(
799
+					__CLASS__,
800
+					__FUNCTION__,
801
+					__LINE__,
802
+					array($transaction),
803
+					false,
804
+					'EE_Transaction: ' . $transaction->ID()
805
+				);
806
+			}
807
+			return;
808
+		}
809
+		// have their been any successful payments made ?
810
+		$payments = $transaction->payments();
811
+		foreach ($payments as $payment) {
812
+			if ($payment instanceof EE_Payment && $payment->status() === EEM_Payment::status_id_approved) {
813
+				if (self::debug) {
814
+					// DEBUG LOG
815
+					EEH_Debug_Tools::log(
816
+						__CLASS__,
817
+						__FUNCTION__,
818
+						__LINE__,
819
+						array($payment),
820
+						false,
821
+						'EE_Transaction: ' . $transaction->ID()
822
+					);
823
+				}
824
+				return;
825
+			}
826
+		}
827
+		// since you haven't even attempted to pay for your ticket...
828
+		EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
829
+	}
830
+
831
+
832
+
833
+	/********************************** PROCESS_FAILED_TRANSACTIONS  **********************************/
834
+
835
+
836
+
837
+	/**
838
+	 * releases reserved tickets for absolutely ALL registrations of a FAILED EE_Transaction
839
+	 *
840
+	 * @param    EE_Transaction $transaction
841
+	 * @return void
842
+	 * @throws EE_Error
843
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
844
+	 */
845
+	public static function process_failed_transactions(EE_Transaction $transaction)
846
+	{
847
+		// since you haven't even attempted to pay for your ticket...
848
+		EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
849
+	}
850
+
851
+
852
+
853
+	/********************************** RESET RESERVATION COUNTS  *********************************/
854
+	/**
855
+	 * Resets all ticket and datetime reserved counts to zero
856
+	 * Tickets that are currently associated with a Transaction that is in progress
857
+	 *
858
+	 * @throws \EE_Error
859
+	 * @throws \DomainException
860
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
861
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
862
+	 * @throws \InvalidArgumentException
863
+	 */
864
+	public static function reset_reservation_counts()
865
+	{
866
+		/** @var EE_Line_Item[] $valid_reserved_tickets */
867
+		$valid_reserved_tickets   = array();
868
+		$transactions_in_progress = EEM_Transaction::instance()->get_transactions_in_progress();
869
+		foreach ($transactions_in_progress as $transaction_in_progress) {
870
+			// if this TXN has been fully completed, then skip it
871
+			if ($transaction_in_progress->reg_step_completed('finalize_registration')) {
872
+				continue;
873
+			}
874
+			/** @var EE_Transaction $transaction_in_progress */
875
+			$total_line_item = $transaction_in_progress->total_line_item();
876
+			// $transaction_in_progress->line
877
+			if (! $total_line_item instanceof EE_Line_Item) {
878
+				throw new DomainException(
879
+					esc_html__(
880
+						'Transaction does not have a valid Total Line Item associated with it.',
881
+						'event_espresso'
882
+					)
883
+				);
884
+			}
885
+			$valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
886
+				$total_line_item
887
+			);
888
+		}
889
+		$total_line_items = EEM_Line_Item::instance()->get_total_line_items_for_active_carts();
890
+		foreach ($total_line_items as $total_line_item) {
891
+			$valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
892
+				$total_line_item
893
+			);
894
+		}
895
+		return EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
896
+			EEM_Ticket::instance()->get_tickets_with_reservations(),
897
+			$valid_reserved_tickets
898
+		);
899
+	}
900
+
901
+
902
+
903
+	/**
904
+	 * @param EE_Line_Item $total_line_item
905
+	 * @return EE_Line_Item[]
906
+	 */
907
+	private static function get_ticket_line_items_for_grand_total(EE_Line_Item $total_line_item)
908
+	{
909
+		/** @var EE_Line_Item[] $valid_reserved_tickets */
910
+		$valid_reserved_tickets = array();
911
+		$ticket_line_items      = EEH_Line_Item::get_ticket_line_items($total_line_item);
912
+		foreach ($ticket_line_items as $ticket_line_item) {
913
+			if ($ticket_line_item instanceof EE_Line_Item) {
914
+				$valid_reserved_tickets[] = $ticket_line_item;
915
+			}
916
+		}
917
+		return $valid_reserved_tickets;
918
+	}
919
+
920
+
921
+
922
+	/**
923
+	 * @param EE_Ticket[]    $tickets_with_reservations
924
+	 * @param EE_Line_Item[] $valid_reserved_ticket_line_items
925
+	 * @return int
926
+	 * @throws \EE_Error
927
+	 */
928
+	private static function release_reservations_for_tickets(
929
+		array $tickets_with_reservations,
930
+		$valid_reserved_ticket_line_items = array()
931
+	) {
932
+		$total_tickets_released = 0;
933
+		foreach ($tickets_with_reservations as $ticket_with_reservations) {
934
+			if (! $ticket_with_reservations instanceof EE_Ticket) {
935
+				continue;
936
+			}
937
+			$reserved_qty = $ticket_with_reservations->reserved();
938
+			foreach ($valid_reserved_ticket_line_items as $valid_reserved_ticket_line_item) {
939
+				if (
940
+					$valid_reserved_ticket_line_item instanceof EE_Line_Item
941
+					&& $valid_reserved_ticket_line_item->OBJ_ID() === $ticket_with_reservations->ID()
942
+				) {
943
+					$reserved_qty -= $valid_reserved_ticket_line_item->quantity();
944
+				}
945
+			}
946
+			if ($reserved_qty > 0) {
947
+				$ticket_with_reservations->decrease_reserved($reserved_qty);
948
+				$ticket_with_reservations->save();
949
+				$total_tickets_released += $reserved_qty;
950
+			}
951
+		}
952
+		return $total_tickets_released;
953
+	}
954
+
955
+
956
+
957
+	/********************************** SHUTDOWN  **********************************/
958
+
959
+
960
+
961
+	/**
962
+	 * @return false|int
963
+	 * @throws EE_Error
964
+	 * @throws InvalidArgumentException
965
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
966
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
967
+	 */
968
+	public static function clear_expired_line_items_with_no_transaction()
969
+	{
970
+		/** @type WPDB $wpdb */
971
+		global $wpdb;
972
+		return $wpdb->query(
973
+			$wpdb->prepare(
974
+				'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
975 975
                 WHERE TXN_ID = 0 AND LIN_timestamp <= %s',
976
-                // use GMT time because that's what LIN_timestamps are in
977
-                date('Y-m-d H:i:s', time() - EE_Registry::instance()->SSN->lifespan())
978
-            )
979
-        );
980
-    }
976
+				// use GMT time because that's what LIN_timestamps are in
977
+				date('Y-m-d H:i:s', time() - EE_Registry::instance()->SSN->lifespan())
978
+			)
979
+		);
980
+	}
981 981
 
982 982
 }
983 983
 // End of file EED_Ticket_Sales_Monitor.module.php
Please login to merge, or discard this patch.
core/helpers/EEH_Export.helper.php 2 patches
Indentation   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -31,9 +31,9 @@  discard block
 block discarded – undo
31 31
 	 * @return string
32 32
 	 */
33 33
 	public static function get_column_name_for_field(EE_Model_Field_Base $field){
34
-	    return wp_specialchars_decode($field->get_nicename(), ENT_QUOTES)
35
-               . "[" . wp_specialchars_decode($field->get_name(), ENT_QUOTES)
36
-               . "]";
34
+		return wp_specialchars_decode($field->get_nicename(), ENT_QUOTES)
35
+			   . "[" . wp_specialchars_decode($field->get_name(), ENT_QUOTES)
36
+			   . "]";
37 37
 	}
38 38
 
39 39
 	/**
@@ -88,13 +88,13 @@  discard block
 block discarded – undo
88 88
 
89 89
 	 /**
90 90
 	  *
91
-	 *	Writes a row to the csv file
92
-	 *	@param array $row - individual row of csv data
93
-	 *	@param string $delimiter - csv delimiter
94
-	 *	@param string $enclosure - csv enclosure
95
-	 *	@param bool $mysql_null - allows php NULL to be overridden with MySQl's insertable NULL value
96
-	 *	@return string of text for teh csv file
97
-	 */
91
+	  *	Writes a row to the csv file
92
+	  *	@param array $row - individual row of csv data
93
+	  *	@param string $delimiter - csv delimiter
94
+	  *	@param string $enclosure - csv enclosure
95
+	  *	@param bool $mysql_null - allows php NULL to be overridden with MySQl's insertable NULL value
96
+	  *	@return string of text for teh csv file
97
+	  */
98 98
 	public static function get_csv_row ( array $row, $delimiter = ',', $enclosure = '"', $mysql_null = false ) {
99 99
 		//Allow user to filter the csv delimiter and enclosure for other countries csv standards
100 100
 		$delimiter = apply_filters( 'FHEE__EE_CSV__fputcsv2__delimiter', $delimiter );
Please login to merge, or discard this patch.
Spacing   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -30,9 +30,9 @@  discard block
 block discarded – undo
30 30
 	 * @param EE_Model_Field_Base $field
31 31
 	 * @return string
32 32
 	 */
33
-	public static function get_column_name_for_field(EE_Model_Field_Base $field){
33
+	public static function get_column_name_for_field(EE_Model_Field_Base $field) {
34 34
 	    return wp_specialchars_decode($field->get_nicename(), ENT_QUOTES)
35
-               . "[" . wp_specialchars_decode($field->get_name(), ENT_QUOTES)
35
+               . "[".wp_specialchars_decode($field->get_name(), ENT_QUOTES)
36 36
                . "]";
37 37
 	}
38 38
 
@@ -54,31 +54,31 @@  discard block
 block discarded – undo
54 54
 	 * 						we consider that a success (because we wrote everything there was...nothing)
55 55
 	 * @throws EE_Error
56 56
 	 */
57
-	public static function write_data_array_to_csv( $filepath, $data, $write_column_headers = true ){
57
+	public static function write_data_array_to_csv($filepath, $data, $write_column_headers = true) {
58 58
 
59 59
 		$new_file_contents = '';
60 60
 		//determine if $data is actually a 2d array
61
-		if ( $data && is_array($data) && is_array(EEH_Array::get_one_item_from_array($data))){
61
+		if ($data && is_array($data) && is_array(EEH_Array::get_one_item_from_array($data))) {
62 62
 			//make sure top level is numerically indexed,
63 63
 
64
-			if( EEH_Array::is_associative_array($data)){
65
-				throw new EE_Error(sprintf(__("top-level array must be numerically indexed. Does these look like numbers to you? %s","event_espresso"),implode(",",array_keys($data))));
64
+			if (EEH_Array::is_associative_array($data)) {
65
+				throw new EE_Error(sprintf(__("top-level array must be numerically indexed. Does these look like numbers to you? %s", "event_espresso"), implode(",", array_keys($data))));
66 66
 			}
67 67
 			$item_in_top_level_array = EEH_Array::get_one_item_from_array($data);
68 68
 			//now, is the last item in the top-level array of $data an associative or numeric array?
69
-			if( $write_column_headers &&
70
-					EEH_Array::is_associative_array($item_in_top_level_array)){
69
+			if ($write_column_headers &&
70
+					EEH_Array::is_associative_array($item_in_top_level_array)) {
71 71
 				//its associative, so we want to output its keys as column headers
72 72
 				$keys = array_keys($item_in_top_level_array);
73
-				$new_file_contents .=  EEH_Export::get_csv_row( $keys );
73
+				$new_file_contents .= EEH_Export::get_csv_row($keys);
74 74
 
75 75
 			}
76 76
 			//start writing data
77
-			foreach($data as $data_row){
78
-				$new_file_contents .= EEH_Export::get_csv_row( $data_row);
77
+			foreach ($data as $data_row) {
78
+				$new_file_contents .= EEH_Export::get_csv_row($data_row);
79 79
 			}
80
-			return EEH_File::write_to_file( $filepath, EEH_File::get_file_contents( $filepath ) . $new_file_contents );
81
-		}else{
80
+			return EEH_File::write_to_file($filepath, EEH_File::get_file_contents($filepath).$new_file_contents);
81
+		} else {
82 82
 			//no data TO write... so we can assume that's a success
83 83
 			return true;
84 84
 		}
@@ -95,29 +95,29 @@  discard block
 block discarded – undo
95 95
 	 *	@param bool $mysql_null - allows php NULL to be overridden with MySQl's insertable NULL value
96 96
 	 *	@return string of text for teh csv file
97 97
 	 */
98
-	public static function get_csv_row ( array $row, $delimiter = ',', $enclosure = '"', $mysql_null = false ) {
98
+	public static function get_csv_row(array $row, $delimiter = ',', $enclosure = '"', $mysql_null = false) {
99 99
 		//Allow user to filter the csv delimiter and enclosure for other countries csv standards
100
-		$delimiter = apply_filters( 'FHEE__EE_CSV__fputcsv2__delimiter', $delimiter );
101
-		$enclosure = apply_filters( 'FHEE__EE_CSV__fputcsv2__enclosure', $enclosure );
100
+		$delimiter = apply_filters('FHEE__EE_CSV__fputcsv2__delimiter', $delimiter);
101
+		$enclosure = apply_filters('FHEE__EE_CSV__fputcsv2__enclosure', $enclosure);
102 102
 
103 103
 		$delimiter_esc = preg_quote($delimiter, '/');
104 104
 		$enclosure_esc = preg_quote($enclosure, '/');
105 105
 
106 106
 		$output = array();
107 107
 		foreach ($row as $field_value) {
108
-			if(is_object($field_value) || is_array($field_value)){
108
+			if (is_object($field_value) || is_array($field_value)) {
109 109
 				$field_value = serialize($field_value);
110 110
 			}
111
-			if ($field_value === null && $mysql_null ) {
111
+			if ($field_value === null && $mysql_null) {
112 112
 				$output[] = 'NULL';
113 113
 				continue;
114 114
 			}
115 115
 
116 116
 			$output[] = preg_match("/(?:${delimiter_esc}|${enclosure_esc}|\s)/", $field_value) ?
117
-				( $enclosure . str_replace($enclosure, $enclosure . $enclosure, $field_value) . $enclosure ) : $field_value;
117
+				($enclosure.str_replace($enclosure, $enclosure.$enclosure, $field_value).$enclosure) : $field_value;
118 118
 		}
119 119
 
120
-		return  implode($delimiter, $output) . PHP_EOL;
120
+		return  implode($delimiter, $output).PHP_EOL;
121 121
 	}
122 122
 
123 123
 
@@ -130,19 +130,19 @@  discard block
 block discarded – undo
130 130
 	 * @param boolean|string $pretty_schema true to display pretty, a string to use a specific "Schema", or false to NOT display pretty
131 131
 	 * @return string
132 132
 	 */
133
-	public static function prepare_value_from_db_for_display( $model, $field_name,  $raw_db_value, $pretty_schema = true ) {
134
-		$field_obj = $model->field_settings_for( $field_name );
135
-		$value_on_model_obj = $field_obj->prepare_for_set_from_db( $raw_db_value );
136
-		if( $field_obj instanceof EE_Datetime_Field ) {
137
-			$field_obj->set_date_format( EEH_Export::get_date_format_for_export( $field_obj->get_date_format( $pretty_schema ) ), $pretty_schema );
138
-			$field_obj->set_time_format( EEH_Export::get_time_format_for_export( $field_obj->get_time_format( $pretty_schema ) ), $pretty_schema );
133
+	public static function prepare_value_from_db_for_display($model, $field_name, $raw_db_value, $pretty_schema = true) {
134
+		$field_obj = $model->field_settings_for($field_name);
135
+		$value_on_model_obj = $field_obj->prepare_for_set_from_db($raw_db_value);
136
+		if ($field_obj instanceof EE_Datetime_Field) {
137
+			$field_obj->set_date_format(EEH_Export::get_date_format_for_export($field_obj->get_date_format($pretty_schema)), $pretty_schema);
138
+			$field_obj->set_time_format(EEH_Export::get_time_format_for_export($field_obj->get_time_format($pretty_schema)), $pretty_schema);
139 139
 		}
140
-		if( $pretty_schema === true){
141
-			return $field_obj->prepare_for_pretty_echoing( $value_on_model_obj );
142
-		}elseif( is_string( $pretty_schema ) ) {
143
-			return $field_obj->prepare_for_pretty_echoing($value_on_model_obj, $pretty_schema );
144
-		}else{
145
-			return $field_obj->prepare_for_get( $value_on_model_obj );
140
+		if ($pretty_schema === true) {
141
+			return $field_obj->prepare_for_pretty_echoing($value_on_model_obj);
142
+		}elseif (is_string($pretty_schema)) {
143
+			return $field_obj->prepare_for_pretty_echoing($value_on_model_obj, $pretty_schema);
144
+		} else {
145
+			return $field_obj->prepare_for_get($value_on_model_obj);
146 146
 		}
147 147
 	}
148 148
 
@@ -153,8 +153,8 @@  discard block
 block discarded – undo
153 153
 	 * @param string $current_format
154 154
 	 * @return string
155 155
 	 */
156
-	public static function get_date_format_for_export( $current_format = null ) {
157
-		return apply_filters( 'FHEE__EE_CSV__get_date_format_for_csv__format', 'Y-m-d', $current_format );
156
+	public static function get_date_format_for_export($current_format = null) {
157
+		return apply_filters('FHEE__EE_CSV__get_date_format_for_csv__format', 'Y-m-d', $current_format);
158 158
 	}
159 159
 
160 160
 
@@ -164,8 +164,8 @@  discard block
 block discarded – undo
164 164
 	 * @param string $current_format
165 165
 	 * @return string
166 166
 	 */
167
-	public static function get_time_format_for_export( $current_format = null ) {
168
-		return apply_filters( 'FHEE__EE_CSV__get_time_format_for_csv__format', 'H:i:s', $current_format );
167
+	public static function get_time_format_for_export($current_format = null) {
168
+		return apply_filters('FHEE__EE_CSV__get_time_format_for_csv__format', 'H:i:s', $current_format);
169 169
 	}
170 170
 
171 171
 
Please login to merge, or discard this patch.
core/libraries/batch/JobHandlers/AttendeesReport.php 2 patches
Spacing   +35 added lines, -35 removed lines patch added patch discarded remove patch
@@ -18,7 +18,7 @@  discard block
 block discarded – undo
18 18
 use EventEspressoBatchRequest\Helpers\JobParameters;
19 19
 use EventEspressoBatchRequest\Helpers\JobStepResponse;
20 20
 
21
-if (!defined('EVENT_ESPRESSO_VERSION')) {
21
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
22 22
 	exit('No direct script access allowed');
23 23
 }
24 24
 
@@ -27,84 +27,84 @@  discard block
 block discarded – undo
27 27
 
28 28
 
29 29
 	public function create_job(JobParameters $job_parameters) {
30
-		if( ! \EE_Capabilities::instance()->current_user_can( 'ee_read_contacts', 'generating_report' ) ) {
30
+		if ( ! \EE_Capabilities::instance()->current_user_can('ee_read_contacts', 'generating_report')) {
31 31
 			throw new BatchRequestException(
32
-				__( 'You do not have permission to view contacts', 'event_espresso')
32
+				__('You do not have permission to view contacts', 'event_espresso')
33 33
 			);
34 34
 		}
35 35
 		$filepath = $this->create_file_from_job_with_name(
36 36
 			$job_parameters->job_id(),
37 37
 			__('contact-list-report.csv', 'event_espresso')
38 38
 		);
39
-		$job_parameters->add_extra_data( 'filepath', $filepath );
40
-		$job_parameters->set_job_size( $this->count_units_to_process() );
39
+		$job_parameters->add_extra_data('filepath', $filepath);
40
+		$job_parameters->set_job_size($this->count_units_to_process());
41 41
 		//we should also set the header columns
42
-		$csv_data_for_row = $this->get_csv_data( 0, 1 );
43
-		\EEH_Export::write_data_array_to_csv( $filepath, $csv_data_for_row, true );
42
+		$csv_data_for_row = $this->get_csv_data(0, 1);
43
+		\EEH_Export::write_data_array_to_csv($filepath, $csv_data_for_row, true);
44 44
 		//if we actually processed a row there, record it
45
-		if( $job_parameters->job_size() ) {
46
-			$job_parameters->mark_processed( 1 );
45
+		if ($job_parameters->job_size()) {
46
+			$job_parameters->mark_processed(1);
47 47
 		}
48 48
 		return new JobStepResponse(
49 49
 			$job_parameters,
50
-			__( 'Contacts report started successfully...', 'event_espresso' )
50
+			__('Contacts report started successfully...', 'event_espresso')
51 51
 		);
52 52
 	}
53 53
 
54 54
 
55 55
 	public function continue_job(JobParameters $job_parameters, $batch_size = 50) {
56
-		$csv_data = $this->get_csv_data( $job_parameters->units_processed(), $batch_size );
57
-		\EEH_Export::write_data_array_to_csv( $job_parameters->extra_datum( 'filepath' ), $csv_data, false );
58
-		$units_processed = count( $csv_data );
59
-		$job_parameters->mark_processed( $units_processed );
56
+		$csv_data = $this->get_csv_data($job_parameters->units_processed(), $batch_size);
57
+		\EEH_Export::write_data_array_to_csv($job_parameters->extra_datum('filepath'), $csv_data, false);
58
+		$units_processed = count($csv_data);
59
+		$job_parameters->mark_processed($units_processed);
60 60
 		$extra_response_data = array(
61 61
 			'file_url' => ''
62 62
 		);
63
-		if( $units_processed < $batch_size ) {
64
-			$job_parameters->set_status( JobParameters::status_complete );
65
-			$extra_response_data[ 'file_url' ] = $this->get_url_to_file( $job_parameters->extra_datum( 'filepath' ) );
63
+		if ($units_processed < $batch_size) {
64
+			$job_parameters->set_status(JobParameters::status_complete);
65
+			$extra_response_data['file_url'] = $this->get_url_to_file($job_parameters->extra_datum('filepath'));
66 66
 		}
67 67
 		return new JobStepResponse(
68 68
 				$job_parameters,
69 69
 				sprintf(
70
-					__( 'Wrote %1$s rows to report CSV file...', 'event_espresso' ),
71
-					count( $csv_data ) ),
70
+					__('Wrote %1$s rows to report CSV file...', 'event_espresso'),
71
+					count($csv_data) ),
72 72
 				$extra_response_data );
73 73
 	}
74 74
 
75 75
 
76 76
 	public function cleanup_job(JobParameters $job_parameters) {
77 77
 		$this->_file_helper->delete(
78
-			\EEH_File::remove_filename_from_filepath( $job_parameters->extra_datum( 'filepath' ) ),
78
+			\EEH_File::remove_filename_from_filepath($job_parameters->extra_datum('filepath')),
79 79
 			true,
80 80
 			'd'
81 81
 		);
82
-		return new JobStepResponse( $job_parameters, __( 'Cleaned up temporary file', 'event_espresso' ) );
82
+		return new JobStepResponse($job_parameters, __('Cleaned up temporary file', 'event_espresso'));
83 83
 	}
84 84
 
85 85
 	public function count_units_to_process() {
86
-		return \EEM_Attendee::instance()->count( array( 'caps' => \EEM_Base::caps_read_admin ));
86
+		return \EEM_Attendee::instance()->count(array('caps' => \EEM_Base::caps_read_admin));
87 87
 	}
88
-	public function get_csv_data( $offset, $limit ) {
88
+	public function get_csv_data($offset, $limit) {
89 89
 		$attendee_rows = \EEM_Attendee::instance()->get_all_wpdb_results( 
90 90
 			array( 
91
-				'limit' => array( $offset, $limit ),
92
-				'force_join' => array( 'State', 'Country' ),
91
+				'limit' => array($offset, $limit),
92
+				'force_join' => array('State', 'Country'),
93 93
 				'caps' => \EEM_Base::caps_read_admin
94 94
 			) 
95 95
 		);
96 96
 		$csv_data = array();
97
-		foreach( $attendee_rows as $attendee_row ){
97
+		foreach ($attendee_rows as $attendee_row) {
98 98
 			$csv_row = array();
99
-			foreach( \EEM_Attendee::instance()->field_settings() as $field_name => $field_obj ){
100
-				if( $field_name == 'STA_ID' ){
101
-					$state_name_field = \EEM_State::instance()->field_settings_for( 'STA_name' );
102
-					$csv_row[ __( 'State', 'event_espresso' ) ] = $attendee_row[ $state_name_field->get_qualified_column() ];
103
-				}elseif( $field_name == 'CNT_ISO' ){
104
-					$country_name_field = \EEM_Country::instance()->field_settings_for( 'CNT_name' );
105
-					$csv_row[ __( 'Country', 'event_espresso' ) ] = $attendee_row[ $country_name_field->get_qualified_column() ];
106
-				}else{
107
-					$csv_row[ wp_specialchars_decode($field_obj->get_nicename(), ENT_QUOTES) ] = $attendee_row[ $field_obj->get_qualified_column() ];
99
+			foreach (\EEM_Attendee::instance()->field_settings() as $field_name => $field_obj) {
100
+				if ($field_name == 'STA_ID') {
101
+					$state_name_field = \EEM_State::instance()->field_settings_for('STA_name');
102
+					$csv_row[__('State', 'event_espresso')] = $attendee_row[$state_name_field->get_qualified_column()];
103
+				}elseif ($field_name == 'CNT_ISO') {
104
+					$country_name_field = \EEM_Country::instance()->field_settings_for('CNT_name');
105
+					$csv_row[__('Country', 'event_espresso')] = $attendee_row[$country_name_field->get_qualified_column()];
106
+				} else {
107
+					$csv_row[wp_specialchars_decode($field_obj->get_nicename(), ENT_QUOTES)] = $attendee_row[$field_obj->get_qualified_column()];
108 108
 				}
109 109
 			}
110 110
 			$csv_data[] = apply_filters(
Please login to merge, or discard this patch.
Braces   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -100,10 +100,10 @@
 block discarded – undo
100 100
 				if( $field_name == 'STA_ID' ){
101 101
 					$state_name_field = \EEM_State::instance()->field_settings_for( 'STA_name' );
102 102
 					$csv_row[ __( 'State', 'event_espresso' ) ] = $attendee_row[ $state_name_field->get_qualified_column() ];
103
-				}elseif( $field_name == 'CNT_ISO' ){
103
+				} elseif( $field_name == 'CNT_ISO' ){
104 104
 					$country_name_field = \EEM_Country::instance()->field_settings_for( 'CNT_name' );
105 105
 					$csv_row[ __( 'Country', 'event_espresso' ) ] = $attendee_row[ $country_name_field->get_qualified_column() ];
106
-				}else{
106
+				} else{
107 107
 					$csv_row[ wp_specialchars_decode($field_obj->get_nicename(), ENT_QUOTES) ] = $attendee_row[ $field_obj->get_qualified_column() ];
108 108
 				}
109 109
 			}
Please login to merge, or discard this patch.