Completed
Branch models-cleanup/main (de94a1)
by
unknown
86:45 queued 77:08
created
core/db_classes/EE_Extra_Join.class.php 2 patches
Indentation   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -12,25 +12,25 @@
 block discarded – undo
12 12
 class EE_Extra_Join extends EE_Base_Class
13 13
 {
14 14
 
15
-    /**
16
-     * @param array $props_n_values
17
-     * @param null  $timezone
18
-     * @return EE_Extra_Join|mixed
19
-     */
20
-    public static function new_instance($props_n_values = array(), $timezone = '')
21
-    {
22
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone);
23
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone);
24
-    }
15
+	/**
16
+	 * @param array $props_n_values
17
+	 * @param null  $timezone
18
+	 * @return EE_Extra_Join|mixed
19
+	 */
20
+	public static function new_instance($props_n_values = array(), $timezone = '')
21
+	{
22
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone);
23
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone);
24
+	}
25 25
 
26 26
 
27
-    /**
28
-     * @param array $props_n_values
29
-     * @param null  $timezone
30
-     * @return EE_Extra_Join
31
-     */
32
-    public static function new_instance_from_db($props_n_values = array(), $timezone = '')
33
-    {
34
-        return new self($props_n_values, true, $timezone);
35
-    }
27
+	/**
28
+	 * @param array $props_n_values
29
+	 * @param null  $timezone
30
+	 * @return EE_Extra_Join
31
+	 */
32
+	public static function new_instance_from_db($props_n_values = array(), $timezone = '')
33
+	{
34
+		return new self($props_n_values, true, $timezone);
35
+	}
36 36
 }
Please login to merge, or discard this patch.
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -14,8 +14,8 @@  discard block
 block discarded – undo
14 14
 
15 15
     /**
16 16
      * @param array $props_n_values
17
-     * @param null  $timezone
18
-     * @return EE_Extra_Join|mixed
17
+     * @param string|null  $timezone
18
+     * @return EE_Base_Class
19 19
      */
20 20
     public static function new_instance($props_n_values = array(), $timezone = '')
21 21
     {
@@ -26,7 +26,7 @@  discard block
 block discarded – undo
26 26
 
27 27
     /**
28 28
      * @param array $props_n_values
29
-     * @param null  $timezone
29
+     * @param string|null  $timezone
30 30
      * @return EE_Extra_Join
31 31
      */
32 32
     public static function new_instance_from_db($props_n_values = array(), $timezone = '')
Please login to merge, or discard this patch.
core/db_classes/EE_Transaction.class.php 1 patch
Indentation   +1701 added lines, -1701 removed lines patch added patch discarded remove patch
@@ -13,1705 +13,1705 @@
 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 = '', $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 = '')
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 (
806
-                $registration instanceof EE_Registration
807
-                && ! in_array($registration->status_ID(), EEM_Registration::closed_reg_statuses(), true)
808
-            ) {
809
-                return $registration;
810
-            }
811
-        }
812
-        // nothing valid found, so just return first thing from array of results
813
-        return reset($registrations);
814
-    }
815
-
816
-
817
-    /**
818
-     * Gets the URL for viewing the receipt
819
-     *
820
-     * @param string $type 'pdf' or 'html' (default is 'html')
821
-     * @return string
822
-     * @throws EE_Error
823
-     * @throws InvalidArgumentException
824
-     * @throws InvalidDataTypeException
825
-     * @throws InvalidInterfaceException
826
-     * @throws ReflectionException
827
-     */
828
-    public function receipt_url($type = 'html')
829
-    {
830
-        $REG = $this->primary_registration();
831
-        if (! $REG instanceof EE_Registration) {
832
-            return '';
833
-        }
834
-        return $REG->receipt_url($type);
835
-    }
836
-
837
-
838
-    /**
839
-     * Gets the URL of the thank you page with this registration REG_url_link added as
840
-     * a query parameter
841
-     *
842
-     * @return string
843
-     * @throws EE_Error
844
-     * @throws InvalidArgumentException
845
-     * @throws InvalidDataTypeException
846
-     * @throws InvalidInterfaceException
847
-     * @throws ReflectionException
848
-     */
849
-    public function payment_overview_url()
850
-    {
851
-        $primary_registration = $this->primary_registration();
852
-        return $primary_registration instanceof EE_Registration ? $primary_registration->payment_overview_url() : false;
853
-    }
854
-
855
-
856
-    /**
857
-     * @return string
858
-     * @throws EE_Error
859
-     * @throws InvalidArgumentException
860
-     * @throws InvalidDataTypeException
861
-     * @throws InvalidInterfaceException
862
-     * @throws ReflectionException
863
-     */
864
-    public function gateway_response_on_transaction()
865
-    {
866
-        $payment = $this->get_first_related('Payment');
867
-        return $payment instanceof EE_Payment ? $payment->gateway_response() : '';
868
-    }
869
-
870
-
871
-    /**
872
-     * Get the status object of this object
873
-     *
874
-     * @return EE_Base_Class|EE_Status
875
-     * @throws EE_Error
876
-     * @throws InvalidArgumentException
877
-     * @throws InvalidDataTypeException
878
-     * @throws InvalidInterfaceException
879
-     * @throws ReflectionException
880
-     */
881
-    public function status_obj()
882
-    {
883
-        return $this->get_first_related('Status');
884
-    }
885
-
886
-
887
-    /**
888
-     * Gets all the extra meta info on this payment
889
-     *
890
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
891
-     * @return EE_Base_Class[]|EE_Extra_Meta
892
-     * @throws EE_Error
893
-     * @throws InvalidArgumentException
894
-     * @throws InvalidDataTypeException
895
-     * @throws InvalidInterfaceException
896
-     * @throws ReflectionException
897
-     */
898
-    public function extra_meta($query_params = array())
899
-    {
900
-        return $this->get_many_related('Extra_Meta', $query_params);
901
-    }
902
-
903
-
904
-    /**
905
-     * Wrapper for _add_relation_to
906
-     *
907
-     * @param EE_Registration $registration
908
-     * @return EE_Base_Class the relation was added to
909
-     * @throws EE_Error
910
-     * @throws InvalidArgumentException
911
-     * @throws InvalidDataTypeException
912
-     * @throws InvalidInterfaceException
913
-     * @throws ReflectionException
914
-     */
915
-    public function add_registration(EE_Registration $registration)
916
-    {
917
-        return $this->_add_relation_to($registration, 'Registration');
918
-    }
919
-
920
-
921
-    /**
922
-     * Removes the given registration from being related (even before saving this transaction).
923
-     * If an ID/index is provided and this transaction isn't saved yet, removes it from list of cached relations
924
-     *
925
-     * @param int $registration_or_id
926
-     * @return EE_Base_Class that was removed from being related
927
-     * @throws EE_Error
928
-     * @throws InvalidArgumentException
929
-     * @throws InvalidDataTypeException
930
-     * @throws InvalidInterfaceException
931
-     * @throws ReflectionException
932
-     */
933
-    public function remove_registration_with_id($registration_or_id)
934
-    {
935
-        return $this->_remove_relation_to($registration_or_id, 'Registration');
936
-    }
937
-
938
-
939
-    /**
940
-     * Gets all the line items which are for ACTUAL items
941
-     *
942
-     * @return EE_Line_Item[]
943
-     * @throws EE_Error
944
-     * @throws InvalidArgumentException
945
-     * @throws InvalidDataTypeException
946
-     * @throws InvalidInterfaceException
947
-     * @throws ReflectionException
948
-     */
949
-    public function items_purchased()
950
-    {
951
-        return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_line_item)));
952
-    }
953
-
954
-
955
-    /**
956
-     * Wrapper for _add_relation_to
957
-     *
958
-     * @param EE_Line_Item $line_item
959
-     * @return EE_Base_Class the relation was added to
960
-     * @throws EE_Error
961
-     * @throws InvalidArgumentException
962
-     * @throws InvalidDataTypeException
963
-     * @throws InvalidInterfaceException
964
-     * @throws ReflectionException
965
-     */
966
-    public function add_line_item(EE_Line_Item $line_item)
967
-    {
968
-        return $this->_add_relation_to($line_item, 'Line_Item');
969
-    }
970
-
971
-
972
-    /**
973
-     * Gets ALL the line items related to this transaction (unstructured)
974
-     *
975
-     * @param array $query_params
976
-     * @return EE_Base_Class[]|EE_Line_Item[]
977
-     * @throws EE_Error
978
-     * @throws InvalidArgumentException
979
-     * @throws InvalidDataTypeException
980
-     * @throws InvalidInterfaceException
981
-     * @throws ReflectionException
982
-     */
983
-    public function line_items($query_params = array())
984
-    {
985
-        return $this->get_many_related('Line_Item', $query_params);
986
-    }
987
-
988
-
989
-    /**
990
-     * Gets all the line items which are taxes on the total
991
-     *
992
-     * @return EE_Line_Item[]
993
-     * @throws EE_Error
994
-     * @throws InvalidArgumentException
995
-     * @throws InvalidDataTypeException
996
-     * @throws InvalidInterfaceException
997
-     * @throws ReflectionException
998
-     */
999
-    public function tax_items()
1000
-    {
1001
-        return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax)));
1002
-    }
1003
-
1004
-
1005
-    /**
1006
-     * Gets the total line item (which is a parent of all other related line items,
1007
-     * meaning it takes them all into account on its total)
1008
-     *
1009
-     * @param bool $create_if_not_found
1010
-     * @return \EE_Line_Item
1011
-     * @throws EE_Error
1012
-     * @throws InvalidArgumentException
1013
-     * @throws InvalidDataTypeException
1014
-     * @throws InvalidInterfaceException
1015
-     * @throws ReflectionException
1016
-     */
1017
-    public function total_line_item($create_if_not_found = true)
1018
-    {
1019
-        $item = $this->get_first_related('Line_Item', array(array('LIN_type' => EEM_Line_Item::type_total)));
1020
-        if (! $item && $create_if_not_found) {
1021
-            $item = EEH_Line_Item::create_total_line_item($this);
1022
-        }
1023
-        return $item;
1024
-    }
1025
-
1026
-
1027
-    /**
1028
-     * Returns the total amount of tax on this transaction
1029
-     * (assumes there's only one tax subtotal line item)
1030
-     *
1031
-     * @return float
1032
-     * @throws EE_Error
1033
-     * @throws InvalidArgumentException
1034
-     * @throws InvalidDataTypeException
1035
-     * @throws InvalidInterfaceException
1036
-     * @throws ReflectionException
1037
-     */
1038
-    public function tax_total()
1039
-    {
1040
-        $tax_line_item = $this->tax_total_line_item();
1041
-        if ($tax_line_item) {
1042
-            return (float) $tax_line_item->total();
1043
-        }
1044
-        return (float) 0;
1045
-    }
1046
-
1047
-
1048
-    /**
1049
-     * Gets the tax subtotal line item (assumes there's only one)
1050
-     *
1051
-     * @return EE_Line_Item
1052
-     * @throws EE_Error
1053
-     * @throws InvalidArgumentException
1054
-     * @throws InvalidDataTypeException
1055
-     * @throws InvalidInterfaceException
1056
-     * @throws ReflectionException
1057
-     */
1058
-    public function tax_total_line_item()
1059
-    {
1060
-        return EEH_Line_Item::get_taxes_subtotal($this->total_line_item());
1061
-    }
1062
-
1063
-
1064
-    /**
1065
-     * Gets the array of billing info for the gateway and for this transaction's primary registration's attendee.
1066
-     *
1067
-     * @return EE_Form_Section_Proper
1068
-     * @throws EE_Error
1069
-     * @throws InvalidArgumentException
1070
-     * @throws InvalidDataTypeException
1071
-     * @throws InvalidInterfaceException
1072
-     * @throws ReflectionException
1073
-     */
1074
-    public function billing_info()
1075
-    {
1076
-        $payment_method = $this->payment_method();
1077
-        if (! $payment_method) {
1078
-            EE_Error::add_error(
1079
-                __(
1080
-                    'Could not find billing info for transaction because no gateway has been used for it yet',
1081
-                    'event_espresso'
1082
-                ),
1083
-                __FILE__,
1084
-                __FUNCTION__,
1085
-                __LINE__
1086
-            );
1087
-            return null;
1088
-        }
1089
-        $primary_reg = $this->primary_registration();
1090
-        if (! $primary_reg) {
1091
-            EE_Error::add_error(
1092
-                __(
1093
-                    'Cannot get billing info for gateway %s on transaction because no primary registration exists',
1094
-                    'event_espresso'
1095
-                ),
1096
-                __FILE__,
1097
-                __FUNCTION__,
1098
-                __LINE__
1099
-            );
1100
-            return null;
1101
-        }
1102
-        $attendee = $primary_reg->attendee();
1103
-        if (! $attendee) {
1104
-            EE_Error::add_error(
1105
-                __(
1106
-                    'Cannot get billing info for gateway %s on transaction because the primary registration has no attendee exists',
1107
-                    'event_espresso'
1108
-                ),
1109
-                __FILE__,
1110
-                __FUNCTION__,
1111
-                __LINE__
1112
-            );
1113
-            return null;
1114
-        }
1115
-        return $attendee->billing_info_for_payment_method($payment_method);
1116
-    }
1117
-
1118
-
1119
-    /**
1120
-     * Gets PMD_ID
1121
-     *
1122
-     * @return int
1123
-     * @throws EE_Error
1124
-     * @throws InvalidArgumentException
1125
-     * @throws InvalidDataTypeException
1126
-     * @throws InvalidInterfaceException
1127
-     * @throws ReflectionException
1128
-     */
1129
-    public function payment_method_ID()
1130
-    {
1131
-        return $this->get('PMD_ID');
1132
-    }
1133
-
1134
-
1135
-    /**
1136
-     * Sets PMD_ID
1137
-     *
1138
-     * @param int $PMD_ID
1139
-     * @throws EE_Error
1140
-     * @throws InvalidArgumentException
1141
-     * @throws InvalidDataTypeException
1142
-     * @throws InvalidInterfaceException
1143
-     * @throws ReflectionException
1144
-     */
1145
-    public function set_payment_method_ID($PMD_ID)
1146
-    {
1147
-        $this->set('PMD_ID', $PMD_ID);
1148
-    }
1149
-
1150
-
1151
-    /**
1152
-     * Gets the last-used payment method on this transaction
1153
-     * (we COULD just use the last-made payment, but some payment methods, namely
1154
-     * offline ones, dont' create payments)
1155
-     *
1156
-     * @return EE_Payment_Method
1157
-     * @throws EE_Error
1158
-     * @throws InvalidArgumentException
1159
-     * @throws InvalidDataTypeException
1160
-     * @throws InvalidInterfaceException
1161
-     * @throws ReflectionException
1162
-     */
1163
-    public function payment_method()
1164
-    {
1165
-        $pm = $this->get_first_related('Payment_Method');
1166
-        if ($pm instanceof EE_Payment_Method) {
1167
-            return $pm;
1168
-        }
1169
-        $last_payment = $this->last_payment();
1170
-        if ($last_payment instanceof EE_Payment && $last_payment->payment_method()) {
1171
-            return $last_payment->payment_method();
1172
-        }
1173
-        return null;
1174
-    }
1175
-
1176
-
1177
-    /**
1178
-     * Gets the last payment made
1179
-     *
1180
-     * @return EE_Base_Class|EE_Payment
1181
-     * @throws EE_Error
1182
-     * @throws InvalidArgumentException
1183
-     * @throws InvalidDataTypeException
1184
-     * @throws InvalidInterfaceException
1185
-     * @throws ReflectionException
1186
-     */
1187
-    public function last_payment()
1188
-    {
1189
-        return $this->get_first_related('Payment', array('order_by' => array('PAY_ID' => 'desc')));
1190
-    }
1191
-
1192
-
1193
-    /**
1194
-     * Gets all the line items which are unrelated to tickets on this transaction
1195
-     *
1196
-     * @return EE_Line_Item[]
1197
-     * @throws EE_Error
1198
-     * @throws InvalidArgumentException
1199
-     * @throws InvalidDataTypeException
1200
-     * @throws InvalidInterfaceException
1201
-     * @throws ReflectionException
1202
-     */
1203
-    public function non_ticket_line_items()
1204
-    {
1205
-        return EEM_Line_Item::instance()->get_all_non_ticket_line_items_for_transaction($this->ID());
1206
-    }
1207
-
1208
-
1209
-    /**
1210
-     * possibly toggles TXN status
1211
-     *
1212
-     * @param  boolean $update whether to save the TXN
1213
-     * @return bool whether the TXN was saved
1214
-     * @throws EE_Error
1215
-     * @throws InvalidArgumentException
1216
-     * @throws InvalidDataTypeException
1217
-     * @throws InvalidInterfaceException
1218
-     * @throws ReflectionException
1219
-     * @throws RuntimeException
1220
-     */
1221
-    public function update_status_based_on_total_paid($update = true)
1222
-    {
1223
-        // set transaction status based on comparison of TXN_paid vs TXN_total
1224
-        if (EEH_Money::compare_floats($this->paid(), $this->total(), '>')) {
1225
-            $new_txn_status = EEM_Transaction::overpaid_status_code;
1226
-        } elseif (EEH_Money::compare_floats($this->paid(), $this->total())) {
1227
-            $new_txn_status = EEM_Transaction::complete_status_code;
1228
-        } elseif (EEH_Money::compare_floats($this->paid(), $this->total(), '<')) {
1229
-            $new_txn_status = EEM_Transaction::incomplete_status_code;
1230
-        } else {
1231
-            throw new RuntimeException(
1232
-                __('The total paid calculation for this transaction is inaccurate.', 'event_espresso')
1233
-            );
1234
-        }
1235
-        if ($new_txn_status !== $this->status_ID()) {
1236
-            $this->set_status($new_txn_status);
1237
-            if ($update) {
1238
-                return $this->save() ? true : false;
1239
-            }
1240
-        }
1241
-        return false;
1242
-    }
1243
-
1244
-
1245
-    /**
1246
-     * Updates the transaction's status and total_paid based on all the payments
1247
-     * that apply to it
1248
-     *
1249
-     * @deprecated
1250
-     * @return array|bool
1251
-     * @throws EE_Error
1252
-     * @throws InvalidArgumentException
1253
-     * @throws ReflectionException
1254
-     * @throws InvalidDataTypeException
1255
-     * @throws InvalidInterfaceException
1256
-     */
1257
-    public function update_based_on_payments()
1258
-    {
1259
-        EE_Error::doing_it_wrong(
1260
-            __CLASS__ . '::' . __FUNCTION__,
1261
-            sprintf(
1262
-                __('This method is deprecated. Please use "%s" instead', 'event_espresso'),
1263
-                'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'
1264
-            ),
1265
-            '4.6.0'
1266
-        );
1267
-        /** @type EE_Transaction_Processor $transaction_processor */
1268
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
1269
-        return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment($this);
1270
-    }
1271
-
1272
-
1273
-    /**
1274
-     * @return string
1275
-     */
1276
-    public function old_txn_status()
1277
-    {
1278
-        return $this->_old_txn_status;
1279
-    }
1280
-
1281
-
1282
-    /**
1283
-     * @param string $old_txn_status
1284
-     */
1285
-    public function set_old_txn_status($old_txn_status)
1286
-    {
1287
-        // only set the first time
1288
-        if ($this->_old_txn_status === null) {
1289
-            $this->_old_txn_status = $old_txn_status;
1290
-        }
1291
-    }
1292
-
1293
-
1294
-    /**
1295
-     * reg_status_updated
1296
-     *
1297
-     * @return bool
1298
-     * @throws EE_Error
1299
-     * @throws InvalidArgumentException
1300
-     * @throws InvalidDataTypeException
1301
-     * @throws InvalidInterfaceException
1302
-     * @throws ReflectionException
1303
-     */
1304
-    public function txn_status_updated()
1305
-    {
1306
-        return $this->status_ID() !== $this->_old_txn_status && $this->_old_txn_status !== null;
1307
-    }
1308
-
1309
-
1310
-    /**
1311
-     * _reg_steps_completed
1312
-     * if $check_all is TRUE, then returns TRUE if ALL reg steps have been marked as completed,
1313
-     * if a $reg_step_slug is provided, then this step will be skipped when testing for completion
1314
-     * if $check_all is FALSE and a $reg_step_slug is provided, then ONLY that reg step will be tested for completion
1315
-     *
1316
-     * @param string $reg_step_slug
1317
-     * @param bool   $check_all
1318
-     * @return bool|int
1319
-     * @throws EE_Error
1320
-     * @throws InvalidArgumentException
1321
-     * @throws InvalidDataTypeException
1322
-     * @throws InvalidInterfaceException
1323
-     * @throws ReflectionException
1324
-     */
1325
-    private function _reg_steps_completed($reg_step_slug = '', $check_all = true)
1326
-    {
1327
-        $reg_steps = $this->reg_steps();
1328
-        if (! is_array($reg_steps) || empty($reg_steps)) {
1329
-            return false;
1330
-        }
1331
-        // loop thru reg steps array)
1332
-        foreach ($reg_steps as $slug => $reg_step_completed) {
1333
-            // if NOT checking ALL steps (only checking one step)
1334
-            if (! $check_all) {
1335
-                // and this is the one
1336
-                if ($slug === $reg_step_slug) {
1337
-                    return $reg_step_completed;
1338
-                }
1339
-                // skip to next reg step in loop
1340
-                continue;
1341
-            }
1342
-            // $check_all must be true, else we would never have gotten to this point
1343
-            if ($slug === $reg_step_slug) {
1344
-                // if we reach this point, then we are testing either:
1345
-                // all_reg_steps_completed_except() or
1346
-                // all_reg_steps_completed_except_final_step(),
1347
-                // and since this is the reg step EXCEPTION being tested
1348
-                // we want to return true (yes true) if this reg step is NOT completed
1349
-                // ie: "is everything completed except the final step?"
1350
-                // "that is correct... the final step is not completed, but all others are."
1351
-                return $reg_step_completed !== true;
1352
-            }
1353
-            if ($reg_step_completed !== true) {
1354
-                // if any reg step is NOT completed, then ALL steps are not completed
1355
-                return false;
1356
-            }
1357
-        }
1358
-        return true;
1359
-    }
1360
-
1361
-
1362
-    /**
1363
-     * all_reg_steps_completed
1364
-     * returns:
1365
-     *    true if ALL reg steps have been marked as completed
1366
-     *        or false if any step is not completed
1367
-     *
1368
-     * @return bool
1369
-     * @throws EE_Error
1370
-     * @throws InvalidArgumentException
1371
-     * @throws InvalidDataTypeException
1372
-     * @throws InvalidInterfaceException
1373
-     * @throws ReflectionException
1374
-     */
1375
-    public function all_reg_steps_completed()
1376
-    {
1377
-        return $this->_reg_steps_completed();
1378
-    }
1379
-
1380
-
1381
-    /**
1382
-     * all_reg_steps_completed_except
1383
-     * returns:
1384
-     *        true if ALL reg steps, except a particular step that you wish to skip over, have been marked as completed
1385
-     *        or false if any other step is not completed
1386
-     *        or false if ALL steps are completed including the exception you are testing !!!
1387
-     *
1388
-     * @param string $exception
1389
-     * @return bool
1390
-     * @throws EE_Error
1391
-     * @throws InvalidArgumentException
1392
-     * @throws InvalidDataTypeException
1393
-     * @throws InvalidInterfaceException
1394
-     * @throws ReflectionException
1395
-     */
1396
-    public function all_reg_steps_completed_except($exception = '')
1397
-    {
1398
-        return $this->_reg_steps_completed($exception);
1399
-    }
1400
-
1401
-
1402
-    /**
1403
-     * all_reg_steps_completed_except
1404
-     * returns:
1405
-     *        true if ALL reg steps, except the final step, have been marked as completed
1406
-     *        or false if any step is not completed
1407
-     *    or false if ALL steps are completed including the final step !!!
1408
-     *
1409
-     * @return bool
1410
-     * @throws EE_Error
1411
-     * @throws InvalidArgumentException
1412
-     * @throws InvalidDataTypeException
1413
-     * @throws InvalidInterfaceException
1414
-     * @throws ReflectionException
1415
-     */
1416
-    public function all_reg_steps_completed_except_final_step()
1417
-    {
1418
-        return $this->_reg_steps_completed('finalize_registration');
1419
-    }
1420
-
1421
-
1422
-    /**
1423
-     * reg_step_completed
1424
-     * returns:
1425
-     *    true if a specific reg step has been marked as completed
1426
-     *    a Unix timestamp if it has been initialized but not yet completed,
1427
-     *    or false if it has not yet been initialized
1428
-     *
1429
-     * @param string $reg_step_slug
1430
-     * @return bool|int
1431
-     * @throws EE_Error
1432
-     * @throws InvalidArgumentException
1433
-     * @throws InvalidDataTypeException
1434
-     * @throws InvalidInterfaceException
1435
-     * @throws ReflectionException
1436
-     */
1437
-    public function reg_step_completed($reg_step_slug)
1438
-    {
1439
-        return $this->_reg_steps_completed($reg_step_slug, false);
1440
-    }
1441
-
1442
-
1443
-    /**
1444
-     * completed_final_reg_step
1445
-     * returns:
1446
-     *    true if the finalize_registration reg step has been marked as completed
1447
-     *    a Unix timestamp if it has been initialized but not yet completed,
1448
-     *    or false if it has not yet been initialized
1449
-     *
1450
-     * @return bool|int
1451
-     * @throws EE_Error
1452
-     * @throws InvalidArgumentException
1453
-     * @throws InvalidDataTypeException
1454
-     * @throws InvalidInterfaceException
1455
-     * @throws ReflectionException
1456
-     */
1457
-    public function final_reg_step_completed()
1458
-    {
1459
-        return $this->_reg_steps_completed('finalize_registration', false);
1460
-    }
1461
-
1462
-
1463
-    /**
1464
-     * set_reg_step_initiated
1465
-     * given a valid TXN_reg_step, this sets it's value to a unix timestamp
1466
-     *
1467
-     * @param string $reg_step_slug
1468
-     * @return boolean
1469
-     * @throws EE_Error
1470
-     * @throws InvalidArgumentException
1471
-     * @throws InvalidDataTypeException
1472
-     * @throws InvalidInterfaceException
1473
-     * @throws ReflectionException
1474
-     */
1475
-    public function set_reg_step_initiated($reg_step_slug)
1476
-    {
1477
-        return $this->_set_reg_step_completed_status($reg_step_slug, time());
1478
-    }
1479
-
1480
-
1481
-    /**
1482
-     * set_reg_step_completed
1483
-     * given a valid TXN_reg_step, this sets the step as completed
1484
-     *
1485
-     * @param string $reg_step_slug
1486
-     * @return boolean
1487
-     * @throws EE_Error
1488
-     * @throws InvalidArgumentException
1489
-     * @throws InvalidDataTypeException
1490
-     * @throws InvalidInterfaceException
1491
-     * @throws ReflectionException
1492
-     */
1493
-    public function set_reg_step_completed($reg_step_slug)
1494
-    {
1495
-        return $this->_set_reg_step_completed_status($reg_step_slug, true);
1496
-    }
1497
-
1498
-
1499
-    /**
1500
-     * set_reg_step_completed
1501
-     * given a valid TXN_reg_step slug, this sets the step as NOT completed
1502
-     *
1503
-     * @param string $reg_step_slug
1504
-     * @return boolean
1505
-     * @throws EE_Error
1506
-     * @throws InvalidArgumentException
1507
-     * @throws InvalidDataTypeException
1508
-     * @throws InvalidInterfaceException
1509
-     * @throws ReflectionException
1510
-     */
1511
-    public function set_reg_step_not_completed($reg_step_slug)
1512
-    {
1513
-        return $this->_set_reg_step_completed_status($reg_step_slug, false);
1514
-    }
1515
-
1516
-
1517
-    /**
1518
-     * set_reg_step_completed
1519
-     * given a valid reg step slug, this sets the TXN_reg_step completed status which is either:
1520
-     *
1521
-     * @param  string      $reg_step_slug
1522
-     * @param  boolean|int $status
1523
-     * @return boolean
1524
-     * @throws EE_Error
1525
-     * @throws InvalidArgumentException
1526
-     * @throws InvalidDataTypeException
1527
-     * @throws InvalidInterfaceException
1528
-     * @throws ReflectionException
1529
-     */
1530
-    private function _set_reg_step_completed_status($reg_step_slug, $status)
1531
-    {
1532
-        // validate status
1533
-        $status = is_bool($status) || is_int($status) ? $status : false;
1534
-        // get reg steps array
1535
-        $txn_reg_steps = $this->reg_steps();
1536
-        // if reg step does NOT exist
1537
-        if (! isset($txn_reg_steps[ $reg_step_slug ])) {
1538
-            return false;
1539
-        }
1540
-        // if  we're trying to complete a step that is already completed
1541
-        if ($txn_reg_steps[ $reg_step_slug ] === true) {
1542
-            return true;
1543
-        }
1544
-        // if  we're trying to complete a step that hasn't even started
1545
-        if ($status === true && $txn_reg_steps[ $reg_step_slug ] === false) {
1546
-            return false;
1547
-        }
1548
-        // if current status value matches the incoming value (no change)
1549
-        // type casting as int means values should collapse to either 0, 1, or a timestamp like 1234567890
1550
-        if ((int) $txn_reg_steps[ $reg_step_slug ] === (int) $status) {
1551
-            // this will happen in cases where multiple AJAX requests occur during the same step
1552
-            return true;
1553
-        }
1554
-        // if we're trying to set a start time, but it has already been set...
1555
-        if (is_numeric($status) && is_numeric($txn_reg_steps[ $reg_step_slug ])) {
1556
-            // skip the update below, but don't return FALSE so that errors won't be displayed
1557
-            return true;
1558
-        }
1559
-        // update completed status
1560
-        $txn_reg_steps[ $reg_step_slug ] = $status;
1561
-        $this->set_reg_steps($txn_reg_steps);
1562
-        $this->save();
1563
-        return true;
1564
-    }
1565
-
1566
-
1567
-    /**
1568
-     * remove_reg_step
1569
-     * given a valid TXN_reg_step slug, this will remove (unset)
1570
-     * the reg step from the TXN reg step array
1571
-     *
1572
-     * @param string $reg_step_slug
1573
-     * @return void
1574
-     * @throws EE_Error
1575
-     * @throws InvalidArgumentException
1576
-     * @throws InvalidDataTypeException
1577
-     * @throws InvalidInterfaceException
1578
-     * @throws ReflectionException
1579
-     */
1580
-    public function remove_reg_step($reg_step_slug)
1581
-    {
1582
-        // get reg steps array
1583
-        $txn_reg_steps = $this->reg_steps();
1584
-        unset($txn_reg_steps[ $reg_step_slug ]);
1585
-        $this->set_reg_steps($txn_reg_steps);
1586
-    }
1587
-
1588
-
1589
-    /**
1590
-     * toggle_failed_transaction_status
1591
-     * upgrades a TXNs status from failed to abandoned,
1592
-     * meaning that contact information has been captured for at least one registrant
1593
-     *
1594
-     * @param bool $save
1595
-     * @return bool
1596
-     * @throws EE_Error
1597
-     * @throws InvalidArgumentException
1598
-     * @throws InvalidDataTypeException
1599
-     * @throws InvalidInterfaceException
1600
-     * @throws ReflectionException
1601
-     */
1602
-    public function toggle_failed_transaction_status($save = true)
1603
-    {
1604
-        // if TXN status is still set as "failed"...
1605
-        if ($this->status_ID() === EEM_Transaction::failed_status_code) {
1606
-            $this->set_status(EEM_Transaction::abandoned_status_code);
1607
-            if ($save) {
1608
-                $this->save();
1609
-            }
1610
-            return true;
1611
-        }
1612
-        return false;
1613
-    }
1614
-
1615
-
1616
-    /**
1617
-     * toggle_abandoned_transaction_status
1618
-     * upgrades a TXNs status from failed or abandoned to incomplete
1619
-     *
1620
-     * @return bool
1621
-     * @throws EE_Error
1622
-     * @throws InvalidArgumentException
1623
-     * @throws InvalidDataTypeException
1624
-     * @throws InvalidInterfaceException
1625
-     * @throws ReflectionException
1626
-     */
1627
-    public function toggle_abandoned_transaction_status()
1628
-    {
1629
-        // if TXN status has not been updated already due to a payment, and is still set as "failed" or "abandoned"...
1630
-        $txn_status = $this->status_ID();
1631
-        if (
1632
-            $txn_status === EEM_Transaction::failed_status_code
1633
-            || $txn_status === EEM_Transaction::abandoned_status_code
1634
-        ) {
1635
-            // if a contact record for the primary registrant has been created
1636
-            if (
1637
-                $this->primary_registration() instanceof EE_Registration
1638
-                && $this->primary_registration()->attendee() instanceof EE_Attendee
1639
-            ) {
1640
-                $this->set_status(EEM_Transaction::incomplete_status_code);
1641
-            } else {
1642
-                // no contact record? yer abandoned!
1643
-                $this->set_status(EEM_Transaction::abandoned_status_code);
1644
-            }
1645
-            return true;
1646
-        }
1647
-        return false;
1648
-    }
1649
-
1650
-
1651
-    /**
1652
-     * checks if an Abandoned TXN has any related payments, and if so,
1653
-     * updates the TXN status based on the amount paid
1654
-     *
1655
-     * @throws EE_Error
1656
-     * @throws InvalidDataTypeException
1657
-     * @throws InvalidInterfaceException
1658
-     * @throws InvalidArgumentException
1659
-     * @throws RuntimeException
1660
-     * @throws ReflectionException
1661
-     */
1662
-    public function verify_abandoned_transaction_status()
1663
-    {
1664
-        if ($this->status_ID() !== EEM_Transaction::abandoned_status_code) {
1665
-            return;
1666
-        }
1667
-        $payments = $this->get_many_related('Payment');
1668
-        if (! empty($payments)) {
1669
-            foreach ($payments as $payment) {
1670
-                if ($payment instanceof EE_Payment) {
1671
-                    // kk this TXN should NOT be abandoned
1672
-                    $this->update_status_based_on_total_paid();
1673
-                    if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1674
-                        EE_Error::add_attention(
1675
-                            sprintf(
1676
-                                esc_html__(
1677
-                                    '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.',
1678
-                                    'event_espresso'
1679
-                                ),
1680
-                                $this->ID(),
1681
-                                $this->pretty_status()
1682
-                            )
1683
-                        );
1684
-                    }
1685
-                    // get final reg step status
1686
-                    $finalized = $this->final_reg_step_completed();
1687
-                    // if the 'finalize_registration' step has been initiated (has a timestamp)
1688
-                    // but has not yet been fully completed (TRUE)
1689
-                    if (is_int($finalized) && $finalized !== false && $finalized !== true) {
1690
-                        $this->set_reg_step_completed('finalize_registration');
1691
-                        $this->save();
1692
-                    }
1693
-                }
1694
-            }
1695
-        }
1696
-    }
1697
-
1698
-
1699
-    /**
1700
-     * @since 4.10.4.p
1701
-     * @throws EE_Error
1702
-     * @throws InvalidArgumentException
1703
-     * @throws InvalidDataTypeException
1704
-     * @throws InvalidInterfaceException
1705
-     * @throws ReflectionException
1706
-     * @throws RuntimeException
1707
-     */
1708
-    public function recalculateLineItems()
1709
-    {
1710
-        $total_line_item = $this->total_line_item(false);
1711
-        if ($total_line_item instanceof EE_Line_Item) {
1712
-            EEH_Line_Item::resetIsTaxableForTickets($total_line_item);
1713
-            return EEH_Line_Item::apply_taxes($total_line_item, true);
1714
-        }
1715
-        return false;
1716
-    }
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 = '', $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 = '')
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 (
806
+				$registration instanceof EE_Registration
807
+				&& ! in_array($registration->status_ID(), EEM_Registration::closed_reg_statuses(), true)
808
+			) {
809
+				return $registration;
810
+			}
811
+		}
812
+		// nothing valid found, so just return first thing from array of results
813
+		return reset($registrations);
814
+	}
815
+
816
+
817
+	/**
818
+	 * Gets the URL for viewing the receipt
819
+	 *
820
+	 * @param string $type 'pdf' or 'html' (default is 'html')
821
+	 * @return string
822
+	 * @throws EE_Error
823
+	 * @throws InvalidArgumentException
824
+	 * @throws InvalidDataTypeException
825
+	 * @throws InvalidInterfaceException
826
+	 * @throws ReflectionException
827
+	 */
828
+	public function receipt_url($type = 'html')
829
+	{
830
+		$REG = $this->primary_registration();
831
+		if (! $REG instanceof EE_Registration) {
832
+			return '';
833
+		}
834
+		return $REG->receipt_url($type);
835
+	}
836
+
837
+
838
+	/**
839
+	 * Gets the URL of the thank you page with this registration REG_url_link added as
840
+	 * a query parameter
841
+	 *
842
+	 * @return string
843
+	 * @throws EE_Error
844
+	 * @throws InvalidArgumentException
845
+	 * @throws InvalidDataTypeException
846
+	 * @throws InvalidInterfaceException
847
+	 * @throws ReflectionException
848
+	 */
849
+	public function payment_overview_url()
850
+	{
851
+		$primary_registration = $this->primary_registration();
852
+		return $primary_registration instanceof EE_Registration ? $primary_registration->payment_overview_url() : false;
853
+	}
854
+
855
+
856
+	/**
857
+	 * @return string
858
+	 * @throws EE_Error
859
+	 * @throws InvalidArgumentException
860
+	 * @throws InvalidDataTypeException
861
+	 * @throws InvalidInterfaceException
862
+	 * @throws ReflectionException
863
+	 */
864
+	public function gateway_response_on_transaction()
865
+	{
866
+		$payment = $this->get_first_related('Payment');
867
+		return $payment instanceof EE_Payment ? $payment->gateway_response() : '';
868
+	}
869
+
870
+
871
+	/**
872
+	 * Get the status object of this object
873
+	 *
874
+	 * @return EE_Base_Class|EE_Status
875
+	 * @throws EE_Error
876
+	 * @throws InvalidArgumentException
877
+	 * @throws InvalidDataTypeException
878
+	 * @throws InvalidInterfaceException
879
+	 * @throws ReflectionException
880
+	 */
881
+	public function status_obj()
882
+	{
883
+		return $this->get_first_related('Status');
884
+	}
885
+
886
+
887
+	/**
888
+	 * Gets all the extra meta info on this payment
889
+	 *
890
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
891
+	 * @return EE_Base_Class[]|EE_Extra_Meta
892
+	 * @throws EE_Error
893
+	 * @throws InvalidArgumentException
894
+	 * @throws InvalidDataTypeException
895
+	 * @throws InvalidInterfaceException
896
+	 * @throws ReflectionException
897
+	 */
898
+	public function extra_meta($query_params = array())
899
+	{
900
+		return $this->get_many_related('Extra_Meta', $query_params);
901
+	}
902
+
903
+
904
+	/**
905
+	 * Wrapper for _add_relation_to
906
+	 *
907
+	 * @param EE_Registration $registration
908
+	 * @return EE_Base_Class the relation was added to
909
+	 * @throws EE_Error
910
+	 * @throws InvalidArgumentException
911
+	 * @throws InvalidDataTypeException
912
+	 * @throws InvalidInterfaceException
913
+	 * @throws ReflectionException
914
+	 */
915
+	public function add_registration(EE_Registration $registration)
916
+	{
917
+		return $this->_add_relation_to($registration, 'Registration');
918
+	}
919
+
920
+
921
+	/**
922
+	 * Removes the given registration from being related (even before saving this transaction).
923
+	 * If an ID/index is provided and this transaction isn't saved yet, removes it from list of cached relations
924
+	 *
925
+	 * @param int $registration_or_id
926
+	 * @return EE_Base_Class that was removed from being related
927
+	 * @throws EE_Error
928
+	 * @throws InvalidArgumentException
929
+	 * @throws InvalidDataTypeException
930
+	 * @throws InvalidInterfaceException
931
+	 * @throws ReflectionException
932
+	 */
933
+	public function remove_registration_with_id($registration_or_id)
934
+	{
935
+		return $this->_remove_relation_to($registration_or_id, 'Registration');
936
+	}
937
+
938
+
939
+	/**
940
+	 * Gets all the line items which are for ACTUAL items
941
+	 *
942
+	 * @return EE_Line_Item[]
943
+	 * @throws EE_Error
944
+	 * @throws InvalidArgumentException
945
+	 * @throws InvalidDataTypeException
946
+	 * @throws InvalidInterfaceException
947
+	 * @throws ReflectionException
948
+	 */
949
+	public function items_purchased()
950
+	{
951
+		return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_line_item)));
952
+	}
953
+
954
+
955
+	/**
956
+	 * Wrapper for _add_relation_to
957
+	 *
958
+	 * @param EE_Line_Item $line_item
959
+	 * @return EE_Base_Class the relation was added to
960
+	 * @throws EE_Error
961
+	 * @throws InvalidArgumentException
962
+	 * @throws InvalidDataTypeException
963
+	 * @throws InvalidInterfaceException
964
+	 * @throws ReflectionException
965
+	 */
966
+	public function add_line_item(EE_Line_Item $line_item)
967
+	{
968
+		return $this->_add_relation_to($line_item, 'Line_Item');
969
+	}
970
+
971
+
972
+	/**
973
+	 * Gets ALL the line items related to this transaction (unstructured)
974
+	 *
975
+	 * @param array $query_params
976
+	 * @return EE_Base_Class[]|EE_Line_Item[]
977
+	 * @throws EE_Error
978
+	 * @throws InvalidArgumentException
979
+	 * @throws InvalidDataTypeException
980
+	 * @throws InvalidInterfaceException
981
+	 * @throws ReflectionException
982
+	 */
983
+	public function line_items($query_params = array())
984
+	{
985
+		return $this->get_many_related('Line_Item', $query_params);
986
+	}
987
+
988
+
989
+	/**
990
+	 * Gets all the line items which are taxes on the total
991
+	 *
992
+	 * @return EE_Line_Item[]
993
+	 * @throws EE_Error
994
+	 * @throws InvalidArgumentException
995
+	 * @throws InvalidDataTypeException
996
+	 * @throws InvalidInterfaceException
997
+	 * @throws ReflectionException
998
+	 */
999
+	public function tax_items()
1000
+	{
1001
+		return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax)));
1002
+	}
1003
+
1004
+
1005
+	/**
1006
+	 * Gets the total line item (which is a parent of all other related line items,
1007
+	 * meaning it takes them all into account on its total)
1008
+	 *
1009
+	 * @param bool $create_if_not_found
1010
+	 * @return \EE_Line_Item
1011
+	 * @throws EE_Error
1012
+	 * @throws InvalidArgumentException
1013
+	 * @throws InvalidDataTypeException
1014
+	 * @throws InvalidInterfaceException
1015
+	 * @throws ReflectionException
1016
+	 */
1017
+	public function total_line_item($create_if_not_found = true)
1018
+	{
1019
+		$item = $this->get_first_related('Line_Item', array(array('LIN_type' => EEM_Line_Item::type_total)));
1020
+		if (! $item && $create_if_not_found) {
1021
+			$item = EEH_Line_Item::create_total_line_item($this);
1022
+		}
1023
+		return $item;
1024
+	}
1025
+
1026
+
1027
+	/**
1028
+	 * Returns the total amount of tax on this transaction
1029
+	 * (assumes there's only one tax subtotal line item)
1030
+	 *
1031
+	 * @return float
1032
+	 * @throws EE_Error
1033
+	 * @throws InvalidArgumentException
1034
+	 * @throws InvalidDataTypeException
1035
+	 * @throws InvalidInterfaceException
1036
+	 * @throws ReflectionException
1037
+	 */
1038
+	public function tax_total()
1039
+	{
1040
+		$tax_line_item = $this->tax_total_line_item();
1041
+		if ($tax_line_item) {
1042
+			return (float) $tax_line_item->total();
1043
+		}
1044
+		return (float) 0;
1045
+	}
1046
+
1047
+
1048
+	/**
1049
+	 * Gets the tax subtotal line item (assumes there's only one)
1050
+	 *
1051
+	 * @return EE_Line_Item
1052
+	 * @throws EE_Error
1053
+	 * @throws InvalidArgumentException
1054
+	 * @throws InvalidDataTypeException
1055
+	 * @throws InvalidInterfaceException
1056
+	 * @throws ReflectionException
1057
+	 */
1058
+	public function tax_total_line_item()
1059
+	{
1060
+		return EEH_Line_Item::get_taxes_subtotal($this->total_line_item());
1061
+	}
1062
+
1063
+
1064
+	/**
1065
+	 * Gets the array of billing info for the gateway and for this transaction's primary registration's attendee.
1066
+	 *
1067
+	 * @return EE_Form_Section_Proper
1068
+	 * @throws EE_Error
1069
+	 * @throws InvalidArgumentException
1070
+	 * @throws InvalidDataTypeException
1071
+	 * @throws InvalidInterfaceException
1072
+	 * @throws ReflectionException
1073
+	 */
1074
+	public function billing_info()
1075
+	{
1076
+		$payment_method = $this->payment_method();
1077
+		if (! $payment_method) {
1078
+			EE_Error::add_error(
1079
+				__(
1080
+					'Could not find billing info for transaction because no gateway has been used for it yet',
1081
+					'event_espresso'
1082
+				),
1083
+				__FILE__,
1084
+				__FUNCTION__,
1085
+				__LINE__
1086
+			);
1087
+			return null;
1088
+		}
1089
+		$primary_reg = $this->primary_registration();
1090
+		if (! $primary_reg) {
1091
+			EE_Error::add_error(
1092
+				__(
1093
+					'Cannot get billing info for gateway %s on transaction because no primary registration exists',
1094
+					'event_espresso'
1095
+				),
1096
+				__FILE__,
1097
+				__FUNCTION__,
1098
+				__LINE__
1099
+			);
1100
+			return null;
1101
+		}
1102
+		$attendee = $primary_reg->attendee();
1103
+		if (! $attendee) {
1104
+			EE_Error::add_error(
1105
+				__(
1106
+					'Cannot get billing info for gateway %s on transaction because the primary registration has no attendee exists',
1107
+					'event_espresso'
1108
+				),
1109
+				__FILE__,
1110
+				__FUNCTION__,
1111
+				__LINE__
1112
+			);
1113
+			return null;
1114
+		}
1115
+		return $attendee->billing_info_for_payment_method($payment_method);
1116
+	}
1117
+
1118
+
1119
+	/**
1120
+	 * Gets PMD_ID
1121
+	 *
1122
+	 * @return int
1123
+	 * @throws EE_Error
1124
+	 * @throws InvalidArgumentException
1125
+	 * @throws InvalidDataTypeException
1126
+	 * @throws InvalidInterfaceException
1127
+	 * @throws ReflectionException
1128
+	 */
1129
+	public function payment_method_ID()
1130
+	{
1131
+		return $this->get('PMD_ID');
1132
+	}
1133
+
1134
+
1135
+	/**
1136
+	 * Sets PMD_ID
1137
+	 *
1138
+	 * @param int $PMD_ID
1139
+	 * @throws EE_Error
1140
+	 * @throws InvalidArgumentException
1141
+	 * @throws InvalidDataTypeException
1142
+	 * @throws InvalidInterfaceException
1143
+	 * @throws ReflectionException
1144
+	 */
1145
+	public function set_payment_method_ID($PMD_ID)
1146
+	{
1147
+		$this->set('PMD_ID', $PMD_ID);
1148
+	}
1149
+
1150
+
1151
+	/**
1152
+	 * Gets the last-used payment method on this transaction
1153
+	 * (we COULD just use the last-made payment, but some payment methods, namely
1154
+	 * offline ones, dont' create payments)
1155
+	 *
1156
+	 * @return EE_Payment_Method
1157
+	 * @throws EE_Error
1158
+	 * @throws InvalidArgumentException
1159
+	 * @throws InvalidDataTypeException
1160
+	 * @throws InvalidInterfaceException
1161
+	 * @throws ReflectionException
1162
+	 */
1163
+	public function payment_method()
1164
+	{
1165
+		$pm = $this->get_first_related('Payment_Method');
1166
+		if ($pm instanceof EE_Payment_Method) {
1167
+			return $pm;
1168
+		}
1169
+		$last_payment = $this->last_payment();
1170
+		if ($last_payment instanceof EE_Payment && $last_payment->payment_method()) {
1171
+			return $last_payment->payment_method();
1172
+		}
1173
+		return null;
1174
+	}
1175
+
1176
+
1177
+	/**
1178
+	 * Gets the last payment made
1179
+	 *
1180
+	 * @return EE_Base_Class|EE_Payment
1181
+	 * @throws EE_Error
1182
+	 * @throws InvalidArgumentException
1183
+	 * @throws InvalidDataTypeException
1184
+	 * @throws InvalidInterfaceException
1185
+	 * @throws ReflectionException
1186
+	 */
1187
+	public function last_payment()
1188
+	{
1189
+		return $this->get_first_related('Payment', array('order_by' => array('PAY_ID' => 'desc')));
1190
+	}
1191
+
1192
+
1193
+	/**
1194
+	 * Gets all the line items which are unrelated to tickets on this transaction
1195
+	 *
1196
+	 * @return EE_Line_Item[]
1197
+	 * @throws EE_Error
1198
+	 * @throws InvalidArgumentException
1199
+	 * @throws InvalidDataTypeException
1200
+	 * @throws InvalidInterfaceException
1201
+	 * @throws ReflectionException
1202
+	 */
1203
+	public function non_ticket_line_items()
1204
+	{
1205
+		return EEM_Line_Item::instance()->get_all_non_ticket_line_items_for_transaction($this->ID());
1206
+	}
1207
+
1208
+
1209
+	/**
1210
+	 * possibly toggles TXN status
1211
+	 *
1212
+	 * @param  boolean $update whether to save the TXN
1213
+	 * @return bool whether the TXN was saved
1214
+	 * @throws EE_Error
1215
+	 * @throws InvalidArgumentException
1216
+	 * @throws InvalidDataTypeException
1217
+	 * @throws InvalidInterfaceException
1218
+	 * @throws ReflectionException
1219
+	 * @throws RuntimeException
1220
+	 */
1221
+	public function update_status_based_on_total_paid($update = true)
1222
+	{
1223
+		// set transaction status based on comparison of TXN_paid vs TXN_total
1224
+		if (EEH_Money::compare_floats($this->paid(), $this->total(), '>')) {
1225
+			$new_txn_status = EEM_Transaction::overpaid_status_code;
1226
+		} elseif (EEH_Money::compare_floats($this->paid(), $this->total())) {
1227
+			$new_txn_status = EEM_Transaction::complete_status_code;
1228
+		} elseif (EEH_Money::compare_floats($this->paid(), $this->total(), '<')) {
1229
+			$new_txn_status = EEM_Transaction::incomplete_status_code;
1230
+		} else {
1231
+			throw new RuntimeException(
1232
+				__('The total paid calculation for this transaction is inaccurate.', 'event_espresso')
1233
+			);
1234
+		}
1235
+		if ($new_txn_status !== $this->status_ID()) {
1236
+			$this->set_status($new_txn_status);
1237
+			if ($update) {
1238
+				return $this->save() ? true : false;
1239
+			}
1240
+		}
1241
+		return false;
1242
+	}
1243
+
1244
+
1245
+	/**
1246
+	 * Updates the transaction's status and total_paid based on all the payments
1247
+	 * that apply to it
1248
+	 *
1249
+	 * @deprecated
1250
+	 * @return array|bool
1251
+	 * @throws EE_Error
1252
+	 * @throws InvalidArgumentException
1253
+	 * @throws ReflectionException
1254
+	 * @throws InvalidDataTypeException
1255
+	 * @throws InvalidInterfaceException
1256
+	 */
1257
+	public function update_based_on_payments()
1258
+	{
1259
+		EE_Error::doing_it_wrong(
1260
+			__CLASS__ . '::' . __FUNCTION__,
1261
+			sprintf(
1262
+				__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
1263
+				'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'
1264
+			),
1265
+			'4.6.0'
1266
+		);
1267
+		/** @type EE_Transaction_Processor $transaction_processor */
1268
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
1269
+		return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment($this);
1270
+	}
1271
+
1272
+
1273
+	/**
1274
+	 * @return string
1275
+	 */
1276
+	public function old_txn_status()
1277
+	{
1278
+		return $this->_old_txn_status;
1279
+	}
1280
+
1281
+
1282
+	/**
1283
+	 * @param string $old_txn_status
1284
+	 */
1285
+	public function set_old_txn_status($old_txn_status)
1286
+	{
1287
+		// only set the first time
1288
+		if ($this->_old_txn_status === null) {
1289
+			$this->_old_txn_status = $old_txn_status;
1290
+		}
1291
+	}
1292
+
1293
+
1294
+	/**
1295
+	 * reg_status_updated
1296
+	 *
1297
+	 * @return bool
1298
+	 * @throws EE_Error
1299
+	 * @throws InvalidArgumentException
1300
+	 * @throws InvalidDataTypeException
1301
+	 * @throws InvalidInterfaceException
1302
+	 * @throws ReflectionException
1303
+	 */
1304
+	public function txn_status_updated()
1305
+	{
1306
+		return $this->status_ID() !== $this->_old_txn_status && $this->_old_txn_status !== null;
1307
+	}
1308
+
1309
+
1310
+	/**
1311
+	 * _reg_steps_completed
1312
+	 * if $check_all is TRUE, then returns TRUE if ALL reg steps have been marked as completed,
1313
+	 * if a $reg_step_slug is provided, then this step will be skipped when testing for completion
1314
+	 * if $check_all is FALSE and a $reg_step_slug is provided, then ONLY that reg step will be tested for completion
1315
+	 *
1316
+	 * @param string $reg_step_slug
1317
+	 * @param bool   $check_all
1318
+	 * @return bool|int
1319
+	 * @throws EE_Error
1320
+	 * @throws InvalidArgumentException
1321
+	 * @throws InvalidDataTypeException
1322
+	 * @throws InvalidInterfaceException
1323
+	 * @throws ReflectionException
1324
+	 */
1325
+	private function _reg_steps_completed($reg_step_slug = '', $check_all = true)
1326
+	{
1327
+		$reg_steps = $this->reg_steps();
1328
+		if (! is_array($reg_steps) || empty($reg_steps)) {
1329
+			return false;
1330
+		}
1331
+		// loop thru reg steps array)
1332
+		foreach ($reg_steps as $slug => $reg_step_completed) {
1333
+			// if NOT checking ALL steps (only checking one step)
1334
+			if (! $check_all) {
1335
+				// and this is the one
1336
+				if ($slug === $reg_step_slug) {
1337
+					return $reg_step_completed;
1338
+				}
1339
+				// skip to next reg step in loop
1340
+				continue;
1341
+			}
1342
+			// $check_all must be true, else we would never have gotten to this point
1343
+			if ($slug === $reg_step_slug) {
1344
+				// if we reach this point, then we are testing either:
1345
+				// all_reg_steps_completed_except() or
1346
+				// all_reg_steps_completed_except_final_step(),
1347
+				// and since this is the reg step EXCEPTION being tested
1348
+				// we want to return true (yes true) if this reg step is NOT completed
1349
+				// ie: "is everything completed except the final step?"
1350
+				// "that is correct... the final step is not completed, but all others are."
1351
+				return $reg_step_completed !== true;
1352
+			}
1353
+			if ($reg_step_completed !== true) {
1354
+				// if any reg step is NOT completed, then ALL steps are not completed
1355
+				return false;
1356
+			}
1357
+		}
1358
+		return true;
1359
+	}
1360
+
1361
+
1362
+	/**
1363
+	 * all_reg_steps_completed
1364
+	 * returns:
1365
+	 *    true if ALL reg steps have been marked as completed
1366
+	 *        or false if any step is not completed
1367
+	 *
1368
+	 * @return bool
1369
+	 * @throws EE_Error
1370
+	 * @throws InvalidArgumentException
1371
+	 * @throws InvalidDataTypeException
1372
+	 * @throws InvalidInterfaceException
1373
+	 * @throws ReflectionException
1374
+	 */
1375
+	public function all_reg_steps_completed()
1376
+	{
1377
+		return $this->_reg_steps_completed();
1378
+	}
1379
+
1380
+
1381
+	/**
1382
+	 * all_reg_steps_completed_except
1383
+	 * returns:
1384
+	 *        true if ALL reg steps, except a particular step that you wish to skip over, have been marked as completed
1385
+	 *        or false if any other step is not completed
1386
+	 *        or false if ALL steps are completed including the exception you are testing !!!
1387
+	 *
1388
+	 * @param string $exception
1389
+	 * @return bool
1390
+	 * @throws EE_Error
1391
+	 * @throws InvalidArgumentException
1392
+	 * @throws InvalidDataTypeException
1393
+	 * @throws InvalidInterfaceException
1394
+	 * @throws ReflectionException
1395
+	 */
1396
+	public function all_reg_steps_completed_except($exception = '')
1397
+	{
1398
+		return $this->_reg_steps_completed($exception);
1399
+	}
1400
+
1401
+
1402
+	/**
1403
+	 * all_reg_steps_completed_except
1404
+	 * returns:
1405
+	 *        true if ALL reg steps, except the final step, have been marked as completed
1406
+	 *        or false if any step is not completed
1407
+	 *    or false if ALL steps are completed including the final step !!!
1408
+	 *
1409
+	 * @return bool
1410
+	 * @throws EE_Error
1411
+	 * @throws InvalidArgumentException
1412
+	 * @throws InvalidDataTypeException
1413
+	 * @throws InvalidInterfaceException
1414
+	 * @throws ReflectionException
1415
+	 */
1416
+	public function all_reg_steps_completed_except_final_step()
1417
+	{
1418
+		return $this->_reg_steps_completed('finalize_registration');
1419
+	}
1420
+
1421
+
1422
+	/**
1423
+	 * reg_step_completed
1424
+	 * returns:
1425
+	 *    true if a specific reg step has been marked as completed
1426
+	 *    a Unix timestamp if it has been initialized but not yet completed,
1427
+	 *    or false if it has not yet been initialized
1428
+	 *
1429
+	 * @param string $reg_step_slug
1430
+	 * @return bool|int
1431
+	 * @throws EE_Error
1432
+	 * @throws InvalidArgumentException
1433
+	 * @throws InvalidDataTypeException
1434
+	 * @throws InvalidInterfaceException
1435
+	 * @throws ReflectionException
1436
+	 */
1437
+	public function reg_step_completed($reg_step_slug)
1438
+	{
1439
+		return $this->_reg_steps_completed($reg_step_slug, false);
1440
+	}
1441
+
1442
+
1443
+	/**
1444
+	 * completed_final_reg_step
1445
+	 * returns:
1446
+	 *    true if the finalize_registration reg step has been marked as completed
1447
+	 *    a Unix timestamp if it has been initialized but not yet completed,
1448
+	 *    or false if it has not yet been initialized
1449
+	 *
1450
+	 * @return bool|int
1451
+	 * @throws EE_Error
1452
+	 * @throws InvalidArgumentException
1453
+	 * @throws InvalidDataTypeException
1454
+	 * @throws InvalidInterfaceException
1455
+	 * @throws ReflectionException
1456
+	 */
1457
+	public function final_reg_step_completed()
1458
+	{
1459
+		return $this->_reg_steps_completed('finalize_registration', false);
1460
+	}
1461
+
1462
+
1463
+	/**
1464
+	 * set_reg_step_initiated
1465
+	 * given a valid TXN_reg_step, this sets it's value to a unix timestamp
1466
+	 *
1467
+	 * @param string $reg_step_slug
1468
+	 * @return boolean
1469
+	 * @throws EE_Error
1470
+	 * @throws InvalidArgumentException
1471
+	 * @throws InvalidDataTypeException
1472
+	 * @throws InvalidInterfaceException
1473
+	 * @throws ReflectionException
1474
+	 */
1475
+	public function set_reg_step_initiated($reg_step_slug)
1476
+	{
1477
+		return $this->_set_reg_step_completed_status($reg_step_slug, time());
1478
+	}
1479
+
1480
+
1481
+	/**
1482
+	 * set_reg_step_completed
1483
+	 * given a valid TXN_reg_step, this sets the step as completed
1484
+	 *
1485
+	 * @param string $reg_step_slug
1486
+	 * @return boolean
1487
+	 * @throws EE_Error
1488
+	 * @throws InvalidArgumentException
1489
+	 * @throws InvalidDataTypeException
1490
+	 * @throws InvalidInterfaceException
1491
+	 * @throws ReflectionException
1492
+	 */
1493
+	public function set_reg_step_completed($reg_step_slug)
1494
+	{
1495
+		return $this->_set_reg_step_completed_status($reg_step_slug, true);
1496
+	}
1497
+
1498
+
1499
+	/**
1500
+	 * set_reg_step_completed
1501
+	 * given a valid TXN_reg_step slug, this sets the step as NOT completed
1502
+	 *
1503
+	 * @param string $reg_step_slug
1504
+	 * @return boolean
1505
+	 * @throws EE_Error
1506
+	 * @throws InvalidArgumentException
1507
+	 * @throws InvalidDataTypeException
1508
+	 * @throws InvalidInterfaceException
1509
+	 * @throws ReflectionException
1510
+	 */
1511
+	public function set_reg_step_not_completed($reg_step_slug)
1512
+	{
1513
+		return $this->_set_reg_step_completed_status($reg_step_slug, false);
1514
+	}
1515
+
1516
+
1517
+	/**
1518
+	 * set_reg_step_completed
1519
+	 * given a valid reg step slug, this sets the TXN_reg_step completed status which is either:
1520
+	 *
1521
+	 * @param  string      $reg_step_slug
1522
+	 * @param  boolean|int $status
1523
+	 * @return boolean
1524
+	 * @throws EE_Error
1525
+	 * @throws InvalidArgumentException
1526
+	 * @throws InvalidDataTypeException
1527
+	 * @throws InvalidInterfaceException
1528
+	 * @throws ReflectionException
1529
+	 */
1530
+	private function _set_reg_step_completed_status($reg_step_slug, $status)
1531
+	{
1532
+		// validate status
1533
+		$status = is_bool($status) || is_int($status) ? $status : false;
1534
+		// get reg steps array
1535
+		$txn_reg_steps = $this->reg_steps();
1536
+		// if reg step does NOT exist
1537
+		if (! isset($txn_reg_steps[ $reg_step_slug ])) {
1538
+			return false;
1539
+		}
1540
+		// if  we're trying to complete a step that is already completed
1541
+		if ($txn_reg_steps[ $reg_step_slug ] === true) {
1542
+			return true;
1543
+		}
1544
+		// if  we're trying to complete a step that hasn't even started
1545
+		if ($status === true && $txn_reg_steps[ $reg_step_slug ] === false) {
1546
+			return false;
1547
+		}
1548
+		// if current status value matches the incoming value (no change)
1549
+		// type casting as int means values should collapse to either 0, 1, or a timestamp like 1234567890
1550
+		if ((int) $txn_reg_steps[ $reg_step_slug ] === (int) $status) {
1551
+			// this will happen in cases where multiple AJAX requests occur during the same step
1552
+			return true;
1553
+		}
1554
+		// if we're trying to set a start time, but it has already been set...
1555
+		if (is_numeric($status) && is_numeric($txn_reg_steps[ $reg_step_slug ])) {
1556
+			// skip the update below, but don't return FALSE so that errors won't be displayed
1557
+			return true;
1558
+		}
1559
+		// update completed status
1560
+		$txn_reg_steps[ $reg_step_slug ] = $status;
1561
+		$this->set_reg_steps($txn_reg_steps);
1562
+		$this->save();
1563
+		return true;
1564
+	}
1565
+
1566
+
1567
+	/**
1568
+	 * remove_reg_step
1569
+	 * given a valid TXN_reg_step slug, this will remove (unset)
1570
+	 * the reg step from the TXN reg step array
1571
+	 *
1572
+	 * @param string $reg_step_slug
1573
+	 * @return void
1574
+	 * @throws EE_Error
1575
+	 * @throws InvalidArgumentException
1576
+	 * @throws InvalidDataTypeException
1577
+	 * @throws InvalidInterfaceException
1578
+	 * @throws ReflectionException
1579
+	 */
1580
+	public function remove_reg_step($reg_step_slug)
1581
+	{
1582
+		// get reg steps array
1583
+		$txn_reg_steps = $this->reg_steps();
1584
+		unset($txn_reg_steps[ $reg_step_slug ]);
1585
+		$this->set_reg_steps($txn_reg_steps);
1586
+	}
1587
+
1588
+
1589
+	/**
1590
+	 * toggle_failed_transaction_status
1591
+	 * upgrades a TXNs status from failed to abandoned,
1592
+	 * meaning that contact information has been captured for at least one registrant
1593
+	 *
1594
+	 * @param bool $save
1595
+	 * @return bool
1596
+	 * @throws EE_Error
1597
+	 * @throws InvalidArgumentException
1598
+	 * @throws InvalidDataTypeException
1599
+	 * @throws InvalidInterfaceException
1600
+	 * @throws ReflectionException
1601
+	 */
1602
+	public function toggle_failed_transaction_status($save = true)
1603
+	{
1604
+		// if TXN status is still set as "failed"...
1605
+		if ($this->status_ID() === EEM_Transaction::failed_status_code) {
1606
+			$this->set_status(EEM_Transaction::abandoned_status_code);
1607
+			if ($save) {
1608
+				$this->save();
1609
+			}
1610
+			return true;
1611
+		}
1612
+		return false;
1613
+	}
1614
+
1615
+
1616
+	/**
1617
+	 * toggle_abandoned_transaction_status
1618
+	 * upgrades a TXNs status from failed or abandoned to incomplete
1619
+	 *
1620
+	 * @return bool
1621
+	 * @throws EE_Error
1622
+	 * @throws InvalidArgumentException
1623
+	 * @throws InvalidDataTypeException
1624
+	 * @throws InvalidInterfaceException
1625
+	 * @throws ReflectionException
1626
+	 */
1627
+	public function toggle_abandoned_transaction_status()
1628
+	{
1629
+		// if TXN status has not been updated already due to a payment, and is still set as "failed" or "abandoned"...
1630
+		$txn_status = $this->status_ID();
1631
+		if (
1632
+			$txn_status === EEM_Transaction::failed_status_code
1633
+			|| $txn_status === EEM_Transaction::abandoned_status_code
1634
+		) {
1635
+			// if a contact record for the primary registrant has been created
1636
+			if (
1637
+				$this->primary_registration() instanceof EE_Registration
1638
+				&& $this->primary_registration()->attendee() instanceof EE_Attendee
1639
+			) {
1640
+				$this->set_status(EEM_Transaction::incomplete_status_code);
1641
+			} else {
1642
+				// no contact record? yer abandoned!
1643
+				$this->set_status(EEM_Transaction::abandoned_status_code);
1644
+			}
1645
+			return true;
1646
+		}
1647
+		return false;
1648
+	}
1649
+
1650
+
1651
+	/**
1652
+	 * checks if an Abandoned TXN has any related payments, and if so,
1653
+	 * updates the TXN status based on the amount paid
1654
+	 *
1655
+	 * @throws EE_Error
1656
+	 * @throws InvalidDataTypeException
1657
+	 * @throws InvalidInterfaceException
1658
+	 * @throws InvalidArgumentException
1659
+	 * @throws RuntimeException
1660
+	 * @throws ReflectionException
1661
+	 */
1662
+	public function verify_abandoned_transaction_status()
1663
+	{
1664
+		if ($this->status_ID() !== EEM_Transaction::abandoned_status_code) {
1665
+			return;
1666
+		}
1667
+		$payments = $this->get_many_related('Payment');
1668
+		if (! empty($payments)) {
1669
+			foreach ($payments as $payment) {
1670
+				if ($payment instanceof EE_Payment) {
1671
+					// kk this TXN should NOT be abandoned
1672
+					$this->update_status_based_on_total_paid();
1673
+					if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1674
+						EE_Error::add_attention(
1675
+							sprintf(
1676
+								esc_html__(
1677
+									'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.',
1678
+									'event_espresso'
1679
+								),
1680
+								$this->ID(),
1681
+								$this->pretty_status()
1682
+							)
1683
+						);
1684
+					}
1685
+					// get final reg step status
1686
+					$finalized = $this->final_reg_step_completed();
1687
+					// if the 'finalize_registration' step has been initiated (has a timestamp)
1688
+					// but has not yet been fully completed (TRUE)
1689
+					if (is_int($finalized) && $finalized !== false && $finalized !== true) {
1690
+						$this->set_reg_step_completed('finalize_registration');
1691
+						$this->save();
1692
+					}
1693
+				}
1694
+			}
1695
+		}
1696
+	}
1697
+
1698
+
1699
+	/**
1700
+	 * @since 4.10.4.p
1701
+	 * @throws EE_Error
1702
+	 * @throws InvalidArgumentException
1703
+	 * @throws InvalidDataTypeException
1704
+	 * @throws InvalidInterfaceException
1705
+	 * @throws ReflectionException
1706
+	 * @throws RuntimeException
1707
+	 */
1708
+	public function recalculateLineItems()
1709
+	{
1710
+		$total_line_item = $this->total_line_item(false);
1711
+		if ($total_line_item instanceof EE_Line_Item) {
1712
+			EEH_Line_Item::resetIsTaxableForTickets($total_line_item);
1713
+			return EEH_Line_Item::apply_taxes($total_line_item, true);
1714
+		}
1715
+		return false;
1716
+	}
1717 1717
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Question.class.php 1 patch
Indentation   +664 added lines, -664 removed lines patch added patch discarded remove patch
@@ -14,668 +14,668 @@
 block discarded – undo
14 14
 class EE_Question extends EE_Soft_Delete_Base_Class implements EEI_Duplicatable
15 15
 {
16 16
 
17
-    /**
18
-     *
19
-     * @param array  $props_n_values          incoming values
20
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
21
-     *                                        used.)
22
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
23
-     *                                        date_format and the second value is the time format
24
-     * @return EE_Question
25
-     */
26
-    public static function new_instance($props_n_values = array(), $timezone = '', $date_formats = array())
27
-    {
28
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
29
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
30
-    }
31
-
32
-
33
-    /**
34
-     * @param array  $props_n_values  incoming values from the database
35
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
36
-     *                                the website will be used.
37
-     * @return EE_Question
38
-     */
39
-    public static function new_instance_from_db($props_n_values = array(), $timezone = '')
40
-    {
41
-        return new self($props_n_values, true, $timezone);
42
-    }
43
-
44
-
45
-    /**
46
-     *        Set    Question display text
47
-     *
48
-     * @access        public
49
-     * @param string $QST_display_text
50
-     */
51
-    public function set_display_text($QST_display_text = '')
52
-    {
53
-        $this->set('QST_display_text', $QST_display_text);
54
-    }
55
-
56
-
57
-    /**
58
-     *        Set    Question admin text
59
-     *
60
-     * @access        public
61
-     * @param        string $QST_admin_label
62
-     */
63
-    public function set_admin_label($QST_admin_label = '')
64
-    {
65
-        $this->set('QST_admin_label', $QST_admin_label);
66
-    }
67
-
68
-
69
-    /**
70
-     *        Set    system name
71
-     *
72
-     * @access        public
73
-     * @param        mixed $QST_system
74
-     */
75
-    public function set_system_ID($QST_system = '')
76
-    {
77
-        $this->set('QST_system', $QST_system);
78
-    }
79
-
80
-
81
-    /**
82
-     *        Set    question's type
83
-     *
84
-     * @access        public
85
-     * @param        string $QST_type
86
-     */
87
-    public function set_question_type($QST_type = '')
88
-    {
89
-        $this->set('QST_type', $QST_type);
90
-    }
91
-
92
-
93
-    /**
94
-     *        Sets whether this question must be answered when presented in a form
95
-     *
96
-     * @access        public
97
-     * @param        bool $QST_required
98
-     */
99
-    public function set_required($QST_required = false)
100
-    {
101
-        $this->set('QST_required', $QST_required);
102
-    }
103
-
104
-
105
-    /**
106
-     *        Set    Question display text
107
-     *
108
-     * @access        public
109
-     * @param        string $QST_required_text
110
-     */
111
-    public function set_required_text($QST_required_text = '')
112
-    {
113
-        $this->set('QST_required_text', $QST_required_text);
114
-    }
115
-
116
-
117
-    /**
118
-     *        Sets the order of this question when placed in a sequence of questions
119
-     *
120
-     * @access        public
121
-     * @param        int $QST_order
122
-     */
123
-    public function set_order($QST_order = 0)
124
-    {
125
-        $this->set('QST_order', $QST_order);
126
-    }
127
-
128
-
129
-    /**
130
-     *        Sets whether the question is admin-only
131
-     *
132
-     * @access        public
133
-     * @param        bool $QST_admin_only
134
-     */
135
-    public function set_admin_only($QST_admin_only = false)
136
-    {
137
-        $this->set('QST_admin_only', $QST_admin_only);
138
-    }
139
-
140
-
141
-    /**
142
-     *        Sets the wordpress user ID on the question
143
-     *
144
-     * @access        public
145
-     * @param        int $QST_wp_user
146
-     */
147
-    public function set_wp_user($QST_wp_user = 1)
148
-    {
149
-        $this->set('QST_wp_user', $QST_wp_user);
150
-    }
151
-
152
-
153
-    /**
154
-     *        Sets whether the question has been deleted
155
-     *        (we use this boolean instead of actually
156
-     *        deleting it because when users delete this question
157
-     *        they really want to remove the question from future
158
-     *        forms, BUT keep their old answers which depend
159
-     *        on this record actually existing.
160
-     *
161
-     * @access        public
162
-     * @param    bool $QST_deleted
163
-     */
164
-    public function set_deleted($QST_deleted = false)
165
-    {
166
-        $this->set('QST_deleted', $QST_deleted);
167
-    }
168
-
169
-
170
-    /**
171
-     * returns the text for displaying the question to users
172
-     *
173
-     * @access public
174
-     * @return string
175
-     */
176
-    public function display_text()
177
-    {
178
-        return $this->get('QST_display_text');
179
-    }
180
-
181
-
182
-    /**
183
-     * returns the text for the administrative label
184
-     *
185
-     * @access public
186
-     * @return string
187
-     */
188
-    public function admin_label()
189
-    {
190
-        return $this->get('QST_admin_label');
191
-    }
192
-
193
-
194
-    /**
195
-     * returns the attendee column name for this question
196
-     *
197
-     * @access public
198
-     * @return string
199
-     */
200
-    public function system_ID()
201
-    {
202
-        return $this->get('QST_system');
203
-    }
204
-
205
-
206
-    /**
207
-     * returns either a string of 'text', 'textfield', etc.
208
-     *
209
-     * @access public
210
-     * @return boolean
211
-     */
212
-    public function required()
213
-    {
214
-        return $this->get('QST_required');
215
-    }
216
-
217
-
218
-    /**
219
-     * returns the text which should be displayed when a user
220
-     * doesn't answer this question in a form
221
-     *
222
-     * @access public
223
-     * @return string
224
-     */
225
-    public function required_text()
226
-    {
227
-        return $this->get('QST_required_text');
228
-    }
229
-
230
-
231
-    /**
232
-     * returns the type of this question
233
-     *
234
-     * @access public
235
-     * @return string
236
-     */
237
-    public function type()
238
-    {
239
-        return $this->get('QST_type');
240
-    }
241
-
242
-
243
-    /**
244
-     * returns an integer showing where this question should
245
-     * be placed in a sequence of questions
246
-     *
247
-     * @access public
248
-     * @return int
249
-     */
250
-    public function order()
251
-    {
252
-        return $this->get('QST_order');
253
-    }
254
-
255
-
256
-    /**
257
-     * returns whether this question should only appears to admins,
258
-     * or to everyone
259
-     *
260
-     * @access public
261
-     * @return boolean
262
-     */
263
-    public function admin_only()
264
-    {
265
-        return $this->get('QST_admin_only');
266
-    }
267
-
268
-
269
-    /**
270
-     * returns the id the wordpress user who created this question
271
-     *
272
-     * @access public
273
-     * @return int
274
-     */
275
-    public function wp_user()
276
-    {
277
-        return $this->get('QST_wp_user');
278
-    }
279
-
280
-
281
-    /**
282
-     * returns whether this question has been marked as 'deleted'
283
-     *
284
-     * @access public
285
-     * @return boolean
286
-     */
287
-    public function deleted()
288
-    {
289
-        return $this->get('QST_deleted');
290
-    }
291
-
292
-
293
-    /**
294
-     * Gets an array of related EE_Answer  to this EE_Question
295
-     *
296
-     * @return EE_Answer[]
297
-     */
298
-    public function answers()
299
-    {
300
-        return $this->get_many_related('Answer');
301
-    }
302
-
303
-
304
-    /**
305
-     * Boolean check for if there are answers on this question in th db
306
-     *
307
-     * @return boolean true = has answers, false = no answers.
308
-     */
309
-    public function has_answers()
310
-    {
311
-        return $this->count_related('Answer') > 0 ? true : false;
312
-    }
313
-
314
-
315
-    /**
316
-     * gets an array of EE_Question_Group which relate to this question
317
-     *
318
-     * @return EE_Question_Group[]
319
-     */
320
-    public function question_groups()
321
-    {
322
-        return $this->get_many_related('Question_Group');
323
-    }
324
-
325
-
326
-    /**
327
-     * Returns all the options for this question. By default, it returns only the not-yet-deleted ones.
328
-     *
329
-     * @param boolean      $notDeletedOptionsOnly            1
330
-     *                                                       whether to return ALL options, or only the ones which have
331
-     *                                                       not yet been deleleted
332
-     * @param string|array $selected_value_to_always_include , when retrieving options to an ANSWERED question,
333
-     *                                                       we want to usually only show non-deleted options AND the
334
-     *                                                       value that was selected for the answer, whether it was
335
-     *                                                       trashed or not.
336
-     * @return EE_Question_Option[]
337
-     */
338
-    public function options($notDeletedOptionsOnly = true, $selected_value_to_always_include = null)
339
-    {
340
-        if (! $this->ID()) {
341
-            return array();
342
-        }
343
-        $query_params = array();
344
-        if ($selected_value_to_always_include) {
345
-            if (is_array($selected_value_to_always_include)) {
346
-                $query_params[0]['OR*options-query']['QSO_value'] = array('IN', $selected_value_to_always_include);
347
-            } else {
348
-                $query_params[0]['OR*options-query']['QSO_value'] = $selected_value_to_always_include;
349
-            }
350
-        }
351
-        if ($notDeletedOptionsOnly) {
352
-            $query_params[0]['OR*options-query']['QSO_deleted'] = false;
353
-        }
354
-        // order by QSO_order
355
-        $query_params['order_by'] = array('QSO_order' => 'ASC');
356
-        return $this->get_many_related('Question_Option', $query_params);
357
-    }
358
-
359
-
360
-    /**
361
-     * returns an array of EE_Question_Options which relate to this question
362
-     *
363
-     * @return \EE_Question_Option[]
364
-     */
365
-    public function temp_options()
366
-    {
367
-        return $this->_model_relations['Question_Option'];
368
-    }
369
-
370
-
371
-    /**
372
-     * Adds an option for this question. Note: if the option were previously associated with a different
373
-     * Question, that relationship will be overwritten.
374
-     *
375
-     * @param EE_Question_Option $option
376
-     * @return boolean success
377
-     */
378
-    public function add_option(EE_Question_Option $option)
379
-    {
380
-        return $this->_add_relation_to($option, 'Question_Option');
381
-    }
382
-
383
-
384
-    /**
385
-     * Adds an option directly to this question without saving to the db
386
-     *
387
-     * @param EE_Question_Option $option
388
-     * @return boolean success
389
-     */
390
-    public function add_temp_option(EE_Question_Option $option)
391
-    {
392
-        $this->_model_relations['Question_Option'][] = $option;
393
-        return true;
394
-    }
395
-
396
-
397
-    /**
398
-     * Marks the option as deleted.
399
-     *
400
-     * @param EE_Question_Option $option
401
-     * @return boolean success
402
-     */
403
-    public function remove_option(EE_Question_Option $option)
404
-    {
405
-        return $this->_remove_relation_to($option, 'Question_Option');
406
-    }
407
-
408
-
409
-    /**
410
-     * @return bool
411
-     */
412
-    public function is_system_question()
413
-    {
414
-        $system_ID = $this->get('QST_system');
415
-        return ! empty($system_ID) ? true : false;
416
-    }
417
-
418
-
419
-    /**
420
-     * The purpose of this method is set the question order this question order to be the max out of all questions
421
-     *
422
-     * @access public
423
-     * @return void
424
-     */
425
-    public function set_order_to_latest()
426
-    {
427
-        $latest_order = $this->get_model()->get_latest_question_order();
428
-        $latest_order++;
429
-        $this->set('QST_order', $latest_order);
430
-    }
431
-
432
-
433
-    /**
434
-     * Retrieves the list of allowed question types from the model.
435
-     *
436
-     * @return string[]
437
-     */
438
-    private function _allowed_question_types()
439
-    {
440
-        $questionModel = $this->get_model();
441
-        /* @var $questionModel EEM_Question */
442
-        return $questionModel->allowed_question_types();
443
-    }
444
-
445
-    /**
446
-     * Duplicates this question and its question options
447
-     *
448
-     * @return \EE_Question
449
-     */
450
-    public function duplicate($options = array())
451
-    {
452
-        $new_question = clone $this;
453
-        $new_question->set('QST_ID', null);
454
-        $new_question->set_display_text(sprintf(__('%s **Duplicate**', 'event_espresso'), $this->display_text()));
455
-        $new_question->set_admin_label(sprintf(__('%s **Duplicate**', 'event_espresso'), $this->admin_label()));
456
-        $new_question->set_system_ID(null);
457
-        $new_question->set_wp_user(get_current_user_id());
458
-        // if we're duplicating a trashed question, assume we don't want the new one to be trashed
459
-        $new_question->set_deleted(false);
460
-        $success = $new_question->save();
461
-        if ($success) {
462
-            // we don't totally want to duplicate the question options, because we want them to be for the NEW question
463
-            foreach ($this->options() as $question_option) {
464
-                $question_option->duplicate(array('QST_ID' => $new_question->ID()));
465
-            }
466
-            return $new_question;
467
-        } else {
468
-            return null;
469
-        }
470
-    }
471
-
472
-    /**
473
-     * Returns the question's maximum allowed response size
474
-     *
475
-     * @return int|float
476
-     */
477
-    public function max()
478
-    {
479
-        return $this->get('QST_max');
480
-    }
481
-
482
-    /**
483
-     * Sets the question's maximum allowed response size
484
-     *
485
-     * @param int|float $new_max
486
-     * @return void
487
-     */
488
-    public function set_max($new_max)
489
-    {
490
-        $this->set('QST_max', $new_max);
491
-    }
492
-
493
-
494
-    /**
495
-     * Creates a form input from this question which can be used in HTML forms
496
-     *
497
-     * @param EE_Registration $registration
498
-     * @param EE_Answer       $answer
499
-     * @param array           $input_constructor_args
500
-     * @return EE_Form_Input_Base
501
-     */
502
-    public function generate_form_input($registration = null, $answer = null, $input_constructor_args = array())
503
-    {
504
-        $identifier = $this->is_system_question() ? $this->system_ID() : $this->ID();
505
-
506
-        $input_constructor_args = array_merge(
507
-            array(
508
-                'required'                          => $this->required() ? true : false,
509
-                'html_label_text'                   => $this->display_text(),
510
-                'required_validation_error_message' => $this->required_text(),
511
-            ),
512
-            $input_constructor_args
513
-        );
514
-        if (! $answer instanceof EE_Answer && $registration instanceof EE_Registration) {
515
-            $answer = EEM_Answer::instance()->get_registration_question_answer_object($registration, $this->ID());
516
-        }
517
-        // has this question been answered ?
518
-        if (
519
-            $answer instanceof EE_Answer
520
-            && $answer->value() !== ''
521
-        ) {
522
-            // answer gets htmlspecialchars called on it, undo that please
523
-            // because the form input's display strategy may call esc_attr too
524
-            // which also does html special characters
525
-            $values_with_html_special_chars = $answer->value();
526
-            if (is_array($values_with_html_special_chars)) {
527
-                $default_value = array_map('htmlspecialchars_decode', $values_with_html_special_chars);
528
-            } else {
529
-                $default_value = htmlspecialchars_decode($values_with_html_special_chars);
530
-            }
531
-            $input_constructor_args['default'] = $default_value;
532
-        }
533
-        $max_max_for_question = EEM_Question::instance()->absolute_max_for_system_question($this->system_ID());
534
-        if (
535
-            in_array(
536
-                $this->type(),
537
-                EEM_Question::instance()->questionTypesWithMaxLength(),
538
-                true
539
-            )
540
-        ) {
541
-            $input_constructor_args['validation_strategies'][] = new EE_Max_Length_Validation_Strategy(
542
-                null,
543
-                min($max_max_for_question, $this->max())
544
-            );
545
-        }
546
-        $input_constructor_args = apply_filters(
547
-            'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__input_constructor_args',
548
-            $input_constructor_args,
549
-            $registration,
550
-            $this,
551
-            $answer
552
-        );
553
-
554
-        $result = null;
555
-        switch ($this->type()) {
556
-            // Text
557
-            case EEM_Question::QST_type_text:
558
-                $result = new EE_Text_Input($input_constructor_args);
559
-                break;
560
-            // Textarea
561
-            case EEM_Question::QST_type_textarea:
562
-                $result = new EE_Text_Area_Input($input_constructor_args);
563
-                break;
564
-            // Radio Buttons
565
-            case EEM_Question::QST_type_radio:
566
-                $result = new EE_Radio_Button_Input($this->options(), $input_constructor_args);
567
-                break;
568
-            // Dropdown
569
-            case EEM_Question::QST_type_dropdown:
570
-                $result = new EE_Select_Input($this->options(), $input_constructor_args);
571
-                break;
572
-            // State Dropdown
573
-            case EEM_Question::QST_type_state:
574
-                $state_options = apply_filters(
575
-                    'FHEE__EE_Question__generate_form_input__state_options',
576
-                    null,
577
-                    $this,
578
-                    $registration,
579
-                    $answer
580
-                );
581
-                $result = new EE_State_Select_Input($state_options, $input_constructor_args);
582
-                break;
583
-            // Country Dropdown
584
-            case EEM_Question::QST_type_country:
585
-                $country_options = apply_filters(
586
-                    'FHEE__EE_Question__generate_form_input__country_options',
587
-                    null,
588
-                    $this,
589
-                    $registration,
590
-                    $answer
591
-                );
592
-                $result = new EE_Country_Select_Input($country_options, $input_constructor_args);
593
-                break;
594
-            // Checkboxes
595
-            case EEM_Question::QST_type_checkbox:
596
-                $result = new EE_Checkbox_Multi_Input($this->options(), $input_constructor_args);
597
-                break;
598
-            // Date
599
-            case EEM_Question::QST_type_date:
600
-                $result = new EE_Datepicker_Input($input_constructor_args);
601
-                break;
602
-            case EEM_Question::QST_type_html_textarea:
603
-                $input_constructor_args['validation_strategies'][] = new EE_Simple_HTML_Validation_Strategy();
604
-                $result = new EE_Text_Area_Input($input_constructor_args);
605
-                $result->remove_validation_strategy('EE_Plaintext_Validation_Strategy');
606
-                break;
607
-            case EEM_Question::QST_type_email:
608
-                    $result = new EE_Email_Input($input_constructor_args);
609
-                break;
610
-            // Email confirm
611
-            case EEM_Question::QST_type_email_confirm:
612
-                $result = new EE_Email_Confirm_Input($input_constructor_args);
613
-                break;
614
-            case EEM_Question::QST_type_us_phone:
615
-                $result = new EE_Phone_Input($input_constructor_args);
616
-                break;
617
-            case EEM_Question::QST_type_int:
618
-                $result = new EE_Integer_Input($input_constructor_args);
619
-                break;
620
-            case EEM_Question::QST_type_decimal:
621
-                $result = new EE_Float_Input($input_constructor_args);
622
-                break;
623
-            case EEM_Question::QST_type_url:
624
-                $input_constructor_args['validation_strategies'][] = LoaderFactory::getLoader()->getNew('EE_URL_Validation_Strategy');
625
-                $result = new EE_Text_Input($input_constructor_args);
626
-                break;
627
-            case EEM_Question::QST_type_year:
628
-                $result = new EE_Year_Input(
629
-                    $input_constructor_args,
630
-                    apply_filters(
631
-                        'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__year_question__four_digit',
632
-                        true,
633
-                        $this
634
-                    ),
635
-                    apply_filters(
636
-                        'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__year_question__early_range',
637
-                        100,
638
-                        $this
639
-                    ),
640
-                    apply_filters(
641
-                        'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__year_question__end_range',
642
-                        100,
643
-                        $this
644
-                    )
645
-                );
646
-                break;
647
-            case EEM_Question::QST_type_multi_select:
648
-                $result = new EE_Select_Multiple_Input($this->options(), $input_constructor_args);
649
-                break;
650
-            // fallback
651
-            default:
652
-                $default_input = apply_filters(
653
-                    'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__default',
654
-                    null,
655
-                    $this->type(),
656
-                    $this,
657
-                    $input_constructor_args
658
-                );
659
-                if (! $default_input) {
660
-                    $default_input = new EE_Text_Input($input_constructor_args);
661
-                }
662
-                $result = $default_input;
663
-        }
664
-        return apply_filters('FHEE__EE_Question__generate_form_input__return', $result, $registration, $this, $answer);
665
-    }
666
-
667
-
668
-    /**
669
-     * Returns whether or not this question type should have question option entries
670
-     *
671
-     * @return bool
672
-     */
673
-    public function should_have_question_options()
674
-    {
675
-        return in_array(
676
-            $this->type(),
677
-            $this->_model->question_types_with_options(),
678
-            true
679
-        );
680
-    }
17
+	/**
18
+	 *
19
+	 * @param array  $props_n_values          incoming values
20
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
21
+	 *                                        used.)
22
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
23
+	 *                                        date_format and the second value is the time format
24
+	 * @return EE_Question
25
+	 */
26
+	public static function new_instance($props_n_values = array(), $timezone = '', $date_formats = array())
27
+	{
28
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
29
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
30
+	}
31
+
32
+
33
+	/**
34
+	 * @param array  $props_n_values  incoming values from the database
35
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
36
+	 *                                the website will be used.
37
+	 * @return EE_Question
38
+	 */
39
+	public static function new_instance_from_db($props_n_values = array(), $timezone = '')
40
+	{
41
+		return new self($props_n_values, true, $timezone);
42
+	}
43
+
44
+
45
+	/**
46
+	 *        Set    Question display text
47
+	 *
48
+	 * @access        public
49
+	 * @param string $QST_display_text
50
+	 */
51
+	public function set_display_text($QST_display_text = '')
52
+	{
53
+		$this->set('QST_display_text', $QST_display_text);
54
+	}
55
+
56
+
57
+	/**
58
+	 *        Set    Question admin text
59
+	 *
60
+	 * @access        public
61
+	 * @param        string $QST_admin_label
62
+	 */
63
+	public function set_admin_label($QST_admin_label = '')
64
+	{
65
+		$this->set('QST_admin_label', $QST_admin_label);
66
+	}
67
+
68
+
69
+	/**
70
+	 *        Set    system name
71
+	 *
72
+	 * @access        public
73
+	 * @param        mixed $QST_system
74
+	 */
75
+	public function set_system_ID($QST_system = '')
76
+	{
77
+		$this->set('QST_system', $QST_system);
78
+	}
79
+
80
+
81
+	/**
82
+	 *        Set    question's type
83
+	 *
84
+	 * @access        public
85
+	 * @param        string $QST_type
86
+	 */
87
+	public function set_question_type($QST_type = '')
88
+	{
89
+		$this->set('QST_type', $QST_type);
90
+	}
91
+
92
+
93
+	/**
94
+	 *        Sets whether this question must be answered when presented in a form
95
+	 *
96
+	 * @access        public
97
+	 * @param        bool $QST_required
98
+	 */
99
+	public function set_required($QST_required = false)
100
+	{
101
+		$this->set('QST_required', $QST_required);
102
+	}
103
+
104
+
105
+	/**
106
+	 *        Set    Question display text
107
+	 *
108
+	 * @access        public
109
+	 * @param        string $QST_required_text
110
+	 */
111
+	public function set_required_text($QST_required_text = '')
112
+	{
113
+		$this->set('QST_required_text', $QST_required_text);
114
+	}
115
+
116
+
117
+	/**
118
+	 *        Sets the order of this question when placed in a sequence of questions
119
+	 *
120
+	 * @access        public
121
+	 * @param        int $QST_order
122
+	 */
123
+	public function set_order($QST_order = 0)
124
+	{
125
+		$this->set('QST_order', $QST_order);
126
+	}
127
+
128
+
129
+	/**
130
+	 *        Sets whether the question is admin-only
131
+	 *
132
+	 * @access        public
133
+	 * @param        bool $QST_admin_only
134
+	 */
135
+	public function set_admin_only($QST_admin_only = false)
136
+	{
137
+		$this->set('QST_admin_only', $QST_admin_only);
138
+	}
139
+
140
+
141
+	/**
142
+	 *        Sets the wordpress user ID on the question
143
+	 *
144
+	 * @access        public
145
+	 * @param        int $QST_wp_user
146
+	 */
147
+	public function set_wp_user($QST_wp_user = 1)
148
+	{
149
+		$this->set('QST_wp_user', $QST_wp_user);
150
+	}
151
+
152
+
153
+	/**
154
+	 *        Sets whether the question has been deleted
155
+	 *        (we use this boolean instead of actually
156
+	 *        deleting it because when users delete this question
157
+	 *        they really want to remove the question from future
158
+	 *        forms, BUT keep their old answers which depend
159
+	 *        on this record actually existing.
160
+	 *
161
+	 * @access        public
162
+	 * @param    bool $QST_deleted
163
+	 */
164
+	public function set_deleted($QST_deleted = false)
165
+	{
166
+		$this->set('QST_deleted', $QST_deleted);
167
+	}
168
+
169
+
170
+	/**
171
+	 * returns the text for displaying the question to users
172
+	 *
173
+	 * @access public
174
+	 * @return string
175
+	 */
176
+	public function display_text()
177
+	{
178
+		return $this->get('QST_display_text');
179
+	}
180
+
181
+
182
+	/**
183
+	 * returns the text for the administrative label
184
+	 *
185
+	 * @access public
186
+	 * @return string
187
+	 */
188
+	public function admin_label()
189
+	{
190
+		return $this->get('QST_admin_label');
191
+	}
192
+
193
+
194
+	/**
195
+	 * returns the attendee column name for this question
196
+	 *
197
+	 * @access public
198
+	 * @return string
199
+	 */
200
+	public function system_ID()
201
+	{
202
+		return $this->get('QST_system');
203
+	}
204
+
205
+
206
+	/**
207
+	 * returns either a string of 'text', 'textfield', etc.
208
+	 *
209
+	 * @access public
210
+	 * @return boolean
211
+	 */
212
+	public function required()
213
+	{
214
+		return $this->get('QST_required');
215
+	}
216
+
217
+
218
+	/**
219
+	 * returns the text which should be displayed when a user
220
+	 * doesn't answer this question in a form
221
+	 *
222
+	 * @access public
223
+	 * @return string
224
+	 */
225
+	public function required_text()
226
+	{
227
+		return $this->get('QST_required_text');
228
+	}
229
+
230
+
231
+	/**
232
+	 * returns the type of this question
233
+	 *
234
+	 * @access public
235
+	 * @return string
236
+	 */
237
+	public function type()
238
+	{
239
+		return $this->get('QST_type');
240
+	}
241
+
242
+
243
+	/**
244
+	 * returns an integer showing where this question should
245
+	 * be placed in a sequence of questions
246
+	 *
247
+	 * @access public
248
+	 * @return int
249
+	 */
250
+	public function order()
251
+	{
252
+		return $this->get('QST_order');
253
+	}
254
+
255
+
256
+	/**
257
+	 * returns whether this question should only appears to admins,
258
+	 * or to everyone
259
+	 *
260
+	 * @access public
261
+	 * @return boolean
262
+	 */
263
+	public function admin_only()
264
+	{
265
+		return $this->get('QST_admin_only');
266
+	}
267
+
268
+
269
+	/**
270
+	 * returns the id the wordpress user who created this question
271
+	 *
272
+	 * @access public
273
+	 * @return int
274
+	 */
275
+	public function wp_user()
276
+	{
277
+		return $this->get('QST_wp_user');
278
+	}
279
+
280
+
281
+	/**
282
+	 * returns whether this question has been marked as 'deleted'
283
+	 *
284
+	 * @access public
285
+	 * @return boolean
286
+	 */
287
+	public function deleted()
288
+	{
289
+		return $this->get('QST_deleted');
290
+	}
291
+
292
+
293
+	/**
294
+	 * Gets an array of related EE_Answer  to this EE_Question
295
+	 *
296
+	 * @return EE_Answer[]
297
+	 */
298
+	public function answers()
299
+	{
300
+		return $this->get_many_related('Answer');
301
+	}
302
+
303
+
304
+	/**
305
+	 * Boolean check for if there are answers on this question in th db
306
+	 *
307
+	 * @return boolean true = has answers, false = no answers.
308
+	 */
309
+	public function has_answers()
310
+	{
311
+		return $this->count_related('Answer') > 0 ? true : false;
312
+	}
313
+
314
+
315
+	/**
316
+	 * gets an array of EE_Question_Group which relate to this question
317
+	 *
318
+	 * @return EE_Question_Group[]
319
+	 */
320
+	public function question_groups()
321
+	{
322
+		return $this->get_many_related('Question_Group');
323
+	}
324
+
325
+
326
+	/**
327
+	 * Returns all the options for this question. By default, it returns only the not-yet-deleted ones.
328
+	 *
329
+	 * @param boolean      $notDeletedOptionsOnly            1
330
+	 *                                                       whether to return ALL options, or only the ones which have
331
+	 *                                                       not yet been deleleted
332
+	 * @param string|array $selected_value_to_always_include , when retrieving options to an ANSWERED question,
333
+	 *                                                       we want to usually only show non-deleted options AND the
334
+	 *                                                       value that was selected for the answer, whether it was
335
+	 *                                                       trashed or not.
336
+	 * @return EE_Question_Option[]
337
+	 */
338
+	public function options($notDeletedOptionsOnly = true, $selected_value_to_always_include = null)
339
+	{
340
+		if (! $this->ID()) {
341
+			return array();
342
+		}
343
+		$query_params = array();
344
+		if ($selected_value_to_always_include) {
345
+			if (is_array($selected_value_to_always_include)) {
346
+				$query_params[0]['OR*options-query']['QSO_value'] = array('IN', $selected_value_to_always_include);
347
+			} else {
348
+				$query_params[0]['OR*options-query']['QSO_value'] = $selected_value_to_always_include;
349
+			}
350
+		}
351
+		if ($notDeletedOptionsOnly) {
352
+			$query_params[0]['OR*options-query']['QSO_deleted'] = false;
353
+		}
354
+		// order by QSO_order
355
+		$query_params['order_by'] = array('QSO_order' => 'ASC');
356
+		return $this->get_many_related('Question_Option', $query_params);
357
+	}
358
+
359
+
360
+	/**
361
+	 * returns an array of EE_Question_Options which relate to this question
362
+	 *
363
+	 * @return \EE_Question_Option[]
364
+	 */
365
+	public function temp_options()
366
+	{
367
+		return $this->_model_relations['Question_Option'];
368
+	}
369
+
370
+
371
+	/**
372
+	 * Adds an option for this question. Note: if the option were previously associated with a different
373
+	 * Question, that relationship will be overwritten.
374
+	 *
375
+	 * @param EE_Question_Option $option
376
+	 * @return boolean success
377
+	 */
378
+	public function add_option(EE_Question_Option $option)
379
+	{
380
+		return $this->_add_relation_to($option, 'Question_Option');
381
+	}
382
+
383
+
384
+	/**
385
+	 * Adds an option directly to this question without saving to the db
386
+	 *
387
+	 * @param EE_Question_Option $option
388
+	 * @return boolean success
389
+	 */
390
+	public function add_temp_option(EE_Question_Option $option)
391
+	{
392
+		$this->_model_relations['Question_Option'][] = $option;
393
+		return true;
394
+	}
395
+
396
+
397
+	/**
398
+	 * Marks the option as deleted.
399
+	 *
400
+	 * @param EE_Question_Option $option
401
+	 * @return boolean success
402
+	 */
403
+	public function remove_option(EE_Question_Option $option)
404
+	{
405
+		return $this->_remove_relation_to($option, 'Question_Option');
406
+	}
407
+
408
+
409
+	/**
410
+	 * @return bool
411
+	 */
412
+	public function is_system_question()
413
+	{
414
+		$system_ID = $this->get('QST_system');
415
+		return ! empty($system_ID) ? true : false;
416
+	}
417
+
418
+
419
+	/**
420
+	 * The purpose of this method is set the question order this question order to be the max out of all questions
421
+	 *
422
+	 * @access public
423
+	 * @return void
424
+	 */
425
+	public function set_order_to_latest()
426
+	{
427
+		$latest_order = $this->get_model()->get_latest_question_order();
428
+		$latest_order++;
429
+		$this->set('QST_order', $latest_order);
430
+	}
431
+
432
+
433
+	/**
434
+	 * Retrieves the list of allowed question types from the model.
435
+	 *
436
+	 * @return string[]
437
+	 */
438
+	private function _allowed_question_types()
439
+	{
440
+		$questionModel = $this->get_model();
441
+		/* @var $questionModel EEM_Question */
442
+		return $questionModel->allowed_question_types();
443
+	}
444
+
445
+	/**
446
+	 * Duplicates this question and its question options
447
+	 *
448
+	 * @return \EE_Question
449
+	 */
450
+	public function duplicate($options = array())
451
+	{
452
+		$new_question = clone $this;
453
+		$new_question->set('QST_ID', null);
454
+		$new_question->set_display_text(sprintf(__('%s **Duplicate**', 'event_espresso'), $this->display_text()));
455
+		$new_question->set_admin_label(sprintf(__('%s **Duplicate**', 'event_espresso'), $this->admin_label()));
456
+		$new_question->set_system_ID(null);
457
+		$new_question->set_wp_user(get_current_user_id());
458
+		// if we're duplicating a trashed question, assume we don't want the new one to be trashed
459
+		$new_question->set_deleted(false);
460
+		$success = $new_question->save();
461
+		if ($success) {
462
+			// we don't totally want to duplicate the question options, because we want them to be for the NEW question
463
+			foreach ($this->options() as $question_option) {
464
+				$question_option->duplicate(array('QST_ID' => $new_question->ID()));
465
+			}
466
+			return $new_question;
467
+		} else {
468
+			return null;
469
+		}
470
+	}
471
+
472
+	/**
473
+	 * Returns the question's maximum allowed response size
474
+	 *
475
+	 * @return int|float
476
+	 */
477
+	public function max()
478
+	{
479
+		return $this->get('QST_max');
480
+	}
481
+
482
+	/**
483
+	 * Sets the question's maximum allowed response size
484
+	 *
485
+	 * @param int|float $new_max
486
+	 * @return void
487
+	 */
488
+	public function set_max($new_max)
489
+	{
490
+		$this->set('QST_max', $new_max);
491
+	}
492
+
493
+
494
+	/**
495
+	 * Creates a form input from this question which can be used in HTML forms
496
+	 *
497
+	 * @param EE_Registration $registration
498
+	 * @param EE_Answer       $answer
499
+	 * @param array           $input_constructor_args
500
+	 * @return EE_Form_Input_Base
501
+	 */
502
+	public function generate_form_input($registration = null, $answer = null, $input_constructor_args = array())
503
+	{
504
+		$identifier = $this->is_system_question() ? $this->system_ID() : $this->ID();
505
+
506
+		$input_constructor_args = array_merge(
507
+			array(
508
+				'required'                          => $this->required() ? true : false,
509
+				'html_label_text'                   => $this->display_text(),
510
+				'required_validation_error_message' => $this->required_text(),
511
+			),
512
+			$input_constructor_args
513
+		);
514
+		if (! $answer instanceof EE_Answer && $registration instanceof EE_Registration) {
515
+			$answer = EEM_Answer::instance()->get_registration_question_answer_object($registration, $this->ID());
516
+		}
517
+		// has this question been answered ?
518
+		if (
519
+			$answer instanceof EE_Answer
520
+			&& $answer->value() !== ''
521
+		) {
522
+			// answer gets htmlspecialchars called on it, undo that please
523
+			// because the form input's display strategy may call esc_attr too
524
+			// which also does html special characters
525
+			$values_with_html_special_chars = $answer->value();
526
+			if (is_array($values_with_html_special_chars)) {
527
+				$default_value = array_map('htmlspecialchars_decode', $values_with_html_special_chars);
528
+			} else {
529
+				$default_value = htmlspecialchars_decode($values_with_html_special_chars);
530
+			}
531
+			$input_constructor_args['default'] = $default_value;
532
+		}
533
+		$max_max_for_question = EEM_Question::instance()->absolute_max_for_system_question($this->system_ID());
534
+		if (
535
+			in_array(
536
+				$this->type(),
537
+				EEM_Question::instance()->questionTypesWithMaxLength(),
538
+				true
539
+			)
540
+		) {
541
+			$input_constructor_args['validation_strategies'][] = new EE_Max_Length_Validation_Strategy(
542
+				null,
543
+				min($max_max_for_question, $this->max())
544
+			);
545
+		}
546
+		$input_constructor_args = apply_filters(
547
+			'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__input_constructor_args',
548
+			$input_constructor_args,
549
+			$registration,
550
+			$this,
551
+			$answer
552
+		);
553
+
554
+		$result = null;
555
+		switch ($this->type()) {
556
+			// Text
557
+			case EEM_Question::QST_type_text:
558
+				$result = new EE_Text_Input($input_constructor_args);
559
+				break;
560
+			// Textarea
561
+			case EEM_Question::QST_type_textarea:
562
+				$result = new EE_Text_Area_Input($input_constructor_args);
563
+				break;
564
+			// Radio Buttons
565
+			case EEM_Question::QST_type_radio:
566
+				$result = new EE_Radio_Button_Input($this->options(), $input_constructor_args);
567
+				break;
568
+			// Dropdown
569
+			case EEM_Question::QST_type_dropdown:
570
+				$result = new EE_Select_Input($this->options(), $input_constructor_args);
571
+				break;
572
+			// State Dropdown
573
+			case EEM_Question::QST_type_state:
574
+				$state_options = apply_filters(
575
+					'FHEE__EE_Question__generate_form_input__state_options',
576
+					null,
577
+					$this,
578
+					$registration,
579
+					$answer
580
+				);
581
+				$result = new EE_State_Select_Input($state_options, $input_constructor_args);
582
+				break;
583
+			// Country Dropdown
584
+			case EEM_Question::QST_type_country:
585
+				$country_options = apply_filters(
586
+					'FHEE__EE_Question__generate_form_input__country_options',
587
+					null,
588
+					$this,
589
+					$registration,
590
+					$answer
591
+				);
592
+				$result = new EE_Country_Select_Input($country_options, $input_constructor_args);
593
+				break;
594
+			// Checkboxes
595
+			case EEM_Question::QST_type_checkbox:
596
+				$result = new EE_Checkbox_Multi_Input($this->options(), $input_constructor_args);
597
+				break;
598
+			// Date
599
+			case EEM_Question::QST_type_date:
600
+				$result = new EE_Datepicker_Input($input_constructor_args);
601
+				break;
602
+			case EEM_Question::QST_type_html_textarea:
603
+				$input_constructor_args['validation_strategies'][] = new EE_Simple_HTML_Validation_Strategy();
604
+				$result = new EE_Text_Area_Input($input_constructor_args);
605
+				$result->remove_validation_strategy('EE_Plaintext_Validation_Strategy');
606
+				break;
607
+			case EEM_Question::QST_type_email:
608
+					$result = new EE_Email_Input($input_constructor_args);
609
+				break;
610
+			// Email confirm
611
+			case EEM_Question::QST_type_email_confirm:
612
+				$result = new EE_Email_Confirm_Input($input_constructor_args);
613
+				break;
614
+			case EEM_Question::QST_type_us_phone:
615
+				$result = new EE_Phone_Input($input_constructor_args);
616
+				break;
617
+			case EEM_Question::QST_type_int:
618
+				$result = new EE_Integer_Input($input_constructor_args);
619
+				break;
620
+			case EEM_Question::QST_type_decimal:
621
+				$result = new EE_Float_Input($input_constructor_args);
622
+				break;
623
+			case EEM_Question::QST_type_url:
624
+				$input_constructor_args['validation_strategies'][] = LoaderFactory::getLoader()->getNew('EE_URL_Validation_Strategy');
625
+				$result = new EE_Text_Input($input_constructor_args);
626
+				break;
627
+			case EEM_Question::QST_type_year:
628
+				$result = new EE_Year_Input(
629
+					$input_constructor_args,
630
+					apply_filters(
631
+						'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__year_question__four_digit',
632
+						true,
633
+						$this
634
+					),
635
+					apply_filters(
636
+						'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__year_question__early_range',
637
+						100,
638
+						$this
639
+					),
640
+					apply_filters(
641
+						'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__year_question__end_range',
642
+						100,
643
+						$this
644
+					)
645
+				);
646
+				break;
647
+			case EEM_Question::QST_type_multi_select:
648
+				$result = new EE_Select_Multiple_Input($this->options(), $input_constructor_args);
649
+				break;
650
+			// fallback
651
+			default:
652
+				$default_input = apply_filters(
653
+					'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__default',
654
+					null,
655
+					$this->type(),
656
+					$this,
657
+					$input_constructor_args
658
+				);
659
+				if (! $default_input) {
660
+					$default_input = new EE_Text_Input($input_constructor_args);
661
+				}
662
+				$result = $default_input;
663
+		}
664
+		return apply_filters('FHEE__EE_Question__generate_form_input__return', $result, $registration, $this, $answer);
665
+	}
666
+
667
+
668
+	/**
669
+	 * Returns whether or not this question type should have question option entries
670
+	 *
671
+	 * @return bool
672
+	 */
673
+	public function should_have_question_options()
674
+	{
675
+		return in_array(
676
+			$this->type(),
677
+			$this->_model->question_types_with_options(),
678
+			true
679
+		);
680
+	}
681 681
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Price.class.php 1 patch
Indentation   +442 added lines, -442 removed lines patch added patch discarded remove patch
@@ -13,446 +13,446 @@
 block discarded – undo
13 13
 class EE_Price extends EE_Soft_Delete_Base_Class
14 14
 {
15 15
 
16
-    /**
17
-     * @param array  $props_n_values          incoming values
18
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
19
-     *                                        used.)
20
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
21
-     *                                        date_format and the second value is the time format
22
-     * @return EE_Price
23
-     * @throws EE_Error
24
-     * @throws InvalidArgumentException
25
-     * @throws ReflectionException
26
-     * @throws InvalidDataTypeException
27
-     * @throws InvalidInterfaceException
28
-     */
29
-    public static function new_instance($props_n_values = array(), $timezone = '', $date_formats = array())
30
-    {
31
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
32
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
33
-    }
34
-
35
-
36
-    /**
37
-     * @param array  $props_n_values  incoming values from the database
38
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
39
-     *                                the website will be used.
40
-     * @return EE_Price
41
-     * @throws EE_Error
42
-     * @throws InvalidArgumentException
43
-     * @throws ReflectionException
44
-     * @throws InvalidDataTypeException
45
-     * @throws InvalidInterfaceException
46
-     */
47
-    public static function new_instance_from_db($props_n_values = array(), $timezone = '')
48
-    {
49
-        return new self($props_n_values, true, $timezone);
50
-    }
51
-
52
-
53
-    /**
54
-     * Set Price type ID
55
-     *
56
-     * @param int $PRT_ID
57
-     * @throws EE_Error
58
-     * @throws InvalidArgumentException
59
-     * @throws ReflectionException
60
-     * @throws InvalidDataTypeException
61
-     * @throws InvalidInterfaceException
62
-     */
63
-    public function set_type($PRT_ID = 0)
64
-    {
65
-        $this->set('PRT_ID', $PRT_ID);
66
-    }
67
-
68
-
69
-    /**
70
-     * Set Price Amount
71
-     *
72
-     * @param float $PRC_amount
73
-     * @throws EE_Error
74
-     * @throws InvalidArgumentException
75
-     * @throws ReflectionException
76
-     * @throws InvalidDataTypeException
77
-     * @throws InvalidInterfaceException
78
-     */
79
-    public function set_amount($PRC_amount = 0.00)
80
-    {
81
-        $this->set('PRC_amount', $PRC_amount);
82
-    }
83
-
84
-
85
-    /**
86
-     * Set Price Name
87
-     *
88
-     * @param string $PRC_name
89
-     * @throws EE_Error
90
-     * @throws InvalidArgumentException
91
-     * @throws ReflectionException
92
-     * @throws InvalidDataTypeException
93
-     * @throws InvalidInterfaceException
94
-     */
95
-    public function set_name($PRC_name = '')
96
-    {
97
-        $this->set('PRC_name', $PRC_name);
98
-    }
99
-
100
-
101
-    /**
102
-     * Set Price Description
103
-     *
104
-     * @param string $PRC_desc
105
-     * @throws EE_Error
106
-     * @throws InvalidArgumentException
107
-     * @throws ReflectionException
108
-     * @throws InvalidDataTypeException
109
-     * @throws InvalidInterfaceException
110
-     */
111
-    public function set_description($PRC_desc = '')
112
-    {
113
-        $this->Set('PRC_desc', $PRC_desc);
114
-    }
115
-
116
-
117
-    /**
118
-     * set is_default
119
-     *
120
-     * @param bool $PRC_is_default
121
-     * @throws EE_Error
122
-     * @throws InvalidArgumentException
123
-     * @throws ReflectionException
124
-     * @throws InvalidDataTypeException
125
-     * @throws InvalidInterfaceException
126
-     */
127
-    public function set_is_default($PRC_is_default = false)
128
-    {
129
-        $this->set('PRC_is_default', $PRC_is_default);
130
-    }
131
-
132
-
133
-    /**
134
-     * set deleted
135
-     *
136
-     * @param bool $PRC_deleted
137
-     * @throws EE_Error
138
-     * @throws InvalidArgumentException
139
-     * @throws ReflectionException
140
-     * @throws InvalidDataTypeException
141
-     * @throws InvalidInterfaceException
142
-     */
143
-    public function set_deleted($PRC_deleted = null)
144
-    {
145
-        $this->set('PRC_deleted', $PRC_deleted);
146
-    }
147
-
148
-
149
-    /**
150
-     * get Price type
151
-     *
152
-     * @return        int
153
-     * @throws EE_Error
154
-     * @throws InvalidArgumentException
155
-     * @throws ReflectionException
156
-     * @throws InvalidDataTypeException
157
-     * @throws InvalidInterfaceException
158
-     */
159
-    public function type()
160
-    {
161
-        return $this->get('PRT_ID');
162
-    }
163
-
164
-
165
-    /**
166
-     * get Price Amount
167
-     *
168
-     * @return        float
169
-     * @throws EE_Error
170
-     * @throws InvalidArgumentException
171
-     * @throws ReflectionException
172
-     * @throws InvalidDataTypeException
173
-     * @throws InvalidInterfaceException
174
-     */
175
-    public function amount()
176
-    {
177
-        return $this->get('PRC_amount');
178
-    }
179
-
180
-
181
-    /**
182
-     * get Price Name
183
-     *
184
-     * @return        string
185
-     * @throws EE_Error
186
-     * @throws InvalidArgumentException
187
-     * @throws ReflectionException
188
-     * @throws InvalidDataTypeException
189
-     * @throws InvalidInterfaceException
190
-     */
191
-    public function name()
192
-    {
193
-        return $this->get('PRC_name');
194
-    }
195
-
196
-
197
-    /**
198
-     * get Price description
199
-     *
200
-     * @return        string
201
-     * @throws EE_Error
202
-     * @throws InvalidArgumentException
203
-     * @throws ReflectionException
204
-     * @throws InvalidDataTypeException
205
-     * @throws InvalidInterfaceException
206
-     */
207
-    public function desc()
208
-    {
209
-        return $this->get('PRC_desc');
210
-    }
211
-
212
-
213
-    /**
214
-     * get overrides
215
-     *
216
-     * @return        int
217
-     * @throws EE_Error
218
-     * @throws InvalidArgumentException
219
-     * @throws ReflectionException
220
-     * @throws InvalidDataTypeException
221
-     * @throws InvalidInterfaceException
222
-     */
223
-    public function overrides()
224
-    {
225
-        return $this->get('PRC_overrides');
226
-    }
227
-
228
-
229
-    /**
230
-     * get order
231
-     *
232
-     * @return int
233
-     * @throws EE_Error
234
-     * @throws InvalidArgumentException
235
-     * @throws ReflectionException
236
-     * @throws InvalidDataTypeException
237
-     * @throws InvalidInterfaceException
238
-     */
239
-    public function order()
240
-    {
241
-        return $this->get('PRC_order');
242
-    }
243
-
244
-
245
-    /**
246
-     * get the author of the price
247
-     *
248
-     * @return int
249
-     * @throws EE_Error
250
-     * @throws InvalidArgumentException
251
-     * @throws ReflectionException
252
-     * @throws InvalidDataTypeException
253
-     * @throws InvalidInterfaceException
254
-     * @since 4.5.0
255
-     */
256
-    public function wp_user()
257
-    {
258
-        return $this->get('PRC_wp_user');
259
-    }
260
-
261
-
262
-    /**
263
-     * get is_default
264
-     *
265
-     * @return bool
266
-     * @throws EE_Error
267
-     * @throws InvalidArgumentException
268
-     * @throws ReflectionException
269
-     * @throws InvalidDataTypeException
270
-     * @throws InvalidInterfaceException
271
-     */
272
-    public function is_default()
273
-    {
274
-        return $this->get('PRC_is_default');
275
-    }
276
-
277
-
278
-    /**
279
-     * get deleted
280
-     *
281
-     * @return bool
282
-     * @throws EE_Error
283
-     * @throws InvalidArgumentException
284
-     * @throws ReflectionException
285
-     * @throws InvalidDataTypeException
286
-     * @throws InvalidInterfaceException
287
-     */
288
-    public function deleted()
289
-    {
290
-        return $this->get('PRC_deleted');
291
-    }
292
-
293
-
294
-    /**
295
-     * @return bool
296
-     * @throws EE_Error
297
-     * @throws InvalidArgumentException
298
-     * @throws ReflectionException
299
-     * @throws InvalidDataTypeException
300
-     * @throws InvalidInterfaceException
301
-     */
302
-    public function parent()
303
-    {
304
-        return $this->get('PRC_parent');
305
-    }
306
-
307
-
308
-    // some helper methods for getting info on the price_type for this price
309
-
310
-
311
-    /**
312
-     * return whether the price is a base price or not
313
-     *
314
-     * @return boolean
315
-     * @throws EE_Error
316
-     * @throws InvalidArgumentException
317
-     * @throws InvalidDataTypeException
318
-     * @throws InvalidInterfaceException
319
-     * @throws ReflectionException
320
-     */
321
-    public function is_base_price()
322
-    {
323
-        $price_type = $this->type_obj();
324
-        return $price_type->is_base_price();
325
-    }
326
-
327
-
328
-    /**
329
-     * @return EE_Base_Class|EE_Price_Type
330
-     * @throws EE_Error
331
-     * @throws InvalidArgumentException
332
-     * @throws ReflectionException
333
-     * @throws InvalidDataTypeException
334
-     * @throws InvalidInterfaceException
335
-     */
336
-    public function type_obj()
337
-    {
338
-        return $this->get_first_related('Price_Type');
339
-    }
340
-
341
-
342
-    /**
343
-     * @return int
344
-     * @throws EE_Error
345
-     * @throws InvalidArgumentException
346
-     * @throws ReflectionException
347
-     * @throws InvalidDataTypeException
348
-     * @throws InvalidInterfaceException
349
-     */
350
-    public function type_order()
351
-    {
352
-        return $this->get_first_related('Price_Type')->order();
353
-    }
354
-
355
-
356
-    /**
357
-     * Simply indicates whether this price increases or decreases the total
358
-     *
359
-     * @return boolean true = discount, otherwise adds to the total
360
-     * @throws EE_Error
361
-     * @throws InvalidArgumentException
362
-     * @throws ReflectionException
363
-     * @throws InvalidDataTypeException
364
-     * @throws InvalidInterfaceException
365
-     */
366
-    public function is_discount()
367
-    {
368
-        $price_type = $this->type_obj();
369
-        return $price_type->is_discount();
370
-    }
371
-
372
-
373
-    /**
374
-     * whether the price is a percentage or not
375
-     *
376
-     * @return boolean
377
-     * @throws EE_Error
378
-     * @throws InvalidArgumentException
379
-     * @throws InvalidDataTypeException
380
-     * @throws InvalidInterfaceException
381
-     * @throws ReflectionException
382
-     */
383
-    public function is_percent()
384
-    {
385
-        $price_type = $this->type_obj();
386
-        return $price_type->is_percent();
387
-    }
388
-
389
-
390
-    /**
391
-     * whether the price is a percentage or not
392
-     *
393
-     * @return boolean
394
-     * @throws EE_Error
395
-     * @throws InvalidArgumentException
396
-     * @throws ReflectionException
397
-     * @throws InvalidDataTypeException
398
-     * @throws InvalidInterfaceException
399
-     */
400
-    public function is_surcharge()
401
-    {
402
-        $price_type = $this->type_obj();
403
-        return $price_type->is_surcharge();
404
-    }
405
-
406
-    /**
407
-     * whether the price is a percentage or not
408
-     *
409
-     * @return boolean
410
-     * @throws EE_Error
411
-     * @throws InvalidArgumentException
412
-     * @throws ReflectionException
413
-     * @throws InvalidDataTypeException
414
-     * @throws InvalidInterfaceException
415
-     */
416
-    public function is_tax()
417
-    {
418
-        $price_type = $this->type_obj();
419
-        return $price_type->is_tax();
420
-    }
421
-
422
-
423
-    /**
424
-     * return pretty price dependant on whether its a dollar or percent.
425
-     *
426
-     * @return string
427
-     * @throws EE_Error
428
-     * @throws InvalidArgumentException
429
-     * @throws ReflectionException
430
-     * @throws InvalidDataTypeException
431
-     * @throws InvalidInterfaceException
432
-     * @since 4.4.0
433
-     */
434
-    public function pretty_price()
435
-    {
436
-        return ! $this->is_percent()
437
-            ? $this->get_pretty('PRC_amount')
438
-            : $this->get('PRC_amount') . '%';
439
-    }
440
-
441
-
442
-    /**
443
-     * @return mixed
444
-     * @throws EE_Error
445
-     * @throws InvalidArgumentException
446
-     * @throws ReflectionException
447
-     * @throws InvalidDataTypeException
448
-     * @throws InvalidInterfaceException
449
-     */
450
-    public function get_price_without_currency_symbol()
451
-    {
452
-        return str_replace(
453
-            EE_Registry::instance()->CFG->currency->sign,
454
-            '',
455
-            $this->get_pretty('PRC_amount')
456
-        );
457
-    }
16
+	/**
17
+	 * @param array  $props_n_values          incoming values
18
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
19
+	 *                                        used.)
20
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
21
+	 *                                        date_format and the second value is the time format
22
+	 * @return EE_Price
23
+	 * @throws EE_Error
24
+	 * @throws InvalidArgumentException
25
+	 * @throws ReflectionException
26
+	 * @throws InvalidDataTypeException
27
+	 * @throws InvalidInterfaceException
28
+	 */
29
+	public static function new_instance($props_n_values = array(), $timezone = '', $date_formats = array())
30
+	{
31
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
32
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
33
+	}
34
+
35
+
36
+	/**
37
+	 * @param array  $props_n_values  incoming values from the database
38
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
39
+	 *                                the website will be used.
40
+	 * @return EE_Price
41
+	 * @throws EE_Error
42
+	 * @throws InvalidArgumentException
43
+	 * @throws ReflectionException
44
+	 * @throws InvalidDataTypeException
45
+	 * @throws InvalidInterfaceException
46
+	 */
47
+	public static function new_instance_from_db($props_n_values = array(), $timezone = '')
48
+	{
49
+		return new self($props_n_values, true, $timezone);
50
+	}
51
+
52
+
53
+	/**
54
+	 * Set Price type ID
55
+	 *
56
+	 * @param int $PRT_ID
57
+	 * @throws EE_Error
58
+	 * @throws InvalidArgumentException
59
+	 * @throws ReflectionException
60
+	 * @throws InvalidDataTypeException
61
+	 * @throws InvalidInterfaceException
62
+	 */
63
+	public function set_type($PRT_ID = 0)
64
+	{
65
+		$this->set('PRT_ID', $PRT_ID);
66
+	}
67
+
68
+
69
+	/**
70
+	 * Set Price Amount
71
+	 *
72
+	 * @param float $PRC_amount
73
+	 * @throws EE_Error
74
+	 * @throws InvalidArgumentException
75
+	 * @throws ReflectionException
76
+	 * @throws InvalidDataTypeException
77
+	 * @throws InvalidInterfaceException
78
+	 */
79
+	public function set_amount($PRC_amount = 0.00)
80
+	{
81
+		$this->set('PRC_amount', $PRC_amount);
82
+	}
83
+
84
+
85
+	/**
86
+	 * Set Price Name
87
+	 *
88
+	 * @param string $PRC_name
89
+	 * @throws EE_Error
90
+	 * @throws InvalidArgumentException
91
+	 * @throws ReflectionException
92
+	 * @throws InvalidDataTypeException
93
+	 * @throws InvalidInterfaceException
94
+	 */
95
+	public function set_name($PRC_name = '')
96
+	{
97
+		$this->set('PRC_name', $PRC_name);
98
+	}
99
+
100
+
101
+	/**
102
+	 * Set Price Description
103
+	 *
104
+	 * @param string $PRC_desc
105
+	 * @throws EE_Error
106
+	 * @throws InvalidArgumentException
107
+	 * @throws ReflectionException
108
+	 * @throws InvalidDataTypeException
109
+	 * @throws InvalidInterfaceException
110
+	 */
111
+	public function set_description($PRC_desc = '')
112
+	{
113
+		$this->Set('PRC_desc', $PRC_desc);
114
+	}
115
+
116
+
117
+	/**
118
+	 * set is_default
119
+	 *
120
+	 * @param bool $PRC_is_default
121
+	 * @throws EE_Error
122
+	 * @throws InvalidArgumentException
123
+	 * @throws ReflectionException
124
+	 * @throws InvalidDataTypeException
125
+	 * @throws InvalidInterfaceException
126
+	 */
127
+	public function set_is_default($PRC_is_default = false)
128
+	{
129
+		$this->set('PRC_is_default', $PRC_is_default);
130
+	}
131
+
132
+
133
+	/**
134
+	 * set deleted
135
+	 *
136
+	 * @param bool $PRC_deleted
137
+	 * @throws EE_Error
138
+	 * @throws InvalidArgumentException
139
+	 * @throws ReflectionException
140
+	 * @throws InvalidDataTypeException
141
+	 * @throws InvalidInterfaceException
142
+	 */
143
+	public function set_deleted($PRC_deleted = null)
144
+	{
145
+		$this->set('PRC_deleted', $PRC_deleted);
146
+	}
147
+
148
+
149
+	/**
150
+	 * get Price type
151
+	 *
152
+	 * @return        int
153
+	 * @throws EE_Error
154
+	 * @throws InvalidArgumentException
155
+	 * @throws ReflectionException
156
+	 * @throws InvalidDataTypeException
157
+	 * @throws InvalidInterfaceException
158
+	 */
159
+	public function type()
160
+	{
161
+		return $this->get('PRT_ID');
162
+	}
163
+
164
+
165
+	/**
166
+	 * get Price Amount
167
+	 *
168
+	 * @return        float
169
+	 * @throws EE_Error
170
+	 * @throws InvalidArgumentException
171
+	 * @throws ReflectionException
172
+	 * @throws InvalidDataTypeException
173
+	 * @throws InvalidInterfaceException
174
+	 */
175
+	public function amount()
176
+	{
177
+		return $this->get('PRC_amount');
178
+	}
179
+
180
+
181
+	/**
182
+	 * get Price Name
183
+	 *
184
+	 * @return        string
185
+	 * @throws EE_Error
186
+	 * @throws InvalidArgumentException
187
+	 * @throws ReflectionException
188
+	 * @throws InvalidDataTypeException
189
+	 * @throws InvalidInterfaceException
190
+	 */
191
+	public function name()
192
+	{
193
+		return $this->get('PRC_name');
194
+	}
195
+
196
+
197
+	/**
198
+	 * get Price description
199
+	 *
200
+	 * @return        string
201
+	 * @throws EE_Error
202
+	 * @throws InvalidArgumentException
203
+	 * @throws ReflectionException
204
+	 * @throws InvalidDataTypeException
205
+	 * @throws InvalidInterfaceException
206
+	 */
207
+	public function desc()
208
+	{
209
+		return $this->get('PRC_desc');
210
+	}
211
+
212
+
213
+	/**
214
+	 * get overrides
215
+	 *
216
+	 * @return        int
217
+	 * @throws EE_Error
218
+	 * @throws InvalidArgumentException
219
+	 * @throws ReflectionException
220
+	 * @throws InvalidDataTypeException
221
+	 * @throws InvalidInterfaceException
222
+	 */
223
+	public function overrides()
224
+	{
225
+		return $this->get('PRC_overrides');
226
+	}
227
+
228
+
229
+	/**
230
+	 * get order
231
+	 *
232
+	 * @return int
233
+	 * @throws EE_Error
234
+	 * @throws InvalidArgumentException
235
+	 * @throws ReflectionException
236
+	 * @throws InvalidDataTypeException
237
+	 * @throws InvalidInterfaceException
238
+	 */
239
+	public function order()
240
+	{
241
+		return $this->get('PRC_order');
242
+	}
243
+
244
+
245
+	/**
246
+	 * get the author of the price
247
+	 *
248
+	 * @return int
249
+	 * @throws EE_Error
250
+	 * @throws InvalidArgumentException
251
+	 * @throws ReflectionException
252
+	 * @throws InvalidDataTypeException
253
+	 * @throws InvalidInterfaceException
254
+	 * @since 4.5.0
255
+	 */
256
+	public function wp_user()
257
+	{
258
+		return $this->get('PRC_wp_user');
259
+	}
260
+
261
+
262
+	/**
263
+	 * get is_default
264
+	 *
265
+	 * @return bool
266
+	 * @throws EE_Error
267
+	 * @throws InvalidArgumentException
268
+	 * @throws ReflectionException
269
+	 * @throws InvalidDataTypeException
270
+	 * @throws InvalidInterfaceException
271
+	 */
272
+	public function is_default()
273
+	{
274
+		return $this->get('PRC_is_default');
275
+	}
276
+
277
+
278
+	/**
279
+	 * get deleted
280
+	 *
281
+	 * @return bool
282
+	 * @throws EE_Error
283
+	 * @throws InvalidArgumentException
284
+	 * @throws ReflectionException
285
+	 * @throws InvalidDataTypeException
286
+	 * @throws InvalidInterfaceException
287
+	 */
288
+	public function deleted()
289
+	{
290
+		return $this->get('PRC_deleted');
291
+	}
292
+
293
+
294
+	/**
295
+	 * @return bool
296
+	 * @throws EE_Error
297
+	 * @throws InvalidArgumentException
298
+	 * @throws ReflectionException
299
+	 * @throws InvalidDataTypeException
300
+	 * @throws InvalidInterfaceException
301
+	 */
302
+	public function parent()
303
+	{
304
+		return $this->get('PRC_parent');
305
+	}
306
+
307
+
308
+	// some helper methods for getting info on the price_type for this price
309
+
310
+
311
+	/**
312
+	 * return whether the price is a base price or not
313
+	 *
314
+	 * @return boolean
315
+	 * @throws EE_Error
316
+	 * @throws InvalidArgumentException
317
+	 * @throws InvalidDataTypeException
318
+	 * @throws InvalidInterfaceException
319
+	 * @throws ReflectionException
320
+	 */
321
+	public function is_base_price()
322
+	{
323
+		$price_type = $this->type_obj();
324
+		return $price_type->is_base_price();
325
+	}
326
+
327
+
328
+	/**
329
+	 * @return EE_Base_Class|EE_Price_Type
330
+	 * @throws EE_Error
331
+	 * @throws InvalidArgumentException
332
+	 * @throws ReflectionException
333
+	 * @throws InvalidDataTypeException
334
+	 * @throws InvalidInterfaceException
335
+	 */
336
+	public function type_obj()
337
+	{
338
+		return $this->get_first_related('Price_Type');
339
+	}
340
+
341
+
342
+	/**
343
+	 * @return int
344
+	 * @throws EE_Error
345
+	 * @throws InvalidArgumentException
346
+	 * @throws ReflectionException
347
+	 * @throws InvalidDataTypeException
348
+	 * @throws InvalidInterfaceException
349
+	 */
350
+	public function type_order()
351
+	{
352
+		return $this->get_first_related('Price_Type')->order();
353
+	}
354
+
355
+
356
+	/**
357
+	 * Simply indicates whether this price increases or decreases the total
358
+	 *
359
+	 * @return boolean true = discount, otherwise adds to the total
360
+	 * @throws EE_Error
361
+	 * @throws InvalidArgumentException
362
+	 * @throws ReflectionException
363
+	 * @throws InvalidDataTypeException
364
+	 * @throws InvalidInterfaceException
365
+	 */
366
+	public function is_discount()
367
+	{
368
+		$price_type = $this->type_obj();
369
+		return $price_type->is_discount();
370
+	}
371
+
372
+
373
+	/**
374
+	 * whether the price is a percentage or not
375
+	 *
376
+	 * @return boolean
377
+	 * @throws EE_Error
378
+	 * @throws InvalidArgumentException
379
+	 * @throws InvalidDataTypeException
380
+	 * @throws InvalidInterfaceException
381
+	 * @throws ReflectionException
382
+	 */
383
+	public function is_percent()
384
+	{
385
+		$price_type = $this->type_obj();
386
+		return $price_type->is_percent();
387
+	}
388
+
389
+
390
+	/**
391
+	 * whether the price is a percentage or not
392
+	 *
393
+	 * @return boolean
394
+	 * @throws EE_Error
395
+	 * @throws InvalidArgumentException
396
+	 * @throws ReflectionException
397
+	 * @throws InvalidDataTypeException
398
+	 * @throws InvalidInterfaceException
399
+	 */
400
+	public function is_surcharge()
401
+	{
402
+		$price_type = $this->type_obj();
403
+		return $price_type->is_surcharge();
404
+	}
405
+
406
+	/**
407
+	 * whether the price is a percentage or not
408
+	 *
409
+	 * @return boolean
410
+	 * @throws EE_Error
411
+	 * @throws InvalidArgumentException
412
+	 * @throws ReflectionException
413
+	 * @throws InvalidDataTypeException
414
+	 * @throws InvalidInterfaceException
415
+	 */
416
+	public function is_tax()
417
+	{
418
+		$price_type = $this->type_obj();
419
+		return $price_type->is_tax();
420
+	}
421
+
422
+
423
+	/**
424
+	 * return pretty price dependant on whether its a dollar or percent.
425
+	 *
426
+	 * @return string
427
+	 * @throws EE_Error
428
+	 * @throws InvalidArgumentException
429
+	 * @throws ReflectionException
430
+	 * @throws InvalidDataTypeException
431
+	 * @throws InvalidInterfaceException
432
+	 * @since 4.4.0
433
+	 */
434
+	public function pretty_price()
435
+	{
436
+		return ! $this->is_percent()
437
+			? $this->get_pretty('PRC_amount')
438
+			: $this->get('PRC_amount') . '%';
439
+	}
440
+
441
+
442
+	/**
443
+	 * @return mixed
444
+	 * @throws EE_Error
445
+	 * @throws InvalidArgumentException
446
+	 * @throws ReflectionException
447
+	 * @throws InvalidDataTypeException
448
+	 * @throws InvalidInterfaceException
449
+	 */
450
+	public function get_price_without_currency_symbol()
451
+	{
452
+		return str_replace(
453
+			EE_Registry::instance()->CFG->currency->sign,
454
+			'',
455
+			$this->get_pretty('PRC_amount')
456
+		);
457
+	}
458 458
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Checkin.class.php 1 patch
Indentation   +103 added lines, -103 removed lines patch added patch discarded remove patch
@@ -11,107 +11,107 @@
 block discarded – undo
11 11
 {
12 12
 
13 13
 
14
-    /**
15
-     * Used to reference when a registration has been checked out.
16
-     *
17
-     * @type int
18
-     */
19
-    const status_checked_out = 0;
20
-
21
-    /**
22
-     * Used to reference when a registration has been checked in.
23
-     *
24
-     * @type int
25
-     */
26
-    const status_checked_in = 1;
27
-
28
-    /**
29
-     * Used to reference when a registration has never been checked in.
30
-     *
31
-     * @type int
32
-     */
33
-    const status_checked_never = 2;
34
-
35
-
36
-    /**
37
-     * @param array  $props_n_values    incoming values
38
-     * @param string $timezone          incoming timezone (if not set the timezone set for the website will be used.)
39
-     * @param array  $date_formats      incoming date_formats in an array
40
-     *                                  where the first value is the date_format
41
-     *                                  and the second value is the time format
42
-     * @return EE_Checkin
43
-     * @throws EE_Error
44
-     * @throws ReflectionException
45
-     */
46
-    public static function new_instance($props_n_values = [], $timezone = '', $date_formats = [])
47
-    {
48
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
49
-        return $has_object
50
-            ? $has_object
51
-            : new self($props_n_values, false, $timezone, $date_formats);
52
-    }
53
-
54
-
55
-    /**
56
-     * @param array  $props_n_values  incoming values from the database
57
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
58
-     *                                the website will be used.
59
-     * @return EE_Checkin
60
-     * @throws EE_Error
61
-     * @throws ReflectionException
62
-     */
63
-    public static function new_instance_from_db($props_n_values = [], $timezone = '')
64
-    {
65
-        return new self($props_n_values, true, $timezone);
66
-    }
67
-
68
-
69
-    /**
70
-     * @return mixed
71
-     * @throws EE_Error
72
-     */
73
-    public function ID()
74
-    {
75
-        return $this->get('CHK_ID');
76
-    }
77
-
78
-
79
-    /**
80
-     * @return mixed
81
-     * @throws EE_Error
82
-     */
83
-    public function registration_id()
84
-    {
85
-        return $this->get('REG_ID');
86
-    }
87
-
88
-
89
-    /**
90
-     * @return mixed
91
-     * @throws EE_Error
92
-     */
93
-    public function datetime_id()
94
-    {
95
-        return $this->get('DTT_ID');
96
-    }
97
-
98
-
99
-    /**
100
-     * @return mixed
101
-     * @throws EE_Error
102
-     */
103
-    public function status()
104
-    {
105
-        return $this->get('CHK_in');
106
-    }
107
-
108
-
109
-    /**
110
-     * @return mixed
111
-     * @throws EE_Error
112
-     */
113
-    public function timestamp()
114
-    {
115
-        return $this->get('CHK_timestamp');
116
-    }
14
+	/**
15
+	 * Used to reference when a registration has been checked out.
16
+	 *
17
+	 * @type int
18
+	 */
19
+	const status_checked_out = 0;
20
+
21
+	/**
22
+	 * Used to reference when a registration has been checked in.
23
+	 *
24
+	 * @type int
25
+	 */
26
+	const status_checked_in = 1;
27
+
28
+	/**
29
+	 * Used to reference when a registration has never been checked in.
30
+	 *
31
+	 * @type int
32
+	 */
33
+	const status_checked_never = 2;
34
+
35
+
36
+	/**
37
+	 * @param array  $props_n_values    incoming values
38
+	 * @param string $timezone          incoming timezone (if not set the timezone set for the website will be used.)
39
+	 * @param array  $date_formats      incoming date_formats in an array
40
+	 *                                  where the first value is the date_format
41
+	 *                                  and the second value is the time format
42
+	 * @return EE_Checkin
43
+	 * @throws EE_Error
44
+	 * @throws ReflectionException
45
+	 */
46
+	public static function new_instance($props_n_values = [], $timezone = '', $date_formats = [])
47
+	{
48
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
49
+		return $has_object
50
+			? $has_object
51
+			: new self($props_n_values, false, $timezone, $date_formats);
52
+	}
53
+
54
+
55
+	/**
56
+	 * @param array  $props_n_values  incoming values from the database
57
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
58
+	 *                                the website will be used.
59
+	 * @return EE_Checkin
60
+	 * @throws EE_Error
61
+	 * @throws ReflectionException
62
+	 */
63
+	public static function new_instance_from_db($props_n_values = [], $timezone = '')
64
+	{
65
+		return new self($props_n_values, true, $timezone);
66
+	}
67
+
68
+
69
+	/**
70
+	 * @return mixed
71
+	 * @throws EE_Error
72
+	 */
73
+	public function ID()
74
+	{
75
+		return $this->get('CHK_ID');
76
+	}
77
+
78
+
79
+	/**
80
+	 * @return mixed
81
+	 * @throws EE_Error
82
+	 */
83
+	public function registration_id()
84
+	{
85
+		return $this->get('REG_ID');
86
+	}
87
+
88
+
89
+	/**
90
+	 * @return mixed
91
+	 * @throws EE_Error
92
+	 */
93
+	public function datetime_id()
94
+	{
95
+		return $this->get('DTT_ID');
96
+	}
97
+
98
+
99
+	/**
100
+	 * @return mixed
101
+	 * @throws EE_Error
102
+	 */
103
+	public function status()
104
+	{
105
+		return $this->get('CHK_in');
106
+	}
107
+
108
+
109
+	/**
110
+	 * @return mixed
111
+	 * @throws EE_Error
112
+	 */
113
+	public function timestamp()
114
+	{
115
+		return $this->get('CHK_timestamp');
116
+	}
117 117
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Currency.class.php 1 patch
Indentation   +234 added lines, -234 removed lines patch added patch discarded remove patch
@@ -10,238 +10,238 @@
 block discarded – undo
10 10
 class EE_Currency extends EE_Base_Class
11 11
 {
12 12
 
13
-    /** Currency COde
14
-     *
15
-     * @var CUR_code
16
-     */
17
-    protected $_CUR_code = null;
18
-
19
-    /** Currency Name Singular
20
-     *
21
-     * @var CUR_single
22
-     */
23
-    protected $_CUR_single = null;
24
-
25
-    /** Currency Name Plural
26
-     *
27
-     * @var CUR_plural
28
-     */
29
-    protected $_CUR_plural = null;
30
-
31
-    /** Currency Sign
32
-     *
33
-     * @var CUR_sign
34
-     */
35
-    protected $_CUR_sign = null;
36
-
37
-    /** Currency Decimal Places
38
-     *
39
-     * @var CUR_dec_plc
40
-     */
41
-    protected $_CUR_dec_plc = null;
42
-
43
-    /** Active?
44
-     *
45
-     * @var CUR_active
46
-     */
47
-    protected $_CUR_active = null;
48
-
49
-    protected $_Payment_Method;
50
-
51
-
52
-    /**
53
-     * @param array  $props_n_values          incoming values
54
-     * @param string $timezone                incoming timezone
55
-     *                                        (if not set the timezone set for the website will be used.)
56
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
57
-     *                                        date_format and the second value is the time format
58
-     * @return EE_Currency
59
-     * @throws EE_Error
60
-     * @throws ReflectionException
61
-     */
62
-    public static function new_instance($props_n_values = [], $timezone = '', $date_formats = [])
63
-    {
64
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
65
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
66
-    }
67
-
68
-
69
-    /**
70
-     * @param array  $props_n_values  incoming values from the database
71
-     * @param string $timezone        incoming timezone as set by the model.
72
-     *                                If not set the timezone for the website will be used.
73
-     * @return EE_Currency
74
-     * @throws EE_Error
75
-     * @throws ReflectionException
76
-     */
77
-    public static function new_instance_from_db($props_n_values = [], $timezone = '')
78
-    {
79
-        return new self($props_n_values, true, $timezone);
80
-    }
81
-
82
-
83
-    /**
84
-     * Sets code
85
-     *
86
-     * @param string $code
87
-     * @throws EE_Error
88
-     * @throws ReflectionException
89
-     */
90
-    public function set_code($code)
91
-    {
92
-        $this->set('CUR_code', $code);
93
-    }
94
-
95
-
96
-    /**
97
-     * Gets active
98
-     *
99
-     * @return boolean
100
-     * @throws EE_Error
101
-     */
102
-    public function active()
103
-    {
104
-        return $this->get('CUR_active');
105
-    }
106
-
107
-
108
-    /**
109
-     * Sets active
110
-     *
111
-     * @param boolean $active
112
-     * @throws EE_Error
113
-     * @throws ReflectionException
114
-     */
115
-    public function set_active($active)
116
-    {
117
-        $this->set('CUR_active', $active);
118
-    }
119
-
120
-
121
-    /**
122
-     * Gets dec_plc
123
-     *
124
-     * @return int
125
-     * @throws EE_Error
126
-     */
127
-    public function dec_plc()
128
-    {
129
-        return $this->get('CUR_dec_plc');
130
-    }
131
-
132
-
133
-    /**
134
-     * Sets dec_plc
135
-     *
136
-     * @param int $dec_plc
137
-     * @throws EE_Error
138
-     * @throws ReflectionException
139
-     */
140
-    public function set_dec_plc($dec_plc)
141
-    {
142
-        $this->set('CUR_dec_plc', $dec_plc);
143
-    }
144
-
145
-
146
-    /**
147
-     * Sets plural
148
-     *
149
-     * @param string $plural
150
-     * @throws EE_Error
151
-     * @throws ReflectionException
152
-     */
153
-    public function set_plural_name($plural)
154
-    {
155
-        $this->set('CUR_plural', $plural);
156
-    }
157
-
158
-
159
-    /**
160
-     * Gets sign
161
-     *
162
-     * @return string
163
-     * @throws EE_Error
164
-     */
165
-    public function sign()
166
-    {
167
-        return $this->get('CUR_sign');
168
-    }
169
-
170
-
171
-    /**
172
-     * Sets sign
173
-     *
174
-     * @param string $sign
175
-     * @throws EE_Error
176
-     * @throws ReflectionException
177
-     */
178
-    public function set_sign($sign)
179
-    {
180
-        $this->set('CUR_sign', $sign);
181
-    }
182
-
183
-
184
-    /**
185
-     * Gets single
186
-     *
187
-     * @return string
188
-     * @throws EE_Error
189
-     */
190
-    public function singular_name()
191
-    {
192
-        return $this->get('CUR_single');
193
-    }
194
-
195
-
196
-    /**
197
-     * Sets single
198
-     *
199
-     * @param string $single
200
-     * @throws EE_Error
201
-     * @throws ReflectionException
202
-     */
203
-    public function set_singular_name($single)
204
-    {
205
-        $this->set('CUR_single', $single);
206
-    }
207
-
208
-
209
-    /**
210
-     * Gets a prettier name
211
-     *
212
-     * @return string
213
-     * @throws EE_Error
214
-     */
215
-    public function name()
216
-    {
217
-        return sprintf(
218
-            esc_html__("%s (%s)", "event_espresso"),
219
-            $this->code(),
220
-            $this->plural_name()
221
-        );
222
-    }
223
-
224
-
225
-    /**
226
-     * Gets code
227
-     *
228
-     * @return string
229
-     * @throws EE_Error
230
-     */
231
-    public function code()
232
-    {
233
-        return $this->get('CUR_code');
234
-    }
235
-
236
-
237
-    /**
238
-     * Gets plural
239
-     *
240
-     * @return string
241
-     * @throws EE_Error
242
-     */
243
-    public function plural_name()
244
-    {
245
-        return $this->get('CUR_plural');
246
-    }
13
+	/** Currency COde
14
+	 *
15
+	 * @var CUR_code
16
+	 */
17
+	protected $_CUR_code = null;
18
+
19
+	/** Currency Name Singular
20
+	 *
21
+	 * @var CUR_single
22
+	 */
23
+	protected $_CUR_single = null;
24
+
25
+	/** Currency Name Plural
26
+	 *
27
+	 * @var CUR_plural
28
+	 */
29
+	protected $_CUR_plural = null;
30
+
31
+	/** Currency Sign
32
+	 *
33
+	 * @var CUR_sign
34
+	 */
35
+	protected $_CUR_sign = null;
36
+
37
+	/** Currency Decimal Places
38
+	 *
39
+	 * @var CUR_dec_plc
40
+	 */
41
+	protected $_CUR_dec_plc = null;
42
+
43
+	/** Active?
44
+	 *
45
+	 * @var CUR_active
46
+	 */
47
+	protected $_CUR_active = null;
48
+
49
+	protected $_Payment_Method;
50
+
51
+
52
+	/**
53
+	 * @param array  $props_n_values          incoming values
54
+	 * @param string $timezone                incoming timezone
55
+	 *                                        (if not set the timezone set for the website will be used.)
56
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
57
+	 *                                        date_format and the second value is the time format
58
+	 * @return EE_Currency
59
+	 * @throws EE_Error
60
+	 * @throws ReflectionException
61
+	 */
62
+	public static function new_instance($props_n_values = [], $timezone = '', $date_formats = [])
63
+	{
64
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
65
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
66
+	}
67
+
68
+
69
+	/**
70
+	 * @param array  $props_n_values  incoming values from the database
71
+	 * @param string $timezone        incoming timezone as set by the model.
72
+	 *                                If not set the timezone for the website will be used.
73
+	 * @return EE_Currency
74
+	 * @throws EE_Error
75
+	 * @throws ReflectionException
76
+	 */
77
+	public static function new_instance_from_db($props_n_values = [], $timezone = '')
78
+	{
79
+		return new self($props_n_values, true, $timezone);
80
+	}
81
+
82
+
83
+	/**
84
+	 * Sets code
85
+	 *
86
+	 * @param string $code
87
+	 * @throws EE_Error
88
+	 * @throws ReflectionException
89
+	 */
90
+	public function set_code($code)
91
+	{
92
+		$this->set('CUR_code', $code);
93
+	}
94
+
95
+
96
+	/**
97
+	 * Gets active
98
+	 *
99
+	 * @return boolean
100
+	 * @throws EE_Error
101
+	 */
102
+	public function active()
103
+	{
104
+		return $this->get('CUR_active');
105
+	}
106
+
107
+
108
+	/**
109
+	 * Sets active
110
+	 *
111
+	 * @param boolean $active
112
+	 * @throws EE_Error
113
+	 * @throws ReflectionException
114
+	 */
115
+	public function set_active($active)
116
+	{
117
+		$this->set('CUR_active', $active);
118
+	}
119
+
120
+
121
+	/**
122
+	 * Gets dec_plc
123
+	 *
124
+	 * @return int
125
+	 * @throws EE_Error
126
+	 */
127
+	public function dec_plc()
128
+	{
129
+		return $this->get('CUR_dec_plc');
130
+	}
131
+
132
+
133
+	/**
134
+	 * Sets dec_plc
135
+	 *
136
+	 * @param int $dec_plc
137
+	 * @throws EE_Error
138
+	 * @throws ReflectionException
139
+	 */
140
+	public function set_dec_plc($dec_plc)
141
+	{
142
+		$this->set('CUR_dec_plc', $dec_plc);
143
+	}
144
+
145
+
146
+	/**
147
+	 * Sets plural
148
+	 *
149
+	 * @param string $plural
150
+	 * @throws EE_Error
151
+	 * @throws ReflectionException
152
+	 */
153
+	public function set_plural_name($plural)
154
+	{
155
+		$this->set('CUR_plural', $plural);
156
+	}
157
+
158
+
159
+	/**
160
+	 * Gets sign
161
+	 *
162
+	 * @return string
163
+	 * @throws EE_Error
164
+	 */
165
+	public function sign()
166
+	{
167
+		return $this->get('CUR_sign');
168
+	}
169
+
170
+
171
+	/**
172
+	 * Sets sign
173
+	 *
174
+	 * @param string $sign
175
+	 * @throws EE_Error
176
+	 * @throws ReflectionException
177
+	 */
178
+	public function set_sign($sign)
179
+	{
180
+		$this->set('CUR_sign', $sign);
181
+	}
182
+
183
+
184
+	/**
185
+	 * Gets single
186
+	 *
187
+	 * @return string
188
+	 * @throws EE_Error
189
+	 */
190
+	public function singular_name()
191
+	{
192
+		return $this->get('CUR_single');
193
+	}
194
+
195
+
196
+	/**
197
+	 * Sets single
198
+	 *
199
+	 * @param string $single
200
+	 * @throws EE_Error
201
+	 * @throws ReflectionException
202
+	 */
203
+	public function set_singular_name($single)
204
+	{
205
+		$this->set('CUR_single', $single);
206
+	}
207
+
208
+
209
+	/**
210
+	 * Gets a prettier name
211
+	 *
212
+	 * @return string
213
+	 * @throws EE_Error
214
+	 */
215
+	public function name()
216
+	{
217
+		return sprintf(
218
+			esc_html__("%s (%s)", "event_espresso"),
219
+			$this->code(),
220
+			$this->plural_name()
221
+		);
222
+	}
223
+
224
+
225
+	/**
226
+	 * Gets code
227
+	 *
228
+	 * @return string
229
+	 * @throws EE_Error
230
+	 */
231
+	public function code()
232
+	{
233
+		return $this->get('CUR_code');
234
+	}
235
+
236
+
237
+	/**
238
+	 * Gets plural
239
+	 *
240
+	 * @return string
241
+	 * @throws EE_Error
242
+	 */
243
+	public function plural_name()
244
+	{
245
+		return $this->get('CUR_plural');
246
+	}
247 247
 }
Please login to merge, or discard this patch.
core/helpers/EEH_DTT_Helper.helper.php 1 patch
Indentation   +988 added lines, -988 removed lines patch added patch discarded remove patch
@@ -16,1052 +16,1052 @@
 block discarded – undo
16 16
 class EEH_DTT_Helper
17 17
 {
18 18
 
19
-    /**
20
-     * return the timezone set for the WP install
21
-     *
22
-     * @return string valid timezone string for PHP DateTimeZone() class
23
-     * @throws InvalidArgumentException
24
-     * @throws InvalidDataTypeException
25
-     * @throws InvalidInterfaceException
26
-     */
27
-    public static function get_timezone()
28
-    {
29
-        return EEH_DTT_Helper::get_valid_timezone_string();
30
-    }
19
+	/**
20
+	 * return the timezone set for the WP install
21
+	 *
22
+	 * @return string valid timezone string for PHP DateTimeZone() class
23
+	 * @throws InvalidArgumentException
24
+	 * @throws InvalidDataTypeException
25
+	 * @throws InvalidInterfaceException
26
+	 */
27
+	public static function get_timezone()
28
+	{
29
+		return EEH_DTT_Helper::get_valid_timezone_string();
30
+	}
31 31
 
32 32
 
33
-    /**
34
-     * get_valid_timezone_string
35
-     *    ensures that a valid timezone string is returned
36
-     *
37
-     * @param string $timezone_string
38
-     * @param bool   $throw_error
39
-     * @return string
40
-     * @throws InvalidArgumentException
41
-     * @throws InvalidDataTypeException
42
-     * @throws InvalidInterfaceException
43
-     */
44
-    public static function get_valid_timezone_string($timezone_string = '', $throw_error = false)
45
-    {
46
-        return self::getHelperAdapter()->getValidTimezoneString($timezone_string, $throw_error);
47
-    }
33
+	/**
34
+	 * get_valid_timezone_string
35
+	 *    ensures that a valid timezone string is returned
36
+	 *
37
+	 * @param string $timezone_string
38
+	 * @param bool   $throw_error
39
+	 * @return string
40
+	 * @throws InvalidArgumentException
41
+	 * @throws InvalidDataTypeException
42
+	 * @throws InvalidInterfaceException
43
+	 */
44
+	public static function get_valid_timezone_string($timezone_string = '', $throw_error = false)
45
+	{
46
+		return self::getHelperAdapter()->getValidTimezoneString($timezone_string, $throw_error);
47
+	}
48 48
 
49 49
 
50
-    public static function resetDefaultTimezoneString()
51
-    {
52
-        self::getHelperAdapter()->resetDefaultTimezoneString();
53
-    }
50
+	public static function resetDefaultTimezoneString()
51
+	{
52
+		self::getHelperAdapter()->resetDefaultTimezoneString();
53
+	}
54 54
 
55 55
 
56
-    /**
57
-     * This only purpose for this static method is to validate that the incoming timezone is a valid php timezone.
58
-     *
59
-     * @static
60
-     * @param  string $timezone_string Timezone string to check
61
-     * @param bool    $throw_error
62
-     * @return bool
63
-     * @throws InvalidArgumentException
64
-     * @throws InvalidDataTypeException
65
-     * @throws InvalidInterfaceException
66
-     */
67
-    public static function validate_timezone($timezone_string, $throw_error = true)
68
-    {
69
-        return self::getHelperAdapter()->validateTimezone($timezone_string, $throw_error);
70
-    }
56
+	/**
57
+	 * This only purpose for this static method is to validate that the incoming timezone is a valid php timezone.
58
+	 *
59
+	 * @static
60
+	 * @param  string $timezone_string Timezone string to check
61
+	 * @param bool    $throw_error
62
+	 * @return bool
63
+	 * @throws InvalidArgumentException
64
+	 * @throws InvalidDataTypeException
65
+	 * @throws InvalidInterfaceException
66
+	 */
67
+	public static function validate_timezone($timezone_string, $throw_error = true)
68
+	{
69
+		return self::getHelperAdapter()->validateTimezone($timezone_string, $throw_error);
70
+	}
71 71
 
72 72
 
73
-    /**
74
-     * This returns a string that can represent the provided gmt offset in format that can be passed into
75
-     * DateTimeZone.  This is NOT a string that can be passed as a value on the WordPress timezone_string option.
76
-     *
77
-     * @param float|string $gmt_offset
78
-     * @return string
79
-     * @throws InvalidArgumentException
80
-     * @throws InvalidDataTypeException
81
-     * @throws InvalidInterfaceException
82
-     */
83
-    public static function get_timezone_string_from_gmt_offset($gmt_offset = '')
84
-    {
85
-        return self::getHelperAdapter()->getTimezoneStringFromGmtOffset($gmt_offset);
86
-    }
73
+	/**
74
+	 * This returns a string that can represent the provided gmt offset in format that can be passed into
75
+	 * DateTimeZone.  This is NOT a string that can be passed as a value on the WordPress timezone_string option.
76
+	 *
77
+	 * @param float|string $gmt_offset
78
+	 * @return string
79
+	 * @throws InvalidArgumentException
80
+	 * @throws InvalidDataTypeException
81
+	 * @throws InvalidInterfaceException
82
+	 */
83
+	public static function get_timezone_string_from_gmt_offset($gmt_offset = '')
84
+	{
85
+		return self::getHelperAdapter()->getTimezoneStringFromGmtOffset($gmt_offset);
86
+	}
87 87
 
88 88
 
89
-    /**
90
-     * Gets the site's GMT offset based on either the timezone string
91
-     * (in which case teh gmt offset will vary depending on the location's
92
-     * observance of daylight savings time) or the gmt_offset wp option
93
-     *
94
-     * @return int seconds offset
95
-     * @throws InvalidArgumentException
96
-     * @throws InvalidDataTypeException
97
-     * @throws InvalidInterfaceException
98
-     */
99
-    public static function get_site_timezone_gmt_offset()
100
-    {
101
-        return self::getHelperAdapter()->getSiteTimezoneGmtOffset();
102
-    }
89
+	/**
90
+	 * Gets the site's GMT offset based on either the timezone string
91
+	 * (in which case teh gmt offset will vary depending on the location's
92
+	 * observance of daylight savings time) or the gmt_offset wp option
93
+	 *
94
+	 * @return int seconds offset
95
+	 * @throws InvalidArgumentException
96
+	 * @throws InvalidDataTypeException
97
+	 * @throws InvalidInterfaceException
98
+	 */
99
+	public static function get_site_timezone_gmt_offset()
100
+	{
101
+		return self::getHelperAdapter()->getSiteTimezoneGmtOffset();
102
+	}
103 103
 
104 104
 
105
-    /**
106
-     * Depending on PHP version,
107
-     * there might not be valid current timezone strings to match these gmt_offsets in its timezone tables.
108
-     * To get around that, for these fringe timezones we bump them to a known valid offset.
109
-     * This method should ONLY be called after first verifying an timezone_string cannot be retrieved for the offset.
110
-     *
111
-     * @deprecated 4.9.54.rc    Developers this was always meant to only be an internally used method.  This will be
112
-     *                          removed in a future version of EE.
113
-     * @param int $gmt_offset
114
-     * @return int
115
-     * @throws InvalidArgumentException
116
-     * @throws InvalidDataTypeException
117
-     * @throws InvalidInterfaceException
118
-     */
119
-    public static function adjust_invalid_gmt_offsets($gmt_offset = 0)
120
-    {
121
-        return self::getHelperAdapter()->adjustInvalidGmtOffsets($gmt_offset);
122
-    }
105
+	/**
106
+	 * Depending on PHP version,
107
+	 * there might not be valid current timezone strings to match these gmt_offsets in its timezone tables.
108
+	 * To get around that, for these fringe timezones we bump them to a known valid offset.
109
+	 * This method should ONLY be called after first verifying an timezone_string cannot be retrieved for the offset.
110
+	 *
111
+	 * @deprecated 4.9.54.rc    Developers this was always meant to only be an internally used method.  This will be
112
+	 *                          removed in a future version of EE.
113
+	 * @param int $gmt_offset
114
+	 * @return int
115
+	 * @throws InvalidArgumentException
116
+	 * @throws InvalidDataTypeException
117
+	 * @throws InvalidInterfaceException
118
+	 */
119
+	public static function adjust_invalid_gmt_offsets($gmt_offset = 0)
120
+	{
121
+		return self::getHelperAdapter()->adjustInvalidGmtOffsets($gmt_offset);
122
+	}
123 123
 
124 124
 
125
-    /**
126
-     * get_timezone_string_from_abbreviations_list
127
-     *
128
-     * @deprecated 4.9.54.rc  Developers, this was never intended to be public.  This is a soft deprecation for now.
129
-     *                        If you are using this, you'll want to work out an alternate way of getting the value.
130
-     * @param int  $gmt_offset
131
-     * @param bool $coerce If true, we attempt to coerce with our adjustment table @see self::adjust_invalid_gmt_offset.
132
-     * @return string
133
-     * @throws EE_Error
134
-     * @throws InvalidArgumentException
135
-     * @throws InvalidDataTypeException
136
-     * @throws InvalidInterfaceException
137
-     */
138
-    public static function get_timezone_string_from_abbreviations_list($gmt_offset = 0, $coerce = true)
139
-    {
140
-        $gmt_offset =  (int) $gmt_offset;
141
-        /** @var array[] $abbreviations */
142
-        $abbreviations = DateTimeZone::listAbbreviations();
143
-        foreach ($abbreviations as $abbreviation) {
144
-            foreach ($abbreviation as $timezone) {
145
-                if ((int) $timezone['offset'] === $gmt_offset && (bool) $timezone['dst'] === false) {
146
-                    try {
147
-                        $offset = self::get_timezone_offset(new DateTimeZone($timezone['timezone_id']));
148
-                        if ($offset !== $gmt_offset) {
149
-                            continue;
150
-                        }
151
-                        return $timezone['timezone_id'];
152
-                    } catch (Exception $e) {
153
-                        continue;
154
-                    }
155
-                }
156
-            }
157
-        }
158
-        // if $coerce is true, let's see if we can get a timezone string after the offset is adjusted
159
-        if ($coerce === true) {
160
-            $timezone_string = self::get_timezone_string_from_abbreviations_list(
161
-                self::adjust_invalid_gmt_offsets($gmt_offset),
162
-                false
163
-            );
164
-            if ($timezone_string) {
165
-                return $timezone_string;
166
-            }
167
-        }
168
-        throw new EE_Error(
169
-            sprintf(
170
-                esc_html__(
171
-                    'The provided GMT offset (%1$s), is invalid, please check with %2$sthis list%3$s for what valid timezones can be used',
172
-                    'event_espresso'
173
-                ),
174
-                $gmt_offset / HOUR_IN_SECONDS,
175
-                '<a href="http://www.php.net/manual/en/timezones.php">',
176
-                '</a>'
177
-            )
178
-        );
179
-    }
125
+	/**
126
+	 * get_timezone_string_from_abbreviations_list
127
+	 *
128
+	 * @deprecated 4.9.54.rc  Developers, this was never intended to be public.  This is a soft deprecation for now.
129
+	 *                        If you are using this, you'll want to work out an alternate way of getting the value.
130
+	 * @param int  $gmt_offset
131
+	 * @param bool $coerce If true, we attempt to coerce with our adjustment table @see self::adjust_invalid_gmt_offset.
132
+	 * @return string
133
+	 * @throws EE_Error
134
+	 * @throws InvalidArgumentException
135
+	 * @throws InvalidDataTypeException
136
+	 * @throws InvalidInterfaceException
137
+	 */
138
+	public static function get_timezone_string_from_abbreviations_list($gmt_offset = 0, $coerce = true)
139
+	{
140
+		$gmt_offset =  (int) $gmt_offset;
141
+		/** @var array[] $abbreviations */
142
+		$abbreviations = DateTimeZone::listAbbreviations();
143
+		foreach ($abbreviations as $abbreviation) {
144
+			foreach ($abbreviation as $timezone) {
145
+				if ((int) $timezone['offset'] === $gmt_offset && (bool) $timezone['dst'] === false) {
146
+					try {
147
+						$offset = self::get_timezone_offset(new DateTimeZone($timezone['timezone_id']));
148
+						if ($offset !== $gmt_offset) {
149
+							continue;
150
+						}
151
+						return $timezone['timezone_id'];
152
+					} catch (Exception $e) {
153
+						continue;
154
+					}
155
+				}
156
+			}
157
+		}
158
+		// if $coerce is true, let's see if we can get a timezone string after the offset is adjusted
159
+		if ($coerce === true) {
160
+			$timezone_string = self::get_timezone_string_from_abbreviations_list(
161
+				self::adjust_invalid_gmt_offsets($gmt_offset),
162
+				false
163
+			);
164
+			if ($timezone_string) {
165
+				return $timezone_string;
166
+			}
167
+		}
168
+		throw new EE_Error(
169
+			sprintf(
170
+				esc_html__(
171
+					'The provided GMT offset (%1$s), is invalid, please check with %2$sthis list%3$s for what valid timezones can be used',
172
+					'event_espresso'
173
+				),
174
+				$gmt_offset / HOUR_IN_SECONDS,
175
+				'<a href="http://www.php.net/manual/en/timezones.php">',
176
+				'</a>'
177
+			)
178
+		);
179
+	}
180 180
 
181 181
 
182
-    /**
183
-     * Get Timezone Transitions
184
-     *
185
-     * @param DateTimeZone $date_time_zone
186
-     * @param int|null     $time
187
-     * @param bool         $first_only
188
-     * @return array
189
-     * @throws InvalidArgumentException
190
-     * @throws InvalidDataTypeException
191
-     * @throws InvalidInterfaceException
192
-     */
193
-    public static function get_timezone_transitions(DateTimeZone $date_time_zone, $time = null, $first_only = true)
194
-    {
195
-        return self::getHelperAdapter()->getTimezoneTransitions($date_time_zone, $time, $first_only);
196
-    }
182
+	/**
183
+	 * Get Timezone Transitions
184
+	 *
185
+	 * @param DateTimeZone $date_time_zone
186
+	 * @param int|null     $time
187
+	 * @param bool         $first_only
188
+	 * @return array
189
+	 * @throws InvalidArgumentException
190
+	 * @throws InvalidDataTypeException
191
+	 * @throws InvalidInterfaceException
192
+	 */
193
+	public static function get_timezone_transitions(DateTimeZone $date_time_zone, $time = null, $first_only = true)
194
+	{
195
+		return self::getHelperAdapter()->getTimezoneTransitions($date_time_zone, $time, $first_only);
196
+	}
197 197
 
198 198
 
199
-    /**
200
-     * Get Timezone Offset for given timezone object.
201
-     *
202
-     * @param DateTimeZone $date_time_zone
203
-     * @param null         $time
204
-     * @return mixed
205
-     * @throws InvalidArgumentException
206
-     * @throws InvalidDataTypeException
207
-     * @throws InvalidInterfaceException
208
-     */
209
-    public static function get_timezone_offset(DateTimeZone $date_time_zone, $time = null)
210
-    {
211
-        return self::getHelperAdapter()->getTimezoneOffset($date_time_zone, $time);
212
-    }
199
+	/**
200
+	 * Get Timezone Offset for given timezone object.
201
+	 *
202
+	 * @param DateTimeZone $date_time_zone
203
+	 * @param null         $time
204
+	 * @return mixed
205
+	 * @throws InvalidArgumentException
206
+	 * @throws InvalidDataTypeException
207
+	 * @throws InvalidInterfaceException
208
+	 */
209
+	public static function get_timezone_offset(DateTimeZone $date_time_zone, $time = null)
210
+	{
211
+		return self::getHelperAdapter()->getTimezoneOffset($date_time_zone, $time);
212
+	}
213 213
 
214 214
 
215
-    /**
216
-     * Prints a select input for the given timezone string.
217
-     * @param string $timezone_string
218
-     * @deprecatd 4.9.54.rc   Soft deprecation.  Consider using \EEH_DTT_Helper::wp_timezone_choice instead.
219
-     * @throws InvalidArgumentException
220
-     * @throws InvalidDataTypeException
221
-     * @throws InvalidInterfaceException
222
-     */
223
-    public static function timezone_select_input($timezone_string = '')
224
-    {
225
-        self::getHelperAdapter()->timezoneSelectInput($timezone_string);
226
-    }
215
+	/**
216
+	 * Prints a select input for the given timezone string.
217
+	 * @param string $timezone_string
218
+	 * @deprecatd 4.9.54.rc   Soft deprecation.  Consider using \EEH_DTT_Helper::wp_timezone_choice instead.
219
+	 * @throws InvalidArgumentException
220
+	 * @throws InvalidDataTypeException
221
+	 * @throws InvalidInterfaceException
222
+	 */
223
+	public static function timezone_select_input($timezone_string = '')
224
+	{
225
+		self::getHelperAdapter()->timezoneSelectInput($timezone_string);
226
+	}
227 227
 
228 228
 
229
-    /**
230
-     * This method will take an incoming unix timestamp and add the offset to it for the given timezone_string.
231
-     * If no unix timestamp is given then time() is used.  If no timezone is given then the set timezone string for
232
-     * the site is used.
233
-     * This is used typically when using a Unix timestamp any core WP functions that expect their specially
234
-     * computed timestamp (i.e. date_i18n() )
235
-     *
236
-     * @param int    $unix_timestamp                  if 0, then time() will be used.
237
-     * @param string $timezone_string                 timezone_string. If empty, then the current set timezone for the
238
-     *                                                site will be used.
239
-     * @return int $unix_timestamp with the offset applied for the given timezone.
240
-     * @throws InvalidArgumentException
241
-     * @throws InvalidDataTypeException
242
-     * @throws InvalidInterfaceException
243
-     */
244
-    public static function get_timestamp_with_offset($unix_timestamp = 0, $timezone_string = '')
245
-    {
246
-        return self::getHelperAdapter()->getTimestampWithOffset($unix_timestamp, $timezone_string);
247
-    }
229
+	/**
230
+	 * This method will take an incoming unix timestamp and add the offset to it for the given timezone_string.
231
+	 * If no unix timestamp is given then time() is used.  If no timezone is given then the set timezone string for
232
+	 * the site is used.
233
+	 * This is used typically when using a Unix timestamp any core WP functions that expect their specially
234
+	 * computed timestamp (i.e. date_i18n() )
235
+	 *
236
+	 * @param int    $unix_timestamp                  if 0, then time() will be used.
237
+	 * @param string $timezone_string                 timezone_string. If empty, then the current set timezone for the
238
+	 *                                                site will be used.
239
+	 * @return int $unix_timestamp with the offset applied for the given timezone.
240
+	 * @throws InvalidArgumentException
241
+	 * @throws InvalidDataTypeException
242
+	 * @throws InvalidInterfaceException
243
+	 */
244
+	public static function get_timestamp_with_offset($unix_timestamp = 0, $timezone_string = '')
245
+	{
246
+		return self::getHelperAdapter()->getTimestampWithOffset($unix_timestamp, $timezone_string);
247
+	}
248 248
 
249 249
 
250
-    /**
251
-     *    _set_date_time_field
252
-     *    modifies EE_Base_Class EE_Datetime_Field objects
253
-     *
254
-     * @param  EE_Base_Class $obj                 EE_Base_Class object
255
-     * @param    DateTime    $DateTime            PHP DateTime object
256
-     * @param  string        $datetime_field_name the datetime fieldname to be manipulated
257
-     * @return EE_Base_Class
258
-     * @throws EE_Error
259
-     */
260
-    protected static function _set_date_time_field(EE_Base_Class $obj, DateTime $DateTime, $datetime_field_name)
261
-    {
262
-        // grab current datetime format
263
-        $current_format = $obj->get_format();
264
-        // set new full timestamp format
265
-        $obj->set_date_format(EE_Datetime_Field::mysql_date_format);
266
-        $obj->set_time_format(EE_Datetime_Field::mysql_time_format);
267
-        // set the new date value using a full timestamp format so that no data is lost
268
-        $obj->set($datetime_field_name, $DateTime->format(EE_Datetime_Field::mysql_timestamp_format));
269
-        // reset datetime formats
270
-        $obj->set_date_format($current_format[0]);
271
-        $obj->set_time_format($current_format[1]);
272
-        return $obj;
273
-    }
250
+	/**
251
+	 *    _set_date_time_field
252
+	 *    modifies EE_Base_Class EE_Datetime_Field objects
253
+	 *
254
+	 * @param  EE_Base_Class $obj                 EE_Base_Class object
255
+	 * @param    DateTime    $DateTime            PHP DateTime object
256
+	 * @param  string        $datetime_field_name the datetime fieldname to be manipulated
257
+	 * @return EE_Base_Class
258
+	 * @throws EE_Error
259
+	 */
260
+	protected static function _set_date_time_field(EE_Base_Class $obj, DateTime $DateTime, $datetime_field_name)
261
+	{
262
+		// grab current datetime format
263
+		$current_format = $obj->get_format();
264
+		// set new full timestamp format
265
+		$obj->set_date_format(EE_Datetime_Field::mysql_date_format);
266
+		$obj->set_time_format(EE_Datetime_Field::mysql_time_format);
267
+		// set the new date value using a full timestamp format so that no data is lost
268
+		$obj->set($datetime_field_name, $DateTime->format(EE_Datetime_Field::mysql_timestamp_format));
269
+		// reset datetime formats
270
+		$obj->set_date_format($current_format[0]);
271
+		$obj->set_time_format($current_format[1]);
272
+		return $obj;
273
+	}
274 274
 
275 275
 
276
-    /**
277
-     *    date_time_add
278
-     *    helper for doing simple datetime calculations on a given datetime from EE_Base_Class
279
-     *    and modifying it IN the EE_Base_Class so you don't have to do anything else.
280
-     *
281
-     * @param  EE_Base_Class $obj                 EE_Base_Class object
282
-     * @param  string        $datetime_field_name name of the EE_Datetime_Filed datatype db column to be manipulated
283
-     * @param  string        $period              what you are adding. The options are (years, months, days, hours,
284
-     *                                            minutes, seconds) defaults to years
285
-     * @param  integer       $value               what you want to increment the time by
286
-     * @return EE_Base_Class return the EE_Base_Class object so right away you can do something with it
287
-     *                                            (chaining)
288
-     * @throws EE_Error
289
-     * @throws Exception
290
-     */
291
-    public static function date_time_add(EE_Base_Class $obj, $datetime_field_name, $period = 'years', $value = 1)
292
-    {
293
-        // get the raw UTC date.
294
-        $DateTime = $obj->get_DateTime_object($datetime_field_name);
295
-        $DateTime = EEH_DTT_Helper::calc_date($DateTime, $period, $value);
296
-        return EEH_DTT_Helper::_set_date_time_field($obj, $DateTime, $datetime_field_name);
297
-    }
276
+	/**
277
+	 *    date_time_add
278
+	 *    helper for doing simple datetime calculations on a given datetime from EE_Base_Class
279
+	 *    and modifying it IN the EE_Base_Class so you don't have to do anything else.
280
+	 *
281
+	 * @param  EE_Base_Class $obj                 EE_Base_Class object
282
+	 * @param  string        $datetime_field_name name of the EE_Datetime_Filed datatype db column to be manipulated
283
+	 * @param  string        $period              what you are adding. The options are (years, months, days, hours,
284
+	 *                                            minutes, seconds) defaults to years
285
+	 * @param  integer       $value               what you want to increment the time by
286
+	 * @return EE_Base_Class return the EE_Base_Class object so right away you can do something with it
287
+	 *                                            (chaining)
288
+	 * @throws EE_Error
289
+	 * @throws Exception
290
+	 */
291
+	public static function date_time_add(EE_Base_Class $obj, $datetime_field_name, $period = 'years', $value = 1)
292
+	{
293
+		// get the raw UTC date.
294
+		$DateTime = $obj->get_DateTime_object($datetime_field_name);
295
+		$DateTime = EEH_DTT_Helper::calc_date($DateTime, $period, $value);
296
+		return EEH_DTT_Helper::_set_date_time_field($obj, $DateTime, $datetime_field_name);
297
+	}
298 298
 
299 299
 
300
-    /**
301
-     *    date_time_subtract
302
-     *    same as date_time_add except subtracting value instead of adding.
303
-     *
304
-     * @param EE_Base_Class $obj
305
-     * @param  string       $datetime_field_name name of the EE_Datetime_Filed datatype db column to be manipulated
306
-     * @param string        $period
307
-     * @param int           $value
308
-     * @return EE_Base_Class
309
-     * @throws EE_Error
310
-     * @throws Exception
311
-     */
312
-    public static function date_time_subtract(EE_Base_Class $obj, $datetime_field_name, $period = 'years', $value = 1)
313
-    {
314
-        // get the raw UTC date
315
-        $DateTime = $obj->get_DateTime_object($datetime_field_name);
316
-        $DateTime = EEH_DTT_Helper::calc_date($DateTime, $period, $value, '-');
317
-        return EEH_DTT_Helper::_set_date_time_field($obj, $DateTime, $datetime_field_name);
318
-    }
300
+	/**
301
+	 *    date_time_subtract
302
+	 *    same as date_time_add except subtracting value instead of adding.
303
+	 *
304
+	 * @param EE_Base_Class $obj
305
+	 * @param  string       $datetime_field_name name of the EE_Datetime_Filed datatype db column to be manipulated
306
+	 * @param string        $period
307
+	 * @param int           $value
308
+	 * @return EE_Base_Class
309
+	 * @throws EE_Error
310
+	 * @throws Exception
311
+	 */
312
+	public static function date_time_subtract(EE_Base_Class $obj, $datetime_field_name, $period = 'years', $value = 1)
313
+	{
314
+		// get the raw UTC date
315
+		$DateTime = $obj->get_DateTime_object($datetime_field_name);
316
+		$DateTime = EEH_DTT_Helper::calc_date($DateTime, $period, $value, '-');
317
+		return EEH_DTT_Helper::_set_date_time_field($obj, $DateTime, $datetime_field_name);
318
+	}
319 319
 
320 320
 
321
-    /**
322
-     * Simply takes an incoming DateTime object and does calculations on it based on the incoming parameters
323
-     *
324
-     * @param  DateTime   $DateTime DateTime object
325
-     * @param  string     $period   a value to indicate what interval is being used in the calculation. The options are
326
-     *                              'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Defaults to years.
327
-     * @param  int|string $value    What you want to increment the date by
328
-     * @param  string     $operand  What operand you wish to use for the calculation
329
-     * @return DateTime return whatever type came in.
330
-     * @throws Exception
331
-     * @throws EE_Error
332
-     */
333
-    protected static function _modify_datetime_object(DateTime $DateTime, $period = 'years', $value = 1, $operand = '+')
334
-    {
335
-        if (! $DateTime instanceof DateTime) {
336
-            throw new EE_Error(
337
-                sprintf(
338
-                    esc_html__('Expected a PHP DateTime object, but instead received %1$s', 'event_espresso'),
339
-                    print_r($DateTime, true)
340
-                )
341
-            );
342
-        }
343
-        switch ($period) {
344
-            case 'years':
345
-                $value = 'P' . $value . 'Y';
346
-                break;
347
-            case 'months':
348
-                $value = 'P' . $value . 'M';
349
-                break;
350
-            case 'weeks':
351
-                $value = 'P' . $value . 'W';
352
-                break;
353
-            case 'days':
354
-                $value = 'P' . $value . 'D';
355
-                break;
356
-            case 'hours':
357
-                $value = 'PT' . $value . 'H';
358
-                break;
359
-            case 'minutes':
360
-                $value = 'PT' . $value . 'M';
361
-                break;
362
-            case 'seconds':
363
-                $value = 'PT' . $value . 'S';
364
-                break;
365
-        }
366
-        switch ($operand) {
367
-            case '+':
368
-                $DateTime->add(new DateInterval($value));
369
-                break;
370
-            case '-':
371
-                $DateTime->sub(new DateInterval($value));
372
-                break;
373
-        }
374
-        return $DateTime;
375
-    }
321
+	/**
322
+	 * Simply takes an incoming DateTime object and does calculations on it based on the incoming parameters
323
+	 *
324
+	 * @param  DateTime   $DateTime DateTime object
325
+	 * @param  string     $period   a value to indicate what interval is being used in the calculation. The options are
326
+	 *                              'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Defaults to years.
327
+	 * @param  int|string $value    What you want to increment the date by
328
+	 * @param  string     $operand  What operand you wish to use for the calculation
329
+	 * @return DateTime return whatever type came in.
330
+	 * @throws Exception
331
+	 * @throws EE_Error
332
+	 */
333
+	protected static function _modify_datetime_object(DateTime $DateTime, $period = 'years', $value = 1, $operand = '+')
334
+	{
335
+		if (! $DateTime instanceof DateTime) {
336
+			throw new EE_Error(
337
+				sprintf(
338
+					esc_html__('Expected a PHP DateTime object, but instead received %1$s', 'event_espresso'),
339
+					print_r($DateTime, true)
340
+				)
341
+			);
342
+		}
343
+		switch ($period) {
344
+			case 'years':
345
+				$value = 'P' . $value . 'Y';
346
+				break;
347
+			case 'months':
348
+				$value = 'P' . $value . 'M';
349
+				break;
350
+			case 'weeks':
351
+				$value = 'P' . $value . 'W';
352
+				break;
353
+			case 'days':
354
+				$value = 'P' . $value . 'D';
355
+				break;
356
+			case 'hours':
357
+				$value = 'PT' . $value . 'H';
358
+				break;
359
+			case 'minutes':
360
+				$value = 'PT' . $value . 'M';
361
+				break;
362
+			case 'seconds':
363
+				$value = 'PT' . $value . 'S';
364
+				break;
365
+		}
366
+		switch ($operand) {
367
+			case '+':
368
+				$DateTime->add(new DateInterval($value));
369
+				break;
370
+			case '-':
371
+				$DateTime->sub(new DateInterval($value));
372
+				break;
373
+		}
374
+		return $DateTime;
375
+	}
376 376
 
377 377
 
378
-    /**
379
-     * Simply takes an incoming Unix timestamp and does calculations on it based on the incoming parameters
380
-     *
381
-     * @param  int     $timestamp Unix timestamp
382
-     * @param  string  $period    a value to indicate what interval is being used in the calculation. The options are
383
-     *                            'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Defaults to years.
384
-     * @param  integer $value     What you want to increment the date by
385
-     * @param  string  $operand   What operand you wish to use for the calculation
386
-     * @return int
387
-     * @throws EE_Error
388
-     */
389
-    protected static function _modify_timestamp($timestamp, $period = 'years', $value = 1, $operand = '+')
390
-    {
391
-        if (! preg_match(EE_Datetime_Field::unix_timestamp_regex, $timestamp)) {
392
-            throw new EE_Error(
393
-                sprintf(
394
-                    esc_html__('Expected a Unix timestamp, but instead received %1$s', 'event_espresso'),
395
-                    print_r($timestamp, true)
396
-                )
397
-            );
398
-        }
399
-        switch ($period) {
400
-            case 'years':
401
-                $value = YEAR_IN_SECONDS * $value;
402
-                break;
403
-            case 'months':
404
-                $value = YEAR_IN_SECONDS / 12 * $value;
405
-                break;
406
-            case 'weeks':
407
-                $value = WEEK_IN_SECONDS * $value;
408
-                break;
409
-            case 'days':
410
-                $value = DAY_IN_SECONDS * $value;
411
-                break;
412
-            case 'hours':
413
-                $value = HOUR_IN_SECONDS * $value;
414
-                break;
415
-            case 'minutes':
416
-                $value = MINUTE_IN_SECONDS * $value;
417
-                break;
418
-        }
419
-        switch ($operand) {
420
-            case '+':
421
-                $timestamp += $value;
422
-                break;
423
-            case '-':
424
-                $timestamp -= $value;
425
-                break;
426
-        }
427
-        return $timestamp;
428
-    }
378
+	/**
379
+	 * Simply takes an incoming Unix timestamp and does calculations on it based on the incoming parameters
380
+	 *
381
+	 * @param  int     $timestamp Unix timestamp
382
+	 * @param  string  $period    a value to indicate what interval is being used in the calculation. The options are
383
+	 *                            'years', 'months', 'days', 'hours', 'minutes', 'seconds'. Defaults to years.
384
+	 * @param  integer $value     What you want to increment the date by
385
+	 * @param  string  $operand   What operand you wish to use for the calculation
386
+	 * @return int
387
+	 * @throws EE_Error
388
+	 */
389
+	protected static function _modify_timestamp($timestamp, $period = 'years', $value = 1, $operand = '+')
390
+	{
391
+		if (! preg_match(EE_Datetime_Field::unix_timestamp_regex, $timestamp)) {
392
+			throw new EE_Error(
393
+				sprintf(
394
+					esc_html__('Expected a Unix timestamp, but instead received %1$s', 'event_espresso'),
395
+					print_r($timestamp, true)
396
+				)
397
+			);
398
+		}
399
+		switch ($period) {
400
+			case 'years':
401
+				$value = YEAR_IN_SECONDS * $value;
402
+				break;
403
+			case 'months':
404
+				$value = YEAR_IN_SECONDS / 12 * $value;
405
+				break;
406
+			case 'weeks':
407
+				$value = WEEK_IN_SECONDS * $value;
408
+				break;
409
+			case 'days':
410
+				$value = DAY_IN_SECONDS * $value;
411
+				break;
412
+			case 'hours':
413
+				$value = HOUR_IN_SECONDS * $value;
414
+				break;
415
+			case 'minutes':
416
+				$value = MINUTE_IN_SECONDS * $value;
417
+				break;
418
+		}
419
+		switch ($operand) {
420
+			case '+':
421
+				$timestamp += $value;
422
+				break;
423
+			case '-':
424
+				$timestamp -= $value;
425
+				break;
426
+		}
427
+		return $timestamp;
428
+	}
429 429
 
430 430
 
431
-    /**
432
-     * Simply takes an incoming UTC timestamp or DateTime object and does calculations on it based on the incoming
433
-     * parameters and returns the new timestamp or DateTime.
434
-     *
435
-     * @param  int | DateTime $DateTime_or_timestamp DateTime object or Unix timestamp
436
-     * @param  string         $period                a value to indicate what interval is being used in the
437
-     *                                               calculation. The options are 'years', 'months', 'days', 'hours',
438
-     *                                               'minutes', 'seconds'. Defaults to years.
439
-     * @param  integer        $value                 What you want to increment the date by
440
-     * @param  string         $operand               What operand you wish to use for the calculation
441
-     * @return mixed string|DateTime          return whatever type came in.
442
-     * @throws Exception
443
-     * @throws EE_Error
444
-     */
445
-    public static function calc_date($DateTime_or_timestamp, $period = 'years', $value = 1, $operand = '+')
446
-    {
447
-        if ($DateTime_or_timestamp instanceof DateTime) {
448
-            return EEH_DTT_Helper::_modify_datetime_object(
449
-                $DateTime_or_timestamp,
450
-                $period,
451
-                $value,
452
-                $operand
453
-            );
454
-        }
455
-        if (preg_match(EE_Datetime_Field::unix_timestamp_regex, $DateTime_or_timestamp)) {
456
-            return EEH_DTT_Helper::_modify_timestamp(
457
-                $DateTime_or_timestamp,
458
-                $period,
459
-                $value,
460
-                $operand
461
-            );
462
-        }
463
-        // error
464
-        return $DateTime_or_timestamp;
465
-    }
431
+	/**
432
+	 * Simply takes an incoming UTC timestamp or DateTime object and does calculations on it based on the incoming
433
+	 * parameters and returns the new timestamp or DateTime.
434
+	 *
435
+	 * @param  int | DateTime $DateTime_or_timestamp DateTime object or Unix timestamp
436
+	 * @param  string         $period                a value to indicate what interval is being used in the
437
+	 *                                               calculation. The options are 'years', 'months', 'days', 'hours',
438
+	 *                                               'minutes', 'seconds'. Defaults to years.
439
+	 * @param  integer        $value                 What you want to increment the date by
440
+	 * @param  string         $operand               What operand you wish to use for the calculation
441
+	 * @return mixed string|DateTime          return whatever type came in.
442
+	 * @throws Exception
443
+	 * @throws EE_Error
444
+	 */
445
+	public static function calc_date($DateTime_or_timestamp, $period = 'years', $value = 1, $operand = '+')
446
+	{
447
+		if ($DateTime_or_timestamp instanceof DateTime) {
448
+			return EEH_DTT_Helper::_modify_datetime_object(
449
+				$DateTime_or_timestamp,
450
+				$period,
451
+				$value,
452
+				$operand
453
+			);
454
+		}
455
+		if (preg_match(EE_Datetime_Field::unix_timestamp_regex, $DateTime_or_timestamp)) {
456
+			return EEH_DTT_Helper::_modify_timestamp(
457
+				$DateTime_or_timestamp,
458
+				$period,
459
+				$value,
460
+				$operand
461
+			);
462
+		}
463
+		// error
464
+		return $DateTime_or_timestamp;
465
+	}
466 466
 
467 467
 
468
-    /**
469
-     * The purpose of this helper method is to receive an incoming format string in php date/time format
470
-     * and spit out the js and moment.js equivalent formats.
471
-     * Note, if no format string is given, then it is assumed the user wants what is set for WP.
472
-     * Note, js date and time formats are those used by the jquery-ui datepicker and the jquery-ui date-
473
-     * time picker.
474
-     *
475
-     * @see http://stackoverflow.com/posts/16725290/ for the code inspiration.
476
-     * @param string $date_format_string
477
-     * @param string $time_format_string
478
-     * @return array
479
-     *              array(
480
-     *              'js' => array (
481
-     *              'date' => //date format
482
-     *              'time' => //time format
483
-     *              ),
484
-     *              'moment' => //date and time format.
485
-     *              )
486
-     */
487
-    public static function convert_php_to_js_and_moment_date_formats(
488
-        $date_format_string = null,
489
-        $time_format_string = null
490
-    ) {
491
-        if ($date_format_string === null) {
492
-            $date_format_string = (string) get_option('date_format');
493
-        }
494
-        if ($time_format_string === null) {
495
-            $time_format_string = (string) get_option('time_format');
496
-        }
497
-        $date_format = self::_php_to_js_moment_converter($date_format_string);
498
-        $time_format = self::_php_to_js_moment_converter($time_format_string);
499
-        return array(
500
-            'js'     => array(
501
-                'date' => $date_format['js'],
502
-                'time' => $time_format['js'],
503
-            ),
504
-            'moment' => $date_format['moment'] . ' ' . $time_format['moment'],
505
-            'moment_split' => array(
506
-                'date' => $date_format['moment'],
507
-                'time' => $time_format['moment']
508
-            )
509
-        );
510
-    }
468
+	/**
469
+	 * The purpose of this helper method is to receive an incoming format string in php date/time format
470
+	 * and spit out the js and moment.js equivalent formats.
471
+	 * Note, if no format string is given, then it is assumed the user wants what is set for WP.
472
+	 * Note, js date and time formats are those used by the jquery-ui datepicker and the jquery-ui date-
473
+	 * time picker.
474
+	 *
475
+	 * @see http://stackoverflow.com/posts/16725290/ for the code inspiration.
476
+	 * @param string $date_format_string
477
+	 * @param string $time_format_string
478
+	 * @return array
479
+	 *              array(
480
+	 *              'js' => array (
481
+	 *              'date' => //date format
482
+	 *              'time' => //time format
483
+	 *              ),
484
+	 *              'moment' => //date and time format.
485
+	 *              )
486
+	 */
487
+	public static function convert_php_to_js_and_moment_date_formats(
488
+		$date_format_string = null,
489
+		$time_format_string = null
490
+	) {
491
+		if ($date_format_string === null) {
492
+			$date_format_string = (string) get_option('date_format');
493
+		}
494
+		if ($time_format_string === null) {
495
+			$time_format_string = (string) get_option('time_format');
496
+		}
497
+		$date_format = self::_php_to_js_moment_converter($date_format_string);
498
+		$time_format = self::_php_to_js_moment_converter($time_format_string);
499
+		return array(
500
+			'js'     => array(
501
+				'date' => $date_format['js'],
502
+				'time' => $time_format['js'],
503
+			),
504
+			'moment' => $date_format['moment'] . ' ' . $time_format['moment'],
505
+			'moment_split' => array(
506
+				'date' => $date_format['moment'],
507
+				'time' => $time_format['moment']
508
+			)
509
+		);
510
+	}
511 511
 
512 512
 
513
-    /**
514
-     * This converts incoming format string into js and moment variations.
515
-     *
516
-     * @param string $format_string incoming php format string
517
-     * @return array js and moment formats.
518
-     */
519
-    protected static function _php_to_js_moment_converter($format_string)
520
-    {
521
-        /**
522
-         * This is a map of symbols for formats.
523
-         * The index is the php symbol, the equivalent values are in the array.
524
-         *
525
-         * @var array
526
-         */
527
-        $symbols_map          = array(
528
-            // Day
529
-            // 01
530
-            'd' => array(
531
-                'js'     => 'dd',
532
-                'moment' => 'DD',
533
-            ),
534
-            // Mon
535
-            'D' => array(
536
-                'js'     => 'D',
537
-                'moment' => 'ddd',
538
-            ),
539
-            // 1,2,...31
540
-            'j' => array(
541
-                'js'     => 'd',
542
-                'moment' => 'D',
543
-            ),
544
-            // Monday
545
-            'l' => array(
546
-                'js'     => 'DD',
547
-                'moment' => 'dddd',
548
-            ),
549
-            // ISO numeric representation of the day of the week (1-6)
550
-            'N' => array(
551
-                'js'     => '',
552
-                'moment' => 'E',
553
-            ),
554
-            // st,nd.rd
555
-            'S' => array(
556
-                'js'     => '',
557
-                'moment' => 'o',
558
-            ),
559
-            // numeric representation of day of week (0-6)
560
-            'w' => array(
561
-                'js'     => '',
562
-                'moment' => 'd',
563
-            ),
564
-            // day of year starting from 0 (0-365)
565
-            'z' => array(
566
-                'js'     => 'o',
567
-                'moment' => 'DDD' // note moment does not start with 0 so will need to modify by subtracting 1
568
-            ),
569
-            // Week
570
-            // ISO-8601 week number of year (weeks starting on monday)
571
-            'W' => array(
572
-                'js'     => '',
573
-                'moment' => 'w',
574
-            ),
575
-            // Month
576
-            // January...December
577
-            'F' => array(
578
-                'js'     => 'MM',
579
-                'moment' => 'MMMM',
580
-            ),
581
-            // 01...12
582
-            'm' => array(
583
-                'js'     => 'mm',
584
-                'moment' => 'MM',
585
-            ),
586
-            // Jan...Dec
587
-            'M' => array(
588
-                'js'     => 'M',
589
-                'moment' => 'MMM',
590
-            ),
591
-            // 1-12
592
-            'n' => array(
593
-                'js'     => 'm',
594
-                'moment' => 'M',
595
-            ),
596
-            // number of days in given month
597
-            't' => array(
598
-                'js'     => '',
599
-                'moment' => '',
600
-            ),
601
-            // Year
602
-            // whether leap year or not 1/0
603
-            'L' => array(
604
-                'js'     => '',
605
-                'moment' => '',
606
-            ),
607
-            // ISO-8601 year number
608
-            'o' => array(
609
-                'js'     => '',
610
-                'moment' => 'GGGG',
611
-            ),
612
-            // 1999...2003
613
-            'Y' => array(
614
-                'js'     => 'yy',
615
-                'moment' => 'YYYY',
616
-            ),
617
-            // 99...03
618
-            'y' => array(
619
-                'js'     => 'y',
620
-                'moment' => 'YY',
621
-            ),
622
-            // Time
623
-            // am/pm
624
-            'a' => array(
625
-                'js'     => 'tt',
626
-                'moment' => 'a',
627
-            ),
628
-            // AM/PM
629
-            'A' => array(
630
-                'js'     => 'TT',
631
-                'moment' => 'A',
632
-            ),
633
-            // Swatch Internet Time?!?
634
-            'B' => array(
635
-                'js'     => '',
636
-                'moment' => '',
637
-            ),
638
-            // 1...12
639
-            'g' => array(
640
-                'js'     => 'h',
641
-                'moment' => 'h',
642
-            ),
643
-            // 0...23
644
-            'G' => array(
645
-                'js'     => 'H',
646
-                'moment' => 'H',
647
-            ),
648
-            // 01...12
649
-            'h' => array(
650
-                'js'     => 'hh',
651
-                'moment' => 'hh',
652
-            ),
653
-            // 00...23
654
-            'H' => array(
655
-                'js'     => 'HH',
656
-                'moment' => 'HH',
657
-            ),
658
-            // 00..59
659
-            'i' => array(
660
-                'js'     => 'mm',
661
-                'moment' => 'mm',
662
-            ),
663
-            // seconds... 00...59
664
-            's' => array(
665
-                'js'     => 'ss',
666
-                'moment' => 'ss',
667
-            ),
668
-            // microseconds
669
-            'u' => array(
670
-                'js'     => '',
671
-                'moment' => '',
672
-            ),
673
-        );
674
-        $jquery_ui_format     = '';
675
-        $moment_format        = '';
676
-        $escaping             = false;
677
-        $format_string_length = strlen($format_string);
678
-        for ($i = 0; $i < $format_string_length; $i++) {
679
-            $char = $format_string[ $i ];
680
-            if ($char === '\\') { // PHP date format escaping character
681
-                $i++;
682
-                if ($escaping) {
683
-                    $jquery_ui_format .= $format_string[ $i ];
684
-                    $moment_format    .= $format_string[ $i ];
685
-                } else {
686
-                    $jquery_ui_format .= '\'' . $format_string[ $i ];
687
-                    $moment_format    .= $format_string[ $i ];
688
-                }
689
-                $escaping = true;
690
-            } else {
691
-                if ($escaping) {
692
-                    $jquery_ui_format .= "'";
693
-                    $moment_format    .= "'";
694
-                    $escaping         = false;
695
-                }
696
-                if (isset($symbols_map[ $char ])) {
697
-                    $jquery_ui_format .= $symbols_map[ $char ]['js'];
698
-                    $moment_format    .= $symbols_map[ $char ]['moment'];
699
-                } else {
700
-                    $jquery_ui_format .= $char;
701
-                    $moment_format    .= $char;
702
-                }
703
-            }
704
-        }
705
-        return array('js' => $jquery_ui_format, 'moment' => $moment_format);
706
-    }
513
+	/**
514
+	 * This converts incoming format string into js and moment variations.
515
+	 *
516
+	 * @param string $format_string incoming php format string
517
+	 * @return array js and moment formats.
518
+	 */
519
+	protected static function _php_to_js_moment_converter($format_string)
520
+	{
521
+		/**
522
+		 * This is a map of symbols for formats.
523
+		 * The index is the php symbol, the equivalent values are in the array.
524
+		 *
525
+		 * @var array
526
+		 */
527
+		$symbols_map          = array(
528
+			// Day
529
+			// 01
530
+			'd' => array(
531
+				'js'     => 'dd',
532
+				'moment' => 'DD',
533
+			),
534
+			// Mon
535
+			'D' => array(
536
+				'js'     => 'D',
537
+				'moment' => 'ddd',
538
+			),
539
+			// 1,2,...31
540
+			'j' => array(
541
+				'js'     => 'd',
542
+				'moment' => 'D',
543
+			),
544
+			// Monday
545
+			'l' => array(
546
+				'js'     => 'DD',
547
+				'moment' => 'dddd',
548
+			),
549
+			// ISO numeric representation of the day of the week (1-6)
550
+			'N' => array(
551
+				'js'     => '',
552
+				'moment' => 'E',
553
+			),
554
+			// st,nd.rd
555
+			'S' => array(
556
+				'js'     => '',
557
+				'moment' => 'o',
558
+			),
559
+			// numeric representation of day of week (0-6)
560
+			'w' => array(
561
+				'js'     => '',
562
+				'moment' => 'd',
563
+			),
564
+			// day of year starting from 0 (0-365)
565
+			'z' => array(
566
+				'js'     => 'o',
567
+				'moment' => 'DDD' // note moment does not start with 0 so will need to modify by subtracting 1
568
+			),
569
+			// Week
570
+			// ISO-8601 week number of year (weeks starting on monday)
571
+			'W' => array(
572
+				'js'     => '',
573
+				'moment' => 'w',
574
+			),
575
+			// Month
576
+			// January...December
577
+			'F' => array(
578
+				'js'     => 'MM',
579
+				'moment' => 'MMMM',
580
+			),
581
+			// 01...12
582
+			'm' => array(
583
+				'js'     => 'mm',
584
+				'moment' => 'MM',
585
+			),
586
+			// Jan...Dec
587
+			'M' => array(
588
+				'js'     => 'M',
589
+				'moment' => 'MMM',
590
+			),
591
+			// 1-12
592
+			'n' => array(
593
+				'js'     => 'm',
594
+				'moment' => 'M',
595
+			),
596
+			// number of days in given month
597
+			't' => array(
598
+				'js'     => '',
599
+				'moment' => '',
600
+			),
601
+			// Year
602
+			// whether leap year or not 1/0
603
+			'L' => array(
604
+				'js'     => '',
605
+				'moment' => '',
606
+			),
607
+			// ISO-8601 year number
608
+			'o' => array(
609
+				'js'     => '',
610
+				'moment' => 'GGGG',
611
+			),
612
+			// 1999...2003
613
+			'Y' => array(
614
+				'js'     => 'yy',
615
+				'moment' => 'YYYY',
616
+			),
617
+			// 99...03
618
+			'y' => array(
619
+				'js'     => 'y',
620
+				'moment' => 'YY',
621
+			),
622
+			// Time
623
+			// am/pm
624
+			'a' => array(
625
+				'js'     => 'tt',
626
+				'moment' => 'a',
627
+			),
628
+			// AM/PM
629
+			'A' => array(
630
+				'js'     => 'TT',
631
+				'moment' => 'A',
632
+			),
633
+			// Swatch Internet Time?!?
634
+			'B' => array(
635
+				'js'     => '',
636
+				'moment' => '',
637
+			),
638
+			// 1...12
639
+			'g' => array(
640
+				'js'     => 'h',
641
+				'moment' => 'h',
642
+			),
643
+			// 0...23
644
+			'G' => array(
645
+				'js'     => 'H',
646
+				'moment' => 'H',
647
+			),
648
+			// 01...12
649
+			'h' => array(
650
+				'js'     => 'hh',
651
+				'moment' => 'hh',
652
+			),
653
+			// 00...23
654
+			'H' => array(
655
+				'js'     => 'HH',
656
+				'moment' => 'HH',
657
+			),
658
+			// 00..59
659
+			'i' => array(
660
+				'js'     => 'mm',
661
+				'moment' => 'mm',
662
+			),
663
+			// seconds... 00...59
664
+			's' => array(
665
+				'js'     => 'ss',
666
+				'moment' => 'ss',
667
+			),
668
+			// microseconds
669
+			'u' => array(
670
+				'js'     => '',
671
+				'moment' => '',
672
+			),
673
+		);
674
+		$jquery_ui_format     = '';
675
+		$moment_format        = '';
676
+		$escaping             = false;
677
+		$format_string_length = strlen($format_string);
678
+		for ($i = 0; $i < $format_string_length; $i++) {
679
+			$char = $format_string[ $i ];
680
+			if ($char === '\\') { // PHP date format escaping character
681
+				$i++;
682
+				if ($escaping) {
683
+					$jquery_ui_format .= $format_string[ $i ];
684
+					$moment_format    .= $format_string[ $i ];
685
+				} else {
686
+					$jquery_ui_format .= '\'' . $format_string[ $i ];
687
+					$moment_format    .= $format_string[ $i ];
688
+				}
689
+				$escaping = true;
690
+			} else {
691
+				if ($escaping) {
692
+					$jquery_ui_format .= "'";
693
+					$moment_format    .= "'";
694
+					$escaping         = false;
695
+				}
696
+				if (isset($symbols_map[ $char ])) {
697
+					$jquery_ui_format .= $symbols_map[ $char ]['js'];
698
+					$moment_format    .= $symbols_map[ $char ]['moment'];
699
+				} else {
700
+					$jquery_ui_format .= $char;
701
+					$moment_format    .= $char;
702
+				}
703
+			}
704
+		}
705
+		return array('js' => $jquery_ui_format, 'moment' => $moment_format);
706
+	}
707 707
 
708 708
 
709
-    /**
710
-     * This takes an incoming format string and validates it to ensure it will work fine with PHP.
711
-     *
712
-     * @param string $format_string   Incoming format string for php date().
713
-     * @return mixed bool|array  If all is okay then TRUE is returned.  Otherwise an array of validation
714
-     *                                errors is returned.  So for client code calling, check for is_array() to
715
-     *                                indicate failed validations.
716
-     */
717
-    public static function validate_format_string($format_string)
718
-    {
719
-        $error_msg = array();
720
-        // time format checks
721
-        switch (true) {
722
-            case strpos($format_string, 'h') !== false:
723
-            case strpos($format_string, 'g') !== false:
724
-                /**
725
-                 * if the time string has a lowercase 'h' which == 12 hour time format and there
726
-                 * is not any ante meridiem format ('a' or 'A').  Then throw an error because its
727
-                 * too ambiguous and PHP won't be able to figure out whether 1 = 1pm or 1am.
728
-                 */
729
-                if (stripos($format_string, 'A') === false) {
730
-                    $error_msg[] = esc_html__(
731
-                        'There is a  time format for 12 hour time but no  "a" or "A" to indicate am/pm.  Without this distinction, PHP is unable to determine if a "1" for the hour value equals "1pm" or "1am".',
732
-                        'event_espresso'
733
-                    );
734
-                }
735
-                break;
736
-        }
737
-        return empty($error_msg) ? true : $error_msg;
738
-    }
709
+	/**
710
+	 * This takes an incoming format string and validates it to ensure it will work fine with PHP.
711
+	 *
712
+	 * @param string $format_string   Incoming format string for php date().
713
+	 * @return mixed bool|array  If all is okay then TRUE is returned.  Otherwise an array of validation
714
+	 *                                errors is returned.  So for client code calling, check for is_array() to
715
+	 *                                indicate failed validations.
716
+	 */
717
+	public static function validate_format_string($format_string)
718
+	{
719
+		$error_msg = array();
720
+		// time format checks
721
+		switch (true) {
722
+			case strpos($format_string, 'h') !== false:
723
+			case strpos($format_string, 'g') !== false:
724
+				/**
725
+				 * if the time string has a lowercase 'h' which == 12 hour time format and there
726
+				 * is not any ante meridiem format ('a' or 'A').  Then throw an error because its
727
+				 * too ambiguous and PHP won't be able to figure out whether 1 = 1pm or 1am.
728
+				 */
729
+				if (stripos($format_string, 'A') === false) {
730
+					$error_msg[] = esc_html__(
731
+						'There is a  time format for 12 hour time but no  "a" or "A" to indicate am/pm.  Without this distinction, PHP is unable to determine if a "1" for the hour value equals "1pm" or "1am".',
732
+						'event_espresso'
733
+					);
734
+				}
735
+				break;
736
+		}
737
+		return empty($error_msg) ? true : $error_msg;
738
+	}
739 739
 
740 740
 
741
-    /**
742
-     *     If the the first date starts at midnight on one day, and the next date ends at midnight on the
743
-     *     very next day then this method will return true.
744
-     *    If $date_1 = 2015-12-15 00:00:00 and $date_2 = 2015-12-16 00:00:00 then this function will return true.
745
-     *    If $date_1 = 2015-12-15 03:00:00 and $date_2 = 2015-12_16 03:00:00 then this function will return false.
746
-     *    If $date_1 = 2015-12-15 00:00:00 and $date_2 = 2015-12-15 00:00:00 then this function will return true.
747
-     *
748
-     * @param mixed $date_1
749
-     * @param mixed $date_2
750
-     * @return bool
751
-     */
752
-    public static function dates_represent_one_24_hour_date($date_1, $date_2)
753
-    {
741
+	/**
742
+	 *     If the the first date starts at midnight on one day, and the next date ends at midnight on the
743
+	 *     very next day then this method will return true.
744
+	 *    If $date_1 = 2015-12-15 00:00:00 and $date_2 = 2015-12-16 00:00:00 then this function will return true.
745
+	 *    If $date_1 = 2015-12-15 03:00:00 and $date_2 = 2015-12_16 03:00:00 then this function will return false.
746
+	 *    If $date_1 = 2015-12-15 00:00:00 and $date_2 = 2015-12-15 00:00:00 then this function will return true.
747
+	 *
748
+	 * @param mixed $date_1
749
+	 * @param mixed $date_2
750
+	 * @return bool
751
+	 */
752
+	public static function dates_represent_one_24_hour_date($date_1, $date_2)
753
+	{
754 754
 
755
-        if (
756
-            (! $date_1 instanceof DateTime || ! $date_2 instanceof DateTime)
757
-            || ($date_1->format(EE_Datetime_Field::mysql_time_format) !== '00:00:00'
758
-                || $date_2->format(
759
-                    EE_Datetime_Field::mysql_time_format
760
-                ) !== '00:00:00')
761
-        ) {
762
-            return false;
763
-        }
764
-        return $date_2->format('U') - $date_1->format('U') === 86400;
765
-    }
755
+		if (
756
+			(! $date_1 instanceof DateTime || ! $date_2 instanceof DateTime)
757
+			|| ($date_1->format(EE_Datetime_Field::mysql_time_format) !== '00:00:00'
758
+				|| $date_2->format(
759
+					EE_Datetime_Field::mysql_time_format
760
+				) !== '00:00:00')
761
+		) {
762
+			return false;
763
+		}
764
+		return $date_2->format('U') - $date_1->format('U') === 86400;
765
+	}
766 766
 
767 767
 
768
-    /**
769
-     * This returns the appropriate query interval string that can be used in sql queries involving mysql Date
770
-     * Functions.
771
-     *
772
-     * @param string $timezone_string    A timezone string in a valid format to instantiate a DateTimeZone object.
773
-     * @param string $field_for_interval The Database field that is the interval is applied to in the query.
774
-     * @return string
775
-     */
776
-    public static function get_sql_query_interval_for_offset($timezone_string, $field_for_interval)
777
-    {
778
-        try {
779
-            /** need to account for timezone offset on the selects */
780
-            $DateTimeZone = new DateTimeZone($timezone_string);
781
-        } catch (Exception $e) {
782
-            $DateTimeZone = null;
783
-        }
784
-        /**
785
-         * Note get_option( 'gmt_offset') returns a value in hours, whereas DateTimeZone::getOffset returns values in seconds.
786
-         * Hence we do the calc for DateTimeZone::getOffset.
787
-         */
788
-        $offset         = $DateTimeZone instanceof DateTimeZone
789
-            ? $DateTimeZone->getOffset(new DateTime('now')) / HOUR_IN_SECONDS
790
-            : (float) get_option('gmt_offset');
791
-        $query_interval = $offset < 0
792
-            ? 'DATE_SUB(' . $field_for_interval . ', INTERVAL ' . $offset * -1 . ' HOUR)'
793
-            : 'DATE_ADD(' . $field_for_interval . ', INTERVAL ' . $offset . ' HOUR)';
794
-        return $query_interval;
795
-    }
768
+	/**
769
+	 * This returns the appropriate query interval string that can be used in sql queries involving mysql Date
770
+	 * Functions.
771
+	 *
772
+	 * @param string $timezone_string    A timezone string in a valid format to instantiate a DateTimeZone object.
773
+	 * @param string $field_for_interval The Database field that is the interval is applied to in the query.
774
+	 * @return string
775
+	 */
776
+	public static function get_sql_query_interval_for_offset($timezone_string, $field_for_interval)
777
+	{
778
+		try {
779
+			/** need to account for timezone offset on the selects */
780
+			$DateTimeZone = new DateTimeZone($timezone_string);
781
+		} catch (Exception $e) {
782
+			$DateTimeZone = null;
783
+		}
784
+		/**
785
+		 * Note get_option( 'gmt_offset') returns a value in hours, whereas DateTimeZone::getOffset returns values in seconds.
786
+		 * Hence we do the calc for DateTimeZone::getOffset.
787
+		 */
788
+		$offset         = $DateTimeZone instanceof DateTimeZone
789
+			? $DateTimeZone->getOffset(new DateTime('now')) / HOUR_IN_SECONDS
790
+			: (float) get_option('gmt_offset');
791
+		$query_interval = $offset < 0
792
+			? 'DATE_SUB(' . $field_for_interval . ', INTERVAL ' . $offset * -1 . ' HOUR)'
793
+			: 'DATE_ADD(' . $field_for_interval . ', INTERVAL ' . $offset . ' HOUR)';
794
+		return $query_interval;
795
+	}
796 796
 
797 797
 
798
-    /**
799
-     * Retrieves the site's default timezone and returns it formatted so it's ready for display
800
-     * to users. If you want to customize how its displayed feel free to fetch the 'timezone_string'
801
-     * and 'gmt_offset' WordPress options directly; or use the filter
802
-     * FHEE__EEH_DTT_Helper__get_timezone_string_for_display
803
-     * (although note that we remove any HTML that may be added)
804
-     *
805
-     * @return string
806
-     */
807
-    public static function get_timezone_string_for_display()
808
-    {
809
-        $pretty_timezone = apply_filters('FHEE__EEH_DTT_Helper__get_timezone_string_for_display', '');
810
-        if (! empty($pretty_timezone)) {
811
-            return esc_html($pretty_timezone);
812
-        }
813
-        $timezone_string = get_option('timezone_string');
814
-        if ($timezone_string) {
815
-            static $mo_loaded = false;
816
-            // Load translations for continents and cities just like wp_timezone_choice does
817
-            if (! $mo_loaded) {
818
-                $locale = get_locale();
819
-                $mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo';
820
-                load_textdomain('continents-cities', $mofile);
821
-                $mo_loaded = true;
822
-            }
823
-            // well that was easy.
824
-            $parts = explode('/', $timezone_string);
825
-            // remove the continent
826
-            unset($parts[0]);
827
-            $t_parts = array();
828
-            // phpcs:disable WordPress.WP.I18n.NonSingularStringLiteralText
829
-            // phpcs:disable WordPress.WP.I18n.TextDomainMismatch
830
-            // disabled because this code is copied from WordPress and is a WordPress domain
831
-            foreach ($parts as $part) {
832
-                $t_parts[] = translate(str_replace('_', ' ', $part), 'continents-cities');
833
-            }
834
-            return implode(' - ', $t_parts);
835
-            // phpcs:enable
836
-        }
837
-        // they haven't set the timezone string, so let's return a string like "UTC+1"
838
-        $gmt_offset = get_option('gmt_offset');
839
-        $prefix     = (int) $gmt_offset >= 0 ? '+' : '';
840
-        $parts      = explode('.', (string) $gmt_offset);
841
-        if (count($parts) === 1) {
842
-            $parts[1] = '00';
843
-        } else {
844
-            // convert the part after the decimal, eg "5" (from x.5) or "25" (from x.25)
845
-            // to minutes, eg 30 or 15, respectively
846
-            $hour_fraction = (float) ('0.' . $parts[1]);
847
-            $parts[1]      = (string) $hour_fraction * 60;
848
-        }
849
-        return sprintf(__('UTC%1$s', 'event_espresso'), $prefix . implode(':', $parts));
850
-    }
798
+	/**
799
+	 * Retrieves the site's default timezone and returns it formatted so it's ready for display
800
+	 * to users. If you want to customize how its displayed feel free to fetch the 'timezone_string'
801
+	 * and 'gmt_offset' WordPress options directly; or use the filter
802
+	 * FHEE__EEH_DTT_Helper__get_timezone_string_for_display
803
+	 * (although note that we remove any HTML that may be added)
804
+	 *
805
+	 * @return string
806
+	 */
807
+	public static function get_timezone_string_for_display()
808
+	{
809
+		$pretty_timezone = apply_filters('FHEE__EEH_DTT_Helper__get_timezone_string_for_display', '');
810
+		if (! empty($pretty_timezone)) {
811
+			return esc_html($pretty_timezone);
812
+		}
813
+		$timezone_string = get_option('timezone_string');
814
+		if ($timezone_string) {
815
+			static $mo_loaded = false;
816
+			// Load translations for continents and cities just like wp_timezone_choice does
817
+			if (! $mo_loaded) {
818
+				$locale = get_locale();
819
+				$mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo';
820
+				load_textdomain('continents-cities', $mofile);
821
+				$mo_loaded = true;
822
+			}
823
+			// well that was easy.
824
+			$parts = explode('/', $timezone_string);
825
+			// remove the continent
826
+			unset($parts[0]);
827
+			$t_parts = array();
828
+			// phpcs:disable WordPress.WP.I18n.NonSingularStringLiteralText
829
+			// phpcs:disable WordPress.WP.I18n.TextDomainMismatch
830
+			// disabled because this code is copied from WordPress and is a WordPress domain
831
+			foreach ($parts as $part) {
832
+				$t_parts[] = translate(str_replace('_', ' ', $part), 'continents-cities');
833
+			}
834
+			return implode(' - ', $t_parts);
835
+			// phpcs:enable
836
+		}
837
+		// they haven't set the timezone string, so let's return a string like "UTC+1"
838
+		$gmt_offset = get_option('gmt_offset');
839
+		$prefix     = (int) $gmt_offset >= 0 ? '+' : '';
840
+		$parts      = explode('.', (string) $gmt_offset);
841
+		if (count($parts) === 1) {
842
+			$parts[1] = '00';
843
+		} else {
844
+			// convert the part after the decimal, eg "5" (from x.5) or "25" (from x.25)
845
+			// to minutes, eg 30 or 15, respectively
846
+			$hour_fraction = (float) ('0.' . $parts[1]);
847
+			$parts[1]      = (string) $hour_fraction * 60;
848
+		}
849
+		return sprintf(__('UTC%1$s', 'event_espresso'), $prefix . implode(':', $parts));
850
+	}
851 851
 
852 852
 
853 853
 
854
-    /**
855
-     * So PHP does this awesome thing where if you are trying to get a timestamp
856
-     * for a month using a string like "February" or "February 2017",
857
-     * and you don't specify a day as part of your string,
858
-     * then PHP will use whatever the current day of the month is.
859
-     * IF the current day of the month happens to be the 30th or 31st,
860
-     * then PHP gets really confused by a date like February 30,
861
-     * so instead of saying
862
-     *      "Hey February only has 28 days (this year)...
863
-     *      ...you must have meant the last day of the month!"
864
-     * PHP does the next most logical thing, and bumps the date up to March 2nd,
865
-     * because someone requesting February 30th obviously meant March 1st!
866
-     * The way around this is to always set the day to the first,
867
-     * so that the month will stay on the month you wanted.
868
-     * this method will add that "1" into your date regardless of the format.
869
-     *
870
-     * @param string $month
871
-     * @return string
872
-     */
873
-    public static function first_of_month_timestamp($month = '')
874
-    {
875
-        $month = (string) $month;
876
-        $year  = '';
877
-        // check if the incoming string has a year in it or not
878
-        if (preg_match('/\b\d{4}\b/', $month, $matches)) {
879
-            $year = $matches[0];
880
-            // ten remove that from the month string as well as any spaces
881
-            $month = trim(str_replace($year, '', $month));
882
-            // add a space before the year
883
-            $year = " {$year}";
884
-        }
885
-        // return timestamp for something like "February 1 2017"
886
-        return strtotime("{$month} 1{$year}");
887
-    }
854
+	/**
855
+	 * So PHP does this awesome thing where if you are trying to get a timestamp
856
+	 * for a month using a string like "February" or "February 2017",
857
+	 * and you don't specify a day as part of your string,
858
+	 * then PHP will use whatever the current day of the month is.
859
+	 * IF the current day of the month happens to be the 30th or 31st,
860
+	 * then PHP gets really confused by a date like February 30,
861
+	 * so instead of saying
862
+	 *      "Hey February only has 28 days (this year)...
863
+	 *      ...you must have meant the last day of the month!"
864
+	 * PHP does the next most logical thing, and bumps the date up to March 2nd,
865
+	 * because someone requesting February 30th obviously meant March 1st!
866
+	 * The way around this is to always set the day to the first,
867
+	 * so that the month will stay on the month you wanted.
868
+	 * this method will add that "1" into your date regardless of the format.
869
+	 *
870
+	 * @param string $month
871
+	 * @return string
872
+	 */
873
+	public static function first_of_month_timestamp($month = '')
874
+	{
875
+		$month = (string) $month;
876
+		$year  = '';
877
+		// check if the incoming string has a year in it or not
878
+		if (preg_match('/\b\d{4}\b/', $month, $matches)) {
879
+			$year = $matches[0];
880
+			// ten remove that from the month string as well as any spaces
881
+			$month = trim(str_replace($year, '', $month));
882
+			// add a space before the year
883
+			$year = " {$year}";
884
+		}
885
+		// return timestamp for something like "February 1 2017"
886
+		return strtotime("{$month} 1{$year}");
887
+	}
888 888
 
889 889
 
890
-    /**
891
-     * This simply returns the timestamp for tomorrow (midnight next day) in this sites timezone.  So it may be midnight
892
-     * for this sites timezone, but the timestamp could be some other time GMT.
893
-     */
894
-    public static function tomorrow()
895
-    {
896
-        // The multiplication of -1 ensures that we switch positive offsets to negative and negative offsets to positive
897
-        // before adding to the timestamp.  Why? Because we want tomorrow to be for midnight the next day in THIS timezone
898
-        // not an offset from midnight in UTC.  So if we're starting with UTC 00:00:00, then we want to make sure the
899
-        // final timestamp is equivalent to midnight in this timezone as represented in GMT.
900
-        return strtotime('tomorrow') + (self::get_site_timezone_gmt_offset() * -1);
901
-    }
890
+	/**
891
+	 * This simply returns the timestamp for tomorrow (midnight next day) in this sites timezone.  So it may be midnight
892
+	 * for this sites timezone, but the timestamp could be some other time GMT.
893
+	 */
894
+	public static function tomorrow()
895
+	{
896
+		// The multiplication of -1 ensures that we switch positive offsets to negative and negative offsets to positive
897
+		// before adding to the timestamp.  Why? Because we want tomorrow to be for midnight the next day in THIS timezone
898
+		// not an offset from midnight in UTC.  So if we're starting with UTC 00:00:00, then we want to make sure the
899
+		// final timestamp is equivalent to midnight in this timezone as represented in GMT.
900
+		return strtotime('tomorrow') + (self::get_site_timezone_gmt_offset() * -1);
901
+	}
902 902
 
903 903
 
904
-    /**
905
-     * **
906
-     * Gives a nicely-formatted list of timezone strings.
907
-     * Copied from the core wp function by the same name so we could customize to remove UTC offsets.
908
-     *
909
-     * @since     4.9.40.rc.008
910
-     * @staticvar bool $mo_loaded
911
-     * @staticvar string $locale_loaded
912
-     * @param string $selected_zone Selected timezone.
913
-     * @param string $locale        Optional. Locale to load the timezones in. Default current site locale.
914
-     * @return string
915
-     */
916
-    public static function wp_timezone_choice($selected_zone, $locale = null)
917
-    {
918
-        static $mo_loaded = false, $locale_loaded = null;
919
-        $continents = array(
920
-            'Africa',
921
-            'America',
922
-            'Antarctica',
923
-            'Arctic',
924
-            'Asia',
925
-            'Atlantic',
926
-            'Australia',
927
-            'Europe',
928
-            'Indian',
929
-            'Pacific',
930
-        );
931
-        // Load translations for continents and cities.
932
-        if (! $mo_loaded || $locale !== $locale_loaded) {
933
-            $locale_loaded = $locale ? $locale : get_locale();
934
-            $mofile        = WP_LANG_DIR . '/continents-cities-' . $locale_loaded . '.mo';
935
-            unload_textdomain('continents-cities');
936
-            load_textdomain('continents-cities', $mofile);
937
-            $mo_loaded = true;
938
-        }
939
-        $zone_data = array();
940
-        foreach (timezone_identifiers_list() as $zone) {
941
-            $zone = explode('/', $zone);
942
-            if (! in_array($zone[0], $continents, true)) {
943
-                continue;
944
-            }
945
-            // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later
946
-            $exists      = array(
947
-                0 => isset($zone[0]) && $zone[0],
948
-                1 => isset($zone[1]) && $zone[1],
949
-                2 => isset($zone[2]) && $zone[2],
950
-            );
951
-            $exists[3]   = $exists[0] && $zone[0] !== 'Etc';
952
-            $exists[4]   = $exists[1] && $exists[3];
953
-            $exists[5]   = $exists[2] && $exists[3];
954
-            // phpcs:disable WordPress.WP.I18n.NonSingularStringLiteralText
955
-            // phpcs:disable WordPress.WP.I18n.TextDomainMismatch
956
-            // disabled because this code is copied from WordPress and is a WordPress domain
957
-            $zone_data[] = array(
958
-                'continent'   => $exists[0] ? $zone[0] : '',
959
-                'city'        => $exists[1] ? $zone[1] : '',
960
-                'subcity'     => $exists[2] ? $zone[2] : '',
961
-                't_continent' => $exists[3]
962
-                    ? translate(str_replace('_', ' ', $zone[0]), 'continents-cities')
963
-                    : '',
964
-                't_city'      => $exists[4]
965
-                    ? translate(str_replace('_', ' ', $zone[1]), 'continents-cities')
966
-                    : '',
967
-                't_subcity'   => $exists[5]
968
-                    ? translate(str_replace('_', ' ', $zone[2]), 'continents-cities')
969
-                    : '',
970
-            );
971
-            // phpcs:enable
972
-        }
973
-        usort($zone_data, '_wp_timezone_choice_usort_callback');
974
-        $structure = array();
975
-        if (empty($selected_zone)) {
976
-            $structure[] = '<option selected="selected" value="">' . __('Select a city', 'event_espresso') . '</option>';
977
-        }
978
-        foreach ($zone_data as $key => $zone) {
979
-            // Build value in an array to join later
980
-            $value = array($zone['continent']);
981
-            if (empty($zone['city'])) {
982
-                // It's at the continent level (generally won't happen)
983
-                $display = $zone['t_continent'];
984
-            } else {
985
-                // It's inside a continent group
986
-                // Continent optgroup
987
-                if (! isset($zone_data[ $key - 1 ]) || $zone_data[ $key - 1 ]['continent'] !== $zone['continent']) {
988
-                    $label       = $zone['t_continent'];
989
-                    $structure[] = '<optgroup label="' . esc_attr($label) . '">';
990
-                }
991
-                // Add the city to the value
992
-                $value[] = $zone['city'];
993
-                $display = $zone['t_city'];
994
-                if (! empty($zone['subcity'])) {
995
-                    // Add the subcity to the value
996
-                    $value[] = $zone['subcity'];
997
-                    $display .= ' - ' . $zone['t_subcity'];
998
-                }
999
-            }
1000
-            // Build the value
1001
-            $value       = implode('/', $value);
1002
-            $selected    = $value === $selected_zone ? ' selected="selected"' : '';
1003
-            $structure[] = '<option value="' . esc_attr($value) . '"' . $selected . '>'
1004
-                           . esc_html($display)
1005
-                           . '</option>';
1006
-            // Close continent optgroup
1007
-            if (
1008
-                ! empty($zone['city'])
1009
-                && (
1010
-                    ! isset($zone_data[ $key + 1 ])
1011
-                    || (isset($zone_data[ $key + 1 ]) && $zone_data[ $key + 1 ]['continent'] !== $zone['continent'])
1012
-                )
1013
-            ) {
1014
-                $structure[] = '</optgroup>';
1015
-            }
1016
-        }
1017
-        return implode("\n", $structure);
1018
-    }
904
+	/**
905
+	 * **
906
+	 * Gives a nicely-formatted list of timezone strings.
907
+	 * Copied from the core wp function by the same name so we could customize to remove UTC offsets.
908
+	 *
909
+	 * @since     4.9.40.rc.008
910
+	 * @staticvar bool $mo_loaded
911
+	 * @staticvar string $locale_loaded
912
+	 * @param string $selected_zone Selected timezone.
913
+	 * @param string $locale        Optional. Locale to load the timezones in. Default current site locale.
914
+	 * @return string
915
+	 */
916
+	public static function wp_timezone_choice($selected_zone, $locale = null)
917
+	{
918
+		static $mo_loaded = false, $locale_loaded = null;
919
+		$continents = array(
920
+			'Africa',
921
+			'America',
922
+			'Antarctica',
923
+			'Arctic',
924
+			'Asia',
925
+			'Atlantic',
926
+			'Australia',
927
+			'Europe',
928
+			'Indian',
929
+			'Pacific',
930
+		);
931
+		// Load translations for continents and cities.
932
+		if (! $mo_loaded || $locale !== $locale_loaded) {
933
+			$locale_loaded = $locale ? $locale : get_locale();
934
+			$mofile        = WP_LANG_DIR . '/continents-cities-' . $locale_loaded . '.mo';
935
+			unload_textdomain('continents-cities');
936
+			load_textdomain('continents-cities', $mofile);
937
+			$mo_loaded = true;
938
+		}
939
+		$zone_data = array();
940
+		foreach (timezone_identifiers_list() as $zone) {
941
+			$zone = explode('/', $zone);
942
+			if (! in_array($zone[0], $continents, true)) {
943
+				continue;
944
+			}
945
+			// This determines what gets set and translated - we don't translate Etc/* strings here, they are done later
946
+			$exists      = array(
947
+				0 => isset($zone[0]) && $zone[0],
948
+				1 => isset($zone[1]) && $zone[1],
949
+				2 => isset($zone[2]) && $zone[2],
950
+			);
951
+			$exists[3]   = $exists[0] && $zone[0] !== 'Etc';
952
+			$exists[4]   = $exists[1] && $exists[3];
953
+			$exists[5]   = $exists[2] && $exists[3];
954
+			// phpcs:disable WordPress.WP.I18n.NonSingularStringLiteralText
955
+			// phpcs:disable WordPress.WP.I18n.TextDomainMismatch
956
+			// disabled because this code is copied from WordPress and is a WordPress domain
957
+			$zone_data[] = array(
958
+				'continent'   => $exists[0] ? $zone[0] : '',
959
+				'city'        => $exists[1] ? $zone[1] : '',
960
+				'subcity'     => $exists[2] ? $zone[2] : '',
961
+				't_continent' => $exists[3]
962
+					? translate(str_replace('_', ' ', $zone[0]), 'continents-cities')
963
+					: '',
964
+				't_city'      => $exists[4]
965
+					? translate(str_replace('_', ' ', $zone[1]), 'continents-cities')
966
+					: '',
967
+				't_subcity'   => $exists[5]
968
+					? translate(str_replace('_', ' ', $zone[2]), 'continents-cities')
969
+					: '',
970
+			);
971
+			// phpcs:enable
972
+		}
973
+		usort($zone_data, '_wp_timezone_choice_usort_callback');
974
+		$structure = array();
975
+		if (empty($selected_zone)) {
976
+			$structure[] = '<option selected="selected" value="">' . __('Select a city', 'event_espresso') . '</option>';
977
+		}
978
+		foreach ($zone_data as $key => $zone) {
979
+			// Build value in an array to join later
980
+			$value = array($zone['continent']);
981
+			if (empty($zone['city'])) {
982
+				// It's at the continent level (generally won't happen)
983
+				$display = $zone['t_continent'];
984
+			} else {
985
+				// It's inside a continent group
986
+				// Continent optgroup
987
+				if (! isset($zone_data[ $key - 1 ]) || $zone_data[ $key - 1 ]['continent'] !== $zone['continent']) {
988
+					$label       = $zone['t_continent'];
989
+					$structure[] = '<optgroup label="' . esc_attr($label) . '">';
990
+				}
991
+				// Add the city to the value
992
+				$value[] = $zone['city'];
993
+				$display = $zone['t_city'];
994
+				if (! empty($zone['subcity'])) {
995
+					// Add the subcity to the value
996
+					$value[] = $zone['subcity'];
997
+					$display .= ' - ' . $zone['t_subcity'];
998
+				}
999
+			}
1000
+			// Build the value
1001
+			$value       = implode('/', $value);
1002
+			$selected    = $value === $selected_zone ? ' selected="selected"' : '';
1003
+			$structure[] = '<option value="' . esc_attr($value) . '"' . $selected . '>'
1004
+						   . esc_html($display)
1005
+						   . '</option>';
1006
+			// Close continent optgroup
1007
+			if (
1008
+				! empty($zone['city'])
1009
+				&& (
1010
+					! isset($zone_data[ $key + 1 ])
1011
+					|| (isset($zone_data[ $key + 1 ]) && $zone_data[ $key + 1 ]['continent'] !== $zone['continent'])
1012
+				)
1013
+			) {
1014
+				$structure[] = '</optgroup>';
1015
+			}
1016
+		}
1017
+		return implode("\n", $structure);
1018
+	}
1019 1019
 
1020 1020
 
1021
-    /**
1022
-     * Shim for the WP function `get_user_locale` that was added in WordPress 4.7.0
1023
-     *
1024
-     * @param int|WP_User $user_id
1025
-     * @return string
1026
-     */
1027
-    public static function get_user_locale($user_id = 0)
1028
-    {
1029
-        if (function_exists('get_user_locale')) {
1030
-            return get_user_locale($user_id);
1031
-        }
1032
-        return get_locale();
1033
-    }
1021
+	/**
1022
+	 * Shim for the WP function `get_user_locale` that was added in WordPress 4.7.0
1023
+	 *
1024
+	 * @param int|WP_User $user_id
1025
+	 * @return string
1026
+	 */
1027
+	public static function get_user_locale($user_id = 0)
1028
+	{
1029
+		if (function_exists('get_user_locale')) {
1030
+			return get_user_locale($user_id);
1031
+		}
1032
+		return get_locale();
1033
+	}
1034 1034
 
1035 1035
 
1036
-    /**
1037
-     * Return the appropriate helper adapter for DTT related things.
1038
-     *
1039
-     * @return HelperInterface
1040
-     * @throws InvalidArgumentException
1041
-     * @throws InvalidDataTypeException
1042
-     * @throws InvalidInterfaceException
1043
-     */
1044
-    private static function getHelperAdapter()
1045
-    {
1046
-        $dtt_helper_fqcn = PHP_VERSION_ID < 50600
1047
-            ? 'EventEspresso\core\services\helpers\datetime\PhpCompatLessFiveSixHelper'
1048
-            : 'EventEspresso\core\services\helpers\datetime\PhpCompatGreaterFiveSixHelper';
1049
-        return LoaderFactory::getLoader()->getShared($dtt_helper_fqcn);
1050
-    }
1036
+	/**
1037
+	 * Return the appropriate helper adapter for DTT related things.
1038
+	 *
1039
+	 * @return HelperInterface
1040
+	 * @throws InvalidArgumentException
1041
+	 * @throws InvalidDataTypeException
1042
+	 * @throws InvalidInterfaceException
1043
+	 */
1044
+	private static function getHelperAdapter()
1045
+	{
1046
+		$dtt_helper_fqcn = PHP_VERSION_ID < 50600
1047
+			? 'EventEspresso\core\services\helpers\datetime\PhpCompatLessFiveSixHelper'
1048
+			: 'EventEspresso\core\services\helpers\datetime\PhpCompatGreaterFiveSixHelper';
1049
+		return LoaderFactory::getLoader()->getShared($dtt_helper_fqcn);
1050
+	}
1051 1051
 
1052 1052
 
1053
-    /**
1054
-     * Helper function for setting the timezone on a DateTime object.
1055
-     * This is implemented to standardize a workaround for a PHP bug outlined in
1056
-     * https://events.codebasehq.com/projects/event-espresso/tickets/11407 and
1057
-     * https://events.codebasehq.com/projects/event-espresso/tickets/11233
1058
-     *
1059
-     * @param DateTime     $datetime
1060
-     * @param DateTimeZone $timezone
1061
-     */
1062
-    public static function setTimezone(DateTime $datetime, DateTimeZone $timezone)
1063
-    {
1064
-        $datetime->setTimezone($timezone);
1065
-        $datetime->getTimestamp();
1066
-    }
1053
+	/**
1054
+	 * Helper function for setting the timezone on a DateTime object.
1055
+	 * This is implemented to standardize a workaround for a PHP bug outlined in
1056
+	 * https://events.codebasehq.com/projects/event-espresso/tickets/11407 and
1057
+	 * https://events.codebasehq.com/projects/event-espresso/tickets/11233
1058
+	 *
1059
+	 * @param DateTime     $datetime
1060
+	 * @param DateTimeZone $timezone
1061
+	 */
1062
+	public static function setTimezone(DateTime $datetime, DateTimeZone $timezone)
1063
+	{
1064
+		$datetime->setTimezone($timezone);
1065
+		$datetime->getTimestamp();
1066
+	}
1067 1067
 }
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_Page.core.php 3 patches
Doc Comments   -1 removed lines patch added patch discarded remove patch
@@ -2280,7 +2280,6 @@
 block discarded – undo
2280 2280
     /**
2281 2281
      * _delete_event
2282 2282
      *
2283
-     * @param bool $redirect_after
2284 2283
      * @throws EE_Error
2285 2284
      * @throws InvalidArgumentException
2286 2285
      * @throws InvalidDataTypeException
Please login to merge, or discard this patch.
Indentation   +2873 added lines, -2873 removed lines patch added patch discarded remove patch
@@ -20,2877 +20,2877 @@
 block discarded – undo
20 20
 class Events_Admin_Page extends EE_Admin_Page_CPT
21 21
 {
22 22
 
23
-    /**
24
-     * This will hold the event object for event_details screen.
25
-     *
26
-     * @var EE_Event $_event
27
-     */
28
-    protected $_event;
29
-
30
-
31
-    /**
32
-     * This will hold the category object for category_details screen.
33
-     *
34
-     * @var stdClass $_category
35
-     */
36
-    protected $_category;
37
-
38
-
39
-    /**
40
-     * @var EEM_Event $_event_model
41
-     */
42
-    protected $_event_model;
43
-
44
-    /**
45
-     * @var EEM_Datetime $datetime_model
46
-     */
47
-    protected $datetime_model;
48
-
49
-    /**
50
-     * @var EEM_Ticket $ticket_model
51
-     */
52
-    protected $ticket_model;
53
-
54
-
55
-    /**
56
-     * @var EE_Event
57
-     */
58
-    protected $_cpt_model_obj;
59
-
60
-
61
-    /**
62
-     * @var NodeGroupDao
63
-     */
64
-    protected $model_obj_node_group_persister;
65
-
66
-    /**
67
-     * Initialize page props for this admin page group.
68
-     */
69
-    protected function _init_page_props()
70
-    {
71
-        $this->page_slug = EVENTS_PG_SLUG;
72
-        $this->page_label = EVENTS_LABEL;
73
-        $this->_admin_base_url = EVENTS_ADMIN_URL;
74
-        $this->_admin_base_path = EVENTS_ADMIN;
75
-        $this->_cpt_model_names = [
76
-            'create_new' => 'EEM_Event',
77
-            'edit'       => 'EEM_Event',
78
-        ];
79
-        $this->_cpt_edit_routes = [
80
-            'espresso_events' => 'edit',
81
-        ];
82
-        add_action(
83
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
84
-            [$this, 'verify_event_edit'],
85
-            10,
86
-            2
87
-        );
88
-    }
89
-
90
-
91
-    /**
92
-     * Sets the ajax hooks used for this admin page group.
93
-     */
94
-    protected function _ajax_hooks()
95
-    {
96
-        add_action('wp_ajax_ee_save_timezone_setting', [$this, 'save_timezonestring_setting']);
97
-    }
98
-
99
-
100
-    /**
101
-     * Sets the page properties for this admin page group.
102
-     */
103
-    protected function _define_page_props()
104
-    {
105
-        $this->_admin_page_title = EVENTS_LABEL;
106
-        $this->_labels = [
107
-            'buttons'      => [
108
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
109
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
110
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
111
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
112
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
113
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
114
-            ],
115
-            'editor_title' => [
116
-                'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
117
-            ],
118
-            'publishbox'   => [
119
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
120
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
121
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
122
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
123
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
124
-            ],
125
-        ];
126
-    }
127
-
128
-
129
-    /**
130
-     * Sets the page routes property for this admin page group.
131
-     */
132
-    protected function _set_page_routes()
133
-    {
134
-        // load formatter helper
135
-        // load field generator helper
136
-        // is there a evt_id in the request?
137
-        $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
138
-            ? $this->_req_data['EVT_ID']
139
-            : 0;
140
-        $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
141
-        $this->_page_routes = [
142
-            'default'                       => [
143
-                'func'       => '_events_overview_list_table',
144
-                'capability' => 'ee_read_events',
145
-            ],
146
-            'create_new'                    => [
147
-                'func'       => '_create_new_cpt_item',
148
-                'capability' => 'ee_edit_events',
149
-            ],
150
-            'edit'                          => [
151
-                'func'       => '_edit_cpt_item',
152
-                'capability' => 'ee_edit_event',
153
-                'obj_id'     => $evt_id,
154
-            ],
155
-            'copy_event'                    => [
156
-                'func'       => '_copy_events',
157
-                'capability' => 'ee_edit_event',
158
-                'obj_id'     => $evt_id,
159
-                'noheader'   => true,
160
-            ],
161
-            'trash_event'                   => [
162
-                'func'       => '_trash_or_restore_event',
163
-                'args'       => ['event_status' => 'trash'],
164
-                'capability' => 'ee_delete_event',
165
-                'obj_id'     => $evt_id,
166
-                'noheader'   => true,
167
-            ],
168
-            'trash_events'                  => [
169
-                'func'       => '_trash_or_restore_events',
170
-                'args'       => ['event_status' => 'trash'],
171
-                'capability' => 'ee_delete_events',
172
-                'noheader'   => true,
173
-            ],
174
-            'restore_event'                 => [
175
-                'func'       => '_trash_or_restore_event',
176
-                'args'       => ['event_status' => 'draft'],
177
-                'capability' => 'ee_delete_event',
178
-                'obj_id'     => $evt_id,
179
-                'noheader'   => true,
180
-            ],
181
-            'restore_events'                => [
182
-                'func'       => '_trash_or_restore_events',
183
-                'args'       => ['event_status' => 'draft'],
184
-                'capability' => 'ee_delete_events',
185
-                'noheader'   => true,
186
-            ],
187
-            'delete_event'                  => [
188
-                'func'       => '_delete_event',
189
-                'capability' => 'ee_delete_event',
190
-                'obj_id'     => $evt_id,
191
-                'noheader'   => true,
192
-            ],
193
-            'delete_events'                 => [
194
-                'func'       => '_delete_events',
195
-                'capability' => 'ee_delete_events',
196
-                'noheader'   => true,
197
-            ],
198
-            'view_report'                   => [
199
-                'func'       => '_view_report',
200
-                'capability' => 'ee_edit_events',
201
-            ],
202
-            'default_event_settings'        => [
203
-                'func'       => '_default_event_settings',
204
-                'capability' => 'manage_options',
205
-            ],
206
-            'update_default_event_settings' => [
207
-                'func'       => '_update_default_event_settings',
208
-                'capability' => 'manage_options',
209
-                'noheader'   => true,
210
-            ],
211
-            'template_settings'             => [
212
-                'func'       => '_template_settings',
213
-                'capability' => 'manage_options',
214
-            ],
215
-            // event category tab related
216
-            'add_category'                  => [
217
-                'func'       => '_category_details',
218
-                'capability' => 'ee_edit_event_category',
219
-                'args'       => ['add'],
220
-            ],
221
-            'edit_category'                 => [
222
-                'func'       => '_category_details',
223
-                'capability' => 'ee_edit_event_category',
224
-                'args'       => ['edit'],
225
-            ],
226
-            'delete_categories'             => [
227
-                'func'       => '_delete_categories',
228
-                'capability' => 'ee_delete_event_category',
229
-                'noheader'   => true,
230
-            ],
231
-            'delete_category'               => [
232
-                'func'       => '_delete_categories',
233
-                'capability' => 'ee_delete_event_category',
234
-                'noheader'   => true,
235
-            ],
236
-            'insert_category'               => [
237
-                'func'       => '_insert_or_update_category',
238
-                'args'       => ['new_category' => true],
239
-                'capability' => 'ee_edit_event_category',
240
-                'noheader'   => true,
241
-            ],
242
-            'update_category'               => [
243
-                'func'       => '_insert_or_update_category',
244
-                'args'       => ['new_category' => false],
245
-                'capability' => 'ee_edit_event_category',
246
-                'noheader'   => true,
247
-            ],
248
-            'category_list'                 => [
249
-                'func'       => '_category_list_table',
250
-                'capability' => 'ee_manage_event_categories',
251
-            ],
252
-            'preview_deletion' => [
253
-                'func' => 'previewDeletion',
254
-                'capability' => 'ee_delete_events',
255
-            ],
256
-            'confirm_deletion' => [
257
-                'func' => 'confirmDeletion',
258
-                'capability' => 'ee_delete_events',
259
-                'noheader' => true,
260
-            ]
261
-        ];
262
-    }
263
-
264
-
265
-    /**
266
-     * Set the _page_config property for this admin page group.
267
-     */
268
-    protected function _set_page_config()
269
-    {
270
-        $this->_page_config = [
271
-            'default'                => [
272
-                'nav'           => [
273
-                    'label' => esc_html__('Overview', 'event_espresso'),
274
-                    'order' => 10,
275
-                ],
276
-                'list_table'    => 'Events_Admin_List_Table',
277
-                'help_tabs'     => [
278
-                    'events_overview_help_tab'                       => [
279
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
280
-                        'filename' => 'events_overview',
281
-                    ],
282
-                    'events_overview_table_column_headings_help_tab' => [
283
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
284
-                        'filename' => 'events_overview_table_column_headings',
285
-                    ],
286
-                    'events_overview_filters_help_tab'               => [
287
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
288
-                        'filename' => 'events_overview_filters',
289
-                    ],
290
-                    'events_overview_view_help_tab'                  => [
291
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
292
-                        'filename' => 'events_overview_views',
293
-                    ],
294
-                    'events_overview_other_help_tab'                 => [
295
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
296
-                        'filename' => 'events_overview_other',
297
-                    ],
298
-                ],
299
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
300
-                // 'help_tour'     => [
301
-                //     'Event_Overview_Help_Tour',
302
-                //     // 'New_Features_Test_Help_Tour' for testing multiple help tour
303
-                // ],
304
-                'require_nonce' => false,
305
-                'qtips'         => ['EE_Event_List_Table_Tips'],
306
-            ],
307
-            'create_new'             => [
308
-                'nav'           => [
309
-                    'label'      => esc_html__('Add Event', 'event_espresso'),
310
-                    'order'      => 5,
311
-                    'persistent' => false,
312
-                ],
313
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
314
-                'help_tabs'     => [
315
-                    'event_editor_help_tab'                            => [
316
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
317
-                        'filename' => 'event_editor',
318
-                    ],
319
-                    'event_editor_title_richtexteditor_help_tab'       => [
320
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
321
-                        'filename' => 'event_editor_title_richtexteditor',
322
-                    ],
323
-                    'event_editor_venue_details_help_tab'              => [
324
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
325
-                        'filename' => 'event_editor_venue_details',
326
-                    ],
327
-                    'event_editor_event_datetimes_help_tab'            => [
328
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
329
-                        'filename' => 'event_editor_event_datetimes',
330
-                    ],
331
-                    'event_editor_event_tickets_help_tab'              => [
332
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
333
-                        'filename' => 'event_editor_event_tickets',
334
-                    ],
335
-                    'event_editor_event_registration_options_help_tab' => [
336
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
337
-                        'filename' => 'event_editor_event_registration_options',
338
-                    ],
339
-                    'event_editor_tags_categories_help_tab'            => [
340
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
341
-                        'filename' => 'event_editor_tags_categories',
342
-                    ],
343
-                    'event_editor_questions_registrants_help_tab'      => [
344
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
345
-                        'filename' => 'event_editor_questions_registrants',
346
-                    ],
347
-                    'event_editor_save_new_event_help_tab'             => [
348
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
349
-                        'filename' => 'event_editor_save_new_event',
350
-                    ],
351
-                    'event_editor_other_help_tab'                      => [
352
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
353
-                        'filename' => 'event_editor_other',
354
-                    ],
355
-                ],
356
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
357
-                // 'help_tour'     => [
358
-                //     'Event_Editor_Help_Tour',
359
-                // ],
360
-                'require_nonce' => false,
361
-            ],
362
-            'edit'                   => [
363
-                'nav'           => [
364
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
365
-                    'order'      => 5,
366
-                    'persistent' => false,
367
-                    'url'        => isset($this->_req_data['post'])
368
-                        ? EE_Admin_Page::add_query_args_and_nonce(
369
-                            ['post' => $this->_req_data['post'], 'action' => 'edit'],
370
-                            $this->_current_page_view_url
371
-                        )
372
-                        : $this->_admin_base_url,
373
-                ],
374
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
375
-                'help_tabs'     => [
376
-                    'event_editor_help_tab'                            => [
377
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
378
-                        'filename' => 'event_editor',
379
-                    ],
380
-                    'event_editor_title_richtexteditor_help_tab'       => [
381
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
382
-                        'filename' => 'event_editor_title_richtexteditor',
383
-                    ],
384
-                    'event_editor_venue_details_help_tab'              => [
385
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
386
-                        'filename' => 'event_editor_venue_details',
387
-                    ],
388
-                    'event_editor_event_datetimes_help_tab'            => [
389
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
390
-                        'filename' => 'event_editor_event_datetimes',
391
-                    ],
392
-                    'event_editor_event_tickets_help_tab'              => [
393
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
394
-                        'filename' => 'event_editor_event_tickets',
395
-                    ],
396
-                    'event_editor_event_registration_options_help_tab' => [
397
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
398
-                        'filename' => 'event_editor_event_registration_options',
399
-                    ],
400
-                    'event_editor_tags_categories_help_tab'            => [
401
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
402
-                        'filename' => 'event_editor_tags_categories',
403
-                    ],
404
-                    'event_editor_questions_registrants_help_tab'      => [
405
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
406
-                        'filename' => 'event_editor_questions_registrants',
407
-                    ],
408
-                    'event_editor_save_new_event_help_tab'             => [
409
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
410
-                        'filename' => 'event_editor_save_new_event',
411
-                    ],
412
-                    'event_editor_other_help_tab'                      => [
413
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
414
-                        'filename' => 'event_editor_other',
415
-                    ],
416
-                ],
417
-                'require_nonce' => false,
418
-            ],
419
-            'default_event_settings' => [
420
-                'nav'           => [
421
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
422
-                    'order' => 40,
423
-                ],
424
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
425
-                'labels'        => [
426
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
427
-                ],
428
-                'help_tabs'     => [
429
-                    'default_settings_help_tab'        => [
430
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
431
-                        'filename' => 'events_default_settings',
432
-                    ],
433
-                    'default_settings_status_help_tab' => [
434
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
435
-                        'filename' => 'events_default_settings_status',
436
-                    ],
437
-                    'default_maximum_tickets_help_tab' => [
438
-                        'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
439
-                        'filename' => 'events_default_settings_max_tickets',
440
-                    ],
441
-                ],
442
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
443
-                // 'help_tour'     => ['Event_Default_Settings_Help_Tour'],
444
-                'require_nonce' => false,
445
-            ],
446
-            // template settings
447
-            'template_settings'      => [
448
-                'nav'           => [
449
-                    'label' => esc_html__('Templates', 'event_espresso'),
450
-                    'order' => 30,
451
-                ],
452
-                'metaboxes'     => $this->_default_espresso_metaboxes,
453
-                'help_tabs'     => [
454
-                    'general_settings_templates_help_tab' => [
455
-                        'title'    => esc_html__('Templates', 'event_espresso'),
456
-                        'filename' => 'general_settings_templates',
457
-                    ],
458
-                ],
459
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
460
-                // 'help_tour'     => ['Templates_Help_Tour'],
461
-                'require_nonce' => false,
462
-            ],
463
-            // event category stuff
464
-            'add_category'           => [
465
-                'nav'           => [
466
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
467
-                    'order'      => 15,
468
-                    'persistent' => false,
469
-                ],
470
-                'help_tabs'     => [
471
-                    'add_category_help_tab' => [
472
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
473
-                        'filename' => 'events_add_category',
474
-                    ],
475
-                ],
476
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
477
-                // 'help_tour'     => ['Event_Add_Category_Help_Tour'],
478
-                'metaboxes'     => ['_publish_post_box'],
479
-                'require_nonce' => false,
480
-            ],
481
-            'edit_category'          => [
482
-                'nav'           => [
483
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
484
-                    'order'      => 15,
485
-                    'persistent' => false,
486
-                    'url'        => isset($this->_req_data['EVT_CAT_ID'])
487
-                        ? add_query_arg(
488
-                            ['EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']],
489
-                            $this->_current_page_view_url
490
-                        )
491
-                        : $this->_admin_base_url,
492
-                ],
493
-                'help_tabs'     => [
494
-                    'edit_category_help_tab' => [
495
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
496
-                        'filename' => 'events_edit_category',
497
-                    ],
498
-                ],
499
-                /*'help_tour' => ['Event_Edit_Category_Help_Tour'],*/
500
-                'metaboxes'     => ['_publish_post_box'],
501
-                'require_nonce' => false,
502
-            ],
503
-            'category_list'          => [
504
-                'nav'           => [
505
-                    'label' => esc_html__('Categories', 'event_espresso'),
506
-                    'order' => 20,
507
-                ],
508
-                'list_table'    => 'Event_Categories_Admin_List_Table',
509
-                'help_tabs'     => [
510
-                    'events_categories_help_tab'                       => [
511
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
512
-                        'filename' => 'events_categories',
513
-                    ],
514
-                    'events_categories_table_column_headings_help_tab' => [
515
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
516
-                        'filename' => 'events_categories_table_column_headings',
517
-                    ],
518
-                    'events_categories_view_help_tab'                  => [
519
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
520
-                        'filename' => 'events_categories_views',
521
-                    ],
522
-                    'events_categories_other_help_tab'                 => [
523
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
524
-                        'filename' => 'events_categories_other',
525
-                    ],
526
-                ],
527
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
528
-                // 'help_tour'     => [
529
-                //     'Event_Categories_Help_Tour',
530
-                // ],
531
-                'metaboxes'     => $this->_default_espresso_metaboxes,
532
-                'require_nonce' => false,
533
-            ],
534
-            'preview_deletion'       => [
535
-                'nav'           => [
536
-                    'label'      => esc_html__('Preview Deletion', 'event_espresso'),
537
-                    'order'      => 15,
538
-                    'persistent' => false,
539
-                    'url'        => '',
540
-                ],
541
-                'require_nonce' => false,
542
-            ],
543
-        ];
544
-        // only load EE_Event_Editor_Decaf_Tips if domain is not caffeinated
545
-        $domain = $this->loader->getShared('EventEspresso\core\domain\Domain');
546
-        if (! $domain->isCaffeinated()) {
547
-            $this->_page_config['create_new']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
548
-            $this->_page_config['edit']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
549
-        }
550
-    }
551
-
552
-
553
-    /**
554
-     * Used to register any global screen options if necessary for every route in this admin page group.
555
-     */
556
-    protected function _add_screen_options()
557
-    {
558
-    }
559
-
560
-
561
-    /**
562
-     * Implementing the screen options for the 'default' route.
563
-     *
564
-     * @throws InvalidArgumentException
565
-     * @throws InvalidDataTypeException
566
-     * @throws InvalidInterfaceException
567
-     */
568
-    protected function _add_screen_options_default()
569
-    {
570
-        $this->_per_page_screen_option();
571
-    }
572
-
573
-
574
-    /**
575
-     * Implementing screen options for the category list route.
576
-     *
577
-     * @throws InvalidArgumentException
578
-     * @throws InvalidDataTypeException
579
-     * @throws InvalidInterfaceException
580
-     */
581
-    protected function _add_screen_options_category_list()
582
-    {
583
-        $page_title = $this->_admin_page_title;
584
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
585
-        $this->_per_page_screen_option();
586
-        $this->_admin_page_title = $page_title;
587
-    }
588
-
589
-
590
-    /**
591
-     * Used to register any global feature pointers for the admin page group.
592
-     */
593
-    protected function _add_feature_pointers()
594
-    {
595
-    }
596
-
597
-
598
-    /**
599
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
600
-     */
601
-    public function load_scripts_styles()
602
-    {
603
-        wp_register_style(
604
-            'events-admin-css',
605
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
606
-            [],
607
-            EVENT_ESPRESSO_VERSION
608
-        );
609
-        wp_register_style(
610
-            'ee-cat-admin',
611
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
612
-            [],
613
-            EVENT_ESPRESSO_VERSION
614
-        );
615
-        wp_enqueue_style('events-admin-css');
616
-        wp_enqueue_style('ee-cat-admin');
617
-        // scripts
618
-        wp_register_script(
619
-            'event_editor_js',
620
-            EVENTS_ASSETS_URL . 'event_editor.js',
621
-            ['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
622
-            EVENT_ESPRESSO_VERSION,
623
-            true
624
-        );
625
-    }
626
-
627
-
628
-    /**
629
-     * Enqueuing scripts and styles specific to this view
630
-     */
631
-    public function load_scripts_styles_create_new()
632
-    {
633
-        $this->load_scripts_styles_edit();
634
-    }
635
-
636
-
637
-    /**
638
-     * Enqueuing scripts and styles specific to this view
639
-     */
640
-    public function load_scripts_styles_edit()
641
-    {
642
-        // styles
643
-        wp_enqueue_style('espresso-ui-theme');
644
-        wp_register_style(
645
-            'event-editor-css',
646
-            EVENTS_ASSETS_URL . 'event-editor.css',
647
-            ['ee-admin-css'],
648
-            EVENT_ESPRESSO_VERSION
649
-        );
650
-        wp_enqueue_style('event-editor-css');
651
-        // scripts
652
-        if (! $this->admin_config->useAdvancedEditor()) {
653
-            wp_register_script(
654
-                'event-datetime-metabox',
655
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
656
-                ['event_editor_js', 'ee-datepicker'],
657
-                EVENT_ESPRESSO_VERSION
658
-            );
659
-            wp_enqueue_script('event-datetime-metabox');
660
-        }
661
-    }
662
-
663
-
664
-    /**
665
-     * Populating the _views property for the category list table view.
666
-     */
667
-    protected function _set_list_table_views_category_list()
668
-    {
669
-        $this->_views = [
670
-            'all' => [
671
-                'slug'        => 'all',
672
-                'label'       => esc_html__('All', 'event_espresso'),
673
-                'count'       => 0,
674
-                'bulk_action' => [
675
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
676
-                ],
677
-            ],
678
-        ];
679
-    }
680
-
681
-
682
-    /**
683
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
684
-     */
685
-    public function admin_init()
686
-    {
687
-        EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
688
-            'Do you really want to delete this image? Please remember to update your event to complete the removal.',
689
-            'event_espresso'
690
-        );
691
-    }
692
-
693
-
694
-    /**
695
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
696
-     * group.
697
-     */
698
-    public function admin_notices()
699
-    {
700
-    }
701
-
702
-
703
-    /**
704
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
705
-     * this admin page group.
706
-     */
707
-    public function admin_footer_scripts()
708
-    {
709
-    }
710
-
711
-
712
-    /**
713
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
714
-     * warning (via EE_Error::add_error());
715
-     *
716
-     * @param EE_Event $event Event object
717
-     * @param string   $req_type
718
-     * @return void
719
-     * @throws EE_Error
720
-     */
721
-    public function verify_event_edit($event = null, $req_type = '')
722
-    {
723
-        // don't need to do this when processing
724
-        if (! empty($req_type)) {
725
-            return;
726
-        }
727
-        // no event?
728
-        if (! $event instanceof EE_Event) {
729
-            $event = $this->_cpt_model_obj;
730
-        }
731
-        // STILL no event?
732
-        if (! $event instanceof EE_Event) {
733
-            return;
734
-        }
735
-        $orig_status = $event->status();
736
-        // first check if event is active.
737
-        if (
738
-            $orig_status === EEM_Event::cancelled
739
-            || $orig_status === EEM_Event::postponed
740
-            || $event->is_expired()
741
-            || $event->is_inactive()
742
-        ) {
743
-            return;
744
-        }
745
-        // made it here so it IS active... next check that any of the tickets are sold.
746
-        if ($event->is_sold_out(true)) {
747
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
748
-                EE_Error::add_attention(
749
-                    sprintf(
750
-                        esc_html__(
751
-                            'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
752
-                            'event_espresso'
753
-                        ),
754
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
755
-                    )
756
-                );
757
-            }
758
-            return;
759
-        }
760
-        if ($orig_status === EEM_Event::sold_out) {
761
-            EE_Error::add_attention(
762
-                sprintf(
763
-                    esc_html__(
764
-                        'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
765
-                        'event_espresso'
766
-                    ),
767
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
768
-                )
769
-            );
770
-        }
771
-        // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
772
-        if (! $event->tickets_on_sale()) {
773
-            return;
774
-        }
775
-        // made it here so show warning
776
-        $this->_edit_event_warning();
777
-    }
778
-
779
-
780
-    /**
781
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
782
-     * When needed, hook this into a EE_Error::add_error() notice.
783
-     *
784
-     * @return void
785
-     */
786
-    protected function _edit_event_warning()
787
-    {
788
-        // we don't want to add warnings during these requests
789
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
790
-            return;
791
-        }
792
-        EE_Error::add_attention(
793
-            sprintf(
794
-                esc_html__(
795
-                    'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
796
-                    'event_espresso'
797
-                ),
798
-                '<a class="espresso-help-tab-lnk">',
799
-                '</a>'
800
-            )
801
-        );
802
-    }
803
-
804
-
805
-    /**
806
-     * When a user is creating a new event, notify them if they haven't set their timezone.
807
-     * Otherwise, do the normal logic
808
-     *
809
-     * @throws EE_Error
810
-     * @throws InvalidArgumentException
811
-     * @throws InvalidDataTypeException
812
-     */
813
-    protected function _create_new_cpt_item()
814
-    {
815
-        $has_timezone_string = get_option('timezone_string');
816
-        // only nag them about setting their timezone if it's their first event, and they haven't already done it
817
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
818
-            EE_Error::add_attention(
819
-                sprintf(
820
-                    __(
821
-                        'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
822
-                        'event_espresso'
823
-                    ),
824
-                    '<br>',
825
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
826
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
827
-                    . '</select>',
828
-                    '<button class="button button-secondary timezone-submit">',
829
-                    '</button><span class="spinner"></span>'
830
-                ),
831
-                __FILE__,
832
-                __FUNCTION__,
833
-                __LINE__
834
-            );
835
-        }
836
-        parent::_create_new_cpt_item();
837
-    }
838
-
839
-
840
-    /**
841
-     * Sets the _views property for the default route in this admin page group.
842
-     */
843
-    protected function _set_list_table_views_default()
844
-    {
845
-        $this->_views = [
846
-            'all'   => [
847
-                'slug'        => 'all',
848
-                'label'       => esc_html__('View All Events', 'event_espresso'),
849
-                'count'       => 0,
850
-                'bulk_action' => [
851
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
852
-                ],
853
-            ],
854
-            'draft' => [
855
-                'slug'        => 'draft',
856
-                'label'       => esc_html__('Draft', 'event_espresso'),
857
-                'count'       => 0,
858
-                'bulk_action' => [
859
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
860
-                ],
861
-            ],
862
-        ];
863
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
864
-            $this->_views['trash'] = [
865
-                'slug'        => 'trash',
866
-                'label'       => esc_html__('Trash', 'event_espresso'),
867
-                'count'       => 0,
868
-                'bulk_action' => [
869
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
870
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
871
-                ],
872
-            ];
873
-        }
874
-    }
875
-
876
-
877
-    /**
878
-     * Provides the legend item array for the default list table view.
879
-     *
880
-     * @return array
881
-     */
882
-    protected function _event_legend_items()
883
-    {
884
-        $items = [
885
-            'view_details'   => [
886
-                'class' => 'dashicons dashicons-search',
887
-                'desc'  => esc_html__('View Event', 'event_espresso'),
888
-            ],
889
-            'edit_event'     => [
890
-                'class' => 'ee-icon ee-icon-calendar-edit',
891
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
892
-            ],
893
-            'view_attendees' => [
894
-                'class' => 'dashicons dashicons-groups',
895
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
896
-            ],
897
-        ];
898
-        $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
899
-        $statuses = [
900
-            'sold_out_status'  => [
901
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
902
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
903
-            ],
904
-            'active_status'    => [
905
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
906
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
907
-            ],
908
-            'upcoming_status'  => [
909
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
910
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
911
-            ],
912
-            'postponed_status' => [
913
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
914
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
915
-            ],
916
-            'cancelled_status' => [
917
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
918
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
919
-            ],
920
-            'expired_status'   => [
921
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
922
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
923
-            ],
924
-            'inactive_status'  => [
925
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
926
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
927
-            ],
928
-        ];
929
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
930
-        return array_merge($items, $statuses);
931
-    }
932
-
933
-
934
-    /**
935
-     * @return EEM_Event
936
-     * @throws EE_Error
937
-     */
938
-    private function eventModel()
939
-    {
940
-        if (! $this->_event_model instanceof EEM_Event) {
941
-            $this->_event_model = EEM_Event::instance();
942
-        }
943
-        return $this->_event_model;
944
-    }
945
-
946
-
947
-    /**
948
-     * @param string $event_timezone_string
949
-     * @return EEM_Datetime
950
-     * @throws EE_Error
951
-     */
952
-    private function datetimeModel($event_timezone_string = '')
953
-    {
954
-        if (! $this->datetime_model instanceof EEM_Datetime) {
955
-            $this->datetime_model = EEM_Datetime::instance($event_timezone_string);
956
-        }
957
-        return $this->datetime_model;
958
-    }
959
-
960
-
961
-    /**
962
-     * @param string $event_timezone_string
963
-     * @return EEM_Ticket
964
-     * @throws EE_Error
965
-     */
966
-    private function ticketModel($event_timezone_string = '')
967
-    {
968
-        if (! $this->ticket_model instanceof EEM_Ticket) {
969
-            $this->ticket_model = EEM_Ticket::instance($event_timezone_string);
970
-        }
971
-        return $this->ticket_model;
972
-    }
973
-
974
-
975
-    /**
976
-     * Adds extra buttons to the WP CPT permalink field row.
977
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
978
-     *
979
-     * @param string $return    the current html
980
-     * @param int    $id        the post id for the page
981
-     * @param string $new_title What the title is
982
-     * @param string $new_slug  what the slug is
983
-     * @return string            The new html string for the permalink area
984
-     */
985
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
986
-    {
987
-        // make sure this is only when editing
988
-        if (! empty($id)) {
989
-            $post = get_post($id);
990
-            $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
991
-                       . esc_html__('Shortcode', 'event_espresso')
992
-                       . '</a> ';
993
-            $return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
994
-                       . $post->ID
995
-                       . ']">';
996
-        }
997
-        return $return;
998
-    }
999
-
1000
-
1001
-    /**
1002
-     * _events_overview_list_table
1003
-     * This contains the logic for showing the events_overview list
1004
-     *
1005
-     * @return void
1006
-     * @throws DomainException
1007
-     * @throws EE_Error
1008
-     * @throws InvalidArgumentException
1009
-     * @throws InvalidDataTypeException
1010
-     * @throws InvalidInterfaceException
1011
-     */
1012
-    protected function _events_overview_list_table()
1013
-    {
1014
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1015
-        $this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
1016
-            ? (array) $this->_template_args['after_list_table']
1017
-            : [];
1018
-        $this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
1019
-                                                                              . EEH_Template::get_button_or_link(
1020
-                                                                                  get_post_type_archive_link('espresso_events'),
1021
-                                                                                  esc_html__('View Event Archive Page', 'event_espresso'),
1022
-                                                                                  'button'
1023
-                                                                              );
1024
-        $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
1025
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1026
-            'create_new',
1027
-            'add',
1028
-            [],
1029
-            'add-new-h2'
1030
-        );
1031
-        $this->display_admin_list_table_page_with_no_sidebar();
1032
-    }
1033
-
1034
-
1035
-    /**
1036
-     * this allows for extra misc actions in the default WP publish box
1037
-     *
1038
-     * @return void
1039
-     * @throws DomainException
1040
-     * @throws EE_Error
1041
-     * @throws InvalidArgumentException
1042
-     * @throws InvalidDataTypeException
1043
-     * @throws InvalidInterfaceException
1044
-     * @throws ReflectionException
1045
-     */
1046
-    public function extra_misc_actions_publish_box()
1047
-    {
1048
-        $this->_generate_publish_box_extra_content();
1049
-    }
1050
-
1051
-
1052
-    /**
1053
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1054
-     * saved.
1055
-     * Typically you would use this to save any additional data.
1056
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
1057
-     * ALSO very important.  When a post transitions from scheduled to published,
1058
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1059
-     * other meta saves. So MAKE sure that you handle this accordingly.
1060
-     *
1061
-     * @abstract
1062
-     * @param string $post_id The ID of the cpt that was saved (so you can link relationally)
1063
-     * @param object $post    The post object of the cpt that was saved.
1064
-     * @return void
1065
-     * @throws EE_Error
1066
-     * @throws InvalidArgumentException
1067
-     * @throws InvalidDataTypeException
1068
-     * @throws InvalidInterfaceException
1069
-     * @throws ReflectionException
1070
-     */
1071
-    protected function _insert_update_cpt_item($post_id, $post)
1072
-    {
1073
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1074
-            // get out we're not processing an event save.
1075
-            return;
1076
-        }
1077
-        $event_values = [
1078
-            'EVT_member_only'     => ! empty($this->_req_data['member_only']) ? 1 : 0,
1079
-            'EVT_allow_overflow'  => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
1080
-            'EVT_timezone_string' => ! empty($this->_req_data['timezone_string'])
1081
-                ? sanitize_text_field($this->_req_data['timezone_string'])
1082
-                : null,
1083
-        ];
1084
-        /** @var FeatureFlags $flags */
1085
-        $flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1086
-        // check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1087
-        if (! $this->admin_config->useAdvancedEditor() || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1088
-            $event_values['EVT_display_ticket_selector'] =
1089
-                ! empty($this->_req_data['display_ticket_selector'])
1090
-                    ? 1
1091
-                    : 0;
1092
-            $event_values['EVT_additional_limit'] = min(
1093
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1094
-                ! empty($this->_req_data['additional_limit'])
1095
-                    ? absint($this->_req_data['additional_limit'])
1096
-                    : null
1097
-            );
1098
-            $event_values['EVT_default_registration_status'] =
1099
-                ! empty($this->_req_data['EVT_default_registration_status'])
1100
-                    ? sanitize_text_field($this->_req_data['EVT_default_registration_status'])
1101
-                    : EE_Registry::instance()->CFG->registration->default_STS_ID;
1102
-            $event_values['EVT_external_URL'] = ! empty($this->_req_data['externalURL'])
1103
-                ? esc_url_raw($this->_req_data['externalURL'])
1104
-                : null;
1105
-            $event_values['EVT_phone'] = ! empty($this->_req_data['event_phone'])
1106
-                ? sanitize_text_field($this->_req_data['event_phone'])
1107
-                : null;
1108
-        }
1109
-        // update event
1110
-        $success = $this->eventModel()->update_by_ID($event_values, $post_id);
1111
-        // get event_object for other metaboxes...
1112
-        // though it would seem to make sense to just use $this->eventModel()->get_one_by_ID( $post_id )..
1113
-        // i have to setup where conditions to override the filters in the model
1114
-        // that filter out autodraft and inherit statuses so we GET the inherit id!
1115
-        $get_one_where = [
1116
-            $this->eventModel()->primary_key_name() => $post_id,
1117
-            'OR'                                    => [
1118
-                'status'   => $post->post_status,
1119
-                // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1120
-                // but the returned object here has a status of "publish", so use the original post status as well
1121
-                'status*1' => $this->_req_data['original_post_status'],
1122
-            ],
1123
-        ];
1124
-        $event = $this->eventModel()->get_one([$get_one_where]);
1125
-        // the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1126
-        $event_update_callbacks = apply_filters(
1127
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1128
-            [
1129
-                [$this, '_default_venue_update'],
1130
-                [$this, '_default_tickets_update'],
1131
-            ]
1132
-        );
1133
-        $att_success = true;
1134
-        foreach ($event_update_callbacks as $e_callback) {
1135
-            $_success = is_callable($e_callback)
1136
-                ? $e_callback($event, $this->_req_data)
1137
-                : false;
1138
-            // if ANY of these updates fail then we want the appropriate global error message
1139
-            $att_success = ! $att_success ? $att_success : $_success;
1140
-        }
1141
-        // any errors?
1142
-        if ($success && false === $att_success) {
1143
-            EE_Error::add_error(
1144
-                esc_html__(
1145
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1146
-                    'event_espresso'
1147
-                ),
1148
-                __FILE__,
1149
-                __FUNCTION__,
1150
-                __LINE__
1151
-            );
1152
-        } elseif ($success === false) {
1153
-            EE_Error::add_error(
1154
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1155
-                __FILE__,
1156
-                __FUNCTION__,
1157
-                __LINE__
1158
-            );
1159
-        }
1160
-    }
1161
-
1162
-
1163
-    /**
1164
-     * @param int $post_id
1165
-     * @param int $revision_id
1166
-     * @throws EE_Error
1167
-     * @throws InvalidArgumentException
1168
-     * @throws InvalidDataTypeException
1169
-     * @throws InvalidInterfaceException
1170
-     * @throws ReflectionException
1171
-     * @see parent::restore_item()
1172
-     */
1173
-    protected function _restore_cpt_item($post_id, $revision_id)
1174
-    {
1175
-        // copy existing event meta to new post
1176
-        $post_evt = $this->eventModel()->get_one_by_ID($post_id);
1177
-        if ($post_evt instanceof EE_Event) {
1178
-            // meta revision restore
1179
-            $post_evt->restore_revision($revision_id);
1180
-            // related objs restore
1181
-            $post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1182
-        }
1183
-    }
1184
-
1185
-
1186
-    /**
1187
-     * Attach the venue to the Event
1188
-     *
1189
-     * @param EE_Event $evtobj Event Object to add the venue to
1190
-     * @param array    $data   The request data from the form
1191
-     * @return bool           Success or fail.
1192
-     * @throws EE_Error
1193
-     * @throws InvalidArgumentException
1194
-     * @throws InvalidDataTypeException
1195
-     * @throws InvalidInterfaceException
1196
-     * @throws ReflectionException
1197
-     */
1198
-    protected function _default_venue_update(EE_Event $evtobj, $data)
1199
-    {
1200
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1201
-        $venue_model = EEM_Venue::instance();
1202
-        $rows_affected = null;
1203
-        $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1204
-        // very important.  If we don't have a venue name...
1205
-        // then we'll get out because not necessary to create empty venue
1206
-        if (empty($data['venue_title'])) {
1207
-            return false;
1208
-        }
1209
-        $venue_array = [
1210
-            'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1211
-            'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1212
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1213
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1214
-            'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1215
-                : null,
1216
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1217
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1218
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1219
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1220
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1221
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1222
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1223
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1224
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1225
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1226
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1227
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1228
-            'status'              => 'publish',
1229
-        ];
1230
-        // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1231
-        if (! empty($venue_id)) {
1232
-            $update_where = [$venue_model->primary_key_name() => $venue_id];
1233
-            $rows_affected = $venue_model->update($venue_array, [$update_where]);
1234
-            // we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1235
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1236
-            return $rows_affected > 0;
1237
-        }
1238
-        // we insert the venue
1239
-        $venue_id = $venue_model->insert($venue_array);
1240
-        $evtobj->_add_relation_to($venue_id, 'Venue');
1241
-        return ! empty($venue_id) ? true : false;
1242
-        // when we have the ancestor come in it's already been handled by the revision save.
1243
-    }
1244
-
1245
-
1246
-    /**
1247
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1248
-     *
1249
-     * @param EE_Event $evtobj The Event object we're attaching data to
1250
-     * @param array    $data   The request data from the form
1251
-     * @return array
1252
-     * @throws EE_Error
1253
-     * @throws InvalidArgumentException
1254
-     * @throws InvalidDataTypeException
1255
-     * @throws InvalidInterfaceException
1256
-     * @throws ReflectionException
1257
-     * @throws Exception
1258
-     */
1259
-    protected function _default_tickets_update(EE_Event $evtobj, $data)
1260
-    {
1261
-        if ($this->admin_config->useAdvancedEditor()) {
1262
-            return [];
1263
-        }
1264
-        $saved_dtt = null;
1265
-        $saved_tickets = [];
1266
-        $incoming_date_formats = ['Y-m-d', 'h:i a'];
1267
-        $event_timezone_string = $evtobj->get_timezone();
1268
-        $event_timezone = new DateTimeZone($event_timezone_string);
1269
-        // let's use now in the set timezone.
1270
-        $now = new DateTime('now', $event_timezone);
1271
-        foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1272
-            // trim all values to ensure any excess whitespace is removed.
1273
-            $dtt = array_map('trim', $dtt);
1274
-            $dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end'])
1275
-                ? $dtt['DTT_EVT_end']
1276
-                : $dtt['DTT_EVT_start'];
1277
-            $datetime_values = [
1278
-                'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1279
-                'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1280
-                'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1281
-                'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1282
-                'DTT_order'     => $row,
1283
-            ];
1284
-            // if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1285
-            if (! empty($dtt['DTT_ID'])) {
1286
-                $DTM = $this->datetimeModel($event_timezone_string)->get_one_by_ID($dtt['DTT_ID']);
1287
-                $DTM->set_date_format($incoming_date_formats[0]);
1288
-                $DTM->set_time_format($incoming_date_formats[1]);
1289
-                foreach ($datetime_values as $field => $value) {
1290
-                    $DTM->set($field, $value);
1291
-                }
1292
-                // make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1293
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1294
-            } else {
1295
-                $DTM = EE_Registry::instance()->load_class(
1296
-                    'Datetime',
1297
-                    [$datetime_values, $event_timezone_string, $incoming_date_formats],
1298
-                    false,
1299
-                    false
1300
-                );
1301
-                foreach ($datetime_values as $field => $value) {
1302
-                    $DTM->set($field, $value);
1303
-                }
1304
-            }
1305
-            $DTM->save();
1306
-            $DTM = $evtobj->_add_relation_to($DTM, 'Datetime');
1307
-            // load DTT helper
1308
-            // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1309
-            if ($DTM->get_raw('DTT_EVT_start') > $DTM->get_raw('DTT_EVT_end')) {
1310
-                $DTM->set('DTT_EVT_end', $DTM->get('DTT_EVT_start'));
1311
-                $DTM = EEH_DTT_Helper::date_time_add($DTM, 'DTT_EVT_end', 'days');
1312
-                $DTM->save();
1313
-            }
1314
-            // now we got to make sure we add the new DTT_ID to the $saved_dtts array
1315
-            //  because it is possible there was a new one created for the autosave.
1316
-            $saved_dtt = $DTM;
1317
-            // if ANY of these updates fail then we want the appropriate global error message.
1318
-            // //todo this is actually sucky we need a better error message but this is what it is for now.
1319
-        }
1320
-        // no dtts get deleted so we don't do any of that logic here.
1321
-        // update tickets next
1322
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1323
-        foreach ($data['edit_tickets'] as $row => $tkt) {
1324
-            $incoming_date_formats = ['Y-m-d', 'h:i a'];
1325
-            $update_prices = false;
1326
-            $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1327
-                ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1328
-            // trim inputs to ensure any excess whitespace is removed.
1329
-            $tkt = array_map('trim', $tkt);
1330
-            if (empty($tkt['TKT_start_date'])) {
1331
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1332
-            }
1333
-            if (empty($tkt['TKT_end_date'])) {
1334
-                // use the start date of the first datetime
1335
-                $dtt = $evtobj->first_datetime();
1336
-                $tkt['TKT_end_date'] = $dtt->start_date_and_time(
1337
-                    $incoming_date_formats[0],
1338
-                    $incoming_date_formats[1]
1339
-                );
1340
-            }
1341
-            $TKT_values = [
1342
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1343
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1344
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1345
-                'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1346
-                'TKT_start_date'  => $tkt['TKT_start_date'],
1347
-                'TKT_end_date'    => $tkt['TKT_end_date'],
1348
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1349
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1350
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1351
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1352
-                'TKT_row'         => $row,
1353
-                'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1354
-                'TKT_price'       => $ticket_price,
1355
-            ];
1356
-            // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1357
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1358
-                $TKT_values['TKT_ID'] = 0;
1359
-                $TKT_values['TKT_is_default'] = 0;
1360
-                $TKT_values['TKT_price'] = $ticket_price;
1361
-                $update_prices = true;
1362
-            }
1363
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1364
-            // we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1365
-            // keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1366
-            if (! empty($tkt['TKT_ID'])) {
1367
-                $TKT = $this->ticketModel($event_timezone_string)->get_one_by_ID($tkt['TKT_ID']);
1368
-                if ($TKT instanceof EE_Ticket) {
1369
-                    $ticket_sold = $TKT->count_related(
1370
-                        'Registration',
1371
-                        [
1372
-                                [
1373
-                                    'STS_ID' => [
1374
-                                        'NOT IN',
1375
-                                        [EEM_Registration::status_id_incomplete],
1376
-                                    ],
1377
-                                ],
1378
-                            ]
1379
-                    ) > 0;
1380
-                    // let's just check the total price for the existing ticket and determine if it matches the new
1381
-                    // total price.  if they are different then we create a new ticket (if tickets sold)
1382
-                    // if they aren't different then we go ahead and modify existing ticket.
1383
-                    $create_new_TKT = $ticket_sold && ! $TKT->deleted()
1384
-                                      && EEH_Money::compare_floats(
1385
-                                          $ticket_price,
1386
-                                          $TKT->get('TKT_price'),
1387
-                                          '!=='
1388
-                                      );
1389
-                    $TKT->set_date_format($incoming_date_formats[0]);
1390
-                    $TKT->set_time_format($incoming_date_formats[1]);
1391
-                    // set new values
1392
-                    foreach ($TKT_values as $field => $value) {
1393
-                        if ($field === 'TKT_qty') {
1394
-                            $TKT->set_qty($value);
1395
-                        } else {
1396
-                            $TKT->set($field, $value);
1397
-                        }
1398
-                    }
1399
-                    // if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1400
-                    if ($create_new_TKT) {
1401
-                        // archive the old ticket first
1402
-                        $TKT->set('TKT_deleted', 1);
1403
-                        $TKT->save();
1404
-                        // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1405
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1406
-                        // create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1407
-                        $TKT = clone $TKT;
1408
-                        $TKT->set('TKT_ID', 0);
1409
-                        $TKT->set('TKT_deleted', 0);
1410
-                        $TKT->set('TKT_price', $ticket_price);
1411
-                        $TKT->set('TKT_sold', 0);
1412
-                        // now we need to make sure that $new prices are created as well and attached to new ticket.
1413
-                        $update_prices = true;
1414
-                    }
1415
-                    // make sure price is set if it hasn't been already
1416
-                    $TKT->set('TKT_price', $ticket_price);
1417
-                }
1418
-            } else {
1419
-                // no TKT_id so a new TKT
1420
-                $TKT_values['TKT_price'] = $ticket_price;
1421
-                $TKT = EE_Registry::instance()->load_class('Ticket', [$TKT_values], false, false);
1422
-                if ($TKT instanceof EE_Ticket) {
1423
-                    // need to reset values to properly account for the date formats
1424
-                    $TKT->set_date_format($incoming_date_formats[0]);
1425
-                    $TKT->set_time_format($incoming_date_formats[1]);
1426
-                    $TKT->set_timezone($evtobj->get_timezone());
1427
-                    // set new values
1428
-                    foreach ($TKT_values as $field => $value) {
1429
-                        if ($field === 'TKT_qty') {
1430
-                            $TKT->set_qty($value);
1431
-                        } else {
1432
-                            $TKT->set($field, $value);
1433
-                        }
1434
-                    }
1435
-                    $update_prices = true;
1436
-                }
1437
-            }
1438
-            // cap ticket qty by datetime reg limits
1439
-            $TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1440
-            // update ticket.
1441
-            $TKT->save();
1442
-            // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1443
-            if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1444
-                $TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1445
-                $TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1446
-                $TKT->save();
1447
-            }
1448
-            // initially let's add the ticket to the dtt
1449
-            $saved_dtt->_add_relation_to($TKT, 'Ticket');
1450
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1451
-            // add prices to ticket
1452
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1453
-        }
1454
-        // however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1455
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1456
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1457
-        foreach ($tickets_removed as $id) {
1458
-            $id = absint($id);
1459
-            // get the ticket for this id
1460
-            $tkt_to_remove = $this->ticketModel($event_timezone_string)->get_one_by_ID($id);
1461
-            // need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1462
-            $dtts = $tkt_to_remove->get_many_related('Datetime');
1463
-            foreach ($dtts as $dtt) {
1464
-                $tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1465
-            }
1466
-            // need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1467
-            $tkt_to_remove->delete_related_permanently('Price');
1468
-            // finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1469
-            $tkt_to_remove->delete_permanently();
1470
-        }
1471
-        return [$saved_dtt, $saved_tickets];
1472
-    }
1473
-
1474
-
1475
-    /**
1476
-     * This attaches a list of given prices to a ticket.
1477
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1478
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1479
-     * price info and prices are automatically "archived" via the ticket.
1480
-     *
1481
-     * @param array     $prices     Array of prices from the form.
1482
-     * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1483
-     * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1484
-     * @return  void
1485
-     * @throws EE_Error
1486
-     * @throws InvalidArgumentException
1487
-     * @throws InvalidDataTypeException
1488
-     * @throws InvalidInterfaceException
1489
-     * @throws ReflectionException
1490
-     */
1491
-    private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1492
-    {
1493
-        foreach ($prices as $row => $prc) {
1494
-            $PRC_values = [
1495
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1496
-                'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1497
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1498
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1499
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1500
-                'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1501
-                'PRC_order'      => $row,
1502
-            ];
1503
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
1504
-                $PRC_values['PRC_ID'] = 0;
1505
-                $PRC = EE_Registry::instance()->load_class('Price', [$PRC_values], false, false);
1506
-            } else {
1507
-                $PRC = EEM_Price::instance()->get_one_by_ID($prc['PRC_ID']);
1508
-                // update this price with new values
1509
-                foreach ($PRC_values as $field => $newprc) {
1510
-                    $PRC->set($field, $newprc);
1511
-                }
1512
-                $PRC->save();
1513
-            }
1514
-            $ticket->_add_relation_to($PRC, 'Price');
1515
-        }
1516
-    }
1517
-
1518
-
1519
-    /**
1520
-     * Add in our autosave ajax handlers
1521
-     *
1522
-     */
1523
-    protected function _ee_autosave_create_new()
1524
-    {
1525
-    }
1526
-
1527
-
1528
-    /**
1529
-     * More autosave handlers.
1530
-     */
1531
-    protected function _ee_autosave_edit()
1532
-    {
1533
-    }
1534
-
1535
-
1536
-    /**
1537
-     *    _generate_publish_box_extra_content
1538
-     *
1539
-     * @throws DomainException
1540
-     * @throws EE_Error
1541
-     * @throws InvalidArgumentException
1542
-     * @throws InvalidDataTypeException
1543
-     * @throws InvalidInterfaceException
1544
-     * @throws ReflectionException
1545
-     */
1546
-    private function _generate_publish_box_extra_content()
1547
-    {
1548
-        // load formatter helper
1549
-        // args for getting related registrations
1550
-        $approved_query_args = [
1551
-            [
1552
-                'REG_deleted' => 0,
1553
-                'STS_ID'      => EEM_Registration::status_id_approved,
1554
-            ],
1555
-        ];
1556
-        $not_approved_query_args = [
1557
-            [
1558
-                'REG_deleted' => 0,
1559
-                'STS_ID'      => EEM_Registration::status_id_not_approved,
1560
-            ],
1561
-        ];
1562
-        $pending_payment_query_args = [
1563
-            [
1564
-                'REG_deleted' => 0,
1565
-                'STS_ID'      => EEM_Registration::status_id_pending_payment,
1566
-            ],
1567
-        ];
1568
-        // publish box
1569
-        $publish_box_extra_args = [
1570
-            'view_approved_reg_url'        => add_query_arg(
1571
-                [
1572
-                    'action'      => 'default',
1573
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1574
-                    '_reg_status' => EEM_Registration::status_id_approved,
1575
-                ],
1576
-                REG_ADMIN_URL
1577
-            ),
1578
-            'view_not_approved_reg_url'    => add_query_arg(
1579
-                [
1580
-                    'action'      => 'default',
1581
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1582
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1583
-                ],
1584
-                REG_ADMIN_URL
1585
-            ),
1586
-            'view_pending_payment_reg_url' => add_query_arg(
1587
-                [
1588
-                    'action'      => 'default',
1589
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1590
-                    '_reg_status' => EEM_Registration::status_id_pending_payment,
1591
-                ],
1592
-                REG_ADMIN_URL
1593
-            ),
1594
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1595
-                'Registration',
1596
-                $approved_query_args
1597
-            ),
1598
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1599
-                'Registration',
1600
-                $not_approved_query_args
1601
-            ),
1602
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1603
-                'Registration',
1604
-                $pending_payment_query_args
1605
-            ),
1606
-            'misc_pub_section_class'       => apply_filters(
1607
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1608
-                'misc-pub-section'
1609
-            ),
1610
-        ];
1611
-        ob_start();
1612
-        do_action(
1613
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1614
-            $this->_cpt_model_obj
1615
-        );
1616
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1617
-        // load template
1618
-        EEH_Template::display_template(
1619
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1620
-            $publish_box_extra_args
1621
-        );
1622
-    }
1623
-
1624
-
1625
-    /**
1626
-     * @return EE_Event
1627
-     */
1628
-    public function get_event_object()
1629
-    {
1630
-        return $this->_cpt_model_obj;
1631
-    }
1632
-
1633
-
1634
-
1635
-
1636
-    /** METABOXES * */
1637
-    /**
1638
-     * _register_event_editor_meta_boxes
1639
-     * add all metaboxes related to the event_editor
1640
-     *
1641
-     * @return void
1642
-     * @throws EE_Error
1643
-     * @throws InvalidArgumentException
1644
-     * @throws InvalidDataTypeException
1645
-     * @throws InvalidInterfaceException
1646
-     * @throws ReflectionException
1647
-     */
1648
-    protected function _register_event_editor_meta_boxes()
1649
-    {
1650
-        $this->verify_cpt_object();
1651
-        $use_advanced_editor = $this->admin_config->useAdvancedEditor();
1652
-        /** @var FeatureFlags $flags */
1653
-        $flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1654
-        // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1655
-        if (! $use_advanced_editor || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1656
-            add_meta_box(
1657
-                'espresso_event_editor_event_options',
1658
-                esc_html__('Event Registration Options', 'event_espresso'),
1659
-                [$this, 'registration_options_meta_box'],
1660
-                $this->page_slug,
1661
-                'side'
1662
-            );
1663
-        }
1664
-        if (! $use_advanced_editor) {
1665
-            add_meta_box(
1666
-                'espresso_event_editor_tickets',
1667
-                esc_html__('Event Datetime & Ticket', 'event_espresso'),
1668
-                [$this, 'ticket_metabox'],
1669
-                $this->page_slug,
1670
-                'normal',
1671
-                'high'
1672
-            );
1673
-        } else {
1674
-            if ($flags->featureAllowed('use_reg_options_meta_box')) {
1675
-                add_action(
1676
-                    'add_meta_boxes_espresso_events',
1677
-                    function () {
1678
-                        global $current_screen;
1679
-                        remove_meta_box('authordiv', $current_screen, 'normal');
1680
-                    },
1681
-                    99
1682
-                );
1683
-            }
1684
-        }
1685
-        // NOTE: if you're looking for other metaboxes in here,
1686
-        // where a metabox has a related management page in the admin
1687
-        // you will find it setup in the related management page's "_Hooks" file.
1688
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1689
-    }
1690
-
1691
-
1692
-    /**
1693
-     * @throws DomainException
1694
-     * @throws EE_Error
1695
-     * @throws InvalidArgumentException
1696
-     * @throws InvalidDataTypeException
1697
-     * @throws InvalidInterfaceException
1698
-     * @throws ReflectionException
1699
-     */
1700
-    public function ticket_metabox()
1701
-    {
1702
-        $existing_datetime_ids = $existing_ticket_ids = [];
1703
-        // defaults for template args
1704
-        $template_args = [
1705
-            'existing_datetime_ids'    => '',
1706
-            'event_datetime_help_link' => '',
1707
-            'ticket_options_help_link' => '',
1708
-            'time'                     => null,
1709
-            'ticket_rows'              => '',
1710
-            'existing_ticket_ids'      => '',
1711
-            'total_ticket_rows'        => 1,
1712
-            'ticket_js_structure'      => '',
1713
-            'trash_icon'               => 'ee-lock-icon',
1714
-            'disabled'                 => '',
1715
-        ];
1716
-        $event_id = $this->_cpt_model_obj instanceof EE_Event ? $this->_cpt_model_obj->ID() : 0;
1717
-        $event_timezone_string = $this->_cpt_model_obj instanceof EE_Event
1718
-            ? $this->_cpt_model_obj->timezone_string()
1719
-            : '';
1720
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1721
-        /**
1722
-         * 1. Start with retrieving Datetimes
1723
-         * 2. Fore each datetime get related tickets
1724
-         * 3. For each ticket get related prices
1725
-         */
1726
-        $times = $this->datetimeModel($event_timezone_string)->get_all_event_dates($event_id);
1727
-        /** @type EE_Datetime $first_datetime */
1728
-        $first_datetime = reset($times);
1729
-        // do we get related tickets?
1730
-        if (
1731
-            $first_datetime instanceof EE_Datetime
1732
-            && $first_datetime->ID() !== 0
1733
-        ) {
1734
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1735
-            $template_args['time'] = $first_datetime;
1736
-            $related_tickets = $first_datetime->tickets(
1737
-                [
1738
-                    ['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1739
-                    'default_where_conditions' => 'none',
1740
-                ]
1741
-            );
1742
-            if (! empty($related_tickets)) {
1743
-                $template_args['total_ticket_rows'] = count($related_tickets);
1744
-                $row = 0;
1745
-                foreach ($related_tickets as $ticket) {
1746
-                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1747
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1748
-                    $row++;
1749
-                }
1750
-            } else {
1751
-                $template_args['total_ticket_rows'] = 1;
1752
-                /** @type EE_Ticket $ticket */
1753
-                $ticket = $this->ticketModel($event_timezone_string)->create_default_object();
1754
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1755
-            }
1756
-        } else {
1757
-            $template_args['time'] = $times[0];
1758
-            /** @type EE_Ticket $ticket */
1759
-            $ticket = $this->ticketModel($event_timezone_string)->get_all_default_tickets();
1760
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1761
-            // NOTE: we're just sending the first default row
1762
-            // (decaf can't manage default tickets so this should be sufficient);
1763
-        }
1764
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1765
-            'event_editor_event_datetimes_help_tab'
1766
-        );
1767
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1768
-        $template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1769
-        $template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1770
-        $template_args['ticket_js_structure'] = $this->_get_ticket_row(
1771
-            $this->ticketModel($event_timezone_string)->create_default_object(),
1772
-            true
1773
-        );
1774
-        $template = apply_filters(
1775
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1776
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1777
-        );
1778
-        EEH_Template::display_template($template, $template_args);
1779
-    }
1780
-
1781
-
1782
-    /**
1783
-     * Setup an individual ticket form for the decaf event editor page
1784
-     *
1785
-     * @param EE_Ticket $ticket   the ticket object
1786
-     * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1787
-     * @param int       $row
1788
-     * @return string generated html for the ticket row.
1789
-     * @throws DomainException
1790
-     * @throws EE_Error
1791
-     * @throws InvalidArgumentException
1792
-     * @throws InvalidDataTypeException
1793
-     * @throws InvalidInterfaceException
1794
-     * @throws ReflectionException
1795
-     */
1796
-    private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1797
-    {
1798
-        $template_args = [
1799
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1800
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1801
-                : '',
1802
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1803
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1804
-            'TKT_name'            => $ticket->get('TKT_name'),
1805
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1806
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1807
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1808
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1809
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1810
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1811
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1812
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1813
-                ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1814
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1815
-                : ' disabled=disabled',
1816
-        ];
1817
-        $price = $ticket->ID() !== 0
1818
-            ? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1819
-            : EEM_Price::instance()->create_default_object();
1820
-        $price_args = [
1821
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1822
-            'PRC_amount'            => $price->get('PRC_amount'),
1823
-            'PRT_ID'                => $price->get('PRT_ID'),
1824
-            'PRC_ID'                => $price->get('PRC_ID'),
1825
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1826
-        ];
1827
-        // make sure we have default start and end dates if skeleton
1828
-        // handle rows that should NOT be empty
1829
-        if (empty($template_args['TKT_start_date'])) {
1830
-            // if empty then the start date will be now.
1831
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1832
-        }
1833
-        if (empty($template_args['TKT_end_date'])) {
1834
-            // get the earliest datetime (if present);
1835
-            $earliest_dtt = $this->_cpt_model_obj->ID() > 0
1836
-                ? $this->_cpt_model_obj->get_first_related(
1837
-                    'Datetime',
1838
-                    ['order_by' => ['DTT_EVT_start' => 'ASC']]
1839
-                )
1840
-                : null;
1841
-            if (! empty($earliest_dtt)) {
1842
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1843
-            } else {
1844
-                $template_args['TKT_end_date'] = date(
1845
-                    'Y-m-d h:i a',
1846
-                    mktime(0, 0, 0, date('m'), date('d') + 7, date('Y'))
1847
-                );
1848
-            }
1849
-        }
1850
-        $template_args = array_merge($template_args, $price_args);
1851
-        $template = apply_filters(
1852
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1853
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1854
-            $ticket
1855
-        );
1856
-        return EEH_Template::display_template($template, $template_args, true);
1857
-    }
1858
-
1859
-
1860
-    /**
1861
-     * @throws DomainException
1862
-     * @throws EE_Error
1863
-     */
1864
-    public function registration_options_meta_box()
1865
-    {
1866
-        $yes_no_values = [
1867
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1868
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1869
-        ];
1870
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1871
-            [
1872
-                EEM_Registration::status_id_cancelled,
1873
-                EEM_Registration::status_id_declined,
1874
-                EEM_Registration::status_id_incomplete,
1875
-            ],
1876
-            true
1877
-        );
1878
-        // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1879
-        $template_args['_event'] = $this->_cpt_model_obj;
1880
-        $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1881
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1882
-        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1883
-            'default_reg_status',
1884
-            $default_reg_status_values,
1885
-            $this->_cpt_model_obj->default_registration_status()
1886
-        );
1887
-        $template_args['display_description'] = EEH_Form_Fields::select_input(
1888
-            'display_desc',
1889
-            $yes_no_values,
1890
-            $this->_cpt_model_obj->display_description()
1891
-        );
1892
-        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1893
-            'display_ticket_selector',
1894
-            $yes_no_values,
1895
-            $this->_cpt_model_obj->display_ticket_selector(),
1896
-            '',
1897
-            '',
1898
-            false
1899
-        );
1900
-        $template_args['additional_registration_options'] = apply_filters(
1901
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1902
-            '',
1903
-            $template_args,
1904
-            $yes_no_values,
1905
-            $default_reg_status_values
1906
-        );
1907
-        EEH_Template::display_template(
1908
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1909
-            $template_args
1910
-        );
1911
-    }
1912
-
1913
-
1914
-    /**
1915
-     * _get_events()
1916
-     * This method simply returns all the events (for the given _view and paging)
1917
-     *
1918
-     * @param int  $per_page     count of items per page (20 default);
1919
-     * @param int  $current_page what is the current page being viewed.
1920
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1921
-     *                           If FALSE then we return an array of event objects
1922
-     *                           that match the given _view and paging parameters.
1923
-     * @return array|int         an array of event objects or count of how many events.
1924
-     * @throws EE_Error
1925
-     * @throws InvalidArgumentException
1926
-     * @throws InvalidDataTypeException
1927
-     * @throws InvalidInterfaceException
1928
-     * @throws ReflectionException
1929
-     * @throws Exception
1930
-     * @throws Exception
1931
-     * @throws Exception
1932
-     */
1933
-    public function get_events($per_page = 10, $current_page = 1, $count = false)
1934
-    {
1935
-        $EEME = $this->eventModel();
1936
-        $offset = ($current_page - 1) * $per_page;
1937
-        $limit = $count ? null : $offset . ',' . $per_page;
1938
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1939
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1940
-        if (isset($this->_req_data['month_range'])) {
1941
-            $pieces = explode(' ', $this->_req_data['month_range'], 3);
1942
-            // simulate the FIRST day of the month, that fixes issues for months like February
1943
-            // where PHP doesn't know what to assume for date.
1944
-            // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1945
-            $month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1946
-            $year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1947
-        }
1948
-        $where = [];
1949
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1950
-        // determine what post_status our condition will have for the query.
1951
-        switch ($status) {
1952
-            case 'month':
1953
-            case 'today':
1954
-            case null:
1955
-            case 'all':
1956
-                break;
1957
-            case 'draft':
1958
-                $where['status'] = ['IN', ['draft', 'auto-draft']];
1959
-                break;
1960
-            default:
1961
-                $where['status'] = $status;
1962
-        }
1963
-        // categories?
1964
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1965
-            ? $this->_req_data['EVT_CAT'] : null;
1966
-        if (! empty($category)) {
1967
-            $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1968
-            $where['Term_Taxonomy.term_id'] = $category;
1969
-        }
1970
-        // date where conditions
1971
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1972
-        if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] !== '') {
1973
-            $DateTime = new DateTime(
1974
-                $year_r . '-' . $month_r . '-01 00:00:00',
1975
-                new DateTimeZone('UTC')
1976
-            );
1977
-            $start = $DateTime->getTimestamp();
1978
-            // set the datetime to be the end of the month
1979
-            $DateTime->setDate(
1980
-                $year_r,
1981
-                $month_r,
1982
-                $DateTime->format('t')
1983
-            )->setTime(23, 59, 59);
1984
-            $end = $DateTime->getTimestamp();
1985
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1986
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'today') {
1987
-            $DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1988
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1989
-            $end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1990
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1991
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'month') {
1992
-            $now = date('Y-m-01');
1993
-            $DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1994
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1995
-            $end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1996
-                            ->setTime(23, 59, 59)
1997
-                            ->format(implode(' ', $start_formats));
1998
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1999
-        }
2000
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
2001
-            $where['EVT_wp_user'] = get_current_user_id();
2002
-        } elseif (
2003
-            ! isset($where['status'])
2004
-                  && ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')
2005
-        ) {
2006
-            $where['OR'] = [
2007
-                'status*restrict_private' => ['!=', 'private'],
2008
-                'AND'                     => [
2009
-                    'status*inclusive' => ['=', 'private'],
2010
-                    'EVT_wp_user'      => get_current_user_id(),
2011
-                ],
2012
-            ];
2013
-        }
2014
-
2015
-        if (
2016
-            isset($this->_req_data['EVT_wp_user'])
2017
-            && (int) $this->_req_data['EVT_wp_user'] !== (int) get_current_user_id()
2018
-            && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
2019
-        ) {
2020
-            $where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
2021
-        }
2022
-        // search query handling
2023
-        if (isset($this->_req_data['s'])) {
2024
-            $search_string = '%' . $this->_req_data['s'] . '%';
2025
-            $where['OR'] = [
2026
-                'EVT_name'       => ['LIKE', $search_string],
2027
-                'EVT_desc'       => ['LIKE', $search_string],
2028
-                'EVT_short_desc' => ['LIKE', $search_string],
2029
-            ];
2030
-        }
2031
-        // filter events by venue.
2032
-        if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
2033
-            $where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
2034
-        }
2035
-        $where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
2036
-        $query_params = apply_filters(
2037
-            'FHEE__Events_Admin_Page__get_events__query_params',
2038
-            [
2039
-                $where,
2040
-                'limit'    => $limit,
2041
-                'order_by' => $orderby,
2042
-                'order'    => $order,
2043
-                'group_by' => 'EVT_ID',
2044
-            ],
2045
-            $this->_req_data
2046
-        );
2047
-
2048
-        // let's first check if we have special requests coming in.
2049
-        if (isset($this->_req_data['active_status'])) {
2050
-            switch ($this->_req_data['active_status']) {
2051
-                case 'upcoming':
2052
-                    return $EEME->get_upcoming_events($query_params, $count);
2053
-                    break;
2054
-                case 'expired':
2055
-                    return $EEME->get_expired_events($query_params, $count);
2056
-                    break;
2057
-                case 'active':
2058
-                    return $EEME->get_active_events($query_params, $count);
2059
-                    break;
2060
-                case 'inactive':
2061
-                    return $EEME->get_inactive_events($query_params, $count);
2062
-                    break;
2063
-            }
2064
-        }
2065
-        return $count
2066
-            ? $EEME->count([$where], 'EVT_ID', true)
2067
-            : $EEME->get_all($query_params);
2068
-    }
2069
-
2070
-
2071
-    /**
2072
-     * handling for WordPress CPT actions (trash, restore, delete)
2073
-     *
2074
-     * @param string $post_id
2075
-     * @throws EE_Error
2076
-     * @throws InvalidArgumentException
2077
-     * @throws InvalidDataTypeException
2078
-     * @throws InvalidInterfaceException
2079
-     * @throws ReflectionException
2080
-     */
2081
-    public function trash_cpt_item($post_id)
2082
-    {
2083
-        $this->_req_data['EVT_ID'] = $post_id;
2084
-        $this->_trash_or_restore_event('trash', false);
2085
-    }
2086
-
2087
-
2088
-    /**
2089
-     * @param string $post_id
2090
-     * @throws EE_Error
2091
-     * @throws InvalidArgumentException
2092
-     * @throws InvalidDataTypeException
2093
-     * @throws InvalidInterfaceException
2094
-     * @throws ReflectionException
2095
-     */
2096
-    public function restore_cpt_item($post_id)
2097
-    {
2098
-        $this->_req_data['EVT_ID'] = $post_id;
2099
-        $this->_trash_or_restore_event('draft', false);
2100
-    }
2101
-
2102
-
2103
-    /**
2104
-     * @param string $post_id
2105
-     * @throws EE_Error
2106
-     * @throws InvalidArgumentException
2107
-     * @throws InvalidDataTypeException
2108
-     * @throws InvalidInterfaceException
2109
-     * @throws ReflectionException
2110
-     */
2111
-    public function delete_cpt_item($post_id)
2112
-    {
2113
-        throw new EE_Error(esc_html__('Please contact Event Espresso support with the details of the steps taken to produce this error.', 'event_espresso'));
2114
-        $this->_req_data['EVT_ID'] = $post_id;
2115
-        $this->_delete_event();
2116
-    }
2117
-
2118
-
2119
-    /**
2120
-     * _trash_or_restore_event
2121
-     *
2122
-     * @param string $event_status
2123
-     * @param bool   $redirect_after
2124
-     * @throws EE_Error
2125
-     * @throws InvalidArgumentException
2126
-     * @throws InvalidDataTypeException
2127
-     * @throws InvalidInterfaceException
2128
-     * @throws ReflectionException
2129
-     */
2130
-    protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
2131
-    {
2132
-        // determine the event id and set to array.
2133
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
2134
-        // loop thru events
2135
-        if ($EVT_ID) {
2136
-            // clean status
2137
-            $event_status = sanitize_key($event_status);
2138
-            // grab status
2139
-            if (! empty($event_status)) {
2140
-                $success = $this->_change_event_status($EVT_ID, $event_status);
2141
-            } else {
2142
-                $success = false;
2143
-                $msg = esc_html__(
2144
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2145
-                    'event_espresso'
2146
-                );
2147
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2148
-            }
2149
-        } else {
2150
-            $success = false;
2151
-            $msg = esc_html__(
2152
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2153
-                'event_espresso'
2154
-            );
2155
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2156
-        }
2157
-        $action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2158
-        if ($redirect_after) {
2159
-            $this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2160
-        }
2161
-    }
2162
-
2163
-
2164
-    /**
2165
-     * _trash_or_restore_events
2166
-     *
2167
-     * @param string $event_status
2168
-     * @return void
2169
-     * @throws EE_Error
2170
-     * @throws InvalidArgumentException
2171
-     * @throws InvalidDataTypeException
2172
-     * @throws InvalidInterfaceException
2173
-     * @throws ReflectionException
2174
-     */
2175
-    protected function _trash_or_restore_events($event_status = 'trash')
2176
-    {
2177
-        // clean status
2178
-        $event_status = sanitize_key($event_status);
2179
-        // grab status
2180
-        if (! empty($event_status)) {
2181
-            $success = true;
2182
-            // determine the event id and set to array.
2183
-            $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : [];
2184
-            // loop thru events
2185
-            foreach ($EVT_IDs as $EVT_ID) {
2186
-                if ($EVT_ID = absint($EVT_ID)) {
2187
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
2188
-                    $success = $results !== false ? $success : false;
2189
-                } else {
2190
-                    $msg = sprintf(
2191
-                        esc_html__(
2192
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2193
-                            'event_espresso'
2194
-                        ),
2195
-                        $EVT_ID
2196
-                    );
2197
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2198
-                    $success = false;
2199
-                }
2200
-            }
2201
-        } else {
2202
-            $success = false;
2203
-            $msg = esc_html__(
2204
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2205
-                'event_espresso'
2206
-            );
2207
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2208
-        }
2209
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2210
-        $success = $success ? 2 : false;
2211
-        $action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2212
-        $this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2213
-    }
2214
-
2215
-
2216
-    /**
2217
-     * _trash_or_restore_events
2218
-     *
2219
-     * @param int    $EVT_ID
2220
-     * @param string $event_status
2221
-     * @return bool
2222
-     * @throws EE_Error
2223
-     * @throws InvalidArgumentException
2224
-     * @throws InvalidDataTypeException
2225
-     * @throws InvalidInterfaceException
2226
-     * @throws ReflectionException
2227
-     */
2228
-    private function _change_event_status($EVT_ID = 0, $event_status = '')
2229
-    {
2230
-        // grab event id
2231
-        if (! $EVT_ID) {
2232
-            $msg = esc_html__(
2233
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2234
-                'event_espresso'
2235
-            );
2236
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2237
-            return false;
2238
-        }
2239
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2240
-        // clean status
2241
-        $event_status = sanitize_key($event_status);
2242
-        // grab status
2243
-        if (empty($event_status)) {
2244
-            $msg = esc_html__(
2245
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2246
-                'event_espresso'
2247
-            );
2248
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2249
-            return false;
2250
-        }
2251
-        // was event trashed or restored ?
2252
-        switch ($event_status) {
2253
-            case 'draft':
2254
-                $action = 'restored from the trash';
2255
-                $hook = 'AHEE_event_restored_from_trash';
2256
-                break;
2257
-            case 'trash':
2258
-                $action = 'moved to the trash';
2259
-                $hook = 'AHEE_event_moved_to_trash';
2260
-                break;
2261
-            default:
2262
-                $action = 'updated';
2263
-                $hook = false;
2264
-        }
2265
-        // use class to change status
2266
-        $this->_cpt_model_obj->set_status($event_status);
2267
-        $success = $this->_cpt_model_obj->save();
2268
-        if ($success === false) {
2269
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2270
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2271
-            return false;
2272
-        }
2273
-        if ($hook) {
2274
-            do_action($hook);
2275
-        }
2276
-        return true;
2277
-    }
2278
-
2279
-
2280
-    /**
2281
-     * _delete_event
2282
-     *
2283
-     * @param bool $redirect_after
2284
-     * @throws EE_Error
2285
-     * @throws InvalidArgumentException
2286
-     * @throws InvalidDataTypeException
2287
-     * @throws InvalidInterfaceException
2288
-     * @throws ReflectionException
2289
-     */
2290
-    protected function _delete_event()
2291
-    {
2292
-        $this->generateDeletionPreview(isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : []);
2293
-    }
2294
-
2295
-    /**
2296
-     * Gets the tree traversal batch persister.
2297
-     * @since $VID:$
2298
-     * @return NodeGroupDao
2299
-     * @throws InvalidArgumentException
2300
-     * @throws InvalidDataTypeException
2301
-     * @throws InvalidInterfaceException
2302
-     */
2303
-    protected function getModelObjNodeGroupPersister()
2304
-    {
2305
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2306
-            $this->model_obj_node_group_persister = $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2307
-        }
2308
-        return $this->model_obj_node_group_persister;
2309
-    }
2310
-
2311
-    /**
2312
-     * _delete_events
2313
-     *
2314
-     * @return void
2315
-     * @throws EE_Error
2316
-     * @throws InvalidArgumentException
2317
-     * @throws InvalidDataTypeException
2318
-     * @throws InvalidInterfaceException
2319
-     * @throws ReflectionException
2320
-     */
2321
-    protected function _delete_events()
2322
-    {
2323
-        $this->generateDeletionPreview(isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : []);
2324
-    }
2325
-
2326
-    protected function generateDeletionPreview($event_ids)
2327
-    {
2328
-        $event_ids = (array) $event_ids;
2329
-        // Set a code we can use to reference this deletion task in the batch jobs and preview page.
2330
-        $deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2331
-        $return_url = EE_Admin_Page::add_query_args_and_nonce(
2332
-            [
2333
-                'action' => 'preview_deletion',
2334
-                'deletion_job_code' => $deletion_job_code,
2335
-            ],
2336
-            $this->_admin_base_url
2337
-        );
2338
-        $event_ids = array_map(
2339
-            'intval',
2340
-            $event_ids
2341
-        );
2342
-
2343
-        EEH_URL::safeRedirectAndExit(
2344
-            EE_Admin_Page::add_query_args_and_nonce(
2345
-                [
2346
-                    'page'              => 'espresso_batch',
2347
-                    'batch'             => EED_Batch::batch_job,
2348
-                    'EVT_IDs'           => $event_ids,
2349
-                    'deletion_job_code' => $deletion_job_code,
2350
-                    'job_handler'       => urlencode('EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'),
2351
-                    'return_url'        => urlencode($return_url),
2352
-                ],
2353
-                admin_url()
2354
-            )
2355
-        );
2356
-    }
2357
-
2358
-    /**
2359
-     * Checks for a POST submission
2360
-     * @since $VID:$
2361
-     */
2362
-    protected function confirmDeletion()
2363
-    {
2364
-        $deletion_redirect_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion');
2365
-        $deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2366
-    }
2367
-
2368
-    /**
2369
-     * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2370
-     * @since $VID:$
2371
-     * @throws EE_Error
2372
-     */
2373
-    protected function previewDeletion()
2374
-    {
2375
-        $preview_deletion_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\PreviewDeletion');
2376
-        $this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2377
-        $this->display_admin_page_with_no_sidebar();
2378
-    }
2379
-
2380
-    /**
2381
-     * get total number of events
2382
-     *
2383
-     * @return int
2384
-     * @throws EE_Error
2385
-     * @throws InvalidArgumentException
2386
-     * @throws InvalidDataTypeException
2387
-     * @throws InvalidInterfaceException
2388
-     */
2389
-    public function total_events()
2390
-    {
2391
-        $count = EEM_Event::instance()->count(['caps' => 'read_admin'], 'EVT_ID', true);
2392
-        return $count;
2393
-    }
2394
-
2395
-
2396
-    /**
2397
-     * get total number of draft events
2398
-     *
2399
-     * @return int
2400
-     * @throws EE_Error
2401
-     * @throws InvalidArgumentException
2402
-     * @throws InvalidDataTypeException
2403
-     * @throws InvalidInterfaceException
2404
-     */
2405
-    public function total_events_draft()
2406
-    {
2407
-        $where = [
2408
-            'status' => ['IN', ['draft', 'auto-draft']],
2409
-        ];
2410
-        $count = EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
2411
-        return $count;
2412
-    }
2413
-
2414
-
2415
-    /**
2416
-     * get total number of trashed events
2417
-     *
2418
-     * @return int
2419
-     * @throws EE_Error
2420
-     * @throws InvalidArgumentException
2421
-     * @throws InvalidDataTypeException
2422
-     * @throws InvalidInterfaceException
2423
-     */
2424
-    public function total_trashed_events()
2425
-    {
2426
-        $where = [
2427
-            'status' => 'trash',
2428
-        ];
2429
-        $count = EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
2430
-        return $count;
2431
-    }
2432
-
2433
-
2434
-    /**
2435
-     *    _default_event_settings
2436
-     *    This generates the Default Settings Tab
2437
-     *
2438
-     * @return void
2439
-     * @throws DomainException
2440
-     * @throws EE_Error
2441
-     * @throws InvalidArgumentException
2442
-     * @throws InvalidDataTypeException
2443
-     * @throws InvalidInterfaceException
2444
-     */
2445
-    protected function _default_event_settings()
2446
-    {
2447
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2448
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
2449
-        $this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2450
-        $this->display_admin_page_with_sidebar();
2451
-    }
2452
-
2453
-
2454
-    /**
2455
-     * Return the form for event settings.
2456
-     *
2457
-     * @return EE_Form_Section_Proper
2458
-     * @throws EE_Error
2459
-     */
2460
-    protected function _default_event_settings_form()
2461
-    {
2462
-        $registration_config = EE_Registry::instance()->CFG->registration;
2463
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2464
-        // exclude
2465
-            [
2466
-                EEM_Registration::status_id_cancelled,
2467
-                EEM_Registration::status_id_declined,
2468
-                EEM_Registration::status_id_incomplete,
2469
-                EEM_Registration::status_id_wait_list,
2470
-            ],
2471
-            true
2472
-        );
2473
-        return new EE_Form_Section_Proper(
2474
-            [
2475
-                'name'            => 'update_default_event_settings',
2476
-                'html_id'         => 'update_default_event_settings',
2477
-                'html_class'      => 'form-table',
2478
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2479
-                'subsections'     => apply_filters(
2480
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2481
-                    [
2482
-                        'default_reg_status'  => new EE_Select_Input(
2483
-                            $registration_stati_for_selection,
2484
-                            [
2485
-                                'default'         => isset($registration_config->default_STS_ID)
2486
-                                                     && array_key_exists(
2487
-                                                         $registration_config->default_STS_ID,
2488
-                                                         $registration_stati_for_selection
2489
-                                                     )
2490
-                                    ? sanitize_text_field($registration_config->default_STS_ID)
2491
-                                    : EEM_Registration::status_id_pending_payment,
2492
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2493
-                                                     . EEH_Template::get_help_tab_link(
2494
-                                                         'default_settings_status_help_tab'
2495
-                                                     ),
2496
-                                'html_help_text'  => esc_html__(
2497
-                                    'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2498
-                                    'event_espresso'
2499
-                                ),
2500
-                            ]
2501
-                        ),
2502
-                        'default_max_tickets' => new EE_Integer_Input(
2503
-                            [
2504
-                                'default'         => isset($registration_config->default_maximum_number_of_tickets)
2505
-                                    ? $registration_config->default_maximum_number_of_tickets
2506
-                                    : EEM_Event::get_default_additional_limit(),
2507
-                                'html_label_text' => esc_html__(
2508
-                                    'Default Maximum Tickets Allowed Per Order:',
2509
-                                    'event_espresso'
2510
-                                )
2511
-                                                     . EEH_Template::get_help_tab_link(
2512
-                                                         'default_maximum_tickets_help_tab"'
2513
-                                                     ),
2514
-                                'html_help_text'  => esc_html__(
2515
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2516
-                                    'event_espresso'
2517
-                                ),
2518
-                            ]
2519
-                        ),
2520
-                    ]
2521
-                ),
2522
-            ]
2523
-        );
2524
-    }
2525
-
2526
-
2527
-    /**
2528
-     * @return void
2529
-     * @throws EE_Error
2530
-     * @throws InvalidArgumentException
2531
-     * @throws InvalidDataTypeException
2532
-     * @throws InvalidInterfaceException
2533
-     */
2534
-    protected function _update_default_event_settings()
2535
-    {
2536
-        $form = $this->_default_event_settings_form();
2537
-        if ($form->was_submitted()) {
2538
-            $form->receive_form_submission();
2539
-            if ($form->is_valid()) {
2540
-                $registration_config = EE_Registry::instance()->CFG->registration;
2541
-                $valid_data = $form->valid_data();
2542
-                if (isset($valid_data['default_reg_status'])) {
2543
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2544
-                }
2545
-                if (isset($valid_data['default_max_tickets'])) {
2546
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2547
-                }
2548
-                do_action(
2549
-                    'AHEE__Events_Admin_Page___update_default_event_settings',
2550
-                    $valid_data,
2551
-                    EE_Registry::instance()->CFG,
2552
-                    $this
2553
-                );
2554
-                // update because data was valid!
2555
-                EE_Registry::instance()->CFG->update_espresso_config();
2556
-                EE_Error::overwrite_success();
2557
-                EE_Error::add_success(
2558
-                    __('Default Event Settings were updated', 'event_espresso')
2559
-                );
2560
-            }
2561
-        }
2562
-        $this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2563
-    }
2564
-
2565
-
2566
-    /*************        Templates        *************/
2567
-    protected function _template_settings()
2568
-    {
2569
-        $this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2570
-        $this->_template_args['preview_img'] = '<img src="'
2571
-                                               . EVENTS_ASSETS_URL
2572
-                                               . '/images/'
2573
-                                               . 'caffeinated_template_features.jpg" alt="'
2574
-                                               . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2575
-                                               . '" />';
2576
-        $this->_template_args['preview_text'] = '<strong>'
2577
-                                                . esc_html__(
2578
-                                                    'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2579
-                                                    'event_espresso'
2580
-                                                ) . '</strong>';
2581
-        $this->display_admin_caf_preview_page('template_settings_tab');
2582
-    }
2583
-
2584
-
2585
-    /** Event Category Stuff **/
2586
-    /**
2587
-     * set the _category property with the category object for the loaded page.
2588
-     *
2589
-     * @return void
2590
-     */
2591
-    private function _set_category_object()
2592
-    {
2593
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2594
-            return;
2595
-        } //already have the category object so get out.
2596
-        // set default category object
2597
-        $this->_set_empty_category_object();
2598
-        // only set if we've got an id
2599
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2600
-            return;
2601
-        }
2602
-        $category_id = absint($this->_req_data['EVT_CAT_ID']);
2603
-        $term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2604
-        if (! empty($term)) {
2605
-            $this->_category->category_name = $term->name;
2606
-            $this->_category->category_identifier = $term->slug;
2607
-            $this->_category->category_desc = $term->description;
2608
-            $this->_category->id = $term->term_id;
2609
-            $this->_category->parent = $term->parent;
2610
-        }
2611
-    }
2612
-
2613
-
2614
-    /**
2615
-     * Clears out category properties.
2616
-     */
2617
-    private function _set_empty_category_object()
2618
-    {
2619
-        $this->_category = new stdClass();
2620
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2621
-        $this->_category->id = $this->_category->parent = 0;
2622
-    }
2623
-
2624
-
2625
-    /**
2626
-     * @throws DomainException
2627
-     * @throws EE_Error
2628
-     * @throws InvalidArgumentException
2629
-     * @throws InvalidDataTypeException
2630
-     * @throws InvalidInterfaceException
2631
-     */
2632
-    protected function _category_list_table()
2633
-    {
2634
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2635
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2636
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2637
-            'add_category',
2638
-            'add_category',
2639
-            [],
2640
-            'add-new-h2'
2641
-        );
2642
-        $this->display_admin_list_table_page_with_sidebar();
2643
-    }
2644
-
2645
-
2646
-    /**
2647
-     * Output category details view.
2648
-     *
2649
-     * @param string $view
2650
-     * @throws DomainException
2651
-     * @throws EE_Error
2652
-     * @throws InvalidArgumentException
2653
-     * @throws InvalidDataTypeException
2654
-     * @throws InvalidInterfaceException
2655
-     */
2656
-    protected function _category_details($view)
2657
-    {
2658
-        // load formatter helper
2659
-        // load field generator helper
2660
-        $route = $view === 'edit' ? 'update_category' : 'insert_category';
2661
-        $this->_set_add_edit_form_tags($route);
2662
-        $this->_set_category_object();
2663
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
2664
-        $delete_action = 'delete_category';
2665
-        // custom redirect
2666
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2667
-            ['action' => 'category_list'],
2668
-            $this->_admin_base_url
2669
-        );
2670
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2671
-        // take care of contents
2672
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2673
-        $this->display_admin_page_with_sidebar();
2674
-    }
2675
-
2676
-
2677
-    /**
2678
-     * Output category details content.
2679
-     *
2680
-     * @throws DomainException
2681
-     */
2682
-    protected function _category_details_content()
2683
-    {
2684
-        $editor_args['category_desc'] = [
2685
-            'type'          => 'wp_editor',
2686
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2687
-            'class'         => 'my_editor_custom',
2688
-            'wpeditor_args' => ['media_buttons' => false],
2689
-        ];
2690
-        $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2691
-        $all_terms = get_terms(
2692
-            [EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2693
-            ['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2694
-        );
2695
-        // setup category select for term parents.
2696
-        $category_select_values[] = [
2697
-            'text' => esc_html__('No Parent', 'event_espresso'),
2698
-            'id'   => 0,
2699
-        ];
2700
-        foreach ($all_terms as $term) {
2701
-            $category_select_values[] = [
2702
-                'text' => $term->name,
2703
-                'id'   => $term->term_id,
2704
-            ];
2705
-        }
2706
-        $category_select = EEH_Form_Fields::select_input(
2707
-            'category_parent',
2708
-            $category_select_values,
2709
-            $this->_category->parent
2710
-        );
2711
-        $template_args = [
2712
-            'category'                 => $this->_category,
2713
-            'category_select'          => $category_select,
2714
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2715
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2716
-            'disable'                  => '',
2717
-            'disabled_message'         => false,
2718
-        ];
2719
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2720
-        return EEH_Template::display_template($template, $template_args, true);
2721
-    }
2722
-
2723
-
2724
-    /**
2725
-     * Handles deleting categories.
2726
-     */
2727
-    protected function _delete_categories()
2728
-    {
2729
-        $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2730
-            : (array) $this->_req_data['category_id'];
2731
-        foreach ($cat_ids as $cat_id) {
2732
-            $this->_delete_category($cat_id);
2733
-        }
2734
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
2735
-        $query_args = [
2736
-            'action' => 'category_list',
2737
-        ];
2738
-        $this->_redirect_after_action(0, '', '', $query_args);
2739
-    }
2740
-
2741
-
2742
-    /**
2743
-     * Handles deleting specific category.
2744
-     *
2745
-     * @param int $cat_id
2746
-     */
2747
-    protected function _delete_category($cat_id)
2748
-    {
2749
-        $cat_id = absint($cat_id);
2750
-        wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2751
-    }
2752
-
2753
-
2754
-    /**
2755
-     * Handles triggering the update or insertion of a new category.
2756
-     *
2757
-     * @param bool $new_category true means we're triggering the insert of a new category.
2758
-     * @throws EE_Error
2759
-     * @throws InvalidArgumentException
2760
-     * @throws InvalidDataTypeException
2761
-     * @throws InvalidInterfaceException
2762
-     */
2763
-    protected function _insert_or_update_category($new_category)
2764
-    {
2765
-        $cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2766
-        $success = 0; // we already have a success message so lets not send another.
2767
-        if ($cat_id) {
2768
-            $query_args = [
2769
-                'action'     => 'edit_category',
2770
-                'EVT_CAT_ID' => $cat_id,
2771
-            ];
2772
-        } else {
2773
-            $query_args = ['action' => 'add_category'];
2774
-        }
2775
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2776
-    }
2777
-
2778
-
2779
-    /**
2780
-     * Inserts or updates category
2781
-     *
2782
-     * @param bool $update (true indicates we're updating a category).
2783
-     * @return bool|mixed|string
2784
-     */
2785
-    private function _insert_category($update = false)
2786
-    {
2787
-        $cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2788
-        $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2789
-        $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2790
-        $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2791
-        if (empty($category_name)) {
2792
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2793
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2794
-            return false;
2795
-        }
2796
-        $term_args = [
2797
-            'name'        => $category_name,
2798
-            'description' => $category_desc,
2799
-            'parent'      => $category_parent,
2800
-        ];
2801
-        // was the category_identifier input disabled?
2802
-        if (isset($this->_req_data['category_identifier'])) {
2803
-            $term_args['slug'] = $this->_req_data['category_identifier'];
2804
-        }
2805
-        $insert_ids = $update
2806
-            ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2807
-            : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2808
-        if (! is_array($insert_ids)) {
2809
-            $msg = esc_html__(
2810
-                'An error occurred and the category has not been saved to the database.',
2811
-                'event_espresso'
2812
-            );
2813
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2814
-        } else {
2815
-            $cat_id = $insert_ids['term_id'];
2816
-            $msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2817
-            EE_Error::add_success($msg);
2818
-        }
2819
-        return $cat_id;
2820
-    }
2821
-
2822
-
2823
-    /**
2824
-     * Gets categories or count of categories matching the arguments in the request.
2825
-     *
2826
-     * @param int  $per_page
2827
-     * @param int  $current_page
2828
-     * @param bool $count
2829
-     * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2830
-     * @throws EE_Error
2831
-     * @throws InvalidArgumentException
2832
-     * @throws InvalidDataTypeException
2833
-     * @throws InvalidInterfaceException
2834
-     */
2835
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
2836
-    {
2837
-        // testing term stuff
2838
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2839
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2840
-        $limit = ($current_page - 1) * $per_page;
2841
-        $where = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2842
-        if (isset($this->_req_data['s'])) {
2843
-            $sstr = '%' . $this->_req_data['s'] . '%';
2844
-            $where['OR'] = [
2845
-                'Term.name'   => ['LIKE', $sstr],
2846
-                'description' => ['LIKE', $sstr],
2847
-            ];
2848
-        }
2849
-        $query_params = [
2850
-            $where,
2851
-            'order_by'   => [$orderby => $order],
2852
-            'limit'      => $limit . ',' . $per_page,
2853
-            'force_join' => ['Term'],
2854
-        ];
2855
-        $categories = $count
2856
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2857
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2858
-        return $categories;
2859
-    }
2860
-
2861
-    /* end category stuff */
2862
-    /**************/
2863
-
2864
-
2865
-    /**
2866
-     * Callback for the `ee_save_timezone_setting` ajax action.
2867
-     *
2868
-     * @throws EE_Error
2869
-     * @throws InvalidArgumentException
2870
-     * @throws InvalidDataTypeException
2871
-     * @throws InvalidInterfaceException
2872
-     */
2873
-    public function save_timezonestring_setting()
2874
-    {
2875
-        $timezone_string = isset($this->_req_data['timezone_selected'])
2876
-            ? $this->_req_data['timezone_selected']
2877
-            : '';
2878
-        if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2879
-            EE_Error::add_error(
2880
-                esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2881
-                __FILE__,
2882
-                __FUNCTION__,
2883
-                __LINE__
2884
-            );
2885
-            $this->_template_args['error'] = true;
2886
-            $this->_return_json();
2887
-        }
2888
-
2889
-        update_option('timezone_string', $timezone_string);
2890
-        EE_Error::add_success(
2891
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2892
-        );
2893
-        $this->_template_args['success'] = true;
2894
-        $this->_return_json(true, ['action' => 'create_new']);
2895
-    }
23
+	/**
24
+	 * This will hold the event object for event_details screen.
25
+	 *
26
+	 * @var EE_Event $_event
27
+	 */
28
+	protected $_event;
29
+
30
+
31
+	/**
32
+	 * This will hold the category object for category_details screen.
33
+	 *
34
+	 * @var stdClass $_category
35
+	 */
36
+	protected $_category;
37
+
38
+
39
+	/**
40
+	 * @var EEM_Event $_event_model
41
+	 */
42
+	protected $_event_model;
43
+
44
+	/**
45
+	 * @var EEM_Datetime $datetime_model
46
+	 */
47
+	protected $datetime_model;
48
+
49
+	/**
50
+	 * @var EEM_Ticket $ticket_model
51
+	 */
52
+	protected $ticket_model;
53
+
54
+
55
+	/**
56
+	 * @var EE_Event
57
+	 */
58
+	protected $_cpt_model_obj;
59
+
60
+
61
+	/**
62
+	 * @var NodeGroupDao
63
+	 */
64
+	protected $model_obj_node_group_persister;
65
+
66
+	/**
67
+	 * Initialize page props for this admin page group.
68
+	 */
69
+	protected function _init_page_props()
70
+	{
71
+		$this->page_slug = EVENTS_PG_SLUG;
72
+		$this->page_label = EVENTS_LABEL;
73
+		$this->_admin_base_url = EVENTS_ADMIN_URL;
74
+		$this->_admin_base_path = EVENTS_ADMIN;
75
+		$this->_cpt_model_names = [
76
+			'create_new' => 'EEM_Event',
77
+			'edit'       => 'EEM_Event',
78
+		];
79
+		$this->_cpt_edit_routes = [
80
+			'espresso_events' => 'edit',
81
+		];
82
+		add_action(
83
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
84
+			[$this, 'verify_event_edit'],
85
+			10,
86
+			2
87
+		);
88
+	}
89
+
90
+
91
+	/**
92
+	 * Sets the ajax hooks used for this admin page group.
93
+	 */
94
+	protected function _ajax_hooks()
95
+	{
96
+		add_action('wp_ajax_ee_save_timezone_setting', [$this, 'save_timezonestring_setting']);
97
+	}
98
+
99
+
100
+	/**
101
+	 * Sets the page properties for this admin page group.
102
+	 */
103
+	protected function _define_page_props()
104
+	{
105
+		$this->_admin_page_title = EVENTS_LABEL;
106
+		$this->_labels = [
107
+			'buttons'      => [
108
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
109
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
110
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
111
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
112
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
113
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
114
+			],
115
+			'editor_title' => [
116
+				'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
117
+			],
118
+			'publishbox'   => [
119
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
120
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
121
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
122
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
123
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
124
+			],
125
+		];
126
+	}
127
+
128
+
129
+	/**
130
+	 * Sets the page routes property for this admin page group.
131
+	 */
132
+	protected function _set_page_routes()
133
+	{
134
+		// load formatter helper
135
+		// load field generator helper
136
+		// is there a evt_id in the request?
137
+		$evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
138
+			? $this->_req_data['EVT_ID']
139
+			: 0;
140
+		$evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
141
+		$this->_page_routes = [
142
+			'default'                       => [
143
+				'func'       => '_events_overview_list_table',
144
+				'capability' => 'ee_read_events',
145
+			],
146
+			'create_new'                    => [
147
+				'func'       => '_create_new_cpt_item',
148
+				'capability' => 'ee_edit_events',
149
+			],
150
+			'edit'                          => [
151
+				'func'       => '_edit_cpt_item',
152
+				'capability' => 'ee_edit_event',
153
+				'obj_id'     => $evt_id,
154
+			],
155
+			'copy_event'                    => [
156
+				'func'       => '_copy_events',
157
+				'capability' => 'ee_edit_event',
158
+				'obj_id'     => $evt_id,
159
+				'noheader'   => true,
160
+			],
161
+			'trash_event'                   => [
162
+				'func'       => '_trash_or_restore_event',
163
+				'args'       => ['event_status' => 'trash'],
164
+				'capability' => 'ee_delete_event',
165
+				'obj_id'     => $evt_id,
166
+				'noheader'   => true,
167
+			],
168
+			'trash_events'                  => [
169
+				'func'       => '_trash_or_restore_events',
170
+				'args'       => ['event_status' => 'trash'],
171
+				'capability' => 'ee_delete_events',
172
+				'noheader'   => true,
173
+			],
174
+			'restore_event'                 => [
175
+				'func'       => '_trash_or_restore_event',
176
+				'args'       => ['event_status' => 'draft'],
177
+				'capability' => 'ee_delete_event',
178
+				'obj_id'     => $evt_id,
179
+				'noheader'   => true,
180
+			],
181
+			'restore_events'                => [
182
+				'func'       => '_trash_or_restore_events',
183
+				'args'       => ['event_status' => 'draft'],
184
+				'capability' => 'ee_delete_events',
185
+				'noheader'   => true,
186
+			],
187
+			'delete_event'                  => [
188
+				'func'       => '_delete_event',
189
+				'capability' => 'ee_delete_event',
190
+				'obj_id'     => $evt_id,
191
+				'noheader'   => true,
192
+			],
193
+			'delete_events'                 => [
194
+				'func'       => '_delete_events',
195
+				'capability' => 'ee_delete_events',
196
+				'noheader'   => true,
197
+			],
198
+			'view_report'                   => [
199
+				'func'       => '_view_report',
200
+				'capability' => 'ee_edit_events',
201
+			],
202
+			'default_event_settings'        => [
203
+				'func'       => '_default_event_settings',
204
+				'capability' => 'manage_options',
205
+			],
206
+			'update_default_event_settings' => [
207
+				'func'       => '_update_default_event_settings',
208
+				'capability' => 'manage_options',
209
+				'noheader'   => true,
210
+			],
211
+			'template_settings'             => [
212
+				'func'       => '_template_settings',
213
+				'capability' => 'manage_options',
214
+			],
215
+			// event category tab related
216
+			'add_category'                  => [
217
+				'func'       => '_category_details',
218
+				'capability' => 'ee_edit_event_category',
219
+				'args'       => ['add'],
220
+			],
221
+			'edit_category'                 => [
222
+				'func'       => '_category_details',
223
+				'capability' => 'ee_edit_event_category',
224
+				'args'       => ['edit'],
225
+			],
226
+			'delete_categories'             => [
227
+				'func'       => '_delete_categories',
228
+				'capability' => 'ee_delete_event_category',
229
+				'noheader'   => true,
230
+			],
231
+			'delete_category'               => [
232
+				'func'       => '_delete_categories',
233
+				'capability' => 'ee_delete_event_category',
234
+				'noheader'   => true,
235
+			],
236
+			'insert_category'               => [
237
+				'func'       => '_insert_or_update_category',
238
+				'args'       => ['new_category' => true],
239
+				'capability' => 'ee_edit_event_category',
240
+				'noheader'   => true,
241
+			],
242
+			'update_category'               => [
243
+				'func'       => '_insert_or_update_category',
244
+				'args'       => ['new_category' => false],
245
+				'capability' => 'ee_edit_event_category',
246
+				'noheader'   => true,
247
+			],
248
+			'category_list'                 => [
249
+				'func'       => '_category_list_table',
250
+				'capability' => 'ee_manage_event_categories',
251
+			],
252
+			'preview_deletion' => [
253
+				'func' => 'previewDeletion',
254
+				'capability' => 'ee_delete_events',
255
+			],
256
+			'confirm_deletion' => [
257
+				'func' => 'confirmDeletion',
258
+				'capability' => 'ee_delete_events',
259
+				'noheader' => true,
260
+			]
261
+		];
262
+	}
263
+
264
+
265
+	/**
266
+	 * Set the _page_config property for this admin page group.
267
+	 */
268
+	protected function _set_page_config()
269
+	{
270
+		$this->_page_config = [
271
+			'default'                => [
272
+				'nav'           => [
273
+					'label' => esc_html__('Overview', 'event_espresso'),
274
+					'order' => 10,
275
+				],
276
+				'list_table'    => 'Events_Admin_List_Table',
277
+				'help_tabs'     => [
278
+					'events_overview_help_tab'                       => [
279
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
280
+						'filename' => 'events_overview',
281
+					],
282
+					'events_overview_table_column_headings_help_tab' => [
283
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
284
+						'filename' => 'events_overview_table_column_headings',
285
+					],
286
+					'events_overview_filters_help_tab'               => [
287
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
288
+						'filename' => 'events_overview_filters',
289
+					],
290
+					'events_overview_view_help_tab'                  => [
291
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
292
+						'filename' => 'events_overview_views',
293
+					],
294
+					'events_overview_other_help_tab'                 => [
295
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
296
+						'filename' => 'events_overview_other',
297
+					],
298
+				],
299
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
300
+				// 'help_tour'     => [
301
+				//     'Event_Overview_Help_Tour',
302
+				//     // 'New_Features_Test_Help_Tour' for testing multiple help tour
303
+				// ],
304
+				'require_nonce' => false,
305
+				'qtips'         => ['EE_Event_List_Table_Tips'],
306
+			],
307
+			'create_new'             => [
308
+				'nav'           => [
309
+					'label'      => esc_html__('Add Event', 'event_espresso'),
310
+					'order'      => 5,
311
+					'persistent' => false,
312
+				],
313
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
314
+				'help_tabs'     => [
315
+					'event_editor_help_tab'                            => [
316
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
317
+						'filename' => 'event_editor',
318
+					],
319
+					'event_editor_title_richtexteditor_help_tab'       => [
320
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
321
+						'filename' => 'event_editor_title_richtexteditor',
322
+					],
323
+					'event_editor_venue_details_help_tab'              => [
324
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
325
+						'filename' => 'event_editor_venue_details',
326
+					],
327
+					'event_editor_event_datetimes_help_tab'            => [
328
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
329
+						'filename' => 'event_editor_event_datetimes',
330
+					],
331
+					'event_editor_event_tickets_help_tab'              => [
332
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
333
+						'filename' => 'event_editor_event_tickets',
334
+					],
335
+					'event_editor_event_registration_options_help_tab' => [
336
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
337
+						'filename' => 'event_editor_event_registration_options',
338
+					],
339
+					'event_editor_tags_categories_help_tab'            => [
340
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
341
+						'filename' => 'event_editor_tags_categories',
342
+					],
343
+					'event_editor_questions_registrants_help_tab'      => [
344
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
345
+						'filename' => 'event_editor_questions_registrants',
346
+					],
347
+					'event_editor_save_new_event_help_tab'             => [
348
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
349
+						'filename' => 'event_editor_save_new_event',
350
+					],
351
+					'event_editor_other_help_tab'                      => [
352
+						'title'    => esc_html__('Event Other', 'event_espresso'),
353
+						'filename' => 'event_editor_other',
354
+					],
355
+				],
356
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
357
+				// 'help_tour'     => [
358
+				//     'Event_Editor_Help_Tour',
359
+				// ],
360
+				'require_nonce' => false,
361
+			],
362
+			'edit'                   => [
363
+				'nav'           => [
364
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
365
+					'order'      => 5,
366
+					'persistent' => false,
367
+					'url'        => isset($this->_req_data['post'])
368
+						? EE_Admin_Page::add_query_args_and_nonce(
369
+							['post' => $this->_req_data['post'], 'action' => 'edit'],
370
+							$this->_current_page_view_url
371
+						)
372
+						: $this->_admin_base_url,
373
+				],
374
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
375
+				'help_tabs'     => [
376
+					'event_editor_help_tab'                            => [
377
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
378
+						'filename' => 'event_editor',
379
+					],
380
+					'event_editor_title_richtexteditor_help_tab'       => [
381
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
382
+						'filename' => 'event_editor_title_richtexteditor',
383
+					],
384
+					'event_editor_venue_details_help_tab'              => [
385
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
386
+						'filename' => 'event_editor_venue_details',
387
+					],
388
+					'event_editor_event_datetimes_help_tab'            => [
389
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
390
+						'filename' => 'event_editor_event_datetimes',
391
+					],
392
+					'event_editor_event_tickets_help_tab'              => [
393
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
394
+						'filename' => 'event_editor_event_tickets',
395
+					],
396
+					'event_editor_event_registration_options_help_tab' => [
397
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
398
+						'filename' => 'event_editor_event_registration_options',
399
+					],
400
+					'event_editor_tags_categories_help_tab'            => [
401
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
402
+						'filename' => 'event_editor_tags_categories',
403
+					],
404
+					'event_editor_questions_registrants_help_tab'      => [
405
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
406
+						'filename' => 'event_editor_questions_registrants',
407
+					],
408
+					'event_editor_save_new_event_help_tab'             => [
409
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
410
+						'filename' => 'event_editor_save_new_event',
411
+					],
412
+					'event_editor_other_help_tab'                      => [
413
+						'title'    => esc_html__('Event Other', 'event_espresso'),
414
+						'filename' => 'event_editor_other',
415
+					],
416
+				],
417
+				'require_nonce' => false,
418
+			],
419
+			'default_event_settings' => [
420
+				'nav'           => [
421
+					'label' => esc_html__('Default Settings', 'event_espresso'),
422
+					'order' => 40,
423
+				],
424
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
425
+				'labels'        => [
426
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
427
+				],
428
+				'help_tabs'     => [
429
+					'default_settings_help_tab'        => [
430
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
431
+						'filename' => 'events_default_settings',
432
+					],
433
+					'default_settings_status_help_tab' => [
434
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
435
+						'filename' => 'events_default_settings_status',
436
+					],
437
+					'default_maximum_tickets_help_tab' => [
438
+						'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
439
+						'filename' => 'events_default_settings_max_tickets',
440
+					],
441
+				],
442
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
443
+				// 'help_tour'     => ['Event_Default_Settings_Help_Tour'],
444
+				'require_nonce' => false,
445
+			],
446
+			// template settings
447
+			'template_settings'      => [
448
+				'nav'           => [
449
+					'label' => esc_html__('Templates', 'event_espresso'),
450
+					'order' => 30,
451
+				],
452
+				'metaboxes'     => $this->_default_espresso_metaboxes,
453
+				'help_tabs'     => [
454
+					'general_settings_templates_help_tab' => [
455
+						'title'    => esc_html__('Templates', 'event_espresso'),
456
+						'filename' => 'general_settings_templates',
457
+					],
458
+				],
459
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
460
+				// 'help_tour'     => ['Templates_Help_Tour'],
461
+				'require_nonce' => false,
462
+			],
463
+			// event category stuff
464
+			'add_category'           => [
465
+				'nav'           => [
466
+					'label'      => esc_html__('Add Category', 'event_espresso'),
467
+					'order'      => 15,
468
+					'persistent' => false,
469
+				],
470
+				'help_tabs'     => [
471
+					'add_category_help_tab' => [
472
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
473
+						'filename' => 'events_add_category',
474
+					],
475
+				],
476
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
477
+				// 'help_tour'     => ['Event_Add_Category_Help_Tour'],
478
+				'metaboxes'     => ['_publish_post_box'],
479
+				'require_nonce' => false,
480
+			],
481
+			'edit_category'          => [
482
+				'nav'           => [
483
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
484
+					'order'      => 15,
485
+					'persistent' => false,
486
+					'url'        => isset($this->_req_data['EVT_CAT_ID'])
487
+						? add_query_arg(
488
+							['EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']],
489
+							$this->_current_page_view_url
490
+						)
491
+						: $this->_admin_base_url,
492
+				],
493
+				'help_tabs'     => [
494
+					'edit_category_help_tab' => [
495
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
496
+						'filename' => 'events_edit_category',
497
+					],
498
+				],
499
+				/*'help_tour' => ['Event_Edit_Category_Help_Tour'],*/
500
+				'metaboxes'     => ['_publish_post_box'],
501
+				'require_nonce' => false,
502
+			],
503
+			'category_list'          => [
504
+				'nav'           => [
505
+					'label' => esc_html__('Categories', 'event_espresso'),
506
+					'order' => 20,
507
+				],
508
+				'list_table'    => 'Event_Categories_Admin_List_Table',
509
+				'help_tabs'     => [
510
+					'events_categories_help_tab'                       => [
511
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
512
+						'filename' => 'events_categories',
513
+					],
514
+					'events_categories_table_column_headings_help_tab' => [
515
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
516
+						'filename' => 'events_categories_table_column_headings',
517
+					],
518
+					'events_categories_view_help_tab'                  => [
519
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
520
+						'filename' => 'events_categories_views',
521
+					],
522
+					'events_categories_other_help_tab'                 => [
523
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
524
+						'filename' => 'events_categories_other',
525
+					],
526
+				],
527
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
528
+				// 'help_tour'     => [
529
+				//     'Event_Categories_Help_Tour',
530
+				// ],
531
+				'metaboxes'     => $this->_default_espresso_metaboxes,
532
+				'require_nonce' => false,
533
+			],
534
+			'preview_deletion'       => [
535
+				'nav'           => [
536
+					'label'      => esc_html__('Preview Deletion', 'event_espresso'),
537
+					'order'      => 15,
538
+					'persistent' => false,
539
+					'url'        => '',
540
+				],
541
+				'require_nonce' => false,
542
+			],
543
+		];
544
+		// only load EE_Event_Editor_Decaf_Tips if domain is not caffeinated
545
+		$domain = $this->loader->getShared('EventEspresso\core\domain\Domain');
546
+		if (! $domain->isCaffeinated()) {
547
+			$this->_page_config['create_new']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
548
+			$this->_page_config['edit']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
549
+		}
550
+	}
551
+
552
+
553
+	/**
554
+	 * Used to register any global screen options if necessary for every route in this admin page group.
555
+	 */
556
+	protected function _add_screen_options()
557
+	{
558
+	}
559
+
560
+
561
+	/**
562
+	 * Implementing the screen options for the 'default' route.
563
+	 *
564
+	 * @throws InvalidArgumentException
565
+	 * @throws InvalidDataTypeException
566
+	 * @throws InvalidInterfaceException
567
+	 */
568
+	protected function _add_screen_options_default()
569
+	{
570
+		$this->_per_page_screen_option();
571
+	}
572
+
573
+
574
+	/**
575
+	 * Implementing screen options for the category list route.
576
+	 *
577
+	 * @throws InvalidArgumentException
578
+	 * @throws InvalidDataTypeException
579
+	 * @throws InvalidInterfaceException
580
+	 */
581
+	protected function _add_screen_options_category_list()
582
+	{
583
+		$page_title = $this->_admin_page_title;
584
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
585
+		$this->_per_page_screen_option();
586
+		$this->_admin_page_title = $page_title;
587
+	}
588
+
589
+
590
+	/**
591
+	 * Used to register any global feature pointers for the admin page group.
592
+	 */
593
+	protected function _add_feature_pointers()
594
+	{
595
+	}
596
+
597
+
598
+	/**
599
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
600
+	 */
601
+	public function load_scripts_styles()
602
+	{
603
+		wp_register_style(
604
+			'events-admin-css',
605
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
606
+			[],
607
+			EVENT_ESPRESSO_VERSION
608
+		);
609
+		wp_register_style(
610
+			'ee-cat-admin',
611
+			EVENTS_ASSETS_URL . 'ee-cat-admin.css',
612
+			[],
613
+			EVENT_ESPRESSO_VERSION
614
+		);
615
+		wp_enqueue_style('events-admin-css');
616
+		wp_enqueue_style('ee-cat-admin');
617
+		// scripts
618
+		wp_register_script(
619
+			'event_editor_js',
620
+			EVENTS_ASSETS_URL . 'event_editor.js',
621
+			['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
622
+			EVENT_ESPRESSO_VERSION,
623
+			true
624
+		);
625
+	}
626
+
627
+
628
+	/**
629
+	 * Enqueuing scripts and styles specific to this view
630
+	 */
631
+	public function load_scripts_styles_create_new()
632
+	{
633
+		$this->load_scripts_styles_edit();
634
+	}
635
+
636
+
637
+	/**
638
+	 * Enqueuing scripts and styles specific to this view
639
+	 */
640
+	public function load_scripts_styles_edit()
641
+	{
642
+		// styles
643
+		wp_enqueue_style('espresso-ui-theme');
644
+		wp_register_style(
645
+			'event-editor-css',
646
+			EVENTS_ASSETS_URL . 'event-editor.css',
647
+			['ee-admin-css'],
648
+			EVENT_ESPRESSO_VERSION
649
+		);
650
+		wp_enqueue_style('event-editor-css');
651
+		// scripts
652
+		if (! $this->admin_config->useAdvancedEditor()) {
653
+			wp_register_script(
654
+				'event-datetime-metabox',
655
+				EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
656
+				['event_editor_js', 'ee-datepicker'],
657
+				EVENT_ESPRESSO_VERSION
658
+			);
659
+			wp_enqueue_script('event-datetime-metabox');
660
+		}
661
+	}
662
+
663
+
664
+	/**
665
+	 * Populating the _views property for the category list table view.
666
+	 */
667
+	protected function _set_list_table_views_category_list()
668
+	{
669
+		$this->_views = [
670
+			'all' => [
671
+				'slug'        => 'all',
672
+				'label'       => esc_html__('All', 'event_espresso'),
673
+				'count'       => 0,
674
+				'bulk_action' => [
675
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
676
+				],
677
+			],
678
+		];
679
+	}
680
+
681
+
682
+	/**
683
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
684
+	 */
685
+	public function admin_init()
686
+	{
687
+		EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
688
+			'Do you really want to delete this image? Please remember to update your event to complete the removal.',
689
+			'event_espresso'
690
+		);
691
+	}
692
+
693
+
694
+	/**
695
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
696
+	 * group.
697
+	 */
698
+	public function admin_notices()
699
+	{
700
+	}
701
+
702
+
703
+	/**
704
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
705
+	 * this admin page group.
706
+	 */
707
+	public function admin_footer_scripts()
708
+	{
709
+	}
710
+
711
+
712
+	/**
713
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
714
+	 * warning (via EE_Error::add_error());
715
+	 *
716
+	 * @param EE_Event $event Event object
717
+	 * @param string   $req_type
718
+	 * @return void
719
+	 * @throws EE_Error
720
+	 */
721
+	public function verify_event_edit($event = null, $req_type = '')
722
+	{
723
+		// don't need to do this when processing
724
+		if (! empty($req_type)) {
725
+			return;
726
+		}
727
+		// no event?
728
+		if (! $event instanceof EE_Event) {
729
+			$event = $this->_cpt_model_obj;
730
+		}
731
+		// STILL no event?
732
+		if (! $event instanceof EE_Event) {
733
+			return;
734
+		}
735
+		$orig_status = $event->status();
736
+		// first check if event is active.
737
+		if (
738
+			$orig_status === EEM_Event::cancelled
739
+			|| $orig_status === EEM_Event::postponed
740
+			|| $event->is_expired()
741
+			|| $event->is_inactive()
742
+		) {
743
+			return;
744
+		}
745
+		// made it here so it IS active... next check that any of the tickets are sold.
746
+		if ($event->is_sold_out(true)) {
747
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
748
+				EE_Error::add_attention(
749
+					sprintf(
750
+						esc_html__(
751
+							'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
752
+							'event_espresso'
753
+						),
754
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
755
+					)
756
+				);
757
+			}
758
+			return;
759
+		}
760
+		if ($orig_status === EEM_Event::sold_out) {
761
+			EE_Error::add_attention(
762
+				sprintf(
763
+					esc_html__(
764
+						'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
765
+						'event_espresso'
766
+					),
767
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
768
+				)
769
+			);
770
+		}
771
+		// now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
772
+		if (! $event->tickets_on_sale()) {
773
+			return;
774
+		}
775
+		// made it here so show warning
776
+		$this->_edit_event_warning();
777
+	}
778
+
779
+
780
+	/**
781
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
782
+	 * When needed, hook this into a EE_Error::add_error() notice.
783
+	 *
784
+	 * @return void
785
+	 */
786
+	protected function _edit_event_warning()
787
+	{
788
+		// we don't want to add warnings during these requests
789
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
790
+			return;
791
+		}
792
+		EE_Error::add_attention(
793
+			sprintf(
794
+				esc_html__(
795
+					'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
796
+					'event_espresso'
797
+				),
798
+				'<a class="espresso-help-tab-lnk">',
799
+				'</a>'
800
+			)
801
+		);
802
+	}
803
+
804
+
805
+	/**
806
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
807
+	 * Otherwise, do the normal logic
808
+	 *
809
+	 * @throws EE_Error
810
+	 * @throws InvalidArgumentException
811
+	 * @throws InvalidDataTypeException
812
+	 */
813
+	protected function _create_new_cpt_item()
814
+	{
815
+		$has_timezone_string = get_option('timezone_string');
816
+		// only nag them about setting their timezone if it's their first event, and they haven't already done it
817
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
818
+			EE_Error::add_attention(
819
+				sprintf(
820
+					__(
821
+						'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
822
+						'event_espresso'
823
+					),
824
+					'<br>',
825
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
826
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
827
+					. '</select>',
828
+					'<button class="button button-secondary timezone-submit">',
829
+					'</button><span class="spinner"></span>'
830
+				),
831
+				__FILE__,
832
+				__FUNCTION__,
833
+				__LINE__
834
+			);
835
+		}
836
+		parent::_create_new_cpt_item();
837
+	}
838
+
839
+
840
+	/**
841
+	 * Sets the _views property for the default route in this admin page group.
842
+	 */
843
+	protected function _set_list_table_views_default()
844
+	{
845
+		$this->_views = [
846
+			'all'   => [
847
+				'slug'        => 'all',
848
+				'label'       => esc_html__('View All Events', 'event_espresso'),
849
+				'count'       => 0,
850
+				'bulk_action' => [
851
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
852
+				],
853
+			],
854
+			'draft' => [
855
+				'slug'        => 'draft',
856
+				'label'       => esc_html__('Draft', 'event_espresso'),
857
+				'count'       => 0,
858
+				'bulk_action' => [
859
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
860
+				],
861
+			],
862
+		];
863
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
864
+			$this->_views['trash'] = [
865
+				'slug'        => 'trash',
866
+				'label'       => esc_html__('Trash', 'event_espresso'),
867
+				'count'       => 0,
868
+				'bulk_action' => [
869
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
870
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
871
+				],
872
+			];
873
+		}
874
+	}
875
+
876
+
877
+	/**
878
+	 * Provides the legend item array for the default list table view.
879
+	 *
880
+	 * @return array
881
+	 */
882
+	protected function _event_legend_items()
883
+	{
884
+		$items = [
885
+			'view_details'   => [
886
+				'class' => 'dashicons dashicons-search',
887
+				'desc'  => esc_html__('View Event', 'event_espresso'),
888
+			],
889
+			'edit_event'     => [
890
+				'class' => 'ee-icon ee-icon-calendar-edit',
891
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
892
+			],
893
+			'view_attendees' => [
894
+				'class' => 'dashicons dashicons-groups',
895
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
896
+			],
897
+		];
898
+		$items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
899
+		$statuses = [
900
+			'sold_out_status'  => [
901
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
902
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
903
+			],
904
+			'active_status'    => [
905
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
906
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
907
+			],
908
+			'upcoming_status'  => [
909
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
910
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
911
+			],
912
+			'postponed_status' => [
913
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
914
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
915
+			],
916
+			'cancelled_status' => [
917
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
918
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
919
+			],
920
+			'expired_status'   => [
921
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
922
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
923
+			],
924
+			'inactive_status'  => [
925
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
926
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
927
+			],
928
+		];
929
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
930
+		return array_merge($items, $statuses);
931
+	}
932
+
933
+
934
+	/**
935
+	 * @return EEM_Event
936
+	 * @throws EE_Error
937
+	 */
938
+	private function eventModel()
939
+	{
940
+		if (! $this->_event_model instanceof EEM_Event) {
941
+			$this->_event_model = EEM_Event::instance();
942
+		}
943
+		return $this->_event_model;
944
+	}
945
+
946
+
947
+	/**
948
+	 * @param string $event_timezone_string
949
+	 * @return EEM_Datetime
950
+	 * @throws EE_Error
951
+	 */
952
+	private function datetimeModel($event_timezone_string = '')
953
+	{
954
+		if (! $this->datetime_model instanceof EEM_Datetime) {
955
+			$this->datetime_model = EEM_Datetime::instance($event_timezone_string);
956
+		}
957
+		return $this->datetime_model;
958
+	}
959
+
960
+
961
+	/**
962
+	 * @param string $event_timezone_string
963
+	 * @return EEM_Ticket
964
+	 * @throws EE_Error
965
+	 */
966
+	private function ticketModel($event_timezone_string = '')
967
+	{
968
+		if (! $this->ticket_model instanceof EEM_Ticket) {
969
+			$this->ticket_model = EEM_Ticket::instance($event_timezone_string);
970
+		}
971
+		return $this->ticket_model;
972
+	}
973
+
974
+
975
+	/**
976
+	 * Adds extra buttons to the WP CPT permalink field row.
977
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
978
+	 *
979
+	 * @param string $return    the current html
980
+	 * @param int    $id        the post id for the page
981
+	 * @param string $new_title What the title is
982
+	 * @param string $new_slug  what the slug is
983
+	 * @return string            The new html string for the permalink area
984
+	 */
985
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
986
+	{
987
+		// make sure this is only when editing
988
+		if (! empty($id)) {
989
+			$post = get_post($id);
990
+			$return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
991
+					   . esc_html__('Shortcode', 'event_espresso')
992
+					   . '</a> ';
993
+			$return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
994
+					   . $post->ID
995
+					   . ']">';
996
+		}
997
+		return $return;
998
+	}
999
+
1000
+
1001
+	/**
1002
+	 * _events_overview_list_table
1003
+	 * This contains the logic for showing the events_overview list
1004
+	 *
1005
+	 * @return void
1006
+	 * @throws DomainException
1007
+	 * @throws EE_Error
1008
+	 * @throws InvalidArgumentException
1009
+	 * @throws InvalidDataTypeException
1010
+	 * @throws InvalidInterfaceException
1011
+	 */
1012
+	protected function _events_overview_list_table()
1013
+	{
1014
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1015
+		$this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
1016
+			? (array) $this->_template_args['after_list_table']
1017
+			: [];
1018
+		$this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
1019
+																			  . EEH_Template::get_button_or_link(
1020
+																				  get_post_type_archive_link('espresso_events'),
1021
+																				  esc_html__('View Event Archive Page', 'event_espresso'),
1022
+																				  'button'
1023
+																			  );
1024
+		$this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
1025
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1026
+			'create_new',
1027
+			'add',
1028
+			[],
1029
+			'add-new-h2'
1030
+		);
1031
+		$this->display_admin_list_table_page_with_no_sidebar();
1032
+	}
1033
+
1034
+
1035
+	/**
1036
+	 * this allows for extra misc actions in the default WP publish box
1037
+	 *
1038
+	 * @return void
1039
+	 * @throws DomainException
1040
+	 * @throws EE_Error
1041
+	 * @throws InvalidArgumentException
1042
+	 * @throws InvalidDataTypeException
1043
+	 * @throws InvalidInterfaceException
1044
+	 * @throws ReflectionException
1045
+	 */
1046
+	public function extra_misc_actions_publish_box()
1047
+	{
1048
+		$this->_generate_publish_box_extra_content();
1049
+	}
1050
+
1051
+
1052
+	/**
1053
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1054
+	 * saved.
1055
+	 * Typically you would use this to save any additional data.
1056
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
1057
+	 * ALSO very important.  When a post transitions from scheduled to published,
1058
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1059
+	 * other meta saves. So MAKE sure that you handle this accordingly.
1060
+	 *
1061
+	 * @abstract
1062
+	 * @param string $post_id The ID of the cpt that was saved (so you can link relationally)
1063
+	 * @param object $post    The post object of the cpt that was saved.
1064
+	 * @return void
1065
+	 * @throws EE_Error
1066
+	 * @throws InvalidArgumentException
1067
+	 * @throws InvalidDataTypeException
1068
+	 * @throws InvalidInterfaceException
1069
+	 * @throws ReflectionException
1070
+	 */
1071
+	protected function _insert_update_cpt_item($post_id, $post)
1072
+	{
1073
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1074
+			// get out we're not processing an event save.
1075
+			return;
1076
+		}
1077
+		$event_values = [
1078
+			'EVT_member_only'     => ! empty($this->_req_data['member_only']) ? 1 : 0,
1079
+			'EVT_allow_overflow'  => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
1080
+			'EVT_timezone_string' => ! empty($this->_req_data['timezone_string'])
1081
+				? sanitize_text_field($this->_req_data['timezone_string'])
1082
+				: null,
1083
+		];
1084
+		/** @var FeatureFlags $flags */
1085
+		$flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1086
+		// check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1087
+		if (! $this->admin_config->useAdvancedEditor() || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1088
+			$event_values['EVT_display_ticket_selector'] =
1089
+				! empty($this->_req_data['display_ticket_selector'])
1090
+					? 1
1091
+					: 0;
1092
+			$event_values['EVT_additional_limit'] = min(
1093
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1094
+				! empty($this->_req_data['additional_limit'])
1095
+					? absint($this->_req_data['additional_limit'])
1096
+					: null
1097
+			);
1098
+			$event_values['EVT_default_registration_status'] =
1099
+				! empty($this->_req_data['EVT_default_registration_status'])
1100
+					? sanitize_text_field($this->_req_data['EVT_default_registration_status'])
1101
+					: EE_Registry::instance()->CFG->registration->default_STS_ID;
1102
+			$event_values['EVT_external_URL'] = ! empty($this->_req_data['externalURL'])
1103
+				? esc_url_raw($this->_req_data['externalURL'])
1104
+				: null;
1105
+			$event_values['EVT_phone'] = ! empty($this->_req_data['event_phone'])
1106
+				? sanitize_text_field($this->_req_data['event_phone'])
1107
+				: null;
1108
+		}
1109
+		// update event
1110
+		$success = $this->eventModel()->update_by_ID($event_values, $post_id);
1111
+		// get event_object for other metaboxes...
1112
+		// though it would seem to make sense to just use $this->eventModel()->get_one_by_ID( $post_id )..
1113
+		// i have to setup where conditions to override the filters in the model
1114
+		// that filter out autodraft and inherit statuses so we GET the inherit id!
1115
+		$get_one_where = [
1116
+			$this->eventModel()->primary_key_name() => $post_id,
1117
+			'OR'                                    => [
1118
+				'status'   => $post->post_status,
1119
+				// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1120
+				// but the returned object here has a status of "publish", so use the original post status as well
1121
+				'status*1' => $this->_req_data['original_post_status'],
1122
+			],
1123
+		];
1124
+		$event = $this->eventModel()->get_one([$get_one_where]);
1125
+		// the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1126
+		$event_update_callbacks = apply_filters(
1127
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1128
+			[
1129
+				[$this, '_default_venue_update'],
1130
+				[$this, '_default_tickets_update'],
1131
+			]
1132
+		);
1133
+		$att_success = true;
1134
+		foreach ($event_update_callbacks as $e_callback) {
1135
+			$_success = is_callable($e_callback)
1136
+				? $e_callback($event, $this->_req_data)
1137
+				: false;
1138
+			// if ANY of these updates fail then we want the appropriate global error message
1139
+			$att_success = ! $att_success ? $att_success : $_success;
1140
+		}
1141
+		// any errors?
1142
+		if ($success && false === $att_success) {
1143
+			EE_Error::add_error(
1144
+				esc_html__(
1145
+					'Event Details saved successfully but something went wrong with saving attachments.',
1146
+					'event_espresso'
1147
+				),
1148
+				__FILE__,
1149
+				__FUNCTION__,
1150
+				__LINE__
1151
+			);
1152
+		} elseif ($success === false) {
1153
+			EE_Error::add_error(
1154
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1155
+				__FILE__,
1156
+				__FUNCTION__,
1157
+				__LINE__
1158
+			);
1159
+		}
1160
+	}
1161
+
1162
+
1163
+	/**
1164
+	 * @param int $post_id
1165
+	 * @param int $revision_id
1166
+	 * @throws EE_Error
1167
+	 * @throws InvalidArgumentException
1168
+	 * @throws InvalidDataTypeException
1169
+	 * @throws InvalidInterfaceException
1170
+	 * @throws ReflectionException
1171
+	 * @see parent::restore_item()
1172
+	 */
1173
+	protected function _restore_cpt_item($post_id, $revision_id)
1174
+	{
1175
+		// copy existing event meta to new post
1176
+		$post_evt = $this->eventModel()->get_one_by_ID($post_id);
1177
+		if ($post_evt instanceof EE_Event) {
1178
+			// meta revision restore
1179
+			$post_evt->restore_revision($revision_id);
1180
+			// related objs restore
1181
+			$post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1182
+		}
1183
+	}
1184
+
1185
+
1186
+	/**
1187
+	 * Attach the venue to the Event
1188
+	 *
1189
+	 * @param EE_Event $evtobj Event Object to add the venue to
1190
+	 * @param array    $data   The request data from the form
1191
+	 * @return bool           Success or fail.
1192
+	 * @throws EE_Error
1193
+	 * @throws InvalidArgumentException
1194
+	 * @throws InvalidDataTypeException
1195
+	 * @throws InvalidInterfaceException
1196
+	 * @throws ReflectionException
1197
+	 */
1198
+	protected function _default_venue_update(EE_Event $evtobj, $data)
1199
+	{
1200
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1201
+		$venue_model = EEM_Venue::instance();
1202
+		$rows_affected = null;
1203
+		$venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1204
+		// very important.  If we don't have a venue name...
1205
+		// then we'll get out because not necessary to create empty venue
1206
+		if (empty($data['venue_title'])) {
1207
+			return false;
1208
+		}
1209
+		$venue_array = [
1210
+			'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1211
+			'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1212
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1213
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1214
+			'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1215
+				: null,
1216
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1217
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1218
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1219
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1220
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1221
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1222
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1223
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1224
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1225
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1226
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1227
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1228
+			'status'              => 'publish',
1229
+		];
1230
+		// if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1231
+		if (! empty($venue_id)) {
1232
+			$update_where = [$venue_model->primary_key_name() => $venue_id];
1233
+			$rows_affected = $venue_model->update($venue_array, [$update_where]);
1234
+			// we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1235
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1236
+			return $rows_affected > 0;
1237
+		}
1238
+		// we insert the venue
1239
+		$venue_id = $venue_model->insert($venue_array);
1240
+		$evtobj->_add_relation_to($venue_id, 'Venue');
1241
+		return ! empty($venue_id) ? true : false;
1242
+		// when we have the ancestor come in it's already been handled by the revision save.
1243
+	}
1244
+
1245
+
1246
+	/**
1247
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1248
+	 *
1249
+	 * @param EE_Event $evtobj The Event object we're attaching data to
1250
+	 * @param array    $data   The request data from the form
1251
+	 * @return array
1252
+	 * @throws EE_Error
1253
+	 * @throws InvalidArgumentException
1254
+	 * @throws InvalidDataTypeException
1255
+	 * @throws InvalidInterfaceException
1256
+	 * @throws ReflectionException
1257
+	 * @throws Exception
1258
+	 */
1259
+	protected function _default_tickets_update(EE_Event $evtobj, $data)
1260
+	{
1261
+		if ($this->admin_config->useAdvancedEditor()) {
1262
+			return [];
1263
+		}
1264
+		$saved_dtt = null;
1265
+		$saved_tickets = [];
1266
+		$incoming_date_formats = ['Y-m-d', 'h:i a'];
1267
+		$event_timezone_string = $evtobj->get_timezone();
1268
+		$event_timezone = new DateTimeZone($event_timezone_string);
1269
+		// let's use now in the set timezone.
1270
+		$now = new DateTime('now', $event_timezone);
1271
+		foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1272
+			// trim all values to ensure any excess whitespace is removed.
1273
+			$dtt = array_map('trim', $dtt);
1274
+			$dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end'])
1275
+				? $dtt['DTT_EVT_end']
1276
+				: $dtt['DTT_EVT_start'];
1277
+			$datetime_values = [
1278
+				'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1279
+				'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1280
+				'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1281
+				'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1282
+				'DTT_order'     => $row,
1283
+			];
1284
+			// if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1285
+			if (! empty($dtt['DTT_ID'])) {
1286
+				$DTM = $this->datetimeModel($event_timezone_string)->get_one_by_ID($dtt['DTT_ID']);
1287
+				$DTM->set_date_format($incoming_date_formats[0]);
1288
+				$DTM->set_time_format($incoming_date_formats[1]);
1289
+				foreach ($datetime_values as $field => $value) {
1290
+					$DTM->set($field, $value);
1291
+				}
1292
+				// make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1293
+				$saved_dtts[ $DTM->ID() ] = $DTM;
1294
+			} else {
1295
+				$DTM = EE_Registry::instance()->load_class(
1296
+					'Datetime',
1297
+					[$datetime_values, $event_timezone_string, $incoming_date_formats],
1298
+					false,
1299
+					false
1300
+				);
1301
+				foreach ($datetime_values as $field => $value) {
1302
+					$DTM->set($field, $value);
1303
+				}
1304
+			}
1305
+			$DTM->save();
1306
+			$DTM = $evtobj->_add_relation_to($DTM, 'Datetime');
1307
+			// load DTT helper
1308
+			// before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1309
+			if ($DTM->get_raw('DTT_EVT_start') > $DTM->get_raw('DTT_EVT_end')) {
1310
+				$DTM->set('DTT_EVT_end', $DTM->get('DTT_EVT_start'));
1311
+				$DTM = EEH_DTT_Helper::date_time_add($DTM, 'DTT_EVT_end', 'days');
1312
+				$DTM->save();
1313
+			}
1314
+			// now we got to make sure we add the new DTT_ID to the $saved_dtts array
1315
+			//  because it is possible there was a new one created for the autosave.
1316
+			$saved_dtt = $DTM;
1317
+			// if ANY of these updates fail then we want the appropriate global error message.
1318
+			// //todo this is actually sucky we need a better error message but this is what it is for now.
1319
+		}
1320
+		// no dtts get deleted so we don't do any of that logic here.
1321
+		// update tickets next
1322
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1323
+		foreach ($data['edit_tickets'] as $row => $tkt) {
1324
+			$incoming_date_formats = ['Y-m-d', 'h:i a'];
1325
+			$update_prices = false;
1326
+			$ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1327
+				? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1328
+			// trim inputs to ensure any excess whitespace is removed.
1329
+			$tkt = array_map('trim', $tkt);
1330
+			if (empty($tkt['TKT_start_date'])) {
1331
+				$tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1332
+			}
1333
+			if (empty($tkt['TKT_end_date'])) {
1334
+				// use the start date of the first datetime
1335
+				$dtt = $evtobj->first_datetime();
1336
+				$tkt['TKT_end_date'] = $dtt->start_date_and_time(
1337
+					$incoming_date_formats[0],
1338
+					$incoming_date_formats[1]
1339
+				);
1340
+			}
1341
+			$TKT_values = [
1342
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1343
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1344
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1345
+				'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1346
+				'TKT_start_date'  => $tkt['TKT_start_date'],
1347
+				'TKT_end_date'    => $tkt['TKT_end_date'],
1348
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1349
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1350
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1351
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1352
+				'TKT_row'         => $row,
1353
+				'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1354
+				'TKT_price'       => $ticket_price,
1355
+			];
1356
+			// if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1357
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1358
+				$TKT_values['TKT_ID'] = 0;
1359
+				$TKT_values['TKT_is_default'] = 0;
1360
+				$TKT_values['TKT_price'] = $ticket_price;
1361
+				$update_prices = true;
1362
+			}
1363
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
1364
+			// we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1365
+			// keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1366
+			if (! empty($tkt['TKT_ID'])) {
1367
+				$TKT = $this->ticketModel($event_timezone_string)->get_one_by_ID($tkt['TKT_ID']);
1368
+				if ($TKT instanceof EE_Ticket) {
1369
+					$ticket_sold = $TKT->count_related(
1370
+						'Registration',
1371
+						[
1372
+								[
1373
+									'STS_ID' => [
1374
+										'NOT IN',
1375
+										[EEM_Registration::status_id_incomplete],
1376
+									],
1377
+								],
1378
+							]
1379
+					) > 0;
1380
+					// let's just check the total price for the existing ticket and determine if it matches the new
1381
+					// total price.  if they are different then we create a new ticket (if tickets sold)
1382
+					// if they aren't different then we go ahead and modify existing ticket.
1383
+					$create_new_TKT = $ticket_sold && ! $TKT->deleted()
1384
+									  && EEH_Money::compare_floats(
1385
+										  $ticket_price,
1386
+										  $TKT->get('TKT_price'),
1387
+										  '!=='
1388
+									  );
1389
+					$TKT->set_date_format($incoming_date_formats[0]);
1390
+					$TKT->set_time_format($incoming_date_formats[1]);
1391
+					// set new values
1392
+					foreach ($TKT_values as $field => $value) {
1393
+						if ($field === 'TKT_qty') {
1394
+							$TKT->set_qty($value);
1395
+						} else {
1396
+							$TKT->set($field, $value);
1397
+						}
1398
+					}
1399
+					// if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1400
+					if ($create_new_TKT) {
1401
+						// archive the old ticket first
1402
+						$TKT->set('TKT_deleted', 1);
1403
+						$TKT->save();
1404
+						// make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1405
+						$saved_tickets[ $TKT->ID() ] = $TKT;
1406
+						// create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1407
+						$TKT = clone $TKT;
1408
+						$TKT->set('TKT_ID', 0);
1409
+						$TKT->set('TKT_deleted', 0);
1410
+						$TKT->set('TKT_price', $ticket_price);
1411
+						$TKT->set('TKT_sold', 0);
1412
+						// now we need to make sure that $new prices are created as well and attached to new ticket.
1413
+						$update_prices = true;
1414
+					}
1415
+					// make sure price is set if it hasn't been already
1416
+					$TKT->set('TKT_price', $ticket_price);
1417
+				}
1418
+			} else {
1419
+				// no TKT_id so a new TKT
1420
+				$TKT_values['TKT_price'] = $ticket_price;
1421
+				$TKT = EE_Registry::instance()->load_class('Ticket', [$TKT_values], false, false);
1422
+				if ($TKT instanceof EE_Ticket) {
1423
+					// need to reset values to properly account for the date formats
1424
+					$TKT->set_date_format($incoming_date_formats[0]);
1425
+					$TKT->set_time_format($incoming_date_formats[1]);
1426
+					$TKT->set_timezone($evtobj->get_timezone());
1427
+					// set new values
1428
+					foreach ($TKT_values as $field => $value) {
1429
+						if ($field === 'TKT_qty') {
1430
+							$TKT->set_qty($value);
1431
+						} else {
1432
+							$TKT->set($field, $value);
1433
+						}
1434
+					}
1435
+					$update_prices = true;
1436
+				}
1437
+			}
1438
+			// cap ticket qty by datetime reg limits
1439
+			$TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1440
+			// update ticket.
1441
+			$TKT->save();
1442
+			// before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1443
+			if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1444
+				$TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1445
+				$TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1446
+				$TKT->save();
1447
+			}
1448
+			// initially let's add the ticket to the dtt
1449
+			$saved_dtt->_add_relation_to($TKT, 'Ticket');
1450
+			$saved_tickets[ $TKT->ID() ] = $TKT;
1451
+			// add prices to ticket
1452
+			$this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1453
+		}
1454
+		// however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1455
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1456
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1457
+		foreach ($tickets_removed as $id) {
1458
+			$id = absint($id);
1459
+			// get the ticket for this id
1460
+			$tkt_to_remove = $this->ticketModel($event_timezone_string)->get_one_by_ID($id);
1461
+			// need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1462
+			$dtts = $tkt_to_remove->get_many_related('Datetime');
1463
+			foreach ($dtts as $dtt) {
1464
+				$tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1465
+			}
1466
+			// need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1467
+			$tkt_to_remove->delete_related_permanently('Price');
1468
+			// finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1469
+			$tkt_to_remove->delete_permanently();
1470
+		}
1471
+		return [$saved_dtt, $saved_tickets];
1472
+	}
1473
+
1474
+
1475
+	/**
1476
+	 * This attaches a list of given prices to a ticket.
1477
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1478
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1479
+	 * price info and prices are automatically "archived" via the ticket.
1480
+	 *
1481
+	 * @param array     $prices     Array of prices from the form.
1482
+	 * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1483
+	 * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1484
+	 * @return  void
1485
+	 * @throws EE_Error
1486
+	 * @throws InvalidArgumentException
1487
+	 * @throws InvalidDataTypeException
1488
+	 * @throws InvalidInterfaceException
1489
+	 * @throws ReflectionException
1490
+	 */
1491
+	private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1492
+	{
1493
+		foreach ($prices as $row => $prc) {
1494
+			$PRC_values = [
1495
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1496
+				'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1497
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1498
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1499
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1500
+				'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1501
+				'PRC_order'      => $row,
1502
+			];
1503
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
1504
+				$PRC_values['PRC_ID'] = 0;
1505
+				$PRC = EE_Registry::instance()->load_class('Price', [$PRC_values], false, false);
1506
+			} else {
1507
+				$PRC = EEM_Price::instance()->get_one_by_ID($prc['PRC_ID']);
1508
+				// update this price with new values
1509
+				foreach ($PRC_values as $field => $newprc) {
1510
+					$PRC->set($field, $newprc);
1511
+				}
1512
+				$PRC->save();
1513
+			}
1514
+			$ticket->_add_relation_to($PRC, 'Price');
1515
+		}
1516
+	}
1517
+
1518
+
1519
+	/**
1520
+	 * Add in our autosave ajax handlers
1521
+	 *
1522
+	 */
1523
+	protected function _ee_autosave_create_new()
1524
+	{
1525
+	}
1526
+
1527
+
1528
+	/**
1529
+	 * More autosave handlers.
1530
+	 */
1531
+	protected function _ee_autosave_edit()
1532
+	{
1533
+	}
1534
+
1535
+
1536
+	/**
1537
+	 *    _generate_publish_box_extra_content
1538
+	 *
1539
+	 * @throws DomainException
1540
+	 * @throws EE_Error
1541
+	 * @throws InvalidArgumentException
1542
+	 * @throws InvalidDataTypeException
1543
+	 * @throws InvalidInterfaceException
1544
+	 * @throws ReflectionException
1545
+	 */
1546
+	private function _generate_publish_box_extra_content()
1547
+	{
1548
+		// load formatter helper
1549
+		// args for getting related registrations
1550
+		$approved_query_args = [
1551
+			[
1552
+				'REG_deleted' => 0,
1553
+				'STS_ID'      => EEM_Registration::status_id_approved,
1554
+			],
1555
+		];
1556
+		$not_approved_query_args = [
1557
+			[
1558
+				'REG_deleted' => 0,
1559
+				'STS_ID'      => EEM_Registration::status_id_not_approved,
1560
+			],
1561
+		];
1562
+		$pending_payment_query_args = [
1563
+			[
1564
+				'REG_deleted' => 0,
1565
+				'STS_ID'      => EEM_Registration::status_id_pending_payment,
1566
+			],
1567
+		];
1568
+		// publish box
1569
+		$publish_box_extra_args = [
1570
+			'view_approved_reg_url'        => add_query_arg(
1571
+				[
1572
+					'action'      => 'default',
1573
+					'event_id'    => $this->_cpt_model_obj->ID(),
1574
+					'_reg_status' => EEM_Registration::status_id_approved,
1575
+				],
1576
+				REG_ADMIN_URL
1577
+			),
1578
+			'view_not_approved_reg_url'    => add_query_arg(
1579
+				[
1580
+					'action'      => 'default',
1581
+					'event_id'    => $this->_cpt_model_obj->ID(),
1582
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1583
+				],
1584
+				REG_ADMIN_URL
1585
+			),
1586
+			'view_pending_payment_reg_url' => add_query_arg(
1587
+				[
1588
+					'action'      => 'default',
1589
+					'event_id'    => $this->_cpt_model_obj->ID(),
1590
+					'_reg_status' => EEM_Registration::status_id_pending_payment,
1591
+				],
1592
+				REG_ADMIN_URL
1593
+			),
1594
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1595
+				'Registration',
1596
+				$approved_query_args
1597
+			),
1598
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1599
+				'Registration',
1600
+				$not_approved_query_args
1601
+			),
1602
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1603
+				'Registration',
1604
+				$pending_payment_query_args
1605
+			),
1606
+			'misc_pub_section_class'       => apply_filters(
1607
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1608
+				'misc-pub-section'
1609
+			),
1610
+		];
1611
+		ob_start();
1612
+		do_action(
1613
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1614
+			$this->_cpt_model_obj
1615
+		);
1616
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1617
+		// load template
1618
+		EEH_Template::display_template(
1619
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1620
+			$publish_box_extra_args
1621
+		);
1622
+	}
1623
+
1624
+
1625
+	/**
1626
+	 * @return EE_Event
1627
+	 */
1628
+	public function get_event_object()
1629
+	{
1630
+		return $this->_cpt_model_obj;
1631
+	}
1632
+
1633
+
1634
+
1635
+
1636
+	/** METABOXES * */
1637
+	/**
1638
+	 * _register_event_editor_meta_boxes
1639
+	 * add all metaboxes related to the event_editor
1640
+	 *
1641
+	 * @return void
1642
+	 * @throws EE_Error
1643
+	 * @throws InvalidArgumentException
1644
+	 * @throws InvalidDataTypeException
1645
+	 * @throws InvalidInterfaceException
1646
+	 * @throws ReflectionException
1647
+	 */
1648
+	protected function _register_event_editor_meta_boxes()
1649
+	{
1650
+		$this->verify_cpt_object();
1651
+		$use_advanced_editor = $this->admin_config->useAdvancedEditor();
1652
+		/** @var FeatureFlags $flags */
1653
+		$flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1654
+		// check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1655
+		if (! $use_advanced_editor || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1656
+			add_meta_box(
1657
+				'espresso_event_editor_event_options',
1658
+				esc_html__('Event Registration Options', 'event_espresso'),
1659
+				[$this, 'registration_options_meta_box'],
1660
+				$this->page_slug,
1661
+				'side'
1662
+			);
1663
+		}
1664
+		if (! $use_advanced_editor) {
1665
+			add_meta_box(
1666
+				'espresso_event_editor_tickets',
1667
+				esc_html__('Event Datetime & Ticket', 'event_espresso'),
1668
+				[$this, 'ticket_metabox'],
1669
+				$this->page_slug,
1670
+				'normal',
1671
+				'high'
1672
+			);
1673
+		} else {
1674
+			if ($flags->featureAllowed('use_reg_options_meta_box')) {
1675
+				add_action(
1676
+					'add_meta_boxes_espresso_events',
1677
+					function () {
1678
+						global $current_screen;
1679
+						remove_meta_box('authordiv', $current_screen, 'normal');
1680
+					},
1681
+					99
1682
+				);
1683
+			}
1684
+		}
1685
+		// NOTE: if you're looking for other metaboxes in here,
1686
+		// where a metabox has a related management page in the admin
1687
+		// you will find it setup in the related management page's "_Hooks" file.
1688
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1689
+	}
1690
+
1691
+
1692
+	/**
1693
+	 * @throws DomainException
1694
+	 * @throws EE_Error
1695
+	 * @throws InvalidArgumentException
1696
+	 * @throws InvalidDataTypeException
1697
+	 * @throws InvalidInterfaceException
1698
+	 * @throws ReflectionException
1699
+	 */
1700
+	public function ticket_metabox()
1701
+	{
1702
+		$existing_datetime_ids = $existing_ticket_ids = [];
1703
+		// defaults for template args
1704
+		$template_args = [
1705
+			'existing_datetime_ids'    => '',
1706
+			'event_datetime_help_link' => '',
1707
+			'ticket_options_help_link' => '',
1708
+			'time'                     => null,
1709
+			'ticket_rows'              => '',
1710
+			'existing_ticket_ids'      => '',
1711
+			'total_ticket_rows'        => 1,
1712
+			'ticket_js_structure'      => '',
1713
+			'trash_icon'               => 'ee-lock-icon',
1714
+			'disabled'                 => '',
1715
+		];
1716
+		$event_id = $this->_cpt_model_obj instanceof EE_Event ? $this->_cpt_model_obj->ID() : 0;
1717
+		$event_timezone_string = $this->_cpt_model_obj instanceof EE_Event
1718
+			? $this->_cpt_model_obj->timezone_string()
1719
+			: '';
1720
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1721
+		/**
1722
+		 * 1. Start with retrieving Datetimes
1723
+		 * 2. Fore each datetime get related tickets
1724
+		 * 3. For each ticket get related prices
1725
+		 */
1726
+		$times = $this->datetimeModel($event_timezone_string)->get_all_event_dates($event_id);
1727
+		/** @type EE_Datetime $first_datetime */
1728
+		$first_datetime = reset($times);
1729
+		// do we get related tickets?
1730
+		if (
1731
+			$first_datetime instanceof EE_Datetime
1732
+			&& $first_datetime->ID() !== 0
1733
+		) {
1734
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1735
+			$template_args['time'] = $first_datetime;
1736
+			$related_tickets = $first_datetime->tickets(
1737
+				[
1738
+					['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1739
+					'default_where_conditions' => 'none',
1740
+				]
1741
+			);
1742
+			if (! empty($related_tickets)) {
1743
+				$template_args['total_ticket_rows'] = count($related_tickets);
1744
+				$row = 0;
1745
+				foreach ($related_tickets as $ticket) {
1746
+					$existing_ticket_ids[] = $ticket->get('TKT_ID');
1747
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1748
+					$row++;
1749
+				}
1750
+			} else {
1751
+				$template_args['total_ticket_rows'] = 1;
1752
+				/** @type EE_Ticket $ticket */
1753
+				$ticket = $this->ticketModel($event_timezone_string)->create_default_object();
1754
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1755
+			}
1756
+		} else {
1757
+			$template_args['time'] = $times[0];
1758
+			/** @type EE_Ticket $ticket */
1759
+			$ticket = $this->ticketModel($event_timezone_string)->get_all_default_tickets();
1760
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1761
+			// NOTE: we're just sending the first default row
1762
+			// (decaf can't manage default tickets so this should be sufficient);
1763
+		}
1764
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1765
+			'event_editor_event_datetimes_help_tab'
1766
+		);
1767
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1768
+		$template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1769
+		$template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1770
+		$template_args['ticket_js_structure'] = $this->_get_ticket_row(
1771
+			$this->ticketModel($event_timezone_string)->create_default_object(),
1772
+			true
1773
+		);
1774
+		$template = apply_filters(
1775
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1776
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1777
+		);
1778
+		EEH_Template::display_template($template, $template_args);
1779
+	}
1780
+
1781
+
1782
+	/**
1783
+	 * Setup an individual ticket form for the decaf event editor page
1784
+	 *
1785
+	 * @param EE_Ticket $ticket   the ticket object
1786
+	 * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1787
+	 * @param int       $row
1788
+	 * @return string generated html for the ticket row.
1789
+	 * @throws DomainException
1790
+	 * @throws EE_Error
1791
+	 * @throws InvalidArgumentException
1792
+	 * @throws InvalidDataTypeException
1793
+	 * @throws InvalidInterfaceException
1794
+	 * @throws ReflectionException
1795
+	 */
1796
+	private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1797
+	{
1798
+		$template_args = [
1799
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1800
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1801
+				: '',
1802
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1803
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1804
+			'TKT_name'            => $ticket->get('TKT_name'),
1805
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1806
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1807
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1808
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1809
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1810
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1811
+			'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1812
+									 && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1813
+				? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1814
+			'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1815
+				: ' disabled=disabled',
1816
+		];
1817
+		$price = $ticket->ID() !== 0
1818
+			? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1819
+			: EEM_Price::instance()->create_default_object();
1820
+		$price_args = [
1821
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1822
+			'PRC_amount'            => $price->get('PRC_amount'),
1823
+			'PRT_ID'                => $price->get('PRT_ID'),
1824
+			'PRC_ID'                => $price->get('PRC_ID'),
1825
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1826
+		];
1827
+		// make sure we have default start and end dates if skeleton
1828
+		// handle rows that should NOT be empty
1829
+		if (empty($template_args['TKT_start_date'])) {
1830
+			// if empty then the start date will be now.
1831
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1832
+		}
1833
+		if (empty($template_args['TKT_end_date'])) {
1834
+			// get the earliest datetime (if present);
1835
+			$earliest_dtt = $this->_cpt_model_obj->ID() > 0
1836
+				? $this->_cpt_model_obj->get_first_related(
1837
+					'Datetime',
1838
+					['order_by' => ['DTT_EVT_start' => 'ASC']]
1839
+				)
1840
+				: null;
1841
+			if (! empty($earliest_dtt)) {
1842
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1843
+			} else {
1844
+				$template_args['TKT_end_date'] = date(
1845
+					'Y-m-d h:i a',
1846
+					mktime(0, 0, 0, date('m'), date('d') + 7, date('Y'))
1847
+				);
1848
+			}
1849
+		}
1850
+		$template_args = array_merge($template_args, $price_args);
1851
+		$template = apply_filters(
1852
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1853
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1854
+			$ticket
1855
+		);
1856
+		return EEH_Template::display_template($template, $template_args, true);
1857
+	}
1858
+
1859
+
1860
+	/**
1861
+	 * @throws DomainException
1862
+	 * @throws EE_Error
1863
+	 */
1864
+	public function registration_options_meta_box()
1865
+	{
1866
+		$yes_no_values = [
1867
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1868
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1869
+		];
1870
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1871
+			[
1872
+				EEM_Registration::status_id_cancelled,
1873
+				EEM_Registration::status_id_declined,
1874
+				EEM_Registration::status_id_incomplete,
1875
+			],
1876
+			true
1877
+		);
1878
+		// $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1879
+		$template_args['_event'] = $this->_cpt_model_obj;
1880
+		$template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1881
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1882
+		$template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1883
+			'default_reg_status',
1884
+			$default_reg_status_values,
1885
+			$this->_cpt_model_obj->default_registration_status()
1886
+		);
1887
+		$template_args['display_description'] = EEH_Form_Fields::select_input(
1888
+			'display_desc',
1889
+			$yes_no_values,
1890
+			$this->_cpt_model_obj->display_description()
1891
+		);
1892
+		$template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1893
+			'display_ticket_selector',
1894
+			$yes_no_values,
1895
+			$this->_cpt_model_obj->display_ticket_selector(),
1896
+			'',
1897
+			'',
1898
+			false
1899
+		);
1900
+		$template_args['additional_registration_options'] = apply_filters(
1901
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1902
+			'',
1903
+			$template_args,
1904
+			$yes_no_values,
1905
+			$default_reg_status_values
1906
+		);
1907
+		EEH_Template::display_template(
1908
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1909
+			$template_args
1910
+		);
1911
+	}
1912
+
1913
+
1914
+	/**
1915
+	 * _get_events()
1916
+	 * This method simply returns all the events (for the given _view and paging)
1917
+	 *
1918
+	 * @param int  $per_page     count of items per page (20 default);
1919
+	 * @param int  $current_page what is the current page being viewed.
1920
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1921
+	 *                           If FALSE then we return an array of event objects
1922
+	 *                           that match the given _view and paging parameters.
1923
+	 * @return array|int         an array of event objects or count of how many events.
1924
+	 * @throws EE_Error
1925
+	 * @throws InvalidArgumentException
1926
+	 * @throws InvalidDataTypeException
1927
+	 * @throws InvalidInterfaceException
1928
+	 * @throws ReflectionException
1929
+	 * @throws Exception
1930
+	 * @throws Exception
1931
+	 * @throws Exception
1932
+	 */
1933
+	public function get_events($per_page = 10, $current_page = 1, $count = false)
1934
+	{
1935
+		$EEME = $this->eventModel();
1936
+		$offset = ($current_page - 1) * $per_page;
1937
+		$limit = $count ? null : $offset . ',' . $per_page;
1938
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1939
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1940
+		if (isset($this->_req_data['month_range'])) {
1941
+			$pieces = explode(' ', $this->_req_data['month_range'], 3);
1942
+			// simulate the FIRST day of the month, that fixes issues for months like February
1943
+			// where PHP doesn't know what to assume for date.
1944
+			// @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1945
+			$month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1946
+			$year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1947
+		}
1948
+		$where = [];
1949
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1950
+		// determine what post_status our condition will have for the query.
1951
+		switch ($status) {
1952
+			case 'month':
1953
+			case 'today':
1954
+			case null:
1955
+			case 'all':
1956
+				break;
1957
+			case 'draft':
1958
+				$where['status'] = ['IN', ['draft', 'auto-draft']];
1959
+				break;
1960
+			default:
1961
+				$where['status'] = $status;
1962
+		}
1963
+		// categories?
1964
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1965
+			? $this->_req_data['EVT_CAT'] : null;
1966
+		if (! empty($category)) {
1967
+			$where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1968
+			$where['Term_Taxonomy.term_id'] = $category;
1969
+		}
1970
+		// date where conditions
1971
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1972
+		if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] !== '') {
1973
+			$DateTime = new DateTime(
1974
+				$year_r . '-' . $month_r . '-01 00:00:00',
1975
+				new DateTimeZone('UTC')
1976
+			);
1977
+			$start = $DateTime->getTimestamp();
1978
+			// set the datetime to be the end of the month
1979
+			$DateTime->setDate(
1980
+				$year_r,
1981
+				$month_r,
1982
+				$DateTime->format('t')
1983
+			)->setTime(23, 59, 59);
1984
+			$end = $DateTime->getTimestamp();
1985
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1986
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'today') {
1987
+			$DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1988
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1989
+			$end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1990
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1991
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'month') {
1992
+			$now = date('Y-m-01');
1993
+			$DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1994
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1995
+			$end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1996
+							->setTime(23, 59, 59)
1997
+							->format(implode(' ', $start_formats));
1998
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1999
+		}
2000
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
2001
+			$where['EVT_wp_user'] = get_current_user_id();
2002
+		} elseif (
2003
+			! isset($where['status'])
2004
+				  && ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')
2005
+		) {
2006
+			$where['OR'] = [
2007
+				'status*restrict_private' => ['!=', 'private'],
2008
+				'AND'                     => [
2009
+					'status*inclusive' => ['=', 'private'],
2010
+					'EVT_wp_user'      => get_current_user_id(),
2011
+				],
2012
+			];
2013
+		}
2014
+
2015
+		if (
2016
+			isset($this->_req_data['EVT_wp_user'])
2017
+			&& (int) $this->_req_data['EVT_wp_user'] !== (int) get_current_user_id()
2018
+			&& EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
2019
+		) {
2020
+			$where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
2021
+		}
2022
+		// search query handling
2023
+		if (isset($this->_req_data['s'])) {
2024
+			$search_string = '%' . $this->_req_data['s'] . '%';
2025
+			$where['OR'] = [
2026
+				'EVT_name'       => ['LIKE', $search_string],
2027
+				'EVT_desc'       => ['LIKE', $search_string],
2028
+				'EVT_short_desc' => ['LIKE', $search_string],
2029
+			];
2030
+		}
2031
+		// filter events by venue.
2032
+		if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
2033
+			$where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
2034
+		}
2035
+		$where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
2036
+		$query_params = apply_filters(
2037
+			'FHEE__Events_Admin_Page__get_events__query_params',
2038
+			[
2039
+				$where,
2040
+				'limit'    => $limit,
2041
+				'order_by' => $orderby,
2042
+				'order'    => $order,
2043
+				'group_by' => 'EVT_ID',
2044
+			],
2045
+			$this->_req_data
2046
+		);
2047
+
2048
+		// let's first check if we have special requests coming in.
2049
+		if (isset($this->_req_data['active_status'])) {
2050
+			switch ($this->_req_data['active_status']) {
2051
+				case 'upcoming':
2052
+					return $EEME->get_upcoming_events($query_params, $count);
2053
+					break;
2054
+				case 'expired':
2055
+					return $EEME->get_expired_events($query_params, $count);
2056
+					break;
2057
+				case 'active':
2058
+					return $EEME->get_active_events($query_params, $count);
2059
+					break;
2060
+				case 'inactive':
2061
+					return $EEME->get_inactive_events($query_params, $count);
2062
+					break;
2063
+			}
2064
+		}
2065
+		return $count
2066
+			? $EEME->count([$where], 'EVT_ID', true)
2067
+			: $EEME->get_all($query_params);
2068
+	}
2069
+
2070
+
2071
+	/**
2072
+	 * handling for WordPress CPT actions (trash, restore, delete)
2073
+	 *
2074
+	 * @param string $post_id
2075
+	 * @throws EE_Error
2076
+	 * @throws InvalidArgumentException
2077
+	 * @throws InvalidDataTypeException
2078
+	 * @throws InvalidInterfaceException
2079
+	 * @throws ReflectionException
2080
+	 */
2081
+	public function trash_cpt_item($post_id)
2082
+	{
2083
+		$this->_req_data['EVT_ID'] = $post_id;
2084
+		$this->_trash_or_restore_event('trash', false);
2085
+	}
2086
+
2087
+
2088
+	/**
2089
+	 * @param string $post_id
2090
+	 * @throws EE_Error
2091
+	 * @throws InvalidArgumentException
2092
+	 * @throws InvalidDataTypeException
2093
+	 * @throws InvalidInterfaceException
2094
+	 * @throws ReflectionException
2095
+	 */
2096
+	public function restore_cpt_item($post_id)
2097
+	{
2098
+		$this->_req_data['EVT_ID'] = $post_id;
2099
+		$this->_trash_or_restore_event('draft', false);
2100
+	}
2101
+
2102
+
2103
+	/**
2104
+	 * @param string $post_id
2105
+	 * @throws EE_Error
2106
+	 * @throws InvalidArgumentException
2107
+	 * @throws InvalidDataTypeException
2108
+	 * @throws InvalidInterfaceException
2109
+	 * @throws ReflectionException
2110
+	 */
2111
+	public function delete_cpt_item($post_id)
2112
+	{
2113
+		throw new EE_Error(esc_html__('Please contact Event Espresso support with the details of the steps taken to produce this error.', 'event_espresso'));
2114
+		$this->_req_data['EVT_ID'] = $post_id;
2115
+		$this->_delete_event();
2116
+	}
2117
+
2118
+
2119
+	/**
2120
+	 * _trash_or_restore_event
2121
+	 *
2122
+	 * @param string $event_status
2123
+	 * @param bool   $redirect_after
2124
+	 * @throws EE_Error
2125
+	 * @throws InvalidArgumentException
2126
+	 * @throws InvalidDataTypeException
2127
+	 * @throws InvalidInterfaceException
2128
+	 * @throws ReflectionException
2129
+	 */
2130
+	protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
2131
+	{
2132
+		// determine the event id and set to array.
2133
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
2134
+		// loop thru events
2135
+		if ($EVT_ID) {
2136
+			// clean status
2137
+			$event_status = sanitize_key($event_status);
2138
+			// grab status
2139
+			if (! empty($event_status)) {
2140
+				$success = $this->_change_event_status($EVT_ID, $event_status);
2141
+			} else {
2142
+				$success = false;
2143
+				$msg = esc_html__(
2144
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2145
+					'event_espresso'
2146
+				);
2147
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2148
+			}
2149
+		} else {
2150
+			$success = false;
2151
+			$msg = esc_html__(
2152
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2153
+				'event_espresso'
2154
+			);
2155
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2156
+		}
2157
+		$action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2158
+		if ($redirect_after) {
2159
+			$this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2160
+		}
2161
+	}
2162
+
2163
+
2164
+	/**
2165
+	 * _trash_or_restore_events
2166
+	 *
2167
+	 * @param string $event_status
2168
+	 * @return void
2169
+	 * @throws EE_Error
2170
+	 * @throws InvalidArgumentException
2171
+	 * @throws InvalidDataTypeException
2172
+	 * @throws InvalidInterfaceException
2173
+	 * @throws ReflectionException
2174
+	 */
2175
+	protected function _trash_or_restore_events($event_status = 'trash')
2176
+	{
2177
+		// clean status
2178
+		$event_status = sanitize_key($event_status);
2179
+		// grab status
2180
+		if (! empty($event_status)) {
2181
+			$success = true;
2182
+			// determine the event id and set to array.
2183
+			$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : [];
2184
+			// loop thru events
2185
+			foreach ($EVT_IDs as $EVT_ID) {
2186
+				if ($EVT_ID = absint($EVT_ID)) {
2187
+					$results = $this->_change_event_status($EVT_ID, $event_status);
2188
+					$success = $results !== false ? $success : false;
2189
+				} else {
2190
+					$msg = sprintf(
2191
+						esc_html__(
2192
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2193
+							'event_espresso'
2194
+						),
2195
+						$EVT_ID
2196
+					);
2197
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2198
+					$success = false;
2199
+				}
2200
+			}
2201
+		} else {
2202
+			$success = false;
2203
+			$msg = esc_html__(
2204
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2205
+				'event_espresso'
2206
+			);
2207
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2208
+		}
2209
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2210
+		$success = $success ? 2 : false;
2211
+		$action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2212
+		$this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2213
+	}
2214
+
2215
+
2216
+	/**
2217
+	 * _trash_or_restore_events
2218
+	 *
2219
+	 * @param int    $EVT_ID
2220
+	 * @param string $event_status
2221
+	 * @return bool
2222
+	 * @throws EE_Error
2223
+	 * @throws InvalidArgumentException
2224
+	 * @throws InvalidDataTypeException
2225
+	 * @throws InvalidInterfaceException
2226
+	 * @throws ReflectionException
2227
+	 */
2228
+	private function _change_event_status($EVT_ID = 0, $event_status = '')
2229
+	{
2230
+		// grab event id
2231
+		if (! $EVT_ID) {
2232
+			$msg = esc_html__(
2233
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2234
+				'event_espresso'
2235
+			);
2236
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2237
+			return false;
2238
+		}
2239
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2240
+		// clean status
2241
+		$event_status = sanitize_key($event_status);
2242
+		// grab status
2243
+		if (empty($event_status)) {
2244
+			$msg = esc_html__(
2245
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2246
+				'event_espresso'
2247
+			);
2248
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2249
+			return false;
2250
+		}
2251
+		// was event trashed or restored ?
2252
+		switch ($event_status) {
2253
+			case 'draft':
2254
+				$action = 'restored from the trash';
2255
+				$hook = 'AHEE_event_restored_from_trash';
2256
+				break;
2257
+			case 'trash':
2258
+				$action = 'moved to the trash';
2259
+				$hook = 'AHEE_event_moved_to_trash';
2260
+				break;
2261
+			default:
2262
+				$action = 'updated';
2263
+				$hook = false;
2264
+		}
2265
+		// use class to change status
2266
+		$this->_cpt_model_obj->set_status($event_status);
2267
+		$success = $this->_cpt_model_obj->save();
2268
+		if ($success === false) {
2269
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2270
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2271
+			return false;
2272
+		}
2273
+		if ($hook) {
2274
+			do_action($hook);
2275
+		}
2276
+		return true;
2277
+	}
2278
+
2279
+
2280
+	/**
2281
+	 * _delete_event
2282
+	 *
2283
+	 * @param bool $redirect_after
2284
+	 * @throws EE_Error
2285
+	 * @throws InvalidArgumentException
2286
+	 * @throws InvalidDataTypeException
2287
+	 * @throws InvalidInterfaceException
2288
+	 * @throws ReflectionException
2289
+	 */
2290
+	protected function _delete_event()
2291
+	{
2292
+		$this->generateDeletionPreview(isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : []);
2293
+	}
2294
+
2295
+	/**
2296
+	 * Gets the tree traversal batch persister.
2297
+	 * @since $VID:$
2298
+	 * @return NodeGroupDao
2299
+	 * @throws InvalidArgumentException
2300
+	 * @throws InvalidDataTypeException
2301
+	 * @throws InvalidInterfaceException
2302
+	 */
2303
+	protected function getModelObjNodeGroupPersister()
2304
+	{
2305
+		if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2306
+			$this->model_obj_node_group_persister = $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2307
+		}
2308
+		return $this->model_obj_node_group_persister;
2309
+	}
2310
+
2311
+	/**
2312
+	 * _delete_events
2313
+	 *
2314
+	 * @return void
2315
+	 * @throws EE_Error
2316
+	 * @throws InvalidArgumentException
2317
+	 * @throws InvalidDataTypeException
2318
+	 * @throws InvalidInterfaceException
2319
+	 * @throws ReflectionException
2320
+	 */
2321
+	protected function _delete_events()
2322
+	{
2323
+		$this->generateDeletionPreview(isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : []);
2324
+	}
2325
+
2326
+	protected function generateDeletionPreview($event_ids)
2327
+	{
2328
+		$event_ids = (array) $event_ids;
2329
+		// Set a code we can use to reference this deletion task in the batch jobs and preview page.
2330
+		$deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2331
+		$return_url = EE_Admin_Page::add_query_args_and_nonce(
2332
+			[
2333
+				'action' => 'preview_deletion',
2334
+				'deletion_job_code' => $deletion_job_code,
2335
+			],
2336
+			$this->_admin_base_url
2337
+		);
2338
+		$event_ids = array_map(
2339
+			'intval',
2340
+			$event_ids
2341
+		);
2342
+
2343
+		EEH_URL::safeRedirectAndExit(
2344
+			EE_Admin_Page::add_query_args_and_nonce(
2345
+				[
2346
+					'page'              => 'espresso_batch',
2347
+					'batch'             => EED_Batch::batch_job,
2348
+					'EVT_IDs'           => $event_ids,
2349
+					'deletion_job_code' => $deletion_job_code,
2350
+					'job_handler'       => urlencode('EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'),
2351
+					'return_url'        => urlencode($return_url),
2352
+				],
2353
+				admin_url()
2354
+			)
2355
+		);
2356
+	}
2357
+
2358
+	/**
2359
+	 * Checks for a POST submission
2360
+	 * @since $VID:$
2361
+	 */
2362
+	protected function confirmDeletion()
2363
+	{
2364
+		$deletion_redirect_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion');
2365
+		$deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2366
+	}
2367
+
2368
+	/**
2369
+	 * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2370
+	 * @since $VID:$
2371
+	 * @throws EE_Error
2372
+	 */
2373
+	protected function previewDeletion()
2374
+	{
2375
+		$preview_deletion_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\PreviewDeletion');
2376
+		$this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2377
+		$this->display_admin_page_with_no_sidebar();
2378
+	}
2379
+
2380
+	/**
2381
+	 * get total number of events
2382
+	 *
2383
+	 * @return int
2384
+	 * @throws EE_Error
2385
+	 * @throws InvalidArgumentException
2386
+	 * @throws InvalidDataTypeException
2387
+	 * @throws InvalidInterfaceException
2388
+	 */
2389
+	public function total_events()
2390
+	{
2391
+		$count = EEM_Event::instance()->count(['caps' => 'read_admin'], 'EVT_ID', true);
2392
+		return $count;
2393
+	}
2394
+
2395
+
2396
+	/**
2397
+	 * get total number of draft events
2398
+	 *
2399
+	 * @return int
2400
+	 * @throws EE_Error
2401
+	 * @throws InvalidArgumentException
2402
+	 * @throws InvalidDataTypeException
2403
+	 * @throws InvalidInterfaceException
2404
+	 */
2405
+	public function total_events_draft()
2406
+	{
2407
+		$where = [
2408
+			'status' => ['IN', ['draft', 'auto-draft']],
2409
+		];
2410
+		$count = EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
2411
+		return $count;
2412
+	}
2413
+
2414
+
2415
+	/**
2416
+	 * get total number of trashed events
2417
+	 *
2418
+	 * @return int
2419
+	 * @throws EE_Error
2420
+	 * @throws InvalidArgumentException
2421
+	 * @throws InvalidDataTypeException
2422
+	 * @throws InvalidInterfaceException
2423
+	 */
2424
+	public function total_trashed_events()
2425
+	{
2426
+		$where = [
2427
+			'status' => 'trash',
2428
+		];
2429
+		$count = EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
2430
+		return $count;
2431
+	}
2432
+
2433
+
2434
+	/**
2435
+	 *    _default_event_settings
2436
+	 *    This generates the Default Settings Tab
2437
+	 *
2438
+	 * @return void
2439
+	 * @throws DomainException
2440
+	 * @throws EE_Error
2441
+	 * @throws InvalidArgumentException
2442
+	 * @throws InvalidDataTypeException
2443
+	 * @throws InvalidInterfaceException
2444
+	 */
2445
+	protected function _default_event_settings()
2446
+	{
2447
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2448
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
2449
+		$this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2450
+		$this->display_admin_page_with_sidebar();
2451
+	}
2452
+
2453
+
2454
+	/**
2455
+	 * Return the form for event settings.
2456
+	 *
2457
+	 * @return EE_Form_Section_Proper
2458
+	 * @throws EE_Error
2459
+	 */
2460
+	protected function _default_event_settings_form()
2461
+	{
2462
+		$registration_config = EE_Registry::instance()->CFG->registration;
2463
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2464
+		// exclude
2465
+			[
2466
+				EEM_Registration::status_id_cancelled,
2467
+				EEM_Registration::status_id_declined,
2468
+				EEM_Registration::status_id_incomplete,
2469
+				EEM_Registration::status_id_wait_list,
2470
+			],
2471
+			true
2472
+		);
2473
+		return new EE_Form_Section_Proper(
2474
+			[
2475
+				'name'            => 'update_default_event_settings',
2476
+				'html_id'         => 'update_default_event_settings',
2477
+				'html_class'      => 'form-table',
2478
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2479
+				'subsections'     => apply_filters(
2480
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2481
+					[
2482
+						'default_reg_status'  => new EE_Select_Input(
2483
+							$registration_stati_for_selection,
2484
+							[
2485
+								'default'         => isset($registration_config->default_STS_ID)
2486
+													 && array_key_exists(
2487
+														 $registration_config->default_STS_ID,
2488
+														 $registration_stati_for_selection
2489
+													 )
2490
+									? sanitize_text_field($registration_config->default_STS_ID)
2491
+									: EEM_Registration::status_id_pending_payment,
2492
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2493
+													 . EEH_Template::get_help_tab_link(
2494
+														 'default_settings_status_help_tab'
2495
+													 ),
2496
+								'html_help_text'  => esc_html__(
2497
+									'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2498
+									'event_espresso'
2499
+								),
2500
+							]
2501
+						),
2502
+						'default_max_tickets' => new EE_Integer_Input(
2503
+							[
2504
+								'default'         => isset($registration_config->default_maximum_number_of_tickets)
2505
+									? $registration_config->default_maximum_number_of_tickets
2506
+									: EEM_Event::get_default_additional_limit(),
2507
+								'html_label_text' => esc_html__(
2508
+									'Default Maximum Tickets Allowed Per Order:',
2509
+									'event_espresso'
2510
+								)
2511
+													 . EEH_Template::get_help_tab_link(
2512
+														 'default_maximum_tickets_help_tab"'
2513
+													 ),
2514
+								'html_help_text'  => esc_html__(
2515
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2516
+									'event_espresso'
2517
+								),
2518
+							]
2519
+						),
2520
+					]
2521
+				),
2522
+			]
2523
+		);
2524
+	}
2525
+
2526
+
2527
+	/**
2528
+	 * @return void
2529
+	 * @throws EE_Error
2530
+	 * @throws InvalidArgumentException
2531
+	 * @throws InvalidDataTypeException
2532
+	 * @throws InvalidInterfaceException
2533
+	 */
2534
+	protected function _update_default_event_settings()
2535
+	{
2536
+		$form = $this->_default_event_settings_form();
2537
+		if ($form->was_submitted()) {
2538
+			$form->receive_form_submission();
2539
+			if ($form->is_valid()) {
2540
+				$registration_config = EE_Registry::instance()->CFG->registration;
2541
+				$valid_data = $form->valid_data();
2542
+				if (isset($valid_data['default_reg_status'])) {
2543
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2544
+				}
2545
+				if (isset($valid_data['default_max_tickets'])) {
2546
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2547
+				}
2548
+				do_action(
2549
+					'AHEE__Events_Admin_Page___update_default_event_settings',
2550
+					$valid_data,
2551
+					EE_Registry::instance()->CFG,
2552
+					$this
2553
+				);
2554
+				// update because data was valid!
2555
+				EE_Registry::instance()->CFG->update_espresso_config();
2556
+				EE_Error::overwrite_success();
2557
+				EE_Error::add_success(
2558
+					__('Default Event Settings were updated', 'event_espresso')
2559
+				);
2560
+			}
2561
+		}
2562
+		$this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2563
+	}
2564
+
2565
+
2566
+	/*************        Templates        *************/
2567
+	protected function _template_settings()
2568
+	{
2569
+		$this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2570
+		$this->_template_args['preview_img'] = '<img src="'
2571
+											   . EVENTS_ASSETS_URL
2572
+											   . '/images/'
2573
+											   . 'caffeinated_template_features.jpg" alt="'
2574
+											   . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2575
+											   . '" />';
2576
+		$this->_template_args['preview_text'] = '<strong>'
2577
+												. esc_html__(
2578
+													'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2579
+													'event_espresso'
2580
+												) . '</strong>';
2581
+		$this->display_admin_caf_preview_page('template_settings_tab');
2582
+	}
2583
+
2584
+
2585
+	/** Event Category Stuff **/
2586
+	/**
2587
+	 * set the _category property with the category object for the loaded page.
2588
+	 *
2589
+	 * @return void
2590
+	 */
2591
+	private function _set_category_object()
2592
+	{
2593
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2594
+			return;
2595
+		} //already have the category object so get out.
2596
+		// set default category object
2597
+		$this->_set_empty_category_object();
2598
+		// only set if we've got an id
2599
+		if (! isset($this->_req_data['EVT_CAT_ID'])) {
2600
+			return;
2601
+		}
2602
+		$category_id = absint($this->_req_data['EVT_CAT_ID']);
2603
+		$term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2604
+		if (! empty($term)) {
2605
+			$this->_category->category_name = $term->name;
2606
+			$this->_category->category_identifier = $term->slug;
2607
+			$this->_category->category_desc = $term->description;
2608
+			$this->_category->id = $term->term_id;
2609
+			$this->_category->parent = $term->parent;
2610
+		}
2611
+	}
2612
+
2613
+
2614
+	/**
2615
+	 * Clears out category properties.
2616
+	 */
2617
+	private function _set_empty_category_object()
2618
+	{
2619
+		$this->_category = new stdClass();
2620
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2621
+		$this->_category->id = $this->_category->parent = 0;
2622
+	}
2623
+
2624
+
2625
+	/**
2626
+	 * @throws DomainException
2627
+	 * @throws EE_Error
2628
+	 * @throws InvalidArgumentException
2629
+	 * @throws InvalidDataTypeException
2630
+	 * @throws InvalidInterfaceException
2631
+	 */
2632
+	protected function _category_list_table()
2633
+	{
2634
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2635
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2636
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2637
+			'add_category',
2638
+			'add_category',
2639
+			[],
2640
+			'add-new-h2'
2641
+		);
2642
+		$this->display_admin_list_table_page_with_sidebar();
2643
+	}
2644
+
2645
+
2646
+	/**
2647
+	 * Output category details view.
2648
+	 *
2649
+	 * @param string $view
2650
+	 * @throws DomainException
2651
+	 * @throws EE_Error
2652
+	 * @throws InvalidArgumentException
2653
+	 * @throws InvalidDataTypeException
2654
+	 * @throws InvalidInterfaceException
2655
+	 */
2656
+	protected function _category_details($view)
2657
+	{
2658
+		// load formatter helper
2659
+		// load field generator helper
2660
+		$route = $view === 'edit' ? 'update_category' : 'insert_category';
2661
+		$this->_set_add_edit_form_tags($route);
2662
+		$this->_set_category_object();
2663
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
2664
+		$delete_action = 'delete_category';
2665
+		// custom redirect
2666
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2667
+			['action' => 'category_list'],
2668
+			$this->_admin_base_url
2669
+		);
2670
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2671
+		// take care of contents
2672
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2673
+		$this->display_admin_page_with_sidebar();
2674
+	}
2675
+
2676
+
2677
+	/**
2678
+	 * Output category details content.
2679
+	 *
2680
+	 * @throws DomainException
2681
+	 */
2682
+	protected function _category_details_content()
2683
+	{
2684
+		$editor_args['category_desc'] = [
2685
+			'type'          => 'wp_editor',
2686
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2687
+			'class'         => 'my_editor_custom',
2688
+			'wpeditor_args' => ['media_buttons' => false],
2689
+		];
2690
+		$_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2691
+		$all_terms = get_terms(
2692
+			[EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2693
+			['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2694
+		);
2695
+		// setup category select for term parents.
2696
+		$category_select_values[] = [
2697
+			'text' => esc_html__('No Parent', 'event_espresso'),
2698
+			'id'   => 0,
2699
+		];
2700
+		foreach ($all_terms as $term) {
2701
+			$category_select_values[] = [
2702
+				'text' => $term->name,
2703
+				'id'   => $term->term_id,
2704
+			];
2705
+		}
2706
+		$category_select = EEH_Form_Fields::select_input(
2707
+			'category_parent',
2708
+			$category_select_values,
2709
+			$this->_category->parent
2710
+		);
2711
+		$template_args = [
2712
+			'category'                 => $this->_category,
2713
+			'category_select'          => $category_select,
2714
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2715
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2716
+			'disable'                  => '',
2717
+			'disabled_message'         => false,
2718
+		];
2719
+		$template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2720
+		return EEH_Template::display_template($template, $template_args, true);
2721
+	}
2722
+
2723
+
2724
+	/**
2725
+	 * Handles deleting categories.
2726
+	 */
2727
+	protected function _delete_categories()
2728
+	{
2729
+		$cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2730
+			: (array) $this->_req_data['category_id'];
2731
+		foreach ($cat_ids as $cat_id) {
2732
+			$this->_delete_category($cat_id);
2733
+		}
2734
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
2735
+		$query_args = [
2736
+			'action' => 'category_list',
2737
+		];
2738
+		$this->_redirect_after_action(0, '', '', $query_args);
2739
+	}
2740
+
2741
+
2742
+	/**
2743
+	 * Handles deleting specific category.
2744
+	 *
2745
+	 * @param int $cat_id
2746
+	 */
2747
+	protected function _delete_category($cat_id)
2748
+	{
2749
+		$cat_id = absint($cat_id);
2750
+		wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2751
+	}
2752
+
2753
+
2754
+	/**
2755
+	 * Handles triggering the update or insertion of a new category.
2756
+	 *
2757
+	 * @param bool $new_category true means we're triggering the insert of a new category.
2758
+	 * @throws EE_Error
2759
+	 * @throws InvalidArgumentException
2760
+	 * @throws InvalidDataTypeException
2761
+	 * @throws InvalidInterfaceException
2762
+	 */
2763
+	protected function _insert_or_update_category($new_category)
2764
+	{
2765
+		$cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2766
+		$success = 0; // we already have a success message so lets not send another.
2767
+		if ($cat_id) {
2768
+			$query_args = [
2769
+				'action'     => 'edit_category',
2770
+				'EVT_CAT_ID' => $cat_id,
2771
+			];
2772
+		} else {
2773
+			$query_args = ['action' => 'add_category'];
2774
+		}
2775
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2776
+	}
2777
+
2778
+
2779
+	/**
2780
+	 * Inserts or updates category
2781
+	 *
2782
+	 * @param bool $update (true indicates we're updating a category).
2783
+	 * @return bool|mixed|string
2784
+	 */
2785
+	private function _insert_category($update = false)
2786
+	{
2787
+		$cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2788
+		$category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2789
+		$category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2790
+		$category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2791
+		if (empty($category_name)) {
2792
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2793
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2794
+			return false;
2795
+		}
2796
+		$term_args = [
2797
+			'name'        => $category_name,
2798
+			'description' => $category_desc,
2799
+			'parent'      => $category_parent,
2800
+		];
2801
+		// was the category_identifier input disabled?
2802
+		if (isset($this->_req_data['category_identifier'])) {
2803
+			$term_args['slug'] = $this->_req_data['category_identifier'];
2804
+		}
2805
+		$insert_ids = $update
2806
+			? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2807
+			: wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2808
+		if (! is_array($insert_ids)) {
2809
+			$msg = esc_html__(
2810
+				'An error occurred and the category has not been saved to the database.',
2811
+				'event_espresso'
2812
+			);
2813
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2814
+		} else {
2815
+			$cat_id = $insert_ids['term_id'];
2816
+			$msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2817
+			EE_Error::add_success($msg);
2818
+		}
2819
+		return $cat_id;
2820
+	}
2821
+
2822
+
2823
+	/**
2824
+	 * Gets categories or count of categories matching the arguments in the request.
2825
+	 *
2826
+	 * @param int  $per_page
2827
+	 * @param int  $current_page
2828
+	 * @param bool $count
2829
+	 * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2830
+	 * @throws EE_Error
2831
+	 * @throws InvalidArgumentException
2832
+	 * @throws InvalidDataTypeException
2833
+	 * @throws InvalidInterfaceException
2834
+	 */
2835
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
2836
+	{
2837
+		// testing term stuff
2838
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2839
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2840
+		$limit = ($current_page - 1) * $per_page;
2841
+		$where = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2842
+		if (isset($this->_req_data['s'])) {
2843
+			$sstr = '%' . $this->_req_data['s'] . '%';
2844
+			$where['OR'] = [
2845
+				'Term.name'   => ['LIKE', $sstr],
2846
+				'description' => ['LIKE', $sstr],
2847
+			];
2848
+		}
2849
+		$query_params = [
2850
+			$where,
2851
+			'order_by'   => [$orderby => $order],
2852
+			'limit'      => $limit . ',' . $per_page,
2853
+			'force_join' => ['Term'],
2854
+		];
2855
+		$categories = $count
2856
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2857
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2858
+		return $categories;
2859
+	}
2860
+
2861
+	/* end category stuff */
2862
+	/**************/
2863
+
2864
+
2865
+	/**
2866
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2867
+	 *
2868
+	 * @throws EE_Error
2869
+	 * @throws InvalidArgumentException
2870
+	 * @throws InvalidDataTypeException
2871
+	 * @throws InvalidInterfaceException
2872
+	 */
2873
+	public function save_timezonestring_setting()
2874
+	{
2875
+		$timezone_string = isset($this->_req_data['timezone_selected'])
2876
+			? $this->_req_data['timezone_selected']
2877
+			: '';
2878
+		if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2879
+			EE_Error::add_error(
2880
+				esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2881
+				__FILE__,
2882
+				__FUNCTION__,
2883
+				__LINE__
2884
+			);
2885
+			$this->_template_args['error'] = true;
2886
+			$this->_return_json();
2887
+		}
2888
+
2889
+		update_option('timezone_string', $timezone_string);
2890
+		EE_Error::add_success(
2891
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2892
+		);
2893
+		$this->_template_args['success'] = true;
2894
+		$this->_return_json(true, ['action' => 'create_new']);
2895
+	}
2896 2896
 }
Please login to merge, or discard this patch.
Spacing   +66 added lines, -66 removed lines patch added patch discarded remove patch
@@ -543,7 +543,7 @@  discard block
 block discarded – undo
543 543
         ];
544 544
         // only load EE_Event_Editor_Decaf_Tips if domain is not caffeinated
545 545
         $domain = $this->loader->getShared('EventEspresso\core\domain\Domain');
546
-        if (! $domain->isCaffeinated()) {
546
+        if ( ! $domain->isCaffeinated()) {
547 547
             $this->_page_config['create_new']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
548 548
             $this->_page_config['edit']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
549 549
         }
@@ -602,13 +602,13 @@  discard block
 block discarded – undo
602 602
     {
603 603
         wp_register_style(
604 604
             'events-admin-css',
605
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
605
+            EVENTS_ASSETS_URL.'events-admin-page.css',
606 606
             [],
607 607
             EVENT_ESPRESSO_VERSION
608 608
         );
609 609
         wp_register_style(
610 610
             'ee-cat-admin',
611
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
611
+            EVENTS_ASSETS_URL.'ee-cat-admin.css',
612 612
             [],
613 613
             EVENT_ESPRESSO_VERSION
614 614
         );
@@ -617,7 +617,7 @@  discard block
 block discarded – undo
617 617
         // scripts
618 618
         wp_register_script(
619 619
             'event_editor_js',
620
-            EVENTS_ASSETS_URL . 'event_editor.js',
620
+            EVENTS_ASSETS_URL.'event_editor.js',
621 621
             ['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
622 622
             EVENT_ESPRESSO_VERSION,
623 623
             true
@@ -643,16 +643,16 @@  discard block
 block discarded – undo
643 643
         wp_enqueue_style('espresso-ui-theme');
644 644
         wp_register_style(
645 645
             'event-editor-css',
646
-            EVENTS_ASSETS_URL . 'event-editor.css',
646
+            EVENTS_ASSETS_URL.'event-editor.css',
647 647
             ['ee-admin-css'],
648 648
             EVENT_ESPRESSO_VERSION
649 649
         );
650 650
         wp_enqueue_style('event-editor-css');
651 651
         // scripts
652
-        if (! $this->admin_config->useAdvancedEditor()) {
652
+        if ( ! $this->admin_config->useAdvancedEditor()) {
653 653
             wp_register_script(
654 654
                 'event-datetime-metabox',
655
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
655
+                EVENTS_ASSETS_URL.'event-datetime-metabox.js',
656 656
                 ['event_editor_js', 'ee-datepicker'],
657 657
                 EVENT_ESPRESSO_VERSION
658 658
             );
@@ -721,15 +721,15 @@  discard block
 block discarded – undo
721 721
     public function verify_event_edit($event = null, $req_type = '')
722 722
     {
723 723
         // don't need to do this when processing
724
-        if (! empty($req_type)) {
724
+        if ( ! empty($req_type)) {
725 725
             return;
726 726
         }
727 727
         // no event?
728
-        if (! $event instanceof EE_Event) {
728
+        if ( ! $event instanceof EE_Event) {
729 729
             $event = $this->_cpt_model_obj;
730 730
         }
731 731
         // STILL no event?
732
-        if (! $event instanceof EE_Event) {
732
+        if ( ! $event instanceof EE_Event) {
733 733
             return;
734 734
         }
735 735
         $orig_status = $event->status();
@@ -769,7 +769,7 @@  discard block
 block discarded – undo
769 769
             );
770 770
         }
771 771
         // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
772
-        if (! $event->tickets_on_sale()) {
772
+        if ( ! $event->tickets_on_sale()) {
773 773
             return;
774 774
         }
775 775
         // made it here so show warning
@@ -814,7 +814,7 @@  discard block
 block discarded – undo
814 814
     {
815 815
         $has_timezone_string = get_option('timezone_string');
816 816
         // only nag them about setting their timezone if it's their first event, and they haven't already done it
817
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
817
+        if ( ! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
818 818
             EE_Error::add_attention(
819 819
                 sprintf(
820 820
                     __(
@@ -898,31 +898,31 @@  discard block
 block discarded – undo
898 898
         $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
899 899
         $statuses = [
900 900
             'sold_out_status'  => [
901
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
901
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::sold_out,
902 902
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
903 903
             ],
904 904
             'active_status'    => [
905
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
905
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::active,
906 906
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
907 907
             ],
908 908
             'upcoming_status'  => [
909
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
909
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::upcoming,
910 910
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
911 911
             ],
912 912
             'postponed_status' => [
913
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
913
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::postponed,
914 914
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
915 915
             ],
916 916
             'cancelled_status' => [
917
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
917
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::cancelled,
918 918
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
919 919
             ],
920 920
             'expired_status'   => [
921
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
921
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::expired,
922 922
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
923 923
             ],
924 924
             'inactive_status'  => [
925
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
925
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::inactive,
926 926
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
927 927
             ],
928 928
         ];
@@ -937,7 +937,7 @@  discard block
 block discarded – undo
937 937
      */
938 938
     private function eventModel()
939 939
     {
940
-        if (! $this->_event_model instanceof EEM_Event) {
940
+        if ( ! $this->_event_model instanceof EEM_Event) {
941 941
             $this->_event_model = EEM_Event::instance();
942 942
         }
943 943
         return $this->_event_model;
@@ -951,7 +951,7 @@  discard block
 block discarded – undo
951 951
      */
952 952
     private function datetimeModel($event_timezone_string = '')
953 953
     {
954
-        if (! $this->datetime_model instanceof EEM_Datetime) {
954
+        if ( ! $this->datetime_model instanceof EEM_Datetime) {
955 955
             $this->datetime_model = EEM_Datetime::instance($event_timezone_string);
956 956
         }
957 957
         return $this->datetime_model;
@@ -965,7 +965,7 @@  discard block
 block discarded – undo
965 965
      */
966 966
     private function ticketModel($event_timezone_string = '')
967 967
     {
968
-        if (! $this->ticket_model instanceof EEM_Ticket) {
968
+        if ( ! $this->ticket_model instanceof EEM_Ticket) {
969 969
             $this->ticket_model = EEM_Ticket::instance($event_timezone_string);
970 970
         }
971 971
         return $this->ticket_model;
@@ -985,7 +985,7 @@  discard block
 block discarded – undo
985 985
     public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
986 986
     {
987 987
         // make sure this is only when editing
988
-        if (! empty($id)) {
988
+        if ( ! empty($id)) {
989 989
             $post = get_post($id);
990 990
             $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
991 991
                        . esc_html__('Shortcode', 'event_espresso')
@@ -1022,7 +1022,7 @@  discard block
 block discarded – undo
1022 1022
                                                                                   'button'
1023 1023
                                                                               );
1024 1024
         $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
1025
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1025
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
1026 1026
             'create_new',
1027 1027
             'add',
1028 1028
             [],
@@ -1084,7 +1084,7 @@  discard block
 block discarded – undo
1084 1084
         /** @var FeatureFlags $flags */
1085 1085
         $flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1086 1086
         // check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1087
-        if (! $this->admin_config->useAdvancedEditor() || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1087
+        if ( ! $this->admin_config->useAdvancedEditor() || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1088 1088
             $event_values['EVT_display_ticket_selector'] =
1089 1089
                 ! empty($this->_req_data['display_ticket_selector'])
1090 1090
                     ? 1
@@ -1197,7 +1197,7 @@  discard block
 block discarded – undo
1197 1197
      */
1198 1198
     protected function _default_venue_update(EE_Event $evtobj, $data)
1199 1199
     {
1200
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1200
+        require_once(EE_MODELS.'EEM_Venue.model.php');
1201 1201
         $venue_model = EEM_Venue::instance();
1202 1202
         $rows_affected = null;
1203 1203
         $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
@@ -1228,7 +1228,7 @@  discard block
 block discarded – undo
1228 1228
             'status'              => 'publish',
1229 1229
         ];
1230 1230
         // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1231
-        if (! empty($venue_id)) {
1231
+        if ( ! empty($venue_id)) {
1232 1232
             $update_where = [$venue_model->primary_key_name() => $venue_id];
1233 1233
             $rows_affected = $venue_model->update($venue_array, [$update_where]);
1234 1234
             // we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
@@ -1282,7 +1282,7 @@  discard block
 block discarded – undo
1282 1282
                 'DTT_order'     => $row,
1283 1283
             ];
1284 1284
             // if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1285
-            if (! empty($dtt['DTT_ID'])) {
1285
+            if ( ! empty($dtt['DTT_ID'])) {
1286 1286
                 $DTM = $this->datetimeModel($event_timezone_string)->get_one_by_ID($dtt['DTT_ID']);
1287 1287
                 $DTM->set_date_format($incoming_date_formats[0]);
1288 1288
                 $DTM->set_time_format($incoming_date_formats[1]);
@@ -1290,7 +1290,7 @@  discard block
 block discarded – undo
1290 1290
                     $DTM->set($field, $value);
1291 1291
                 }
1292 1292
                 // make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1293
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1293
+                $saved_dtts[$DTM->ID()] = $DTM;
1294 1294
             } else {
1295 1295
                 $DTM = EE_Registry::instance()->load_class(
1296 1296
                     'Datetime',
@@ -1323,12 +1323,12 @@  discard block
 block discarded – undo
1323 1323
         foreach ($data['edit_tickets'] as $row => $tkt) {
1324 1324
             $incoming_date_formats = ['Y-m-d', 'h:i a'];
1325 1325
             $update_prices = false;
1326
-            $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1327
-                ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1326
+            $ticket_price = isset($data['edit_prices'][$row][1]['PRC_amount'])
1327
+                ? $data['edit_prices'][$row][1]['PRC_amount'] : 0;
1328 1328
             // trim inputs to ensure any excess whitespace is removed.
1329 1329
             $tkt = array_map('trim', $tkt);
1330 1330
             if (empty($tkt['TKT_start_date'])) {
1331
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1331
+                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0].' '.$incoming_date_formats[1]);
1332 1332
             }
1333 1333
             if (empty($tkt['TKT_end_date'])) {
1334 1334
                 // use the start date of the first datetime
@@ -1363,7 +1363,7 @@  discard block
 block discarded – undo
1363 1363
             // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1364 1364
             // we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1365 1365
             // keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1366
-            if (! empty($tkt['TKT_ID'])) {
1366
+            if ( ! empty($tkt['TKT_ID'])) {
1367 1367
                 $TKT = $this->ticketModel($event_timezone_string)->get_one_by_ID($tkt['TKT_ID']);
1368 1368
                 if ($TKT instanceof EE_Ticket) {
1369 1369
                     $ticket_sold = $TKT->count_related(
@@ -1402,7 +1402,7 @@  discard block
 block discarded – undo
1402 1402
                         $TKT->set('TKT_deleted', 1);
1403 1403
                         $TKT->save();
1404 1404
                         // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1405
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1405
+                        $saved_tickets[$TKT->ID()] = $TKT;
1406 1406
                         // create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1407 1407
                         $TKT = clone $TKT;
1408 1408
                         $TKT->set('TKT_ID', 0);
@@ -1447,9 +1447,9 @@  discard block
 block discarded – undo
1447 1447
             }
1448 1448
             // initially let's add the ticket to the dtt
1449 1449
             $saved_dtt->_add_relation_to($TKT, 'Ticket');
1450
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1450
+            $saved_tickets[$TKT->ID()] = $TKT;
1451 1451
             // add prices to ticket
1452
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1452
+            $this->_add_prices_to_ticket($data['edit_prices'][$row], $TKT, $update_prices);
1453 1453
         }
1454 1454
         // however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1455 1455
         $old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
@@ -1616,7 +1616,7 @@  discard block
 block discarded – undo
1616 1616
         $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1617 1617
         // load template
1618 1618
         EEH_Template::display_template(
1619
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1619
+            EVENTS_TEMPLATE_PATH.'event_publish_box_extras.template.php',
1620 1620
             $publish_box_extra_args
1621 1621
         );
1622 1622
     }
@@ -1652,7 +1652,7 @@  discard block
 block discarded – undo
1652 1652
         /** @var FeatureFlags $flags */
1653 1653
         $flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1654 1654
         // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1655
-        if (! $use_advanced_editor || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1655
+        if ( ! $use_advanced_editor || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1656 1656
             add_meta_box(
1657 1657
                 'espresso_event_editor_event_options',
1658 1658
                 esc_html__('Event Registration Options', 'event_espresso'),
@@ -1661,7 +1661,7 @@  discard block
 block discarded – undo
1661 1661
                 'side'
1662 1662
             );
1663 1663
         }
1664
-        if (! $use_advanced_editor) {
1664
+        if ( ! $use_advanced_editor) {
1665 1665
             add_meta_box(
1666 1666
                 'espresso_event_editor_tickets',
1667 1667
                 esc_html__('Event Datetime & Ticket', 'event_espresso'),
@@ -1674,7 +1674,7 @@  discard block
 block discarded – undo
1674 1674
             if ($flags->featureAllowed('use_reg_options_meta_box')) {
1675 1675
                 add_action(
1676 1676
                     'add_meta_boxes_espresso_events',
1677
-                    function () {
1677
+                    function() {
1678 1678
                         global $current_screen;
1679 1679
                         remove_meta_box('authordiv', $current_screen, 'normal');
1680 1680
                     },
@@ -1739,7 +1739,7 @@  discard block
 block discarded – undo
1739 1739
                     'default_where_conditions' => 'none',
1740 1740
                 ]
1741 1741
             );
1742
-            if (! empty($related_tickets)) {
1742
+            if ( ! empty($related_tickets)) {
1743 1743
                 $template_args['total_ticket_rows'] = count($related_tickets);
1744 1744
                 $row = 0;
1745 1745
                 foreach ($related_tickets as $ticket) {
@@ -1773,7 +1773,7 @@  discard block
 block discarded – undo
1773 1773
         );
1774 1774
         $template = apply_filters(
1775 1775
             'FHEE__Events_Admin_Page__ticket_metabox__template',
1776
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1776
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_main.template.php'
1777 1777
         );
1778 1778
         EEH_Template::display_template($template, $template_args);
1779 1779
     }
@@ -1796,7 +1796,7 @@  discard block
 block discarded – undo
1796 1796
     private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1797 1797
     {
1798 1798
         $template_args = [
1799
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1799
+            'tkt_status_class'    => ' tkt-status-'.$ticket->ticket_status(),
1800 1800
             'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1801 1801
                 : '',
1802 1802
             'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
@@ -1808,10 +1808,10 @@  discard block
 block discarded – undo
1808 1808
             'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1809 1809
             'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1810 1810
             'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1811
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1812
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1811
+            'trash_icon'          => ($skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')))
1812
+                                     && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1813 1813
                 ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1814
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1814
+            'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1815 1815
                 : ' disabled=disabled',
1816 1816
         ];
1817 1817
         $price = $ticket->ID() !== 0
@@ -1838,7 +1838,7 @@  discard block
 block discarded – undo
1838 1838
                     ['order_by' => ['DTT_EVT_start' => 'ASC']]
1839 1839
                 )
1840 1840
                 : null;
1841
-            if (! empty($earliest_dtt)) {
1841
+            if ( ! empty($earliest_dtt)) {
1842 1842
                 $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1843 1843
             } else {
1844 1844
                 $template_args['TKT_end_date'] = date(
@@ -1850,7 +1850,7 @@  discard block
 block discarded – undo
1850 1850
         $template_args = array_merge($template_args, $price_args);
1851 1851
         $template = apply_filters(
1852 1852
             'FHEE__Events_Admin_Page__get_ticket_row__template',
1853
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1853
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_ticket_row.template.php',
1854 1854
             $ticket
1855 1855
         );
1856 1856
         return EEH_Template::display_template($template, $template_args, true);
@@ -1905,7 +1905,7 @@  discard block
 block discarded – undo
1905 1905
             $default_reg_status_values
1906 1906
         );
1907 1907
         EEH_Template::display_template(
1908
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1908
+            EVENTS_TEMPLATE_PATH.'event_registration_options.template.php',
1909 1909
             $template_args
1910 1910
         );
1911 1911
     }
@@ -1934,7 +1934,7 @@  discard block
 block discarded – undo
1934 1934
     {
1935 1935
         $EEME = $this->eventModel();
1936 1936
         $offset = ($current_page - 1) * $per_page;
1937
-        $limit = $count ? null : $offset . ',' . $per_page;
1937
+        $limit = $count ? null : $offset.','.$per_page;
1938 1938
         $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1939 1939
         $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1940 1940
         if (isset($this->_req_data['month_range'])) {
@@ -1963,7 +1963,7 @@  discard block
 block discarded – undo
1963 1963
         // categories?
1964 1964
         $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1965 1965
             ? $this->_req_data['EVT_CAT'] : null;
1966
-        if (! empty($category)) {
1966
+        if ( ! empty($category)) {
1967 1967
             $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1968 1968
             $where['Term_Taxonomy.term_id'] = $category;
1969 1969
         }
@@ -1971,7 +1971,7 @@  discard block
 block discarded – undo
1971 1971
         $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1972 1972
         if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] !== '') {
1973 1973
             $DateTime = new DateTime(
1974
-                $year_r . '-' . $month_r . '-01 00:00:00',
1974
+                $year_r.'-'.$month_r.'-01 00:00:00',
1975 1975
                 new DateTimeZone('UTC')
1976 1976
             );
1977 1977
             $start = $DateTime->getTimestamp();
@@ -1997,7 +1997,7 @@  discard block
 block discarded – undo
1997 1997
                             ->format(implode(' ', $start_formats));
1998 1998
             $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1999 1999
         }
2000
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
2000
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
2001 2001
             $where['EVT_wp_user'] = get_current_user_id();
2002 2002
         } elseif (
2003 2003
             ! isset($where['status'])
@@ -2021,7 +2021,7 @@  discard block
 block discarded – undo
2021 2021
         }
2022 2022
         // search query handling
2023 2023
         if (isset($this->_req_data['s'])) {
2024
-            $search_string = '%' . $this->_req_data['s'] . '%';
2024
+            $search_string = '%'.$this->_req_data['s'].'%';
2025 2025
             $where['OR'] = [
2026 2026
                 'EVT_name'       => ['LIKE', $search_string],
2027 2027
                 'EVT_desc'       => ['LIKE', $search_string],
@@ -2136,7 +2136,7 @@  discard block
 block discarded – undo
2136 2136
             // clean status
2137 2137
             $event_status = sanitize_key($event_status);
2138 2138
             // grab status
2139
-            if (! empty($event_status)) {
2139
+            if ( ! empty($event_status)) {
2140 2140
                 $success = $this->_change_event_status($EVT_ID, $event_status);
2141 2141
             } else {
2142 2142
                 $success = false;
@@ -2177,7 +2177,7 @@  discard block
 block discarded – undo
2177 2177
         // clean status
2178 2178
         $event_status = sanitize_key($event_status);
2179 2179
         // grab status
2180
-        if (! empty($event_status)) {
2180
+        if ( ! empty($event_status)) {
2181 2181
             $success = true;
2182 2182
             // determine the event id and set to array.
2183 2183
             $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : [];
@@ -2228,7 +2228,7 @@  discard block
 block discarded – undo
2228 2228
     private function _change_event_status($EVT_ID = 0, $event_status = '')
2229 2229
     {
2230 2230
         // grab event id
2231
-        if (! $EVT_ID) {
2231
+        if ( ! $EVT_ID) {
2232 2232
             $msg = esc_html__(
2233 2233
                 'An error occurred. No Event ID or an invalid Event ID was received.',
2234 2234
                 'event_espresso'
@@ -2302,7 +2302,7 @@  discard block
 block discarded – undo
2302 2302
      */
2303 2303
     protected function getModelObjNodeGroupPersister()
2304 2304
     {
2305
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2305
+        if ( ! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2306 2306
             $this->model_obj_node_group_persister = $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2307 2307
         }
2308 2308
         return $this->model_obj_node_group_persister;
@@ -2577,7 +2577,7 @@  discard block
 block discarded – undo
2577 2577
                                                 . esc_html__(
2578 2578
                                                     'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2579 2579
                                                     'event_espresso'
2580
-                                                ) . '</strong>';
2580
+                                                ).'</strong>';
2581 2581
         $this->display_admin_caf_preview_page('template_settings_tab');
2582 2582
     }
2583 2583
 
@@ -2596,12 +2596,12 @@  discard block
 block discarded – undo
2596 2596
         // set default category object
2597 2597
         $this->_set_empty_category_object();
2598 2598
         // only set if we've got an id
2599
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2599
+        if ( ! isset($this->_req_data['EVT_CAT_ID'])) {
2600 2600
             return;
2601 2601
         }
2602 2602
         $category_id = absint($this->_req_data['EVT_CAT_ID']);
2603 2603
         $term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2604
-        if (! empty($term)) {
2604
+        if ( ! empty($term)) {
2605 2605
             $this->_category->category_name = $term->name;
2606 2606
             $this->_category->category_identifier = $term->slug;
2607 2607
             $this->_category->category_desc = $term->description;
@@ -2633,7 +2633,7 @@  discard block
 block discarded – undo
2633 2633
     {
2634 2634
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2635 2635
         $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2636
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2636
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
2637 2637
             'add_category',
2638 2638
             'add_category',
2639 2639
             [],
@@ -2716,7 +2716,7 @@  discard block
 block discarded – undo
2716 2716
             'disable'                  => '',
2717 2717
             'disabled_message'         => false,
2718 2718
         ];
2719
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2719
+        $template = EVENTS_TEMPLATE_PATH.'event_category_details.template.php';
2720 2720
         return EEH_Template::display_template($template, $template_args, true);
2721 2721
     }
2722 2722
 
@@ -2805,7 +2805,7 @@  discard block
 block discarded – undo
2805 2805
         $insert_ids = $update
2806 2806
             ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2807 2807
             : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2808
-        if (! is_array($insert_ids)) {
2808
+        if ( ! is_array($insert_ids)) {
2809 2809
             $msg = esc_html__(
2810 2810
                 'An error occurred and the category has not been saved to the database.',
2811 2811
                 'event_espresso'
@@ -2840,7 +2840,7 @@  discard block
 block discarded – undo
2840 2840
         $limit = ($current_page - 1) * $per_page;
2841 2841
         $where = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2842 2842
         if (isset($this->_req_data['s'])) {
2843
-            $sstr = '%' . $this->_req_data['s'] . '%';
2843
+            $sstr = '%'.$this->_req_data['s'].'%';
2844 2844
             $where['OR'] = [
2845 2845
                 'Term.name'   => ['LIKE', $sstr],
2846 2846
                 'description' => ['LIKE', $sstr],
@@ -2849,7 +2849,7 @@  discard block
 block discarded – undo
2849 2849
         $query_params = [
2850 2850
             $where,
2851 2851
             'order_by'   => [$orderby => $order],
2852
-            'limit'      => $limit . ',' . $per_page,
2852
+            'limit'      => $limit.','.$per_page,
2853 2853
             'force_join' => ['Term'],
2854 2854
         ];
2855 2855
         $categories = $count
Please login to merge, or discard this patch.
core/business/EE_Transaction_Processor.class.php 2 patches
Doc Comments   +1 added lines patch added patch discarded remove patch
@@ -186,6 +186,7 @@
 block discarded – undo
186 186
      *                                                         when retrieving cached registrations from a transaction
187 187
      * @param bool              $trigger_notifications        whether or not to call
188 188
      *                                                         \EE_Registration_Processor::trigger_registration_update_notifications()
189
+     * @param EE_Base_Class $payment
189 190
      * @return array
190 191
      * @throws EE_Error
191 192
      * @throws ReflectionException
Please login to merge, or discard this patch.
Indentation   +955 added lines, -955 removed lines patch added patch discarded remove patch
@@ -17,959 +17,959 @@
 block discarded – undo
17 17
 class EE_Transaction_Processor extends EE_Processor_Base
18 18
 {
19 19
 
20
-    /**
21
-     * @var EE_Registration_Processor $_instance
22
-     * @access    private
23
-     */
24
-    private static $_instance;
25
-
26
-    /**
27
-     * array of query WHERE params to use when retrieving cached registrations from a transaction
28
-     *
29
-     * @var array $registration_query_params
30
-     * @access private
31
-     */
32
-    private $_registration_query_params = array();
33
-
34
-    /**
35
-     * @deprecated
36
-     * @var string
37
-     */
38
-    protected $_old_txn_status;
39
-
40
-    /**
41
-     * @deprecated
42
-     * @var string
43
-     */
44
-    protected $_new_txn_status;
45
-
46
-
47
-    /**
48
-     * @singleton method used to instantiate class object
49
-     * @access    public
50
-     * @param array $registration_query_params
51
-     * @return EE_Transaction_Processor instance
52
-     */
53
-    public static function instance($registration_query_params = array())
54
-    {
55
-        // check if class object is instantiated
56
-        if (! self::$_instance instanceof EE_Transaction_Processor) {
57
-            self::$_instance = new self($registration_query_params);
58
-        }
59
-        return self::$_instance;
60
-    }
61
-
62
-
63
-    /**
64
-     * @param array $registration_query_params
65
-     */
66
-    private function __construct($registration_query_params = array())
67
-    {
68
-        // make sure some query params are set for retrieving registrations
69
-        $this->_set_registration_query_params($registration_query_params);
70
-    }
71
-
72
-
73
-    /**
74
-     * @access private
75
-     * @param array $registration_query_params
76
-     */
77
-    private function _set_registration_query_params($registration_query_params)
78
-    {
79
-        $this->_registration_query_params = ! empty($registration_query_params) ? $registration_query_params
80
-            : array('order_by' => array('REG_count' => 'ASC'));
81
-    }
82
-
83
-
84
-    /**
85
-     * manually_update_registration_statuses
86
-     *
87
-     * @access public
88
-     * @param EE_Transaction $transaction
89
-     * @param string         $new_reg_status
90
-     * @param array          $registration_query_params array of query WHERE params to use
91
-     *                                                  when retrieving cached registrations from a transaction
92
-     * @return    boolean
93
-     * @throws EE_Error
94
-     * @throws ReflectionException
95
-     */
96
-    public function manually_update_registration_statuses(
97
-        EE_Transaction $transaction,
98
-        $new_reg_status = '',
99
-        $registration_query_params = array()
100
-    ) {
101
-        $status_updates = $this->_call_method_on_registrations_via_Registration_Processor(
102
-            'manually_update_registration_status',
103
-            $transaction,
104
-            $registration_query_params,
105
-            $new_reg_status
106
-        );
107
-        // send messages
108
-        /** @type EE_Registration_Processor $registration_processor */
109
-        $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
110
-        $registration_processor->trigger_registration_update_notifications(
111
-            $transaction->primary_registration(),
112
-            array('manually_updated' => true)
113
-        );
114
-        do_action(
115
-            'AHEE__EE_Transaction_Processor__manually_update_registration_statuses',
116
-            $transaction,
117
-            $status_updates
118
-        );
119
-        return $status_updates;
120
-    }
121
-
122
-
123
-    /**
124
-     * toggle_registration_statuses_for_default_approved_events
125
-     *
126
-     * @access public
127
-     * @param EE_Transaction $transaction
128
-     * @param array          $registration_query_params array of query WHERE params to use
129
-     *                                                  when retrieving cached registrations from a transaction
130
-     * @return    boolean
131
-     * @throws EE_Error
132
-     */
133
-    public function toggle_registration_statuses_for_default_approved_events(
134
-        EE_Transaction $transaction,
135
-        $registration_query_params = array()
136
-    ) {
137
-        $status_updates = $this->_call_method_on_registrations_via_Registration_Processor(
138
-            'toggle_registration_status_for_default_approved_events',
139
-            $transaction,
140
-            $registration_query_params
141
-        );
142
-        do_action(
143
-            'AHEE__EE_Transaction_Processor__toggle_registration_statuses_for_default_approved_events',
144
-            $transaction,
145
-            $status_updates
146
-        );
147
-        return $status_updates;
148
-    }
149
-
150
-
151
-    /**
152
-     * toggle_registration_statuses_if_no_monies_owing
153
-     *
154
-     * @access public
155
-     * @param EE_Transaction $transaction
156
-     * @param array          $registration_query_params array of query WHERE params to use
157
-     *                                                  when retrieving cached registrations from a transaction
158
-     * @return    boolean
159
-     * @throws EE_Error
160
-     */
161
-    public function toggle_registration_statuses_if_no_monies_owing(
162
-        EE_Transaction $transaction,
163
-        $registration_query_params = array()
164
-    ) {
165
-        $status_updates = $this->_call_method_on_registrations_via_Registration_Processor(
166
-            'toggle_registration_status_if_no_monies_owing',
167
-            $transaction,
168
-            $registration_query_params
169
-        );
170
-        do_action(
171
-            'AHEE__EE_Transaction_Processor__toggle_registration_statuses_if_no_monies_owing',
172
-            $transaction,
173
-            $status_updates
174
-        );
175
-        return $status_updates;
176
-    }
177
-
178
-
179
-    /**
180
-     * update_transaction_and_registrations_after_checkout_or_payment
181
-     * cycles thru related registrations and calls update_registration_after_checkout_or_payment() on each
182
-     *
183
-     * @param EE_Transaction    $transaction
184
-     * @param EE_Payment | NULL $payment
185
-     * @param array             $registration_query_params    array of query WHERE params to use
186
-     *                                                         when retrieving cached registrations from a transaction
187
-     * @param bool              $trigger_notifications        whether or not to call
188
-     *                                                         \EE_Registration_Processor::trigger_registration_update_notifications()
189
-     * @return array
190
-     * @throws EE_Error
191
-     * @throws ReflectionException
192
-     */
193
-    public function update_transaction_and_registrations_after_checkout_or_payment(
194
-        EE_Transaction $transaction,
195
-        $payment = null,
196
-        $registration_query_params = array(),
197
-        $trigger_notifications = true
198
-    ): array {
199
-        // make sure some query params are set for retrieving registrations
200
-        $this->_set_registration_query_params($registration_query_params);
201
-        // get final reg step status
202
-        $finalized = $transaction->final_reg_step_completed();
203
-        // if the 'finalize_registration' step has been initiated (has a timestamp)
204
-        // but has not yet been fully completed (TRUE)
205
-        if (is_int($finalized) && $finalized !== false && $finalized !== true) {
206
-            $transaction->set_reg_step_completed('finalize_registration');
207
-            $finalized = true;
208
-        }
209
-        $transaction->save();
210
-        // array of details to aid in decision making by systems
211
-        $update_params = array(
212
-            'old_txn_status'  => $transaction->old_txn_status(),
213
-            'new_txn_status'  => $transaction->status_ID(),
214
-            'finalized'       => $finalized,
215
-            'revisit'         => $this->_revisit,
216
-            'payment_updates' => $payment instanceof EE_Payment ? true : false,
217
-            'last_payment'    => $payment,
218
-        );
219
-        // now update the registrations and add the results to our $update_params
220
-        $update_params['status_updates'] = $this->_call_method_on_registrations_via_Registration_Processor(
221
-            'update_registration_after_checkout_or_payment',
222
-            $transaction,
223
-            $this->_registration_query_params,
224
-            $update_params
225
-        );
226
-        if ($trigger_notifications) {
227
-            // send messages
228
-            /** @type EE_Registration_Processor $registration_processor */
229
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
230
-            $registration_processor->trigger_registration_update_notifications(
231
-                $transaction->primary_registration(),
232
-                $update_params
233
-            );
234
-        }
235
-        do_action(
236
-            'AHEE__EE_Transaction_Processor__update_transaction_and_registrations_after_checkout_or_payment',
237
-            $transaction,
238
-            $update_params
239
-        );
240
-        return $update_params;
241
-    }
242
-
243
-
244
-    /**
245
-     * update_transaction_after_registration_reopened
246
-     * readjusts TXN and Line Item totals after a registration is changed from
247
-     * cancelled or declined to another reg status such as pending payment or approved
248
-     *
249
-     * @param EE_Registration $registration
250
-     * @param array           $closed_reg_statuses
251
-     * @param bool            $update_txn
252
-     * @return bool
253
-     * @throws EE_Error
254
-     * @throws ReflectionException
255
-     */
256
-    public function update_transaction_after_reinstating_canceled_registration(
257
-        EE_Registration $registration,
258
-        $closed_reg_statuses = array(),
259
-        $update_txn = true
260
-    ) {
261
-        // these reg statuses should not be considered in any calculations involving monies owing
262
-        $closed_reg_statuses = ! empty($closed_reg_statuses) ? $closed_reg_statuses
263
-            : EEM_Registration::closed_reg_statuses();
264
-        if (in_array($registration->status_ID(), $closed_reg_statuses, true)) {
265
-            return false;
266
-        }
267
-        try {
268
-            $transaction = $this->get_transaction_for_registration($registration);
269
-            $ticket_line_item = $this->get_ticket_line_item_for_transaction_registration(
270
-                $transaction,
271
-                $registration
272
-            );
273
-            // un-cancel the ticket
274
-            $success = EEH_Line_Item::reinstate_canceled_ticket_line_item($ticket_line_item);
275
-        } catch (EE_Error $e) {
276
-            EE_Error::add_error(
277
-                sprintf(
278
-                    __(
279
-                        'The Ticket Line Item for Registration %1$d could not be reinstated because :%2$s%3$s',
280
-                        'event_espresso'
281
-                    ),
282
-                    $registration->ID(),
283
-                    '<br />',
284
-                    $e->getMessage()
285
-                ),
286
-                __FILE__,
287
-                __FUNCTION__,
288
-                __LINE__
289
-            );
290
-            return false;
291
-        }
292
-        if ($update_txn) {
293
-            return $transaction->save() ? $success : false;
294
-        }
295
-        return $success;
296
-    }
297
-
298
-
299
-    /**
300
-     * update_transaction_after_canceled_or_declined_registration
301
-     * readjusts TXN and Line Item totals after a registration is cancelled or declined
302
-     *
303
-     * @param EE_Registration $registration
304
-     * @param array           $closed_reg_statuses
305
-     * @param bool            $update_txn
306
-     * @return bool
307
-     * @throws EE_Error
308
-     * @throws ReflectionException
309
-     */
310
-    public function update_transaction_after_canceled_or_declined_registration(
311
-        EE_Registration $registration,
312
-        $closed_reg_statuses = array(),
313
-        $update_txn = true
314
-    ) {
315
-        // these reg statuses should not be considered in any calculations involving monies owing
316
-        $closed_reg_statuses = ! empty($closed_reg_statuses) ? $closed_reg_statuses
317
-            : EEM_Registration::closed_reg_statuses();
318
-        if (! in_array($registration->status_ID(), $closed_reg_statuses, true)) {
319
-            return false;
320
-        }
321
-        try {
322
-            $transaction = $this->get_transaction_for_registration($registration);
323
-            if (
324
-                apply_filters(
325
-                    'FHEE__EE_Transaction_Processor__update_transaction_after_canceled_or_declined_registration__cancel_ticket_line_item',
326
-                    true,
327
-                    $registration,
328
-                    $transaction
329
-                )
330
-            ) {
331
-                $ticket_line_item = $this->get_ticket_line_item_for_transaction_registration(
332
-                    $transaction,
333
-                    $registration
334
-                );
335
-                EEH_Line_Item::cancel_ticket_line_item($ticket_line_item);
336
-            }
337
-        } catch (EE_Error $e) {
338
-            EE_Error::add_error(
339
-                sprintf(
340
-                    __(
341
-                        'The Ticket Line Item for Registration %1$d could not be cancelled because :%2$s%3$s',
342
-                        'event_espresso'
343
-                    ),
344
-                    $registration->ID(),
345
-                    '<br />',
346
-                    $e->getMessage()
347
-                ),
348
-                __FILE__,
349
-                __FUNCTION__,
350
-                __LINE__
351
-            );
352
-            return false;
353
-        }
354
-        if ($update_txn) {
355
-            return $transaction->save() ? true : false;
356
-        }
357
-        return true;
358
-    }
359
-
360
-
361
-    /**
362
-     * get_transaction_for_registration
363
-     *
364
-     * @access    public
365
-     * @param    EE_Registration $registration
366
-     * @return    EE_Transaction
367
-     * @throws    EE_Error
368
-     */
369
-    public function get_transaction_for_registration(EE_Registration $registration)
370
-    {
371
-        $transaction = $registration->transaction();
372
-        if (! $transaction instanceof EE_Transaction) {
373
-            throw new EE_Error(
374
-                sprintf(
375
-                    __('The Transaction for Registration %1$d was not found or is invalid.', 'event_espresso'),
376
-                    $registration->ID()
377
-                )
378
-            );
379
-        }
380
-        return $transaction;
381
-    }
382
-
383
-
384
-    /**
385
-     * get_ticket_line_item_for_transaction_registration
386
-     *
387
-     * @access    public
388
-     * @param EE_Transaction  $transaction
389
-     * @param EE_Registration $registration
390
-     * @return    EE_Line_Item
391
-     * @throws    EE_Error
392
-     * @throws ReflectionException
393
-     */
394
-    public function get_ticket_line_item_for_transaction_registration(
395
-        EE_Transaction $transaction,
396
-        EE_Registration $registration
397
-    ) {
398
-        EE_Registry::instance()->load_helper('Line_Item');
399
-        $ticket_line_item = EEM_Line_Item::instance()->get_ticket_line_item_for_transaction(
400
-            $transaction->ID(),
401
-            $registration->ticket_ID()
402
-        );
403
-        if (! $ticket_line_item instanceof EE_Line_Item) {
404
-            throw new EE_Error(
405
-                sprintf(
406
-                    __(
407
-                        'The Line Item for Transaction %1$d and Ticket %2$d was not found or is invalid.',
408
-                        'event_espresso'
409
-                    ),
410
-                    $transaction->ID(),
411
-                    $registration->ticket_ID()
412
-                )
413
-            );
414
-        }
415
-        return $ticket_line_item;
416
-    }
417
-
418
-
419
-    /**
420
-     * cancel_transaction_if_all_registrations_canceled
421
-     * cycles thru related registrations and checks their statuses
422
-     * if ALL registrations are Cancelled or Declined, then this sets the TXN status to
423
-     *
424
-     * @access    public
425
-     * @param    EE_Transaction $transaction
426
-     * @param    string         $new_TXN_status
427
-     * @param    array          $registration_query_params - array of query WHERE params to use when
428
-     *                                                     retrieving cached registrations from a transaction
429
-     * @param    array          $closed_reg_statuses
430
-     * @param    bool           $update_txn
431
-     * @return    bool            true if TXN status was updated, false if not
432
-     */
433
-    public function toggle_transaction_status_if_all_registrations_canceled_or_declined(
434
-        EE_Transaction $transaction,
435
-        $new_TXN_status = '',
436
-        $registration_query_params = array(),
437
-        $closed_reg_statuses = array(),
438
-        $update_txn = true
439
-    ) {
440
-        // make sure some query params are set for retrieving registrations
441
-        $this->_set_registration_query_params($registration_query_params);
442
-        // these reg statuses should not be considered in any calculations involving monies owing
443
-        $closed_reg_statuses = ! empty($closed_reg_statuses) ? $closed_reg_statuses
444
-            : EEM_Registration::closed_reg_statuses();
445
-        // loop through cached registrations
446
-        foreach ($transaction->registrations($this->_registration_query_params) as $registration) {
447
-            if (
448
-                $registration instanceof EE_Registration
449
-                && ! in_array($registration->status_ID(), $closed_reg_statuses)
450
-            ) {
451
-                return false;
452
-            }
453
-        }
454
-        if (in_array($new_TXN_status, EEM_Transaction::txn_status_array())) {
455
-            $transaction->set_status($new_TXN_status);
456
-        }
457
-        if ($update_txn) {
458
-            return $transaction->save() ? true : false;
459
-        }
460
-        return true;
461
-    }
462
-
463
-
464
-    /**
465
-     * _call_method_on_registrations_via_Registration_Processor
466
-     * cycles thru related registrations and calls the requested method on each
467
-     *
468
-     * @access private
469
-     * @param string         $method_name
470
-     * @param EE_Transaction $transaction
471
-     * @param array          $registration_query_params array of query WHERE params to use
472
-     *                                                  when retrieving cached registrations from a transaction
473
-     * @param string         $additional_param
474
-     * @return boolean
475
-     * @throws ReflectionException
476
-     * @throws EE_Error
477
-     */
478
-    private function _call_method_on_registrations_via_Registration_Processor(
479
-        $method_name,
480
-        EE_Transaction $transaction,
481
-        $registration_query_params = array(),
482
-        $additional_param = null
483
-    ) {
484
-        $response = false;
485
-        /** @type EE_Registration_Processor $registration_processor */
486
-        $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
487
-        // check that method exists
488
-        if (! method_exists($registration_processor, $method_name)) {
489
-            throw new EE_Error(__('Method does not exist.', 'event_espresso'));
490
-        }
491
-        // make sure some query params are set for retrieving registrations
492
-        $this->_set_registration_query_params($registration_query_params);
493
-        // loop through cached registrations
494
-        foreach ($transaction->registrations($this->_registration_query_params) as $registration) {
495
-            if ($registration instanceof EE_Registration) {
496
-                if ($additional_param) {
497
-                    $response = $registration_processor->{$method_name}($registration, $additional_param)
498
-                        ? true
499
-                        : $response;
500
-                } else {
501
-                    $response = $registration_processor->{$method_name}($registration)
502
-                        ? true
503
-                        : $response;
504
-                }
505
-            }
506
-        }
507
-        return $response;
508
-    }
509
-
510
-
511
-    /**
512
-     * set_transaction_payment_method_based_on_registration_statuses
513
-     * sets or unsets the PMD_ID field on the TXN based on the related REG statuses
514
-     * basically if ALL Registrations are "Not Approved", then the EE_Transaction.PMD_ID is set to null,
515
-     * but if any Registration has a different status, then EE_Transaction.PMD_ID is set to either:
516
-     *        the first "default" Payment Method
517
-     *        the first active Payment Method
518
-     *    whichever is found first.
519
-     *
520
-     * @param EE_Registration $edited_registration
521
-     * @return void
522
-     * @throws EE_Error
523
-     * @throws ReflectionException
524
-     */
525
-    public function set_transaction_payment_method_based_on_registration_statuses(
526
-        EE_Registration $edited_registration
527
-    ) {
528
-        if ($edited_registration instanceof EE_Registration) {
529
-            $transaction = $edited_registration->transaction();
530
-            if ($transaction instanceof EE_Transaction) {
531
-                $all_not_approved = true;
532
-                foreach ($transaction->registrations() as $registration) {
533
-                    if ($registration instanceof EE_Registration) {
534
-                        // if any REG != "Not Approved" then toggle to false
535
-                        $all_not_approved = $registration->is_not_approved() ? $all_not_approved : false;
536
-                    }
537
-                }
538
-                // if ALL Registrations are "Not Approved"
539
-                if ($all_not_approved) {
540
-                    $transaction->set_payment_method_ID(null);
541
-                    $transaction->save();
542
-                } else {
543
-                    $available_payment_methods = EEM_Payment_Method::instance()->get_all_for_transaction(
544
-                        $transaction,
545
-                        EEM_Payment_Method::scope_cart
546
-                    );
547
-                    if (! empty($available_payment_methods)) {
548
-                        $PMD_ID = 0;
549
-                        foreach ($available_payment_methods as $available_payment_method) {
550
-                            if (
551
-                                $available_payment_method instanceof EE_Payment_Method
552
-                                && $available_payment_method->open_by_default()
553
-                            ) {
554
-                                $PMD_ID = $available_payment_method->ID();
555
-                                break;
556
-                            }
557
-                        }
558
-                        if (! $PMD_ID) {
559
-                            $first_payment_method = reset($available_payment_methods);
560
-                            if ($first_payment_method instanceof EE_Payment_Method) {
561
-                                $PMD_ID = $first_payment_method->ID();
562
-                            } else {
563
-                                EE_Error::add_error(
564
-                                    __(
565
-                                        'A valid Payment Method could not be determined. Please ensure that at least one Payment Method is activated.',
566
-                                        'event_espresso'
567
-                                    ),
568
-                                    __FILE__,
569
-                                    __LINE__,
570
-                                    __FUNCTION__
571
-                                );
572
-                            }
573
-                        }
574
-                        $transaction->set_payment_method_ID($PMD_ID);
575
-                        $transaction->save();
576
-                    } else {
577
-                        EE_Error::add_error(
578
-                            __(
579
-                                'Please activate at least one Payment Method in order for things to operate correctly.',
580
-                                'event_espresso'
581
-                            ),
582
-                            __FILE__,
583
-                            __LINE__,
584
-                            __FUNCTION__
585
-                        );
586
-                    }
587
-                }
588
-            }
589
-        }
590
-    }
591
-
592
-
593
-
594
-    /********************************** DEPRECATED METHODS **********************************/
595
-
596
-
597
-    /**
598
-     * @deprecated 4.9.12
599
-     * @return string
600
-     */
601
-    public function old_txn_status()
602
-    {
603
-        EE_Error::doing_it_wrong(
604
-            __METHOD__,
605
-            esc_html__(
606
-                'This logic has been moved into \EE_Transaction::old_txn_status(), please use that method instead.',
607
-                'event_espresso'
608
-            ),
609
-            '4.9.12'
610
-        );
611
-        return $this->_old_txn_status;
612
-    }
613
-
614
-
615
-    /**
616
-     * @deprecated 4.9.12
617
-     * @param string $old_txn_status
618
-     */
619
-    public function set_old_txn_status($old_txn_status)
620
-    {
621
-        EE_Error::doing_it_wrong(
622
-            __METHOD__,
623
-            esc_html__(
624
-                'This logic has been moved into \EE_Transaction::set_old_txn_status(), please use that method instead.',
625
-                'event_espresso'
626
-            ),
627
-            '4.9.12'
628
-        );
629
-        // only set the first time
630
-        if ($this->_old_txn_status === null) {
631
-            $this->_old_txn_status = $old_txn_status;
632
-        }
633
-    }
634
-
635
-
636
-    /**
637
-     * @deprecated 4.9.12
638
-     * @return string
639
-     */
640
-    public function new_txn_status()
641
-    {
642
-        EE_Error::doing_it_wrong(
643
-            __METHOD__,
644
-            esc_html__(
645
-                'This logic has been removed. Please just use \EE_Transaction::status_ID() instead.',
646
-                'event_espresso'
647
-            ),
648
-            '4.9.12'
649
-        );
650
-        return $this->_new_txn_status;
651
-    }
652
-
653
-
654
-    /**
655
-     * @deprecated 4.9.12
656
-     * @param string $new_txn_status
657
-     */
658
-    public function set_new_txn_status($new_txn_status)
659
-    {
660
-        EE_Error::doing_it_wrong(
661
-            __METHOD__,
662
-            esc_html__(
663
-                'This logic has been removed. Please just use \EE_Transaction::set_status() instead.',
664
-                'event_espresso'
665
-            ),
666
-            '4.9.12'
667
-        );
668
-        $this->_new_txn_status = $new_txn_status;
669
-    }
670
-
671
-
672
-    /**
673
-     * reg_status_updated
674
-     *
675
-     * @deprecated 4.9.12
676
-     * @return bool
677
-     */
678
-    public function txn_status_updated()
679
-    {
680
-        EE_Error::doing_it_wrong(
681
-            __METHOD__,
682
-            esc_html__(
683
-                'This logic has been moved into \EE_Transaction::txn_status_updated(), please use that method instead.',
684
-                'event_espresso'
685
-            ),
686
-            '4.9.12'
687
-        );
688
-        return $this->_new_txn_status !== $this->_old_txn_status && $this->_old_txn_status !== null ? true : false;
689
-    }
690
-
691
-
692
-    /**
693
-     * all_reg_steps_completed
694
-     * returns:
695
-     *    true if ALL reg steps have been marked as completed
696
-     *        or false if any step is not completed
697
-     *
698
-     * @deprecated 4.9.12
699
-     * @param EE_Transaction $transaction
700
-     * @return boolean
701
-     */
702
-    public function all_reg_steps_completed(EE_Transaction $transaction)
703
-    {
704
-        EE_Error::doing_it_wrong(
705
-            __METHOD__,
706
-            esc_html__(
707
-                'This logic has been moved into \EE_Transaction::all_reg_steps_completed(), please use that method instead.',
708
-                'event_espresso'
709
-            ),
710
-            '4.9.12',
711
-            '5.0.0'
712
-        );
713
-        return $transaction->all_reg_steps_completed();
714
-    }
715
-
716
-
717
-    /**
718
-     * all_reg_steps_completed_except
719
-     * returns:
720
-     *        true if ALL reg steps, except a particular step that you wish to skip over, have been marked as completed
721
-     *        or false if any other step is not completed
722
-     *        or false if ALL steps are completed including the exception you are testing !!!
723
-     *
724
-     * @deprecated 4.9.12
725
-     * @param EE_Transaction $transaction
726
-     * @param string         $exception
727
-     * @return boolean
728
-     */
729
-    public function all_reg_steps_completed_except(EE_Transaction $transaction, $exception = '')
730
-    {
731
-        EE_Error::doing_it_wrong(
732
-            __METHOD__,
733
-            esc_html__(
734
-                'This logic has been moved into \EE_Transaction::all_reg_steps_completed_except(), please use that method instead.',
735
-                'event_espresso'
736
-            ),
737
-            '4.9.12',
738
-            '5.0.0'
739
-        );
740
-        return $transaction->all_reg_steps_completed_except($exception);
741
-    }
742
-
743
-
744
-    /**
745
-     * all_reg_steps_completed_except
746
-     * returns:
747
-     *        true if ALL reg steps, except the final step, have been marked as completed
748
-     *        or false if any step is not completed
749
-     *    or false if ALL steps are completed including the final step !!!
750
-     *
751
-     * @deprecated 4.9.12
752
-     * @param EE_Transaction $transaction
753
-     * @return boolean
754
-     */
755
-    public function all_reg_steps_completed_except_final_step(EE_Transaction $transaction)
756
-    {
757
-        EE_Error::doing_it_wrong(
758
-            __METHOD__,
759
-            esc_html__(
760
-                'This logic has been moved into \EE_Transaction::all_reg_steps_completed_except_final_step(), please use that method instead.',
761
-                'event_espresso'
762
-            ),
763
-            '4.9.12',
764
-            '5.0.0'
765
-        );
766
-        return $transaction->all_reg_steps_completed_except_final_step();
767
-    }
768
-
769
-
770
-    /**
771
-     * reg_step_completed
772
-     * returns:
773
-     *    true if a specific reg step has been marked as completed
774
-     *    a Unix timestamp if it has been initialized but not yet completed,
775
-     *    or false if it has not yet been initialized
776
-     *
777
-     * @deprecated 4.9.12
778
-     * @param EE_Transaction $transaction
779
-     * @param string         $reg_step_slug
780
-     * @return boolean | int
781
-     */
782
-    public function reg_step_completed(EE_Transaction $transaction, $reg_step_slug)
783
-    {
784
-        EE_Error::doing_it_wrong(
785
-            __METHOD__,
786
-            esc_html__(
787
-                'This logic has been moved into \EE_Transaction::reg_step_completed(), please use that method instead.',
788
-                'event_espresso'
789
-            ),
790
-            '4.9.12',
791
-            '5.0.0'
792
-        );
793
-        return $transaction->reg_step_completed($reg_step_slug);
794
-    }
795
-
796
-
797
-    /**
798
-     * completed_final_reg_step
799
-     * returns:
800
-     *    true if the finalize_registration reg step has been marked as completed
801
-     *    a Unix timestamp if it has been initialized but not yet completed,
802
-     *    or false if it has not yet been initialized
803
-     *
804
-     * @deprecated 4.9.12
805
-     * @param EE_Transaction $transaction
806
-     * @return boolean | int
807
-     */
808
-    public function final_reg_step_completed(EE_Transaction $transaction)
809
-    {
810
-        EE_Error::doing_it_wrong(
811
-            __METHOD__,
812
-            esc_html__(
813
-                'This logic has been moved into \EE_Transaction::final_reg_step_completed(), please use that method instead.',
814
-                'event_espresso'
815
-            ),
816
-            '4.9.12',
817
-            '5.0.0'
818
-        );
819
-        return $transaction->final_reg_step_completed();
820
-    }
821
-
822
-
823
-    /**
824
-     * set_reg_step_initiated
825
-     * given a valid TXN_reg_step, this sets it's value to a unix timestamp
826
-     *
827
-     * @param EE_Transaction $transaction
828
-     * @param string         $reg_step_slug
829
-     * @return boolean
830
-     * @throws EE_Error*@throws ReflectionException
831
-     * @deprecated 4.9.12
832
-     * @access     public
833
-     */
834
-    public function set_reg_step_initiated(EE_Transaction $transaction, $reg_step_slug)
835
-    {
836
-        EE_Error::doing_it_wrong(
837
-            __METHOD__,
838
-            esc_html__(
839
-                'This logic has been moved into \EE_Transaction::set_reg_step_initiated(), please use that method instead.',
840
-                'event_espresso'
841
-            ),
842
-            '4.9.12',
843
-            '5.0.0'
844
-        );
845
-        return $transaction->set_reg_step_initiated($reg_step_slug);
846
-    }
847
-
848
-
849
-    /**
850
-     * set_reg_step_completed
851
-     * given a valid TXN_reg_step, this sets the step as completed
852
-     *
853
-     * @param EE_Transaction $transaction
854
-     * @param string         $reg_step_slug
855
-     * @return boolean
856
-     * @throws EE_Error*@throws ReflectionException
857
-     * @deprecated 4.9.12
858
-     * @access     public
859
-     */
860
-    public function set_reg_step_completed(EE_Transaction $transaction, $reg_step_slug)
861
-    {
862
-        EE_Error::doing_it_wrong(
863
-            __METHOD__,
864
-            esc_html__(
865
-                'This logic has been moved into \EE_Transaction::set_reg_step_completed(), please use that method instead.',
866
-                'event_espresso'
867
-            ),
868
-            '4.9.12',
869
-            '5.0.0'
870
-        );
871
-        return $transaction->set_reg_step_completed($reg_step_slug);
872
-    }
873
-
874
-
875
-    /**
876
-     * set_reg_step_completed
877
-     * given a valid TXN_reg_step slug, this sets the step as NOT completed
878
-     *
879
-     * @param EE_Transaction $transaction
880
-     * @param string         $reg_step_slug
881
-     * @return boolean
882
-     * @throws EE_Error*@throws ReflectionException
883
-     * @deprecated 4.9.12
884
-     * @access     public
885
-     */
886
-    public function set_reg_step_not_completed(EE_Transaction $transaction, $reg_step_slug)
887
-    {
888
-        EE_Error::doing_it_wrong(
889
-            __METHOD__,
890
-            esc_html__(
891
-                'This logic has been moved into \EE_Transaction::set_reg_step_not_completed(), please use that method instead.',
892
-                'event_espresso'
893
-            ),
894
-            '4.9.12',
895
-            '5.0.0'
896
-        );
897
-        return $transaction->set_reg_step_not_completed($reg_step_slug);
898
-    }
899
-
900
-
901
-    /**
902
-     * remove_reg_step
903
-     * given a valid TXN_reg_step slug, this will remove (unset)
904
-     * the reg step from the TXN reg step array
905
-     *
906
-     * @param EE_Transaction $transaction
907
-     * @param string         $reg_step_slug
908
-     * @return void
909
-     *@deprecated 4.9.12
910
-     * @access     public
911
-     */
912
-    public function remove_reg_step(EE_Transaction $transaction, $reg_step_slug)
913
-    {
914
-        EE_Error::doing_it_wrong(
915
-            __METHOD__,
916
-            esc_html__(
917
-                'This logic has been moved into \EE_Transaction::remove_reg_step(), please use that method instead.',
918
-                'event_espresso'
919
-            ),
920
-            '4.9.12',
921
-            '5.0.0'
922
-        );
923
-        $transaction->remove_reg_step($reg_step_slug);
924
-    }
925
-
926
-
927
-    /**
928
-     *    toggle_failed_transaction_status
929
-     * upgrades a TXNs status from failed to abandoned,
930
-     * meaning that contact information has been captured for at least one registrant
931
-     *
932
-     * @param EE_Transaction $transaction
933
-     * @return    boolean
934
-     * @throws EE_Error*@throws ReflectionException
935
-     * @deprecated 4.9.12
936
-     * @access     public
937
-     */
938
-    public function toggle_failed_transaction_status(EE_Transaction $transaction)
939
-    {
940
-        EE_Error::doing_it_wrong(
941
-            __METHOD__,
942
-            esc_html__(
943
-                'This logic has been moved into \EE_Transaction::toggle_failed_transaction_status(), please use that method instead.',
944
-                'event_espresso'
945
-            ),
946
-            '4.9.12',
947
-            '5.0.0'
948
-        );
949
-        return $transaction->toggle_failed_transaction_status();
950
-    }
951
-
952
-
953
-    /**
954
-     * toggle_abandoned_transaction_status
955
-     * upgrades a TXNs status from failed or abandoned to incomplete
956
-     *
957
-     * @deprecated 4.9.12
958
-     * @access     public
959
-     * @param  EE_Transaction $transaction
960
-     * @return boolean
961
-     */
962
-    public function toggle_abandoned_transaction_status(EE_Transaction $transaction)
963
-    {
964
-        EE_Error::doing_it_wrong(
965
-            __METHOD__,
966
-            esc_html__(
967
-                'This logic has been moved into \EE_Transaction::toggle_abandoned_transaction_status(), please use that method instead.',
968
-                'event_espresso'
969
-            ),
970
-            '4.9.12',
971
-            '5.0.0'
972
-        );
973
-        return $transaction->toggle_abandoned_transaction_status();
974
-    }
20
+	/**
21
+	 * @var EE_Registration_Processor $_instance
22
+	 * @access    private
23
+	 */
24
+	private static $_instance;
25
+
26
+	/**
27
+	 * array of query WHERE params to use when retrieving cached registrations from a transaction
28
+	 *
29
+	 * @var array $registration_query_params
30
+	 * @access private
31
+	 */
32
+	private $_registration_query_params = array();
33
+
34
+	/**
35
+	 * @deprecated
36
+	 * @var string
37
+	 */
38
+	protected $_old_txn_status;
39
+
40
+	/**
41
+	 * @deprecated
42
+	 * @var string
43
+	 */
44
+	protected $_new_txn_status;
45
+
46
+
47
+	/**
48
+	 * @singleton method used to instantiate class object
49
+	 * @access    public
50
+	 * @param array $registration_query_params
51
+	 * @return EE_Transaction_Processor instance
52
+	 */
53
+	public static function instance($registration_query_params = array())
54
+	{
55
+		// check if class object is instantiated
56
+		if (! self::$_instance instanceof EE_Transaction_Processor) {
57
+			self::$_instance = new self($registration_query_params);
58
+		}
59
+		return self::$_instance;
60
+	}
61
+
62
+
63
+	/**
64
+	 * @param array $registration_query_params
65
+	 */
66
+	private function __construct($registration_query_params = array())
67
+	{
68
+		// make sure some query params are set for retrieving registrations
69
+		$this->_set_registration_query_params($registration_query_params);
70
+	}
71
+
72
+
73
+	/**
74
+	 * @access private
75
+	 * @param array $registration_query_params
76
+	 */
77
+	private function _set_registration_query_params($registration_query_params)
78
+	{
79
+		$this->_registration_query_params = ! empty($registration_query_params) ? $registration_query_params
80
+			: array('order_by' => array('REG_count' => 'ASC'));
81
+	}
82
+
83
+
84
+	/**
85
+	 * manually_update_registration_statuses
86
+	 *
87
+	 * @access public
88
+	 * @param EE_Transaction $transaction
89
+	 * @param string         $new_reg_status
90
+	 * @param array          $registration_query_params array of query WHERE params to use
91
+	 *                                                  when retrieving cached registrations from a transaction
92
+	 * @return    boolean
93
+	 * @throws EE_Error
94
+	 * @throws ReflectionException
95
+	 */
96
+	public function manually_update_registration_statuses(
97
+		EE_Transaction $transaction,
98
+		$new_reg_status = '',
99
+		$registration_query_params = array()
100
+	) {
101
+		$status_updates = $this->_call_method_on_registrations_via_Registration_Processor(
102
+			'manually_update_registration_status',
103
+			$transaction,
104
+			$registration_query_params,
105
+			$new_reg_status
106
+		);
107
+		// send messages
108
+		/** @type EE_Registration_Processor $registration_processor */
109
+		$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
110
+		$registration_processor->trigger_registration_update_notifications(
111
+			$transaction->primary_registration(),
112
+			array('manually_updated' => true)
113
+		);
114
+		do_action(
115
+			'AHEE__EE_Transaction_Processor__manually_update_registration_statuses',
116
+			$transaction,
117
+			$status_updates
118
+		);
119
+		return $status_updates;
120
+	}
121
+
122
+
123
+	/**
124
+	 * toggle_registration_statuses_for_default_approved_events
125
+	 *
126
+	 * @access public
127
+	 * @param EE_Transaction $transaction
128
+	 * @param array          $registration_query_params array of query WHERE params to use
129
+	 *                                                  when retrieving cached registrations from a transaction
130
+	 * @return    boolean
131
+	 * @throws EE_Error
132
+	 */
133
+	public function toggle_registration_statuses_for_default_approved_events(
134
+		EE_Transaction $transaction,
135
+		$registration_query_params = array()
136
+	) {
137
+		$status_updates = $this->_call_method_on_registrations_via_Registration_Processor(
138
+			'toggle_registration_status_for_default_approved_events',
139
+			$transaction,
140
+			$registration_query_params
141
+		);
142
+		do_action(
143
+			'AHEE__EE_Transaction_Processor__toggle_registration_statuses_for_default_approved_events',
144
+			$transaction,
145
+			$status_updates
146
+		);
147
+		return $status_updates;
148
+	}
149
+
150
+
151
+	/**
152
+	 * toggle_registration_statuses_if_no_monies_owing
153
+	 *
154
+	 * @access public
155
+	 * @param EE_Transaction $transaction
156
+	 * @param array          $registration_query_params array of query WHERE params to use
157
+	 *                                                  when retrieving cached registrations from a transaction
158
+	 * @return    boolean
159
+	 * @throws EE_Error
160
+	 */
161
+	public function toggle_registration_statuses_if_no_monies_owing(
162
+		EE_Transaction $transaction,
163
+		$registration_query_params = array()
164
+	) {
165
+		$status_updates = $this->_call_method_on_registrations_via_Registration_Processor(
166
+			'toggle_registration_status_if_no_monies_owing',
167
+			$transaction,
168
+			$registration_query_params
169
+		);
170
+		do_action(
171
+			'AHEE__EE_Transaction_Processor__toggle_registration_statuses_if_no_monies_owing',
172
+			$transaction,
173
+			$status_updates
174
+		);
175
+		return $status_updates;
176
+	}
177
+
178
+
179
+	/**
180
+	 * update_transaction_and_registrations_after_checkout_or_payment
181
+	 * cycles thru related registrations and calls update_registration_after_checkout_or_payment() on each
182
+	 *
183
+	 * @param EE_Transaction    $transaction
184
+	 * @param EE_Payment | NULL $payment
185
+	 * @param array             $registration_query_params    array of query WHERE params to use
186
+	 *                                                         when retrieving cached registrations from a transaction
187
+	 * @param bool              $trigger_notifications        whether or not to call
188
+	 *                                                         \EE_Registration_Processor::trigger_registration_update_notifications()
189
+	 * @return array
190
+	 * @throws EE_Error
191
+	 * @throws ReflectionException
192
+	 */
193
+	public function update_transaction_and_registrations_after_checkout_or_payment(
194
+		EE_Transaction $transaction,
195
+		$payment = null,
196
+		$registration_query_params = array(),
197
+		$trigger_notifications = true
198
+	): array {
199
+		// make sure some query params are set for retrieving registrations
200
+		$this->_set_registration_query_params($registration_query_params);
201
+		// get final reg step status
202
+		$finalized = $transaction->final_reg_step_completed();
203
+		// if the 'finalize_registration' step has been initiated (has a timestamp)
204
+		// but has not yet been fully completed (TRUE)
205
+		if (is_int($finalized) && $finalized !== false && $finalized !== true) {
206
+			$transaction->set_reg_step_completed('finalize_registration');
207
+			$finalized = true;
208
+		}
209
+		$transaction->save();
210
+		// array of details to aid in decision making by systems
211
+		$update_params = array(
212
+			'old_txn_status'  => $transaction->old_txn_status(),
213
+			'new_txn_status'  => $transaction->status_ID(),
214
+			'finalized'       => $finalized,
215
+			'revisit'         => $this->_revisit,
216
+			'payment_updates' => $payment instanceof EE_Payment ? true : false,
217
+			'last_payment'    => $payment,
218
+		);
219
+		// now update the registrations and add the results to our $update_params
220
+		$update_params['status_updates'] = $this->_call_method_on_registrations_via_Registration_Processor(
221
+			'update_registration_after_checkout_or_payment',
222
+			$transaction,
223
+			$this->_registration_query_params,
224
+			$update_params
225
+		);
226
+		if ($trigger_notifications) {
227
+			// send messages
228
+			/** @type EE_Registration_Processor $registration_processor */
229
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
230
+			$registration_processor->trigger_registration_update_notifications(
231
+				$transaction->primary_registration(),
232
+				$update_params
233
+			);
234
+		}
235
+		do_action(
236
+			'AHEE__EE_Transaction_Processor__update_transaction_and_registrations_after_checkout_or_payment',
237
+			$transaction,
238
+			$update_params
239
+		);
240
+		return $update_params;
241
+	}
242
+
243
+
244
+	/**
245
+	 * update_transaction_after_registration_reopened
246
+	 * readjusts TXN and Line Item totals after a registration is changed from
247
+	 * cancelled or declined to another reg status such as pending payment or approved
248
+	 *
249
+	 * @param EE_Registration $registration
250
+	 * @param array           $closed_reg_statuses
251
+	 * @param bool            $update_txn
252
+	 * @return bool
253
+	 * @throws EE_Error
254
+	 * @throws ReflectionException
255
+	 */
256
+	public function update_transaction_after_reinstating_canceled_registration(
257
+		EE_Registration $registration,
258
+		$closed_reg_statuses = array(),
259
+		$update_txn = true
260
+	) {
261
+		// these reg statuses should not be considered in any calculations involving monies owing
262
+		$closed_reg_statuses = ! empty($closed_reg_statuses) ? $closed_reg_statuses
263
+			: EEM_Registration::closed_reg_statuses();
264
+		if (in_array($registration->status_ID(), $closed_reg_statuses, true)) {
265
+			return false;
266
+		}
267
+		try {
268
+			$transaction = $this->get_transaction_for_registration($registration);
269
+			$ticket_line_item = $this->get_ticket_line_item_for_transaction_registration(
270
+				$transaction,
271
+				$registration
272
+			);
273
+			// un-cancel the ticket
274
+			$success = EEH_Line_Item::reinstate_canceled_ticket_line_item($ticket_line_item);
275
+		} catch (EE_Error $e) {
276
+			EE_Error::add_error(
277
+				sprintf(
278
+					__(
279
+						'The Ticket Line Item for Registration %1$d could not be reinstated because :%2$s%3$s',
280
+						'event_espresso'
281
+					),
282
+					$registration->ID(),
283
+					'<br />',
284
+					$e->getMessage()
285
+				),
286
+				__FILE__,
287
+				__FUNCTION__,
288
+				__LINE__
289
+			);
290
+			return false;
291
+		}
292
+		if ($update_txn) {
293
+			return $transaction->save() ? $success : false;
294
+		}
295
+		return $success;
296
+	}
297
+
298
+
299
+	/**
300
+	 * update_transaction_after_canceled_or_declined_registration
301
+	 * readjusts TXN and Line Item totals after a registration is cancelled or declined
302
+	 *
303
+	 * @param EE_Registration $registration
304
+	 * @param array           $closed_reg_statuses
305
+	 * @param bool            $update_txn
306
+	 * @return bool
307
+	 * @throws EE_Error
308
+	 * @throws ReflectionException
309
+	 */
310
+	public function update_transaction_after_canceled_or_declined_registration(
311
+		EE_Registration $registration,
312
+		$closed_reg_statuses = array(),
313
+		$update_txn = true
314
+	) {
315
+		// these reg statuses should not be considered in any calculations involving monies owing
316
+		$closed_reg_statuses = ! empty($closed_reg_statuses) ? $closed_reg_statuses
317
+			: EEM_Registration::closed_reg_statuses();
318
+		if (! in_array($registration->status_ID(), $closed_reg_statuses, true)) {
319
+			return false;
320
+		}
321
+		try {
322
+			$transaction = $this->get_transaction_for_registration($registration);
323
+			if (
324
+				apply_filters(
325
+					'FHEE__EE_Transaction_Processor__update_transaction_after_canceled_or_declined_registration__cancel_ticket_line_item',
326
+					true,
327
+					$registration,
328
+					$transaction
329
+				)
330
+			) {
331
+				$ticket_line_item = $this->get_ticket_line_item_for_transaction_registration(
332
+					$transaction,
333
+					$registration
334
+				);
335
+				EEH_Line_Item::cancel_ticket_line_item($ticket_line_item);
336
+			}
337
+		} catch (EE_Error $e) {
338
+			EE_Error::add_error(
339
+				sprintf(
340
+					__(
341
+						'The Ticket Line Item for Registration %1$d could not be cancelled because :%2$s%3$s',
342
+						'event_espresso'
343
+					),
344
+					$registration->ID(),
345
+					'<br />',
346
+					$e->getMessage()
347
+				),
348
+				__FILE__,
349
+				__FUNCTION__,
350
+				__LINE__
351
+			);
352
+			return false;
353
+		}
354
+		if ($update_txn) {
355
+			return $transaction->save() ? true : false;
356
+		}
357
+		return true;
358
+	}
359
+
360
+
361
+	/**
362
+	 * get_transaction_for_registration
363
+	 *
364
+	 * @access    public
365
+	 * @param    EE_Registration $registration
366
+	 * @return    EE_Transaction
367
+	 * @throws    EE_Error
368
+	 */
369
+	public function get_transaction_for_registration(EE_Registration $registration)
370
+	{
371
+		$transaction = $registration->transaction();
372
+		if (! $transaction instanceof EE_Transaction) {
373
+			throw new EE_Error(
374
+				sprintf(
375
+					__('The Transaction for Registration %1$d was not found or is invalid.', 'event_espresso'),
376
+					$registration->ID()
377
+				)
378
+			);
379
+		}
380
+		return $transaction;
381
+	}
382
+
383
+
384
+	/**
385
+	 * get_ticket_line_item_for_transaction_registration
386
+	 *
387
+	 * @access    public
388
+	 * @param EE_Transaction  $transaction
389
+	 * @param EE_Registration $registration
390
+	 * @return    EE_Line_Item
391
+	 * @throws    EE_Error
392
+	 * @throws ReflectionException
393
+	 */
394
+	public function get_ticket_line_item_for_transaction_registration(
395
+		EE_Transaction $transaction,
396
+		EE_Registration $registration
397
+	) {
398
+		EE_Registry::instance()->load_helper('Line_Item');
399
+		$ticket_line_item = EEM_Line_Item::instance()->get_ticket_line_item_for_transaction(
400
+			$transaction->ID(),
401
+			$registration->ticket_ID()
402
+		);
403
+		if (! $ticket_line_item instanceof EE_Line_Item) {
404
+			throw new EE_Error(
405
+				sprintf(
406
+					__(
407
+						'The Line Item for Transaction %1$d and Ticket %2$d was not found or is invalid.',
408
+						'event_espresso'
409
+					),
410
+					$transaction->ID(),
411
+					$registration->ticket_ID()
412
+				)
413
+			);
414
+		}
415
+		return $ticket_line_item;
416
+	}
417
+
418
+
419
+	/**
420
+	 * cancel_transaction_if_all_registrations_canceled
421
+	 * cycles thru related registrations and checks their statuses
422
+	 * if ALL registrations are Cancelled or Declined, then this sets the TXN status to
423
+	 *
424
+	 * @access    public
425
+	 * @param    EE_Transaction $transaction
426
+	 * @param    string         $new_TXN_status
427
+	 * @param    array          $registration_query_params - array of query WHERE params to use when
428
+	 *                                                     retrieving cached registrations from a transaction
429
+	 * @param    array          $closed_reg_statuses
430
+	 * @param    bool           $update_txn
431
+	 * @return    bool            true if TXN status was updated, false if not
432
+	 */
433
+	public function toggle_transaction_status_if_all_registrations_canceled_or_declined(
434
+		EE_Transaction $transaction,
435
+		$new_TXN_status = '',
436
+		$registration_query_params = array(),
437
+		$closed_reg_statuses = array(),
438
+		$update_txn = true
439
+	) {
440
+		// make sure some query params are set for retrieving registrations
441
+		$this->_set_registration_query_params($registration_query_params);
442
+		// these reg statuses should not be considered in any calculations involving monies owing
443
+		$closed_reg_statuses = ! empty($closed_reg_statuses) ? $closed_reg_statuses
444
+			: EEM_Registration::closed_reg_statuses();
445
+		// loop through cached registrations
446
+		foreach ($transaction->registrations($this->_registration_query_params) as $registration) {
447
+			if (
448
+				$registration instanceof EE_Registration
449
+				&& ! in_array($registration->status_ID(), $closed_reg_statuses)
450
+			) {
451
+				return false;
452
+			}
453
+		}
454
+		if (in_array($new_TXN_status, EEM_Transaction::txn_status_array())) {
455
+			$transaction->set_status($new_TXN_status);
456
+		}
457
+		if ($update_txn) {
458
+			return $transaction->save() ? true : false;
459
+		}
460
+		return true;
461
+	}
462
+
463
+
464
+	/**
465
+	 * _call_method_on_registrations_via_Registration_Processor
466
+	 * cycles thru related registrations and calls the requested method on each
467
+	 *
468
+	 * @access private
469
+	 * @param string         $method_name
470
+	 * @param EE_Transaction $transaction
471
+	 * @param array          $registration_query_params array of query WHERE params to use
472
+	 *                                                  when retrieving cached registrations from a transaction
473
+	 * @param string         $additional_param
474
+	 * @return boolean
475
+	 * @throws ReflectionException
476
+	 * @throws EE_Error
477
+	 */
478
+	private function _call_method_on_registrations_via_Registration_Processor(
479
+		$method_name,
480
+		EE_Transaction $transaction,
481
+		$registration_query_params = array(),
482
+		$additional_param = null
483
+	) {
484
+		$response = false;
485
+		/** @type EE_Registration_Processor $registration_processor */
486
+		$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
487
+		// check that method exists
488
+		if (! method_exists($registration_processor, $method_name)) {
489
+			throw new EE_Error(__('Method does not exist.', 'event_espresso'));
490
+		}
491
+		// make sure some query params are set for retrieving registrations
492
+		$this->_set_registration_query_params($registration_query_params);
493
+		// loop through cached registrations
494
+		foreach ($transaction->registrations($this->_registration_query_params) as $registration) {
495
+			if ($registration instanceof EE_Registration) {
496
+				if ($additional_param) {
497
+					$response = $registration_processor->{$method_name}($registration, $additional_param)
498
+						? true
499
+						: $response;
500
+				} else {
501
+					$response = $registration_processor->{$method_name}($registration)
502
+						? true
503
+						: $response;
504
+				}
505
+			}
506
+		}
507
+		return $response;
508
+	}
509
+
510
+
511
+	/**
512
+	 * set_transaction_payment_method_based_on_registration_statuses
513
+	 * sets or unsets the PMD_ID field on the TXN based on the related REG statuses
514
+	 * basically if ALL Registrations are "Not Approved", then the EE_Transaction.PMD_ID is set to null,
515
+	 * but if any Registration has a different status, then EE_Transaction.PMD_ID is set to either:
516
+	 *        the first "default" Payment Method
517
+	 *        the first active Payment Method
518
+	 *    whichever is found first.
519
+	 *
520
+	 * @param EE_Registration $edited_registration
521
+	 * @return void
522
+	 * @throws EE_Error
523
+	 * @throws ReflectionException
524
+	 */
525
+	public function set_transaction_payment_method_based_on_registration_statuses(
526
+		EE_Registration $edited_registration
527
+	) {
528
+		if ($edited_registration instanceof EE_Registration) {
529
+			$transaction = $edited_registration->transaction();
530
+			if ($transaction instanceof EE_Transaction) {
531
+				$all_not_approved = true;
532
+				foreach ($transaction->registrations() as $registration) {
533
+					if ($registration instanceof EE_Registration) {
534
+						// if any REG != "Not Approved" then toggle to false
535
+						$all_not_approved = $registration->is_not_approved() ? $all_not_approved : false;
536
+					}
537
+				}
538
+				// if ALL Registrations are "Not Approved"
539
+				if ($all_not_approved) {
540
+					$transaction->set_payment_method_ID(null);
541
+					$transaction->save();
542
+				} else {
543
+					$available_payment_methods = EEM_Payment_Method::instance()->get_all_for_transaction(
544
+						$transaction,
545
+						EEM_Payment_Method::scope_cart
546
+					);
547
+					if (! empty($available_payment_methods)) {
548
+						$PMD_ID = 0;
549
+						foreach ($available_payment_methods as $available_payment_method) {
550
+							if (
551
+								$available_payment_method instanceof EE_Payment_Method
552
+								&& $available_payment_method->open_by_default()
553
+							) {
554
+								$PMD_ID = $available_payment_method->ID();
555
+								break;
556
+							}
557
+						}
558
+						if (! $PMD_ID) {
559
+							$first_payment_method = reset($available_payment_methods);
560
+							if ($first_payment_method instanceof EE_Payment_Method) {
561
+								$PMD_ID = $first_payment_method->ID();
562
+							} else {
563
+								EE_Error::add_error(
564
+									__(
565
+										'A valid Payment Method could not be determined. Please ensure that at least one Payment Method is activated.',
566
+										'event_espresso'
567
+									),
568
+									__FILE__,
569
+									__LINE__,
570
+									__FUNCTION__
571
+								);
572
+							}
573
+						}
574
+						$transaction->set_payment_method_ID($PMD_ID);
575
+						$transaction->save();
576
+					} else {
577
+						EE_Error::add_error(
578
+							__(
579
+								'Please activate at least one Payment Method in order for things to operate correctly.',
580
+								'event_espresso'
581
+							),
582
+							__FILE__,
583
+							__LINE__,
584
+							__FUNCTION__
585
+						);
586
+					}
587
+				}
588
+			}
589
+		}
590
+	}
591
+
592
+
593
+
594
+	/********************************** DEPRECATED METHODS **********************************/
595
+
596
+
597
+	/**
598
+	 * @deprecated 4.9.12
599
+	 * @return string
600
+	 */
601
+	public function old_txn_status()
602
+	{
603
+		EE_Error::doing_it_wrong(
604
+			__METHOD__,
605
+			esc_html__(
606
+				'This logic has been moved into \EE_Transaction::old_txn_status(), please use that method instead.',
607
+				'event_espresso'
608
+			),
609
+			'4.9.12'
610
+		);
611
+		return $this->_old_txn_status;
612
+	}
613
+
614
+
615
+	/**
616
+	 * @deprecated 4.9.12
617
+	 * @param string $old_txn_status
618
+	 */
619
+	public function set_old_txn_status($old_txn_status)
620
+	{
621
+		EE_Error::doing_it_wrong(
622
+			__METHOD__,
623
+			esc_html__(
624
+				'This logic has been moved into \EE_Transaction::set_old_txn_status(), please use that method instead.',
625
+				'event_espresso'
626
+			),
627
+			'4.9.12'
628
+		);
629
+		// only set the first time
630
+		if ($this->_old_txn_status === null) {
631
+			$this->_old_txn_status = $old_txn_status;
632
+		}
633
+	}
634
+
635
+
636
+	/**
637
+	 * @deprecated 4.9.12
638
+	 * @return string
639
+	 */
640
+	public function new_txn_status()
641
+	{
642
+		EE_Error::doing_it_wrong(
643
+			__METHOD__,
644
+			esc_html__(
645
+				'This logic has been removed. Please just use \EE_Transaction::status_ID() instead.',
646
+				'event_espresso'
647
+			),
648
+			'4.9.12'
649
+		);
650
+		return $this->_new_txn_status;
651
+	}
652
+
653
+
654
+	/**
655
+	 * @deprecated 4.9.12
656
+	 * @param string $new_txn_status
657
+	 */
658
+	public function set_new_txn_status($new_txn_status)
659
+	{
660
+		EE_Error::doing_it_wrong(
661
+			__METHOD__,
662
+			esc_html__(
663
+				'This logic has been removed. Please just use \EE_Transaction::set_status() instead.',
664
+				'event_espresso'
665
+			),
666
+			'4.9.12'
667
+		);
668
+		$this->_new_txn_status = $new_txn_status;
669
+	}
670
+
671
+
672
+	/**
673
+	 * reg_status_updated
674
+	 *
675
+	 * @deprecated 4.9.12
676
+	 * @return bool
677
+	 */
678
+	public function txn_status_updated()
679
+	{
680
+		EE_Error::doing_it_wrong(
681
+			__METHOD__,
682
+			esc_html__(
683
+				'This logic has been moved into \EE_Transaction::txn_status_updated(), please use that method instead.',
684
+				'event_espresso'
685
+			),
686
+			'4.9.12'
687
+		);
688
+		return $this->_new_txn_status !== $this->_old_txn_status && $this->_old_txn_status !== null ? true : false;
689
+	}
690
+
691
+
692
+	/**
693
+	 * all_reg_steps_completed
694
+	 * returns:
695
+	 *    true if ALL reg steps have been marked as completed
696
+	 *        or false if any step is not completed
697
+	 *
698
+	 * @deprecated 4.9.12
699
+	 * @param EE_Transaction $transaction
700
+	 * @return boolean
701
+	 */
702
+	public function all_reg_steps_completed(EE_Transaction $transaction)
703
+	{
704
+		EE_Error::doing_it_wrong(
705
+			__METHOD__,
706
+			esc_html__(
707
+				'This logic has been moved into \EE_Transaction::all_reg_steps_completed(), please use that method instead.',
708
+				'event_espresso'
709
+			),
710
+			'4.9.12',
711
+			'5.0.0'
712
+		);
713
+		return $transaction->all_reg_steps_completed();
714
+	}
715
+
716
+
717
+	/**
718
+	 * all_reg_steps_completed_except
719
+	 * returns:
720
+	 *        true if ALL reg steps, except a particular step that you wish to skip over, have been marked as completed
721
+	 *        or false if any other step is not completed
722
+	 *        or false if ALL steps are completed including the exception you are testing !!!
723
+	 *
724
+	 * @deprecated 4.9.12
725
+	 * @param EE_Transaction $transaction
726
+	 * @param string         $exception
727
+	 * @return boolean
728
+	 */
729
+	public function all_reg_steps_completed_except(EE_Transaction $transaction, $exception = '')
730
+	{
731
+		EE_Error::doing_it_wrong(
732
+			__METHOD__,
733
+			esc_html__(
734
+				'This logic has been moved into \EE_Transaction::all_reg_steps_completed_except(), please use that method instead.',
735
+				'event_espresso'
736
+			),
737
+			'4.9.12',
738
+			'5.0.0'
739
+		);
740
+		return $transaction->all_reg_steps_completed_except($exception);
741
+	}
742
+
743
+
744
+	/**
745
+	 * all_reg_steps_completed_except
746
+	 * returns:
747
+	 *        true if ALL reg steps, except the final step, have been marked as completed
748
+	 *        or false if any step is not completed
749
+	 *    or false if ALL steps are completed including the final step !!!
750
+	 *
751
+	 * @deprecated 4.9.12
752
+	 * @param EE_Transaction $transaction
753
+	 * @return boolean
754
+	 */
755
+	public function all_reg_steps_completed_except_final_step(EE_Transaction $transaction)
756
+	{
757
+		EE_Error::doing_it_wrong(
758
+			__METHOD__,
759
+			esc_html__(
760
+				'This logic has been moved into \EE_Transaction::all_reg_steps_completed_except_final_step(), please use that method instead.',
761
+				'event_espresso'
762
+			),
763
+			'4.9.12',
764
+			'5.0.0'
765
+		);
766
+		return $transaction->all_reg_steps_completed_except_final_step();
767
+	}
768
+
769
+
770
+	/**
771
+	 * reg_step_completed
772
+	 * returns:
773
+	 *    true if a specific reg step has been marked as completed
774
+	 *    a Unix timestamp if it has been initialized but not yet completed,
775
+	 *    or false if it has not yet been initialized
776
+	 *
777
+	 * @deprecated 4.9.12
778
+	 * @param EE_Transaction $transaction
779
+	 * @param string         $reg_step_slug
780
+	 * @return boolean | int
781
+	 */
782
+	public function reg_step_completed(EE_Transaction $transaction, $reg_step_slug)
783
+	{
784
+		EE_Error::doing_it_wrong(
785
+			__METHOD__,
786
+			esc_html__(
787
+				'This logic has been moved into \EE_Transaction::reg_step_completed(), please use that method instead.',
788
+				'event_espresso'
789
+			),
790
+			'4.9.12',
791
+			'5.0.0'
792
+		);
793
+		return $transaction->reg_step_completed($reg_step_slug);
794
+	}
795
+
796
+
797
+	/**
798
+	 * completed_final_reg_step
799
+	 * returns:
800
+	 *    true if the finalize_registration reg step has been marked as completed
801
+	 *    a Unix timestamp if it has been initialized but not yet completed,
802
+	 *    or false if it has not yet been initialized
803
+	 *
804
+	 * @deprecated 4.9.12
805
+	 * @param EE_Transaction $transaction
806
+	 * @return boolean | int
807
+	 */
808
+	public function final_reg_step_completed(EE_Transaction $transaction)
809
+	{
810
+		EE_Error::doing_it_wrong(
811
+			__METHOD__,
812
+			esc_html__(
813
+				'This logic has been moved into \EE_Transaction::final_reg_step_completed(), please use that method instead.',
814
+				'event_espresso'
815
+			),
816
+			'4.9.12',
817
+			'5.0.0'
818
+		);
819
+		return $transaction->final_reg_step_completed();
820
+	}
821
+
822
+
823
+	/**
824
+	 * set_reg_step_initiated
825
+	 * given a valid TXN_reg_step, this sets it's value to a unix timestamp
826
+	 *
827
+	 * @param EE_Transaction $transaction
828
+	 * @param string         $reg_step_slug
829
+	 * @return boolean
830
+	 * @throws EE_Error*@throws ReflectionException
831
+	 * @deprecated 4.9.12
832
+	 * @access     public
833
+	 */
834
+	public function set_reg_step_initiated(EE_Transaction $transaction, $reg_step_slug)
835
+	{
836
+		EE_Error::doing_it_wrong(
837
+			__METHOD__,
838
+			esc_html__(
839
+				'This logic has been moved into \EE_Transaction::set_reg_step_initiated(), please use that method instead.',
840
+				'event_espresso'
841
+			),
842
+			'4.9.12',
843
+			'5.0.0'
844
+		);
845
+		return $transaction->set_reg_step_initiated($reg_step_slug);
846
+	}
847
+
848
+
849
+	/**
850
+	 * set_reg_step_completed
851
+	 * given a valid TXN_reg_step, this sets the step as completed
852
+	 *
853
+	 * @param EE_Transaction $transaction
854
+	 * @param string         $reg_step_slug
855
+	 * @return boolean
856
+	 * @throws EE_Error*@throws ReflectionException
857
+	 * @deprecated 4.9.12
858
+	 * @access     public
859
+	 */
860
+	public function set_reg_step_completed(EE_Transaction $transaction, $reg_step_slug)
861
+	{
862
+		EE_Error::doing_it_wrong(
863
+			__METHOD__,
864
+			esc_html__(
865
+				'This logic has been moved into \EE_Transaction::set_reg_step_completed(), please use that method instead.',
866
+				'event_espresso'
867
+			),
868
+			'4.9.12',
869
+			'5.0.0'
870
+		);
871
+		return $transaction->set_reg_step_completed($reg_step_slug);
872
+	}
873
+
874
+
875
+	/**
876
+	 * set_reg_step_completed
877
+	 * given a valid TXN_reg_step slug, this sets the step as NOT completed
878
+	 *
879
+	 * @param EE_Transaction $transaction
880
+	 * @param string         $reg_step_slug
881
+	 * @return boolean
882
+	 * @throws EE_Error*@throws ReflectionException
883
+	 * @deprecated 4.9.12
884
+	 * @access     public
885
+	 */
886
+	public function set_reg_step_not_completed(EE_Transaction $transaction, $reg_step_slug)
887
+	{
888
+		EE_Error::doing_it_wrong(
889
+			__METHOD__,
890
+			esc_html__(
891
+				'This logic has been moved into \EE_Transaction::set_reg_step_not_completed(), please use that method instead.',
892
+				'event_espresso'
893
+			),
894
+			'4.9.12',
895
+			'5.0.0'
896
+		);
897
+		return $transaction->set_reg_step_not_completed($reg_step_slug);
898
+	}
899
+
900
+
901
+	/**
902
+	 * remove_reg_step
903
+	 * given a valid TXN_reg_step slug, this will remove (unset)
904
+	 * the reg step from the TXN reg step array
905
+	 *
906
+	 * @param EE_Transaction $transaction
907
+	 * @param string         $reg_step_slug
908
+	 * @return void
909
+	 *@deprecated 4.9.12
910
+	 * @access     public
911
+	 */
912
+	public function remove_reg_step(EE_Transaction $transaction, $reg_step_slug)
913
+	{
914
+		EE_Error::doing_it_wrong(
915
+			__METHOD__,
916
+			esc_html__(
917
+				'This logic has been moved into \EE_Transaction::remove_reg_step(), please use that method instead.',
918
+				'event_espresso'
919
+			),
920
+			'4.9.12',
921
+			'5.0.0'
922
+		);
923
+		$transaction->remove_reg_step($reg_step_slug);
924
+	}
925
+
926
+
927
+	/**
928
+	 *    toggle_failed_transaction_status
929
+	 * upgrades a TXNs status from failed to abandoned,
930
+	 * meaning that contact information has been captured for at least one registrant
931
+	 *
932
+	 * @param EE_Transaction $transaction
933
+	 * @return    boolean
934
+	 * @throws EE_Error*@throws ReflectionException
935
+	 * @deprecated 4.9.12
936
+	 * @access     public
937
+	 */
938
+	public function toggle_failed_transaction_status(EE_Transaction $transaction)
939
+	{
940
+		EE_Error::doing_it_wrong(
941
+			__METHOD__,
942
+			esc_html__(
943
+				'This logic has been moved into \EE_Transaction::toggle_failed_transaction_status(), please use that method instead.',
944
+				'event_espresso'
945
+			),
946
+			'4.9.12',
947
+			'5.0.0'
948
+		);
949
+		return $transaction->toggle_failed_transaction_status();
950
+	}
951
+
952
+
953
+	/**
954
+	 * toggle_abandoned_transaction_status
955
+	 * upgrades a TXNs status from failed or abandoned to incomplete
956
+	 *
957
+	 * @deprecated 4.9.12
958
+	 * @access     public
959
+	 * @param  EE_Transaction $transaction
960
+	 * @return boolean
961
+	 */
962
+	public function toggle_abandoned_transaction_status(EE_Transaction $transaction)
963
+	{
964
+		EE_Error::doing_it_wrong(
965
+			__METHOD__,
966
+			esc_html__(
967
+				'This logic has been moved into \EE_Transaction::toggle_abandoned_transaction_status(), please use that method instead.',
968
+				'event_espresso'
969
+			),
970
+			'4.9.12',
971
+			'5.0.0'
972
+		);
973
+		return $transaction->toggle_abandoned_transaction_status();
974
+	}
975 975
 }
Please login to merge, or discard this patch.