Completed
Branch FET/event-question-group-refac... (0d8185)
by
unknown
20:08 queued 10:56
created
core/db_classes/EE_Transaction.class.php 2 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -366,7 +366,7 @@  discard block
 block discarded – undo
366 366
 
367 367
 
368 368
     /**
369
-     * @return mixed|null
369
+     * @return EE_Cart|null
370 370
      * @throws EE_Error
371 371
      * @throws InvalidArgumentException
372 372
      * @throws InvalidDataTypeException
@@ -508,7 +508,7 @@  discard block
 block discarded – undo
508 508
      * Gets all the attendees for this transaction (handy for use with EE_Attendee's get_registrations_for_event
509 509
      * function for getting attendees and how many registrations they each have for an event)
510 510
      *
511
-     * @return mixed EE_Attendee[] by default, int if $output is set to 'COUNT'
511
+     * @return EE_Base_Class[] EE_Attendee[] by default, int if $output is set to 'COUNT'
512 512
      * @throws EE_Error
513 513
      * @throws InvalidArgumentException
514 514
      * @throws InvalidDataTypeException
@@ -564,7 +564,7 @@  discard block
 block discarded – undo
564 564
     /**
565 565
      * Gets all payments which have not been approved
566 566
      *
567
-     * @return EE_Base_Class[]|EEI_Payment[]
567
+     * @return EE_Base_Class[]
568 568
      * @throws EE_Error if a model is misconfigured somehow
569 569
      * @throws InvalidArgumentException
570 570
      * @throws InvalidDataTypeException
Please login to merge, or discard this patch.
Indentation   +1678 added lines, -1678 removed lines patch added patch discarded remove patch
@@ -13,1682 +13,1682 @@
 block discarded – undo
13 13
 class EE_Transaction extends EE_Base_Class implements EEI_Transaction
14 14
 {
15 15
 
16
-    /**
17
-     * The length of time in seconds that a lock is applied before being considered expired.
18
-     * It is not long because a transaction should only be locked for the duration of the request that locked it
19
-     */
20
-    const LOCK_EXPIRATION = 2;
21
-
22
-    /**
23
-     * txn status upon initial construction.
24
-     *
25
-     * @var string
26
-     */
27
-    protected $_old_txn_status;
28
-
29
-
30
-    /**
31
-     * @param array  $props_n_values          incoming values
32
-     * @param string $timezone                incoming timezone
33
-     *                                        (if not set the timezone set for the website will be used.)
34
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
35
-     *                                        date_format and the second value is the time format
36
-     * @return EE_Transaction
37
-     * @throws EE_Error
38
-     * @throws InvalidArgumentException
39
-     * @throws InvalidDataTypeException
40
-     * @throws InvalidInterfaceException
41
-     * @throws ReflectionException
42
-     */
43
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
44
-    {
45
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
46
-        $txn = $has_object
47
-            ? $has_object
48
-            : new self($props_n_values, false, $timezone, $date_formats);
49
-        if (! $has_object) {
50
-            $txn->set_old_txn_status($txn->status_ID());
51
-        }
52
-        return $txn;
53
-    }
54
-
55
-
56
-    /**
57
-     * @param array  $props_n_values  incoming values from the database
58
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
59
-     *                                the website will be used.
60
-     * @return EE_Transaction
61
-     * @throws EE_Error
62
-     * @throws InvalidArgumentException
63
-     * @throws InvalidDataTypeException
64
-     * @throws InvalidInterfaceException
65
-     * @throws ReflectionException
66
-     */
67
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
68
-    {
69
-        $txn = new self($props_n_values, true, $timezone);
70
-        $txn->set_old_txn_status($txn->status_ID());
71
-        return $txn;
72
-    }
73
-
74
-
75
-    /**
76
-     * Sets a meta field indicating that this TXN is locked and should not be updated in the db.
77
-     * If a lock has already been set, then we will attempt to remove it in case it has expired.
78
-     * If that also fails, then an exception is thrown.
79
-     *
80
-     * @throws EE_Error
81
-     * @throws InvalidArgumentException
82
-     * @throws InvalidDataTypeException
83
-     * @throws InvalidInterfaceException
84
-     * @throws ReflectionException
85
-     */
86
-    public function lock()
87
-    {
88
-        // attempt to set lock, but if that fails...
89
-        if (! $this->add_extra_meta('lock', time(), true)) {
90
-            // then attempt to remove the lock in case it is expired
91
-            if ($this->_remove_expired_lock()) {
92
-                // if removal was successful, then try setting lock again
93
-                $this->lock();
94
-            } else {
95
-                // but if the lock can not be removed, then throw an exception
96
-                throw new EE_Error(
97
-                    sprintf(
98
-                        __(
99
-                            'Could not lock Transaction %1$d because it is already locked, meaning another part of the system is currently editing it. It should already be unlocked by the time you read this, so please refresh the page and try again.',
100
-                            'event_espresso'
101
-                        ),
102
-                        $this->ID()
103
-                    )
104
-                );
105
-            }
106
-        }
107
-    }
108
-
109
-
110
-    /**
111
-     * removes transaction lock applied in EE_Transaction::lock()
112
-     *
113
-     * @return int
114
-     * @throws EE_Error
115
-     * @throws InvalidArgumentException
116
-     * @throws InvalidDataTypeException
117
-     * @throws InvalidInterfaceException
118
-     * @throws ReflectionException
119
-     */
120
-    public function unlock()
121
-    {
122
-        return $this->delete_extra_meta('lock');
123
-    }
124
-
125
-
126
-    /**
127
-     * Decides whether or not now is the right time to update the transaction.
128
-     * This is useful because we don't always know if it is safe to update the transaction
129
-     * and its related data. why?
130
-     * because it's possible that the transaction is being used in another
131
-     * request and could overwrite anything we save.
132
-     * So we want to only update the txn once we know that won't happen.
133
-     * We also check that the lock isn't expired, and remove it if it is
134
-     *
135
-     * @return boolean
136
-     * @throws EE_Error
137
-     * @throws InvalidArgumentException
138
-     * @throws InvalidDataTypeException
139
-     * @throws InvalidInterfaceException
140
-     * @throws ReflectionException
141
-     */
142
-    public function is_locked()
143
-    {
144
-        // if TXN is not locked, then return false immediately
145
-        if (! $this->_get_lock()) {
146
-            return false;
147
-        }
148
-        // if not, then let's try and remove the lock in case it's expired...
149
-        // _remove_expired_lock() returns 0 when lock is valid (ie: removed = false)
150
-        // and a positive number if the lock was removed (ie: number of locks deleted),
151
-        // so we need to return the opposite
152
-        return ! $this->_remove_expired_lock() ? true : false;
153
-    }
154
-
155
-
156
-    /**
157
-     * Gets the meta field indicating that this TXN is locked
158
-     *
159
-     * @return int
160
-     * @throws EE_Error
161
-     * @throws InvalidArgumentException
162
-     * @throws InvalidDataTypeException
163
-     * @throws InvalidInterfaceException
164
-     * @throws ReflectionException
165
-     */
166
-    protected function _get_lock()
167
-    {
168
-        return (int) $this->get_extra_meta('lock', true, 0);
169
-    }
170
-
171
-
172
-    /**
173
-     * If the lock on this transaction is expired, then we want to remove it so that the transaction can be updated
174
-     *
175
-     * @return int
176
-     * @throws EE_Error
177
-     * @throws InvalidArgumentException
178
-     * @throws InvalidDataTypeException
179
-     * @throws InvalidInterfaceException
180
-     * @throws ReflectionException
181
-     */
182
-    protected function _remove_expired_lock()
183
-    {
184
-        $locked = $this->_get_lock();
185
-        if ($locked && time() - EE_Transaction::LOCK_EXPIRATION > $locked) {
186
-            return $this->unlock();
187
-        }
188
-        return 0;
189
-    }
190
-
191
-
192
-    /**
193
-     * Set transaction total
194
-     *
195
-     * @param float $total total value of transaction
196
-     * @throws EE_Error
197
-     * @throws InvalidArgumentException
198
-     * @throws InvalidDataTypeException
199
-     * @throws InvalidInterfaceException
200
-     * @throws ReflectionException
201
-     */
202
-    public function set_total($total = 0.00)
203
-    {
204
-        $this->set('TXN_total', (float) $total);
205
-    }
206
-
207
-
208
-    /**
209
-     * Set Total Amount Paid to Date
210
-     *
211
-     * @param float $total_paid total amount paid to date (sum of all payments)
212
-     * @throws EE_Error
213
-     * @throws InvalidArgumentException
214
-     * @throws InvalidDataTypeException
215
-     * @throws InvalidInterfaceException
216
-     * @throws ReflectionException
217
-     */
218
-    public function set_paid($total_paid = 0.00)
219
-    {
220
-        $this->set('TXN_paid', (float) $total_paid);
221
-    }
222
-
223
-
224
-    /**
225
-     * Set transaction status
226
-     *
227
-     * @param string $status        whether the transaction is open, declined, accepted,
228
-     *                              or any number of custom values that can be set
229
-     * @throws EE_Error
230
-     * @throws InvalidArgumentException
231
-     * @throws InvalidDataTypeException
232
-     * @throws InvalidInterfaceException
233
-     * @throws ReflectionException
234
-     */
235
-    public function set_status($status = '')
236
-    {
237
-        $this->set('STS_ID', $status);
238
-    }
239
-
240
-
241
-    /**
242
-     * Set hash salt
243
-     *
244
-     * @param string $hash_salt required for some payment gateways
245
-     * @throws EE_Error
246
-     * @throws InvalidArgumentException
247
-     * @throws InvalidDataTypeException
248
-     * @throws InvalidInterfaceException
249
-     * @throws ReflectionException
250
-     */
251
-    public function set_hash_salt($hash_salt = '')
252
-    {
253
-        $this->set('TXN_hash_salt', $hash_salt);
254
-    }
255
-
256
-
257
-    /**
258
-     * Sets TXN_reg_steps array
259
-     *
260
-     * @param array $txn_reg_steps
261
-     * @throws EE_Error
262
-     * @throws InvalidArgumentException
263
-     * @throws InvalidDataTypeException
264
-     * @throws InvalidInterfaceException
265
-     * @throws ReflectionException
266
-     */
267
-    public function set_reg_steps(array $txn_reg_steps)
268
-    {
269
-        $this->set('TXN_reg_steps', $txn_reg_steps);
270
-    }
271
-
272
-
273
-    /**
274
-     * Gets TXN_reg_steps
275
-     *
276
-     * @return array
277
-     * @throws EE_Error
278
-     * @throws InvalidArgumentException
279
-     * @throws InvalidDataTypeException
280
-     * @throws InvalidInterfaceException
281
-     * @throws ReflectionException
282
-     */
283
-    public function reg_steps()
284
-    {
285
-        $TXN_reg_steps = $this->get('TXN_reg_steps');
286
-        return is_array($TXN_reg_steps) ? (array) $TXN_reg_steps : array();
287
-    }
288
-
289
-
290
-    /**
291
-     * @return string of transaction's total cost, with currency symbol and decimal
292
-     * @throws EE_Error
293
-     * @throws InvalidArgumentException
294
-     * @throws InvalidDataTypeException
295
-     * @throws InvalidInterfaceException
296
-     * @throws ReflectionException
297
-     */
298
-    public function pretty_total()
299
-    {
300
-        return $this->get_pretty('TXN_total');
301
-    }
302
-
303
-
304
-    /**
305
-     * Gets the amount paid in a pretty string (formatted and with currency symbol)
306
-     *
307
-     * @return string
308
-     * @throws EE_Error
309
-     * @throws InvalidArgumentException
310
-     * @throws InvalidDataTypeException
311
-     * @throws InvalidInterfaceException
312
-     * @throws ReflectionException
313
-     */
314
-    public function pretty_paid()
315
-    {
316
-        return $this->get_pretty('TXN_paid');
317
-    }
318
-
319
-
320
-    /**
321
-     * calculate the amount remaining for this transaction and return;
322
-     *
323
-     * @return float amount remaining
324
-     * @throws EE_Error
325
-     * @throws InvalidArgumentException
326
-     * @throws InvalidDataTypeException
327
-     * @throws InvalidInterfaceException
328
-     * @throws ReflectionException
329
-     */
330
-    public function remaining()
331
-    {
332
-        return $this->total() - $this->paid();
333
-    }
334
-
335
-
336
-    /**
337
-     * get Transaction Total
338
-     *
339
-     * @return float
340
-     * @throws EE_Error
341
-     * @throws InvalidArgumentException
342
-     * @throws InvalidDataTypeException
343
-     * @throws InvalidInterfaceException
344
-     * @throws ReflectionException
345
-     */
346
-    public function total()
347
-    {
348
-        return (float) $this->get('TXN_total');
349
-    }
350
-
351
-
352
-    /**
353
-     * get Total Amount Paid to Date
354
-     *
355
-     * @return float
356
-     * @throws EE_Error
357
-     * @throws InvalidArgumentException
358
-     * @throws InvalidDataTypeException
359
-     * @throws InvalidInterfaceException
360
-     * @throws ReflectionException
361
-     */
362
-    public function paid()
363
-    {
364
-        return (float) $this->get('TXN_paid');
365
-    }
366
-
367
-
368
-    /**
369
-     * @return mixed|null
370
-     * @throws EE_Error
371
-     * @throws InvalidArgumentException
372
-     * @throws InvalidDataTypeException
373
-     * @throws InvalidInterfaceException
374
-     * @throws ReflectionException
375
-     */
376
-    public function get_cart_session()
377
-    {
378
-        $session_data = (array) $this->get('TXN_session_data');
379
-        return isset($session_data['cart']) && $session_data['cart'] instanceof EE_Cart
380
-            ? $session_data['cart']
381
-            : null;
382
-    }
383
-
384
-
385
-    /**
386
-     * get Transaction session data
387
-     *
388
-     * @return array|mixed
389
-     * @throws EE_Error
390
-     * @throws InvalidArgumentException
391
-     * @throws InvalidDataTypeException
392
-     * @throws InvalidInterfaceException
393
-     * @throws ReflectionException
394
-     */
395
-    public function session_data()
396
-    {
397
-        $session_data = $this->get('TXN_session_data');
398
-        if (empty($session_data)) {
399
-            $session_data = array(
400
-                'id'            => null,
401
-                'user_id'       => null,
402
-                'ip_address'    => null,
403
-                'user_agent'    => null,
404
-                'init_access'   => null,
405
-                'last_access'   => null,
406
-                'pages_visited' => array(),
407
-            );
408
-        }
409
-        return $session_data;
410
-    }
411
-
412
-
413
-    /**
414
-     * Set session data within the TXN object
415
-     *
416
-     * @param EE_Session|array $session_data
417
-     * @throws EE_Error
418
-     * @throws InvalidArgumentException
419
-     * @throws InvalidDataTypeException
420
-     * @throws InvalidInterfaceException
421
-     * @throws ReflectionException
422
-     */
423
-    public function set_txn_session_data($session_data)
424
-    {
425
-        if ($session_data instanceof EE_Session) {
426
-            $this->set('TXN_session_data', $session_data->get_session_data(null, true));
427
-        } else {
428
-            $this->set('TXN_session_data', $session_data);
429
-        }
430
-    }
431
-
432
-
433
-    /**
434
-     * get Transaction hash salt
435
-     *
436
-     * @return mixed
437
-     * @throws EE_Error
438
-     * @throws InvalidArgumentException
439
-     * @throws InvalidDataTypeException
440
-     * @throws InvalidInterfaceException
441
-     * @throws ReflectionException
442
-     */
443
-    public function hash_salt_()
444
-    {
445
-        return $this->get('TXN_hash_salt');
446
-    }
447
-
448
-
449
-    /**
450
-     * Returns the transaction datetime as either:
451
-     *            - unix timestamp format ($format = false, $gmt = true)
452
-     *            - formatted date string including the UTC (timezone) offset ($format = true ($gmt
453
-     *              has no affect with this option)), this also may include a timezone abbreviation if the
454
-     *              set timezone in this class differs from what the timezone is on the blog.
455
-     *            - formatted date string including the UTC (timezone) offset (default).
456
-     *
457
-     * @param boolean $format   - whether to return a unix timestamp (default) or formatted date string
458
-     * @param boolean $gmt      - whether to return a unix timestamp with UTC offset applied (default)
459
-     *                          or no UTC offset applied
460
-     * @return string | int
461
-     * @throws EE_Error
462
-     * @throws InvalidArgumentException
463
-     * @throws InvalidDataTypeException
464
-     * @throws InvalidInterfaceException
465
-     * @throws ReflectionException
466
-     */
467
-    public function datetime($format = false, $gmt = false)
468
-    {
469
-        if ($format) {
470
-            return $this->get_pretty('TXN_timestamp');
471
-        }
472
-        if ($gmt) {
473
-            return $this->get_raw('TXN_timestamp');
474
-        }
475
-        return $this->get('TXN_timestamp');
476
-    }
477
-
478
-
479
-    /**
480
-     * Gets registrations on this transaction
481
-     *
482
-     * @param array   $query_params array of query parameters
483
-     * @param boolean $get_cached   TRUE to retrieve cached registrations or FALSE to pull from the db
484
-     * @return EE_Base_Class[]|EE_Registration[]
485
-     * @throws EE_Error
486
-     * @throws InvalidArgumentException
487
-     * @throws InvalidDataTypeException
488
-     * @throws InvalidInterfaceException
489
-     * @throws ReflectionException
490
-     */
491
-    public function registrations($query_params = array(), $get_cached = false)
492
-    {
493
-        $query_params = (empty($query_params) || ! is_array($query_params))
494
-            ? array(
495
-                'order_by' => array(
496
-                    'Event.EVT_name'     => 'ASC',
497
-                    'Attendee.ATT_lname' => 'ASC',
498
-                    'Attendee.ATT_fname' => 'ASC',
499
-                ),
500
-            )
501
-            : $query_params;
502
-        $query_params = $get_cached ? array() : $query_params;
503
-        return $this->get_many_related('Registration', $query_params);
504
-    }
505
-
506
-
507
-    /**
508
-     * Gets all the attendees for this transaction (handy for use with EE_Attendee's get_registrations_for_event
509
-     * function for getting attendees and how many registrations they each have for an event)
510
-     *
511
-     * @return mixed EE_Attendee[] by default, int if $output is set to 'COUNT'
512
-     * @throws EE_Error
513
-     * @throws InvalidArgumentException
514
-     * @throws InvalidDataTypeException
515
-     * @throws InvalidInterfaceException
516
-     * @throws ReflectionException
517
-     */
518
-    public function attendees()
519
-    {
520
-        return $this->get_many_related('Attendee', array(array('Registration.Transaction.TXN_ID' => $this->ID())));
521
-    }
522
-
523
-
524
-    /**
525
-     * Gets payments for this transaction. Unlike other such functions, order by 'DESC' by default
526
-     *
527
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
528
-     * @return EE_Base_Class[]|EE_Payment[]
529
-     * @throws EE_Error
530
-     * @throws InvalidArgumentException
531
-     * @throws InvalidDataTypeException
532
-     * @throws InvalidInterfaceException
533
-     * @throws ReflectionException
534
-     */
535
-    public function payments($query_params = array())
536
-    {
537
-        return $this->get_many_related('Payment', $query_params);
538
-    }
539
-
540
-
541
-    /**
542
-     * gets only approved payments for this transaction
543
-     *
544
-     * @return EE_Base_Class[]|EE_Payment[]
545
-     * @throws EE_Error
546
-     * @throws InvalidArgumentException
547
-     * @throws ReflectionException
548
-     * @throws InvalidDataTypeException
549
-     * @throws InvalidInterfaceException
550
-     */
551
-    public function approved_payments()
552
-    {
553
-        EE_Registry::instance()->load_model('Payment');
554
-        return $this->get_many_related(
555
-            'Payment',
556
-            array(
557
-                array('STS_ID' => EEM_Payment::status_id_approved),
558
-                'order_by' => array('PAY_timestamp' => 'DESC'),
559
-            )
560
-        );
561
-    }
562
-
563
-
564
-    /**
565
-     * Gets all payments which have not been approved
566
-     *
567
-     * @return EE_Base_Class[]|EEI_Payment[]
568
-     * @throws EE_Error if a model is misconfigured somehow
569
-     * @throws InvalidArgumentException
570
-     * @throws InvalidDataTypeException
571
-     * @throws InvalidInterfaceException
572
-     * @throws ReflectionException
573
-     */
574
-    public function pending_payments()
575
-    {
576
-        return $this->get_many_related(
577
-            'Payment',
578
-            array(
579
-                array(
580
-                    'STS_ID' => EEM_Payment::status_id_pending,
581
-                ),
582
-                'order_by' => array(
583
-                    'PAY_timestamp' => 'DESC',
584
-                ),
585
-            )
586
-        );
587
-    }
588
-
589
-
590
-    /**
591
-     * echoes $this->pretty_status()
592
-     *
593
-     * @param bool $show_icons
594
-     * @throws EE_Error
595
-     * @throws InvalidArgumentException
596
-     * @throws InvalidDataTypeException
597
-     * @throws InvalidInterfaceException
598
-     * @throws ReflectionException
599
-     */
600
-    public function e_pretty_status($show_icons = false)
601
-    {
602
-        echo $this->pretty_status($show_icons);
603
-    }
604
-
605
-
606
-    /**
607
-     * returns a pretty version of the status, good for displaying to users
608
-     *
609
-     * @param bool $show_icons
610
-     * @return string
611
-     * @throws EE_Error
612
-     * @throws InvalidArgumentException
613
-     * @throws InvalidDataTypeException
614
-     * @throws InvalidInterfaceException
615
-     * @throws ReflectionException
616
-     */
617
-    public function pretty_status($show_icons = false)
618
-    {
619
-        $status = EEM_Status::instance()->localized_status(
620
-            array($this->status_ID() => __('unknown', 'event_espresso')),
621
-            false,
622
-            'sentence'
623
-        );
624
-        $icon = '';
625
-        switch ($this->status_ID()) {
626
-            case EEM_Transaction::complete_status_code:
627
-                $icon = $show_icons ? '<span class="dashicons dashicons-yes ee-icon-size-24 green-text"></span>' : '';
628
-                break;
629
-            case EEM_Transaction::incomplete_status_code:
630
-                $icon = $show_icons ? '<span class="dashicons dashicons-marker ee-icon-size-16 lt-blue-text"></span>'
631
-                    : '';
632
-                break;
633
-            case EEM_Transaction::abandoned_status_code:
634
-                $icon = $show_icons ? '<span class="dashicons dashicons-marker ee-icon-size-16 red-text"></span>' : '';
635
-                break;
636
-            case EEM_Transaction::failed_status_code:
637
-                $icon = $show_icons ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>' : '';
638
-                break;
639
-            case EEM_Transaction::overpaid_status_code:
640
-                $icon = $show_icons ? '<span class="dashicons dashicons-plus ee-icon-size-16 orange-text"></span>' : '';
641
-                break;
642
-        }
643
-        return $icon . $status[ $this->status_ID() ];
644
-    }
645
-
646
-
647
-    /**
648
-     * get Transaction Status
649
-     *
650
-     * @return mixed
651
-     * @throws EE_Error
652
-     * @throws InvalidArgumentException
653
-     * @throws InvalidDataTypeException
654
-     * @throws InvalidInterfaceException
655
-     * @throws ReflectionException
656
-     */
657
-    public function status_ID()
658
-    {
659
-        return $this->get('STS_ID');
660
-    }
661
-
662
-
663
-    /**
664
-     * Returns TRUE or FALSE for whether or not this transaction cost any money
665
-     *
666
-     * @return boolean
667
-     * @throws EE_Error
668
-     * @throws InvalidArgumentException
669
-     * @throws InvalidDataTypeException
670
-     * @throws InvalidInterfaceException
671
-     * @throws ReflectionException
672
-     */
673
-    public function is_free()
674
-    {
675
-        return EEH_Money::compare_floats($this->get('TXN_total'), 0, '==');
676
-    }
677
-
678
-
679
-    /**
680
-     * Returns whether this transaction is complete
681
-     * Useful in templates and other logic for deciding if we should ask for another payment...
682
-     *
683
-     * @return boolean
684
-     * @throws EE_Error
685
-     * @throws InvalidArgumentException
686
-     * @throws InvalidDataTypeException
687
-     * @throws InvalidInterfaceException
688
-     * @throws ReflectionException
689
-     */
690
-    public function is_completed()
691
-    {
692
-        return $this->status_ID() === EEM_Transaction::complete_status_code;
693
-    }
694
-
695
-
696
-    /**
697
-     * Returns whether this transaction is incomplete
698
-     * Useful in templates and other logic for deciding if we should ask for another payment...
699
-     *
700
-     * @return boolean
701
-     * @throws EE_Error
702
-     * @throws InvalidArgumentException
703
-     * @throws InvalidDataTypeException
704
-     * @throws InvalidInterfaceException
705
-     * @throws ReflectionException
706
-     */
707
-    public function is_incomplete()
708
-    {
709
-        return $this->status_ID() === EEM_Transaction::incomplete_status_code;
710
-    }
711
-
712
-
713
-    /**
714
-     * Returns whether this transaction is overpaid
715
-     * Useful in templates and other logic for deciding if monies need to be refunded
716
-     *
717
-     * @return boolean
718
-     * @throws EE_Error
719
-     * @throws InvalidArgumentException
720
-     * @throws InvalidDataTypeException
721
-     * @throws InvalidInterfaceException
722
-     * @throws ReflectionException
723
-     */
724
-    public function is_overpaid()
725
-    {
726
-        return $this->status_ID() === EEM_Transaction::overpaid_status_code;
727
-    }
728
-
729
-
730
-    /**
731
-     * Returns whether this transaction was abandoned
732
-     * meaning that the transaction/registration process was somehow interrupted and never completed
733
-     * but that contact information exists for at least one registrant
734
-     *
735
-     * @return boolean
736
-     * @throws EE_Error
737
-     * @throws InvalidArgumentException
738
-     * @throws InvalidDataTypeException
739
-     * @throws InvalidInterfaceException
740
-     * @throws ReflectionException
741
-     */
742
-    public function is_abandoned()
743
-    {
744
-        return $this->status_ID() === EEM_Transaction::abandoned_status_code;
745
-    }
746
-
747
-
748
-    /**
749
-     * Returns whether this transaction failed
750
-     * meaning that the transaction/registration process was somehow interrupted and never completed
751
-     * and that NO contact information exists for any registrants
752
-     *
753
-     * @return boolean
754
-     * @throws EE_Error
755
-     * @throws InvalidArgumentException
756
-     * @throws InvalidDataTypeException
757
-     * @throws InvalidInterfaceException
758
-     * @throws ReflectionException
759
-     */
760
-    public function failed()
761
-    {
762
-        return $this->status_ID() === EEM_Transaction::failed_status_code;
763
-    }
764
-
765
-
766
-    /**
767
-     * This returns the url for the invoice of this transaction
768
-     *
769
-     * @param string $type 'html' or 'pdf' (default is pdf)
770
-     * @return string
771
-     * @throws EE_Error
772
-     * @throws InvalidArgumentException
773
-     * @throws InvalidDataTypeException
774
-     * @throws InvalidInterfaceException
775
-     * @throws ReflectionException
776
-     */
777
-    public function invoice_url($type = 'html')
778
-    {
779
-        $REG = $this->primary_registration();
780
-        if (! $REG instanceof EE_Registration) {
781
-            return '';
782
-        }
783
-        return $REG->invoice_url($type);
784
-    }
785
-
786
-
787
-    /**
788
-     * Gets the primary registration only
789
-     *
790
-     * @return EE_Base_Class|EE_Registration
791
-     * @throws EE_Error
792
-     * @throws InvalidArgumentException
793
-     * @throws InvalidDataTypeException
794
-     * @throws InvalidInterfaceException
795
-     * @throws ReflectionException
796
-     */
797
-    public function primary_registration()
798
-    {
799
-        $registrations = (array) $this->get_many_related(
800
-            'Registration',
801
-            array(array('REG_count' => EEM_Registration::PRIMARY_REGISTRANT_COUNT))
802
-        );
803
-        foreach ($registrations as $registration) {
804
-            // valid registration that is NOT cancelled or declined ?
805
-            if ($registration instanceof EE_Registration
806
-                && ! in_array($registration->status_ID(), EEM_Registration::closed_reg_statuses(), true)
807
-            ) {
808
-                return $registration;
809
-            }
810
-        }
811
-        // nothing valid found, so just return first thing from array of results
812
-        return reset($registrations);
813
-    }
814
-
815
-
816
-    /**
817
-     * Gets the URL for viewing the receipt
818
-     *
819
-     * @param string $type 'pdf' or 'html' (default is 'html')
820
-     * @return string
821
-     * @throws EE_Error
822
-     * @throws InvalidArgumentException
823
-     * @throws InvalidDataTypeException
824
-     * @throws InvalidInterfaceException
825
-     * @throws ReflectionException
826
-     */
827
-    public function receipt_url($type = 'html')
828
-    {
829
-        $REG = $this->primary_registration();
830
-        if (! $REG instanceof EE_Registration) {
831
-            return '';
832
-        }
833
-        return $REG->receipt_url($type);
834
-    }
835
-
836
-
837
-    /**
838
-     * Gets the URL of the thank you page with this registration REG_url_link added as
839
-     * a query parameter
840
-     *
841
-     * @return string
842
-     * @throws EE_Error
843
-     * @throws InvalidArgumentException
844
-     * @throws InvalidDataTypeException
845
-     * @throws InvalidInterfaceException
846
-     * @throws ReflectionException
847
-     */
848
-    public function payment_overview_url()
849
-    {
850
-        $primary_registration = $this->primary_registration();
851
-        return $primary_registration instanceof EE_Registration ? $primary_registration->payment_overview_url() : false;
852
-    }
853
-
854
-
855
-    /**
856
-     * @return string
857
-     * @throws EE_Error
858
-     * @throws InvalidArgumentException
859
-     * @throws InvalidDataTypeException
860
-     * @throws InvalidInterfaceException
861
-     * @throws ReflectionException
862
-     */
863
-    public function gateway_response_on_transaction()
864
-    {
865
-        $payment = $this->get_first_related('Payment');
866
-        return $payment instanceof EE_Payment ? $payment->gateway_response() : '';
867
-    }
868
-
869
-
870
-    /**
871
-     * Get the status object of this object
872
-     *
873
-     * @return EE_Base_Class|EE_Status
874
-     * @throws EE_Error
875
-     * @throws InvalidArgumentException
876
-     * @throws InvalidDataTypeException
877
-     * @throws InvalidInterfaceException
878
-     * @throws ReflectionException
879
-     */
880
-    public function status_obj()
881
-    {
882
-        return $this->get_first_related('Status');
883
-    }
884
-
885
-
886
-    /**
887
-     * Gets all the extra meta info on this payment
888
-     *
889
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
890
-     * @return EE_Base_Class[]|EE_Extra_Meta
891
-     * @throws EE_Error
892
-     * @throws InvalidArgumentException
893
-     * @throws InvalidDataTypeException
894
-     * @throws InvalidInterfaceException
895
-     * @throws ReflectionException
896
-     */
897
-    public function extra_meta($query_params = array())
898
-    {
899
-        return $this->get_many_related('Extra_Meta', $query_params);
900
-    }
901
-
902
-
903
-    /**
904
-     * Wrapper for _add_relation_to
905
-     *
906
-     * @param EE_Registration $registration
907
-     * @return EE_Base_Class the relation was added to
908
-     * @throws EE_Error
909
-     * @throws InvalidArgumentException
910
-     * @throws InvalidDataTypeException
911
-     * @throws InvalidInterfaceException
912
-     * @throws ReflectionException
913
-     */
914
-    public function add_registration(EE_Registration $registration)
915
-    {
916
-        return $this->_add_relation_to($registration, 'Registration');
917
-    }
918
-
919
-
920
-    /**
921
-     * Removes the given registration from being related (even before saving this transaction).
922
-     * If an ID/index is provided and this transaction isn't saved yet, removes it from list of cached relations
923
-     *
924
-     * @param int $registration_or_id
925
-     * @return EE_Base_Class that was removed from being related
926
-     * @throws EE_Error
927
-     * @throws InvalidArgumentException
928
-     * @throws InvalidDataTypeException
929
-     * @throws InvalidInterfaceException
930
-     * @throws ReflectionException
931
-     */
932
-    public function remove_registration_with_id($registration_or_id)
933
-    {
934
-        return $this->_remove_relation_to($registration_or_id, 'Registration');
935
-    }
936
-
937
-
938
-    /**
939
-     * Gets all the line items which are for ACTUAL items
940
-     *
941
-     * @return EE_Line_Item[]
942
-     * @throws EE_Error
943
-     * @throws InvalidArgumentException
944
-     * @throws InvalidDataTypeException
945
-     * @throws InvalidInterfaceException
946
-     * @throws ReflectionException
947
-     */
948
-    public function items_purchased()
949
-    {
950
-        return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_line_item)));
951
-    }
952
-
953
-
954
-    /**
955
-     * Wrapper for _add_relation_to
956
-     *
957
-     * @param EE_Line_Item $line_item
958
-     * @return EE_Base_Class the relation was added to
959
-     * @throws EE_Error
960
-     * @throws InvalidArgumentException
961
-     * @throws InvalidDataTypeException
962
-     * @throws InvalidInterfaceException
963
-     * @throws ReflectionException
964
-     */
965
-    public function add_line_item(EE_Line_Item $line_item)
966
-    {
967
-        return $this->_add_relation_to($line_item, 'Line_Item');
968
-    }
969
-
970
-
971
-    /**
972
-     * Gets ALL the line items related to this transaction (unstructured)
973
-     *
974
-     * @param array $query_params
975
-     * @return EE_Base_Class[]|EE_Line_Item[]
976
-     * @throws EE_Error
977
-     * @throws InvalidArgumentException
978
-     * @throws InvalidDataTypeException
979
-     * @throws InvalidInterfaceException
980
-     * @throws ReflectionException
981
-     */
982
-    public function line_items($query_params = array())
983
-    {
984
-        return $this->get_many_related('Line_Item', $query_params);
985
-    }
986
-
987
-
988
-    /**
989
-     * Gets all the line items which are taxes on the total
990
-     *
991
-     * @return EE_Line_Item[]
992
-     * @throws EE_Error
993
-     * @throws InvalidArgumentException
994
-     * @throws InvalidDataTypeException
995
-     * @throws InvalidInterfaceException
996
-     * @throws ReflectionException
997
-     */
998
-    public function tax_items()
999
-    {
1000
-        return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax)));
1001
-    }
1002
-
1003
-
1004
-    /**
1005
-     * Gets the total line item (which is a parent of all other related line items,
1006
-     * meaning it takes them all into account on its total)
1007
-     *
1008
-     * @param bool $create_if_not_found
1009
-     * @return \EE_Line_Item
1010
-     * @throws EE_Error
1011
-     * @throws InvalidArgumentException
1012
-     * @throws InvalidDataTypeException
1013
-     * @throws InvalidInterfaceException
1014
-     * @throws ReflectionException
1015
-     */
1016
-    public function total_line_item($create_if_not_found = true)
1017
-    {
1018
-        $item = $this->get_first_related('Line_Item', array(array('LIN_type' => EEM_Line_Item::type_total)));
1019
-        if (! $item && $create_if_not_found) {
1020
-            $item = EEH_Line_Item::create_total_line_item($this);
1021
-        }
1022
-        return $item;
1023
-    }
1024
-
1025
-
1026
-    /**
1027
-     * Returns the total amount of tax on this transaction
1028
-     * (assumes there's only one tax subtotal line item)
1029
-     *
1030
-     * @return float
1031
-     * @throws EE_Error
1032
-     * @throws InvalidArgumentException
1033
-     * @throws InvalidDataTypeException
1034
-     * @throws InvalidInterfaceException
1035
-     * @throws ReflectionException
1036
-     */
1037
-    public function tax_total()
1038
-    {
1039
-        $tax_line_item = $this->tax_total_line_item();
1040
-        if ($tax_line_item) {
1041
-            return (float) $tax_line_item->total();
1042
-        }
1043
-        return (float) 0;
1044
-    }
1045
-
1046
-
1047
-    /**
1048
-     * Gets the tax subtotal line item (assumes there's only one)
1049
-     *
1050
-     * @return EE_Line_Item
1051
-     * @throws EE_Error
1052
-     * @throws InvalidArgumentException
1053
-     * @throws InvalidDataTypeException
1054
-     * @throws InvalidInterfaceException
1055
-     * @throws ReflectionException
1056
-     */
1057
-    public function tax_total_line_item()
1058
-    {
1059
-        return EEH_Line_Item::get_taxes_subtotal($this->total_line_item());
1060
-    }
1061
-
1062
-
1063
-    /**
1064
-     * Gets the array of billing info for the gateway and for this transaction's primary registration's attendee.
1065
-     *
1066
-     * @return EE_Form_Section_Proper
1067
-     * @throws EE_Error
1068
-     * @throws InvalidArgumentException
1069
-     * @throws InvalidDataTypeException
1070
-     * @throws InvalidInterfaceException
1071
-     * @throws ReflectionException
1072
-     */
1073
-    public function billing_info()
1074
-    {
1075
-        $payment_method = $this->payment_method();
1076
-        if (! $payment_method) {
1077
-            EE_Error::add_error(
1078
-                __(
1079
-                    'Could not find billing info for transaction because no gateway has been used for it yet',
1080
-                    'event_espresso'
1081
-                ),
1082
-                __FILE__,
1083
-                __FUNCTION__,
1084
-                __LINE__
1085
-            );
1086
-            return null;
1087
-        }
1088
-        $primary_reg = $this->primary_registration();
1089
-        if (! $primary_reg) {
1090
-            EE_Error::add_error(
1091
-                __(
1092
-                    'Cannot get billing info for gateway %s on transaction because no primary registration exists',
1093
-                    'event_espresso'
1094
-                ),
1095
-                __FILE__,
1096
-                __FUNCTION__,
1097
-                __LINE__
1098
-            );
1099
-            return null;
1100
-        }
1101
-        $attendee = $primary_reg->attendee();
1102
-        if (! $attendee) {
1103
-            EE_Error::add_error(
1104
-                __(
1105
-                    'Cannot get billing info for gateway %s on transaction because the primary registration has no attendee exists',
1106
-                    'event_espresso'
1107
-                ),
1108
-                __FILE__,
1109
-                __FUNCTION__,
1110
-                __LINE__
1111
-            );
1112
-            return null;
1113
-        }
1114
-        return $attendee->billing_info_for_payment_method($payment_method);
1115
-    }
1116
-
1117
-
1118
-    /**
1119
-     * Gets PMD_ID
1120
-     *
1121
-     * @return int
1122
-     * @throws EE_Error
1123
-     * @throws InvalidArgumentException
1124
-     * @throws InvalidDataTypeException
1125
-     * @throws InvalidInterfaceException
1126
-     * @throws ReflectionException
1127
-     */
1128
-    public function payment_method_ID()
1129
-    {
1130
-        return $this->get('PMD_ID');
1131
-    }
1132
-
1133
-
1134
-    /**
1135
-     * Sets PMD_ID
1136
-     *
1137
-     * @param int $PMD_ID
1138
-     * @throws EE_Error
1139
-     * @throws InvalidArgumentException
1140
-     * @throws InvalidDataTypeException
1141
-     * @throws InvalidInterfaceException
1142
-     * @throws ReflectionException
1143
-     */
1144
-    public function set_payment_method_ID($PMD_ID)
1145
-    {
1146
-        $this->set('PMD_ID', $PMD_ID);
1147
-    }
1148
-
1149
-
1150
-    /**
1151
-     * Gets the last-used payment method on this transaction
1152
-     * (we COULD just use the last-made payment, but some payment methods, namely
1153
-     * offline ones, dont' create payments)
1154
-     *
1155
-     * @return EE_Payment_Method
1156
-     * @throws EE_Error
1157
-     * @throws InvalidArgumentException
1158
-     * @throws InvalidDataTypeException
1159
-     * @throws InvalidInterfaceException
1160
-     * @throws ReflectionException
1161
-     */
1162
-    public function payment_method()
1163
-    {
1164
-        $pm = $this->get_first_related('Payment_Method');
1165
-        if ($pm instanceof EE_Payment_Method) {
1166
-            return $pm;
1167
-        }
1168
-        $last_payment = $this->last_payment();
1169
-        if ($last_payment instanceof EE_Payment && $last_payment->payment_method()) {
1170
-            return $last_payment->payment_method();
1171
-        }
1172
-        return null;
1173
-    }
1174
-
1175
-
1176
-    /**
1177
-     * Gets the last payment made
1178
-     *
1179
-     * @return EE_Base_Class|EE_Payment
1180
-     * @throws EE_Error
1181
-     * @throws InvalidArgumentException
1182
-     * @throws InvalidDataTypeException
1183
-     * @throws InvalidInterfaceException
1184
-     * @throws ReflectionException
1185
-     */
1186
-    public function last_payment()
1187
-    {
1188
-        return $this->get_first_related('Payment', array('order_by' => array('PAY_ID' => 'desc')));
1189
-    }
1190
-
1191
-
1192
-    /**
1193
-     * Gets all the line items which are unrelated to tickets on this transaction
1194
-     *
1195
-     * @return EE_Line_Item[]
1196
-     * @throws EE_Error
1197
-     * @throws InvalidArgumentException
1198
-     * @throws InvalidDataTypeException
1199
-     * @throws InvalidInterfaceException
1200
-     * @throws ReflectionException
1201
-     */
1202
-    public function non_ticket_line_items()
1203
-    {
1204
-        return EEM_Line_Item::instance()->get_all_non_ticket_line_items_for_transaction($this->ID());
1205
-    }
1206
-
1207
-
1208
-    /**
1209
-     * possibly toggles TXN status
1210
-     *
1211
-     * @param  boolean $update whether to save the TXN
1212
-     * @return bool whether the TXN was saved
1213
-     * @throws EE_Error
1214
-     * @throws InvalidArgumentException
1215
-     * @throws InvalidDataTypeException
1216
-     * @throws InvalidInterfaceException
1217
-     * @throws ReflectionException
1218
-     * @throws RuntimeException
1219
-     */
1220
-    public function update_status_based_on_total_paid($update = true)
1221
-    {
1222
-        // set transaction status based on comparison of TXN_paid vs TXN_total
1223
-        if (EEH_Money::compare_floats($this->paid(), $this->total(), '>')) {
1224
-            $new_txn_status = EEM_Transaction::overpaid_status_code;
1225
-        } elseif (EEH_Money::compare_floats($this->paid(), $this->total())) {
1226
-            $new_txn_status = EEM_Transaction::complete_status_code;
1227
-        } elseif (EEH_Money::compare_floats($this->paid(), $this->total(), '<')) {
1228
-            $new_txn_status = EEM_Transaction::incomplete_status_code;
1229
-        } else {
1230
-            throw new RuntimeException(
1231
-                __('The total paid calculation for this transaction is inaccurate.', 'event_espresso')
1232
-            );
1233
-        }
1234
-        if ($new_txn_status !== $this->status_ID()) {
1235
-            $this->set_status($new_txn_status);
1236
-            if ($update) {
1237
-                return $this->save() ? true : false;
1238
-            }
1239
-        }
1240
-        return false;
1241
-    }
1242
-
1243
-
1244
-    /**
1245
-     * Updates the transaction's status and total_paid based on all the payments
1246
-     * that apply to it
1247
-     *
1248
-     * @deprecated
1249
-     * @return array|bool
1250
-     * @throws EE_Error
1251
-     * @throws InvalidArgumentException
1252
-     * @throws ReflectionException
1253
-     * @throws InvalidDataTypeException
1254
-     * @throws InvalidInterfaceException
1255
-     */
1256
-    public function update_based_on_payments()
1257
-    {
1258
-        EE_Error::doing_it_wrong(
1259
-            __CLASS__ . '::' . __FUNCTION__,
1260
-            sprintf(
1261
-                __('This method is deprecated. Please use "%s" instead', 'event_espresso'),
1262
-                'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'
1263
-            ),
1264
-            '4.6.0'
1265
-        );
1266
-        /** @type EE_Transaction_Processor $transaction_processor */
1267
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
1268
-        return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment($this);
1269
-    }
1270
-
1271
-
1272
-    /**
1273
-     * @return string
1274
-     */
1275
-    public function old_txn_status()
1276
-    {
1277
-        return $this->_old_txn_status;
1278
-    }
1279
-
1280
-
1281
-    /**
1282
-     * @param string $old_txn_status
1283
-     */
1284
-    public function set_old_txn_status($old_txn_status)
1285
-    {
1286
-        // only set the first time
1287
-        if ($this->_old_txn_status === null) {
1288
-            $this->_old_txn_status = $old_txn_status;
1289
-        }
1290
-    }
1291
-
1292
-
1293
-    /**
1294
-     * reg_status_updated
1295
-     *
1296
-     * @return bool
1297
-     * @throws EE_Error
1298
-     * @throws InvalidArgumentException
1299
-     * @throws InvalidDataTypeException
1300
-     * @throws InvalidInterfaceException
1301
-     * @throws ReflectionException
1302
-     */
1303
-    public function txn_status_updated()
1304
-    {
1305
-        return $this->status_ID() !== $this->_old_txn_status && $this->_old_txn_status !== null;
1306
-    }
1307
-
1308
-
1309
-    /**
1310
-     * _reg_steps_completed
1311
-     * if $check_all is TRUE, then returns TRUE if ALL reg steps have been marked as completed,
1312
-     * if a $reg_step_slug is provided, then this step will be skipped when testing for completion
1313
-     * if $check_all is FALSE and a $reg_step_slug is provided, then ONLY that reg step will be tested for completion
1314
-     *
1315
-     * @param string $reg_step_slug
1316
-     * @param bool   $check_all
1317
-     * @return bool|int
1318
-     * @throws EE_Error
1319
-     * @throws InvalidArgumentException
1320
-     * @throws InvalidDataTypeException
1321
-     * @throws InvalidInterfaceException
1322
-     * @throws ReflectionException
1323
-     */
1324
-    private function _reg_steps_completed($reg_step_slug = '', $check_all = true)
1325
-    {
1326
-        $reg_steps = $this->reg_steps();
1327
-        if (! is_array($reg_steps) || empty($reg_steps)) {
1328
-            return false;
1329
-        }
1330
-        // loop thru reg steps array)
1331
-        foreach ($reg_steps as $slug => $reg_step_completed) {
1332
-            // if NOT checking ALL steps (only checking one step)
1333
-            if (! $check_all) {
1334
-                // and this is the one
1335
-                if ($slug === $reg_step_slug) {
1336
-                    return $reg_step_completed;
1337
-                }
1338
-                // skip to next reg step in loop
1339
-                continue;
1340
-            }
1341
-            // $check_all must be true, else we would never have gotten to this point
1342
-            if ($slug === $reg_step_slug) {
1343
-                // if we reach this point, then we are testing either:
1344
-                // all_reg_steps_completed_except() or
1345
-                // all_reg_steps_completed_except_final_step(),
1346
-                // and since this is the reg step EXCEPTION being tested
1347
-                // we want to return true (yes true) if this reg step is NOT completed
1348
-                // ie: "is everything completed except the final step?"
1349
-                // "that is correct... the final step is not completed, but all others are."
1350
-                return $reg_step_completed !== true;
1351
-            }
1352
-            if ($reg_step_completed !== true) {
1353
-                // if any reg step is NOT completed, then ALL steps are not completed
1354
-                return false;
1355
-            }
1356
-        }
1357
-        return true;
1358
-    }
1359
-
1360
-
1361
-    /**
1362
-     * all_reg_steps_completed
1363
-     * returns:
1364
-     *    true if ALL reg steps have been marked as completed
1365
-     *        or false if any step is not completed
1366
-     *
1367
-     * @return bool
1368
-     * @throws EE_Error
1369
-     * @throws InvalidArgumentException
1370
-     * @throws InvalidDataTypeException
1371
-     * @throws InvalidInterfaceException
1372
-     * @throws ReflectionException
1373
-     */
1374
-    public function all_reg_steps_completed()
1375
-    {
1376
-        return $this->_reg_steps_completed();
1377
-    }
1378
-
1379
-
1380
-    /**
1381
-     * all_reg_steps_completed_except
1382
-     * returns:
1383
-     *        true if ALL reg steps, except a particular step that you wish to skip over, have been marked as completed
1384
-     *        or false if any other step is not completed
1385
-     *        or false if ALL steps are completed including the exception you are testing !!!
1386
-     *
1387
-     * @param string $exception
1388
-     * @return bool
1389
-     * @throws EE_Error
1390
-     * @throws InvalidArgumentException
1391
-     * @throws InvalidDataTypeException
1392
-     * @throws InvalidInterfaceException
1393
-     * @throws ReflectionException
1394
-     */
1395
-    public function all_reg_steps_completed_except($exception = '')
1396
-    {
1397
-        return $this->_reg_steps_completed($exception);
1398
-    }
1399
-
1400
-
1401
-    /**
1402
-     * all_reg_steps_completed_except
1403
-     * returns:
1404
-     *        true if ALL reg steps, except the final step, have been marked as completed
1405
-     *        or false if any step is not completed
1406
-     *    or false if ALL steps are completed including the final step !!!
1407
-     *
1408
-     * @return bool
1409
-     * @throws EE_Error
1410
-     * @throws InvalidArgumentException
1411
-     * @throws InvalidDataTypeException
1412
-     * @throws InvalidInterfaceException
1413
-     * @throws ReflectionException
1414
-     */
1415
-    public function all_reg_steps_completed_except_final_step()
1416
-    {
1417
-        return $this->_reg_steps_completed('finalize_registration');
1418
-    }
1419
-
1420
-
1421
-    /**
1422
-     * reg_step_completed
1423
-     * returns:
1424
-     *    true if a specific reg step has been marked as completed
1425
-     *    a Unix timestamp if it has been initialized but not yet completed,
1426
-     *    or false if it has not yet been initialized
1427
-     *
1428
-     * @param string $reg_step_slug
1429
-     * @return bool|int
1430
-     * @throws EE_Error
1431
-     * @throws InvalidArgumentException
1432
-     * @throws InvalidDataTypeException
1433
-     * @throws InvalidInterfaceException
1434
-     * @throws ReflectionException
1435
-     */
1436
-    public function reg_step_completed($reg_step_slug)
1437
-    {
1438
-        return $this->_reg_steps_completed($reg_step_slug, false);
1439
-    }
1440
-
1441
-
1442
-    /**
1443
-     * completed_final_reg_step
1444
-     * returns:
1445
-     *    true if the finalize_registration reg step has been marked as completed
1446
-     *    a Unix timestamp if it has been initialized but not yet completed,
1447
-     *    or false if it has not yet been initialized
1448
-     *
1449
-     * @return bool|int
1450
-     * @throws EE_Error
1451
-     * @throws InvalidArgumentException
1452
-     * @throws InvalidDataTypeException
1453
-     * @throws InvalidInterfaceException
1454
-     * @throws ReflectionException
1455
-     */
1456
-    public function final_reg_step_completed()
1457
-    {
1458
-        return $this->_reg_steps_completed('finalize_registration', false);
1459
-    }
1460
-
1461
-
1462
-    /**
1463
-     * set_reg_step_initiated
1464
-     * given a valid TXN_reg_step, this sets it's value to a unix timestamp
1465
-     *
1466
-     * @param string $reg_step_slug
1467
-     * @return boolean
1468
-     * @throws EE_Error
1469
-     * @throws InvalidArgumentException
1470
-     * @throws InvalidDataTypeException
1471
-     * @throws InvalidInterfaceException
1472
-     * @throws ReflectionException
1473
-     */
1474
-    public function set_reg_step_initiated($reg_step_slug)
1475
-    {
1476
-        return $this->_set_reg_step_completed_status($reg_step_slug, time());
1477
-    }
1478
-
1479
-
1480
-    /**
1481
-     * set_reg_step_completed
1482
-     * given a valid TXN_reg_step, this sets the step as completed
1483
-     *
1484
-     * @param string $reg_step_slug
1485
-     * @return boolean
1486
-     * @throws EE_Error
1487
-     * @throws InvalidArgumentException
1488
-     * @throws InvalidDataTypeException
1489
-     * @throws InvalidInterfaceException
1490
-     * @throws ReflectionException
1491
-     */
1492
-    public function set_reg_step_completed($reg_step_slug)
1493
-    {
1494
-        return $this->_set_reg_step_completed_status($reg_step_slug, true);
1495
-    }
1496
-
1497
-
1498
-    /**
1499
-     * set_reg_step_completed
1500
-     * given a valid TXN_reg_step slug, this sets the step as NOT completed
1501
-     *
1502
-     * @param string $reg_step_slug
1503
-     * @return boolean
1504
-     * @throws EE_Error
1505
-     * @throws InvalidArgumentException
1506
-     * @throws InvalidDataTypeException
1507
-     * @throws InvalidInterfaceException
1508
-     * @throws ReflectionException
1509
-     */
1510
-    public function set_reg_step_not_completed($reg_step_slug)
1511
-    {
1512
-        return $this->_set_reg_step_completed_status($reg_step_slug, false);
1513
-    }
1514
-
1515
-
1516
-    /**
1517
-     * set_reg_step_completed
1518
-     * given a valid reg step slug, this sets the TXN_reg_step completed status which is either:
1519
-     *
1520
-     * @param  string      $reg_step_slug
1521
-     * @param  boolean|int $status
1522
-     * @return boolean
1523
-     * @throws EE_Error
1524
-     * @throws InvalidArgumentException
1525
-     * @throws InvalidDataTypeException
1526
-     * @throws InvalidInterfaceException
1527
-     * @throws ReflectionException
1528
-     */
1529
-    private function _set_reg_step_completed_status($reg_step_slug, $status)
1530
-    {
1531
-        // validate status
1532
-        $status = is_bool($status) || is_int($status) ? $status : false;
1533
-        // get reg steps array
1534
-        $txn_reg_steps = $this->reg_steps();
1535
-        // if reg step does NOT exist
1536
-        if (! isset($txn_reg_steps[ $reg_step_slug ])) {
1537
-            return false;
1538
-        }
1539
-        // if  we're trying to complete a step that is already completed
1540
-        if ($txn_reg_steps[ $reg_step_slug ] === true) {
1541
-            return true;
1542
-        }
1543
-        // if  we're trying to complete a step that hasn't even started
1544
-        if ($status === true && $txn_reg_steps[ $reg_step_slug ] === false) {
1545
-            return false;
1546
-        }
1547
-        // if current status value matches the incoming value (no change)
1548
-        // type casting as int means values should collapse to either 0, 1, or a timestamp like 1234567890
1549
-        if ((int) $txn_reg_steps[ $reg_step_slug ] === (int) $status) {
1550
-            // this will happen in cases where multiple AJAX requests occur during the same step
1551
-            return true;
1552
-        }
1553
-        // if we're trying to set a start time, but it has already been set...
1554
-        if (is_numeric($status) && is_numeric($txn_reg_steps[ $reg_step_slug ])) {
1555
-            // skip the update below, but don't return FALSE so that errors won't be displayed
1556
-            return true;
1557
-        }
1558
-        // update completed status
1559
-        $txn_reg_steps[ $reg_step_slug ] = $status;
1560
-        $this->set_reg_steps($txn_reg_steps);
1561
-        $this->save();
1562
-        return true;
1563
-    }
1564
-
1565
-
1566
-    /**
1567
-     * remove_reg_step
1568
-     * given a valid TXN_reg_step slug, this will remove (unset)
1569
-     * the reg step from the TXN reg step array
1570
-     *
1571
-     * @param string $reg_step_slug
1572
-     * @return void
1573
-     * @throws EE_Error
1574
-     * @throws InvalidArgumentException
1575
-     * @throws InvalidDataTypeException
1576
-     * @throws InvalidInterfaceException
1577
-     * @throws ReflectionException
1578
-     */
1579
-    public function remove_reg_step($reg_step_slug)
1580
-    {
1581
-        // get reg steps array
1582
-        $txn_reg_steps = $this->reg_steps();
1583
-        unset($txn_reg_steps[ $reg_step_slug ]);
1584
-        $this->set_reg_steps($txn_reg_steps);
1585
-    }
1586
-
1587
-
1588
-    /**
1589
-     * toggle_failed_transaction_status
1590
-     * upgrades a TXNs status from failed to abandoned,
1591
-     * meaning that contact information has been captured for at least one registrant
1592
-     *
1593
-     * @param bool $save
1594
-     * @return bool
1595
-     * @throws EE_Error
1596
-     * @throws InvalidArgumentException
1597
-     * @throws InvalidDataTypeException
1598
-     * @throws InvalidInterfaceException
1599
-     * @throws ReflectionException
1600
-     */
1601
-    public function toggle_failed_transaction_status($save = true)
1602
-    {
1603
-        // if TXN status is still set as "failed"...
1604
-        if ($this->status_ID() === EEM_Transaction::failed_status_code) {
1605
-            $this->set_status(EEM_Transaction::abandoned_status_code);
1606
-            if ($save) {
1607
-                $this->save();
1608
-            }
1609
-            return true;
1610
-        }
1611
-        return false;
1612
-    }
1613
-
1614
-
1615
-    /**
1616
-     * toggle_abandoned_transaction_status
1617
-     * upgrades a TXNs status from failed or abandoned to incomplete
1618
-     *
1619
-     * @return bool
1620
-     * @throws EE_Error
1621
-     * @throws InvalidArgumentException
1622
-     * @throws InvalidDataTypeException
1623
-     * @throws InvalidInterfaceException
1624
-     * @throws ReflectionException
1625
-     */
1626
-    public function toggle_abandoned_transaction_status()
1627
-    {
1628
-        // if TXN status has not been updated already due to a payment, and is still set as "failed" or "abandoned"...
1629
-        $txn_status = $this->status_ID();
1630
-        if ($txn_status === EEM_Transaction::failed_status_code
1631
-            || $txn_status === EEM_Transaction::abandoned_status_code
1632
-        ) {
1633
-            // if a contact record for the primary registrant has been created
1634
-            if ($this->primary_registration() instanceof EE_Registration
1635
-                && $this->primary_registration()->attendee() instanceof EE_Attendee
1636
-            ) {
1637
-                $this->set_status(EEM_Transaction::incomplete_status_code);
1638
-            } else {
1639
-                // no contact record? yer abandoned!
1640
-                $this->set_status(EEM_Transaction::abandoned_status_code);
1641
-            }
1642
-            return true;
1643
-        }
1644
-        return false;
1645
-    }
1646
-
1647
-
1648
-    /**
1649
-     * checks if an Abandoned TXN has any related payments, and if so,
1650
-     * updates the TXN status based on the amount paid
1651
-     *
1652
-     * @throws EE_Error
1653
-     * @throws InvalidDataTypeException
1654
-     * @throws InvalidInterfaceException
1655
-     * @throws InvalidArgumentException
1656
-     * @throws RuntimeException
1657
-     * @throws ReflectionException
1658
-     */
1659
-    public function verify_abandoned_transaction_status()
1660
-    {
1661
-        if ($this->status_ID() !== EEM_Transaction::abandoned_status_code) {
1662
-            return;
1663
-        }
1664
-        $payments = $this->get_many_related('Payment');
1665
-        if (! empty($payments)) {
1666
-            foreach ($payments as $payment) {
1667
-                if ($payment instanceof EE_Payment) {
1668
-                    // kk this TXN should NOT be abandoned
1669
-                    $this->update_status_based_on_total_paid();
1670
-                    if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1671
-                        EE_Error::add_attention(
1672
-                            sprintf(
1673
-                                esc_html__(
1674
-                                    'The status for Transaction #%1$d has been updated from "Abandoned" to "%2$s", because at least one payment has been made towards it. If the payment appears in the "Payment Details" table below, you may need to edit its status and/or other details as well.',
1675
-                                    'event_espresso'
1676
-                                ),
1677
-                                $this->ID(),
1678
-                                $this->pretty_status()
1679
-                            )
1680
-                        );
1681
-                    }
1682
-                    // get final reg step status
1683
-                    $finalized = $this->final_reg_step_completed();
1684
-                    // if the 'finalize_registration' step has been initiated (has a timestamp)
1685
-                    // but has not yet been fully completed (TRUE)
1686
-                    if (is_int($finalized) && $finalized !== false && $finalized !== true) {
1687
-                        $this->set_reg_step_completed('finalize_registration');
1688
-                        $this->save();
1689
-                    }
1690
-                }
1691
-            }
1692
-        }
1693
-    }
16
+	/**
17
+	 * The length of time in seconds that a lock is applied before being considered expired.
18
+	 * It is not long because a transaction should only be locked for the duration of the request that locked it
19
+	 */
20
+	const LOCK_EXPIRATION = 2;
21
+
22
+	/**
23
+	 * txn status upon initial construction.
24
+	 *
25
+	 * @var string
26
+	 */
27
+	protected $_old_txn_status;
28
+
29
+
30
+	/**
31
+	 * @param array  $props_n_values          incoming values
32
+	 * @param string $timezone                incoming timezone
33
+	 *                                        (if not set the timezone set for the website will be used.)
34
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
35
+	 *                                        date_format and the second value is the time format
36
+	 * @return EE_Transaction
37
+	 * @throws EE_Error
38
+	 * @throws InvalidArgumentException
39
+	 * @throws InvalidDataTypeException
40
+	 * @throws InvalidInterfaceException
41
+	 * @throws ReflectionException
42
+	 */
43
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
44
+	{
45
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
46
+		$txn = $has_object
47
+			? $has_object
48
+			: new self($props_n_values, false, $timezone, $date_formats);
49
+		if (! $has_object) {
50
+			$txn->set_old_txn_status($txn->status_ID());
51
+		}
52
+		return $txn;
53
+	}
54
+
55
+
56
+	/**
57
+	 * @param array  $props_n_values  incoming values from the database
58
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
59
+	 *                                the website will be used.
60
+	 * @return EE_Transaction
61
+	 * @throws EE_Error
62
+	 * @throws InvalidArgumentException
63
+	 * @throws InvalidDataTypeException
64
+	 * @throws InvalidInterfaceException
65
+	 * @throws ReflectionException
66
+	 */
67
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
68
+	{
69
+		$txn = new self($props_n_values, true, $timezone);
70
+		$txn->set_old_txn_status($txn->status_ID());
71
+		return $txn;
72
+	}
73
+
74
+
75
+	/**
76
+	 * Sets a meta field indicating that this TXN is locked and should not be updated in the db.
77
+	 * If a lock has already been set, then we will attempt to remove it in case it has expired.
78
+	 * If that also fails, then an exception is thrown.
79
+	 *
80
+	 * @throws EE_Error
81
+	 * @throws InvalidArgumentException
82
+	 * @throws InvalidDataTypeException
83
+	 * @throws InvalidInterfaceException
84
+	 * @throws ReflectionException
85
+	 */
86
+	public function lock()
87
+	{
88
+		// attempt to set lock, but if that fails...
89
+		if (! $this->add_extra_meta('lock', time(), true)) {
90
+			// then attempt to remove the lock in case it is expired
91
+			if ($this->_remove_expired_lock()) {
92
+				// if removal was successful, then try setting lock again
93
+				$this->lock();
94
+			} else {
95
+				// but if the lock can not be removed, then throw an exception
96
+				throw new EE_Error(
97
+					sprintf(
98
+						__(
99
+							'Could not lock Transaction %1$d because it is already locked, meaning another part of the system is currently editing it. It should already be unlocked by the time you read this, so please refresh the page and try again.',
100
+							'event_espresso'
101
+						),
102
+						$this->ID()
103
+					)
104
+				);
105
+			}
106
+		}
107
+	}
108
+
109
+
110
+	/**
111
+	 * removes transaction lock applied in EE_Transaction::lock()
112
+	 *
113
+	 * @return int
114
+	 * @throws EE_Error
115
+	 * @throws InvalidArgumentException
116
+	 * @throws InvalidDataTypeException
117
+	 * @throws InvalidInterfaceException
118
+	 * @throws ReflectionException
119
+	 */
120
+	public function unlock()
121
+	{
122
+		return $this->delete_extra_meta('lock');
123
+	}
124
+
125
+
126
+	/**
127
+	 * Decides whether or not now is the right time to update the transaction.
128
+	 * This is useful because we don't always know if it is safe to update the transaction
129
+	 * and its related data. why?
130
+	 * because it's possible that the transaction is being used in another
131
+	 * request and could overwrite anything we save.
132
+	 * So we want to only update the txn once we know that won't happen.
133
+	 * We also check that the lock isn't expired, and remove it if it is
134
+	 *
135
+	 * @return boolean
136
+	 * @throws EE_Error
137
+	 * @throws InvalidArgumentException
138
+	 * @throws InvalidDataTypeException
139
+	 * @throws InvalidInterfaceException
140
+	 * @throws ReflectionException
141
+	 */
142
+	public function is_locked()
143
+	{
144
+		// if TXN is not locked, then return false immediately
145
+		if (! $this->_get_lock()) {
146
+			return false;
147
+		}
148
+		// if not, then let's try and remove the lock in case it's expired...
149
+		// _remove_expired_lock() returns 0 when lock is valid (ie: removed = false)
150
+		// and a positive number if the lock was removed (ie: number of locks deleted),
151
+		// so we need to return the opposite
152
+		return ! $this->_remove_expired_lock() ? true : false;
153
+	}
154
+
155
+
156
+	/**
157
+	 * Gets the meta field indicating that this TXN is locked
158
+	 *
159
+	 * @return int
160
+	 * @throws EE_Error
161
+	 * @throws InvalidArgumentException
162
+	 * @throws InvalidDataTypeException
163
+	 * @throws InvalidInterfaceException
164
+	 * @throws ReflectionException
165
+	 */
166
+	protected function _get_lock()
167
+	{
168
+		return (int) $this->get_extra_meta('lock', true, 0);
169
+	}
170
+
171
+
172
+	/**
173
+	 * If the lock on this transaction is expired, then we want to remove it so that the transaction can be updated
174
+	 *
175
+	 * @return int
176
+	 * @throws EE_Error
177
+	 * @throws InvalidArgumentException
178
+	 * @throws InvalidDataTypeException
179
+	 * @throws InvalidInterfaceException
180
+	 * @throws ReflectionException
181
+	 */
182
+	protected function _remove_expired_lock()
183
+	{
184
+		$locked = $this->_get_lock();
185
+		if ($locked && time() - EE_Transaction::LOCK_EXPIRATION > $locked) {
186
+			return $this->unlock();
187
+		}
188
+		return 0;
189
+	}
190
+
191
+
192
+	/**
193
+	 * Set transaction total
194
+	 *
195
+	 * @param float $total total value of transaction
196
+	 * @throws EE_Error
197
+	 * @throws InvalidArgumentException
198
+	 * @throws InvalidDataTypeException
199
+	 * @throws InvalidInterfaceException
200
+	 * @throws ReflectionException
201
+	 */
202
+	public function set_total($total = 0.00)
203
+	{
204
+		$this->set('TXN_total', (float) $total);
205
+	}
206
+
207
+
208
+	/**
209
+	 * Set Total Amount Paid to Date
210
+	 *
211
+	 * @param float $total_paid total amount paid to date (sum of all payments)
212
+	 * @throws EE_Error
213
+	 * @throws InvalidArgumentException
214
+	 * @throws InvalidDataTypeException
215
+	 * @throws InvalidInterfaceException
216
+	 * @throws ReflectionException
217
+	 */
218
+	public function set_paid($total_paid = 0.00)
219
+	{
220
+		$this->set('TXN_paid', (float) $total_paid);
221
+	}
222
+
223
+
224
+	/**
225
+	 * Set transaction status
226
+	 *
227
+	 * @param string $status        whether the transaction is open, declined, accepted,
228
+	 *                              or any number of custom values that can be set
229
+	 * @throws EE_Error
230
+	 * @throws InvalidArgumentException
231
+	 * @throws InvalidDataTypeException
232
+	 * @throws InvalidInterfaceException
233
+	 * @throws ReflectionException
234
+	 */
235
+	public function set_status($status = '')
236
+	{
237
+		$this->set('STS_ID', $status);
238
+	}
239
+
240
+
241
+	/**
242
+	 * Set hash salt
243
+	 *
244
+	 * @param string $hash_salt required for some payment gateways
245
+	 * @throws EE_Error
246
+	 * @throws InvalidArgumentException
247
+	 * @throws InvalidDataTypeException
248
+	 * @throws InvalidInterfaceException
249
+	 * @throws ReflectionException
250
+	 */
251
+	public function set_hash_salt($hash_salt = '')
252
+	{
253
+		$this->set('TXN_hash_salt', $hash_salt);
254
+	}
255
+
256
+
257
+	/**
258
+	 * Sets TXN_reg_steps array
259
+	 *
260
+	 * @param array $txn_reg_steps
261
+	 * @throws EE_Error
262
+	 * @throws InvalidArgumentException
263
+	 * @throws InvalidDataTypeException
264
+	 * @throws InvalidInterfaceException
265
+	 * @throws ReflectionException
266
+	 */
267
+	public function set_reg_steps(array $txn_reg_steps)
268
+	{
269
+		$this->set('TXN_reg_steps', $txn_reg_steps);
270
+	}
271
+
272
+
273
+	/**
274
+	 * Gets TXN_reg_steps
275
+	 *
276
+	 * @return array
277
+	 * @throws EE_Error
278
+	 * @throws InvalidArgumentException
279
+	 * @throws InvalidDataTypeException
280
+	 * @throws InvalidInterfaceException
281
+	 * @throws ReflectionException
282
+	 */
283
+	public function reg_steps()
284
+	{
285
+		$TXN_reg_steps = $this->get('TXN_reg_steps');
286
+		return is_array($TXN_reg_steps) ? (array) $TXN_reg_steps : array();
287
+	}
288
+
289
+
290
+	/**
291
+	 * @return string of transaction's total cost, with currency symbol and decimal
292
+	 * @throws EE_Error
293
+	 * @throws InvalidArgumentException
294
+	 * @throws InvalidDataTypeException
295
+	 * @throws InvalidInterfaceException
296
+	 * @throws ReflectionException
297
+	 */
298
+	public function pretty_total()
299
+	{
300
+		return $this->get_pretty('TXN_total');
301
+	}
302
+
303
+
304
+	/**
305
+	 * Gets the amount paid in a pretty string (formatted and with currency symbol)
306
+	 *
307
+	 * @return string
308
+	 * @throws EE_Error
309
+	 * @throws InvalidArgumentException
310
+	 * @throws InvalidDataTypeException
311
+	 * @throws InvalidInterfaceException
312
+	 * @throws ReflectionException
313
+	 */
314
+	public function pretty_paid()
315
+	{
316
+		return $this->get_pretty('TXN_paid');
317
+	}
318
+
319
+
320
+	/**
321
+	 * calculate the amount remaining for this transaction and return;
322
+	 *
323
+	 * @return float amount remaining
324
+	 * @throws EE_Error
325
+	 * @throws InvalidArgumentException
326
+	 * @throws InvalidDataTypeException
327
+	 * @throws InvalidInterfaceException
328
+	 * @throws ReflectionException
329
+	 */
330
+	public function remaining()
331
+	{
332
+		return $this->total() - $this->paid();
333
+	}
334
+
335
+
336
+	/**
337
+	 * get Transaction Total
338
+	 *
339
+	 * @return float
340
+	 * @throws EE_Error
341
+	 * @throws InvalidArgumentException
342
+	 * @throws InvalidDataTypeException
343
+	 * @throws InvalidInterfaceException
344
+	 * @throws ReflectionException
345
+	 */
346
+	public function total()
347
+	{
348
+		return (float) $this->get('TXN_total');
349
+	}
350
+
351
+
352
+	/**
353
+	 * get Total Amount Paid to Date
354
+	 *
355
+	 * @return float
356
+	 * @throws EE_Error
357
+	 * @throws InvalidArgumentException
358
+	 * @throws InvalidDataTypeException
359
+	 * @throws InvalidInterfaceException
360
+	 * @throws ReflectionException
361
+	 */
362
+	public function paid()
363
+	{
364
+		return (float) $this->get('TXN_paid');
365
+	}
366
+
367
+
368
+	/**
369
+	 * @return mixed|null
370
+	 * @throws EE_Error
371
+	 * @throws InvalidArgumentException
372
+	 * @throws InvalidDataTypeException
373
+	 * @throws InvalidInterfaceException
374
+	 * @throws ReflectionException
375
+	 */
376
+	public function get_cart_session()
377
+	{
378
+		$session_data = (array) $this->get('TXN_session_data');
379
+		return isset($session_data['cart']) && $session_data['cart'] instanceof EE_Cart
380
+			? $session_data['cart']
381
+			: null;
382
+	}
383
+
384
+
385
+	/**
386
+	 * get Transaction session data
387
+	 *
388
+	 * @return array|mixed
389
+	 * @throws EE_Error
390
+	 * @throws InvalidArgumentException
391
+	 * @throws InvalidDataTypeException
392
+	 * @throws InvalidInterfaceException
393
+	 * @throws ReflectionException
394
+	 */
395
+	public function session_data()
396
+	{
397
+		$session_data = $this->get('TXN_session_data');
398
+		if (empty($session_data)) {
399
+			$session_data = array(
400
+				'id'            => null,
401
+				'user_id'       => null,
402
+				'ip_address'    => null,
403
+				'user_agent'    => null,
404
+				'init_access'   => null,
405
+				'last_access'   => null,
406
+				'pages_visited' => array(),
407
+			);
408
+		}
409
+		return $session_data;
410
+	}
411
+
412
+
413
+	/**
414
+	 * Set session data within the TXN object
415
+	 *
416
+	 * @param EE_Session|array $session_data
417
+	 * @throws EE_Error
418
+	 * @throws InvalidArgumentException
419
+	 * @throws InvalidDataTypeException
420
+	 * @throws InvalidInterfaceException
421
+	 * @throws ReflectionException
422
+	 */
423
+	public function set_txn_session_data($session_data)
424
+	{
425
+		if ($session_data instanceof EE_Session) {
426
+			$this->set('TXN_session_data', $session_data->get_session_data(null, true));
427
+		} else {
428
+			$this->set('TXN_session_data', $session_data);
429
+		}
430
+	}
431
+
432
+
433
+	/**
434
+	 * get Transaction hash salt
435
+	 *
436
+	 * @return mixed
437
+	 * @throws EE_Error
438
+	 * @throws InvalidArgumentException
439
+	 * @throws InvalidDataTypeException
440
+	 * @throws InvalidInterfaceException
441
+	 * @throws ReflectionException
442
+	 */
443
+	public function hash_salt_()
444
+	{
445
+		return $this->get('TXN_hash_salt');
446
+	}
447
+
448
+
449
+	/**
450
+	 * Returns the transaction datetime as either:
451
+	 *            - unix timestamp format ($format = false, $gmt = true)
452
+	 *            - formatted date string including the UTC (timezone) offset ($format = true ($gmt
453
+	 *              has no affect with this option)), this also may include a timezone abbreviation if the
454
+	 *              set timezone in this class differs from what the timezone is on the blog.
455
+	 *            - formatted date string including the UTC (timezone) offset (default).
456
+	 *
457
+	 * @param boolean $format   - whether to return a unix timestamp (default) or formatted date string
458
+	 * @param boolean $gmt      - whether to return a unix timestamp with UTC offset applied (default)
459
+	 *                          or no UTC offset applied
460
+	 * @return string | int
461
+	 * @throws EE_Error
462
+	 * @throws InvalidArgumentException
463
+	 * @throws InvalidDataTypeException
464
+	 * @throws InvalidInterfaceException
465
+	 * @throws ReflectionException
466
+	 */
467
+	public function datetime($format = false, $gmt = false)
468
+	{
469
+		if ($format) {
470
+			return $this->get_pretty('TXN_timestamp');
471
+		}
472
+		if ($gmt) {
473
+			return $this->get_raw('TXN_timestamp');
474
+		}
475
+		return $this->get('TXN_timestamp');
476
+	}
477
+
478
+
479
+	/**
480
+	 * Gets registrations on this transaction
481
+	 *
482
+	 * @param array   $query_params array of query parameters
483
+	 * @param boolean $get_cached   TRUE to retrieve cached registrations or FALSE to pull from the db
484
+	 * @return EE_Base_Class[]|EE_Registration[]
485
+	 * @throws EE_Error
486
+	 * @throws InvalidArgumentException
487
+	 * @throws InvalidDataTypeException
488
+	 * @throws InvalidInterfaceException
489
+	 * @throws ReflectionException
490
+	 */
491
+	public function registrations($query_params = array(), $get_cached = false)
492
+	{
493
+		$query_params = (empty($query_params) || ! is_array($query_params))
494
+			? array(
495
+				'order_by' => array(
496
+					'Event.EVT_name'     => 'ASC',
497
+					'Attendee.ATT_lname' => 'ASC',
498
+					'Attendee.ATT_fname' => 'ASC',
499
+				),
500
+			)
501
+			: $query_params;
502
+		$query_params = $get_cached ? array() : $query_params;
503
+		return $this->get_many_related('Registration', $query_params);
504
+	}
505
+
506
+
507
+	/**
508
+	 * Gets all the attendees for this transaction (handy for use with EE_Attendee's get_registrations_for_event
509
+	 * function for getting attendees and how many registrations they each have for an event)
510
+	 *
511
+	 * @return mixed EE_Attendee[] by default, int if $output is set to 'COUNT'
512
+	 * @throws EE_Error
513
+	 * @throws InvalidArgumentException
514
+	 * @throws InvalidDataTypeException
515
+	 * @throws InvalidInterfaceException
516
+	 * @throws ReflectionException
517
+	 */
518
+	public function attendees()
519
+	{
520
+		return $this->get_many_related('Attendee', array(array('Registration.Transaction.TXN_ID' => $this->ID())));
521
+	}
522
+
523
+
524
+	/**
525
+	 * Gets payments for this transaction. Unlike other such functions, order by 'DESC' by default
526
+	 *
527
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
528
+	 * @return EE_Base_Class[]|EE_Payment[]
529
+	 * @throws EE_Error
530
+	 * @throws InvalidArgumentException
531
+	 * @throws InvalidDataTypeException
532
+	 * @throws InvalidInterfaceException
533
+	 * @throws ReflectionException
534
+	 */
535
+	public function payments($query_params = array())
536
+	{
537
+		return $this->get_many_related('Payment', $query_params);
538
+	}
539
+
540
+
541
+	/**
542
+	 * gets only approved payments for this transaction
543
+	 *
544
+	 * @return EE_Base_Class[]|EE_Payment[]
545
+	 * @throws EE_Error
546
+	 * @throws InvalidArgumentException
547
+	 * @throws ReflectionException
548
+	 * @throws InvalidDataTypeException
549
+	 * @throws InvalidInterfaceException
550
+	 */
551
+	public function approved_payments()
552
+	{
553
+		EE_Registry::instance()->load_model('Payment');
554
+		return $this->get_many_related(
555
+			'Payment',
556
+			array(
557
+				array('STS_ID' => EEM_Payment::status_id_approved),
558
+				'order_by' => array('PAY_timestamp' => 'DESC'),
559
+			)
560
+		);
561
+	}
562
+
563
+
564
+	/**
565
+	 * Gets all payments which have not been approved
566
+	 *
567
+	 * @return EE_Base_Class[]|EEI_Payment[]
568
+	 * @throws EE_Error if a model is misconfigured somehow
569
+	 * @throws InvalidArgumentException
570
+	 * @throws InvalidDataTypeException
571
+	 * @throws InvalidInterfaceException
572
+	 * @throws ReflectionException
573
+	 */
574
+	public function pending_payments()
575
+	{
576
+		return $this->get_many_related(
577
+			'Payment',
578
+			array(
579
+				array(
580
+					'STS_ID' => EEM_Payment::status_id_pending,
581
+				),
582
+				'order_by' => array(
583
+					'PAY_timestamp' => 'DESC',
584
+				),
585
+			)
586
+		);
587
+	}
588
+
589
+
590
+	/**
591
+	 * echoes $this->pretty_status()
592
+	 *
593
+	 * @param bool $show_icons
594
+	 * @throws EE_Error
595
+	 * @throws InvalidArgumentException
596
+	 * @throws InvalidDataTypeException
597
+	 * @throws InvalidInterfaceException
598
+	 * @throws ReflectionException
599
+	 */
600
+	public function e_pretty_status($show_icons = false)
601
+	{
602
+		echo $this->pretty_status($show_icons);
603
+	}
604
+
605
+
606
+	/**
607
+	 * returns a pretty version of the status, good for displaying to users
608
+	 *
609
+	 * @param bool $show_icons
610
+	 * @return string
611
+	 * @throws EE_Error
612
+	 * @throws InvalidArgumentException
613
+	 * @throws InvalidDataTypeException
614
+	 * @throws InvalidInterfaceException
615
+	 * @throws ReflectionException
616
+	 */
617
+	public function pretty_status($show_icons = false)
618
+	{
619
+		$status = EEM_Status::instance()->localized_status(
620
+			array($this->status_ID() => __('unknown', 'event_espresso')),
621
+			false,
622
+			'sentence'
623
+		);
624
+		$icon = '';
625
+		switch ($this->status_ID()) {
626
+			case EEM_Transaction::complete_status_code:
627
+				$icon = $show_icons ? '<span class="dashicons dashicons-yes ee-icon-size-24 green-text"></span>' : '';
628
+				break;
629
+			case EEM_Transaction::incomplete_status_code:
630
+				$icon = $show_icons ? '<span class="dashicons dashicons-marker ee-icon-size-16 lt-blue-text"></span>'
631
+					: '';
632
+				break;
633
+			case EEM_Transaction::abandoned_status_code:
634
+				$icon = $show_icons ? '<span class="dashicons dashicons-marker ee-icon-size-16 red-text"></span>' : '';
635
+				break;
636
+			case EEM_Transaction::failed_status_code:
637
+				$icon = $show_icons ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>' : '';
638
+				break;
639
+			case EEM_Transaction::overpaid_status_code:
640
+				$icon = $show_icons ? '<span class="dashicons dashicons-plus ee-icon-size-16 orange-text"></span>' : '';
641
+				break;
642
+		}
643
+		return $icon . $status[ $this->status_ID() ];
644
+	}
645
+
646
+
647
+	/**
648
+	 * get Transaction Status
649
+	 *
650
+	 * @return mixed
651
+	 * @throws EE_Error
652
+	 * @throws InvalidArgumentException
653
+	 * @throws InvalidDataTypeException
654
+	 * @throws InvalidInterfaceException
655
+	 * @throws ReflectionException
656
+	 */
657
+	public function status_ID()
658
+	{
659
+		return $this->get('STS_ID');
660
+	}
661
+
662
+
663
+	/**
664
+	 * Returns TRUE or FALSE for whether or not this transaction cost any money
665
+	 *
666
+	 * @return boolean
667
+	 * @throws EE_Error
668
+	 * @throws InvalidArgumentException
669
+	 * @throws InvalidDataTypeException
670
+	 * @throws InvalidInterfaceException
671
+	 * @throws ReflectionException
672
+	 */
673
+	public function is_free()
674
+	{
675
+		return EEH_Money::compare_floats($this->get('TXN_total'), 0, '==');
676
+	}
677
+
678
+
679
+	/**
680
+	 * Returns whether this transaction is complete
681
+	 * Useful in templates and other logic for deciding if we should ask for another payment...
682
+	 *
683
+	 * @return boolean
684
+	 * @throws EE_Error
685
+	 * @throws InvalidArgumentException
686
+	 * @throws InvalidDataTypeException
687
+	 * @throws InvalidInterfaceException
688
+	 * @throws ReflectionException
689
+	 */
690
+	public function is_completed()
691
+	{
692
+		return $this->status_ID() === EEM_Transaction::complete_status_code;
693
+	}
694
+
695
+
696
+	/**
697
+	 * Returns whether this transaction is incomplete
698
+	 * Useful in templates and other logic for deciding if we should ask for another payment...
699
+	 *
700
+	 * @return boolean
701
+	 * @throws EE_Error
702
+	 * @throws InvalidArgumentException
703
+	 * @throws InvalidDataTypeException
704
+	 * @throws InvalidInterfaceException
705
+	 * @throws ReflectionException
706
+	 */
707
+	public function is_incomplete()
708
+	{
709
+		return $this->status_ID() === EEM_Transaction::incomplete_status_code;
710
+	}
711
+
712
+
713
+	/**
714
+	 * Returns whether this transaction is overpaid
715
+	 * Useful in templates and other logic for deciding if monies need to be refunded
716
+	 *
717
+	 * @return boolean
718
+	 * @throws EE_Error
719
+	 * @throws InvalidArgumentException
720
+	 * @throws InvalidDataTypeException
721
+	 * @throws InvalidInterfaceException
722
+	 * @throws ReflectionException
723
+	 */
724
+	public function is_overpaid()
725
+	{
726
+		return $this->status_ID() === EEM_Transaction::overpaid_status_code;
727
+	}
728
+
729
+
730
+	/**
731
+	 * Returns whether this transaction was abandoned
732
+	 * meaning that the transaction/registration process was somehow interrupted and never completed
733
+	 * but that contact information exists for at least one registrant
734
+	 *
735
+	 * @return boolean
736
+	 * @throws EE_Error
737
+	 * @throws InvalidArgumentException
738
+	 * @throws InvalidDataTypeException
739
+	 * @throws InvalidInterfaceException
740
+	 * @throws ReflectionException
741
+	 */
742
+	public function is_abandoned()
743
+	{
744
+		return $this->status_ID() === EEM_Transaction::abandoned_status_code;
745
+	}
746
+
747
+
748
+	/**
749
+	 * Returns whether this transaction failed
750
+	 * meaning that the transaction/registration process was somehow interrupted and never completed
751
+	 * and that NO contact information exists for any registrants
752
+	 *
753
+	 * @return boolean
754
+	 * @throws EE_Error
755
+	 * @throws InvalidArgumentException
756
+	 * @throws InvalidDataTypeException
757
+	 * @throws InvalidInterfaceException
758
+	 * @throws ReflectionException
759
+	 */
760
+	public function failed()
761
+	{
762
+		return $this->status_ID() === EEM_Transaction::failed_status_code;
763
+	}
764
+
765
+
766
+	/**
767
+	 * This returns the url for the invoice of this transaction
768
+	 *
769
+	 * @param string $type 'html' or 'pdf' (default is pdf)
770
+	 * @return string
771
+	 * @throws EE_Error
772
+	 * @throws InvalidArgumentException
773
+	 * @throws InvalidDataTypeException
774
+	 * @throws InvalidInterfaceException
775
+	 * @throws ReflectionException
776
+	 */
777
+	public function invoice_url($type = 'html')
778
+	{
779
+		$REG = $this->primary_registration();
780
+		if (! $REG instanceof EE_Registration) {
781
+			return '';
782
+		}
783
+		return $REG->invoice_url($type);
784
+	}
785
+
786
+
787
+	/**
788
+	 * Gets the primary registration only
789
+	 *
790
+	 * @return EE_Base_Class|EE_Registration
791
+	 * @throws EE_Error
792
+	 * @throws InvalidArgumentException
793
+	 * @throws InvalidDataTypeException
794
+	 * @throws InvalidInterfaceException
795
+	 * @throws ReflectionException
796
+	 */
797
+	public function primary_registration()
798
+	{
799
+		$registrations = (array) $this->get_many_related(
800
+			'Registration',
801
+			array(array('REG_count' => EEM_Registration::PRIMARY_REGISTRANT_COUNT))
802
+		);
803
+		foreach ($registrations as $registration) {
804
+			// valid registration that is NOT cancelled or declined ?
805
+			if ($registration instanceof EE_Registration
806
+				&& ! in_array($registration->status_ID(), EEM_Registration::closed_reg_statuses(), true)
807
+			) {
808
+				return $registration;
809
+			}
810
+		}
811
+		// nothing valid found, so just return first thing from array of results
812
+		return reset($registrations);
813
+	}
814
+
815
+
816
+	/**
817
+	 * Gets the URL for viewing the receipt
818
+	 *
819
+	 * @param string $type 'pdf' or 'html' (default is 'html')
820
+	 * @return string
821
+	 * @throws EE_Error
822
+	 * @throws InvalidArgumentException
823
+	 * @throws InvalidDataTypeException
824
+	 * @throws InvalidInterfaceException
825
+	 * @throws ReflectionException
826
+	 */
827
+	public function receipt_url($type = 'html')
828
+	{
829
+		$REG = $this->primary_registration();
830
+		if (! $REG instanceof EE_Registration) {
831
+			return '';
832
+		}
833
+		return $REG->receipt_url($type);
834
+	}
835
+
836
+
837
+	/**
838
+	 * Gets the URL of the thank you page with this registration REG_url_link added as
839
+	 * a query parameter
840
+	 *
841
+	 * @return string
842
+	 * @throws EE_Error
843
+	 * @throws InvalidArgumentException
844
+	 * @throws InvalidDataTypeException
845
+	 * @throws InvalidInterfaceException
846
+	 * @throws ReflectionException
847
+	 */
848
+	public function payment_overview_url()
849
+	{
850
+		$primary_registration = $this->primary_registration();
851
+		return $primary_registration instanceof EE_Registration ? $primary_registration->payment_overview_url() : false;
852
+	}
853
+
854
+
855
+	/**
856
+	 * @return string
857
+	 * @throws EE_Error
858
+	 * @throws InvalidArgumentException
859
+	 * @throws InvalidDataTypeException
860
+	 * @throws InvalidInterfaceException
861
+	 * @throws ReflectionException
862
+	 */
863
+	public function gateway_response_on_transaction()
864
+	{
865
+		$payment = $this->get_first_related('Payment');
866
+		return $payment instanceof EE_Payment ? $payment->gateway_response() : '';
867
+	}
868
+
869
+
870
+	/**
871
+	 * Get the status object of this object
872
+	 *
873
+	 * @return EE_Base_Class|EE_Status
874
+	 * @throws EE_Error
875
+	 * @throws InvalidArgumentException
876
+	 * @throws InvalidDataTypeException
877
+	 * @throws InvalidInterfaceException
878
+	 * @throws ReflectionException
879
+	 */
880
+	public function status_obj()
881
+	{
882
+		return $this->get_first_related('Status');
883
+	}
884
+
885
+
886
+	/**
887
+	 * Gets all the extra meta info on this payment
888
+	 *
889
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
890
+	 * @return EE_Base_Class[]|EE_Extra_Meta
891
+	 * @throws EE_Error
892
+	 * @throws InvalidArgumentException
893
+	 * @throws InvalidDataTypeException
894
+	 * @throws InvalidInterfaceException
895
+	 * @throws ReflectionException
896
+	 */
897
+	public function extra_meta($query_params = array())
898
+	{
899
+		return $this->get_many_related('Extra_Meta', $query_params);
900
+	}
901
+
902
+
903
+	/**
904
+	 * Wrapper for _add_relation_to
905
+	 *
906
+	 * @param EE_Registration $registration
907
+	 * @return EE_Base_Class the relation was added to
908
+	 * @throws EE_Error
909
+	 * @throws InvalidArgumentException
910
+	 * @throws InvalidDataTypeException
911
+	 * @throws InvalidInterfaceException
912
+	 * @throws ReflectionException
913
+	 */
914
+	public function add_registration(EE_Registration $registration)
915
+	{
916
+		return $this->_add_relation_to($registration, 'Registration');
917
+	}
918
+
919
+
920
+	/**
921
+	 * Removes the given registration from being related (even before saving this transaction).
922
+	 * If an ID/index is provided and this transaction isn't saved yet, removes it from list of cached relations
923
+	 *
924
+	 * @param int $registration_or_id
925
+	 * @return EE_Base_Class that was removed from being related
926
+	 * @throws EE_Error
927
+	 * @throws InvalidArgumentException
928
+	 * @throws InvalidDataTypeException
929
+	 * @throws InvalidInterfaceException
930
+	 * @throws ReflectionException
931
+	 */
932
+	public function remove_registration_with_id($registration_or_id)
933
+	{
934
+		return $this->_remove_relation_to($registration_or_id, 'Registration');
935
+	}
936
+
937
+
938
+	/**
939
+	 * Gets all the line items which are for ACTUAL items
940
+	 *
941
+	 * @return EE_Line_Item[]
942
+	 * @throws EE_Error
943
+	 * @throws InvalidArgumentException
944
+	 * @throws InvalidDataTypeException
945
+	 * @throws InvalidInterfaceException
946
+	 * @throws ReflectionException
947
+	 */
948
+	public function items_purchased()
949
+	{
950
+		return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_line_item)));
951
+	}
952
+
953
+
954
+	/**
955
+	 * Wrapper for _add_relation_to
956
+	 *
957
+	 * @param EE_Line_Item $line_item
958
+	 * @return EE_Base_Class the relation was added to
959
+	 * @throws EE_Error
960
+	 * @throws InvalidArgumentException
961
+	 * @throws InvalidDataTypeException
962
+	 * @throws InvalidInterfaceException
963
+	 * @throws ReflectionException
964
+	 */
965
+	public function add_line_item(EE_Line_Item $line_item)
966
+	{
967
+		return $this->_add_relation_to($line_item, 'Line_Item');
968
+	}
969
+
970
+
971
+	/**
972
+	 * Gets ALL the line items related to this transaction (unstructured)
973
+	 *
974
+	 * @param array $query_params
975
+	 * @return EE_Base_Class[]|EE_Line_Item[]
976
+	 * @throws EE_Error
977
+	 * @throws InvalidArgumentException
978
+	 * @throws InvalidDataTypeException
979
+	 * @throws InvalidInterfaceException
980
+	 * @throws ReflectionException
981
+	 */
982
+	public function line_items($query_params = array())
983
+	{
984
+		return $this->get_many_related('Line_Item', $query_params);
985
+	}
986
+
987
+
988
+	/**
989
+	 * Gets all the line items which are taxes on the total
990
+	 *
991
+	 * @return EE_Line_Item[]
992
+	 * @throws EE_Error
993
+	 * @throws InvalidArgumentException
994
+	 * @throws InvalidDataTypeException
995
+	 * @throws InvalidInterfaceException
996
+	 * @throws ReflectionException
997
+	 */
998
+	public function tax_items()
999
+	{
1000
+		return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax)));
1001
+	}
1002
+
1003
+
1004
+	/**
1005
+	 * Gets the total line item (which is a parent of all other related line items,
1006
+	 * meaning it takes them all into account on its total)
1007
+	 *
1008
+	 * @param bool $create_if_not_found
1009
+	 * @return \EE_Line_Item
1010
+	 * @throws EE_Error
1011
+	 * @throws InvalidArgumentException
1012
+	 * @throws InvalidDataTypeException
1013
+	 * @throws InvalidInterfaceException
1014
+	 * @throws ReflectionException
1015
+	 */
1016
+	public function total_line_item($create_if_not_found = true)
1017
+	{
1018
+		$item = $this->get_first_related('Line_Item', array(array('LIN_type' => EEM_Line_Item::type_total)));
1019
+		if (! $item && $create_if_not_found) {
1020
+			$item = EEH_Line_Item::create_total_line_item($this);
1021
+		}
1022
+		return $item;
1023
+	}
1024
+
1025
+
1026
+	/**
1027
+	 * Returns the total amount of tax on this transaction
1028
+	 * (assumes there's only one tax subtotal line item)
1029
+	 *
1030
+	 * @return float
1031
+	 * @throws EE_Error
1032
+	 * @throws InvalidArgumentException
1033
+	 * @throws InvalidDataTypeException
1034
+	 * @throws InvalidInterfaceException
1035
+	 * @throws ReflectionException
1036
+	 */
1037
+	public function tax_total()
1038
+	{
1039
+		$tax_line_item = $this->tax_total_line_item();
1040
+		if ($tax_line_item) {
1041
+			return (float) $tax_line_item->total();
1042
+		}
1043
+		return (float) 0;
1044
+	}
1045
+
1046
+
1047
+	/**
1048
+	 * Gets the tax subtotal line item (assumes there's only one)
1049
+	 *
1050
+	 * @return EE_Line_Item
1051
+	 * @throws EE_Error
1052
+	 * @throws InvalidArgumentException
1053
+	 * @throws InvalidDataTypeException
1054
+	 * @throws InvalidInterfaceException
1055
+	 * @throws ReflectionException
1056
+	 */
1057
+	public function tax_total_line_item()
1058
+	{
1059
+		return EEH_Line_Item::get_taxes_subtotal($this->total_line_item());
1060
+	}
1061
+
1062
+
1063
+	/**
1064
+	 * Gets the array of billing info for the gateway and for this transaction's primary registration's attendee.
1065
+	 *
1066
+	 * @return EE_Form_Section_Proper
1067
+	 * @throws EE_Error
1068
+	 * @throws InvalidArgumentException
1069
+	 * @throws InvalidDataTypeException
1070
+	 * @throws InvalidInterfaceException
1071
+	 * @throws ReflectionException
1072
+	 */
1073
+	public function billing_info()
1074
+	{
1075
+		$payment_method = $this->payment_method();
1076
+		if (! $payment_method) {
1077
+			EE_Error::add_error(
1078
+				__(
1079
+					'Could not find billing info for transaction because no gateway has been used for it yet',
1080
+					'event_espresso'
1081
+				),
1082
+				__FILE__,
1083
+				__FUNCTION__,
1084
+				__LINE__
1085
+			);
1086
+			return null;
1087
+		}
1088
+		$primary_reg = $this->primary_registration();
1089
+		if (! $primary_reg) {
1090
+			EE_Error::add_error(
1091
+				__(
1092
+					'Cannot get billing info for gateway %s on transaction because no primary registration exists',
1093
+					'event_espresso'
1094
+				),
1095
+				__FILE__,
1096
+				__FUNCTION__,
1097
+				__LINE__
1098
+			);
1099
+			return null;
1100
+		}
1101
+		$attendee = $primary_reg->attendee();
1102
+		if (! $attendee) {
1103
+			EE_Error::add_error(
1104
+				__(
1105
+					'Cannot get billing info for gateway %s on transaction because the primary registration has no attendee exists',
1106
+					'event_espresso'
1107
+				),
1108
+				__FILE__,
1109
+				__FUNCTION__,
1110
+				__LINE__
1111
+			);
1112
+			return null;
1113
+		}
1114
+		return $attendee->billing_info_for_payment_method($payment_method);
1115
+	}
1116
+
1117
+
1118
+	/**
1119
+	 * Gets PMD_ID
1120
+	 *
1121
+	 * @return int
1122
+	 * @throws EE_Error
1123
+	 * @throws InvalidArgumentException
1124
+	 * @throws InvalidDataTypeException
1125
+	 * @throws InvalidInterfaceException
1126
+	 * @throws ReflectionException
1127
+	 */
1128
+	public function payment_method_ID()
1129
+	{
1130
+		return $this->get('PMD_ID');
1131
+	}
1132
+
1133
+
1134
+	/**
1135
+	 * Sets PMD_ID
1136
+	 *
1137
+	 * @param int $PMD_ID
1138
+	 * @throws EE_Error
1139
+	 * @throws InvalidArgumentException
1140
+	 * @throws InvalidDataTypeException
1141
+	 * @throws InvalidInterfaceException
1142
+	 * @throws ReflectionException
1143
+	 */
1144
+	public function set_payment_method_ID($PMD_ID)
1145
+	{
1146
+		$this->set('PMD_ID', $PMD_ID);
1147
+	}
1148
+
1149
+
1150
+	/**
1151
+	 * Gets the last-used payment method on this transaction
1152
+	 * (we COULD just use the last-made payment, but some payment methods, namely
1153
+	 * offline ones, dont' create payments)
1154
+	 *
1155
+	 * @return EE_Payment_Method
1156
+	 * @throws EE_Error
1157
+	 * @throws InvalidArgumentException
1158
+	 * @throws InvalidDataTypeException
1159
+	 * @throws InvalidInterfaceException
1160
+	 * @throws ReflectionException
1161
+	 */
1162
+	public function payment_method()
1163
+	{
1164
+		$pm = $this->get_first_related('Payment_Method');
1165
+		if ($pm instanceof EE_Payment_Method) {
1166
+			return $pm;
1167
+		}
1168
+		$last_payment = $this->last_payment();
1169
+		if ($last_payment instanceof EE_Payment && $last_payment->payment_method()) {
1170
+			return $last_payment->payment_method();
1171
+		}
1172
+		return null;
1173
+	}
1174
+
1175
+
1176
+	/**
1177
+	 * Gets the last payment made
1178
+	 *
1179
+	 * @return EE_Base_Class|EE_Payment
1180
+	 * @throws EE_Error
1181
+	 * @throws InvalidArgumentException
1182
+	 * @throws InvalidDataTypeException
1183
+	 * @throws InvalidInterfaceException
1184
+	 * @throws ReflectionException
1185
+	 */
1186
+	public function last_payment()
1187
+	{
1188
+		return $this->get_first_related('Payment', array('order_by' => array('PAY_ID' => 'desc')));
1189
+	}
1190
+
1191
+
1192
+	/**
1193
+	 * Gets all the line items which are unrelated to tickets on this transaction
1194
+	 *
1195
+	 * @return EE_Line_Item[]
1196
+	 * @throws EE_Error
1197
+	 * @throws InvalidArgumentException
1198
+	 * @throws InvalidDataTypeException
1199
+	 * @throws InvalidInterfaceException
1200
+	 * @throws ReflectionException
1201
+	 */
1202
+	public function non_ticket_line_items()
1203
+	{
1204
+		return EEM_Line_Item::instance()->get_all_non_ticket_line_items_for_transaction($this->ID());
1205
+	}
1206
+
1207
+
1208
+	/**
1209
+	 * possibly toggles TXN status
1210
+	 *
1211
+	 * @param  boolean $update whether to save the TXN
1212
+	 * @return bool whether the TXN was saved
1213
+	 * @throws EE_Error
1214
+	 * @throws InvalidArgumentException
1215
+	 * @throws InvalidDataTypeException
1216
+	 * @throws InvalidInterfaceException
1217
+	 * @throws ReflectionException
1218
+	 * @throws RuntimeException
1219
+	 */
1220
+	public function update_status_based_on_total_paid($update = true)
1221
+	{
1222
+		// set transaction status based on comparison of TXN_paid vs TXN_total
1223
+		if (EEH_Money::compare_floats($this->paid(), $this->total(), '>')) {
1224
+			$new_txn_status = EEM_Transaction::overpaid_status_code;
1225
+		} elseif (EEH_Money::compare_floats($this->paid(), $this->total())) {
1226
+			$new_txn_status = EEM_Transaction::complete_status_code;
1227
+		} elseif (EEH_Money::compare_floats($this->paid(), $this->total(), '<')) {
1228
+			$new_txn_status = EEM_Transaction::incomplete_status_code;
1229
+		} else {
1230
+			throw new RuntimeException(
1231
+				__('The total paid calculation for this transaction is inaccurate.', 'event_espresso')
1232
+			);
1233
+		}
1234
+		if ($new_txn_status !== $this->status_ID()) {
1235
+			$this->set_status($new_txn_status);
1236
+			if ($update) {
1237
+				return $this->save() ? true : false;
1238
+			}
1239
+		}
1240
+		return false;
1241
+	}
1242
+
1243
+
1244
+	/**
1245
+	 * Updates the transaction's status and total_paid based on all the payments
1246
+	 * that apply to it
1247
+	 *
1248
+	 * @deprecated
1249
+	 * @return array|bool
1250
+	 * @throws EE_Error
1251
+	 * @throws InvalidArgumentException
1252
+	 * @throws ReflectionException
1253
+	 * @throws InvalidDataTypeException
1254
+	 * @throws InvalidInterfaceException
1255
+	 */
1256
+	public function update_based_on_payments()
1257
+	{
1258
+		EE_Error::doing_it_wrong(
1259
+			__CLASS__ . '::' . __FUNCTION__,
1260
+			sprintf(
1261
+				__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
1262
+				'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'
1263
+			),
1264
+			'4.6.0'
1265
+		);
1266
+		/** @type EE_Transaction_Processor $transaction_processor */
1267
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
1268
+		return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment($this);
1269
+	}
1270
+
1271
+
1272
+	/**
1273
+	 * @return string
1274
+	 */
1275
+	public function old_txn_status()
1276
+	{
1277
+		return $this->_old_txn_status;
1278
+	}
1279
+
1280
+
1281
+	/**
1282
+	 * @param string $old_txn_status
1283
+	 */
1284
+	public function set_old_txn_status($old_txn_status)
1285
+	{
1286
+		// only set the first time
1287
+		if ($this->_old_txn_status === null) {
1288
+			$this->_old_txn_status = $old_txn_status;
1289
+		}
1290
+	}
1291
+
1292
+
1293
+	/**
1294
+	 * reg_status_updated
1295
+	 *
1296
+	 * @return bool
1297
+	 * @throws EE_Error
1298
+	 * @throws InvalidArgumentException
1299
+	 * @throws InvalidDataTypeException
1300
+	 * @throws InvalidInterfaceException
1301
+	 * @throws ReflectionException
1302
+	 */
1303
+	public function txn_status_updated()
1304
+	{
1305
+		return $this->status_ID() !== $this->_old_txn_status && $this->_old_txn_status !== null;
1306
+	}
1307
+
1308
+
1309
+	/**
1310
+	 * _reg_steps_completed
1311
+	 * if $check_all is TRUE, then returns TRUE if ALL reg steps have been marked as completed,
1312
+	 * if a $reg_step_slug is provided, then this step will be skipped when testing for completion
1313
+	 * if $check_all is FALSE and a $reg_step_slug is provided, then ONLY that reg step will be tested for completion
1314
+	 *
1315
+	 * @param string $reg_step_slug
1316
+	 * @param bool   $check_all
1317
+	 * @return bool|int
1318
+	 * @throws EE_Error
1319
+	 * @throws InvalidArgumentException
1320
+	 * @throws InvalidDataTypeException
1321
+	 * @throws InvalidInterfaceException
1322
+	 * @throws ReflectionException
1323
+	 */
1324
+	private function _reg_steps_completed($reg_step_slug = '', $check_all = true)
1325
+	{
1326
+		$reg_steps = $this->reg_steps();
1327
+		if (! is_array($reg_steps) || empty($reg_steps)) {
1328
+			return false;
1329
+		}
1330
+		// loop thru reg steps array)
1331
+		foreach ($reg_steps as $slug => $reg_step_completed) {
1332
+			// if NOT checking ALL steps (only checking one step)
1333
+			if (! $check_all) {
1334
+				// and this is the one
1335
+				if ($slug === $reg_step_slug) {
1336
+					return $reg_step_completed;
1337
+				}
1338
+				// skip to next reg step in loop
1339
+				continue;
1340
+			}
1341
+			// $check_all must be true, else we would never have gotten to this point
1342
+			if ($slug === $reg_step_slug) {
1343
+				// if we reach this point, then we are testing either:
1344
+				// all_reg_steps_completed_except() or
1345
+				// all_reg_steps_completed_except_final_step(),
1346
+				// and since this is the reg step EXCEPTION being tested
1347
+				// we want to return true (yes true) if this reg step is NOT completed
1348
+				// ie: "is everything completed except the final step?"
1349
+				// "that is correct... the final step is not completed, but all others are."
1350
+				return $reg_step_completed !== true;
1351
+			}
1352
+			if ($reg_step_completed !== true) {
1353
+				// if any reg step is NOT completed, then ALL steps are not completed
1354
+				return false;
1355
+			}
1356
+		}
1357
+		return true;
1358
+	}
1359
+
1360
+
1361
+	/**
1362
+	 * all_reg_steps_completed
1363
+	 * returns:
1364
+	 *    true if ALL reg steps have been marked as completed
1365
+	 *        or false if any step is not completed
1366
+	 *
1367
+	 * @return bool
1368
+	 * @throws EE_Error
1369
+	 * @throws InvalidArgumentException
1370
+	 * @throws InvalidDataTypeException
1371
+	 * @throws InvalidInterfaceException
1372
+	 * @throws ReflectionException
1373
+	 */
1374
+	public function all_reg_steps_completed()
1375
+	{
1376
+		return $this->_reg_steps_completed();
1377
+	}
1378
+
1379
+
1380
+	/**
1381
+	 * all_reg_steps_completed_except
1382
+	 * returns:
1383
+	 *        true if ALL reg steps, except a particular step that you wish to skip over, have been marked as completed
1384
+	 *        or false if any other step is not completed
1385
+	 *        or false if ALL steps are completed including the exception you are testing !!!
1386
+	 *
1387
+	 * @param string $exception
1388
+	 * @return bool
1389
+	 * @throws EE_Error
1390
+	 * @throws InvalidArgumentException
1391
+	 * @throws InvalidDataTypeException
1392
+	 * @throws InvalidInterfaceException
1393
+	 * @throws ReflectionException
1394
+	 */
1395
+	public function all_reg_steps_completed_except($exception = '')
1396
+	{
1397
+		return $this->_reg_steps_completed($exception);
1398
+	}
1399
+
1400
+
1401
+	/**
1402
+	 * all_reg_steps_completed_except
1403
+	 * returns:
1404
+	 *        true if ALL reg steps, except the final step, have been marked as completed
1405
+	 *        or false if any step is not completed
1406
+	 *    or false if ALL steps are completed including the final step !!!
1407
+	 *
1408
+	 * @return bool
1409
+	 * @throws EE_Error
1410
+	 * @throws InvalidArgumentException
1411
+	 * @throws InvalidDataTypeException
1412
+	 * @throws InvalidInterfaceException
1413
+	 * @throws ReflectionException
1414
+	 */
1415
+	public function all_reg_steps_completed_except_final_step()
1416
+	{
1417
+		return $this->_reg_steps_completed('finalize_registration');
1418
+	}
1419
+
1420
+
1421
+	/**
1422
+	 * reg_step_completed
1423
+	 * returns:
1424
+	 *    true if a specific reg step has been marked as completed
1425
+	 *    a Unix timestamp if it has been initialized but not yet completed,
1426
+	 *    or false if it has not yet been initialized
1427
+	 *
1428
+	 * @param string $reg_step_slug
1429
+	 * @return bool|int
1430
+	 * @throws EE_Error
1431
+	 * @throws InvalidArgumentException
1432
+	 * @throws InvalidDataTypeException
1433
+	 * @throws InvalidInterfaceException
1434
+	 * @throws ReflectionException
1435
+	 */
1436
+	public function reg_step_completed($reg_step_slug)
1437
+	{
1438
+		return $this->_reg_steps_completed($reg_step_slug, false);
1439
+	}
1440
+
1441
+
1442
+	/**
1443
+	 * completed_final_reg_step
1444
+	 * returns:
1445
+	 *    true if the finalize_registration reg step has been marked as completed
1446
+	 *    a Unix timestamp if it has been initialized but not yet completed,
1447
+	 *    or false if it has not yet been initialized
1448
+	 *
1449
+	 * @return bool|int
1450
+	 * @throws EE_Error
1451
+	 * @throws InvalidArgumentException
1452
+	 * @throws InvalidDataTypeException
1453
+	 * @throws InvalidInterfaceException
1454
+	 * @throws ReflectionException
1455
+	 */
1456
+	public function final_reg_step_completed()
1457
+	{
1458
+		return $this->_reg_steps_completed('finalize_registration', false);
1459
+	}
1460
+
1461
+
1462
+	/**
1463
+	 * set_reg_step_initiated
1464
+	 * given a valid TXN_reg_step, this sets it's value to a unix timestamp
1465
+	 *
1466
+	 * @param string $reg_step_slug
1467
+	 * @return boolean
1468
+	 * @throws EE_Error
1469
+	 * @throws InvalidArgumentException
1470
+	 * @throws InvalidDataTypeException
1471
+	 * @throws InvalidInterfaceException
1472
+	 * @throws ReflectionException
1473
+	 */
1474
+	public function set_reg_step_initiated($reg_step_slug)
1475
+	{
1476
+		return $this->_set_reg_step_completed_status($reg_step_slug, time());
1477
+	}
1478
+
1479
+
1480
+	/**
1481
+	 * set_reg_step_completed
1482
+	 * given a valid TXN_reg_step, this sets the step as completed
1483
+	 *
1484
+	 * @param string $reg_step_slug
1485
+	 * @return boolean
1486
+	 * @throws EE_Error
1487
+	 * @throws InvalidArgumentException
1488
+	 * @throws InvalidDataTypeException
1489
+	 * @throws InvalidInterfaceException
1490
+	 * @throws ReflectionException
1491
+	 */
1492
+	public function set_reg_step_completed($reg_step_slug)
1493
+	{
1494
+		return $this->_set_reg_step_completed_status($reg_step_slug, true);
1495
+	}
1496
+
1497
+
1498
+	/**
1499
+	 * set_reg_step_completed
1500
+	 * given a valid TXN_reg_step slug, this sets the step as NOT completed
1501
+	 *
1502
+	 * @param string $reg_step_slug
1503
+	 * @return boolean
1504
+	 * @throws EE_Error
1505
+	 * @throws InvalidArgumentException
1506
+	 * @throws InvalidDataTypeException
1507
+	 * @throws InvalidInterfaceException
1508
+	 * @throws ReflectionException
1509
+	 */
1510
+	public function set_reg_step_not_completed($reg_step_slug)
1511
+	{
1512
+		return $this->_set_reg_step_completed_status($reg_step_slug, false);
1513
+	}
1514
+
1515
+
1516
+	/**
1517
+	 * set_reg_step_completed
1518
+	 * given a valid reg step slug, this sets the TXN_reg_step completed status which is either:
1519
+	 *
1520
+	 * @param  string      $reg_step_slug
1521
+	 * @param  boolean|int $status
1522
+	 * @return boolean
1523
+	 * @throws EE_Error
1524
+	 * @throws InvalidArgumentException
1525
+	 * @throws InvalidDataTypeException
1526
+	 * @throws InvalidInterfaceException
1527
+	 * @throws ReflectionException
1528
+	 */
1529
+	private function _set_reg_step_completed_status($reg_step_slug, $status)
1530
+	{
1531
+		// validate status
1532
+		$status = is_bool($status) || is_int($status) ? $status : false;
1533
+		// get reg steps array
1534
+		$txn_reg_steps = $this->reg_steps();
1535
+		// if reg step does NOT exist
1536
+		if (! isset($txn_reg_steps[ $reg_step_slug ])) {
1537
+			return false;
1538
+		}
1539
+		// if  we're trying to complete a step that is already completed
1540
+		if ($txn_reg_steps[ $reg_step_slug ] === true) {
1541
+			return true;
1542
+		}
1543
+		// if  we're trying to complete a step that hasn't even started
1544
+		if ($status === true && $txn_reg_steps[ $reg_step_slug ] === false) {
1545
+			return false;
1546
+		}
1547
+		// if current status value matches the incoming value (no change)
1548
+		// type casting as int means values should collapse to either 0, 1, or a timestamp like 1234567890
1549
+		if ((int) $txn_reg_steps[ $reg_step_slug ] === (int) $status) {
1550
+			// this will happen in cases where multiple AJAX requests occur during the same step
1551
+			return true;
1552
+		}
1553
+		// if we're trying to set a start time, but it has already been set...
1554
+		if (is_numeric($status) && is_numeric($txn_reg_steps[ $reg_step_slug ])) {
1555
+			// skip the update below, but don't return FALSE so that errors won't be displayed
1556
+			return true;
1557
+		}
1558
+		// update completed status
1559
+		$txn_reg_steps[ $reg_step_slug ] = $status;
1560
+		$this->set_reg_steps($txn_reg_steps);
1561
+		$this->save();
1562
+		return true;
1563
+	}
1564
+
1565
+
1566
+	/**
1567
+	 * remove_reg_step
1568
+	 * given a valid TXN_reg_step slug, this will remove (unset)
1569
+	 * the reg step from the TXN reg step array
1570
+	 *
1571
+	 * @param string $reg_step_slug
1572
+	 * @return void
1573
+	 * @throws EE_Error
1574
+	 * @throws InvalidArgumentException
1575
+	 * @throws InvalidDataTypeException
1576
+	 * @throws InvalidInterfaceException
1577
+	 * @throws ReflectionException
1578
+	 */
1579
+	public function remove_reg_step($reg_step_slug)
1580
+	{
1581
+		// get reg steps array
1582
+		$txn_reg_steps = $this->reg_steps();
1583
+		unset($txn_reg_steps[ $reg_step_slug ]);
1584
+		$this->set_reg_steps($txn_reg_steps);
1585
+	}
1586
+
1587
+
1588
+	/**
1589
+	 * toggle_failed_transaction_status
1590
+	 * upgrades a TXNs status from failed to abandoned,
1591
+	 * meaning that contact information has been captured for at least one registrant
1592
+	 *
1593
+	 * @param bool $save
1594
+	 * @return bool
1595
+	 * @throws EE_Error
1596
+	 * @throws InvalidArgumentException
1597
+	 * @throws InvalidDataTypeException
1598
+	 * @throws InvalidInterfaceException
1599
+	 * @throws ReflectionException
1600
+	 */
1601
+	public function toggle_failed_transaction_status($save = true)
1602
+	{
1603
+		// if TXN status is still set as "failed"...
1604
+		if ($this->status_ID() === EEM_Transaction::failed_status_code) {
1605
+			$this->set_status(EEM_Transaction::abandoned_status_code);
1606
+			if ($save) {
1607
+				$this->save();
1608
+			}
1609
+			return true;
1610
+		}
1611
+		return false;
1612
+	}
1613
+
1614
+
1615
+	/**
1616
+	 * toggle_abandoned_transaction_status
1617
+	 * upgrades a TXNs status from failed or abandoned to incomplete
1618
+	 *
1619
+	 * @return bool
1620
+	 * @throws EE_Error
1621
+	 * @throws InvalidArgumentException
1622
+	 * @throws InvalidDataTypeException
1623
+	 * @throws InvalidInterfaceException
1624
+	 * @throws ReflectionException
1625
+	 */
1626
+	public function toggle_abandoned_transaction_status()
1627
+	{
1628
+		// if TXN status has not been updated already due to a payment, and is still set as "failed" or "abandoned"...
1629
+		$txn_status = $this->status_ID();
1630
+		if ($txn_status === EEM_Transaction::failed_status_code
1631
+			|| $txn_status === EEM_Transaction::abandoned_status_code
1632
+		) {
1633
+			// if a contact record for the primary registrant has been created
1634
+			if ($this->primary_registration() instanceof EE_Registration
1635
+				&& $this->primary_registration()->attendee() instanceof EE_Attendee
1636
+			) {
1637
+				$this->set_status(EEM_Transaction::incomplete_status_code);
1638
+			} else {
1639
+				// no contact record? yer abandoned!
1640
+				$this->set_status(EEM_Transaction::abandoned_status_code);
1641
+			}
1642
+			return true;
1643
+		}
1644
+		return false;
1645
+	}
1646
+
1647
+
1648
+	/**
1649
+	 * checks if an Abandoned TXN has any related payments, and if so,
1650
+	 * updates the TXN status based on the amount paid
1651
+	 *
1652
+	 * @throws EE_Error
1653
+	 * @throws InvalidDataTypeException
1654
+	 * @throws InvalidInterfaceException
1655
+	 * @throws InvalidArgumentException
1656
+	 * @throws RuntimeException
1657
+	 * @throws ReflectionException
1658
+	 */
1659
+	public function verify_abandoned_transaction_status()
1660
+	{
1661
+		if ($this->status_ID() !== EEM_Transaction::abandoned_status_code) {
1662
+			return;
1663
+		}
1664
+		$payments = $this->get_many_related('Payment');
1665
+		if (! empty($payments)) {
1666
+			foreach ($payments as $payment) {
1667
+				if ($payment instanceof EE_Payment) {
1668
+					// kk this TXN should NOT be abandoned
1669
+					$this->update_status_based_on_total_paid();
1670
+					if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1671
+						EE_Error::add_attention(
1672
+							sprintf(
1673
+								esc_html__(
1674
+									'The status for Transaction #%1$d has been updated from "Abandoned" to "%2$s", because at least one payment has been made towards it. If the payment appears in the "Payment Details" table below, you may need to edit its status and/or other details as well.',
1675
+									'event_espresso'
1676
+								),
1677
+								$this->ID(),
1678
+								$this->pretty_status()
1679
+							)
1680
+						);
1681
+					}
1682
+					// get final reg step status
1683
+					$finalized = $this->final_reg_step_completed();
1684
+					// if the 'finalize_registration' step has been initiated (has a timestamp)
1685
+					// but has not yet been fully completed (TRUE)
1686
+					if (is_int($finalized) && $finalized !== false && $finalized !== true) {
1687
+						$this->set_reg_step_completed('finalize_registration');
1688
+						$this->save();
1689
+					}
1690
+				}
1691
+			}
1692
+		}
1693
+	}
1694 1694
 }
Please login to merge, or discard this patch.
admin/extend/registrations/Extend_Registrations_Admin_Page.core.php 2 patches
Indentation   +1202 added lines, -1202 removed lines patch added patch discarded remove patch
@@ -16,1259 +16,1259 @@
 block discarded – undo
16 16
 {
17 17
 
18 18
 
19
-    /**
20
-     * This is used to hold the reports template data which is setup early in the request.
21
-     *
22
-     * @type array
23
-     */
24
-    protected $_reports_template_data = array();
19
+	/**
20
+	 * This is used to hold the reports template data which is setup early in the request.
21
+	 *
22
+	 * @type array
23
+	 */
24
+	protected $_reports_template_data = array();
25 25
 
26 26
 
27
-    /**
28
-     * Extend_Registrations_Admin_Page constructor.
29
-     *
30
-     * @param bool $routing
31
-     */
32
-    public function __construct($routing = true)
33
-    {
34
-        parent::__construct($routing);
35
-        if (! defined('REG_CAF_TEMPLATE_PATH')) {
36
-            define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/templates/');
37
-            define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/assets/');
38
-            define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registrations/assets/');
39
-        }
40
-    }
27
+	/**
28
+	 * Extend_Registrations_Admin_Page constructor.
29
+	 *
30
+	 * @param bool $routing
31
+	 */
32
+	public function __construct($routing = true)
33
+	{
34
+		parent::__construct($routing);
35
+		if (! defined('REG_CAF_TEMPLATE_PATH')) {
36
+			define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/templates/');
37
+			define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/assets/');
38
+			define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registrations/assets/');
39
+		}
40
+	}
41 41
 
42 42
 
43
-    /**
44
-     * Extending page configuration.
45
-     */
46
-    protected function _extend_page_config()
47
-    {
48
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'registrations';
49
-        $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
50
-            ? $this->_req_data['_REG_ID']
51
-            : 0;
52
-        $new_page_routes = array(
53
-            'reports'                      => array(
54
-                'func'       => '_registration_reports',
55
-                'capability' => 'ee_read_registrations',
56
-            ),
57
-            'registration_checkins'        => array(
58
-                'func'       => '_registration_checkin_list_table',
59
-                'capability' => 'ee_read_checkins',
60
-            ),
61
-            'newsletter_selected_send'     => array(
62
-                'func'       => '_newsletter_selected_send',
63
-                'noheader'   => true,
64
-                'capability' => 'ee_send_message',
65
-            ),
66
-            'delete_checkin_rows'          => array(
67
-                'func'       => '_delete_checkin_rows',
68
-                'noheader'   => true,
69
-                'capability' => 'ee_delete_checkins',
70
-            ),
71
-            'delete_checkin_row'           => array(
72
-                'func'       => '_delete_checkin_row',
73
-                'noheader'   => true,
74
-                'capability' => 'ee_delete_checkin',
75
-                'obj_id'     => $reg_id,
76
-            ),
77
-            'toggle_checkin_status'        => array(
78
-                'func'       => '_toggle_checkin_status',
79
-                'noheader'   => true,
80
-                'capability' => 'ee_edit_checkin',
81
-                'obj_id'     => $reg_id,
82
-            ),
83
-            'toggle_checkin_status_bulk'   => array(
84
-                'func'       => '_toggle_checkin_status',
85
-                'noheader'   => true,
86
-                'capability' => 'ee_edit_checkins',
87
-            ),
88
-            'event_registrations'          => array(
89
-                'func'       => '_event_registrations_list_table',
90
-                'capability' => 'ee_read_checkins',
91
-            ),
92
-            'registrations_checkin_report' => array(
93
-                'func'       => '_registrations_checkin_report',
94
-                'noheader'   => true,
95
-                'capability' => 'ee_read_registrations',
96
-            ),
97
-        );
98
-        $this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
99
-        $new_page_config = array(
100
-            'reports'               => array(
101
-                'nav'           => array(
102
-                    'label' => esc_html__('Reports', 'event_espresso'),
103
-                    'order' => 30,
104
-                ),
105
-                'help_tabs'     => array(
106
-                    'registrations_reports_help_tab' => array(
107
-                        'title'    => esc_html__('Registration Reports', 'event_espresso'),
108
-                        'filename' => 'registrations_reports',
109
-                    ),
110
-                ),
111
-                /*'help_tour' => array( 'Registration_Reports_Help_Tour' ),*/
112
-                'require_nonce' => false,
113
-            ),
114
-            'event_registrations'   => array(
115
-                'nav'           => array(
116
-                    'label'      => esc_html__('Event Check-In', 'event_espresso'),
117
-                    'order'      => 10,
118
-                    'persistent' => true,
119
-                ),
120
-                'help_tabs'     => array(
121
-                    'registrations_event_checkin_help_tab'                       => array(
122
-                        'title'    => esc_html__('Registrations Event Check-In', 'event_espresso'),
123
-                        'filename' => 'registrations_event_checkin',
124
-                    ),
125
-                    'registrations_event_checkin_table_column_headings_help_tab' => array(
126
-                        'title'    => esc_html__('Event Check-In Table Column Headings', 'event_espresso'),
127
-                        'filename' => 'registrations_event_checkin_table_column_headings',
128
-                    ),
129
-                    'registrations_event_checkin_filters_help_tab'               => array(
130
-                        'title'    => esc_html__('Event Check-In Filters', 'event_espresso'),
131
-                        'filename' => 'registrations_event_checkin_filters',
132
-                    ),
133
-                    'registrations_event_checkin_views_help_tab'                 => array(
134
-                        'title'    => esc_html__('Event Check-In Views', 'event_espresso'),
135
-                        'filename' => 'registrations_event_checkin_views',
136
-                    ),
137
-                    'registrations_event_checkin_other_help_tab'                 => array(
138
-                        'title'    => esc_html__('Event Check-In Other', 'event_espresso'),
139
-                        'filename' => 'registrations_event_checkin_other',
140
-                    ),
141
-                ),
142
-                'help_tour'     => array('Event_Checkin_Help_Tour'),
143
-                'qtips'         => array('Registration_List_Table_Tips'),
144
-                'list_table'    => 'EE_Event_Registrations_List_Table',
145
-                'metaboxes'     => array(),
146
-                'require_nonce' => false,
147
-            ),
148
-            'registration_checkins' => array(
149
-                'nav'           => array(
150
-                    'label'      => esc_html__('Check-In Records', 'event_espresso'),
151
-                    'order'      => 15,
152
-                    'persistent' => false,
153
-                    'url'        => '',
154
-                ),
155
-                'list_table'    => 'EE_Registration_CheckIn_List_Table',
156
-                // 'help_tour' => array( 'Checkin_Toggle_View_Help_Tour' ),
157
-                'metaboxes'     => array(),
158
-                'require_nonce' => false,
159
-            ),
160
-        );
161
-        $this->_page_config = array_merge($this->_page_config, $new_page_config);
162
-        $this->_page_config['contact_list']['list_table'] = 'Extend_EE_Attendee_Contact_List_Table';
163
-        $this->_page_config['default']['list_table'] = 'Extend_EE_Registrations_List_Table';
164
-    }
43
+	/**
44
+	 * Extending page configuration.
45
+	 */
46
+	protected function _extend_page_config()
47
+	{
48
+		$this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'registrations';
49
+		$reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
50
+			? $this->_req_data['_REG_ID']
51
+			: 0;
52
+		$new_page_routes = array(
53
+			'reports'                      => array(
54
+				'func'       => '_registration_reports',
55
+				'capability' => 'ee_read_registrations',
56
+			),
57
+			'registration_checkins'        => array(
58
+				'func'       => '_registration_checkin_list_table',
59
+				'capability' => 'ee_read_checkins',
60
+			),
61
+			'newsletter_selected_send'     => array(
62
+				'func'       => '_newsletter_selected_send',
63
+				'noheader'   => true,
64
+				'capability' => 'ee_send_message',
65
+			),
66
+			'delete_checkin_rows'          => array(
67
+				'func'       => '_delete_checkin_rows',
68
+				'noheader'   => true,
69
+				'capability' => 'ee_delete_checkins',
70
+			),
71
+			'delete_checkin_row'           => array(
72
+				'func'       => '_delete_checkin_row',
73
+				'noheader'   => true,
74
+				'capability' => 'ee_delete_checkin',
75
+				'obj_id'     => $reg_id,
76
+			),
77
+			'toggle_checkin_status'        => array(
78
+				'func'       => '_toggle_checkin_status',
79
+				'noheader'   => true,
80
+				'capability' => 'ee_edit_checkin',
81
+				'obj_id'     => $reg_id,
82
+			),
83
+			'toggle_checkin_status_bulk'   => array(
84
+				'func'       => '_toggle_checkin_status',
85
+				'noheader'   => true,
86
+				'capability' => 'ee_edit_checkins',
87
+			),
88
+			'event_registrations'          => array(
89
+				'func'       => '_event_registrations_list_table',
90
+				'capability' => 'ee_read_checkins',
91
+			),
92
+			'registrations_checkin_report' => array(
93
+				'func'       => '_registrations_checkin_report',
94
+				'noheader'   => true,
95
+				'capability' => 'ee_read_registrations',
96
+			),
97
+		);
98
+		$this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
99
+		$new_page_config = array(
100
+			'reports'               => array(
101
+				'nav'           => array(
102
+					'label' => esc_html__('Reports', 'event_espresso'),
103
+					'order' => 30,
104
+				),
105
+				'help_tabs'     => array(
106
+					'registrations_reports_help_tab' => array(
107
+						'title'    => esc_html__('Registration Reports', 'event_espresso'),
108
+						'filename' => 'registrations_reports',
109
+					),
110
+				),
111
+				/*'help_tour' => array( 'Registration_Reports_Help_Tour' ),*/
112
+				'require_nonce' => false,
113
+			),
114
+			'event_registrations'   => array(
115
+				'nav'           => array(
116
+					'label'      => esc_html__('Event Check-In', 'event_espresso'),
117
+					'order'      => 10,
118
+					'persistent' => true,
119
+				),
120
+				'help_tabs'     => array(
121
+					'registrations_event_checkin_help_tab'                       => array(
122
+						'title'    => esc_html__('Registrations Event Check-In', 'event_espresso'),
123
+						'filename' => 'registrations_event_checkin',
124
+					),
125
+					'registrations_event_checkin_table_column_headings_help_tab' => array(
126
+						'title'    => esc_html__('Event Check-In Table Column Headings', 'event_espresso'),
127
+						'filename' => 'registrations_event_checkin_table_column_headings',
128
+					),
129
+					'registrations_event_checkin_filters_help_tab'               => array(
130
+						'title'    => esc_html__('Event Check-In Filters', 'event_espresso'),
131
+						'filename' => 'registrations_event_checkin_filters',
132
+					),
133
+					'registrations_event_checkin_views_help_tab'                 => array(
134
+						'title'    => esc_html__('Event Check-In Views', 'event_espresso'),
135
+						'filename' => 'registrations_event_checkin_views',
136
+					),
137
+					'registrations_event_checkin_other_help_tab'                 => array(
138
+						'title'    => esc_html__('Event Check-In Other', 'event_espresso'),
139
+						'filename' => 'registrations_event_checkin_other',
140
+					),
141
+				),
142
+				'help_tour'     => array('Event_Checkin_Help_Tour'),
143
+				'qtips'         => array('Registration_List_Table_Tips'),
144
+				'list_table'    => 'EE_Event_Registrations_List_Table',
145
+				'metaboxes'     => array(),
146
+				'require_nonce' => false,
147
+			),
148
+			'registration_checkins' => array(
149
+				'nav'           => array(
150
+					'label'      => esc_html__('Check-In Records', 'event_espresso'),
151
+					'order'      => 15,
152
+					'persistent' => false,
153
+					'url'        => '',
154
+				),
155
+				'list_table'    => 'EE_Registration_CheckIn_List_Table',
156
+				// 'help_tour' => array( 'Checkin_Toggle_View_Help_Tour' ),
157
+				'metaboxes'     => array(),
158
+				'require_nonce' => false,
159
+			),
160
+		);
161
+		$this->_page_config = array_merge($this->_page_config, $new_page_config);
162
+		$this->_page_config['contact_list']['list_table'] = 'Extend_EE_Attendee_Contact_List_Table';
163
+		$this->_page_config['default']['list_table'] = 'Extend_EE_Registrations_List_Table';
164
+	}
165 165
 
166 166
 
167
-    /**
168
-     * Ajax hooks for all routes in this page.
169
-     */
170
-    protected function _ajax_hooks()
171
-    {
172
-        parent::_ajax_hooks();
173
-        add_action('wp_ajax_get_newsletter_form_content', array($this, 'get_newsletter_form_content'));
174
-    }
167
+	/**
168
+	 * Ajax hooks for all routes in this page.
169
+	 */
170
+	protected function _ajax_hooks()
171
+	{
172
+		parent::_ajax_hooks();
173
+		add_action('wp_ajax_get_newsletter_form_content', array($this, 'get_newsletter_form_content'));
174
+	}
175 175
 
176 176
 
177
-    /**
178
-     * Global scripts for all routes in this page.
179
-     */
180
-    public function load_scripts_styles()
181
-    {
182
-        parent::load_scripts_styles();
183
-        // if newsletter message type is active then let's add filter and load js for it.
184
-        if (EEH_MSG_Template::is_mt_active('newsletter')) {
185
-            // enqueue newsletter js
186
-            wp_enqueue_script(
187
-                'ee-newsletter-trigger',
188
-                REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.js',
189
-                array('ee-dialog'),
190
-                EVENT_ESPRESSO_VERSION,
191
-                true
192
-            );
193
-            wp_enqueue_style(
194
-                'ee-newsletter-trigger-css',
195
-                REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.css',
196
-                array(),
197
-                EVENT_ESPRESSO_VERSION
198
-            );
199
-            // hook in buttons for newsletter message type trigger.
200
-            add_action(
201
-                'AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons',
202
-                array($this, 'add_newsletter_action_buttons'),
203
-                10
204
-            );
205
-        }
206
-    }
177
+	/**
178
+	 * Global scripts for all routes in this page.
179
+	 */
180
+	public function load_scripts_styles()
181
+	{
182
+		parent::load_scripts_styles();
183
+		// if newsletter message type is active then let's add filter and load js for it.
184
+		if (EEH_MSG_Template::is_mt_active('newsletter')) {
185
+			// enqueue newsletter js
186
+			wp_enqueue_script(
187
+				'ee-newsletter-trigger',
188
+				REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.js',
189
+				array('ee-dialog'),
190
+				EVENT_ESPRESSO_VERSION,
191
+				true
192
+			);
193
+			wp_enqueue_style(
194
+				'ee-newsletter-trigger-css',
195
+				REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.css',
196
+				array(),
197
+				EVENT_ESPRESSO_VERSION
198
+			);
199
+			// hook in buttons for newsletter message type trigger.
200
+			add_action(
201
+				'AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons',
202
+				array($this, 'add_newsletter_action_buttons'),
203
+				10
204
+			);
205
+		}
206
+	}
207 207
 
208 208
 
209
-    /**
210
-     * Scripts and styles for just the reports route.
211
-     */
212
-    public function load_scripts_styles_reports()
213
-    {
214
-        wp_register_script(
215
-            'ee-reg-reports-js',
216
-            REG_CAF_ASSETS_URL . 'ee-registration-admin-reports.js',
217
-            array('google-charts'),
218
-            EVENT_ESPRESSO_VERSION,
219
-            true
220
-        );
221
-        wp_enqueue_script('ee-reg-reports-js');
222
-        $this->_registration_reports_js_setup();
223
-    }
209
+	/**
210
+	 * Scripts and styles for just the reports route.
211
+	 */
212
+	public function load_scripts_styles_reports()
213
+	{
214
+		wp_register_script(
215
+			'ee-reg-reports-js',
216
+			REG_CAF_ASSETS_URL . 'ee-registration-admin-reports.js',
217
+			array('google-charts'),
218
+			EVENT_ESPRESSO_VERSION,
219
+			true
220
+		);
221
+		wp_enqueue_script('ee-reg-reports-js');
222
+		$this->_registration_reports_js_setup();
223
+	}
224 224
 
225 225
 
226
-    /**
227
-     * Register screen options for event_registrations route.
228
-     */
229
-    protected function _add_screen_options_event_registrations()
230
-    {
231
-        $this->_per_page_screen_option();
232
-    }
226
+	/**
227
+	 * Register screen options for event_registrations route.
228
+	 */
229
+	protected function _add_screen_options_event_registrations()
230
+	{
231
+		$this->_per_page_screen_option();
232
+	}
233 233
 
234 234
 
235
-    /**
236
-     * Register screen options for registration_checkins route
237
-     */
238
-    protected function _add_screen_options_registration_checkins()
239
-    {
240
-        $page_title = $this->_admin_page_title;
241
-        $this->_admin_page_title = esc_html__('Check-In Records', 'event_espresso');
242
-        $this->_per_page_screen_option();
243
-        $this->_admin_page_title = $page_title;
244
-    }
235
+	/**
236
+	 * Register screen options for registration_checkins route
237
+	 */
238
+	protected function _add_screen_options_registration_checkins()
239
+	{
240
+		$page_title = $this->_admin_page_title;
241
+		$this->_admin_page_title = esc_html__('Check-In Records', 'event_espresso');
242
+		$this->_per_page_screen_option();
243
+		$this->_admin_page_title = $page_title;
244
+	}
245 245
 
246 246
 
247
-    /**
248
-     * Set views property for event_registrations route.
249
-     */
250
-    protected function _set_list_table_views_event_registrations()
251
-    {
252
-        $this->_views = array(
253
-            'all' => array(
254
-                'slug'        => 'all',
255
-                'label'       => esc_html__('All', 'event_espresso'),
256
-                'count'       => 0,
257
-                'bulk_action' => ! isset($this->_req_data['event_id'])
258
-                    ? array()
259
-                    : array(
260
-                        'toggle_checkin_status_bulk' => esc_html__('Toggle Check-In', 'event_espresso'),
261
-                    ),
262
-            ),
263
-        );
264
-    }
247
+	/**
248
+	 * Set views property for event_registrations route.
249
+	 */
250
+	protected function _set_list_table_views_event_registrations()
251
+	{
252
+		$this->_views = array(
253
+			'all' => array(
254
+				'slug'        => 'all',
255
+				'label'       => esc_html__('All', 'event_espresso'),
256
+				'count'       => 0,
257
+				'bulk_action' => ! isset($this->_req_data['event_id'])
258
+					? array()
259
+					: array(
260
+						'toggle_checkin_status_bulk' => esc_html__('Toggle Check-In', 'event_espresso'),
261
+					),
262
+			),
263
+		);
264
+	}
265 265
 
266 266
 
267
-    /**
268
-     * Set views property for registration_checkins route.
269
-     */
270
-    protected function _set_list_table_views_registration_checkins()
271
-    {
272
-        $this->_views = array(
273
-            'all' => array(
274
-                'slug'        => 'all',
275
-                'label'       => esc_html__('All', 'event_espresso'),
276
-                'count'       => 0,
277
-                'bulk_action' => array('delete_checkin_rows' => esc_html__('Delete Check-In Rows', 'event_espresso')),
278
-            ),
279
-        );
280
-    }
267
+	/**
268
+	 * Set views property for registration_checkins route.
269
+	 */
270
+	protected function _set_list_table_views_registration_checkins()
271
+	{
272
+		$this->_views = array(
273
+			'all' => array(
274
+				'slug'        => 'all',
275
+				'label'       => esc_html__('All', 'event_espresso'),
276
+				'count'       => 0,
277
+				'bulk_action' => array('delete_checkin_rows' => esc_html__('Delete Check-In Rows', 'event_espresso')),
278
+			),
279
+		);
280
+	}
281 281
 
282 282
 
283
-    /**
284
-     * callback for ajax action.
285
-     *
286
-     * @since 4.3.0
287
-     * @return void (JSON)
288
-     * @throws EE_Error
289
-     * @throws InvalidArgumentException
290
-     * @throws InvalidDataTypeException
291
-     * @throws InvalidInterfaceException
292
-     */
293
-    public function get_newsletter_form_content()
294
-    {
295
-        // do a nonce check cause we're not coming in from an normal route here.
296
-        $nonce = isset($this->_req_data['get_newsletter_form_content_nonce']) ? sanitize_text_field(
297
-            $this->_req_data['get_newsletter_form_content_nonce']
298
-        ) : '';
299
-        $nonce_ref = 'get_newsletter_form_content_nonce';
300
-        $this->_verify_nonce($nonce, $nonce_ref);
301
-        // let's get the mtp for the incoming MTP_ ID
302
-        if (! isset($this->_req_data['GRP_ID'])) {
303
-            EE_Error::add_error(
304
-                esc_html__(
305
-                    '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).',
306
-                    'event_espresso'
307
-                ),
308
-                __FILE__,
309
-                __FUNCTION__,
310
-                __LINE__
311
-            );
312
-            $this->_template_args['success'] = false;
313
-            $this->_template_args['error'] = true;
314
-            $this->_return_json();
315
-        }
316
-        $MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID($this->_req_data['GRP_ID']);
317
-        if (! $MTPG instanceof EE_Message_Template_Group) {
318
-            EE_Error::add_error(
319
-                sprintf(
320
-                    esc_html__(
321
-                        'The GRP_ID given (%d) does not appear to have a corresponding row in the database.',
322
-                        'event_espresso'
323
-                    ),
324
-                    $this->_req_data['GRP_ID']
325
-                ),
326
-                __FILE__,
327
-                __FUNCTION__,
328
-                __LINE__
329
-            );
330
-            $this->_template_args['success'] = false;
331
-            $this->_template_args['error'] = true;
332
-            $this->_return_json();
333
-        }
334
-        $MTPs = $MTPG->context_templates();
335
-        $MTPs = $MTPs['attendee'];
336
-        $template_fields = array();
337
-        /** @var EE_Message_Template $MTP */
338
-        foreach ($MTPs as $MTP) {
339
-            $field = $MTP->get('MTP_template_field');
340
-            if ($field === 'content') {
341
-                $content = $MTP->get('MTP_content');
342
-                if (! empty($content['newsletter_content'])) {
343
-                    $template_fields['newsletter_content'] = $content['newsletter_content'];
344
-                }
345
-                continue;
346
-            }
347
-            $template_fields[ $MTP->get('MTP_template_field') ] = $MTP->get('MTP_content');
348
-        }
349
-        $this->_template_args['success'] = true;
350
-        $this->_template_args['error'] = false;
351
-        $this->_template_args['data'] = array(
352
-            'batch_message_from'    => isset($template_fields['from'])
353
-                ? $template_fields['from']
354
-                : '',
355
-            'batch_message_subject' => isset($template_fields['subject'])
356
-                ? $template_fields['subject']
357
-                : '',
358
-            'batch_message_content' => isset($template_fields['newsletter_content'])
359
-                ? $template_fields['newsletter_content']
360
-                : '',
361
-        );
362
-        $this->_return_json();
363
-    }
283
+	/**
284
+	 * callback for ajax action.
285
+	 *
286
+	 * @since 4.3.0
287
+	 * @return void (JSON)
288
+	 * @throws EE_Error
289
+	 * @throws InvalidArgumentException
290
+	 * @throws InvalidDataTypeException
291
+	 * @throws InvalidInterfaceException
292
+	 */
293
+	public function get_newsletter_form_content()
294
+	{
295
+		// do a nonce check cause we're not coming in from an normal route here.
296
+		$nonce = isset($this->_req_data['get_newsletter_form_content_nonce']) ? sanitize_text_field(
297
+			$this->_req_data['get_newsletter_form_content_nonce']
298
+		) : '';
299
+		$nonce_ref = 'get_newsletter_form_content_nonce';
300
+		$this->_verify_nonce($nonce, $nonce_ref);
301
+		// let's get the mtp for the incoming MTP_ ID
302
+		if (! isset($this->_req_data['GRP_ID'])) {
303
+			EE_Error::add_error(
304
+				esc_html__(
305
+					'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).',
306
+					'event_espresso'
307
+				),
308
+				__FILE__,
309
+				__FUNCTION__,
310
+				__LINE__
311
+			);
312
+			$this->_template_args['success'] = false;
313
+			$this->_template_args['error'] = true;
314
+			$this->_return_json();
315
+		}
316
+		$MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID($this->_req_data['GRP_ID']);
317
+		if (! $MTPG instanceof EE_Message_Template_Group) {
318
+			EE_Error::add_error(
319
+				sprintf(
320
+					esc_html__(
321
+						'The GRP_ID given (%d) does not appear to have a corresponding row in the database.',
322
+						'event_espresso'
323
+					),
324
+					$this->_req_data['GRP_ID']
325
+				),
326
+				__FILE__,
327
+				__FUNCTION__,
328
+				__LINE__
329
+			);
330
+			$this->_template_args['success'] = false;
331
+			$this->_template_args['error'] = true;
332
+			$this->_return_json();
333
+		}
334
+		$MTPs = $MTPG->context_templates();
335
+		$MTPs = $MTPs['attendee'];
336
+		$template_fields = array();
337
+		/** @var EE_Message_Template $MTP */
338
+		foreach ($MTPs as $MTP) {
339
+			$field = $MTP->get('MTP_template_field');
340
+			if ($field === 'content') {
341
+				$content = $MTP->get('MTP_content');
342
+				if (! empty($content['newsletter_content'])) {
343
+					$template_fields['newsletter_content'] = $content['newsletter_content'];
344
+				}
345
+				continue;
346
+			}
347
+			$template_fields[ $MTP->get('MTP_template_field') ] = $MTP->get('MTP_content');
348
+		}
349
+		$this->_template_args['success'] = true;
350
+		$this->_template_args['error'] = false;
351
+		$this->_template_args['data'] = array(
352
+			'batch_message_from'    => isset($template_fields['from'])
353
+				? $template_fields['from']
354
+				: '',
355
+			'batch_message_subject' => isset($template_fields['subject'])
356
+				? $template_fields['subject']
357
+				: '',
358
+			'batch_message_content' => isset($template_fields['newsletter_content'])
359
+				? $template_fields['newsletter_content']
360
+				: '',
361
+		);
362
+		$this->_return_json();
363
+	}
364 364
 
365 365
 
366
-    /**
367
-     * callback for AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons action
368
-     *
369
-     * @since 4.3.0
370
-     * @param EE_Admin_List_Table $list_table
371
-     * @return void
372
-     * @throws InvalidArgumentException
373
-     * @throws InvalidDataTypeException
374
-     * @throws InvalidInterfaceException
375
-     */
376
-    public function add_newsletter_action_buttons(EE_Admin_List_Table $list_table)
377
-    {
378
-        if (! EE_Registry::instance()->CAP->current_user_can(
379
-            'ee_send_message',
380
-            'espresso_registrations_newsletter_selected_send'
381
-        )
382
-        ) {
383
-            return;
384
-        }
385
-        $routes_to_add_to = array(
386
-            'contact_list',
387
-            'event_registrations',
388
-            'default',
389
-        );
390
-        if ($this->_current_page === 'espresso_registrations' && in_array($this->_req_action, $routes_to_add_to)) {
391
-            if (($this->_req_action === 'event_registrations' && empty($this->_req_data['event_id']))
392
-                || (isset($this->_req_data['status']) && $this->_req_data['status'] === 'trash')
393
-            ) {
394
-                echo '';
395
-            } else {
396
-                $button_text = sprintf(
397
-                    esc_html__('Send Batch Message (%s selected)', 'event_espresso'),
398
-                    '<span class="send-selected-newsletter-count">0</span>'
399
-                );
400
-                echo '<button id="selected-batch-send-trigger" class="button secondary-button">'
401
-                     . '<span class="dashicons dashicons-email "></span>'
402
-                     . $button_text
403
-                     . '</button>';
404
-                add_action('admin_footer', array($this, 'newsletter_send_form_skeleton'));
405
-            }
406
-        }
407
-    }
366
+	/**
367
+	 * callback for AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons action
368
+	 *
369
+	 * @since 4.3.0
370
+	 * @param EE_Admin_List_Table $list_table
371
+	 * @return void
372
+	 * @throws InvalidArgumentException
373
+	 * @throws InvalidDataTypeException
374
+	 * @throws InvalidInterfaceException
375
+	 */
376
+	public function add_newsletter_action_buttons(EE_Admin_List_Table $list_table)
377
+	{
378
+		if (! EE_Registry::instance()->CAP->current_user_can(
379
+			'ee_send_message',
380
+			'espresso_registrations_newsletter_selected_send'
381
+		)
382
+		) {
383
+			return;
384
+		}
385
+		$routes_to_add_to = array(
386
+			'contact_list',
387
+			'event_registrations',
388
+			'default',
389
+		);
390
+		if ($this->_current_page === 'espresso_registrations' && in_array($this->_req_action, $routes_to_add_to)) {
391
+			if (($this->_req_action === 'event_registrations' && empty($this->_req_data['event_id']))
392
+				|| (isset($this->_req_data['status']) && $this->_req_data['status'] === 'trash')
393
+			) {
394
+				echo '';
395
+			} else {
396
+				$button_text = sprintf(
397
+					esc_html__('Send Batch Message (%s selected)', 'event_espresso'),
398
+					'<span class="send-selected-newsletter-count">0</span>'
399
+				);
400
+				echo '<button id="selected-batch-send-trigger" class="button secondary-button">'
401
+					 . '<span class="dashicons dashicons-email "></span>'
402
+					 . $button_text
403
+					 . '</button>';
404
+				add_action('admin_footer', array($this, 'newsletter_send_form_skeleton'));
405
+			}
406
+		}
407
+	}
408 408
 
409 409
 
410
-    /**
411
-     * @throws DomainException
412
-     * @throws EE_Error
413
-     * @throws InvalidArgumentException
414
-     * @throws InvalidDataTypeException
415
-     * @throws InvalidInterfaceException
416
-     */
417
-    public function newsletter_send_form_skeleton()
418
-    {
419
-        $list_table = $this->_list_table_object;
420
-        $codes = array();
421
-        // need to templates for the newsletter message type for the template selector.
422
-        $values[] = array('text' => esc_html__('Select Template to Use', 'event_espresso'), 'id' => 0);
423
-        $mtps = EEM_Message_Template_Group::instance()->get_all(
424
-            array(array('MTP_message_type' => 'newsletter', 'MTP_messenger' => 'email'))
425
-        );
426
-        foreach ($mtps as $mtp) {
427
-            $name = $mtp->name();
428
-            $values[] = array(
429
-                'text' => empty($name) ? esc_html__('Global', 'event_espresso') : $name,
430
-                'id'   => $mtp->ID(),
431
-            );
432
-        }
433
-        // need to get a list of shortcodes that are available for the newsletter message type.
434
-        $shortcodes = EEH_MSG_Template::get_shortcodes(
435
-            'newsletter',
436
-            'email',
437
-            array(),
438
-            'attendee',
439
-            false
440
-        );
441
-        foreach ($shortcodes as $field => $shortcode_array) {
442
-            $available_shortcodes = array();
443
-            foreach ($shortcode_array as $shortcode => $shortcode_details) {
444
-                $field_id = $field === '[NEWSLETTER_CONTENT]'
445
-                    ? 'content'
446
-                    : $field;
447
-                $field_id = 'batch-message-' . strtolower($field_id);
448
-                $available_shortcodes[] = '<span class="js-shortcode-selection" data-value="'
449
-                                          . $shortcode
450
-                                          . '" data-linked-input-id="' . $field_id . '">'
451
-                                          . $shortcode
452
-                                          . '</span>';
453
-            }
454
-            $codes[ $field ] = implode(', ', $available_shortcodes);
455
-        }
456
-        $shortcodes = $codes;
457
-        $form_template = REG_CAF_TEMPLATE_PATH . 'newsletter-send-form.template.php';
458
-        $form_template_args = array(
459
-            'form_action'       => admin_url('admin.php?page=espresso_registrations'),
460
-            'form_route'        => 'newsletter_selected_send',
461
-            'form_nonce_name'   => 'newsletter_selected_send_nonce',
462
-            'form_nonce'        => wp_create_nonce('newsletter_selected_send_nonce'),
463
-            'redirect_back_to'  => $this->_req_action,
464
-            'ajax_nonce'        => wp_create_nonce('get_newsletter_form_content_nonce'),
465
-            'template_selector' => EEH_Form_Fields::select_input('newsletter_mtp_selected', $values),
466
-            'shortcodes'        => $shortcodes,
467
-            'id_type'           => $list_table instanceof EE_Attendee_Contact_List_Table ? 'contact' : 'registration',
468
-        );
469
-        EEH_Template::display_template($form_template, $form_template_args);
470
-    }
410
+	/**
411
+	 * @throws DomainException
412
+	 * @throws EE_Error
413
+	 * @throws InvalidArgumentException
414
+	 * @throws InvalidDataTypeException
415
+	 * @throws InvalidInterfaceException
416
+	 */
417
+	public function newsletter_send_form_skeleton()
418
+	{
419
+		$list_table = $this->_list_table_object;
420
+		$codes = array();
421
+		// need to templates for the newsletter message type for the template selector.
422
+		$values[] = array('text' => esc_html__('Select Template to Use', 'event_espresso'), 'id' => 0);
423
+		$mtps = EEM_Message_Template_Group::instance()->get_all(
424
+			array(array('MTP_message_type' => 'newsletter', 'MTP_messenger' => 'email'))
425
+		);
426
+		foreach ($mtps as $mtp) {
427
+			$name = $mtp->name();
428
+			$values[] = array(
429
+				'text' => empty($name) ? esc_html__('Global', 'event_espresso') : $name,
430
+				'id'   => $mtp->ID(),
431
+			);
432
+		}
433
+		// need to get a list of shortcodes that are available for the newsletter message type.
434
+		$shortcodes = EEH_MSG_Template::get_shortcodes(
435
+			'newsletter',
436
+			'email',
437
+			array(),
438
+			'attendee',
439
+			false
440
+		);
441
+		foreach ($shortcodes as $field => $shortcode_array) {
442
+			$available_shortcodes = array();
443
+			foreach ($shortcode_array as $shortcode => $shortcode_details) {
444
+				$field_id = $field === '[NEWSLETTER_CONTENT]'
445
+					? 'content'
446
+					: $field;
447
+				$field_id = 'batch-message-' . strtolower($field_id);
448
+				$available_shortcodes[] = '<span class="js-shortcode-selection" data-value="'
449
+										  . $shortcode
450
+										  . '" data-linked-input-id="' . $field_id . '">'
451
+										  . $shortcode
452
+										  . '</span>';
453
+			}
454
+			$codes[ $field ] = implode(', ', $available_shortcodes);
455
+		}
456
+		$shortcodes = $codes;
457
+		$form_template = REG_CAF_TEMPLATE_PATH . 'newsletter-send-form.template.php';
458
+		$form_template_args = array(
459
+			'form_action'       => admin_url('admin.php?page=espresso_registrations'),
460
+			'form_route'        => 'newsletter_selected_send',
461
+			'form_nonce_name'   => 'newsletter_selected_send_nonce',
462
+			'form_nonce'        => wp_create_nonce('newsletter_selected_send_nonce'),
463
+			'redirect_back_to'  => $this->_req_action,
464
+			'ajax_nonce'        => wp_create_nonce('get_newsletter_form_content_nonce'),
465
+			'template_selector' => EEH_Form_Fields::select_input('newsletter_mtp_selected', $values),
466
+			'shortcodes'        => $shortcodes,
467
+			'id_type'           => $list_table instanceof EE_Attendee_Contact_List_Table ? 'contact' : 'registration',
468
+		);
469
+		EEH_Template::display_template($form_template, $form_template_args);
470
+	}
471 471
 
472 472
 
473
-    /**
474
-     * Handles sending selected registrations/contacts a newsletter.
475
-     *
476
-     * @since  4.3.0
477
-     * @return void
478
-     * @throws EE_Error
479
-     * @throws InvalidArgumentException
480
-     * @throws InvalidDataTypeException
481
-     * @throws InvalidInterfaceException
482
-     */
483
-    protected function _newsletter_selected_send()
484
-    {
485
-        $success = true;
486
-        // first we need to make sure we have a GRP_ID so we know what template we're sending and updating!
487
-        if (empty($this->_req_data['newsletter_mtp_selected'])) {
488
-            EE_Error::add_error(
489
-                esc_html__(
490
-                    'In order to send a message, a Message Template GRP_ID is needed. It was not provided so messages were not sent.',
491
-                    'event_espresso'
492
-                ),
493
-                __FILE__,
494
-                __FUNCTION__,
495
-                __LINE__
496
-            );
497
-            $success = false;
498
-        }
499
-        if ($success) {
500
-            // update Message template in case there are any changes
501
-            $Message_Template_Group = EEM_Message_Template_Group::instance()->get_one_by_ID(
502
-                $this->_req_data['newsletter_mtp_selected']
503
-            );
504
-            $Message_Templates = $Message_Template_Group instanceof EE_Message_Template_Group
505
-                ? $Message_Template_Group->context_templates()
506
-                : array();
507
-            if (empty($Message_Templates)) {
508
-                EE_Error::add_error(
509
-                    esc_html__(
510
-                        'Unable to retrieve message template fields from the db. Messages not sent.',
511
-                        'event_espresso'
512
-                    ),
513
-                    __FILE__,
514
-                    __FUNCTION__,
515
-                    __LINE__
516
-                );
517
-            }
518
-            // let's just update the specific fields
519
-            foreach ($Message_Templates['attendee'] as $Message_Template) {
520
-                if ($Message_Template instanceof EE_Message_Template) {
521
-                    $field = $Message_Template->get('MTP_template_field');
522
-                    $content = $Message_Template->get('MTP_content');
523
-                    $new_content = $content;
524
-                    switch ($field) {
525
-                        case 'from':
526
-                            $new_content = ! empty($this->_req_data['batch_message']['from'])
527
-                                ? $this->_req_data['batch_message']['from']
528
-                                : $content;
529
-                            break;
530
-                        case 'subject':
531
-                            $new_content = ! empty($this->_req_data['batch_message']['subject'])
532
-                                ? $this->_req_data['batch_message']['subject']
533
-                                : $content;
534
-                            break;
535
-                        case 'content':
536
-                            $new_content = $content;
537
-                            $new_content['newsletter_content'] = ! empty($this->_req_data['batch_message']['content'])
538
-                                ? $this->_req_data['batch_message']['content']
539
-                                : $content['newsletter_content'];
540
-                            break;
541
-                        default:
542
-                            // continue the foreach loop, we don't want to set $new_content nor save.
543
-                            continue 2;
544
-                    }
545
-                    $Message_Template->set('MTP_content', $new_content);
546
-                    $Message_Template->save();
547
-                }
548
-            }
549
-            // great fields are updated!  now let's make sure we just have contact objects (EE_Attendee).
550
-            $id_type = ! empty($this->_req_data['batch_message']['id_type'])
551
-                ? $this->_req_data['batch_message']['id_type']
552
-                : 'registration';
553
-            // id_type will affect how we assemble the ids.
554
-            $ids = ! empty($this->_req_data['batch_message']['ids'])
555
-                ? json_decode(stripslashes($this->_req_data['batch_message']['ids']))
556
-                : array();
557
-            $registrations_used_for_contact_data = array();
558
-            // using switch because eventually we'll have other contexts that will be used for generating messages.
559
-            switch ($id_type) {
560
-                case 'registration':
561
-                    $registrations_used_for_contact_data = EEM_Registration::instance()->get_all(
562
-                        array(
563
-                            array(
564
-                                'REG_ID' => array('IN', $ids),
565
-                            ),
566
-                        )
567
-                    );
568
-                    break;
569
-                case 'contact':
570
-                    $registrations_used_for_contact_data = EEM_Registration::instance()
571
-                                                                           ->get_latest_registration_for_each_of_given_contacts(
572
-                                                                               $ids
573
-                                                                           );
574
-                    break;
575
-            }
576
-            do_action_ref_array(
577
-                'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations',
578
-                array(
579
-                    $registrations_used_for_contact_data,
580
-                    $Message_Template_Group->ID(),
581
-                )
582
-            );
583
-            // kept for backward compat, internally we no longer use this action.
584
-            // @deprecated 4.8.36.rc.002
585
-            $contacts = $id_type === 'registration'
586
-                ? EEM_Attendee::instance()->get_array_of_contacts_from_reg_ids($ids)
587
-                : EEM_Attendee::instance()->get_all(array(array('ATT_ID' => array('in', $ids))));
588
-            do_action_ref_array(
589
-                'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send',
590
-                array(
591
-                    $contacts,
592
-                    $Message_Template_Group->ID(),
593
-                )
594
-            );
595
-        }
596
-        $query_args = array(
597
-            'action' => ! empty($this->_req_data['redirect_back_to'])
598
-                ? $this->_req_data['redirect_back_to']
599
-                : 'default',
600
-        );
601
-        $this->_redirect_after_action(false, '', '', $query_args, true);
602
-    }
473
+	/**
474
+	 * Handles sending selected registrations/contacts a newsletter.
475
+	 *
476
+	 * @since  4.3.0
477
+	 * @return void
478
+	 * @throws EE_Error
479
+	 * @throws InvalidArgumentException
480
+	 * @throws InvalidDataTypeException
481
+	 * @throws InvalidInterfaceException
482
+	 */
483
+	protected function _newsletter_selected_send()
484
+	{
485
+		$success = true;
486
+		// first we need to make sure we have a GRP_ID so we know what template we're sending and updating!
487
+		if (empty($this->_req_data['newsletter_mtp_selected'])) {
488
+			EE_Error::add_error(
489
+				esc_html__(
490
+					'In order to send a message, a Message Template GRP_ID is needed. It was not provided so messages were not sent.',
491
+					'event_espresso'
492
+				),
493
+				__FILE__,
494
+				__FUNCTION__,
495
+				__LINE__
496
+			);
497
+			$success = false;
498
+		}
499
+		if ($success) {
500
+			// update Message template in case there are any changes
501
+			$Message_Template_Group = EEM_Message_Template_Group::instance()->get_one_by_ID(
502
+				$this->_req_data['newsletter_mtp_selected']
503
+			);
504
+			$Message_Templates = $Message_Template_Group instanceof EE_Message_Template_Group
505
+				? $Message_Template_Group->context_templates()
506
+				: array();
507
+			if (empty($Message_Templates)) {
508
+				EE_Error::add_error(
509
+					esc_html__(
510
+						'Unable to retrieve message template fields from the db. Messages not sent.',
511
+						'event_espresso'
512
+					),
513
+					__FILE__,
514
+					__FUNCTION__,
515
+					__LINE__
516
+				);
517
+			}
518
+			// let's just update the specific fields
519
+			foreach ($Message_Templates['attendee'] as $Message_Template) {
520
+				if ($Message_Template instanceof EE_Message_Template) {
521
+					$field = $Message_Template->get('MTP_template_field');
522
+					$content = $Message_Template->get('MTP_content');
523
+					$new_content = $content;
524
+					switch ($field) {
525
+						case 'from':
526
+							$new_content = ! empty($this->_req_data['batch_message']['from'])
527
+								? $this->_req_data['batch_message']['from']
528
+								: $content;
529
+							break;
530
+						case 'subject':
531
+							$new_content = ! empty($this->_req_data['batch_message']['subject'])
532
+								? $this->_req_data['batch_message']['subject']
533
+								: $content;
534
+							break;
535
+						case 'content':
536
+							$new_content = $content;
537
+							$new_content['newsletter_content'] = ! empty($this->_req_data['batch_message']['content'])
538
+								? $this->_req_data['batch_message']['content']
539
+								: $content['newsletter_content'];
540
+							break;
541
+						default:
542
+							// continue the foreach loop, we don't want to set $new_content nor save.
543
+							continue 2;
544
+					}
545
+					$Message_Template->set('MTP_content', $new_content);
546
+					$Message_Template->save();
547
+				}
548
+			}
549
+			// great fields are updated!  now let's make sure we just have contact objects (EE_Attendee).
550
+			$id_type = ! empty($this->_req_data['batch_message']['id_type'])
551
+				? $this->_req_data['batch_message']['id_type']
552
+				: 'registration';
553
+			// id_type will affect how we assemble the ids.
554
+			$ids = ! empty($this->_req_data['batch_message']['ids'])
555
+				? json_decode(stripslashes($this->_req_data['batch_message']['ids']))
556
+				: array();
557
+			$registrations_used_for_contact_data = array();
558
+			// using switch because eventually we'll have other contexts that will be used for generating messages.
559
+			switch ($id_type) {
560
+				case 'registration':
561
+					$registrations_used_for_contact_data = EEM_Registration::instance()->get_all(
562
+						array(
563
+							array(
564
+								'REG_ID' => array('IN', $ids),
565
+							),
566
+						)
567
+					);
568
+					break;
569
+				case 'contact':
570
+					$registrations_used_for_contact_data = EEM_Registration::instance()
571
+																		   ->get_latest_registration_for_each_of_given_contacts(
572
+																			   $ids
573
+																		   );
574
+					break;
575
+			}
576
+			do_action_ref_array(
577
+				'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations',
578
+				array(
579
+					$registrations_used_for_contact_data,
580
+					$Message_Template_Group->ID(),
581
+				)
582
+			);
583
+			// kept for backward compat, internally we no longer use this action.
584
+			// @deprecated 4.8.36.rc.002
585
+			$contacts = $id_type === 'registration'
586
+				? EEM_Attendee::instance()->get_array_of_contacts_from_reg_ids($ids)
587
+				: EEM_Attendee::instance()->get_all(array(array('ATT_ID' => array('in', $ids))));
588
+			do_action_ref_array(
589
+				'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send',
590
+				array(
591
+					$contacts,
592
+					$Message_Template_Group->ID(),
593
+				)
594
+			);
595
+		}
596
+		$query_args = array(
597
+			'action' => ! empty($this->_req_data['redirect_back_to'])
598
+				? $this->_req_data['redirect_back_to']
599
+				: 'default',
600
+		);
601
+		$this->_redirect_after_action(false, '', '', $query_args, true);
602
+	}
603 603
 
604 604
 
605
-    /**
606
-     * This is called when javascript is being enqueued to setup the various data needed for the reports js.
607
-     * Also $this->{$_reports_template_data} property is set for later usage by the _registration_reports method.
608
-     */
609
-    protected function _registration_reports_js_setup()
610
-    {
611
-        $this->_reports_template_data['admin_reports'][] = $this->_registrations_per_day_report();
612
-        $this->_reports_template_data['admin_reports'][] = $this->_registrations_per_event_report();
613
-    }
605
+	/**
606
+	 * This is called when javascript is being enqueued to setup the various data needed for the reports js.
607
+	 * Also $this->{$_reports_template_data} property is set for later usage by the _registration_reports method.
608
+	 */
609
+	protected function _registration_reports_js_setup()
610
+	{
611
+		$this->_reports_template_data['admin_reports'][] = $this->_registrations_per_day_report();
612
+		$this->_reports_template_data['admin_reports'][] = $this->_registrations_per_event_report();
613
+	}
614 614
 
615 615
 
616
-    /**
617
-     *        generates Business Reports regarding Registrations
618
-     *
619
-     * @access protected
620
-     * @return void
621
-     * @throws DomainException
622
-     */
623
-    protected function _registration_reports()
624
-    {
625
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_reports.template.php';
626
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
627
-            $template_path,
628
-            $this->_reports_template_data,
629
-            true
630
-        );
631
-        // the final template wrapper
632
-        $this->display_admin_page_with_no_sidebar();
633
-    }
616
+	/**
617
+	 *        generates Business Reports regarding Registrations
618
+	 *
619
+	 * @access protected
620
+	 * @return void
621
+	 * @throws DomainException
622
+	 */
623
+	protected function _registration_reports()
624
+	{
625
+		$template_path = EE_ADMIN_TEMPLATE . 'admin_reports.template.php';
626
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
627
+			$template_path,
628
+			$this->_reports_template_data,
629
+			true
630
+		);
631
+		// the final template wrapper
632
+		$this->display_admin_page_with_no_sidebar();
633
+	}
634 634
 
635 635
 
636
-    /**
637
-     * Generates Business Report showing total registrations per day.
638
-     *
639
-     * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
640
-     * @return string
641
-     * @throws EE_Error
642
-     * @throws InvalidArgumentException
643
-     * @throws InvalidDataTypeException
644
-     * @throws InvalidInterfaceException
645
-     */
646
-    private function _registrations_per_day_report($period = '-1 month')
647
-    {
648
-        $report_ID = 'reg-admin-registrations-per-day-report-dv';
649
-        $results = EEM_Registration::instance()->get_registrations_per_day_and_per_status_report($period);
650
-        $results = (array) $results;
651
-        $regs = array();
652
-        $subtitle = '';
653
-        if ($results) {
654
-            $column_titles = array();
655
-            $tracker = 0;
656
-            foreach ($results as $result) {
657
-                $report_column_values = array();
658
-                foreach ($result as $property_name => $property_value) {
659
-                    $property_value = $property_name === 'Registration_REG_date' ? $property_value
660
-                        : (int) $property_value;
661
-                    $report_column_values[] = $property_value;
662
-                    if ($tracker === 0) {
663
-                        if ($property_name === 'Registration_REG_date') {
664
-                            $column_titles[] = esc_html__(
665
-                                'Date (only days with registrations are shown)',
666
-                                'event_espresso'
667
-                            );
668
-                        } else {
669
-                            $column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
670
-                        }
671
-                    }
672
-                }
673
-                $tracker++;
674
-                $regs[] = $report_column_values;
675
-            }
676
-            // make sure the column_titles is pushed to the beginning of the array
677
-            array_unshift($regs, $column_titles);
678
-            // setup the date range.
679
-            $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
680
-            $beginning_date = new DateTime("now " . $period, $DateTimeZone);
681
-            $ending_date = new DateTime("now", $DateTimeZone);
682
-            $subtitle = sprintf(
683
-                _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
684
-                $beginning_date->format('Y-m-d'),
685
-                $ending_date->format('Y-m-d')
686
-            );
687
-        }
688
-        $report_title = esc_html__('Total Registrations per Day', 'event_espresso');
689
-        $report_params = array(
690
-            'title'     => $report_title,
691
-            'subtitle'  => $subtitle,
692
-            'id'        => $report_ID,
693
-            'regs'      => $regs,
694
-            'noResults' => empty($regs),
695
-            'noRegsMsg' => sprintf(
696
-                esc_html__(
697
-                    '%sThere are currently no registration records in the last month for this report.%s',
698
-                    'event_espresso'
699
-                ),
700
-                '<h2>' . $report_title . '</h2><p>',
701
-                '</p>'
702
-            ),
703
-        );
704
-        wp_localize_script('ee-reg-reports-js', 'regPerDay', $report_params);
705
-        return $report_ID;
706
-    }
636
+	/**
637
+	 * Generates Business Report showing total registrations per day.
638
+	 *
639
+	 * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
640
+	 * @return string
641
+	 * @throws EE_Error
642
+	 * @throws InvalidArgumentException
643
+	 * @throws InvalidDataTypeException
644
+	 * @throws InvalidInterfaceException
645
+	 */
646
+	private function _registrations_per_day_report($period = '-1 month')
647
+	{
648
+		$report_ID = 'reg-admin-registrations-per-day-report-dv';
649
+		$results = EEM_Registration::instance()->get_registrations_per_day_and_per_status_report($period);
650
+		$results = (array) $results;
651
+		$regs = array();
652
+		$subtitle = '';
653
+		if ($results) {
654
+			$column_titles = array();
655
+			$tracker = 0;
656
+			foreach ($results as $result) {
657
+				$report_column_values = array();
658
+				foreach ($result as $property_name => $property_value) {
659
+					$property_value = $property_name === 'Registration_REG_date' ? $property_value
660
+						: (int) $property_value;
661
+					$report_column_values[] = $property_value;
662
+					if ($tracker === 0) {
663
+						if ($property_name === 'Registration_REG_date') {
664
+							$column_titles[] = esc_html__(
665
+								'Date (only days with registrations are shown)',
666
+								'event_espresso'
667
+							);
668
+						} else {
669
+							$column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
670
+						}
671
+					}
672
+				}
673
+				$tracker++;
674
+				$regs[] = $report_column_values;
675
+			}
676
+			// make sure the column_titles is pushed to the beginning of the array
677
+			array_unshift($regs, $column_titles);
678
+			// setup the date range.
679
+			$DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
680
+			$beginning_date = new DateTime("now " . $period, $DateTimeZone);
681
+			$ending_date = new DateTime("now", $DateTimeZone);
682
+			$subtitle = sprintf(
683
+				_x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
684
+				$beginning_date->format('Y-m-d'),
685
+				$ending_date->format('Y-m-d')
686
+			);
687
+		}
688
+		$report_title = esc_html__('Total Registrations per Day', 'event_espresso');
689
+		$report_params = array(
690
+			'title'     => $report_title,
691
+			'subtitle'  => $subtitle,
692
+			'id'        => $report_ID,
693
+			'regs'      => $regs,
694
+			'noResults' => empty($regs),
695
+			'noRegsMsg' => sprintf(
696
+				esc_html__(
697
+					'%sThere are currently no registration records in the last month for this report.%s',
698
+					'event_espresso'
699
+				),
700
+				'<h2>' . $report_title . '</h2><p>',
701
+				'</p>'
702
+			),
703
+		);
704
+		wp_localize_script('ee-reg-reports-js', 'regPerDay', $report_params);
705
+		return $report_ID;
706
+	}
707 707
 
708 708
 
709
-    /**
710
-     * Generates Business Report showing total registrations per event.
711
-     *
712
-     * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
713
-     * @return string
714
-     * @throws EE_Error
715
-     * @throws InvalidArgumentException
716
-     * @throws InvalidDataTypeException
717
-     * @throws InvalidInterfaceException
718
-     */
719
-    private function _registrations_per_event_report($period = '-1 month')
720
-    {
721
-        $report_ID = 'reg-admin-registrations-per-event-report-dv';
722
-        $results = EEM_Registration::instance()->get_registrations_per_event_and_per_status_report($period);
723
-        $results = (array) $results;
724
-        $regs = array();
725
-        $subtitle = '';
726
-        if ($results) {
727
-            $column_titles = array();
728
-            $tracker = 0;
729
-            foreach ($results as $result) {
730
-                $report_column_values = array();
731
-                foreach ($result as $property_name => $property_value) {
732
-                    $property_value = $property_name === 'Registration_Event' ? wp_trim_words(
733
-                        $property_value,
734
-                        4,
735
-                        '...'
736
-                    ) : (int) $property_value;
737
-                    $report_column_values[] = $property_value;
738
-                    if ($tracker === 0) {
739
-                        if ($property_name === 'Registration_Event') {
740
-                            $column_titles[] = esc_html__('Event', 'event_espresso');
741
-                        } else {
742
-                            $column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
743
-                        }
744
-                    }
745
-                }
746
-                $tracker++;
747
-                $regs[] = $report_column_values;
748
-            }
749
-            // make sure the column_titles is pushed to the beginning of the array
750
-            array_unshift($regs, $column_titles);
751
-            // setup the date range.
752
-            $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
753
-            $beginning_date = new DateTime("now " . $period, $DateTimeZone);
754
-            $ending_date = new DateTime("now", $DateTimeZone);
755
-            $subtitle = sprintf(
756
-                _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
757
-                $beginning_date->format('Y-m-d'),
758
-                $ending_date->format('Y-m-d')
759
-            );
760
-        }
761
-        $report_title = esc_html__('Total Registrations per Event', 'event_espresso');
762
-        $report_params = array(
763
-            'title'     => $report_title,
764
-            'subtitle'  => $subtitle,
765
-            'id'        => $report_ID,
766
-            'regs'      => $regs,
767
-            'noResults' => empty($regs),
768
-            'noRegsMsg' => sprintf(
769
-                esc_html__(
770
-                    '%sThere are currently no registration records in the last month for this report.%s',
771
-                    'event_espresso'
772
-                ),
773
-                '<h2>' . $report_title . '</h2><p>',
774
-                '</p>'
775
-            ),
776
-        );
777
-        wp_localize_script('ee-reg-reports-js', 'regPerEvent', $report_params);
778
-        return $report_ID;
779
-    }
709
+	/**
710
+	 * Generates Business Report showing total registrations per event.
711
+	 *
712
+	 * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated.
713
+	 * @return string
714
+	 * @throws EE_Error
715
+	 * @throws InvalidArgumentException
716
+	 * @throws InvalidDataTypeException
717
+	 * @throws InvalidInterfaceException
718
+	 */
719
+	private function _registrations_per_event_report($period = '-1 month')
720
+	{
721
+		$report_ID = 'reg-admin-registrations-per-event-report-dv';
722
+		$results = EEM_Registration::instance()->get_registrations_per_event_and_per_status_report($period);
723
+		$results = (array) $results;
724
+		$regs = array();
725
+		$subtitle = '';
726
+		if ($results) {
727
+			$column_titles = array();
728
+			$tracker = 0;
729
+			foreach ($results as $result) {
730
+				$report_column_values = array();
731
+				foreach ($result as $property_name => $property_value) {
732
+					$property_value = $property_name === 'Registration_Event' ? wp_trim_words(
733
+						$property_value,
734
+						4,
735
+						'...'
736
+					) : (int) $property_value;
737
+					$report_column_values[] = $property_value;
738
+					if ($tracker === 0) {
739
+						if ($property_name === 'Registration_Event') {
740
+							$column_titles[] = esc_html__('Event', 'event_espresso');
741
+						} else {
742
+							$column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence');
743
+						}
744
+					}
745
+				}
746
+				$tracker++;
747
+				$regs[] = $report_column_values;
748
+			}
749
+			// make sure the column_titles is pushed to the beginning of the array
750
+			array_unshift($regs, $column_titles);
751
+			// setup the date range.
752
+			$DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
753
+			$beginning_date = new DateTime("now " . $period, $DateTimeZone);
754
+			$ending_date = new DateTime("now", $DateTimeZone);
755
+			$subtitle = sprintf(
756
+				_x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
757
+				$beginning_date->format('Y-m-d'),
758
+				$ending_date->format('Y-m-d')
759
+			);
760
+		}
761
+		$report_title = esc_html__('Total Registrations per Event', 'event_espresso');
762
+		$report_params = array(
763
+			'title'     => $report_title,
764
+			'subtitle'  => $subtitle,
765
+			'id'        => $report_ID,
766
+			'regs'      => $regs,
767
+			'noResults' => empty($regs),
768
+			'noRegsMsg' => sprintf(
769
+				esc_html__(
770
+					'%sThere are currently no registration records in the last month for this report.%s',
771
+					'event_espresso'
772
+				),
773
+				'<h2>' . $report_title . '</h2><p>',
774
+				'</p>'
775
+			),
776
+		);
777
+		wp_localize_script('ee-reg-reports-js', 'regPerEvent', $report_params);
778
+		return $report_ID;
779
+	}
780 780
 
781 781
 
782
-    /**
783
-     * generates HTML for the Registration Check-in list table (showing all Check-ins for a specific registration)
784
-     *
785
-     * @access protected
786
-     * @return void
787
-     * @throws EE_Error
788
-     * @throws InvalidArgumentException
789
-     * @throws InvalidDataTypeException
790
-     * @throws InvalidInterfaceException
791
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
792
-     */
793
-    protected function _registration_checkin_list_table()
794
-    {
795
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
796
-        $reg_id = isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : null;
797
-        /** @var EE_Registration $registration */
798
-        $registration = EEM_Registration::instance()->get_one_by_ID($reg_id);
799
-        $attendee = $registration->attendee();
800
-        $this->_admin_page_title .= $this->get_action_link_or_button(
801
-            'new_registration',
802
-            'add-registrant',
803
-            array('event_id' => $registration->event_ID()),
804
-            'add-new-h2'
805
-        );
806
-        $checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
807
-        $checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
808
-        $legend_items = array(
809
-            'checkin'  => array(
810
-                'class' => $checked_in->cssClasses(),
811
-                'desc'  => $checked_in->legendLabel(),
812
-            ),
813
-            'checkout' => array(
814
-                'class' => $checked_out->cssClasses(),
815
-                'desc'  => $checked_out->legendLabel(),
816
-            ),
817
-        );
818
-        $this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
819
-        $dtt_id = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
820
-        /** @var EE_Datetime $datetime */
821
-        $datetime = EEM_Datetime::instance()->get_one_by_ID($dtt_id);
822
-        $datetime_label = '';
823
-        if ($datetime instanceof EE_Datetime) {
824
-            $datetime_label = $datetime->get_dtt_display_name(true);
825
-            $datetime_label .= ! empty($datetime_label)
826
-                ? ' (' . $datetime->get_dtt_display_name() . ')'
827
-                : $datetime->get_dtt_display_name();
828
-        }
829
-        $datetime_link = ! empty($dtt_id) && $registration instanceof EE_Registration
830
-            ? EE_Admin_Page::add_query_args_and_nonce(
831
-                array(
832
-                    'action'   => 'event_registrations',
833
-                    'event_id' => $registration->event_ID(),
834
-                    'DTT_ID'   => $dtt_id,
835
-                ),
836
-                $this->_admin_base_url
837
-            )
838
-            : '';
839
-        $datetime_link = ! empty($datetime_link)
840
-            ? '<a href="' . $datetime_link . '">'
841
-              . '<span id="checkin-dtt">'
842
-              . $datetime_label
843
-              . '</span></a>'
844
-            : $datetime_label;
845
-        $attendee_name = $attendee instanceof EE_Attendee
846
-            ? $attendee->full_name()
847
-            : '';
848
-        $attendee_link = $attendee instanceof EE_Attendee
849
-            ? $attendee->get_admin_details_link()
850
-            : '';
851
-        $attendee_link = ! empty($attendee_link)
852
-            ? '<a href="' . $attendee->get_admin_details_link() . '"'
853
-              . ' title="' . esc_html__('Click for attendee details', 'event_espresso') . '">'
854
-              . '<span id="checkin-attendee-name">'
855
-              . $attendee_name
856
-              . '</span></a>'
857
-            : '';
858
-        $event_link = $registration->event() instanceof EE_Event
859
-            ? $registration->event()->get_admin_details_link()
860
-            : '';
861
-        $event_link = ! empty($event_link)
862
-            ? '<a href="' . $event_link . '"'
863
-              . ' title="' . esc_html__('Click here to edit event.', 'event_espresso') . '">'
864
-              . '<span id="checkin-event-name">'
865
-              . $registration->event_name()
866
-              . '</span>'
867
-              . '</a>'
868
-            : '';
869
-        $this->_template_args['before_list_table'] = ! empty($reg_id) && ! empty($dtt_id)
870
-            ? '<h2>' . sprintf(
871
-                esc_html__('Displaying check in records for %1$s for %2$s at the event, %3$s', 'event_espresso'),
872
-                $attendee_link,
873
-                $datetime_link,
874
-                $event_link
875
-            ) . '</h2>'
876
-            : '';
877
-        $this->_template_args['list_table_hidden_fields'] = ! empty($reg_id)
878
-            ? '<input type="hidden" name="_REG_ID" value="' . $reg_id . '">' : '';
879
-        $this->_template_args['list_table_hidden_fields'] .= ! empty($dtt_id)
880
-            ? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : '';
881
-        $this->display_admin_list_table_page_with_no_sidebar();
882
-    }
782
+	/**
783
+	 * generates HTML for the Registration Check-in list table (showing all Check-ins for a specific registration)
784
+	 *
785
+	 * @access protected
786
+	 * @return void
787
+	 * @throws EE_Error
788
+	 * @throws InvalidArgumentException
789
+	 * @throws InvalidDataTypeException
790
+	 * @throws InvalidInterfaceException
791
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
792
+	 */
793
+	protected function _registration_checkin_list_table()
794
+	{
795
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
796
+		$reg_id = isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : null;
797
+		/** @var EE_Registration $registration */
798
+		$registration = EEM_Registration::instance()->get_one_by_ID($reg_id);
799
+		$attendee = $registration->attendee();
800
+		$this->_admin_page_title .= $this->get_action_link_or_button(
801
+			'new_registration',
802
+			'add-registrant',
803
+			array('event_id' => $registration->event_ID()),
804
+			'add-new-h2'
805
+		);
806
+		$checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
807
+		$checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
808
+		$legend_items = array(
809
+			'checkin'  => array(
810
+				'class' => $checked_in->cssClasses(),
811
+				'desc'  => $checked_in->legendLabel(),
812
+			),
813
+			'checkout' => array(
814
+				'class' => $checked_out->cssClasses(),
815
+				'desc'  => $checked_out->legendLabel(),
816
+			),
817
+		);
818
+		$this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
819
+		$dtt_id = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
820
+		/** @var EE_Datetime $datetime */
821
+		$datetime = EEM_Datetime::instance()->get_one_by_ID($dtt_id);
822
+		$datetime_label = '';
823
+		if ($datetime instanceof EE_Datetime) {
824
+			$datetime_label = $datetime->get_dtt_display_name(true);
825
+			$datetime_label .= ! empty($datetime_label)
826
+				? ' (' . $datetime->get_dtt_display_name() . ')'
827
+				: $datetime->get_dtt_display_name();
828
+		}
829
+		$datetime_link = ! empty($dtt_id) && $registration instanceof EE_Registration
830
+			? EE_Admin_Page::add_query_args_and_nonce(
831
+				array(
832
+					'action'   => 'event_registrations',
833
+					'event_id' => $registration->event_ID(),
834
+					'DTT_ID'   => $dtt_id,
835
+				),
836
+				$this->_admin_base_url
837
+			)
838
+			: '';
839
+		$datetime_link = ! empty($datetime_link)
840
+			? '<a href="' . $datetime_link . '">'
841
+			  . '<span id="checkin-dtt">'
842
+			  . $datetime_label
843
+			  . '</span></a>'
844
+			: $datetime_label;
845
+		$attendee_name = $attendee instanceof EE_Attendee
846
+			? $attendee->full_name()
847
+			: '';
848
+		$attendee_link = $attendee instanceof EE_Attendee
849
+			? $attendee->get_admin_details_link()
850
+			: '';
851
+		$attendee_link = ! empty($attendee_link)
852
+			? '<a href="' . $attendee->get_admin_details_link() . '"'
853
+			  . ' title="' . esc_html__('Click for attendee details', 'event_espresso') . '">'
854
+			  . '<span id="checkin-attendee-name">'
855
+			  . $attendee_name
856
+			  . '</span></a>'
857
+			: '';
858
+		$event_link = $registration->event() instanceof EE_Event
859
+			? $registration->event()->get_admin_details_link()
860
+			: '';
861
+		$event_link = ! empty($event_link)
862
+			? '<a href="' . $event_link . '"'
863
+			  . ' title="' . esc_html__('Click here to edit event.', 'event_espresso') . '">'
864
+			  . '<span id="checkin-event-name">'
865
+			  . $registration->event_name()
866
+			  . '</span>'
867
+			  . '</a>'
868
+			: '';
869
+		$this->_template_args['before_list_table'] = ! empty($reg_id) && ! empty($dtt_id)
870
+			? '<h2>' . sprintf(
871
+				esc_html__('Displaying check in records for %1$s for %2$s at the event, %3$s', 'event_espresso'),
872
+				$attendee_link,
873
+				$datetime_link,
874
+				$event_link
875
+			) . '</h2>'
876
+			: '';
877
+		$this->_template_args['list_table_hidden_fields'] = ! empty($reg_id)
878
+			? '<input type="hidden" name="_REG_ID" value="' . $reg_id . '">' : '';
879
+		$this->_template_args['list_table_hidden_fields'] .= ! empty($dtt_id)
880
+			? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : '';
881
+		$this->display_admin_list_table_page_with_no_sidebar();
882
+	}
883 883
 
884 884
 
885
-    /**
886
-     * toggle the Check-in status for the given registration (coming from ajax)
887
-     *
888
-     * @return void (JSON)
889
-     * @throws EE_Error
890
-     * @throws InvalidArgumentException
891
-     * @throws InvalidDataTypeException
892
-     * @throws InvalidInterfaceException
893
-     */
894
-    public function toggle_checkin_status()
895
-    {
896
-        // first make sure we have the necessary data
897
-        if (! isset($this->_req_data['_regid'])) {
898
-            EE_Error::add_error(
899
-                esc_html__(
900
-                    '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',
901
-                    'event_espresso'
902
-                ),
903
-                __FILE__,
904
-                __FUNCTION__,
905
-                __LINE__
906
-            );
907
-            $this->_template_args['success'] = false;
908
-            $this->_template_args['error'] = true;
909
-            $this->_return_json();
910
-        };
911
-        // do a nonce check cause we're not coming in from an normal route here.
912
-        $nonce = isset($this->_req_data['checkinnonce']) ? sanitize_text_field($this->_req_data['checkinnonce'])
913
-            : '';
914
-        $nonce_ref = 'checkin_nonce';
915
-        $this->_verify_nonce($nonce, $nonce_ref);
916
-        // beautiful! Made it this far so let's get the status.
917
-        $new_status = new CheckinStatusDashicon($this->_toggle_checkin_status());
918
-        // setup new class to return via ajax
919
-        $this->_template_args['admin_page_content'] = 'clickable trigger-checkin ' . $new_status->cssClasses();
920
-        $this->_template_args['success'] = true;
921
-        $this->_return_json();
922
-    }
885
+	/**
886
+	 * toggle the Check-in status for the given registration (coming from ajax)
887
+	 *
888
+	 * @return void (JSON)
889
+	 * @throws EE_Error
890
+	 * @throws InvalidArgumentException
891
+	 * @throws InvalidDataTypeException
892
+	 * @throws InvalidInterfaceException
893
+	 */
894
+	public function toggle_checkin_status()
895
+	{
896
+		// first make sure we have the necessary data
897
+		if (! isset($this->_req_data['_regid'])) {
898
+			EE_Error::add_error(
899
+				esc_html__(
900
+					'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',
901
+					'event_espresso'
902
+				),
903
+				__FILE__,
904
+				__FUNCTION__,
905
+				__LINE__
906
+			);
907
+			$this->_template_args['success'] = false;
908
+			$this->_template_args['error'] = true;
909
+			$this->_return_json();
910
+		};
911
+		// do a nonce check cause we're not coming in from an normal route here.
912
+		$nonce = isset($this->_req_data['checkinnonce']) ? sanitize_text_field($this->_req_data['checkinnonce'])
913
+			: '';
914
+		$nonce_ref = 'checkin_nonce';
915
+		$this->_verify_nonce($nonce, $nonce_ref);
916
+		// beautiful! Made it this far so let's get the status.
917
+		$new_status = new CheckinStatusDashicon($this->_toggle_checkin_status());
918
+		// setup new class to return via ajax
919
+		$this->_template_args['admin_page_content'] = 'clickable trigger-checkin ' . $new_status->cssClasses();
920
+		$this->_template_args['success'] = true;
921
+		$this->_return_json();
922
+	}
923 923
 
924 924
 
925
-    /**
926
-     * handles toggling the checkin status for the registration,
927
-     *
928
-     * @access protected
929
-     * @return int|void
930
-     * @throws EE_Error
931
-     * @throws InvalidArgumentException
932
-     * @throws InvalidDataTypeException
933
-     * @throws InvalidInterfaceException
934
-     */
935
-    protected function _toggle_checkin_status()
936
-    {
937
-        // first let's get the query args out of the way for the redirect
938
-        $query_args = array(
939
-            'action'   => 'event_registrations',
940
-            'event_id' => isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null,
941
-            'DTT_ID'   => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null,
942
-        );
943
-        $new_status = false;
944
-        // bulk action check in toggle
945
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
946
-            // cycle thru checkboxes
947
-            while (list($REG_ID, $value) = each($this->_req_data['checkbox'])) {
948
-                $DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
949
-                $new_status = $this->_toggle_checkin($REG_ID, $DTT_ID);
950
-            }
951
-        } elseif (isset($this->_req_data['_regid'])) {
952
-            // coming from ajax request
953
-            $DTT_ID = isset($this->_req_data['dttid']) ? $this->_req_data['dttid'] : null;
954
-            $query_args['DTT_ID'] = $DTT_ID;
955
-            $new_status = $this->_toggle_checkin($this->_req_data['_regid'], $DTT_ID);
956
-        } else {
957
-            EE_Error::add_error(
958
-                esc_html__('Missing some required data to toggle the Check-in', 'event_espresso'),
959
-                __FILE__,
960
-                __FUNCTION__,
961
-                __LINE__
962
-            );
963
-        }
964
-        if (defined('DOING_AJAX')) {
965
-            return $new_status;
966
-        }
967
-        $this->_redirect_after_action(false, '', '', $query_args, true);
968
-    }
925
+	/**
926
+	 * handles toggling the checkin status for the registration,
927
+	 *
928
+	 * @access protected
929
+	 * @return int|void
930
+	 * @throws EE_Error
931
+	 * @throws InvalidArgumentException
932
+	 * @throws InvalidDataTypeException
933
+	 * @throws InvalidInterfaceException
934
+	 */
935
+	protected function _toggle_checkin_status()
936
+	{
937
+		// first let's get the query args out of the way for the redirect
938
+		$query_args = array(
939
+			'action'   => 'event_registrations',
940
+			'event_id' => isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null,
941
+			'DTT_ID'   => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null,
942
+		);
943
+		$new_status = false;
944
+		// bulk action check in toggle
945
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
946
+			// cycle thru checkboxes
947
+			while (list($REG_ID, $value) = each($this->_req_data['checkbox'])) {
948
+				$DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
949
+				$new_status = $this->_toggle_checkin($REG_ID, $DTT_ID);
950
+			}
951
+		} elseif (isset($this->_req_data['_regid'])) {
952
+			// coming from ajax request
953
+			$DTT_ID = isset($this->_req_data['dttid']) ? $this->_req_data['dttid'] : null;
954
+			$query_args['DTT_ID'] = $DTT_ID;
955
+			$new_status = $this->_toggle_checkin($this->_req_data['_regid'], $DTT_ID);
956
+		} else {
957
+			EE_Error::add_error(
958
+				esc_html__('Missing some required data to toggle the Check-in', 'event_espresso'),
959
+				__FILE__,
960
+				__FUNCTION__,
961
+				__LINE__
962
+			);
963
+		}
964
+		if (defined('DOING_AJAX')) {
965
+			return $new_status;
966
+		}
967
+		$this->_redirect_after_action(false, '', '', $query_args, true);
968
+	}
969 969
 
970 970
 
971
-    /**
972
-     * This is toggles a single Check-in for the given registration and datetime.
973
-     *
974
-     * @param  int $REG_ID The registration we're toggling
975
-     * @param  int $DTT_ID The datetime we're toggling
976
-     * @return int The new status toggled to.
977
-     * @throws EE_Error
978
-     * @throws InvalidArgumentException
979
-     * @throws InvalidDataTypeException
980
-     * @throws InvalidInterfaceException
981
-     */
982
-    private function _toggle_checkin($REG_ID, $DTT_ID)
983
-    {
984
-        /** @var EE_Registration $REG */
985
-        $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
986
-        $new_status = $REG->toggle_checkin_status($DTT_ID);
987
-        if ($new_status !== false) {
988
-            EE_Error::add_success($REG->get_checkin_msg($DTT_ID));
989
-        } else {
990
-            EE_Error::add_error($REG->get_checkin_msg($DTT_ID, true), __FILE__, __FUNCTION__, __LINE__);
991
-            $new_status = false;
992
-        }
993
-        return $new_status;
994
-    }
971
+	/**
972
+	 * This is toggles a single Check-in for the given registration and datetime.
973
+	 *
974
+	 * @param  int $REG_ID The registration we're toggling
975
+	 * @param  int $DTT_ID The datetime we're toggling
976
+	 * @return int The new status toggled to.
977
+	 * @throws EE_Error
978
+	 * @throws InvalidArgumentException
979
+	 * @throws InvalidDataTypeException
980
+	 * @throws InvalidInterfaceException
981
+	 */
982
+	private function _toggle_checkin($REG_ID, $DTT_ID)
983
+	{
984
+		/** @var EE_Registration $REG */
985
+		$REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
986
+		$new_status = $REG->toggle_checkin_status($DTT_ID);
987
+		if ($new_status !== false) {
988
+			EE_Error::add_success($REG->get_checkin_msg($DTT_ID));
989
+		} else {
990
+			EE_Error::add_error($REG->get_checkin_msg($DTT_ID, true), __FILE__, __FUNCTION__, __LINE__);
991
+			$new_status = false;
992
+		}
993
+		return $new_status;
994
+	}
995 995
 
996 996
 
997
-    /**
998
-     * Takes care of deleting multiple EE_Checkin table rows
999
-     *
1000
-     * @access protected
1001
-     * @return void
1002
-     * @throws EE_Error
1003
-     * @throws InvalidArgumentException
1004
-     * @throws InvalidDataTypeException
1005
-     * @throws InvalidInterfaceException
1006
-     */
1007
-    protected function _delete_checkin_rows()
1008
-    {
1009
-        $query_args = array(
1010
-            'action'  => 'registration_checkins',
1011
-            'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1012
-            '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1013
-        );
1014
-        $errors = 0;
1015
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1016
-            while (list($CHK_ID, $value) = each($this->_req_data['checkbox'])) {
1017
-                if (! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) {
1018
-                    $errors++;
1019
-                }
1020
-            }
1021
-        } else {
1022
-            EE_Error::add_error(
1023
-                esc_html__(
1024
-                    'So, something went wrong with the bulk delete because there was no data received for instructions on WHAT to delete!',
1025
-                    'event_espresso'
1026
-                ),
1027
-                __FILE__,
1028
-                __FUNCTION__,
1029
-                __LINE__
1030
-            );
1031
-            $this->_redirect_after_action(false, '', '', $query_args, true);
1032
-        }
1033
-        if ($errors > 0) {
1034
-            EE_Error::add_error(
1035
-                sprintf(__('There were %d records that did not delete successfully', 'event_espresso'), $errors),
1036
-                __FILE__,
1037
-                __FUNCTION__,
1038
-                __LINE__
1039
-            );
1040
-        } else {
1041
-            EE_Error::add_success(__('Records were successfully deleted', 'event_espresso'));
1042
-        }
1043
-        $this->_redirect_after_action(false, '', '', $query_args, true);
1044
-    }
997
+	/**
998
+	 * Takes care of deleting multiple EE_Checkin table rows
999
+	 *
1000
+	 * @access protected
1001
+	 * @return void
1002
+	 * @throws EE_Error
1003
+	 * @throws InvalidArgumentException
1004
+	 * @throws InvalidDataTypeException
1005
+	 * @throws InvalidInterfaceException
1006
+	 */
1007
+	protected function _delete_checkin_rows()
1008
+	{
1009
+		$query_args = array(
1010
+			'action'  => 'registration_checkins',
1011
+			'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1012
+			'_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1013
+		);
1014
+		$errors = 0;
1015
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1016
+			while (list($CHK_ID, $value) = each($this->_req_data['checkbox'])) {
1017
+				if (! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) {
1018
+					$errors++;
1019
+				}
1020
+			}
1021
+		} else {
1022
+			EE_Error::add_error(
1023
+				esc_html__(
1024
+					'So, something went wrong with the bulk delete because there was no data received for instructions on WHAT to delete!',
1025
+					'event_espresso'
1026
+				),
1027
+				__FILE__,
1028
+				__FUNCTION__,
1029
+				__LINE__
1030
+			);
1031
+			$this->_redirect_after_action(false, '', '', $query_args, true);
1032
+		}
1033
+		if ($errors > 0) {
1034
+			EE_Error::add_error(
1035
+				sprintf(__('There were %d records that did not delete successfully', 'event_espresso'), $errors),
1036
+				__FILE__,
1037
+				__FUNCTION__,
1038
+				__LINE__
1039
+			);
1040
+		} else {
1041
+			EE_Error::add_success(__('Records were successfully deleted', 'event_espresso'));
1042
+		}
1043
+		$this->_redirect_after_action(false, '', '', $query_args, true);
1044
+	}
1045 1045
 
1046 1046
 
1047
-    /**
1048
-     * Deletes a single EE_Checkin row
1049
-     *
1050
-     * @return void
1051
-     * @throws EE_Error
1052
-     * @throws InvalidArgumentException
1053
-     * @throws InvalidDataTypeException
1054
-     * @throws InvalidInterfaceException
1055
-     */
1056
-    protected function _delete_checkin_row()
1057
-    {
1058
-        $query_args = array(
1059
-            'action'  => 'registration_checkins',
1060
-            'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1061
-            '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1062
-        );
1063
-        if (! empty($this->_req_data['CHK_ID'])) {
1064
-            if (! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
1065
-                EE_Error::add_error(
1066
-                    esc_html__('Something went wrong and this check-in record was not deleted', 'event_espresso'),
1067
-                    __FILE__,
1068
-                    __FUNCTION__,
1069
-                    __LINE__
1070
-                );
1071
-            } else {
1072
-                EE_Error::add_success(__('Check-In record successfully deleted', 'event_espresso'));
1073
-            }
1074
-        } else {
1075
-            EE_Error::add_error(
1076
-                esc_html__(
1077
-                    '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',
1078
-                    'event_espresso'
1079
-                ),
1080
-                __FILE__,
1081
-                __FUNCTION__,
1082
-                __LINE__
1083
-            );
1084
-        }
1085
-        $this->_redirect_after_action(false, '', '', $query_args, true);
1086
-    }
1047
+	/**
1048
+	 * Deletes a single EE_Checkin row
1049
+	 *
1050
+	 * @return void
1051
+	 * @throws EE_Error
1052
+	 * @throws InvalidArgumentException
1053
+	 * @throws InvalidDataTypeException
1054
+	 * @throws InvalidInterfaceException
1055
+	 */
1056
+	protected function _delete_checkin_row()
1057
+	{
1058
+		$query_args = array(
1059
+			'action'  => 'registration_checkins',
1060
+			'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1061
+			'_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1062
+		);
1063
+		if (! empty($this->_req_data['CHK_ID'])) {
1064
+			if (! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
1065
+				EE_Error::add_error(
1066
+					esc_html__('Something went wrong and this check-in record was not deleted', 'event_espresso'),
1067
+					__FILE__,
1068
+					__FUNCTION__,
1069
+					__LINE__
1070
+				);
1071
+			} else {
1072
+				EE_Error::add_success(__('Check-In record successfully deleted', 'event_espresso'));
1073
+			}
1074
+		} else {
1075
+			EE_Error::add_error(
1076
+				esc_html__(
1077
+					'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',
1078
+					'event_espresso'
1079
+				),
1080
+				__FILE__,
1081
+				__FUNCTION__,
1082
+				__LINE__
1083
+			);
1084
+		}
1085
+		$this->_redirect_after_action(false, '', '', $query_args, true);
1086
+	}
1087 1087
 
1088 1088
 
1089
-    /**
1090
-     *        generates HTML for the Event Registrations List Table
1091
-     *
1092
-     * @access protected
1093
-     * @return void
1094
-     * @throws EE_Error
1095
-     * @throws InvalidArgumentException
1096
-     * @throws InvalidDataTypeException
1097
-     * @throws InvalidInterfaceException
1098
-     */
1099
-    protected function _event_registrations_list_table()
1100
-    {
1101
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1102
-        $this->_admin_page_title .= isset($this->_req_data['event_id'])
1103
-            ? $this->get_action_link_or_button(
1104
-                'new_registration',
1105
-                'add-registrant',
1106
-                array('event_id' => $this->_req_data['event_id']),
1107
-                'add-new-h2',
1108
-                '',
1109
-                false
1110
-            )
1111
-            : '';
1112
-        $checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
1113
-        $checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
1114
-        $checked_never = new CheckinStatusDashicon(EE_Checkin::status_checked_never);
1115
-        $legend_items = array(
1116
-            'star-icon'        => array(
1117
-                'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
1118
-                'desc'  => esc_html__('This Registrant is the Primary Registrant', 'event_espresso'),
1119
-            ),
1120
-            'checkin'          => array(
1121
-                'class' => $checked_in->cssClasses(),
1122
-                'desc'  => $checked_in->legendLabel(),
1123
-            ),
1124
-            'checkout'         => array(
1125
-                'class' => $checked_out->cssClasses(),
1126
-                'desc'  => $checked_out->legendLabel(),
1127
-            ),
1128
-            'nocheckinrecord'  => array(
1129
-                'class' => $checked_never->cssClasses(),
1130
-                'desc'  => $checked_never->legendLabel(),
1131
-            ),
1132
-            'approved_status'  => array(
1133
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1134
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'),
1135
-            ),
1136
-            'cancelled_status' => array(
1137
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1138
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'),
1139
-            ),
1140
-            'declined_status'  => array(
1141
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1142
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'),
1143
-            ),
1144
-            'not_approved'     => array(
1145
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1146
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'),
1147
-            ),
1148
-            'pending_status'   => array(
1149
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1150
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'),
1151
-            ),
1152
-            'wait_list'        => array(
1153
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1154
-                'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'),
1155
-            ),
1156
-        );
1157
-        $this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
1158
-        $event_id = isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null;
1159
-        /** @var EE_Event $event */
1160
-        $event = EEM_Event::instance()->get_one_by_ID($event_id);
1161
-        $this->_template_args['before_list_table'] = $event instanceof EE_Event
1162
-            ? '<h2>' . sprintf(
1163
-                esc_html__('Viewing Registrations for Event: %s', 'event_espresso'),
1164
-                EEM_Event::instance()->get_one_by_ID($event_id)->get('EVT_name')
1165
-            ) . '</h2>'
1166
-            : '';
1167
-        // need to get the number of datetimes on the event and set default datetime_id if there is only one datetime on
1168
-        // the event.
1169
-        $DTT_ID = ! empty($this->_req_data['DTT_ID']) ? absint($this->_req_data['DTT_ID']) : 0;
1170
-        $datetime = null;
1171
-        if ($event instanceof EE_Event) {
1172
-            $datetimes_on_event = $event->datetimes();
1173
-            if (count($datetimes_on_event) === 1) {
1174
-                $datetime = reset($datetimes_on_event);
1175
-            }
1176
-        }
1177
-        $datetime = $datetime instanceof EE_Datetime ? $datetime : EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1178
-        if ($datetime instanceof EE_Datetime && $this->_template_args['before_list_table'] !== '') {
1179
-            $this->_template_args['before_list_table'] = substr($this->_template_args['before_list_table'], 0, -5);
1180
-            $this->_template_args['before_list_table'] .= ' &nbsp;<span class="drk-grey-text">';
1181
-            $this->_template_args['before_list_table'] .= '<span class="dashicons dashicons-calendar"></span>';
1182
-            $this->_template_args['before_list_table'] .= $datetime->name();
1183
-            $this->_template_args['before_list_table'] .= ' ( ' . $datetime->date_and_time_range() . ' )';
1184
-            $this->_template_args['before_list_table'] .= '</span></h2>';
1185
-        }
1186
-        // if no datetime, then we're on the initial view, so let's give some helpful instructions on what the status
1187
-        // column represents
1188
-        if (! $datetime instanceof EE_Datetime) {
1189
-            $this->_template_args['before_list_table'] .= '<br><p class="description">'
1190
-                                                          . esc_html__(
1191
-                                                              'In this view, the check-in status represents the latest check-in record for the registration in that row.',
1192
-                                                              'event_espresso'
1193
-                                                          )
1194
-                                                          . '</p>';
1195
-        }
1196
-        $this->display_admin_list_table_page_with_no_sidebar();
1197
-    }
1089
+	/**
1090
+	 *        generates HTML for the Event Registrations List Table
1091
+	 *
1092
+	 * @access protected
1093
+	 * @return void
1094
+	 * @throws EE_Error
1095
+	 * @throws InvalidArgumentException
1096
+	 * @throws InvalidDataTypeException
1097
+	 * @throws InvalidInterfaceException
1098
+	 */
1099
+	protected function _event_registrations_list_table()
1100
+	{
1101
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1102
+		$this->_admin_page_title .= isset($this->_req_data['event_id'])
1103
+			? $this->get_action_link_or_button(
1104
+				'new_registration',
1105
+				'add-registrant',
1106
+				array('event_id' => $this->_req_data['event_id']),
1107
+				'add-new-h2',
1108
+				'',
1109
+				false
1110
+			)
1111
+			: '';
1112
+		$checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in);
1113
+		$checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out);
1114
+		$checked_never = new CheckinStatusDashicon(EE_Checkin::status_checked_never);
1115
+		$legend_items = array(
1116
+			'star-icon'        => array(
1117
+				'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
1118
+				'desc'  => esc_html__('This Registrant is the Primary Registrant', 'event_espresso'),
1119
+			),
1120
+			'checkin'          => array(
1121
+				'class' => $checked_in->cssClasses(),
1122
+				'desc'  => $checked_in->legendLabel(),
1123
+			),
1124
+			'checkout'         => array(
1125
+				'class' => $checked_out->cssClasses(),
1126
+				'desc'  => $checked_out->legendLabel(),
1127
+			),
1128
+			'nocheckinrecord'  => array(
1129
+				'class' => $checked_never->cssClasses(),
1130
+				'desc'  => $checked_never->legendLabel(),
1131
+			),
1132
+			'approved_status'  => array(
1133
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1134
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'),
1135
+			),
1136
+			'cancelled_status' => array(
1137
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1138
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'),
1139
+			),
1140
+			'declined_status'  => array(
1141
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1142
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'),
1143
+			),
1144
+			'not_approved'     => array(
1145
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1146
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'),
1147
+			),
1148
+			'pending_status'   => array(
1149
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1150
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'),
1151
+			),
1152
+			'wait_list'        => array(
1153
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1154
+				'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'),
1155
+			),
1156
+		);
1157
+		$this->_template_args['after_list_table'] = $this->_display_legend($legend_items);
1158
+		$event_id = isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null;
1159
+		/** @var EE_Event $event */
1160
+		$event = EEM_Event::instance()->get_one_by_ID($event_id);
1161
+		$this->_template_args['before_list_table'] = $event instanceof EE_Event
1162
+			? '<h2>' . sprintf(
1163
+				esc_html__('Viewing Registrations for Event: %s', 'event_espresso'),
1164
+				EEM_Event::instance()->get_one_by_ID($event_id)->get('EVT_name')
1165
+			) . '</h2>'
1166
+			: '';
1167
+		// need to get the number of datetimes on the event and set default datetime_id if there is only one datetime on
1168
+		// the event.
1169
+		$DTT_ID = ! empty($this->_req_data['DTT_ID']) ? absint($this->_req_data['DTT_ID']) : 0;
1170
+		$datetime = null;
1171
+		if ($event instanceof EE_Event) {
1172
+			$datetimes_on_event = $event->datetimes();
1173
+			if (count($datetimes_on_event) === 1) {
1174
+				$datetime = reset($datetimes_on_event);
1175
+			}
1176
+		}
1177
+		$datetime = $datetime instanceof EE_Datetime ? $datetime : EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1178
+		if ($datetime instanceof EE_Datetime && $this->_template_args['before_list_table'] !== '') {
1179
+			$this->_template_args['before_list_table'] = substr($this->_template_args['before_list_table'], 0, -5);
1180
+			$this->_template_args['before_list_table'] .= ' &nbsp;<span class="drk-grey-text">';
1181
+			$this->_template_args['before_list_table'] .= '<span class="dashicons dashicons-calendar"></span>';
1182
+			$this->_template_args['before_list_table'] .= $datetime->name();
1183
+			$this->_template_args['before_list_table'] .= ' ( ' . $datetime->date_and_time_range() . ' )';
1184
+			$this->_template_args['before_list_table'] .= '</span></h2>';
1185
+		}
1186
+		// if no datetime, then we're on the initial view, so let's give some helpful instructions on what the status
1187
+		// column represents
1188
+		if (! $datetime instanceof EE_Datetime) {
1189
+			$this->_template_args['before_list_table'] .= '<br><p class="description">'
1190
+														  . esc_html__(
1191
+															  'In this view, the check-in status represents the latest check-in record for the registration in that row.',
1192
+															  'event_espresso'
1193
+														  )
1194
+														  . '</p>';
1195
+		}
1196
+		$this->display_admin_list_table_page_with_no_sidebar();
1197
+	}
1198 1198
 
1199
-    /**
1200
-     * Download the registrations check-in report (same as the normal registration report, but with different where
1201
-     * conditions)
1202
-     *
1203
-     * @return void ends the request by a redirect or download
1204
-     */
1205
-    public function _registrations_checkin_report()
1206
-    {
1207
-        $this->_registrations_report_base('_get_checkin_query_params_from_request');
1208
-    }
1199
+	/**
1200
+	 * Download the registrations check-in report (same as the normal registration report, but with different where
1201
+	 * conditions)
1202
+	 *
1203
+	 * @return void ends the request by a redirect or download
1204
+	 */
1205
+	public function _registrations_checkin_report()
1206
+	{
1207
+		$this->_registrations_report_base('_get_checkin_query_params_from_request');
1208
+	}
1209 1209
 
1210
-    /**
1211
-     * Gets the query params from the request, plus adds a where condition for the registration status,
1212
-     * because on the checkin page we only ever want to see approved and pending-approval registrations
1213
-     *
1214
-     * @param array $request
1215
-     * @param int   $per_page
1216
-     * @param bool  $count
1217
-     * @return array
1218
-     * @throws EE_Error
1219
-     */
1220
-    protected function _get_checkin_query_params_from_request(
1221
-        $request,
1222
-        $per_page = 10,
1223
-        $count = false
1224
-    ) {
1225
-        $query_params = $this->_get_registration_query_parameters($request, $per_page, $count);
1226
-        // unlike the regular registrations list table,
1227
-        $status_ids_array = apply_filters(
1228
-            'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array',
1229
-            array(EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved)
1230
-        );
1231
-        $query_params[0]['STS_ID'] = array('IN', $status_ids_array);
1232
-        return $query_params;
1233
-    }
1210
+	/**
1211
+	 * Gets the query params from the request, plus adds a where condition for the registration status,
1212
+	 * because on the checkin page we only ever want to see approved and pending-approval registrations
1213
+	 *
1214
+	 * @param array $request
1215
+	 * @param int   $per_page
1216
+	 * @param bool  $count
1217
+	 * @return array
1218
+	 * @throws EE_Error
1219
+	 */
1220
+	protected function _get_checkin_query_params_from_request(
1221
+		$request,
1222
+		$per_page = 10,
1223
+		$count = false
1224
+	) {
1225
+		$query_params = $this->_get_registration_query_parameters($request, $per_page, $count);
1226
+		// unlike the regular registrations list table,
1227
+		$status_ids_array = apply_filters(
1228
+			'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array',
1229
+			array(EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved)
1230
+		);
1231
+		$query_params[0]['STS_ID'] = array('IN', $status_ids_array);
1232
+		return $query_params;
1233
+	}
1234 1234
 
1235 1235
 
1236
-    /**
1237
-     * Gets registrations for an event
1238
-     *
1239
-     * @param int    $per_page
1240
-     * @param bool   $count whether to return count or data.
1241
-     * @param bool   $trash
1242
-     * @param string $orderby
1243
-     * @return EE_Registration[]|int
1244
-     * @throws EE_Error
1245
-     * @throws InvalidArgumentException
1246
-     * @throws InvalidDataTypeException
1247
-     * @throws InvalidInterfaceException
1248
-     */
1249
-    public function get_event_attendees($per_page = 10, $count = false, $trash = false, $orderby = 'ATT_fname')
1250
-    {
1251
-        // normalize some request params that get setup by the parent `get_registrations` method.
1252
-        $request = $this->_req_data;
1253
-        $request['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : $orderby;
1254
-        $request['order'] = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'ASC';
1255
-        if ($trash) {
1256
-            $request['status'] = 'trash';
1257
-        }
1258
-        $query_params = $this->_get_checkin_query_params_from_request($request, $per_page, $count);
1259
-        /**
1260
-         * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1261
-         *
1262
-         * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1263
-         * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1264
-         *                             or if you have the development copy of EE you can view this at the path:
1265
-         *                             /docs/G--Model-System/model-query-params.md
1266
-         */
1267
-        $query_params['group_by'] = '';
1236
+	/**
1237
+	 * Gets registrations for an event
1238
+	 *
1239
+	 * @param int    $per_page
1240
+	 * @param bool   $count whether to return count or data.
1241
+	 * @param bool   $trash
1242
+	 * @param string $orderby
1243
+	 * @return EE_Registration[]|int
1244
+	 * @throws EE_Error
1245
+	 * @throws InvalidArgumentException
1246
+	 * @throws InvalidDataTypeException
1247
+	 * @throws InvalidInterfaceException
1248
+	 */
1249
+	public function get_event_attendees($per_page = 10, $count = false, $trash = false, $orderby = 'ATT_fname')
1250
+	{
1251
+		// normalize some request params that get setup by the parent `get_registrations` method.
1252
+		$request = $this->_req_data;
1253
+		$request['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : $orderby;
1254
+		$request['order'] = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'ASC';
1255
+		if ($trash) {
1256
+			$request['status'] = 'trash';
1257
+		}
1258
+		$query_params = $this->_get_checkin_query_params_from_request($request, $per_page, $count);
1259
+		/**
1260
+		 * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1261
+		 *
1262
+		 * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1263
+		 * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1264
+		 *                             or if you have the development copy of EE you can view this at the path:
1265
+		 *                             /docs/G--Model-System/model-query-params.md
1266
+		 */
1267
+		$query_params['group_by'] = '';
1268 1268
 
1269
-        return $count
1270
-            ? EEM_Registration::instance()->count($query_params)
1271
-            /** @type EE_Registration[] */
1272
-            : EEM_Registration::instance()->get_all($query_params);
1273
-    }
1269
+		return $count
1270
+			? EEM_Registration::instance()->count($query_params)
1271
+			/** @type EE_Registration[] */
1272
+			: EEM_Registration::instance()->get_all($query_params);
1273
+	}
1274 1274
 }
Please login to merge, or discard this patch.
Spacing   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -32,10 +32,10 @@  discard block
 block discarded – undo
32 32
     public function __construct($routing = true)
33 33
     {
34 34
         parent::__construct($routing);
35
-        if (! defined('REG_CAF_TEMPLATE_PATH')) {
36
-            define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/templates/');
37
-            define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/assets/');
38
-            define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registrations/assets/');
35
+        if ( ! defined('REG_CAF_TEMPLATE_PATH')) {
36
+            define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND.'registrations/templates/');
37
+            define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND.'registrations/assets/');
38
+            define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL.'registrations/assets/');
39 39
         }
40 40
     }
41 41
 
@@ -45,7 +45,7 @@  discard block
 block discarded – undo
45 45
      */
46 46
     protected function _extend_page_config()
47 47
     {
48
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'registrations';
48
+        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND.'registrations';
49 49
         $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
50 50
             ? $this->_req_data['_REG_ID']
51 51
             : 0;
@@ -185,14 +185,14 @@  discard block
 block discarded – undo
185 185
             // enqueue newsletter js
186 186
             wp_enqueue_script(
187 187
                 'ee-newsletter-trigger',
188
-                REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.js',
188
+                REG_CAF_ASSETS_URL.'ee-newsletter-trigger.js',
189 189
                 array('ee-dialog'),
190 190
                 EVENT_ESPRESSO_VERSION,
191 191
                 true
192 192
             );
193 193
             wp_enqueue_style(
194 194
                 'ee-newsletter-trigger-css',
195
-                REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.css',
195
+                REG_CAF_ASSETS_URL.'ee-newsletter-trigger.css',
196 196
                 array(),
197 197
                 EVENT_ESPRESSO_VERSION
198 198
             );
@@ -213,7 +213,7 @@  discard block
 block discarded – undo
213 213
     {
214 214
         wp_register_script(
215 215
             'ee-reg-reports-js',
216
-            REG_CAF_ASSETS_URL . 'ee-registration-admin-reports.js',
216
+            REG_CAF_ASSETS_URL.'ee-registration-admin-reports.js',
217 217
             array('google-charts'),
218 218
             EVENT_ESPRESSO_VERSION,
219 219
             true
@@ -299,7 +299,7 @@  discard block
 block discarded – undo
299 299
         $nonce_ref = 'get_newsletter_form_content_nonce';
300 300
         $this->_verify_nonce($nonce, $nonce_ref);
301 301
         // let's get the mtp for the incoming MTP_ ID
302
-        if (! isset($this->_req_data['GRP_ID'])) {
302
+        if ( ! isset($this->_req_data['GRP_ID'])) {
303 303
             EE_Error::add_error(
304 304
                 esc_html__(
305 305
                     '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).',
@@ -314,7 +314,7 @@  discard block
 block discarded – undo
314 314
             $this->_return_json();
315 315
         }
316 316
         $MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID($this->_req_data['GRP_ID']);
317
-        if (! $MTPG instanceof EE_Message_Template_Group) {
317
+        if ( ! $MTPG instanceof EE_Message_Template_Group) {
318 318
             EE_Error::add_error(
319 319
                 sprintf(
320 320
                     esc_html__(
@@ -339,12 +339,12 @@  discard block
 block discarded – undo
339 339
             $field = $MTP->get('MTP_template_field');
340 340
             if ($field === 'content') {
341 341
                 $content = $MTP->get('MTP_content');
342
-                if (! empty($content['newsletter_content'])) {
342
+                if ( ! empty($content['newsletter_content'])) {
343 343
                     $template_fields['newsletter_content'] = $content['newsletter_content'];
344 344
                 }
345 345
                 continue;
346 346
             }
347
-            $template_fields[ $MTP->get('MTP_template_field') ] = $MTP->get('MTP_content');
347
+            $template_fields[$MTP->get('MTP_template_field')] = $MTP->get('MTP_content');
348 348
         }
349 349
         $this->_template_args['success'] = true;
350 350
         $this->_template_args['error'] = false;
@@ -375,7 +375,7 @@  discard block
 block discarded – undo
375 375
      */
376 376
     public function add_newsletter_action_buttons(EE_Admin_List_Table $list_table)
377 377
     {
378
-        if (! EE_Registry::instance()->CAP->current_user_can(
378
+        if ( ! EE_Registry::instance()->CAP->current_user_can(
379 379
             'ee_send_message',
380 380
             'espresso_registrations_newsletter_selected_send'
381 381
         )
@@ -444,17 +444,17 @@  discard block
 block discarded – undo
444 444
                 $field_id = $field === '[NEWSLETTER_CONTENT]'
445 445
                     ? 'content'
446 446
                     : $field;
447
-                $field_id = 'batch-message-' . strtolower($field_id);
447
+                $field_id = 'batch-message-'.strtolower($field_id);
448 448
                 $available_shortcodes[] = '<span class="js-shortcode-selection" data-value="'
449 449
                                           . $shortcode
450
-                                          . '" data-linked-input-id="' . $field_id . '">'
450
+                                          . '" data-linked-input-id="'.$field_id.'">'
451 451
                                           . $shortcode
452 452
                                           . '</span>';
453 453
             }
454
-            $codes[ $field ] = implode(', ', $available_shortcodes);
454
+            $codes[$field] = implode(', ', $available_shortcodes);
455 455
         }
456 456
         $shortcodes = $codes;
457
-        $form_template = REG_CAF_TEMPLATE_PATH . 'newsletter-send-form.template.php';
457
+        $form_template = REG_CAF_TEMPLATE_PATH.'newsletter-send-form.template.php';
458 458
         $form_template_args = array(
459 459
             'form_action'       => admin_url('admin.php?page=espresso_registrations'),
460 460
             'form_route'        => 'newsletter_selected_send',
@@ -622,7 +622,7 @@  discard block
 block discarded – undo
622 622
      */
623 623
     protected function _registration_reports()
624 624
     {
625
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_reports.template.php';
625
+        $template_path = EE_ADMIN_TEMPLATE.'admin_reports.template.php';
626 626
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
627 627
             $template_path,
628 628
             $this->_reports_template_data,
@@ -677,7 +677,7 @@  discard block
 block discarded – undo
677 677
             array_unshift($regs, $column_titles);
678 678
             // setup the date range.
679 679
             $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
680
-            $beginning_date = new DateTime("now " . $period, $DateTimeZone);
680
+            $beginning_date = new DateTime("now ".$period, $DateTimeZone);
681 681
             $ending_date = new DateTime("now", $DateTimeZone);
682 682
             $subtitle = sprintf(
683 683
                 _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
@@ -697,7 +697,7 @@  discard block
 block discarded – undo
697 697
                     '%sThere are currently no registration records in the last month for this report.%s',
698 698
                     'event_espresso'
699 699
                 ),
700
-                '<h2>' . $report_title . '</h2><p>',
700
+                '<h2>'.$report_title.'</h2><p>',
701 701
                 '</p>'
702 702
             ),
703 703
         );
@@ -750,7 +750,7 @@  discard block
 block discarded – undo
750 750
             array_unshift($regs, $column_titles);
751 751
             // setup the date range.
752 752
             $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone());
753
-            $beginning_date = new DateTime("now " . $period, $DateTimeZone);
753
+            $beginning_date = new DateTime("now ".$period, $DateTimeZone);
754 754
             $ending_date = new DateTime("now", $DateTimeZone);
755 755
             $subtitle = sprintf(
756 756
                 _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'),
@@ -770,7 +770,7 @@  discard block
 block discarded – undo
770 770
                     '%sThere are currently no registration records in the last month for this report.%s',
771 771
                     'event_espresso'
772 772
                 ),
773
-                '<h2>' . $report_title . '</h2><p>',
773
+                '<h2>'.$report_title.'</h2><p>',
774 774
                 '</p>'
775 775
             ),
776 776
         );
@@ -823,7 +823,7 @@  discard block
 block discarded – undo
823 823
         if ($datetime instanceof EE_Datetime) {
824 824
             $datetime_label = $datetime->get_dtt_display_name(true);
825 825
             $datetime_label .= ! empty($datetime_label)
826
-                ? ' (' . $datetime->get_dtt_display_name() . ')'
826
+                ? ' ('.$datetime->get_dtt_display_name().')'
827 827
                 : $datetime->get_dtt_display_name();
828 828
         }
829 829
         $datetime_link = ! empty($dtt_id) && $registration instanceof EE_Registration
@@ -837,7 +837,7 @@  discard block
 block discarded – undo
837 837
             )
838 838
             : '';
839 839
         $datetime_link = ! empty($datetime_link)
840
-            ? '<a href="' . $datetime_link . '">'
840
+            ? '<a href="'.$datetime_link.'">'
841 841
               . '<span id="checkin-dtt">'
842 842
               . $datetime_label
843 843
               . '</span></a>'
@@ -849,8 +849,8 @@  discard block
 block discarded – undo
849 849
             ? $attendee->get_admin_details_link()
850 850
             : '';
851 851
         $attendee_link = ! empty($attendee_link)
852
-            ? '<a href="' . $attendee->get_admin_details_link() . '"'
853
-              . ' title="' . esc_html__('Click for attendee details', 'event_espresso') . '">'
852
+            ? '<a href="'.$attendee->get_admin_details_link().'"'
853
+              . ' title="'.esc_html__('Click for attendee details', 'event_espresso').'">'
854 854
               . '<span id="checkin-attendee-name">'
855 855
               . $attendee_name
856 856
               . '</span></a>'
@@ -859,25 +859,25 @@  discard block
 block discarded – undo
859 859
             ? $registration->event()->get_admin_details_link()
860 860
             : '';
861 861
         $event_link = ! empty($event_link)
862
-            ? '<a href="' . $event_link . '"'
863
-              . ' title="' . esc_html__('Click here to edit event.', 'event_espresso') . '">'
862
+            ? '<a href="'.$event_link.'"'
863
+              . ' title="'.esc_html__('Click here to edit event.', 'event_espresso').'">'
864 864
               . '<span id="checkin-event-name">'
865 865
               . $registration->event_name()
866 866
               . '</span>'
867 867
               . '</a>'
868 868
             : '';
869 869
         $this->_template_args['before_list_table'] = ! empty($reg_id) && ! empty($dtt_id)
870
-            ? '<h2>' . sprintf(
870
+            ? '<h2>'.sprintf(
871 871
                 esc_html__('Displaying check in records for %1$s for %2$s at the event, %3$s', 'event_espresso'),
872 872
                 $attendee_link,
873 873
                 $datetime_link,
874 874
                 $event_link
875
-            ) . '</h2>'
875
+            ).'</h2>'
876 876
             : '';
877 877
         $this->_template_args['list_table_hidden_fields'] = ! empty($reg_id)
878
-            ? '<input type="hidden" name="_REG_ID" value="' . $reg_id . '">' : '';
878
+            ? '<input type="hidden" name="_REG_ID" value="'.$reg_id.'">' : '';
879 879
         $this->_template_args['list_table_hidden_fields'] .= ! empty($dtt_id)
880
-            ? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : '';
880
+            ? '<input type="hidden" name="DTT_ID" value="'.$dtt_id.'">' : '';
881 881
         $this->display_admin_list_table_page_with_no_sidebar();
882 882
     }
883 883
 
@@ -894,7 +894,7 @@  discard block
 block discarded – undo
894 894
     public function toggle_checkin_status()
895 895
     {
896 896
         // first make sure we have the necessary data
897
-        if (! isset($this->_req_data['_regid'])) {
897
+        if ( ! isset($this->_req_data['_regid'])) {
898 898
             EE_Error::add_error(
899 899
                 esc_html__(
900 900
                     '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',
@@ -916,7 +916,7 @@  discard block
 block discarded – undo
916 916
         // beautiful! Made it this far so let's get the status.
917 917
         $new_status = new CheckinStatusDashicon($this->_toggle_checkin_status());
918 918
         // setup new class to return via ajax
919
-        $this->_template_args['admin_page_content'] = 'clickable trigger-checkin ' . $new_status->cssClasses();
919
+        $this->_template_args['admin_page_content'] = 'clickable trigger-checkin '.$new_status->cssClasses();
920 920
         $this->_template_args['success'] = true;
921 921
         $this->_return_json();
922 922
     }
@@ -942,7 +942,7 @@  discard block
 block discarded – undo
942 942
         );
943 943
         $new_status = false;
944 944
         // bulk action check in toggle
945
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
945
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
946 946
             // cycle thru checkboxes
947 947
             while (list($REG_ID, $value) = each($this->_req_data['checkbox'])) {
948 948
                 $DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null;
@@ -1012,9 +1012,9 @@  discard block
 block discarded – undo
1012 1012
             '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1013 1013
         );
1014 1014
         $errors = 0;
1015
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1015
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1016 1016
             while (list($CHK_ID, $value) = each($this->_req_data['checkbox'])) {
1017
-                if (! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) {
1017
+                if ( ! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) {
1018 1018
                     $errors++;
1019 1019
                 }
1020 1020
             }
@@ -1060,8 +1060,8 @@  discard block
 block discarded – undo
1060 1060
             'DTT_ID'  => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0,
1061 1061
             '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0,
1062 1062
         );
1063
-        if (! empty($this->_req_data['CHK_ID'])) {
1064
-            if (! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
1063
+        if ( ! empty($this->_req_data['CHK_ID'])) {
1064
+            if ( ! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) {
1065 1065
                 EE_Error::add_error(
1066 1066
                     esc_html__('Something went wrong and this check-in record was not deleted', 'event_espresso'),
1067 1067
                     __FILE__,
@@ -1130,27 +1130,27 @@  discard block
 block discarded – undo
1130 1130
                 'desc'  => $checked_never->legendLabel(),
1131 1131
             ),
1132 1132
             'approved_status'  => array(
1133
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
1133
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_approved,
1134 1134
                 'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'),
1135 1135
             ),
1136 1136
             'cancelled_status' => array(
1137
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1137
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_cancelled,
1138 1138
                 'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'),
1139 1139
             ),
1140 1140
             'declined_status'  => array(
1141
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
1141
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_declined,
1142 1142
                 'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'),
1143 1143
             ),
1144 1144
             'not_approved'     => array(
1145
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
1145
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_not_approved,
1146 1146
                 'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'),
1147 1147
             ),
1148 1148
             'pending_status'   => array(
1149
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
1149
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_pending_payment,
1150 1150
                 'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'),
1151 1151
             ),
1152 1152
             'wait_list'        => array(
1153
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
1153
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_wait_list,
1154 1154
                 'desc'  => EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'),
1155 1155
             ),
1156 1156
         );
@@ -1159,10 +1159,10 @@  discard block
 block discarded – undo
1159 1159
         /** @var EE_Event $event */
1160 1160
         $event = EEM_Event::instance()->get_one_by_ID($event_id);
1161 1161
         $this->_template_args['before_list_table'] = $event instanceof EE_Event
1162
-            ? '<h2>' . sprintf(
1162
+            ? '<h2>'.sprintf(
1163 1163
                 esc_html__('Viewing Registrations for Event: %s', 'event_espresso'),
1164 1164
                 EEM_Event::instance()->get_one_by_ID($event_id)->get('EVT_name')
1165
-            ) . '</h2>'
1165
+            ).'</h2>'
1166 1166
             : '';
1167 1167
         // need to get the number of datetimes on the event and set default datetime_id if there is only one datetime on
1168 1168
         // the event.
@@ -1180,12 +1180,12 @@  discard block
 block discarded – undo
1180 1180
             $this->_template_args['before_list_table'] .= ' &nbsp;<span class="drk-grey-text">';
1181 1181
             $this->_template_args['before_list_table'] .= '<span class="dashicons dashicons-calendar"></span>';
1182 1182
             $this->_template_args['before_list_table'] .= $datetime->name();
1183
-            $this->_template_args['before_list_table'] .= ' ( ' . $datetime->date_and_time_range() . ' )';
1183
+            $this->_template_args['before_list_table'] .= ' ( '.$datetime->date_and_time_range().' )';
1184 1184
             $this->_template_args['before_list_table'] .= '</span></h2>';
1185 1185
         }
1186 1186
         // if no datetime, then we're on the initial view, so let's give some helpful instructions on what the status
1187 1187
         // column represents
1188
-        if (! $datetime instanceof EE_Datetime) {
1188
+        if ( ! $datetime instanceof EE_Datetime) {
1189 1189
             $this->_template_args['before_list_table'] .= '<br><p class="description">'
1190 1190
                                                           . esc_html__(
1191 1191
                                                               'In this view, the check-in status represents the latest check-in record for the registration in that row.',
Please login to merge, or discard this patch.
admin_pages/events/Event_Categories_Admin_List_Table.class.php 2 patches
Indentation   +138 added lines, -138 removed lines patch added patch discarded remove patch
@@ -16,142 +16,142 @@
 block discarded – undo
16 16
 class Event_Categories_Admin_List_Table extends EE_Admin_List_Table
17 17
 {
18 18
 
19
-    public function __construct($admin_page)
20
-    {
21
-        parent::__construct($admin_page);
22
-    }
23
-
24
-
25
-    protected function _setup_data()
26
-    {
27
-        $this->_data = $this->_admin_page->get_categories($this->_per_page, $this->_current_page);
28
-        $this->_all_data_count = EEM_Term_Taxonomy::instance()->count(
29
-            array(array('taxonomy' => 'espresso_event_categories'))
30
-        );
31
-    }
32
-
33
-
34
-    protected function _set_properties()
35
-    {
36
-        $this->_wp_list_args = array(
37
-            'singular' => esc_html__('event category', 'event_espresso'),
38
-            'plural'   => esc_html__('event categories', 'event_espresso'),
39
-            'ajax'     => true, // for now,
40
-            'screen'   => $this->_admin_page->get_current_screen()->id,
41
-        );
42
-
43
-        $this->_columns = array(
44
-            'cb'        => '<input type="checkbox" />',
45
-            'id'        => esc_html__('ID', 'event_espresso'),
46
-            'name'      => esc_html__('Name', 'event_espresso'),
47
-            'shortcode' => esc_html__('Shortcode', 'event_espresso'),
48
-            'count'     => esc_html__('Events', 'event_espresso'),
49
-        );
50
-
51
-        $this->_sortable_columns = array(
52
-            'id'    => array('Term.term_id' => true),
53
-            'name'  => array('Term.slug' => false),
54
-            'count' => array('term_count' => false),
55
-        );
56
-
57
-        $this->_primary_column = 'id';
58
-
59
-        $this->_hidden_columns = array();
60
-    }
61
-
62
-
63
-    // not needed
64
-    protected function _get_table_filters()
65
-    {
66
-        return array();
67
-    }
68
-
69
-
70
-    protected function _add_view_counts()
71
-    {
72
-        $this->_views['all']['count'] = $this->_all_data_count;
73
-    }
74
-
75
-
76
-    public function column_cb($item)
77
-    {
78
-        return sprintf('<input type="checkbox" name="EVT_CAT_ID[]" value="%s" />', $item->get('term_id'));
79
-    }
80
-
81
-
82
-    public function column_id($item)
83
-    {
84
-        $content = $item->get('term_id');
85
-        $content .= '  <span class="show-on-mobile-view-only">' . $item->get_first_related('Term')->get(
86
-            'name'
87
-        ) . '</span>';
88
-        return $content;
89
-    }
90
-
91
-
92
-    public function column_name($item)
93
-    {
94
-        $edit_query_args = array(
95
-            'action'     => 'edit_category',
96
-            'EVT_CAT_ID' => $item->get('term_id'),
97
-        );
98
-
99
-        $delete_query_args = array(
100
-            'action'     => 'delete_category',
101
-            'EVT_CAT_ID' => $item->get('term_id'),
102
-        );
103
-
104
-        $edit_link = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
105
-        $delete_link = EE_Admin_Page::add_query_args_and_nonce($delete_query_args, EVENTS_ADMIN_URL);
106
-
107
-        $actions = array(
108
-            'edit' => '<a href="' . $edit_link . '" aria-label="' . esc_attr__(
109
-                'Edit Category',
110
-                'event_espresso'
111
-            ) . '">' . esc_html__('Edit', 'event_espresso') . '</a>',
112
-        );
113
-
114
-        $actions['delete'] = '<a href="' . $delete_link . '" aria-label="' . esc_attr__(
115
-            'Delete Category',
116
-            'event_espresso'
117
-        ) . '">' . esc_html__('Delete', 'event_espresso') . '</a>';
118
-
119
-        $actions['view'] = sprintf(
120
-            '<a href="%s" aria-label="%s">%s</a>',
121
-            get_term_link($item->get('term_id')),
122
-            esc_attr(
123
-                sprintf(
124
-                    /* translators: %s: event category name */
125
-                    __('View &#8220;%s&#8221; archive', 'event_espresso'),
126
-                    $item->get_first_related('Term')->get('name')
127
-                )
128
-            ),
129
-            esc_html__('View', 'event_espresso')
130
-        );
131
-
132
-        $content = '<strong><a class="row-title" href="' . $edit_link . '">' . $item->get_first_related('Term')->get(
133
-            'name'
134
-        ) . '</a></strong>';
135
-        $content .= $this->row_actions($actions);
136
-        return $content;
137
-    }
138
-
139
-
140
-    public function column_shortcode($item)
141
-    {
142
-        $content = '[ESPRESSO_EVENTS category_slug=' . $item->get_first_related('Term')->get('slug') . ']';
143
-        return $content;
144
-    }
145
-
146
-
147
-    public function column_count($item)
148
-    {
149
-        $e_args = array(
150
-            'action'  => 'default',
151
-            'EVT_CAT' => $item->get_first_related('Term')->ID(),
152
-        );
153
-        $e_link = EE_Admin_Page::add_query_args_and_nonce($e_args, EVENTS_ADMIN_URL);
154
-        $content = '<a href="' . $e_link . '">' . $item->get('term_count') . '</a>';
155
-        return $content;
156
-    }
19
+	public function __construct($admin_page)
20
+	{
21
+		parent::__construct($admin_page);
22
+	}
23
+
24
+
25
+	protected function _setup_data()
26
+	{
27
+		$this->_data = $this->_admin_page->get_categories($this->_per_page, $this->_current_page);
28
+		$this->_all_data_count = EEM_Term_Taxonomy::instance()->count(
29
+			array(array('taxonomy' => 'espresso_event_categories'))
30
+		);
31
+	}
32
+
33
+
34
+	protected function _set_properties()
35
+	{
36
+		$this->_wp_list_args = array(
37
+			'singular' => esc_html__('event category', 'event_espresso'),
38
+			'plural'   => esc_html__('event categories', 'event_espresso'),
39
+			'ajax'     => true, // for now,
40
+			'screen'   => $this->_admin_page->get_current_screen()->id,
41
+		);
42
+
43
+		$this->_columns = array(
44
+			'cb'        => '<input type="checkbox" />',
45
+			'id'        => esc_html__('ID', 'event_espresso'),
46
+			'name'      => esc_html__('Name', 'event_espresso'),
47
+			'shortcode' => esc_html__('Shortcode', 'event_espresso'),
48
+			'count'     => esc_html__('Events', 'event_espresso'),
49
+		);
50
+
51
+		$this->_sortable_columns = array(
52
+			'id'    => array('Term.term_id' => true),
53
+			'name'  => array('Term.slug' => false),
54
+			'count' => array('term_count' => false),
55
+		);
56
+
57
+		$this->_primary_column = 'id';
58
+
59
+		$this->_hidden_columns = array();
60
+	}
61
+
62
+
63
+	// not needed
64
+	protected function _get_table_filters()
65
+	{
66
+		return array();
67
+	}
68
+
69
+
70
+	protected function _add_view_counts()
71
+	{
72
+		$this->_views['all']['count'] = $this->_all_data_count;
73
+	}
74
+
75
+
76
+	public function column_cb($item)
77
+	{
78
+		return sprintf('<input type="checkbox" name="EVT_CAT_ID[]" value="%s" />', $item->get('term_id'));
79
+	}
80
+
81
+
82
+	public function column_id($item)
83
+	{
84
+		$content = $item->get('term_id');
85
+		$content .= '  <span class="show-on-mobile-view-only">' . $item->get_first_related('Term')->get(
86
+			'name'
87
+		) . '</span>';
88
+		return $content;
89
+	}
90
+
91
+
92
+	public function column_name($item)
93
+	{
94
+		$edit_query_args = array(
95
+			'action'     => 'edit_category',
96
+			'EVT_CAT_ID' => $item->get('term_id'),
97
+		);
98
+
99
+		$delete_query_args = array(
100
+			'action'     => 'delete_category',
101
+			'EVT_CAT_ID' => $item->get('term_id'),
102
+		);
103
+
104
+		$edit_link = EE_Admin_Page::add_query_args_and_nonce($edit_query_args, EVENTS_ADMIN_URL);
105
+		$delete_link = EE_Admin_Page::add_query_args_and_nonce($delete_query_args, EVENTS_ADMIN_URL);
106
+
107
+		$actions = array(
108
+			'edit' => '<a href="' . $edit_link . '" aria-label="' . esc_attr__(
109
+				'Edit Category',
110
+				'event_espresso'
111
+			) . '">' . esc_html__('Edit', 'event_espresso') . '</a>',
112
+		);
113
+
114
+		$actions['delete'] = '<a href="' . $delete_link . '" aria-label="' . esc_attr__(
115
+			'Delete Category',
116
+			'event_espresso'
117
+		) . '">' . esc_html__('Delete', 'event_espresso') . '</a>';
118
+
119
+		$actions['view'] = sprintf(
120
+			'<a href="%s" aria-label="%s">%s</a>',
121
+			get_term_link($item->get('term_id')),
122
+			esc_attr(
123
+				sprintf(
124
+					/* translators: %s: event category name */
125
+					__('View &#8220;%s&#8221; archive', 'event_espresso'),
126
+					$item->get_first_related('Term')->get('name')
127
+				)
128
+			),
129
+			esc_html__('View', 'event_espresso')
130
+		);
131
+
132
+		$content = '<strong><a class="row-title" href="' . $edit_link . '">' . $item->get_first_related('Term')->get(
133
+			'name'
134
+		) . '</a></strong>';
135
+		$content .= $this->row_actions($actions);
136
+		return $content;
137
+	}
138
+
139
+
140
+	public function column_shortcode($item)
141
+	{
142
+		$content = '[ESPRESSO_EVENTS category_slug=' . $item->get_first_related('Term')->get('slug') . ']';
143
+		return $content;
144
+	}
145
+
146
+
147
+	public function column_count($item)
148
+	{
149
+		$e_args = array(
150
+			'action'  => 'default',
151
+			'EVT_CAT' => $item->get_first_related('Term')->ID(),
152
+		);
153
+		$e_link = EE_Admin_Page::add_query_args_and_nonce($e_args, EVENTS_ADMIN_URL);
154
+		$content = '<a href="' . $e_link . '">' . $item->get('term_count') . '</a>';
155
+		return $content;
156
+	}
157 157
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -82,9 +82,9 @@  discard block
 block discarded – undo
82 82
     public function column_id($item)
83 83
     {
84 84
         $content = $item->get('term_id');
85
-        $content .= '  <span class="show-on-mobile-view-only">' . $item->get_first_related('Term')->get(
85
+        $content .= '  <span class="show-on-mobile-view-only">'.$item->get_first_related('Term')->get(
86 86
             'name'
87
-        ) . '</span>';
87
+        ).'</span>';
88 88
         return $content;
89 89
     }
90 90
 
@@ -105,16 +105,16 @@  discard block
 block discarded – undo
105 105
         $delete_link = EE_Admin_Page::add_query_args_and_nonce($delete_query_args, EVENTS_ADMIN_URL);
106 106
 
107 107
         $actions = array(
108
-            'edit' => '<a href="' . $edit_link . '" aria-label="' . esc_attr__(
108
+            'edit' => '<a href="'.$edit_link.'" aria-label="'.esc_attr__(
109 109
                 'Edit Category',
110 110
                 'event_espresso'
111
-            ) . '">' . esc_html__('Edit', 'event_espresso') . '</a>',
111
+            ).'">'.esc_html__('Edit', 'event_espresso').'</a>',
112 112
         );
113 113
 
114
-        $actions['delete'] = '<a href="' . $delete_link . '" aria-label="' . esc_attr__(
114
+        $actions['delete'] = '<a href="'.$delete_link.'" aria-label="'.esc_attr__(
115 115
             'Delete Category',
116 116
             'event_espresso'
117
-        ) . '">' . esc_html__('Delete', 'event_espresso') . '</a>';
117
+        ).'">'.esc_html__('Delete', 'event_espresso').'</a>';
118 118
 
119 119
         $actions['view'] = sprintf(
120 120
             '<a href="%s" aria-label="%s">%s</a>',
@@ -129,9 +129,9 @@  discard block
 block discarded – undo
129 129
             esc_html__('View', 'event_espresso')
130 130
         );
131 131
 
132
-        $content = '<strong><a class="row-title" href="' . $edit_link . '">' . $item->get_first_related('Term')->get(
132
+        $content = '<strong><a class="row-title" href="'.$edit_link.'">'.$item->get_first_related('Term')->get(
133 133
             'name'
134
-        ) . '</a></strong>';
134
+        ).'</a></strong>';
135 135
         $content .= $this->row_actions($actions);
136 136
         return $content;
137 137
     }
@@ -139,7 +139,7 @@  discard block
 block discarded – undo
139 139
 
140 140
     public function column_shortcode($item)
141 141
     {
142
-        $content = '[ESPRESSO_EVENTS category_slug=' . $item->get_first_related('Term')->get('slug') . ']';
142
+        $content = '[ESPRESSO_EVENTS category_slug='.$item->get_first_related('Term')->get('slug').']';
143 143
         return $content;
144 144
     }
145 145
 
@@ -151,7 +151,7 @@  discard block
 block discarded – undo
151 151
             'EVT_CAT' => $item->get_first_related('Term')->ID(),
152 152
         );
153 153
         $e_link = EE_Admin_Page::add_query_args_and_nonce($e_args, EVENTS_ADMIN_URL);
154
-        $content = '<a href="' . $e_link . '">' . $item->get('term_count') . '</a>';
154
+        $content = '<a href="'.$e_link.'">'.$item->get('term_count').'</a>';
155 155
         return $content;
156 156
     }
157 157
 }
Please login to merge, or discard this patch.
core/libraries/messages/data_class/EE_Messages_incoming_data.core.php 2 patches
Indentation   +515 added lines, -515 removed lines patch added patch discarded remove patch
@@ -18,519 +18,519 @@
 block discarded – undo
18 18
 {
19 19
 
20 20
 
21
-    /**
22
-     * user id for logged in user when data collected
23
-     *
24
-     * @var string $user_id
25
-     */
26
-    public $user_id;
27
-
28
-    /**
29
-     * IP Address of browser used
30
-     *
31
-     * @var string $ip_address
32
-     */
33
-    public $ip_address;
34
-
35
-    /**
36
-     * browser
37
-     *
38
-     * @var string $user_agent
39
-     */
40
-    public $user_agent;
41
-
42
-    /**
43
-     * Unix timestamp
44
-     *
45
-     * @var string $init_access
46
-     */
47
-    public $init_access;
48
-
49
-    /**
50
-     * Unix timestamp
51
-     *
52
-     * @var string $last_access
53
-     */
54
-    public $last_access;
55
-
56
-    /**
57
-     * The registrations details from the cart
58
-     *
59
-     * @var array $reg_info
60
-     */
61
-    public $reg_info;
62
-
63
-    /**
64
-     * Some data handlers can set what reg status all the registrations are filtered by.
65
-     * The status should match a EEM_Registration status constant.
66
-     *
67
-     * @var string $filtered_reg_status
68
-     */
69
-    public $filtered_reg_status;
70
-
71
-    /**
72
-     * will hold an array of events assembled from $reg_info
73
-     *
74
-     * @var EE_Event[] $events
75
-     */
76
-    public $events;
77
-
78
-    /**
79
-     * holds an array of datetimes assembled from the incoming data.
80
-     *
81
-     * @var EE_Datetime[] $datetimes
82
-     */
83
-    public $datetimes;
84
-
85
-    /**
86
-     * holds an array of tickets assembled from the incoming data.
87
-     *
88
-     * @var EE_Ticket[] $tickets
89
-     */
90
-    public $tickets;
91
-
92
-    /**
93
-     * holds an array with a key of parent line item and values are an array of children of that line item.
94
-     *
95
-     * @since 4.5.0
96
-     * @var EE_Line_Item[] $line_items_with_children
97
-     */
98
-    public $line_items_with_children;
99
-
100
-    /**
101
-     * will hold an array of attendees assembled from the $reg_info
102
-     *
103
-     * @var EE_Attendee[] $attendees
104
-     */
105
-    public $attendees;
106
-
107
-    /**
108
-     * will hold an array of cached registration objects and info assembled from reg_info
109
-     *
110
-     * @var array $registrations
111
-     */
112
-    public $registrations;
113
-
114
-    /**
115
-     * will hold an array of answers assembled from the $reg_info
116
-     *
117
-     * @var EE_Answer[] $answers
118
-     */
119
-    public $answers;
120
-
121
-    /**
122
-     * will hold an array of questions assembled from the $reg_info (indexed by Answer ID);
123
-     *
124
-     * @var EE_Question[] $questions
125
-     */
126
-    public $questions;
127
-
128
-    /**
129
-     * Will hold billing data assembled from $billing_info (if present)
130
-     *
131
-     * @var mixed (array|null) $billing
132
-     */
133
-    public $billing;
134
-
135
-    /**
136
-     * The total amount of tax for the transaction
137
-     *
138
-     * @var float $taxes
139
-     */
140
-    public $taxes;
141
-
142
-    /**
143
-     * Holds the line items related to taxes
144
-     *
145
-     * @since 4.5.0
146
-     * @var EE_Line_Item[] $tax_line_items
147
-     */
148
-    public $tax_line_items;
149
-
150
-    /**
151
-     * Hold the line items which aren't taxes and don't relate
152
-     * to tickets. So: promotions and miscellaneous charges
153
-     *
154
-     * @since 4.5
155
-     * @var EE_Line_Item[] $additional_line_items
156
-     */
157
-    public $additional_line_items;
158
-
159
-    /**
160
-     * Holds the grand total EE_Line_Item
161
-     *
162
-     * @var EE_Line_Item $grand_total_line_item
163
-     */
164
-    public $grand_total_line_item;
165
-
166
-    /**
167
-     * holds the grand total price object
168
-     * currently not used.
169
-     *
170
-     * @var null $grand_total_price_object
171
-     */
172
-    public $grand_total_price_object;
173
-
174
-    /**
175
-     * total number of tickets
176
-     *
177
-     * @var int $total_ticket_count
178
-     */
179
-    public $total_ticket_count;
180
-
181
-    /**
182
-     * Will hold the final transaction object (EE_Transaction)
183
-     *
184
-     * @var EE_Transaction $txn
185
-     */
186
-    public $txn;
187
-
188
-    /**
189
-     * Holds the payments related to a transaction
190
-     *
191
-     * @since 4.5.0
192
-     * @var EE_Payment[] $payments
193
-     */
194
-    public $payments;
195
-
196
-    /**
197
-     * Holds the first related payment related for a transaction
198
-     *
199
-     * @since 4.5.0
200
-     * @var EE_Payment $payment
201
-     */
202
-    public $payment;
203
-
204
-    /**
205
-     * Will hold the label for the txn status
206
-     *
207
-     * @var string $txn_status
208
-     */
209
-    public $txn_status;
210
-
211
-    /**
212
-     * Will hold the final registration object (EE_Registration)
213
-     *
214
-     * @var EE_Registration[] $reg_objs
215
-     */
216
-    public $reg_objs;
217
-
218
-    /**
219
-     * Will hold an array of primary attendee data (if present)
220
-     *
221
-     * @var array $primary_attendee_data
222
-     */
223
-    public $primary_attendee_data;
224
-
225
-    /**
226
-     * This is just an internal object used for passing around the incoming data.
227
-     *
228
-     * @var mixed $_data
229
-     */
230
-    protected $_data;
231
-
232
-    /**
233
-     * This is just an internal object used for passing around the incoming data.
234
-     *
235
-     * @var mixed $incoming_data
236
-     */
237
-    public $incoming_data;
238
-
239
-    /**
240
-     * hold objects that might be created
241
-     *
242
-     * @type EE_Registration $reg_obj
243
-     */
244
-    public $reg_obj;
245
-
246
-
247
-    /**
248
-     * constructor
249
-     *
250
-     * @param mixed $data incoming data object|array.  Suggested that child classes use type hinting for expected
251
-     *                    data object.  But here parent will be generic because we don't know what's coming in.
252
-     */
253
-    public function __construct($data)
254
-    {
255
-        $this->_data = $data;
256
-        $this->_setup_data();
257
-    }
258
-
259
-
260
-    /**
261
-     * Every child class has to setup the data object !
262
-     *
263
-     * @return void
264
-     */
265
-    abstract protected function _setup_data();
266
-
267
-
268
-    /**
269
-     * Returns database safe representation of the data later used to when instantiating this object.
270
-     *
271
-     * @param mixed $data The incoming data to be prepped.
272
-     * @return mixed   The prepped data for db
273
-     */
274
-    public static function convert_data_for_persistent_storage($data)
275
-    {
276
-        return $data;
277
-    }
278
-
279
-
280
-    /**
281
-     * Data that has been stored in persistent storage that was prepped by _convert_data_for_persistent_storage
282
-     * can be sent into this method and converted back into the format used for instantiating with this data handler.
283
-     *
284
-     * @param $data
285
-     * @return mixed
286
-     */
287
-    public static function convert_data_from_persistent_storage($data)
288
-    {
289
-        return $data;
290
-    }
291
-
292
-
293
-    /**
294
-     * only purpose is to return the data
295
-     *
296
-     * @access public
297
-     * @return mixed the formatted data object!
298
-     */
299
-    public function data()
300
-    {
301
-        return $this->_data;
302
-    }
303
-
304
-
305
-    /**
306
-     * This helper method can be used by any incoming data handlers to setup the data correctly.  All that is required
307
-     * is that $this->reg_objs be set.
308
-     *
309
-     * @throws EE_Error
310
-     * @throws InvalidDataTypeException
311
-     * @throws InvalidInterfaceException
312
-     * @throws InvalidArgumentException
313
-     * @throws EntityNotFoundException
314
-     */
315
-    protected function _assemble_data()
316
-    {
317
-        // verify that reg_objs is set
318
-        if (! is_array($this->reg_objs)
319
-            && ! reset($this->reg_objs) instanceof EE_Registration
320
-        ) {
321
-            throw new EE_Error(
322
-                esc_html__(
323
-                    'In order to assemble the data correctly, the "reg_objs" property must be an array of EE_Registration objects',
324
-                    'event_espresso'
325
-                )
326
-            );
327
-        }
328
-
329
-        // get all attendee and events associated with the registrations in this transaction
330
-        $events             = $event_setup = $evtcache = $tickets = $datetimes = array();
331
-        $answers            = $questions = $attendees = $line_items = $registrations = array();
332
-        $total_ticket_count = 0;
333
-
334
-        if (! empty($this->reg_objs)) {
335
-            $event_attendee_count = array();
336
-            /** @var EE_Registration $reg */
337
-            foreach ($this->reg_objs as $reg) {
338
-                if ($this->_skip_registration_for_processing($reg)
339
-                ) {
340
-                    continue;
341
-                }
342
-
343
-                $evt_id = $reg->event_ID();
344
-                /** @type EE_Ticket $ticket */
345
-                $ticket          = $reg->get_first_related('Ticket');
346
-                $attendee = $reg->attendee();
347
-                $event = $reg->event();
348
-                // if none of the following entities are available, then we can't setup other data reliably,
349
-                // so let's just skip.
350
-                if (! $ticket instanceof EE_Ticket
351
-                    || ! $attendee instanceof EE_Attendee
352
-                    || ! $event instanceof EE_Event
353
-                ) {
354
-                    continue;
355
-                }
356
-                $relateddatetime = $ticket->datetimes();
357
-                $total_ticket_count++;
358
-                $tickets[ $ticket->ID() ]['ticket']                        = $ticket;
359
-                $tickets[ $ticket->ID() ]['count']                         = is_array($tickets[ $ticket->ID() ])
360
-                                                                           && isset($tickets[ $ticket->ID() ]['count'])
361
-                    ? $tickets[ $ticket->ID() ]['count'] + 1
362
-                    : 1;
363
-                $tickets[ $ticket->ID() ]['att_objs'][ $attendee->ID() ] = $attendee;
364
-                $tickets[ $ticket->ID() ]['dtt_objs']                      = $relateddatetime;
365
-                $tickets[ $ticket->ID() ]['reg_objs'][ $reg->ID() ]          = $reg;
366
-                $tickets[ $ticket->ID() ]['EE_Event']                      = $event;
367
-                $evtcache[ $evt_id ]                                       = $event;
368
-                $eventsetup[ $evt_id ]['reg_objs'][ $reg->ID() ]             = $reg;
369
-                $eventsetup[ $evt_id ]['tkt_objs'][ $ticket->ID() ]          = $ticket;
370
-                $eventsetup[ $evt_id ]['att_objs'][ $attendee->ID() ]    = $attendee;
371
-                $event_attendee_count[ $evt_id ]                           = isset($event_attendee_count[ $evt_id ])
372
-                    ? $event_attendee_count[ $evt_id ] + 1
373
-                    : 0;
374
-                $attendees[ $reg->attendee_ID() ]['line_ref'][]            = $evt_id;
375
-                $attendees[ $reg->attendee_ID() ]['att_obj']               = $attendee;
376
-                $attendees[ $reg->attendee_ID() ]['reg_objs'][ $reg->ID() ]  = $reg;
377
-                // $attendees[ $reg->attendee_ID() ]['registration_id'] = $reg->ID();
378
-                $attendees[ $reg->attendee_ID() ]['attendee_email']          = $attendee->email();
379
-                $attendees[ $reg->attendee_ID() ]['tkt_objs'][ $ticket->ID() ] = $ticket;
380
-                $attendees[ $reg->attendee_ID() ]['evt_objs'][ $evt_id ]       = $event;
381
-
382
-                // registrations
383
-                $registrations[ $reg->ID() ]['tkt_obj'] = $ticket;
384
-                $registrations[ $reg->ID() ]['evt_obj'] = $event;
385
-                $registrations[ $reg->ID() ]['reg_obj'] = $reg;
386
-                $registrations[ $reg->ID() ]['att_obj'] = $attendee;
387
-
388
-                // set up answer objects
389
-                $rel_ans = $reg->get_many_related('Answer');
390
-                foreach ($rel_ans as $ansid => $answer) {
391
-                    if (! isset($questions[ $ansid ])) {
392
-                        $questions[ $ansid ] = $answer->get_first_related('Question');
393
-                    }
394
-                    $answers[ $ansid ]                               = $answer;
395
-                    $registrations[ $reg->ID() ]['ans_objs'][ $ansid ] = $answer;
396
-                }
397
-                /**
398
-                 * @var int $dtt_id
399
-                 * @var EE_Datetime $datetime
400
-                 */
401
-                foreach ($relateddatetime as $dtt_id => $datetime) {
402
-                    $eventsetup[ $evt_id ]['dtt_objs'][ $dtt_id ]       = $datetime;
403
-                    $registrations[ $reg->ID() ]['dtt_objs'][ $dtt_id ] = $datetime;
404
-
405
-                    if (isset($datetimes[ $dtt_id ])) {
406
-                        continue; // already have this info in the datetimes array.
407
-                    }
408
-
409
-                    $datetimes[ $dtt_id ]['tkt_objs'][]           = $ticket;
410
-                    $datetimes[ $dtt_id ]['datetime']             = $datetime;
411
-                    $datetimes[ $dtt_id ]['evt_objs'][ $evt_id ]    = $event;
412
-                    $datetimes[ $dtt_id ]['reg_objs'][ $reg->ID() ] = $reg;
413
-                }
414
-            }
415
-
416
-            // let's loop through the unique event=>reg items and setup data on them
417
-
418
-            if (! empty($eventsetup)) {
419
-                foreach ($eventsetup as $evt_id => $items) {
420
-                    $ticket_line_items_for_event = array();
421
-                    if ($this->txn instanceof EE_Transaction) {
422
-                        $ticket_line_items_for_event = EEM_Line_Item::instance()->get_all(
423
-                            array(
424
-                                array(
425
-                                    'Ticket.Datetime.EVT_ID' => $evt_id,
426
-                                    'TXN_ID'                 => $this->txn->ID(),
427
-                                ),
428
-                                'default_where_conditions' => 'none',
429
-                            )
430
-                        );
431
-                    }
432
-                    $events[ $evt_id ] = array(
433
-                        'ID'              => $evt_id,
434
-                        'event'           => $evtcache[ $evt_id ],
435
-                        'name'            => $evtcache[ $evt_id ] instanceof EE_Event ? $evtcache[ $evt_id ]->name() : '',
436
-                        'total_attendees' => $event_attendee_count[ $evt_id ],
437
-                        'reg_objs'        => $items['reg_objs'],
438
-                        'tkt_objs'        => $items['tkt_objs'],
439
-                        'att_objs'        => $items['att_objs'],
440
-                        'dtt_objs'        => isset($items['dtt_objs']) ? $items['dtt_objs'] : array(),
441
-                        'line_items'      => $ticket_line_items_for_event,
442
-                    );
443
-
444
-                    // make sure the tickets have the line items setup for them.
445
-                    foreach ($ticket_line_items_for_event as $line_id => $line_item) {
446
-                        // only add the ticket line items if we already have this ticket in the $tickets array.
447
-                        if ($line_item instanceof EE_Line_Item && isset($tickets[ $line_item->ticket()->ID() ])) {
448
-                            $tickets[ $line_item->ticket()->ID() ]['line_item']      = $line_item;
449
-                            $tickets[ $line_item->ticket()->ID() ]['sub_line_items'] = $line_item->children();
450
-                            $line_items[ $line_item->ID() ]['children']              = $line_item->children();
451
-                            $line_items[ $line_item->ID() ]['EE_Ticket']             = $line_item->ticket();
452
-                        }
453
-                    }
454
-                }
455
-            }
456
-
457
-            $this->grand_total_line_item = $this->txn instanceof EE_Transaction
458
-                ? $this->txn->total_line_item()
459
-                : null;
460
-        }
461
-
462
-        // lets set the attendees and events properties
463
-        $this->attendees                = $attendees;
464
-        $this->events                   = $events;
465
-        $this->tickets                  = $tickets;
466
-        $this->line_items_with_children = $line_items;
467
-        $this->datetimes                = $datetimes;
468
-        $this->questions                = $questions;
469
-        $this->answers                  = $answers;
470
-        $this->total_ticket_count       = $total_ticket_count;
471
-        $this->registrations            = $registrations;
472
-
473
-        if ($this->txn instanceof EE_Transaction) {
474
-            $this->tax_line_items        = $this->txn->tax_items();
475
-            $this->additional_line_items = $this->txn->non_ticket_line_items();
476
-            $this->payments              = $this->txn->payments();
477
-
478
-            // setup primary registration if we have a single transaction object to work with
479
-
480
-            // let's get just the primary_attendee_data!  First we get the primary registration object.
481
-            $primary_reg = $this->txn->primary_registration();
482
-            // verify
483
-            if ($primary_reg instanceof EE_Registration) {
484
-                // get attendee object
485
-                if ($primary_reg->attendee() instanceof EE_Attendee) {
486
-                    // now we can setup the primary_attendee_data array
487
-                    $this->primary_attendee_data = array(
488
-                        'registration_id' => $primary_reg->ID(),
489
-                        'att_obj'         => $primary_reg->attendee(),
490
-                        'reg_obj'         => $primary_reg,
491
-                        'primary_att_obj' => $primary_reg->attendee(),
492
-                        'primary_reg_obj' => $primary_reg,
493
-                    );
494
-                } else {
495
-                    EE_Error::add_error(
496
-                        esc_html__(
497
-                            'Incoming data does not have a valid Attendee object for the primary registrant.',
498
-                            'event_espresso'
499
-                        ),
500
-                        __FILE__,
501
-                        __FUNCTION__,
502
-                        __LINE__
503
-                    );
504
-                }
505
-            } else {
506
-                EE_Error::add_error(
507
-                    esc_html__(
508
-                        'Incoming data does not have a valid Registration object for the primary registrant.',
509
-                        'event_espresso'
510
-                    ),
511
-                    __FILE__,
512
-                    __FUNCTION__,
513
-                    __LINE__
514
-                );
515
-            }
516
-        }
517
-    }
518
-
519
-    /**
520
-     * This simply considers whether the given registration should be processed or not based on comparison with the
521
-     * filtered_reg_status property.
522
-     *
523
-     * @param EE_Registration $registration
524
-     * @return bool  returning true means we DO want to skip processing.  returning false means we DON'T want to skip
525
-     *               processing
526
-     */
527
-    protected function _skip_registration_for_processing(EE_Registration $registration)
528
-    {
529
-        if (empty($this->filtered_reg_status)) {
530
-            return false;
531
-        }
532
-
533
-        // if we made it here then we just compare the filtered_reg_status with the registration status and return that
534
-        return $this->filtered_reg_status !== $registration->status_ID();
535
-    }
21
+	/**
22
+	 * user id for logged in user when data collected
23
+	 *
24
+	 * @var string $user_id
25
+	 */
26
+	public $user_id;
27
+
28
+	/**
29
+	 * IP Address of browser used
30
+	 *
31
+	 * @var string $ip_address
32
+	 */
33
+	public $ip_address;
34
+
35
+	/**
36
+	 * browser
37
+	 *
38
+	 * @var string $user_agent
39
+	 */
40
+	public $user_agent;
41
+
42
+	/**
43
+	 * Unix timestamp
44
+	 *
45
+	 * @var string $init_access
46
+	 */
47
+	public $init_access;
48
+
49
+	/**
50
+	 * Unix timestamp
51
+	 *
52
+	 * @var string $last_access
53
+	 */
54
+	public $last_access;
55
+
56
+	/**
57
+	 * The registrations details from the cart
58
+	 *
59
+	 * @var array $reg_info
60
+	 */
61
+	public $reg_info;
62
+
63
+	/**
64
+	 * Some data handlers can set what reg status all the registrations are filtered by.
65
+	 * The status should match a EEM_Registration status constant.
66
+	 *
67
+	 * @var string $filtered_reg_status
68
+	 */
69
+	public $filtered_reg_status;
70
+
71
+	/**
72
+	 * will hold an array of events assembled from $reg_info
73
+	 *
74
+	 * @var EE_Event[] $events
75
+	 */
76
+	public $events;
77
+
78
+	/**
79
+	 * holds an array of datetimes assembled from the incoming data.
80
+	 *
81
+	 * @var EE_Datetime[] $datetimes
82
+	 */
83
+	public $datetimes;
84
+
85
+	/**
86
+	 * holds an array of tickets assembled from the incoming data.
87
+	 *
88
+	 * @var EE_Ticket[] $tickets
89
+	 */
90
+	public $tickets;
91
+
92
+	/**
93
+	 * holds an array with a key of parent line item and values are an array of children of that line item.
94
+	 *
95
+	 * @since 4.5.0
96
+	 * @var EE_Line_Item[] $line_items_with_children
97
+	 */
98
+	public $line_items_with_children;
99
+
100
+	/**
101
+	 * will hold an array of attendees assembled from the $reg_info
102
+	 *
103
+	 * @var EE_Attendee[] $attendees
104
+	 */
105
+	public $attendees;
106
+
107
+	/**
108
+	 * will hold an array of cached registration objects and info assembled from reg_info
109
+	 *
110
+	 * @var array $registrations
111
+	 */
112
+	public $registrations;
113
+
114
+	/**
115
+	 * will hold an array of answers assembled from the $reg_info
116
+	 *
117
+	 * @var EE_Answer[] $answers
118
+	 */
119
+	public $answers;
120
+
121
+	/**
122
+	 * will hold an array of questions assembled from the $reg_info (indexed by Answer ID);
123
+	 *
124
+	 * @var EE_Question[] $questions
125
+	 */
126
+	public $questions;
127
+
128
+	/**
129
+	 * Will hold billing data assembled from $billing_info (if present)
130
+	 *
131
+	 * @var mixed (array|null) $billing
132
+	 */
133
+	public $billing;
134
+
135
+	/**
136
+	 * The total amount of tax for the transaction
137
+	 *
138
+	 * @var float $taxes
139
+	 */
140
+	public $taxes;
141
+
142
+	/**
143
+	 * Holds the line items related to taxes
144
+	 *
145
+	 * @since 4.5.0
146
+	 * @var EE_Line_Item[] $tax_line_items
147
+	 */
148
+	public $tax_line_items;
149
+
150
+	/**
151
+	 * Hold the line items which aren't taxes and don't relate
152
+	 * to tickets. So: promotions and miscellaneous charges
153
+	 *
154
+	 * @since 4.5
155
+	 * @var EE_Line_Item[] $additional_line_items
156
+	 */
157
+	public $additional_line_items;
158
+
159
+	/**
160
+	 * Holds the grand total EE_Line_Item
161
+	 *
162
+	 * @var EE_Line_Item $grand_total_line_item
163
+	 */
164
+	public $grand_total_line_item;
165
+
166
+	/**
167
+	 * holds the grand total price object
168
+	 * currently not used.
169
+	 *
170
+	 * @var null $grand_total_price_object
171
+	 */
172
+	public $grand_total_price_object;
173
+
174
+	/**
175
+	 * total number of tickets
176
+	 *
177
+	 * @var int $total_ticket_count
178
+	 */
179
+	public $total_ticket_count;
180
+
181
+	/**
182
+	 * Will hold the final transaction object (EE_Transaction)
183
+	 *
184
+	 * @var EE_Transaction $txn
185
+	 */
186
+	public $txn;
187
+
188
+	/**
189
+	 * Holds the payments related to a transaction
190
+	 *
191
+	 * @since 4.5.0
192
+	 * @var EE_Payment[] $payments
193
+	 */
194
+	public $payments;
195
+
196
+	/**
197
+	 * Holds the first related payment related for a transaction
198
+	 *
199
+	 * @since 4.5.0
200
+	 * @var EE_Payment $payment
201
+	 */
202
+	public $payment;
203
+
204
+	/**
205
+	 * Will hold the label for the txn status
206
+	 *
207
+	 * @var string $txn_status
208
+	 */
209
+	public $txn_status;
210
+
211
+	/**
212
+	 * Will hold the final registration object (EE_Registration)
213
+	 *
214
+	 * @var EE_Registration[] $reg_objs
215
+	 */
216
+	public $reg_objs;
217
+
218
+	/**
219
+	 * Will hold an array of primary attendee data (if present)
220
+	 *
221
+	 * @var array $primary_attendee_data
222
+	 */
223
+	public $primary_attendee_data;
224
+
225
+	/**
226
+	 * This is just an internal object used for passing around the incoming data.
227
+	 *
228
+	 * @var mixed $_data
229
+	 */
230
+	protected $_data;
231
+
232
+	/**
233
+	 * This is just an internal object used for passing around the incoming data.
234
+	 *
235
+	 * @var mixed $incoming_data
236
+	 */
237
+	public $incoming_data;
238
+
239
+	/**
240
+	 * hold objects that might be created
241
+	 *
242
+	 * @type EE_Registration $reg_obj
243
+	 */
244
+	public $reg_obj;
245
+
246
+
247
+	/**
248
+	 * constructor
249
+	 *
250
+	 * @param mixed $data incoming data object|array.  Suggested that child classes use type hinting for expected
251
+	 *                    data object.  But here parent will be generic because we don't know what's coming in.
252
+	 */
253
+	public function __construct($data)
254
+	{
255
+		$this->_data = $data;
256
+		$this->_setup_data();
257
+	}
258
+
259
+
260
+	/**
261
+	 * Every child class has to setup the data object !
262
+	 *
263
+	 * @return void
264
+	 */
265
+	abstract protected function _setup_data();
266
+
267
+
268
+	/**
269
+	 * Returns database safe representation of the data later used to when instantiating this object.
270
+	 *
271
+	 * @param mixed $data The incoming data to be prepped.
272
+	 * @return mixed   The prepped data for db
273
+	 */
274
+	public static function convert_data_for_persistent_storage($data)
275
+	{
276
+		return $data;
277
+	}
278
+
279
+
280
+	/**
281
+	 * Data that has been stored in persistent storage that was prepped by _convert_data_for_persistent_storage
282
+	 * can be sent into this method and converted back into the format used for instantiating with this data handler.
283
+	 *
284
+	 * @param $data
285
+	 * @return mixed
286
+	 */
287
+	public static function convert_data_from_persistent_storage($data)
288
+	{
289
+		return $data;
290
+	}
291
+
292
+
293
+	/**
294
+	 * only purpose is to return the data
295
+	 *
296
+	 * @access public
297
+	 * @return mixed the formatted data object!
298
+	 */
299
+	public function data()
300
+	{
301
+		return $this->_data;
302
+	}
303
+
304
+
305
+	/**
306
+	 * This helper method can be used by any incoming data handlers to setup the data correctly.  All that is required
307
+	 * is that $this->reg_objs be set.
308
+	 *
309
+	 * @throws EE_Error
310
+	 * @throws InvalidDataTypeException
311
+	 * @throws InvalidInterfaceException
312
+	 * @throws InvalidArgumentException
313
+	 * @throws EntityNotFoundException
314
+	 */
315
+	protected function _assemble_data()
316
+	{
317
+		// verify that reg_objs is set
318
+		if (! is_array($this->reg_objs)
319
+			&& ! reset($this->reg_objs) instanceof EE_Registration
320
+		) {
321
+			throw new EE_Error(
322
+				esc_html__(
323
+					'In order to assemble the data correctly, the "reg_objs" property must be an array of EE_Registration objects',
324
+					'event_espresso'
325
+				)
326
+			);
327
+		}
328
+
329
+		// get all attendee and events associated with the registrations in this transaction
330
+		$events             = $event_setup = $evtcache = $tickets = $datetimes = array();
331
+		$answers            = $questions = $attendees = $line_items = $registrations = array();
332
+		$total_ticket_count = 0;
333
+
334
+		if (! empty($this->reg_objs)) {
335
+			$event_attendee_count = array();
336
+			/** @var EE_Registration $reg */
337
+			foreach ($this->reg_objs as $reg) {
338
+				if ($this->_skip_registration_for_processing($reg)
339
+				) {
340
+					continue;
341
+				}
342
+
343
+				$evt_id = $reg->event_ID();
344
+				/** @type EE_Ticket $ticket */
345
+				$ticket          = $reg->get_first_related('Ticket');
346
+				$attendee = $reg->attendee();
347
+				$event = $reg->event();
348
+				// if none of the following entities are available, then we can't setup other data reliably,
349
+				// so let's just skip.
350
+				if (! $ticket instanceof EE_Ticket
351
+					|| ! $attendee instanceof EE_Attendee
352
+					|| ! $event instanceof EE_Event
353
+				) {
354
+					continue;
355
+				}
356
+				$relateddatetime = $ticket->datetimes();
357
+				$total_ticket_count++;
358
+				$tickets[ $ticket->ID() ]['ticket']                        = $ticket;
359
+				$tickets[ $ticket->ID() ]['count']                         = is_array($tickets[ $ticket->ID() ])
360
+																		   && isset($tickets[ $ticket->ID() ]['count'])
361
+					? $tickets[ $ticket->ID() ]['count'] + 1
362
+					: 1;
363
+				$tickets[ $ticket->ID() ]['att_objs'][ $attendee->ID() ] = $attendee;
364
+				$tickets[ $ticket->ID() ]['dtt_objs']                      = $relateddatetime;
365
+				$tickets[ $ticket->ID() ]['reg_objs'][ $reg->ID() ]          = $reg;
366
+				$tickets[ $ticket->ID() ]['EE_Event']                      = $event;
367
+				$evtcache[ $evt_id ]                                       = $event;
368
+				$eventsetup[ $evt_id ]['reg_objs'][ $reg->ID() ]             = $reg;
369
+				$eventsetup[ $evt_id ]['tkt_objs'][ $ticket->ID() ]          = $ticket;
370
+				$eventsetup[ $evt_id ]['att_objs'][ $attendee->ID() ]    = $attendee;
371
+				$event_attendee_count[ $evt_id ]                           = isset($event_attendee_count[ $evt_id ])
372
+					? $event_attendee_count[ $evt_id ] + 1
373
+					: 0;
374
+				$attendees[ $reg->attendee_ID() ]['line_ref'][]            = $evt_id;
375
+				$attendees[ $reg->attendee_ID() ]['att_obj']               = $attendee;
376
+				$attendees[ $reg->attendee_ID() ]['reg_objs'][ $reg->ID() ]  = $reg;
377
+				// $attendees[ $reg->attendee_ID() ]['registration_id'] = $reg->ID();
378
+				$attendees[ $reg->attendee_ID() ]['attendee_email']          = $attendee->email();
379
+				$attendees[ $reg->attendee_ID() ]['tkt_objs'][ $ticket->ID() ] = $ticket;
380
+				$attendees[ $reg->attendee_ID() ]['evt_objs'][ $evt_id ]       = $event;
381
+
382
+				// registrations
383
+				$registrations[ $reg->ID() ]['tkt_obj'] = $ticket;
384
+				$registrations[ $reg->ID() ]['evt_obj'] = $event;
385
+				$registrations[ $reg->ID() ]['reg_obj'] = $reg;
386
+				$registrations[ $reg->ID() ]['att_obj'] = $attendee;
387
+
388
+				// set up answer objects
389
+				$rel_ans = $reg->get_many_related('Answer');
390
+				foreach ($rel_ans as $ansid => $answer) {
391
+					if (! isset($questions[ $ansid ])) {
392
+						$questions[ $ansid ] = $answer->get_first_related('Question');
393
+					}
394
+					$answers[ $ansid ]                               = $answer;
395
+					$registrations[ $reg->ID() ]['ans_objs'][ $ansid ] = $answer;
396
+				}
397
+				/**
398
+				 * @var int $dtt_id
399
+				 * @var EE_Datetime $datetime
400
+				 */
401
+				foreach ($relateddatetime as $dtt_id => $datetime) {
402
+					$eventsetup[ $evt_id ]['dtt_objs'][ $dtt_id ]       = $datetime;
403
+					$registrations[ $reg->ID() ]['dtt_objs'][ $dtt_id ] = $datetime;
404
+
405
+					if (isset($datetimes[ $dtt_id ])) {
406
+						continue; // already have this info in the datetimes array.
407
+					}
408
+
409
+					$datetimes[ $dtt_id ]['tkt_objs'][]           = $ticket;
410
+					$datetimes[ $dtt_id ]['datetime']             = $datetime;
411
+					$datetimes[ $dtt_id ]['evt_objs'][ $evt_id ]    = $event;
412
+					$datetimes[ $dtt_id ]['reg_objs'][ $reg->ID() ] = $reg;
413
+				}
414
+			}
415
+
416
+			// let's loop through the unique event=>reg items and setup data on them
417
+
418
+			if (! empty($eventsetup)) {
419
+				foreach ($eventsetup as $evt_id => $items) {
420
+					$ticket_line_items_for_event = array();
421
+					if ($this->txn instanceof EE_Transaction) {
422
+						$ticket_line_items_for_event = EEM_Line_Item::instance()->get_all(
423
+							array(
424
+								array(
425
+									'Ticket.Datetime.EVT_ID' => $evt_id,
426
+									'TXN_ID'                 => $this->txn->ID(),
427
+								),
428
+								'default_where_conditions' => 'none',
429
+							)
430
+						);
431
+					}
432
+					$events[ $evt_id ] = array(
433
+						'ID'              => $evt_id,
434
+						'event'           => $evtcache[ $evt_id ],
435
+						'name'            => $evtcache[ $evt_id ] instanceof EE_Event ? $evtcache[ $evt_id ]->name() : '',
436
+						'total_attendees' => $event_attendee_count[ $evt_id ],
437
+						'reg_objs'        => $items['reg_objs'],
438
+						'tkt_objs'        => $items['tkt_objs'],
439
+						'att_objs'        => $items['att_objs'],
440
+						'dtt_objs'        => isset($items['dtt_objs']) ? $items['dtt_objs'] : array(),
441
+						'line_items'      => $ticket_line_items_for_event,
442
+					);
443
+
444
+					// make sure the tickets have the line items setup for them.
445
+					foreach ($ticket_line_items_for_event as $line_id => $line_item) {
446
+						// only add the ticket line items if we already have this ticket in the $tickets array.
447
+						if ($line_item instanceof EE_Line_Item && isset($tickets[ $line_item->ticket()->ID() ])) {
448
+							$tickets[ $line_item->ticket()->ID() ]['line_item']      = $line_item;
449
+							$tickets[ $line_item->ticket()->ID() ]['sub_line_items'] = $line_item->children();
450
+							$line_items[ $line_item->ID() ]['children']              = $line_item->children();
451
+							$line_items[ $line_item->ID() ]['EE_Ticket']             = $line_item->ticket();
452
+						}
453
+					}
454
+				}
455
+			}
456
+
457
+			$this->grand_total_line_item = $this->txn instanceof EE_Transaction
458
+				? $this->txn->total_line_item()
459
+				: null;
460
+		}
461
+
462
+		// lets set the attendees and events properties
463
+		$this->attendees                = $attendees;
464
+		$this->events                   = $events;
465
+		$this->tickets                  = $tickets;
466
+		$this->line_items_with_children = $line_items;
467
+		$this->datetimes                = $datetimes;
468
+		$this->questions                = $questions;
469
+		$this->answers                  = $answers;
470
+		$this->total_ticket_count       = $total_ticket_count;
471
+		$this->registrations            = $registrations;
472
+
473
+		if ($this->txn instanceof EE_Transaction) {
474
+			$this->tax_line_items        = $this->txn->tax_items();
475
+			$this->additional_line_items = $this->txn->non_ticket_line_items();
476
+			$this->payments              = $this->txn->payments();
477
+
478
+			// setup primary registration if we have a single transaction object to work with
479
+
480
+			// let's get just the primary_attendee_data!  First we get the primary registration object.
481
+			$primary_reg = $this->txn->primary_registration();
482
+			// verify
483
+			if ($primary_reg instanceof EE_Registration) {
484
+				// get attendee object
485
+				if ($primary_reg->attendee() instanceof EE_Attendee) {
486
+					// now we can setup the primary_attendee_data array
487
+					$this->primary_attendee_data = array(
488
+						'registration_id' => $primary_reg->ID(),
489
+						'att_obj'         => $primary_reg->attendee(),
490
+						'reg_obj'         => $primary_reg,
491
+						'primary_att_obj' => $primary_reg->attendee(),
492
+						'primary_reg_obj' => $primary_reg,
493
+					);
494
+				} else {
495
+					EE_Error::add_error(
496
+						esc_html__(
497
+							'Incoming data does not have a valid Attendee object for the primary registrant.',
498
+							'event_espresso'
499
+						),
500
+						__FILE__,
501
+						__FUNCTION__,
502
+						__LINE__
503
+					);
504
+				}
505
+			} else {
506
+				EE_Error::add_error(
507
+					esc_html__(
508
+						'Incoming data does not have a valid Registration object for the primary registrant.',
509
+						'event_espresso'
510
+					),
511
+					__FILE__,
512
+					__FUNCTION__,
513
+					__LINE__
514
+				);
515
+			}
516
+		}
517
+	}
518
+
519
+	/**
520
+	 * This simply considers whether the given registration should be processed or not based on comparison with the
521
+	 * filtered_reg_status property.
522
+	 *
523
+	 * @param EE_Registration $registration
524
+	 * @return bool  returning true means we DO want to skip processing.  returning false means we DON'T want to skip
525
+	 *               processing
526
+	 */
527
+	protected function _skip_registration_for_processing(EE_Registration $registration)
528
+	{
529
+		if (empty($this->filtered_reg_status)) {
530
+			return false;
531
+		}
532
+
533
+		// if we made it here then we just compare the filtered_reg_status with the registration status and return that
534
+		return $this->filtered_reg_status !== $registration->status_ID();
535
+	}
536 536
 }
Please login to merge, or discard this patch.
Spacing   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -315,7 +315,7 @@  discard block
 block discarded – undo
315 315
     protected function _assemble_data()
316 316
     {
317 317
         // verify that reg_objs is set
318
-        if (! is_array($this->reg_objs)
318
+        if ( ! is_array($this->reg_objs)
319 319
             && ! reset($this->reg_objs) instanceof EE_Registration
320 320
         ) {
321 321
             throw new EE_Error(
@@ -331,7 +331,7 @@  discard block
 block discarded – undo
331 331
         $answers            = $questions = $attendees = $line_items = $registrations = array();
332 332
         $total_ticket_count = 0;
333 333
 
334
-        if (! empty($this->reg_objs)) {
334
+        if ( ! empty($this->reg_objs)) {
335 335
             $event_attendee_count = array();
336 336
             /** @var EE_Registration $reg */
337 337
             foreach ($this->reg_objs as $reg) {
@@ -342,12 +342,12 @@  discard block
 block discarded – undo
342 342
 
343 343
                 $evt_id = $reg->event_ID();
344 344
                 /** @type EE_Ticket $ticket */
345
-                $ticket          = $reg->get_first_related('Ticket');
345
+                $ticket = $reg->get_first_related('Ticket');
346 346
                 $attendee = $reg->attendee();
347 347
                 $event = $reg->event();
348 348
                 // if none of the following entities are available, then we can't setup other data reliably,
349 349
                 // so let's just skip.
350
-                if (! $ticket instanceof EE_Ticket
350
+                if ( ! $ticket instanceof EE_Ticket
351 351
                     || ! $attendee instanceof EE_Attendee
352 352
                     || ! $event instanceof EE_Event
353 353
                 ) {
@@ -355,67 +355,67 @@  discard block
 block discarded – undo
355 355
                 }
356 356
                 $relateddatetime = $ticket->datetimes();
357 357
                 $total_ticket_count++;
358
-                $tickets[ $ticket->ID() ]['ticket']                        = $ticket;
359
-                $tickets[ $ticket->ID() ]['count']                         = is_array($tickets[ $ticket->ID() ])
360
-                                                                           && isset($tickets[ $ticket->ID() ]['count'])
361
-                    ? $tickets[ $ticket->ID() ]['count'] + 1
358
+                $tickets[$ticket->ID()]['ticket']                        = $ticket;
359
+                $tickets[$ticket->ID()]['count']                         = is_array($tickets[$ticket->ID()])
360
+                                                                           && isset($tickets[$ticket->ID()]['count'])
361
+                    ? $tickets[$ticket->ID()]['count'] + 1
362 362
                     : 1;
363
-                $tickets[ $ticket->ID() ]['att_objs'][ $attendee->ID() ] = $attendee;
364
-                $tickets[ $ticket->ID() ]['dtt_objs']                      = $relateddatetime;
365
-                $tickets[ $ticket->ID() ]['reg_objs'][ $reg->ID() ]          = $reg;
366
-                $tickets[ $ticket->ID() ]['EE_Event']                      = $event;
367
-                $evtcache[ $evt_id ]                                       = $event;
368
-                $eventsetup[ $evt_id ]['reg_objs'][ $reg->ID() ]             = $reg;
369
-                $eventsetup[ $evt_id ]['tkt_objs'][ $ticket->ID() ]          = $ticket;
370
-                $eventsetup[ $evt_id ]['att_objs'][ $attendee->ID() ]    = $attendee;
371
-                $event_attendee_count[ $evt_id ]                           = isset($event_attendee_count[ $evt_id ])
372
-                    ? $event_attendee_count[ $evt_id ] + 1
363
+                $tickets[$ticket->ID()]['att_objs'][$attendee->ID()] = $attendee;
364
+                $tickets[$ticket->ID()]['dtt_objs']                      = $relateddatetime;
365
+                $tickets[$ticket->ID()]['reg_objs'][$reg->ID()]          = $reg;
366
+                $tickets[$ticket->ID()]['EE_Event']                      = $event;
367
+                $evtcache[$evt_id]                                       = $event;
368
+                $eventsetup[$evt_id]['reg_objs'][$reg->ID()]             = $reg;
369
+                $eventsetup[$evt_id]['tkt_objs'][$ticket->ID()]          = $ticket;
370
+                $eventsetup[$evt_id]['att_objs'][$attendee->ID()] = $attendee;
371
+                $event_attendee_count[$evt_id]                           = isset($event_attendee_count[$evt_id])
372
+                    ? $event_attendee_count[$evt_id] + 1
373 373
                     : 0;
374
-                $attendees[ $reg->attendee_ID() ]['line_ref'][]            = $evt_id;
375
-                $attendees[ $reg->attendee_ID() ]['att_obj']               = $attendee;
376
-                $attendees[ $reg->attendee_ID() ]['reg_objs'][ $reg->ID() ]  = $reg;
374
+                $attendees[$reg->attendee_ID()]['line_ref'][]            = $evt_id;
375
+                $attendees[$reg->attendee_ID()]['att_obj']               = $attendee;
376
+                $attendees[$reg->attendee_ID()]['reg_objs'][$reg->ID()]  = $reg;
377 377
                 // $attendees[ $reg->attendee_ID() ]['registration_id'] = $reg->ID();
378
-                $attendees[ $reg->attendee_ID() ]['attendee_email']          = $attendee->email();
379
-                $attendees[ $reg->attendee_ID() ]['tkt_objs'][ $ticket->ID() ] = $ticket;
380
-                $attendees[ $reg->attendee_ID() ]['evt_objs'][ $evt_id ]       = $event;
378
+                $attendees[$reg->attendee_ID()]['attendee_email']          = $attendee->email();
379
+                $attendees[$reg->attendee_ID()]['tkt_objs'][$ticket->ID()] = $ticket;
380
+                $attendees[$reg->attendee_ID()]['evt_objs'][$evt_id]       = $event;
381 381
 
382 382
                 // registrations
383
-                $registrations[ $reg->ID() ]['tkt_obj'] = $ticket;
384
-                $registrations[ $reg->ID() ]['evt_obj'] = $event;
385
-                $registrations[ $reg->ID() ]['reg_obj'] = $reg;
386
-                $registrations[ $reg->ID() ]['att_obj'] = $attendee;
383
+                $registrations[$reg->ID()]['tkt_obj'] = $ticket;
384
+                $registrations[$reg->ID()]['evt_obj'] = $event;
385
+                $registrations[$reg->ID()]['reg_obj'] = $reg;
386
+                $registrations[$reg->ID()]['att_obj'] = $attendee;
387 387
 
388 388
                 // set up answer objects
389 389
                 $rel_ans = $reg->get_many_related('Answer');
390 390
                 foreach ($rel_ans as $ansid => $answer) {
391
-                    if (! isset($questions[ $ansid ])) {
392
-                        $questions[ $ansid ] = $answer->get_first_related('Question');
391
+                    if ( ! isset($questions[$ansid])) {
392
+                        $questions[$ansid] = $answer->get_first_related('Question');
393 393
                     }
394
-                    $answers[ $ansid ]                               = $answer;
395
-                    $registrations[ $reg->ID() ]['ans_objs'][ $ansid ] = $answer;
394
+                    $answers[$ansid] = $answer;
395
+                    $registrations[$reg->ID()]['ans_objs'][$ansid] = $answer;
396 396
                 }
397 397
                 /**
398 398
                  * @var int $dtt_id
399 399
                  * @var EE_Datetime $datetime
400 400
                  */
401 401
                 foreach ($relateddatetime as $dtt_id => $datetime) {
402
-                    $eventsetup[ $evt_id ]['dtt_objs'][ $dtt_id ]       = $datetime;
403
-                    $registrations[ $reg->ID() ]['dtt_objs'][ $dtt_id ] = $datetime;
402
+                    $eventsetup[$evt_id]['dtt_objs'][$dtt_id]       = $datetime;
403
+                    $registrations[$reg->ID()]['dtt_objs'][$dtt_id] = $datetime;
404 404
 
405
-                    if (isset($datetimes[ $dtt_id ])) {
405
+                    if (isset($datetimes[$dtt_id])) {
406 406
                         continue; // already have this info in the datetimes array.
407 407
                     }
408 408
 
409
-                    $datetimes[ $dtt_id ]['tkt_objs'][]           = $ticket;
410
-                    $datetimes[ $dtt_id ]['datetime']             = $datetime;
411
-                    $datetimes[ $dtt_id ]['evt_objs'][ $evt_id ]    = $event;
412
-                    $datetimes[ $dtt_id ]['reg_objs'][ $reg->ID() ] = $reg;
409
+                    $datetimes[$dtt_id]['tkt_objs'][]           = $ticket;
410
+                    $datetimes[$dtt_id]['datetime']             = $datetime;
411
+                    $datetimes[$dtt_id]['evt_objs'][$evt_id]    = $event;
412
+                    $datetimes[$dtt_id]['reg_objs'][$reg->ID()] = $reg;
413 413
                 }
414 414
             }
415 415
 
416 416
             // let's loop through the unique event=>reg items and setup data on them
417 417
 
418
-            if (! empty($eventsetup)) {
418
+            if ( ! empty($eventsetup)) {
419 419
                 foreach ($eventsetup as $evt_id => $items) {
420 420
                     $ticket_line_items_for_event = array();
421 421
                     if ($this->txn instanceof EE_Transaction) {
@@ -429,11 +429,11 @@  discard block
 block discarded – undo
429 429
                             )
430 430
                         );
431 431
                     }
432
-                    $events[ $evt_id ] = array(
432
+                    $events[$evt_id] = array(
433 433
                         'ID'              => $evt_id,
434
-                        'event'           => $evtcache[ $evt_id ],
435
-                        'name'            => $evtcache[ $evt_id ] instanceof EE_Event ? $evtcache[ $evt_id ]->name() : '',
436
-                        'total_attendees' => $event_attendee_count[ $evt_id ],
434
+                        'event'           => $evtcache[$evt_id],
435
+                        'name'            => $evtcache[$evt_id] instanceof EE_Event ? $evtcache[$evt_id]->name() : '',
436
+                        'total_attendees' => $event_attendee_count[$evt_id],
437 437
                         'reg_objs'        => $items['reg_objs'],
438 438
                         'tkt_objs'        => $items['tkt_objs'],
439 439
                         'att_objs'        => $items['att_objs'],
@@ -444,11 +444,11 @@  discard block
 block discarded – undo
444 444
                     // make sure the tickets have the line items setup for them.
445 445
                     foreach ($ticket_line_items_for_event as $line_id => $line_item) {
446 446
                         // only add the ticket line items if we already have this ticket in the $tickets array.
447
-                        if ($line_item instanceof EE_Line_Item && isset($tickets[ $line_item->ticket()->ID() ])) {
448
-                            $tickets[ $line_item->ticket()->ID() ]['line_item']      = $line_item;
449
-                            $tickets[ $line_item->ticket()->ID() ]['sub_line_items'] = $line_item->children();
450
-                            $line_items[ $line_item->ID() ]['children']              = $line_item->children();
451
-                            $line_items[ $line_item->ID() ]['EE_Ticket']             = $line_item->ticket();
447
+                        if ($line_item instanceof EE_Line_Item && isset($tickets[$line_item->ticket()->ID()])) {
448
+                            $tickets[$line_item->ticket()->ID()]['line_item']      = $line_item;
449
+                            $tickets[$line_item->ticket()->ID()]['sub_line_items'] = $line_item->children();
450
+                            $line_items[$line_item->ID()]['children']              = $line_item->children();
451
+                            $line_items[$line_item->ID()]['EE_Ticket']             = $line_item->ticket();
452 452
                         }
453 453
                     }
454 454
                 }
Please login to merge, or discard this patch.
core/libraries/rest_api/ModelDataTranslator.php 2 patches
Unused Use Statements   -4 removed lines patch added patch discarded remove patch
@@ -4,14 +4,10 @@
 block discarded – undo
4 4
 
5 5
 use DomainException;
6 6
 use EE_Boolean_Field;
7
-use EE_Capabilities;
8 7
 use EE_Datetime_Field;
9 8
 use EE_Error;
10 9
 use EE_Infinite_Integer_Field;
11
-use EE_Maybe_Serialized_Simple_HTML_Field;
12 10
 use EE_Model_Field_Base;
13
-use EE_Password_Field;
14
-use EE_Restriction_Generator_Base;
15 11
 use EE_Serialized_Text_Field;
16 12
 use EED_Core_Rest_Api;
17 13
 use EEM_Base;
Please login to merge, or discard this patch.
Indentation   +642 added lines, -642 removed lines patch added patch discarded remove patch
@@ -39,646 +39,646 @@
 block discarded – undo
39 39
 class ModelDataTranslator
40 40
 {
41 41
 
42
-    /**
43
-     * We used to use -1 for infinity in the rest api, but that's ambiguous for
44
-     * fields that COULD contain -1; so we use null
45
-     */
46
-    const EE_INF_IN_REST = null;
47
-
48
-
49
-    /**
50
-     * Prepares a possible array of input values from JSON for use by the models
51
-     *
52
-     * @param EE_Model_Field_Base $field_obj
53
-     * @param mixed               $original_value_maybe_array
54
-     * @param string              $requested_version
55
-     * @param string              $timezone_string treat values as being in this timezone
56
-     * @return mixed
57
-     * @throws RestException
58
-     */
59
-    public static function prepareFieldValuesFromJson(
60
-        $field_obj,
61
-        $original_value_maybe_array,
62
-        $requested_version,
63
-        $timezone_string = 'UTC'
64
-    ) {
65
-        if (is_array($original_value_maybe_array)
66
-            && ! $field_obj instanceof EE_Serialized_Text_Field
67
-        ) {
68
-            $new_value_maybe_array = array();
69
-            foreach ($original_value_maybe_array as $array_key => $array_item) {
70
-                $new_value_maybe_array[ $array_key ] = ModelDataTranslator::prepareFieldValueFromJson(
71
-                    $field_obj,
72
-                    $array_item,
73
-                    $requested_version,
74
-                    $timezone_string
75
-                );
76
-            }
77
-        } else {
78
-            $new_value_maybe_array = ModelDataTranslator::prepareFieldValueFromJson(
79
-                $field_obj,
80
-                $original_value_maybe_array,
81
-                $requested_version,
82
-                $timezone_string
83
-            );
84
-        }
85
-        return $new_value_maybe_array;
86
-    }
87
-
88
-
89
-    /**
90
-     * Prepares an array of field values FOR use in JSON/REST API
91
-     *
92
-     * @param EE_Model_Field_Base $field_obj
93
-     * @param mixed               $original_value_maybe_array
94
-     * @param string              $request_version (eg 4.8.36)
95
-     * @return array
96
-     */
97
-    public static function prepareFieldValuesForJson($field_obj, $original_value_maybe_array, $request_version)
98
-    {
99
-        if (is_array($original_value_maybe_array)) {
100
-            $new_value = array();
101
-            foreach ($original_value_maybe_array as $key => $value) {
102
-                $new_value[ $key ] = ModelDataTranslator::prepareFieldValuesForJson(
103
-                    $field_obj,
104
-                    $value,
105
-                    $request_version
106
-                );
107
-            }
108
-        } else {
109
-            $new_value = ModelDataTranslator::prepareFieldValueForJson(
110
-                $field_obj,
111
-                $original_value_maybe_array,
112
-                $request_version
113
-            );
114
-        }
115
-        return $new_value;
116
-    }
117
-
118
-
119
-    /**
120
-     * Prepares incoming data from the json or $_REQUEST parameters for the models'
121
-     * "$query_params".
122
-     *
123
-     * @param EE_Model_Field_Base $field_obj
124
-     * @param mixed               $original_value
125
-     * @param string              $requested_version
126
-     * @param string              $timezone_string treat values as being in this timezone
127
-     * @return mixed
128
-     * @throws RestException
129
-     * @throws DomainException
130
-     * @throws EE_Error
131
-     */
132
-    public static function prepareFieldValueFromJson(
133
-        $field_obj,
134
-        $original_value,
135
-        $requested_version,
136
-        $timezone_string = 'UTC' // UTC
137
-    ) {
138
-        // check if they accidentally submitted an error value. If so throw an exception
139
-        if (is_array($original_value)
140
-            && isset($original_value['error_code'], $original_value['error_message'])) {
141
-            throw new RestException(
142
-                'rest_submitted_error_value',
143
-                sprintf(
144
-                    esc_html__(
145
-                        'You tried to submit a JSON error object as a value for %1$s. That\'s not allowed.',
146
-                        'event_espresso'
147
-                    ),
148
-                    $field_obj->get_name()
149
-                ),
150
-                array(
151
-                    'status' => 400,
152
-                )
153
-            );
154
-        }
155
-        // double-check for serialized PHP. We never accept serialized PHP. No way Jose.
156
-        ModelDataTranslator::throwExceptionIfContainsSerializedData($original_value);
157
-        $timezone_string = $timezone_string !== '' ? $timezone_string : get_option('timezone_string', '');
158
-        $new_value = null;
159
-        // walk through the submitted data and double-check for serialized PHP. We never accept serialized PHP. No
160
-        // way Jose.
161
-        ModelDataTranslator::throwExceptionIfContainsSerializedData($original_value);
162
-        if ($field_obj instanceof EE_Infinite_Integer_Field
163
-            && in_array($original_value, array(null, ''), true)
164
-        ) {
165
-            $new_value = EE_INF;
166
-        } elseif ($field_obj instanceof EE_Datetime_Field) {
167
-            $new_value = rest_parse_date(
168
-                self::getTimestampWithTimezoneOffset($original_value, $field_obj, $timezone_string)
169
-            );
170
-            if ($new_value === false) {
171
-                throw new RestException(
172
-                    'invalid_format_for_timestamp',
173
-                    sprintf(
174
-                        esc_html__(
175
-                            'Timestamps received on a request as the value for Date and Time fields must be in %1$s/%2$s format.  The timestamp provided (%3$s) is not that format.',
176
-                            'event_espresso'
177
-                        ),
178
-                        'RFC3339',
179
-                        'ISO8601',
180
-                        $original_value
181
-                    ),
182
-                    array(
183
-                        'status' => 400,
184
-                    )
185
-                );
186
-            }
187
-        } elseif ($field_obj instanceof EE_Boolean_Field) {
188
-            // Interpreted the strings "false", "true", "on", "off" appropriately.
189
-            $new_value = filter_var($original_value, FILTER_VALIDATE_BOOLEAN);
190
-        } else {
191
-            $new_value = $original_value;
192
-        }
193
-        return $new_value;
194
-    }
195
-
196
-
197
-    /**
198
-     * This checks if the incoming timestamp has timezone information already on it and if it doesn't then adds timezone
199
-     * information via details obtained from the host site.
200
-     *
201
-     * @param string            $original_timestamp
202
-     * @param EE_Datetime_Field $datetime_field
203
-     * @param                   $timezone_string
204
-     * @return string
205
-     * @throws DomainException
206
-     */
207
-    private static function getTimestampWithTimezoneOffset(
208
-        $original_timestamp,
209
-        EE_Datetime_Field $datetime_field,
210
-        $timezone_string
211
-    ) {
212
-        // already have timezone information?
213
-        if (preg_match('/Z|(\+|\-)(\d{2}:\d{2})/', $original_timestamp)) {
214
-            // yes, we're ignoring the timezone.
215
-            return $original_timestamp;
216
-        }
217
-        // need to append timezone
218
-        list($offset_sign, $offset_secs) = self::parseTimezoneOffset(
219
-            $datetime_field->get_timezone_offset(
220
-                new \DateTimeZone($timezone_string),
221
-                $original_timestamp
222
-            )
223
-        );
224
-        $offset_string =
225
-            str_pad(
226
-                floor($offset_secs / HOUR_IN_SECONDS),
227
-                2,
228
-                '0',
229
-                STR_PAD_LEFT
230
-            )
231
-            . ':'
232
-            . str_pad(
233
-                ($offset_secs % HOUR_IN_SECONDS) / MINUTE_IN_SECONDS,
234
-                2,
235
-                '0',
236
-                STR_PAD_LEFT
237
-            );
238
-        return $original_timestamp . $offset_sign . $offset_string;
239
-    }
240
-
241
-
242
-    /**
243
-     * Throws an exception if $data is a serialized PHP string (or somehow an actually PHP object, although I don't
244
-     * think that can happen). If $data is an array, recurses into its keys and values
245
-     *
246
-     * @param mixed $data
247
-     * @throws RestException
248
-     * @return void
249
-     */
250
-    public static function throwExceptionIfContainsSerializedData($data)
251
-    {
252
-        if (is_array($data)) {
253
-            foreach ($data as $key => $value) {
254
-                ModelDataTranslator::throwExceptionIfContainsSerializedData($key);
255
-                ModelDataTranslator::throwExceptionIfContainsSerializedData($value);
256
-            }
257
-        } else {
258
-            if (is_serialized($data) || is_object($data)) {
259
-                throw new RestException(
260
-                    'serialized_data_submission_prohibited',
261
-                    esc_html__(
262
-                    // @codingStandardsIgnoreStart
263
-                        'You tried to submit a string of serialized text. Serialized PHP is prohibited over the EE4 REST API.',
264
-                        // @codingStandardsIgnoreEnd
265
-                        'event_espresso'
266
-                    )
267
-                );
268
-            }
269
-        }
270
-    }
271
-
272
-
273
-    /**
274
-     * determines what's going on with them timezone strings
275
-     *
276
-     * @param int $timezone_offset
277
-     * @return array
278
-     */
279
-    private static function parseTimezoneOffset($timezone_offset)
280
-    {
281
-        $first_char = substr((string) $timezone_offset, 0, 1);
282
-        if ($first_char === '+' || $first_char === '-') {
283
-            $offset_sign = $first_char;
284
-            $offset_secs = substr((string) $timezone_offset, 1);
285
-        } else {
286
-            $offset_sign = '+';
287
-            $offset_secs = $timezone_offset;
288
-        }
289
-        return array($offset_sign, $offset_secs);
290
-    }
291
-
292
-
293
-    /**
294
-     * Prepares a field's value for display in the API
295
-     *
296
-     * @param EE_Model_Field_Base $field_obj
297
-     * @param mixed               $original_value
298
-     * @param string              $requested_version
299
-     * @return mixed
300
-     */
301
-    public static function prepareFieldValueForJson($field_obj, $original_value, $requested_version)
302
-    {
303
-        if ($original_value === EE_INF) {
304
-            $new_value = ModelDataTranslator::EE_INF_IN_REST;
305
-        } elseif ($field_obj instanceof EE_Datetime_Field) {
306
-            if (is_string($original_value)) {
307
-                // did they submit a string of a unix timestamp?
308
-                if (is_numeric($original_value)) {
309
-                    $datetime_obj = new \DateTime();
310
-                    $datetime_obj->setTimestamp((int) $original_value);
311
-                } else {
312
-                    // first, check if its a MySQL timestamp in GMT
313
-                    $datetime_obj = \DateTime::createFromFormat('Y-m-d H:i:s', $original_value);
314
-                }
315
-                if (! $datetime_obj instanceof \DateTime) {
316
-                    // so it's not a unix timestamp or a MySQL timestamp. Maybe its in the field's date/time format?
317
-                    $datetime_obj = $field_obj->prepare_for_set($original_value);
318
-                }
319
-                $original_value = $datetime_obj;
320
-            }
321
-            if ($original_value instanceof \DateTime) {
322
-                $new_value = $original_value->format('Y-m-d H:i:s');
323
-            } elseif (is_int($original_value) || is_float($original_value)) {
324
-                $new_value = date('Y-m-d H:i:s', $original_value);
325
-            } elseif ($original_value === null || $original_value === '') {
326
-                $new_value = null;
327
-            } else {
328
-                // so it's not a datetime object, unix timestamp (as string or int),
329
-                // MySQL timestamp, or even a string in the field object's format. So no idea what it is
330
-                throw new \EE_Error(
331
-                    sprintf(
332
-                        esc_html__(
333
-                        // @codingStandardsIgnoreStart
334
-                            'The value "%1$s" for the field "%2$s" on model "%3$s" could not be understood. It should be a PHP DateTime, unix timestamp, MySQL date, or string in the format "%4$s".',
335
-                            // @codingStandardsIgnoreEnd
336
-                            'event_espresso'
337
-                        ),
338
-                        $original_value,
339
-                        $field_obj->get_name(),
340
-                        $field_obj->get_model_name(),
341
-                        $field_obj->get_time_format() . ' ' . $field_obj->get_time_format()
342
-                    )
343
-                );
344
-            }
345
-            if ($new_value !== null) {
346
-                $new_value = mysql_to_rfc3339($new_value);
347
-            }
348
-        } else {
349
-            $new_value = $original_value;
350
-        }
351
-        // are we about to send an object? just don't. We have no good way to represent it in JSON.
352
-        // can't just check using is_object() because that missed PHP incomplete objects
353
-        if (! ModelDataTranslator::isRepresentableInJson($new_value)) {
354
-            $new_value = array(
355
-                'error_code'    => 'php_object_not_return',
356
-                'error_message' => esc_html__(
357
-                    'The value of this field in the database is a PHP object, which can\'t be represented in JSON.',
358
-                    'event_espresso'
359
-                ),
360
-            );
361
-        }
362
-        return apply_filters(
363
-            'FHEE__EventEspresso\core\libraries\rest_api\Model_Data_Translator__prepare_field_for_rest_api',
364
-            $new_value,
365
-            $field_obj,
366
-            $original_value,
367
-            $requested_version
368
-        );
369
-    }
370
-
371
-
372
-    /**
373
-     * Prepares condition-query-parameters (like what's in where and having) from
374
-     * the format expected in the API to use in the models
375
-     *
376
-     * @param array $inputted_query_params_of_this_type
377
-     * @param EEM_Base $model
378
-     * @param string $requested_version
379
-     * @param boolean $writing whether this data will be written to the DB, or if we're just building a query.
380
-     *                          If we're writing to the DB, we don't expect any operators, or any logic query
381
-     *                          parameters, and we also won't accept serialized data unless the current user has
382
-     *                          unfiltered_html.
383
-     * @return array
384
-     * @throws DomainException
385
-     * @throws EE_Error
386
-     * @throws RestException
387
-     * @throws InvalidDataTypeException
388
-     * @throws InvalidInterfaceException
389
-     * @throws InvalidArgumentException
390
-     */
391
-    public static function prepareConditionsQueryParamsForModels(
392
-        $inputted_query_params_of_this_type,
393
-        EEM_Base $model,
394
-        $requested_version,
395
-        $writing = false
396
-    ) {
397
-        $query_param_for_models = array();
398
-        $context = new RestIncomingQueryParamContext($model, $requested_version, $writing);
399
-        foreach ($inputted_query_params_of_this_type as $query_param_key => $query_param_value) {
400
-            $query_param_meta = new RestIncomingQueryParamMetadata($query_param_key, $query_param_value, $context);
401
-            if ($query_param_meta->getField() instanceof EE_Model_Field_Base) {
402
-                $translated_value = $query_param_meta->determineConditionsQueryParameterValue();
403
-                if ((isset($query_param_for_models[ $query_param_meta->getQueryParamKey() ]) && $query_param_meta->isGmtField())
404
-                    || $translated_value === null
405
-                ) {
406
-                    // they have already provided a non-gmt field, ignore the gmt one. That's what WP core
407
-                    // currently does (they might change it though). See https://core.trac.wordpress.org/ticket/39954
408
-                    // OR we couldn't create a translated value from their input
409
-                    continue;
410
-                }
411
-                $query_param_for_models[ $query_param_meta->getQueryParamKey() ] = $translated_value;
412
-            } else {
413
-                $nested_query_params = $query_param_meta->determineNestedConditionQueryParameters();
414
-                if ($nested_query_params) {
415
-                    $query_param_for_models[ $query_param_meta->getQueryParamKey() ] = $nested_query_params;
416
-                }
417
-            }
418
-        }
419
-        return $query_param_for_models;
420
-    }
421
-
422
-    /**
423
-     * Mostly checks if the last 4 characters are "_gmt", indicating its a
424
-     * gmt date field name
425
-     *
426
-     * @param string $field_name
427
-     * @return boolean
428
-     */
429
-    public static function isGmtDateFieldName($field_name)
430
-    {
431
-        return substr(
432
-            ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey($field_name),
433
-            -4,
434
-            4
435
-        ) === '_gmt';
436
-    }
437
-
438
-
439
-    /**
440
-     * Removes the last "_gmt" part of a field name (and if there is no "_gmt" at the end, leave it alone)
441
-     *
442
-     * @param string $field_name
443
-     * @return string
444
-     */
445
-    public static function removeGmtFromFieldName($field_name)
446
-    {
447
-        if (! ModelDataTranslator::isGmtDateFieldName($field_name)) {
448
-            return $field_name;
449
-        }
450
-        $query_param_sans_stars = ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey(
451
-            $field_name
452
-        );
453
-        $query_param_sans_gmt_and_sans_stars = substr(
454
-            $query_param_sans_stars,
455
-            0,
456
-            strrpos(
457
-                $field_name,
458
-                '_gmt'
459
-            )
460
-        );
461
-        return str_replace($query_param_sans_stars, $query_param_sans_gmt_and_sans_stars, $field_name);
462
-    }
463
-
464
-
465
-    /**
466
-     * Takes a field name from the REST API and prepares it for the model querying
467
-     *
468
-     * @param string $field_name
469
-     * @return string
470
-     */
471
-    public static function prepareFieldNameFromJson($field_name)
472
-    {
473
-        if (ModelDataTranslator::isGmtDateFieldName($field_name)) {
474
-            return ModelDataTranslator::removeGmtFromFieldName($field_name);
475
-        }
476
-        return $field_name;
477
-    }
478
-
479
-
480
-    /**
481
-     * Takes array of field names from REST API and prepares for models
482
-     *
483
-     * @param array $field_names
484
-     * @return array of field names (possibly include model prefixes)
485
-     */
486
-    public static function prepareFieldNamesFromJson(array $field_names)
487
-    {
488
-        $new_array = array();
489
-        foreach ($field_names as $key => $field_name) {
490
-            $new_array[ $key ] = ModelDataTranslator::prepareFieldNameFromJson($field_name);
491
-        }
492
-        return $new_array;
493
-    }
494
-
495
-
496
-    /**
497
-     * Takes array where array keys are field names (possibly with model path prefixes)
498
-     * from the REST API and prepares them for model querying
499
-     *
500
-     * @param array $field_names_as_keys
501
-     * @return array
502
-     */
503
-    public static function prepareFieldNamesInArrayKeysFromJson(array $field_names_as_keys)
504
-    {
505
-        $new_array = array();
506
-        foreach ($field_names_as_keys as $field_name => $value) {
507
-            $new_array[ ModelDataTranslator::prepareFieldNameFromJson($field_name) ] = $value;
508
-        }
509
-        return $new_array;
510
-    }
511
-
512
-
513
-    /**
514
-     * Prepares an array of model query params for use in the REST API
515
-     *
516
-     * @param array    $model_query_params
517
-     * @param EEM_Base $model
518
-     * @param string   $requested_version  eg "4.8.36". If null is provided, defaults to the latest release of the EE4
519
-     *                                     REST API
520
-     * @return array which can be passed into the EE4 REST API when querying a model resource
521
-     * @throws EE_Error
522
-     */
523
-    public static function prepareQueryParamsForRestApi(
524
-        array $model_query_params,
525
-        EEM_Base $model,
526
-        $requested_version = null
527
-    ) {
528
-        if ($requested_version === null) {
529
-            $requested_version = EED_Core_Rest_Api::latest_rest_api_version();
530
-        }
531
-        $rest_query_params = $model_query_params;
532
-        if (isset($model_query_params[0])) {
533
-            $rest_query_params['where'] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
534
-                $model_query_params[0],
535
-                $model,
536
-                $requested_version
537
-            );
538
-            unset($rest_query_params[0]);
539
-        }
540
-        if (isset($model_query_params['having'])) {
541
-            $rest_query_params['having'] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
542
-                $model_query_params['having'],
543
-                $model,
544
-                $requested_version
545
-            );
546
-        }
547
-        return apply_filters(
548
-            'FHEE__EventEspresso\core\libraries\rest_api\Model_Data_Translator__prepare_query_params_for_rest_api',
549
-            $rest_query_params,
550
-            $model_query_params,
551
-            $model,
552
-            $requested_version
553
-        );
554
-    }
555
-
556
-
557
-    /**
558
-     * Prepares all the sub-conditions query parameters (eg having or where conditions) for use in the rest api
559
-     *
560
-     * @param array    $inputted_query_params_of_this_type  eg like the "where" or "having" conditions query params
561
-     *                                                      @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
562
-     * @param EEM_Base $model
563
-     * @param string   $requested_version                   eg "4.8.36"
564
-     * @return array ready for use in the rest api query params
565
-     * @throws EE_Error
566
-     * @throws ObjectDetectedException if somehow a PHP object were in the query params' values,
567
-     *                                                      (which would be really unusual)
568
-     */
569
-    public static function prepareConditionsQueryParamsForRestApi(
570
-        $inputted_query_params_of_this_type,
571
-        EEM_Base $model,
572
-        $requested_version
573
-    ) {
574
-        $query_param_for_models = array();
575
-        foreach ($inputted_query_params_of_this_type as $query_param_key => $query_param_value) {
576
-            $field = ModelDataTranslator::deduceFieldFromQueryParam(
577
-                ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey($query_param_key),
578
-                $model
579
-            );
580
-            if ($field instanceof EE_Model_Field_Base) {
581
-                // did they specify an operator?
582
-                if (is_array($query_param_value)) {
583
-                    $op = $query_param_value[0];
584
-                    $translated_value = array($op);
585
-                    if (isset($query_param_value[1])) {
586
-                        $value = $query_param_value[1];
587
-                        $translated_value[1] = ModelDataTranslator::prepareFieldValuesForJson(
588
-                            $field,
589
-                            $value,
590
-                            $requested_version
591
-                        );
592
-                    }
593
-                } else {
594
-                    $translated_value = ModelDataTranslator::prepareFieldValueForJson(
595
-                        $field,
596
-                        $query_param_value,
597
-                        $requested_version
598
-                    );
599
-                }
600
-                $query_param_for_models[ $query_param_key ] = $translated_value;
601
-            } else {
602
-                // so it's not for a field, assume it's a logic query param key
603
-                $query_param_for_models[ $query_param_key ] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
604
-                    $query_param_value,
605
-                    $model,
606
-                    $requested_version
607
-                );
608
-            }
609
-        }
610
-        return $query_param_for_models;
611
-    }
612
-
613
-
614
-    /**
615
-     * @param $condition_query_param_key
616
-     * @return string
617
-     */
618
-    public static function removeStarsAndAnythingAfterFromConditionQueryParamKey($condition_query_param_key)
619
-    {
620
-        $pos_of_star = strpos($condition_query_param_key, '*');
621
-        if ($pos_of_star === false) {
622
-            return $condition_query_param_key;
623
-        } else {
624
-            $condition_query_param_sans_star = substr($condition_query_param_key, 0, $pos_of_star);
625
-            return $condition_query_param_sans_star;
626
-        }
627
-    }
628
-
629
-
630
-    /**
631
-     * Takes the input parameter and finds the model field that it indicates.
632
-     *
633
-     * @param string   $query_param_name like Registration.Transaction.TXN_ID, Event.Datetime.start_time, or REG_ID
634
-     * @param EEM_Base $model
635
-     * @return EE_Model_Field_Base
636
-     * @throws EE_Error
637
-     */
638
-    public static function deduceFieldFromQueryParam($query_param_name, EEM_Base $model)
639
-    {
640
-        // ok, now proceed with deducing which part is the model's name, and which is the field's name
641
-        // which will help us find the database table and column
642
-        $query_param_parts = explode('.', $query_param_name);
643
-        if (empty($query_param_parts)) {
644
-            throw new EE_Error(
645
-                sprintf(
646
-                    __(
647
-                        '_extract_column_name is empty when trying to extract column and table name from %s',
648
-                        'event_espresso'
649
-                    ),
650
-                    $query_param_name
651
-                )
652
-            );
653
-        }
654
-        $number_of_parts = count($query_param_parts);
655
-        $last_query_param_part = $query_param_parts[ count($query_param_parts) - 1 ];
656
-        if ($number_of_parts === 1) {
657
-            $field_name = $last_query_param_part;
658
-        } else {// $number_of_parts >= 2
659
-            // the last part is the column name, and there are only 2parts. therefore...
660
-            $field_name = $last_query_param_part;
661
-            $model = \EE_Registry::instance()->load_model($query_param_parts[ $number_of_parts - 2 ]);
662
-        }
663
-        try {
664
-            return $model->field_settings_for($field_name, false);
665
-        } catch (EE_Error $e) {
666
-            return null;
667
-        }
668
-    }
669
-
670
-
671
-    /**
672
-     * Returns true if $data can be easily represented in JSON.
673
-     * Basically, objects and resources can't be represented in JSON easily.
674
-     *
675
-     * @param mixed $data
676
-     * @return bool
677
-     */
678
-    protected static function isRepresentableInJson($data)
679
-    {
680
-        return is_scalar($data)
681
-               || is_array($data)
682
-               || is_null($data);
683
-    }
42
+	/**
43
+	 * We used to use -1 for infinity in the rest api, but that's ambiguous for
44
+	 * fields that COULD contain -1; so we use null
45
+	 */
46
+	const EE_INF_IN_REST = null;
47
+
48
+
49
+	/**
50
+	 * Prepares a possible array of input values from JSON for use by the models
51
+	 *
52
+	 * @param EE_Model_Field_Base $field_obj
53
+	 * @param mixed               $original_value_maybe_array
54
+	 * @param string              $requested_version
55
+	 * @param string              $timezone_string treat values as being in this timezone
56
+	 * @return mixed
57
+	 * @throws RestException
58
+	 */
59
+	public static function prepareFieldValuesFromJson(
60
+		$field_obj,
61
+		$original_value_maybe_array,
62
+		$requested_version,
63
+		$timezone_string = 'UTC'
64
+	) {
65
+		if (is_array($original_value_maybe_array)
66
+			&& ! $field_obj instanceof EE_Serialized_Text_Field
67
+		) {
68
+			$new_value_maybe_array = array();
69
+			foreach ($original_value_maybe_array as $array_key => $array_item) {
70
+				$new_value_maybe_array[ $array_key ] = ModelDataTranslator::prepareFieldValueFromJson(
71
+					$field_obj,
72
+					$array_item,
73
+					$requested_version,
74
+					$timezone_string
75
+				);
76
+			}
77
+		} else {
78
+			$new_value_maybe_array = ModelDataTranslator::prepareFieldValueFromJson(
79
+				$field_obj,
80
+				$original_value_maybe_array,
81
+				$requested_version,
82
+				$timezone_string
83
+			);
84
+		}
85
+		return $new_value_maybe_array;
86
+	}
87
+
88
+
89
+	/**
90
+	 * Prepares an array of field values FOR use in JSON/REST API
91
+	 *
92
+	 * @param EE_Model_Field_Base $field_obj
93
+	 * @param mixed               $original_value_maybe_array
94
+	 * @param string              $request_version (eg 4.8.36)
95
+	 * @return array
96
+	 */
97
+	public static function prepareFieldValuesForJson($field_obj, $original_value_maybe_array, $request_version)
98
+	{
99
+		if (is_array($original_value_maybe_array)) {
100
+			$new_value = array();
101
+			foreach ($original_value_maybe_array as $key => $value) {
102
+				$new_value[ $key ] = ModelDataTranslator::prepareFieldValuesForJson(
103
+					$field_obj,
104
+					$value,
105
+					$request_version
106
+				);
107
+			}
108
+		} else {
109
+			$new_value = ModelDataTranslator::prepareFieldValueForJson(
110
+				$field_obj,
111
+				$original_value_maybe_array,
112
+				$request_version
113
+			);
114
+		}
115
+		return $new_value;
116
+	}
117
+
118
+
119
+	/**
120
+	 * Prepares incoming data from the json or $_REQUEST parameters for the models'
121
+	 * "$query_params".
122
+	 *
123
+	 * @param EE_Model_Field_Base $field_obj
124
+	 * @param mixed               $original_value
125
+	 * @param string              $requested_version
126
+	 * @param string              $timezone_string treat values as being in this timezone
127
+	 * @return mixed
128
+	 * @throws RestException
129
+	 * @throws DomainException
130
+	 * @throws EE_Error
131
+	 */
132
+	public static function prepareFieldValueFromJson(
133
+		$field_obj,
134
+		$original_value,
135
+		$requested_version,
136
+		$timezone_string = 'UTC' // UTC
137
+	) {
138
+		// check if they accidentally submitted an error value. If so throw an exception
139
+		if (is_array($original_value)
140
+			&& isset($original_value['error_code'], $original_value['error_message'])) {
141
+			throw new RestException(
142
+				'rest_submitted_error_value',
143
+				sprintf(
144
+					esc_html__(
145
+						'You tried to submit a JSON error object as a value for %1$s. That\'s not allowed.',
146
+						'event_espresso'
147
+					),
148
+					$field_obj->get_name()
149
+				),
150
+				array(
151
+					'status' => 400,
152
+				)
153
+			);
154
+		}
155
+		// double-check for serialized PHP. We never accept serialized PHP. No way Jose.
156
+		ModelDataTranslator::throwExceptionIfContainsSerializedData($original_value);
157
+		$timezone_string = $timezone_string !== '' ? $timezone_string : get_option('timezone_string', '');
158
+		$new_value = null;
159
+		// walk through the submitted data and double-check for serialized PHP. We never accept serialized PHP. No
160
+		// way Jose.
161
+		ModelDataTranslator::throwExceptionIfContainsSerializedData($original_value);
162
+		if ($field_obj instanceof EE_Infinite_Integer_Field
163
+			&& in_array($original_value, array(null, ''), true)
164
+		) {
165
+			$new_value = EE_INF;
166
+		} elseif ($field_obj instanceof EE_Datetime_Field) {
167
+			$new_value = rest_parse_date(
168
+				self::getTimestampWithTimezoneOffset($original_value, $field_obj, $timezone_string)
169
+			);
170
+			if ($new_value === false) {
171
+				throw new RestException(
172
+					'invalid_format_for_timestamp',
173
+					sprintf(
174
+						esc_html__(
175
+							'Timestamps received on a request as the value for Date and Time fields must be in %1$s/%2$s format.  The timestamp provided (%3$s) is not that format.',
176
+							'event_espresso'
177
+						),
178
+						'RFC3339',
179
+						'ISO8601',
180
+						$original_value
181
+					),
182
+					array(
183
+						'status' => 400,
184
+					)
185
+				);
186
+			}
187
+		} elseif ($field_obj instanceof EE_Boolean_Field) {
188
+			// Interpreted the strings "false", "true", "on", "off" appropriately.
189
+			$new_value = filter_var($original_value, FILTER_VALIDATE_BOOLEAN);
190
+		} else {
191
+			$new_value = $original_value;
192
+		}
193
+		return $new_value;
194
+	}
195
+
196
+
197
+	/**
198
+	 * This checks if the incoming timestamp has timezone information already on it and if it doesn't then adds timezone
199
+	 * information via details obtained from the host site.
200
+	 *
201
+	 * @param string            $original_timestamp
202
+	 * @param EE_Datetime_Field $datetime_field
203
+	 * @param                   $timezone_string
204
+	 * @return string
205
+	 * @throws DomainException
206
+	 */
207
+	private static function getTimestampWithTimezoneOffset(
208
+		$original_timestamp,
209
+		EE_Datetime_Field $datetime_field,
210
+		$timezone_string
211
+	) {
212
+		// already have timezone information?
213
+		if (preg_match('/Z|(\+|\-)(\d{2}:\d{2})/', $original_timestamp)) {
214
+			// yes, we're ignoring the timezone.
215
+			return $original_timestamp;
216
+		}
217
+		// need to append timezone
218
+		list($offset_sign, $offset_secs) = self::parseTimezoneOffset(
219
+			$datetime_field->get_timezone_offset(
220
+				new \DateTimeZone($timezone_string),
221
+				$original_timestamp
222
+			)
223
+		);
224
+		$offset_string =
225
+			str_pad(
226
+				floor($offset_secs / HOUR_IN_SECONDS),
227
+				2,
228
+				'0',
229
+				STR_PAD_LEFT
230
+			)
231
+			. ':'
232
+			. str_pad(
233
+				($offset_secs % HOUR_IN_SECONDS) / MINUTE_IN_SECONDS,
234
+				2,
235
+				'0',
236
+				STR_PAD_LEFT
237
+			);
238
+		return $original_timestamp . $offset_sign . $offset_string;
239
+	}
240
+
241
+
242
+	/**
243
+	 * Throws an exception if $data is a serialized PHP string (or somehow an actually PHP object, although I don't
244
+	 * think that can happen). If $data is an array, recurses into its keys and values
245
+	 *
246
+	 * @param mixed $data
247
+	 * @throws RestException
248
+	 * @return void
249
+	 */
250
+	public static function throwExceptionIfContainsSerializedData($data)
251
+	{
252
+		if (is_array($data)) {
253
+			foreach ($data as $key => $value) {
254
+				ModelDataTranslator::throwExceptionIfContainsSerializedData($key);
255
+				ModelDataTranslator::throwExceptionIfContainsSerializedData($value);
256
+			}
257
+		} else {
258
+			if (is_serialized($data) || is_object($data)) {
259
+				throw new RestException(
260
+					'serialized_data_submission_prohibited',
261
+					esc_html__(
262
+					// @codingStandardsIgnoreStart
263
+						'You tried to submit a string of serialized text. Serialized PHP is prohibited over the EE4 REST API.',
264
+						// @codingStandardsIgnoreEnd
265
+						'event_espresso'
266
+					)
267
+				);
268
+			}
269
+		}
270
+	}
271
+
272
+
273
+	/**
274
+	 * determines what's going on with them timezone strings
275
+	 *
276
+	 * @param int $timezone_offset
277
+	 * @return array
278
+	 */
279
+	private static function parseTimezoneOffset($timezone_offset)
280
+	{
281
+		$first_char = substr((string) $timezone_offset, 0, 1);
282
+		if ($first_char === '+' || $first_char === '-') {
283
+			$offset_sign = $first_char;
284
+			$offset_secs = substr((string) $timezone_offset, 1);
285
+		} else {
286
+			$offset_sign = '+';
287
+			$offset_secs = $timezone_offset;
288
+		}
289
+		return array($offset_sign, $offset_secs);
290
+	}
291
+
292
+
293
+	/**
294
+	 * Prepares a field's value for display in the API
295
+	 *
296
+	 * @param EE_Model_Field_Base $field_obj
297
+	 * @param mixed               $original_value
298
+	 * @param string              $requested_version
299
+	 * @return mixed
300
+	 */
301
+	public static function prepareFieldValueForJson($field_obj, $original_value, $requested_version)
302
+	{
303
+		if ($original_value === EE_INF) {
304
+			$new_value = ModelDataTranslator::EE_INF_IN_REST;
305
+		} elseif ($field_obj instanceof EE_Datetime_Field) {
306
+			if (is_string($original_value)) {
307
+				// did they submit a string of a unix timestamp?
308
+				if (is_numeric($original_value)) {
309
+					$datetime_obj = new \DateTime();
310
+					$datetime_obj->setTimestamp((int) $original_value);
311
+				} else {
312
+					// first, check if its a MySQL timestamp in GMT
313
+					$datetime_obj = \DateTime::createFromFormat('Y-m-d H:i:s', $original_value);
314
+				}
315
+				if (! $datetime_obj instanceof \DateTime) {
316
+					// so it's not a unix timestamp or a MySQL timestamp. Maybe its in the field's date/time format?
317
+					$datetime_obj = $field_obj->prepare_for_set($original_value);
318
+				}
319
+				$original_value = $datetime_obj;
320
+			}
321
+			if ($original_value instanceof \DateTime) {
322
+				$new_value = $original_value->format('Y-m-d H:i:s');
323
+			} elseif (is_int($original_value) || is_float($original_value)) {
324
+				$new_value = date('Y-m-d H:i:s', $original_value);
325
+			} elseif ($original_value === null || $original_value === '') {
326
+				$new_value = null;
327
+			} else {
328
+				// so it's not a datetime object, unix timestamp (as string or int),
329
+				// MySQL timestamp, or even a string in the field object's format. So no idea what it is
330
+				throw new \EE_Error(
331
+					sprintf(
332
+						esc_html__(
333
+						// @codingStandardsIgnoreStart
334
+							'The value "%1$s" for the field "%2$s" on model "%3$s" could not be understood. It should be a PHP DateTime, unix timestamp, MySQL date, or string in the format "%4$s".',
335
+							// @codingStandardsIgnoreEnd
336
+							'event_espresso'
337
+						),
338
+						$original_value,
339
+						$field_obj->get_name(),
340
+						$field_obj->get_model_name(),
341
+						$field_obj->get_time_format() . ' ' . $field_obj->get_time_format()
342
+					)
343
+				);
344
+			}
345
+			if ($new_value !== null) {
346
+				$new_value = mysql_to_rfc3339($new_value);
347
+			}
348
+		} else {
349
+			$new_value = $original_value;
350
+		}
351
+		// are we about to send an object? just don't. We have no good way to represent it in JSON.
352
+		// can't just check using is_object() because that missed PHP incomplete objects
353
+		if (! ModelDataTranslator::isRepresentableInJson($new_value)) {
354
+			$new_value = array(
355
+				'error_code'    => 'php_object_not_return',
356
+				'error_message' => esc_html__(
357
+					'The value of this field in the database is a PHP object, which can\'t be represented in JSON.',
358
+					'event_espresso'
359
+				),
360
+			);
361
+		}
362
+		return apply_filters(
363
+			'FHEE__EventEspresso\core\libraries\rest_api\Model_Data_Translator__prepare_field_for_rest_api',
364
+			$new_value,
365
+			$field_obj,
366
+			$original_value,
367
+			$requested_version
368
+		);
369
+	}
370
+
371
+
372
+	/**
373
+	 * Prepares condition-query-parameters (like what's in where and having) from
374
+	 * the format expected in the API to use in the models
375
+	 *
376
+	 * @param array $inputted_query_params_of_this_type
377
+	 * @param EEM_Base $model
378
+	 * @param string $requested_version
379
+	 * @param boolean $writing whether this data will be written to the DB, or if we're just building a query.
380
+	 *                          If we're writing to the DB, we don't expect any operators, or any logic query
381
+	 *                          parameters, and we also won't accept serialized data unless the current user has
382
+	 *                          unfiltered_html.
383
+	 * @return array
384
+	 * @throws DomainException
385
+	 * @throws EE_Error
386
+	 * @throws RestException
387
+	 * @throws InvalidDataTypeException
388
+	 * @throws InvalidInterfaceException
389
+	 * @throws InvalidArgumentException
390
+	 */
391
+	public static function prepareConditionsQueryParamsForModels(
392
+		$inputted_query_params_of_this_type,
393
+		EEM_Base $model,
394
+		$requested_version,
395
+		$writing = false
396
+	) {
397
+		$query_param_for_models = array();
398
+		$context = new RestIncomingQueryParamContext($model, $requested_version, $writing);
399
+		foreach ($inputted_query_params_of_this_type as $query_param_key => $query_param_value) {
400
+			$query_param_meta = new RestIncomingQueryParamMetadata($query_param_key, $query_param_value, $context);
401
+			if ($query_param_meta->getField() instanceof EE_Model_Field_Base) {
402
+				$translated_value = $query_param_meta->determineConditionsQueryParameterValue();
403
+				if ((isset($query_param_for_models[ $query_param_meta->getQueryParamKey() ]) && $query_param_meta->isGmtField())
404
+					|| $translated_value === null
405
+				) {
406
+					// they have already provided a non-gmt field, ignore the gmt one. That's what WP core
407
+					// currently does (they might change it though). See https://core.trac.wordpress.org/ticket/39954
408
+					// OR we couldn't create a translated value from their input
409
+					continue;
410
+				}
411
+				$query_param_for_models[ $query_param_meta->getQueryParamKey() ] = $translated_value;
412
+			} else {
413
+				$nested_query_params = $query_param_meta->determineNestedConditionQueryParameters();
414
+				if ($nested_query_params) {
415
+					$query_param_for_models[ $query_param_meta->getQueryParamKey() ] = $nested_query_params;
416
+				}
417
+			}
418
+		}
419
+		return $query_param_for_models;
420
+	}
421
+
422
+	/**
423
+	 * Mostly checks if the last 4 characters are "_gmt", indicating its a
424
+	 * gmt date field name
425
+	 *
426
+	 * @param string $field_name
427
+	 * @return boolean
428
+	 */
429
+	public static function isGmtDateFieldName($field_name)
430
+	{
431
+		return substr(
432
+			ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey($field_name),
433
+			-4,
434
+			4
435
+		) === '_gmt';
436
+	}
437
+
438
+
439
+	/**
440
+	 * Removes the last "_gmt" part of a field name (and if there is no "_gmt" at the end, leave it alone)
441
+	 *
442
+	 * @param string $field_name
443
+	 * @return string
444
+	 */
445
+	public static function removeGmtFromFieldName($field_name)
446
+	{
447
+		if (! ModelDataTranslator::isGmtDateFieldName($field_name)) {
448
+			return $field_name;
449
+		}
450
+		$query_param_sans_stars = ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey(
451
+			$field_name
452
+		);
453
+		$query_param_sans_gmt_and_sans_stars = substr(
454
+			$query_param_sans_stars,
455
+			0,
456
+			strrpos(
457
+				$field_name,
458
+				'_gmt'
459
+			)
460
+		);
461
+		return str_replace($query_param_sans_stars, $query_param_sans_gmt_and_sans_stars, $field_name);
462
+	}
463
+
464
+
465
+	/**
466
+	 * Takes a field name from the REST API and prepares it for the model querying
467
+	 *
468
+	 * @param string $field_name
469
+	 * @return string
470
+	 */
471
+	public static function prepareFieldNameFromJson($field_name)
472
+	{
473
+		if (ModelDataTranslator::isGmtDateFieldName($field_name)) {
474
+			return ModelDataTranslator::removeGmtFromFieldName($field_name);
475
+		}
476
+		return $field_name;
477
+	}
478
+
479
+
480
+	/**
481
+	 * Takes array of field names from REST API and prepares for models
482
+	 *
483
+	 * @param array $field_names
484
+	 * @return array of field names (possibly include model prefixes)
485
+	 */
486
+	public static function prepareFieldNamesFromJson(array $field_names)
487
+	{
488
+		$new_array = array();
489
+		foreach ($field_names as $key => $field_name) {
490
+			$new_array[ $key ] = ModelDataTranslator::prepareFieldNameFromJson($field_name);
491
+		}
492
+		return $new_array;
493
+	}
494
+
495
+
496
+	/**
497
+	 * Takes array where array keys are field names (possibly with model path prefixes)
498
+	 * from the REST API and prepares them for model querying
499
+	 *
500
+	 * @param array $field_names_as_keys
501
+	 * @return array
502
+	 */
503
+	public static function prepareFieldNamesInArrayKeysFromJson(array $field_names_as_keys)
504
+	{
505
+		$new_array = array();
506
+		foreach ($field_names_as_keys as $field_name => $value) {
507
+			$new_array[ ModelDataTranslator::prepareFieldNameFromJson($field_name) ] = $value;
508
+		}
509
+		return $new_array;
510
+	}
511
+
512
+
513
+	/**
514
+	 * Prepares an array of model query params for use in the REST API
515
+	 *
516
+	 * @param array    $model_query_params
517
+	 * @param EEM_Base $model
518
+	 * @param string   $requested_version  eg "4.8.36". If null is provided, defaults to the latest release of the EE4
519
+	 *                                     REST API
520
+	 * @return array which can be passed into the EE4 REST API when querying a model resource
521
+	 * @throws EE_Error
522
+	 */
523
+	public static function prepareQueryParamsForRestApi(
524
+		array $model_query_params,
525
+		EEM_Base $model,
526
+		$requested_version = null
527
+	) {
528
+		if ($requested_version === null) {
529
+			$requested_version = EED_Core_Rest_Api::latest_rest_api_version();
530
+		}
531
+		$rest_query_params = $model_query_params;
532
+		if (isset($model_query_params[0])) {
533
+			$rest_query_params['where'] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
534
+				$model_query_params[0],
535
+				$model,
536
+				$requested_version
537
+			);
538
+			unset($rest_query_params[0]);
539
+		}
540
+		if (isset($model_query_params['having'])) {
541
+			$rest_query_params['having'] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
542
+				$model_query_params['having'],
543
+				$model,
544
+				$requested_version
545
+			);
546
+		}
547
+		return apply_filters(
548
+			'FHEE__EventEspresso\core\libraries\rest_api\Model_Data_Translator__prepare_query_params_for_rest_api',
549
+			$rest_query_params,
550
+			$model_query_params,
551
+			$model,
552
+			$requested_version
553
+		);
554
+	}
555
+
556
+
557
+	/**
558
+	 * Prepares all the sub-conditions query parameters (eg having or where conditions) for use in the rest api
559
+	 *
560
+	 * @param array    $inputted_query_params_of_this_type  eg like the "where" or "having" conditions query params
561
+	 *                                                      @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
562
+	 * @param EEM_Base $model
563
+	 * @param string   $requested_version                   eg "4.8.36"
564
+	 * @return array ready for use in the rest api query params
565
+	 * @throws EE_Error
566
+	 * @throws ObjectDetectedException if somehow a PHP object were in the query params' values,
567
+	 *                                                      (which would be really unusual)
568
+	 */
569
+	public static function prepareConditionsQueryParamsForRestApi(
570
+		$inputted_query_params_of_this_type,
571
+		EEM_Base $model,
572
+		$requested_version
573
+	) {
574
+		$query_param_for_models = array();
575
+		foreach ($inputted_query_params_of_this_type as $query_param_key => $query_param_value) {
576
+			$field = ModelDataTranslator::deduceFieldFromQueryParam(
577
+				ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey($query_param_key),
578
+				$model
579
+			);
580
+			if ($field instanceof EE_Model_Field_Base) {
581
+				// did they specify an operator?
582
+				if (is_array($query_param_value)) {
583
+					$op = $query_param_value[0];
584
+					$translated_value = array($op);
585
+					if (isset($query_param_value[1])) {
586
+						$value = $query_param_value[1];
587
+						$translated_value[1] = ModelDataTranslator::prepareFieldValuesForJson(
588
+							$field,
589
+							$value,
590
+							$requested_version
591
+						);
592
+					}
593
+				} else {
594
+					$translated_value = ModelDataTranslator::prepareFieldValueForJson(
595
+						$field,
596
+						$query_param_value,
597
+						$requested_version
598
+					);
599
+				}
600
+				$query_param_for_models[ $query_param_key ] = $translated_value;
601
+			} else {
602
+				// so it's not for a field, assume it's a logic query param key
603
+				$query_param_for_models[ $query_param_key ] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
604
+					$query_param_value,
605
+					$model,
606
+					$requested_version
607
+				);
608
+			}
609
+		}
610
+		return $query_param_for_models;
611
+	}
612
+
613
+
614
+	/**
615
+	 * @param $condition_query_param_key
616
+	 * @return string
617
+	 */
618
+	public static function removeStarsAndAnythingAfterFromConditionQueryParamKey($condition_query_param_key)
619
+	{
620
+		$pos_of_star = strpos($condition_query_param_key, '*');
621
+		if ($pos_of_star === false) {
622
+			return $condition_query_param_key;
623
+		} else {
624
+			$condition_query_param_sans_star = substr($condition_query_param_key, 0, $pos_of_star);
625
+			return $condition_query_param_sans_star;
626
+		}
627
+	}
628
+
629
+
630
+	/**
631
+	 * Takes the input parameter and finds the model field that it indicates.
632
+	 *
633
+	 * @param string   $query_param_name like Registration.Transaction.TXN_ID, Event.Datetime.start_time, or REG_ID
634
+	 * @param EEM_Base $model
635
+	 * @return EE_Model_Field_Base
636
+	 * @throws EE_Error
637
+	 */
638
+	public static function deduceFieldFromQueryParam($query_param_name, EEM_Base $model)
639
+	{
640
+		// ok, now proceed with deducing which part is the model's name, and which is the field's name
641
+		// which will help us find the database table and column
642
+		$query_param_parts = explode('.', $query_param_name);
643
+		if (empty($query_param_parts)) {
644
+			throw new EE_Error(
645
+				sprintf(
646
+					__(
647
+						'_extract_column_name is empty when trying to extract column and table name from %s',
648
+						'event_espresso'
649
+					),
650
+					$query_param_name
651
+				)
652
+			);
653
+		}
654
+		$number_of_parts = count($query_param_parts);
655
+		$last_query_param_part = $query_param_parts[ count($query_param_parts) - 1 ];
656
+		if ($number_of_parts === 1) {
657
+			$field_name = $last_query_param_part;
658
+		} else {// $number_of_parts >= 2
659
+			// the last part is the column name, and there are only 2parts. therefore...
660
+			$field_name = $last_query_param_part;
661
+			$model = \EE_Registry::instance()->load_model($query_param_parts[ $number_of_parts - 2 ]);
662
+		}
663
+		try {
664
+			return $model->field_settings_for($field_name, false);
665
+		} catch (EE_Error $e) {
666
+			return null;
667
+		}
668
+	}
669
+
670
+
671
+	/**
672
+	 * Returns true if $data can be easily represented in JSON.
673
+	 * Basically, objects and resources can't be represented in JSON easily.
674
+	 *
675
+	 * @param mixed $data
676
+	 * @return bool
677
+	 */
678
+	protected static function isRepresentableInJson($data)
679
+	{
680
+		return is_scalar($data)
681
+			   || is_array($data)
682
+			   || is_null($data);
683
+	}
684 684
 }
Please login to merge, or discard this patch.
core/EE_System.core.php 1 patch
Indentation   +1309 added lines, -1309 removed lines patch added patch discarded remove patch
@@ -27,1313 +27,1313 @@
 block discarded – undo
27 27
 final class EE_System implements ResettableInterface
28 28
 {
29 29
 
30
-    /**
31
-     * indicates this is a 'normal' request. Ie, not activation, nor upgrade, nor activation.
32
-     * So examples of this would be a normal GET request on the frontend or backend, or a POST, etc
33
-     */
34
-    const req_type_normal = 0;
35
-
36
-    /**
37
-     * Indicates this is a brand new installation of EE so we should install
38
-     * tables and default data etc
39
-     */
40
-    const req_type_new_activation = 1;
41
-
42
-    /**
43
-     * we've detected that EE has been reactivated (or EE was activated during maintenance mode,
44
-     * and we just exited maintenance mode). We MUST check the database is setup properly
45
-     * and that default data is setup too
46
-     */
47
-    const req_type_reactivation = 2;
48
-
49
-    /**
50
-     * indicates that EE has been upgraded since its previous request.
51
-     * We may have data migration scripts to call and will want to trigger maintenance mode
52
-     */
53
-    const req_type_upgrade = 3;
54
-
55
-    /**
56
-     * TODO  will detect that EE has been DOWNGRADED. We probably don't want to run in this case...
57
-     */
58
-    const req_type_downgrade = 4;
59
-
60
-    /**
61
-     * @deprecated since version 4.6.0.dev.006
62
-     * Now whenever a new_activation is detected the request type is still just
63
-     * new_activation (same for reactivation, upgrade, downgrade etc), but if we'r ein maintenance mode
64
-     * EE_System::initialize_db_if_no_migrations_required and EE_Addon::initialize_db_if_no_migrations_required
65
-     * will instead enqueue that EE plugin's db initialization for when we're taken out of maintenance mode.
66
-     * (Specifically, when the migration manager indicates migrations are finished
67
-     * EE_Data_Migration_Manager::initialize_db_for_enqueued_ee_plugins() will be called)
68
-     */
69
-    const req_type_activation_but_not_installed = 5;
70
-
71
-    /**
72
-     * option prefix for recording the activation history (like core's "espresso_db_update") of addons
73
-     */
74
-    const addon_activation_history_option_prefix = 'ee_addon_activation_history_';
75
-
76
-    /**
77
-     * @var EE_System $_instance
78
-     */
79
-    private static $_instance;
80
-
81
-    /**
82
-     * @var EE_Registry $registry
83
-     */
84
-    private $registry;
85
-
86
-    /**
87
-     * @var LoaderInterface $loader
88
-     */
89
-    private $loader;
90
-
91
-    /**
92
-     * @var EE_Capabilities $capabilities
93
-     */
94
-    private $capabilities;
95
-
96
-    /**
97
-     * @var RequestInterface $request
98
-     */
99
-    private $request;
100
-
101
-    /**
102
-     * @var EE_Maintenance_Mode $maintenance_mode
103
-     */
104
-    private $maintenance_mode;
105
-
106
-    /**
107
-     * Stores which type of request this is, options being one of the constants on EE_System starting with req_type_*.
108
-     * It can be a brand-new activation, a reactivation, an upgrade, a downgrade, or a normal request.
109
-     *
110
-     * @var int $_req_type
111
-     */
112
-    private $_req_type;
113
-
114
-    /**
115
-     * Whether or not there was a non-micro version change in EE core version during this request
116
-     *
117
-     * @var boolean $_major_version_change
118
-     */
119
-    private $_major_version_change = false;
120
-
121
-    /**
122
-     * A Context DTO dedicated solely to identifying the current request type.
123
-     *
124
-     * @var RequestTypeContextCheckerInterface $request_type
125
-     */
126
-    private $request_type;
127
-
128
-
129
-    /**
130
-     * @singleton method used to instantiate class object
131
-     * @param EE_Registry|null         $registry
132
-     * @param LoaderInterface|null     $loader
133
-     * @param RequestInterface|null    $request
134
-     * @param EE_Maintenance_Mode|null $maintenance_mode
135
-     * @return EE_System
136
-     */
137
-    public static function instance(
138
-        EE_Registry $registry = null,
139
-        LoaderInterface $loader = null,
140
-        RequestInterface $request = null,
141
-        EE_Maintenance_Mode $maintenance_mode = null
142
-    ) {
143
-        // check if class object is instantiated
144
-        if (! self::$_instance instanceof EE_System) {
145
-            self::$_instance = new self($registry, $loader, $request, $maintenance_mode);
146
-        }
147
-        return self::$_instance;
148
-    }
149
-
150
-
151
-    /**
152
-     * resets the instance and returns it
153
-     *
154
-     * @return EE_System
155
-     */
156
-    public static function reset()
157
-    {
158
-        self::$_instance->_req_type = null;
159
-        // make sure none of the old hooks are left hanging around
160
-        remove_all_actions('AHEE__EE_System__perform_activations_upgrades_and_migrations');
161
-        // we need to reset the migration manager in order for it to detect DMSs properly
162
-        EE_Data_Migration_Manager::reset();
163
-        self::instance()->detect_activations_or_upgrades();
164
-        self::instance()->perform_activations_upgrades_and_migrations();
165
-        return self::instance();
166
-    }
167
-
168
-
169
-    /**
170
-     * sets hooks for running rest of system
171
-     * provides "AHEE__EE_System__construct__complete" hook for EE Addons to use as their starting point
172
-     * starting EE Addons from any other point may lead to problems
173
-     *
174
-     * @param EE_Registry         $registry
175
-     * @param LoaderInterface     $loader
176
-     * @param RequestInterface    $request
177
-     * @param EE_Maintenance_Mode $maintenance_mode
178
-     */
179
-    private function __construct(
180
-        EE_Registry $registry,
181
-        LoaderInterface $loader,
182
-        RequestInterface $request,
183
-        EE_Maintenance_Mode $maintenance_mode
184
-    ) {
185
-        $this->registry = $registry;
186
-        $this->loader = $loader;
187
-        $this->request = $request;
188
-        $this->maintenance_mode = $maintenance_mode;
189
-        do_action('AHEE__EE_System__construct__begin', $this);
190
-        add_action(
191
-            'AHEE__EE_Bootstrap__load_espresso_addons',
192
-            array($this, 'loadCapabilities'),
193
-            5
194
-        );
195
-        add_action(
196
-            'AHEE__EE_Bootstrap__load_espresso_addons',
197
-            array($this, 'loadCommandBus'),
198
-            7
199
-        );
200
-        add_action(
201
-            'AHEE__EE_Bootstrap__load_espresso_addons',
202
-            array($this, 'loadPluginApi'),
203
-            9
204
-        );
205
-        // allow addons to load first so that they can register autoloaders, set hooks for running DMS's, etc
206
-        add_action(
207
-            'AHEE__EE_Bootstrap__load_espresso_addons',
208
-            array($this, 'load_espresso_addons')
209
-        );
210
-        // when an ee addon is activated, we want to call the core hook(s) again
211
-        // because the newly-activated addon didn't get a chance to run at all
212
-        add_action('activate_plugin', array($this, 'load_espresso_addons'), 1);
213
-        // detect whether install or upgrade
214
-        add_action(
215
-            'AHEE__EE_Bootstrap__detect_activations_or_upgrades',
216
-            array($this, 'detect_activations_or_upgrades'),
217
-            3
218
-        );
219
-        // load EE_Config, EE_Textdomain, etc
220
-        add_action(
221
-            'AHEE__EE_Bootstrap__load_core_configuration',
222
-            array($this, 'load_core_configuration'),
223
-            5
224
-        );
225
-        // load specifications for matching routes to current request
226
-        add_action(
227
-            'AHEE__EE_Bootstrap__load_core_configuration',
228
-            array($this, 'loadRouteMatchSpecifications')
229
-        );
230
-        // load EE_Config, EE_Textdomain, etc
231
-        add_action(
232
-            'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets',
233
-            array($this, 'register_shortcodes_modules_and_widgets'),
234
-            7
235
-        );
236
-        // you wanna get going? I wanna get going... let's get going!
237
-        add_action(
238
-            'AHEE__EE_Bootstrap__brew_espresso',
239
-            array($this, 'brew_espresso'),
240
-            9
241
-        );
242
-        // other housekeeping
243
-        // exclude EE critical pages from wp_list_pages
244
-        add_filter(
245
-            'wp_list_pages_excludes',
246
-            array($this, 'remove_pages_from_wp_list_pages'),
247
-            10
248
-        );
249
-        // ALL EE Addons should use the following hook point to attach their initial setup too
250
-        // it's extremely important for EE Addons to register any class autoloaders so that they can be available when the EE_Config loads
251
-        do_action('AHEE__EE_System__construct__complete', $this);
252
-    }
253
-
254
-
255
-    /**
256
-     * load and setup EE_Capabilities
257
-     *
258
-     * @return void
259
-     * @throws EE_Error
260
-     */
261
-    public function loadCapabilities()
262
-    {
263
-        $this->capabilities = $this->loader->getShared('EE_Capabilities');
264
-        add_action(
265
-            'AHEE__EE_Capabilities__init_caps__before_initialization',
266
-            function () {
267
-                LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager');
268
-            }
269
-        );
270
-    }
271
-
272
-
273
-    /**
274
-     * create and cache the CommandBus, and also add middleware
275
-     * The CapChecker middleware requires the use of EE_Capabilities
276
-     * which is why we need to load the CommandBus after Caps are set up
277
-     *
278
-     * @return void
279
-     * @throws EE_Error
280
-     */
281
-    public function loadCommandBus()
282
-    {
283
-        $this->loader->getShared(
284
-            'CommandBusInterface',
285
-            array(
286
-                null,
287
-                apply_filters(
288
-                    'FHEE__EE_Load_Espresso_Core__handle_request__CommandBus_middleware',
289
-                    array(
290
-                        $this->loader->getShared('EventEspresso\core\services\commands\middleware\CapChecker'),
291
-                        $this->loader->getShared('EventEspresso\core\services\commands\middleware\AddActionHook'),
292
-                    )
293
-                ),
294
-            )
295
-        );
296
-    }
297
-
298
-
299
-    /**
300
-     * @return void
301
-     * @throws EE_Error
302
-     */
303
-    public function loadPluginApi()
304
-    {
305
-        // set autoloaders for all of the classes implementing EEI_Plugin_API
306
-        // which provide helpers for EE plugin authors to more easily register certain components with EE.
307
-        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
308
-        $this->loader->getShared('EE_Request_Handler');
309
-    }
310
-
311
-
312
-    /**
313
-     * @param string $addon_name
314
-     * @param string $version_constant
315
-     * @param string $min_version_required
316
-     * @param string $load_callback
317
-     * @param string $plugin_file_constant
318
-     * @return void
319
-     */
320
-    private function deactivateIncompatibleAddon(
321
-        $addon_name,
322
-        $version_constant,
323
-        $min_version_required,
324
-        $load_callback,
325
-        $plugin_file_constant
326
-    ) {
327
-        if (! defined($version_constant)) {
328
-            return;
329
-        }
330
-        $addon_version = constant($version_constant);
331
-        if ($addon_version && version_compare($addon_version, $min_version_required, '<')) {
332
-            remove_action('AHEE__EE_System__load_espresso_addons', $load_callback);
333
-            if (! function_exists('deactivate_plugins')) {
334
-                require_once ABSPATH . 'wp-admin/includes/plugin.php';
335
-            }
336
-            deactivate_plugins(plugin_basename(constant($plugin_file_constant)));
337
-            unset($_GET['activate'], $_REQUEST['activate'], $_GET['activate-multi'], $_REQUEST['activate-multi']);
338
-            EE_Error::add_error(
339
-                sprintf(
340
-                    esc_html__(
341
-                        'We\'re sorry, but the Event Espresso %1$s addon was deactivated because version %2$s or higher is required with this version of Event Espresso core.',
342
-                        'event_espresso'
343
-                    ),
344
-                    $addon_name,
345
-                    $min_version_required
346
-                ),
347
-                __FILE__,
348
-                __FUNCTION__ . "({$addon_name})",
349
-                __LINE__
350
-            );
351
-            EE_Error::get_notices(false, true);
352
-        }
353
-    }
354
-
355
-
356
-    /**
357
-     * load_espresso_addons
358
-     * allow addons to load first so that they can set hooks for running DMS's, etc
359
-     * this is hooked into both:
360
-     *    'AHEE__EE_Bootstrap__load_core_configuration'
361
-     *        which runs during the WP 'plugins_loaded' action at priority 5
362
-     *    and the WP 'activate_plugin' hook point
363
-     *
364
-     * @access public
365
-     * @return void
366
-     */
367
-    public function load_espresso_addons()
368
-    {
369
-        $this->deactivateIncompatibleAddon(
370
-            'Wait Lists',
371
-            'EE_WAIT_LISTS_VERSION',
372
-            '1.0.0.beta.074',
373
-            'load_espresso_wait_lists',
374
-            'EE_WAIT_LISTS_PLUGIN_FILE'
375
-        );
376
-        $this->deactivateIncompatibleAddon(
377
-            'Automated Upcoming Event Notifications',
378
-            'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_VERSION',
379
-            '1.0.0.beta.091',
380
-            'load_espresso_automated_upcoming_event_notification',
381
-            'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_PLUGIN_FILE'
382
-        );
383
-        do_action('AHEE__EE_System__load_espresso_addons');
384
-        // if the WP API basic auth plugin isn't already loaded, load it now.
385
-        // We want it for mobile apps. Just include the entire plugin
386
-        // also, don't load the basic auth when a plugin is getting activated, because
387
-        // it could be the basic auth plugin, and it doesn't check if its methods are already defined
388
-        // and causes a fatal error
389
-        if (($this->request->isWordPressApi() || $this->request->isApi())
390
-            && $this->request->getRequestParam('activate') !== 'true'
391
-            && ! function_exists('json_basic_auth_handler')
392
-            && ! function_exists('json_basic_auth_error')
393
-            && ! in_array(
394
-                $this->request->getRequestParam('action'),
395
-                array('activate', 'activate-selected'),
396
-                true
397
-            )
398
-        ) {
399
-            include_once EE_THIRD_PARTY . 'wp-api-basic-auth' . DS . 'basic-auth.php';
400
-        }
401
-        do_action('AHEE__EE_System__load_espresso_addons__complete');
402
-    }
403
-
404
-
405
-    /**
406
-     * detect_activations_or_upgrades
407
-     * Checks for activation or upgrade of core first;
408
-     * then also checks if any registered addons have been activated or upgraded
409
-     * This is hooked into 'AHEE__EE_Bootstrap__detect_activations_or_upgrades'
410
-     * which runs during the WP 'plugins_loaded' action at priority 3
411
-     *
412
-     * @access public
413
-     * @return void
414
-     */
415
-    public function detect_activations_or_upgrades()
416
-    {
417
-        // first off: let's make sure to handle core
418
-        $this->detect_if_activation_or_upgrade();
419
-        foreach ($this->registry->addons as $addon) {
420
-            if ($addon instanceof EE_Addon) {
421
-                // detect teh request type for that addon
422
-                $addon->detect_activation_or_upgrade();
423
-            }
424
-        }
425
-    }
426
-
427
-
428
-    /**
429
-     * detect_if_activation_or_upgrade
430
-     * Takes care of detecting whether this is a brand new install or code upgrade,
431
-     * and either setting up the DB or setting up maintenance mode etc.
432
-     *
433
-     * @access public
434
-     * @return void
435
-     */
436
-    public function detect_if_activation_or_upgrade()
437
-    {
438
-        do_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin');
439
-        // check if db has been updated, or if its a brand-new installation
440
-        $espresso_db_update = $this->fix_espresso_db_upgrade_option();
441
-        $request_type = $this->detect_req_type($espresso_db_update);
442
-        // EEH_Debug_Tools::printr( $request_type, '$request_type', __FILE__, __LINE__ );
443
-        switch ($request_type) {
444
-            case EE_System::req_type_new_activation:
445
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__new_activation');
446
-                $this->_handle_core_version_change($espresso_db_update);
447
-                break;
448
-            case EE_System::req_type_reactivation:
449
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__reactivation');
450
-                $this->_handle_core_version_change($espresso_db_update);
451
-                break;
452
-            case EE_System::req_type_upgrade:
453
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__upgrade');
454
-                // migrations may be required now that we've upgraded
455
-                $this->maintenance_mode->set_maintenance_mode_if_db_old();
456
-                $this->_handle_core_version_change($espresso_db_update);
457
-                break;
458
-            case EE_System::req_type_downgrade:
459
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__downgrade');
460
-                // its possible migrations are no longer required
461
-                $this->maintenance_mode->set_maintenance_mode_if_db_old();
462
-                $this->_handle_core_version_change($espresso_db_update);
463
-                break;
464
-            case EE_System::req_type_normal:
465
-            default:
466
-                break;
467
-        }
468
-        do_action('AHEE__EE_System__detect_if_activation_or_upgrade__complete');
469
-    }
470
-
471
-
472
-    /**
473
-     * Updates the list of installed versions and sets hooks for
474
-     * initializing the database later during the request
475
-     *
476
-     * @param array $espresso_db_update
477
-     */
478
-    private function _handle_core_version_change($espresso_db_update)
479
-    {
480
-        $this->update_list_of_installed_versions($espresso_db_update);
481
-        // get ready to verify the DB is ok (provided we aren't in maintenance mode, of course)
482
-        add_action(
483
-            'AHEE__EE_System__perform_activations_upgrades_and_migrations',
484
-            array($this, 'initialize_db_if_no_migrations_required')
485
-        );
486
-    }
487
-
488
-
489
-    /**
490
-     * standardizes the wp option 'espresso_db_upgrade' which actually stores
491
-     * information about what versions of EE have been installed and activated,
492
-     * NOT necessarily the state of the database
493
-     *
494
-     * @param mixed $espresso_db_update           the value of the WordPress option.
495
-     *                                            If not supplied, fetches it from the options table
496
-     * @return array the correct value of 'espresso_db_upgrade', after saving it, if it needed correction
497
-     */
498
-    private function fix_espresso_db_upgrade_option($espresso_db_update = null)
499
-    {
500
-        do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
501
-        if (! $espresso_db_update) {
502
-            $espresso_db_update = get_option('espresso_db_update');
503
-        }
504
-        // check that option is an array
505
-        if (! is_array($espresso_db_update)) {
506
-            // if option is FALSE, then it never existed
507
-            if ($espresso_db_update === false) {
508
-                // make $espresso_db_update an array and save option with autoload OFF
509
-                $espresso_db_update = array();
510
-                add_option('espresso_db_update', $espresso_db_update, '', 'no');
511
-            } else {
512
-                // option is NOT FALSE but also is NOT an array, so make it an array and save it
513
-                $espresso_db_update = array($espresso_db_update => array());
514
-                update_option('espresso_db_update', $espresso_db_update);
515
-            }
516
-        } else {
517
-            $corrected_db_update = array();
518
-            // if IS an array, but is it an array where KEYS are version numbers, and values are arrays?
519
-            foreach ($espresso_db_update as $should_be_version_string => $should_be_array) {
520
-                if (is_int($should_be_version_string) && ! is_array($should_be_array)) {
521
-                    // the key is an int, and the value IS NOT an array
522
-                    // so it must be numerically-indexed, where values are versions installed...
523
-                    // fix it!
524
-                    $version_string = $should_be_array;
525
-                    $corrected_db_update[ $version_string ] = array('unknown-date');
526
-                } else {
527
-                    // ok it checks out
528
-                    $corrected_db_update[ $should_be_version_string ] = $should_be_array;
529
-                }
530
-            }
531
-            $espresso_db_update = $corrected_db_update;
532
-            update_option('espresso_db_update', $espresso_db_update);
533
-        }
534
-        do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__complete', $espresso_db_update);
535
-        return $espresso_db_update;
536
-    }
537
-
538
-
539
-    /**
540
-     * Does the traditional work of setting up the plugin's database and adding default data.
541
-     * If migration script/process did not exist, this is what would happen on every activation/reactivation/upgrade.
542
-     * NOTE: if we're in maintenance mode (which would be the case if we detect there are data
543
-     * migration scripts that need to be run and a version change happens), enqueues core for database initialization,
544
-     * so that it will be done when migrations are finished
545
-     *
546
-     * @param boolean $initialize_addons_too if true, we double-check addons' database tables etc too;
547
-     * @param boolean $verify_schema         if true will re-check the database tables have the correct schema.
548
-     *                                       This is a resource-intensive job
549
-     *                                       so we prefer to only do it when necessary
550
-     * @return void
551
-     * @throws EE_Error
552
-     */
553
-    public function initialize_db_if_no_migrations_required($initialize_addons_too = false, $verify_schema = true)
554
-    {
555
-        $request_type = $this->detect_req_type();
556
-        // only initialize system if we're not in maintenance mode.
557
-        if ($this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) {
558
-            /** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
559
-            $rewrite_rules = $this->loader->getShared(
560
-                'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
561
-            );
562
-            $rewrite_rules->flush();
563
-            if ($verify_schema) {
564
-                EEH_Activation::initialize_db_and_folders();
565
-            }
566
-            EEH_Activation::initialize_db_content();
567
-            EEH_Activation::system_initialization();
568
-            if ($initialize_addons_too) {
569
-                $this->initialize_addons();
570
-            }
571
-        } else {
572
-            EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for('Core');
573
-        }
574
-        if ($request_type === EE_System::req_type_new_activation
575
-            || $request_type === EE_System::req_type_reactivation
576
-            || (
577
-                $request_type === EE_System::req_type_upgrade
578
-                && $this->is_major_version_change()
579
-            )
580
-        ) {
581
-            add_action('AHEE__EE_System__initialize_last', array($this, 'redirect_to_about_ee'), 9);
582
-        }
583
-    }
584
-
585
-
586
-    /**
587
-     * Initializes the db for all registered addons
588
-     *
589
-     * @throws EE_Error
590
-     */
591
-    public function initialize_addons()
592
-    {
593
-        // foreach registered addon, make sure its db is up-to-date too
594
-        foreach ($this->registry->addons as $addon) {
595
-            if ($addon instanceof EE_Addon) {
596
-                $addon->initialize_db_if_no_migrations_required();
597
-            }
598
-        }
599
-    }
600
-
601
-
602
-    /**
603
-     * Adds the current code version to the saved wp option which stores a list of all ee versions ever installed.
604
-     *
605
-     * @param    array  $version_history
606
-     * @param    string $current_version_to_add version to be added to the version history
607
-     * @return    boolean success as to whether or not this option was changed
608
-     */
609
-    public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
610
-    {
611
-        if (! $version_history) {
612
-            $version_history = $this->fix_espresso_db_upgrade_option($version_history);
613
-        }
614
-        if ($current_version_to_add === null) {
615
-            $current_version_to_add = espresso_version();
616
-        }
617
-        $version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
618
-        // re-save
619
-        return update_option('espresso_db_update', $version_history);
620
-    }
621
-
622
-
623
-    /**
624
-     * Detects if the current version indicated in the has existed in the list of
625
-     * previously-installed versions of EE (espresso_db_update). Does NOT modify it (ie, no side-effect)
626
-     *
627
-     * @param array $espresso_db_update array from the wp option stored under the name 'espresso_db_update'.
628
-     *                                  If not supplied, fetches it from the options table.
629
-     *                                  Also, caches its result so later parts of the code can also know whether
630
-     *                                  there's been an update or not. This way we can add the current version to
631
-     *                                  espresso_db_update, but still know if this is a new install or not
632
-     * @return int one of the constants on EE_System::req_type_
633
-     */
634
-    public function detect_req_type($espresso_db_update = null)
635
-    {
636
-        if ($this->_req_type === null) {
637
-            $espresso_db_update = ! empty($espresso_db_update)
638
-                ? $espresso_db_update
639
-                : $this->fix_espresso_db_upgrade_option();
640
-            $this->_req_type = EE_System::detect_req_type_given_activation_history(
641
-                $espresso_db_update,
642
-                'ee_espresso_activation',
643
-                espresso_version()
644
-            );
645
-            $this->_major_version_change = $this->_detect_major_version_change($espresso_db_update);
646
-            $this->request->setIsActivation($this->_req_type !== EE_System::req_type_normal);
647
-        }
648
-        return $this->_req_type;
649
-    }
650
-
651
-
652
-    /**
653
-     * Returns whether or not there was a non-micro version change (ie, change in either
654
-     * the first or second number in the version. Eg 4.9.0.rc.001 to 4.10.0.rc.000,
655
-     * but not 4.9.0.rc.0001 to 4.9.1.rc.0001
656
-     *
657
-     * @param $activation_history
658
-     * @return bool
659
-     */
660
-    private function _detect_major_version_change($activation_history)
661
-    {
662
-        $previous_version = EE_System::_get_most_recently_active_version_from_activation_history($activation_history);
663
-        $previous_version_parts = explode('.', $previous_version);
664
-        $current_version_parts = explode('.', espresso_version());
665
-        return isset($previous_version_parts[0], $previous_version_parts[1], $current_version_parts[0], $current_version_parts[1])
666
-               && ($previous_version_parts[0] !== $current_version_parts[0]
667
-                   || $previous_version_parts[1] !== $current_version_parts[1]
668
-               );
669
-    }
670
-
671
-
672
-    /**
673
-     * Returns true if either the major or minor version of EE changed during this request.
674
-     * Eg 4.9.0.rc.001 to 4.10.0.rc.000, but not 4.9.0.rc.0001 to 4.9.1.rc.0001
675
-     *
676
-     * @return bool
677
-     */
678
-    public function is_major_version_change()
679
-    {
680
-        return $this->_major_version_change;
681
-    }
682
-
683
-
684
-    /**
685
-     * Determines the request type for any ee addon, given three piece of info: the current array of activation
686
-     * histories (for core that' 'espresso_db_update' wp option); the name of the WordPress option which is temporarily
687
-     * set upon activation of the plugin (for core it's 'ee_espresso_activation'); and the version that this plugin was
688
-     * just activated to (for core that will always be espresso_version())
689
-     *
690
-     * @param array  $activation_history_for_addon     the option's value which stores the activation history for this
691
-     *                                                 ee plugin. for core that's 'espresso_db_update'
692
-     * @param string $activation_indicator_option_name the name of the WordPress option that is temporarily set to
693
-     *                                                 indicate that this plugin was just activated
694
-     * @param string $version_to_upgrade_to            the version that was just upgraded to (for core that will be
695
-     *                                                 espresso_version())
696
-     * @return int one of the constants on EE_System::req_type_*
697
-     */
698
-    public static function detect_req_type_given_activation_history(
699
-        $activation_history_for_addon,
700
-        $activation_indicator_option_name,
701
-        $version_to_upgrade_to
702
-    ) {
703
-        $version_is_higher = self::_new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to);
704
-        if ($activation_history_for_addon) {
705
-            // it exists, so this isn't a completely new install
706
-            // check if this version already in that list of previously installed versions
707
-            if (! isset($activation_history_for_addon[ $version_to_upgrade_to ])) {
708
-                // it a version we haven't seen before
709
-                if ($version_is_higher === 1) {
710
-                    $req_type = EE_System::req_type_upgrade;
711
-                } else {
712
-                    $req_type = EE_System::req_type_downgrade;
713
-                }
714
-                delete_option($activation_indicator_option_name);
715
-            } else {
716
-                // its not an update. maybe a reactivation?
717
-                if (get_option($activation_indicator_option_name, false)) {
718
-                    if ($version_is_higher === -1) {
719
-                        $req_type = EE_System::req_type_downgrade;
720
-                    } elseif ($version_is_higher === 0) {
721
-                        // we've seen this version before, but it's an activation. must be a reactivation
722
-                        $req_type = EE_System::req_type_reactivation;
723
-                    } else {// $version_is_higher === 1
724
-                        $req_type = EE_System::req_type_upgrade;
725
-                    }
726
-                    delete_option($activation_indicator_option_name);
727
-                } else {
728
-                    // we've seen this version before and the activation indicate doesn't show it was just activated
729
-                    if ($version_is_higher === -1) {
730
-                        $req_type = EE_System::req_type_downgrade;
731
-                    } elseif ($version_is_higher === 0) {
732
-                        // we've seen this version before and it's not an activation. its normal request
733
-                        $req_type = EE_System::req_type_normal;
734
-                    } else {// $version_is_higher === 1
735
-                        $req_type = EE_System::req_type_upgrade;
736
-                    }
737
-                }
738
-            }
739
-        } else {
740
-            // brand new install
741
-            $req_type = EE_System::req_type_new_activation;
742
-            delete_option($activation_indicator_option_name);
743
-        }
744
-        return $req_type;
745
-    }
746
-
747
-
748
-    /**
749
-     * Detects if the $version_to_upgrade_to is higher than the most recent version in
750
-     * the $activation_history_for_addon
751
-     *
752
-     * @param array  $activation_history_for_addon (keys are versions, values are arrays of times activated,
753
-     *                                             sometimes containing 'unknown-date'
754
-     * @param string $version_to_upgrade_to        (current version)
755
-     * @return int results of version_compare( $version_to_upgrade_to, $most_recently_active_version ).
756
-     *                                             ie, -1 if $version_to_upgrade_to is LOWER (downgrade);
757
-     *                                             0 if $version_to_upgrade_to MATCHES (reactivation or normal request);
758
-     *                                             1 if $version_to_upgrade_to is HIGHER (upgrade) ;
759
-     */
760
-    private static function _new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to)
761
-    {
762
-        // find the most recently-activated version
763
-        $most_recently_active_version =
764
-            EE_System::_get_most_recently_active_version_from_activation_history($activation_history_for_addon);
765
-        return version_compare($version_to_upgrade_to, $most_recently_active_version);
766
-    }
767
-
768
-
769
-    /**
770
-     * Gets the most recently active version listed in the activation history,
771
-     * and if none are found (ie, it's a brand new install) returns '0.0.0.dev.000'.
772
-     *
773
-     * @param array $activation_history  (keys are versions, values are arrays of times activated,
774
-     *                                   sometimes containing 'unknown-date'
775
-     * @return string
776
-     */
777
-    private static function _get_most_recently_active_version_from_activation_history($activation_history)
778
-    {
779
-        $most_recently_active_version_activation = '1970-01-01 00:00:00';
780
-        $most_recently_active_version = '0.0.0.dev.000';
781
-        if (is_array($activation_history)) {
782
-            foreach ($activation_history as $version => $times_activated) {
783
-                // check there is a record of when this version was activated. Otherwise,
784
-                // mark it as unknown
785
-                if (! $times_activated) {
786
-                    $times_activated = array('unknown-date');
787
-                }
788
-                if (is_string($times_activated)) {
789
-                    $times_activated = array($times_activated);
790
-                }
791
-                foreach ($times_activated as $an_activation) {
792
-                    if ($an_activation !== 'unknown-date'
793
-                        && $an_activation
794
-                           > $most_recently_active_version_activation) {
795
-                        $most_recently_active_version = $version;
796
-                        $most_recently_active_version_activation = $an_activation === 'unknown-date'
797
-                            ? '1970-01-01 00:00:00'
798
-                            : $an_activation;
799
-                    }
800
-                }
801
-            }
802
-        }
803
-        return $most_recently_active_version;
804
-    }
805
-
806
-
807
-    /**
808
-     * This redirects to the about EE page after activation
809
-     *
810
-     * @return void
811
-     */
812
-    public function redirect_to_about_ee()
813
-    {
814
-        $notices = EE_Error::get_notices(false);
815
-        // if current user is an admin and it's not an ajax or rest request
816
-        if (! isset($notices['errors'])
817
-            && $this->request->isAdmin()
818
-            && apply_filters(
819
-                'FHEE__EE_System__redirect_to_about_ee__do_redirect',
820
-                $this->capabilities->current_user_can('manage_options', 'espresso_about_default')
821
-            )
822
-        ) {
823
-            $query_params = array('page' => 'espresso_about');
824
-            if (EE_System::instance()->detect_req_type() === EE_System::req_type_new_activation) {
825
-                $query_params['new_activation'] = true;
826
-            }
827
-            if (EE_System::instance()->detect_req_type() === EE_System::req_type_reactivation) {
828
-                $query_params['reactivation'] = true;
829
-            }
830
-            $url = add_query_arg($query_params, admin_url('admin.php'));
831
-            wp_safe_redirect($url);
832
-            exit();
833
-        }
834
-    }
835
-
836
-
837
-    /**
838
-     * load_core_configuration
839
-     * this is hooked into 'AHEE__EE_Bootstrap__load_core_configuration'
840
-     * which runs during the WP 'plugins_loaded' action at priority 5
841
-     *
842
-     * @return void
843
-     * @throws ReflectionException
844
-     * @throws Exception
845
-     */
846
-    public function load_core_configuration()
847
-    {
848
-        do_action('AHEE__EE_System__load_core_configuration__begin', $this);
849
-        $this->loader->getShared('EE_Load_Textdomain');
850
-        // load textdomain
851
-        EE_Load_Textdomain::load_textdomain();
852
-        // load and setup EE_Config and EE_Network_Config
853
-        $config = $this->loader->getShared('EE_Config');
854
-        $this->loader->getShared('EE_Network_Config');
855
-        // setup autoloaders
856
-        // enable logging?
857
-        if ($config->admin->use_full_logging) {
858
-            $this->loader->getShared('EE_Log');
859
-        }
860
-        // check for activation errors
861
-        $activation_errors = get_option('ee_plugin_activation_errors', false);
862
-        if ($activation_errors) {
863
-            EE_Error::add_error($activation_errors, __FILE__, __FUNCTION__, __LINE__);
864
-            update_option('ee_plugin_activation_errors', false);
865
-        }
866
-        // get model names
867
-        $this->_parse_model_names();
868
-        // load caf stuff a chance to play during the activation process too.
869
-        $this->_maybe_brew_regular();
870
-        // configure custom post type definitions
871
-        $this->loader->getShared('EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions');
872
-        $this->loader->getShared('EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions');
873
-        do_action('AHEE__EE_System__load_core_configuration__complete', $this);
874
-    }
875
-
876
-
877
-    /**
878
-     * cycles through all of the models/*.model.php files, and assembles an array of model names
879
-     *
880
-     * @return void
881
-     * @throws ReflectionException
882
-     */
883
-    private function _parse_model_names()
884
-    {
885
-        // get all the files in the EE_MODELS folder that end in .model.php
886
-        $models = glob(EE_MODELS . '*.model.php');
887
-        $model_names = array();
888
-        $non_abstract_db_models = array();
889
-        foreach ($models as $model) {
890
-            // get model classname
891
-            $classname = EEH_File::get_classname_from_filepath_with_standard_filename($model);
892
-            $short_name = str_replace('EEM_', '', $classname);
893
-            $reflectionClass = new ReflectionClass($classname);
894
-            if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
895
-                $non_abstract_db_models[ $short_name ] = $classname;
896
-            }
897
-            $model_names[ $short_name ] = $classname;
898
-        }
899
-        $this->registry->models = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
900
-        $this->registry->non_abstract_db_models = apply_filters(
901
-            'FHEE__EE_System__parse_implemented_model_names',
902
-            $non_abstract_db_models
903
-        );
904
-    }
905
-
906
-
907
-    /**
908
-     * The purpose of this method is to simply check for a file named "caffeinated/brewing_regular.php" for any hooks
909
-     * that need to be setup before our EE_System launches.
910
-     *
911
-     * @return void
912
-     * @throws DomainException
913
-     * @throws InvalidArgumentException
914
-     * @throws InvalidDataTypeException
915
-     * @throws InvalidInterfaceException
916
-     * @throws InvalidClassException
917
-     * @throws InvalidFilePathException
918
-     */
919
-    private function _maybe_brew_regular()
920
-    {
921
-        /** @var Domain $domain */
922
-        $domain = DomainFactory::getShared(
923
-            new FullyQualifiedName(
924
-                'EventEspresso\core\domain\Domain'
925
-            ),
926
-            array(
927
-                new FilePath(EVENT_ESPRESSO_MAIN_FILE),
928
-                Version::fromString(espresso_version()),
929
-            )
930
-        );
931
-        if ($domain->isCaffeinated()) {
932
-            require_once EE_CAFF_PATH . 'brewing_regular.php';
933
-        }
934
-    }
935
-
936
-
937
-    /**
938
-     * @since 4.9.71.p
939
-     * @throws Exception
940
-     */
941
-    public function loadRouteMatchSpecifications()
942
-    {
943
-        try {
944
-            $this->loader->getShared(
945
-                'EventEspresso\core\services\route_match\RouteMatchSpecificationManager'
946
-            );
947
-        } catch (Exception $exception) {
948
-            new ExceptionStackTraceDisplay($exception);
949
-        }
950
-        do_action('AHEE__EE_System__loadRouteMatchSpecifications');
951
-    }
952
-
953
-
954
-    /**
955
-     * register_shortcodes_modules_and_widgets
956
-     * generate lists of shortcodes and modules, then verify paths and classes
957
-     * This is hooked into 'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets'
958
-     * which runs during the WP 'plugins_loaded' action at priority 7
959
-     *
960
-     * @access public
961
-     * @return void
962
-     * @throws Exception
963
-     */
964
-    public function register_shortcodes_modules_and_widgets()
965
-    {
966
-        if ($this->request->isFrontend() || $this->request->isIframe() || $this->request->isAjax()) {
967
-            try {
968
-                // load, register, and add shortcodes the new way
969
-                $this->loader->getShared(
970
-                    'EventEspresso\core\services\shortcodes\ShortcodesManager',
971
-                    array(
972
-                        // and the old way, but we'll put it under control of the new system
973
-                        EE_Config::getLegacyShortcodesManager(),
974
-                    )
975
-                );
976
-            } catch (Exception $exception) {
977
-                new ExceptionStackTraceDisplay($exception);
978
-            }
979
-        }
980
-        do_action('AHEE__EE_System__register_shortcodes_modules_and_widgets');
981
-        // check for addons using old hook point
982
-        if (has_action('AHEE__EE_System__register_shortcodes_modules_and_addons')) {
983
-            $this->_incompatible_addon_error();
984
-        }
985
-    }
986
-
987
-
988
-    /**
989
-     * _incompatible_addon_error
990
-     *
991
-     * @access public
992
-     * @return void
993
-     */
994
-    private function _incompatible_addon_error()
995
-    {
996
-        // get array of classes hooking into here
997
-        $class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook(
998
-            'AHEE__EE_System__register_shortcodes_modules_and_addons'
999
-        );
1000
-        if (! empty($class_names)) {
1001
-            $msg = __(
1002
-                'The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
1003
-                'event_espresso'
1004
-            );
1005
-            $msg .= '<ul>';
1006
-            foreach ($class_names as $class_name) {
1007
-                $msg .= '<li><b>Event Espresso - '
1008
-                        . str_replace(
1009
-                            array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'),
1010
-                            '',
1011
-                            $class_name
1012
-                        ) . '</b></li>';
1013
-            }
1014
-            $msg .= '</ul>';
1015
-            $msg .= __(
1016
-                'Compatibility issues can be avoided and/or resolved by keeping addons and plugins updated to the latest version.',
1017
-                'event_espresso'
1018
-            );
1019
-            // save list of incompatible addons to wp-options for later use
1020
-            add_option('ee_incompatible_addons', $class_names, '', 'no');
1021
-            if (is_admin()) {
1022
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1023
-            }
1024
-        }
1025
-    }
1026
-
1027
-
1028
-    /**
1029
-     * brew_espresso
1030
-     * begins the process of setting hooks for initializing EE in the correct order
1031
-     * This is happening on the 'AHEE__EE_Bootstrap__brew_espresso' hook point
1032
-     * which runs during the WP 'plugins_loaded' action at priority 9
1033
-     *
1034
-     * @return void
1035
-     */
1036
-    public function brew_espresso()
1037
-    {
1038
-        do_action('AHEE__EE_System__brew_espresso__begin', $this);
1039
-        // load some final core systems
1040
-        add_action('init', array($this, 'set_hooks_for_core'), 1);
1041
-        add_action('init', array($this, 'perform_activations_upgrades_and_migrations'), 3);
1042
-        add_action('init', array($this, 'load_CPTs_and_session'), 5);
1043
-        add_action('init', array($this, 'load_controllers'), 7);
1044
-        add_action('init', array($this, 'core_loaded_and_ready'), 9);
1045
-        add_action('init', array($this, 'initialize'), 10);
1046
-        add_action('init', array($this, 'initialize_last'), 100);
1047
-        if (is_admin() && apply_filters('FHEE__EE_System__brew_espresso__load_pue', true)) {
1048
-            // pew pew pew
1049
-            $this->loader->getShared('EventEspresso\core\services\licensing\LicenseService');
1050
-            do_action('AHEE__EE_System__brew_espresso__after_pue_init');
1051
-        }
1052
-        do_action('AHEE__EE_System__brew_espresso__complete', $this);
1053
-    }
1054
-
1055
-
1056
-    /**
1057
-     *    set_hooks_for_core
1058
-     *
1059
-     * @access public
1060
-     * @return    void
1061
-     * @throws EE_Error
1062
-     */
1063
-    public function set_hooks_for_core()
1064
-    {
1065
-        $this->_deactivate_incompatible_addons();
1066
-        do_action('AHEE__EE_System__set_hooks_for_core');
1067
-        $this->loader->getShared('EventEspresso\core\domain\values\session\SessionLifespan');
1068
-        // caps need to be initialized on every request so that capability maps are set.
1069
-        // @see https://events.codebasehq.com/projects/event-espresso/tickets/8674
1070
-        $this->registry->CAP->init_caps();
1071
-    }
1072
-
1073
-
1074
-    /**
1075
-     * Using the information gathered in EE_System::_incompatible_addon_error,
1076
-     * deactivates any addons considered incompatible with the current version of EE
1077
-     */
1078
-    private function _deactivate_incompatible_addons()
1079
-    {
1080
-        $incompatible_addons = get_option('ee_incompatible_addons', array());
1081
-        if (! empty($incompatible_addons)) {
1082
-            $active_plugins = get_option('active_plugins', array());
1083
-            foreach ($active_plugins as $active_plugin) {
1084
-                foreach ($incompatible_addons as $incompatible_addon) {
1085
-                    if (strpos($active_plugin, $incompatible_addon) !== false) {
1086
-                        unset($_GET['activate']);
1087
-                        espresso_deactivate_plugin($active_plugin);
1088
-                    }
1089
-                }
1090
-            }
1091
-        }
1092
-    }
1093
-
1094
-
1095
-    /**
1096
-     *    perform_activations_upgrades_and_migrations
1097
-     *
1098
-     * @access public
1099
-     * @return    void
1100
-     */
1101
-    public function perform_activations_upgrades_and_migrations()
1102
-    {
1103
-        do_action('AHEE__EE_System__perform_activations_upgrades_and_migrations');
1104
-    }
1105
-
1106
-
1107
-    /**
1108
-     * @return void
1109
-     * @throws DomainException
1110
-     */
1111
-    public function load_CPTs_and_session()
1112
-    {
1113
-        do_action('AHEE__EE_System__load_CPTs_and_session__start');
1114
-        /** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies $register_custom_taxonomies */
1115
-        $register_custom_taxonomies = $this->loader->getShared(
1116
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'
1117
-        );
1118
-        $register_custom_taxonomies->registerCustomTaxonomies();
1119
-        /** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes $register_custom_post_types */
1120
-        $register_custom_post_types = $this->loader->getShared(
1121
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'
1122
-        );
1123
-        $register_custom_post_types->registerCustomPostTypes();
1124
-        /** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomyTerms $register_custom_taxonomy_terms */
1125
-        $register_custom_taxonomy_terms = $this->loader->getShared(
1126
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomyTerms'
1127
-        );
1128
-        $register_custom_taxonomy_terms->registerCustomTaxonomyTerms();
1129
-        // load legacy Custom Post Types and Taxonomies
1130
-        $this->loader->getShared('EE_Register_CPTs');
1131
-        do_action('AHEE__EE_System__load_CPTs_and_session__complete');
1132
-    }
1133
-
1134
-
1135
-    /**
1136
-     * load_controllers
1137
-     * this is the best place to load any additional controllers that needs access to EE core.
1138
-     * it is expected that all basic core EE systems, that are not dependant on the current request are loaded at this
1139
-     * time
1140
-     *
1141
-     * @access public
1142
-     * @return void
1143
-     */
1144
-    public function load_controllers()
1145
-    {
1146
-        do_action('AHEE__EE_System__load_controllers__start');
1147
-        // let's get it started
1148
-        if (! $this->maintenance_mode->level()
1149
-            && ($this->request->isFrontend() || $this->request->isFrontAjax())
1150
-        ) {
1151
-            do_action('AHEE__EE_System__load_controllers__load_front_controllers');
1152
-            $this->loader->getShared('EE_Front_Controller');
1153
-        } elseif ($this->request->isAdmin() || $this->request->isAdminAjax()) {
1154
-            do_action('AHEE__EE_System__load_controllers__load_admin_controllers');
1155
-            $this->loader->getShared('EE_Admin');
1156
-        } elseif ($this->request->isWordPressHeartbeat()) {
1157
-            $this->loader->getShared('EventEspresso\core\domain\services\admin\ajax\WordpressHeartbeat');
1158
-        }
1159
-        do_action('AHEE__EE_System__load_controllers__complete');
1160
-    }
1161
-
1162
-
1163
-    /**
1164
-     * core_loaded_and_ready
1165
-     * all of the basic EE core should be loaded at this point and available regardless of M-Mode
1166
-     *
1167
-     * @access public
1168
-     * @return void
1169
-     * @throws Exception
1170
-     */
1171
-    public function core_loaded_and_ready()
1172
-    {
1173
-        if ($this->request->isAdmin()
1174
-            || $this->request->isFrontend()
1175
-            || $this->request->isIframe()
1176
-            || $this->request->isWordPressApi()
1177
-        ) {
1178
-            try {
1179
-                $this->loader->getShared('EventEspresso\core\services\assets\Registry');
1180
-                $this->loader->getShared('EventEspresso\core\domain\services\assets\CoreAssetManager');
1181
-                if ($this->canLoadBlocks()) {
1182
-                    $this->loader->getShared(
1183
-                        'EventEspresso\core\services\editor\BlockRegistrationManager'
1184
-                    );
1185
-                }
1186
-            } catch (Exception $exception) {
1187
-                new ExceptionStackTraceDisplay($exception);
1188
-            }
1189
-        }
1190
-        if ($this->request->isAdmin()
1191
-            || $this->request->isEeAjax()
1192
-            || $this->request->isFrontend()
1193
-        ) {
1194
-            $this->loader->getShared('EE_Session');
1195
-        }
1196
-        // integrate WP_Query with the EE models
1197
-        $this->loader->getShared('EE_CPT_Strategy');
1198
-        do_action('AHEE__EE_System__core_loaded_and_ready');
1199
-        // always load template tags, because it's faster than checking if it's a front-end request, and many page
1200
-        // builders require these even on the front-end
1201
-        require_once EE_PUBLIC . 'template_tags.php';
1202
-        do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
1203
-    }
1204
-
1205
-
1206
-    /**
1207
-     * initialize
1208
-     * this is the best place to begin initializing client code
1209
-     *
1210
-     * @access public
1211
-     * @return void
1212
-     */
1213
-    public function initialize()
1214
-    {
1215
-        do_action('AHEE__EE_System__initialize');
1216
-    }
1217
-
1218
-
1219
-    /**
1220
-     * initialize_last
1221
-     * this is run really late during the WP init hook point, and ensures that mostly everything else that needs to
1222
-     * initialize has done so
1223
-     *
1224
-     * @access public
1225
-     * @return void
1226
-     */
1227
-    public function initialize_last()
1228
-    {
1229
-        do_action('AHEE__EE_System__initialize_last');
1230
-        /** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
1231
-        $rewrite_rules = $this->loader->getShared(
1232
-            'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
1233
-        );
1234
-        $rewrite_rules->flushRewriteRules();
1235
-        add_action('admin_bar_init', array($this, 'addEspressoToolbar'));
1236
-        if (($this->request->isAjax() || $this->request->isAdmin())
1237
-            && $this->maintenance_mode->models_can_query()) {
1238
-            $this->loader->getShared('EventEspresso\core\services\privacy\export\PersonalDataExporterManager');
1239
-            $this->loader->getShared('EventEspresso\core\services\privacy\erasure\PersonalDataEraserManager');
1240
-        }
1241
-    }
1242
-
1243
-
1244
-    /**
1245
-     * @return void
1246
-     * @throws EE_Error
1247
-     */
1248
-    public function addEspressoToolbar()
1249
-    {
1250
-        $this->loader->getShared(
1251
-            'EventEspresso\core\domain\services\admin\AdminToolBar',
1252
-            array($this->registry->CAP)
1253
-        );
1254
-    }
1255
-
1256
-
1257
-    /**
1258
-     * do_not_cache
1259
-     * sets no cache headers and defines no cache constants for WP plugins
1260
-     *
1261
-     * @access public
1262
-     * @return void
1263
-     */
1264
-    public static function do_not_cache()
1265
-    {
1266
-        // set no cache constants
1267
-        if (! defined('DONOTCACHEPAGE')) {
1268
-            define('DONOTCACHEPAGE', true);
1269
-        }
1270
-        if (! defined('DONOTCACHCEOBJECT')) {
1271
-            define('DONOTCACHCEOBJECT', true);
1272
-        }
1273
-        if (! defined('DONOTCACHEDB')) {
1274
-            define('DONOTCACHEDB', true);
1275
-        }
1276
-        // add no cache headers
1277
-        add_action('send_headers', array('EE_System', 'nocache_headers'), 10);
1278
-        // plus a little extra for nginx and Google Chrome
1279
-        add_filter('nocache_headers', array('EE_System', 'extra_nocache_headers'), 10, 1);
1280
-        // prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes with the registration process
1281
-        remove_action('wp_head', 'adjacent_posts_rel_link_wp_head');
1282
-    }
1283
-
1284
-
1285
-    /**
1286
-     *    extra_nocache_headers
1287
-     *
1288
-     * @access    public
1289
-     * @param $headers
1290
-     * @return    array
1291
-     */
1292
-    public static function extra_nocache_headers($headers)
1293
-    {
1294
-        // for NGINX
1295
-        $headers['X-Accel-Expires'] = 0;
1296
-        // plus extra for Google Chrome since it doesn't seem to respect "no-cache", but WILL respect "no-store"
1297
-        $headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0';
1298
-        return $headers;
1299
-    }
1300
-
1301
-
1302
-    /**
1303
-     *    nocache_headers
1304
-     *
1305
-     * @access    public
1306
-     * @return    void
1307
-     */
1308
-    public static function nocache_headers()
1309
-    {
1310
-        nocache_headers();
1311
-    }
1312
-
1313
-
1314
-    /**
1315
-     * simply hooks into "wp_list_pages_exclude" filter (for wp_list_pages method) and makes sure EE critical pages are
1316
-     * never returned with the function.
1317
-     *
1318
-     * @param  array $exclude_array any existing pages being excluded are in this array.
1319
-     * @return array
1320
-     */
1321
-    public function remove_pages_from_wp_list_pages($exclude_array)
1322
-    {
1323
-        return array_merge($exclude_array, $this->registry->CFG->core->get_critical_pages_array());
1324
-    }
1325
-
1326
-
1327
-    /**
1328
-     * Return whether blocks can be registered/loaded or not.
1329
-     * @return bool
1330
-     */
1331
-    private function canLoadBlocks()
1332
-    {
1333
-        return apply_filters('FHEE__EE_System__canLoadBlocks', true)
1334
-               && function_exists('register_block_type')
1335
-               // don't load blocks if in the Divi page builder editor context
1336
-               // @see https://github.com/eventespresso/event-espresso-core/issues/814
1337
-               && ! $this->request->getRequestParam('et_fb', false);
1338
-    }
30
+	/**
31
+	 * indicates this is a 'normal' request. Ie, not activation, nor upgrade, nor activation.
32
+	 * So examples of this would be a normal GET request on the frontend or backend, or a POST, etc
33
+	 */
34
+	const req_type_normal = 0;
35
+
36
+	/**
37
+	 * Indicates this is a brand new installation of EE so we should install
38
+	 * tables and default data etc
39
+	 */
40
+	const req_type_new_activation = 1;
41
+
42
+	/**
43
+	 * we've detected that EE has been reactivated (or EE was activated during maintenance mode,
44
+	 * and we just exited maintenance mode). We MUST check the database is setup properly
45
+	 * and that default data is setup too
46
+	 */
47
+	const req_type_reactivation = 2;
48
+
49
+	/**
50
+	 * indicates that EE has been upgraded since its previous request.
51
+	 * We may have data migration scripts to call and will want to trigger maintenance mode
52
+	 */
53
+	const req_type_upgrade = 3;
54
+
55
+	/**
56
+	 * TODO  will detect that EE has been DOWNGRADED. We probably don't want to run in this case...
57
+	 */
58
+	const req_type_downgrade = 4;
59
+
60
+	/**
61
+	 * @deprecated since version 4.6.0.dev.006
62
+	 * Now whenever a new_activation is detected the request type is still just
63
+	 * new_activation (same for reactivation, upgrade, downgrade etc), but if we'r ein maintenance mode
64
+	 * EE_System::initialize_db_if_no_migrations_required and EE_Addon::initialize_db_if_no_migrations_required
65
+	 * will instead enqueue that EE plugin's db initialization for when we're taken out of maintenance mode.
66
+	 * (Specifically, when the migration manager indicates migrations are finished
67
+	 * EE_Data_Migration_Manager::initialize_db_for_enqueued_ee_plugins() will be called)
68
+	 */
69
+	const req_type_activation_but_not_installed = 5;
70
+
71
+	/**
72
+	 * option prefix for recording the activation history (like core's "espresso_db_update") of addons
73
+	 */
74
+	const addon_activation_history_option_prefix = 'ee_addon_activation_history_';
75
+
76
+	/**
77
+	 * @var EE_System $_instance
78
+	 */
79
+	private static $_instance;
80
+
81
+	/**
82
+	 * @var EE_Registry $registry
83
+	 */
84
+	private $registry;
85
+
86
+	/**
87
+	 * @var LoaderInterface $loader
88
+	 */
89
+	private $loader;
90
+
91
+	/**
92
+	 * @var EE_Capabilities $capabilities
93
+	 */
94
+	private $capabilities;
95
+
96
+	/**
97
+	 * @var RequestInterface $request
98
+	 */
99
+	private $request;
100
+
101
+	/**
102
+	 * @var EE_Maintenance_Mode $maintenance_mode
103
+	 */
104
+	private $maintenance_mode;
105
+
106
+	/**
107
+	 * Stores which type of request this is, options being one of the constants on EE_System starting with req_type_*.
108
+	 * It can be a brand-new activation, a reactivation, an upgrade, a downgrade, or a normal request.
109
+	 *
110
+	 * @var int $_req_type
111
+	 */
112
+	private $_req_type;
113
+
114
+	/**
115
+	 * Whether or not there was a non-micro version change in EE core version during this request
116
+	 *
117
+	 * @var boolean $_major_version_change
118
+	 */
119
+	private $_major_version_change = false;
120
+
121
+	/**
122
+	 * A Context DTO dedicated solely to identifying the current request type.
123
+	 *
124
+	 * @var RequestTypeContextCheckerInterface $request_type
125
+	 */
126
+	private $request_type;
127
+
128
+
129
+	/**
130
+	 * @singleton method used to instantiate class object
131
+	 * @param EE_Registry|null         $registry
132
+	 * @param LoaderInterface|null     $loader
133
+	 * @param RequestInterface|null    $request
134
+	 * @param EE_Maintenance_Mode|null $maintenance_mode
135
+	 * @return EE_System
136
+	 */
137
+	public static function instance(
138
+		EE_Registry $registry = null,
139
+		LoaderInterface $loader = null,
140
+		RequestInterface $request = null,
141
+		EE_Maintenance_Mode $maintenance_mode = null
142
+	) {
143
+		// check if class object is instantiated
144
+		if (! self::$_instance instanceof EE_System) {
145
+			self::$_instance = new self($registry, $loader, $request, $maintenance_mode);
146
+		}
147
+		return self::$_instance;
148
+	}
149
+
150
+
151
+	/**
152
+	 * resets the instance and returns it
153
+	 *
154
+	 * @return EE_System
155
+	 */
156
+	public static function reset()
157
+	{
158
+		self::$_instance->_req_type = null;
159
+		// make sure none of the old hooks are left hanging around
160
+		remove_all_actions('AHEE__EE_System__perform_activations_upgrades_and_migrations');
161
+		// we need to reset the migration manager in order for it to detect DMSs properly
162
+		EE_Data_Migration_Manager::reset();
163
+		self::instance()->detect_activations_or_upgrades();
164
+		self::instance()->perform_activations_upgrades_and_migrations();
165
+		return self::instance();
166
+	}
167
+
168
+
169
+	/**
170
+	 * sets hooks for running rest of system
171
+	 * provides "AHEE__EE_System__construct__complete" hook for EE Addons to use as their starting point
172
+	 * starting EE Addons from any other point may lead to problems
173
+	 *
174
+	 * @param EE_Registry         $registry
175
+	 * @param LoaderInterface     $loader
176
+	 * @param RequestInterface    $request
177
+	 * @param EE_Maintenance_Mode $maintenance_mode
178
+	 */
179
+	private function __construct(
180
+		EE_Registry $registry,
181
+		LoaderInterface $loader,
182
+		RequestInterface $request,
183
+		EE_Maintenance_Mode $maintenance_mode
184
+	) {
185
+		$this->registry = $registry;
186
+		$this->loader = $loader;
187
+		$this->request = $request;
188
+		$this->maintenance_mode = $maintenance_mode;
189
+		do_action('AHEE__EE_System__construct__begin', $this);
190
+		add_action(
191
+			'AHEE__EE_Bootstrap__load_espresso_addons',
192
+			array($this, 'loadCapabilities'),
193
+			5
194
+		);
195
+		add_action(
196
+			'AHEE__EE_Bootstrap__load_espresso_addons',
197
+			array($this, 'loadCommandBus'),
198
+			7
199
+		);
200
+		add_action(
201
+			'AHEE__EE_Bootstrap__load_espresso_addons',
202
+			array($this, 'loadPluginApi'),
203
+			9
204
+		);
205
+		// allow addons to load first so that they can register autoloaders, set hooks for running DMS's, etc
206
+		add_action(
207
+			'AHEE__EE_Bootstrap__load_espresso_addons',
208
+			array($this, 'load_espresso_addons')
209
+		);
210
+		// when an ee addon is activated, we want to call the core hook(s) again
211
+		// because the newly-activated addon didn't get a chance to run at all
212
+		add_action('activate_plugin', array($this, 'load_espresso_addons'), 1);
213
+		// detect whether install or upgrade
214
+		add_action(
215
+			'AHEE__EE_Bootstrap__detect_activations_or_upgrades',
216
+			array($this, 'detect_activations_or_upgrades'),
217
+			3
218
+		);
219
+		// load EE_Config, EE_Textdomain, etc
220
+		add_action(
221
+			'AHEE__EE_Bootstrap__load_core_configuration',
222
+			array($this, 'load_core_configuration'),
223
+			5
224
+		);
225
+		// load specifications for matching routes to current request
226
+		add_action(
227
+			'AHEE__EE_Bootstrap__load_core_configuration',
228
+			array($this, 'loadRouteMatchSpecifications')
229
+		);
230
+		// load EE_Config, EE_Textdomain, etc
231
+		add_action(
232
+			'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets',
233
+			array($this, 'register_shortcodes_modules_and_widgets'),
234
+			7
235
+		);
236
+		// you wanna get going? I wanna get going... let's get going!
237
+		add_action(
238
+			'AHEE__EE_Bootstrap__brew_espresso',
239
+			array($this, 'brew_espresso'),
240
+			9
241
+		);
242
+		// other housekeeping
243
+		// exclude EE critical pages from wp_list_pages
244
+		add_filter(
245
+			'wp_list_pages_excludes',
246
+			array($this, 'remove_pages_from_wp_list_pages'),
247
+			10
248
+		);
249
+		// ALL EE Addons should use the following hook point to attach their initial setup too
250
+		// it's extremely important for EE Addons to register any class autoloaders so that they can be available when the EE_Config loads
251
+		do_action('AHEE__EE_System__construct__complete', $this);
252
+	}
253
+
254
+
255
+	/**
256
+	 * load and setup EE_Capabilities
257
+	 *
258
+	 * @return void
259
+	 * @throws EE_Error
260
+	 */
261
+	public function loadCapabilities()
262
+	{
263
+		$this->capabilities = $this->loader->getShared('EE_Capabilities');
264
+		add_action(
265
+			'AHEE__EE_Capabilities__init_caps__before_initialization',
266
+			function () {
267
+				LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager');
268
+			}
269
+		);
270
+	}
271
+
272
+
273
+	/**
274
+	 * create and cache the CommandBus, and also add middleware
275
+	 * The CapChecker middleware requires the use of EE_Capabilities
276
+	 * which is why we need to load the CommandBus after Caps are set up
277
+	 *
278
+	 * @return void
279
+	 * @throws EE_Error
280
+	 */
281
+	public function loadCommandBus()
282
+	{
283
+		$this->loader->getShared(
284
+			'CommandBusInterface',
285
+			array(
286
+				null,
287
+				apply_filters(
288
+					'FHEE__EE_Load_Espresso_Core__handle_request__CommandBus_middleware',
289
+					array(
290
+						$this->loader->getShared('EventEspresso\core\services\commands\middleware\CapChecker'),
291
+						$this->loader->getShared('EventEspresso\core\services\commands\middleware\AddActionHook'),
292
+					)
293
+				),
294
+			)
295
+		);
296
+	}
297
+
298
+
299
+	/**
300
+	 * @return void
301
+	 * @throws EE_Error
302
+	 */
303
+	public function loadPluginApi()
304
+	{
305
+		// set autoloaders for all of the classes implementing EEI_Plugin_API
306
+		// which provide helpers for EE plugin authors to more easily register certain components with EE.
307
+		EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
308
+		$this->loader->getShared('EE_Request_Handler');
309
+	}
310
+
311
+
312
+	/**
313
+	 * @param string $addon_name
314
+	 * @param string $version_constant
315
+	 * @param string $min_version_required
316
+	 * @param string $load_callback
317
+	 * @param string $plugin_file_constant
318
+	 * @return void
319
+	 */
320
+	private function deactivateIncompatibleAddon(
321
+		$addon_name,
322
+		$version_constant,
323
+		$min_version_required,
324
+		$load_callback,
325
+		$plugin_file_constant
326
+	) {
327
+		if (! defined($version_constant)) {
328
+			return;
329
+		}
330
+		$addon_version = constant($version_constant);
331
+		if ($addon_version && version_compare($addon_version, $min_version_required, '<')) {
332
+			remove_action('AHEE__EE_System__load_espresso_addons', $load_callback);
333
+			if (! function_exists('deactivate_plugins')) {
334
+				require_once ABSPATH . 'wp-admin/includes/plugin.php';
335
+			}
336
+			deactivate_plugins(plugin_basename(constant($plugin_file_constant)));
337
+			unset($_GET['activate'], $_REQUEST['activate'], $_GET['activate-multi'], $_REQUEST['activate-multi']);
338
+			EE_Error::add_error(
339
+				sprintf(
340
+					esc_html__(
341
+						'We\'re sorry, but the Event Espresso %1$s addon was deactivated because version %2$s or higher is required with this version of Event Espresso core.',
342
+						'event_espresso'
343
+					),
344
+					$addon_name,
345
+					$min_version_required
346
+				),
347
+				__FILE__,
348
+				__FUNCTION__ . "({$addon_name})",
349
+				__LINE__
350
+			);
351
+			EE_Error::get_notices(false, true);
352
+		}
353
+	}
354
+
355
+
356
+	/**
357
+	 * load_espresso_addons
358
+	 * allow addons to load first so that they can set hooks for running DMS's, etc
359
+	 * this is hooked into both:
360
+	 *    'AHEE__EE_Bootstrap__load_core_configuration'
361
+	 *        which runs during the WP 'plugins_loaded' action at priority 5
362
+	 *    and the WP 'activate_plugin' hook point
363
+	 *
364
+	 * @access public
365
+	 * @return void
366
+	 */
367
+	public function load_espresso_addons()
368
+	{
369
+		$this->deactivateIncompatibleAddon(
370
+			'Wait Lists',
371
+			'EE_WAIT_LISTS_VERSION',
372
+			'1.0.0.beta.074',
373
+			'load_espresso_wait_lists',
374
+			'EE_WAIT_LISTS_PLUGIN_FILE'
375
+		);
376
+		$this->deactivateIncompatibleAddon(
377
+			'Automated Upcoming Event Notifications',
378
+			'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_VERSION',
379
+			'1.0.0.beta.091',
380
+			'load_espresso_automated_upcoming_event_notification',
381
+			'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_PLUGIN_FILE'
382
+		);
383
+		do_action('AHEE__EE_System__load_espresso_addons');
384
+		// if the WP API basic auth plugin isn't already loaded, load it now.
385
+		// We want it for mobile apps. Just include the entire plugin
386
+		// also, don't load the basic auth when a plugin is getting activated, because
387
+		// it could be the basic auth plugin, and it doesn't check if its methods are already defined
388
+		// and causes a fatal error
389
+		if (($this->request->isWordPressApi() || $this->request->isApi())
390
+			&& $this->request->getRequestParam('activate') !== 'true'
391
+			&& ! function_exists('json_basic_auth_handler')
392
+			&& ! function_exists('json_basic_auth_error')
393
+			&& ! in_array(
394
+				$this->request->getRequestParam('action'),
395
+				array('activate', 'activate-selected'),
396
+				true
397
+			)
398
+		) {
399
+			include_once EE_THIRD_PARTY . 'wp-api-basic-auth' . DS . 'basic-auth.php';
400
+		}
401
+		do_action('AHEE__EE_System__load_espresso_addons__complete');
402
+	}
403
+
404
+
405
+	/**
406
+	 * detect_activations_or_upgrades
407
+	 * Checks for activation or upgrade of core first;
408
+	 * then also checks if any registered addons have been activated or upgraded
409
+	 * This is hooked into 'AHEE__EE_Bootstrap__detect_activations_or_upgrades'
410
+	 * which runs during the WP 'plugins_loaded' action at priority 3
411
+	 *
412
+	 * @access public
413
+	 * @return void
414
+	 */
415
+	public function detect_activations_or_upgrades()
416
+	{
417
+		// first off: let's make sure to handle core
418
+		$this->detect_if_activation_or_upgrade();
419
+		foreach ($this->registry->addons as $addon) {
420
+			if ($addon instanceof EE_Addon) {
421
+				// detect teh request type for that addon
422
+				$addon->detect_activation_or_upgrade();
423
+			}
424
+		}
425
+	}
426
+
427
+
428
+	/**
429
+	 * detect_if_activation_or_upgrade
430
+	 * Takes care of detecting whether this is a brand new install or code upgrade,
431
+	 * and either setting up the DB or setting up maintenance mode etc.
432
+	 *
433
+	 * @access public
434
+	 * @return void
435
+	 */
436
+	public function detect_if_activation_or_upgrade()
437
+	{
438
+		do_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin');
439
+		// check if db has been updated, or if its a brand-new installation
440
+		$espresso_db_update = $this->fix_espresso_db_upgrade_option();
441
+		$request_type = $this->detect_req_type($espresso_db_update);
442
+		// EEH_Debug_Tools::printr( $request_type, '$request_type', __FILE__, __LINE__ );
443
+		switch ($request_type) {
444
+			case EE_System::req_type_new_activation:
445
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__new_activation');
446
+				$this->_handle_core_version_change($espresso_db_update);
447
+				break;
448
+			case EE_System::req_type_reactivation:
449
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__reactivation');
450
+				$this->_handle_core_version_change($espresso_db_update);
451
+				break;
452
+			case EE_System::req_type_upgrade:
453
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__upgrade');
454
+				// migrations may be required now that we've upgraded
455
+				$this->maintenance_mode->set_maintenance_mode_if_db_old();
456
+				$this->_handle_core_version_change($espresso_db_update);
457
+				break;
458
+			case EE_System::req_type_downgrade:
459
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__downgrade');
460
+				// its possible migrations are no longer required
461
+				$this->maintenance_mode->set_maintenance_mode_if_db_old();
462
+				$this->_handle_core_version_change($espresso_db_update);
463
+				break;
464
+			case EE_System::req_type_normal:
465
+			default:
466
+				break;
467
+		}
468
+		do_action('AHEE__EE_System__detect_if_activation_or_upgrade__complete');
469
+	}
470
+
471
+
472
+	/**
473
+	 * Updates the list of installed versions and sets hooks for
474
+	 * initializing the database later during the request
475
+	 *
476
+	 * @param array $espresso_db_update
477
+	 */
478
+	private function _handle_core_version_change($espresso_db_update)
479
+	{
480
+		$this->update_list_of_installed_versions($espresso_db_update);
481
+		// get ready to verify the DB is ok (provided we aren't in maintenance mode, of course)
482
+		add_action(
483
+			'AHEE__EE_System__perform_activations_upgrades_and_migrations',
484
+			array($this, 'initialize_db_if_no_migrations_required')
485
+		);
486
+	}
487
+
488
+
489
+	/**
490
+	 * standardizes the wp option 'espresso_db_upgrade' which actually stores
491
+	 * information about what versions of EE have been installed and activated,
492
+	 * NOT necessarily the state of the database
493
+	 *
494
+	 * @param mixed $espresso_db_update           the value of the WordPress option.
495
+	 *                                            If not supplied, fetches it from the options table
496
+	 * @return array the correct value of 'espresso_db_upgrade', after saving it, if it needed correction
497
+	 */
498
+	private function fix_espresso_db_upgrade_option($espresso_db_update = null)
499
+	{
500
+		do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
501
+		if (! $espresso_db_update) {
502
+			$espresso_db_update = get_option('espresso_db_update');
503
+		}
504
+		// check that option is an array
505
+		if (! is_array($espresso_db_update)) {
506
+			// if option is FALSE, then it never existed
507
+			if ($espresso_db_update === false) {
508
+				// make $espresso_db_update an array and save option with autoload OFF
509
+				$espresso_db_update = array();
510
+				add_option('espresso_db_update', $espresso_db_update, '', 'no');
511
+			} else {
512
+				// option is NOT FALSE but also is NOT an array, so make it an array and save it
513
+				$espresso_db_update = array($espresso_db_update => array());
514
+				update_option('espresso_db_update', $espresso_db_update);
515
+			}
516
+		} else {
517
+			$corrected_db_update = array();
518
+			// if IS an array, but is it an array where KEYS are version numbers, and values are arrays?
519
+			foreach ($espresso_db_update as $should_be_version_string => $should_be_array) {
520
+				if (is_int($should_be_version_string) && ! is_array($should_be_array)) {
521
+					// the key is an int, and the value IS NOT an array
522
+					// so it must be numerically-indexed, where values are versions installed...
523
+					// fix it!
524
+					$version_string = $should_be_array;
525
+					$corrected_db_update[ $version_string ] = array('unknown-date');
526
+				} else {
527
+					// ok it checks out
528
+					$corrected_db_update[ $should_be_version_string ] = $should_be_array;
529
+				}
530
+			}
531
+			$espresso_db_update = $corrected_db_update;
532
+			update_option('espresso_db_update', $espresso_db_update);
533
+		}
534
+		do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__complete', $espresso_db_update);
535
+		return $espresso_db_update;
536
+	}
537
+
538
+
539
+	/**
540
+	 * Does the traditional work of setting up the plugin's database and adding default data.
541
+	 * If migration script/process did not exist, this is what would happen on every activation/reactivation/upgrade.
542
+	 * NOTE: if we're in maintenance mode (which would be the case if we detect there are data
543
+	 * migration scripts that need to be run and a version change happens), enqueues core for database initialization,
544
+	 * so that it will be done when migrations are finished
545
+	 *
546
+	 * @param boolean $initialize_addons_too if true, we double-check addons' database tables etc too;
547
+	 * @param boolean $verify_schema         if true will re-check the database tables have the correct schema.
548
+	 *                                       This is a resource-intensive job
549
+	 *                                       so we prefer to only do it when necessary
550
+	 * @return void
551
+	 * @throws EE_Error
552
+	 */
553
+	public function initialize_db_if_no_migrations_required($initialize_addons_too = false, $verify_schema = true)
554
+	{
555
+		$request_type = $this->detect_req_type();
556
+		// only initialize system if we're not in maintenance mode.
557
+		if ($this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) {
558
+			/** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
559
+			$rewrite_rules = $this->loader->getShared(
560
+				'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
561
+			);
562
+			$rewrite_rules->flush();
563
+			if ($verify_schema) {
564
+				EEH_Activation::initialize_db_and_folders();
565
+			}
566
+			EEH_Activation::initialize_db_content();
567
+			EEH_Activation::system_initialization();
568
+			if ($initialize_addons_too) {
569
+				$this->initialize_addons();
570
+			}
571
+		} else {
572
+			EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for('Core');
573
+		}
574
+		if ($request_type === EE_System::req_type_new_activation
575
+			|| $request_type === EE_System::req_type_reactivation
576
+			|| (
577
+				$request_type === EE_System::req_type_upgrade
578
+				&& $this->is_major_version_change()
579
+			)
580
+		) {
581
+			add_action('AHEE__EE_System__initialize_last', array($this, 'redirect_to_about_ee'), 9);
582
+		}
583
+	}
584
+
585
+
586
+	/**
587
+	 * Initializes the db for all registered addons
588
+	 *
589
+	 * @throws EE_Error
590
+	 */
591
+	public function initialize_addons()
592
+	{
593
+		// foreach registered addon, make sure its db is up-to-date too
594
+		foreach ($this->registry->addons as $addon) {
595
+			if ($addon instanceof EE_Addon) {
596
+				$addon->initialize_db_if_no_migrations_required();
597
+			}
598
+		}
599
+	}
600
+
601
+
602
+	/**
603
+	 * Adds the current code version to the saved wp option which stores a list of all ee versions ever installed.
604
+	 *
605
+	 * @param    array  $version_history
606
+	 * @param    string $current_version_to_add version to be added to the version history
607
+	 * @return    boolean success as to whether or not this option was changed
608
+	 */
609
+	public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
610
+	{
611
+		if (! $version_history) {
612
+			$version_history = $this->fix_espresso_db_upgrade_option($version_history);
613
+		}
614
+		if ($current_version_to_add === null) {
615
+			$current_version_to_add = espresso_version();
616
+		}
617
+		$version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
618
+		// re-save
619
+		return update_option('espresso_db_update', $version_history);
620
+	}
621
+
622
+
623
+	/**
624
+	 * Detects if the current version indicated in the has existed in the list of
625
+	 * previously-installed versions of EE (espresso_db_update). Does NOT modify it (ie, no side-effect)
626
+	 *
627
+	 * @param array $espresso_db_update array from the wp option stored under the name 'espresso_db_update'.
628
+	 *                                  If not supplied, fetches it from the options table.
629
+	 *                                  Also, caches its result so later parts of the code can also know whether
630
+	 *                                  there's been an update or not. This way we can add the current version to
631
+	 *                                  espresso_db_update, but still know if this is a new install or not
632
+	 * @return int one of the constants on EE_System::req_type_
633
+	 */
634
+	public function detect_req_type($espresso_db_update = null)
635
+	{
636
+		if ($this->_req_type === null) {
637
+			$espresso_db_update = ! empty($espresso_db_update)
638
+				? $espresso_db_update
639
+				: $this->fix_espresso_db_upgrade_option();
640
+			$this->_req_type = EE_System::detect_req_type_given_activation_history(
641
+				$espresso_db_update,
642
+				'ee_espresso_activation',
643
+				espresso_version()
644
+			);
645
+			$this->_major_version_change = $this->_detect_major_version_change($espresso_db_update);
646
+			$this->request->setIsActivation($this->_req_type !== EE_System::req_type_normal);
647
+		}
648
+		return $this->_req_type;
649
+	}
650
+
651
+
652
+	/**
653
+	 * Returns whether or not there was a non-micro version change (ie, change in either
654
+	 * the first or second number in the version. Eg 4.9.0.rc.001 to 4.10.0.rc.000,
655
+	 * but not 4.9.0.rc.0001 to 4.9.1.rc.0001
656
+	 *
657
+	 * @param $activation_history
658
+	 * @return bool
659
+	 */
660
+	private function _detect_major_version_change($activation_history)
661
+	{
662
+		$previous_version = EE_System::_get_most_recently_active_version_from_activation_history($activation_history);
663
+		$previous_version_parts = explode('.', $previous_version);
664
+		$current_version_parts = explode('.', espresso_version());
665
+		return isset($previous_version_parts[0], $previous_version_parts[1], $current_version_parts[0], $current_version_parts[1])
666
+			   && ($previous_version_parts[0] !== $current_version_parts[0]
667
+				   || $previous_version_parts[1] !== $current_version_parts[1]
668
+			   );
669
+	}
670
+
671
+
672
+	/**
673
+	 * Returns true if either the major or minor version of EE changed during this request.
674
+	 * Eg 4.9.0.rc.001 to 4.10.0.rc.000, but not 4.9.0.rc.0001 to 4.9.1.rc.0001
675
+	 *
676
+	 * @return bool
677
+	 */
678
+	public function is_major_version_change()
679
+	{
680
+		return $this->_major_version_change;
681
+	}
682
+
683
+
684
+	/**
685
+	 * Determines the request type for any ee addon, given three piece of info: the current array of activation
686
+	 * histories (for core that' 'espresso_db_update' wp option); the name of the WordPress option which is temporarily
687
+	 * set upon activation of the plugin (for core it's 'ee_espresso_activation'); and the version that this plugin was
688
+	 * just activated to (for core that will always be espresso_version())
689
+	 *
690
+	 * @param array  $activation_history_for_addon     the option's value which stores the activation history for this
691
+	 *                                                 ee plugin. for core that's 'espresso_db_update'
692
+	 * @param string $activation_indicator_option_name the name of the WordPress option that is temporarily set to
693
+	 *                                                 indicate that this plugin was just activated
694
+	 * @param string $version_to_upgrade_to            the version that was just upgraded to (for core that will be
695
+	 *                                                 espresso_version())
696
+	 * @return int one of the constants on EE_System::req_type_*
697
+	 */
698
+	public static function detect_req_type_given_activation_history(
699
+		$activation_history_for_addon,
700
+		$activation_indicator_option_name,
701
+		$version_to_upgrade_to
702
+	) {
703
+		$version_is_higher = self::_new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to);
704
+		if ($activation_history_for_addon) {
705
+			// it exists, so this isn't a completely new install
706
+			// check if this version already in that list of previously installed versions
707
+			if (! isset($activation_history_for_addon[ $version_to_upgrade_to ])) {
708
+				// it a version we haven't seen before
709
+				if ($version_is_higher === 1) {
710
+					$req_type = EE_System::req_type_upgrade;
711
+				} else {
712
+					$req_type = EE_System::req_type_downgrade;
713
+				}
714
+				delete_option($activation_indicator_option_name);
715
+			} else {
716
+				// its not an update. maybe a reactivation?
717
+				if (get_option($activation_indicator_option_name, false)) {
718
+					if ($version_is_higher === -1) {
719
+						$req_type = EE_System::req_type_downgrade;
720
+					} elseif ($version_is_higher === 0) {
721
+						// we've seen this version before, but it's an activation. must be a reactivation
722
+						$req_type = EE_System::req_type_reactivation;
723
+					} else {// $version_is_higher === 1
724
+						$req_type = EE_System::req_type_upgrade;
725
+					}
726
+					delete_option($activation_indicator_option_name);
727
+				} else {
728
+					// we've seen this version before and the activation indicate doesn't show it was just activated
729
+					if ($version_is_higher === -1) {
730
+						$req_type = EE_System::req_type_downgrade;
731
+					} elseif ($version_is_higher === 0) {
732
+						// we've seen this version before and it's not an activation. its normal request
733
+						$req_type = EE_System::req_type_normal;
734
+					} else {// $version_is_higher === 1
735
+						$req_type = EE_System::req_type_upgrade;
736
+					}
737
+				}
738
+			}
739
+		} else {
740
+			// brand new install
741
+			$req_type = EE_System::req_type_new_activation;
742
+			delete_option($activation_indicator_option_name);
743
+		}
744
+		return $req_type;
745
+	}
746
+
747
+
748
+	/**
749
+	 * Detects if the $version_to_upgrade_to is higher than the most recent version in
750
+	 * the $activation_history_for_addon
751
+	 *
752
+	 * @param array  $activation_history_for_addon (keys are versions, values are arrays of times activated,
753
+	 *                                             sometimes containing 'unknown-date'
754
+	 * @param string $version_to_upgrade_to        (current version)
755
+	 * @return int results of version_compare( $version_to_upgrade_to, $most_recently_active_version ).
756
+	 *                                             ie, -1 if $version_to_upgrade_to is LOWER (downgrade);
757
+	 *                                             0 if $version_to_upgrade_to MATCHES (reactivation or normal request);
758
+	 *                                             1 if $version_to_upgrade_to is HIGHER (upgrade) ;
759
+	 */
760
+	private static function _new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to)
761
+	{
762
+		// find the most recently-activated version
763
+		$most_recently_active_version =
764
+			EE_System::_get_most_recently_active_version_from_activation_history($activation_history_for_addon);
765
+		return version_compare($version_to_upgrade_to, $most_recently_active_version);
766
+	}
767
+
768
+
769
+	/**
770
+	 * Gets the most recently active version listed in the activation history,
771
+	 * and if none are found (ie, it's a brand new install) returns '0.0.0.dev.000'.
772
+	 *
773
+	 * @param array $activation_history  (keys are versions, values are arrays of times activated,
774
+	 *                                   sometimes containing 'unknown-date'
775
+	 * @return string
776
+	 */
777
+	private static function _get_most_recently_active_version_from_activation_history($activation_history)
778
+	{
779
+		$most_recently_active_version_activation = '1970-01-01 00:00:00';
780
+		$most_recently_active_version = '0.0.0.dev.000';
781
+		if (is_array($activation_history)) {
782
+			foreach ($activation_history as $version => $times_activated) {
783
+				// check there is a record of when this version was activated. Otherwise,
784
+				// mark it as unknown
785
+				if (! $times_activated) {
786
+					$times_activated = array('unknown-date');
787
+				}
788
+				if (is_string($times_activated)) {
789
+					$times_activated = array($times_activated);
790
+				}
791
+				foreach ($times_activated as $an_activation) {
792
+					if ($an_activation !== 'unknown-date'
793
+						&& $an_activation
794
+						   > $most_recently_active_version_activation) {
795
+						$most_recently_active_version = $version;
796
+						$most_recently_active_version_activation = $an_activation === 'unknown-date'
797
+							? '1970-01-01 00:00:00'
798
+							: $an_activation;
799
+					}
800
+				}
801
+			}
802
+		}
803
+		return $most_recently_active_version;
804
+	}
805
+
806
+
807
+	/**
808
+	 * This redirects to the about EE page after activation
809
+	 *
810
+	 * @return void
811
+	 */
812
+	public function redirect_to_about_ee()
813
+	{
814
+		$notices = EE_Error::get_notices(false);
815
+		// if current user is an admin and it's not an ajax or rest request
816
+		if (! isset($notices['errors'])
817
+			&& $this->request->isAdmin()
818
+			&& apply_filters(
819
+				'FHEE__EE_System__redirect_to_about_ee__do_redirect',
820
+				$this->capabilities->current_user_can('manage_options', 'espresso_about_default')
821
+			)
822
+		) {
823
+			$query_params = array('page' => 'espresso_about');
824
+			if (EE_System::instance()->detect_req_type() === EE_System::req_type_new_activation) {
825
+				$query_params['new_activation'] = true;
826
+			}
827
+			if (EE_System::instance()->detect_req_type() === EE_System::req_type_reactivation) {
828
+				$query_params['reactivation'] = true;
829
+			}
830
+			$url = add_query_arg($query_params, admin_url('admin.php'));
831
+			wp_safe_redirect($url);
832
+			exit();
833
+		}
834
+	}
835
+
836
+
837
+	/**
838
+	 * load_core_configuration
839
+	 * this is hooked into 'AHEE__EE_Bootstrap__load_core_configuration'
840
+	 * which runs during the WP 'plugins_loaded' action at priority 5
841
+	 *
842
+	 * @return void
843
+	 * @throws ReflectionException
844
+	 * @throws Exception
845
+	 */
846
+	public function load_core_configuration()
847
+	{
848
+		do_action('AHEE__EE_System__load_core_configuration__begin', $this);
849
+		$this->loader->getShared('EE_Load_Textdomain');
850
+		// load textdomain
851
+		EE_Load_Textdomain::load_textdomain();
852
+		// load and setup EE_Config and EE_Network_Config
853
+		$config = $this->loader->getShared('EE_Config');
854
+		$this->loader->getShared('EE_Network_Config');
855
+		// setup autoloaders
856
+		// enable logging?
857
+		if ($config->admin->use_full_logging) {
858
+			$this->loader->getShared('EE_Log');
859
+		}
860
+		// check for activation errors
861
+		$activation_errors = get_option('ee_plugin_activation_errors', false);
862
+		if ($activation_errors) {
863
+			EE_Error::add_error($activation_errors, __FILE__, __FUNCTION__, __LINE__);
864
+			update_option('ee_plugin_activation_errors', false);
865
+		}
866
+		// get model names
867
+		$this->_parse_model_names();
868
+		// load caf stuff a chance to play during the activation process too.
869
+		$this->_maybe_brew_regular();
870
+		// configure custom post type definitions
871
+		$this->loader->getShared('EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions');
872
+		$this->loader->getShared('EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions');
873
+		do_action('AHEE__EE_System__load_core_configuration__complete', $this);
874
+	}
875
+
876
+
877
+	/**
878
+	 * cycles through all of the models/*.model.php files, and assembles an array of model names
879
+	 *
880
+	 * @return void
881
+	 * @throws ReflectionException
882
+	 */
883
+	private function _parse_model_names()
884
+	{
885
+		// get all the files in the EE_MODELS folder that end in .model.php
886
+		$models = glob(EE_MODELS . '*.model.php');
887
+		$model_names = array();
888
+		$non_abstract_db_models = array();
889
+		foreach ($models as $model) {
890
+			// get model classname
891
+			$classname = EEH_File::get_classname_from_filepath_with_standard_filename($model);
892
+			$short_name = str_replace('EEM_', '', $classname);
893
+			$reflectionClass = new ReflectionClass($classname);
894
+			if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
895
+				$non_abstract_db_models[ $short_name ] = $classname;
896
+			}
897
+			$model_names[ $short_name ] = $classname;
898
+		}
899
+		$this->registry->models = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
900
+		$this->registry->non_abstract_db_models = apply_filters(
901
+			'FHEE__EE_System__parse_implemented_model_names',
902
+			$non_abstract_db_models
903
+		);
904
+	}
905
+
906
+
907
+	/**
908
+	 * The purpose of this method is to simply check for a file named "caffeinated/brewing_regular.php" for any hooks
909
+	 * that need to be setup before our EE_System launches.
910
+	 *
911
+	 * @return void
912
+	 * @throws DomainException
913
+	 * @throws InvalidArgumentException
914
+	 * @throws InvalidDataTypeException
915
+	 * @throws InvalidInterfaceException
916
+	 * @throws InvalidClassException
917
+	 * @throws InvalidFilePathException
918
+	 */
919
+	private function _maybe_brew_regular()
920
+	{
921
+		/** @var Domain $domain */
922
+		$domain = DomainFactory::getShared(
923
+			new FullyQualifiedName(
924
+				'EventEspresso\core\domain\Domain'
925
+			),
926
+			array(
927
+				new FilePath(EVENT_ESPRESSO_MAIN_FILE),
928
+				Version::fromString(espresso_version()),
929
+			)
930
+		);
931
+		if ($domain->isCaffeinated()) {
932
+			require_once EE_CAFF_PATH . 'brewing_regular.php';
933
+		}
934
+	}
935
+
936
+
937
+	/**
938
+	 * @since 4.9.71.p
939
+	 * @throws Exception
940
+	 */
941
+	public function loadRouteMatchSpecifications()
942
+	{
943
+		try {
944
+			$this->loader->getShared(
945
+				'EventEspresso\core\services\route_match\RouteMatchSpecificationManager'
946
+			);
947
+		} catch (Exception $exception) {
948
+			new ExceptionStackTraceDisplay($exception);
949
+		}
950
+		do_action('AHEE__EE_System__loadRouteMatchSpecifications');
951
+	}
952
+
953
+
954
+	/**
955
+	 * register_shortcodes_modules_and_widgets
956
+	 * generate lists of shortcodes and modules, then verify paths and classes
957
+	 * This is hooked into 'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets'
958
+	 * which runs during the WP 'plugins_loaded' action at priority 7
959
+	 *
960
+	 * @access public
961
+	 * @return void
962
+	 * @throws Exception
963
+	 */
964
+	public function register_shortcodes_modules_and_widgets()
965
+	{
966
+		if ($this->request->isFrontend() || $this->request->isIframe() || $this->request->isAjax()) {
967
+			try {
968
+				// load, register, and add shortcodes the new way
969
+				$this->loader->getShared(
970
+					'EventEspresso\core\services\shortcodes\ShortcodesManager',
971
+					array(
972
+						// and the old way, but we'll put it under control of the new system
973
+						EE_Config::getLegacyShortcodesManager(),
974
+					)
975
+				);
976
+			} catch (Exception $exception) {
977
+				new ExceptionStackTraceDisplay($exception);
978
+			}
979
+		}
980
+		do_action('AHEE__EE_System__register_shortcodes_modules_and_widgets');
981
+		// check for addons using old hook point
982
+		if (has_action('AHEE__EE_System__register_shortcodes_modules_and_addons')) {
983
+			$this->_incompatible_addon_error();
984
+		}
985
+	}
986
+
987
+
988
+	/**
989
+	 * _incompatible_addon_error
990
+	 *
991
+	 * @access public
992
+	 * @return void
993
+	 */
994
+	private function _incompatible_addon_error()
995
+	{
996
+		// get array of classes hooking into here
997
+		$class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook(
998
+			'AHEE__EE_System__register_shortcodes_modules_and_addons'
999
+		);
1000
+		if (! empty($class_names)) {
1001
+			$msg = __(
1002
+				'The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
1003
+				'event_espresso'
1004
+			);
1005
+			$msg .= '<ul>';
1006
+			foreach ($class_names as $class_name) {
1007
+				$msg .= '<li><b>Event Espresso - '
1008
+						. str_replace(
1009
+							array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'),
1010
+							'',
1011
+							$class_name
1012
+						) . '</b></li>';
1013
+			}
1014
+			$msg .= '</ul>';
1015
+			$msg .= __(
1016
+				'Compatibility issues can be avoided and/or resolved by keeping addons and plugins updated to the latest version.',
1017
+				'event_espresso'
1018
+			);
1019
+			// save list of incompatible addons to wp-options for later use
1020
+			add_option('ee_incompatible_addons', $class_names, '', 'no');
1021
+			if (is_admin()) {
1022
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1023
+			}
1024
+		}
1025
+	}
1026
+
1027
+
1028
+	/**
1029
+	 * brew_espresso
1030
+	 * begins the process of setting hooks for initializing EE in the correct order
1031
+	 * This is happening on the 'AHEE__EE_Bootstrap__brew_espresso' hook point
1032
+	 * which runs during the WP 'plugins_loaded' action at priority 9
1033
+	 *
1034
+	 * @return void
1035
+	 */
1036
+	public function brew_espresso()
1037
+	{
1038
+		do_action('AHEE__EE_System__brew_espresso__begin', $this);
1039
+		// load some final core systems
1040
+		add_action('init', array($this, 'set_hooks_for_core'), 1);
1041
+		add_action('init', array($this, 'perform_activations_upgrades_and_migrations'), 3);
1042
+		add_action('init', array($this, 'load_CPTs_and_session'), 5);
1043
+		add_action('init', array($this, 'load_controllers'), 7);
1044
+		add_action('init', array($this, 'core_loaded_and_ready'), 9);
1045
+		add_action('init', array($this, 'initialize'), 10);
1046
+		add_action('init', array($this, 'initialize_last'), 100);
1047
+		if (is_admin() && apply_filters('FHEE__EE_System__brew_espresso__load_pue', true)) {
1048
+			// pew pew pew
1049
+			$this->loader->getShared('EventEspresso\core\services\licensing\LicenseService');
1050
+			do_action('AHEE__EE_System__brew_espresso__after_pue_init');
1051
+		}
1052
+		do_action('AHEE__EE_System__brew_espresso__complete', $this);
1053
+	}
1054
+
1055
+
1056
+	/**
1057
+	 *    set_hooks_for_core
1058
+	 *
1059
+	 * @access public
1060
+	 * @return    void
1061
+	 * @throws EE_Error
1062
+	 */
1063
+	public function set_hooks_for_core()
1064
+	{
1065
+		$this->_deactivate_incompatible_addons();
1066
+		do_action('AHEE__EE_System__set_hooks_for_core');
1067
+		$this->loader->getShared('EventEspresso\core\domain\values\session\SessionLifespan');
1068
+		// caps need to be initialized on every request so that capability maps are set.
1069
+		// @see https://events.codebasehq.com/projects/event-espresso/tickets/8674
1070
+		$this->registry->CAP->init_caps();
1071
+	}
1072
+
1073
+
1074
+	/**
1075
+	 * Using the information gathered in EE_System::_incompatible_addon_error,
1076
+	 * deactivates any addons considered incompatible with the current version of EE
1077
+	 */
1078
+	private function _deactivate_incompatible_addons()
1079
+	{
1080
+		$incompatible_addons = get_option('ee_incompatible_addons', array());
1081
+		if (! empty($incompatible_addons)) {
1082
+			$active_plugins = get_option('active_plugins', array());
1083
+			foreach ($active_plugins as $active_plugin) {
1084
+				foreach ($incompatible_addons as $incompatible_addon) {
1085
+					if (strpos($active_plugin, $incompatible_addon) !== false) {
1086
+						unset($_GET['activate']);
1087
+						espresso_deactivate_plugin($active_plugin);
1088
+					}
1089
+				}
1090
+			}
1091
+		}
1092
+	}
1093
+
1094
+
1095
+	/**
1096
+	 *    perform_activations_upgrades_and_migrations
1097
+	 *
1098
+	 * @access public
1099
+	 * @return    void
1100
+	 */
1101
+	public function perform_activations_upgrades_and_migrations()
1102
+	{
1103
+		do_action('AHEE__EE_System__perform_activations_upgrades_and_migrations');
1104
+	}
1105
+
1106
+
1107
+	/**
1108
+	 * @return void
1109
+	 * @throws DomainException
1110
+	 */
1111
+	public function load_CPTs_and_session()
1112
+	{
1113
+		do_action('AHEE__EE_System__load_CPTs_and_session__start');
1114
+		/** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies $register_custom_taxonomies */
1115
+		$register_custom_taxonomies = $this->loader->getShared(
1116
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'
1117
+		);
1118
+		$register_custom_taxonomies->registerCustomTaxonomies();
1119
+		/** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes $register_custom_post_types */
1120
+		$register_custom_post_types = $this->loader->getShared(
1121
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'
1122
+		);
1123
+		$register_custom_post_types->registerCustomPostTypes();
1124
+		/** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomyTerms $register_custom_taxonomy_terms */
1125
+		$register_custom_taxonomy_terms = $this->loader->getShared(
1126
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomyTerms'
1127
+		);
1128
+		$register_custom_taxonomy_terms->registerCustomTaxonomyTerms();
1129
+		// load legacy Custom Post Types and Taxonomies
1130
+		$this->loader->getShared('EE_Register_CPTs');
1131
+		do_action('AHEE__EE_System__load_CPTs_and_session__complete');
1132
+	}
1133
+
1134
+
1135
+	/**
1136
+	 * load_controllers
1137
+	 * this is the best place to load any additional controllers that needs access to EE core.
1138
+	 * it is expected that all basic core EE systems, that are not dependant on the current request are loaded at this
1139
+	 * time
1140
+	 *
1141
+	 * @access public
1142
+	 * @return void
1143
+	 */
1144
+	public function load_controllers()
1145
+	{
1146
+		do_action('AHEE__EE_System__load_controllers__start');
1147
+		// let's get it started
1148
+		if (! $this->maintenance_mode->level()
1149
+			&& ($this->request->isFrontend() || $this->request->isFrontAjax())
1150
+		) {
1151
+			do_action('AHEE__EE_System__load_controllers__load_front_controllers');
1152
+			$this->loader->getShared('EE_Front_Controller');
1153
+		} elseif ($this->request->isAdmin() || $this->request->isAdminAjax()) {
1154
+			do_action('AHEE__EE_System__load_controllers__load_admin_controllers');
1155
+			$this->loader->getShared('EE_Admin');
1156
+		} elseif ($this->request->isWordPressHeartbeat()) {
1157
+			$this->loader->getShared('EventEspresso\core\domain\services\admin\ajax\WordpressHeartbeat');
1158
+		}
1159
+		do_action('AHEE__EE_System__load_controllers__complete');
1160
+	}
1161
+
1162
+
1163
+	/**
1164
+	 * core_loaded_and_ready
1165
+	 * all of the basic EE core should be loaded at this point and available regardless of M-Mode
1166
+	 *
1167
+	 * @access public
1168
+	 * @return void
1169
+	 * @throws Exception
1170
+	 */
1171
+	public function core_loaded_and_ready()
1172
+	{
1173
+		if ($this->request->isAdmin()
1174
+			|| $this->request->isFrontend()
1175
+			|| $this->request->isIframe()
1176
+			|| $this->request->isWordPressApi()
1177
+		) {
1178
+			try {
1179
+				$this->loader->getShared('EventEspresso\core\services\assets\Registry');
1180
+				$this->loader->getShared('EventEspresso\core\domain\services\assets\CoreAssetManager');
1181
+				if ($this->canLoadBlocks()) {
1182
+					$this->loader->getShared(
1183
+						'EventEspresso\core\services\editor\BlockRegistrationManager'
1184
+					);
1185
+				}
1186
+			} catch (Exception $exception) {
1187
+				new ExceptionStackTraceDisplay($exception);
1188
+			}
1189
+		}
1190
+		if ($this->request->isAdmin()
1191
+			|| $this->request->isEeAjax()
1192
+			|| $this->request->isFrontend()
1193
+		) {
1194
+			$this->loader->getShared('EE_Session');
1195
+		}
1196
+		// integrate WP_Query with the EE models
1197
+		$this->loader->getShared('EE_CPT_Strategy');
1198
+		do_action('AHEE__EE_System__core_loaded_and_ready');
1199
+		// always load template tags, because it's faster than checking if it's a front-end request, and many page
1200
+		// builders require these even on the front-end
1201
+		require_once EE_PUBLIC . 'template_tags.php';
1202
+		do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
1203
+	}
1204
+
1205
+
1206
+	/**
1207
+	 * initialize
1208
+	 * this is the best place to begin initializing client code
1209
+	 *
1210
+	 * @access public
1211
+	 * @return void
1212
+	 */
1213
+	public function initialize()
1214
+	{
1215
+		do_action('AHEE__EE_System__initialize');
1216
+	}
1217
+
1218
+
1219
+	/**
1220
+	 * initialize_last
1221
+	 * this is run really late during the WP init hook point, and ensures that mostly everything else that needs to
1222
+	 * initialize has done so
1223
+	 *
1224
+	 * @access public
1225
+	 * @return void
1226
+	 */
1227
+	public function initialize_last()
1228
+	{
1229
+		do_action('AHEE__EE_System__initialize_last');
1230
+		/** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
1231
+		$rewrite_rules = $this->loader->getShared(
1232
+			'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
1233
+		);
1234
+		$rewrite_rules->flushRewriteRules();
1235
+		add_action('admin_bar_init', array($this, 'addEspressoToolbar'));
1236
+		if (($this->request->isAjax() || $this->request->isAdmin())
1237
+			&& $this->maintenance_mode->models_can_query()) {
1238
+			$this->loader->getShared('EventEspresso\core\services\privacy\export\PersonalDataExporterManager');
1239
+			$this->loader->getShared('EventEspresso\core\services\privacy\erasure\PersonalDataEraserManager');
1240
+		}
1241
+	}
1242
+
1243
+
1244
+	/**
1245
+	 * @return void
1246
+	 * @throws EE_Error
1247
+	 */
1248
+	public function addEspressoToolbar()
1249
+	{
1250
+		$this->loader->getShared(
1251
+			'EventEspresso\core\domain\services\admin\AdminToolBar',
1252
+			array($this->registry->CAP)
1253
+		);
1254
+	}
1255
+
1256
+
1257
+	/**
1258
+	 * do_not_cache
1259
+	 * sets no cache headers and defines no cache constants for WP plugins
1260
+	 *
1261
+	 * @access public
1262
+	 * @return void
1263
+	 */
1264
+	public static function do_not_cache()
1265
+	{
1266
+		// set no cache constants
1267
+		if (! defined('DONOTCACHEPAGE')) {
1268
+			define('DONOTCACHEPAGE', true);
1269
+		}
1270
+		if (! defined('DONOTCACHCEOBJECT')) {
1271
+			define('DONOTCACHCEOBJECT', true);
1272
+		}
1273
+		if (! defined('DONOTCACHEDB')) {
1274
+			define('DONOTCACHEDB', true);
1275
+		}
1276
+		// add no cache headers
1277
+		add_action('send_headers', array('EE_System', 'nocache_headers'), 10);
1278
+		// plus a little extra for nginx and Google Chrome
1279
+		add_filter('nocache_headers', array('EE_System', 'extra_nocache_headers'), 10, 1);
1280
+		// prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes with the registration process
1281
+		remove_action('wp_head', 'adjacent_posts_rel_link_wp_head');
1282
+	}
1283
+
1284
+
1285
+	/**
1286
+	 *    extra_nocache_headers
1287
+	 *
1288
+	 * @access    public
1289
+	 * @param $headers
1290
+	 * @return    array
1291
+	 */
1292
+	public static function extra_nocache_headers($headers)
1293
+	{
1294
+		// for NGINX
1295
+		$headers['X-Accel-Expires'] = 0;
1296
+		// plus extra for Google Chrome since it doesn't seem to respect "no-cache", but WILL respect "no-store"
1297
+		$headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0';
1298
+		return $headers;
1299
+	}
1300
+
1301
+
1302
+	/**
1303
+	 *    nocache_headers
1304
+	 *
1305
+	 * @access    public
1306
+	 * @return    void
1307
+	 */
1308
+	public static function nocache_headers()
1309
+	{
1310
+		nocache_headers();
1311
+	}
1312
+
1313
+
1314
+	/**
1315
+	 * simply hooks into "wp_list_pages_exclude" filter (for wp_list_pages method) and makes sure EE critical pages are
1316
+	 * never returned with the function.
1317
+	 *
1318
+	 * @param  array $exclude_array any existing pages being excluded are in this array.
1319
+	 * @return array
1320
+	 */
1321
+	public function remove_pages_from_wp_list_pages($exclude_array)
1322
+	{
1323
+		return array_merge($exclude_array, $this->registry->CFG->core->get_critical_pages_array());
1324
+	}
1325
+
1326
+
1327
+	/**
1328
+	 * Return whether blocks can be registered/loaded or not.
1329
+	 * @return bool
1330
+	 */
1331
+	private function canLoadBlocks()
1332
+	{
1333
+		return apply_filters('FHEE__EE_System__canLoadBlocks', true)
1334
+			   && function_exists('register_block_type')
1335
+			   // don't load blocks if in the Divi page builder editor context
1336
+			   // @see https://github.com/eventespresso/event-espresso-core/issues/814
1337
+			   && ! $this->request->getRequestParam('et_fb', false);
1338
+	}
1339 1339
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Datetime.model.php 1 patch
Indentation   +658 added lines, -658 removed lines patch added patch discarded remove patch
@@ -9,662 +9,662 @@
 block discarded – undo
9 9
 class EEM_Datetime extends EEM_Soft_Delete_Base
10 10
 {
11 11
 
12
-    /**
13
-     * @var EEM_Datetime $_instance
14
-     */
15
-    protected static $_instance;
16
-
17
-
18
-    /**
19
-     * private constructor to prevent direct creation
20
-     *
21
-     * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
22
-     *                         (and any incoming timezone data that gets saved).
23
-     *                         Note this just sends the timezone info to the date time model field objects.
24
-     *                         Default is NULL
25
-     *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
26
-     * @throws EE_Error
27
-     * @throws InvalidArgumentException
28
-     * @throws InvalidArgumentException
29
-     */
30
-    protected function __construct($timezone)
31
-    {
32
-        $this->singular_item           = esc_html__('Datetime', 'event_espresso');
33
-        $this->plural_item             = esc_html__('Datetimes', 'event_espresso');
34
-        $this->_tables                 = array(
35
-            'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
36
-        );
37
-        $this->_fields                 = array(
38
-            'Datetime' => array(
39
-                'DTT_ID'          => new EE_Primary_Key_Int_Field(
40
-                    'DTT_ID',
41
-                    esc_html__('Datetime ID', 'event_espresso')
42
-                ),
43
-                'EVT_ID'          => new EE_Foreign_Key_Int_Field(
44
-                    'EVT_ID',
45
-                    esc_html__('Event ID', 'event_espresso'),
46
-                    false,
47
-                    0,
48
-                    'Event'
49
-                ),
50
-                'DTT_name'        => new EE_Plain_Text_Field(
51
-                    'DTT_name',
52
-                    esc_html__('Datetime Name', 'event_espresso'),
53
-                    false,
54
-                    ''
55
-                ),
56
-                'DTT_description' => new EE_Post_Content_Field(
57
-                    'DTT_description',
58
-                    esc_html__('Description for Datetime', 'event_espresso'),
59
-                    false,
60
-                    ''
61
-                ),
62
-                'DTT_EVT_start'   => new EE_Datetime_Field(
63
-                    'DTT_EVT_start',
64
-                    esc_html__('Start time/date of Event', 'event_espresso'),
65
-                    false,
66
-                    EE_Datetime_Field::now,
67
-                    $timezone
68
-                ),
69
-                'DTT_EVT_end'     => new EE_Datetime_Field(
70
-                    'DTT_EVT_end',
71
-                    esc_html__('End time/date of Event', 'event_espresso'),
72
-                    false,
73
-                    EE_Datetime_Field::now,
74
-                    $timezone
75
-                ),
76
-                'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
77
-                    'DTT_reg_limit',
78
-                    esc_html__('Registration Limit for this time', 'event_espresso'),
79
-                    true,
80
-                    EE_INF
81
-                ),
82
-                'DTT_sold'        => new EE_Integer_Field(
83
-                    'DTT_sold',
84
-                    esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
85
-                    true,
86
-                    0
87
-                ),
88
-                'DTT_reserved'    => new EE_Integer_Field(
89
-                    'DTT_reserved',
90
-                    esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
91
-                    false,
92
-                    0
93
-                ),
94
-                'DTT_is_primary'  => new EE_Boolean_Field(
95
-                    'DTT_is_primary',
96
-                    esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
97
-                    false,
98
-                    false
99
-                ),
100
-                'DTT_order'       => new EE_Integer_Field(
101
-                    'DTT_order',
102
-                    esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
103
-                    false,
104
-                    0
105
-                ),
106
-                'DTT_parent'      => new EE_Integer_Field(
107
-                    'DTT_parent',
108
-                    esc_html__('Indicates what DTT_ID is the parent of this DTT_ID', 'event_espresso'),
109
-                    true,
110
-                    0
111
-                ),
112
-                'DTT_deleted'     => new EE_Trashed_Flag_Field(
113
-                    'DTT_deleted',
114
-                    esc_html__('Flag indicating datetime is archived', 'event_espresso'),
115
-                    false,
116
-                    false
117
-                ),
118
-            ),
119
-        );
120
-        $this->_model_relations        = array(
121
-            'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
122
-            'Event'   => new EE_Belongs_To_Relation(),
123
-            'Checkin' => new EE_Has_Many_Relation(),
124
-            'Datetime_Ticket' => new EE_Has_Many_Relation(),
125
-        );
126
-        $path_to_event_model = 'Event';
127
-        $this->model_chain_to_password = $path_to_event_model;
128
-        $this->_model_chain_to_wp_user = $path_to_event_model;
129
-        // this model is generally available for reading
130
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Event_Related_Public(
131
-            $path_to_event_model
132
-        );
133
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
134
-            $path_to_event_model
135
-        );
136
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Event_Related_Protected(
137
-            $path_to_event_model
138
-        );
139
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Event_Related_Protected(
140
-            $path_to_event_model,
141
-            EEM_Base::caps_edit
142
-        );
143
-        parent::__construct($timezone);
144
-    }
145
-
146
-
147
-    /**
148
-     * create new blank datetime
149
-     *
150
-     * @access public
151
-     * @return EE_Datetime[] array on success, FALSE on fail
152
-     * @throws EE_Error
153
-     */
154
-    public function create_new_blank_datetime()
155
-    {
156
-        // makes sure timezone is always set.
157
-        $timezone_string = $this->get_timezone();
158
-        $blank_datetime  = EE_Datetime::new_instance(
159
-            array(
160
-                'DTT_EVT_start' => $this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS,
161
-                'DTT_EVT_end'   => $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS,
162
-                'DTT_order'     => 1,
163
-                'DTT_reg_limit' => EE_INF,
164
-            ),
165
-            $timezone_string
166
-        );
167
-        $blank_datetime->set_start_time(
168
-            $this->convert_datetime_for_query(
169
-                'DTT_EVT_start',
170
-                '8am',
171
-                'ga',
172
-                $timezone_string
173
-            )
174
-        );
175
-        $blank_datetime->set_end_time(
176
-            $this->convert_datetime_for_query(
177
-                'DTT_EVT_end',
178
-                '5pm',
179
-                'ga',
180
-                $timezone_string
181
-            )
182
-        );
183
-        return array($blank_datetime);
184
-    }
185
-
186
-
187
-    /**
188
-     * get event start date from db
189
-     *
190
-     * @access public
191
-     * @param  int $EVT_ID
192
-     * @return EE_Datetime[] array on success, FALSE on fail
193
-     * @throws EE_Error
194
-     */
195
-    public function get_all_event_dates($EVT_ID = 0)
196
-    {
197
-        if (! $EVT_ID) { // on add_new_event event_id gets set to 0
198
-            return $this->create_new_blank_datetime();
199
-        }
200
-        $results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
201
-        if (empty($results)) {
202
-            return $this->create_new_blank_datetime();
203
-        }
204
-        return $results;
205
-    }
206
-
207
-
208
-    /**
209
-     * get all datetimes attached to an event ordered by the DTT_order field
210
-     *
211
-     * @public
212
-     * @param  int    $EVT_ID     event id
213
-     * @param boolean $include_expired
214
-     * @param boolean $include_deleted
215
-     * @param  int    $limit      If included then limit the count of results by
216
-     *                            the given number
217
-     * @return EE_Datetime[]
218
-     * @throws EE_Error
219
-     */
220
-    public function get_datetimes_for_event_ordered_by_DTT_order(
221
-        $EVT_ID,
222
-        $include_expired = true,
223
-        $include_deleted = true,
224
-        $limit = null
225
-    ) {
226
-        // sanitize EVT_ID
227
-        $EVT_ID         = absint($EVT_ID);
228
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
229
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
230
-        $where_params = array('Event.EVT_ID' => $EVT_ID);
231
-        $query_params = ! empty($limit)
232
-            ? array(
233
-                $where_params,
234
-                'limit'                    => $limit,
235
-                'order_by'                 => array('DTT_order' => 'ASC'),
236
-                'default_where_conditions' => 'none',
237
-            )
238
-            : array(
239
-                $where_params,
240
-                'order_by'                 => array('DTT_order' => 'ASC'),
241
-                'default_where_conditions' => 'none',
242
-            );
243
-        if (! $include_expired) {
244
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
245
-        }
246
-        if ($include_deleted) {
247
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
248
-        }
249
-        /** @var EE_Datetime[] $result */
250
-        $result = $this->get_all($query_params);
251
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
252
-        return $result;
253
-    }
254
-
255
-
256
-    /**
257
-     * Gets the datetimes for the event (with the given limit), and orders them by "importance".
258
-     * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
259
-     * and then the earlier datetimes are the most important.
260
-     * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
261
-     *
262
-     * @param int $EVT_ID
263
-     * @param int $limit
264
-     * @return EE_Datetime[]|EE_Base_Class[]
265
-     * @throws EE_Error
266
-     */
267
-    public function get_datetimes_for_event_ordered_by_importance($EVT_ID = 0, $limit = null)
268
-    {
269
-        return $this->get_all(
270
-            array(
271
-                array('Event.EVT_ID' => $EVT_ID),
272
-                'limit'                    => $limit,
273
-                'order_by'                 => array('DTT_EVT_start' => 'ASC'),
274
-                'default_where_conditions' => 'none',
275
-            )
276
-        );
277
-    }
278
-
279
-
280
-    /**
281
-     * @param int     $EVT_ID
282
-     * @param boolean $include_expired
283
-     * @param boolean $include_deleted
284
-     * @return EE_Datetime
285
-     * @throws EE_Error
286
-     */
287
-    public function get_oldest_datetime_for_event($EVT_ID, $include_expired = false, $include_deleted = false)
288
-    {
289
-        $results = $this->get_datetimes_for_event_ordered_by_start_time(
290
-            $EVT_ID,
291
-            $include_expired,
292
-            $include_deleted,
293
-            1
294
-        );
295
-        if ($results) {
296
-            return array_shift($results);
297
-        }
298
-        return null;
299
-    }
300
-
301
-
302
-    /**
303
-     * Gets the 'primary' datetime for an event.
304
-     *
305
-     * @param int  $EVT_ID
306
-     * @param bool $try_to_exclude_expired
307
-     * @param bool $try_to_exclude_deleted
308
-     * @return \EE_Datetime
309
-     * @throws EE_Error
310
-     */
311
-    public function get_primary_datetime_for_event(
312
-        $EVT_ID,
313
-        $try_to_exclude_expired = true,
314
-        $try_to_exclude_deleted = true
315
-    ) {
316
-        if ($try_to_exclude_expired) {
317
-            $non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
318
-            if ($non_expired) {
319
-                return $non_expired;
320
-            }
321
-        }
322
-        if ($try_to_exclude_deleted) {
323
-            $expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
324
-            if ($expired_even) {
325
-                return $expired_even;
326
-            }
327
-        }
328
-        return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
329
-    }
330
-
331
-
332
-    /**
333
-     * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
334
-     * only by start date
335
-     *
336
-     * @param int     $EVT_ID
337
-     * @param boolean $include_expired
338
-     * @param boolean $include_deleted
339
-     * @param int     $limit
340
-     * @return EE_Datetime[]
341
-     * @throws EE_Error
342
-     */
343
-    public function get_datetimes_for_event_ordered_by_start_time(
344
-        $EVT_ID,
345
-        $include_expired = true,
346
-        $include_deleted = true,
347
-        $limit = null
348
-    ) {
349
-        // sanitize EVT_ID
350
-        $EVT_ID         = absint($EVT_ID);
351
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
352
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
353
-        $query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
354
-        if (! $include_expired) {
355
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
356
-        }
357
-        if ($include_deleted) {
358
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
359
-        }
360
-        if ($limit) {
361
-            $query_params['limit'] = $limit;
362
-        }
363
-        /** @var EE_Datetime[] $result */
364
-        $result = $this->get_all($query_params);
365
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
366
-        return $result;
367
-    }
368
-
369
-
370
-    /**
371
-     * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
372
-     * only by start date
373
-     *
374
-     * @param int     $TKT_ID
375
-     * @param boolean $include_expired
376
-     * @param boolean $include_deleted
377
-     * @param int     $limit
378
-     * @return EE_Datetime[]
379
-     * @throws EE_Error
380
-     */
381
-    public function get_datetimes_for_ticket_ordered_by_start_time(
382
-        $TKT_ID,
383
-        $include_expired = true,
384
-        $include_deleted = true,
385
-        $limit = null
386
-    ) {
387
-        // sanitize TKT_ID
388
-        $TKT_ID         = absint($TKT_ID);
389
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
390
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
391
-        $query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
392
-        if (! $include_expired) {
393
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
394
-        }
395
-        if ($include_deleted) {
396
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
397
-        }
398
-        if ($limit) {
399
-            $query_params['limit'] = $limit;
400
-        }
401
-        /** @var EE_Datetime[] $result */
402
-        $result = $this->get_all($query_params);
403
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
404
-        return $result;
405
-    }
406
-
407
-
408
-    /**
409
-     * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
410
-     * datetimes.
411
-     *
412
-     * @param  int      $TKT_ID          ID of ticket to retrieve the datetimes for
413
-     * @param  boolean  $include_expired whether to include expired datetimes or not
414
-     * @param  boolean  $include_deleted whether to include trashed datetimes or not.
415
-     * @param  int|null $limit           if null, no limit, if int then limit results by
416
-     *                                   that number
417
-     * @return EE_Datetime[]
418
-     * @throws EE_Error
419
-     */
420
-    public function get_datetimes_for_ticket_ordered_by_DTT_order(
421
-        $TKT_ID,
422
-        $include_expired = true,
423
-        $include_deleted = true,
424
-        $limit = null
425
-    ) {
426
-        // sanitize id.
427
-        $TKT_ID         = absint($TKT_ID);
428
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
429
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
430
-        $where_params = array('Ticket.TKT_ID' => $TKT_ID);
431
-        $query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
432
-        if (! $include_expired) {
433
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
434
-        }
435
-        if ($include_deleted) {
436
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
437
-        }
438
-        if ($limit) {
439
-            $query_params['limit'] = $limit;
440
-        }
441
-        /** @var EE_Datetime[] $result */
442
-        $result = $this->get_all($query_params);
443
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
444
-        return $result;
445
-    }
446
-
447
-
448
-    /**
449
-     * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
450
-     * reason it doesn't exist, we consider the earliest event the most important)
451
-     *
452
-     * @param int $EVT_ID
453
-     * @return EE_Datetime
454
-     * @throws EE_Error
455
-     */
456
-    public function get_most_important_datetime_for_event($EVT_ID)
457
-    {
458
-        $results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
459
-        if ($results) {
460
-            return array_shift($results);
461
-        }
462
-        return null;
463
-    }
464
-
465
-
466
-    /**
467
-     * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
468
-     * grouped by month and year.
469
-     *
470
-     * @param  array  $where_params      @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
471
-     * @param  string $evt_active_status A string representing the evt active status to filter the months by.
472
-     *                                   Can be:
473
-     *                                   - '' = no filter
474
-     *                                   - upcoming = Published events with at least one upcoming datetime.
475
-     *                                   - expired = Events with all datetimes expired.
476
-     *                                   - active = Events that are published and have at least one datetime that
477
-     *                                   starts before now and ends after now.
478
-     *                                   - inactive = Events that are either not published.
479
-     * @return EE_Base_Class[]
480
-     * @throws EE_Error
481
-     * @throws InvalidArgumentException
482
-     * @throws InvalidArgumentException
483
-     */
484
-    public function get_dtt_months_and_years($where_params, $evt_active_status = '')
485
-    {
486
-        $current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
487
-        $current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
488
-        switch ($evt_active_status) {
489
-            case 'upcoming':
490
-                $where_params['Event.status'] = 'publish';
491
-                // if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
492
-                if (isset($where_params['DTT_EVT_start'])) {
493
-                    $where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
494
-                }
495
-                $where_params['DTT_EVT_start'] = array('>', $current_time_for_DTT_EVT_start);
496
-                break;
497
-            case 'expired':
498
-                if (isset($where_params['Event.status'])) {
499
-                    unset($where_params['Event.status']);
500
-                }
501
-                // get events to exclude
502
-                $exclude_query[0] = array_merge(
503
-                    $where_params,
504
-                    array('DTT_EVT_end' => array('>', $current_time_for_DTT_EVT_end))
505
-                );
506
-                // first get all events that have datetimes where its not expired.
507
-                $event_ids = $this->_get_all_wpdb_results(
508
-                    $exclude_query,
509
-                    OBJECT_K,
510
-                    'Datetime.EVT_ID'
511
-                );
512
-                $event_ids = array_keys($event_ids);
513
-                if (isset($where_params['DTT_EVT_end'])) {
514
-                    $where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
515
-                }
516
-                $where_params['DTT_EVT_end']  = array('<', $current_time_for_DTT_EVT_end);
517
-                $where_params['Event.EVT_ID'] = array('NOT IN', $event_ids);
518
-                break;
519
-            case 'active':
520
-                $where_params['Event.status'] = 'publish';
521
-                if (isset($where_params['DTT_EVT_start'])) {
522
-                    $where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
523
-                }
524
-                if (isset($where_params['Datetime.DTT_EVT_end'])) {
525
-                    $where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
526
-                }
527
-                $where_params['DTT_EVT_start'] = array('<', $current_time_for_DTT_EVT_start);
528
-                $where_params['DTT_EVT_end']   = array('>', $current_time_for_DTT_EVT_end);
529
-                break;
530
-            case 'inactive':
531
-                if (isset($where_params['Event.status'])) {
532
-                    unset($where_params['Event.status']);
533
-                }
534
-                if (isset($where_params['OR'])) {
535
-                    $where_params['AND']['OR'] = $where_params['OR'];
536
-                }
537
-                if (isset($where_params['DTT_EVT_end'])) {
538
-                    $where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
539
-                    unset($where_params['DTT_EVT_end']);
540
-                }
541
-                if (isset($where_params['DTT_EVT_start'])) {
542
-                    $where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
543
-                    unset($where_params['DTT_EVT_start']);
544
-                }
545
-                $where_params['AND']['Event.status'] = array('!=', 'publish');
546
-                break;
547
-        }
548
-        $query_params[0]          = $where_params;
549
-        $query_params['group_by'] = array('dtt_year', 'dtt_month');
550
-        $query_params['order_by'] = array('DTT_EVT_start' => 'DESC');
551
-        $query_interval           = EEH_DTT_Helper::get_sql_query_interval_for_offset(
552
-            $this->get_timezone(),
553
-            'DTT_EVT_start'
554
-        );
555
-        $columns_to_select        = array(
556
-            'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
557
-            'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
558
-            'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
559
-        );
560
-        return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
561
-    }
562
-
563
-
564
-    /**
565
-     * Updates the DTT_sold attribute on each datetime (based on the registrations
566
-     * for the tickets for each datetime)
567
-     *
568
-     * @param EE_Base_Class[]|EE_Datetime[] $datetimes
569
-     * @throws EE_Error
570
-     */
571
-    public function update_sold($datetimes)
572
-    {
573
-        EE_Error::doing_it_wrong(
574
-            __FUNCTION__,
575
-            esc_html__(
576
-                'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
577
-                'event_espresso'
578
-            ),
579
-            '4.9.32.rc.005'
580
-        );
581
-        foreach ($datetimes as $datetime) {
582
-            $datetime->update_sold();
583
-        }
584
-    }
585
-
586
-
587
-    /**
588
-     *    Gets the total number of tickets available at a particular datetime
589
-     *    (does NOT take into account the datetime's spaces available)
590
-     *
591
-     * @param int   $DTT_ID
592
-     * @param array $query_params
593
-     * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
594
-     *             tickets attached to datetime then FALSE is returned.
595
-     */
596
-    public function sum_tickets_currently_available_at_datetime($DTT_ID, array $query_params = array())
597
-    {
598
-        $datetime = $this->get_one_by_ID($DTT_ID);
599
-        if ($datetime instanceof EE_Datetime) {
600
-            return $datetime->tickets_remaining($query_params);
601
-        }
602
-        return 0;
603
-    }
604
-
605
-
606
-    /**
607
-     * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
608
-     *
609
-     * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
610
-     *                                 stati you want counts for as values in the array.  An empty array returns counts
611
-     *                                 for all valid stati.
612
-     * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
613
-     *                                 only for Datetimes connected to a specific event, or specific ticket.
614
-     * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
615
-     * @throws EE_Error
616
-     *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming
617
-     *                                 EE_Datetime::expired
618
-     */
619
-    public function get_datetime_counts_by_status(array $stati_to_include = array(), array $query_params = array())
620
-    {
621
-        // only accept where conditions for this query.
622
-        $_where            = isset($query_params[0]) ? $query_params[0] : array();
623
-        $status_query_args = array(
624
-            EE_Datetime::active   => array_merge(
625
-                $_where,
626
-                array('DTT_EVT_start' => array('<', time()), 'DTT_EVT_end' => array('>', time()))
627
-            ),
628
-            EE_Datetime::upcoming => array_merge(
629
-                $_where,
630
-                array('DTT_EVT_start' => array('>', time()))
631
-            ),
632
-            EE_Datetime::expired  => array_merge(
633
-                $_where,
634
-                array('DTT_EVT_end' => array('<', time()))
635
-            ),
636
-        );
637
-        if (! empty($stati_to_include)) {
638
-            foreach (array_keys($status_query_args) as $status) {
639
-                if (! in_array($status, $stati_to_include, true)) {
640
-                    unset($status_query_args[ $status ]);
641
-                }
642
-            }
643
-        }
644
-        // loop through and query counts for each stati.
645
-        $status_query_results = array();
646
-        foreach ($status_query_args as $status => $status_where_conditions) {
647
-            $status_query_results[ $status ] = EEM_Datetime::count(
648
-                array($status_where_conditions),
649
-                'DTT_ID',
650
-                true
651
-            );
652
-        }
653
-        return $status_query_results;
654
-    }
655
-
656
-
657
-    /**
658
-     * Returns the specific count for a given Datetime status matching any given query_params.
659
-     *
660
-     * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
661
-     * @param array  $query_params
662
-     * @return int
663
-     * @throws EE_Error
664
-     */
665
-    public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = array())
666
-    {
667
-        $count = $this->get_datetime_counts_by_status(array($status), $query_params);
668
-        return ! empty($count[ $status ]) ? $count[ $status ] : 0;
669
-    }
12
+	/**
13
+	 * @var EEM_Datetime $_instance
14
+	 */
15
+	protected static $_instance;
16
+
17
+
18
+	/**
19
+	 * private constructor to prevent direct creation
20
+	 *
21
+	 * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
22
+	 *                         (and any incoming timezone data that gets saved).
23
+	 *                         Note this just sends the timezone info to the date time model field objects.
24
+	 *                         Default is NULL
25
+	 *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
26
+	 * @throws EE_Error
27
+	 * @throws InvalidArgumentException
28
+	 * @throws InvalidArgumentException
29
+	 */
30
+	protected function __construct($timezone)
31
+	{
32
+		$this->singular_item           = esc_html__('Datetime', 'event_espresso');
33
+		$this->plural_item             = esc_html__('Datetimes', 'event_espresso');
34
+		$this->_tables                 = array(
35
+			'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
36
+		);
37
+		$this->_fields                 = array(
38
+			'Datetime' => array(
39
+				'DTT_ID'          => new EE_Primary_Key_Int_Field(
40
+					'DTT_ID',
41
+					esc_html__('Datetime ID', 'event_espresso')
42
+				),
43
+				'EVT_ID'          => new EE_Foreign_Key_Int_Field(
44
+					'EVT_ID',
45
+					esc_html__('Event ID', 'event_espresso'),
46
+					false,
47
+					0,
48
+					'Event'
49
+				),
50
+				'DTT_name'        => new EE_Plain_Text_Field(
51
+					'DTT_name',
52
+					esc_html__('Datetime Name', 'event_espresso'),
53
+					false,
54
+					''
55
+				),
56
+				'DTT_description' => new EE_Post_Content_Field(
57
+					'DTT_description',
58
+					esc_html__('Description for Datetime', 'event_espresso'),
59
+					false,
60
+					''
61
+				),
62
+				'DTT_EVT_start'   => new EE_Datetime_Field(
63
+					'DTT_EVT_start',
64
+					esc_html__('Start time/date of Event', 'event_espresso'),
65
+					false,
66
+					EE_Datetime_Field::now,
67
+					$timezone
68
+				),
69
+				'DTT_EVT_end'     => new EE_Datetime_Field(
70
+					'DTT_EVT_end',
71
+					esc_html__('End time/date of Event', 'event_espresso'),
72
+					false,
73
+					EE_Datetime_Field::now,
74
+					$timezone
75
+				),
76
+				'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
77
+					'DTT_reg_limit',
78
+					esc_html__('Registration Limit for this time', 'event_espresso'),
79
+					true,
80
+					EE_INF
81
+				),
82
+				'DTT_sold'        => new EE_Integer_Field(
83
+					'DTT_sold',
84
+					esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
85
+					true,
86
+					0
87
+				),
88
+				'DTT_reserved'    => new EE_Integer_Field(
89
+					'DTT_reserved',
90
+					esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
91
+					false,
92
+					0
93
+				),
94
+				'DTT_is_primary'  => new EE_Boolean_Field(
95
+					'DTT_is_primary',
96
+					esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
97
+					false,
98
+					false
99
+				),
100
+				'DTT_order'       => new EE_Integer_Field(
101
+					'DTT_order',
102
+					esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
103
+					false,
104
+					0
105
+				),
106
+				'DTT_parent'      => new EE_Integer_Field(
107
+					'DTT_parent',
108
+					esc_html__('Indicates what DTT_ID is the parent of this DTT_ID', 'event_espresso'),
109
+					true,
110
+					0
111
+				),
112
+				'DTT_deleted'     => new EE_Trashed_Flag_Field(
113
+					'DTT_deleted',
114
+					esc_html__('Flag indicating datetime is archived', 'event_espresso'),
115
+					false,
116
+					false
117
+				),
118
+			),
119
+		);
120
+		$this->_model_relations        = array(
121
+			'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
122
+			'Event'   => new EE_Belongs_To_Relation(),
123
+			'Checkin' => new EE_Has_Many_Relation(),
124
+			'Datetime_Ticket' => new EE_Has_Many_Relation(),
125
+		);
126
+		$path_to_event_model = 'Event';
127
+		$this->model_chain_to_password = $path_to_event_model;
128
+		$this->_model_chain_to_wp_user = $path_to_event_model;
129
+		// this model is generally available for reading
130
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Event_Related_Public(
131
+			$path_to_event_model
132
+		);
133
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
134
+			$path_to_event_model
135
+		);
136
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Event_Related_Protected(
137
+			$path_to_event_model
138
+		);
139
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Event_Related_Protected(
140
+			$path_to_event_model,
141
+			EEM_Base::caps_edit
142
+		);
143
+		parent::__construct($timezone);
144
+	}
145
+
146
+
147
+	/**
148
+	 * create new blank datetime
149
+	 *
150
+	 * @access public
151
+	 * @return EE_Datetime[] array on success, FALSE on fail
152
+	 * @throws EE_Error
153
+	 */
154
+	public function create_new_blank_datetime()
155
+	{
156
+		// makes sure timezone is always set.
157
+		$timezone_string = $this->get_timezone();
158
+		$blank_datetime  = EE_Datetime::new_instance(
159
+			array(
160
+				'DTT_EVT_start' => $this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS,
161
+				'DTT_EVT_end'   => $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS,
162
+				'DTT_order'     => 1,
163
+				'DTT_reg_limit' => EE_INF,
164
+			),
165
+			$timezone_string
166
+		);
167
+		$blank_datetime->set_start_time(
168
+			$this->convert_datetime_for_query(
169
+				'DTT_EVT_start',
170
+				'8am',
171
+				'ga',
172
+				$timezone_string
173
+			)
174
+		);
175
+		$blank_datetime->set_end_time(
176
+			$this->convert_datetime_for_query(
177
+				'DTT_EVT_end',
178
+				'5pm',
179
+				'ga',
180
+				$timezone_string
181
+			)
182
+		);
183
+		return array($blank_datetime);
184
+	}
185
+
186
+
187
+	/**
188
+	 * get event start date from db
189
+	 *
190
+	 * @access public
191
+	 * @param  int $EVT_ID
192
+	 * @return EE_Datetime[] array on success, FALSE on fail
193
+	 * @throws EE_Error
194
+	 */
195
+	public function get_all_event_dates($EVT_ID = 0)
196
+	{
197
+		if (! $EVT_ID) { // on add_new_event event_id gets set to 0
198
+			return $this->create_new_blank_datetime();
199
+		}
200
+		$results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
201
+		if (empty($results)) {
202
+			return $this->create_new_blank_datetime();
203
+		}
204
+		return $results;
205
+	}
206
+
207
+
208
+	/**
209
+	 * get all datetimes attached to an event ordered by the DTT_order field
210
+	 *
211
+	 * @public
212
+	 * @param  int    $EVT_ID     event id
213
+	 * @param boolean $include_expired
214
+	 * @param boolean $include_deleted
215
+	 * @param  int    $limit      If included then limit the count of results by
216
+	 *                            the given number
217
+	 * @return EE_Datetime[]
218
+	 * @throws EE_Error
219
+	 */
220
+	public function get_datetimes_for_event_ordered_by_DTT_order(
221
+		$EVT_ID,
222
+		$include_expired = true,
223
+		$include_deleted = true,
224
+		$limit = null
225
+	) {
226
+		// sanitize EVT_ID
227
+		$EVT_ID         = absint($EVT_ID);
228
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
229
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
230
+		$where_params = array('Event.EVT_ID' => $EVT_ID);
231
+		$query_params = ! empty($limit)
232
+			? array(
233
+				$where_params,
234
+				'limit'                    => $limit,
235
+				'order_by'                 => array('DTT_order' => 'ASC'),
236
+				'default_where_conditions' => 'none',
237
+			)
238
+			: array(
239
+				$where_params,
240
+				'order_by'                 => array('DTT_order' => 'ASC'),
241
+				'default_where_conditions' => 'none',
242
+			);
243
+		if (! $include_expired) {
244
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
245
+		}
246
+		if ($include_deleted) {
247
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
248
+		}
249
+		/** @var EE_Datetime[] $result */
250
+		$result = $this->get_all($query_params);
251
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
252
+		return $result;
253
+	}
254
+
255
+
256
+	/**
257
+	 * Gets the datetimes for the event (with the given limit), and orders them by "importance".
258
+	 * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
259
+	 * and then the earlier datetimes are the most important.
260
+	 * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
261
+	 *
262
+	 * @param int $EVT_ID
263
+	 * @param int $limit
264
+	 * @return EE_Datetime[]|EE_Base_Class[]
265
+	 * @throws EE_Error
266
+	 */
267
+	public function get_datetimes_for_event_ordered_by_importance($EVT_ID = 0, $limit = null)
268
+	{
269
+		return $this->get_all(
270
+			array(
271
+				array('Event.EVT_ID' => $EVT_ID),
272
+				'limit'                    => $limit,
273
+				'order_by'                 => array('DTT_EVT_start' => 'ASC'),
274
+				'default_where_conditions' => 'none',
275
+			)
276
+		);
277
+	}
278
+
279
+
280
+	/**
281
+	 * @param int     $EVT_ID
282
+	 * @param boolean $include_expired
283
+	 * @param boolean $include_deleted
284
+	 * @return EE_Datetime
285
+	 * @throws EE_Error
286
+	 */
287
+	public function get_oldest_datetime_for_event($EVT_ID, $include_expired = false, $include_deleted = false)
288
+	{
289
+		$results = $this->get_datetimes_for_event_ordered_by_start_time(
290
+			$EVT_ID,
291
+			$include_expired,
292
+			$include_deleted,
293
+			1
294
+		);
295
+		if ($results) {
296
+			return array_shift($results);
297
+		}
298
+		return null;
299
+	}
300
+
301
+
302
+	/**
303
+	 * Gets the 'primary' datetime for an event.
304
+	 *
305
+	 * @param int  $EVT_ID
306
+	 * @param bool $try_to_exclude_expired
307
+	 * @param bool $try_to_exclude_deleted
308
+	 * @return \EE_Datetime
309
+	 * @throws EE_Error
310
+	 */
311
+	public function get_primary_datetime_for_event(
312
+		$EVT_ID,
313
+		$try_to_exclude_expired = true,
314
+		$try_to_exclude_deleted = true
315
+	) {
316
+		if ($try_to_exclude_expired) {
317
+			$non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
318
+			if ($non_expired) {
319
+				return $non_expired;
320
+			}
321
+		}
322
+		if ($try_to_exclude_deleted) {
323
+			$expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
324
+			if ($expired_even) {
325
+				return $expired_even;
326
+			}
327
+		}
328
+		return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
329
+	}
330
+
331
+
332
+	/**
333
+	 * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
334
+	 * only by start date
335
+	 *
336
+	 * @param int     $EVT_ID
337
+	 * @param boolean $include_expired
338
+	 * @param boolean $include_deleted
339
+	 * @param int     $limit
340
+	 * @return EE_Datetime[]
341
+	 * @throws EE_Error
342
+	 */
343
+	public function get_datetimes_for_event_ordered_by_start_time(
344
+		$EVT_ID,
345
+		$include_expired = true,
346
+		$include_deleted = true,
347
+		$limit = null
348
+	) {
349
+		// sanitize EVT_ID
350
+		$EVT_ID         = absint($EVT_ID);
351
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
352
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
353
+		$query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
354
+		if (! $include_expired) {
355
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
356
+		}
357
+		if ($include_deleted) {
358
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
359
+		}
360
+		if ($limit) {
361
+			$query_params['limit'] = $limit;
362
+		}
363
+		/** @var EE_Datetime[] $result */
364
+		$result = $this->get_all($query_params);
365
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
366
+		return $result;
367
+	}
368
+
369
+
370
+	/**
371
+	 * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
372
+	 * only by start date
373
+	 *
374
+	 * @param int     $TKT_ID
375
+	 * @param boolean $include_expired
376
+	 * @param boolean $include_deleted
377
+	 * @param int     $limit
378
+	 * @return EE_Datetime[]
379
+	 * @throws EE_Error
380
+	 */
381
+	public function get_datetimes_for_ticket_ordered_by_start_time(
382
+		$TKT_ID,
383
+		$include_expired = true,
384
+		$include_deleted = true,
385
+		$limit = null
386
+	) {
387
+		// sanitize TKT_ID
388
+		$TKT_ID         = absint($TKT_ID);
389
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
390
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
391
+		$query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
392
+		if (! $include_expired) {
393
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
394
+		}
395
+		if ($include_deleted) {
396
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
397
+		}
398
+		if ($limit) {
399
+			$query_params['limit'] = $limit;
400
+		}
401
+		/** @var EE_Datetime[] $result */
402
+		$result = $this->get_all($query_params);
403
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
404
+		return $result;
405
+	}
406
+
407
+
408
+	/**
409
+	 * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
410
+	 * datetimes.
411
+	 *
412
+	 * @param  int      $TKT_ID          ID of ticket to retrieve the datetimes for
413
+	 * @param  boolean  $include_expired whether to include expired datetimes or not
414
+	 * @param  boolean  $include_deleted whether to include trashed datetimes or not.
415
+	 * @param  int|null $limit           if null, no limit, if int then limit results by
416
+	 *                                   that number
417
+	 * @return EE_Datetime[]
418
+	 * @throws EE_Error
419
+	 */
420
+	public function get_datetimes_for_ticket_ordered_by_DTT_order(
421
+		$TKT_ID,
422
+		$include_expired = true,
423
+		$include_deleted = true,
424
+		$limit = null
425
+	) {
426
+		// sanitize id.
427
+		$TKT_ID         = absint($TKT_ID);
428
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
429
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
430
+		$where_params = array('Ticket.TKT_ID' => $TKT_ID);
431
+		$query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
432
+		if (! $include_expired) {
433
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
434
+		}
435
+		if ($include_deleted) {
436
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
437
+		}
438
+		if ($limit) {
439
+			$query_params['limit'] = $limit;
440
+		}
441
+		/** @var EE_Datetime[] $result */
442
+		$result = $this->get_all($query_params);
443
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
444
+		return $result;
445
+	}
446
+
447
+
448
+	/**
449
+	 * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
450
+	 * reason it doesn't exist, we consider the earliest event the most important)
451
+	 *
452
+	 * @param int $EVT_ID
453
+	 * @return EE_Datetime
454
+	 * @throws EE_Error
455
+	 */
456
+	public function get_most_important_datetime_for_event($EVT_ID)
457
+	{
458
+		$results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
459
+		if ($results) {
460
+			return array_shift($results);
461
+		}
462
+		return null;
463
+	}
464
+
465
+
466
+	/**
467
+	 * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
468
+	 * grouped by month and year.
469
+	 *
470
+	 * @param  array  $where_params      @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
471
+	 * @param  string $evt_active_status A string representing the evt active status to filter the months by.
472
+	 *                                   Can be:
473
+	 *                                   - '' = no filter
474
+	 *                                   - upcoming = Published events with at least one upcoming datetime.
475
+	 *                                   - expired = Events with all datetimes expired.
476
+	 *                                   - active = Events that are published and have at least one datetime that
477
+	 *                                   starts before now and ends after now.
478
+	 *                                   - inactive = Events that are either not published.
479
+	 * @return EE_Base_Class[]
480
+	 * @throws EE_Error
481
+	 * @throws InvalidArgumentException
482
+	 * @throws InvalidArgumentException
483
+	 */
484
+	public function get_dtt_months_and_years($where_params, $evt_active_status = '')
485
+	{
486
+		$current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
487
+		$current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
488
+		switch ($evt_active_status) {
489
+			case 'upcoming':
490
+				$where_params['Event.status'] = 'publish';
491
+				// if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
492
+				if (isset($where_params['DTT_EVT_start'])) {
493
+					$where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
494
+				}
495
+				$where_params['DTT_EVT_start'] = array('>', $current_time_for_DTT_EVT_start);
496
+				break;
497
+			case 'expired':
498
+				if (isset($where_params['Event.status'])) {
499
+					unset($where_params['Event.status']);
500
+				}
501
+				// get events to exclude
502
+				$exclude_query[0] = array_merge(
503
+					$where_params,
504
+					array('DTT_EVT_end' => array('>', $current_time_for_DTT_EVT_end))
505
+				);
506
+				// first get all events that have datetimes where its not expired.
507
+				$event_ids = $this->_get_all_wpdb_results(
508
+					$exclude_query,
509
+					OBJECT_K,
510
+					'Datetime.EVT_ID'
511
+				);
512
+				$event_ids = array_keys($event_ids);
513
+				if (isset($where_params['DTT_EVT_end'])) {
514
+					$where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
515
+				}
516
+				$where_params['DTT_EVT_end']  = array('<', $current_time_for_DTT_EVT_end);
517
+				$where_params['Event.EVT_ID'] = array('NOT IN', $event_ids);
518
+				break;
519
+			case 'active':
520
+				$where_params['Event.status'] = 'publish';
521
+				if (isset($where_params['DTT_EVT_start'])) {
522
+					$where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
523
+				}
524
+				if (isset($where_params['Datetime.DTT_EVT_end'])) {
525
+					$where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
526
+				}
527
+				$where_params['DTT_EVT_start'] = array('<', $current_time_for_DTT_EVT_start);
528
+				$where_params['DTT_EVT_end']   = array('>', $current_time_for_DTT_EVT_end);
529
+				break;
530
+			case 'inactive':
531
+				if (isset($where_params['Event.status'])) {
532
+					unset($where_params['Event.status']);
533
+				}
534
+				if (isset($where_params['OR'])) {
535
+					$where_params['AND']['OR'] = $where_params['OR'];
536
+				}
537
+				if (isset($where_params['DTT_EVT_end'])) {
538
+					$where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
539
+					unset($where_params['DTT_EVT_end']);
540
+				}
541
+				if (isset($where_params['DTT_EVT_start'])) {
542
+					$where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
543
+					unset($where_params['DTT_EVT_start']);
544
+				}
545
+				$where_params['AND']['Event.status'] = array('!=', 'publish');
546
+				break;
547
+		}
548
+		$query_params[0]          = $where_params;
549
+		$query_params['group_by'] = array('dtt_year', 'dtt_month');
550
+		$query_params['order_by'] = array('DTT_EVT_start' => 'DESC');
551
+		$query_interval           = EEH_DTT_Helper::get_sql_query_interval_for_offset(
552
+			$this->get_timezone(),
553
+			'DTT_EVT_start'
554
+		);
555
+		$columns_to_select        = array(
556
+			'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
557
+			'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
558
+			'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
559
+		);
560
+		return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
561
+	}
562
+
563
+
564
+	/**
565
+	 * Updates the DTT_sold attribute on each datetime (based on the registrations
566
+	 * for the tickets for each datetime)
567
+	 *
568
+	 * @param EE_Base_Class[]|EE_Datetime[] $datetimes
569
+	 * @throws EE_Error
570
+	 */
571
+	public function update_sold($datetimes)
572
+	{
573
+		EE_Error::doing_it_wrong(
574
+			__FUNCTION__,
575
+			esc_html__(
576
+				'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
577
+				'event_espresso'
578
+			),
579
+			'4.9.32.rc.005'
580
+		);
581
+		foreach ($datetimes as $datetime) {
582
+			$datetime->update_sold();
583
+		}
584
+	}
585
+
586
+
587
+	/**
588
+	 *    Gets the total number of tickets available at a particular datetime
589
+	 *    (does NOT take into account the datetime's spaces available)
590
+	 *
591
+	 * @param int   $DTT_ID
592
+	 * @param array $query_params
593
+	 * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
594
+	 *             tickets attached to datetime then FALSE is returned.
595
+	 */
596
+	public function sum_tickets_currently_available_at_datetime($DTT_ID, array $query_params = array())
597
+	{
598
+		$datetime = $this->get_one_by_ID($DTT_ID);
599
+		if ($datetime instanceof EE_Datetime) {
600
+			return $datetime->tickets_remaining($query_params);
601
+		}
602
+		return 0;
603
+	}
604
+
605
+
606
+	/**
607
+	 * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
608
+	 *
609
+	 * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
610
+	 *                                 stati you want counts for as values in the array.  An empty array returns counts
611
+	 *                                 for all valid stati.
612
+	 * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
613
+	 *                                 only for Datetimes connected to a specific event, or specific ticket.
614
+	 * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
615
+	 * @throws EE_Error
616
+	 *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming
617
+	 *                                 EE_Datetime::expired
618
+	 */
619
+	public function get_datetime_counts_by_status(array $stati_to_include = array(), array $query_params = array())
620
+	{
621
+		// only accept where conditions for this query.
622
+		$_where            = isset($query_params[0]) ? $query_params[0] : array();
623
+		$status_query_args = array(
624
+			EE_Datetime::active   => array_merge(
625
+				$_where,
626
+				array('DTT_EVT_start' => array('<', time()), 'DTT_EVT_end' => array('>', time()))
627
+			),
628
+			EE_Datetime::upcoming => array_merge(
629
+				$_where,
630
+				array('DTT_EVT_start' => array('>', time()))
631
+			),
632
+			EE_Datetime::expired  => array_merge(
633
+				$_where,
634
+				array('DTT_EVT_end' => array('<', time()))
635
+			),
636
+		);
637
+		if (! empty($stati_to_include)) {
638
+			foreach (array_keys($status_query_args) as $status) {
639
+				if (! in_array($status, $stati_to_include, true)) {
640
+					unset($status_query_args[ $status ]);
641
+				}
642
+			}
643
+		}
644
+		// loop through and query counts for each stati.
645
+		$status_query_results = array();
646
+		foreach ($status_query_args as $status => $status_where_conditions) {
647
+			$status_query_results[ $status ] = EEM_Datetime::count(
648
+				array($status_where_conditions),
649
+				'DTT_ID',
650
+				true
651
+			);
652
+		}
653
+		return $status_query_results;
654
+	}
655
+
656
+
657
+	/**
658
+	 * Returns the specific count for a given Datetime status matching any given query_params.
659
+	 *
660
+	 * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
661
+	 * @param array  $query_params
662
+	 * @return int
663
+	 * @throws EE_Error
664
+	 */
665
+	public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = array())
666
+	{
667
+		$count = $this->get_datetime_counts_by_status(array($status), $query_params);
668
+		return ! empty($count[ $status ]) ? $count[ $status ] : 0;
669
+	}
670 670
 }
Please login to merge, or discard this patch.
admin_pages/registrations/Registrations_Admin_Page.core.php 2 patches
Indentation   +3823 added lines, -3823 removed lines patch added patch discarded remove patch
@@ -19,2396 +19,2396 @@  discard block
 block discarded – undo
19 19
 class Registrations_Admin_Page extends EE_Admin_Page_CPT
20 20
 {
21 21
 
22
-    /**
23
-     * @var EE_Registration
24
-     */
25
-    private $_registration;
26
-
27
-    /**
28
-     * @var EE_Event
29
-     */
30
-    private $_reg_event;
31
-
32
-    /**
33
-     * @var EE_Session
34
-     */
35
-    private $_session;
36
-
37
-    private static $_reg_status;
38
-
39
-    /**
40
-     * Form for displaying the custom questions for this registration.
41
-     * This gets used a few times throughout the request so its best to cache it
42
-     *
43
-     * @var EE_Registration_Custom_Questions_Form
44
-     */
45
-    protected $_reg_custom_questions_form = null;
46
-
47
-
48
-    /**
49
-     *        constructor
50
-     *
51
-     * @Constructor
52
-     * @access public
53
-     * @param bool $routing
54
-     * @return Registrations_Admin_Page
55
-     */
56
-    public function __construct($routing = true)
57
-    {
58
-        parent::__construct($routing);
59
-        add_action('wp_loaded', array($this, 'wp_loaded'));
60
-    }
61
-
62
-
63
-    public function wp_loaded()
64
-    {
65
-        // when adding a new registration...
66
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
67
-            EE_System::do_not_cache();
68
-            if (! isset($this->_req_data['processing_registration'])
69
-                || absint($this->_req_data['processing_registration']) !== 1
70
-            ) {
71
-                // and it's NOT the attendee information reg step
72
-                // force cookie expiration by setting time to last week
73
-                setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
74
-                // and update the global
75
-                $_COOKIE['ee_registration_added'] = 0;
76
-            }
77
-        }
78
-    }
79
-
80
-
81
-    protected function _init_page_props()
82
-    {
83
-        $this->page_slug = REG_PG_SLUG;
84
-        $this->_admin_base_url = REG_ADMIN_URL;
85
-        $this->_admin_base_path = REG_ADMIN;
86
-        $this->page_label = esc_html__('Registrations', 'event_espresso');
87
-        $this->_cpt_routes = array(
88
-            'add_new_attendee' => 'espresso_attendees',
89
-            'edit_attendee'    => 'espresso_attendees',
90
-            'insert_attendee'  => 'espresso_attendees',
91
-            'update_attendee'  => 'espresso_attendees',
92
-        );
93
-        $this->_cpt_model_names = array(
94
-            'add_new_attendee' => 'EEM_Attendee',
95
-            'edit_attendee'    => 'EEM_Attendee',
96
-        );
97
-        $this->_cpt_edit_routes = array(
98
-            'espresso_attendees' => 'edit_attendee',
99
-        );
100
-        $this->_pagenow_map = array(
101
-            'add_new_attendee' => 'post-new.php',
102
-            'edit_attendee'    => 'post.php',
103
-            'trash'            => 'post.php',
104
-        );
105
-        add_action('edit_form_after_title', array($this, 'after_title_form_fields'), 10);
106
-        // add filters so that the comment urls don't take users to a confusing 404 page
107
-        add_filter('get_comment_link', array($this, 'clear_comment_link'), 10, 3);
108
-    }
109
-
110
-
111
-    public function clear_comment_link($link, $comment, $args)
112
-    {
113
-        // gotta make sure this only happens on this route
114
-        $post_type = get_post_type($comment->comment_post_ID);
115
-        if ($post_type === 'espresso_attendees') {
116
-            return '#commentsdiv';
117
-        }
118
-        return $link;
119
-    }
120
-
121
-
122
-    protected function _ajax_hooks()
123
-    {
124
-        // todo: all hooks for registrations ajax goes in here
125
-        add_action('wp_ajax_toggle_checkin_status', array($this, 'toggle_checkin_status'));
126
-    }
127
-
128
-
129
-    protected function _define_page_props()
130
-    {
131
-        $this->_admin_page_title = $this->page_label;
132
-        $this->_labels = array(
133
-            'buttons'                      => array(
134
-                'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
135
-                'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
136
-                'edit'                => esc_html__('Edit Contact', 'event_espresso'),
137
-                'report'              => esc_html__("Event Registrations CSV Report", "event_espresso"),
138
-                'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
139
-                'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
140
-                'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
141
-                'contact_list_export' => esc_html__("Export Data", "event_espresso"),
142
-            ),
143
-            'publishbox'                   => array(
144
-                'add_new_attendee' => esc_html__("Add Contact Record", 'event_espresso'),
145
-                'edit_attendee'    => esc_html__("Update Contact Record", 'event_espresso'),
146
-            ),
147
-            'hide_add_button_on_cpt_route' => array(
148
-                'edit_attendee' => true,
149
-            ),
150
-        );
151
-    }
152
-
153
-
154
-    /**
155
-     *        grab url requests and route them
156
-     *
157
-     * @access private
158
-     * @return void
159
-     */
160
-    public function _set_page_routes()
161
-    {
162
-        $this->_get_registration_status_array();
163
-        $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
164
-            ? $this->_req_data['_REG_ID'] : 0;
165
-        $reg_id = empty($reg_id) && ! empty($this->_req_data['reg_status_change_form']['REG_ID'])
166
-            ? $this->_req_data['reg_status_change_form']['REG_ID']
167
-            : $reg_id;
168
-        $att_id = ! empty($this->_req_data['ATT_ID']) && ! is_array($this->_req_data['ATT_ID'])
169
-            ? $this->_req_data['ATT_ID'] : 0;
170
-        $att_id = ! empty($this->_req_data['post']) && ! is_array($this->_req_data['post'])
171
-            ? $this->_req_data['post']
172
-            : $att_id;
173
-        $this->_page_routes = array(
174
-            'default'                             => array(
175
-                'func'       => '_registrations_overview_list_table',
176
-                'capability' => 'ee_read_registrations',
177
-            ),
178
-            'view_registration'                   => array(
179
-                'func'       => '_registration_details',
180
-                'capability' => 'ee_read_registration',
181
-                'obj_id'     => $reg_id,
182
-            ),
183
-            'edit_registration'                   => array(
184
-                'func'               => '_update_attendee_registration_form',
185
-                'noheader'           => true,
186
-                'headers_sent_route' => 'view_registration',
187
-                'capability'         => 'ee_edit_registration',
188
-                'obj_id'             => $reg_id,
189
-                '_REG_ID'            => $reg_id,
190
-            ),
191
-            'trash_registrations'                 => array(
192
-                'func'       => '_trash_or_restore_registrations',
193
-                'args'       => array('trash' => true),
194
-                'noheader'   => true,
195
-                'capability' => 'ee_delete_registrations',
196
-            ),
197
-            'restore_registrations'               => array(
198
-                'func'       => '_trash_or_restore_registrations',
199
-                'args'       => array('trash' => false),
200
-                'noheader'   => true,
201
-                'capability' => 'ee_delete_registrations',
202
-            ),
203
-            'delete_registrations'                => array(
204
-                'func'       => '_delete_registrations',
205
-                'noheader'   => true,
206
-                'capability' => 'ee_delete_registrations',
207
-            ),
208
-            'new_registration'                    => array(
209
-                'func'       => 'new_registration',
210
-                'capability' => 'ee_edit_registrations',
211
-            ),
212
-            'process_reg_step'                    => array(
213
-                'func'       => 'process_reg_step',
214
-                'noheader'   => true,
215
-                'capability' => 'ee_edit_registrations',
216
-            ),
217
-            'redirect_to_txn'                     => array(
218
-                'func'       => 'redirect_to_txn',
219
-                'noheader'   => true,
220
-                'capability' => 'ee_edit_registrations',
221
-            ),
222
-            'change_reg_status'                   => array(
223
-                'func'       => '_change_reg_status',
224
-                'noheader'   => true,
225
-                'capability' => 'ee_edit_registration',
226
-                'obj_id'     => $reg_id,
227
-            ),
228
-            'approve_registration'                => array(
229
-                'func'       => 'approve_registration',
230
-                'noheader'   => true,
231
-                'capability' => 'ee_edit_registration',
232
-                'obj_id'     => $reg_id,
233
-            ),
234
-            'approve_and_notify_registration'     => array(
235
-                'func'       => 'approve_registration',
236
-                'noheader'   => true,
237
-                'args'       => array(true),
238
-                'capability' => 'ee_edit_registration',
239
-                'obj_id'     => $reg_id,
240
-            ),
241
-            'approve_registrations'               => array(
242
-                'func'       => 'bulk_action_on_registrations',
243
-                'noheader'   => true,
244
-                'capability' => 'ee_edit_registrations',
245
-                'args'       => array('approve'),
246
-            ),
247
-            'approve_and_notify_registrations'    => array(
248
-                'func'       => 'bulk_action_on_registrations',
249
-                'noheader'   => true,
250
-                'capability' => 'ee_edit_registrations',
251
-                'args'       => array('approve', true),
252
-            ),
253
-            'decline_registration'                => array(
254
-                'func'       => 'decline_registration',
255
-                'noheader'   => true,
256
-                'capability' => 'ee_edit_registration',
257
-                'obj_id'     => $reg_id,
258
-            ),
259
-            'decline_and_notify_registration'     => array(
260
-                'func'       => 'decline_registration',
261
-                'noheader'   => true,
262
-                'args'       => array(true),
263
-                'capability' => 'ee_edit_registration',
264
-                'obj_id'     => $reg_id,
265
-            ),
266
-            'decline_registrations'               => array(
267
-                'func'       => 'bulk_action_on_registrations',
268
-                'noheader'   => true,
269
-                'capability' => 'ee_edit_registrations',
270
-                'args'       => array('decline'),
271
-            ),
272
-            'decline_and_notify_registrations'    => array(
273
-                'func'       => 'bulk_action_on_registrations',
274
-                'noheader'   => true,
275
-                'capability' => 'ee_edit_registrations',
276
-                'args'       => array('decline', true),
277
-            ),
278
-            'pending_registration'                => array(
279
-                'func'       => 'pending_registration',
280
-                'noheader'   => true,
281
-                'capability' => 'ee_edit_registration',
282
-                'obj_id'     => $reg_id,
283
-            ),
284
-            'pending_and_notify_registration'     => array(
285
-                'func'       => 'pending_registration',
286
-                'noheader'   => true,
287
-                'args'       => array(true),
288
-                'capability' => 'ee_edit_registration',
289
-                'obj_id'     => $reg_id,
290
-            ),
291
-            'pending_registrations'               => array(
292
-                'func'       => 'bulk_action_on_registrations',
293
-                'noheader'   => true,
294
-                'capability' => 'ee_edit_registrations',
295
-                'args'       => array('pending'),
296
-            ),
297
-            'pending_and_notify_registrations'    => array(
298
-                'func'       => 'bulk_action_on_registrations',
299
-                'noheader'   => true,
300
-                'capability' => 'ee_edit_registrations',
301
-                'args'       => array('pending', true),
302
-            ),
303
-            'no_approve_registration'             => array(
304
-                'func'       => 'not_approve_registration',
305
-                'noheader'   => true,
306
-                'capability' => 'ee_edit_registration',
307
-                'obj_id'     => $reg_id,
308
-            ),
309
-            'no_approve_and_notify_registration'  => array(
310
-                'func'       => 'not_approve_registration',
311
-                'noheader'   => true,
312
-                'args'       => array(true),
313
-                'capability' => 'ee_edit_registration',
314
-                'obj_id'     => $reg_id,
315
-            ),
316
-            'no_approve_registrations'            => array(
317
-                'func'       => 'bulk_action_on_registrations',
318
-                'noheader'   => true,
319
-                'capability' => 'ee_edit_registrations',
320
-                'args'       => array('not_approve'),
321
-            ),
322
-            'no_approve_and_notify_registrations' => array(
323
-                'func'       => 'bulk_action_on_registrations',
324
-                'noheader'   => true,
325
-                'capability' => 'ee_edit_registrations',
326
-                'args'       => array('not_approve', true),
327
-            ),
328
-            'cancel_registration'                 => array(
329
-                'func'       => 'cancel_registration',
330
-                'noheader'   => true,
331
-                'capability' => 'ee_edit_registration',
332
-                'obj_id'     => $reg_id,
333
-            ),
334
-            'cancel_and_notify_registration'      => array(
335
-                'func'       => 'cancel_registration',
336
-                'noheader'   => true,
337
-                'args'       => array(true),
338
-                'capability' => 'ee_edit_registration',
339
-                'obj_id'     => $reg_id,
340
-            ),
341
-            'cancel_registrations'                => array(
342
-                'func'       => 'bulk_action_on_registrations',
343
-                'noheader'   => true,
344
-                'capability' => 'ee_edit_registrations',
345
-                'args'       => array('cancel'),
346
-            ),
347
-            'cancel_and_notify_registrations'     => array(
348
-                'func'       => 'bulk_action_on_registrations',
349
-                'noheader'   => true,
350
-                'capability' => 'ee_edit_registrations',
351
-                'args'       => array('cancel', true),
352
-            ),
353
-            'wait_list_registration'              => array(
354
-                'func'       => 'wait_list_registration',
355
-                'noheader'   => true,
356
-                'capability' => 'ee_edit_registration',
357
-                'obj_id'     => $reg_id,
358
-            ),
359
-            'wait_list_and_notify_registration'   => array(
360
-                'func'       => 'wait_list_registration',
361
-                'noheader'   => true,
362
-                'args'       => array(true),
363
-                'capability' => 'ee_edit_registration',
364
-                'obj_id'     => $reg_id,
365
-            ),
366
-            'contact_list'                        => array(
367
-                'func'       => '_attendee_contact_list_table',
368
-                'capability' => 'ee_read_contacts',
369
-            ),
370
-            'add_new_attendee'                    => array(
371
-                'func' => '_create_new_cpt_item',
372
-                'args' => array(
373
-                    'new_attendee' => true,
374
-                    'capability'   => 'ee_edit_contacts',
375
-                ),
376
-            ),
377
-            'edit_attendee'                       => array(
378
-                'func'       => '_edit_cpt_item',
379
-                'capability' => 'ee_edit_contacts',
380
-                'obj_id'     => $att_id,
381
-            ),
382
-            'duplicate_attendee'                  => array(
383
-                'func'       => '_duplicate_attendee',
384
-                'noheader'   => true,
385
-                'capability' => 'ee_edit_contacts',
386
-                'obj_id'     => $att_id,
387
-            ),
388
-            'insert_attendee'                     => array(
389
-                'func'       => '_insert_or_update_attendee',
390
-                'args'       => array(
391
-                    'new_attendee' => true,
392
-                ),
393
-                'noheader'   => true,
394
-                'capability' => 'ee_edit_contacts',
395
-            ),
396
-            'update_attendee'                     => array(
397
-                'func'       => '_insert_or_update_attendee',
398
-                'args'       => array(
399
-                    'new_attendee' => false,
400
-                ),
401
-                'noheader'   => true,
402
-                'capability' => 'ee_edit_contacts',
403
-                'obj_id'     => $att_id,
404
-            ),
405
-            'trash_attendees'                     => array(
406
-                'func'       => '_trash_or_restore_attendees',
407
-                'args'       => array(
408
-                    'trash' => 'true',
409
-                ),
410
-                'noheader'   => true,
411
-                'capability' => 'ee_delete_contacts',
412
-            ),
413
-            'trash_attendee'                      => array(
414
-                'func'       => '_trash_or_restore_attendees',
415
-                'args'       => array(
416
-                    'trash' => true,
417
-                ),
418
-                'noheader'   => true,
419
-                'capability' => 'ee_delete_contacts',
420
-                'obj_id'     => $att_id,
421
-            ),
422
-            'restore_attendees'                   => array(
423
-                'func'       => '_trash_or_restore_attendees',
424
-                'args'       => array(
425
-                    'trash' => false,
426
-                ),
427
-                'noheader'   => true,
428
-                'capability' => 'ee_delete_contacts',
429
-                'obj_id'     => $att_id,
430
-            ),
431
-            'resend_registration'                 => array(
432
-                'func'       => '_resend_registration',
433
-                'noheader'   => true,
434
-                'capability' => 'ee_send_message',
435
-            ),
436
-            'registrations_report'                => array(
437
-                'func'       => '_registrations_report',
438
-                'noheader'   => true,
439
-                'capability' => 'ee_read_registrations',
440
-            ),
441
-            'contact_list_export'                 => array(
442
-                'func'       => '_contact_list_export',
443
-                'noheader'   => true,
444
-                'capability' => 'export',
445
-            ),
446
-            'contact_list_report'                 => array(
447
-                'func'       => '_contact_list_report',
448
-                'noheader'   => true,
449
-                'capability' => 'ee_read_contacts',
450
-            ),
451
-        );
452
-    }
453
-
454
-
455
-    protected function _set_page_config()
456
-    {
457
-        $this->_page_config = array(
458
-            'default'           => array(
459
-                'nav'           => array(
460
-                    'label' => esc_html__('Overview', 'event_espresso'),
461
-                    'order' => 5,
462
-                ),
463
-                'help_tabs'     => array(
464
-                    'registrations_overview_help_tab'                       => array(
465
-                        'title'    => esc_html__('Registrations Overview', 'event_espresso'),
466
-                        'filename' => 'registrations_overview',
467
-                    ),
468
-                    'registrations_overview_table_column_headings_help_tab' => array(
469
-                        'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
470
-                        'filename' => 'registrations_overview_table_column_headings',
471
-                    ),
472
-                    'registrations_overview_filters_help_tab'               => array(
473
-                        'title'    => esc_html__('Registration Filters', 'event_espresso'),
474
-                        'filename' => 'registrations_overview_filters',
475
-                    ),
476
-                    'registrations_overview_views_help_tab'                 => array(
477
-                        'title'    => esc_html__('Registration Views', 'event_espresso'),
478
-                        'filename' => 'registrations_overview_views',
479
-                    ),
480
-                    'registrations_regoverview_other_help_tab'              => array(
481
-                        'title'    => esc_html__('Registrations Other', 'event_espresso'),
482
-                        'filename' => 'registrations_overview_other',
483
-                    ),
484
-                ),
485
-                'help_tour'     => array('Registration_Overview_Help_Tour'),
486
-                'qtips'         => array('Registration_List_Table_Tips'),
487
-                'list_table'    => 'EE_Registrations_List_Table',
488
-                'require_nonce' => false,
489
-            ),
490
-            'view_registration' => array(
491
-                'nav'           => array(
492
-                    'label'      => esc_html__('REG Details', 'event_espresso'),
493
-                    'order'      => 15,
494
-                    'url'        => isset($this->_req_data['_REG_ID'])
495
-                        ? add_query_arg(array('_REG_ID' => $this->_req_data['_REG_ID']), $this->_current_page_view_url)
496
-                        : $this->_admin_base_url,
497
-                    'persistent' => false,
498
-                ),
499
-                'help_tabs'     => array(
500
-                    'registrations_details_help_tab'                    => array(
501
-                        'title'    => esc_html__('Registration Details', 'event_espresso'),
502
-                        'filename' => 'registrations_details',
503
-                    ),
504
-                    'registrations_details_table_help_tab'              => array(
505
-                        'title'    => esc_html__('Registration Details Table', 'event_espresso'),
506
-                        'filename' => 'registrations_details_table',
507
-                    ),
508
-                    'registrations_details_form_answers_help_tab'       => array(
509
-                        'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
510
-                        'filename' => 'registrations_details_form_answers',
511
-                    ),
512
-                    'registrations_details_registrant_details_help_tab' => array(
513
-                        'title'    => esc_html__('Contact Details', 'event_espresso'),
514
-                        'filename' => 'registrations_details_registrant_details',
515
-                    ),
516
-                ),
517
-                'help_tour'     => array('Registration_Details_Help_Tour'),
518
-                'metaboxes'     => array_merge(
519
-                    $this->_default_espresso_metaboxes,
520
-                    array('_registration_details_metaboxes')
521
-                ),
522
-                'require_nonce' => false,
523
-            ),
524
-            'new_registration'  => array(
525
-                'nav'           => array(
526
-                    'label'      => esc_html__('Add New Registration', 'event_espresso'),
527
-                    'url'        => '#',
528
-                    'order'      => 15,
529
-                    'persistent' => false,
530
-                ),
531
-                'metaboxes'     => $this->_default_espresso_metaboxes,
532
-                'labels'        => array(
533
-                    'publishbox' => esc_html__('Save Registration', 'event_espresso'),
534
-                ),
535
-                'require_nonce' => false,
536
-            ),
537
-            'add_new_attendee'  => array(
538
-                'nav'           => array(
539
-                    'label'      => esc_html__('Add Contact', 'event_espresso'),
540
-                    'order'      => 15,
541
-                    'persistent' => false,
542
-                ),
543
-                'metaboxes'     => array_merge(
544
-                    $this->_default_espresso_metaboxes,
545
-                    array('_publish_post_box', 'attendee_editor_metaboxes')
546
-                ),
547
-                'require_nonce' => false,
548
-            ),
549
-            'edit_attendee'     => array(
550
-                'nav'           => array(
551
-                    'label'      => esc_html__('Edit Contact', 'event_espresso'),
552
-                    'order'      => 15,
553
-                    'persistent' => false,
554
-                    'url'        => isset($this->_req_data['ATT_ID'])
555
-                        ? add_query_arg(array('ATT_ID' => $this->_req_data['ATT_ID']), $this->_current_page_view_url)
556
-                        : $this->_admin_base_url,
557
-                ),
558
-                'metaboxes'     => array('attendee_editor_metaboxes'),
559
-                'require_nonce' => false,
560
-            ),
561
-            'contact_list'      => array(
562
-                'nav'           => array(
563
-                    'label' => esc_html__('Contact List', 'event_espresso'),
564
-                    'order' => 20,
565
-                ),
566
-                'list_table'    => 'EE_Attendee_Contact_List_Table',
567
-                'help_tabs'     => array(
568
-                    'registrations_contact_list_help_tab'                       => array(
569
-                        'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
570
-                        'filename' => 'registrations_contact_list',
571
-                    ),
572
-                    'registrations_contact-list_table_column_headings_help_tab' => array(
573
-                        'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
574
-                        'filename' => 'registrations_contact_list_table_column_headings',
575
-                    ),
576
-                    'registrations_contact_list_views_help_tab'                 => array(
577
-                        'title'    => esc_html__('Contact List Views', 'event_espresso'),
578
-                        'filename' => 'registrations_contact_list_views',
579
-                    ),
580
-                    'registrations_contact_list_other_help_tab'                 => array(
581
-                        'title'    => esc_html__('Contact List Other', 'event_espresso'),
582
-                        'filename' => 'registrations_contact_list_other',
583
-                    ),
584
-                ),
585
-                'help_tour'     => array('Contact_List_Help_Tour'),
586
-                'metaboxes'     => array(),
587
-                'require_nonce' => false,
588
-            ),
589
-            // override default cpt routes
590
-            'create_new'        => '',
591
-            'edit'              => '',
592
-        );
593
-    }
594
-
595
-
596
-    /**
597
-     * The below methods aren't used by this class currently
598
-     */
599
-    protected function _add_screen_options()
600
-    {
601
-    }
602
-
603
-
604
-    protected function _add_feature_pointers()
605
-    {
606
-    }
607
-
608
-
609
-    public function admin_init()
610
-    {
611
-        EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
612
-            'click "Update Registration Questions" to save your changes',
613
-            'event_espresso'
614
-        );
615
-    }
616
-
617
-
618
-    public function admin_notices()
619
-    {
620
-    }
621
-
622
-
623
-    public function admin_footer_scripts()
624
-    {
625
-    }
626
-
627
-
628
-    /**
629
-     *        get list of registration statuses
630
-     *
631
-     * @access private
632
-     * @return void
633
-     * @throws EE_Error
634
-     */
635
-    private function _get_registration_status_array()
636
-    {
637
-        self::$_reg_status = EEM_Registration::reg_status_array(array(), true);
638
-    }
639
-
640
-
641
-    protected function _add_screen_options_default()
642
-    {
643
-        $this->_per_page_screen_option();
644
-    }
645
-
646
-
647
-    protected function _add_screen_options_contact_list()
648
-    {
649
-        $page_title = $this->_admin_page_title;
650
-        $this->_admin_page_title = esc_html__("Contacts", 'event_espresso');
651
-        $this->_per_page_screen_option();
652
-        $this->_admin_page_title = $page_title;
653
-    }
654
-
655
-
656
-    public function load_scripts_styles()
657
-    {
658
-        // style
659
-        wp_register_style(
660
-            'espresso_reg',
661
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
662
-            array('ee-admin-css'),
663
-            EVENT_ESPRESSO_VERSION
664
-        );
665
-        wp_enqueue_style('espresso_reg');
666
-        // script
667
-        wp_register_script(
668
-            'espresso_reg',
669
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
670
-            array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
671
-            EVENT_ESPRESSO_VERSION,
672
-            true
673
-        );
674
-        wp_enqueue_script('espresso_reg');
675
-    }
676
-
677
-
678
-    public function load_scripts_styles_edit_attendee()
679
-    {
680
-        // stuff to only show up on our attendee edit details page.
681
-        $attendee_details_translations = array(
682
-            'att_publish_text' => sprintf(
683
-                esc_html__('Created on: <b>%1$s</b>', 'event_espresso'),
684
-                $this->_cpt_model_obj->get_datetime('ATT_created')
685
-            ),
686
-        );
687
-        wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
688
-        wp_enqueue_script('jquery-validate');
689
-    }
690
-
691
-
692
-    public function load_scripts_styles_view_registration()
693
-    {
694
-        // styles
695
-        wp_enqueue_style('espresso-ui-theme');
696
-        // scripts
697
-        $this->_get_reg_custom_questions_form($this->_registration->ID());
698
-        $this->_reg_custom_questions_form->wp_enqueue_scripts(true);
699
-    }
700
-
701
-
702
-    public function load_scripts_styles_contact_list()
703
-    {
704
-        wp_dequeue_style('espresso_reg');
705
-        wp_register_style(
706
-            'espresso_att',
707
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
708
-            array('ee-admin-css'),
709
-            EVENT_ESPRESSO_VERSION
710
-        );
711
-        wp_enqueue_style('espresso_att');
712
-    }
713
-
714
-
715
-    public function load_scripts_styles_new_registration()
716
-    {
717
-        wp_register_script(
718
-            'ee-spco-for-admin',
719
-            REG_ASSETS_URL . 'spco_for_admin.js',
720
-            array('underscore', 'jquery'),
721
-            EVENT_ESPRESSO_VERSION,
722
-            true
723
-        );
724
-        wp_enqueue_script('ee-spco-for-admin');
725
-        add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
726
-        EE_Form_Section_Proper::wp_enqueue_scripts();
727
-        EED_Ticket_Selector::load_tckt_slctr_assets();
728
-        EE_Datepicker_Input::enqueue_styles_and_scripts();
729
-    }
730
-
731
-
732
-    public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
733
-    {
734
-        add_filter('FHEE_load_EE_messages', '__return_true');
735
-    }
736
-
737
-
738
-    public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
739
-    {
740
-        add_filter('FHEE_load_EE_messages', '__return_true');
741
-    }
742
-
743
-
744
-    protected function _set_list_table_views_default()
745
-    {
746
-        // for notification related bulk actions we need to make sure only active messengers have an option.
747
-        EED_Messages::set_autoloaders();
748
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
749
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
750
-        $active_mts = $message_resource_manager->list_of_active_message_types();
751
-        // key= bulk_action_slug, value= message type.
752
-        $match_array = array(
753
-            'approve_registrations'    => 'registration',
754
-            'decline_registrations'    => 'declined_registration',
755
-            'pending_registrations'    => 'pending_approval',
756
-            'no_approve_registrations' => 'not_approved_registration',
757
-            'cancel_registrations'     => 'cancelled_registration',
758
-        );
759
-        $can_send = EE_Registry::instance()->CAP->current_user_can(
760
-            'ee_send_message',
761
-            'batch_send_messages'
762
-        );
763
-        /** setup reg status bulk actions **/
764
-        $def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
765
-        if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
766
-            $def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
767
-                'Approve and Notify Registrations',
768
-                'event_espresso'
769
-            );
770
-        }
771
-        $def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
772
-        if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
773
-            $def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
774
-                'Decline and Notify Registrations',
775
-                'event_espresso'
776
-            );
777
-        }
778
-        $def_reg_status_actions['pending_registrations'] = esc_html__(
779
-            'Set Registrations to Pending Payment',
780
-            'event_espresso'
781
-        );
782
-        if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
783
-            $def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
784
-                'Set Registrations to Pending Payment and Notify',
785
-                'event_espresso'
786
-            );
787
-        }
788
-        $def_reg_status_actions['no_approve_registrations'] = esc_html__(
789
-            'Set Registrations to Not Approved',
790
-            'event_espresso'
791
-        );
792
-        if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
793
-            $def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
794
-                'Set Registrations to Not Approved and Notify',
795
-                'event_espresso'
796
-            );
797
-        }
798
-        $def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
799
-        if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
800
-            $def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
801
-                'Cancel Registrations and Notify',
802
-                'event_espresso'
803
-            );
804
-        }
805
-        $def_reg_status_actions = apply_filters(
806
-            'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
807
-            $def_reg_status_actions,
808
-            $active_mts,
809
-            $can_send
810
-        );
811
-
812
-        $this->_views = array(
813
-            'all'   => array(
814
-                'slug'        => 'all',
815
-                'label'       => esc_html__('View All Registrations', 'event_espresso'),
816
-                'count'       => 0,
817
-                'bulk_action' => array_merge(
818
-                    $def_reg_status_actions,
819
-                    array(
820
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
821
-                    )
822
-                ),
823
-            ),
824
-            'month' => array(
825
-                'slug'        => 'month',
826
-                'label'       => esc_html__('This Month', 'event_espresso'),
827
-                'count'       => 0,
828
-                'bulk_action' => array_merge(
829
-                    $def_reg_status_actions,
830
-                    array(
831
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
832
-                    )
833
-                ),
834
-            ),
835
-            'today' => array(
836
-                'slug'        => 'today',
837
-                'label'       => sprintf(
838
-                    esc_html__('Today - %s', 'event_espresso'),
839
-                    date('M d, Y', current_time('timestamp'))
840
-                ),
841
-                'count'       => 0,
842
-                'bulk_action' => array_merge(
843
-                    $def_reg_status_actions,
844
-                    array(
845
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
846
-                    )
847
-                ),
848
-            ),
849
-        );
850
-        if (EE_Registry::instance()->CAP->current_user_can(
851
-            'ee_delete_registrations',
852
-            'espresso_registrations_delete_registration'
853
-        )) {
854
-            $this->_views['incomplete'] = array(
855
-                'slug'        => 'incomplete',
856
-                'label'       => esc_html__('Incomplete', 'event_espresso'),
857
-                'count'       => 0,
858
-                'bulk_action' => array(
859
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
860
-                ),
861
-            );
862
-            $this->_views['trash'] = array(
863
-                'slug'        => 'trash',
864
-                'label'       => esc_html__('Trash', 'event_espresso'),
865
-                'count'       => 0,
866
-                'bulk_action' => array(
867
-                    'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
868
-                    'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
869
-                ),
870
-            );
871
-        }
872
-    }
873
-
874
-
875
-    protected function _set_list_table_views_contact_list()
876
-    {
877
-        $this->_views = array(
878
-            'in_use' => array(
879
-                'slug'        => 'in_use',
880
-                'label'       => esc_html__('In Use', 'event_espresso'),
881
-                'count'       => 0,
882
-                'bulk_action' => array(
883
-                    'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
884
-                ),
885
-            ),
886
-        );
887
-        if (EE_Registry::instance()->CAP->current_user_can(
888
-            'ee_delete_contacts',
889
-            'espresso_registrations_trash_attendees'
890
-        )
891
-        ) {
892
-            $this->_views['trash'] = array(
893
-                'slug'        => 'trash',
894
-                'label'       => esc_html__('Trash', 'event_espresso'),
895
-                'count'       => 0,
896
-                'bulk_action' => array(
897
-                    'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
898
-                ),
899
-            );
900
-        }
901
-    }
902
-
903
-
904
-    protected function _registration_legend_items()
905
-    {
906
-        $fc_items = array(
907
-            'star-icon'        => array(
908
-                'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
909
-                'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
910
-            ),
911
-            'view_details'     => array(
912
-                'class' => 'dashicons dashicons-clipboard',
913
-                'desc'  => esc_html__('View Registration Details', 'event_espresso'),
914
-            ),
915
-            'edit_attendee'    => array(
916
-                'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
917
-                'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
918
-            ),
919
-            'view_transaction' => array(
920
-                'class' => 'dashicons dashicons-cart',
921
-                'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
922
-            ),
923
-            'view_invoice'     => array(
924
-                'class' => 'dashicons dashicons-media-spreadsheet',
925
-                'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
926
-            ),
927
-        );
928
-        if (EE_Registry::instance()->CAP->current_user_can(
929
-            'ee_send_message',
930
-            'espresso_registrations_resend_registration'
931
-        )) {
932
-            $fc_items['resend_registration'] = array(
933
-                'class' => 'dashicons dashicons-email-alt',
934
-                'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
935
-            );
936
-        } else {
937
-            $fc_items['blank'] = array('class' => 'blank', 'desc' => '');
938
-        }
939
-        if (EE_Registry::instance()->CAP->current_user_can(
940
-            'ee_read_global_messages',
941
-            'view_filtered_messages'
942
-        )) {
943
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
944
-            if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
945
-                $fc_items['view_related_messages'] = array(
946
-                    'class' => $related_for_icon['css_class'],
947
-                    'desc'  => $related_for_icon['label'],
948
-                );
949
-            }
950
-        }
951
-        $sc_items = array(
952
-            'approved_status'   => array(
953
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
954
-                'desc'  => EEH_Template::pretty_status(
955
-                    EEM_Registration::status_id_approved,
956
-                    false,
957
-                    'sentence'
958
-                ),
959
-            ),
960
-            'pending_status'    => array(
961
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
962
-                'desc'  => EEH_Template::pretty_status(
963
-                    EEM_Registration::status_id_pending_payment,
964
-                    false,
965
-                    'sentence'
966
-                ),
967
-            ),
968
-            'wait_list'         => array(
969
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
970
-                'desc'  => EEH_Template::pretty_status(
971
-                    EEM_Registration::status_id_wait_list,
972
-                    false,
973
-                    'sentence'
974
-                ),
975
-            ),
976
-            'incomplete_status' => array(
977
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
978
-                'desc'  => EEH_Template::pretty_status(
979
-                    EEM_Registration::status_id_incomplete,
980
-                    false,
981
-                    'sentence'
982
-                ),
983
-            ),
984
-            'not_approved'      => array(
985
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
986
-                'desc'  => EEH_Template::pretty_status(
987
-                    EEM_Registration::status_id_not_approved,
988
-                    false,
989
-                    'sentence'
990
-                ),
991
-            ),
992
-            'declined_status'   => array(
993
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
994
-                'desc'  => EEH_Template::pretty_status(
995
-                    EEM_Registration::status_id_declined,
996
-                    false,
997
-                    'sentence'
998
-                ),
999
-            ),
1000
-            'cancelled_status'  => array(
1001
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1002
-                'desc'  => EEH_Template::pretty_status(
1003
-                    EEM_Registration::status_id_cancelled,
1004
-                    false,
1005
-                    'sentence'
1006
-                ),
1007
-            ),
1008
-        );
1009
-        return array_merge($fc_items, $sc_items);
1010
-    }
1011
-
1012
-
1013
-
1014
-    /***************************************        REGISTRATION OVERVIEW        **************************************/
1015
-    /**
1016
-     * @throws \EE_Error
1017
-     */
1018
-    protected function _registrations_overview_list_table()
1019
-    {
1020
-        $this->_template_args['admin_page_header'] = '';
1021
-        $EVT_ID = ! empty($this->_req_data['event_id'])
1022
-            ? absint($this->_req_data['event_id'])
1023
-            : 0;
1024
-        $ATT_ID = ! empty($this->_req_data['ATT_ID'])
1025
-            ? absint($this->_req_data['ATT_ID'])
1026
-            : 0;
1027
-        if ($ATT_ID) {
1028
-            $attendee = EEM_Attendee::instance()->get_one_by_ID($ATT_ID);
1029
-            if ($attendee instanceof EE_Attendee) {
1030
-                $this->_template_args['admin_page_header'] = sprintf(
1031
-                    esc_html__(
1032
-                        '%1$s Viewing registrations for %2$s%3$s',
1033
-                        'event_espresso'
1034
-                    ),
1035
-                    '<h3 style="line-height:1.5em;">',
1036
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
1037
-                        array(
1038
-                            'action' => 'edit_attendee',
1039
-                            'post'   => $ATT_ID,
1040
-                        ),
1041
-                        REG_ADMIN_URL
1042
-                    ) . '">' . $attendee->full_name() . '</a>',
1043
-                    '</h3>'
1044
-                );
1045
-            }
1046
-        }
1047
-        if ($EVT_ID) {
1048
-            if (EE_Registry::instance()->CAP->current_user_can(
1049
-                'ee_edit_registrations',
1050
-                'espresso_registrations_new_registration',
1051
-                $EVT_ID
1052
-            )) {
1053
-                $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1054
-                    'new_registration',
1055
-                    'add-registrant',
1056
-                    array('event_id' => $EVT_ID),
1057
-                    'add-new-h2'
1058
-                );
1059
-            }
1060
-            $event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
1061
-            if ($event instanceof EE_Event) {
1062
-                $this->_template_args['admin_page_header'] = sprintf(
1063
-                    esc_html__(
1064
-                        '%s Viewing registrations for the event: %s%s',
1065
-                        'event_espresso'
1066
-                    ),
1067
-                    '<h3 style="line-height:1.5em;">',
1068
-                    '<br /><a href="'
1069
-                    . EE_Admin_Page::add_query_args_and_nonce(
1070
-                        array(
1071
-                            'action' => 'edit',
1072
-                            'post'   => $event->ID(),
1073
-                        ),
1074
-                        EVENTS_ADMIN_URL
1075
-                    )
1076
-                    . '">&nbsp;'
1077
-                    . $event->get('EVT_name')
1078
-                    . '&nbsp;</a>&nbsp;',
1079
-                    '</h3>'
1080
-                );
1081
-            }
1082
-            $DTT_ID = ! empty($this->_req_data['datetime_id']) ? absint($this->_req_data['datetime_id']) : 0;
1083
-            $datetime = EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1084
-            if ($datetime instanceof EE_Datetime && $this->_template_args['admin_page_header'] !== '') {
1085
-                $this->_template_args['admin_page_header'] = substr(
1086
-                    $this->_template_args['admin_page_header'],
1087
-                    0,
1088
-                    -5
1089
-                );
1090
-                $this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
1091
-                $this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
1092
-                $this->_template_args['admin_page_header'] .= $datetime->name();
1093
-                $this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
1094
-                $this->_template_args['admin_page_header'] .= '</span></h3>';
1095
-            }
1096
-        }
1097
-        $this->_template_args['after_list_table'] = $this->_display_legend($this->_registration_legend_items());
1098
-        $this->display_admin_list_table_page_with_no_sidebar();
1099
-    }
1100
-
1101
-
1102
-    /**
1103
-     * This sets the _registration property for the registration details screen
1104
-     *
1105
-     * @access private
1106
-     * @return bool
1107
-     * @throws EE_Error
1108
-     * @throws InvalidArgumentException
1109
-     * @throws InvalidDataTypeException
1110
-     * @throws InvalidInterfaceException
1111
-     */
1112
-    private function _set_registration_object()
1113
-    {
1114
-        // get out if we've already set the object
1115
-        if ($this->_registration instanceof EE_Registration) {
1116
-            return true;
1117
-        }
1118
-        $REG = EEM_Registration::instance();
1119
-        $REG_ID = (! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1120
-        if ($this->_registration = $REG->get_one_by_ID($REG_ID)) {
1121
-            return true;
1122
-        } else {
1123
-            $error_msg = sprintf(
1124
-                esc_html__(
1125
-                    'An error occurred and the details for Registration ID #%s could not be retrieved.',
1126
-                    'event_espresso'
1127
-                ),
1128
-                $REG_ID
1129
-            );
1130
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1131
-            $this->_registration = null;
1132
-            return false;
1133
-        }
1134
-    }
1135
-
1136
-
1137
-    /**
1138
-     * Used to retrieve registrations for the list table.
1139
-     *
1140
-     * @param int  $per_page
1141
-     * @param bool $count
1142
-     * @param bool $this_month
1143
-     * @param bool $today
1144
-     * @return EE_Registration[]|int
1145
-     * @throws EE_Error
1146
-     * @throws InvalidArgumentException
1147
-     * @throws InvalidDataTypeException
1148
-     * @throws InvalidInterfaceException
1149
-     */
1150
-    public function get_registrations(
1151
-        $per_page = 10,
1152
-        $count = false,
1153
-        $this_month = false,
1154
-        $today = false
1155
-    ) {
1156
-        if ($this_month) {
1157
-            $this->_req_data['status'] = 'month';
1158
-        }
1159
-        if ($today) {
1160
-            $this->_req_data['status'] = 'today';
1161
-        }
1162
-        $query_params = $this->_get_registration_query_parameters($this->_req_data, $per_page, $count);
1163
-        /**
1164
-         * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1165
-         *
1166
-         * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1167
-         * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1168
-         *                             or if you have the development copy of EE you can view this at the path:
1169
-         *                             /docs/G--Model-System/model-query-params.md
1170
-         */
1171
-        $query_params['group_by'] = '';
1172
-
1173
-        return $count
1174
-            ? EEM_Registration::instance()->count($query_params)
1175
-            /** @type EE_Registration[] */
1176
-            : EEM_Registration::instance()->get_all($query_params);
1177
-    }
1178
-
1179
-
1180
-    /**
1181
-     * Retrieves the query parameters to be used by the Registration model for getting registrations.
1182
-     * Note: this listens to values on the request for some of the query parameters.
1183
-     *
1184
-     * @param array $request
1185
-     * @param int   $per_page
1186
-     * @param bool  $count
1187
-     * @return array
1188
-     * @throws EE_Error
1189
-     */
1190
-    protected function _get_registration_query_parameters(
1191
-        $request = array(),
1192
-        $per_page = 10,
1193
-        $count = false
1194
-    ) {
1195
-
1196
-        $query_params = array(
1197
-            0                          => $this->_get_where_conditions_for_registrations_query(
1198
-                $request
1199
-            ),
1200
-            'caps'                     => EEM_Registration::caps_read_admin,
1201
-            'default_where_conditions' => 'this_model_only',
1202
-        );
1203
-        if (! $count) {
1204
-            $query_params = array_merge(
1205
-                $query_params,
1206
-                $this->_get_orderby_for_registrations_query(),
1207
-                $this->_get_limit($per_page)
1208
-            );
1209
-        }
1210
-
1211
-        return $query_params;
1212
-    }
1213
-
1214
-
1215
-    /**
1216
-     * This will add ATT_ID to the provided $where array for EE model query parameters.
1217
-     *
1218
-     * @param array $request usually the same as $this->_req_data but not necessarily
1219
-     * @return array
1220
-     */
1221
-    protected function addAttendeeIdToWhereConditions(array $request)
1222
-    {
1223
-        $where = array();
1224
-        if (! empty($request['ATT_ID'])) {
1225
-            $where['ATT_ID'] = absint($request['ATT_ID']);
1226
-        }
1227
-        return $where;
1228
-    }
1229
-
1230
-
1231
-    /**
1232
-     * This will add EVT_ID to the provided $where array for EE model query parameters.
1233
-     *
1234
-     * @param array $request usually the same as $this->_req_data but not necessarily
1235
-     * @return array
1236
-     */
1237
-    protected function _add_event_id_to_where_conditions(array $request)
1238
-    {
1239
-        $where = array();
1240
-        if (! empty($request['event_id'])) {
1241
-            $where['EVT_ID'] = absint($request['event_id']);
1242
-        }
1243
-        return $where;
1244
-    }
1245
-
1246
-
1247
-    /**
1248
-     * Adds category ID if it exists in the request to the where conditions for the registrations query.
1249
-     *
1250
-     * @param array $request usually the same as $this->_req_data but not necessarily
1251
-     * @return array
1252
-     */
1253
-    protected function _add_category_id_to_where_conditions(array $request)
1254
-    {
1255
-        $where = array();
1256
-        if (! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1257
-            $where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1258
-        }
1259
-        return $where;
1260
-    }
1261
-
1262
-
1263
-    /**
1264
-     * Adds the datetime ID if it exists in the request to the where conditions for the registrations query.
1265
-     *
1266
-     * @param array $request usually the same as $this->_req_data but not necessarily
1267
-     * @return array
1268
-     */
1269
-    protected function _add_datetime_id_to_where_conditions(array $request)
1270
-    {
1271
-        $where = array();
1272
-        if (! empty($request['datetime_id'])) {
1273
-            $where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1274
-        }
1275
-        if (! empty($request['DTT_ID'])) {
1276
-            $where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1277
-        }
1278
-        return $where;
1279
-    }
1280
-
1281
-
1282
-    /**
1283
-     * Adds the correct registration status to the where conditions for the registrations query.
1284
-     *
1285
-     * @param array $request usually the same as $this->_req_data but not necessarily
1286
-     * @return array
1287
-     */
1288
-    protected function _add_registration_status_to_where_conditions(array $request)
1289
-    {
1290
-        $where = array();
1291
-        $view = EEH_Array::is_set($request, 'status', '');
1292
-        $registration_status = ! empty($request['_reg_status'])
1293
-            ? sanitize_text_field($request['_reg_status'])
1294
-            : '';
1295
-
1296
-        /*
22
+	/**
23
+	 * @var EE_Registration
24
+	 */
25
+	private $_registration;
26
+
27
+	/**
28
+	 * @var EE_Event
29
+	 */
30
+	private $_reg_event;
31
+
32
+	/**
33
+	 * @var EE_Session
34
+	 */
35
+	private $_session;
36
+
37
+	private static $_reg_status;
38
+
39
+	/**
40
+	 * Form for displaying the custom questions for this registration.
41
+	 * This gets used a few times throughout the request so its best to cache it
42
+	 *
43
+	 * @var EE_Registration_Custom_Questions_Form
44
+	 */
45
+	protected $_reg_custom_questions_form = null;
46
+
47
+
48
+	/**
49
+	 *        constructor
50
+	 *
51
+	 * @Constructor
52
+	 * @access public
53
+	 * @param bool $routing
54
+	 * @return Registrations_Admin_Page
55
+	 */
56
+	public function __construct($routing = true)
57
+	{
58
+		parent::__construct($routing);
59
+		add_action('wp_loaded', array($this, 'wp_loaded'));
60
+	}
61
+
62
+
63
+	public function wp_loaded()
64
+	{
65
+		// when adding a new registration...
66
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
67
+			EE_System::do_not_cache();
68
+			if (! isset($this->_req_data['processing_registration'])
69
+				|| absint($this->_req_data['processing_registration']) !== 1
70
+			) {
71
+				// and it's NOT the attendee information reg step
72
+				// force cookie expiration by setting time to last week
73
+				setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
74
+				// and update the global
75
+				$_COOKIE['ee_registration_added'] = 0;
76
+			}
77
+		}
78
+	}
79
+
80
+
81
+	protected function _init_page_props()
82
+	{
83
+		$this->page_slug = REG_PG_SLUG;
84
+		$this->_admin_base_url = REG_ADMIN_URL;
85
+		$this->_admin_base_path = REG_ADMIN;
86
+		$this->page_label = esc_html__('Registrations', 'event_espresso');
87
+		$this->_cpt_routes = array(
88
+			'add_new_attendee' => 'espresso_attendees',
89
+			'edit_attendee'    => 'espresso_attendees',
90
+			'insert_attendee'  => 'espresso_attendees',
91
+			'update_attendee'  => 'espresso_attendees',
92
+		);
93
+		$this->_cpt_model_names = array(
94
+			'add_new_attendee' => 'EEM_Attendee',
95
+			'edit_attendee'    => 'EEM_Attendee',
96
+		);
97
+		$this->_cpt_edit_routes = array(
98
+			'espresso_attendees' => 'edit_attendee',
99
+		);
100
+		$this->_pagenow_map = array(
101
+			'add_new_attendee' => 'post-new.php',
102
+			'edit_attendee'    => 'post.php',
103
+			'trash'            => 'post.php',
104
+		);
105
+		add_action('edit_form_after_title', array($this, 'after_title_form_fields'), 10);
106
+		// add filters so that the comment urls don't take users to a confusing 404 page
107
+		add_filter('get_comment_link', array($this, 'clear_comment_link'), 10, 3);
108
+	}
109
+
110
+
111
+	public function clear_comment_link($link, $comment, $args)
112
+	{
113
+		// gotta make sure this only happens on this route
114
+		$post_type = get_post_type($comment->comment_post_ID);
115
+		if ($post_type === 'espresso_attendees') {
116
+			return '#commentsdiv';
117
+		}
118
+		return $link;
119
+	}
120
+
121
+
122
+	protected function _ajax_hooks()
123
+	{
124
+		// todo: all hooks for registrations ajax goes in here
125
+		add_action('wp_ajax_toggle_checkin_status', array($this, 'toggle_checkin_status'));
126
+	}
127
+
128
+
129
+	protected function _define_page_props()
130
+	{
131
+		$this->_admin_page_title = $this->page_label;
132
+		$this->_labels = array(
133
+			'buttons'                      => array(
134
+				'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
135
+				'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
136
+				'edit'                => esc_html__('Edit Contact', 'event_espresso'),
137
+				'report'              => esc_html__("Event Registrations CSV Report", "event_espresso"),
138
+				'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
139
+				'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
140
+				'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
141
+				'contact_list_export' => esc_html__("Export Data", "event_espresso"),
142
+			),
143
+			'publishbox'                   => array(
144
+				'add_new_attendee' => esc_html__("Add Contact Record", 'event_espresso'),
145
+				'edit_attendee'    => esc_html__("Update Contact Record", 'event_espresso'),
146
+			),
147
+			'hide_add_button_on_cpt_route' => array(
148
+				'edit_attendee' => true,
149
+			),
150
+		);
151
+	}
152
+
153
+
154
+	/**
155
+	 *        grab url requests and route them
156
+	 *
157
+	 * @access private
158
+	 * @return void
159
+	 */
160
+	public function _set_page_routes()
161
+	{
162
+		$this->_get_registration_status_array();
163
+		$reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID'])
164
+			? $this->_req_data['_REG_ID'] : 0;
165
+		$reg_id = empty($reg_id) && ! empty($this->_req_data['reg_status_change_form']['REG_ID'])
166
+			? $this->_req_data['reg_status_change_form']['REG_ID']
167
+			: $reg_id;
168
+		$att_id = ! empty($this->_req_data['ATT_ID']) && ! is_array($this->_req_data['ATT_ID'])
169
+			? $this->_req_data['ATT_ID'] : 0;
170
+		$att_id = ! empty($this->_req_data['post']) && ! is_array($this->_req_data['post'])
171
+			? $this->_req_data['post']
172
+			: $att_id;
173
+		$this->_page_routes = array(
174
+			'default'                             => array(
175
+				'func'       => '_registrations_overview_list_table',
176
+				'capability' => 'ee_read_registrations',
177
+			),
178
+			'view_registration'                   => array(
179
+				'func'       => '_registration_details',
180
+				'capability' => 'ee_read_registration',
181
+				'obj_id'     => $reg_id,
182
+			),
183
+			'edit_registration'                   => array(
184
+				'func'               => '_update_attendee_registration_form',
185
+				'noheader'           => true,
186
+				'headers_sent_route' => 'view_registration',
187
+				'capability'         => 'ee_edit_registration',
188
+				'obj_id'             => $reg_id,
189
+				'_REG_ID'            => $reg_id,
190
+			),
191
+			'trash_registrations'                 => array(
192
+				'func'       => '_trash_or_restore_registrations',
193
+				'args'       => array('trash' => true),
194
+				'noheader'   => true,
195
+				'capability' => 'ee_delete_registrations',
196
+			),
197
+			'restore_registrations'               => array(
198
+				'func'       => '_trash_or_restore_registrations',
199
+				'args'       => array('trash' => false),
200
+				'noheader'   => true,
201
+				'capability' => 'ee_delete_registrations',
202
+			),
203
+			'delete_registrations'                => array(
204
+				'func'       => '_delete_registrations',
205
+				'noheader'   => true,
206
+				'capability' => 'ee_delete_registrations',
207
+			),
208
+			'new_registration'                    => array(
209
+				'func'       => 'new_registration',
210
+				'capability' => 'ee_edit_registrations',
211
+			),
212
+			'process_reg_step'                    => array(
213
+				'func'       => 'process_reg_step',
214
+				'noheader'   => true,
215
+				'capability' => 'ee_edit_registrations',
216
+			),
217
+			'redirect_to_txn'                     => array(
218
+				'func'       => 'redirect_to_txn',
219
+				'noheader'   => true,
220
+				'capability' => 'ee_edit_registrations',
221
+			),
222
+			'change_reg_status'                   => array(
223
+				'func'       => '_change_reg_status',
224
+				'noheader'   => true,
225
+				'capability' => 'ee_edit_registration',
226
+				'obj_id'     => $reg_id,
227
+			),
228
+			'approve_registration'                => array(
229
+				'func'       => 'approve_registration',
230
+				'noheader'   => true,
231
+				'capability' => 'ee_edit_registration',
232
+				'obj_id'     => $reg_id,
233
+			),
234
+			'approve_and_notify_registration'     => array(
235
+				'func'       => 'approve_registration',
236
+				'noheader'   => true,
237
+				'args'       => array(true),
238
+				'capability' => 'ee_edit_registration',
239
+				'obj_id'     => $reg_id,
240
+			),
241
+			'approve_registrations'               => array(
242
+				'func'       => 'bulk_action_on_registrations',
243
+				'noheader'   => true,
244
+				'capability' => 'ee_edit_registrations',
245
+				'args'       => array('approve'),
246
+			),
247
+			'approve_and_notify_registrations'    => array(
248
+				'func'       => 'bulk_action_on_registrations',
249
+				'noheader'   => true,
250
+				'capability' => 'ee_edit_registrations',
251
+				'args'       => array('approve', true),
252
+			),
253
+			'decline_registration'                => array(
254
+				'func'       => 'decline_registration',
255
+				'noheader'   => true,
256
+				'capability' => 'ee_edit_registration',
257
+				'obj_id'     => $reg_id,
258
+			),
259
+			'decline_and_notify_registration'     => array(
260
+				'func'       => 'decline_registration',
261
+				'noheader'   => true,
262
+				'args'       => array(true),
263
+				'capability' => 'ee_edit_registration',
264
+				'obj_id'     => $reg_id,
265
+			),
266
+			'decline_registrations'               => array(
267
+				'func'       => 'bulk_action_on_registrations',
268
+				'noheader'   => true,
269
+				'capability' => 'ee_edit_registrations',
270
+				'args'       => array('decline'),
271
+			),
272
+			'decline_and_notify_registrations'    => array(
273
+				'func'       => 'bulk_action_on_registrations',
274
+				'noheader'   => true,
275
+				'capability' => 'ee_edit_registrations',
276
+				'args'       => array('decline', true),
277
+			),
278
+			'pending_registration'                => array(
279
+				'func'       => 'pending_registration',
280
+				'noheader'   => true,
281
+				'capability' => 'ee_edit_registration',
282
+				'obj_id'     => $reg_id,
283
+			),
284
+			'pending_and_notify_registration'     => array(
285
+				'func'       => 'pending_registration',
286
+				'noheader'   => true,
287
+				'args'       => array(true),
288
+				'capability' => 'ee_edit_registration',
289
+				'obj_id'     => $reg_id,
290
+			),
291
+			'pending_registrations'               => array(
292
+				'func'       => 'bulk_action_on_registrations',
293
+				'noheader'   => true,
294
+				'capability' => 'ee_edit_registrations',
295
+				'args'       => array('pending'),
296
+			),
297
+			'pending_and_notify_registrations'    => array(
298
+				'func'       => 'bulk_action_on_registrations',
299
+				'noheader'   => true,
300
+				'capability' => 'ee_edit_registrations',
301
+				'args'       => array('pending', true),
302
+			),
303
+			'no_approve_registration'             => array(
304
+				'func'       => 'not_approve_registration',
305
+				'noheader'   => true,
306
+				'capability' => 'ee_edit_registration',
307
+				'obj_id'     => $reg_id,
308
+			),
309
+			'no_approve_and_notify_registration'  => array(
310
+				'func'       => 'not_approve_registration',
311
+				'noheader'   => true,
312
+				'args'       => array(true),
313
+				'capability' => 'ee_edit_registration',
314
+				'obj_id'     => $reg_id,
315
+			),
316
+			'no_approve_registrations'            => array(
317
+				'func'       => 'bulk_action_on_registrations',
318
+				'noheader'   => true,
319
+				'capability' => 'ee_edit_registrations',
320
+				'args'       => array('not_approve'),
321
+			),
322
+			'no_approve_and_notify_registrations' => array(
323
+				'func'       => 'bulk_action_on_registrations',
324
+				'noheader'   => true,
325
+				'capability' => 'ee_edit_registrations',
326
+				'args'       => array('not_approve', true),
327
+			),
328
+			'cancel_registration'                 => array(
329
+				'func'       => 'cancel_registration',
330
+				'noheader'   => true,
331
+				'capability' => 'ee_edit_registration',
332
+				'obj_id'     => $reg_id,
333
+			),
334
+			'cancel_and_notify_registration'      => array(
335
+				'func'       => 'cancel_registration',
336
+				'noheader'   => true,
337
+				'args'       => array(true),
338
+				'capability' => 'ee_edit_registration',
339
+				'obj_id'     => $reg_id,
340
+			),
341
+			'cancel_registrations'                => array(
342
+				'func'       => 'bulk_action_on_registrations',
343
+				'noheader'   => true,
344
+				'capability' => 'ee_edit_registrations',
345
+				'args'       => array('cancel'),
346
+			),
347
+			'cancel_and_notify_registrations'     => array(
348
+				'func'       => 'bulk_action_on_registrations',
349
+				'noheader'   => true,
350
+				'capability' => 'ee_edit_registrations',
351
+				'args'       => array('cancel', true),
352
+			),
353
+			'wait_list_registration'              => array(
354
+				'func'       => 'wait_list_registration',
355
+				'noheader'   => true,
356
+				'capability' => 'ee_edit_registration',
357
+				'obj_id'     => $reg_id,
358
+			),
359
+			'wait_list_and_notify_registration'   => array(
360
+				'func'       => 'wait_list_registration',
361
+				'noheader'   => true,
362
+				'args'       => array(true),
363
+				'capability' => 'ee_edit_registration',
364
+				'obj_id'     => $reg_id,
365
+			),
366
+			'contact_list'                        => array(
367
+				'func'       => '_attendee_contact_list_table',
368
+				'capability' => 'ee_read_contacts',
369
+			),
370
+			'add_new_attendee'                    => array(
371
+				'func' => '_create_new_cpt_item',
372
+				'args' => array(
373
+					'new_attendee' => true,
374
+					'capability'   => 'ee_edit_contacts',
375
+				),
376
+			),
377
+			'edit_attendee'                       => array(
378
+				'func'       => '_edit_cpt_item',
379
+				'capability' => 'ee_edit_contacts',
380
+				'obj_id'     => $att_id,
381
+			),
382
+			'duplicate_attendee'                  => array(
383
+				'func'       => '_duplicate_attendee',
384
+				'noheader'   => true,
385
+				'capability' => 'ee_edit_contacts',
386
+				'obj_id'     => $att_id,
387
+			),
388
+			'insert_attendee'                     => array(
389
+				'func'       => '_insert_or_update_attendee',
390
+				'args'       => array(
391
+					'new_attendee' => true,
392
+				),
393
+				'noheader'   => true,
394
+				'capability' => 'ee_edit_contacts',
395
+			),
396
+			'update_attendee'                     => array(
397
+				'func'       => '_insert_or_update_attendee',
398
+				'args'       => array(
399
+					'new_attendee' => false,
400
+				),
401
+				'noheader'   => true,
402
+				'capability' => 'ee_edit_contacts',
403
+				'obj_id'     => $att_id,
404
+			),
405
+			'trash_attendees'                     => array(
406
+				'func'       => '_trash_or_restore_attendees',
407
+				'args'       => array(
408
+					'trash' => 'true',
409
+				),
410
+				'noheader'   => true,
411
+				'capability' => 'ee_delete_contacts',
412
+			),
413
+			'trash_attendee'                      => array(
414
+				'func'       => '_trash_or_restore_attendees',
415
+				'args'       => array(
416
+					'trash' => true,
417
+				),
418
+				'noheader'   => true,
419
+				'capability' => 'ee_delete_contacts',
420
+				'obj_id'     => $att_id,
421
+			),
422
+			'restore_attendees'                   => array(
423
+				'func'       => '_trash_or_restore_attendees',
424
+				'args'       => array(
425
+					'trash' => false,
426
+				),
427
+				'noheader'   => true,
428
+				'capability' => 'ee_delete_contacts',
429
+				'obj_id'     => $att_id,
430
+			),
431
+			'resend_registration'                 => array(
432
+				'func'       => '_resend_registration',
433
+				'noheader'   => true,
434
+				'capability' => 'ee_send_message',
435
+			),
436
+			'registrations_report'                => array(
437
+				'func'       => '_registrations_report',
438
+				'noheader'   => true,
439
+				'capability' => 'ee_read_registrations',
440
+			),
441
+			'contact_list_export'                 => array(
442
+				'func'       => '_contact_list_export',
443
+				'noheader'   => true,
444
+				'capability' => 'export',
445
+			),
446
+			'contact_list_report'                 => array(
447
+				'func'       => '_contact_list_report',
448
+				'noheader'   => true,
449
+				'capability' => 'ee_read_contacts',
450
+			),
451
+		);
452
+	}
453
+
454
+
455
+	protected function _set_page_config()
456
+	{
457
+		$this->_page_config = array(
458
+			'default'           => array(
459
+				'nav'           => array(
460
+					'label' => esc_html__('Overview', 'event_espresso'),
461
+					'order' => 5,
462
+				),
463
+				'help_tabs'     => array(
464
+					'registrations_overview_help_tab'                       => array(
465
+						'title'    => esc_html__('Registrations Overview', 'event_espresso'),
466
+						'filename' => 'registrations_overview',
467
+					),
468
+					'registrations_overview_table_column_headings_help_tab' => array(
469
+						'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
470
+						'filename' => 'registrations_overview_table_column_headings',
471
+					),
472
+					'registrations_overview_filters_help_tab'               => array(
473
+						'title'    => esc_html__('Registration Filters', 'event_espresso'),
474
+						'filename' => 'registrations_overview_filters',
475
+					),
476
+					'registrations_overview_views_help_tab'                 => array(
477
+						'title'    => esc_html__('Registration Views', 'event_espresso'),
478
+						'filename' => 'registrations_overview_views',
479
+					),
480
+					'registrations_regoverview_other_help_tab'              => array(
481
+						'title'    => esc_html__('Registrations Other', 'event_espresso'),
482
+						'filename' => 'registrations_overview_other',
483
+					),
484
+				),
485
+				'help_tour'     => array('Registration_Overview_Help_Tour'),
486
+				'qtips'         => array('Registration_List_Table_Tips'),
487
+				'list_table'    => 'EE_Registrations_List_Table',
488
+				'require_nonce' => false,
489
+			),
490
+			'view_registration' => array(
491
+				'nav'           => array(
492
+					'label'      => esc_html__('REG Details', 'event_espresso'),
493
+					'order'      => 15,
494
+					'url'        => isset($this->_req_data['_REG_ID'])
495
+						? add_query_arg(array('_REG_ID' => $this->_req_data['_REG_ID']), $this->_current_page_view_url)
496
+						: $this->_admin_base_url,
497
+					'persistent' => false,
498
+				),
499
+				'help_tabs'     => array(
500
+					'registrations_details_help_tab'                    => array(
501
+						'title'    => esc_html__('Registration Details', 'event_espresso'),
502
+						'filename' => 'registrations_details',
503
+					),
504
+					'registrations_details_table_help_tab'              => array(
505
+						'title'    => esc_html__('Registration Details Table', 'event_espresso'),
506
+						'filename' => 'registrations_details_table',
507
+					),
508
+					'registrations_details_form_answers_help_tab'       => array(
509
+						'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
510
+						'filename' => 'registrations_details_form_answers',
511
+					),
512
+					'registrations_details_registrant_details_help_tab' => array(
513
+						'title'    => esc_html__('Contact Details', 'event_espresso'),
514
+						'filename' => 'registrations_details_registrant_details',
515
+					),
516
+				),
517
+				'help_tour'     => array('Registration_Details_Help_Tour'),
518
+				'metaboxes'     => array_merge(
519
+					$this->_default_espresso_metaboxes,
520
+					array('_registration_details_metaboxes')
521
+				),
522
+				'require_nonce' => false,
523
+			),
524
+			'new_registration'  => array(
525
+				'nav'           => array(
526
+					'label'      => esc_html__('Add New Registration', 'event_espresso'),
527
+					'url'        => '#',
528
+					'order'      => 15,
529
+					'persistent' => false,
530
+				),
531
+				'metaboxes'     => $this->_default_espresso_metaboxes,
532
+				'labels'        => array(
533
+					'publishbox' => esc_html__('Save Registration', 'event_espresso'),
534
+				),
535
+				'require_nonce' => false,
536
+			),
537
+			'add_new_attendee'  => array(
538
+				'nav'           => array(
539
+					'label'      => esc_html__('Add Contact', 'event_espresso'),
540
+					'order'      => 15,
541
+					'persistent' => false,
542
+				),
543
+				'metaboxes'     => array_merge(
544
+					$this->_default_espresso_metaboxes,
545
+					array('_publish_post_box', 'attendee_editor_metaboxes')
546
+				),
547
+				'require_nonce' => false,
548
+			),
549
+			'edit_attendee'     => array(
550
+				'nav'           => array(
551
+					'label'      => esc_html__('Edit Contact', 'event_espresso'),
552
+					'order'      => 15,
553
+					'persistent' => false,
554
+					'url'        => isset($this->_req_data['ATT_ID'])
555
+						? add_query_arg(array('ATT_ID' => $this->_req_data['ATT_ID']), $this->_current_page_view_url)
556
+						: $this->_admin_base_url,
557
+				),
558
+				'metaboxes'     => array('attendee_editor_metaboxes'),
559
+				'require_nonce' => false,
560
+			),
561
+			'contact_list'      => array(
562
+				'nav'           => array(
563
+					'label' => esc_html__('Contact List', 'event_espresso'),
564
+					'order' => 20,
565
+				),
566
+				'list_table'    => 'EE_Attendee_Contact_List_Table',
567
+				'help_tabs'     => array(
568
+					'registrations_contact_list_help_tab'                       => array(
569
+						'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
570
+						'filename' => 'registrations_contact_list',
571
+					),
572
+					'registrations_contact-list_table_column_headings_help_tab' => array(
573
+						'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
574
+						'filename' => 'registrations_contact_list_table_column_headings',
575
+					),
576
+					'registrations_contact_list_views_help_tab'                 => array(
577
+						'title'    => esc_html__('Contact List Views', 'event_espresso'),
578
+						'filename' => 'registrations_contact_list_views',
579
+					),
580
+					'registrations_contact_list_other_help_tab'                 => array(
581
+						'title'    => esc_html__('Contact List Other', 'event_espresso'),
582
+						'filename' => 'registrations_contact_list_other',
583
+					),
584
+				),
585
+				'help_tour'     => array('Contact_List_Help_Tour'),
586
+				'metaboxes'     => array(),
587
+				'require_nonce' => false,
588
+			),
589
+			// override default cpt routes
590
+			'create_new'        => '',
591
+			'edit'              => '',
592
+		);
593
+	}
594
+
595
+
596
+	/**
597
+	 * The below methods aren't used by this class currently
598
+	 */
599
+	protected function _add_screen_options()
600
+	{
601
+	}
602
+
603
+
604
+	protected function _add_feature_pointers()
605
+	{
606
+	}
607
+
608
+
609
+	public function admin_init()
610
+	{
611
+		EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
612
+			'click "Update Registration Questions" to save your changes',
613
+			'event_espresso'
614
+		);
615
+	}
616
+
617
+
618
+	public function admin_notices()
619
+	{
620
+	}
621
+
622
+
623
+	public function admin_footer_scripts()
624
+	{
625
+	}
626
+
627
+
628
+	/**
629
+	 *        get list of registration statuses
630
+	 *
631
+	 * @access private
632
+	 * @return void
633
+	 * @throws EE_Error
634
+	 */
635
+	private function _get_registration_status_array()
636
+	{
637
+		self::$_reg_status = EEM_Registration::reg_status_array(array(), true);
638
+	}
639
+
640
+
641
+	protected function _add_screen_options_default()
642
+	{
643
+		$this->_per_page_screen_option();
644
+	}
645
+
646
+
647
+	protected function _add_screen_options_contact_list()
648
+	{
649
+		$page_title = $this->_admin_page_title;
650
+		$this->_admin_page_title = esc_html__("Contacts", 'event_espresso');
651
+		$this->_per_page_screen_option();
652
+		$this->_admin_page_title = $page_title;
653
+	}
654
+
655
+
656
+	public function load_scripts_styles()
657
+	{
658
+		// style
659
+		wp_register_style(
660
+			'espresso_reg',
661
+			REG_ASSETS_URL . 'espresso_registrations_admin.css',
662
+			array('ee-admin-css'),
663
+			EVENT_ESPRESSO_VERSION
664
+		);
665
+		wp_enqueue_style('espresso_reg');
666
+		// script
667
+		wp_register_script(
668
+			'espresso_reg',
669
+			REG_ASSETS_URL . 'espresso_registrations_admin.js',
670
+			array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
671
+			EVENT_ESPRESSO_VERSION,
672
+			true
673
+		);
674
+		wp_enqueue_script('espresso_reg');
675
+	}
676
+
677
+
678
+	public function load_scripts_styles_edit_attendee()
679
+	{
680
+		// stuff to only show up on our attendee edit details page.
681
+		$attendee_details_translations = array(
682
+			'att_publish_text' => sprintf(
683
+				esc_html__('Created on: <b>%1$s</b>', 'event_espresso'),
684
+				$this->_cpt_model_obj->get_datetime('ATT_created')
685
+			),
686
+		);
687
+		wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
688
+		wp_enqueue_script('jquery-validate');
689
+	}
690
+
691
+
692
+	public function load_scripts_styles_view_registration()
693
+	{
694
+		// styles
695
+		wp_enqueue_style('espresso-ui-theme');
696
+		// scripts
697
+		$this->_get_reg_custom_questions_form($this->_registration->ID());
698
+		$this->_reg_custom_questions_form->wp_enqueue_scripts(true);
699
+	}
700
+
701
+
702
+	public function load_scripts_styles_contact_list()
703
+	{
704
+		wp_dequeue_style('espresso_reg');
705
+		wp_register_style(
706
+			'espresso_att',
707
+			REG_ASSETS_URL . 'espresso_attendees_admin.css',
708
+			array('ee-admin-css'),
709
+			EVENT_ESPRESSO_VERSION
710
+		);
711
+		wp_enqueue_style('espresso_att');
712
+	}
713
+
714
+
715
+	public function load_scripts_styles_new_registration()
716
+	{
717
+		wp_register_script(
718
+			'ee-spco-for-admin',
719
+			REG_ASSETS_URL . 'spco_for_admin.js',
720
+			array('underscore', 'jquery'),
721
+			EVENT_ESPRESSO_VERSION,
722
+			true
723
+		);
724
+		wp_enqueue_script('ee-spco-for-admin');
725
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
726
+		EE_Form_Section_Proper::wp_enqueue_scripts();
727
+		EED_Ticket_Selector::load_tckt_slctr_assets();
728
+		EE_Datepicker_Input::enqueue_styles_and_scripts();
729
+	}
730
+
731
+
732
+	public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
733
+	{
734
+		add_filter('FHEE_load_EE_messages', '__return_true');
735
+	}
736
+
737
+
738
+	public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
739
+	{
740
+		add_filter('FHEE_load_EE_messages', '__return_true');
741
+	}
742
+
743
+
744
+	protected function _set_list_table_views_default()
745
+	{
746
+		// for notification related bulk actions we need to make sure only active messengers have an option.
747
+		EED_Messages::set_autoloaders();
748
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
749
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
750
+		$active_mts = $message_resource_manager->list_of_active_message_types();
751
+		// key= bulk_action_slug, value= message type.
752
+		$match_array = array(
753
+			'approve_registrations'    => 'registration',
754
+			'decline_registrations'    => 'declined_registration',
755
+			'pending_registrations'    => 'pending_approval',
756
+			'no_approve_registrations' => 'not_approved_registration',
757
+			'cancel_registrations'     => 'cancelled_registration',
758
+		);
759
+		$can_send = EE_Registry::instance()->CAP->current_user_can(
760
+			'ee_send_message',
761
+			'batch_send_messages'
762
+		);
763
+		/** setup reg status bulk actions **/
764
+		$def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
765
+		if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
766
+			$def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
767
+				'Approve and Notify Registrations',
768
+				'event_espresso'
769
+			);
770
+		}
771
+		$def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
772
+		if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
773
+			$def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
774
+				'Decline and Notify Registrations',
775
+				'event_espresso'
776
+			);
777
+		}
778
+		$def_reg_status_actions['pending_registrations'] = esc_html__(
779
+			'Set Registrations to Pending Payment',
780
+			'event_espresso'
781
+		);
782
+		if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
783
+			$def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
784
+				'Set Registrations to Pending Payment and Notify',
785
+				'event_espresso'
786
+			);
787
+		}
788
+		$def_reg_status_actions['no_approve_registrations'] = esc_html__(
789
+			'Set Registrations to Not Approved',
790
+			'event_espresso'
791
+		);
792
+		if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
793
+			$def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
794
+				'Set Registrations to Not Approved and Notify',
795
+				'event_espresso'
796
+			);
797
+		}
798
+		$def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
799
+		if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
800
+			$def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
801
+				'Cancel Registrations and Notify',
802
+				'event_espresso'
803
+			);
804
+		}
805
+		$def_reg_status_actions = apply_filters(
806
+			'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
807
+			$def_reg_status_actions,
808
+			$active_mts,
809
+			$can_send
810
+		);
811
+
812
+		$this->_views = array(
813
+			'all'   => array(
814
+				'slug'        => 'all',
815
+				'label'       => esc_html__('View All Registrations', 'event_espresso'),
816
+				'count'       => 0,
817
+				'bulk_action' => array_merge(
818
+					$def_reg_status_actions,
819
+					array(
820
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
821
+					)
822
+				),
823
+			),
824
+			'month' => array(
825
+				'slug'        => 'month',
826
+				'label'       => esc_html__('This Month', 'event_espresso'),
827
+				'count'       => 0,
828
+				'bulk_action' => array_merge(
829
+					$def_reg_status_actions,
830
+					array(
831
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
832
+					)
833
+				),
834
+			),
835
+			'today' => array(
836
+				'slug'        => 'today',
837
+				'label'       => sprintf(
838
+					esc_html__('Today - %s', 'event_espresso'),
839
+					date('M d, Y', current_time('timestamp'))
840
+				),
841
+				'count'       => 0,
842
+				'bulk_action' => array_merge(
843
+					$def_reg_status_actions,
844
+					array(
845
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
846
+					)
847
+				),
848
+			),
849
+		);
850
+		if (EE_Registry::instance()->CAP->current_user_can(
851
+			'ee_delete_registrations',
852
+			'espresso_registrations_delete_registration'
853
+		)) {
854
+			$this->_views['incomplete'] = array(
855
+				'slug'        => 'incomplete',
856
+				'label'       => esc_html__('Incomplete', 'event_espresso'),
857
+				'count'       => 0,
858
+				'bulk_action' => array(
859
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
860
+				),
861
+			);
862
+			$this->_views['trash'] = array(
863
+				'slug'        => 'trash',
864
+				'label'       => esc_html__('Trash', 'event_espresso'),
865
+				'count'       => 0,
866
+				'bulk_action' => array(
867
+					'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
868
+					'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
869
+				),
870
+			);
871
+		}
872
+	}
873
+
874
+
875
+	protected function _set_list_table_views_contact_list()
876
+	{
877
+		$this->_views = array(
878
+			'in_use' => array(
879
+				'slug'        => 'in_use',
880
+				'label'       => esc_html__('In Use', 'event_espresso'),
881
+				'count'       => 0,
882
+				'bulk_action' => array(
883
+					'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
884
+				),
885
+			),
886
+		);
887
+		if (EE_Registry::instance()->CAP->current_user_can(
888
+			'ee_delete_contacts',
889
+			'espresso_registrations_trash_attendees'
890
+		)
891
+		) {
892
+			$this->_views['trash'] = array(
893
+				'slug'        => 'trash',
894
+				'label'       => esc_html__('Trash', 'event_espresso'),
895
+				'count'       => 0,
896
+				'bulk_action' => array(
897
+					'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
898
+				),
899
+			);
900
+		}
901
+	}
902
+
903
+
904
+	protected function _registration_legend_items()
905
+	{
906
+		$fc_items = array(
907
+			'star-icon'        => array(
908
+				'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8',
909
+				'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
910
+			),
911
+			'view_details'     => array(
912
+				'class' => 'dashicons dashicons-clipboard',
913
+				'desc'  => esc_html__('View Registration Details', 'event_espresso'),
914
+			),
915
+			'edit_attendee'    => array(
916
+				'class' => 'ee-icon ee-icon-user-edit ee-icon-size-16',
917
+				'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
918
+			),
919
+			'view_transaction' => array(
920
+				'class' => 'dashicons dashicons-cart',
921
+				'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
922
+			),
923
+			'view_invoice'     => array(
924
+				'class' => 'dashicons dashicons-media-spreadsheet',
925
+				'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
926
+			),
927
+		);
928
+		if (EE_Registry::instance()->CAP->current_user_can(
929
+			'ee_send_message',
930
+			'espresso_registrations_resend_registration'
931
+		)) {
932
+			$fc_items['resend_registration'] = array(
933
+				'class' => 'dashicons dashicons-email-alt',
934
+				'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
935
+			);
936
+		} else {
937
+			$fc_items['blank'] = array('class' => 'blank', 'desc' => '');
938
+		}
939
+		if (EE_Registry::instance()->CAP->current_user_can(
940
+			'ee_read_global_messages',
941
+			'view_filtered_messages'
942
+		)) {
943
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
944
+			if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
945
+				$fc_items['view_related_messages'] = array(
946
+					'class' => $related_for_icon['css_class'],
947
+					'desc'  => $related_for_icon['label'],
948
+				);
949
+			}
950
+		}
951
+		$sc_items = array(
952
+			'approved_status'   => array(
953
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
954
+				'desc'  => EEH_Template::pretty_status(
955
+					EEM_Registration::status_id_approved,
956
+					false,
957
+					'sentence'
958
+				),
959
+			),
960
+			'pending_status'    => array(
961
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
962
+				'desc'  => EEH_Template::pretty_status(
963
+					EEM_Registration::status_id_pending_payment,
964
+					false,
965
+					'sentence'
966
+				),
967
+			),
968
+			'wait_list'         => array(
969
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
970
+				'desc'  => EEH_Template::pretty_status(
971
+					EEM_Registration::status_id_wait_list,
972
+					false,
973
+					'sentence'
974
+				),
975
+			),
976
+			'incomplete_status' => array(
977
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
978
+				'desc'  => EEH_Template::pretty_status(
979
+					EEM_Registration::status_id_incomplete,
980
+					false,
981
+					'sentence'
982
+				),
983
+			),
984
+			'not_approved'      => array(
985
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
986
+				'desc'  => EEH_Template::pretty_status(
987
+					EEM_Registration::status_id_not_approved,
988
+					false,
989
+					'sentence'
990
+				),
991
+			),
992
+			'declined_status'   => array(
993
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
994
+				'desc'  => EEH_Template::pretty_status(
995
+					EEM_Registration::status_id_declined,
996
+					false,
997
+					'sentence'
998
+				),
999
+			),
1000
+			'cancelled_status'  => array(
1001
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1002
+				'desc'  => EEH_Template::pretty_status(
1003
+					EEM_Registration::status_id_cancelled,
1004
+					false,
1005
+					'sentence'
1006
+				),
1007
+			),
1008
+		);
1009
+		return array_merge($fc_items, $sc_items);
1010
+	}
1011
+
1012
+
1013
+
1014
+	/***************************************        REGISTRATION OVERVIEW        **************************************/
1015
+	/**
1016
+	 * @throws \EE_Error
1017
+	 */
1018
+	protected function _registrations_overview_list_table()
1019
+	{
1020
+		$this->_template_args['admin_page_header'] = '';
1021
+		$EVT_ID = ! empty($this->_req_data['event_id'])
1022
+			? absint($this->_req_data['event_id'])
1023
+			: 0;
1024
+		$ATT_ID = ! empty($this->_req_data['ATT_ID'])
1025
+			? absint($this->_req_data['ATT_ID'])
1026
+			: 0;
1027
+		if ($ATT_ID) {
1028
+			$attendee = EEM_Attendee::instance()->get_one_by_ID($ATT_ID);
1029
+			if ($attendee instanceof EE_Attendee) {
1030
+				$this->_template_args['admin_page_header'] = sprintf(
1031
+					esc_html__(
1032
+						'%1$s Viewing registrations for %2$s%3$s',
1033
+						'event_espresso'
1034
+					),
1035
+					'<h3 style="line-height:1.5em;">',
1036
+					'<a href="' . EE_Admin_Page::add_query_args_and_nonce(
1037
+						array(
1038
+							'action' => 'edit_attendee',
1039
+							'post'   => $ATT_ID,
1040
+						),
1041
+						REG_ADMIN_URL
1042
+					) . '">' . $attendee->full_name() . '</a>',
1043
+					'</h3>'
1044
+				);
1045
+			}
1046
+		}
1047
+		if ($EVT_ID) {
1048
+			if (EE_Registry::instance()->CAP->current_user_can(
1049
+				'ee_edit_registrations',
1050
+				'espresso_registrations_new_registration',
1051
+				$EVT_ID
1052
+			)) {
1053
+				$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1054
+					'new_registration',
1055
+					'add-registrant',
1056
+					array('event_id' => $EVT_ID),
1057
+					'add-new-h2'
1058
+				);
1059
+			}
1060
+			$event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
1061
+			if ($event instanceof EE_Event) {
1062
+				$this->_template_args['admin_page_header'] = sprintf(
1063
+					esc_html__(
1064
+						'%s Viewing registrations for the event: %s%s',
1065
+						'event_espresso'
1066
+					),
1067
+					'<h3 style="line-height:1.5em;">',
1068
+					'<br /><a href="'
1069
+					. EE_Admin_Page::add_query_args_and_nonce(
1070
+						array(
1071
+							'action' => 'edit',
1072
+							'post'   => $event->ID(),
1073
+						),
1074
+						EVENTS_ADMIN_URL
1075
+					)
1076
+					. '">&nbsp;'
1077
+					. $event->get('EVT_name')
1078
+					. '&nbsp;</a>&nbsp;',
1079
+					'</h3>'
1080
+				);
1081
+			}
1082
+			$DTT_ID = ! empty($this->_req_data['datetime_id']) ? absint($this->_req_data['datetime_id']) : 0;
1083
+			$datetime = EEM_Datetime::instance()->get_one_by_ID($DTT_ID);
1084
+			if ($datetime instanceof EE_Datetime && $this->_template_args['admin_page_header'] !== '') {
1085
+				$this->_template_args['admin_page_header'] = substr(
1086
+					$this->_template_args['admin_page_header'],
1087
+					0,
1088
+					-5
1089
+				);
1090
+				$this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
1091
+				$this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
1092
+				$this->_template_args['admin_page_header'] .= $datetime->name();
1093
+				$this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
1094
+				$this->_template_args['admin_page_header'] .= '</span></h3>';
1095
+			}
1096
+		}
1097
+		$this->_template_args['after_list_table'] = $this->_display_legend($this->_registration_legend_items());
1098
+		$this->display_admin_list_table_page_with_no_sidebar();
1099
+	}
1100
+
1101
+
1102
+	/**
1103
+	 * This sets the _registration property for the registration details screen
1104
+	 *
1105
+	 * @access private
1106
+	 * @return bool
1107
+	 * @throws EE_Error
1108
+	 * @throws InvalidArgumentException
1109
+	 * @throws InvalidDataTypeException
1110
+	 * @throws InvalidInterfaceException
1111
+	 */
1112
+	private function _set_registration_object()
1113
+	{
1114
+		// get out if we've already set the object
1115
+		if ($this->_registration instanceof EE_Registration) {
1116
+			return true;
1117
+		}
1118
+		$REG = EEM_Registration::instance();
1119
+		$REG_ID = (! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1120
+		if ($this->_registration = $REG->get_one_by_ID($REG_ID)) {
1121
+			return true;
1122
+		} else {
1123
+			$error_msg = sprintf(
1124
+				esc_html__(
1125
+					'An error occurred and the details for Registration ID #%s could not be retrieved.',
1126
+					'event_espresso'
1127
+				),
1128
+				$REG_ID
1129
+			);
1130
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1131
+			$this->_registration = null;
1132
+			return false;
1133
+		}
1134
+	}
1135
+
1136
+
1137
+	/**
1138
+	 * Used to retrieve registrations for the list table.
1139
+	 *
1140
+	 * @param int  $per_page
1141
+	 * @param bool $count
1142
+	 * @param bool $this_month
1143
+	 * @param bool $today
1144
+	 * @return EE_Registration[]|int
1145
+	 * @throws EE_Error
1146
+	 * @throws InvalidArgumentException
1147
+	 * @throws InvalidDataTypeException
1148
+	 * @throws InvalidInterfaceException
1149
+	 */
1150
+	public function get_registrations(
1151
+		$per_page = 10,
1152
+		$count = false,
1153
+		$this_month = false,
1154
+		$today = false
1155
+	) {
1156
+		if ($this_month) {
1157
+			$this->_req_data['status'] = 'month';
1158
+		}
1159
+		if ($today) {
1160
+			$this->_req_data['status'] = 'today';
1161
+		}
1162
+		$query_params = $this->_get_registration_query_parameters($this->_req_data, $per_page, $count);
1163
+		/**
1164
+		 * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1165
+		 *
1166
+		 * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1167
+		 * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1168
+		 *                             or if you have the development copy of EE you can view this at the path:
1169
+		 *                             /docs/G--Model-System/model-query-params.md
1170
+		 */
1171
+		$query_params['group_by'] = '';
1172
+
1173
+		return $count
1174
+			? EEM_Registration::instance()->count($query_params)
1175
+			/** @type EE_Registration[] */
1176
+			: EEM_Registration::instance()->get_all($query_params);
1177
+	}
1178
+
1179
+
1180
+	/**
1181
+	 * Retrieves the query parameters to be used by the Registration model for getting registrations.
1182
+	 * Note: this listens to values on the request for some of the query parameters.
1183
+	 *
1184
+	 * @param array $request
1185
+	 * @param int   $per_page
1186
+	 * @param bool  $count
1187
+	 * @return array
1188
+	 * @throws EE_Error
1189
+	 */
1190
+	protected function _get_registration_query_parameters(
1191
+		$request = array(),
1192
+		$per_page = 10,
1193
+		$count = false
1194
+	) {
1195
+
1196
+		$query_params = array(
1197
+			0                          => $this->_get_where_conditions_for_registrations_query(
1198
+				$request
1199
+			),
1200
+			'caps'                     => EEM_Registration::caps_read_admin,
1201
+			'default_where_conditions' => 'this_model_only',
1202
+		);
1203
+		if (! $count) {
1204
+			$query_params = array_merge(
1205
+				$query_params,
1206
+				$this->_get_orderby_for_registrations_query(),
1207
+				$this->_get_limit($per_page)
1208
+			);
1209
+		}
1210
+
1211
+		return $query_params;
1212
+	}
1213
+
1214
+
1215
+	/**
1216
+	 * This will add ATT_ID to the provided $where array for EE model query parameters.
1217
+	 *
1218
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1219
+	 * @return array
1220
+	 */
1221
+	protected function addAttendeeIdToWhereConditions(array $request)
1222
+	{
1223
+		$where = array();
1224
+		if (! empty($request['ATT_ID'])) {
1225
+			$where['ATT_ID'] = absint($request['ATT_ID']);
1226
+		}
1227
+		return $where;
1228
+	}
1229
+
1230
+
1231
+	/**
1232
+	 * This will add EVT_ID to the provided $where array for EE model query parameters.
1233
+	 *
1234
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1235
+	 * @return array
1236
+	 */
1237
+	protected function _add_event_id_to_where_conditions(array $request)
1238
+	{
1239
+		$where = array();
1240
+		if (! empty($request['event_id'])) {
1241
+			$where['EVT_ID'] = absint($request['event_id']);
1242
+		}
1243
+		return $where;
1244
+	}
1245
+
1246
+
1247
+	/**
1248
+	 * Adds category ID if it exists in the request to the where conditions for the registrations query.
1249
+	 *
1250
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1251
+	 * @return array
1252
+	 */
1253
+	protected function _add_category_id_to_where_conditions(array $request)
1254
+	{
1255
+		$where = array();
1256
+		if (! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1257
+			$where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1258
+		}
1259
+		return $where;
1260
+	}
1261
+
1262
+
1263
+	/**
1264
+	 * Adds the datetime ID if it exists in the request to the where conditions for the registrations query.
1265
+	 *
1266
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1267
+	 * @return array
1268
+	 */
1269
+	protected function _add_datetime_id_to_where_conditions(array $request)
1270
+	{
1271
+		$where = array();
1272
+		if (! empty($request['datetime_id'])) {
1273
+			$where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1274
+		}
1275
+		if (! empty($request['DTT_ID'])) {
1276
+			$where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1277
+		}
1278
+		return $where;
1279
+	}
1280
+
1281
+
1282
+	/**
1283
+	 * Adds the correct registration status to the where conditions for the registrations query.
1284
+	 *
1285
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1286
+	 * @return array
1287
+	 */
1288
+	protected function _add_registration_status_to_where_conditions(array $request)
1289
+	{
1290
+		$where = array();
1291
+		$view = EEH_Array::is_set($request, 'status', '');
1292
+		$registration_status = ! empty($request['_reg_status'])
1293
+			? sanitize_text_field($request['_reg_status'])
1294
+			: '';
1295
+
1296
+		/*
1297 1297
          * If filtering by registration status, then we show registrations matching that status.
1298 1298
          * If not filtering by specified status, then we show all registrations excluding incomplete registrations
1299 1299
          * UNLESS viewing trashed registrations.
1300 1300
          */
1301
-        if (! empty($registration_status)) {
1302
-            $where['STS_ID'] = $registration_status;
1303
-        } else {
1304
-            // make sure we exclude incomplete registrations, but only if not trashed.
1305
-            if ($view === 'trash') {
1306
-                $where['REG_deleted'] = true;
1307
-            } elseif ($view === 'incomplete') {
1308
-                $where['STS_ID'] = EEM_Registration::status_id_incomplete;
1309
-            } else {
1310
-                $where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
1311
-            }
1312
-        }
1313
-        return $where;
1314
-    }
1315
-
1316
-
1317
-    /**
1318
-     * Adds any provided date restraints to the where conditions for the registrations query.
1319
-     *
1320
-     * @param array $request usually the same as $this->_req_data but not necessarily
1321
-     * @return array
1322
-     * @throws EE_Error
1323
-     * @throws InvalidArgumentException
1324
-     * @throws InvalidDataTypeException
1325
-     * @throws InvalidInterfaceException
1326
-     */
1327
-    protected function _add_date_to_where_conditions(array $request)
1328
-    {
1329
-        $where = array();
1330
-        $view = EEH_Array::is_set($request, 'status', '');
1331
-        $month_range = ! empty($request['month_range'])
1332
-            ? sanitize_text_field($request['month_range'])
1333
-            : '';
1334
-        $retrieve_for_today = $view === 'today';
1335
-        $retrieve_for_this_month = $view === 'month';
1336
-
1337
-        if ($retrieve_for_today) {
1338
-            $now = date('Y-m-d', current_time('timestamp'));
1339
-            $where['REG_date'] = array(
1340
-                'BETWEEN',
1341
-                array(
1342
-                    EEM_Registration::instance()->convert_datetime_for_query(
1343
-                        'REG_date',
1344
-                        $now . ' 00:00:00',
1345
-                        'Y-m-d H:i:s'
1346
-                    ),
1347
-                    EEM_Registration::instance()->convert_datetime_for_query(
1348
-                        'REG_date',
1349
-                        $now . ' 23:59:59',
1350
-                        'Y-m-d H:i:s'
1351
-                    ),
1352
-                ),
1353
-            );
1354
-        } elseif ($retrieve_for_this_month) {
1355
-            $current_year_and_month = date('Y-m', current_time('timestamp'));
1356
-            $days_this_month = date('t', current_time('timestamp'));
1357
-            $where['REG_date'] = array(
1358
-                'BETWEEN',
1359
-                array(
1360
-                    EEM_Registration::instance()->convert_datetime_for_query(
1361
-                        'REG_date',
1362
-                        $current_year_and_month . '-01 00:00:00',
1363
-                        'Y-m-d H:i:s'
1364
-                    ),
1365
-                    EEM_Registration::instance()->convert_datetime_for_query(
1366
-                        'REG_date',
1367
-                        $current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1368
-                        'Y-m-d H:i:s'
1369
-                    ),
1370
-                ),
1371
-            );
1372
-        } elseif ($month_range) {
1373
-            $pieces = explode(' ', $month_range, 3);
1374
-            $month_requested = ! empty($pieces[0])
1375
-                ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0]))
1376
-                : '';
1377
-            $year_requested = ! empty($pieces[1])
1378
-                ? $pieces[1]
1379
-                : '';
1380
-            // if there is not a month or year then we can't go further
1381
-            if ($month_requested && $year_requested) {
1382
-                $days_in_month = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1383
-                $where['REG_date'] = array(
1384
-                    'BETWEEN',
1385
-                    array(
1386
-                        EEM_Registration::instance()->convert_datetime_for_query(
1387
-                            'REG_date',
1388
-                            $year_requested . '-' . $month_requested . '-01 00:00:00',
1389
-                            'Y-m-d H:i:s'
1390
-                        ),
1391
-                        EEM_Registration::instance()->convert_datetime_for_query(
1392
-                            'REG_date',
1393
-                            $year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1394
-                            'Y-m-d H:i:s'
1395
-                        ),
1396
-                    ),
1397
-                );
1398
-            }
1399
-        }
1400
-        return $where;
1401
-    }
1402
-
1403
-
1404
-    /**
1405
-     * Adds any provided search restraints to the where conditions for the registrations query
1406
-     *
1407
-     * @param array $request usually the same as $this->_req_data but not necessarily
1408
-     * @return array
1409
-     */
1410
-    protected function _add_search_to_where_conditions(array $request)
1411
-    {
1412
-        $where = array();
1413
-        if (! empty($request['s'])) {
1414
-            $search_string = '%' . sanitize_text_field($request['s']) . '%';
1415
-            $where['OR*search_conditions'] = array(
1416
-                'Event.EVT_name'                          => array('LIKE', $search_string),
1417
-                'Event.EVT_desc'                          => array('LIKE', $search_string),
1418
-                'Event.EVT_short_desc'                    => array('LIKE', $search_string),
1419
-                'Attendee.ATT_full_name'                  => array('LIKE', $search_string),
1420
-                'Attendee.ATT_fname'                      => array('LIKE', $search_string),
1421
-                'Attendee.ATT_lname'                      => array('LIKE', $search_string),
1422
-                'Attendee.ATT_short_bio'                  => array('LIKE', $search_string),
1423
-                'Attendee.ATT_email'                      => array('LIKE', $search_string),
1424
-                'Attendee.ATT_address'                    => array('LIKE', $search_string),
1425
-                'Attendee.ATT_address2'                   => array('LIKE', $search_string),
1426
-                'Attendee.ATT_city'                       => array('LIKE', $search_string),
1427
-                'REG_final_price'                         => array('LIKE', $search_string),
1428
-                'REG_code'                                => array('LIKE', $search_string),
1429
-                'REG_count'                               => array('LIKE', $search_string),
1430
-                'REG_group_size'                          => array('LIKE', $search_string),
1431
-                'Ticket.TKT_name'                         => array('LIKE', $search_string),
1432
-                'Ticket.TKT_description'                  => array('LIKE', $search_string),
1433
-                'Transaction.Payment.PAY_txn_id_chq_nmbr' => array('LIKE', $search_string),
1434
-            );
1435
-        }
1436
-        return $where;
1437
-    }
1438
-
1439
-
1440
-    /**
1441
-     * Sets up the where conditions for the registrations query.
1442
-     *
1443
-     * @param array $request
1444
-     * @return array
1445
-     * @throws EE_Error
1446
-     */
1447
-    protected function _get_where_conditions_for_registrations_query($request)
1448
-    {
1449
-        return apply_filters(
1450
-            'FHEE__Registrations_Admin_Page___get_where_conditions_for_registrations_query',
1451
-            array_merge(
1452
-                $this->addAttendeeIdToWhereConditions($request),
1453
-                $this->_add_event_id_to_where_conditions($request),
1454
-                $this->_add_category_id_to_where_conditions($request),
1455
-                $this->_add_datetime_id_to_where_conditions($request),
1456
-                $this->_add_registration_status_to_where_conditions($request),
1457
-                $this->_add_date_to_where_conditions($request),
1458
-                $this->_add_search_to_where_conditions($request)
1459
-            ),
1460
-            $request
1461
-        );
1462
-    }
1463
-
1464
-
1465
-    /**
1466
-     * Sets up the orderby for the registrations query.
1467
-     *
1468
-     * @return array
1469
-     */
1470
-    protected function _get_orderby_for_registrations_query()
1471
-    {
1472
-        $orderby_field = ! empty($this->_req_data['orderby'])
1473
-            ? sanitize_text_field($this->_req_data['orderby'])
1474
-            : '_REG_date';
1475
-        switch ($orderby_field) {
1476
-            case '_REG_ID':
1477
-                $orderby = array('REG_ID');
1478
-                break;
1479
-            case '_Reg_status':
1480
-                $orderby = array('STS_ID');
1481
-                break;
1482
-            case 'ATT_fname':
1483
-                $orderby = array('Attendee.ATT_fname', 'Attendee.ATT_lname');
1484
-                break;
1485
-            case 'ATT_lname':
1486
-                $orderby = array('Attendee.ATT_lname', 'Attendee.ATT_fname');
1487
-                break;
1488
-            case 'event_name':
1489
-                $orderby = array('Event.EVT_name');
1490
-                break;
1491
-            case 'DTT_EVT_start':
1492
-                $orderby = array('Event.Datetime.DTT_EVT_start');
1493
-                break;
1494
-            case '_REG_date':
1495
-                $orderby = array('REG_date');
1496
-                break;
1497
-            default:
1498
-                $orderby = array($orderby_field);
1499
-                break;
1500
-        }
1501
-
1502
-        // order
1503
-        $order = ! empty($this->_req_data['order'])
1504
-            ? sanitize_text_field($this->_req_data['order'])
1505
-            : 'DESC';
1506
-        $orderby = array_combine(
1507
-            $orderby,
1508
-            array_fill(0, count($orderby), $order)
1509
-        );
1510
-        // because there are many registrations with the same date, define
1511
-        // a secondary way to order them, otherwise MySQL seems to be a bit random
1512
-        if (empty($orderby['REG_ID'])) {
1513
-            $orderby['REG_ID'] = $order;
1514
-        }
1515
-
1516
-        $orderby = apply_filters(
1517
-            'FHEE__Registrations_Admin_Page___get_orderby_for_registrations_query',
1518
-            $orderby,
1519
-            $this->_req_data
1520
-        );
1521
-
1522
-        return array('order_by' => $orderby);
1523
-    }
1524
-
1525
-
1526
-    /**
1527
-     * Sets up the limit for the registrations query.
1528
-     *
1529
-     * @param $per_page
1530
-     * @return array
1531
-     */
1532
-    protected function _get_limit($per_page)
1533
-    {
1534
-        $current_page = ! empty($this->_req_data['paged'])
1535
-            ? absint($this->_req_data['paged'])
1536
-            : 1;
1537
-        $per_page = ! empty($this->_req_data['perpage'])
1538
-            ? $this->_req_data['perpage']
1539
-            : $per_page;
1540
-
1541
-        // -1 means return all results so get out if that's set.
1542
-        if ((int) $per_page === -1) {
1543
-            return array();
1544
-        }
1545
-        $per_page = absint($per_page);
1546
-        $offset = ($current_page - 1) * $per_page;
1547
-        return array('limit' => array($offset, $per_page));
1548
-    }
1549
-
1550
-
1551
-    public function get_registration_status_array()
1552
-    {
1553
-        return self::$_reg_status;
1554
-    }
1555
-
1556
-
1557
-
1558
-
1559
-    /***************************************        REGISTRATION DETAILS        ***************************************/
1560
-    /**
1561
-     *        generates HTML for the View Registration Details Admin page
1562
-     *
1563
-     * @access protected
1564
-     * @return void
1565
-     * @throws DomainException
1566
-     * @throws EE_Error
1567
-     * @throws InvalidArgumentException
1568
-     * @throws InvalidDataTypeException
1569
-     * @throws InvalidInterfaceException
1570
-     * @throws EntityNotFoundException
1571
-     */
1572
-    protected function _registration_details()
1573
-    {
1574
-        $this->_template_args = array();
1575
-        $this->_set_registration_object();
1576
-        if (is_object($this->_registration)) {
1577
-            $transaction = $this->_registration->transaction()
1578
-                ? $this->_registration->transaction()
1579
-                : EE_Transaction::new_instance();
1580
-            $this->_session = $transaction->session_data();
1581
-            $event_id = $this->_registration->event_ID();
1582
-            $this->_template_args['reg_nmbr']['value'] = $this->_registration->ID();
1583
-            $this->_template_args['reg_nmbr']['label'] = esc_html__('Registration Number', 'event_espresso');
1584
-            $this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1585
-            $this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1586
-            $this->_template_args['grand_total'] = $transaction->total();
1587
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
1588
-            // link back to overview
1589
-            $this->_template_args['reg_overview_url'] = REG_ADMIN_URL;
1590
-            $this->_template_args['registration'] = $this->_registration;
1591
-            $this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1592
-                array(
1593
-                    'action'   => 'default',
1594
-                    'event_id' => $event_id,
1595
-                ),
1596
-                REG_ADMIN_URL
1597
-            );
1598
-            $this->_template_args['filtered_transactions_link'] = EE_Admin_Page::add_query_args_and_nonce(
1599
-                array(
1600
-                    'action' => 'default',
1601
-                    'EVT_ID' => $event_id,
1602
-                    'page'   => 'espresso_transactions',
1603
-                ),
1604
-                admin_url('admin.php')
1605
-            );
1606
-            $this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
1607
-                array(
1608
-                    'page'   => 'espresso_events',
1609
-                    'action' => 'edit',
1610
-                    'post'   => $event_id,
1611
-                ),
1612
-                admin_url('admin.php')
1613
-            );
1614
-            // next and previous links
1615
-            $next_reg = $this->_registration->next(
1616
-                null,
1617
-                array(),
1618
-                'REG_ID'
1619
-            );
1620
-            $this->_template_args['next_registration'] = $next_reg
1621
-                ? $this->_next_link(
1622
-                    EE_Admin_Page::add_query_args_and_nonce(
1623
-                        array(
1624
-                            'action'  => 'view_registration',
1625
-                            '_REG_ID' => $next_reg['REG_ID'],
1626
-                        ),
1627
-                        REG_ADMIN_URL
1628
-                    ),
1629
-                    'dashicons dashicons-arrow-right ee-icon-size-22'
1630
-                )
1631
-                : '';
1632
-            $previous_reg = $this->_registration->previous(
1633
-                null,
1634
-                array(),
1635
-                'REG_ID'
1636
-            );
1637
-            $this->_template_args['previous_registration'] = $previous_reg
1638
-                ? $this->_previous_link(
1639
-                    EE_Admin_Page::add_query_args_and_nonce(
1640
-                        array(
1641
-                            'action'  => 'view_registration',
1642
-                            '_REG_ID' => $previous_reg['REG_ID'],
1643
-                        ),
1644
-                        REG_ADMIN_URL
1645
-                    ),
1646
-                    'dashicons dashicons-arrow-left ee-icon-size-22'
1647
-                )
1648
-                : '';
1649
-            // grab header
1650
-            $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1651
-            $this->_template_args['REG_ID'] = $this->_registration->ID();
1652
-            $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1653
-                $template_path,
1654
-                $this->_template_args,
1655
-                true
1656
-            );
1657
-        } else {
1658
-            $this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1659
-        }
1660
-        // the details template wrapper
1661
-        $this->display_admin_page_with_sidebar();
1662
-    }
1663
-
1664
-
1665
-    protected function _registration_details_metaboxes()
1666
-    {
1667
-        do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1668
-        $this->_set_registration_object();
1669
-        $attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1670
-        add_meta_box(
1671
-            'edit-reg-status-mbox',
1672
-            esc_html__('Registration Status', 'event_espresso'),
1673
-            array($this, 'set_reg_status_buttons_metabox'),
1674
-            $this->wp_page_slug,
1675
-            'normal',
1676
-            'high'
1677
-        );
1678
-        add_meta_box(
1679
-            'edit-reg-details-mbox',
1680
-            esc_html__('Registration Details', 'event_espresso'),
1681
-            array($this, '_reg_details_meta_box'),
1682
-            $this->wp_page_slug,
1683
-            'normal',
1684
-            'high'
1685
-        );
1686
-        if ($attendee instanceof EE_Attendee
1687
-            && EE_Registry::instance()->CAP->current_user_can(
1688
-                'ee_read_registration',
1689
-                'edit-reg-questions-mbox',
1690
-                $this->_registration->ID()
1691
-            )
1692
-        ) {
1693
-            add_meta_box(
1694
-                'edit-reg-questions-mbox',
1695
-                esc_html__('Registration Form Answers', 'event_espresso'),
1696
-                array($this, '_reg_questions_meta_box'),
1697
-                $this->wp_page_slug,
1698
-                'normal',
1699
-                'high'
1700
-            );
1701
-        }
1702
-        add_meta_box(
1703
-            'edit-reg-registrant-mbox',
1704
-            esc_html__('Contact Details', 'event_espresso'),
1705
-            array($this, '_reg_registrant_side_meta_box'),
1706
-            $this->wp_page_slug,
1707
-            'side',
1708
-            'high'
1709
-        );
1710
-        if ($this->_registration->group_size() > 1) {
1711
-            add_meta_box(
1712
-                'edit-reg-attendees-mbox',
1713
-                esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1714
-                array($this, '_reg_attendees_meta_box'),
1715
-                $this->wp_page_slug,
1716
-                'normal',
1717
-                'high'
1718
-            );
1719
-        }
1720
-    }
1721
-
1722
-
1723
-    /**
1724
-     * set_reg_status_buttons_metabox
1725
-     *
1726
-     * @access protected
1727
-     * @return string
1728
-     * @throws \EE_Error
1729
-     */
1730
-    public function set_reg_status_buttons_metabox()
1731
-    {
1732
-        $this->_set_registration_object();
1733
-        $change_reg_status_form = $this->_generate_reg_status_change_form();
1734
-        echo $change_reg_status_form->form_open(
1735
-            self::add_query_args_and_nonce(
1736
-                array(
1737
-                    'action' => 'change_reg_status',
1738
-                ),
1739
-                REG_ADMIN_URL
1740
-            )
1741
-        );
1742
-        echo $change_reg_status_form->get_html();
1743
-        echo $change_reg_status_form->form_close();
1744
-    }
1745
-
1746
-
1747
-    /**
1748
-     * @return EE_Form_Section_Proper
1749
-     * @throws EE_Error
1750
-     * @throws InvalidArgumentException
1751
-     * @throws InvalidDataTypeException
1752
-     * @throws InvalidInterfaceException
1753
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1754
-     */
1755
-    protected function _generate_reg_status_change_form()
1756
-    {
1757
-        $reg_status_change_form_array = array(
1758
-            'name'            => 'reg_status_change_form',
1759
-            'html_id'         => 'reg-status-change-form',
1760
-            'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1761
-            'subsections'     => array(
1762
-                'return'             => new EE_Hidden_Input(
1763
-                    array(
1764
-                        'name'    => 'return',
1765
-                        'default' => 'view_registration',
1766
-                    )
1767
-                ),
1768
-                'REG_ID'             => new EE_Hidden_Input(
1769
-                    array(
1770
-                        'name'    => 'REG_ID',
1771
-                        'default' => $this->_registration->ID(),
1772
-                    )
1773
-                ),
1774
-                'current_status'     => new EE_Form_Section_HTML(
1775
-                    EEH_HTML::tr(
1776
-                        EEH_HTML::th(
1777
-                            EEH_HTML::label(
1778
-                                EEH_HTML::strong(
1779
-                                    esc_html__('Current Registration Status', 'event_espresso')
1780
-                                )
1781
-                            )
1782
-                        )
1783
-                        . EEH_HTML::td(
1784
-                            EEH_HTML::strong(
1785
-                                $this->_registration->pretty_status(),
1786
-                                '',
1787
-                                'status-' . $this->_registration->status_ID(),
1788
-                                'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1789
-                            )
1790
-                        )
1791
-                    )
1792
-                )
1793
-            )
1794
-        );
1795
-        if (EE_Registry::instance()->CAP->current_user_can(
1796
-            'ee_edit_registration',
1797
-            'toggle_registration_status',
1798
-            $this->_registration->ID()
1799
-        )) {
1800
-            $reg_status_change_form_array['subsections']['reg_status'] = new EE_Select_Input(
1801
-                $this->_get_reg_statuses(),
1802
-                array(
1803
-                    'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1804
-                    'default'         => $this->_registration->status_ID(),
1805
-                )
1806
-            );
1807
-            $reg_status_change_form_array['subsections']['send_notifications'] = new EE_Yes_No_Input(
1808
-                array(
1809
-                    'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1810
-                    'default'         => false,
1811
-                    'html_help_text'  => esc_html__(
1812
-                        'If set to "Yes", then the related messages will be sent to the registrant.',
1813
-                        'event_espresso'
1814
-                    )
1815
-                )
1816
-            );
1817
-            $reg_status_change_form_array['subsections']['submit'] = new EE_Submit_Input(
1818
-                array(
1819
-                    'html_class'      => 'button-primary',
1820
-                    'html_label_text' => '&nbsp;',
1821
-                    'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1822
-                )
1823
-            );
1824
-        }
1825
-        return new EE_Form_Section_Proper($reg_status_change_form_array);
1826
-    }
1827
-
1828
-
1829
-    /**
1830
-     * Returns an array of all the buttons for the various statuses and switch status actions
1831
-     *
1832
-     * @return array
1833
-     * @throws EE_Error
1834
-     * @throws InvalidArgumentException
1835
-     * @throws InvalidDataTypeException
1836
-     * @throws InvalidInterfaceException
1837
-     * @throws EntityNotFoundException
1838
-     */
1839
-    protected function _get_reg_statuses()
1840
-    {
1841
-        $reg_status_array = EEM_Registration::instance()->reg_status_array();
1842
-        unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1843
-        // get current reg status
1844
-        $current_status = $this->_registration->status_ID();
1845
-        // is registration for free event? This will determine whether to display the pending payment option
1846
-        if ($current_status !== EEM_Registration::status_id_pending_payment
1847
-            && EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1848
-        ) {
1849
-            unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1850
-        }
1851
-        return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1852
-    }
1853
-
1854
-
1855
-    /**
1856
-     * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1857
-     *
1858
-     * @param bool $status REG status given for changing registrations to.
1859
-     * @param bool $notify Whether to send messages notifications or not.
1860
-     * @return array (array with reg_id(s) updated and whether update was successful.
1861
-     * @throws EE_Error
1862
-     * @throws InvalidArgumentException
1863
-     * @throws InvalidDataTypeException
1864
-     * @throws InvalidInterfaceException
1865
-     * @throws ReflectionException
1866
-     * @throws RuntimeException
1867
-     * @throws EntityNotFoundException
1868
-     */
1869
-    protected function _set_registration_status_from_request($status = false, $notify = false)
1870
-    {
1871
-        if (isset($this->_req_data['reg_status_change_form'])) {
1872
-            $REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1873
-                ? (array) $this->_req_data['reg_status_change_form']['REG_ID']
1874
-                : array();
1875
-        } else {
1876
-            $REG_IDs = isset($this->_req_data['_REG_ID'])
1877
-                ? (array) $this->_req_data['_REG_ID']
1878
-                : array();
1879
-        }
1880
-        // sanitize $REG_IDs
1881
-        $REG_IDs = array_map('absint', $REG_IDs);
1882
-        // and remove empty entries
1883
-        $REG_IDs = array_filter($REG_IDs);
1884
-
1885
-        $result = $this->_set_registration_status($REG_IDs, $status, $notify);
1886
-
1887
-        /**
1888
-         * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1889
-         * Currently this value is used downstream by the _process_resend_registration method.
1890
-         *
1891
-         * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1892
-         * @param bool                     $status           The status registrations were changed to.
1893
-         * @param bool                     $success          If the status was changed successfully for all registrations.
1894
-         * @param Registrations_Admin_Page $admin_page_object
1895
-         */
1896
-        $this->_req_data['_REG_ID'] = apply_filters(
1897
-            'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1898
-            $result['REG_ID'],
1899
-            $status,
1900
-            $result['success'],
1901
-            $this
1902
-        );
1903
-
1904
-        // notify?
1905
-        if ($notify
1906
-            && $result['success']
1907
-            && ! empty($this->_req_data['_REG_ID'])
1908
-            && EE_Registry::instance()->CAP->current_user_can(
1909
-                'ee_send_message',
1910
-                'espresso_registrations_resend_registration'
1911
-            )
1912
-        ) {
1913
-            $this->_process_resend_registration();
1914
-        }
1915
-        return $result;
1916
-    }
1917
-
1918
-
1919
-    /**
1920
-     * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1921
-     * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1922
-     *
1923
-     * @param array  $REG_IDs
1924
-     * @param string $status
1925
-     * @param bool   $notify  Used to indicate whether notification was requested or not.  This determines the context
1926
-     *                        slug sent with setting the registration status.
1927
-     * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1928
-     * @throws EE_Error
1929
-     * @throws InvalidArgumentException
1930
-     * @throws InvalidDataTypeException
1931
-     * @throws InvalidInterfaceException
1932
-     * @throws ReflectionException
1933
-     * @throws RuntimeException
1934
-     * @throws EntityNotFoundException
1935
-     */
1936
-    protected function _set_registration_status($REG_IDs = array(), $status = '', $notify = false)
1937
-    {
1938
-        $success = false;
1939
-        // typecast $REG_IDs
1940
-        $REG_IDs = (array) $REG_IDs;
1941
-        if (! empty($REG_IDs)) {
1942
-            $success = true;
1943
-            // set default status if none is passed
1944
-            $status = $status ? $status : EEM_Registration::status_id_pending_payment;
1945
-            $status_context = $notify
1946
-                ? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1947
-                : Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1948
-            // loop through REG_ID's and change status
1949
-            foreach ($REG_IDs as $REG_ID) {
1950
-                $registration = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1951
-                if ($registration instanceof EE_Registration) {
1952
-                    $registration->set_status(
1953
-                        $status,
1954
-                        false,
1955
-                        new Context(
1956
-                            $status_context,
1957
-                            esc_html__(
1958
-                                'Manually triggered status change on a Registration Admin Page route.',
1959
-                                'event_espresso'
1960
-                            )
1961
-                        )
1962
-                    );
1963
-                    $result = $registration->save();
1964
-                    // verifying explicit fails because update *may* just return 0 for 0 rows affected
1965
-                    $success = $result !== false ? $success : false;
1966
-                }
1967
-            }
1968
-        }
1969
-
1970
-        // return $success and processed registrations
1971
-        return array('REG_ID' => $REG_IDs, 'success' => $success);
1972
-    }
1973
-
1974
-
1975
-    /**
1976
-     * Common logic for setting up success message and redirecting to appropriate route
1977
-     *
1978
-     * @param  string $STS_ID status id for the registration changed to
1979
-     * @param   bool  $notify indicates whether the _set_registration_status_from_request does notifications or not.
1980
-     * @return void
1981
-     * @throws EE_Error
1982
-     */
1983
-    protected function _reg_status_change_return($STS_ID, $notify = false)
1984
-    {
1985
-        $result = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1986
-            : array('success' => false);
1987
-        $success = isset($result['success']) && $result['success'];
1988
-        // setup success message
1989
-        if ($success) {
1990
-            if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1991
-                $msg = sprintf(
1992
-                    esc_html__('Registration status has been set to %s', 'event_espresso'),
1993
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1994
-                );
1995
-            } else {
1996
-                $msg = sprintf(
1997
-                    esc_html__('Registrations have been set to %s.', 'event_espresso'),
1998
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1999
-                );
2000
-            }
2001
-            EE_Error::add_success($msg);
2002
-        } else {
2003
-            EE_Error::add_error(
2004
-                esc_html__(
2005
-                    'Something went wrong, and the status was not changed',
2006
-                    'event_espresso'
2007
-                ),
2008
-                __FILE__,
2009
-                __LINE__,
2010
-                __FUNCTION__
2011
-            );
2012
-        }
2013
-        if (isset($this->_req_data['return']) && $this->_req_data['return'] == 'view_registration') {
2014
-            $route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
2015
-        } else {
2016
-            $route = array('action' => 'default');
2017
-        }
2018
-        $route = $this->mergeExistingRequestParamsWithRedirectArgs($route);
2019
-        $this->_redirect_after_action($success, '', '', $route, true);
2020
-    }
2021
-
2022
-
2023
-    /**
2024
-     * incoming reg status change from reg details page.
2025
-     *
2026
-     * @return void
2027
-     */
2028
-    protected function _change_reg_status()
2029
-    {
2030
-        $this->_req_data['return'] = 'view_registration';
2031
-        // set notify based on whether the send notifications toggle is set or not
2032
-        $notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
2033
-        // $notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
2034
-        $this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
2035
-            ? $this->_req_data['reg_status_change_form']['reg_status'] : '';
2036
-        switch ($this->_req_data['reg_status_change_form']['reg_status']) {
2037
-            case EEM_Registration::status_id_approved:
2038
-            case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'):
2039
-                $this->approve_registration($notify);
2040
-                break;
2041
-            case EEM_Registration::status_id_pending_payment:
2042
-            case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'):
2043
-                $this->pending_registration($notify);
2044
-                break;
2045
-            case EEM_Registration::status_id_not_approved:
2046
-            case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'):
2047
-                $this->not_approve_registration($notify);
2048
-                break;
2049
-            case EEM_Registration::status_id_declined:
2050
-            case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'):
2051
-                $this->decline_registration($notify);
2052
-                break;
2053
-            case EEM_Registration::status_id_cancelled:
2054
-            case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'):
2055
-                $this->cancel_registration($notify);
2056
-                break;
2057
-            case EEM_Registration::status_id_wait_list:
2058
-            case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'):
2059
-                $this->wait_list_registration($notify);
2060
-                break;
2061
-            case EEM_Registration::status_id_incomplete:
2062
-            default:
2063
-                $result['success'] = false;
2064
-                unset($this->_req_data['return']);
2065
-                $this->_reg_status_change_return('', false);
2066
-                break;
2067
-        }
2068
-    }
2069
-
2070
-
2071
-    /**
2072
-     * Callback for bulk action routes.
2073
-     * Note: although we could just register the singular route callbacks for each bulk action route as well, this
2074
-     * method was chosen so there is one central place all the registration status bulk actions are going through.
2075
-     * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
2076
-     * when an action is happening on just a single registration).
2077
-     *
2078
-     * @param      $action
2079
-     * @param bool $notify
2080
-     */
2081
-    protected function bulk_action_on_registrations($action, $notify = false)
2082
-    {
2083
-        do_action(
2084
-            'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
2085
-            $this,
2086
-            $action,
2087
-            $notify
2088
-        );
2089
-        $method = $action . '_registration';
2090
-        if (method_exists($this, $method)) {
2091
-            $this->$method($notify);
2092
-        }
2093
-    }
2094
-
2095
-
2096
-    /**
2097
-     * approve_registration
2098
-     *
2099
-     * @access protected
2100
-     * @param bool $notify whether or not to notify the registrant about their approval.
2101
-     * @return void
2102
-     */
2103
-    protected function approve_registration($notify = false)
2104
-    {
2105
-        $this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
2106
-    }
2107
-
2108
-
2109
-    /**
2110
-     *        decline_registration
2111
-     *
2112
-     * @access protected
2113
-     * @param bool $notify whether or not to notify the registrant about their status change.
2114
-     * @return void
2115
-     */
2116
-    protected function decline_registration($notify = false)
2117
-    {
2118
-        $this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
2119
-    }
2120
-
2121
-
2122
-    /**
2123
-     *        cancel_registration
2124
-     *
2125
-     * @access protected
2126
-     * @param bool $notify whether or not to notify the registrant about their status change.
2127
-     * @return void
2128
-     */
2129
-    protected function cancel_registration($notify = false)
2130
-    {
2131
-        $this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
2132
-    }
2133
-
2134
-
2135
-    /**
2136
-     *        not_approve_registration
2137
-     *
2138
-     * @access protected
2139
-     * @param bool $notify whether or not to notify the registrant about their status change.
2140
-     * @return void
2141
-     */
2142
-    protected function not_approve_registration($notify = false)
2143
-    {
2144
-        $this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
2145
-    }
2146
-
2147
-
2148
-    /**
2149
-     *        decline_registration
2150
-     *
2151
-     * @access protected
2152
-     * @param bool $notify whether or not to notify the registrant about their status change.
2153
-     * @return void
2154
-     */
2155
-    protected function pending_registration($notify = false)
2156
-    {
2157
-        $this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
2158
-    }
2159
-
2160
-
2161
-    /**
2162
-     * waitlist_registration
2163
-     *
2164
-     * @access protected
2165
-     * @param bool $notify whether or not to notify the registrant about their status change.
2166
-     * @return void
2167
-     */
2168
-    protected function wait_list_registration($notify = false)
2169
-    {
2170
-        $this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
2171
-    }
2172
-
2173
-
2174
-    /**
2175
-     *        generates HTML for the Registration main meta box
2176
-     *
2177
-     * @access public
2178
-     * @return void
2179
-     * @throws DomainException
2180
-     * @throws EE_Error
2181
-     * @throws InvalidArgumentException
2182
-     * @throws InvalidDataTypeException
2183
-     * @throws InvalidInterfaceException
2184
-     * @throws ReflectionException
2185
-     * @throws EntityNotFoundException
2186
-     */
2187
-    public function _reg_details_meta_box()
2188
-    {
2189
-        EEH_Autoloader::register_line_item_display_autoloaders();
2190
-        EEH_Autoloader::register_line_item_filter_autoloaders();
2191
-        EE_Registry::instance()->load_helper('Line_Item');
2192
-        $transaction = $this->_registration->transaction() ? $this->_registration->transaction()
2193
-            : EE_Transaction::new_instance();
2194
-        $this->_session = $transaction->session_data();
2195
-        $filters = new EE_Line_Item_Filter_Collection();
2196
-        // $filters->add( new EE_Non_Zero_Line_Item_Filter() );
2197
-        $filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2198
-        $line_item_filter_processor = new EE_Line_Item_Filter_Processor(
2199
-            $filters,
2200
-            $transaction->total_line_item()
2201
-        );
2202
-        $filtered_line_item_tree = $line_item_filter_processor->process();
2203
-        $line_item_display = new EE_Line_Item_Display(
2204
-            'reg_admin_table',
2205
-            'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2206
-        );
2207
-        $this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2208
-            $filtered_line_item_tree,
2209
-            array('EE_Registration' => $this->_registration)
2210
-        );
2211
-        $attendee = $this->_registration->attendee();
2212
-        if (EE_Registry::instance()->CAP->current_user_can(
2213
-            'ee_read_transaction',
2214
-            'espresso_transactions_view_transaction'
2215
-        )) {
2216
-            $this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2217
-                EE_Admin_Page::add_query_args_and_nonce(
2218
-                    array(
2219
-                        'action' => 'view_transaction',
2220
-                        'TXN_ID' => $transaction->ID(),
2221
-                    ),
2222
-                    TXN_ADMIN_URL
2223
-                ),
2224
-                esc_html__(' View Transaction', 'event_espresso'),
2225
-                'button secondary-button right',
2226
-                'dashicons dashicons-cart'
2227
-            );
2228
-        } else {
2229
-            $this->_template_args['view_transaction_button'] = '';
2230
-        }
2231
-        if ($attendee instanceof EE_Attendee
2232
-            && EE_Registry::instance()->CAP->current_user_can(
2233
-                'ee_send_message',
2234
-                'espresso_registrations_resend_registration'
2235
-            )
2236
-        ) {
2237
-            $this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2238
-                EE_Admin_Page::add_query_args_and_nonce(
2239
-                    array(
2240
-                        'action'      => 'resend_registration',
2241
-                        '_REG_ID'     => $this->_registration->ID(),
2242
-                        'redirect_to' => 'view_registration',
2243
-                    ),
2244
-                    REG_ADMIN_URL
2245
-                ),
2246
-                esc_html__(' Resend Registration', 'event_espresso'),
2247
-                'button secondary-button right',
2248
-                'dashicons dashicons-email-alt'
2249
-            );
2250
-        } else {
2251
-            $this->_template_args['resend_registration_button'] = '';
2252
-        }
2253
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2254
-        $payment = $transaction->get_first_related('Payment');
2255
-        $payment = ! $payment instanceof EE_Payment
2256
-            ? EE_Payment::new_instance()
2257
-            : $payment;
2258
-        $payment_method = $payment->get_first_related('Payment_Method');
2259
-        $payment_method = ! $payment_method instanceof EE_Payment_Method
2260
-            ? EE_Payment_Method::new_instance()
2261
-            : $payment_method;
2262
-        $reg_details = array(
2263
-            'payment_method'       => $payment_method->name(),
2264
-            'response_msg'         => $payment->gateway_response(),
2265
-            'registration_id'      => $this->_registration->get('REG_code'),
2266
-            'registration_session' => $this->_registration->session_ID(),
2267
-            'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2268
-            'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2269
-        );
2270
-        if (isset($reg_details['registration_id'])) {
2271
-            $this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2272
-            $this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2273
-                'Registration ID',
2274
-                'event_espresso'
2275
-            );
2276
-            $this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2277
-        }
2278
-        if (isset($reg_details['payment_method'])) {
2279
-            $this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2280
-            $this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2281
-                'Most Recent Payment Method',
2282
-                'event_espresso'
2283
-            );
2284
-            $this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2285
-            $this->_template_args['reg_details']['response_msg']['value'] = $reg_details['response_msg'];
2286
-            $this->_template_args['reg_details']['response_msg']['label'] = esc_html__(
2287
-                'Payment method response',
2288
-                'event_espresso'
2289
-            );
2290
-            $this->_template_args['reg_details']['response_msg']['class'] = 'regular-text';
2291
-        }
2292
-        $this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2293
-        $this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2294
-            'Registration Session',
2295
-            'event_espresso'
2296
-        );
2297
-        $this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2298
-        $this->_template_args['reg_details']['ip_address']['value'] = $reg_details['ip_address'];
2299
-        $this->_template_args['reg_details']['ip_address']['label'] = esc_html__(
2300
-            'Registration placed from IP',
2301
-            'event_espresso'
2302
-        );
2303
-        $this->_template_args['reg_details']['ip_address']['class'] = 'regular-text';
2304
-        $this->_template_args['reg_details']['user_agent']['value'] = $reg_details['user_agent'];
2305
-        $this->_template_args['reg_details']['user_agent']['label'] = esc_html__(
2306
-            'Registrant User Agent',
2307
-            'event_espresso'
2308
-        );
2309
-        $this->_template_args['reg_details']['user_agent']['class'] = 'large-text';
2310
-        $this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
2311
-            array(
2312
-                'action'   => 'default',
2313
-                'event_id' => $this->_registration->event_ID(),
2314
-            ),
2315
-            REG_ADMIN_URL
2316
-        );
2317
-        $this->_template_args['REG_ID'] = $this->_registration->ID();
2318
-        $this->_template_args['event_id'] = $this->_registration->event_ID();
2319
-        $template_path =
2320
-            REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2321
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2322
-    }
2323
-
2324
-
2325
-    /**
2326
-     * generates HTML for the Registration Questions meta box.
2327
-     * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2328
-     * otherwise uses new forms system
2329
-     *
2330
-     * @access public
2331
-     * @return void
2332
-     * @throws DomainException
2333
-     * @throws EE_Error
2334
-     */
2335
-    public function _reg_questions_meta_box()
2336
-    {
2337
-        // allow someone to override this method entirely
2338
-        if (apply_filters(
2339
-            'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2340
-            true,
2341
-            $this,
2342
-            $this->_registration
2343
-        )) {
2344
-            $form = $this->_get_reg_custom_questions_form(
2345
-                $this->_registration->ID()
2346
-            );
2347
-            $this->_template_args['att_questions'] = count($form->subforms()) > 0
2348
-                ? $form->get_html_and_js()
2349
-                : '';
2350
-            $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2351
-            $this->_template_args['REG_ID'] = $this->_registration->ID();
2352
-            $template_path =
2353
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2354
-            echo EEH_Template::display_template($template_path, $this->_template_args, true);
2355
-        }
2356
-    }
2357
-
2358
-
2359
-    /**
2360
-     * form_before_question_group
2361
-     *
2362
-     * @deprecated    as of 4.8.32.rc.000
2363
-     * @access        public
2364
-     * @param        string $output
2365
-     * @return        string
2366
-     */
2367
-    public function form_before_question_group($output)
2368
-    {
2369
-        EE_Error::doing_it_wrong(
2370
-            __CLASS__ . '::' . __FUNCTION__,
2371
-            esc_html__(
2372
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2373
-                'event_espresso'
2374
-            ),
2375
-            '4.8.32.rc.000'
2376
-        );
2377
-        return '
1301
+		if (! empty($registration_status)) {
1302
+			$where['STS_ID'] = $registration_status;
1303
+		} else {
1304
+			// make sure we exclude incomplete registrations, but only if not trashed.
1305
+			if ($view === 'trash') {
1306
+				$where['REG_deleted'] = true;
1307
+			} elseif ($view === 'incomplete') {
1308
+				$where['STS_ID'] = EEM_Registration::status_id_incomplete;
1309
+			} else {
1310
+				$where['STS_ID'] = array('!=', EEM_Registration::status_id_incomplete);
1311
+			}
1312
+		}
1313
+		return $where;
1314
+	}
1315
+
1316
+
1317
+	/**
1318
+	 * Adds any provided date restraints to the where conditions for the registrations query.
1319
+	 *
1320
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1321
+	 * @return array
1322
+	 * @throws EE_Error
1323
+	 * @throws InvalidArgumentException
1324
+	 * @throws InvalidDataTypeException
1325
+	 * @throws InvalidInterfaceException
1326
+	 */
1327
+	protected function _add_date_to_where_conditions(array $request)
1328
+	{
1329
+		$where = array();
1330
+		$view = EEH_Array::is_set($request, 'status', '');
1331
+		$month_range = ! empty($request['month_range'])
1332
+			? sanitize_text_field($request['month_range'])
1333
+			: '';
1334
+		$retrieve_for_today = $view === 'today';
1335
+		$retrieve_for_this_month = $view === 'month';
1336
+
1337
+		if ($retrieve_for_today) {
1338
+			$now = date('Y-m-d', current_time('timestamp'));
1339
+			$where['REG_date'] = array(
1340
+				'BETWEEN',
1341
+				array(
1342
+					EEM_Registration::instance()->convert_datetime_for_query(
1343
+						'REG_date',
1344
+						$now . ' 00:00:00',
1345
+						'Y-m-d H:i:s'
1346
+					),
1347
+					EEM_Registration::instance()->convert_datetime_for_query(
1348
+						'REG_date',
1349
+						$now . ' 23:59:59',
1350
+						'Y-m-d H:i:s'
1351
+					),
1352
+				),
1353
+			);
1354
+		} elseif ($retrieve_for_this_month) {
1355
+			$current_year_and_month = date('Y-m', current_time('timestamp'));
1356
+			$days_this_month = date('t', current_time('timestamp'));
1357
+			$where['REG_date'] = array(
1358
+				'BETWEEN',
1359
+				array(
1360
+					EEM_Registration::instance()->convert_datetime_for_query(
1361
+						'REG_date',
1362
+						$current_year_and_month . '-01 00:00:00',
1363
+						'Y-m-d H:i:s'
1364
+					),
1365
+					EEM_Registration::instance()->convert_datetime_for_query(
1366
+						'REG_date',
1367
+						$current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1368
+						'Y-m-d H:i:s'
1369
+					),
1370
+				),
1371
+			);
1372
+		} elseif ($month_range) {
1373
+			$pieces = explode(' ', $month_range, 3);
1374
+			$month_requested = ! empty($pieces[0])
1375
+				? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0]))
1376
+				: '';
1377
+			$year_requested = ! empty($pieces[1])
1378
+				? $pieces[1]
1379
+				: '';
1380
+			// if there is not a month or year then we can't go further
1381
+			if ($month_requested && $year_requested) {
1382
+				$days_in_month = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1383
+				$where['REG_date'] = array(
1384
+					'BETWEEN',
1385
+					array(
1386
+						EEM_Registration::instance()->convert_datetime_for_query(
1387
+							'REG_date',
1388
+							$year_requested . '-' . $month_requested . '-01 00:00:00',
1389
+							'Y-m-d H:i:s'
1390
+						),
1391
+						EEM_Registration::instance()->convert_datetime_for_query(
1392
+							'REG_date',
1393
+							$year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1394
+							'Y-m-d H:i:s'
1395
+						),
1396
+					),
1397
+				);
1398
+			}
1399
+		}
1400
+		return $where;
1401
+	}
1402
+
1403
+
1404
+	/**
1405
+	 * Adds any provided search restraints to the where conditions for the registrations query
1406
+	 *
1407
+	 * @param array $request usually the same as $this->_req_data but not necessarily
1408
+	 * @return array
1409
+	 */
1410
+	protected function _add_search_to_where_conditions(array $request)
1411
+	{
1412
+		$where = array();
1413
+		if (! empty($request['s'])) {
1414
+			$search_string = '%' . sanitize_text_field($request['s']) . '%';
1415
+			$where['OR*search_conditions'] = array(
1416
+				'Event.EVT_name'                          => array('LIKE', $search_string),
1417
+				'Event.EVT_desc'                          => array('LIKE', $search_string),
1418
+				'Event.EVT_short_desc'                    => array('LIKE', $search_string),
1419
+				'Attendee.ATT_full_name'                  => array('LIKE', $search_string),
1420
+				'Attendee.ATT_fname'                      => array('LIKE', $search_string),
1421
+				'Attendee.ATT_lname'                      => array('LIKE', $search_string),
1422
+				'Attendee.ATT_short_bio'                  => array('LIKE', $search_string),
1423
+				'Attendee.ATT_email'                      => array('LIKE', $search_string),
1424
+				'Attendee.ATT_address'                    => array('LIKE', $search_string),
1425
+				'Attendee.ATT_address2'                   => array('LIKE', $search_string),
1426
+				'Attendee.ATT_city'                       => array('LIKE', $search_string),
1427
+				'REG_final_price'                         => array('LIKE', $search_string),
1428
+				'REG_code'                                => array('LIKE', $search_string),
1429
+				'REG_count'                               => array('LIKE', $search_string),
1430
+				'REG_group_size'                          => array('LIKE', $search_string),
1431
+				'Ticket.TKT_name'                         => array('LIKE', $search_string),
1432
+				'Ticket.TKT_description'                  => array('LIKE', $search_string),
1433
+				'Transaction.Payment.PAY_txn_id_chq_nmbr' => array('LIKE', $search_string),
1434
+			);
1435
+		}
1436
+		return $where;
1437
+	}
1438
+
1439
+
1440
+	/**
1441
+	 * Sets up the where conditions for the registrations query.
1442
+	 *
1443
+	 * @param array $request
1444
+	 * @return array
1445
+	 * @throws EE_Error
1446
+	 */
1447
+	protected function _get_where_conditions_for_registrations_query($request)
1448
+	{
1449
+		return apply_filters(
1450
+			'FHEE__Registrations_Admin_Page___get_where_conditions_for_registrations_query',
1451
+			array_merge(
1452
+				$this->addAttendeeIdToWhereConditions($request),
1453
+				$this->_add_event_id_to_where_conditions($request),
1454
+				$this->_add_category_id_to_where_conditions($request),
1455
+				$this->_add_datetime_id_to_where_conditions($request),
1456
+				$this->_add_registration_status_to_where_conditions($request),
1457
+				$this->_add_date_to_where_conditions($request),
1458
+				$this->_add_search_to_where_conditions($request)
1459
+			),
1460
+			$request
1461
+		);
1462
+	}
1463
+
1464
+
1465
+	/**
1466
+	 * Sets up the orderby for the registrations query.
1467
+	 *
1468
+	 * @return array
1469
+	 */
1470
+	protected function _get_orderby_for_registrations_query()
1471
+	{
1472
+		$orderby_field = ! empty($this->_req_data['orderby'])
1473
+			? sanitize_text_field($this->_req_data['orderby'])
1474
+			: '_REG_date';
1475
+		switch ($orderby_field) {
1476
+			case '_REG_ID':
1477
+				$orderby = array('REG_ID');
1478
+				break;
1479
+			case '_Reg_status':
1480
+				$orderby = array('STS_ID');
1481
+				break;
1482
+			case 'ATT_fname':
1483
+				$orderby = array('Attendee.ATT_fname', 'Attendee.ATT_lname');
1484
+				break;
1485
+			case 'ATT_lname':
1486
+				$orderby = array('Attendee.ATT_lname', 'Attendee.ATT_fname');
1487
+				break;
1488
+			case 'event_name':
1489
+				$orderby = array('Event.EVT_name');
1490
+				break;
1491
+			case 'DTT_EVT_start':
1492
+				$orderby = array('Event.Datetime.DTT_EVT_start');
1493
+				break;
1494
+			case '_REG_date':
1495
+				$orderby = array('REG_date');
1496
+				break;
1497
+			default:
1498
+				$orderby = array($orderby_field);
1499
+				break;
1500
+		}
1501
+
1502
+		// order
1503
+		$order = ! empty($this->_req_data['order'])
1504
+			? sanitize_text_field($this->_req_data['order'])
1505
+			: 'DESC';
1506
+		$orderby = array_combine(
1507
+			$orderby,
1508
+			array_fill(0, count($orderby), $order)
1509
+		);
1510
+		// because there are many registrations with the same date, define
1511
+		// a secondary way to order them, otherwise MySQL seems to be a bit random
1512
+		if (empty($orderby['REG_ID'])) {
1513
+			$orderby['REG_ID'] = $order;
1514
+		}
1515
+
1516
+		$orderby = apply_filters(
1517
+			'FHEE__Registrations_Admin_Page___get_orderby_for_registrations_query',
1518
+			$orderby,
1519
+			$this->_req_data
1520
+		);
1521
+
1522
+		return array('order_by' => $orderby);
1523
+	}
1524
+
1525
+
1526
+	/**
1527
+	 * Sets up the limit for the registrations query.
1528
+	 *
1529
+	 * @param $per_page
1530
+	 * @return array
1531
+	 */
1532
+	protected function _get_limit($per_page)
1533
+	{
1534
+		$current_page = ! empty($this->_req_data['paged'])
1535
+			? absint($this->_req_data['paged'])
1536
+			: 1;
1537
+		$per_page = ! empty($this->_req_data['perpage'])
1538
+			? $this->_req_data['perpage']
1539
+			: $per_page;
1540
+
1541
+		// -1 means return all results so get out if that's set.
1542
+		if ((int) $per_page === -1) {
1543
+			return array();
1544
+		}
1545
+		$per_page = absint($per_page);
1546
+		$offset = ($current_page - 1) * $per_page;
1547
+		return array('limit' => array($offset, $per_page));
1548
+	}
1549
+
1550
+
1551
+	public function get_registration_status_array()
1552
+	{
1553
+		return self::$_reg_status;
1554
+	}
1555
+
1556
+
1557
+
1558
+
1559
+	/***************************************        REGISTRATION DETAILS        ***************************************/
1560
+	/**
1561
+	 *        generates HTML for the View Registration Details Admin page
1562
+	 *
1563
+	 * @access protected
1564
+	 * @return void
1565
+	 * @throws DomainException
1566
+	 * @throws EE_Error
1567
+	 * @throws InvalidArgumentException
1568
+	 * @throws InvalidDataTypeException
1569
+	 * @throws InvalidInterfaceException
1570
+	 * @throws EntityNotFoundException
1571
+	 */
1572
+	protected function _registration_details()
1573
+	{
1574
+		$this->_template_args = array();
1575
+		$this->_set_registration_object();
1576
+		if (is_object($this->_registration)) {
1577
+			$transaction = $this->_registration->transaction()
1578
+				? $this->_registration->transaction()
1579
+				: EE_Transaction::new_instance();
1580
+			$this->_session = $transaction->session_data();
1581
+			$event_id = $this->_registration->event_ID();
1582
+			$this->_template_args['reg_nmbr']['value'] = $this->_registration->ID();
1583
+			$this->_template_args['reg_nmbr']['label'] = esc_html__('Registration Number', 'event_espresso');
1584
+			$this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1585
+			$this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1586
+			$this->_template_args['grand_total'] = $transaction->total();
1587
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
1588
+			// link back to overview
1589
+			$this->_template_args['reg_overview_url'] = REG_ADMIN_URL;
1590
+			$this->_template_args['registration'] = $this->_registration;
1591
+			$this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1592
+				array(
1593
+					'action'   => 'default',
1594
+					'event_id' => $event_id,
1595
+				),
1596
+				REG_ADMIN_URL
1597
+			);
1598
+			$this->_template_args['filtered_transactions_link'] = EE_Admin_Page::add_query_args_and_nonce(
1599
+				array(
1600
+					'action' => 'default',
1601
+					'EVT_ID' => $event_id,
1602
+					'page'   => 'espresso_transactions',
1603
+				),
1604
+				admin_url('admin.php')
1605
+			);
1606
+			$this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
1607
+				array(
1608
+					'page'   => 'espresso_events',
1609
+					'action' => 'edit',
1610
+					'post'   => $event_id,
1611
+				),
1612
+				admin_url('admin.php')
1613
+			);
1614
+			// next and previous links
1615
+			$next_reg = $this->_registration->next(
1616
+				null,
1617
+				array(),
1618
+				'REG_ID'
1619
+			);
1620
+			$this->_template_args['next_registration'] = $next_reg
1621
+				? $this->_next_link(
1622
+					EE_Admin_Page::add_query_args_and_nonce(
1623
+						array(
1624
+							'action'  => 'view_registration',
1625
+							'_REG_ID' => $next_reg['REG_ID'],
1626
+						),
1627
+						REG_ADMIN_URL
1628
+					),
1629
+					'dashicons dashicons-arrow-right ee-icon-size-22'
1630
+				)
1631
+				: '';
1632
+			$previous_reg = $this->_registration->previous(
1633
+				null,
1634
+				array(),
1635
+				'REG_ID'
1636
+			);
1637
+			$this->_template_args['previous_registration'] = $previous_reg
1638
+				? $this->_previous_link(
1639
+					EE_Admin_Page::add_query_args_and_nonce(
1640
+						array(
1641
+							'action'  => 'view_registration',
1642
+							'_REG_ID' => $previous_reg['REG_ID'],
1643
+						),
1644
+						REG_ADMIN_URL
1645
+					),
1646
+					'dashicons dashicons-arrow-left ee-icon-size-22'
1647
+				)
1648
+				: '';
1649
+			// grab header
1650
+			$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1651
+			$this->_template_args['REG_ID'] = $this->_registration->ID();
1652
+			$this->_template_args['admin_page_header'] = EEH_Template::display_template(
1653
+				$template_path,
1654
+				$this->_template_args,
1655
+				true
1656
+			);
1657
+		} else {
1658
+			$this->_template_args['admin_page_header'] = $this->display_espresso_notices();
1659
+		}
1660
+		// the details template wrapper
1661
+		$this->display_admin_page_with_sidebar();
1662
+	}
1663
+
1664
+
1665
+	protected function _registration_details_metaboxes()
1666
+	{
1667
+		do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1668
+		$this->_set_registration_object();
1669
+		$attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1670
+		add_meta_box(
1671
+			'edit-reg-status-mbox',
1672
+			esc_html__('Registration Status', 'event_espresso'),
1673
+			array($this, 'set_reg_status_buttons_metabox'),
1674
+			$this->wp_page_slug,
1675
+			'normal',
1676
+			'high'
1677
+		);
1678
+		add_meta_box(
1679
+			'edit-reg-details-mbox',
1680
+			esc_html__('Registration Details', 'event_espresso'),
1681
+			array($this, '_reg_details_meta_box'),
1682
+			$this->wp_page_slug,
1683
+			'normal',
1684
+			'high'
1685
+		);
1686
+		if ($attendee instanceof EE_Attendee
1687
+			&& EE_Registry::instance()->CAP->current_user_can(
1688
+				'ee_read_registration',
1689
+				'edit-reg-questions-mbox',
1690
+				$this->_registration->ID()
1691
+			)
1692
+		) {
1693
+			add_meta_box(
1694
+				'edit-reg-questions-mbox',
1695
+				esc_html__('Registration Form Answers', 'event_espresso'),
1696
+				array($this, '_reg_questions_meta_box'),
1697
+				$this->wp_page_slug,
1698
+				'normal',
1699
+				'high'
1700
+			);
1701
+		}
1702
+		add_meta_box(
1703
+			'edit-reg-registrant-mbox',
1704
+			esc_html__('Contact Details', 'event_espresso'),
1705
+			array($this, '_reg_registrant_side_meta_box'),
1706
+			$this->wp_page_slug,
1707
+			'side',
1708
+			'high'
1709
+		);
1710
+		if ($this->_registration->group_size() > 1) {
1711
+			add_meta_box(
1712
+				'edit-reg-attendees-mbox',
1713
+				esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1714
+				array($this, '_reg_attendees_meta_box'),
1715
+				$this->wp_page_slug,
1716
+				'normal',
1717
+				'high'
1718
+			);
1719
+		}
1720
+	}
1721
+
1722
+
1723
+	/**
1724
+	 * set_reg_status_buttons_metabox
1725
+	 *
1726
+	 * @access protected
1727
+	 * @return string
1728
+	 * @throws \EE_Error
1729
+	 */
1730
+	public function set_reg_status_buttons_metabox()
1731
+	{
1732
+		$this->_set_registration_object();
1733
+		$change_reg_status_form = $this->_generate_reg_status_change_form();
1734
+		echo $change_reg_status_form->form_open(
1735
+			self::add_query_args_and_nonce(
1736
+				array(
1737
+					'action' => 'change_reg_status',
1738
+				),
1739
+				REG_ADMIN_URL
1740
+			)
1741
+		);
1742
+		echo $change_reg_status_form->get_html();
1743
+		echo $change_reg_status_form->form_close();
1744
+	}
1745
+
1746
+
1747
+	/**
1748
+	 * @return EE_Form_Section_Proper
1749
+	 * @throws EE_Error
1750
+	 * @throws InvalidArgumentException
1751
+	 * @throws InvalidDataTypeException
1752
+	 * @throws InvalidInterfaceException
1753
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1754
+	 */
1755
+	protected function _generate_reg_status_change_form()
1756
+	{
1757
+		$reg_status_change_form_array = array(
1758
+			'name'            => 'reg_status_change_form',
1759
+			'html_id'         => 'reg-status-change-form',
1760
+			'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1761
+			'subsections'     => array(
1762
+				'return'             => new EE_Hidden_Input(
1763
+					array(
1764
+						'name'    => 'return',
1765
+						'default' => 'view_registration',
1766
+					)
1767
+				),
1768
+				'REG_ID'             => new EE_Hidden_Input(
1769
+					array(
1770
+						'name'    => 'REG_ID',
1771
+						'default' => $this->_registration->ID(),
1772
+					)
1773
+				),
1774
+				'current_status'     => new EE_Form_Section_HTML(
1775
+					EEH_HTML::tr(
1776
+						EEH_HTML::th(
1777
+							EEH_HTML::label(
1778
+								EEH_HTML::strong(
1779
+									esc_html__('Current Registration Status', 'event_espresso')
1780
+								)
1781
+							)
1782
+						)
1783
+						. EEH_HTML::td(
1784
+							EEH_HTML::strong(
1785
+								$this->_registration->pretty_status(),
1786
+								'',
1787
+								'status-' . $this->_registration->status_ID(),
1788
+								'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1789
+							)
1790
+						)
1791
+					)
1792
+				)
1793
+			)
1794
+		);
1795
+		if (EE_Registry::instance()->CAP->current_user_can(
1796
+			'ee_edit_registration',
1797
+			'toggle_registration_status',
1798
+			$this->_registration->ID()
1799
+		)) {
1800
+			$reg_status_change_form_array['subsections']['reg_status'] = new EE_Select_Input(
1801
+				$this->_get_reg_statuses(),
1802
+				array(
1803
+					'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1804
+					'default'         => $this->_registration->status_ID(),
1805
+				)
1806
+			);
1807
+			$reg_status_change_form_array['subsections']['send_notifications'] = new EE_Yes_No_Input(
1808
+				array(
1809
+					'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1810
+					'default'         => false,
1811
+					'html_help_text'  => esc_html__(
1812
+						'If set to "Yes", then the related messages will be sent to the registrant.',
1813
+						'event_espresso'
1814
+					)
1815
+				)
1816
+			);
1817
+			$reg_status_change_form_array['subsections']['submit'] = new EE_Submit_Input(
1818
+				array(
1819
+					'html_class'      => 'button-primary',
1820
+					'html_label_text' => '&nbsp;',
1821
+					'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1822
+				)
1823
+			);
1824
+		}
1825
+		return new EE_Form_Section_Proper($reg_status_change_form_array);
1826
+	}
1827
+
1828
+
1829
+	/**
1830
+	 * Returns an array of all the buttons for the various statuses and switch status actions
1831
+	 *
1832
+	 * @return array
1833
+	 * @throws EE_Error
1834
+	 * @throws InvalidArgumentException
1835
+	 * @throws InvalidDataTypeException
1836
+	 * @throws InvalidInterfaceException
1837
+	 * @throws EntityNotFoundException
1838
+	 */
1839
+	protected function _get_reg_statuses()
1840
+	{
1841
+		$reg_status_array = EEM_Registration::instance()->reg_status_array();
1842
+		unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1843
+		// get current reg status
1844
+		$current_status = $this->_registration->status_ID();
1845
+		// is registration for free event? This will determine whether to display the pending payment option
1846
+		if ($current_status !== EEM_Registration::status_id_pending_payment
1847
+			&& EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1848
+		) {
1849
+			unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1850
+		}
1851
+		return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1852
+	}
1853
+
1854
+
1855
+	/**
1856
+	 * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1857
+	 *
1858
+	 * @param bool $status REG status given for changing registrations to.
1859
+	 * @param bool $notify Whether to send messages notifications or not.
1860
+	 * @return array (array with reg_id(s) updated and whether update was successful.
1861
+	 * @throws EE_Error
1862
+	 * @throws InvalidArgumentException
1863
+	 * @throws InvalidDataTypeException
1864
+	 * @throws InvalidInterfaceException
1865
+	 * @throws ReflectionException
1866
+	 * @throws RuntimeException
1867
+	 * @throws EntityNotFoundException
1868
+	 */
1869
+	protected function _set_registration_status_from_request($status = false, $notify = false)
1870
+	{
1871
+		if (isset($this->_req_data['reg_status_change_form'])) {
1872
+			$REG_IDs = isset($this->_req_data['reg_status_change_form']['REG_ID'])
1873
+				? (array) $this->_req_data['reg_status_change_form']['REG_ID']
1874
+				: array();
1875
+		} else {
1876
+			$REG_IDs = isset($this->_req_data['_REG_ID'])
1877
+				? (array) $this->_req_data['_REG_ID']
1878
+				: array();
1879
+		}
1880
+		// sanitize $REG_IDs
1881
+		$REG_IDs = array_map('absint', $REG_IDs);
1882
+		// and remove empty entries
1883
+		$REG_IDs = array_filter($REG_IDs);
1884
+
1885
+		$result = $this->_set_registration_status($REG_IDs, $status, $notify);
1886
+
1887
+		/**
1888
+		 * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1889
+		 * Currently this value is used downstream by the _process_resend_registration method.
1890
+		 *
1891
+		 * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1892
+		 * @param bool                     $status           The status registrations were changed to.
1893
+		 * @param bool                     $success          If the status was changed successfully for all registrations.
1894
+		 * @param Registrations_Admin_Page $admin_page_object
1895
+		 */
1896
+		$this->_req_data['_REG_ID'] = apply_filters(
1897
+			'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1898
+			$result['REG_ID'],
1899
+			$status,
1900
+			$result['success'],
1901
+			$this
1902
+		);
1903
+
1904
+		// notify?
1905
+		if ($notify
1906
+			&& $result['success']
1907
+			&& ! empty($this->_req_data['_REG_ID'])
1908
+			&& EE_Registry::instance()->CAP->current_user_can(
1909
+				'ee_send_message',
1910
+				'espresso_registrations_resend_registration'
1911
+			)
1912
+		) {
1913
+			$this->_process_resend_registration();
1914
+		}
1915
+		return $result;
1916
+	}
1917
+
1918
+
1919
+	/**
1920
+	 * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1921
+	 * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1922
+	 *
1923
+	 * @param array  $REG_IDs
1924
+	 * @param string $status
1925
+	 * @param bool   $notify  Used to indicate whether notification was requested or not.  This determines the context
1926
+	 *                        slug sent with setting the registration status.
1927
+	 * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1928
+	 * @throws EE_Error
1929
+	 * @throws InvalidArgumentException
1930
+	 * @throws InvalidDataTypeException
1931
+	 * @throws InvalidInterfaceException
1932
+	 * @throws ReflectionException
1933
+	 * @throws RuntimeException
1934
+	 * @throws EntityNotFoundException
1935
+	 */
1936
+	protected function _set_registration_status($REG_IDs = array(), $status = '', $notify = false)
1937
+	{
1938
+		$success = false;
1939
+		// typecast $REG_IDs
1940
+		$REG_IDs = (array) $REG_IDs;
1941
+		if (! empty($REG_IDs)) {
1942
+			$success = true;
1943
+			// set default status if none is passed
1944
+			$status = $status ? $status : EEM_Registration::status_id_pending_payment;
1945
+			$status_context = $notify
1946
+				? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1947
+				: Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1948
+			// loop through REG_ID's and change status
1949
+			foreach ($REG_IDs as $REG_ID) {
1950
+				$registration = EEM_Registration::instance()->get_one_by_ID($REG_ID);
1951
+				if ($registration instanceof EE_Registration) {
1952
+					$registration->set_status(
1953
+						$status,
1954
+						false,
1955
+						new Context(
1956
+							$status_context,
1957
+							esc_html__(
1958
+								'Manually triggered status change on a Registration Admin Page route.',
1959
+								'event_espresso'
1960
+							)
1961
+						)
1962
+					);
1963
+					$result = $registration->save();
1964
+					// verifying explicit fails because update *may* just return 0 for 0 rows affected
1965
+					$success = $result !== false ? $success : false;
1966
+				}
1967
+			}
1968
+		}
1969
+
1970
+		// return $success and processed registrations
1971
+		return array('REG_ID' => $REG_IDs, 'success' => $success);
1972
+	}
1973
+
1974
+
1975
+	/**
1976
+	 * Common logic for setting up success message and redirecting to appropriate route
1977
+	 *
1978
+	 * @param  string $STS_ID status id for the registration changed to
1979
+	 * @param   bool  $notify indicates whether the _set_registration_status_from_request does notifications or not.
1980
+	 * @return void
1981
+	 * @throws EE_Error
1982
+	 */
1983
+	protected function _reg_status_change_return($STS_ID, $notify = false)
1984
+	{
1985
+		$result = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1986
+			: array('success' => false);
1987
+		$success = isset($result['success']) && $result['success'];
1988
+		// setup success message
1989
+		if ($success) {
1990
+			if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1991
+				$msg = sprintf(
1992
+					esc_html__('Registration status has been set to %s', 'event_espresso'),
1993
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1994
+				);
1995
+			} else {
1996
+				$msg = sprintf(
1997
+					esc_html__('Registrations have been set to %s.', 'event_espresso'),
1998
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1999
+				);
2000
+			}
2001
+			EE_Error::add_success($msg);
2002
+		} else {
2003
+			EE_Error::add_error(
2004
+				esc_html__(
2005
+					'Something went wrong, and the status was not changed',
2006
+					'event_espresso'
2007
+				),
2008
+				__FILE__,
2009
+				__LINE__,
2010
+				__FUNCTION__
2011
+			);
2012
+		}
2013
+		if (isset($this->_req_data['return']) && $this->_req_data['return'] == 'view_registration') {
2014
+			$route = array('action' => 'view_registration', '_REG_ID' => reset($result['REG_ID']));
2015
+		} else {
2016
+			$route = array('action' => 'default');
2017
+		}
2018
+		$route = $this->mergeExistingRequestParamsWithRedirectArgs($route);
2019
+		$this->_redirect_after_action($success, '', '', $route, true);
2020
+	}
2021
+
2022
+
2023
+	/**
2024
+	 * incoming reg status change from reg details page.
2025
+	 *
2026
+	 * @return void
2027
+	 */
2028
+	protected function _change_reg_status()
2029
+	{
2030
+		$this->_req_data['return'] = 'view_registration';
2031
+		// set notify based on whether the send notifications toggle is set or not
2032
+		$notify = ! empty($this->_req_data['reg_status_change_form']['send_notifications']);
2033
+		// $notify = ! empty( $this->_req_data['txn_reg_status_change']['send_notifications'] );
2034
+		$this->_req_data['reg_status_change_form']['reg_status'] = isset($this->_req_data['reg_status_change_form']['reg_status'])
2035
+			? $this->_req_data['reg_status_change_form']['reg_status'] : '';
2036
+		switch ($this->_req_data['reg_status_change_form']['reg_status']) {
2037
+			case EEM_Registration::status_id_approved:
2038
+			case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'):
2039
+				$this->approve_registration($notify);
2040
+				break;
2041
+			case EEM_Registration::status_id_pending_payment:
2042
+			case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'):
2043
+				$this->pending_registration($notify);
2044
+				break;
2045
+			case EEM_Registration::status_id_not_approved:
2046
+			case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'):
2047
+				$this->not_approve_registration($notify);
2048
+				break;
2049
+			case EEM_Registration::status_id_declined:
2050
+			case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'):
2051
+				$this->decline_registration($notify);
2052
+				break;
2053
+			case EEM_Registration::status_id_cancelled:
2054
+			case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'):
2055
+				$this->cancel_registration($notify);
2056
+				break;
2057
+			case EEM_Registration::status_id_wait_list:
2058
+			case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'):
2059
+				$this->wait_list_registration($notify);
2060
+				break;
2061
+			case EEM_Registration::status_id_incomplete:
2062
+			default:
2063
+				$result['success'] = false;
2064
+				unset($this->_req_data['return']);
2065
+				$this->_reg_status_change_return('', false);
2066
+				break;
2067
+		}
2068
+	}
2069
+
2070
+
2071
+	/**
2072
+	 * Callback for bulk action routes.
2073
+	 * Note: although we could just register the singular route callbacks for each bulk action route as well, this
2074
+	 * method was chosen so there is one central place all the registration status bulk actions are going through.
2075
+	 * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
2076
+	 * when an action is happening on just a single registration).
2077
+	 *
2078
+	 * @param      $action
2079
+	 * @param bool $notify
2080
+	 */
2081
+	protected function bulk_action_on_registrations($action, $notify = false)
2082
+	{
2083
+		do_action(
2084
+			'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
2085
+			$this,
2086
+			$action,
2087
+			$notify
2088
+		);
2089
+		$method = $action . '_registration';
2090
+		if (method_exists($this, $method)) {
2091
+			$this->$method($notify);
2092
+		}
2093
+	}
2094
+
2095
+
2096
+	/**
2097
+	 * approve_registration
2098
+	 *
2099
+	 * @access protected
2100
+	 * @param bool $notify whether or not to notify the registrant about their approval.
2101
+	 * @return void
2102
+	 */
2103
+	protected function approve_registration($notify = false)
2104
+	{
2105
+		$this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
2106
+	}
2107
+
2108
+
2109
+	/**
2110
+	 *        decline_registration
2111
+	 *
2112
+	 * @access protected
2113
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2114
+	 * @return void
2115
+	 */
2116
+	protected function decline_registration($notify = false)
2117
+	{
2118
+		$this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
2119
+	}
2120
+
2121
+
2122
+	/**
2123
+	 *        cancel_registration
2124
+	 *
2125
+	 * @access protected
2126
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2127
+	 * @return void
2128
+	 */
2129
+	protected function cancel_registration($notify = false)
2130
+	{
2131
+		$this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
2132
+	}
2133
+
2134
+
2135
+	/**
2136
+	 *        not_approve_registration
2137
+	 *
2138
+	 * @access protected
2139
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2140
+	 * @return void
2141
+	 */
2142
+	protected function not_approve_registration($notify = false)
2143
+	{
2144
+		$this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
2145
+	}
2146
+
2147
+
2148
+	/**
2149
+	 *        decline_registration
2150
+	 *
2151
+	 * @access protected
2152
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2153
+	 * @return void
2154
+	 */
2155
+	protected function pending_registration($notify = false)
2156
+	{
2157
+		$this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
2158
+	}
2159
+
2160
+
2161
+	/**
2162
+	 * waitlist_registration
2163
+	 *
2164
+	 * @access protected
2165
+	 * @param bool $notify whether or not to notify the registrant about their status change.
2166
+	 * @return void
2167
+	 */
2168
+	protected function wait_list_registration($notify = false)
2169
+	{
2170
+		$this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
2171
+	}
2172
+
2173
+
2174
+	/**
2175
+	 *        generates HTML for the Registration main meta box
2176
+	 *
2177
+	 * @access public
2178
+	 * @return void
2179
+	 * @throws DomainException
2180
+	 * @throws EE_Error
2181
+	 * @throws InvalidArgumentException
2182
+	 * @throws InvalidDataTypeException
2183
+	 * @throws InvalidInterfaceException
2184
+	 * @throws ReflectionException
2185
+	 * @throws EntityNotFoundException
2186
+	 */
2187
+	public function _reg_details_meta_box()
2188
+	{
2189
+		EEH_Autoloader::register_line_item_display_autoloaders();
2190
+		EEH_Autoloader::register_line_item_filter_autoloaders();
2191
+		EE_Registry::instance()->load_helper('Line_Item');
2192
+		$transaction = $this->_registration->transaction() ? $this->_registration->transaction()
2193
+			: EE_Transaction::new_instance();
2194
+		$this->_session = $transaction->session_data();
2195
+		$filters = new EE_Line_Item_Filter_Collection();
2196
+		// $filters->add( new EE_Non_Zero_Line_Item_Filter() );
2197
+		$filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
2198
+		$line_item_filter_processor = new EE_Line_Item_Filter_Processor(
2199
+			$filters,
2200
+			$transaction->total_line_item()
2201
+		);
2202
+		$filtered_line_item_tree = $line_item_filter_processor->process();
2203
+		$line_item_display = new EE_Line_Item_Display(
2204
+			'reg_admin_table',
2205
+			'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2206
+		);
2207
+		$this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2208
+			$filtered_line_item_tree,
2209
+			array('EE_Registration' => $this->_registration)
2210
+		);
2211
+		$attendee = $this->_registration->attendee();
2212
+		if (EE_Registry::instance()->CAP->current_user_can(
2213
+			'ee_read_transaction',
2214
+			'espresso_transactions_view_transaction'
2215
+		)) {
2216
+			$this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2217
+				EE_Admin_Page::add_query_args_and_nonce(
2218
+					array(
2219
+						'action' => 'view_transaction',
2220
+						'TXN_ID' => $transaction->ID(),
2221
+					),
2222
+					TXN_ADMIN_URL
2223
+				),
2224
+				esc_html__(' View Transaction', 'event_espresso'),
2225
+				'button secondary-button right',
2226
+				'dashicons dashicons-cart'
2227
+			);
2228
+		} else {
2229
+			$this->_template_args['view_transaction_button'] = '';
2230
+		}
2231
+		if ($attendee instanceof EE_Attendee
2232
+			&& EE_Registry::instance()->CAP->current_user_can(
2233
+				'ee_send_message',
2234
+				'espresso_registrations_resend_registration'
2235
+			)
2236
+		) {
2237
+			$this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2238
+				EE_Admin_Page::add_query_args_and_nonce(
2239
+					array(
2240
+						'action'      => 'resend_registration',
2241
+						'_REG_ID'     => $this->_registration->ID(),
2242
+						'redirect_to' => 'view_registration',
2243
+					),
2244
+					REG_ADMIN_URL
2245
+				),
2246
+				esc_html__(' Resend Registration', 'event_espresso'),
2247
+				'button secondary-button right',
2248
+				'dashicons dashicons-email-alt'
2249
+			);
2250
+		} else {
2251
+			$this->_template_args['resend_registration_button'] = '';
2252
+		}
2253
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2254
+		$payment = $transaction->get_first_related('Payment');
2255
+		$payment = ! $payment instanceof EE_Payment
2256
+			? EE_Payment::new_instance()
2257
+			: $payment;
2258
+		$payment_method = $payment->get_first_related('Payment_Method');
2259
+		$payment_method = ! $payment_method instanceof EE_Payment_Method
2260
+			? EE_Payment_Method::new_instance()
2261
+			: $payment_method;
2262
+		$reg_details = array(
2263
+			'payment_method'       => $payment_method->name(),
2264
+			'response_msg'         => $payment->gateway_response(),
2265
+			'registration_id'      => $this->_registration->get('REG_code'),
2266
+			'registration_session' => $this->_registration->session_ID(),
2267
+			'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2268
+			'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2269
+		);
2270
+		if (isset($reg_details['registration_id'])) {
2271
+			$this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2272
+			$this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2273
+				'Registration ID',
2274
+				'event_espresso'
2275
+			);
2276
+			$this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2277
+		}
2278
+		if (isset($reg_details['payment_method'])) {
2279
+			$this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2280
+			$this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2281
+				'Most Recent Payment Method',
2282
+				'event_espresso'
2283
+			);
2284
+			$this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2285
+			$this->_template_args['reg_details']['response_msg']['value'] = $reg_details['response_msg'];
2286
+			$this->_template_args['reg_details']['response_msg']['label'] = esc_html__(
2287
+				'Payment method response',
2288
+				'event_espresso'
2289
+			);
2290
+			$this->_template_args['reg_details']['response_msg']['class'] = 'regular-text';
2291
+		}
2292
+		$this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2293
+		$this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2294
+			'Registration Session',
2295
+			'event_espresso'
2296
+		);
2297
+		$this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2298
+		$this->_template_args['reg_details']['ip_address']['value'] = $reg_details['ip_address'];
2299
+		$this->_template_args['reg_details']['ip_address']['label'] = esc_html__(
2300
+			'Registration placed from IP',
2301
+			'event_espresso'
2302
+		);
2303
+		$this->_template_args['reg_details']['ip_address']['class'] = 'regular-text';
2304
+		$this->_template_args['reg_details']['user_agent']['value'] = $reg_details['user_agent'];
2305
+		$this->_template_args['reg_details']['user_agent']['label'] = esc_html__(
2306
+			'Registrant User Agent',
2307
+			'event_espresso'
2308
+		);
2309
+		$this->_template_args['reg_details']['user_agent']['class'] = 'large-text';
2310
+		$this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
2311
+			array(
2312
+				'action'   => 'default',
2313
+				'event_id' => $this->_registration->event_ID(),
2314
+			),
2315
+			REG_ADMIN_URL
2316
+		);
2317
+		$this->_template_args['REG_ID'] = $this->_registration->ID();
2318
+		$this->_template_args['event_id'] = $this->_registration->event_ID();
2319
+		$template_path =
2320
+			REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2321
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2322
+	}
2323
+
2324
+
2325
+	/**
2326
+	 * generates HTML for the Registration Questions meta box.
2327
+	 * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2328
+	 * otherwise uses new forms system
2329
+	 *
2330
+	 * @access public
2331
+	 * @return void
2332
+	 * @throws DomainException
2333
+	 * @throws EE_Error
2334
+	 */
2335
+	public function _reg_questions_meta_box()
2336
+	{
2337
+		// allow someone to override this method entirely
2338
+		if (apply_filters(
2339
+			'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2340
+			true,
2341
+			$this,
2342
+			$this->_registration
2343
+		)) {
2344
+			$form = $this->_get_reg_custom_questions_form(
2345
+				$this->_registration->ID()
2346
+			);
2347
+			$this->_template_args['att_questions'] = count($form->subforms()) > 0
2348
+				? $form->get_html_and_js()
2349
+				: '';
2350
+			$this->_template_args['reg_questions_form_action'] = 'edit_registration';
2351
+			$this->_template_args['REG_ID'] = $this->_registration->ID();
2352
+			$template_path =
2353
+				REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2354
+			echo EEH_Template::display_template($template_path, $this->_template_args, true);
2355
+		}
2356
+	}
2357
+
2358
+
2359
+	/**
2360
+	 * form_before_question_group
2361
+	 *
2362
+	 * @deprecated    as of 4.8.32.rc.000
2363
+	 * @access        public
2364
+	 * @param        string $output
2365
+	 * @return        string
2366
+	 */
2367
+	public function form_before_question_group($output)
2368
+	{
2369
+		EE_Error::doing_it_wrong(
2370
+			__CLASS__ . '::' . __FUNCTION__,
2371
+			esc_html__(
2372
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2373
+				'event_espresso'
2374
+			),
2375
+			'4.8.32.rc.000'
2376
+		);
2377
+		return '
2378 2378
 	<table class="form-table ee-width-100">
2379 2379
 		<tbody>
2380 2380
 			';
2381
-    }
2382
-
2383
-
2384
-    /**
2385
-     * form_after_question_group
2386
-     *
2387
-     * @deprecated    as of 4.8.32.rc.000
2388
-     * @access        public
2389
-     * @param        string $output
2390
-     * @return        string
2391
-     */
2392
-    public function form_after_question_group($output)
2393
-    {
2394
-        EE_Error::doing_it_wrong(
2395
-            __CLASS__ . '::' . __FUNCTION__,
2396
-            esc_html__(
2397
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2398
-                'event_espresso'
2399
-            ),
2400
-            '4.8.32.rc.000'
2401
-        );
2402
-        return '
2381
+	}
2382
+
2383
+
2384
+	/**
2385
+	 * form_after_question_group
2386
+	 *
2387
+	 * @deprecated    as of 4.8.32.rc.000
2388
+	 * @access        public
2389
+	 * @param        string $output
2390
+	 * @return        string
2391
+	 */
2392
+	public function form_after_question_group($output)
2393
+	{
2394
+		EE_Error::doing_it_wrong(
2395
+			__CLASS__ . '::' . __FUNCTION__,
2396
+			esc_html__(
2397
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2398
+				'event_espresso'
2399
+			),
2400
+			'4.8.32.rc.000'
2401
+		);
2402
+		return '
2403 2403
 			<tr class="hide-if-no-js">
2404 2404
 				<th> </th>
2405 2405
 				<td class="reg-admin-edit-attendee-question-td">
2406 2406
 					<a class="reg-admin-edit-attendee-question-lnk" href="#" title="'
2407
-               . esc_attr__('click to edit question', 'event_espresso')
2408
-               . '">
2407
+			   . esc_attr__('click to edit question', 'event_espresso')
2408
+			   . '">
2409 2409
 						<span class="reg-admin-edit-question-group-spn lt-grey-txt">'
2410
-               . esc_html__('edit the above question group', 'event_espresso')
2411
-               . '</span>
2410
+			   . esc_html__('edit the above question group', 'event_espresso')
2411
+			   . '</span>
2412 2412
 						<div class="dashicons dashicons-edit"></div>
2413 2413
 					</a>
2414 2414
 				</td>
@@ -2416,608 +2416,608 @@  discard block
 block discarded – undo
2416 2416
 		</tbody>
2417 2417
 	</table>
2418 2418
 ';
2419
-    }
2420
-
2421
-
2422
-    /**
2423
-     * form_form_field_label_wrap
2424
-     *
2425
-     * @deprecated    as of 4.8.32.rc.000
2426
-     * @access        public
2427
-     * @param        string $label
2428
-     * @return        string
2429
-     */
2430
-    public function form_form_field_label_wrap($label)
2431
-    {
2432
-        EE_Error::doing_it_wrong(
2433
-            __CLASS__ . '::' . __FUNCTION__,
2434
-            esc_html__(
2435
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2436
-                'event_espresso'
2437
-            ),
2438
-            '4.8.32.rc.000'
2439
-        );
2440
-        return '
2419
+	}
2420
+
2421
+
2422
+	/**
2423
+	 * form_form_field_label_wrap
2424
+	 *
2425
+	 * @deprecated    as of 4.8.32.rc.000
2426
+	 * @access        public
2427
+	 * @param        string $label
2428
+	 * @return        string
2429
+	 */
2430
+	public function form_form_field_label_wrap($label)
2431
+	{
2432
+		EE_Error::doing_it_wrong(
2433
+			__CLASS__ . '::' . __FUNCTION__,
2434
+			esc_html__(
2435
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2436
+				'event_espresso'
2437
+			),
2438
+			'4.8.32.rc.000'
2439
+		);
2440
+		return '
2441 2441
 			<tr>
2442 2442
 				<th>
2443 2443
 					' . $label . '
2444 2444
 				</th>';
2445
-    }
2446
-
2447
-
2448
-    /**
2449
-     * form_form_field_input__wrap
2450
-     *
2451
-     * @deprecated    as of 4.8.32.rc.000
2452
-     * @access        public
2453
-     * @param        string $input
2454
-     * @return        string
2455
-     */
2456
-    public function form_form_field_input__wrap($input)
2457
-    {
2458
-        EE_Error::doing_it_wrong(
2459
-            __CLASS__ . '::' . __FUNCTION__,
2460
-            esc_html__(
2461
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2462
-                'event_espresso'
2463
-            ),
2464
-            '4.8.32.rc.000'
2465
-        );
2466
-        return '
2445
+	}
2446
+
2447
+
2448
+	/**
2449
+	 * form_form_field_input__wrap
2450
+	 *
2451
+	 * @deprecated    as of 4.8.32.rc.000
2452
+	 * @access        public
2453
+	 * @param        string $input
2454
+	 * @return        string
2455
+	 */
2456
+	public function form_form_field_input__wrap($input)
2457
+	{
2458
+		EE_Error::doing_it_wrong(
2459
+			__CLASS__ . '::' . __FUNCTION__,
2460
+			esc_html__(
2461
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2462
+				'event_espresso'
2463
+			),
2464
+			'4.8.32.rc.000'
2465
+		);
2466
+		return '
2467 2467
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2468 2468
 					' . $input . '
2469 2469
 				</td>
2470 2470
 			</tr>';
2471
-    }
2472
-
2473
-
2474
-    /**
2475
-     * Updates the registration's custom questions according to the form info, if the form is submitted.
2476
-     * If it's not a post, the "view_registrations" route will be called next on the SAME request
2477
-     * to display the page
2478
-     *
2479
-     * @access protected
2480
-     * @return void
2481
-     * @throws EE_Error
2482
-     */
2483
-    protected function _update_attendee_registration_form()
2484
-    {
2485
-        do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2486
-        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2487
-            $REG_ID = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2488
-            $success = $this->_save_reg_custom_questions_form($REG_ID);
2489
-            if ($success) {
2490
-                $what = esc_html__('Registration Form', 'event_espresso');
2491
-                $route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2492
-                    : array('action' => 'default');
2493
-                $this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2494
-            }
2495
-        }
2496
-    }
2497
-
2498
-
2499
-    /**
2500
-     * Gets the form for saving registrations custom questions (if done
2501
-     * previously retrieves the cached form object, which may have validation errors in it)
2502
-     *
2503
-     * @param int $REG_ID
2504
-     * @return EE_Registration_Custom_Questions_Form
2505
-     * @throws EE_Error
2506
-     * @throws InvalidArgumentException
2507
-     * @throws InvalidDataTypeException
2508
-     * @throws InvalidInterfaceException
2509
-     */
2510
-    protected function _get_reg_custom_questions_form($REG_ID)
2511
-    {
2512
-        if (! $this->_reg_custom_questions_form) {
2513
-            require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2514
-            $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2515
-                EEM_Registration::instance()->get_one_by_ID($REG_ID)
2516
-            );
2517
-            $this->_reg_custom_questions_form->_construct_finalize(null, null);
2518
-        }
2519
-        return $this->_reg_custom_questions_form;
2520
-    }
2521
-
2522
-
2523
-    /**
2524
-     * Saves
2525
-     *
2526
-     * @access private
2527
-     * @param bool $REG_ID
2528
-     * @return bool
2529
-     * @throws EE_Error
2530
-     * @throws InvalidArgumentException
2531
-     * @throws InvalidDataTypeException
2532
-     * @throws InvalidInterfaceException
2533
-     */
2534
-    private function _save_reg_custom_questions_form($REG_ID = false)
2535
-    {
2536
-        if (! $REG_ID) {
2537
-            EE_Error::add_error(
2538
-                esc_html__(
2539
-                    'An error occurred. No registration ID was received.',
2540
-                    'event_espresso'
2541
-                ),
2542
-                __FILE__,
2543
-                __FUNCTION__,
2544
-                __LINE__
2545
-            );
2546
-        }
2547
-        $form = $this->_get_reg_custom_questions_form($REG_ID);
2548
-        $form->receive_form_submission($this->_req_data);
2549
-        $success = false;
2550
-        if ($form->is_valid()) {
2551
-            foreach ($form->subforms() as $question_group_id => $question_group_form) {
2552
-                foreach ($question_group_form->inputs() as $question_id => $input) {
2553
-                    $where_conditions = array(
2554
-                        'QST_ID' => $question_id,
2555
-                        'REG_ID' => $REG_ID,
2556
-                    );
2557
-                    $possibly_new_values = array(
2558
-                        'ANS_value' => $input->normalized_value(),
2559
-                    );
2560
-                    $answer = EEM_Answer::instance()->get_one(array($where_conditions));
2561
-                    if ($answer instanceof EE_Answer) {
2562
-                        $success = $answer->save($possibly_new_values);
2563
-                    } else {
2564
-                        // insert it then
2565
-                        $cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2566
-                        $answer = EE_Answer::new_instance($cols_n_vals);
2567
-                        $success = $answer->save();
2568
-                    }
2569
-                }
2570
-            }
2571
-        } else {
2572
-            EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2573
-        }
2574
-        return $success;
2575
-    }
2576
-
2577
-
2578
-    /**
2579
-     *        generates HTML for the Registration main meta box
2580
-     *
2581
-     * @access public
2582
-     * @return void
2583
-     * @throws DomainException
2584
-     * @throws EE_Error
2585
-     * @throws InvalidArgumentException
2586
-     * @throws InvalidDataTypeException
2587
-     * @throws InvalidInterfaceException
2588
-     */
2589
-    public function _reg_attendees_meta_box()
2590
-    {
2591
-        $REG = EEM_Registration::instance();
2592
-        // get all other registrations on this transaction, and cache
2593
-        // the attendees for them so we don't have to run another query using force_join
2594
-        $registrations = $REG->get_all(
2595
-            array(
2596
-                array(
2597
-                    'TXN_ID' => $this->_registration->transaction_ID(),
2598
-                    'REG_ID' => array('!=', $this->_registration->ID()),
2599
-                ),
2600
-                'force_join' => array('Attendee'),
2601
-            )
2602
-        );
2603
-        $this->_template_args['attendees'] = array();
2604
-        $this->_template_args['attendee_notice'] = '';
2605
-        if (empty($registrations)
2606
-            || (is_array($registrations)
2607
-                && ! EEH_Array::get_one_item_from_array($registrations))
2608
-        ) {
2609
-            EE_Error::add_error(
2610
-                esc_html__(
2611
-                    'There are no records attached to this registration. Something may have gone wrong with the registration',
2612
-                    'event_espresso'
2613
-                ),
2614
-                __FILE__,
2615
-                __FUNCTION__,
2616
-                __LINE__
2617
-            );
2618
-            $this->_template_args['attendee_notice'] = EE_Error::get_notices();
2619
-        } else {
2620
-            $att_nmbr = 1;
2621
-            foreach ($registrations as $registration) {
2622
-                /* @var $registration EE_Registration */
2623
-                $attendee = $registration->attendee()
2624
-                    ? $registration->attendee()
2625
-                    : EEM_Attendee::instance()
2626
-                                  ->create_default_object();
2627
-                $this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2628
-                $this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2629
-                $this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2630
-                $this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2631
-                $this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2632
-                $this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2633
-                    ', ',
2634
-                    $attendee->full_address_as_array()
2635
-                );
2636
-                $this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2637
-                    array(
2638
-                        'action' => 'edit_attendee',
2639
-                        'post'   => $attendee->ID(),
2640
-                    ),
2641
-                    REG_ADMIN_URL
2642
-                );
2643
-                $this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj() instanceof EE_Event
2644
-                    ? $registration->event_obj()->name()
2645
-                    : '';
2646
-                $att_nmbr++;
2647
-            }
2648
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2649
-        }
2650
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2651
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2652
-    }
2653
-
2654
-
2655
-    /**
2656
-     *        generates HTML for the Edit Registration side meta box
2657
-     *
2658
-     * @access public
2659
-     * @return void
2660
-     * @throws DomainException
2661
-     * @throws EE_Error
2662
-     * @throws InvalidArgumentException
2663
-     * @throws InvalidDataTypeException
2664
-     * @throws InvalidInterfaceException
2665
-     */
2666
-    public function _reg_registrant_side_meta_box()
2667
-    {
2668
-        /*@var $attendee EE_Attendee */
2669
-        $att_check = $this->_registration->attendee();
2670
-        $attendee = $att_check instanceof EE_Attendee ? $att_check : EEM_Attendee::instance()->create_default_object();
2671
-        // now let's determine if this is not the primary registration.  If it isn't then we set the
2672
-        // primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2673
-        // primary registration object (that way we know if we need to show create button or not)
2674
-        if (! $this->_registration->is_primary_registrant()) {
2675
-            $primary_registration = $this->_registration->get_primary_registration();
2676
-            $primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2677
-                : null;
2678
-            if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2679
-                // in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2680
-                // custom attendee object so let's not worry about the primary reg.
2681
-                $primary_registration = null;
2682
-            }
2683
-        } else {
2684
-            $primary_registration = null;
2685
-        }
2686
-        $this->_template_args['ATT_ID'] = $attendee->ID();
2687
-        $this->_template_args['fname'] = $attendee->fname();
2688
-        $this->_template_args['lname'] = $attendee->lname();
2689
-        $this->_template_args['email'] = $attendee->email();
2690
-        $this->_template_args['phone'] = $attendee->phone();
2691
-        $this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2692
-        // edit link
2693
-        $this->_template_args['att_edit_link'] = EE_Admin_Page::add_query_args_and_nonce(
2694
-            array(
2695
-                'action' => 'edit_attendee',
2696
-                'post'   => $attendee->ID(),
2697
-            ),
2698
-            REG_ADMIN_URL
2699
-        );
2700
-        $this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2701
-        // create link
2702
-        $this->_template_args['create_link'] = $primary_registration instanceof EE_Registration
2703
-            ? EE_Admin_Page::add_query_args_and_nonce(
2704
-                array(
2705
-                    'action'  => 'duplicate_attendee',
2706
-                    '_REG_ID' => $this->_registration->ID(),
2707
-                ),
2708
-                REG_ADMIN_URL
2709
-            ) : '';
2710
-        $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2711
-        $this->_template_args['att_check'] = $att_check;
2712
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2713
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2714
-    }
2715
-
2716
-
2717
-    /**
2718
-     * trash or restore registrations
2719
-     *
2720
-     * @param  boolean $trash whether to archive or restore
2721
-     * @return void
2722
-     * @throws EE_Error
2723
-     * @throws InvalidArgumentException
2724
-     * @throws InvalidDataTypeException
2725
-     * @throws InvalidInterfaceException
2726
-     * @throws RuntimeException
2727
-     * @access protected
2728
-     */
2729
-    protected function _trash_or_restore_registrations($trash = true)
2730
-    {
2731
-        // if empty _REG_ID then get out because there's nothing to do
2732
-        if (empty($this->_req_data['_REG_ID'])) {
2733
-            EE_Error::add_error(
2734
-                sprintf(
2735
-                    esc_html__(
2736
-                        'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2737
-                        'event_espresso'
2738
-                    ),
2739
-                    $trash ? 'trash' : 'restore'
2740
-                ),
2741
-                __FILE__,
2742
-                __LINE__,
2743
-                __FUNCTION__
2744
-            );
2745
-            $this->_redirect_after_action(false, '', '', array(), true);
2746
-        }
2747
-        $success = 0;
2748
-        $overwrite_msgs = false;
2749
-        // Checkboxes
2750
-        if (! is_array($this->_req_data['_REG_ID'])) {
2751
-            $this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2752
-        }
2753
-        $reg_count = count($this->_req_data['_REG_ID']);
2754
-        // cycle thru checkboxes
2755
-        foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2756
-            /** @var EE_Registration $REG */
2757
-            $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2758
-            $payments = $REG->registration_payments();
2759
-            if (! empty($payments)) {
2760
-                $name = $REG->attendee() instanceof EE_Attendee
2761
-                    ? $REG->attendee()->full_name()
2762
-                    : esc_html__('Unknown Attendee', 'event_espresso');
2763
-                $overwrite_msgs = true;
2764
-                EE_Error::add_error(
2765
-                    sprintf(
2766
-                        esc_html__(
2767
-                            'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2768
-                            'event_espresso'
2769
-                        ),
2770
-                        $name
2771
-                    ),
2772
-                    __FILE__,
2773
-                    __FUNCTION__,
2774
-                    __LINE__
2775
-                );
2776
-                // can't trash this registration because it has payments.
2777
-                continue;
2778
-            }
2779
-            $updated = $trash ? $REG->delete() : $REG->restore();
2780
-            if ($updated) {
2781
-                $success++;
2782
-            }
2783
-        }
2784
-        $this->_redirect_after_action(
2785
-            $success === $reg_count, // were ALL registrations affected?
2786
-            $success > 1
2787
-                ? esc_html__('Registrations', 'event_espresso')
2788
-                : esc_html__('Registration', 'event_espresso'),
2789
-            $trash
2790
-                ? esc_html__('moved to the trash', 'event_espresso')
2791
-                : esc_html__('restored', 'event_espresso'),
2792
-            $this->mergeExistingRequestParamsWithRedirectArgs(array('action' => 'default')),
2793
-            $overwrite_msgs
2794
-        );
2795
-    }
2796
-
2797
-
2798
-    /**
2799
-     * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2800
-     * registration but also.
2801
-     * 1. Removing relations to EE_Attendee
2802
-     * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2803
-     * ALSO trashed.
2804
-     * 3. Deleting permanently any related Line items but only if the above conditions are met.
2805
-     * 4. Removing relationships between all tickets and the related registrations
2806
-     * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2807
-     * 6. Deleting permanently any related Checkins.
2808
-     *
2809
-     * @return void
2810
-     * @throws EE_Error
2811
-     * @throws InvalidArgumentException
2812
-     * @throws InvalidDataTypeException
2813
-     * @throws InvalidInterfaceException
2814
-     */
2815
-    protected function _delete_registrations()
2816
-    {
2817
-        $REG_MDL = EEM_Registration::instance();
2818
-        $success = 1;
2819
-        // Checkboxes
2820
-        if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2821
-            // if array has more than one element than success message should be plural
2822
-            $success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2823
-            // cycle thru checkboxes
2824
-            while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2825
-                $REG = $REG_MDL->get_one_by_ID($REG_ID);
2826
-                if (! $REG instanceof EE_Registration) {
2827
-                    continue;
2828
-                }
2829
-                $deleted = $this->_delete_registration($REG);
2830
-                if (! $deleted) {
2831
-                    $success = 0;
2832
-                }
2833
-            }
2834
-        } else {
2835
-            // grab single id and delete
2836
-            $REG_ID = $this->_req_data['_REG_ID'];
2837
-            $REG = $REG_MDL->get_one_by_ID($REG_ID);
2838
-            $deleted = $this->_delete_registration($REG);
2839
-            if (! $deleted) {
2840
-                $success = 0;
2841
-            }
2842
-        }
2843
-        $what = $success > 1
2844
-            ? esc_html__('Registrations', 'event_espresso')
2845
-            : esc_html__('Registration', 'event_espresso');
2846
-        $action_desc = esc_html__('permanently deleted.', 'event_espresso');
2847
-        $this->_redirect_after_action(
2848
-            $success,
2849
-            $what,
2850
-            $action_desc,
2851
-            $this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2852
-            true
2853
-        );
2854
-    }
2855
-
2856
-
2857
-    /**
2858
-     * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2859
-     * models get affected.
2860
-     *
2861
-     * @param  EE_Registration $REG registration to be deleted permenantly
2862
-     * @return bool true = successful deletion, false = fail.
2863
-     * @throws EE_Error
2864
-     */
2865
-    protected function _delete_registration(EE_Registration $REG)
2866
-    {
2867
-        // first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2868
-        // registrations on the transaction that are NOT trashed.
2869
-        $TXN = $REG->get_first_related('Transaction');
2870
-        $REGS = $TXN->get_many_related('Registration');
2871
-        $all_trashed = true;
2872
-        foreach ($REGS as $registration) {
2873
-            if (! $registration->get('REG_deleted')) {
2874
-                $all_trashed = false;
2875
-            }
2876
-        }
2877
-        if (! $all_trashed) {
2878
-            EE_Error::add_error(
2879
-                esc_html__(
2880
-                    'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2881
-                    'event_espresso'
2882
-                ),
2883
-                __FILE__,
2884
-                __FUNCTION__,
2885
-                __LINE__
2886
-            );
2887
-            return false;
2888
-        }
2889
-        // k made it here so that means we can delete all the related transactions and their answers (but let's do them
2890
-        // separately from THIS one).
2891
-        foreach ($REGS as $registration) {
2892
-            // delete related answers
2893
-            $registration->delete_related_permanently('Answer');
2894
-            // remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2895
-            $attendee = $registration->get_first_related('Attendee');
2896
-            if ($attendee instanceof EE_Attendee) {
2897
-                $registration->_remove_relation_to($attendee, 'Attendee');
2898
-            }
2899
-            // now remove relationships to tickets on this registration.
2900
-            $registration->_remove_relations('Ticket');
2901
-            // now delete permanently the checkins related to this registration.
2902
-            $registration->delete_related_permanently('Checkin');
2903
-            if ($registration->ID() === $REG->ID()) {
2904
-                continue;
2905
-            } //we don't want to delete permanently the existing registration just yet.
2906
-            // remove relation to transaction for these registrations if NOT the existing registrations
2907
-            $registration->_remove_relations('Transaction');
2908
-            // delete permanently any related messages.
2909
-            $registration->delete_related_permanently('Message');
2910
-            // now delete this registration permanently
2911
-            $registration->delete_permanently();
2912
-        }
2913
-        // now all related registrations on the transaction are handled.  So let's just handle this registration itself
2914
-        // (the transaction and line items should be all that's left).
2915
-        // delete the line items related to the transaction for this registration.
2916
-        $TXN->delete_related_permanently('Line_Item');
2917
-        // we need to remove all the relationships on the transaction
2918
-        $TXN->delete_related_permanently('Payment');
2919
-        $TXN->delete_related_permanently('Extra_Meta');
2920
-        $TXN->delete_related_permanently('Message');
2921
-        // now we can delete this REG permanently (and the transaction of course)
2922
-        $REG->delete_related_permanently('Transaction');
2923
-        return $REG->delete_permanently();
2924
-    }
2925
-
2926
-
2927
-    /**
2928
-     *    generates HTML for the Register New Attendee Admin page
2929
-     *
2930
-     * @access private
2931
-     * @throws DomainException
2932
-     * @throws EE_Error
2933
-     */
2934
-    public function new_registration()
2935
-    {
2936
-        if (! $this->_set_reg_event()) {
2937
-            throw new EE_Error(
2938
-                esc_html__(
2939
-                    'Unable to continue with registering because there is no Event ID in the request',
2940
-                    'event_espresso'
2941
-                )
2942
-            );
2943
-        }
2944
-        EE_Registry::instance()->REQ->set_espresso_page(true);
2945
-        // gotta start with a clean slate if we're not coming here via ajax
2946
-        if (! defined('DOING_AJAX')
2947
-            && (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2948
-        ) {
2949
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2950
-        }
2951
-        $this->_template_args['event_name'] = '';
2952
-        // event name
2953
-        if ($this->_reg_event) {
2954
-            $this->_template_args['event_name'] = $this->_reg_event->name();
2955
-            $edit_event_url = self::add_query_args_and_nonce(
2956
-                array(
2957
-                    'action' => 'edit',
2958
-                    'post'   => $this->_reg_event->ID(),
2959
-                ),
2960
-                EVENTS_ADMIN_URL
2961
-            );
2962
-            $edit_event_lnk = '<a href="'
2963
-                              . $edit_event_url
2964
-                              . '" title="'
2965
-                              . esc_attr__('Edit ', 'event_espresso')
2966
-                              . $this->_reg_event->name()
2967
-                              . '">'
2968
-                              . esc_html__('Edit Event', 'event_espresso')
2969
-                              . '</a>';
2970
-            $this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2971
-                                                   . $edit_event_lnk
2972
-                                                   . '</span>';
2973
-        }
2974
-        $this->_template_args['step_content'] = $this->_get_registration_step_content();
2975
-        if (defined('DOING_AJAX')) {
2976
-            $this->_return_json();
2977
-        }
2978
-        // grab header
2979
-        $template_path =
2980
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2981
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2982
-            $template_path,
2983
-            $this->_template_args,
2984
-            true
2985
-        );
2986
-        // $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2987
-        // the details template wrapper
2988
-        $this->display_admin_page_with_sidebar();
2989
-    }
2990
-
2991
-
2992
-    /**
2993
-     * This returns the content for a registration step
2994
-     *
2995
-     * @access protected
2996
-     * @return string html
2997
-     * @throws DomainException
2998
-     * @throws EE_Error
2999
-     * @throws InvalidArgumentException
3000
-     * @throws InvalidDataTypeException
3001
-     * @throws InvalidInterfaceException
3002
-     */
3003
-    protected function _get_registration_step_content()
3004
-    {
3005
-        if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
3006
-            $warning_msg = sprintf(
3007
-                esc_html__(
3008
-                    '%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
3009
-                    'event_espresso'
3010
-                ),
3011
-                '<br />',
3012
-                '<h3 class="important-notice">',
3013
-                '</h3>',
3014
-                '<div class="float-right">',
3015
-                '<span id="redirect_timer" class="important-notice">30</span>',
3016
-                '</div>',
3017
-                '<b>',
3018
-                '</b>'
3019
-            );
3020
-            return '
2471
+	}
2472
+
2473
+
2474
+	/**
2475
+	 * Updates the registration's custom questions according to the form info, if the form is submitted.
2476
+	 * If it's not a post, the "view_registrations" route will be called next on the SAME request
2477
+	 * to display the page
2478
+	 *
2479
+	 * @access protected
2480
+	 * @return void
2481
+	 * @throws EE_Error
2482
+	 */
2483
+	protected function _update_attendee_registration_form()
2484
+	{
2485
+		do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2486
+		if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2487
+			$REG_ID = isset($this->_req_data['_REG_ID']) ? absint($this->_req_data['_REG_ID']) : false;
2488
+			$success = $this->_save_reg_custom_questions_form($REG_ID);
2489
+			if ($success) {
2490
+				$what = esc_html__('Registration Form', 'event_espresso');
2491
+				$route = $REG_ID ? array('action' => 'view_registration', '_REG_ID' => $REG_ID)
2492
+					: array('action' => 'default');
2493
+				$this->_redirect_after_action($success, $what, esc_html__('updated', 'event_espresso'), $route);
2494
+			}
2495
+		}
2496
+	}
2497
+
2498
+
2499
+	/**
2500
+	 * Gets the form for saving registrations custom questions (if done
2501
+	 * previously retrieves the cached form object, which may have validation errors in it)
2502
+	 *
2503
+	 * @param int $REG_ID
2504
+	 * @return EE_Registration_Custom_Questions_Form
2505
+	 * @throws EE_Error
2506
+	 * @throws InvalidArgumentException
2507
+	 * @throws InvalidDataTypeException
2508
+	 * @throws InvalidInterfaceException
2509
+	 */
2510
+	protected function _get_reg_custom_questions_form($REG_ID)
2511
+	{
2512
+		if (! $this->_reg_custom_questions_form) {
2513
+			require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2514
+			$this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2515
+				EEM_Registration::instance()->get_one_by_ID($REG_ID)
2516
+			);
2517
+			$this->_reg_custom_questions_form->_construct_finalize(null, null);
2518
+		}
2519
+		return $this->_reg_custom_questions_form;
2520
+	}
2521
+
2522
+
2523
+	/**
2524
+	 * Saves
2525
+	 *
2526
+	 * @access private
2527
+	 * @param bool $REG_ID
2528
+	 * @return bool
2529
+	 * @throws EE_Error
2530
+	 * @throws InvalidArgumentException
2531
+	 * @throws InvalidDataTypeException
2532
+	 * @throws InvalidInterfaceException
2533
+	 */
2534
+	private function _save_reg_custom_questions_form($REG_ID = false)
2535
+	{
2536
+		if (! $REG_ID) {
2537
+			EE_Error::add_error(
2538
+				esc_html__(
2539
+					'An error occurred. No registration ID was received.',
2540
+					'event_espresso'
2541
+				),
2542
+				__FILE__,
2543
+				__FUNCTION__,
2544
+				__LINE__
2545
+			);
2546
+		}
2547
+		$form = $this->_get_reg_custom_questions_form($REG_ID);
2548
+		$form->receive_form_submission($this->_req_data);
2549
+		$success = false;
2550
+		if ($form->is_valid()) {
2551
+			foreach ($form->subforms() as $question_group_id => $question_group_form) {
2552
+				foreach ($question_group_form->inputs() as $question_id => $input) {
2553
+					$where_conditions = array(
2554
+						'QST_ID' => $question_id,
2555
+						'REG_ID' => $REG_ID,
2556
+					);
2557
+					$possibly_new_values = array(
2558
+						'ANS_value' => $input->normalized_value(),
2559
+					);
2560
+					$answer = EEM_Answer::instance()->get_one(array($where_conditions));
2561
+					if ($answer instanceof EE_Answer) {
2562
+						$success = $answer->save($possibly_new_values);
2563
+					} else {
2564
+						// insert it then
2565
+						$cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2566
+						$answer = EE_Answer::new_instance($cols_n_vals);
2567
+						$success = $answer->save();
2568
+					}
2569
+				}
2570
+			}
2571
+		} else {
2572
+			EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2573
+		}
2574
+		return $success;
2575
+	}
2576
+
2577
+
2578
+	/**
2579
+	 *        generates HTML for the Registration main meta box
2580
+	 *
2581
+	 * @access public
2582
+	 * @return void
2583
+	 * @throws DomainException
2584
+	 * @throws EE_Error
2585
+	 * @throws InvalidArgumentException
2586
+	 * @throws InvalidDataTypeException
2587
+	 * @throws InvalidInterfaceException
2588
+	 */
2589
+	public function _reg_attendees_meta_box()
2590
+	{
2591
+		$REG = EEM_Registration::instance();
2592
+		// get all other registrations on this transaction, and cache
2593
+		// the attendees for them so we don't have to run another query using force_join
2594
+		$registrations = $REG->get_all(
2595
+			array(
2596
+				array(
2597
+					'TXN_ID' => $this->_registration->transaction_ID(),
2598
+					'REG_ID' => array('!=', $this->_registration->ID()),
2599
+				),
2600
+				'force_join' => array('Attendee'),
2601
+			)
2602
+		);
2603
+		$this->_template_args['attendees'] = array();
2604
+		$this->_template_args['attendee_notice'] = '';
2605
+		if (empty($registrations)
2606
+			|| (is_array($registrations)
2607
+				&& ! EEH_Array::get_one_item_from_array($registrations))
2608
+		) {
2609
+			EE_Error::add_error(
2610
+				esc_html__(
2611
+					'There are no records attached to this registration. Something may have gone wrong with the registration',
2612
+					'event_espresso'
2613
+				),
2614
+				__FILE__,
2615
+				__FUNCTION__,
2616
+				__LINE__
2617
+			);
2618
+			$this->_template_args['attendee_notice'] = EE_Error::get_notices();
2619
+		} else {
2620
+			$att_nmbr = 1;
2621
+			foreach ($registrations as $registration) {
2622
+				/* @var $registration EE_Registration */
2623
+				$attendee = $registration->attendee()
2624
+					? $registration->attendee()
2625
+					: EEM_Attendee::instance()
2626
+								  ->create_default_object();
2627
+				$this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2628
+				$this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2629
+				$this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2630
+				$this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2631
+				$this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2632
+				$this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2633
+					', ',
2634
+					$attendee->full_address_as_array()
2635
+				);
2636
+				$this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2637
+					array(
2638
+						'action' => 'edit_attendee',
2639
+						'post'   => $attendee->ID(),
2640
+					),
2641
+					REG_ADMIN_URL
2642
+				);
2643
+				$this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj() instanceof EE_Event
2644
+					? $registration->event_obj()->name()
2645
+					: '';
2646
+				$att_nmbr++;
2647
+			}
2648
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2649
+		}
2650
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2651
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2652
+	}
2653
+
2654
+
2655
+	/**
2656
+	 *        generates HTML for the Edit Registration side meta box
2657
+	 *
2658
+	 * @access public
2659
+	 * @return void
2660
+	 * @throws DomainException
2661
+	 * @throws EE_Error
2662
+	 * @throws InvalidArgumentException
2663
+	 * @throws InvalidDataTypeException
2664
+	 * @throws InvalidInterfaceException
2665
+	 */
2666
+	public function _reg_registrant_side_meta_box()
2667
+	{
2668
+		/*@var $attendee EE_Attendee */
2669
+		$att_check = $this->_registration->attendee();
2670
+		$attendee = $att_check instanceof EE_Attendee ? $att_check : EEM_Attendee::instance()->create_default_object();
2671
+		// now let's determine if this is not the primary registration.  If it isn't then we set the
2672
+		// primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2673
+		// primary registration object (that way we know if we need to show create button or not)
2674
+		if (! $this->_registration->is_primary_registrant()) {
2675
+			$primary_registration = $this->_registration->get_primary_registration();
2676
+			$primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2677
+				: null;
2678
+			if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2679
+				// in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2680
+				// custom attendee object so let's not worry about the primary reg.
2681
+				$primary_registration = null;
2682
+			}
2683
+		} else {
2684
+			$primary_registration = null;
2685
+		}
2686
+		$this->_template_args['ATT_ID'] = $attendee->ID();
2687
+		$this->_template_args['fname'] = $attendee->fname();
2688
+		$this->_template_args['lname'] = $attendee->lname();
2689
+		$this->_template_args['email'] = $attendee->email();
2690
+		$this->_template_args['phone'] = $attendee->phone();
2691
+		$this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2692
+		// edit link
2693
+		$this->_template_args['att_edit_link'] = EE_Admin_Page::add_query_args_and_nonce(
2694
+			array(
2695
+				'action' => 'edit_attendee',
2696
+				'post'   => $attendee->ID(),
2697
+			),
2698
+			REG_ADMIN_URL
2699
+		);
2700
+		$this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2701
+		// create link
2702
+		$this->_template_args['create_link'] = $primary_registration instanceof EE_Registration
2703
+			? EE_Admin_Page::add_query_args_and_nonce(
2704
+				array(
2705
+					'action'  => 'duplicate_attendee',
2706
+					'_REG_ID' => $this->_registration->ID(),
2707
+				),
2708
+				REG_ADMIN_URL
2709
+			) : '';
2710
+		$this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2711
+		$this->_template_args['att_check'] = $att_check;
2712
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2713
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2714
+	}
2715
+
2716
+
2717
+	/**
2718
+	 * trash or restore registrations
2719
+	 *
2720
+	 * @param  boolean $trash whether to archive or restore
2721
+	 * @return void
2722
+	 * @throws EE_Error
2723
+	 * @throws InvalidArgumentException
2724
+	 * @throws InvalidDataTypeException
2725
+	 * @throws InvalidInterfaceException
2726
+	 * @throws RuntimeException
2727
+	 * @access protected
2728
+	 */
2729
+	protected function _trash_or_restore_registrations($trash = true)
2730
+	{
2731
+		// if empty _REG_ID then get out because there's nothing to do
2732
+		if (empty($this->_req_data['_REG_ID'])) {
2733
+			EE_Error::add_error(
2734
+				sprintf(
2735
+					esc_html__(
2736
+						'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2737
+						'event_espresso'
2738
+					),
2739
+					$trash ? 'trash' : 'restore'
2740
+				),
2741
+				__FILE__,
2742
+				__LINE__,
2743
+				__FUNCTION__
2744
+			);
2745
+			$this->_redirect_after_action(false, '', '', array(), true);
2746
+		}
2747
+		$success = 0;
2748
+		$overwrite_msgs = false;
2749
+		// Checkboxes
2750
+		if (! is_array($this->_req_data['_REG_ID'])) {
2751
+			$this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2752
+		}
2753
+		$reg_count = count($this->_req_data['_REG_ID']);
2754
+		// cycle thru checkboxes
2755
+		foreach ($this->_req_data['_REG_ID'] as $REG_ID) {
2756
+			/** @var EE_Registration $REG */
2757
+			$REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2758
+			$payments = $REG->registration_payments();
2759
+			if (! empty($payments)) {
2760
+				$name = $REG->attendee() instanceof EE_Attendee
2761
+					? $REG->attendee()->full_name()
2762
+					: esc_html__('Unknown Attendee', 'event_espresso');
2763
+				$overwrite_msgs = true;
2764
+				EE_Error::add_error(
2765
+					sprintf(
2766
+						esc_html__(
2767
+							'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2768
+							'event_espresso'
2769
+						),
2770
+						$name
2771
+					),
2772
+					__FILE__,
2773
+					__FUNCTION__,
2774
+					__LINE__
2775
+				);
2776
+				// can't trash this registration because it has payments.
2777
+				continue;
2778
+			}
2779
+			$updated = $trash ? $REG->delete() : $REG->restore();
2780
+			if ($updated) {
2781
+				$success++;
2782
+			}
2783
+		}
2784
+		$this->_redirect_after_action(
2785
+			$success === $reg_count, // were ALL registrations affected?
2786
+			$success > 1
2787
+				? esc_html__('Registrations', 'event_espresso')
2788
+				: esc_html__('Registration', 'event_espresso'),
2789
+			$trash
2790
+				? esc_html__('moved to the trash', 'event_espresso')
2791
+				: esc_html__('restored', 'event_espresso'),
2792
+			$this->mergeExistingRequestParamsWithRedirectArgs(array('action' => 'default')),
2793
+			$overwrite_msgs
2794
+		);
2795
+	}
2796
+
2797
+
2798
+	/**
2799
+	 * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2800
+	 * registration but also.
2801
+	 * 1. Removing relations to EE_Attendee
2802
+	 * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2803
+	 * ALSO trashed.
2804
+	 * 3. Deleting permanently any related Line items but only if the above conditions are met.
2805
+	 * 4. Removing relationships between all tickets and the related registrations
2806
+	 * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2807
+	 * 6. Deleting permanently any related Checkins.
2808
+	 *
2809
+	 * @return void
2810
+	 * @throws EE_Error
2811
+	 * @throws InvalidArgumentException
2812
+	 * @throws InvalidDataTypeException
2813
+	 * @throws InvalidInterfaceException
2814
+	 */
2815
+	protected function _delete_registrations()
2816
+	{
2817
+		$REG_MDL = EEM_Registration::instance();
2818
+		$success = 1;
2819
+		// Checkboxes
2820
+		if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2821
+			// if array has more than one element than success message should be plural
2822
+			$success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2823
+			// cycle thru checkboxes
2824
+			while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2825
+				$REG = $REG_MDL->get_one_by_ID($REG_ID);
2826
+				if (! $REG instanceof EE_Registration) {
2827
+					continue;
2828
+				}
2829
+				$deleted = $this->_delete_registration($REG);
2830
+				if (! $deleted) {
2831
+					$success = 0;
2832
+				}
2833
+			}
2834
+		} else {
2835
+			// grab single id and delete
2836
+			$REG_ID = $this->_req_data['_REG_ID'];
2837
+			$REG = $REG_MDL->get_one_by_ID($REG_ID);
2838
+			$deleted = $this->_delete_registration($REG);
2839
+			if (! $deleted) {
2840
+				$success = 0;
2841
+			}
2842
+		}
2843
+		$what = $success > 1
2844
+			? esc_html__('Registrations', 'event_espresso')
2845
+			: esc_html__('Registration', 'event_espresso');
2846
+		$action_desc = esc_html__('permanently deleted.', 'event_espresso');
2847
+		$this->_redirect_after_action(
2848
+			$success,
2849
+			$what,
2850
+			$action_desc,
2851
+			$this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2852
+			true
2853
+		);
2854
+	}
2855
+
2856
+
2857
+	/**
2858
+	 * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2859
+	 * models get affected.
2860
+	 *
2861
+	 * @param  EE_Registration $REG registration to be deleted permenantly
2862
+	 * @return bool true = successful deletion, false = fail.
2863
+	 * @throws EE_Error
2864
+	 */
2865
+	protected function _delete_registration(EE_Registration $REG)
2866
+	{
2867
+		// first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2868
+		// registrations on the transaction that are NOT trashed.
2869
+		$TXN = $REG->get_first_related('Transaction');
2870
+		$REGS = $TXN->get_many_related('Registration');
2871
+		$all_trashed = true;
2872
+		foreach ($REGS as $registration) {
2873
+			if (! $registration->get('REG_deleted')) {
2874
+				$all_trashed = false;
2875
+			}
2876
+		}
2877
+		if (! $all_trashed) {
2878
+			EE_Error::add_error(
2879
+				esc_html__(
2880
+					'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2881
+					'event_espresso'
2882
+				),
2883
+				__FILE__,
2884
+				__FUNCTION__,
2885
+				__LINE__
2886
+			);
2887
+			return false;
2888
+		}
2889
+		// k made it here so that means we can delete all the related transactions and their answers (but let's do them
2890
+		// separately from THIS one).
2891
+		foreach ($REGS as $registration) {
2892
+			// delete related answers
2893
+			$registration->delete_related_permanently('Answer');
2894
+			// remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2895
+			$attendee = $registration->get_first_related('Attendee');
2896
+			if ($attendee instanceof EE_Attendee) {
2897
+				$registration->_remove_relation_to($attendee, 'Attendee');
2898
+			}
2899
+			// now remove relationships to tickets on this registration.
2900
+			$registration->_remove_relations('Ticket');
2901
+			// now delete permanently the checkins related to this registration.
2902
+			$registration->delete_related_permanently('Checkin');
2903
+			if ($registration->ID() === $REG->ID()) {
2904
+				continue;
2905
+			} //we don't want to delete permanently the existing registration just yet.
2906
+			// remove relation to transaction for these registrations if NOT the existing registrations
2907
+			$registration->_remove_relations('Transaction');
2908
+			// delete permanently any related messages.
2909
+			$registration->delete_related_permanently('Message');
2910
+			// now delete this registration permanently
2911
+			$registration->delete_permanently();
2912
+		}
2913
+		// now all related registrations on the transaction are handled.  So let's just handle this registration itself
2914
+		// (the transaction and line items should be all that's left).
2915
+		// delete the line items related to the transaction for this registration.
2916
+		$TXN->delete_related_permanently('Line_Item');
2917
+		// we need to remove all the relationships on the transaction
2918
+		$TXN->delete_related_permanently('Payment');
2919
+		$TXN->delete_related_permanently('Extra_Meta');
2920
+		$TXN->delete_related_permanently('Message');
2921
+		// now we can delete this REG permanently (and the transaction of course)
2922
+		$REG->delete_related_permanently('Transaction');
2923
+		return $REG->delete_permanently();
2924
+	}
2925
+
2926
+
2927
+	/**
2928
+	 *    generates HTML for the Register New Attendee Admin page
2929
+	 *
2930
+	 * @access private
2931
+	 * @throws DomainException
2932
+	 * @throws EE_Error
2933
+	 */
2934
+	public function new_registration()
2935
+	{
2936
+		if (! $this->_set_reg_event()) {
2937
+			throw new EE_Error(
2938
+				esc_html__(
2939
+					'Unable to continue with registering because there is no Event ID in the request',
2940
+					'event_espresso'
2941
+				)
2942
+			);
2943
+		}
2944
+		EE_Registry::instance()->REQ->set_espresso_page(true);
2945
+		// gotta start with a clean slate if we're not coming here via ajax
2946
+		if (! defined('DOING_AJAX')
2947
+			&& (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2948
+		) {
2949
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2950
+		}
2951
+		$this->_template_args['event_name'] = '';
2952
+		// event name
2953
+		if ($this->_reg_event) {
2954
+			$this->_template_args['event_name'] = $this->_reg_event->name();
2955
+			$edit_event_url = self::add_query_args_and_nonce(
2956
+				array(
2957
+					'action' => 'edit',
2958
+					'post'   => $this->_reg_event->ID(),
2959
+				),
2960
+				EVENTS_ADMIN_URL
2961
+			);
2962
+			$edit_event_lnk = '<a href="'
2963
+							  . $edit_event_url
2964
+							  . '" title="'
2965
+							  . esc_attr__('Edit ', 'event_espresso')
2966
+							  . $this->_reg_event->name()
2967
+							  . '">'
2968
+							  . esc_html__('Edit Event', 'event_espresso')
2969
+							  . '</a>';
2970
+			$this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2971
+												   . $edit_event_lnk
2972
+												   . '</span>';
2973
+		}
2974
+		$this->_template_args['step_content'] = $this->_get_registration_step_content();
2975
+		if (defined('DOING_AJAX')) {
2976
+			$this->_return_json();
2977
+		}
2978
+		// grab header
2979
+		$template_path =
2980
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2981
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2982
+			$template_path,
2983
+			$this->_template_args,
2984
+			true
2985
+		);
2986
+		// $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2987
+		// the details template wrapper
2988
+		$this->display_admin_page_with_sidebar();
2989
+	}
2990
+
2991
+
2992
+	/**
2993
+	 * This returns the content for a registration step
2994
+	 *
2995
+	 * @access protected
2996
+	 * @return string html
2997
+	 * @throws DomainException
2998
+	 * @throws EE_Error
2999
+	 * @throws InvalidArgumentException
3000
+	 * @throws InvalidDataTypeException
3001
+	 * @throws InvalidInterfaceException
3002
+	 */
3003
+	protected function _get_registration_step_content()
3004
+	{
3005
+		if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
3006
+			$warning_msg = sprintf(
3007
+				esc_html__(
3008
+					'%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
3009
+					'event_espresso'
3010
+				),
3011
+				'<br />',
3012
+				'<h3 class="important-notice">',
3013
+				'</h3>',
3014
+				'<div class="float-right">',
3015
+				'<span id="redirect_timer" class="important-notice">30</span>',
3016
+				'</div>',
3017
+				'<b>',
3018
+				'</b>'
3019
+			);
3020
+			return '
3021 3021
 	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
3022 3022
 	<script >
3023 3023
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
@@ -3030,855 +3030,855 @@  discard block
 block discarded – undo
3030 3030
 	        }
3031 3031
 	    }, 800 );
3032 3032
 	</script >';
3033
-        }
3034
-        $template_args = array(
3035
-            'title'                    => '',
3036
-            'content'                  => '',
3037
-            'step_button_text'         => '',
3038
-            'show_notification_toggle' => false,
3039
-        );
3040
-        // to indicate we're processing a new registration
3041
-        $hidden_fields = array(
3042
-            'processing_registration' => array(
3043
-                'type'  => 'hidden',
3044
-                'value' => 0,
3045
-            ),
3046
-            'event_id'                => array(
3047
-                'type'  => 'hidden',
3048
-                'value' => $this->_reg_event->ID(),
3049
-            ),
3050
-        );
3051
-        // if the cart is empty then we know we're at step one so we'll display ticket selector
3052
-        $cart = EE_Registry::instance()->SSN->cart();
3053
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3054
-        switch ($step) {
3055
-            case 'ticket':
3056
-                $hidden_fields['processing_registration']['value'] = 1;
3057
-                $template_args['title'] = esc_html__(
3058
-                    'Step One: Select the Ticket for this registration',
3059
-                    'event_espresso'
3060
-                );
3061
-                $template_args['content'] =
3062
-                    EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
3063
-                $template_args['step_button_text'] = esc_html__(
3064
-                    'Add Tickets and Continue to Registrant Details',
3065
-                    'event_espresso'
3066
-                );
3067
-                $template_args['show_notification_toggle'] = false;
3068
-                break;
3069
-            case 'questions':
3070
-                $hidden_fields['processing_registration']['value'] = 2;
3071
-                $template_args['title'] = esc_html__(
3072
-                    'Step Two: Add Registrant Details for this Registration',
3073
-                    'event_espresso'
3074
-                );
3075
-                // in theory we should be able to run EED_SPCO at this point because the cart should have been setup
3076
-                // properly by the first process_reg_step run.
3077
-                $template_args['content'] =
3078
-                    EED_Single_Page_Checkout::registration_checkout_for_admin();
3079
-                $template_args['step_button_text'] = esc_html__(
3080
-                    'Save Registration and Continue to Details',
3081
-                    'event_espresso'
3082
-                );
3083
-                $template_args['show_notification_toggle'] = true;
3084
-                break;
3085
-        }
3086
-        // we come back to the process_registration_step route.
3087
-        $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3088
-        return EEH_Template::display_template(
3089
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3090
-            $template_args,
3091
-            true
3092
-        );
3093
-    }
3094
-
3095
-
3096
-    /**
3097
-     *        set_reg_event
3098
-     *
3099
-     * @access private
3100
-     * @return bool
3101
-     * @throws EE_Error
3102
-     * @throws InvalidArgumentException
3103
-     * @throws InvalidDataTypeException
3104
-     * @throws InvalidInterfaceException
3105
-     */
3106
-    private function _set_reg_event()
3107
-    {
3108
-        if (is_object($this->_reg_event)) {
3109
-            return true;
3110
-        }
3111
-        $EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3112
-        if (! $EVT_ID) {
3113
-            return false;
3114
-        }
3115
-        $this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
3116
-        return true;
3117
-    }
3118
-
3119
-
3120
-    /**
3121
-     * process_reg_step
3122
-     *
3123
-     * @access        public
3124
-     * @return string
3125
-     * @throws DomainException
3126
-     * @throws EE_Error
3127
-     * @throws InvalidArgumentException
3128
-     * @throws InvalidDataTypeException
3129
-     * @throws InvalidInterfaceException
3130
-     * @throws ReflectionException
3131
-     * @throws RuntimeException
3132
-     */
3133
-    public function process_reg_step()
3134
-    {
3135
-        EE_System::do_not_cache();
3136
-        $this->_set_reg_event();
3137
-        EE_Registry::instance()->REQ->set_espresso_page(true);
3138
-        EE_Registry::instance()->REQ->set('uts', time());
3139
-        // what step are we on?
3140
-        $cart = EE_Registry::instance()->SSN->cart();
3141
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3142
-        // if doing ajax then we need to verify the nonce
3143
-        if (defined('DOING_AJAX')) {
3144
-            $nonce = isset($this->_req_data[ $this->_req_nonce ])
3145
-                ? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3146
-            $this->_verify_nonce($nonce, $this->_req_nonce);
3147
-        }
3148
-        switch ($step) {
3149
-            case 'ticket':
3150
-                // process ticket selection
3151
-                $success = EED_Ticket_Selector::instance()->process_ticket_selections();
3152
-                if ($success) {
3153
-                    EE_Error::add_success(
3154
-                        esc_html__(
3155
-                            'Tickets Selected. Now complete the registration.',
3156
-                            'event_espresso'
3157
-                        )
3158
-                    );
3159
-                } else {
3160
-                    $query_args['step_error'] = $this->_req_data['step_error'] = true;
3161
-                }
3162
-                if (defined('DOING_AJAX')) {
3163
-                    $this->new_registration(); // display next step
3164
-                } else {
3165
-                    $query_args = array(
3166
-                        'action'                  => 'new_registration',
3167
-                        'processing_registration' => 1,
3168
-                        'event_id'                => $this->_reg_event->ID(),
3169
-                        'uts'                     => time(),
3170
-                    );
3171
-                    $this->_redirect_after_action(
3172
-                        false,
3173
-                        '',
3174
-                        '',
3175
-                        $query_args,
3176
-                        true
3177
-                    );
3178
-                }
3179
-                break;
3180
-            case 'questions':
3181
-                if (! isset(
3182
-                    $this->_req_data['txn_reg_status_change'],
3183
-                    $this->_req_data['txn_reg_status_change']['send_notifications']
3184
-                )
3185
-                ) {
3186
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3187
-                }
3188
-                // process registration
3189
-                $transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3190
-                if ($cart instanceof EE_Cart) {
3191
-                    $grand_total = $cart->get_cart_grand_total();
3192
-                    if ($grand_total instanceof EE_Line_Item) {
3193
-                        $grand_total->save_this_and_descendants_to_txn();
3194
-                    }
3195
-                }
3196
-                if (! $transaction instanceof EE_Transaction) {
3197
-                    $query_args = array(
3198
-                        'action'                  => 'new_registration',
3199
-                        'processing_registration' => 2,
3200
-                        'event_id'                => $this->_reg_event->ID(),
3201
-                        'uts'                     => time(),
3202
-                    );
3203
-                    if (defined('DOING_AJAX')) {
3204
-                        // display registration form again because there are errors (maybe validation?)
3205
-                        $this->new_registration();
3206
-                        return;
3207
-                    } else {
3208
-                        $this->_redirect_after_action(
3209
-                            false,
3210
-                            '',
3211
-                            '',
3212
-                            $query_args,
3213
-                            true
3214
-                        );
3215
-                        return;
3216
-                    }
3217
-                }
3218
-                // maybe update status, and make sure to save transaction if not done already
3219
-                if (! $transaction->update_status_based_on_total_paid()) {
3220
-                    $transaction->save();
3221
-                }
3222
-                EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3223
-                $this->_req_data = array();
3224
-                $query_args = array(
3225
-                    'action'        => 'redirect_to_txn',
3226
-                    'TXN_ID'        => $transaction->ID(),
3227
-                    'EVT_ID'        => $this->_reg_event->ID(),
3228
-                    'event_name'    => urlencode($this->_reg_event->name()),
3229
-                    'redirect_from' => 'new_registration',
3230
-                );
3231
-                $this->_redirect_after_action(false, '', '', $query_args, true);
3232
-                break;
3233
-        }
3234
-        // what are you looking here for?  Should be nothing to do at this point.
3235
-    }
3236
-
3237
-
3238
-    /**
3239
-     * redirect_to_txn
3240
-     *
3241
-     * @access public
3242
-     * @return void
3243
-     * @throws EE_Error
3244
-     * @throws InvalidArgumentException
3245
-     * @throws InvalidDataTypeException
3246
-     * @throws InvalidInterfaceException
3247
-     */
3248
-    public function redirect_to_txn()
3249
-    {
3250
-        EE_System::do_not_cache();
3251
-        EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3252
-        $query_args = array(
3253
-            'action' => 'view_transaction',
3254
-            'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
3255
-            'page'   => 'espresso_transactions',
3256
-        );
3257
-        if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
3258
-            $query_args['EVT_ID'] = $this->_req_data['EVT_ID'];
3259
-            $query_args['event_name'] = urlencode($this->_req_data['event_name']);
3260
-            $query_args['redirect_from'] = $this->_req_data['redirect_from'];
3261
-        }
3262
-        EE_Error::add_success(
3263
-            esc_html__(
3264
-                'Registration Created.  Please review the transaction and add any payments as necessary',
3265
-                'event_espresso'
3266
-            )
3267
-        );
3268
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3269
-    }
3270
-
3271
-
3272
-    /**
3273
-     *        generates HTML for the Attendee Contact List
3274
-     *
3275
-     * @access protected
3276
-     * @return void
3277
-     */
3278
-    protected function _attendee_contact_list_table()
3279
-    {
3280
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3281
-        $this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3282
-        $this->display_admin_list_table_page_with_no_sidebar();
3283
-    }
3284
-
3285
-
3286
-    /**
3287
-     *        get_attendees
3288
-     *
3289
-     * @param      $per_page
3290
-     * @param bool $count whether to return count or data.
3291
-     * @param bool $trash
3292
-     * @return array
3293
-     * @throws EE_Error
3294
-     * @throws InvalidArgumentException
3295
-     * @throws InvalidDataTypeException
3296
-     * @throws InvalidInterfaceException
3297
-     * @access public
3298
-     */
3299
-    public function get_attendees($per_page, $count = false, $trash = false)
3300
-    {
3301
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3302
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3303
-        $ATT_MDL = EEM_Attendee::instance();
3304
-        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3305
-        switch ($this->_req_data['orderby']) {
3306
-            case 'ATT_ID':
3307
-                $orderby = 'ATT_ID';
3308
-                break;
3309
-            case 'ATT_fname':
3310
-                $orderby = 'ATT_fname';
3311
-                break;
3312
-            case 'ATT_email':
3313
-                $orderby = 'ATT_email';
3314
-                break;
3315
-            case 'ATT_city':
3316
-                $orderby = 'ATT_city';
3317
-                break;
3318
-            case 'STA_ID':
3319
-                $orderby = 'STA_ID';
3320
-                break;
3321
-            case 'CNT_ID':
3322
-                $orderby = 'CNT_ID';
3323
-                break;
3324
-            case 'Registration_Count':
3325
-                $orderby = 'Registration_Count';
3326
-                break;
3327
-            default:
3328
-                $orderby = 'ATT_lname';
3329
-        }
3330
-        $sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
3331
-            ? $this->_req_data['order']
3332
-            : 'ASC';
3333
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
3334
-            ? $this->_req_data['paged']
3335
-            : 1;
3336
-        $per_page = isset($per_page) && ! empty($per_page) ? $per_page : 10;
3337
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3338
-            ? $this->_req_data['perpage']
3339
-            : $per_page;
3340
-        $_where = array();
3341
-        if (! empty($this->_req_data['s'])) {
3342
-            $sstr = '%' . $this->_req_data['s'] . '%';
3343
-            $_where['OR'] = array(
3344
-                'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3345
-                'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3346
-                'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3347
-                'ATT_fname'                         => array('LIKE', $sstr),
3348
-                'ATT_lname'                         => array('LIKE', $sstr),
3349
-                'ATT_short_bio'                     => array('LIKE', $sstr),
3350
-                'ATT_email'                         => array('LIKE', $sstr),
3351
-                'ATT_address'                       => array('LIKE', $sstr),
3352
-                'ATT_address2'                      => array('LIKE', $sstr),
3353
-                'ATT_city'                          => array('LIKE', $sstr),
3354
-                'Country.CNT_name'                  => array('LIKE', $sstr),
3355
-                'State.STA_name'                    => array('LIKE', $sstr),
3356
-                'ATT_phone'                         => array('LIKE', $sstr),
3357
-                'Registration.REG_final_price'      => array('LIKE', $sstr),
3358
-                'Registration.REG_code'             => array('LIKE', $sstr),
3359
-                'Registration.REG_group_size'       => array('LIKE', $sstr),
3360
-            );
3361
-        }
3362
-        $offset = ($current_page - 1) * $per_page;
3363
-        $limit = $count ? null : array($offset, $per_page);
3364
-        $query_args = array(
3365
-            $_where,
3366
-            'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3367
-            'limit'         => $limit,
3368
-        );
3369
-        if (! $count) {
3370
-            $query_args['order_by'] = array($orderby => $sort);
3371
-        }
3372
-        if ($trash) {
3373
-            $query_args[0]['status'] = array('!=', 'publish');
3374
-            $all_attendees = $count
3375
-                ? $ATT_MDL->count($query_args, 'ATT_ID', true)
3376
-                : $ATT_MDL->get_all($query_args);
3377
-        } else {
3378
-            $query_args[0]['status'] = array('IN', array('publish'));
3379
-            $all_attendees = $count
3380
-                ? $ATT_MDL->count($query_args, 'ATT_ID', true)
3381
-                : $ATT_MDL->get_all($query_args);
3382
-        }
3383
-        return $all_attendees;
3384
-    }
3385
-
3386
-
3387
-    /**
3388
-     * This is just taking care of resending the registration confirmation
3389
-     *
3390
-     * @access protected
3391
-     * @return void
3392
-     */
3393
-    protected function _resend_registration()
3394
-    {
3395
-        $this->_process_resend_registration();
3396
-        $query_args = isset($this->_req_data['redirect_to'])
3397
-            ? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3398
-            : array('action' => 'default');
3399
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3400
-    }
3401
-
3402
-    /**
3403
-     * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3404
-     * to use when selecting registrations
3405
-     *
3406
-     * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3407
-     *                                                     the query parameters from the request
3408
-     * @return void ends the request with a redirect or download
3409
-     */
3410
-    public function _registrations_report_base($method_name_for_getting_query_params)
3411
-    {
3412
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3413
-            wp_redirect(
3414
-                EE_Admin_Page::add_query_args_and_nonce(
3415
-                    array(
3416
-                        'page'        => 'espresso_batch',
3417
-                        'batch'       => 'file',
3418
-                        'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3419
-                        'filters'     => urlencode(
3420
-                            serialize(
3421
-                                call_user_func(
3422
-                                    array($this, $method_name_for_getting_query_params),
3423
-                                    EEH_Array::is_set(
3424
-                                        $this->_req_data,
3425
-                                        'filters',
3426
-                                        array()
3427
-                                    )
3428
-                                )
3429
-                            )
3430
-                        ),
3431
-                        'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3432
-                        'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3433
-                        'return_url'  => urlencode($this->_req_data['return_url']),
3434
-                    )
3435
-                )
3436
-            );
3437
-        } else {
3438
-            $new_request_args = array(
3439
-                'export' => 'report',
3440
-                'action' => 'registrations_report_for_event',
3441
-                'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3442
-            );
3443
-            $this->_req_data = array_merge($this->_req_data, $new_request_args);
3444
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3445
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3446
-                $EE_Export = EE_Export::instance($this->_req_data);
3447
-                $EE_Export->export();
3448
-            }
3449
-        }
3450
-    }
3451
-
3452
-
3453
-    /**
3454
-     * Creates a registration report using only query parameters in the request
3455
-     *
3456
-     * @return void
3457
-     */
3458
-    public function _registrations_report()
3459
-    {
3460
-        $this->_registrations_report_base('_get_registration_query_parameters');
3461
-    }
3462
-
3463
-
3464
-    public function _contact_list_export()
3465
-    {
3466
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3467
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3468
-            $EE_Export = EE_Export::instance($this->_req_data);
3469
-            $EE_Export->export_attendees();
3470
-        }
3471
-    }
3472
-
3473
-
3474
-    public function _contact_list_report()
3475
-    {
3476
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3477
-            wp_redirect(
3478
-                EE_Admin_Page::add_query_args_and_nonce(
3479
-                    array(
3480
-                        'page'        => 'espresso_batch',
3481
-                        'batch'       => 'file',
3482
-                        'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3483
-                        'return_url'  => urlencode($this->_req_data['return_url']),
3484
-                    )
3485
-                )
3486
-            );
3487
-        } else {
3488
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3489
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3490
-                $EE_Export = EE_Export::instance($this->_req_data);
3491
-                $EE_Export->report_attendees();
3492
-            }
3493
-        }
3494
-    }
3495
-
3496
-
3497
-
3498
-
3499
-
3500
-    /***************************************        ATTENDEE DETAILS        ***************************************/
3501
-    /**
3502
-     * This duplicates the attendee object for the given incoming registration id and attendee_id.
3503
-     *
3504
-     * @return void
3505
-     * @throws EE_Error
3506
-     * @throws InvalidArgumentException
3507
-     * @throws InvalidDataTypeException
3508
-     * @throws InvalidInterfaceException
3509
-     */
3510
-    protected function _duplicate_attendee()
3511
-    {
3512
-        $action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3513
-        // verify we have necessary info
3514
-        if (empty($this->_req_data['_REG_ID'])) {
3515
-            EE_Error::add_error(
3516
-                esc_html__(
3517
-                    'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3518
-                    'event_espresso'
3519
-                ),
3520
-                __FILE__,
3521
-                __LINE__,
3522
-                __FUNCTION__
3523
-            );
3524
-            $query_args = array('action' => $action);
3525
-            $this->_redirect_after_action('', '', '', $query_args, true);
3526
-        }
3527
-        // okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3528
-        $registration = EEM_Registration::instance()->get_one_by_ID($this->_req_data['_REG_ID']);
3529
-        $attendee = $registration->attendee();
3530
-        // remove relation of existing attendee on registration
3531
-        $registration->_remove_relation_to($attendee, 'Attendee');
3532
-        // new attendee
3533
-        $new_attendee = clone $attendee;
3534
-        $new_attendee->set('ATT_ID', 0);
3535
-        $new_attendee->save();
3536
-        // add new attendee to reg
3537
-        $registration->_add_relation_to($new_attendee, 'Attendee');
3538
-        EE_Error::add_success(
3539
-            esc_html__(
3540
-                'New Contact record created.  Now make any edits you wish to make for this contact.',
3541
-                'event_espresso'
3542
-            )
3543
-        );
3544
-        // redirect to edit page for attendee
3545
-        $query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3546
-        $this->_redirect_after_action('', '', '', $query_args, true);
3547
-    }
3548
-
3549
-
3550
-    /**
3551
-     * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3552
-     *
3553
-     * @param int     $post_id
3554
-     * @param WP_POST $post
3555
-     * @throws DomainException
3556
-     * @throws EE_Error
3557
-     * @throws InvalidArgumentException
3558
-     * @throws InvalidDataTypeException
3559
-     * @throws InvalidInterfaceException
3560
-     * @throws LogicException
3561
-     * @throws InvalidFormSubmissionException
3562
-     */
3563
-    protected function _insert_update_cpt_item($post_id, $post)
3564
-    {
3565
-        $success = true;
3566
-        $attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3567
-            ? EEM_Attendee::instance()->get_one_by_ID($post_id)
3568
-            : null;
3569
-        // for attendee updates
3570
-        if ($attendee instanceof EE_Attendee) {
3571
-            // note we should only be UPDATING attendees at this point.
3572
-            $updated_fields = array(
3573
-                'ATT_fname'     => $this->_req_data['ATT_fname'],
3574
-                'ATT_lname'     => $this->_req_data['ATT_lname'],
3575
-                'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3576
-                'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3577
-                'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3578
-                'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3579
-                'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3580
-                'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3581
-                'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3582
-            );
3583
-            foreach ($updated_fields as $field => $value) {
3584
-                $attendee->set($field, $value);
3585
-            }
3586
-
3587
-            // process contact details metabox form handler (which will also save the attendee)
3588
-            $contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3589
-            $success = $contact_details_form->process($this->_req_data);
3590
-
3591
-            $attendee_update_callbacks = apply_filters(
3592
-                'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3593
-                array()
3594
-            );
3595
-            foreach ($attendee_update_callbacks as $a_callback) {
3596
-                if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3597
-                    throw new EE_Error(
3598
-                        sprintf(
3599
-                            esc_html__(
3600
-                                'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3601
-                                'event_espresso'
3602
-                            ),
3603
-                            $a_callback
3604
-                        )
3605
-                    );
3606
-                }
3607
-            }
3608
-        }
3609
-
3610
-        if ($success === false) {
3611
-            EE_Error::add_error(
3612
-                esc_html__(
3613
-                    'Something went wrong with updating the meta table data for the registration.',
3614
-                    'event_espresso'
3615
-                ),
3616
-                __FILE__,
3617
-                __FUNCTION__,
3618
-                __LINE__
3619
-            );
3620
-        }
3621
-    }
3622
-
3623
-
3624
-    public function trash_cpt_item($post_id)
3625
-    {
3626
-    }
3627
-
3628
-
3629
-    public function delete_cpt_item($post_id)
3630
-    {
3631
-    }
3632
-
3633
-
3634
-    public function restore_cpt_item($post_id)
3635
-    {
3636
-    }
3637
-
3638
-
3639
-    protected function _restore_cpt_item($post_id, $revision_id)
3640
-    {
3641
-    }
3642
-
3643
-
3644
-    public function attendee_editor_metaboxes()
3645
-    {
3646
-        $this->verify_cpt_object();
3647
-        remove_meta_box(
3648
-            'postexcerpt',
3649
-            esc_html__('Excerpt', 'event_espresso'),
3650
-            'post_excerpt_meta_box',
3651
-            $this->_cpt_routes[ $this->_req_action ],
3652
-            'normal',
3653
-            'core'
3654
-        );
3655
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3656
-        if (post_type_supports('espresso_attendees', 'excerpt')) {
3657
-            add_meta_box(
3658
-                'postexcerpt',
3659
-                esc_html__('Short Biography', 'event_espresso'),
3660
-                'post_excerpt_meta_box',
3661
-                $this->_cpt_routes[ $this->_req_action ],
3662
-                'normal'
3663
-            );
3664
-        }
3665
-        if (post_type_supports('espresso_attendees', 'comments')) {
3666
-            add_meta_box(
3667
-                'commentsdiv',
3668
-                esc_html__('Notes on the Contact', 'event_espresso'),
3669
-                'post_comment_meta_box',
3670
-                $this->_cpt_routes[ $this->_req_action ],
3671
-                'normal',
3672
-                'core'
3673
-            );
3674
-        }
3675
-        add_meta_box(
3676
-            'attendee_contact_info',
3677
-            esc_html__('Contact Info', 'event_espresso'),
3678
-            array($this, 'attendee_contact_info'),
3679
-            $this->_cpt_routes[ $this->_req_action ],
3680
-            'side',
3681
-            'core'
3682
-        );
3683
-        add_meta_box(
3684
-            'attendee_details_address',
3685
-            esc_html__('Address Details', 'event_espresso'),
3686
-            array($this, 'attendee_address_details'),
3687
-            $this->_cpt_routes[ $this->_req_action ],
3688
-            'normal',
3689
-            'core'
3690
-        );
3691
-        add_meta_box(
3692
-            'attendee_registrations',
3693
-            esc_html__('Registrations for this Contact', 'event_espresso'),
3694
-            array($this, 'attendee_registrations_meta_box'),
3695
-            $this->_cpt_routes[ $this->_req_action ],
3696
-            'normal',
3697
-            'high'
3698
-        );
3699
-    }
3700
-
3701
-
3702
-    /**
3703
-     * Metabox for attendee contact info
3704
-     *
3705
-     * @param  WP_Post $post wp post object
3706
-     * @return string attendee contact info ( and form )
3707
-     * @throws EE_Error
3708
-     * @throws InvalidArgumentException
3709
-     * @throws InvalidDataTypeException
3710
-     * @throws InvalidInterfaceException
3711
-     * @throws LogicException
3712
-     * @throws DomainException
3713
-     */
3714
-    public function attendee_contact_info($post)
3715
-    {
3716
-        // get attendee object ( should already have it )
3717
-        $form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3718
-        $form->enqueueStylesAndScripts();
3719
-        echo $form->display();
3720
-    }
3721
-
3722
-
3723
-    /**
3724
-     * Return form handler for the contact details metabox
3725
-     *
3726
-     * @param EE_Attendee $attendee
3727
-     * @return AttendeeContactDetailsMetaboxFormHandler
3728
-     * @throws DomainException
3729
-     * @throws InvalidArgumentException
3730
-     * @throws InvalidDataTypeException
3731
-     * @throws InvalidInterfaceException
3732
-     */
3733
-    protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3734
-    {
3735
-        return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3736
-    }
3737
-
3738
-
3739
-    /**
3740
-     * Metabox for attendee details
3741
-     *
3742
-     * @param  WP_Post $post wp post object
3743
-     * @throws DomainException
3744
-     */
3745
-    public function attendee_address_details($post)
3746
-    {
3747
-        // get attendee object (should already have it)
3748
-        $this->_template_args['attendee'] = $this->_cpt_model_obj;
3749
-        $this->_template_args['state_html'] = EEH_Form_Fields::generate_form_input(
3750
-            new EE_Question_Form_Input(
3751
-                EE_Question::new_instance(
3752
-                    array(
3753
-                        'QST_ID'           => 0,
3754
-                        'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3755
-                        'QST_system'       => 'admin-state',
3756
-                    )
3757
-                ),
3758
-                EE_Answer::new_instance(
3759
-                    array(
3760
-                        'ANS_ID'    => 0,
3761
-                        'ANS_value' => $this->_cpt_model_obj->state_ID(),
3762
-                    )
3763
-                ),
3764
-                array(
3765
-                    'input_id'       => 'STA_ID',
3766
-                    'input_name'     => 'STA_ID',
3767
-                    'input_prefix'   => '',
3768
-                    'append_qstn_id' => false,
3769
-                )
3770
-            )
3771
-        );
3772
-        $this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3773
-            new EE_Question_Form_Input(
3774
-                EE_Question::new_instance(
3775
-                    array(
3776
-                        'QST_ID'           => 0,
3777
-                        'QST_display_text' => esc_html__('Country', 'event_espresso'),
3778
-                        'QST_system'       => 'admin-country',
3779
-                    )
3780
-                ),
3781
-                EE_Answer::new_instance(
3782
-                    array(
3783
-                        'ANS_ID'    => 0,
3784
-                        'ANS_value' => $this->_cpt_model_obj->country_ID(),
3785
-                    )
3786
-                ),
3787
-                array(
3788
-                    'input_id'       => 'CNT_ISO',
3789
-                    'input_name'     => 'CNT_ISO',
3790
-                    'input_prefix'   => '',
3791
-                    'append_qstn_id' => false,
3792
-                )
3793
-            )
3794
-        );
3795
-        $template =
3796
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3797
-        EEH_Template::display_template($template, $this->_template_args);
3798
-    }
3799
-
3800
-
3801
-    /**
3802
-     *        _attendee_details
3803
-     *
3804
-     * @access protected
3805
-     * @param $post
3806
-     * @return void
3807
-     * @throws DomainException
3808
-     * @throws EE_Error
3809
-     */
3810
-    public function attendee_registrations_meta_box($post)
3811
-    {
3812
-        $this->_template_args['attendee'] = $this->_cpt_model_obj;
3813
-        $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3814
-        $template =
3815
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3816
-        EEH_Template::display_template($template, $this->_template_args);
3817
-    }
3818
-
3819
-
3820
-    /**
3821
-     * add in the form fields for the attendee edit
3822
-     *
3823
-     * @param  WP_Post $post wp post object
3824
-     * @return string html for new form.
3825
-     * @throws DomainException
3826
-     */
3827
-    public function after_title_form_fields($post)
3828
-    {
3829
-        if ($post->post_type == 'espresso_attendees') {
3830
-            $template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3831
-            $template_args['attendee'] = $this->_cpt_model_obj;
3832
-            EEH_Template::display_template($template, $template_args);
3833
-        }
3834
-    }
3835
-
3836
-
3837
-    /**
3838
-     *        _trash_or_restore_attendee
3839
-     *
3840
-     * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3841
-     * @return void
3842
-     * @throws EE_Error
3843
-     * @throws InvalidArgumentException
3844
-     * @throws InvalidDataTypeException
3845
-     * @throws InvalidInterfaceException
3846
-     * @access protected
3847
-     */
3848
-    protected function _trash_or_restore_attendees($trash = true)
3849
-    {
3850
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3851
-        $ATT_MDL = EEM_Attendee::instance();
3852
-        $success = 1;
3853
-        // Checkboxes
3854
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3855
-            // if array has more than one element than success message should be plural
3856
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3857
-            // cycle thru checkboxes
3858
-            while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3859
-                $updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3860
-                    : $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3861
-                if (! $updated) {
3862
-                    $success = 0;
3863
-                }
3864
-            }
3865
-        } else {
3866
-            // grab single id and delete
3867
-            $ATT_ID = absint($this->_req_data['ATT_ID']);
3868
-            // get attendee
3869
-            $att = $ATT_MDL->get_one_by_ID($ATT_ID);
3870
-            $updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3871
-            $updated = $att->save();
3872
-            if (! $updated) {
3873
-                $success = 0;
3874
-            }
3875
-        }
3876
-        $what = $success > 1
3877
-            ? esc_html__('Contacts', 'event_espresso')
3878
-            : esc_html__('Contact', 'event_espresso');
3879
-        $action_desc = $trash
3880
-            ? esc_html__('moved to the trash', 'event_espresso')
3881
-            : esc_html__('restored', 'event_espresso');
3882
-        $this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3883
-    }
3033
+		}
3034
+		$template_args = array(
3035
+			'title'                    => '',
3036
+			'content'                  => '',
3037
+			'step_button_text'         => '',
3038
+			'show_notification_toggle' => false,
3039
+		);
3040
+		// to indicate we're processing a new registration
3041
+		$hidden_fields = array(
3042
+			'processing_registration' => array(
3043
+				'type'  => 'hidden',
3044
+				'value' => 0,
3045
+			),
3046
+			'event_id'                => array(
3047
+				'type'  => 'hidden',
3048
+				'value' => $this->_reg_event->ID(),
3049
+			),
3050
+		);
3051
+		// if the cart is empty then we know we're at step one so we'll display ticket selector
3052
+		$cart = EE_Registry::instance()->SSN->cart();
3053
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3054
+		switch ($step) {
3055
+			case 'ticket':
3056
+				$hidden_fields['processing_registration']['value'] = 1;
3057
+				$template_args['title'] = esc_html__(
3058
+					'Step One: Select the Ticket for this registration',
3059
+					'event_espresso'
3060
+				);
3061
+				$template_args['content'] =
3062
+					EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
3063
+				$template_args['step_button_text'] = esc_html__(
3064
+					'Add Tickets and Continue to Registrant Details',
3065
+					'event_espresso'
3066
+				);
3067
+				$template_args['show_notification_toggle'] = false;
3068
+				break;
3069
+			case 'questions':
3070
+				$hidden_fields['processing_registration']['value'] = 2;
3071
+				$template_args['title'] = esc_html__(
3072
+					'Step Two: Add Registrant Details for this Registration',
3073
+					'event_espresso'
3074
+				);
3075
+				// in theory we should be able to run EED_SPCO at this point because the cart should have been setup
3076
+				// properly by the first process_reg_step run.
3077
+				$template_args['content'] =
3078
+					EED_Single_Page_Checkout::registration_checkout_for_admin();
3079
+				$template_args['step_button_text'] = esc_html__(
3080
+					'Save Registration and Continue to Details',
3081
+					'event_espresso'
3082
+				);
3083
+				$template_args['show_notification_toggle'] = true;
3084
+				break;
3085
+		}
3086
+		// we come back to the process_registration_step route.
3087
+		$this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3088
+		return EEH_Template::display_template(
3089
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3090
+			$template_args,
3091
+			true
3092
+		);
3093
+	}
3094
+
3095
+
3096
+	/**
3097
+	 *        set_reg_event
3098
+	 *
3099
+	 * @access private
3100
+	 * @return bool
3101
+	 * @throws EE_Error
3102
+	 * @throws InvalidArgumentException
3103
+	 * @throws InvalidDataTypeException
3104
+	 * @throws InvalidInterfaceException
3105
+	 */
3106
+	private function _set_reg_event()
3107
+	{
3108
+		if (is_object($this->_reg_event)) {
3109
+			return true;
3110
+		}
3111
+		$EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3112
+		if (! $EVT_ID) {
3113
+			return false;
3114
+		}
3115
+		$this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
3116
+		return true;
3117
+	}
3118
+
3119
+
3120
+	/**
3121
+	 * process_reg_step
3122
+	 *
3123
+	 * @access        public
3124
+	 * @return string
3125
+	 * @throws DomainException
3126
+	 * @throws EE_Error
3127
+	 * @throws InvalidArgumentException
3128
+	 * @throws InvalidDataTypeException
3129
+	 * @throws InvalidInterfaceException
3130
+	 * @throws ReflectionException
3131
+	 * @throws RuntimeException
3132
+	 */
3133
+	public function process_reg_step()
3134
+	{
3135
+		EE_System::do_not_cache();
3136
+		$this->_set_reg_event();
3137
+		EE_Registry::instance()->REQ->set_espresso_page(true);
3138
+		EE_Registry::instance()->REQ->set('uts', time());
3139
+		// what step are we on?
3140
+		$cart = EE_Registry::instance()->SSN->cart();
3141
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3142
+		// if doing ajax then we need to verify the nonce
3143
+		if (defined('DOING_AJAX')) {
3144
+			$nonce = isset($this->_req_data[ $this->_req_nonce ])
3145
+				? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3146
+			$this->_verify_nonce($nonce, $this->_req_nonce);
3147
+		}
3148
+		switch ($step) {
3149
+			case 'ticket':
3150
+				// process ticket selection
3151
+				$success = EED_Ticket_Selector::instance()->process_ticket_selections();
3152
+				if ($success) {
3153
+					EE_Error::add_success(
3154
+						esc_html__(
3155
+							'Tickets Selected. Now complete the registration.',
3156
+							'event_espresso'
3157
+						)
3158
+					);
3159
+				} else {
3160
+					$query_args['step_error'] = $this->_req_data['step_error'] = true;
3161
+				}
3162
+				if (defined('DOING_AJAX')) {
3163
+					$this->new_registration(); // display next step
3164
+				} else {
3165
+					$query_args = array(
3166
+						'action'                  => 'new_registration',
3167
+						'processing_registration' => 1,
3168
+						'event_id'                => $this->_reg_event->ID(),
3169
+						'uts'                     => time(),
3170
+					);
3171
+					$this->_redirect_after_action(
3172
+						false,
3173
+						'',
3174
+						'',
3175
+						$query_args,
3176
+						true
3177
+					);
3178
+				}
3179
+				break;
3180
+			case 'questions':
3181
+				if (! isset(
3182
+					$this->_req_data['txn_reg_status_change'],
3183
+					$this->_req_data['txn_reg_status_change']['send_notifications']
3184
+				)
3185
+				) {
3186
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3187
+				}
3188
+				// process registration
3189
+				$transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3190
+				if ($cart instanceof EE_Cart) {
3191
+					$grand_total = $cart->get_cart_grand_total();
3192
+					if ($grand_total instanceof EE_Line_Item) {
3193
+						$grand_total->save_this_and_descendants_to_txn();
3194
+					}
3195
+				}
3196
+				if (! $transaction instanceof EE_Transaction) {
3197
+					$query_args = array(
3198
+						'action'                  => 'new_registration',
3199
+						'processing_registration' => 2,
3200
+						'event_id'                => $this->_reg_event->ID(),
3201
+						'uts'                     => time(),
3202
+					);
3203
+					if (defined('DOING_AJAX')) {
3204
+						// display registration form again because there are errors (maybe validation?)
3205
+						$this->new_registration();
3206
+						return;
3207
+					} else {
3208
+						$this->_redirect_after_action(
3209
+							false,
3210
+							'',
3211
+							'',
3212
+							$query_args,
3213
+							true
3214
+						);
3215
+						return;
3216
+					}
3217
+				}
3218
+				// maybe update status, and make sure to save transaction if not done already
3219
+				if (! $transaction->update_status_based_on_total_paid()) {
3220
+					$transaction->save();
3221
+				}
3222
+				EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3223
+				$this->_req_data = array();
3224
+				$query_args = array(
3225
+					'action'        => 'redirect_to_txn',
3226
+					'TXN_ID'        => $transaction->ID(),
3227
+					'EVT_ID'        => $this->_reg_event->ID(),
3228
+					'event_name'    => urlencode($this->_reg_event->name()),
3229
+					'redirect_from' => 'new_registration',
3230
+				);
3231
+				$this->_redirect_after_action(false, '', '', $query_args, true);
3232
+				break;
3233
+		}
3234
+		// what are you looking here for?  Should be nothing to do at this point.
3235
+	}
3236
+
3237
+
3238
+	/**
3239
+	 * redirect_to_txn
3240
+	 *
3241
+	 * @access public
3242
+	 * @return void
3243
+	 * @throws EE_Error
3244
+	 * @throws InvalidArgumentException
3245
+	 * @throws InvalidDataTypeException
3246
+	 * @throws InvalidInterfaceException
3247
+	 */
3248
+	public function redirect_to_txn()
3249
+	{
3250
+		EE_System::do_not_cache();
3251
+		EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3252
+		$query_args = array(
3253
+			'action' => 'view_transaction',
3254
+			'TXN_ID' => isset($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : 0,
3255
+			'page'   => 'espresso_transactions',
3256
+		);
3257
+		if (isset($this->_req_data['EVT_ID'], $this->_req_data['redirect_from'])) {
3258
+			$query_args['EVT_ID'] = $this->_req_data['EVT_ID'];
3259
+			$query_args['event_name'] = urlencode($this->_req_data['event_name']);
3260
+			$query_args['redirect_from'] = $this->_req_data['redirect_from'];
3261
+		}
3262
+		EE_Error::add_success(
3263
+			esc_html__(
3264
+				'Registration Created.  Please review the transaction and add any payments as necessary',
3265
+				'event_espresso'
3266
+			)
3267
+		);
3268
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3269
+	}
3270
+
3271
+
3272
+	/**
3273
+	 *        generates HTML for the Attendee Contact List
3274
+	 *
3275
+	 * @access protected
3276
+	 * @return void
3277
+	 */
3278
+	protected function _attendee_contact_list_table()
3279
+	{
3280
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3281
+		$this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3282
+		$this->display_admin_list_table_page_with_no_sidebar();
3283
+	}
3284
+
3285
+
3286
+	/**
3287
+	 *        get_attendees
3288
+	 *
3289
+	 * @param      $per_page
3290
+	 * @param bool $count whether to return count or data.
3291
+	 * @param bool $trash
3292
+	 * @return array
3293
+	 * @throws EE_Error
3294
+	 * @throws InvalidArgumentException
3295
+	 * @throws InvalidDataTypeException
3296
+	 * @throws InvalidInterfaceException
3297
+	 * @access public
3298
+	 */
3299
+	public function get_attendees($per_page, $count = false, $trash = false)
3300
+	{
3301
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3302
+		require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3303
+		$ATT_MDL = EEM_Attendee::instance();
3304
+		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3305
+		switch ($this->_req_data['orderby']) {
3306
+			case 'ATT_ID':
3307
+				$orderby = 'ATT_ID';
3308
+				break;
3309
+			case 'ATT_fname':
3310
+				$orderby = 'ATT_fname';
3311
+				break;
3312
+			case 'ATT_email':
3313
+				$orderby = 'ATT_email';
3314
+				break;
3315
+			case 'ATT_city':
3316
+				$orderby = 'ATT_city';
3317
+				break;
3318
+			case 'STA_ID':
3319
+				$orderby = 'STA_ID';
3320
+				break;
3321
+			case 'CNT_ID':
3322
+				$orderby = 'CNT_ID';
3323
+				break;
3324
+			case 'Registration_Count':
3325
+				$orderby = 'Registration_Count';
3326
+				break;
3327
+			default:
3328
+				$orderby = 'ATT_lname';
3329
+		}
3330
+		$sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
3331
+			? $this->_req_data['order']
3332
+			: 'ASC';
3333
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
3334
+			? $this->_req_data['paged']
3335
+			: 1;
3336
+		$per_page = isset($per_page) && ! empty($per_page) ? $per_page : 10;
3337
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
3338
+			? $this->_req_data['perpage']
3339
+			: $per_page;
3340
+		$_where = array();
3341
+		if (! empty($this->_req_data['s'])) {
3342
+			$sstr = '%' . $this->_req_data['s'] . '%';
3343
+			$_where['OR'] = array(
3344
+				'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3345
+				'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
3346
+				'Registration.Event.EVT_short_desc' => array('LIKE', $sstr),
3347
+				'ATT_fname'                         => array('LIKE', $sstr),
3348
+				'ATT_lname'                         => array('LIKE', $sstr),
3349
+				'ATT_short_bio'                     => array('LIKE', $sstr),
3350
+				'ATT_email'                         => array('LIKE', $sstr),
3351
+				'ATT_address'                       => array('LIKE', $sstr),
3352
+				'ATT_address2'                      => array('LIKE', $sstr),
3353
+				'ATT_city'                          => array('LIKE', $sstr),
3354
+				'Country.CNT_name'                  => array('LIKE', $sstr),
3355
+				'State.STA_name'                    => array('LIKE', $sstr),
3356
+				'ATT_phone'                         => array('LIKE', $sstr),
3357
+				'Registration.REG_final_price'      => array('LIKE', $sstr),
3358
+				'Registration.REG_code'             => array('LIKE', $sstr),
3359
+				'Registration.REG_group_size'       => array('LIKE', $sstr),
3360
+			);
3361
+		}
3362
+		$offset = ($current_page - 1) * $per_page;
3363
+		$limit = $count ? null : array($offset, $per_page);
3364
+		$query_args = array(
3365
+			$_where,
3366
+			'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3367
+			'limit'         => $limit,
3368
+		);
3369
+		if (! $count) {
3370
+			$query_args['order_by'] = array($orderby => $sort);
3371
+		}
3372
+		if ($trash) {
3373
+			$query_args[0]['status'] = array('!=', 'publish');
3374
+			$all_attendees = $count
3375
+				? $ATT_MDL->count($query_args, 'ATT_ID', true)
3376
+				: $ATT_MDL->get_all($query_args);
3377
+		} else {
3378
+			$query_args[0]['status'] = array('IN', array('publish'));
3379
+			$all_attendees = $count
3380
+				? $ATT_MDL->count($query_args, 'ATT_ID', true)
3381
+				: $ATT_MDL->get_all($query_args);
3382
+		}
3383
+		return $all_attendees;
3384
+	}
3385
+
3386
+
3387
+	/**
3388
+	 * This is just taking care of resending the registration confirmation
3389
+	 *
3390
+	 * @access protected
3391
+	 * @return void
3392
+	 */
3393
+	protected function _resend_registration()
3394
+	{
3395
+		$this->_process_resend_registration();
3396
+		$query_args = isset($this->_req_data['redirect_to'])
3397
+			? array('action' => $this->_req_data['redirect_to'], '_REG_ID' => $this->_req_data['_REG_ID'])
3398
+			: array('action' => 'default');
3399
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3400
+	}
3401
+
3402
+	/**
3403
+	 * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3404
+	 * to use when selecting registrations
3405
+	 *
3406
+	 * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3407
+	 *                                                     the query parameters from the request
3408
+	 * @return void ends the request with a redirect or download
3409
+	 */
3410
+	public function _registrations_report_base($method_name_for_getting_query_params)
3411
+	{
3412
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3413
+			wp_redirect(
3414
+				EE_Admin_Page::add_query_args_and_nonce(
3415
+					array(
3416
+						'page'        => 'espresso_batch',
3417
+						'batch'       => 'file',
3418
+						'EVT_ID'      => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3419
+						'filters'     => urlencode(
3420
+							serialize(
3421
+								call_user_func(
3422
+									array($this, $method_name_for_getting_query_params),
3423
+									EEH_Array::is_set(
3424
+										$this->_req_data,
3425
+										'filters',
3426
+										array()
3427
+									)
3428
+								)
3429
+							)
3430
+						),
3431
+						'use_filters' => EEH_Array::is_set($this->_req_data, 'use_filters', false),
3432
+						'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3433
+						'return_url'  => urlencode($this->_req_data['return_url']),
3434
+					)
3435
+				)
3436
+			);
3437
+		} else {
3438
+			$new_request_args = array(
3439
+				'export' => 'report',
3440
+				'action' => 'registrations_report_for_event',
3441
+				'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3442
+			);
3443
+			$this->_req_data = array_merge($this->_req_data, $new_request_args);
3444
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3445
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3446
+				$EE_Export = EE_Export::instance($this->_req_data);
3447
+				$EE_Export->export();
3448
+			}
3449
+		}
3450
+	}
3451
+
3452
+
3453
+	/**
3454
+	 * Creates a registration report using only query parameters in the request
3455
+	 *
3456
+	 * @return void
3457
+	 */
3458
+	public function _registrations_report()
3459
+	{
3460
+		$this->_registrations_report_base('_get_registration_query_parameters');
3461
+	}
3462
+
3463
+
3464
+	public function _contact_list_export()
3465
+	{
3466
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3467
+			require_once(EE_CLASSES . 'EE_Export.class.php');
3468
+			$EE_Export = EE_Export::instance($this->_req_data);
3469
+			$EE_Export->export_attendees();
3470
+		}
3471
+	}
3472
+
3473
+
3474
+	public function _contact_list_report()
3475
+	{
3476
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3477
+			wp_redirect(
3478
+				EE_Admin_Page::add_query_args_and_nonce(
3479
+					array(
3480
+						'page'        => 'espresso_batch',
3481
+						'batch'       => 'file',
3482
+						'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3483
+						'return_url'  => urlencode($this->_req_data['return_url']),
3484
+					)
3485
+				)
3486
+			);
3487
+		} else {
3488
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3489
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3490
+				$EE_Export = EE_Export::instance($this->_req_data);
3491
+				$EE_Export->report_attendees();
3492
+			}
3493
+		}
3494
+	}
3495
+
3496
+
3497
+
3498
+
3499
+
3500
+	/***************************************        ATTENDEE DETAILS        ***************************************/
3501
+	/**
3502
+	 * This duplicates the attendee object for the given incoming registration id and attendee_id.
3503
+	 *
3504
+	 * @return void
3505
+	 * @throws EE_Error
3506
+	 * @throws InvalidArgumentException
3507
+	 * @throws InvalidDataTypeException
3508
+	 * @throws InvalidInterfaceException
3509
+	 */
3510
+	protected function _duplicate_attendee()
3511
+	{
3512
+		$action = ! empty($this->_req_data['return']) ? $this->_req_data['return'] : 'default';
3513
+		// verify we have necessary info
3514
+		if (empty($this->_req_data['_REG_ID'])) {
3515
+			EE_Error::add_error(
3516
+				esc_html__(
3517
+					'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3518
+					'event_espresso'
3519
+				),
3520
+				__FILE__,
3521
+				__LINE__,
3522
+				__FUNCTION__
3523
+			);
3524
+			$query_args = array('action' => $action);
3525
+			$this->_redirect_after_action('', '', '', $query_args, true);
3526
+		}
3527
+		// okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3528
+		$registration = EEM_Registration::instance()->get_one_by_ID($this->_req_data['_REG_ID']);
3529
+		$attendee = $registration->attendee();
3530
+		// remove relation of existing attendee on registration
3531
+		$registration->_remove_relation_to($attendee, 'Attendee');
3532
+		// new attendee
3533
+		$new_attendee = clone $attendee;
3534
+		$new_attendee->set('ATT_ID', 0);
3535
+		$new_attendee->save();
3536
+		// add new attendee to reg
3537
+		$registration->_add_relation_to($new_attendee, 'Attendee');
3538
+		EE_Error::add_success(
3539
+			esc_html__(
3540
+				'New Contact record created.  Now make any edits you wish to make for this contact.',
3541
+				'event_espresso'
3542
+			)
3543
+		);
3544
+		// redirect to edit page for attendee
3545
+		$query_args = array('post' => $new_attendee->ID(), 'action' => 'edit_attendee');
3546
+		$this->_redirect_after_action('', '', '', $query_args, true);
3547
+	}
3548
+
3549
+
3550
+	/**
3551
+	 * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3552
+	 *
3553
+	 * @param int     $post_id
3554
+	 * @param WP_POST $post
3555
+	 * @throws DomainException
3556
+	 * @throws EE_Error
3557
+	 * @throws InvalidArgumentException
3558
+	 * @throws InvalidDataTypeException
3559
+	 * @throws InvalidInterfaceException
3560
+	 * @throws LogicException
3561
+	 * @throws InvalidFormSubmissionException
3562
+	 */
3563
+	protected function _insert_update_cpt_item($post_id, $post)
3564
+	{
3565
+		$success = true;
3566
+		$attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3567
+			? EEM_Attendee::instance()->get_one_by_ID($post_id)
3568
+			: null;
3569
+		// for attendee updates
3570
+		if ($attendee instanceof EE_Attendee) {
3571
+			// note we should only be UPDATING attendees at this point.
3572
+			$updated_fields = array(
3573
+				'ATT_fname'     => $this->_req_data['ATT_fname'],
3574
+				'ATT_lname'     => $this->_req_data['ATT_lname'],
3575
+				'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3576
+				'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3577
+				'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3578
+				'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
3579
+				'STA_ID'        => isset($this->_req_data['STA_ID']) ? $this->_req_data['STA_ID'] : '',
3580
+				'CNT_ISO'       => isset($this->_req_data['CNT_ISO']) ? $this->_req_data['CNT_ISO'] : '',
3581
+				'ATT_zip'       => isset($this->_req_data['ATT_zip']) ? $this->_req_data['ATT_zip'] : '',
3582
+			);
3583
+			foreach ($updated_fields as $field => $value) {
3584
+				$attendee->set($field, $value);
3585
+			}
3586
+
3587
+			// process contact details metabox form handler (which will also save the attendee)
3588
+			$contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3589
+			$success = $contact_details_form->process($this->_req_data);
3590
+
3591
+			$attendee_update_callbacks = apply_filters(
3592
+				'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3593
+				array()
3594
+			);
3595
+			foreach ($attendee_update_callbacks as $a_callback) {
3596
+				if (false === call_user_func_array($a_callback, array($attendee, $this->_req_data))) {
3597
+					throw new EE_Error(
3598
+						sprintf(
3599
+							esc_html__(
3600
+								'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3601
+								'event_espresso'
3602
+							),
3603
+							$a_callback
3604
+						)
3605
+					);
3606
+				}
3607
+			}
3608
+		}
3609
+
3610
+		if ($success === false) {
3611
+			EE_Error::add_error(
3612
+				esc_html__(
3613
+					'Something went wrong with updating the meta table data for the registration.',
3614
+					'event_espresso'
3615
+				),
3616
+				__FILE__,
3617
+				__FUNCTION__,
3618
+				__LINE__
3619
+			);
3620
+		}
3621
+	}
3622
+
3623
+
3624
+	public function trash_cpt_item($post_id)
3625
+	{
3626
+	}
3627
+
3628
+
3629
+	public function delete_cpt_item($post_id)
3630
+	{
3631
+	}
3632
+
3633
+
3634
+	public function restore_cpt_item($post_id)
3635
+	{
3636
+	}
3637
+
3638
+
3639
+	protected function _restore_cpt_item($post_id, $revision_id)
3640
+	{
3641
+	}
3642
+
3643
+
3644
+	public function attendee_editor_metaboxes()
3645
+	{
3646
+		$this->verify_cpt_object();
3647
+		remove_meta_box(
3648
+			'postexcerpt',
3649
+			esc_html__('Excerpt', 'event_espresso'),
3650
+			'post_excerpt_meta_box',
3651
+			$this->_cpt_routes[ $this->_req_action ],
3652
+			'normal',
3653
+			'core'
3654
+		);
3655
+		remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3656
+		if (post_type_supports('espresso_attendees', 'excerpt')) {
3657
+			add_meta_box(
3658
+				'postexcerpt',
3659
+				esc_html__('Short Biography', 'event_espresso'),
3660
+				'post_excerpt_meta_box',
3661
+				$this->_cpt_routes[ $this->_req_action ],
3662
+				'normal'
3663
+			);
3664
+		}
3665
+		if (post_type_supports('espresso_attendees', 'comments')) {
3666
+			add_meta_box(
3667
+				'commentsdiv',
3668
+				esc_html__('Notes on the Contact', 'event_espresso'),
3669
+				'post_comment_meta_box',
3670
+				$this->_cpt_routes[ $this->_req_action ],
3671
+				'normal',
3672
+				'core'
3673
+			);
3674
+		}
3675
+		add_meta_box(
3676
+			'attendee_contact_info',
3677
+			esc_html__('Contact Info', 'event_espresso'),
3678
+			array($this, 'attendee_contact_info'),
3679
+			$this->_cpt_routes[ $this->_req_action ],
3680
+			'side',
3681
+			'core'
3682
+		);
3683
+		add_meta_box(
3684
+			'attendee_details_address',
3685
+			esc_html__('Address Details', 'event_espresso'),
3686
+			array($this, 'attendee_address_details'),
3687
+			$this->_cpt_routes[ $this->_req_action ],
3688
+			'normal',
3689
+			'core'
3690
+		);
3691
+		add_meta_box(
3692
+			'attendee_registrations',
3693
+			esc_html__('Registrations for this Contact', 'event_espresso'),
3694
+			array($this, 'attendee_registrations_meta_box'),
3695
+			$this->_cpt_routes[ $this->_req_action ],
3696
+			'normal',
3697
+			'high'
3698
+		);
3699
+	}
3700
+
3701
+
3702
+	/**
3703
+	 * Metabox for attendee contact info
3704
+	 *
3705
+	 * @param  WP_Post $post wp post object
3706
+	 * @return string attendee contact info ( and form )
3707
+	 * @throws EE_Error
3708
+	 * @throws InvalidArgumentException
3709
+	 * @throws InvalidDataTypeException
3710
+	 * @throws InvalidInterfaceException
3711
+	 * @throws LogicException
3712
+	 * @throws DomainException
3713
+	 */
3714
+	public function attendee_contact_info($post)
3715
+	{
3716
+		// get attendee object ( should already have it )
3717
+		$form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3718
+		$form->enqueueStylesAndScripts();
3719
+		echo $form->display();
3720
+	}
3721
+
3722
+
3723
+	/**
3724
+	 * Return form handler for the contact details metabox
3725
+	 *
3726
+	 * @param EE_Attendee $attendee
3727
+	 * @return AttendeeContactDetailsMetaboxFormHandler
3728
+	 * @throws DomainException
3729
+	 * @throws InvalidArgumentException
3730
+	 * @throws InvalidDataTypeException
3731
+	 * @throws InvalidInterfaceException
3732
+	 */
3733
+	protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3734
+	{
3735
+		return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3736
+	}
3737
+
3738
+
3739
+	/**
3740
+	 * Metabox for attendee details
3741
+	 *
3742
+	 * @param  WP_Post $post wp post object
3743
+	 * @throws DomainException
3744
+	 */
3745
+	public function attendee_address_details($post)
3746
+	{
3747
+		// get attendee object (should already have it)
3748
+		$this->_template_args['attendee'] = $this->_cpt_model_obj;
3749
+		$this->_template_args['state_html'] = EEH_Form_Fields::generate_form_input(
3750
+			new EE_Question_Form_Input(
3751
+				EE_Question::new_instance(
3752
+					array(
3753
+						'QST_ID'           => 0,
3754
+						'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3755
+						'QST_system'       => 'admin-state',
3756
+					)
3757
+				),
3758
+				EE_Answer::new_instance(
3759
+					array(
3760
+						'ANS_ID'    => 0,
3761
+						'ANS_value' => $this->_cpt_model_obj->state_ID(),
3762
+					)
3763
+				),
3764
+				array(
3765
+					'input_id'       => 'STA_ID',
3766
+					'input_name'     => 'STA_ID',
3767
+					'input_prefix'   => '',
3768
+					'append_qstn_id' => false,
3769
+				)
3770
+			)
3771
+		);
3772
+		$this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3773
+			new EE_Question_Form_Input(
3774
+				EE_Question::new_instance(
3775
+					array(
3776
+						'QST_ID'           => 0,
3777
+						'QST_display_text' => esc_html__('Country', 'event_espresso'),
3778
+						'QST_system'       => 'admin-country',
3779
+					)
3780
+				),
3781
+				EE_Answer::new_instance(
3782
+					array(
3783
+						'ANS_ID'    => 0,
3784
+						'ANS_value' => $this->_cpt_model_obj->country_ID(),
3785
+					)
3786
+				),
3787
+				array(
3788
+					'input_id'       => 'CNT_ISO',
3789
+					'input_name'     => 'CNT_ISO',
3790
+					'input_prefix'   => '',
3791
+					'append_qstn_id' => false,
3792
+				)
3793
+			)
3794
+		);
3795
+		$template =
3796
+			REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3797
+		EEH_Template::display_template($template, $this->_template_args);
3798
+	}
3799
+
3800
+
3801
+	/**
3802
+	 *        _attendee_details
3803
+	 *
3804
+	 * @access protected
3805
+	 * @param $post
3806
+	 * @return void
3807
+	 * @throws DomainException
3808
+	 * @throws EE_Error
3809
+	 */
3810
+	public function attendee_registrations_meta_box($post)
3811
+	{
3812
+		$this->_template_args['attendee'] = $this->_cpt_model_obj;
3813
+		$this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3814
+		$template =
3815
+			REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3816
+		EEH_Template::display_template($template, $this->_template_args);
3817
+	}
3818
+
3819
+
3820
+	/**
3821
+	 * add in the form fields for the attendee edit
3822
+	 *
3823
+	 * @param  WP_Post $post wp post object
3824
+	 * @return string html for new form.
3825
+	 * @throws DomainException
3826
+	 */
3827
+	public function after_title_form_fields($post)
3828
+	{
3829
+		if ($post->post_type == 'espresso_attendees') {
3830
+			$template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3831
+			$template_args['attendee'] = $this->_cpt_model_obj;
3832
+			EEH_Template::display_template($template, $template_args);
3833
+		}
3834
+	}
3835
+
3836
+
3837
+	/**
3838
+	 *        _trash_or_restore_attendee
3839
+	 *
3840
+	 * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3841
+	 * @return void
3842
+	 * @throws EE_Error
3843
+	 * @throws InvalidArgumentException
3844
+	 * @throws InvalidDataTypeException
3845
+	 * @throws InvalidInterfaceException
3846
+	 * @access protected
3847
+	 */
3848
+	protected function _trash_or_restore_attendees($trash = true)
3849
+	{
3850
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3851
+		$ATT_MDL = EEM_Attendee::instance();
3852
+		$success = 1;
3853
+		// Checkboxes
3854
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3855
+			// if array has more than one element than success message should be plural
3856
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3857
+			// cycle thru checkboxes
3858
+			while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3859
+				$updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3860
+					: $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3861
+				if (! $updated) {
3862
+					$success = 0;
3863
+				}
3864
+			}
3865
+		} else {
3866
+			// grab single id and delete
3867
+			$ATT_ID = absint($this->_req_data['ATT_ID']);
3868
+			// get attendee
3869
+			$att = $ATT_MDL->get_one_by_ID($ATT_ID);
3870
+			$updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3871
+			$updated = $att->save();
3872
+			if (! $updated) {
3873
+				$success = 0;
3874
+			}
3875
+		}
3876
+		$what = $success > 1
3877
+			? esc_html__('Contacts', 'event_espresso')
3878
+			: esc_html__('Contact', 'event_espresso');
3879
+		$action_desc = $trash
3880
+			? esc_html__('moved to the trash', 'event_espresso')
3881
+			: esc_html__('restored', 'event_espresso');
3882
+		$this->_redirect_after_action($success, $what, $action_desc, array('action' => 'contact_list'));
3883
+	}
3884 3884
 }
Please login to merge, or discard this patch.
Spacing   +109 added lines, -109 removed lines patch added patch discarded remove patch
@@ -65,7 +65,7 @@  discard block
 block discarded – undo
65 65
         // when adding a new registration...
66 66
         if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'new_registration') {
67 67
             EE_System::do_not_cache();
68
-            if (! isset($this->_req_data['processing_registration'])
68
+            if ( ! isset($this->_req_data['processing_registration'])
69 69
                 || absint($this->_req_data['processing_registration']) !== 1
70 70
             ) {
71 71
                 // and it's NOT the attendee information reg step
@@ -658,7 +658,7 @@  discard block
 block discarded – undo
658 658
         // style
659 659
         wp_register_style(
660 660
             'espresso_reg',
661
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
661
+            REG_ASSETS_URL.'espresso_registrations_admin.css',
662 662
             array('ee-admin-css'),
663 663
             EVENT_ESPRESSO_VERSION
664 664
         );
@@ -666,7 +666,7 @@  discard block
 block discarded – undo
666 666
         // script
667 667
         wp_register_script(
668 668
             'espresso_reg',
669
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
669
+            REG_ASSETS_URL.'espresso_registrations_admin.js',
670 670
             array('jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'),
671 671
             EVENT_ESPRESSO_VERSION,
672 672
             true
@@ -704,7 +704,7 @@  discard block
 block discarded – undo
704 704
         wp_dequeue_style('espresso_reg');
705 705
         wp_register_style(
706 706
             'espresso_att',
707
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
707
+            REG_ASSETS_URL.'espresso_attendees_admin.css',
708 708
             array('ee-admin-css'),
709 709
             EVENT_ESPRESSO_VERSION
710 710
         );
@@ -716,7 +716,7 @@  discard block
 block discarded – undo
716 716
     {
717 717
         wp_register_script(
718 718
             'ee-spco-for-admin',
719
-            REG_ASSETS_URL . 'spco_for_admin.js',
719
+            REG_ASSETS_URL.'spco_for_admin.js',
720 720
             array('underscore', 'jquery'),
721 721
             EVENT_ESPRESSO_VERSION,
722 722
             true
@@ -950,7 +950,7 @@  discard block
 block discarded – undo
950 950
         }
951 951
         $sc_items = array(
952 952
             'approved_status'   => array(
953
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved,
953
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_approved,
954 954
                 'desc'  => EEH_Template::pretty_status(
955 955
                     EEM_Registration::status_id_approved,
956 956
                     false,
@@ -958,7 +958,7 @@  discard block
 block discarded – undo
958 958
                 ),
959 959
             ),
960 960
             'pending_status'    => array(
961
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment,
961
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_pending_payment,
962 962
                 'desc'  => EEH_Template::pretty_status(
963 963
                     EEM_Registration::status_id_pending_payment,
964 964
                     false,
@@ -966,7 +966,7 @@  discard block
 block discarded – undo
966 966
                 ),
967 967
             ),
968 968
             'wait_list'         => array(
969
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list,
969
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_wait_list,
970 970
                 'desc'  => EEH_Template::pretty_status(
971 971
                     EEM_Registration::status_id_wait_list,
972 972
                     false,
@@ -974,7 +974,7 @@  discard block
 block discarded – undo
974 974
                 ),
975 975
             ),
976 976
             'incomplete_status' => array(
977
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_incomplete,
977
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_incomplete,
978 978
                 'desc'  => EEH_Template::pretty_status(
979 979
                     EEM_Registration::status_id_incomplete,
980 980
                     false,
@@ -982,7 +982,7 @@  discard block
 block discarded – undo
982 982
                 ),
983 983
             ),
984 984
             'not_approved'      => array(
985
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved,
985
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_not_approved,
986 986
                 'desc'  => EEH_Template::pretty_status(
987 987
                     EEM_Registration::status_id_not_approved,
988 988
                     false,
@@ -990,7 +990,7 @@  discard block
 block discarded – undo
990 990
                 ),
991 991
             ),
992 992
             'declined_status'   => array(
993
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined,
993
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_declined,
994 994
                 'desc'  => EEH_Template::pretty_status(
995 995
                     EEM_Registration::status_id_declined,
996 996
                     false,
@@ -998,7 +998,7 @@  discard block
 block discarded – undo
998 998
                 ),
999 999
             ),
1000 1000
             'cancelled_status'  => array(
1001
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled,
1001
+                'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_cancelled,
1002 1002
                 'desc'  => EEH_Template::pretty_status(
1003 1003
                     EEM_Registration::status_id_cancelled,
1004 1004
                     false,
@@ -1033,13 +1033,13 @@  discard block
 block discarded – undo
1033 1033
                         'event_espresso'
1034 1034
                     ),
1035 1035
                     '<h3 style="line-height:1.5em;">',
1036
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
1036
+                    '<a href="'.EE_Admin_Page::add_query_args_and_nonce(
1037 1037
                         array(
1038 1038
                             'action' => 'edit_attendee',
1039 1039
                             'post'   => $ATT_ID,
1040 1040
                         ),
1041 1041
                         REG_ADMIN_URL
1042
-                    ) . '">' . $attendee->full_name() . '</a>',
1042
+                    ).'">'.$attendee->full_name().'</a>',
1043 1043
                     '</h3>'
1044 1044
                 );
1045 1045
             }
@@ -1050,7 +1050,7 @@  discard block
 block discarded – undo
1050 1050
                 'espresso_registrations_new_registration',
1051 1051
                 $EVT_ID
1052 1052
             )) {
1053
-                $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1053
+                $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
1054 1054
                     'new_registration',
1055 1055
                     'add-registrant',
1056 1056
                     array('event_id' => $EVT_ID),
@@ -1090,7 +1090,7 @@  discard block
 block discarded – undo
1090 1090
                 $this->_template_args['admin_page_header'] .= ' &nbsp;<span class="drk-grey-text">';
1091 1091
                 $this->_template_args['admin_page_header'] .= '<span class="dashicons dashicons-calendar"></span>';
1092 1092
                 $this->_template_args['admin_page_header'] .= $datetime->name();
1093
-                $this->_template_args['admin_page_header'] .= ' ( ' . $datetime->start_date() . ' )';
1093
+                $this->_template_args['admin_page_header'] .= ' ( '.$datetime->start_date().' )';
1094 1094
                 $this->_template_args['admin_page_header'] .= '</span></h3>';
1095 1095
             }
1096 1096
         }
@@ -1116,7 +1116,7 @@  discard block
 block discarded – undo
1116 1116
             return true;
1117 1117
         }
1118 1118
         $REG = EEM_Registration::instance();
1119
-        $REG_ID = (! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1119
+        $REG_ID = ( ! empty($this->_req_data['_REG_ID'])) ? absint($this->_req_data['_REG_ID']) : false;
1120 1120
         if ($this->_registration = $REG->get_one_by_ID($REG_ID)) {
1121 1121
             return true;
1122 1122
         } else {
@@ -1200,7 +1200,7 @@  discard block
 block discarded – undo
1200 1200
             'caps'                     => EEM_Registration::caps_read_admin,
1201 1201
             'default_where_conditions' => 'this_model_only',
1202 1202
         );
1203
-        if (! $count) {
1203
+        if ( ! $count) {
1204 1204
             $query_params = array_merge(
1205 1205
                 $query_params,
1206 1206
                 $this->_get_orderby_for_registrations_query(),
@@ -1221,7 +1221,7 @@  discard block
 block discarded – undo
1221 1221
     protected function addAttendeeIdToWhereConditions(array $request)
1222 1222
     {
1223 1223
         $where = array();
1224
-        if (! empty($request['ATT_ID'])) {
1224
+        if ( ! empty($request['ATT_ID'])) {
1225 1225
             $where['ATT_ID'] = absint($request['ATT_ID']);
1226 1226
         }
1227 1227
         return $where;
@@ -1237,7 +1237,7 @@  discard block
 block discarded – undo
1237 1237
     protected function _add_event_id_to_where_conditions(array $request)
1238 1238
     {
1239 1239
         $where = array();
1240
-        if (! empty($request['event_id'])) {
1240
+        if ( ! empty($request['event_id'])) {
1241 1241
             $where['EVT_ID'] = absint($request['event_id']);
1242 1242
         }
1243 1243
         return $where;
@@ -1253,7 +1253,7 @@  discard block
 block discarded – undo
1253 1253
     protected function _add_category_id_to_where_conditions(array $request)
1254 1254
     {
1255 1255
         $where = array();
1256
-        if (! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1256
+        if ( ! empty($request['EVT_CAT']) && (int) $request['EVT_CAT'] !== -1) {
1257 1257
             $where['Event.Term_Taxonomy.term_id'] = absint($request['EVT_CAT']);
1258 1258
         }
1259 1259
         return $where;
@@ -1269,10 +1269,10 @@  discard block
 block discarded – undo
1269 1269
     protected function _add_datetime_id_to_where_conditions(array $request)
1270 1270
     {
1271 1271
         $where = array();
1272
-        if (! empty($request['datetime_id'])) {
1272
+        if ( ! empty($request['datetime_id'])) {
1273 1273
             $where['Ticket.Datetime.DTT_ID'] = absint($request['datetime_id']);
1274 1274
         }
1275
-        if (! empty($request['DTT_ID'])) {
1275
+        if ( ! empty($request['DTT_ID'])) {
1276 1276
             $where['Ticket.Datetime.DTT_ID'] = absint($request['DTT_ID']);
1277 1277
         }
1278 1278
         return $where;
@@ -1298,7 +1298,7 @@  discard block
 block discarded – undo
1298 1298
          * If not filtering by specified status, then we show all registrations excluding incomplete registrations
1299 1299
          * UNLESS viewing trashed registrations.
1300 1300
          */
1301
-        if (! empty($registration_status)) {
1301
+        if ( ! empty($registration_status)) {
1302 1302
             $where['STS_ID'] = $registration_status;
1303 1303
         } else {
1304 1304
             // make sure we exclude incomplete registrations, but only if not trashed.
@@ -1341,12 +1341,12 @@  discard block
 block discarded – undo
1341 1341
                 array(
1342 1342
                     EEM_Registration::instance()->convert_datetime_for_query(
1343 1343
                         'REG_date',
1344
-                        $now . ' 00:00:00',
1344
+                        $now.' 00:00:00',
1345 1345
                         'Y-m-d H:i:s'
1346 1346
                     ),
1347 1347
                     EEM_Registration::instance()->convert_datetime_for_query(
1348 1348
                         'REG_date',
1349
-                        $now . ' 23:59:59',
1349
+                        $now.' 23:59:59',
1350 1350
                         'Y-m-d H:i:s'
1351 1351
                     ),
1352 1352
                 ),
@@ -1359,12 +1359,12 @@  discard block
 block discarded – undo
1359 1359
                 array(
1360 1360
                     EEM_Registration::instance()->convert_datetime_for_query(
1361 1361
                         'REG_date',
1362
-                        $current_year_and_month . '-01 00:00:00',
1362
+                        $current_year_and_month.'-01 00:00:00',
1363 1363
                         'Y-m-d H:i:s'
1364 1364
                     ),
1365 1365
                     EEM_Registration::instance()->convert_datetime_for_query(
1366 1366
                         'REG_date',
1367
-                        $current_year_and_month . '-' . $days_this_month . ' 23:59:59',
1367
+                        $current_year_and_month.'-'.$days_this_month.' 23:59:59',
1368 1368
                         'Y-m-d H:i:s'
1369 1369
                     ),
1370 1370
                 ),
@@ -1379,18 +1379,18 @@  discard block
 block discarded – undo
1379 1379
                 : '';
1380 1380
             // if there is not a month or year then we can't go further
1381 1381
             if ($month_requested && $year_requested) {
1382
-                $days_in_month = date('t', strtotime($year_requested . '-' . $month_requested . '-' . '01'));
1382
+                $days_in_month = date('t', strtotime($year_requested.'-'.$month_requested.'-'.'01'));
1383 1383
                 $where['REG_date'] = array(
1384 1384
                     'BETWEEN',
1385 1385
                     array(
1386 1386
                         EEM_Registration::instance()->convert_datetime_for_query(
1387 1387
                             'REG_date',
1388
-                            $year_requested . '-' . $month_requested . '-01 00:00:00',
1388
+                            $year_requested.'-'.$month_requested.'-01 00:00:00',
1389 1389
                             'Y-m-d H:i:s'
1390 1390
                         ),
1391 1391
                         EEM_Registration::instance()->convert_datetime_for_query(
1392 1392
                             'REG_date',
1393
-                            $year_requested . '-' . $month_requested . '-' . $days_in_month . ' 23:59:59',
1393
+                            $year_requested.'-'.$month_requested.'-'.$days_in_month.' 23:59:59',
1394 1394
                             'Y-m-d H:i:s'
1395 1395
                         ),
1396 1396
                     ),
@@ -1410,8 +1410,8 @@  discard block
 block discarded – undo
1410 1410
     protected function _add_search_to_where_conditions(array $request)
1411 1411
     {
1412 1412
         $where = array();
1413
-        if (! empty($request['s'])) {
1414
-            $search_string = '%' . sanitize_text_field($request['s']) . '%';
1413
+        if ( ! empty($request['s'])) {
1414
+            $search_string = '%'.sanitize_text_field($request['s']).'%';
1415 1415
             $where['OR*search_conditions'] = array(
1416 1416
                 'Event.EVT_name'                          => array('LIKE', $search_string),
1417 1417
                 'Event.EVT_desc'                          => array('LIKE', $search_string),
@@ -1647,7 +1647,7 @@  discard block
 block discarded – undo
1647 1647
                 )
1648 1648
                 : '';
1649 1649
             // grab header
1650
-            $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1650
+            $template_path = REG_TEMPLATE_PATH.'reg_admin_details_header.template.php';
1651 1651
             $this->_template_args['REG_ID'] = $this->_registration->ID();
1652 1652
             $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1653 1653
                 $template_path,
@@ -1784,7 +1784,7 @@  discard block
 block discarded – undo
1784 1784
                             EEH_HTML::strong(
1785 1785
                                 $this->_registration->pretty_status(),
1786 1786
                                 '',
1787
-                                'status-' . $this->_registration->status_ID(),
1787
+                                'status-'.$this->_registration->status_ID(),
1788 1788
                                 'line-height: 1em; font-size: 1.5em; font-weight: bold;'
1789 1789
                             )
1790 1790
                         )
@@ -1839,14 +1839,14 @@  discard block
 block discarded – undo
1839 1839
     protected function _get_reg_statuses()
1840 1840
     {
1841 1841
         $reg_status_array = EEM_Registration::instance()->reg_status_array();
1842
-        unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1842
+        unset($reg_status_array[EEM_Registration::status_id_incomplete]);
1843 1843
         // get current reg status
1844 1844
         $current_status = $this->_registration->status_ID();
1845 1845
         // is registration for free event? This will determine whether to display the pending payment option
1846 1846
         if ($current_status !== EEM_Registration::status_id_pending_payment
1847 1847
             && EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1848 1848
         ) {
1849
-            unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1849
+            unset($reg_status_array[EEM_Registration::status_id_pending_payment]);
1850 1850
         }
1851 1851
         return EEM_Status::instance()->localized_status($reg_status_array, false, 'sentence');
1852 1852
     }
@@ -1938,7 +1938,7 @@  discard block
 block discarded – undo
1938 1938
         $success = false;
1939 1939
         // typecast $REG_IDs
1940 1940
         $REG_IDs = (array) $REG_IDs;
1941
-        if (! empty($REG_IDs)) {
1941
+        if ( ! empty($REG_IDs)) {
1942 1942
             $success = true;
1943 1943
             // set default status if none is passed
1944 1944
             $status = $status ? $status : EEM_Registration::status_id_pending_payment;
@@ -2086,7 +2086,7 @@  discard block
 block discarded – undo
2086 2086
             $action,
2087 2087
             $notify
2088 2088
         );
2089
-        $method = $action . '_registration';
2089
+        $method = $action.'_registration';
2090 2090
         if (method_exists($this, $method)) {
2091 2091
             $this->$method($notify);
2092 2092
         }
@@ -2317,7 +2317,7 @@  discard block
 block discarded – undo
2317 2317
         $this->_template_args['REG_ID'] = $this->_registration->ID();
2318 2318
         $this->_template_args['event_id'] = $this->_registration->event_ID();
2319 2319
         $template_path =
2320
-            REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2320
+            REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_reg_details.template.php';
2321 2321
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2322 2322
     }
2323 2323
 
@@ -2350,7 +2350,7 @@  discard block
 block discarded – undo
2350 2350
             $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2351 2351
             $this->_template_args['REG_ID'] = $this->_registration->ID();
2352 2352
             $template_path =
2353
-                REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2353
+                REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_reg_questions.template.php';
2354 2354
             echo EEH_Template::display_template($template_path, $this->_template_args, true);
2355 2355
         }
2356 2356
     }
@@ -2367,7 +2367,7 @@  discard block
 block discarded – undo
2367 2367
     public function form_before_question_group($output)
2368 2368
     {
2369 2369
         EE_Error::doing_it_wrong(
2370
-            __CLASS__ . '::' . __FUNCTION__,
2370
+            __CLASS__.'::'.__FUNCTION__,
2371 2371
             esc_html__(
2372 2372
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2373 2373
                 'event_espresso'
@@ -2392,7 +2392,7 @@  discard block
 block discarded – undo
2392 2392
     public function form_after_question_group($output)
2393 2393
     {
2394 2394
         EE_Error::doing_it_wrong(
2395
-            __CLASS__ . '::' . __FUNCTION__,
2395
+            __CLASS__.'::'.__FUNCTION__,
2396 2396
             esc_html__(
2397 2397
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2398 2398
                 'event_espresso'
@@ -2430,7 +2430,7 @@  discard block
 block discarded – undo
2430 2430
     public function form_form_field_label_wrap($label)
2431 2431
     {
2432 2432
         EE_Error::doing_it_wrong(
2433
-            __CLASS__ . '::' . __FUNCTION__,
2433
+            __CLASS__.'::'.__FUNCTION__,
2434 2434
             esc_html__(
2435 2435
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2436 2436
                 'event_espresso'
@@ -2440,7 +2440,7 @@  discard block
 block discarded – undo
2440 2440
         return '
2441 2441
 			<tr>
2442 2442
 				<th>
2443
-					' . $label . '
2443
+					' . $label.'
2444 2444
 				</th>';
2445 2445
     }
2446 2446
 
@@ -2456,7 +2456,7 @@  discard block
 block discarded – undo
2456 2456
     public function form_form_field_input__wrap($input)
2457 2457
     {
2458 2458
         EE_Error::doing_it_wrong(
2459
-            __CLASS__ . '::' . __FUNCTION__,
2459
+            __CLASS__.'::'.__FUNCTION__,
2460 2460
             esc_html__(
2461 2461
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2462 2462
                 'event_espresso'
@@ -2465,7 +2465,7 @@  discard block
 block discarded – undo
2465 2465
         );
2466 2466
         return '
2467 2467
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2468
-					' . $input . '
2468
+					' . $input.'
2469 2469
 				</td>
2470 2470
 			</tr>';
2471 2471
     }
@@ -2509,8 +2509,8 @@  discard block
 block discarded – undo
2509 2509
      */
2510 2510
     protected function _get_reg_custom_questions_form($REG_ID)
2511 2511
     {
2512
-        if (! $this->_reg_custom_questions_form) {
2513
-            require_once(REG_ADMIN . 'form_sections' . DS . 'EE_Registration_Custom_Questions_Form.form.php');
2512
+        if ( ! $this->_reg_custom_questions_form) {
2513
+            require_once(REG_ADMIN.'form_sections'.DS.'EE_Registration_Custom_Questions_Form.form.php');
2514 2514
             $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2515 2515
                 EEM_Registration::instance()->get_one_by_ID($REG_ID)
2516 2516
             );
@@ -2533,7 +2533,7 @@  discard block
 block discarded – undo
2533 2533
      */
2534 2534
     private function _save_reg_custom_questions_form($REG_ID = false)
2535 2535
     {
2536
-        if (! $REG_ID) {
2536
+        if ( ! $REG_ID) {
2537 2537
             EE_Error::add_error(
2538 2538
                 esc_html__(
2539 2539
                     'An error occurred. No registration ID was received.',
@@ -2624,30 +2624,30 @@  discard block
 block discarded – undo
2624 2624
                     ? $registration->attendee()
2625 2625
                     : EEM_Attendee::instance()
2626 2626
                                   ->create_default_object();
2627
-                $this->_template_args['attendees'][ $att_nmbr ]['STS_ID'] = $registration->status_ID();
2628
-                $this->_template_args['attendees'][ $att_nmbr ]['fname'] = $attendee->fname();
2629
-                $this->_template_args['attendees'][ $att_nmbr ]['lname'] = $attendee->lname();
2630
-                $this->_template_args['attendees'][ $att_nmbr ]['email'] = $attendee->email();
2631
-                $this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2632
-                $this->_template_args['attendees'][ $att_nmbr ]['address'] = implode(
2627
+                $this->_template_args['attendees'][$att_nmbr]['STS_ID'] = $registration->status_ID();
2628
+                $this->_template_args['attendees'][$att_nmbr]['fname'] = $attendee->fname();
2629
+                $this->_template_args['attendees'][$att_nmbr]['lname'] = $attendee->lname();
2630
+                $this->_template_args['attendees'][$att_nmbr]['email'] = $attendee->email();
2631
+                $this->_template_args['attendees'][$att_nmbr]['final_price'] = $registration->final_price();
2632
+                $this->_template_args['attendees'][$att_nmbr]['address'] = implode(
2633 2633
                     ', ',
2634 2634
                     $attendee->full_address_as_array()
2635 2635
                 );
2636
-                $this->_template_args['attendees'][ $att_nmbr ]['att_link'] = self::add_query_args_and_nonce(
2636
+                $this->_template_args['attendees'][$att_nmbr]['att_link'] = self::add_query_args_and_nonce(
2637 2637
                     array(
2638 2638
                         'action' => 'edit_attendee',
2639 2639
                         'post'   => $attendee->ID(),
2640 2640
                     ),
2641 2641
                     REG_ADMIN_URL
2642 2642
                 );
2643
-                $this->_template_args['attendees'][ $att_nmbr ]['event_name'] = $registration->event_obj() instanceof EE_Event
2643
+                $this->_template_args['attendees'][$att_nmbr]['event_name'] = $registration->event_obj() instanceof EE_Event
2644 2644
                     ? $registration->event_obj()->name()
2645 2645
                     : '';
2646 2646
                 $att_nmbr++;
2647 2647
             }
2648 2648
             $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2649 2649
         }
2650
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2650
+        $template_path = REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_attendees.template.php';
2651 2651
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2652 2652
     }
2653 2653
 
@@ -2671,11 +2671,11 @@  discard block
 block discarded – undo
2671 2671
         // now let's determine if this is not the primary registration.  If it isn't then we set the
2672 2672
         // primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2673 2673
         // primary registration object (that way we know if we need to show create button or not)
2674
-        if (! $this->_registration->is_primary_registrant()) {
2674
+        if ( ! $this->_registration->is_primary_registrant()) {
2675 2675
             $primary_registration = $this->_registration->get_primary_registration();
2676 2676
             $primary_attendee = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2677 2677
                 : null;
2678
-            if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2678
+            if ( ! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2679 2679
                 // in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2680 2680
                 // custom attendee object so let's not worry about the primary reg.
2681 2681
                 $primary_registration = null;
@@ -2709,7 +2709,7 @@  discard block
 block discarded – undo
2709 2709
             ) : '';
2710 2710
         $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2711 2711
         $this->_template_args['att_check'] = $att_check;
2712
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2712
+        $template_path = REG_TEMPLATE_PATH.'reg_admin_details_side_meta_box_registrant.template.php';
2713 2713
         echo EEH_Template::display_template($template_path, $this->_template_args, true);
2714 2714
     }
2715 2715
 
@@ -2747,7 +2747,7 @@  discard block
 block discarded – undo
2747 2747
         $success = 0;
2748 2748
         $overwrite_msgs = false;
2749 2749
         // Checkboxes
2750
-        if (! is_array($this->_req_data['_REG_ID'])) {
2750
+        if ( ! is_array($this->_req_data['_REG_ID'])) {
2751 2751
             $this->_req_data['_REG_ID'] = array($this->_req_data['_REG_ID']);
2752 2752
         }
2753 2753
         $reg_count = count($this->_req_data['_REG_ID']);
@@ -2756,7 +2756,7 @@  discard block
 block discarded – undo
2756 2756
             /** @var EE_Registration $REG */
2757 2757
             $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID);
2758 2758
             $payments = $REG->registration_payments();
2759
-            if (! empty($payments)) {
2759
+            if ( ! empty($payments)) {
2760 2760
                 $name = $REG->attendee() instanceof EE_Attendee
2761 2761
                     ? $REG->attendee()->full_name()
2762 2762
                     : esc_html__('Unknown Attendee', 'event_espresso');
@@ -2817,17 +2817,17 @@  discard block
 block discarded – undo
2817 2817
         $REG_MDL = EEM_Registration::instance();
2818 2818
         $success = 1;
2819 2819
         // Checkboxes
2820
-        if (! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2820
+        if ( ! empty($this->_req_data['_REG_ID']) && is_array($this->_req_data['_REG_ID'])) {
2821 2821
             // if array has more than one element than success message should be plural
2822 2822
             $success = count($this->_req_data['_REG_ID']) > 1 ? 2 : 1;
2823 2823
             // cycle thru checkboxes
2824 2824
             while (list($ind, $REG_ID) = each($this->_req_data['_REG_ID'])) {
2825 2825
                 $REG = $REG_MDL->get_one_by_ID($REG_ID);
2826
-                if (! $REG instanceof EE_Registration) {
2826
+                if ( ! $REG instanceof EE_Registration) {
2827 2827
                     continue;
2828 2828
                 }
2829 2829
                 $deleted = $this->_delete_registration($REG);
2830
-                if (! $deleted) {
2830
+                if ( ! $deleted) {
2831 2831
                     $success = 0;
2832 2832
                 }
2833 2833
             }
@@ -2836,7 +2836,7 @@  discard block
 block discarded – undo
2836 2836
             $REG_ID = $this->_req_data['_REG_ID'];
2837 2837
             $REG = $REG_MDL->get_one_by_ID($REG_ID);
2838 2838
             $deleted = $this->_delete_registration($REG);
2839
-            if (! $deleted) {
2839
+            if ( ! $deleted) {
2840 2840
                 $success = 0;
2841 2841
             }
2842 2842
         }
@@ -2870,11 +2870,11 @@  discard block
 block discarded – undo
2870 2870
         $REGS = $TXN->get_many_related('Registration');
2871 2871
         $all_trashed = true;
2872 2872
         foreach ($REGS as $registration) {
2873
-            if (! $registration->get('REG_deleted')) {
2873
+            if ( ! $registration->get('REG_deleted')) {
2874 2874
                 $all_trashed = false;
2875 2875
             }
2876 2876
         }
2877
-        if (! $all_trashed) {
2877
+        if ( ! $all_trashed) {
2878 2878
             EE_Error::add_error(
2879 2879
                 esc_html__(
2880 2880
                     'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
@@ -2933,7 +2933,7 @@  discard block
 block discarded – undo
2933 2933
      */
2934 2934
     public function new_registration()
2935 2935
     {
2936
-        if (! $this->_set_reg_event()) {
2936
+        if ( ! $this->_set_reg_event()) {
2937 2937
             throw new EE_Error(
2938 2938
                 esc_html__(
2939 2939
                     'Unable to continue with registering because there is no Event ID in the request',
@@ -2943,8 +2943,8 @@  discard block
 block discarded – undo
2943 2943
         }
2944 2944
         EE_Registry::instance()->REQ->set_espresso_page(true);
2945 2945
         // gotta start with a clean slate if we're not coming here via ajax
2946
-        if (! defined('DOING_AJAX')
2947
-            && (! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2946
+        if ( ! defined('DOING_AJAX')
2947
+            && ( ! isset($this->_req_data['processing_registration']) || isset($this->_req_data['step_error']))
2948 2948
         ) {
2949 2949
             EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2950 2950
         }
@@ -2977,7 +2977,7 @@  discard block
 block discarded – undo
2977 2977
         }
2978 2978
         // grab header
2979 2979
         $template_path =
2980
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2980
+            REG_TEMPLATE_PATH.'reg_admin_register_new_attendee.template.php';
2981 2981
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2982 2982
             $template_path,
2983 2983
             $this->_template_args,
@@ -3018,7 +3018,7 @@  discard block
 block discarded – undo
3018 3018
                 '</b>'
3019 3019
             );
3020 3020
             return '
3021
-	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
3021
+	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg.'</p></div>
3022 3022
 	<script >
3023 3023
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
3024 3024
 		// after just adding a new registration... we gotta try to put a stop to that !!!
@@ -3086,7 +3086,7 @@  discard block
 block discarded – undo
3086 3086
         // we come back to the process_registration_step route.
3087 3087
         $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
3088 3088
         return EEH_Template::display_template(
3089
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
3089
+            REG_TEMPLATE_PATH.'reg_admin_register_new_attendee_step_content.template.php',
3090 3090
             $template_args,
3091 3091
             true
3092 3092
         );
@@ -3108,8 +3108,8 @@  discard block
 block discarded – undo
3108 3108
         if (is_object($this->_reg_event)) {
3109 3109
             return true;
3110 3110
         }
3111
-        $EVT_ID = (! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3112
-        if (! $EVT_ID) {
3111
+        $EVT_ID = ( ! empty($this->_req_data['event_id'])) ? absint($this->_req_data['event_id']) : false;
3112
+        if ( ! $EVT_ID) {
3113 3113
             return false;
3114 3114
         }
3115 3115
         $this->_reg_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
@@ -3141,8 +3141,8 @@  discard block
 block discarded – undo
3141 3141
         $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
3142 3142
         // if doing ajax then we need to verify the nonce
3143 3143
         if (defined('DOING_AJAX')) {
3144
-            $nonce = isset($this->_req_data[ $this->_req_nonce ])
3145
-                ? sanitize_text_field($this->_req_data[ $this->_req_nonce ]) : '';
3144
+            $nonce = isset($this->_req_data[$this->_req_nonce])
3145
+                ? sanitize_text_field($this->_req_data[$this->_req_nonce]) : '';
3146 3146
             $this->_verify_nonce($nonce, $this->_req_nonce);
3147 3147
         }
3148 3148
         switch ($step) {
@@ -3178,7 +3178,7 @@  discard block
 block discarded – undo
3178 3178
                 }
3179 3179
                 break;
3180 3180
             case 'questions':
3181
-                if (! isset(
3181
+                if ( ! isset(
3182 3182
                     $this->_req_data['txn_reg_status_change'],
3183 3183
                     $this->_req_data['txn_reg_status_change']['send_notifications']
3184 3184
                 )
@@ -3193,7 +3193,7 @@  discard block
 block discarded – undo
3193 3193
                         $grand_total->save_this_and_descendants_to_txn();
3194 3194
                     }
3195 3195
                 }
3196
-                if (! $transaction instanceof EE_Transaction) {
3196
+                if ( ! $transaction instanceof EE_Transaction) {
3197 3197
                     $query_args = array(
3198 3198
                         'action'                  => 'new_registration',
3199 3199
                         'processing_registration' => 2,
@@ -3216,7 +3216,7 @@  discard block
 block discarded – undo
3216 3216
                     }
3217 3217
                 }
3218 3218
                 // maybe update status, and make sure to save transaction if not done already
3219
-                if (! $transaction->update_status_based_on_total_paid()) {
3219
+                if ( ! $transaction->update_status_based_on_total_paid()) {
3220 3220
                     $transaction->save();
3221 3221
                 }
3222 3222
                 EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
@@ -3299,7 +3299,7 @@  discard block
 block discarded – undo
3299 3299
     public function get_attendees($per_page, $count = false, $trash = false)
3300 3300
     {
3301 3301
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3302
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3302
+        require_once(REG_ADMIN.'EE_Attendee_Contact_List_Table.class.php');
3303 3303
         $ATT_MDL = EEM_Attendee::instance();
3304 3304
         $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
3305 3305
         switch ($this->_req_data['orderby']) {
@@ -3338,8 +3338,8 @@  discard block
 block discarded – undo
3338 3338
             ? $this->_req_data['perpage']
3339 3339
             : $per_page;
3340 3340
         $_where = array();
3341
-        if (! empty($this->_req_data['s'])) {
3342
-            $sstr = '%' . $this->_req_data['s'] . '%';
3341
+        if ( ! empty($this->_req_data['s'])) {
3342
+            $sstr = '%'.$this->_req_data['s'].'%';
3343 3343
             $_where['OR'] = array(
3344 3344
                 'Registration.Event.EVT_name'       => array('LIKE', $sstr),
3345 3345
                 'Registration.Event.EVT_desc'       => array('LIKE', $sstr),
@@ -3366,7 +3366,7 @@  discard block
 block discarded – undo
3366 3366
             'extra_selects' => array('Registration_Count' => array('Registration.REG_ID', 'count', '%d')),
3367 3367
             'limit'         => $limit,
3368 3368
         );
3369
-        if (! $count) {
3369
+        if ( ! $count) {
3370 3370
             $query_args['order_by'] = array($orderby => $sort);
3371 3371
         }
3372 3372
         if ($trash) {
@@ -3409,7 +3409,7 @@  discard block
 block discarded – undo
3409 3409
      */
3410 3410
     public function _registrations_report_base($method_name_for_getting_query_params)
3411 3411
     {
3412
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3412
+        if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3413 3413
             wp_redirect(
3414 3414
                 EE_Admin_Page::add_query_args_and_nonce(
3415 3415
                     array(
@@ -3441,8 +3441,8 @@  discard block
 block discarded – undo
3441 3441
                 'EVT_ID' => isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : null,
3442 3442
             );
3443 3443
             $this->_req_data = array_merge($this->_req_data, $new_request_args);
3444
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3445
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3444
+            if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3445
+                require_once(EE_CLASSES.'EE_Export.class.php');
3446 3446
                 $EE_Export = EE_Export::instance($this->_req_data);
3447 3447
                 $EE_Export->export();
3448 3448
             }
@@ -3463,8 +3463,8 @@  discard block
 block discarded – undo
3463 3463
 
3464 3464
     public function _contact_list_export()
3465 3465
     {
3466
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3467
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3466
+        if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3467
+            require_once(EE_CLASSES.'EE_Export.class.php');
3468 3468
             $EE_Export = EE_Export::instance($this->_req_data);
3469 3469
             $EE_Export->export_attendees();
3470 3470
         }
@@ -3473,7 +3473,7 @@  discard block
 block discarded – undo
3473 3473
 
3474 3474
     public function _contact_list_report()
3475 3475
     {
3476
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3476
+        if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3477 3477
             wp_redirect(
3478 3478
                 EE_Admin_Page::add_query_args_and_nonce(
3479 3479
                     array(
@@ -3485,8 +3485,8 @@  discard block
 block discarded – undo
3485 3485
                 )
3486 3486
             );
3487 3487
         } else {
3488
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3489
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3488
+            if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3489
+                require_once(EE_CLASSES.'EE_Export.class.php');
3490 3490
                 $EE_Export = EE_Export::instance($this->_req_data);
3491 3491
                 $EE_Export->report_attendees();
3492 3492
             }
@@ -3572,7 +3572,7 @@  discard block
 block discarded – undo
3572 3572
             $updated_fields = array(
3573 3573
                 'ATT_fname'     => $this->_req_data['ATT_fname'],
3574 3574
                 'ATT_lname'     => $this->_req_data['ATT_lname'],
3575
-                'ATT_full_name' => $this->_req_data['ATT_fname'] . ' ' . $this->_req_data['ATT_lname'],
3575
+                'ATT_full_name' => $this->_req_data['ATT_fname'].' '.$this->_req_data['ATT_lname'],
3576 3576
                 'ATT_address'   => isset($this->_req_data['ATT_address']) ? $this->_req_data['ATT_address'] : '',
3577 3577
                 'ATT_address2'  => isset($this->_req_data['ATT_address2']) ? $this->_req_data['ATT_address2'] : '',
3578 3578
                 'ATT_city'      => isset($this->_req_data['ATT_city']) ? $this->_req_data['ATT_city'] : '',
@@ -3648,17 +3648,17 @@  discard block
 block discarded – undo
3648 3648
             'postexcerpt',
3649 3649
             esc_html__('Excerpt', 'event_espresso'),
3650 3650
             'post_excerpt_meta_box',
3651
-            $this->_cpt_routes[ $this->_req_action ],
3651
+            $this->_cpt_routes[$this->_req_action],
3652 3652
             'normal',
3653 3653
             'core'
3654 3654
         );
3655
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal', 'core');
3655
+        remove_meta_box('commentstatusdiv', $this->_cpt_routes[$this->_req_action], 'normal', 'core');
3656 3656
         if (post_type_supports('espresso_attendees', 'excerpt')) {
3657 3657
             add_meta_box(
3658 3658
                 'postexcerpt',
3659 3659
                 esc_html__('Short Biography', 'event_espresso'),
3660 3660
                 'post_excerpt_meta_box',
3661
-                $this->_cpt_routes[ $this->_req_action ],
3661
+                $this->_cpt_routes[$this->_req_action],
3662 3662
                 'normal'
3663 3663
             );
3664 3664
         }
@@ -3667,7 +3667,7 @@  discard block
 block discarded – undo
3667 3667
                 'commentsdiv',
3668 3668
                 esc_html__('Notes on the Contact', 'event_espresso'),
3669 3669
                 'post_comment_meta_box',
3670
-                $this->_cpt_routes[ $this->_req_action ],
3670
+                $this->_cpt_routes[$this->_req_action],
3671 3671
                 'normal',
3672 3672
                 'core'
3673 3673
             );
@@ -3676,7 +3676,7 @@  discard block
 block discarded – undo
3676 3676
             'attendee_contact_info',
3677 3677
             esc_html__('Contact Info', 'event_espresso'),
3678 3678
             array($this, 'attendee_contact_info'),
3679
-            $this->_cpt_routes[ $this->_req_action ],
3679
+            $this->_cpt_routes[$this->_req_action],
3680 3680
             'side',
3681 3681
             'core'
3682 3682
         );
@@ -3684,7 +3684,7 @@  discard block
 block discarded – undo
3684 3684
             'attendee_details_address',
3685 3685
             esc_html__('Address Details', 'event_espresso'),
3686 3686
             array($this, 'attendee_address_details'),
3687
-            $this->_cpt_routes[ $this->_req_action ],
3687
+            $this->_cpt_routes[$this->_req_action],
3688 3688
             'normal',
3689 3689
             'core'
3690 3690
         );
@@ -3692,7 +3692,7 @@  discard block
 block discarded – undo
3692 3692
             'attendee_registrations',
3693 3693
             esc_html__('Registrations for this Contact', 'event_espresso'),
3694 3694
             array($this, 'attendee_registrations_meta_box'),
3695
-            $this->_cpt_routes[ $this->_req_action ],
3695
+            $this->_cpt_routes[$this->_req_action],
3696 3696
             'normal',
3697 3697
             'high'
3698 3698
         );
@@ -3793,7 +3793,7 @@  discard block
 block discarded – undo
3793 3793
             )
3794 3794
         );
3795 3795
         $template =
3796
-            REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3796
+            REG_TEMPLATE_PATH.'attendee_address_details_metabox_content.template.php';
3797 3797
         EEH_Template::display_template($template, $this->_template_args);
3798 3798
     }
3799 3799
 
@@ -3812,7 +3812,7 @@  discard block
 block discarded – undo
3812 3812
         $this->_template_args['attendee'] = $this->_cpt_model_obj;
3813 3813
         $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3814 3814
         $template =
3815
-            REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3815
+            REG_TEMPLATE_PATH.'attendee_registrations_main_meta_box.template.php';
3816 3816
         EEH_Template::display_template($template, $this->_template_args);
3817 3817
     }
3818 3818
 
@@ -3827,7 +3827,7 @@  discard block
 block discarded – undo
3827 3827
     public function after_title_form_fields($post)
3828 3828
     {
3829 3829
         if ($post->post_type == 'espresso_attendees') {
3830
-            $template = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3830
+            $template = REG_TEMPLATE_PATH.'attendee_details_after_title_form_fields.template.php';
3831 3831
             $template_args['attendee'] = $this->_cpt_model_obj;
3832 3832
             EEH_Template::display_template($template, $template_args);
3833 3833
         }
@@ -3851,14 +3851,14 @@  discard block
 block discarded – undo
3851 3851
         $ATT_MDL = EEM_Attendee::instance();
3852 3852
         $success = 1;
3853 3853
         // Checkboxes
3854
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3854
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3855 3855
             // if array has more than one element than success message should be plural
3856 3856
             $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3857 3857
             // cycle thru checkboxes
3858 3858
             while (list($ATT_ID, $value) = each($this->_req_data['checkbox'])) {
3859 3859
                 $updated = $trash ? $ATT_MDL->update_by_ID(array('status' => 'trash'), $ATT_ID)
3860 3860
                     : $ATT_MDL->update_by_ID(array('status' => 'publish'), $ATT_ID);
3861
-                if (! $updated) {
3861
+                if ( ! $updated) {
3862 3862
                     $success = 0;
3863 3863
                 }
3864 3864
             }
@@ -3869,7 +3869,7 @@  discard block
 block discarded – undo
3869 3869
             $att = $ATT_MDL->get_one_by_ID($ATT_ID);
3870 3870
             $updated = $trash ? $att->set_status('trash') : $att->set_status('publish');
3871 3871
             $updated = $att->save();
3872
-            if (! $updated) {
3872
+            if ( ! $updated) {
3873 3873
                 $success = 0;
3874 3874
             }
3875 3875
         }
Please login to merge, or discard this patch.
core/domain/services/assets/CoreAssetManager.php 1 patch
Indentation   +534 added lines, -534 removed lines patch added patch discarded remove patch
@@ -31,557 +31,557 @@
 block discarded – undo
31 31
 class CoreAssetManager extends AssetManager
32 32
 {
33 33
 
34
-    // WordPress core / Third party JS asset handles
35
-    const JS_HANDLE_JQUERY = 'jquery';
34
+	// WordPress core / Third party JS asset handles
35
+	const JS_HANDLE_JQUERY = 'jquery';
36 36
 
37
-    const JS_HANDLE_JQUERY_VALIDATE = 'jquery-validate';
37
+	const JS_HANDLE_JQUERY_VALIDATE = 'jquery-validate';
38 38
 
39
-    const JS_HANDLE_JQUERY_VALIDATE_EXTRA = 'jquery-validate-extra-methods';
39
+	const JS_HANDLE_JQUERY_VALIDATE_EXTRA = 'jquery-validate-extra-methods';
40 40
 
41
-    const JS_HANDLE_UNDERSCORE = 'underscore';
41
+	const JS_HANDLE_UNDERSCORE = 'underscore';
42 42
 
43
-    const JS_HANDLE_ACCOUNTING_CORE = 'ee-accounting-core';
43
+	const JS_HANDLE_ACCOUNTING_CORE = 'ee-accounting-core';
44 44
 
45
-    /**
46
-     * @since 4.9.71.p
47
-     */
48
-    const JS_HANDLE_REACT = 'react';
45
+	/**
46
+	 * @since 4.9.71.p
47
+	 */
48
+	const JS_HANDLE_REACT = 'react';
49 49
 
50
-    /**
51
-     * @since 4.9.71.p
52
-     */
53
-    const JS_HANDLE_REACT_DOM = 'react-dom';
50
+	/**
51
+	 * @since 4.9.71.p
52
+	 */
53
+	const JS_HANDLE_REACT_DOM = 'react-dom';
54 54
 
55
-    /**
56
-     * @since 4.9.71.p
57
-     */
58
-    const JS_HANDLE_LODASH = 'lodash';
55
+	/**
56
+	 * @since 4.9.71.p
57
+	 */
58
+	const JS_HANDLE_LODASH = 'lodash';
59 59
 
60
-    // EE JS assets handles
61
-    const JS_HANDLE_MANIFEST = 'ee-manifest';
60
+	// EE JS assets handles
61
+	const JS_HANDLE_MANIFEST = 'ee-manifest';
62 62
 
63
-    const JS_HANDLE_JS_CORE = 'eejs-core';
63
+	const JS_HANDLE_JS_CORE = 'eejs-core';
64 64
 
65
-    const JS_HANDLE_VENDOR = 'eventespresso-vendor';
65
+	const JS_HANDLE_VENDOR = 'eventespresso-vendor';
66 66
 
67
-    const JS_HANDLE_DATA_STORES = 'eventespresso-data-stores';
67
+	const JS_HANDLE_DATA_STORES = 'eventespresso-data-stores';
68 68
 
69
-    const JS_HANDLE_HELPERS = 'eventespresso-helpers';
69
+	const JS_HANDLE_HELPERS = 'eventespresso-helpers';
70 70
 
71
-    const JS_HANDLE_MODEL = 'eventespresso-model';
71
+	const JS_HANDLE_MODEL = 'eventespresso-model';
72 72
 
73
-    const JS_HANDLE_VALUE_OBJECTS = 'eventespresso-value-objects';
73
+	const JS_HANDLE_VALUE_OBJECTS = 'eventespresso-value-objects';
74 74
 
75
-    const JS_HANDLE_HOCS = 'eventespresso-hocs';
75
+	const JS_HANDLE_HOCS = 'eventespresso-hocs';
76 76
 
77
-    const JS_HANDLE_COMPONENTS = 'eventespresso-components';
78
-
79
-    const JS_HANDLE_EDITOR_HOCS = 'eventespresso-editor-hocs';
77
+	const JS_HANDLE_COMPONENTS = 'eventespresso-components';
78
+
79
+	const JS_HANDLE_EDITOR_HOCS = 'eventespresso-editor-hocs';
80 80
 
81
-    const JS_HANDLE_VALIDATORS = 'eventespresso-validators';
81
+	const JS_HANDLE_VALIDATORS = 'eventespresso-validators';
82 82
 
83
-    const JS_HANDLE_CORE = 'espresso_core';
83
+	const JS_HANDLE_CORE = 'espresso_core';
84 84
 
85
-    const JS_HANDLE_I18N = 'eei18n';
86
-
87
-    const JS_HANDLE_ACCOUNTING = 'ee-accounting';
88
-
89
-    const JS_HANDLE_WP_PLUGINS_PAGE = 'ee-wp-plugins-page';
90
-
91
-    // EE CSS assets handles
92
-    const CSS_HANDLE_DEFAULT = 'espresso_default';
93
-
94
-    const CSS_HANDLE_CUSTOM = 'espresso_custom_css';
95
-
96
-    const CSS_HANDLE_COMPONENTS = 'eventespresso-components';
97
-
98
-    /**
99
-     * @var EE_Currency_Config $currency_config
100
-     */
101
-    protected $currency_config;
102
-
103
-    /**
104
-     * @var EE_Template_Config $template_config
105
-     */
106
-    protected $template_config;
107
-
108
-
109
-    /**
110
-     * CoreAssetRegister constructor.
111
-     *
112
-     * @param AssetCollection    $assets
113
-     * @param EE_Currency_Config $currency_config
114
-     * @param EE_Template_Config $template_config
115
-     * @param DomainInterface    $domain
116
-     * @param Registry           $registry
117
-     */
118
-    public function __construct(
119
-        AssetCollection $assets,
120
-        EE_Currency_Config $currency_config,
121
-        EE_Template_Config $template_config,
122
-        DomainInterface $domain,
123
-        Registry $registry
124
-    ) {
125
-        $this->currency_config = $currency_config;
126
-        $this->template_config = $template_config;
127
-        parent::__construct($domain, $assets, $registry);
128
-    }
129
-
130
-
131
-    /**
132
-     * @since 4.9.62.p
133
-     * @throws DomainException
134
-     * @throws DuplicateCollectionIdentifierException
135
-     * @throws InvalidArgumentException
136
-     * @throws InvalidDataTypeException
137
-     * @throws InvalidEntityException
138
-     * @throws InvalidInterfaceException
139
-     */
140
-    public function addAssets()
141
-    {
142
-        $this->addJavascriptFiles();
143
-        $this->addStylesheetFiles();
144
-    }
145
-
146
-
147
-    /**
148
-     * @since 4.9.62.p
149
-     * @throws DomainException
150
-     * @throws DuplicateCollectionIdentifierException
151
-     * @throws InvalidArgumentException
152
-     * @throws InvalidDataTypeException
153
-     * @throws InvalidEntityException
154
-     * @throws InvalidInterfaceException
155
-     */
156
-    public function addJavascriptFiles()
157
-    {
158
-        $this->loadCoreJs();
159
-        $this->loadJqueryValidate();
160
-        $this->loadAccountingJs();
161
-        add_action(
162
-            'AHEE__EventEspresso_core_services_assets_Registry__registerScripts__before_script',
163
-            array($this, 'loadQtipJs')
164
-        );
165
-        $this->registerAdminAssets();
166
-    }
167
-
168
-
169
-    /**
170
-     * @since 4.9.62.p
171
-     * @throws DuplicateCollectionIdentifierException
172
-     * @throws InvalidDataTypeException
173
-     * @throws InvalidEntityException
174
-     */
175
-    public function addStylesheetFiles()
176
-    {
177
-        $this->loadCoreCss();
178
-    }
179
-
180
-
181
-    /**
182
-     * core default javascript
183
-     *
184
-     * @since 4.9.62.p
185
-     * @throws DomainException
186
-     * @throws DuplicateCollectionIdentifierException
187
-     * @throws InvalidArgumentException
188
-     * @throws InvalidDataTypeException
189
-     * @throws InvalidEntityException
190
-     * @throws InvalidInterfaceException
191
-     */
192
-    private function loadCoreJs()
193
-    {
194
-        // conditionally load third-party libraries that WP core MIGHT have.
195
-        $this->registerWpAssets();
196
-
197
-        $this->addJavascript(
198
-            CoreAssetManager::JS_HANDLE_MANIFEST,
199
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'manifest')
200
-        );
201
-
202
-        $this->addJavascript(
203
-            CoreAssetManager::JS_HANDLE_JS_CORE,
204
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'eejs'),
205
-            array(CoreAssetManager::JS_HANDLE_MANIFEST)
206
-        )
207
-        ->setHasInlineData();
208
-
209
-        $this->addJavascript(
210
-            CoreAssetManager::JS_HANDLE_VENDOR,
211
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'vendor'),
212
-            array(
213
-                CoreAssetManager::JS_HANDLE_JS_CORE,
214
-                CoreAssetManager::JS_HANDLE_REACT,
215
-                CoreAssetManager::JS_HANDLE_REACT_DOM,
216
-                CoreAssetManager::JS_HANDLE_LODASH,
217
-            )
218
-        );
219
-
220
-        $this->addJavascript(
221
-            CoreAssetManager::JS_HANDLE_VALIDATORS,
222
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'validators')
223
-        )->setRequiresTranslation();
224
-
225
-        $this->addJavascript(
226
-            CoreAssetManager::JS_HANDLE_HELPERS,
227
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'helpers'),
228
-            array(
229
-                CoreAssetManager::JS_HANDLE_VALIDATORS
230
-            )
231
-        )->setRequiresTranslation();
232
-
233
-        $this->addJavascript(
234
-            CoreAssetManager::JS_HANDLE_MODEL,
235
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'model'),
236
-            array(
237
-                CoreAssetManager::JS_HANDLE_HELPERS,
238
-                CoreAssetManager::JS_HANDLE_VALUE_OBJECTS,
239
-            )
240
-        )->setRequiresTranslation();
241
-
242
-        $this->addJavascript(
243
-            CoreAssetManager::JS_HANDLE_VALUE_OBJECTS,
244
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'valueObjects'),
245
-            array(
246
-                CoreAssetManager::JS_HANDLE_VALIDATORS,
247
-                CoreAssetManager::JS_HANDLE_HELPERS,
248
-            )
249
-        )->setRequiresTranslation();
250
-
251
-        $this->addJavascript(
252
-            CoreAssetManager::JS_HANDLE_DATA_STORES,
253
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'data-stores'),
254
-            array(
255
-                CoreAssetManager::JS_HANDLE_VENDOR,
256
-                'wp-data',
257
-                'wp-api-fetch',
258
-                CoreAssetManager::JS_HANDLE_VALUE_OBJECTS,
259
-                CoreAssetManager::JS_HANDLE_MODEL,
260
-            )
261
-        )
262
-             ->setRequiresTranslation()
263
-             ->setInlineDataCallback(
264
-                 function() {
265
-                     wp_add_inline_script(
266
-                         CoreAssetManager::JS_HANDLE_DATA_STORES,
267
-                         is_admin()
268
-                             ? 'wp.apiFetch.use( eejs.middleWares.apiFetch.capsMiddleware( eejs.middleWares.apiFetch.CONTEXT_CAPS_EDIT ) )'
269
-                             : 'wp.apiFetch.use( eejs.middleWares.apiFetch.capsMiddleware )'
270
-                     );
271
-                 }
272
-             );
273
-
274
-        $this->addJavascript(
275
-            CoreAssetManager::JS_HANDLE_HOCS,
276
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'hocs'),
277
-            array(
278
-                CoreAssetManager::JS_HANDLE_DATA_STORES,
279
-                CoreAssetManager::JS_HANDLE_VALUE_OBJECTS,
280
-                'wp-components',
281
-            )
282
-        )->setRequiresTranslation();
283
-
284
-        $this->addJavascript(
285
-            CoreAssetManager::JS_HANDLE_COMPONENTS,
286
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'components'),
287
-            array(
288
-                CoreAssetManager::JS_HANDLE_DATA_STORES,
289
-                CoreAssetManager::JS_HANDLE_VALUE_OBJECTS,
290
-                'wp-components',
291
-            )
292
-        )
293
-        ->setRequiresTranslation();
294
-
295
-        $this->addJavascript(
296
-            CoreAssetManager::JS_HANDLE_EDITOR_HOCS,
297
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'editor-hocs'),
298
-            array(
299
-                CoreAssetManager::JS_HANDLE_COMPONENTS
300
-            )
301
-        )->setRequiresTranslation();
302
-
303
-        $this->registry->addData('eejs_api_nonce', wp_create_nonce('wp_rest'));
304
-        $this->registry->addData(
305
-            'paths',
306
-            array(
307
-                'base_rest_route' => rest_url(),
308
-                'rest_route' => rest_url('ee/v4.8.36/'),
309
-                'collection_endpoints' => EED_Core_Rest_Api::getCollectionRoutesIndexedByModelName(),
310
-                'primary_keys' => EED_Core_Rest_Api::getPrimaryKeyNamesIndexedByModelName(),
311
-                'site_url' => site_url('/'),
312
-                'admin_url' => admin_url('/'),
313
-            )
314
-        );
315
-        /** site formatting values **/
316
-        $this->registry->addData(
317
-            'site_formats',
318
-            array(
319
-                'date_formats' => EEH_DTT_Helper::convert_php_to_js_and_moment_date_formats()
320
-            )
321
-        );
322
-        /** currency data **/
323
-        $this->registry->addData(
324
-            'currency_config',
325
-            $this->getCurrencySettings()
326
-        );
327
-        /** site timezone */
328
-        $this->registry->addData(
329
-            'default_timezone',
330
-            array(
331
-                'pretty' => EEH_DTT_Helper::get_timezone_string_for_display(),
332
-                'string' => get_option('timezone_string'),
333
-                'offset' => EEH_DTT_Helper::get_site_timezone_gmt_offset(),
334
-            )
335
-        );
336
-        /** site locale (user locale if user logged in) */
337
-        $this->registry->addData(
338
-            'locale',
339
-            array(
340
-                'user' => get_user_locale(),
341
-                'site' => get_locale()
342
-            )
343
-        );
344
-
345
-        $this->addJavascript(
346
-            CoreAssetManager::JS_HANDLE_CORE,
347
-            EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
348
-            array(CoreAssetManager::JS_HANDLE_JQUERY)
349
-        )
350
-        ->setInlineDataCallback(
351
-            function () {
352
-                wp_localize_script(
353
-                    CoreAssetManager::JS_HANDLE_CORE,
354
-                    CoreAssetManager::JS_HANDLE_I18N,
355
-                    EE_Registry::$i18n_js_strings
356
-                );
357
-            }
358
-        );
359
-    }
360
-
361
-
362
-    /**
363
-     * Registers vendor files that are bundled with a later version WP but might not be for the current version of
364
-     * WordPress in the running environment.
365
-     *
366
-     * @throws DuplicateCollectionIdentifierException
367
-     * @throws InvalidDataTypeException
368
-     * @throws InvalidEntityException
369
-     * @throws DomainException
370
-     * @since 4.9.71.p
371
-     */
372
-    private function registerWpAssets()
373
-    {
374
-        global $wp_version;
375
-        if (version_compare($wp_version, '5.0.beta', '>=')) {
376
-            return;
377
-        }
378
-        $this->addVendorJavascript(CoreAssetManager::JS_HANDLE_REACT)
379
-            ->setVersion('16.6.0');
380
-        $this->addVendorJavascript(
381
-            CoreAssetManager::JS_HANDLE_REACT_DOM,
382
-            array(CoreAssetManager::JS_HANDLE_REACT)
383
-        )->setVersion('16.6.0');
384
-        $this->addVendorJavascript(CoreAssetManager::JS_HANDLE_LODASH)
385
-            ->setInlineDataCallback(
386
-                function() {
387
-                    wp_add_inline_script(
388
-                        CoreAssetManager::JS_HANDLE_LODASH,
389
-                        'window.lodash = _.noConflict();'
390
-                    );
391
-                }
392
-            )
393
-            ->setVersion('4.17.11');
394
-    }
395
-
396
-
397
-    /**
398
-     * Returns configuration data for the accounting-js library.
399
-     * @since 4.9.71.p
400
-     * @return array
401
-     */
402
-    private function getAccountingSettings() {
403
-        return array(
404
-            'currency' => array(
405
-                'symbol'    => $this->currency_config->sign,
406
-                'format'    => array(
407
-                    'pos'  => $this->currency_config->sign_b4 ? '%s%v' : '%v%s',
408
-                    'neg'  => $this->currency_config->sign_b4 ? '- %s%v' : '- %v%s',
409
-                    'zero' => $this->currency_config->sign_b4 ? '%s--' : '--%s',
410
-                ),
411
-                'decimal'   => $this->currency_config->dec_mrk,
412
-                'thousand'  => $this->currency_config->thsnds,
413
-                'precision' => $this->currency_config->dec_plc,
414
-            ),
415
-            'number'   => array(
416
-                'precision' => $this->currency_config->dec_plc,
417
-                'thousand'  => $this->currency_config->thsnds,
418
-                'decimal'   => $this->currency_config->dec_mrk,
419
-            ),
420
-        );
421
-    }
422
-
423
-
424
-    /**
425
-     * Returns configuration data for the js Currency VO.
426
-     * @since 4.9.71.p
427
-     * @return array
428
-     */
429
-    private function getCurrencySettings()
430
-    {
431
-        return array(
432
-            'code' => $this->currency_config->code,
433
-            'singularLabel' => $this->currency_config->name,
434
-            'pluralLabel' => $this->currency_config->plural,
435
-            'sign' => $this->currency_config->sign,
436
-            'signB4' => $this->currency_config->sign_b4,
437
-            'decimalPlaces' => $this->currency_config->dec_plc,
438
-            'decimalMark' => $this->currency_config->dec_mrk,
439
-            'thousandsSeparator' => $this->currency_config->thsnds,
440
-        );
441
-    }
442
-
443
-
444
-    /**
445
-     * @since 4.9.62.p
446
-     * @throws DuplicateCollectionIdentifierException
447
-     * @throws InvalidDataTypeException
448
-     * @throws InvalidEntityException
449
-     */
450
-    private function loadCoreCss()
451
-    {
452
-        if ($this->template_config->enable_default_style && ! is_admin()) {
453
-            $this->addStylesheet(
454
-                CoreAssetManager::CSS_HANDLE_DEFAULT,
455
-                is_readable(EVENT_ESPRESSO_UPLOAD_DIR . 'css/style.css')
456
-                    ? EVENT_ESPRESSO_UPLOAD_DIR . 'css/espresso_default.css'
457
-                    : EE_GLOBAL_ASSETS_URL . 'css/espresso_default.css',
458
-                array('dashicons')
459
-            );
460
-            //Load custom style sheet if available
461
-            if ($this->template_config->custom_style_sheet !== null) {
462
-                $this->addStylesheet(
463
-                    CoreAssetManager::CSS_HANDLE_CUSTOM,
464
-                    EVENT_ESPRESSO_UPLOAD_URL . 'css/' . $this->template_config->custom_style_sheet,
465
-                    array(CoreAssetManager::CSS_HANDLE_DEFAULT)
466
-                );
467
-            }
468
-        }
469
-        $this->addStylesheet(
470
-            CoreAssetManager::CSS_HANDLE_COMPONENTS,
471
-            $this->registry->getCssUrl(
472
-                $this->domain->assetNamespace(),
473
-                'components'
474
-            )
475
-        );
476
-    }
477
-
478
-
479
-    /**
480
-     * jQuery Validate for form validation
481
-     *
482
-     * @since 4.9.62.p
483
-     * @throws DomainException
484
-     * @throws DuplicateCollectionIdentifierException
485
-     * @throws InvalidDataTypeException
486
-     * @throws InvalidEntityException
487
-     */
488
-    private function loadJqueryValidate()
489
-    {
490
-        $this->addJavascript(
491
-            CoreAssetManager::JS_HANDLE_JQUERY_VALIDATE,
492
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery.validate.min.js',
493
-            array(CoreAssetManager::JS_HANDLE_JQUERY)
494
-        )
495
-        ->setVersion('1.15.0');
496
-
497
-        $this->addJavascript(
498
-            CoreAssetManager::JS_HANDLE_JQUERY_VALIDATE_EXTRA,
499
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery.validate.additional-methods.min.js',
500
-            array(CoreAssetManager::JS_HANDLE_JQUERY_VALIDATE)
501
-        )
502
-        ->setVersion('1.15.0');
503
-    }
504
-
505
-
506
-    /**
507
-     * accounting.js for performing client-side calculations
508
-     *
509
-     * @since 4.9.62.p
510
-     * @throws DomainException
511
-     * @throws DuplicateCollectionIdentifierException
512
-     * @throws InvalidDataTypeException
513
-     * @throws InvalidEntityException
514
-     */
515
-    private function loadAccountingJs()
516
-    {
517
-        //accounting.js library
518
-        // @link http://josscrowcroft.github.io/accounting.js/
519
-        $this->addJavascript(
520
-            CoreAssetManager::JS_HANDLE_ACCOUNTING_CORE,
521
-            EE_THIRD_PARTY_URL . 'accounting/accounting.js',
522
-            array(CoreAssetManager::JS_HANDLE_UNDERSCORE)
523
-        )
524
-        ->setVersion('0.3.2');
525
-
526
-        $this->addJavascript(
527
-            CoreAssetManager::JS_HANDLE_ACCOUNTING,
528
-            EE_GLOBAL_ASSETS_URL . 'scripts/ee-accounting-config.js',
529
-            array(CoreAssetManager::JS_HANDLE_ACCOUNTING_CORE)
530
-        )
531
-        ->setInlineDataCallback(
532
-            function () {
533
-                 wp_localize_script(
534
-                     CoreAssetManager::JS_HANDLE_ACCOUNTING,
535
-                     'EE_ACCOUNTING_CFG',
536
-                     $this->getAccountingSettings()
537
-                 );
538
-            }
539
-        )
540
-        ->setVersion();
541
-    }
542
-
543
-
544
-    /**
545
-     * registers assets for cleaning your ears
546
-     *
547
-     * @param JavascriptAsset $script
548
-     */
549
-    public function loadQtipJs(JavascriptAsset $script)
550
-    {
551
-        // qtip is turned OFF by default, but prior to the wp_enqueue_scripts hook,
552
-        // can be turned back on again via: add_filter('FHEE_load_qtip', '__return_true' );
553
-        if (
554
-            $script->handle() === CoreAssetManager::JS_HANDLE_WP_PLUGINS_PAGE
555
-            && apply_filters('FHEE_load_qtip', false)
556
-        ) {
557
-            EEH_Qtip_Loader::instance()->register_and_enqueue();
558
-        }
559
-    }
560
-
561
-
562
-    /**
563
-     * assets that are used in the WordPress admin
564
-     *
565
-     * @since 4.9.62.p
566
-     * @throws DuplicateCollectionIdentifierException
567
-     * @throws InvalidDataTypeException
568
-     * @throws InvalidEntityException
569
-     */
570
-    private function registerAdminAssets()
571
-    {
572
-        $this->addJavascript(
573
-            CoreAssetManager::JS_HANDLE_WP_PLUGINS_PAGE,
574
-            $this->registry->getJsUrl($this->domain->assetNamespace(), 'wp-plugins-page'),
575
-            array(
576
-                CoreAssetManager::JS_HANDLE_JQUERY,
577
-                CoreAssetManager::JS_HANDLE_VENDOR,
578
-            )
579
-        )
580
-        ->setRequiresTranslation();
581
-
582
-        $this->addStylesheet(
583
-            CoreAssetManager::JS_HANDLE_WP_PLUGINS_PAGE,
584
-            $this->registry->getCssUrl($this->domain->assetNamespace(), 'wp-plugins-page')
585
-        );
586
-    }
85
+	const JS_HANDLE_I18N = 'eei18n';
86
+
87
+	const JS_HANDLE_ACCOUNTING = 'ee-accounting';
88
+
89
+	const JS_HANDLE_WP_PLUGINS_PAGE = 'ee-wp-plugins-page';
90
+
91
+	// EE CSS assets handles
92
+	const CSS_HANDLE_DEFAULT = 'espresso_default';
93
+
94
+	const CSS_HANDLE_CUSTOM = 'espresso_custom_css';
95
+
96
+	const CSS_HANDLE_COMPONENTS = 'eventespresso-components';
97
+
98
+	/**
99
+	 * @var EE_Currency_Config $currency_config
100
+	 */
101
+	protected $currency_config;
102
+
103
+	/**
104
+	 * @var EE_Template_Config $template_config
105
+	 */
106
+	protected $template_config;
107
+
108
+
109
+	/**
110
+	 * CoreAssetRegister constructor.
111
+	 *
112
+	 * @param AssetCollection    $assets
113
+	 * @param EE_Currency_Config $currency_config
114
+	 * @param EE_Template_Config $template_config
115
+	 * @param DomainInterface    $domain
116
+	 * @param Registry           $registry
117
+	 */
118
+	public function __construct(
119
+		AssetCollection $assets,
120
+		EE_Currency_Config $currency_config,
121
+		EE_Template_Config $template_config,
122
+		DomainInterface $domain,
123
+		Registry $registry
124
+	) {
125
+		$this->currency_config = $currency_config;
126
+		$this->template_config = $template_config;
127
+		parent::__construct($domain, $assets, $registry);
128
+	}
129
+
130
+
131
+	/**
132
+	 * @since 4.9.62.p
133
+	 * @throws DomainException
134
+	 * @throws DuplicateCollectionIdentifierException
135
+	 * @throws InvalidArgumentException
136
+	 * @throws InvalidDataTypeException
137
+	 * @throws InvalidEntityException
138
+	 * @throws InvalidInterfaceException
139
+	 */
140
+	public function addAssets()
141
+	{
142
+		$this->addJavascriptFiles();
143
+		$this->addStylesheetFiles();
144
+	}
145
+
146
+
147
+	/**
148
+	 * @since 4.9.62.p
149
+	 * @throws DomainException
150
+	 * @throws DuplicateCollectionIdentifierException
151
+	 * @throws InvalidArgumentException
152
+	 * @throws InvalidDataTypeException
153
+	 * @throws InvalidEntityException
154
+	 * @throws InvalidInterfaceException
155
+	 */
156
+	public function addJavascriptFiles()
157
+	{
158
+		$this->loadCoreJs();
159
+		$this->loadJqueryValidate();
160
+		$this->loadAccountingJs();
161
+		add_action(
162
+			'AHEE__EventEspresso_core_services_assets_Registry__registerScripts__before_script',
163
+			array($this, 'loadQtipJs')
164
+		);
165
+		$this->registerAdminAssets();
166
+	}
167
+
168
+
169
+	/**
170
+	 * @since 4.9.62.p
171
+	 * @throws DuplicateCollectionIdentifierException
172
+	 * @throws InvalidDataTypeException
173
+	 * @throws InvalidEntityException
174
+	 */
175
+	public function addStylesheetFiles()
176
+	{
177
+		$this->loadCoreCss();
178
+	}
179
+
180
+
181
+	/**
182
+	 * core default javascript
183
+	 *
184
+	 * @since 4.9.62.p
185
+	 * @throws DomainException
186
+	 * @throws DuplicateCollectionIdentifierException
187
+	 * @throws InvalidArgumentException
188
+	 * @throws InvalidDataTypeException
189
+	 * @throws InvalidEntityException
190
+	 * @throws InvalidInterfaceException
191
+	 */
192
+	private function loadCoreJs()
193
+	{
194
+		// conditionally load third-party libraries that WP core MIGHT have.
195
+		$this->registerWpAssets();
196
+
197
+		$this->addJavascript(
198
+			CoreAssetManager::JS_HANDLE_MANIFEST,
199
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'manifest')
200
+		);
201
+
202
+		$this->addJavascript(
203
+			CoreAssetManager::JS_HANDLE_JS_CORE,
204
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'eejs'),
205
+			array(CoreAssetManager::JS_HANDLE_MANIFEST)
206
+		)
207
+		->setHasInlineData();
208
+
209
+		$this->addJavascript(
210
+			CoreAssetManager::JS_HANDLE_VENDOR,
211
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'vendor'),
212
+			array(
213
+				CoreAssetManager::JS_HANDLE_JS_CORE,
214
+				CoreAssetManager::JS_HANDLE_REACT,
215
+				CoreAssetManager::JS_HANDLE_REACT_DOM,
216
+				CoreAssetManager::JS_HANDLE_LODASH,
217
+			)
218
+		);
219
+
220
+		$this->addJavascript(
221
+			CoreAssetManager::JS_HANDLE_VALIDATORS,
222
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'validators')
223
+		)->setRequiresTranslation();
224
+
225
+		$this->addJavascript(
226
+			CoreAssetManager::JS_HANDLE_HELPERS,
227
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'helpers'),
228
+			array(
229
+				CoreAssetManager::JS_HANDLE_VALIDATORS
230
+			)
231
+		)->setRequiresTranslation();
232
+
233
+		$this->addJavascript(
234
+			CoreAssetManager::JS_HANDLE_MODEL,
235
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'model'),
236
+			array(
237
+				CoreAssetManager::JS_HANDLE_HELPERS,
238
+				CoreAssetManager::JS_HANDLE_VALUE_OBJECTS,
239
+			)
240
+		)->setRequiresTranslation();
241
+
242
+		$this->addJavascript(
243
+			CoreAssetManager::JS_HANDLE_VALUE_OBJECTS,
244
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'valueObjects'),
245
+			array(
246
+				CoreAssetManager::JS_HANDLE_VALIDATORS,
247
+				CoreAssetManager::JS_HANDLE_HELPERS,
248
+			)
249
+		)->setRequiresTranslation();
250
+
251
+		$this->addJavascript(
252
+			CoreAssetManager::JS_HANDLE_DATA_STORES,
253
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'data-stores'),
254
+			array(
255
+				CoreAssetManager::JS_HANDLE_VENDOR,
256
+				'wp-data',
257
+				'wp-api-fetch',
258
+				CoreAssetManager::JS_HANDLE_VALUE_OBJECTS,
259
+				CoreAssetManager::JS_HANDLE_MODEL,
260
+			)
261
+		)
262
+			 ->setRequiresTranslation()
263
+			 ->setInlineDataCallback(
264
+				 function() {
265
+					 wp_add_inline_script(
266
+						 CoreAssetManager::JS_HANDLE_DATA_STORES,
267
+						 is_admin()
268
+							 ? 'wp.apiFetch.use( eejs.middleWares.apiFetch.capsMiddleware( eejs.middleWares.apiFetch.CONTEXT_CAPS_EDIT ) )'
269
+							 : 'wp.apiFetch.use( eejs.middleWares.apiFetch.capsMiddleware )'
270
+					 );
271
+				 }
272
+			 );
273
+
274
+		$this->addJavascript(
275
+			CoreAssetManager::JS_HANDLE_HOCS,
276
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'hocs'),
277
+			array(
278
+				CoreAssetManager::JS_HANDLE_DATA_STORES,
279
+				CoreAssetManager::JS_HANDLE_VALUE_OBJECTS,
280
+				'wp-components',
281
+			)
282
+		)->setRequiresTranslation();
283
+
284
+		$this->addJavascript(
285
+			CoreAssetManager::JS_HANDLE_COMPONENTS,
286
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'components'),
287
+			array(
288
+				CoreAssetManager::JS_HANDLE_DATA_STORES,
289
+				CoreAssetManager::JS_HANDLE_VALUE_OBJECTS,
290
+				'wp-components',
291
+			)
292
+		)
293
+		->setRequiresTranslation();
294
+
295
+		$this->addJavascript(
296
+			CoreAssetManager::JS_HANDLE_EDITOR_HOCS,
297
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'editor-hocs'),
298
+			array(
299
+				CoreAssetManager::JS_HANDLE_COMPONENTS
300
+			)
301
+		)->setRequiresTranslation();
302
+
303
+		$this->registry->addData('eejs_api_nonce', wp_create_nonce('wp_rest'));
304
+		$this->registry->addData(
305
+			'paths',
306
+			array(
307
+				'base_rest_route' => rest_url(),
308
+				'rest_route' => rest_url('ee/v4.8.36/'),
309
+				'collection_endpoints' => EED_Core_Rest_Api::getCollectionRoutesIndexedByModelName(),
310
+				'primary_keys' => EED_Core_Rest_Api::getPrimaryKeyNamesIndexedByModelName(),
311
+				'site_url' => site_url('/'),
312
+				'admin_url' => admin_url('/'),
313
+			)
314
+		);
315
+		/** site formatting values **/
316
+		$this->registry->addData(
317
+			'site_formats',
318
+			array(
319
+				'date_formats' => EEH_DTT_Helper::convert_php_to_js_and_moment_date_formats()
320
+			)
321
+		);
322
+		/** currency data **/
323
+		$this->registry->addData(
324
+			'currency_config',
325
+			$this->getCurrencySettings()
326
+		);
327
+		/** site timezone */
328
+		$this->registry->addData(
329
+			'default_timezone',
330
+			array(
331
+				'pretty' => EEH_DTT_Helper::get_timezone_string_for_display(),
332
+				'string' => get_option('timezone_string'),
333
+				'offset' => EEH_DTT_Helper::get_site_timezone_gmt_offset(),
334
+			)
335
+		);
336
+		/** site locale (user locale if user logged in) */
337
+		$this->registry->addData(
338
+			'locale',
339
+			array(
340
+				'user' => get_user_locale(),
341
+				'site' => get_locale()
342
+			)
343
+		);
344
+
345
+		$this->addJavascript(
346
+			CoreAssetManager::JS_HANDLE_CORE,
347
+			EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
348
+			array(CoreAssetManager::JS_HANDLE_JQUERY)
349
+		)
350
+		->setInlineDataCallback(
351
+			function () {
352
+				wp_localize_script(
353
+					CoreAssetManager::JS_HANDLE_CORE,
354
+					CoreAssetManager::JS_HANDLE_I18N,
355
+					EE_Registry::$i18n_js_strings
356
+				);
357
+			}
358
+		);
359
+	}
360
+
361
+
362
+	/**
363
+	 * Registers vendor files that are bundled with a later version WP but might not be for the current version of
364
+	 * WordPress in the running environment.
365
+	 *
366
+	 * @throws DuplicateCollectionIdentifierException
367
+	 * @throws InvalidDataTypeException
368
+	 * @throws InvalidEntityException
369
+	 * @throws DomainException
370
+	 * @since 4.9.71.p
371
+	 */
372
+	private function registerWpAssets()
373
+	{
374
+		global $wp_version;
375
+		if (version_compare($wp_version, '5.0.beta', '>=')) {
376
+			return;
377
+		}
378
+		$this->addVendorJavascript(CoreAssetManager::JS_HANDLE_REACT)
379
+			->setVersion('16.6.0');
380
+		$this->addVendorJavascript(
381
+			CoreAssetManager::JS_HANDLE_REACT_DOM,
382
+			array(CoreAssetManager::JS_HANDLE_REACT)
383
+		)->setVersion('16.6.0');
384
+		$this->addVendorJavascript(CoreAssetManager::JS_HANDLE_LODASH)
385
+			->setInlineDataCallback(
386
+				function() {
387
+					wp_add_inline_script(
388
+						CoreAssetManager::JS_HANDLE_LODASH,
389
+						'window.lodash = _.noConflict();'
390
+					);
391
+				}
392
+			)
393
+			->setVersion('4.17.11');
394
+	}
395
+
396
+
397
+	/**
398
+	 * Returns configuration data for the accounting-js library.
399
+	 * @since 4.9.71.p
400
+	 * @return array
401
+	 */
402
+	private function getAccountingSettings() {
403
+		return array(
404
+			'currency' => array(
405
+				'symbol'    => $this->currency_config->sign,
406
+				'format'    => array(
407
+					'pos'  => $this->currency_config->sign_b4 ? '%s%v' : '%v%s',
408
+					'neg'  => $this->currency_config->sign_b4 ? '- %s%v' : '- %v%s',
409
+					'zero' => $this->currency_config->sign_b4 ? '%s--' : '--%s',
410
+				),
411
+				'decimal'   => $this->currency_config->dec_mrk,
412
+				'thousand'  => $this->currency_config->thsnds,
413
+				'precision' => $this->currency_config->dec_plc,
414
+			),
415
+			'number'   => array(
416
+				'precision' => $this->currency_config->dec_plc,
417
+				'thousand'  => $this->currency_config->thsnds,
418
+				'decimal'   => $this->currency_config->dec_mrk,
419
+			),
420
+		);
421
+	}
422
+
423
+
424
+	/**
425
+	 * Returns configuration data for the js Currency VO.
426
+	 * @since 4.9.71.p
427
+	 * @return array
428
+	 */
429
+	private function getCurrencySettings()
430
+	{
431
+		return array(
432
+			'code' => $this->currency_config->code,
433
+			'singularLabel' => $this->currency_config->name,
434
+			'pluralLabel' => $this->currency_config->plural,
435
+			'sign' => $this->currency_config->sign,
436
+			'signB4' => $this->currency_config->sign_b4,
437
+			'decimalPlaces' => $this->currency_config->dec_plc,
438
+			'decimalMark' => $this->currency_config->dec_mrk,
439
+			'thousandsSeparator' => $this->currency_config->thsnds,
440
+		);
441
+	}
442
+
443
+
444
+	/**
445
+	 * @since 4.9.62.p
446
+	 * @throws DuplicateCollectionIdentifierException
447
+	 * @throws InvalidDataTypeException
448
+	 * @throws InvalidEntityException
449
+	 */
450
+	private function loadCoreCss()
451
+	{
452
+		if ($this->template_config->enable_default_style && ! is_admin()) {
453
+			$this->addStylesheet(
454
+				CoreAssetManager::CSS_HANDLE_DEFAULT,
455
+				is_readable(EVENT_ESPRESSO_UPLOAD_DIR . 'css/style.css')
456
+					? EVENT_ESPRESSO_UPLOAD_DIR . 'css/espresso_default.css'
457
+					: EE_GLOBAL_ASSETS_URL . 'css/espresso_default.css',
458
+				array('dashicons')
459
+			);
460
+			//Load custom style sheet if available
461
+			if ($this->template_config->custom_style_sheet !== null) {
462
+				$this->addStylesheet(
463
+					CoreAssetManager::CSS_HANDLE_CUSTOM,
464
+					EVENT_ESPRESSO_UPLOAD_URL . 'css/' . $this->template_config->custom_style_sheet,
465
+					array(CoreAssetManager::CSS_HANDLE_DEFAULT)
466
+				);
467
+			}
468
+		}
469
+		$this->addStylesheet(
470
+			CoreAssetManager::CSS_HANDLE_COMPONENTS,
471
+			$this->registry->getCssUrl(
472
+				$this->domain->assetNamespace(),
473
+				'components'
474
+			)
475
+		);
476
+	}
477
+
478
+
479
+	/**
480
+	 * jQuery Validate for form validation
481
+	 *
482
+	 * @since 4.9.62.p
483
+	 * @throws DomainException
484
+	 * @throws DuplicateCollectionIdentifierException
485
+	 * @throws InvalidDataTypeException
486
+	 * @throws InvalidEntityException
487
+	 */
488
+	private function loadJqueryValidate()
489
+	{
490
+		$this->addJavascript(
491
+			CoreAssetManager::JS_HANDLE_JQUERY_VALIDATE,
492
+			EE_GLOBAL_ASSETS_URL . 'scripts/jquery.validate.min.js',
493
+			array(CoreAssetManager::JS_HANDLE_JQUERY)
494
+		)
495
+		->setVersion('1.15.0');
496
+
497
+		$this->addJavascript(
498
+			CoreAssetManager::JS_HANDLE_JQUERY_VALIDATE_EXTRA,
499
+			EE_GLOBAL_ASSETS_URL . 'scripts/jquery.validate.additional-methods.min.js',
500
+			array(CoreAssetManager::JS_HANDLE_JQUERY_VALIDATE)
501
+		)
502
+		->setVersion('1.15.0');
503
+	}
504
+
505
+
506
+	/**
507
+	 * accounting.js for performing client-side calculations
508
+	 *
509
+	 * @since 4.9.62.p
510
+	 * @throws DomainException
511
+	 * @throws DuplicateCollectionIdentifierException
512
+	 * @throws InvalidDataTypeException
513
+	 * @throws InvalidEntityException
514
+	 */
515
+	private function loadAccountingJs()
516
+	{
517
+		//accounting.js library
518
+		// @link http://josscrowcroft.github.io/accounting.js/
519
+		$this->addJavascript(
520
+			CoreAssetManager::JS_HANDLE_ACCOUNTING_CORE,
521
+			EE_THIRD_PARTY_URL . 'accounting/accounting.js',
522
+			array(CoreAssetManager::JS_HANDLE_UNDERSCORE)
523
+		)
524
+		->setVersion('0.3.2');
525
+
526
+		$this->addJavascript(
527
+			CoreAssetManager::JS_HANDLE_ACCOUNTING,
528
+			EE_GLOBAL_ASSETS_URL . 'scripts/ee-accounting-config.js',
529
+			array(CoreAssetManager::JS_HANDLE_ACCOUNTING_CORE)
530
+		)
531
+		->setInlineDataCallback(
532
+			function () {
533
+				 wp_localize_script(
534
+					 CoreAssetManager::JS_HANDLE_ACCOUNTING,
535
+					 'EE_ACCOUNTING_CFG',
536
+					 $this->getAccountingSettings()
537
+				 );
538
+			}
539
+		)
540
+		->setVersion();
541
+	}
542
+
543
+
544
+	/**
545
+	 * registers assets for cleaning your ears
546
+	 *
547
+	 * @param JavascriptAsset $script
548
+	 */
549
+	public function loadQtipJs(JavascriptAsset $script)
550
+	{
551
+		// qtip is turned OFF by default, but prior to the wp_enqueue_scripts hook,
552
+		// can be turned back on again via: add_filter('FHEE_load_qtip', '__return_true' );
553
+		if (
554
+			$script->handle() === CoreAssetManager::JS_HANDLE_WP_PLUGINS_PAGE
555
+			&& apply_filters('FHEE_load_qtip', false)
556
+		) {
557
+			EEH_Qtip_Loader::instance()->register_and_enqueue();
558
+		}
559
+	}
560
+
561
+
562
+	/**
563
+	 * assets that are used in the WordPress admin
564
+	 *
565
+	 * @since 4.9.62.p
566
+	 * @throws DuplicateCollectionIdentifierException
567
+	 * @throws InvalidDataTypeException
568
+	 * @throws InvalidEntityException
569
+	 */
570
+	private function registerAdminAssets()
571
+	{
572
+		$this->addJavascript(
573
+			CoreAssetManager::JS_HANDLE_WP_PLUGINS_PAGE,
574
+			$this->registry->getJsUrl($this->domain->assetNamespace(), 'wp-plugins-page'),
575
+			array(
576
+				CoreAssetManager::JS_HANDLE_JQUERY,
577
+				CoreAssetManager::JS_HANDLE_VENDOR,
578
+			)
579
+		)
580
+		->setRequiresTranslation();
581
+
582
+		$this->addStylesheet(
583
+			CoreAssetManager::JS_HANDLE_WP_PLUGINS_PAGE,
584
+			$this->registry->getCssUrl($this->domain->assetNamespace(), 'wp-plugins-page')
585
+		);
586
+	}
587 587
 }
Please login to merge, or discard this patch.