Completed
Branch release-gh-workflow (107bf7)
by
unknown
06:53 queued 05:10
created
core/db_classes/EE_Currency_Payment_Method.class.php 1 patch
Indentation   +32 added lines, -32 removed lines patch added patch discarded remove patch
@@ -14,40 +14,40 @@
 block discarded – undo
14 14
 class EE_Currency_Payment_Method extends EE_Base_Class
15 15
 {
16 16
 
17
-    /** Currency to Payment Method Link ID @var CPM_ID */
18
-    protected $_CPM_ID = null;
19
-    /** Currency Code @var CUR_code */
20
-    protected $_CUR_code = null;
21
-    /** Payment Method ID @var PMD_ID */
22
-    protected $_PMD_ID = null;
23
-    protected $_Payment_Method;
24
-    protected $_Currency;
17
+	/** Currency to Payment Method Link ID @var CPM_ID */
18
+	protected $_CPM_ID = null;
19
+	/** Currency Code @var CUR_code */
20
+	protected $_CUR_code = null;
21
+	/** Payment Method ID @var PMD_ID */
22
+	protected $_PMD_ID = null;
23
+	protected $_Payment_Method;
24
+	protected $_Currency;
25 25
 
26 26
 
27
-    /**
28
-     *
29
-     * @param array  $props_n_values          incoming values
30
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
31
-     *                                        used.)
32
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
33
-     *                                        date_format and the second value is the time format
34
-     * @return EE_Attendee
35
-     */
36
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
37
-    {
38
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
39
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
40
-    }
27
+	/**
28
+	 *
29
+	 * @param array  $props_n_values          incoming values
30
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
31
+	 *                                        used.)
32
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
33
+	 *                                        date_format and the second value is the time format
34
+	 * @return EE_Attendee
35
+	 */
36
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
37
+	{
38
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
39
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
40
+	}
41 41
 
42 42
 
43
-    /**
44
-     * @param array  $props_n_values  incoming values from the database
45
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
46
-     *                                the website will be used.
47
-     * @return EE_Attendee
48
-     */
49
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
50
-    {
51
-        return new self($props_n_values, true, $timezone);
52
-    }
43
+	/**
44
+	 * @param array  $props_n_values  incoming values from the database
45
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
46
+	 *                                the website will be used.
47
+	 * @return EE_Attendee
48
+	 */
49
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
50
+	{
51
+		return new self($props_n_values, true, $timezone);
52
+	}
53 53
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Transaction.class.php 2 patches
Spacing   +22 added lines, -22 removed lines patch added patch discarded remove patch
@@ -42,7 +42,7 @@  discard block
 block discarded – undo
42 42
         $txn = $has_object
43 43
             ? $has_object
44 44
             : new self($props_n_values, false, $timezone, $date_formats);
45
-        if (! $has_object) {
45
+        if ( ! $has_object) {
46 46
             $txn->set_old_txn_status($txn->status_ID());
47 47
         }
48 48
         return $txn;
@@ -74,7 +74,7 @@  discard block
 block discarded – undo
74 74
     public function lock()
75 75
     {
76 76
         // attempt to set lock, but if that fails...
77
-        if (! $this->add_extra_meta('lock', time(), true)) {
77
+        if ( ! $this->add_extra_meta('lock', time(), true)) {
78 78
             // then attempt to remove the lock in case it is expired
79 79
             if ($this->_remove_expired_lock()) {
80 80
                 // if removal was successful, then try setting lock again
@@ -122,7 +122,7 @@  discard block
 block discarded – undo
122 122
     public function is_locked()
123 123
     {
124 124
         // if TXN is not locked, then return false immediately
125
-        if (! $this->_get_lock()) {
125
+        if ( ! $this->_get_lock()) {
126 126
             return false;
127 127
         }
128 128
         // if not, then let's try and remove the lock in case it's expired...
@@ -527,7 +527,7 @@  discard block
 block discarded – undo
527 527
                 $icon = $show_icons ? '<span class="dashicons dashicons-plus ee-icon-size-16 orange-text"></span>' : '';
528 528
                 break;
529 529
         }
530
-        return $icon . $status[ $this->status_ID() ];
530
+        return $icon.$status[$this->status_ID()];
531 531
     }
532 532
 
533 533
 
@@ -631,7 +631,7 @@  discard block
 block discarded – undo
631 631
     public function invoice_url($type = 'html')
632 632
     {
633 633
         $REG = $this->primary_registration();
634
-        if (! $REG instanceof EE_Registration) {
634
+        if ( ! $REG instanceof EE_Registration) {
635 635
             return '';
636 636
         }
637 637
         return $REG->invoice_url($type);
@@ -673,7 +673,7 @@  discard block
 block discarded – undo
673 673
     public function receipt_url($type = 'html')
674 674
     {
675 675
         $REG = $this->primary_registration();
676
-        if (! $REG instanceof EE_Registration) {
676
+        if ( ! $REG instanceof EE_Registration) {
677 677
             return '';
678 678
         }
679 679
         return $REG->receipt_url($type);
@@ -818,7 +818,7 @@  discard block
 block discarded – undo
818 818
     public function total_line_item($create_if_not_found = true)
819 819
     {
820 820
         $item = $this->get_first_related('Line_Item', array(array('LIN_type' => EEM_Line_Item::type_total)));
821
-        if (! $item && $create_if_not_found) {
821
+        if ( ! $item && $create_if_not_found) {
822 822
             $item = EEH_Line_Item::create_total_line_item($this);
823 823
         }
824 824
         return $item;
@@ -863,7 +863,7 @@  discard block
 block discarded – undo
863 863
     public function billing_info()
864 864
     {
865 865
         $payment_method = $this->payment_method();
866
-        if (! $payment_method) {
866
+        if ( ! $payment_method) {
867 867
             EE_Error::add_error(
868 868
                 __(
869 869
                     'Could not find billing info for transaction because no gateway has been used for it yet',
@@ -876,7 +876,7 @@  discard block
 block discarded – undo
876 876
             return null;
877 877
         }
878 878
         $primary_reg = $this->primary_registration();
879
-        if (! $primary_reg) {
879
+        if ( ! $primary_reg) {
880 880
             EE_Error::add_error(
881 881
                 __(
882 882
                     'Cannot get billing info for gateway %s on transaction because no primary registration exists',
@@ -889,7 +889,7 @@  discard block
 block discarded – undo
889 889
             return null;
890 890
         }
891 891
         $attendee = $primary_reg->attendee();
892
-        if (! $attendee) {
892
+        if ( ! $attendee) {
893 893
             EE_Error::add_error(
894 894
                 __(
895 895
                     'Cannot get billing info for gateway %s on transaction because the primary registration has no attendee exists',
@@ -1025,7 +1025,7 @@  discard block
 block discarded – undo
1025 1025
     public function update_based_on_payments()
1026 1026
     {
1027 1027
         EE_Error::doing_it_wrong(
1028
-            __CLASS__ . '::' . __FUNCTION__,
1028
+            __CLASS__.'::'.__FUNCTION__,
1029 1029
             sprintf(
1030 1030
                 __('This method is deprecated. Please use "%s" instead', 'event_espresso'),
1031 1031
                 'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'
@@ -1085,13 +1085,13 @@  discard block
 block discarded – undo
1085 1085
     private function _reg_steps_completed($reg_step_slug = '', $check_all = true)
1086 1086
     {
1087 1087
         $reg_steps = $this->reg_steps();
1088
-        if (! is_array($reg_steps) || empty($reg_steps)) {
1088
+        if ( ! is_array($reg_steps) || empty($reg_steps)) {
1089 1089
             return false;
1090 1090
         }
1091 1091
         // loop thru reg steps array)
1092 1092
         foreach ($reg_steps as $slug => $reg_step_completed) {
1093 1093
             // if NOT checking ALL steps (only checking one step)
1094
-            if (! $check_all) {
1094
+            if ( ! $check_all) {
1095 1095
                 // and this is the one
1096 1096
                 if ($slug === $reg_step_slug) {
1097 1097
                     return $reg_step_completed;
@@ -1258,30 +1258,30 @@  discard block
 block discarded – undo
1258 1258
         // get reg steps array
1259 1259
         $txn_reg_steps = $this->reg_steps();
1260 1260
         // if reg step does NOT exist
1261
-        if (! isset($txn_reg_steps[ $reg_step_slug ])) {
1261
+        if ( ! isset($txn_reg_steps[$reg_step_slug])) {
1262 1262
             return false;
1263 1263
         }
1264 1264
         // if  we're trying to complete a step that is already completed
1265
-        if ($txn_reg_steps[ $reg_step_slug ] === true) {
1265
+        if ($txn_reg_steps[$reg_step_slug] === true) {
1266 1266
             return true;
1267 1267
         }
1268 1268
         // if  we're trying to complete a step that hasn't even started
1269
-        if ($status === true && $txn_reg_steps[ $reg_step_slug ] === false) {
1269
+        if ($status === true && $txn_reg_steps[$reg_step_slug] === false) {
1270 1270
             return false;
1271 1271
         }
1272 1272
         // if current status value matches the incoming value (no change)
1273 1273
         // type casting as int means values should collapse to either 0, 1, or a timestamp like 1234567890
1274
-        if ((int) $txn_reg_steps[ $reg_step_slug ] === (int) $status) {
1274
+        if ((int) $txn_reg_steps[$reg_step_slug] === (int) $status) {
1275 1275
             // this will happen in cases where multiple AJAX requests occur during the same step
1276 1276
             return true;
1277 1277
         }
1278 1278
         // if we're trying to set a start time, but it has already been set...
1279
-        if (is_numeric($status) && is_numeric($txn_reg_steps[ $reg_step_slug ])) {
1279
+        if (is_numeric($status) && is_numeric($txn_reg_steps[$reg_step_slug])) {
1280 1280
             // skip the update below, but don't return FALSE so that errors won't be displayed
1281 1281
             return true;
1282 1282
         }
1283 1283
         // update completed status
1284
-        $txn_reg_steps[ $reg_step_slug ] = $status;
1284
+        $txn_reg_steps[$reg_step_slug] = $status;
1285 1285
         $this->set_reg_steps($txn_reg_steps);
1286 1286
         $this->save();
1287 1287
         return true;
@@ -1301,7 +1301,7 @@  discard block
 block discarded – undo
1301 1301
     {
1302 1302
         // get reg steps array
1303 1303
         $txn_reg_steps = $this->reg_steps();
1304
-        unset($txn_reg_steps[ $reg_step_slug ]);
1304
+        unset($txn_reg_steps[$reg_step_slug]);
1305 1305
         $this->set_reg_steps($txn_reg_steps);
1306 1306
     }
1307 1307
 
@@ -1374,12 +1374,12 @@  discard block
 block discarded – undo
1374 1374
             return;
1375 1375
         }
1376 1376
         $payments = $this->get_many_related('Payment');
1377
-        if (! empty($payments)) {
1377
+        if ( ! empty($payments)) {
1378 1378
             foreach ($payments as $payment) {
1379 1379
                 if ($payment instanceof EE_Payment) {
1380 1380
                     // kk this TXN should NOT be abandoned
1381 1381
                     $this->update_status_based_on_total_paid();
1382
-                    if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1382
+                    if ( ! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1383 1383
                         EE_Error::add_attention(
1384 1384
                             sprintf(
1385 1385
                                 esc_html__(
Please login to merge, or discard this patch.
Indentation   +1698 added lines, -1698 removed lines patch added patch discarded remove patch
@@ -13,1702 +13,1702 @@
 block discarded – undo
13 13
 class EE_Transaction extends EE_Base_Class implements EEI_Transaction
14 14
 {
15 15
 
16
-    /**
17
-     * The length of time in seconds that a lock is applied before being considered expired.
18
-     * It is not long because a transaction should only be locked for the duration of the request that locked it
19
-     */
20
-    const LOCK_EXPIRATION = 2;
21
-
22
-    /**
23
-     * txn status upon initial construction.
24
-     *
25
-     * @var string
26
-     */
27
-    protected $_old_txn_status;
28
-
29
-
30
-    /**
31
-     * @param array  $props_n_values          incoming values
32
-     * @param string $timezone                incoming timezone
33
-     *                                        (if not set the timezone set for the website will be used.)
34
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
35
-     *                                        date_format and the second value is the time format
36
-     * @return EE_Transaction
37
-     * @throws EE_Error
38
-     * @throws InvalidArgumentException
39
-     * @throws InvalidDataTypeException
40
-     * @throws InvalidInterfaceException
41
-     * @throws ReflectionException
42
-     */
43
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
44
-    {
45
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
46
-        $txn = $has_object
47
-            ? $has_object
48
-            : new self($props_n_values, false, $timezone, $date_formats);
49
-        if (! $has_object) {
50
-            $txn->set_old_txn_status($txn->status_ID());
51
-        }
52
-        return $txn;
53
-    }
54
-
55
-
56
-    /**
57
-     * @param array  $props_n_values  incoming values from the database
58
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
59
-     *                                the website will be used.
60
-     * @return EE_Transaction
61
-     * @throws EE_Error
62
-     * @throws InvalidArgumentException
63
-     * @throws InvalidDataTypeException
64
-     * @throws InvalidInterfaceException
65
-     * @throws ReflectionException
66
-     */
67
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
68
-    {
69
-        $txn = new self($props_n_values, true, $timezone);
70
-        $txn->set_old_txn_status($txn->status_ID());
71
-        return $txn;
72
-    }
73
-
74
-
75
-    /**
76
-     * Sets a meta field indicating that this TXN is locked and should not be updated in the db.
77
-     * If a lock has already been set, then we will attempt to remove it in case it has expired.
78
-     * If that also fails, then an exception is thrown.
79
-     *
80
-     * @throws EE_Error
81
-     * @throws InvalidArgumentException
82
-     * @throws InvalidDataTypeException
83
-     * @throws InvalidInterfaceException
84
-     * @throws ReflectionException
85
-     */
86
-    public function lock()
87
-    {
88
-        // attempt to set lock, but if that fails...
89
-        if (! $this->add_extra_meta('lock', time(), true)) {
90
-            // then attempt to remove the lock in case it is expired
91
-            if ($this->_remove_expired_lock()) {
92
-                // if removal was successful, then try setting lock again
93
-                $this->lock();
94
-            } else {
95
-                // but if the lock can not be removed, then throw an exception
96
-                throw new EE_Error(
97
-                    sprintf(
98
-                        __(
99
-                            'Could not lock Transaction %1$d because it is already locked, meaning another part of the system is currently editing it. It should already be unlocked by the time you read this, so please refresh the page and try again.',
100
-                            'event_espresso'
101
-                        ),
102
-                        $this->ID()
103
-                    )
104
-                );
105
-            }
106
-        }
107
-    }
108
-
109
-
110
-    /**
111
-     * removes transaction lock applied in EE_Transaction::lock()
112
-     *
113
-     * @return int
114
-     * @throws EE_Error
115
-     * @throws InvalidArgumentException
116
-     * @throws InvalidDataTypeException
117
-     * @throws InvalidInterfaceException
118
-     * @throws ReflectionException
119
-     */
120
-    public function unlock()
121
-    {
122
-        return $this->delete_extra_meta('lock');
123
-    }
124
-
125
-
126
-    /**
127
-     * Decides whether or not now is the right time to update the transaction.
128
-     * This is useful because we don't always know if it is safe to update the transaction
129
-     * and its related data. why?
130
-     * because it's possible that the transaction is being used in another
131
-     * request and could overwrite anything we save.
132
-     * So we want to only update the txn once we know that won't happen.
133
-     * We also check that the lock isn't expired, and remove it if it is
134
-     *
135
-     * @return boolean
136
-     * @throws EE_Error
137
-     * @throws InvalidArgumentException
138
-     * @throws InvalidDataTypeException
139
-     * @throws InvalidInterfaceException
140
-     * @throws ReflectionException
141
-     */
142
-    public function is_locked()
143
-    {
144
-        // if TXN is not locked, then return false immediately
145
-        if (! $this->_get_lock()) {
146
-            return false;
147
-        }
148
-        // if not, then let's try and remove the lock in case it's expired...
149
-        // _remove_expired_lock() returns 0 when lock is valid (ie: removed = false)
150
-        // and a positive number if the lock was removed (ie: number of locks deleted),
151
-        // so we need to return the opposite
152
-        return ! $this->_remove_expired_lock() ? true : false;
153
-    }
154
-
155
-
156
-    /**
157
-     * Gets the meta field indicating that this TXN is locked
158
-     *
159
-     * @return int
160
-     * @throws EE_Error
161
-     * @throws InvalidArgumentException
162
-     * @throws InvalidDataTypeException
163
-     * @throws InvalidInterfaceException
164
-     * @throws ReflectionException
165
-     */
166
-    protected function _get_lock()
167
-    {
168
-        return (int) $this->get_extra_meta('lock', true, 0);
169
-    }
170
-
171
-
172
-    /**
173
-     * If the lock on this transaction is expired, then we want to remove it so that the transaction can be updated
174
-     *
175
-     * @return int
176
-     * @throws EE_Error
177
-     * @throws InvalidArgumentException
178
-     * @throws InvalidDataTypeException
179
-     * @throws InvalidInterfaceException
180
-     * @throws ReflectionException
181
-     */
182
-    protected function _remove_expired_lock()
183
-    {
184
-        $locked = $this->_get_lock();
185
-        if ($locked && time() - EE_Transaction::LOCK_EXPIRATION > $locked) {
186
-            return $this->unlock();
187
-        }
188
-        return 0;
189
-    }
190
-
191
-
192
-    /**
193
-     * Set transaction total
194
-     *
195
-     * @param float $total total value of transaction
196
-     * @throws EE_Error
197
-     * @throws InvalidArgumentException
198
-     * @throws InvalidDataTypeException
199
-     * @throws InvalidInterfaceException
200
-     * @throws ReflectionException
201
-     */
202
-    public function set_total($total = 0.00)
203
-    {
204
-        $this->set('TXN_total', (float) $total);
205
-    }
206
-
207
-
208
-    /**
209
-     * Set Total Amount Paid to Date
210
-     *
211
-     * @param float $total_paid total amount paid to date (sum of all payments)
212
-     * @throws EE_Error
213
-     * @throws InvalidArgumentException
214
-     * @throws InvalidDataTypeException
215
-     * @throws InvalidInterfaceException
216
-     * @throws ReflectionException
217
-     */
218
-    public function set_paid($total_paid = 0.00)
219
-    {
220
-        $this->set('TXN_paid', (float) $total_paid);
221
-    }
222
-
223
-
224
-    /**
225
-     * Set transaction status
226
-     *
227
-     * @param string $status        whether the transaction is open, declined, accepted,
228
-     *                              or any number of custom values that can be set
229
-     * @throws EE_Error
230
-     * @throws InvalidArgumentException
231
-     * @throws InvalidDataTypeException
232
-     * @throws InvalidInterfaceException
233
-     * @throws ReflectionException
234
-     */
235
-    public function set_status($status = '')
236
-    {
237
-        $this->set('STS_ID', $status);
238
-    }
239
-
240
-
241
-    /**
242
-     * Set hash salt
243
-     *
244
-     * @param string $hash_salt required for some payment gateways
245
-     * @throws EE_Error
246
-     * @throws InvalidArgumentException
247
-     * @throws InvalidDataTypeException
248
-     * @throws InvalidInterfaceException
249
-     * @throws ReflectionException
250
-     */
251
-    public function set_hash_salt($hash_salt = '')
252
-    {
253
-        $this->set('TXN_hash_salt', $hash_salt);
254
-    }
255
-
256
-
257
-    /**
258
-     * Sets TXN_reg_steps array
259
-     *
260
-     * @param array $txn_reg_steps
261
-     * @throws EE_Error
262
-     * @throws InvalidArgumentException
263
-     * @throws InvalidDataTypeException
264
-     * @throws InvalidInterfaceException
265
-     * @throws ReflectionException
266
-     */
267
-    public function set_reg_steps(array $txn_reg_steps)
268
-    {
269
-        $this->set('TXN_reg_steps', $txn_reg_steps);
270
-    }
271
-
272
-
273
-    /**
274
-     * Gets TXN_reg_steps
275
-     *
276
-     * @return array
277
-     * @throws EE_Error
278
-     * @throws InvalidArgumentException
279
-     * @throws InvalidDataTypeException
280
-     * @throws InvalidInterfaceException
281
-     * @throws ReflectionException
282
-     */
283
-    public function reg_steps()
284
-    {
285
-        $TXN_reg_steps = $this->get('TXN_reg_steps');
286
-        return is_array($TXN_reg_steps) ? (array) $TXN_reg_steps : array();
287
-    }
288
-
289
-
290
-    /**
291
-     * @return string of transaction's total cost, with currency symbol and decimal
292
-     * @throws EE_Error
293
-     * @throws InvalidArgumentException
294
-     * @throws InvalidDataTypeException
295
-     * @throws InvalidInterfaceException
296
-     * @throws ReflectionException
297
-     */
298
-    public function pretty_total()
299
-    {
300
-        return $this->get_pretty('TXN_total');
301
-    }
302
-
303
-
304
-    /**
305
-     * Gets the amount paid in a pretty string (formatted and with currency symbol)
306
-     *
307
-     * @return string
308
-     * @throws EE_Error
309
-     * @throws InvalidArgumentException
310
-     * @throws InvalidDataTypeException
311
-     * @throws InvalidInterfaceException
312
-     * @throws ReflectionException
313
-     */
314
-    public function pretty_paid()
315
-    {
316
-        return $this->get_pretty('TXN_paid');
317
-    }
318
-
319
-
320
-    /**
321
-     * calculate the amount remaining for this transaction and return;
322
-     *
323
-     * @return float amount remaining
324
-     * @throws EE_Error
325
-     * @throws InvalidArgumentException
326
-     * @throws InvalidDataTypeException
327
-     * @throws InvalidInterfaceException
328
-     * @throws ReflectionException
329
-     */
330
-    public function remaining()
331
-    {
332
-        return $this->total() - $this->paid();
333
-    }
334
-
335
-
336
-    /**
337
-     * get Transaction Total
338
-     *
339
-     * @return float
340
-     * @throws EE_Error
341
-     * @throws InvalidArgumentException
342
-     * @throws InvalidDataTypeException
343
-     * @throws InvalidInterfaceException
344
-     * @throws ReflectionException
345
-     */
346
-    public function total()
347
-    {
348
-        return (float) $this->get('TXN_total');
349
-    }
350
-
351
-
352
-    /**
353
-     * get Total Amount Paid to Date
354
-     *
355
-     * @return float
356
-     * @throws EE_Error
357
-     * @throws InvalidArgumentException
358
-     * @throws InvalidDataTypeException
359
-     * @throws InvalidInterfaceException
360
-     * @throws ReflectionException
361
-     */
362
-    public function paid()
363
-    {
364
-        return (float) $this->get('TXN_paid');
365
-    }
366
-
367
-
368
-    /**
369
-     * @return mixed|null
370
-     * @throws EE_Error
371
-     * @throws InvalidArgumentException
372
-     * @throws InvalidDataTypeException
373
-     * @throws InvalidInterfaceException
374
-     * @throws ReflectionException
375
-     */
376
-    public function get_cart_session()
377
-    {
378
-        $session_data = (array) $this->get('TXN_session_data');
379
-        return isset($session_data['cart']) && $session_data['cart'] instanceof EE_Cart
380
-            ? $session_data['cart']
381
-            : null;
382
-    }
383
-
384
-
385
-    /**
386
-     * get Transaction session data
387
-     *
388
-     * @return array|mixed
389
-     * @throws EE_Error
390
-     * @throws InvalidArgumentException
391
-     * @throws InvalidDataTypeException
392
-     * @throws InvalidInterfaceException
393
-     * @throws ReflectionException
394
-     */
395
-    public function session_data()
396
-    {
397
-        $session_data = $this->get('TXN_session_data');
398
-        if (empty($session_data)) {
399
-            $session_data = array(
400
-                'id'            => null,
401
-                'user_id'       => null,
402
-                'ip_address'    => null,
403
-                'user_agent'    => null,
404
-                'init_access'   => null,
405
-                'last_access'   => null,
406
-                'pages_visited' => array(),
407
-            );
408
-        }
409
-        return $session_data;
410
-    }
411
-
412
-
413
-    /**
414
-     * Set session data within the TXN object
415
-     *
416
-     * @param EE_Session|array $session_data
417
-     * @throws EE_Error
418
-     * @throws InvalidArgumentException
419
-     * @throws InvalidDataTypeException
420
-     * @throws InvalidInterfaceException
421
-     * @throws ReflectionException
422
-     */
423
-    public function set_txn_session_data($session_data)
424
-    {
425
-        if ($session_data instanceof EE_Session) {
426
-            $this->set('TXN_session_data', $session_data->get_session_data(null, true));
427
-        } else {
428
-            $this->set('TXN_session_data', $session_data);
429
-        }
430
-    }
431
-
432
-
433
-    /**
434
-     * get Transaction hash salt
435
-     *
436
-     * @return mixed
437
-     * @throws EE_Error
438
-     * @throws InvalidArgumentException
439
-     * @throws InvalidDataTypeException
440
-     * @throws InvalidInterfaceException
441
-     * @throws ReflectionException
442
-     */
443
-    public function hash_salt_()
444
-    {
445
-        return $this->get('TXN_hash_salt');
446
-    }
447
-
448
-
449
-    /**
450
-     * Returns the transaction datetime as either:
451
-     *            - unix timestamp format ($format = false, $gmt = true)
452
-     *            - formatted date string including the UTC (timezone) offset ($format = true ($gmt
453
-     *              has no affect with this option)), this also may include a timezone abbreviation if the
454
-     *              set timezone in this class differs from what the timezone is on the blog.
455
-     *            - formatted date string including the UTC (timezone) offset (default).
456
-     *
457
-     * @param boolean $format   - whether to return a unix timestamp (default) or formatted date string
458
-     * @param boolean $gmt      - whether to return a unix timestamp with UTC offset applied (default)
459
-     *                          or no UTC offset applied
460
-     * @return string | int
461
-     * @throws EE_Error
462
-     * @throws InvalidArgumentException
463
-     * @throws InvalidDataTypeException
464
-     * @throws InvalidInterfaceException
465
-     * @throws ReflectionException
466
-     */
467
-    public function datetime($format = false, $gmt = false)
468
-    {
469
-        if ($format) {
470
-            return $this->get_pretty('TXN_timestamp');
471
-        }
472
-        if ($gmt) {
473
-            return $this->get_raw('TXN_timestamp');
474
-        }
475
-        return $this->get('TXN_timestamp');
476
-    }
477
-
478
-
479
-    /**
480
-     * Gets registrations on this transaction
481
-     *
482
-     * @param array   $query_params array of query parameters
483
-     * @param boolean $get_cached   TRUE to retrieve cached registrations or FALSE to pull from the db
484
-     * @return EE_Base_Class[]|EE_Registration[]
485
-     * @throws EE_Error
486
-     * @throws InvalidArgumentException
487
-     * @throws InvalidDataTypeException
488
-     * @throws InvalidInterfaceException
489
-     * @throws ReflectionException
490
-     */
491
-    public function registrations($query_params = array(), $get_cached = false)
492
-    {
493
-        $query_params = (empty($query_params) || ! is_array($query_params))
494
-            ? array(
495
-                'order_by' => array(
496
-                    'Event.EVT_name'     => 'ASC',
497
-                    'Attendee.ATT_lname' => 'ASC',
498
-                    'Attendee.ATT_fname' => 'ASC',
499
-                ),
500
-            )
501
-            : $query_params;
502
-        $query_params = $get_cached ? array() : $query_params;
503
-        return $this->get_many_related('Registration', $query_params);
504
-    }
505
-
506
-
507
-    /**
508
-     * Gets all the attendees for this transaction (handy for use with EE_Attendee's get_registrations_for_event
509
-     * function for getting attendees and how many registrations they each have for an event)
510
-     *
511
-     * @return mixed EE_Attendee[] by default, int if $output is set to 'COUNT'
512
-     * @throws EE_Error
513
-     * @throws InvalidArgumentException
514
-     * @throws InvalidDataTypeException
515
-     * @throws InvalidInterfaceException
516
-     * @throws ReflectionException
517
-     */
518
-    public function attendees()
519
-    {
520
-        return $this->get_many_related('Attendee', array(array('Registration.Transaction.TXN_ID' => $this->ID())));
521
-    }
522
-
523
-
524
-    /**
525
-     * Gets payments for this transaction. Unlike other such functions, order by 'DESC' by default
526
-     *
527
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
528
-     * @return EE_Base_Class[]|EE_Payment[]
529
-     * @throws EE_Error
530
-     * @throws InvalidArgumentException
531
-     * @throws InvalidDataTypeException
532
-     * @throws InvalidInterfaceException
533
-     * @throws ReflectionException
534
-     */
535
-    public function payments($query_params = array())
536
-    {
537
-        return $this->get_many_related('Payment', $query_params);
538
-    }
539
-
540
-
541
-    /**
542
-     * gets only approved payments for this transaction
543
-     *
544
-     * @return EE_Base_Class[]|EE_Payment[]
545
-     * @throws EE_Error
546
-     * @throws InvalidArgumentException
547
-     * @throws ReflectionException
548
-     * @throws InvalidDataTypeException
549
-     * @throws InvalidInterfaceException
550
-     */
551
-    public function approved_payments()
552
-    {
553
-        EE_Registry::instance()->load_model('Payment');
554
-        return $this->get_many_related(
555
-            'Payment',
556
-            array(
557
-                array('STS_ID' => EEM_Payment::status_id_approved),
558
-                'order_by' => array('PAY_timestamp' => 'DESC'),
559
-            )
560
-        );
561
-    }
562
-
563
-
564
-    /**
565
-     * Gets all payments which have not been approved
566
-     *
567
-     * @return EE_Base_Class[]|EEI_Payment[]
568
-     * @throws EE_Error if a model is misconfigured somehow
569
-     * @throws InvalidArgumentException
570
-     * @throws InvalidDataTypeException
571
-     * @throws InvalidInterfaceException
572
-     * @throws ReflectionException
573
-     */
574
-    public function pending_payments()
575
-    {
576
-        return $this->get_many_related(
577
-            'Payment',
578
-            array(
579
-                array(
580
-                    'STS_ID' => EEM_Payment::status_id_pending,
581
-                ),
582
-                'order_by' => array(
583
-                    'PAY_timestamp' => 'DESC',
584
-                ),
585
-            )
586
-        );
587
-    }
588
-
589
-
590
-    /**
591
-     * echoes $this->pretty_status()
592
-     *
593
-     * @param bool $show_icons
594
-     * @throws EE_Error
595
-     * @throws InvalidArgumentException
596
-     * @throws InvalidDataTypeException
597
-     * @throws InvalidInterfaceException
598
-     * @throws ReflectionException
599
-     */
600
-    public function e_pretty_status($show_icons = false)
601
-    {
602
-        echo $this->pretty_status($show_icons);
603
-    }
604
-
605
-
606
-    /**
607
-     * returns a pretty version of the status, good for displaying to users
608
-     *
609
-     * @param bool $show_icons
610
-     * @return string
611
-     * @throws EE_Error
612
-     * @throws InvalidArgumentException
613
-     * @throws InvalidDataTypeException
614
-     * @throws InvalidInterfaceException
615
-     * @throws ReflectionException
616
-     */
617
-    public function pretty_status($show_icons = false)
618
-    {
619
-        $status = EEM_Status::instance()->localized_status(
620
-            array($this->status_ID() => __('unknown', 'event_espresso')),
621
-            false,
622
-            'sentence'
623
-        );
624
-        $icon = '';
625
-        switch ($this->status_ID()) {
626
-            case EEM_Transaction::complete_status_code:
627
-                $icon = $show_icons ? '<span class="dashicons dashicons-yes ee-icon-size-24 green-text"></span>' : '';
628
-                break;
629
-            case EEM_Transaction::incomplete_status_code:
630
-                $icon = $show_icons ? '<span class="dashicons dashicons-marker ee-icon-size-16 lt-blue-text"></span>'
631
-                    : '';
632
-                break;
633
-            case EEM_Transaction::abandoned_status_code:
634
-                $icon = $show_icons ? '<span class="dashicons dashicons-marker ee-icon-size-16 red-text"></span>' : '';
635
-                break;
636
-            case EEM_Transaction::failed_status_code:
637
-                $icon = $show_icons ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>' : '';
638
-                break;
639
-            case EEM_Transaction::overpaid_status_code:
640
-                $icon = $show_icons ? '<span class="dashicons dashicons-plus ee-icon-size-16 orange-text"></span>' : '';
641
-                break;
642
-        }
643
-        return $icon . $status[ $this->status_ID() ];
644
-    }
645
-
646
-
647
-    /**
648
-     * get Transaction Status
649
-     *
650
-     * @return mixed
651
-     * @throws EE_Error
652
-     * @throws InvalidArgumentException
653
-     * @throws InvalidDataTypeException
654
-     * @throws InvalidInterfaceException
655
-     * @throws ReflectionException
656
-     */
657
-    public function status_ID()
658
-    {
659
-        return $this->get('STS_ID');
660
-    }
661
-
662
-
663
-    /**
664
-     * Returns TRUE or FALSE for whether or not this transaction cost any money
665
-     *
666
-     * @return boolean
667
-     * @throws EE_Error
668
-     * @throws InvalidArgumentException
669
-     * @throws InvalidDataTypeException
670
-     * @throws InvalidInterfaceException
671
-     * @throws ReflectionException
672
-     */
673
-    public function is_free()
674
-    {
675
-        return EEH_Money::compare_floats($this->get('TXN_total'), 0, '==');
676
-    }
677
-
678
-
679
-    /**
680
-     * Returns whether this transaction is complete
681
-     * Useful in templates and other logic for deciding if we should ask for another payment...
682
-     *
683
-     * @return boolean
684
-     * @throws EE_Error
685
-     * @throws InvalidArgumentException
686
-     * @throws InvalidDataTypeException
687
-     * @throws InvalidInterfaceException
688
-     * @throws ReflectionException
689
-     */
690
-    public function is_completed()
691
-    {
692
-        return $this->status_ID() === EEM_Transaction::complete_status_code;
693
-    }
694
-
695
-
696
-    /**
697
-     * Returns whether this transaction is incomplete
698
-     * Useful in templates and other logic for deciding if we should ask for another payment...
699
-     *
700
-     * @return boolean
701
-     * @throws EE_Error
702
-     * @throws InvalidArgumentException
703
-     * @throws InvalidDataTypeException
704
-     * @throws InvalidInterfaceException
705
-     * @throws ReflectionException
706
-     */
707
-    public function is_incomplete()
708
-    {
709
-        return $this->status_ID() === EEM_Transaction::incomplete_status_code;
710
-    }
711
-
712
-
713
-    /**
714
-     * Returns whether this transaction is overpaid
715
-     * Useful in templates and other logic for deciding if monies need to be refunded
716
-     *
717
-     * @return boolean
718
-     * @throws EE_Error
719
-     * @throws InvalidArgumentException
720
-     * @throws InvalidDataTypeException
721
-     * @throws InvalidInterfaceException
722
-     * @throws ReflectionException
723
-     */
724
-    public function is_overpaid()
725
-    {
726
-        return $this->status_ID() === EEM_Transaction::overpaid_status_code;
727
-    }
728
-
729
-
730
-    /**
731
-     * Returns whether this transaction was abandoned
732
-     * meaning that the transaction/registration process was somehow interrupted and never completed
733
-     * but that contact information exists for at least one registrant
734
-     *
735
-     * @return boolean
736
-     * @throws EE_Error
737
-     * @throws InvalidArgumentException
738
-     * @throws InvalidDataTypeException
739
-     * @throws InvalidInterfaceException
740
-     * @throws ReflectionException
741
-     */
742
-    public function is_abandoned()
743
-    {
744
-        return $this->status_ID() === EEM_Transaction::abandoned_status_code;
745
-    }
746
-
747
-
748
-    /**
749
-     * Returns whether this transaction failed
750
-     * meaning that the transaction/registration process was somehow interrupted and never completed
751
-     * and that NO contact information exists for any registrants
752
-     *
753
-     * @return boolean
754
-     * @throws EE_Error
755
-     * @throws InvalidArgumentException
756
-     * @throws InvalidDataTypeException
757
-     * @throws InvalidInterfaceException
758
-     * @throws ReflectionException
759
-     */
760
-    public function failed()
761
-    {
762
-        return $this->status_ID() === EEM_Transaction::failed_status_code;
763
-    }
764
-
765
-
766
-    /**
767
-     * This returns the url for the invoice of this transaction
768
-     *
769
-     * @param string $type 'html' or 'pdf' (default is pdf)
770
-     * @return string
771
-     * @throws EE_Error
772
-     * @throws InvalidArgumentException
773
-     * @throws InvalidDataTypeException
774
-     * @throws InvalidInterfaceException
775
-     * @throws ReflectionException
776
-     */
777
-    public function invoice_url($type = 'html')
778
-    {
779
-        $REG = $this->primary_registration();
780
-        if (! $REG instanceof EE_Registration) {
781
-            return '';
782
-        }
783
-        return $REG->invoice_url($type);
784
-    }
785
-
786
-
787
-    /**
788
-     * Gets the primary registration only
789
-     *
790
-     * @return EE_Base_Class|EE_Registration
791
-     * @throws EE_Error
792
-     * @throws InvalidArgumentException
793
-     * @throws InvalidDataTypeException
794
-     * @throws InvalidInterfaceException
795
-     * @throws ReflectionException
796
-     */
797
-    public function primary_registration()
798
-    {
799
-        $registrations = (array) $this->get_many_related(
800
-            'Registration',
801
-            array(array('REG_count' => EEM_Registration::PRIMARY_REGISTRANT_COUNT))
802
-        );
803
-        foreach ($registrations as $registration) {
804
-            // valid registration that is NOT cancelled or declined ?
805
-            if ($registration instanceof EE_Registration
806
-                && ! in_array($registration->status_ID(), EEM_Registration::closed_reg_statuses(), true)
807
-            ) {
808
-                return $registration;
809
-            }
810
-        }
811
-        // nothing valid found, so just return first thing from array of results
812
-        return reset($registrations);
813
-    }
814
-
815
-
816
-    /**
817
-     * Gets the URL for viewing the receipt
818
-     *
819
-     * @param string $type 'pdf' or 'html' (default is 'html')
820
-     * @return string
821
-     * @throws EE_Error
822
-     * @throws InvalidArgumentException
823
-     * @throws InvalidDataTypeException
824
-     * @throws InvalidInterfaceException
825
-     * @throws ReflectionException
826
-     */
827
-    public function receipt_url($type = 'html')
828
-    {
829
-        $REG = $this->primary_registration();
830
-        if (! $REG instanceof EE_Registration) {
831
-            return '';
832
-        }
833
-        return $REG->receipt_url($type);
834
-    }
835
-
836
-
837
-    /**
838
-     * Gets the URL of the thank you page with this registration REG_url_link added as
839
-     * a query parameter
840
-     *
841
-     * @return string
842
-     * @throws EE_Error
843
-     * @throws InvalidArgumentException
844
-     * @throws InvalidDataTypeException
845
-     * @throws InvalidInterfaceException
846
-     * @throws ReflectionException
847
-     */
848
-    public function payment_overview_url()
849
-    {
850
-        $primary_registration = $this->primary_registration();
851
-        return $primary_registration instanceof EE_Registration ? $primary_registration->payment_overview_url() : false;
852
-    }
853
-
854
-
855
-    /**
856
-     * @return string
857
-     * @throws EE_Error
858
-     * @throws InvalidArgumentException
859
-     * @throws InvalidDataTypeException
860
-     * @throws InvalidInterfaceException
861
-     * @throws ReflectionException
862
-     */
863
-    public function gateway_response_on_transaction()
864
-    {
865
-        $payment = $this->get_first_related('Payment');
866
-        return $payment instanceof EE_Payment ? $payment->gateway_response() : '';
867
-    }
868
-
869
-
870
-    /**
871
-     * Get the status object of this object
872
-     *
873
-     * @return EE_Base_Class|EE_Status
874
-     * @throws EE_Error
875
-     * @throws InvalidArgumentException
876
-     * @throws InvalidDataTypeException
877
-     * @throws InvalidInterfaceException
878
-     * @throws ReflectionException
879
-     */
880
-    public function status_obj()
881
-    {
882
-        return $this->get_first_related('Status');
883
-    }
884
-
885
-
886
-    /**
887
-     * Gets all the extra meta info on this payment
888
-     *
889
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
890
-     * @return EE_Base_Class[]|EE_Extra_Meta
891
-     * @throws EE_Error
892
-     * @throws InvalidArgumentException
893
-     * @throws InvalidDataTypeException
894
-     * @throws InvalidInterfaceException
895
-     * @throws ReflectionException
896
-     */
897
-    public function extra_meta($query_params = array())
898
-    {
899
-        return $this->get_many_related('Extra_Meta', $query_params);
900
-    }
901
-
902
-
903
-    /**
904
-     * Wrapper for _add_relation_to
905
-     *
906
-     * @param EE_Registration $registration
907
-     * @return EE_Base_Class the relation was added to
908
-     * @throws EE_Error
909
-     * @throws InvalidArgumentException
910
-     * @throws InvalidDataTypeException
911
-     * @throws InvalidInterfaceException
912
-     * @throws ReflectionException
913
-     */
914
-    public function add_registration(EE_Registration $registration)
915
-    {
916
-        return $this->_add_relation_to($registration, 'Registration');
917
-    }
918
-
919
-
920
-    /**
921
-     * Removes the given registration from being related (even before saving this transaction).
922
-     * If an ID/index is provided and this transaction isn't saved yet, removes it from list of cached relations
923
-     *
924
-     * @param int $registration_or_id
925
-     * @return EE_Base_Class that was removed from being related
926
-     * @throws EE_Error
927
-     * @throws InvalidArgumentException
928
-     * @throws InvalidDataTypeException
929
-     * @throws InvalidInterfaceException
930
-     * @throws ReflectionException
931
-     */
932
-    public function remove_registration_with_id($registration_or_id)
933
-    {
934
-        return $this->_remove_relation_to($registration_or_id, 'Registration');
935
-    }
936
-
937
-
938
-    /**
939
-     * Gets all the line items which are for ACTUAL items
940
-     *
941
-     * @return EE_Line_Item[]
942
-     * @throws EE_Error
943
-     * @throws InvalidArgumentException
944
-     * @throws InvalidDataTypeException
945
-     * @throws InvalidInterfaceException
946
-     * @throws ReflectionException
947
-     */
948
-    public function items_purchased()
949
-    {
950
-        return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_line_item)));
951
-    }
952
-
953
-
954
-    /**
955
-     * Wrapper for _add_relation_to
956
-     *
957
-     * @param EE_Line_Item $line_item
958
-     * @return EE_Base_Class the relation was added to
959
-     * @throws EE_Error
960
-     * @throws InvalidArgumentException
961
-     * @throws InvalidDataTypeException
962
-     * @throws InvalidInterfaceException
963
-     * @throws ReflectionException
964
-     */
965
-    public function add_line_item(EE_Line_Item $line_item)
966
-    {
967
-        return $this->_add_relation_to($line_item, 'Line_Item');
968
-    }
969
-
970
-
971
-    /**
972
-     * Gets ALL the line items related to this transaction (unstructured)
973
-     *
974
-     * @param array $query_params
975
-     * @return EE_Base_Class[]|EE_Line_Item[]
976
-     * @throws EE_Error
977
-     * @throws InvalidArgumentException
978
-     * @throws InvalidDataTypeException
979
-     * @throws InvalidInterfaceException
980
-     * @throws ReflectionException
981
-     */
982
-    public function line_items($query_params = array())
983
-    {
984
-        return $this->get_many_related('Line_Item', $query_params);
985
-    }
986
-
987
-
988
-    /**
989
-     * Gets all the line items which are taxes on the total
990
-     *
991
-     * @return EE_Line_Item[]
992
-     * @throws EE_Error
993
-     * @throws InvalidArgumentException
994
-     * @throws InvalidDataTypeException
995
-     * @throws InvalidInterfaceException
996
-     * @throws ReflectionException
997
-     */
998
-    public function tax_items()
999
-    {
1000
-        return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax)));
1001
-    }
1002
-
1003
-
1004
-    /**
1005
-     * Gets the total line item (which is a parent of all other related line items,
1006
-     * meaning it takes them all into account on its total)
1007
-     *
1008
-     * @param bool $create_if_not_found
1009
-     * @return \EE_Line_Item
1010
-     * @throws EE_Error
1011
-     * @throws InvalidArgumentException
1012
-     * @throws InvalidDataTypeException
1013
-     * @throws InvalidInterfaceException
1014
-     * @throws ReflectionException
1015
-     */
1016
-    public function total_line_item($create_if_not_found = true)
1017
-    {
1018
-        $item = $this->get_first_related('Line_Item', array(array('LIN_type' => EEM_Line_Item::type_total)));
1019
-        if (! $item && $create_if_not_found) {
1020
-            $item = EEH_Line_Item::create_total_line_item($this);
1021
-        }
1022
-        return $item;
1023
-    }
1024
-
1025
-
1026
-    /**
1027
-     * Returns the total amount of tax on this transaction
1028
-     * (assumes there's only one tax subtotal line item)
1029
-     *
1030
-     * @return float
1031
-     * @throws EE_Error
1032
-     * @throws InvalidArgumentException
1033
-     * @throws InvalidDataTypeException
1034
-     * @throws InvalidInterfaceException
1035
-     * @throws ReflectionException
1036
-     */
1037
-    public function tax_total()
1038
-    {
1039
-        $tax_line_item = $this->tax_total_line_item();
1040
-        if ($tax_line_item) {
1041
-            return (float) $tax_line_item->total();
1042
-        }
1043
-        return (float) 0;
1044
-    }
1045
-
1046
-
1047
-    /**
1048
-     * Gets the tax subtotal line item (assumes there's only one)
1049
-     *
1050
-     * @return EE_Line_Item
1051
-     * @throws EE_Error
1052
-     * @throws InvalidArgumentException
1053
-     * @throws InvalidDataTypeException
1054
-     * @throws InvalidInterfaceException
1055
-     * @throws ReflectionException
1056
-     */
1057
-    public function tax_total_line_item()
1058
-    {
1059
-        return EEH_Line_Item::get_taxes_subtotal($this->total_line_item());
1060
-    }
1061
-
1062
-
1063
-    /**
1064
-     * Gets the array of billing info for the gateway and for this transaction's primary registration's attendee.
1065
-     *
1066
-     * @return EE_Form_Section_Proper
1067
-     * @throws EE_Error
1068
-     * @throws InvalidArgumentException
1069
-     * @throws InvalidDataTypeException
1070
-     * @throws InvalidInterfaceException
1071
-     * @throws ReflectionException
1072
-     */
1073
-    public function billing_info()
1074
-    {
1075
-        $payment_method = $this->payment_method();
1076
-        if (! $payment_method) {
1077
-            EE_Error::add_error(
1078
-                __(
1079
-                    'Could not find billing info for transaction because no gateway has been used for it yet',
1080
-                    'event_espresso'
1081
-                ),
1082
-                __FILE__,
1083
-                __FUNCTION__,
1084
-                __LINE__
1085
-            );
1086
-            return null;
1087
-        }
1088
-        $primary_reg = $this->primary_registration();
1089
-        if (! $primary_reg) {
1090
-            EE_Error::add_error(
1091
-                __(
1092
-                    'Cannot get billing info for gateway %s on transaction because no primary registration exists',
1093
-                    'event_espresso'
1094
-                ),
1095
-                __FILE__,
1096
-                __FUNCTION__,
1097
-                __LINE__
1098
-            );
1099
-            return null;
1100
-        }
1101
-        $attendee = $primary_reg->attendee();
1102
-        if (! $attendee) {
1103
-            EE_Error::add_error(
1104
-                __(
1105
-                    'Cannot get billing info for gateway %s on transaction because the primary registration has no attendee exists',
1106
-                    'event_espresso'
1107
-                ),
1108
-                __FILE__,
1109
-                __FUNCTION__,
1110
-                __LINE__
1111
-            );
1112
-            return null;
1113
-        }
1114
-        return $attendee->billing_info_for_payment_method($payment_method);
1115
-    }
1116
-
1117
-
1118
-    /**
1119
-     * Gets PMD_ID
1120
-     *
1121
-     * @return int
1122
-     * @throws EE_Error
1123
-     * @throws InvalidArgumentException
1124
-     * @throws InvalidDataTypeException
1125
-     * @throws InvalidInterfaceException
1126
-     * @throws ReflectionException
1127
-     */
1128
-    public function payment_method_ID()
1129
-    {
1130
-        return $this->get('PMD_ID');
1131
-    }
1132
-
1133
-
1134
-    /**
1135
-     * Sets PMD_ID
1136
-     *
1137
-     * @param int $PMD_ID
1138
-     * @throws EE_Error
1139
-     * @throws InvalidArgumentException
1140
-     * @throws InvalidDataTypeException
1141
-     * @throws InvalidInterfaceException
1142
-     * @throws ReflectionException
1143
-     */
1144
-    public function set_payment_method_ID($PMD_ID)
1145
-    {
1146
-        $this->set('PMD_ID', $PMD_ID);
1147
-    }
1148
-
1149
-
1150
-    /**
1151
-     * Gets the last-used payment method on this transaction
1152
-     * (we COULD just use the last-made payment, but some payment methods, namely
1153
-     * offline ones, dont' create payments)
1154
-     *
1155
-     * @return EE_Payment_Method
1156
-     * @throws EE_Error
1157
-     * @throws InvalidArgumentException
1158
-     * @throws InvalidDataTypeException
1159
-     * @throws InvalidInterfaceException
1160
-     * @throws ReflectionException
1161
-     */
1162
-    public function payment_method()
1163
-    {
1164
-        $pm = $this->get_first_related('Payment_Method');
1165
-        if ($pm instanceof EE_Payment_Method) {
1166
-            return $pm;
1167
-        }
1168
-        $last_payment = $this->last_payment();
1169
-        if ($last_payment instanceof EE_Payment && $last_payment->payment_method()) {
1170
-            return $last_payment->payment_method();
1171
-        }
1172
-        return null;
1173
-    }
1174
-
1175
-
1176
-    /**
1177
-     * Gets the last payment made
1178
-     *
1179
-     * @return EE_Base_Class|EE_Payment
1180
-     * @throws EE_Error
1181
-     * @throws InvalidArgumentException
1182
-     * @throws InvalidDataTypeException
1183
-     * @throws InvalidInterfaceException
1184
-     * @throws ReflectionException
1185
-     */
1186
-    public function last_payment()
1187
-    {
1188
-        return $this->get_first_related('Payment', array('order_by' => array('PAY_ID' => 'desc')));
1189
-    }
1190
-
1191
-
1192
-    /**
1193
-     * Gets all the line items which are unrelated to tickets on this transaction
1194
-     *
1195
-     * @return EE_Line_Item[]
1196
-     * @throws EE_Error
1197
-     * @throws InvalidArgumentException
1198
-     * @throws InvalidDataTypeException
1199
-     * @throws InvalidInterfaceException
1200
-     * @throws ReflectionException
1201
-     */
1202
-    public function non_ticket_line_items()
1203
-    {
1204
-        return EEM_Line_Item::instance()->get_all_non_ticket_line_items_for_transaction($this->ID());
1205
-    }
1206
-
1207
-
1208
-    /**
1209
-     * possibly toggles TXN status
1210
-     *
1211
-     * @param  boolean $update whether to save the TXN
1212
-     * @return bool whether the TXN was saved
1213
-     * @throws EE_Error
1214
-     * @throws InvalidArgumentException
1215
-     * @throws InvalidDataTypeException
1216
-     * @throws InvalidInterfaceException
1217
-     * @throws ReflectionException
1218
-     * @throws RuntimeException
1219
-     */
1220
-    public function update_status_based_on_total_paid($update = true)
1221
-    {
1222
-        // set transaction status based on comparison of TXN_paid vs TXN_total
1223
-        if (EEH_Money::compare_floats($this->paid(), $this->total(), '>')) {
1224
-            $new_txn_status = EEM_Transaction::overpaid_status_code;
1225
-        } elseif (EEH_Money::compare_floats($this->paid(), $this->total())) {
1226
-            $new_txn_status = EEM_Transaction::complete_status_code;
1227
-        } elseif (EEH_Money::compare_floats($this->paid(), $this->total(), '<')) {
1228
-            $new_txn_status = EEM_Transaction::incomplete_status_code;
1229
-        } else {
1230
-            throw new RuntimeException(
1231
-                __('The total paid calculation for this transaction is inaccurate.', 'event_espresso')
1232
-            );
1233
-        }
1234
-        if ($new_txn_status !== $this->status_ID()) {
1235
-            $this->set_status($new_txn_status);
1236
-            if ($update) {
1237
-                return $this->save() ? true : false;
1238
-            }
1239
-        }
1240
-        return false;
1241
-    }
1242
-
1243
-
1244
-    /**
1245
-     * Updates the transaction's status and total_paid based on all the payments
1246
-     * that apply to it
1247
-     *
1248
-     * @deprecated
1249
-     * @return array|bool
1250
-     * @throws EE_Error
1251
-     * @throws InvalidArgumentException
1252
-     * @throws ReflectionException
1253
-     * @throws InvalidDataTypeException
1254
-     * @throws InvalidInterfaceException
1255
-     */
1256
-    public function update_based_on_payments()
1257
-    {
1258
-        EE_Error::doing_it_wrong(
1259
-            __CLASS__ . '::' . __FUNCTION__,
1260
-            sprintf(
1261
-                __('This method is deprecated. Please use "%s" instead', 'event_espresso'),
1262
-                'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'
1263
-            ),
1264
-            '4.6.0'
1265
-        );
1266
-        /** @type EE_Transaction_Processor $transaction_processor */
1267
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
1268
-        return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment($this);
1269
-    }
1270
-
1271
-
1272
-    /**
1273
-     * @return string
1274
-     */
1275
-    public function old_txn_status()
1276
-    {
1277
-        return $this->_old_txn_status;
1278
-    }
1279
-
1280
-
1281
-    /**
1282
-     * @param string $old_txn_status
1283
-     */
1284
-    public function set_old_txn_status($old_txn_status)
1285
-    {
1286
-        // only set the first time
1287
-        if ($this->_old_txn_status === null) {
1288
-            $this->_old_txn_status = $old_txn_status;
1289
-        }
1290
-    }
1291
-
1292
-
1293
-    /**
1294
-     * reg_status_updated
1295
-     *
1296
-     * @return bool
1297
-     * @throws EE_Error
1298
-     * @throws InvalidArgumentException
1299
-     * @throws InvalidDataTypeException
1300
-     * @throws InvalidInterfaceException
1301
-     * @throws ReflectionException
1302
-     */
1303
-    public function txn_status_updated()
1304
-    {
1305
-        return $this->status_ID() !== $this->_old_txn_status && $this->_old_txn_status !== null;
1306
-    }
1307
-
1308
-
1309
-    /**
1310
-     * _reg_steps_completed
1311
-     * if $check_all is TRUE, then returns TRUE if ALL reg steps have been marked as completed,
1312
-     * if a $reg_step_slug is provided, then this step will be skipped when testing for completion
1313
-     * if $check_all is FALSE and a $reg_step_slug is provided, then ONLY that reg step will be tested for completion
1314
-     *
1315
-     * @param string $reg_step_slug
1316
-     * @param bool   $check_all
1317
-     * @return bool|int
1318
-     * @throws EE_Error
1319
-     * @throws InvalidArgumentException
1320
-     * @throws InvalidDataTypeException
1321
-     * @throws InvalidInterfaceException
1322
-     * @throws ReflectionException
1323
-     */
1324
-    private function _reg_steps_completed($reg_step_slug = '', $check_all = true)
1325
-    {
1326
-        $reg_steps = $this->reg_steps();
1327
-        if (! is_array($reg_steps) || empty($reg_steps)) {
1328
-            return false;
1329
-        }
1330
-        // loop thru reg steps array)
1331
-        foreach ($reg_steps as $slug => $reg_step_completed) {
1332
-            // if NOT checking ALL steps (only checking one step)
1333
-            if (! $check_all) {
1334
-                // and this is the one
1335
-                if ($slug === $reg_step_slug) {
1336
-                    return $reg_step_completed;
1337
-                }
1338
-                // skip to next reg step in loop
1339
-                continue;
1340
-            }
1341
-            // $check_all must be true, else we would never have gotten to this point
1342
-            if ($slug === $reg_step_slug) {
1343
-                // if we reach this point, then we are testing either:
1344
-                // all_reg_steps_completed_except() or
1345
-                // all_reg_steps_completed_except_final_step(),
1346
-                // and since this is the reg step EXCEPTION being tested
1347
-                // we want to return true (yes true) if this reg step is NOT completed
1348
-                // ie: "is everything completed except the final step?"
1349
-                // "that is correct... the final step is not completed, but all others are."
1350
-                return $reg_step_completed !== true;
1351
-            }
1352
-            if ($reg_step_completed !== true) {
1353
-                // if any reg step is NOT completed, then ALL steps are not completed
1354
-                return false;
1355
-            }
1356
-        }
1357
-        return true;
1358
-    }
1359
-
1360
-
1361
-    /**
1362
-     * all_reg_steps_completed
1363
-     * returns:
1364
-     *    true if ALL reg steps have been marked as completed
1365
-     *        or false if any step is not completed
1366
-     *
1367
-     * @return bool
1368
-     * @throws EE_Error
1369
-     * @throws InvalidArgumentException
1370
-     * @throws InvalidDataTypeException
1371
-     * @throws InvalidInterfaceException
1372
-     * @throws ReflectionException
1373
-     */
1374
-    public function all_reg_steps_completed()
1375
-    {
1376
-        return $this->_reg_steps_completed();
1377
-    }
1378
-
1379
-
1380
-    /**
1381
-     * all_reg_steps_completed_except
1382
-     * returns:
1383
-     *        true if ALL reg steps, except a particular step that you wish to skip over, have been marked as completed
1384
-     *        or false if any other step is not completed
1385
-     *        or false if ALL steps are completed including the exception you are testing !!!
1386
-     *
1387
-     * @param string $exception
1388
-     * @return bool
1389
-     * @throws EE_Error
1390
-     * @throws InvalidArgumentException
1391
-     * @throws InvalidDataTypeException
1392
-     * @throws InvalidInterfaceException
1393
-     * @throws ReflectionException
1394
-     */
1395
-    public function all_reg_steps_completed_except($exception = '')
1396
-    {
1397
-        return $this->_reg_steps_completed($exception);
1398
-    }
1399
-
1400
-
1401
-    /**
1402
-     * all_reg_steps_completed_except
1403
-     * returns:
1404
-     *        true if ALL reg steps, except the final step, have been marked as completed
1405
-     *        or false if any step is not completed
1406
-     *    or false if ALL steps are completed including the final step !!!
1407
-     *
1408
-     * @return bool
1409
-     * @throws EE_Error
1410
-     * @throws InvalidArgumentException
1411
-     * @throws InvalidDataTypeException
1412
-     * @throws InvalidInterfaceException
1413
-     * @throws ReflectionException
1414
-     */
1415
-    public function all_reg_steps_completed_except_final_step()
1416
-    {
1417
-        return $this->_reg_steps_completed('finalize_registration');
1418
-    }
1419
-
1420
-
1421
-    /**
1422
-     * reg_step_completed
1423
-     * returns:
1424
-     *    true if a specific reg step has been marked as completed
1425
-     *    a Unix timestamp if it has been initialized but not yet completed,
1426
-     *    or false if it has not yet been initialized
1427
-     *
1428
-     * @param string $reg_step_slug
1429
-     * @return bool|int
1430
-     * @throws EE_Error
1431
-     * @throws InvalidArgumentException
1432
-     * @throws InvalidDataTypeException
1433
-     * @throws InvalidInterfaceException
1434
-     * @throws ReflectionException
1435
-     */
1436
-    public function reg_step_completed($reg_step_slug)
1437
-    {
1438
-        return $this->_reg_steps_completed($reg_step_slug, false);
1439
-    }
1440
-
1441
-
1442
-    /**
1443
-     * completed_final_reg_step
1444
-     * returns:
1445
-     *    true if the finalize_registration reg step has been marked as completed
1446
-     *    a Unix timestamp if it has been initialized but not yet completed,
1447
-     *    or false if it has not yet been initialized
1448
-     *
1449
-     * @return bool|int
1450
-     * @throws EE_Error
1451
-     * @throws InvalidArgumentException
1452
-     * @throws InvalidDataTypeException
1453
-     * @throws InvalidInterfaceException
1454
-     * @throws ReflectionException
1455
-     */
1456
-    public function final_reg_step_completed()
1457
-    {
1458
-        return $this->_reg_steps_completed('finalize_registration', false);
1459
-    }
1460
-
1461
-
1462
-    /**
1463
-     * set_reg_step_initiated
1464
-     * given a valid TXN_reg_step, this sets it's value to a unix timestamp
1465
-     *
1466
-     * @param string $reg_step_slug
1467
-     * @return boolean
1468
-     * @throws EE_Error
1469
-     * @throws InvalidArgumentException
1470
-     * @throws InvalidDataTypeException
1471
-     * @throws InvalidInterfaceException
1472
-     * @throws ReflectionException
1473
-     */
1474
-    public function set_reg_step_initiated($reg_step_slug)
1475
-    {
1476
-        return $this->_set_reg_step_completed_status($reg_step_slug, time());
1477
-    }
1478
-
1479
-
1480
-    /**
1481
-     * set_reg_step_completed
1482
-     * given a valid TXN_reg_step, this sets the step as completed
1483
-     *
1484
-     * @param string $reg_step_slug
1485
-     * @return boolean
1486
-     * @throws EE_Error
1487
-     * @throws InvalidArgumentException
1488
-     * @throws InvalidDataTypeException
1489
-     * @throws InvalidInterfaceException
1490
-     * @throws ReflectionException
1491
-     */
1492
-    public function set_reg_step_completed($reg_step_slug)
1493
-    {
1494
-        return $this->_set_reg_step_completed_status($reg_step_slug, true);
1495
-    }
1496
-
1497
-
1498
-    /**
1499
-     * set_reg_step_completed
1500
-     * given a valid TXN_reg_step slug, this sets the step as NOT completed
1501
-     *
1502
-     * @param string $reg_step_slug
1503
-     * @return boolean
1504
-     * @throws EE_Error
1505
-     * @throws InvalidArgumentException
1506
-     * @throws InvalidDataTypeException
1507
-     * @throws InvalidInterfaceException
1508
-     * @throws ReflectionException
1509
-     */
1510
-    public function set_reg_step_not_completed($reg_step_slug)
1511
-    {
1512
-        return $this->_set_reg_step_completed_status($reg_step_slug, false);
1513
-    }
1514
-
1515
-
1516
-    /**
1517
-     * set_reg_step_completed
1518
-     * given a valid reg step slug, this sets the TXN_reg_step completed status which is either:
1519
-     *
1520
-     * @param  string      $reg_step_slug
1521
-     * @param  boolean|int $status
1522
-     * @return boolean
1523
-     * @throws EE_Error
1524
-     * @throws InvalidArgumentException
1525
-     * @throws InvalidDataTypeException
1526
-     * @throws InvalidInterfaceException
1527
-     * @throws ReflectionException
1528
-     */
1529
-    private function _set_reg_step_completed_status($reg_step_slug, $status)
1530
-    {
1531
-        // validate status
1532
-        $status = is_bool($status) || is_int($status) ? $status : false;
1533
-        // get reg steps array
1534
-        $txn_reg_steps = $this->reg_steps();
1535
-        // if reg step does NOT exist
1536
-        if (! isset($txn_reg_steps[ $reg_step_slug ])) {
1537
-            return false;
1538
-        }
1539
-        // if  we're trying to complete a step that is already completed
1540
-        if ($txn_reg_steps[ $reg_step_slug ] === true) {
1541
-            return true;
1542
-        }
1543
-        // if  we're trying to complete a step that hasn't even started
1544
-        if ($status === true && $txn_reg_steps[ $reg_step_slug ] === false) {
1545
-            return false;
1546
-        }
1547
-        // if current status value matches the incoming value (no change)
1548
-        // type casting as int means values should collapse to either 0, 1, or a timestamp like 1234567890
1549
-        if ((int) $txn_reg_steps[ $reg_step_slug ] === (int) $status) {
1550
-            // this will happen in cases where multiple AJAX requests occur during the same step
1551
-            return true;
1552
-        }
1553
-        // if we're trying to set a start time, but it has already been set...
1554
-        if (is_numeric($status) && is_numeric($txn_reg_steps[ $reg_step_slug ])) {
1555
-            // skip the update below, but don't return FALSE so that errors won't be displayed
1556
-            return true;
1557
-        }
1558
-        // update completed status
1559
-        $txn_reg_steps[ $reg_step_slug ] = $status;
1560
-        $this->set_reg_steps($txn_reg_steps);
1561
-        $this->save();
1562
-        return true;
1563
-    }
1564
-
1565
-
1566
-    /**
1567
-     * remove_reg_step
1568
-     * given a valid TXN_reg_step slug, this will remove (unset)
1569
-     * the reg step from the TXN reg step array
1570
-     *
1571
-     * @param string $reg_step_slug
1572
-     * @return void
1573
-     * @throws EE_Error
1574
-     * @throws InvalidArgumentException
1575
-     * @throws InvalidDataTypeException
1576
-     * @throws InvalidInterfaceException
1577
-     * @throws ReflectionException
1578
-     */
1579
-    public function remove_reg_step($reg_step_slug)
1580
-    {
1581
-        // get reg steps array
1582
-        $txn_reg_steps = $this->reg_steps();
1583
-        unset($txn_reg_steps[ $reg_step_slug ]);
1584
-        $this->set_reg_steps($txn_reg_steps);
1585
-    }
1586
-
1587
-
1588
-    /**
1589
-     * toggle_failed_transaction_status
1590
-     * upgrades a TXNs status from failed to abandoned,
1591
-     * meaning that contact information has been captured for at least one registrant
1592
-     *
1593
-     * @param bool $save
1594
-     * @return bool
1595
-     * @throws EE_Error
1596
-     * @throws InvalidArgumentException
1597
-     * @throws InvalidDataTypeException
1598
-     * @throws InvalidInterfaceException
1599
-     * @throws ReflectionException
1600
-     */
1601
-    public function toggle_failed_transaction_status($save = true)
1602
-    {
1603
-        // if TXN status is still set as "failed"...
1604
-        if ($this->status_ID() === EEM_Transaction::failed_status_code) {
1605
-            $this->set_status(EEM_Transaction::abandoned_status_code);
1606
-            if ($save) {
1607
-                $this->save();
1608
-            }
1609
-            return true;
1610
-        }
1611
-        return false;
1612
-    }
1613
-
1614
-
1615
-    /**
1616
-     * toggle_abandoned_transaction_status
1617
-     * upgrades a TXNs status from failed or abandoned to incomplete
1618
-     *
1619
-     * @return bool
1620
-     * @throws EE_Error
1621
-     * @throws InvalidArgumentException
1622
-     * @throws InvalidDataTypeException
1623
-     * @throws InvalidInterfaceException
1624
-     * @throws ReflectionException
1625
-     */
1626
-    public function toggle_abandoned_transaction_status()
1627
-    {
1628
-        // if TXN status has not been updated already due to a payment, and is still set as "failed" or "abandoned"...
1629
-        $txn_status = $this->status_ID();
1630
-        if ($txn_status === EEM_Transaction::failed_status_code
1631
-            || $txn_status === EEM_Transaction::abandoned_status_code
1632
-        ) {
1633
-            // if a contact record for the primary registrant has been created
1634
-            if ($this->primary_registration() instanceof EE_Registration
1635
-                && $this->primary_registration()->attendee() instanceof EE_Attendee
1636
-            ) {
1637
-                $this->set_status(EEM_Transaction::incomplete_status_code);
1638
-            } else {
1639
-                // no contact record? yer abandoned!
1640
-                $this->set_status(EEM_Transaction::abandoned_status_code);
1641
-            }
1642
-            return true;
1643
-        }
1644
-        return false;
1645
-    }
1646
-
1647
-
1648
-    /**
1649
-     * checks if an Abandoned TXN has any related payments, and if so,
1650
-     * updates the TXN status based on the amount paid
1651
-     *
1652
-     * @throws EE_Error
1653
-     * @throws InvalidDataTypeException
1654
-     * @throws InvalidInterfaceException
1655
-     * @throws InvalidArgumentException
1656
-     * @throws RuntimeException
1657
-     * @throws ReflectionException
1658
-     */
1659
-    public function verify_abandoned_transaction_status()
1660
-    {
1661
-        if ($this->status_ID() !== EEM_Transaction::abandoned_status_code) {
1662
-            return;
1663
-        }
1664
-        $payments = $this->get_many_related('Payment');
1665
-        if (! empty($payments)) {
1666
-            foreach ($payments as $payment) {
1667
-                if ($payment instanceof EE_Payment) {
1668
-                    // kk this TXN should NOT be abandoned
1669
-                    $this->update_status_based_on_total_paid();
1670
-                    if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1671
-                        EE_Error::add_attention(
1672
-                            sprintf(
1673
-                                esc_html__(
1674
-                                    'The status for Transaction #%1$d has been updated from "Abandoned" to "%2$s", because at least one payment has been made towards it. If the payment appears in the "Payment Details" table below, you may need to edit its status and/or other details as well.',
1675
-                                    'event_espresso'
1676
-                                ),
1677
-                                $this->ID(),
1678
-                                $this->pretty_status()
1679
-                            )
1680
-                        );
1681
-                    }
1682
-                    // get final reg step status
1683
-                    $finalized = $this->final_reg_step_completed();
1684
-                    // if the 'finalize_registration' step has been initiated (has a timestamp)
1685
-                    // but has not yet been fully completed (TRUE)
1686
-                    if (is_int($finalized) && $finalized !== false && $finalized !== true) {
1687
-                        $this->set_reg_step_completed('finalize_registration');
1688
-                        $this->save();
1689
-                    }
1690
-                }
1691
-            }
1692
-        }
1693
-    }
1694
-
1695
-
1696
-    /**
1697
-     * @since 4.10.4.p
1698
-     * @throws EE_Error
1699
-     * @throws InvalidArgumentException
1700
-     * @throws InvalidDataTypeException
1701
-     * @throws InvalidInterfaceException
1702
-     * @throws ReflectionException
1703
-     * @throws RuntimeException
1704
-     */
1705
-    public function recalculateLineItems()
1706
-    {
1707
-        $total_line_item = $this->total_line_item(false);
1708
-        if ($total_line_item instanceof EE_Line_Item) {
1709
-            EEH_Line_Item::resetIsTaxableForTickets($total_line_item);
1710
-            return EEH_Line_Item::apply_taxes($total_line_item, true);
1711
-        }
1712
-        return false;
1713
-    }
16
+	/**
17
+	 * The length of time in seconds that a lock is applied before being considered expired.
18
+	 * It is not long because a transaction should only be locked for the duration of the request that locked it
19
+	 */
20
+	const LOCK_EXPIRATION = 2;
21
+
22
+	/**
23
+	 * txn status upon initial construction.
24
+	 *
25
+	 * @var string
26
+	 */
27
+	protected $_old_txn_status;
28
+
29
+
30
+	/**
31
+	 * @param array  $props_n_values          incoming values
32
+	 * @param string $timezone                incoming timezone
33
+	 *                                        (if not set the timezone set for the website will be used.)
34
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
35
+	 *                                        date_format and the second value is the time format
36
+	 * @return EE_Transaction
37
+	 * @throws EE_Error
38
+	 * @throws InvalidArgumentException
39
+	 * @throws InvalidDataTypeException
40
+	 * @throws InvalidInterfaceException
41
+	 * @throws ReflectionException
42
+	 */
43
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
44
+	{
45
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
46
+		$txn = $has_object
47
+			? $has_object
48
+			: new self($props_n_values, false, $timezone, $date_formats);
49
+		if (! $has_object) {
50
+			$txn->set_old_txn_status($txn->status_ID());
51
+		}
52
+		return $txn;
53
+	}
54
+
55
+
56
+	/**
57
+	 * @param array  $props_n_values  incoming values from the database
58
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
59
+	 *                                the website will be used.
60
+	 * @return EE_Transaction
61
+	 * @throws EE_Error
62
+	 * @throws InvalidArgumentException
63
+	 * @throws InvalidDataTypeException
64
+	 * @throws InvalidInterfaceException
65
+	 * @throws ReflectionException
66
+	 */
67
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
68
+	{
69
+		$txn = new self($props_n_values, true, $timezone);
70
+		$txn->set_old_txn_status($txn->status_ID());
71
+		return $txn;
72
+	}
73
+
74
+
75
+	/**
76
+	 * Sets a meta field indicating that this TXN is locked and should not be updated in the db.
77
+	 * If a lock has already been set, then we will attempt to remove it in case it has expired.
78
+	 * If that also fails, then an exception is thrown.
79
+	 *
80
+	 * @throws EE_Error
81
+	 * @throws InvalidArgumentException
82
+	 * @throws InvalidDataTypeException
83
+	 * @throws InvalidInterfaceException
84
+	 * @throws ReflectionException
85
+	 */
86
+	public function lock()
87
+	{
88
+		// attempt to set lock, but if that fails...
89
+		if (! $this->add_extra_meta('lock', time(), true)) {
90
+			// then attempt to remove the lock in case it is expired
91
+			if ($this->_remove_expired_lock()) {
92
+				// if removal was successful, then try setting lock again
93
+				$this->lock();
94
+			} else {
95
+				// but if the lock can not be removed, then throw an exception
96
+				throw new EE_Error(
97
+					sprintf(
98
+						__(
99
+							'Could not lock Transaction %1$d because it is already locked, meaning another part of the system is currently editing it. It should already be unlocked by the time you read this, so please refresh the page and try again.',
100
+							'event_espresso'
101
+						),
102
+						$this->ID()
103
+					)
104
+				);
105
+			}
106
+		}
107
+	}
108
+
109
+
110
+	/**
111
+	 * removes transaction lock applied in EE_Transaction::lock()
112
+	 *
113
+	 * @return int
114
+	 * @throws EE_Error
115
+	 * @throws InvalidArgumentException
116
+	 * @throws InvalidDataTypeException
117
+	 * @throws InvalidInterfaceException
118
+	 * @throws ReflectionException
119
+	 */
120
+	public function unlock()
121
+	{
122
+		return $this->delete_extra_meta('lock');
123
+	}
124
+
125
+
126
+	/**
127
+	 * Decides whether or not now is the right time to update the transaction.
128
+	 * This is useful because we don't always know if it is safe to update the transaction
129
+	 * and its related data. why?
130
+	 * because it's possible that the transaction is being used in another
131
+	 * request and could overwrite anything we save.
132
+	 * So we want to only update the txn once we know that won't happen.
133
+	 * We also check that the lock isn't expired, and remove it if it is
134
+	 *
135
+	 * @return boolean
136
+	 * @throws EE_Error
137
+	 * @throws InvalidArgumentException
138
+	 * @throws InvalidDataTypeException
139
+	 * @throws InvalidInterfaceException
140
+	 * @throws ReflectionException
141
+	 */
142
+	public function is_locked()
143
+	{
144
+		// if TXN is not locked, then return false immediately
145
+		if (! $this->_get_lock()) {
146
+			return false;
147
+		}
148
+		// if not, then let's try and remove the lock in case it's expired...
149
+		// _remove_expired_lock() returns 0 when lock is valid (ie: removed = false)
150
+		// and a positive number if the lock was removed (ie: number of locks deleted),
151
+		// so we need to return the opposite
152
+		return ! $this->_remove_expired_lock() ? true : false;
153
+	}
154
+
155
+
156
+	/**
157
+	 * Gets the meta field indicating that this TXN is locked
158
+	 *
159
+	 * @return int
160
+	 * @throws EE_Error
161
+	 * @throws InvalidArgumentException
162
+	 * @throws InvalidDataTypeException
163
+	 * @throws InvalidInterfaceException
164
+	 * @throws ReflectionException
165
+	 */
166
+	protected function _get_lock()
167
+	{
168
+		return (int) $this->get_extra_meta('lock', true, 0);
169
+	}
170
+
171
+
172
+	/**
173
+	 * If the lock on this transaction is expired, then we want to remove it so that the transaction can be updated
174
+	 *
175
+	 * @return int
176
+	 * @throws EE_Error
177
+	 * @throws InvalidArgumentException
178
+	 * @throws InvalidDataTypeException
179
+	 * @throws InvalidInterfaceException
180
+	 * @throws ReflectionException
181
+	 */
182
+	protected function _remove_expired_lock()
183
+	{
184
+		$locked = $this->_get_lock();
185
+		if ($locked && time() - EE_Transaction::LOCK_EXPIRATION > $locked) {
186
+			return $this->unlock();
187
+		}
188
+		return 0;
189
+	}
190
+
191
+
192
+	/**
193
+	 * Set transaction total
194
+	 *
195
+	 * @param float $total total value of transaction
196
+	 * @throws EE_Error
197
+	 * @throws InvalidArgumentException
198
+	 * @throws InvalidDataTypeException
199
+	 * @throws InvalidInterfaceException
200
+	 * @throws ReflectionException
201
+	 */
202
+	public function set_total($total = 0.00)
203
+	{
204
+		$this->set('TXN_total', (float) $total);
205
+	}
206
+
207
+
208
+	/**
209
+	 * Set Total Amount Paid to Date
210
+	 *
211
+	 * @param float $total_paid total amount paid to date (sum of all payments)
212
+	 * @throws EE_Error
213
+	 * @throws InvalidArgumentException
214
+	 * @throws InvalidDataTypeException
215
+	 * @throws InvalidInterfaceException
216
+	 * @throws ReflectionException
217
+	 */
218
+	public function set_paid($total_paid = 0.00)
219
+	{
220
+		$this->set('TXN_paid', (float) $total_paid);
221
+	}
222
+
223
+
224
+	/**
225
+	 * Set transaction status
226
+	 *
227
+	 * @param string $status        whether the transaction is open, declined, accepted,
228
+	 *                              or any number of custom values that can be set
229
+	 * @throws EE_Error
230
+	 * @throws InvalidArgumentException
231
+	 * @throws InvalidDataTypeException
232
+	 * @throws InvalidInterfaceException
233
+	 * @throws ReflectionException
234
+	 */
235
+	public function set_status($status = '')
236
+	{
237
+		$this->set('STS_ID', $status);
238
+	}
239
+
240
+
241
+	/**
242
+	 * Set hash salt
243
+	 *
244
+	 * @param string $hash_salt required for some payment gateways
245
+	 * @throws EE_Error
246
+	 * @throws InvalidArgumentException
247
+	 * @throws InvalidDataTypeException
248
+	 * @throws InvalidInterfaceException
249
+	 * @throws ReflectionException
250
+	 */
251
+	public function set_hash_salt($hash_salt = '')
252
+	{
253
+		$this->set('TXN_hash_salt', $hash_salt);
254
+	}
255
+
256
+
257
+	/**
258
+	 * Sets TXN_reg_steps array
259
+	 *
260
+	 * @param array $txn_reg_steps
261
+	 * @throws EE_Error
262
+	 * @throws InvalidArgumentException
263
+	 * @throws InvalidDataTypeException
264
+	 * @throws InvalidInterfaceException
265
+	 * @throws ReflectionException
266
+	 */
267
+	public function set_reg_steps(array $txn_reg_steps)
268
+	{
269
+		$this->set('TXN_reg_steps', $txn_reg_steps);
270
+	}
271
+
272
+
273
+	/**
274
+	 * Gets TXN_reg_steps
275
+	 *
276
+	 * @return array
277
+	 * @throws EE_Error
278
+	 * @throws InvalidArgumentException
279
+	 * @throws InvalidDataTypeException
280
+	 * @throws InvalidInterfaceException
281
+	 * @throws ReflectionException
282
+	 */
283
+	public function reg_steps()
284
+	{
285
+		$TXN_reg_steps = $this->get('TXN_reg_steps');
286
+		return is_array($TXN_reg_steps) ? (array) $TXN_reg_steps : array();
287
+	}
288
+
289
+
290
+	/**
291
+	 * @return string of transaction's total cost, with currency symbol and decimal
292
+	 * @throws EE_Error
293
+	 * @throws InvalidArgumentException
294
+	 * @throws InvalidDataTypeException
295
+	 * @throws InvalidInterfaceException
296
+	 * @throws ReflectionException
297
+	 */
298
+	public function pretty_total()
299
+	{
300
+		return $this->get_pretty('TXN_total');
301
+	}
302
+
303
+
304
+	/**
305
+	 * Gets the amount paid in a pretty string (formatted and with currency symbol)
306
+	 *
307
+	 * @return string
308
+	 * @throws EE_Error
309
+	 * @throws InvalidArgumentException
310
+	 * @throws InvalidDataTypeException
311
+	 * @throws InvalidInterfaceException
312
+	 * @throws ReflectionException
313
+	 */
314
+	public function pretty_paid()
315
+	{
316
+		return $this->get_pretty('TXN_paid');
317
+	}
318
+
319
+
320
+	/**
321
+	 * calculate the amount remaining for this transaction and return;
322
+	 *
323
+	 * @return float amount remaining
324
+	 * @throws EE_Error
325
+	 * @throws InvalidArgumentException
326
+	 * @throws InvalidDataTypeException
327
+	 * @throws InvalidInterfaceException
328
+	 * @throws ReflectionException
329
+	 */
330
+	public function remaining()
331
+	{
332
+		return $this->total() - $this->paid();
333
+	}
334
+
335
+
336
+	/**
337
+	 * get Transaction Total
338
+	 *
339
+	 * @return float
340
+	 * @throws EE_Error
341
+	 * @throws InvalidArgumentException
342
+	 * @throws InvalidDataTypeException
343
+	 * @throws InvalidInterfaceException
344
+	 * @throws ReflectionException
345
+	 */
346
+	public function total()
347
+	{
348
+		return (float) $this->get('TXN_total');
349
+	}
350
+
351
+
352
+	/**
353
+	 * get Total Amount Paid to Date
354
+	 *
355
+	 * @return float
356
+	 * @throws EE_Error
357
+	 * @throws InvalidArgumentException
358
+	 * @throws InvalidDataTypeException
359
+	 * @throws InvalidInterfaceException
360
+	 * @throws ReflectionException
361
+	 */
362
+	public function paid()
363
+	{
364
+		return (float) $this->get('TXN_paid');
365
+	}
366
+
367
+
368
+	/**
369
+	 * @return mixed|null
370
+	 * @throws EE_Error
371
+	 * @throws InvalidArgumentException
372
+	 * @throws InvalidDataTypeException
373
+	 * @throws InvalidInterfaceException
374
+	 * @throws ReflectionException
375
+	 */
376
+	public function get_cart_session()
377
+	{
378
+		$session_data = (array) $this->get('TXN_session_data');
379
+		return isset($session_data['cart']) && $session_data['cart'] instanceof EE_Cart
380
+			? $session_data['cart']
381
+			: null;
382
+	}
383
+
384
+
385
+	/**
386
+	 * get Transaction session data
387
+	 *
388
+	 * @return array|mixed
389
+	 * @throws EE_Error
390
+	 * @throws InvalidArgumentException
391
+	 * @throws InvalidDataTypeException
392
+	 * @throws InvalidInterfaceException
393
+	 * @throws ReflectionException
394
+	 */
395
+	public function session_data()
396
+	{
397
+		$session_data = $this->get('TXN_session_data');
398
+		if (empty($session_data)) {
399
+			$session_data = array(
400
+				'id'            => null,
401
+				'user_id'       => null,
402
+				'ip_address'    => null,
403
+				'user_agent'    => null,
404
+				'init_access'   => null,
405
+				'last_access'   => null,
406
+				'pages_visited' => array(),
407
+			);
408
+		}
409
+		return $session_data;
410
+	}
411
+
412
+
413
+	/**
414
+	 * Set session data within the TXN object
415
+	 *
416
+	 * @param EE_Session|array $session_data
417
+	 * @throws EE_Error
418
+	 * @throws InvalidArgumentException
419
+	 * @throws InvalidDataTypeException
420
+	 * @throws InvalidInterfaceException
421
+	 * @throws ReflectionException
422
+	 */
423
+	public function set_txn_session_data($session_data)
424
+	{
425
+		if ($session_data instanceof EE_Session) {
426
+			$this->set('TXN_session_data', $session_data->get_session_data(null, true));
427
+		} else {
428
+			$this->set('TXN_session_data', $session_data);
429
+		}
430
+	}
431
+
432
+
433
+	/**
434
+	 * get Transaction hash salt
435
+	 *
436
+	 * @return mixed
437
+	 * @throws EE_Error
438
+	 * @throws InvalidArgumentException
439
+	 * @throws InvalidDataTypeException
440
+	 * @throws InvalidInterfaceException
441
+	 * @throws ReflectionException
442
+	 */
443
+	public function hash_salt_()
444
+	{
445
+		return $this->get('TXN_hash_salt');
446
+	}
447
+
448
+
449
+	/**
450
+	 * Returns the transaction datetime as either:
451
+	 *            - unix timestamp format ($format = false, $gmt = true)
452
+	 *            - formatted date string including the UTC (timezone) offset ($format = true ($gmt
453
+	 *              has no affect with this option)), this also may include a timezone abbreviation if the
454
+	 *              set timezone in this class differs from what the timezone is on the blog.
455
+	 *            - formatted date string including the UTC (timezone) offset (default).
456
+	 *
457
+	 * @param boolean $format   - whether to return a unix timestamp (default) or formatted date string
458
+	 * @param boolean $gmt      - whether to return a unix timestamp with UTC offset applied (default)
459
+	 *                          or no UTC offset applied
460
+	 * @return string | int
461
+	 * @throws EE_Error
462
+	 * @throws InvalidArgumentException
463
+	 * @throws InvalidDataTypeException
464
+	 * @throws InvalidInterfaceException
465
+	 * @throws ReflectionException
466
+	 */
467
+	public function datetime($format = false, $gmt = false)
468
+	{
469
+		if ($format) {
470
+			return $this->get_pretty('TXN_timestamp');
471
+		}
472
+		if ($gmt) {
473
+			return $this->get_raw('TXN_timestamp');
474
+		}
475
+		return $this->get('TXN_timestamp');
476
+	}
477
+
478
+
479
+	/**
480
+	 * Gets registrations on this transaction
481
+	 *
482
+	 * @param array   $query_params array of query parameters
483
+	 * @param boolean $get_cached   TRUE to retrieve cached registrations or FALSE to pull from the db
484
+	 * @return EE_Base_Class[]|EE_Registration[]
485
+	 * @throws EE_Error
486
+	 * @throws InvalidArgumentException
487
+	 * @throws InvalidDataTypeException
488
+	 * @throws InvalidInterfaceException
489
+	 * @throws ReflectionException
490
+	 */
491
+	public function registrations($query_params = array(), $get_cached = false)
492
+	{
493
+		$query_params = (empty($query_params) || ! is_array($query_params))
494
+			? array(
495
+				'order_by' => array(
496
+					'Event.EVT_name'     => 'ASC',
497
+					'Attendee.ATT_lname' => 'ASC',
498
+					'Attendee.ATT_fname' => 'ASC',
499
+				),
500
+			)
501
+			: $query_params;
502
+		$query_params = $get_cached ? array() : $query_params;
503
+		return $this->get_many_related('Registration', $query_params);
504
+	}
505
+
506
+
507
+	/**
508
+	 * Gets all the attendees for this transaction (handy for use with EE_Attendee's get_registrations_for_event
509
+	 * function for getting attendees and how many registrations they each have for an event)
510
+	 *
511
+	 * @return mixed EE_Attendee[] by default, int if $output is set to 'COUNT'
512
+	 * @throws EE_Error
513
+	 * @throws InvalidArgumentException
514
+	 * @throws InvalidDataTypeException
515
+	 * @throws InvalidInterfaceException
516
+	 * @throws ReflectionException
517
+	 */
518
+	public function attendees()
519
+	{
520
+		return $this->get_many_related('Attendee', array(array('Registration.Transaction.TXN_ID' => $this->ID())));
521
+	}
522
+
523
+
524
+	/**
525
+	 * Gets payments for this transaction. Unlike other such functions, order by 'DESC' by default
526
+	 *
527
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
528
+	 * @return EE_Base_Class[]|EE_Payment[]
529
+	 * @throws EE_Error
530
+	 * @throws InvalidArgumentException
531
+	 * @throws InvalidDataTypeException
532
+	 * @throws InvalidInterfaceException
533
+	 * @throws ReflectionException
534
+	 */
535
+	public function payments($query_params = array())
536
+	{
537
+		return $this->get_many_related('Payment', $query_params);
538
+	}
539
+
540
+
541
+	/**
542
+	 * gets only approved payments for this transaction
543
+	 *
544
+	 * @return EE_Base_Class[]|EE_Payment[]
545
+	 * @throws EE_Error
546
+	 * @throws InvalidArgumentException
547
+	 * @throws ReflectionException
548
+	 * @throws InvalidDataTypeException
549
+	 * @throws InvalidInterfaceException
550
+	 */
551
+	public function approved_payments()
552
+	{
553
+		EE_Registry::instance()->load_model('Payment');
554
+		return $this->get_many_related(
555
+			'Payment',
556
+			array(
557
+				array('STS_ID' => EEM_Payment::status_id_approved),
558
+				'order_by' => array('PAY_timestamp' => 'DESC'),
559
+			)
560
+		);
561
+	}
562
+
563
+
564
+	/**
565
+	 * Gets all payments which have not been approved
566
+	 *
567
+	 * @return EE_Base_Class[]|EEI_Payment[]
568
+	 * @throws EE_Error if a model is misconfigured somehow
569
+	 * @throws InvalidArgumentException
570
+	 * @throws InvalidDataTypeException
571
+	 * @throws InvalidInterfaceException
572
+	 * @throws ReflectionException
573
+	 */
574
+	public function pending_payments()
575
+	{
576
+		return $this->get_many_related(
577
+			'Payment',
578
+			array(
579
+				array(
580
+					'STS_ID' => EEM_Payment::status_id_pending,
581
+				),
582
+				'order_by' => array(
583
+					'PAY_timestamp' => 'DESC',
584
+				),
585
+			)
586
+		);
587
+	}
588
+
589
+
590
+	/**
591
+	 * echoes $this->pretty_status()
592
+	 *
593
+	 * @param bool $show_icons
594
+	 * @throws EE_Error
595
+	 * @throws InvalidArgumentException
596
+	 * @throws InvalidDataTypeException
597
+	 * @throws InvalidInterfaceException
598
+	 * @throws ReflectionException
599
+	 */
600
+	public function e_pretty_status($show_icons = false)
601
+	{
602
+		echo $this->pretty_status($show_icons);
603
+	}
604
+
605
+
606
+	/**
607
+	 * returns a pretty version of the status, good for displaying to users
608
+	 *
609
+	 * @param bool $show_icons
610
+	 * @return string
611
+	 * @throws EE_Error
612
+	 * @throws InvalidArgumentException
613
+	 * @throws InvalidDataTypeException
614
+	 * @throws InvalidInterfaceException
615
+	 * @throws ReflectionException
616
+	 */
617
+	public function pretty_status($show_icons = false)
618
+	{
619
+		$status = EEM_Status::instance()->localized_status(
620
+			array($this->status_ID() => __('unknown', 'event_espresso')),
621
+			false,
622
+			'sentence'
623
+		);
624
+		$icon = '';
625
+		switch ($this->status_ID()) {
626
+			case EEM_Transaction::complete_status_code:
627
+				$icon = $show_icons ? '<span class="dashicons dashicons-yes ee-icon-size-24 green-text"></span>' : '';
628
+				break;
629
+			case EEM_Transaction::incomplete_status_code:
630
+				$icon = $show_icons ? '<span class="dashicons dashicons-marker ee-icon-size-16 lt-blue-text"></span>'
631
+					: '';
632
+				break;
633
+			case EEM_Transaction::abandoned_status_code:
634
+				$icon = $show_icons ? '<span class="dashicons dashicons-marker ee-icon-size-16 red-text"></span>' : '';
635
+				break;
636
+			case EEM_Transaction::failed_status_code:
637
+				$icon = $show_icons ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>' : '';
638
+				break;
639
+			case EEM_Transaction::overpaid_status_code:
640
+				$icon = $show_icons ? '<span class="dashicons dashicons-plus ee-icon-size-16 orange-text"></span>' : '';
641
+				break;
642
+		}
643
+		return $icon . $status[ $this->status_ID() ];
644
+	}
645
+
646
+
647
+	/**
648
+	 * get Transaction Status
649
+	 *
650
+	 * @return mixed
651
+	 * @throws EE_Error
652
+	 * @throws InvalidArgumentException
653
+	 * @throws InvalidDataTypeException
654
+	 * @throws InvalidInterfaceException
655
+	 * @throws ReflectionException
656
+	 */
657
+	public function status_ID()
658
+	{
659
+		return $this->get('STS_ID');
660
+	}
661
+
662
+
663
+	/**
664
+	 * Returns TRUE or FALSE for whether or not this transaction cost any money
665
+	 *
666
+	 * @return boolean
667
+	 * @throws EE_Error
668
+	 * @throws InvalidArgumentException
669
+	 * @throws InvalidDataTypeException
670
+	 * @throws InvalidInterfaceException
671
+	 * @throws ReflectionException
672
+	 */
673
+	public function is_free()
674
+	{
675
+		return EEH_Money::compare_floats($this->get('TXN_total'), 0, '==');
676
+	}
677
+
678
+
679
+	/**
680
+	 * Returns whether this transaction is complete
681
+	 * Useful in templates and other logic for deciding if we should ask for another payment...
682
+	 *
683
+	 * @return boolean
684
+	 * @throws EE_Error
685
+	 * @throws InvalidArgumentException
686
+	 * @throws InvalidDataTypeException
687
+	 * @throws InvalidInterfaceException
688
+	 * @throws ReflectionException
689
+	 */
690
+	public function is_completed()
691
+	{
692
+		return $this->status_ID() === EEM_Transaction::complete_status_code;
693
+	}
694
+
695
+
696
+	/**
697
+	 * Returns whether this transaction is incomplete
698
+	 * Useful in templates and other logic for deciding if we should ask for another payment...
699
+	 *
700
+	 * @return boolean
701
+	 * @throws EE_Error
702
+	 * @throws InvalidArgumentException
703
+	 * @throws InvalidDataTypeException
704
+	 * @throws InvalidInterfaceException
705
+	 * @throws ReflectionException
706
+	 */
707
+	public function is_incomplete()
708
+	{
709
+		return $this->status_ID() === EEM_Transaction::incomplete_status_code;
710
+	}
711
+
712
+
713
+	/**
714
+	 * Returns whether this transaction is overpaid
715
+	 * Useful in templates and other logic for deciding if monies need to be refunded
716
+	 *
717
+	 * @return boolean
718
+	 * @throws EE_Error
719
+	 * @throws InvalidArgumentException
720
+	 * @throws InvalidDataTypeException
721
+	 * @throws InvalidInterfaceException
722
+	 * @throws ReflectionException
723
+	 */
724
+	public function is_overpaid()
725
+	{
726
+		return $this->status_ID() === EEM_Transaction::overpaid_status_code;
727
+	}
728
+
729
+
730
+	/**
731
+	 * Returns whether this transaction was abandoned
732
+	 * meaning that the transaction/registration process was somehow interrupted and never completed
733
+	 * but that contact information exists for at least one registrant
734
+	 *
735
+	 * @return boolean
736
+	 * @throws EE_Error
737
+	 * @throws InvalidArgumentException
738
+	 * @throws InvalidDataTypeException
739
+	 * @throws InvalidInterfaceException
740
+	 * @throws ReflectionException
741
+	 */
742
+	public function is_abandoned()
743
+	{
744
+		return $this->status_ID() === EEM_Transaction::abandoned_status_code;
745
+	}
746
+
747
+
748
+	/**
749
+	 * Returns whether this transaction failed
750
+	 * meaning that the transaction/registration process was somehow interrupted and never completed
751
+	 * and that NO contact information exists for any registrants
752
+	 *
753
+	 * @return boolean
754
+	 * @throws EE_Error
755
+	 * @throws InvalidArgumentException
756
+	 * @throws InvalidDataTypeException
757
+	 * @throws InvalidInterfaceException
758
+	 * @throws ReflectionException
759
+	 */
760
+	public function failed()
761
+	{
762
+		return $this->status_ID() === EEM_Transaction::failed_status_code;
763
+	}
764
+
765
+
766
+	/**
767
+	 * This returns the url for the invoice of this transaction
768
+	 *
769
+	 * @param string $type 'html' or 'pdf' (default is pdf)
770
+	 * @return string
771
+	 * @throws EE_Error
772
+	 * @throws InvalidArgumentException
773
+	 * @throws InvalidDataTypeException
774
+	 * @throws InvalidInterfaceException
775
+	 * @throws ReflectionException
776
+	 */
777
+	public function invoice_url($type = 'html')
778
+	{
779
+		$REG = $this->primary_registration();
780
+		if (! $REG instanceof EE_Registration) {
781
+			return '';
782
+		}
783
+		return $REG->invoice_url($type);
784
+	}
785
+
786
+
787
+	/**
788
+	 * Gets the primary registration only
789
+	 *
790
+	 * @return EE_Base_Class|EE_Registration
791
+	 * @throws EE_Error
792
+	 * @throws InvalidArgumentException
793
+	 * @throws InvalidDataTypeException
794
+	 * @throws InvalidInterfaceException
795
+	 * @throws ReflectionException
796
+	 */
797
+	public function primary_registration()
798
+	{
799
+		$registrations = (array) $this->get_many_related(
800
+			'Registration',
801
+			array(array('REG_count' => EEM_Registration::PRIMARY_REGISTRANT_COUNT))
802
+		);
803
+		foreach ($registrations as $registration) {
804
+			// valid registration that is NOT cancelled or declined ?
805
+			if ($registration instanceof EE_Registration
806
+				&& ! in_array($registration->status_ID(), EEM_Registration::closed_reg_statuses(), true)
807
+			) {
808
+				return $registration;
809
+			}
810
+		}
811
+		// nothing valid found, so just return first thing from array of results
812
+		return reset($registrations);
813
+	}
814
+
815
+
816
+	/**
817
+	 * Gets the URL for viewing the receipt
818
+	 *
819
+	 * @param string $type 'pdf' or 'html' (default is 'html')
820
+	 * @return string
821
+	 * @throws EE_Error
822
+	 * @throws InvalidArgumentException
823
+	 * @throws InvalidDataTypeException
824
+	 * @throws InvalidInterfaceException
825
+	 * @throws ReflectionException
826
+	 */
827
+	public function receipt_url($type = 'html')
828
+	{
829
+		$REG = $this->primary_registration();
830
+		if (! $REG instanceof EE_Registration) {
831
+			return '';
832
+		}
833
+		return $REG->receipt_url($type);
834
+	}
835
+
836
+
837
+	/**
838
+	 * Gets the URL of the thank you page with this registration REG_url_link added as
839
+	 * a query parameter
840
+	 *
841
+	 * @return string
842
+	 * @throws EE_Error
843
+	 * @throws InvalidArgumentException
844
+	 * @throws InvalidDataTypeException
845
+	 * @throws InvalidInterfaceException
846
+	 * @throws ReflectionException
847
+	 */
848
+	public function payment_overview_url()
849
+	{
850
+		$primary_registration = $this->primary_registration();
851
+		return $primary_registration instanceof EE_Registration ? $primary_registration->payment_overview_url() : false;
852
+	}
853
+
854
+
855
+	/**
856
+	 * @return string
857
+	 * @throws EE_Error
858
+	 * @throws InvalidArgumentException
859
+	 * @throws InvalidDataTypeException
860
+	 * @throws InvalidInterfaceException
861
+	 * @throws ReflectionException
862
+	 */
863
+	public function gateway_response_on_transaction()
864
+	{
865
+		$payment = $this->get_first_related('Payment');
866
+		return $payment instanceof EE_Payment ? $payment->gateway_response() : '';
867
+	}
868
+
869
+
870
+	/**
871
+	 * Get the status object of this object
872
+	 *
873
+	 * @return EE_Base_Class|EE_Status
874
+	 * @throws EE_Error
875
+	 * @throws InvalidArgumentException
876
+	 * @throws InvalidDataTypeException
877
+	 * @throws InvalidInterfaceException
878
+	 * @throws ReflectionException
879
+	 */
880
+	public function status_obj()
881
+	{
882
+		return $this->get_first_related('Status');
883
+	}
884
+
885
+
886
+	/**
887
+	 * Gets all the extra meta info on this payment
888
+	 *
889
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
890
+	 * @return EE_Base_Class[]|EE_Extra_Meta
891
+	 * @throws EE_Error
892
+	 * @throws InvalidArgumentException
893
+	 * @throws InvalidDataTypeException
894
+	 * @throws InvalidInterfaceException
895
+	 * @throws ReflectionException
896
+	 */
897
+	public function extra_meta($query_params = array())
898
+	{
899
+		return $this->get_many_related('Extra_Meta', $query_params);
900
+	}
901
+
902
+
903
+	/**
904
+	 * Wrapper for _add_relation_to
905
+	 *
906
+	 * @param EE_Registration $registration
907
+	 * @return EE_Base_Class the relation was added to
908
+	 * @throws EE_Error
909
+	 * @throws InvalidArgumentException
910
+	 * @throws InvalidDataTypeException
911
+	 * @throws InvalidInterfaceException
912
+	 * @throws ReflectionException
913
+	 */
914
+	public function add_registration(EE_Registration $registration)
915
+	{
916
+		return $this->_add_relation_to($registration, 'Registration');
917
+	}
918
+
919
+
920
+	/**
921
+	 * Removes the given registration from being related (even before saving this transaction).
922
+	 * If an ID/index is provided and this transaction isn't saved yet, removes it from list of cached relations
923
+	 *
924
+	 * @param int $registration_or_id
925
+	 * @return EE_Base_Class that was removed from being related
926
+	 * @throws EE_Error
927
+	 * @throws InvalidArgumentException
928
+	 * @throws InvalidDataTypeException
929
+	 * @throws InvalidInterfaceException
930
+	 * @throws ReflectionException
931
+	 */
932
+	public function remove_registration_with_id($registration_or_id)
933
+	{
934
+		return $this->_remove_relation_to($registration_or_id, 'Registration');
935
+	}
936
+
937
+
938
+	/**
939
+	 * Gets all the line items which are for ACTUAL items
940
+	 *
941
+	 * @return EE_Line_Item[]
942
+	 * @throws EE_Error
943
+	 * @throws InvalidArgumentException
944
+	 * @throws InvalidDataTypeException
945
+	 * @throws InvalidInterfaceException
946
+	 * @throws ReflectionException
947
+	 */
948
+	public function items_purchased()
949
+	{
950
+		return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_line_item)));
951
+	}
952
+
953
+
954
+	/**
955
+	 * Wrapper for _add_relation_to
956
+	 *
957
+	 * @param EE_Line_Item $line_item
958
+	 * @return EE_Base_Class the relation was added to
959
+	 * @throws EE_Error
960
+	 * @throws InvalidArgumentException
961
+	 * @throws InvalidDataTypeException
962
+	 * @throws InvalidInterfaceException
963
+	 * @throws ReflectionException
964
+	 */
965
+	public function add_line_item(EE_Line_Item $line_item)
966
+	{
967
+		return $this->_add_relation_to($line_item, 'Line_Item');
968
+	}
969
+
970
+
971
+	/**
972
+	 * Gets ALL the line items related to this transaction (unstructured)
973
+	 *
974
+	 * @param array $query_params
975
+	 * @return EE_Base_Class[]|EE_Line_Item[]
976
+	 * @throws EE_Error
977
+	 * @throws InvalidArgumentException
978
+	 * @throws InvalidDataTypeException
979
+	 * @throws InvalidInterfaceException
980
+	 * @throws ReflectionException
981
+	 */
982
+	public function line_items($query_params = array())
983
+	{
984
+		return $this->get_many_related('Line_Item', $query_params);
985
+	}
986
+
987
+
988
+	/**
989
+	 * Gets all the line items which are taxes on the total
990
+	 *
991
+	 * @return EE_Line_Item[]
992
+	 * @throws EE_Error
993
+	 * @throws InvalidArgumentException
994
+	 * @throws InvalidDataTypeException
995
+	 * @throws InvalidInterfaceException
996
+	 * @throws ReflectionException
997
+	 */
998
+	public function tax_items()
999
+	{
1000
+		return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax)));
1001
+	}
1002
+
1003
+
1004
+	/**
1005
+	 * Gets the total line item (which is a parent of all other related line items,
1006
+	 * meaning it takes them all into account on its total)
1007
+	 *
1008
+	 * @param bool $create_if_not_found
1009
+	 * @return \EE_Line_Item
1010
+	 * @throws EE_Error
1011
+	 * @throws InvalidArgumentException
1012
+	 * @throws InvalidDataTypeException
1013
+	 * @throws InvalidInterfaceException
1014
+	 * @throws ReflectionException
1015
+	 */
1016
+	public function total_line_item($create_if_not_found = true)
1017
+	{
1018
+		$item = $this->get_first_related('Line_Item', array(array('LIN_type' => EEM_Line_Item::type_total)));
1019
+		if (! $item && $create_if_not_found) {
1020
+			$item = EEH_Line_Item::create_total_line_item($this);
1021
+		}
1022
+		return $item;
1023
+	}
1024
+
1025
+
1026
+	/**
1027
+	 * Returns the total amount of tax on this transaction
1028
+	 * (assumes there's only one tax subtotal line item)
1029
+	 *
1030
+	 * @return float
1031
+	 * @throws EE_Error
1032
+	 * @throws InvalidArgumentException
1033
+	 * @throws InvalidDataTypeException
1034
+	 * @throws InvalidInterfaceException
1035
+	 * @throws ReflectionException
1036
+	 */
1037
+	public function tax_total()
1038
+	{
1039
+		$tax_line_item = $this->tax_total_line_item();
1040
+		if ($tax_line_item) {
1041
+			return (float) $tax_line_item->total();
1042
+		}
1043
+		return (float) 0;
1044
+	}
1045
+
1046
+
1047
+	/**
1048
+	 * Gets the tax subtotal line item (assumes there's only one)
1049
+	 *
1050
+	 * @return EE_Line_Item
1051
+	 * @throws EE_Error
1052
+	 * @throws InvalidArgumentException
1053
+	 * @throws InvalidDataTypeException
1054
+	 * @throws InvalidInterfaceException
1055
+	 * @throws ReflectionException
1056
+	 */
1057
+	public function tax_total_line_item()
1058
+	{
1059
+		return EEH_Line_Item::get_taxes_subtotal($this->total_line_item());
1060
+	}
1061
+
1062
+
1063
+	/**
1064
+	 * Gets the array of billing info for the gateway and for this transaction's primary registration's attendee.
1065
+	 *
1066
+	 * @return EE_Form_Section_Proper
1067
+	 * @throws EE_Error
1068
+	 * @throws InvalidArgumentException
1069
+	 * @throws InvalidDataTypeException
1070
+	 * @throws InvalidInterfaceException
1071
+	 * @throws ReflectionException
1072
+	 */
1073
+	public function billing_info()
1074
+	{
1075
+		$payment_method = $this->payment_method();
1076
+		if (! $payment_method) {
1077
+			EE_Error::add_error(
1078
+				__(
1079
+					'Could not find billing info for transaction because no gateway has been used for it yet',
1080
+					'event_espresso'
1081
+				),
1082
+				__FILE__,
1083
+				__FUNCTION__,
1084
+				__LINE__
1085
+			);
1086
+			return null;
1087
+		}
1088
+		$primary_reg = $this->primary_registration();
1089
+		if (! $primary_reg) {
1090
+			EE_Error::add_error(
1091
+				__(
1092
+					'Cannot get billing info for gateway %s on transaction because no primary registration exists',
1093
+					'event_espresso'
1094
+				),
1095
+				__FILE__,
1096
+				__FUNCTION__,
1097
+				__LINE__
1098
+			);
1099
+			return null;
1100
+		}
1101
+		$attendee = $primary_reg->attendee();
1102
+		if (! $attendee) {
1103
+			EE_Error::add_error(
1104
+				__(
1105
+					'Cannot get billing info for gateway %s on transaction because the primary registration has no attendee exists',
1106
+					'event_espresso'
1107
+				),
1108
+				__FILE__,
1109
+				__FUNCTION__,
1110
+				__LINE__
1111
+			);
1112
+			return null;
1113
+		}
1114
+		return $attendee->billing_info_for_payment_method($payment_method);
1115
+	}
1116
+
1117
+
1118
+	/**
1119
+	 * Gets PMD_ID
1120
+	 *
1121
+	 * @return int
1122
+	 * @throws EE_Error
1123
+	 * @throws InvalidArgumentException
1124
+	 * @throws InvalidDataTypeException
1125
+	 * @throws InvalidInterfaceException
1126
+	 * @throws ReflectionException
1127
+	 */
1128
+	public function payment_method_ID()
1129
+	{
1130
+		return $this->get('PMD_ID');
1131
+	}
1132
+
1133
+
1134
+	/**
1135
+	 * Sets PMD_ID
1136
+	 *
1137
+	 * @param int $PMD_ID
1138
+	 * @throws EE_Error
1139
+	 * @throws InvalidArgumentException
1140
+	 * @throws InvalidDataTypeException
1141
+	 * @throws InvalidInterfaceException
1142
+	 * @throws ReflectionException
1143
+	 */
1144
+	public function set_payment_method_ID($PMD_ID)
1145
+	{
1146
+		$this->set('PMD_ID', $PMD_ID);
1147
+	}
1148
+
1149
+
1150
+	/**
1151
+	 * Gets the last-used payment method on this transaction
1152
+	 * (we COULD just use the last-made payment, but some payment methods, namely
1153
+	 * offline ones, dont' create payments)
1154
+	 *
1155
+	 * @return EE_Payment_Method
1156
+	 * @throws EE_Error
1157
+	 * @throws InvalidArgumentException
1158
+	 * @throws InvalidDataTypeException
1159
+	 * @throws InvalidInterfaceException
1160
+	 * @throws ReflectionException
1161
+	 */
1162
+	public function payment_method()
1163
+	{
1164
+		$pm = $this->get_first_related('Payment_Method');
1165
+		if ($pm instanceof EE_Payment_Method) {
1166
+			return $pm;
1167
+		}
1168
+		$last_payment = $this->last_payment();
1169
+		if ($last_payment instanceof EE_Payment && $last_payment->payment_method()) {
1170
+			return $last_payment->payment_method();
1171
+		}
1172
+		return null;
1173
+	}
1174
+
1175
+
1176
+	/**
1177
+	 * Gets the last payment made
1178
+	 *
1179
+	 * @return EE_Base_Class|EE_Payment
1180
+	 * @throws EE_Error
1181
+	 * @throws InvalidArgumentException
1182
+	 * @throws InvalidDataTypeException
1183
+	 * @throws InvalidInterfaceException
1184
+	 * @throws ReflectionException
1185
+	 */
1186
+	public function last_payment()
1187
+	{
1188
+		return $this->get_first_related('Payment', array('order_by' => array('PAY_ID' => 'desc')));
1189
+	}
1190
+
1191
+
1192
+	/**
1193
+	 * Gets all the line items which are unrelated to tickets on this transaction
1194
+	 *
1195
+	 * @return EE_Line_Item[]
1196
+	 * @throws EE_Error
1197
+	 * @throws InvalidArgumentException
1198
+	 * @throws InvalidDataTypeException
1199
+	 * @throws InvalidInterfaceException
1200
+	 * @throws ReflectionException
1201
+	 */
1202
+	public function non_ticket_line_items()
1203
+	{
1204
+		return EEM_Line_Item::instance()->get_all_non_ticket_line_items_for_transaction($this->ID());
1205
+	}
1206
+
1207
+
1208
+	/**
1209
+	 * possibly toggles TXN status
1210
+	 *
1211
+	 * @param  boolean $update whether to save the TXN
1212
+	 * @return bool whether the TXN was saved
1213
+	 * @throws EE_Error
1214
+	 * @throws InvalidArgumentException
1215
+	 * @throws InvalidDataTypeException
1216
+	 * @throws InvalidInterfaceException
1217
+	 * @throws ReflectionException
1218
+	 * @throws RuntimeException
1219
+	 */
1220
+	public function update_status_based_on_total_paid($update = true)
1221
+	{
1222
+		// set transaction status based on comparison of TXN_paid vs TXN_total
1223
+		if (EEH_Money::compare_floats($this->paid(), $this->total(), '>')) {
1224
+			$new_txn_status = EEM_Transaction::overpaid_status_code;
1225
+		} elseif (EEH_Money::compare_floats($this->paid(), $this->total())) {
1226
+			$new_txn_status = EEM_Transaction::complete_status_code;
1227
+		} elseif (EEH_Money::compare_floats($this->paid(), $this->total(), '<')) {
1228
+			$new_txn_status = EEM_Transaction::incomplete_status_code;
1229
+		} else {
1230
+			throw new RuntimeException(
1231
+				__('The total paid calculation for this transaction is inaccurate.', 'event_espresso')
1232
+			);
1233
+		}
1234
+		if ($new_txn_status !== $this->status_ID()) {
1235
+			$this->set_status($new_txn_status);
1236
+			if ($update) {
1237
+				return $this->save() ? true : false;
1238
+			}
1239
+		}
1240
+		return false;
1241
+	}
1242
+
1243
+
1244
+	/**
1245
+	 * Updates the transaction's status and total_paid based on all the payments
1246
+	 * that apply to it
1247
+	 *
1248
+	 * @deprecated
1249
+	 * @return array|bool
1250
+	 * @throws EE_Error
1251
+	 * @throws InvalidArgumentException
1252
+	 * @throws ReflectionException
1253
+	 * @throws InvalidDataTypeException
1254
+	 * @throws InvalidInterfaceException
1255
+	 */
1256
+	public function update_based_on_payments()
1257
+	{
1258
+		EE_Error::doing_it_wrong(
1259
+			__CLASS__ . '::' . __FUNCTION__,
1260
+			sprintf(
1261
+				__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
1262
+				'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'
1263
+			),
1264
+			'4.6.0'
1265
+		);
1266
+		/** @type EE_Transaction_Processor $transaction_processor */
1267
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
1268
+		return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment($this);
1269
+	}
1270
+
1271
+
1272
+	/**
1273
+	 * @return string
1274
+	 */
1275
+	public function old_txn_status()
1276
+	{
1277
+		return $this->_old_txn_status;
1278
+	}
1279
+
1280
+
1281
+	/**
1282
+	 * @param string $old_txn_status
1283
+	 */
1284
+	public function set_old_txn_status($old_txn_status)
1285
+	{
1286
+		// only set the first time
1287
+		if ($this->_old_txn_status === null) {
1288
+			$this->_old_txn_status = $old_txn_status;
1289
+		}
1290
+	}
1291
+
1292
+
1293
+	/**
1294
+	 * reg_status_updated
1295
+	 *
1296
+	 * @return bool
1297
+	 * @throws EE_Error
1298
+	 * @throws InvalidArgumentException
1299
+	 * @throws InvalidDataTypeException
1300
+	 * @throws InvalidInterfaceException
1301
+	 * @throws ReflectionException
1302
+	 */
1303
+	public function txn_status_updated()
1304
+	{
1305
+		return $this->status_ID() !== $this->_old_txn_status && $this->_old_txn_status !== null;
1306
+	}
1307
+
1308
+
1309
+	/**
1310
+	 * _reg_steps_completed
1311
+	 * if $check_all is TRUE, then returns TRUE if ALL reg steps have been marked as completed,
1312
+	 * if a $reg_step_slug is provided, then this step will be skipped when testing for completion
1313
+	 * if $check_all is FALSE and a $reg_step_slug is provided, then ONLY that reg step will be tested for completion
1314
+	 *
1315
+	 * @param string $reg_step_slug
1316
+	 * @param bool   $check_all
1317
+	 * @return bool|int
1318
+	 * @throws EE_Error
1319
+	 * @throws InvalidArgumentException
1320
+	 * @throws InvalidDataTypeException
1321
+	 * @throws InvalidInterfaceException
1322
+	 * @throws ReflectionException
1323
+	 */
1324
+	private function _reg_steps_completed($reg_step_slug = '', $check_all = true)
1325
+	{
1326
+		$reg_steps = $this->reg_steps();
1327
+		if (! is_array($reg_steps) || empty($reg_steps)) {
1328
+			return false;
1329
+		}
1330
+		// loop thru reg steps array)
1331
+		foreach ($reg_steps as $slug => $reg_step_completed) {
1332
+			// if NOT checking ALL steps (only checking one step)
1333
+			if (! $check_all) {
1334
+				// and this is the one
1335
+				if ($slug === $reg_step_slug) {
1336
+					return $reg_step_completed;
1337
+				}
1338
+				// skip to next reg step in loop
1339
+				continue;
1340
+			}
1341
+			// $check_all must be true, else we would never have gotten to this point
1342
+			if ($slug === $reg_step_slug) {
1343
+				// if we reach this point, then we are testing either:
1344
+				// all_reg_steps_completed_except() or
1345
+				// all_reg_steps_completed_except_final_step(),
1346
+				// and since this is the reg step EXCEPTION being tested
1347
+				// we want to return true (yes true) if this reg step is NOT completed
1348
+				// ie: "is everything completed except the final step?"
1349
+				// "that is correct... the final step is not completed, but all others are."
1350
+				return $reg_step_completed !== true;
1351
+			}
1352
+			if ($reg_step_completed !== true) {
1353
+				// if any reg step is NOT completed, then ALL steps are not completed
1354
+				return false;
1355
+			}
1356
+		}
1357
+		return true;
1358
+	}
1359
+
1360
+
1361
+	/**
1362
+	 * all_reg_steps_completed
1363
+	 * returns:
1364
+	 *    true if ALL reg steps have been marked as completed
1365
+	 *        or false if any step is not completed
1366
+	 *
1367
+	 * @return bool
1368
+	 * @throws EE_Error
1369
+	 * @throws InvalidArgumentException
1370
+	 * @throws InvalidDataTypeException
1371
+	 * @throws InvalidInterfaceException
1372
+	 * @throws ReflectionException
1373
+	 */
1374
+	public function all_reg_steps_completed()
1375
+	{
1376
+		return $this->_reg_steps_completed();
1377
+	}
1378
+
1379
+
1380
+	/**
1381
+	 * all_reg_steps_completed_except
1382
+	 * returns:
1383
+	 *        true if ALL reg steps, except a particular step that you wish to skip over, have been marked as completed
1384
+	 *        or false if any other step is not completed
1385
+	 *        or false if ALL steps are completed including the exception you are testing !!!
1386
+	 *
1387
+	 * @param string $exception
1388
+	 * @return bool
1389
+	 * @throws EE_Error
1390
+	 * @throws InvalidArgumentException
1391
+	 * @throws InvalidDataTypeException
1392
+	 * @throws InvalidInterfaceException
1393
+	 * @throws ReflectionException
1394
+	 */
1395
+	public function all_reg_steps_completed_except($exception = '')
1396
+	{
1397
+		return $this->_reg_steps_completed($exception);
1398
+	}
1399
+
1400
+
1401
+	/**
1402
+	 * all_reg_steps_completed_except
1403
+	 * returns:
1404
+	 *        true if ALL reg steps, except the final step, have been marked as completed
1405
+	 *        or false if any step is not completed
1406
+	 *    or false if ALL steps are completed including the final step !!!
1407
+	 *
1408
+	 * @return bool
1409
+	 * @throws EE_Error
1410
+	 * @throws InvalidArgumentException
1411
+	 * @throws InvalidDataTypeException
1412
+	 * @throws InvalidInterfaceException
1413
+	 * @throws ReflectionException
1414
+	 */
1415
+	public function all_reg_steps_completed_except_final_step()
1416
+	{
1417
+		return $this->_reg_steps_completed('finalize_registration');
1418
+	}
1419
+
1420
+
1421
+	/**
1422
+	 * reg_step_completed
1423
+	 * returns:
1424
+	 *    true if a specific reg step has been marked as completed
1425
+	 *    a Unix timestamp if it has been initialized but not yet completed,
1426
+	 *    or false if it has not yet been initialized
1427
+	 *
1428
+	 * @param string $reg_step_slug
1429
+	 * @return bool|int
1430
+	 * @throws EE_Error
1431
+	 * @throws InvalidArgumentException
1432
+	 * @throws InvalidDataTypeException
1433
+	 * @throws InvalidInterfaceException
1434
+	 * @throws ReflectionException
1435
+	 */
1436
+	public function reg_step_completed($reg_step_slug)
1437
+	{
1438
+		return $this->_reg_steps_completed($reg_step_slug, false);
1439
+	}
1440
+
1441
+
1442
+	/**
1443
+	 * completed_final_reg_step
1444
+	 * returns:
1445
+	 *    true if the finalize_registration reg step has been marked as completed
1446
+	 *    a Unix timestamp if it has been initialized but not yet completed,
1447
+	 *    or false if it has not yet been initialized
1448
+	 *
1449
+	 * @return bool|int
1450
+	 * @throws EE_Error
1451
+	 * @throws InvalidArgumentException
1452
+	 * @throws InvalidDataTypeException
1453
+	 * @throws InvalidInterfaceException
1454
+	 * @throws ReflectionException
1455
+	 */
1456
+	public function final_reg_step_completed()
1457
+	{
1458
+		return $this->_reg_steps_completed('finalize_registration', false);
1459
+	}
1460
+
1461
+
1462
+	/**
1463
+	 * set_reg_step_initiated
1464
+	 * given a valid TXN_reg_step, this sets it's value to a unix timestamp
1465
+	 *
1466
+	 * @param string $reg_step_slug
1467
+	 * @return boolean
1468
+	 * @throws EE_Error
1469
+	 * @throws InvalidArgumentException
1470
+	 * @throws InvalidDataTypeException
1471
+	 * @throws InvalidInterfaceException
1472
+	 * @throws ReflectionException
1473
+	 */
1474
+	public function set_reg_step_initiated($reg_step_slug)
1475
+	{
1476
+		return $this->_set_reg_step_completed_status($reg_step_slug, time());
1477
+	}
1478
+
1479
+
1480
+	/**
1481
+	 * set_reg_step_completed
1482
+	 * given a valid TXN_reg_step, this sets the step as completed
1483
+	 *
1484
+	 * @param string $reg_step_slug
1485
+	 * @return boolean
1486
+	 * @throws EE_Error
1487
+	 * @throws InvalidArgumentException
1488
+	 * @throws InvalidDataTypeException
1489
+	 * @throws InvalidInterfaceException
1490
+	 * @throws ReflectionException
1491
+	 */
1492
+	public function set_reg_step_completed($reg_step_slug)
1493
+	{
1494
+		return $this->_set_reg_step_completed_status($reg_step_slug, true);
1495
+	}
1496
+
1497
+
1498
+	/**
1499
+	 * set_reg_step_completed
1500
+	 * given a valid TXN_reg_step slug, this sets the step as NOT completed
1501
+	 *
1502
+	 * @param string $reg_step_slug
1503
+	 * @return boolean
1504
+	 * @throws EE_Error
1505
+	 * @throws InvalidArgumentException
1506
+	 * @throws InvalidDataTypeException
1507
+	 * @throws InvalidInterfaceException
1508
+	 * @throws ReflectionException
1509
+	 */
1510
+	public function set_reg_step_not_completed($reg_step_slug)
1511
+	{
1512
+		return $this->_set_reg_step_completed_status($reg_step_slug, false);
1513
+	}
1514
+
1515
+
1516
+	/**
1517
+	 * set_reg_step_completed
1518
+	 * given a valid reg step slug, this sets the TXN_reg_step completed status which is either:
1519
+	 *
1520
+	 * @param  string      $reg_step_slug
1521
+	 * @param  boolean|int $status
1522
+	 * @return boolean
1523
+	 * @throws EE_Error
1524
+	 * @throws InvalidArgumentException
1525
+	 * @throws InvalidDataTypeException
1526
+	 * @throws InvalidInterfaceException
1527
+	 * @throws ReflectionException
1528
+	 */
1529
+	private function _set_reg_step_completed_status($reg_step_slug, $status)
1530
+	{
1531
+		// validate status
1532
+		$status = is_bool($status) || is_int($status) ? $status : false;
1533
+		// get reg steps array
1534
+		$txn_reg_steps = $this->reg_steps();
1535
+		// if reg step does NOT exist
1536
+		if (! isset($txn_reg_steps[ $reg_step_slug ])) {
1537
+			return false;
1538
+		}
1539
+		// if  we're trying to complete a step that is already completed
1540
+		if ($txn_reg_steps[ $reg_step_slug ] === true) {
1541
+			return true;
1542
+		}
1543
+		// if  we're trying to complete a step that hasn't even started
1544
+		if ($status === true && $txn_reg_steps[ $reg_step_slug ] === false) {
1545
+			return false;
1546
+		}
1547
+		// if current status value matches the incoming value (no change)
1548
+		// type casting as int means values should collapse to either 0, 1, or a timestamp like 1234567890
1549
+		if ((int) $txn_reg_steps[ $reg_step_slug ] === (int) $status) {
1550
+			// this will happen in cases where multiple AJAX requests occur during the same step
1551
+			return true;
1552
+		}
1553
+		// if we're trying to set a start time, but it has already been set...
1554
+		if (is_numeric($status) && is_numeric($txn_reg_steps[ $reg_step_slug ])) {
1555
+			// skip the update below, but don't return FALSE so that errors won't be displayed
1556
+			return true;
1557
+		}
1558
+		// update completed status
1559
+		$txn_reg_steps[ $reg_step_slug ] = $status;
1560
+		$this->set_reg_steps($txn_reg_steps);
1561
+		$this->save();
1562
+		return true;
1563
+	}
1564
+
1565
+
1566
+	/**
1567
+	 * remove_reg_step
1568
+	 * given a valid TXN_reg_step slug, this will remove (unset)
1569
+	 * the reg step from the TXN reg step array
1570
+	 *
1571
+	 * @param string $reg_step_slug
1572
+	 * @return void
1573
+	 * @throws EE_Error
1574
+	 * @throws InvalidArgumentException
1575
+	 * @throws InvalidDataTypeException
1576
+	 * @throws InvalidInterfaceException
1577
+	 * @throws ReflectionException
1578
+	 */
1579
+	public function remove_reg_step($reg_step_slug)
1580
+	{
1581
+		// get reg steps array
1582
+		$txn_reg_steps = $this->reg_steps();
1583
+		unset($txn_reg_steps[ $reg_step_slug ]);
1584
+		$this->set_reg_steps($txn_reg_steps);
1585
+	}
1586
+
1587
+
1588
+	/**
1589
+	 * toggle_failed_transaction_status
1590
+	 * upgrades a TXNs status from failed to abandoned,
1591
+	 * meaning that contact information has been captured for at least one registrant
1592
+	 *
1593
+	 * @param bool $save
1594
+	 * @return bool
1595
+	 * @throws EE_Error
1596
+	 * @throws InvalidArgumentException
1597
+	 * @throws InvalidDataTypeException
1598
+	 * @throws InvalidInterfaceException
1599
+	 * @throws ReflectionException
1600
+	 */
1601
+	public function toggle_failed_transaction_status($save = true)
1602
+	{
1603
+		// if TXN status is still set as "failed"...
1604
+		if ($this->status_ID() === EEM_Transaction::failed_status_code) {
1605
+			$this->set_status(EEM_Transaction::abandoned_status_code);
1606
+			if ($save) {
1607
+				$this->save();
1608
+			}
1609
+			return true;
1610
+		}
1611
+		return false;
1612
+	}
1613
+
1614
+
1615
+	/**
1616
+	 * toggle_abandoned_transaction_status
1617
+	 * upgrades a TXNs status from failed or abandoned to incomplete
1618
+	 *
1619
+	 * @return bool
1620
+	 * @throws EE_Error
1621
+	 * @throws InvalidArgumentException
1622
+	 * @throws InvalidDataTypeException
1623
+	 * @throws InvalidInterfaceException
1624
+	 * @throws ReflectionException
1625
+	 */
1626
+	public function toggle_abandoned_transaction_status()
1627
+	{
1628
+		// if TXN status has not been updated already due to a payment, and is still set as "failed" or "abandoned"...
1629
+		$txn_status = $this->status_ID();
1630
+		if ($txn_status === EEM_Transaction::failed_status_code
1631
+			|| $txn_status === EEM_Transaction::abandoned_status_code
1632
+		) {
1633
+			// if a contact record for the primary registrant has been created
1634
+			if ($this->primary_registration() instanceof EE_Registration
1635
+				&& $this->primary_registration()->attendee() instanceof EE_Attendee
1636
+			) {
1637
+				$this->set_status(EEM_Transaction::incomplete_status_code);
1638
+			} else {
1639
+				// no contact record? yer abandoned!
1640
+				$this->set_status(EEM_Transaction::abandoned_status_code);
1641
+			}
1642
+			return true;
1643
+		}
1644
+		return false;
1645
+	}
1646
+
1647
+
1648
+	/**
1649
+	 * checks if an Abandoned TXN has any related payments, and if so,
1650
+	 * updates the TXN status based on the amount paid
1651
+	 *
1652
+	 * @throws EE_Error
1653
+	 * @throws InvalidDataTypeException
1654
+	 * @throws InvalidInterfaceException
1655
+	 * @throws InvalidArgumentException
1656
+	 * @throws RuntimeException
1657
+	 * @throws ReflectionException
1658
+	 */
1659
+	public function verify_abandoned_transaction_status()
1660
+	{
1661
+		if ($this->status_ID() !== EEM_Transaction::abandoned_status_code) {
1662
+			return;
1663
+		}
1664
+		$payments = $this->get_many_related('Payment');
1665
+		if (! empty($payments)) {
1666
+			foreach ($payments as $payment) {
1667
+				if ($payment instanceof EE_Payment) {
1668
+					// kk this TXN should NOT be abandoned
1669
+					$this->update_status_based_on_total_paid();
1670
+					if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) {
1671
+						EE_Error::add_attention(
1672
+							sprintf(
1673
+								esc_html__(
1674
+									'The status for Transaction #%1$d has been updated from "Abandoned" to "%2$s", because at least one payment has been made towards it. If the payment appears in the "Payment Details" table below, you may need to edit its status and/or other details as well.',
1675
+									'event_espresso'
1676
+								),
1677
+								$this->ID(),
1678
+								$this->pretty_status()
1679
+							)
1680
+						);
1681
+					}
1682
+					// get final reg step status
1683
+					$finalized = $this->final_reg_step_completed();
1684
+					// if the 'finalize_registration' step has been initiated (has a timestamp)
1685
+					// but has not yet been fully completed (TRUE)
1686
+					if (is_int($finalized) && $finalized !== false && $finalized !== true) {
1687
+						$this->set_reg_step_completed('finalize_registration');
1688
+						$this->save();
1689
+					}
1690
+				}
1691
+			}
1692
+		}
1693
+	}
1694
+
1695
+
1696
+	/**
1697
+	 * @since 4.10.4.p
1698
+	 * @throws EE_Error
1699
+	 * @throws InvalidArgumentException
1700
+	 * @throws InvalidDataTypeException
1701
+	 * @throws InvalidInterfaceException
1702
+	 * @throws ReflectionException
1703
+	 * @throws RuntimeException
1704
+	 */
1705
+	public function recalculateLineItems()
1706
+	{
1707
+		$total_line_item = $this->total_line_item(false);
1708
+		if ($total_line_item instanceof EE_Line_Item) {
1709
+			EEH_Line_Item::resetIsTaxableForTickets($total_line_item);
1710
+			return EEH_Line_Item::apply_taxes($total_line_item, true);
1711
+		}
1712
+		return false;
1713
+	}
1714 1714
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Datetime.class.php 2 patches
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -495,7 +495,7 @@  discard block
 block discarded – undo
495 495
             $date_or_time,
496 496
             $echo
497 497
         );
498
-        if (! $echo) {
498
+        if ( ! $echo) {
499 499
             return $dtt;
500 500
         }
501 501
         return '';
@@ -597,7 +597,7 @@  discard block
 block discarded – undo
597 597
             '&nbsp;',
598 598
             $this->get_i18n_datetime('DTT_EVT_end', $dt_frmt)
599 599
         );
600
-        return $start !== $end ? $start . $conjunction . $end : $start;
600
+        return $start !== $end ? $start.$conjunction.$end : $start;
601 601
     }
602 602
 
603 603
 
@@ -705,7 +705,7 @@  discard block
 block discarded – undo
705 705
             '&nbsp;',
706 706
             $this->get_i18n_datetime('DTT_EVT_end', $tm_format)
707 707
         );
708
-        return $start !== $end ? $start . $conjunction . $end : $start;
708
+        return $start !== $end ? $start.$conjunction.$end : $start;
709 709
     }
710 710
 
711 711
 
@@ -750,7 +750,7 @@  discard block
 block discarded – undo
750 750
     ) {
751 751
         $dt_format = ! empty($dt_format) ? $dt_format : $this->_dt_frmt;
752 752
         $tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
753
-        $full_format = $dt_format . $separator . $tm_format;
753
+        $full_format = $dt_format.$separator.$tm_format;
754 754
         // the range output depends on various conditions
755 755
         switch (true) {
756 756
             // start date timestamp and end date timestamp are the same.
@@ -991,7 +991,7 @@  discard block
 block discarded – undo
991 991
         // tickets remaining available for purchase
992 992
         // no need for special checks for infinite, because if DTT_reg_limit == EE_INF, then EE_INF - x = EE_INF
993 993
         $dtt_remaining = $this->reg_limit() - $this->sold_and_reserved();
994
-        if (! $consider_tickets) {
994
+        if ( ! $consider_tickets) {
995 995
             return $dtt_remaining;
996 996
         }
997 997
         $tickets_remaining = $this->tickets_remaining();
@@ -1015,7 +1015,7 @@  discard block
 block discarded – undo
1015 1015
     {
1016 1016
         $sum = 0;
1017 1017
         $tickets = $this->tickets($query_params);
1018
-        if (! empty($tickets)) {
1018
+        if ( ! empty($tickets)) {
1019 1019
             foreach ($tickets as $ticket) {
1020 1020
                 if ($ticket instanceof EE_Ticket) {
1021 1021
                     // get the actual amount of tickets that can be sold
@@ -1166,20 +1166,20 @@  discard block
 block discarded – undo
1166 1166
     {
1167 1167
         if ($use_dtt_name) {
1168 1168
             $dtt_name = $this->name();
1169
-            if (! empty($dtt_name)) {
1169
+            if ( ! empty($dtt_name)) {
1170 1170
                 return $dtt_name;
1171 1171
             }
1172 1172
         }
1173 1173
         // first condition is to see if the months are different
1174 1174
         if (date('m', $this->get_raw('DTT_EVT_start')) !== date('m', $this->get_raw('DTT_EVT_end'))
1175 1175
         ) {
1176
-            $display_date = $this->start_date('M j\, Y g:i a') . ' - ' . $this->end_date('M j\, Y g:i a');
1176
+            $display_date = $this->start_date('M j\, Y g:i a').' - '.$this->end_date('M j\, Y g:i a');
1177 1177
             // next condition is if its the same month but different day
1178 1178
         } else {
1179 1179
             if (date('m', $this->get_raw('DTT_EVT_start')) === date('m', $this->get_raw('DTT_EVT_end'))
1180 1180
                 && date('d', $this->get_raw('DTT_EVT_start')) !== date('d', $this->get_raw('DTT_EVT_end'))
1181 1181
             ) {
1182
-                $display_date = $this->start_date('M j\, g:i a') . ' - ' . $this->end_date('M j\, g:i a Y');
1182
+                $display_date = $this->start_date('M j\, g:i a').' - '.$this->end_date('M j\, g:i a Y');
1183 1183
             } else {
1184 1184
                 $display_date = $this->start_date('F j\, Y')
1185 1185
                                 . ' @ '
Please login to merge, or discard this patch.
Indentation   +1402 added lines, -1402 removed lines patch added patch discarded remove patch
@@ -13,1410 +13,1410 @@
 block discarded – undo
13 13
 class EE_Datetime extends EE_Soft_Delete_Base_Class
14 14
 {
15 15
 
16
-    /**
17
-     * constant used by get_active_status, indicates datetime has no more available spaces
18
-     */
19
-    const sold_out = 'DTS';
20
-
21
-    /**
22
-     * constant used by get_active_status, indicating datetime is still active (even is not over, can be registered-for)
23
-     */
24
-    const active = 'DTA';
25
-
26
-    /**
27
-     * constant used by get_active_status, indicating the datetime cannot be used for registrations yet, but has not
28
-     * expired
29
-     */
30
-    const upcoming = 'DTU';
31
-
32
-    /**
33
-     * Datetime is postponed
34
-     */
35
-    const postponed = 'DTP';
36
-
37
-    /**
38
-     * Datetime is cancelled
39
-     */
40
-    const cancelled = 'DTC';
41
-
42
-    /**
43
-     * constant used by get_active_status, indicates datetime has expired (event is over)
44
-     */
45
-    const expired = 'DTE';
46
-
47
-    /**
48
-     * constant used in various places indicating that an event is INACTIVE (not yet ready to be published)
49
-     */
50
-    const inactive = 'DTI';
51
-
52
-
53
-    /**
54
-     * @param array  $props_n_values    incoming values
55
-     * @param string $timezone          incoming timezone (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 date_format
57
-     *                                  and the second value is the time format
58
-     * @return EE_Datetime
59
-     * @throws ReflectionException
60
-     * @throws InvalidArgumentException
61
-     * @throws InvalidInterfaceException
62
-     * @throws InvalidDataTypeException
63
-     * @throws EE_Error
64
-     */
65
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
66
-    {
67
-        $has_object = parent::_check_for_object(
68
-            $props_n_values,
69
-            __CLASS__,
70
-            $timezone,
71
-            $date_formats
72
-        );
73
-        return $has_object
74
-            ? $has_object
75
-            : new self($props_n_values, false, $timezone, $date_formats);
76
-    }
77
-
78
-
79
-    /**
80
-     * @param array  $props_n_values  incoming values from the database
81
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
82
-     *                                the website will be used.
83
-     * @return EE_Datetime
84
-     * @throws ReflectionException
85
-     * @throws InvalidArgumentException
86
-     * @throws InvalidInterfaceException
87
-     * @throws InvalidDataTypeException
88
-     * @throws EE_Error
89
-     */
90
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
91
-    {
92
-        return new self($props_n_values, true, $timezone);
93
-    }
94
-
95
-
96
-    /**
97
-     * @param $name
98
-     * @throws ReflectionException
99
-     * @throws InvalidArgumentException
100
-     * @throws InvalidInterfaceException
101
-     * @throws InvalidDataTypeException
102
-     * @throws EE_Error
103
-     */
104
-    public function set_name($name)
105
-    {
106
-        $this->set('DTT_name', $name);
107
-    }
108
-
109
-
110
-    /**
111
-     * @param $description
112
-     * @throws ReflectionException
113
-     * @throws InvalidArgumentException
114
-     * @throws InvalidInterfaceException
115
-     * @throws InvalidDataTypeException
116
-     * @throws EE_Error
117
-     */
118
-    public function set_description($description)
119
-    {
120
-        $this->set('DTT_description', $description);
121
-    }
122
-
123
-
124
-    /**
125
-     * Set event start date
126
-     * set the start date for an event
127
-     *
128
-     * @param string $date a string representation of the event's date ex:  Dec. 25, 2025 or 12-25-2025
129
-     * @throws ReflectionException
130
-     * @throws InvalidArgumentException
131
-     * @throws InvalidInterfaceException
132
-     * @throws InvalidDataTypeException
133
-     * @throws EE_Error
134
-     */
135
-    public function set_start_date($date)
136
-    {
137
-        $this->_set_date_for($date, 'DTT_EVT_start');
138
-    }
139
-
140
-
141
-    /**
142
-     * Set event start time
143
-     * set the start time for an event
144
-     *
145
-     * @param string $time a string representation of the event time ex:  9am  or  7:30 PM
146
-     * @throws ReflectionException
147
-     * @throws InvalidArgumentException
148
-     * @throws InvalidInterfaceException
149
-     * @throws InvalidDataTypeException
150
-     * @throws EE_Error
151
-     */
152
-    public function set_start_time($time)
153
-    {
154
-        $this->_set_time_for($time, 'DTT_EVT_start');
155
-    }
156
-
157
-
158
-    /**
159
-     * Set event end date
160
-     * set the end date for an event
161
-     *
162
-     * @param string $date a string representation of the event's date ex:  Dec. 25, 2025 or 12-25-2025
163
-     * @throws ReflectionException
164
-     * @throws InvalidArgumentException
165
-     * @throws InvalidInterfaceException
166
-     * @throws InvalidDataTypeException
167
-     * @throws EE_Error
168
-     */
169
-    public function set_end_date($date)
170
-    {
171
-        $this->_set_date_for($date, 'DTT_EVT_end');
172
-    }
173
-
174
-
175
-    /**
176
-     * Set event end time
177
-     * set the end time for an event
178
-     *
179
-     * @param string $time a string representation of the event time ex:  9am  or  7:30 PM
180
-     * @throws ReflectionException
181
-     * @throws InvalidArgumentException
182
-     * @throws InvalidInterfaceException
183
-     * @throws InvalidDataTypeException
184
-     * @throws EE_Error
185
-     */
186
-    public function set_end_time($time)
187
-    {
188
-        $this->_set_time_for($time, 'DTT_EVT_end');
189
-    }
190
-
191
-
192
-    /**
193
-     * Set registration limit
194
-     * set the maximum number of attendees that can be registered for this datetime slot
195
-     *
196
-     * @param int $reg_limit
197
-     * @throws ReflectionException
198
-     * @throws InvalidArgumentException
199
-     * @throws InvalidInterfaceException
200
-     * @throws InvalidDataTypeException
201
-     * @throws EE_Error
202
-     */
203
-    public function set_reg_limit($reg_limit)
204
-    {
205
-        $this->set('DTT_reg_limit', $reg_limit);
206
-    }
207
-
208
-
209
-    /**
210
-     * get the number of tickets sold for this datetime slot
211
-     *
212
-     * @return mixed int on success, FALSE on fail
213
-     * @throws ReflectionException
214
-     * @throws InvalidArgumentException
215
-     * @throws InvalidInterfaceException
216
-     * @throws InvalidDataTypeException
217
-     * @throws EE_Error
218
-     */
219
-    public function sold()
220
-    {
221
-        return $this->get_raw('DTT_sold');
222
-    }
223
-
224
-
225
-    /**
226
-     * @param int $sold
227
-     * @throws ReflectionException
228
-     * @throws InvalidArgumentException
229
-     * @throws InvalidInterfaceException
230
-     * @throws InvalidDataTypeException
231
-     * @throws EE_Error
232
-     */
233
-    public function set_sold($sold)
234
-    {
235
-        // sold can not go below zero
236
-        $sold = max(0, $sold);
237
-        $this->set('DTT_sold', $sold);
238
-    }
239
-
240
-
241
-    /**
242
-     * Increments sold by amount passed by $qty, and persists it immediately to the database.
243
-     * Simultaneously decreases the reserved count, unless $also_decrease_reserved is false.
244
-     *
245
-     * @param int $qty
246
-     * @param boolean $also_decrease_reserved
247
-     * @return boolean indicating success
248
-     * @throws ReflectionException
249
-     * @throws InvalidArgumentException
250
-     * @throws InvalidInterfaceException
251
-     * @throws InvalidDataTypeException
252
-     * @throws EE_Error
253
-     */
254
-    public function increaseSold($qty = 1, $also_decrease_reserved = true)
255
-    {
256
-        $qty = absint($qty);
257
-        if ($also_decrease_reserved) {
258
-            $success = $this->adjustNumericFieldsInDb(
259
-                [
260
-                    'DTT_reserved' => $qty * -1,
261
-                    'DTT_sold' => $qty
262
-                ]
263
-            );
264
-        } else {
265
-            $success = $this->adjustNumericFieldsInDb(
266
-                [
267
-                    'DTT_sold' => $qty
268
-                ]
269
-            );
270
-        }
271
-
272
-        do_action(
273
-            'AHEE__EE_Datetime__increase_sold',
274
-            $this,
275
-            $qty,
276
-            $this->sold(),
277
-            $success
278
-        );
279
-        return $success;
280
-    }
281
-
282
-
283
-    /**
284
-     * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need
285
-     * to save afterwards.)
286
-     *
287
-     * @param int $qty
288
-     * @return boolean indicating success
289
-     * @throws ReflectionException
290
-     * @throws InvalidArgumentException
291
-     * @throws InvalidInterfaceException
292
-     * @throws InvalidDataTypeException
293
-     * @throws EE_Error
294
-     */
295
-    public function decreaseSold($qty = 1)
296
-    {
297
-        $qty = absint($qty);
298
-        $success = $this->adjustNumericFieldsInDb(
299
-            [
300
-                'DTT_sold' => $qty * -1
301
-            ]
302
-        );
303
-        do_action(
304
-            'AHEE__EE_Datetime__decrease_sold',
305
-            $this,
306
-            $qty,
307
-            $this->sold(),
308
-            $success
309
-        );
310
-        return $success;
311
-    }
312
-
313
-
314
-    /**
315
-     * Gets qty of reserved tickets for this datetime
316
-     *
317
-     * @return int
318
-     * @throws ReflectionException
319
-     * @throws InvalidArgumentException
320
-     * @throws InvalidInterfaceException
321
-     * @throws InvalidDataTypeException
322
-     * @throws EE_Error
323
-     */
324
-    public function reserved()
325
-    {
326
-        return $this->get_raw('DTT_reserved');
327
-    }
328
-
329
-
330
-    /**
331
-     * Sets qty of reserved tickets for this datetime
332
-     *
333
-     * @param int $reserved
334
-     * @throws ReflectionException
335
-     * @throws InvalidArgumentException
336
-     * @throws InvalidInterfaceException
337
-     * @throws InvalidDataTypeException
338
-     * @throws EE_Error
339
-     */
340
-    public function set_reserved($reserved)
341
-    {
342
-        // reserved can not go below zero
343
-        $reserved = max(0, (int) $reserved);
344
-        $this->set('DTT_reserved', $reserved);
345
-    }
346
-
347
-
348
-    /**
349
-     * Increments reserved by amount passed by $qty, and persists it immediately to the database.
350
-     *
351
-     * @param int $qty
352
-     * @return boolean indicating success
353
-     * @throws ReflectionException
354
-     * @throws InvalidArgumentException
355
-     * @throws InvalidInterfaceException
356
-     * @throws InvalidDataTypeException
357
-     * @throws EE_Error
358
-     */
359
-    public function increaseReserved($qty = 1)
360
-    {
361
-        $qty = absint($qty);
362
-        $success = $this->incrementFieldConditionallyInDb(
363
-            'DTT_reserved',
364
-            'DTT_sold',
365
-            'DTT_reg_limit',
366
-            $qty
367
-        );
368
-        do_action(
369
-            'AHEE__EE_Datetime__increase_reserved',
370
-            $this,
371
-            $qty,
372
-            $this->reserved(),
373
-            $success
374
-        );
375
-        return $success;
376
-    }
377
-
378
-
379
-    /**
380
-     * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
381
-     *
382
-     * @param int $qty
383
-     * @return boolean indicating success
384
-     * @throws ReflectionException
385
-     * @throws InvalidArgumentException
386
-     * @throws InvalidInterfaceException
387
-     * @throws InvalidDataTypeException
388
-     * @throws EE_Error
389
-     */
390
-    public function decreaseReserved($qty = 1)
391
-    {
392
-        $qty = absint($qty);
393
-        $success = $this->adjustNumericFieldsInDb(
394
-            [
395
-                'DTT_reserved' => $qty * -1
396
-            ]
397
-        );
398
-        do_action(
399
-            'AHEE__EE_Datetime__decrease_reserved',
400
-            $this,
401
-            $qty,
402
-            $this->reserved(),
403
-            $success
404
-        );
405
-        return $success;
406
-    }
407
-
408
-
409
-    /**
410
-     * total sold and reserved tickets
411
-     *
412
-     * @return int
413
-     * @throws ReflectionException
414
-     * @throws InvalidArgumentException
415
-     * @throws InvalidInterfaceException
416
-     * @throws InvalidDataTypeException
417
-     * @throws EE_Error
418
-     */
419
-    public function sold_and_reserved()
420
-    {
421
-        return $this->sold() + $this->reserved();
422
-    }
423
-
424
-
425
-    /**
426
-     * returns the datetime name
427
-     *
428
-     * @return string
429
-     * @throws ReflectionException
430
-     * @throws InvalidArgumentException
431
-     * @throws InvalidInterfaceException
432
-     * @throws InvalidDataTypeException
433
-     * @throws EE_Error
434
-     */
435
-    public function name()
436
-    {
437
-        return $this->get('DTT_name');
438
-    }
439
-
440
-
441
-    /**
442
-     * returns the datetime description
443
-     *
444
-     * @return string
445
-     * @throws ReflectionException
446
-     * @throws InvalidArgumentException
447
-     * @throws InvalidInterfaceException
448
-     * @throws InvalidDataTypeException
449
-     * @throws EE_Error
450
-     */
451
-    public function description()
452
-    {
453
-        return $this->get('DTT_description');
454
-    }
455
-
456
-
457
-    /**
458
-     * This helper simply returns whether the event_datetime for the current datetime is a primary datetime
459
-     *
460
-     * @return boolean  TRUE if is primary, FALSE if not.
461
-     * @throws ReflectionException
462
-     * @throws InvalidArgumentException
463
-     * @throws InvalidInterfaceException
464
-     * @throws InvalidDataTypeException
465
-     * @throws EE_Error
466
-     */
467
-    public function is_primary()
468
-    {
469
-        return $this->get('DTT_is_primary');
470
-    }
471
-
472
-
473
-    /**
474
-     * This helper simply returns the order for the datetime
475
-     *
476
-     * @return int  The order of the datetime for this event.
477
-     * @throws ReflectionException
478
-     * @throws InvalidArgumentException
479
-     * @throws InvalidInterfaceException
480
-     * @throws InvalidDataTypeException
481
-     * @throws EE_Error
482
-     */
483
-    public function order()
484
-    {
485
-        return $this->get('DTT_order');
486
-    }
487
-
488
-
489
-    /**
490
-     * This helper simply returns the parent id for the datetime
491
-     *
492
-     * @return int
493
-     * @throws ReflectionException
494
-     * @throws InvalidArgumentException
495
-     * @throws InvalidInterfaceException
496
-     * @throws InvalidDataTypeException
497
-     * @throws EE_Error
498
-     */
499
-    public function parent()
500
-    {
501
-        return $this->get('DTT_parent');
502
-    }
503
-
504
-
505
-    /**
506
-     * show date and/or time
507
-     *
508
-     * @param string $date_or_time    whether to display a date or time or both
509
-     * @param string $start_or_end    whether to display start or end datetimes
510
-     * @param string $dt_frmt
511
-     * @param string $tm_frmt
512
-     * @param bool   $echo            whether we echo or return (note echoing uses "pretty" formats,
513
-     *                                otherwise we use the standard formats)
514
-     * @return string|bool  string on success, FALSE on fail
515
-     * @throws ReflectionException
516
-     * @throws InvalidArgumentException
517
-     * @throws InvalidInterfaceException
518
-     * @throws InvalidDataTypeException
519
-     * @throws EE_Error
520
-     */
521
-    private function _show_datetime(
522
-        $date_or_time = null,
523
-        $start_or_end = 'start',
524
-        $dt_frmt = '',
525
-        $tm_frmt = '',
526
-        $echo = false
527
-    ) {
528
-        $field_name = "DTT_EVT_{$start_or_end}";
529
-        $dtt = $this->_get_datetime(
530
-            $field_name,
531
-            $dt_frmt,
532
-            $tm_frmt,
533
-            $date_or_time,
534
-            $echo
535
-        );
536
-        if (! $echo) {
537
-            return $dtt;
538
-        }
539
-        return '';
540
-    }
541
-
542
-
543
-    /**
544
-     * get event start date.  Provide either the date format, or NULL to re-use the
545
-     * last-used format, or '' to use the default date format
546
-     *
547
-     * @param string $dt_frmt string representation of date format defaults to 'F j, Y'
548
-     * @return mixed            string on success, FALSE on fail
549
-     * @throws ReflectionException
550
-     * @throws InvalidArgumentException
551
-     * @throws InvalidInterfaceException
552
-     * @throws InvalidDataTypeException
553
-     * @throws EE_Error
554
-     */
555
-    public function start_date($dt_frmt = '')
556
-    {
557
-        return $this->_show_datetime('D', 'start', $dt_frmt);
558
-    }
559
-
560
-
561
-    /**
562
-     * Echoes start_date()
563
-     *
564
-     * @param string $dt_frmt
565
-     * @throws ReflectionException
566
-     * @throws InvalidArgumentException
567
-     * @throws InvalidInterfaceException
568
-     * @throws InvalidDataTypeException
569
-     * @throws EE_Error
570
-     */
571
-    public function e_start_date($dt_frmt = '')
572
-    {
573
-        $this->_show_datetime('D', 'start', $dt_frmt, null, true);
574
-    }
575
-
576
-
577
-    /**
578
-     * get end date. Provide either the date format, or NULL to re-use the
579
-     * last-used format, or '' to use the default date format
580
-     *
581
-     * @param string $dt_frmt string representation of date format defaults to 'F j, Y'
582
-     * @return mixed            string on success, FALSE on fail
583
-     * @throws ReflectionException
584
-     * @throws InvalidArgumentException
585
-     * @throws InvalidInterfaceException
586
-     * @throws InvalidDataTypeException
587
-     * @throws EE_Error
588
-     */
589
-    public function end_date($dt_frmt = '')
590
-    {
591
-        return $this->_show_datetime('D', 'end', $dt_frmt);
592
-    }
593
-
594
-
595
-    /**
596
-     * Echoes the end date. See end_date()
597
-     *
598
-     * @param string $dt_frmt
599
-     * @throws ReflectionException
600
-     * @throws InvalidArgumentException
601
-     * @throws InvalidInterfaceException
602
-     * @throws InvalidDataTypeException
603
-     * @throws EE_Error
604
-     */
605
-    public function e_end_date($dt_frmt = '')
606
-    {
607
-        $this->_show_datetime('D', 'end', $dt_frmt, null, true);
608
-    }
609
-
610
-
611
-    /**
612
-     * get date_range - meaning the start AND end date
613
-     *
614
-     * @access public
615
-     * @param string $dt_frmt     string representation of date format defaults to WP settings
616
-     * @param string $conjunction conjunction junction what's your function ?
617
-     *                            this string joins the start date with the end date ie: Jan 01 "to" Dec 31
618
-     * @return mixed              string on success, FALSE on fail
619
-     * @throws ReflectionException
620
-     * @throws InvalidArgumentException
621
-     * @throws InvalidInterfaceException
622
-     * @throws InvalidDataTypeException
623
-     * @throws EE_Error
624
-     */
625
-    public function date_range($dt_frmt = '', $conjunction = ' - ')
626
-    {
627
-        $dt_frmt = ! empty($dt_frmt) ? $dt_frmt : $this->_dt_frmt;
628
-        $start = str_replace(
629
-            ' ',
630
-            '&nbsp;',
631
-            $this->get_i18n_datetime('DTT_EVT_start', $dt_frmt)
632
-        );
633
-        $end = str_replace(
634
-            ' ',
635
-            '&nbsp;',
636
-            $this->get_i18n_datetime('DTT_EVT_end', $dt_frmt)
637
-        );
638
-        return $start !== $end ? $start . $conjunction . $end : $start;
639
-    }
640
-
641
-
642
-    /**
643
-     * @param string $dt_frmt
644
-     * @param string $conjunction
645
-     * @throws ReflectionException
646
-     * @throws InvalidArgumentException
647
-     * @throws InvalidInterfaceException
648
-     * @throws InvalidDataTypeException
649
-     * @throws EE_Error
650
-     */
651
-    public function e_date_range($dt_frmt = '', $conjunction = ' - ')
652
-    {
653
-        echo $this->date_range($dt_frmt, $conjunction);
654
-    }
655
-
656
-
657
-    /**
658
-     * get start time
659
-     *
660
-     * @param string $tm_format - string representation of time format defaults to 'g:i a'
661
-     * @return mixed        string on success, FALSE on fail
662
-     * @throws ReflectionException
663
-     * @throws InvalidArgumentException
664
-     * @throws InvalidInterfaceException
665
-     * @throws InvalidDataTypeException
666
-     * @throws EE_Error
667
-     */
668
-    public function start_time($tm_format = '')
669
-    {
670
-        return $this->_show_datetime('T', 'start', null, $tm_format);
671
-    }
672
-
673
-
674
-    /**
675
-     * @param string $tm_format
676
-     * @throws ReflectionException
677
-     * @throws InvalidArgumentException
678
-     * @throws InvalidInterfaceException
679
-     * @throws InvalidDataTypeException
680
-     * @throws EE_Error
681
-     */
682
-    public function e_start_time($tm_format = '')
683
-    {
684
-        $this->_show_datetime('T', 'start', null, $tm_format, true);
685
-    }
686
-
687
-
688
-    /**
689
-     * get end time
690
-     *
691
-     * @param string $tm_format string representation of time format defaults to 'g:i a'
692
-     * @return mixed                string on success, FALSE on fail
693
-     * @throws ReflectionException
694
-     * @throws InvalidArgumentException
695
-     * @throws InvalidInterfaceException
696
-     * @throws InvalidDataTypeException
697
-     * @throws EE_Error
698
-     */
699
-    public function end_time($tm_format = '')
700
-    {
701
-        return $this->_show_datetime('T', 'end', null, $tm_format);
702
-    }
703
-
704
-
705
-    /**
706
-     * @param string $tm_format
707
-     * @throws ReflectionException
708
-     * @throws InvalidArgumentException
709
-     * @throws InvalidInterfaceException
710
-     * @throws InvalidDataTypeException
711
-     * @throws EE_Error
712
-     */
713
-    public function e_end_time($tm_format = '')
714
-    {
715
-        $this->_show_datetime('T', 'end', null, $tm_format, true);
716
-    }
717
-
718
-
719
-    /**
720
-     * get time_range
721
-     *
722
-     * @access public
723
-     * @param string $tm_format   string representation of time format defaults to 'g:i a'
724
-     * @param string $conjunction conjunction junction what's your function ?
725
-     *                            this string joins the start date with the end date ie: Jan 01 "to" Dec 31
726
-     * @return mixed              string on success, FALSE on fail
727
-     * @throws ReflectionException
728
-     * @throws InvalidArgumentException
729
-     * @throws InvalidInterfaceException
730
-     * @throws InvalidDataTypeException
731
-     * @throws EE_Error
732
-     */
733
-    public function time_range($tm_format = '', $conjunction = ' - ')
734
-    {
735
-        $tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
736
-        $start = str_replace(
737
-            ' ',
738
-            '&nbsp;',
739
-            $this->get_i18n_datetime('DTT_EVT_start', $tm_format)
740
-        );
741
-        $end = str_replace(
742
-            ' ',
743
-            '&nbsp;',
744
-            $this->get_i18n_datetime('DTT_EVT_end', $tm_format)
745
-        );
746
-        return $start !== $end ? $start . $conjunction . $end : $start;
747
-    }
748
-
749
-
750
-    /**
751
-     * @param string $tm_format
752
-     * @param string $conjunction
753
-     * @throws ReflectionException
754
-     * @throws InvalidArgumentException
755
-     * @throws InvalidInterfaceException
756
-     * @throws InvalidDataTypeException
757
-     * @throws EE_Error
758
-     */
759
-    public function e_time_range($tm_format = '', $conjunction = ' - ')
760
-    {
761
-        echo $this->time_range($tm_format, $conjunction);
762
-    }
763
-
764
-
765
-    /**
766
-     * This returns a range representation of the date and times.
767
-     * Output is dependent on the difference (or similarity) between DTT_EVT_start and DTT_EVT_end.
768
-     * Also, the return value is localized.
769
-     *
770
-     * @param string $dt_format
771
-     * @param string $tm_format
772
-     * @param string $conjunction used between two different dates or times.
773
-     *                            ex: Dec 1{$conjunction}}Dec 6, or 2pm{$conjunction}3pm
774
-     * @param string $separator   used between the date and time formats.
775
-     *                            ex: Dec 1, 2016{$separator}2pm
776
-     * @return string
777
-     * @throws ReflectionException
778
-     * @throws InvalidArgumentException
779
-     * @throws InvalidInterfaceException
780
-     * @throws InvalidDataTypeException
781
-     * @throws EE_Error
782
-     */
783
-    public function date_and_time_range(
784
-        $dt_format = '',
785
-        $tm_format = '',
786
-        $conjunction = ' - ',
787
-        $separator = ' '
788
-    ) {
789
-        $dt_format = ! empty($dt_format) ? $dt_format : $this->_dt_frmt;
790
-        $tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
791
-        $full_format = $dt_format . $separator . $tm_format;
792
-        // the range output depends on various conditions
793
-        switch (true) {
794
-            // start date timestamp and end date timestamp are the same.
795
-            case ($this->get_raw('DTT_EVT_start') === $this->get_raw('DTT_EVT_end')):
796
-                $output = $this->get_i18n_datetime('DTT_EVT_start', $full_format);
797
-                break;
798
-            // start and end date are the same but times are different
799
-            case ($this->start_date() === $this->end_date()):
800
-                $output = $this->get_i18n_datetime('DTT_EVT_start', $full_format)
801
-                          . $conjunction
802
-                          . $this->get_i18n_datetime('DTT_EVT_end', $tm_format);
803
-                break;
804
-            // all other conditions
805
-            default:
806
-                $output = $this->get_i18n_datetime('DTT_EVT_start', $full_format)
807
-                          . $conjunction
808
-                          . $this->get_i18n_datetime('DTT_EVT_end', $full_format);
809
-                break;
810
-        }
811
-        return $output;
812
-    }
813
-
814
-
815
-    /**
816
-     * This echos the results of date and time range.
817
-     *
818
-     * @see date_and_time_range() for more details on purpose.
819
-     * @param string $dt_format
820
-     * @param string $tm_format
821
-     * @param string $conjunction
822
-     * @return void
823
-     * @throws ReflectionException
824
-     * @throws InvalidArgumentException
825
-     * @throws InvalidInterfaceException
826
-     * @throws InvalidDataTypeException
827
-     * @throws EE_Error
828
-     */
829
-    public function e_date_and_time_range($dt_format = '', $tm_format = '', $conjunction = ' - ')
830
-    {
831
-        echo $this->date_and_time_range($dt_format, $tm_format, $conjunction);
832
-    }
833
-
834
-
835
-    /**
836
-     * get start date and start time
837
-     *
838
-     * @param    string $dt_format - string representation of date format defaults to 'F j, Y'
839
-     * @param    string $tm_format - string representation of time format defaults to 'g:i a'
840
-     * @return    mixed    string on success, FALSE on fail
841
-     * @throws ReflectionException
842
-     * @throws InvalidArgumentException
843
-     * @throws InvalidInterfaceException
844
-     * @throws InvalidDataTypeException
845
-     * @throws EE_Error
846
-     */
847
-    public function start_date_and_time($dt_format = '', $tm_format = '')
848
-    {
849
-        return $this->_show_datetime('', 'start', $dt_format, $tm_format);
850
-    }
851
-
852
-
853
-    /**
854
-     * @param string $dt_frmt
855
-     * @param string $tm_format
856
-     * @throws ReflectionException
857
-     * @throws InvalidArgumentException
858
-     * @throws InvalidInterfaceException
859
-     * @throws InvalidDataTypeException
860
-     * @throws EE_Error
861
-     */
862
-    public function e_start_date_and_time($dt_frmt = '', $tm_format = '')
863
-    {
864
-        $this->_show_datetime('', 'start', $dt_frmt, $tm_format, true);
865
-    }
866
-
867
-
868
-    /**
869
-     * Shows the length of the event (start to end time).
870
-     * Can be shown in 'seconds','minutes','hours', or 'days'.
871
-     * By default, rounds up. (So if you use 'days', and then event
872
-     * only occurs for 1 hour, it will return 1 day).
873
-     *
874
-     * @param string $units 'seconds','minutes','hours','days'
875
-     * @param bool   $round_up
876
-     * @return float|int|mixed
877
-     * @throws ReflectionException
878
-     * @throws InvalidArgumentException
879
-     * @throws InvalidInterfaceException
880
-     * @throws InvalidDataTypeException
881
-     * @throws EE_Error
882
-     */
883
-    public function length($units = 'seconds', $round_up = false)
884
-    {
885
-        $start = $this->get_raw('DTT_EVT_start');
886
-        $end = $this->get_raw('DTT_EVT_end');
887
-        $length_in_units = $end - $start;
888
-        switch ($units) {
889
-            // NOTE: We purposefully don't use "break;" in order to chain the divisions
890
-            /** @noinspection PhpMissingBreakStatementInspection */
891
-            // phpcs:disable PSR2.ControlStructures.SwitchDeclaration.TerminatingComment
892
-            case 'days':
893
-                $length_in_units /= 24;
894
-            /** @noinspection PhpMissingBreakStatementInspection */
895
-            case 'hours':
896
-                // fall through is intentional
897
-                $length_in_units /= 60;
898
-            /** @noinspection PhpMissingBreakStatementInspection */
899
-            case 'minutes':
900
-                // fall through is intentional
901
-                $length_in_units /= 60;
902
-            case 'seconds':
903
-            default:
904
-                $length_in_units = ceil($length_in_units);
905
-        }
906
-        // phpcs:enable
907
-        if ($round_up) {
908
-            $length_in_units = max($length_in_units, 1);
909
-        }
910
-        return $length_in_units;
911
-    }
912
-
913
-
914
-    /**
915
-     *        get end date and time
916
-     *
917
-     * @param string $dt_frmt   - string representation of date format defaults to 'F j, Y'
918
-     * @param string $tm_format - string representation of time format defaults to 'g:i a'
919
-     * @return    mixed                string on success, FALSE on fail
920
-     * @throws ReflectionException
921
-     * @throws InvalidArgumentException
922
-     * @throws InvalidInterfaceException
923
-     * @throws InvalidDataTypeException
924
-     * @throws EE_Error
925
-     */
926
-    public function end_date_and_time($dt_frmt = '', $tm_format = '')
927
-    {
928
-        return $this->_show_datetime('', 'end', $dt_frmt, $tm_format);
929
-    }
930
-
931
-
932
-    /**
933
-     * @param string $dt_frmt
934
-     * @param string $tm_format
935
-     * @throws ReflectionException
936
-     * @throws InvalidArgumentException
937
-     * @throws InvalidInterfaceException
938
-     * @throws InvalidDataTypeException
939
-     * @throws EE_Error
940
-     */
941
-    public function e_end_date_and_time($dt_frmt = '', $tm_format = '')
942
-    {
943
-        $this->_show_datetime('', 'end', $dt_frmt, $tm_format, true);
944
-    }
945
-
946
-
947
-    /**
948
-     *        get start timestamp
949
-     *
950
-     * @return        int
951
-     * @throws ReflectionException
952
-     * @throws InvalidArgumentException
953
-     * @throws InvalidInterfaceException
954
-     * @throws InvalidDataTypeException
955
-     * @throws EE_Error
956
-     */
957
-    public function start()
958
-    {
959
-        return $this->get_raw('DTT_EVT_start');
960
-    }
961
-
962
-
963
-    /**
964
-     *        get end timestamp
965
-     *
966
-     * @return        int
967
-     * @throws ReflectionException
968
-     * @throws InvalidArgumentException
969
-     * @throws InvalidInterfaceException
970
-     * @throws InvalidDataTypeException
971
-     * @throws EE_Error
972
-     */
973
-    public function end()
974
-    {
975
-        return $this->get_raw('DTT_EVT_end');
976
-    }
977
-
978
-
979
-    /**
980
-     *    get the registration limit for this datetime slot
981
-     *
982
-     * @return        mixed        int on success, FALSE on fail
983
-     * @throws ReflectionException
984
-     * @throws InvalidArgumentException
985
-     * @throws InvalidInterfaceException
986
-     * @throws InvalidDataTypeException
987
-     * @throws EE_Error
988
-     */
989
-    public function reg_limit()
990
-    {
991
-        return $this->get_raw('DTT_reg_limit');
992
-    }
993
-
994
-
995
-    /**
996
-     *    have the tickets sold for this datetime, met or exceed the registration limit ?
997
-     *
998
-     * @return        boolean
999
-     * @throws ReflectionException
1000
-     * @throws InvalidArgumentException
1001
-     * @throws InvalidInterfaceException
1002
-     * @throws InvalidDataTypeException
1003
-     * @throws EE_Error
1004
-     */
1005
-    public function sold_out()
1006
-    {
1007
-        return $this->reg_limit() > 0 && $this->sold() >= $this->reg_limit();
1008
-    }
1009
-
1010
-
1011
-    /**
1012
-     * return the total number of spaces remaining at this venue.
1013
-     * This only takes the venue's capacity into account, NOT the tickets available for sale
1014
-     *
1015
-     * @param bool $consider_tickets Whether to consider tickets remaining when determining if there are any spaces left
1016
-     *                               Because if all tickets attached to this datetime have no spaces left,
1017
-     *                               then this datetime IS effectively sold out.
1018
-     *                               However, there are cases where we just want to know the spaces
1019
-     *                               remaining for this particular datetime, hence the flag.
1020
-     * @return int
1021
-     * @throws ReflectionException
1022
-     * @throws InvalidArgumentException
1023
-     * @throws InvalidInterfaceException
1024
-     * @throws InvalidDataTypeException
1025
-     * @throws EE_Error
1026
-     */
1027
-    public function spaces_remaining($consider_tickets = false)
1028
-    {
1029
-        // tickets remaining available for purchase
1030
-        // no need for special checks for infinite, because if DTT_reg_limit == EE_INF, then EE_INF - x = EE_INF
1031
-        $dtt_remaining = $this->reg_limit() - $this->sold_and_reserved();
1032
-        if (! $consider_tickets) {
1033
-            return $dtt_remaining;
1034
-        }
1035
-        $tickets_remaining = $this->tickets_remaining();
1036
-        return min($dtt_remaining, $tickets_remaining);
1037
-    }
1038
-
1039
-
1040
-    /**
1041
-     * Counts the total tickets available
1042
-     * (from all the different types of tickets which are available for this datetime).
1043
-     *
1044
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1045
-     * @return int
1046
-     * @throws ReflectionException
1047
-     * @throws InvalidArgumentException
1048
-     * @throws InvalidInterfaceException
1049
-     * @throws InvalidDataTypeException
1050
-     * @throws EE_Error
1051
-     */
1052
-    public function tickets_remaining($query_params = array())
1053
-    {
1054
-        $sum = 0;
1055
-        $tickets = $this->tickets($query_params);
1056
-        if (! empty($tickets)) {
1057
-            foreach ($tickets as $ticket) {
1058
-                if ($ticket instanceof EE_Ticket) {
1059
-                    // get the actual amount of tickets that can be sold
1060
-                    $qty = $ticket->qty('saleable');
1061
-                    if ($qty === EE_INF) {
1062
-                        return EE_INF;
1063
-                    }
1064
-                    // no negative ticket quantities plz
1065
-                    if ($qty > 0) {
1066
-                        $sum += $qty;
1067
-                    }
1068
-                }
1069
-            }
1070
-        }
1071
-        return $sum;
1072
-    }
1073
-
1074
-
1075
-    /**
1076
-     * Gets the count of all the tickets available at this datetime (not ticket types)
1077
-     * before any were sold
1078
-     *
1079
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1080
-     * @return int
1081
-     * @throws ReflectionException
1082
-     * @throws InvalidArgumentException
1083
-     * @throws InvalidInterfaceException
1084
-     * @throws InvalidDataTypeException
1085
-     * @throws EE_Error
1086
-     */
1087
-    public function sum_tickets_initially_available($query_params = array())
1088
-    {
1089
-        return $this->sum_related('Ticket', $query_params, 'TKT_qty');
1090
-    }
1091
-
1092
-
1093
-    /**
1094
-     * Returns the lesser-of-the two: spaces remaining at this datetime, or
1095
-     * the total tickets remaining (a sum of the tickets remaining for each ticket type
1096
-     * that is available for this datetime).
1097
-     *
1098
-     * @return int
1099
-     * @throws ReflectionException
1100
-     * @throws InvalidArgumentException
1101
-     * @throws InvalidInterfaceException
1102
-     * @throws InvalidDataTypeException
1103
-     * @throws EE_Error
1104
-     */
1105
-    public function total_tickets_available_at_this_datetime()
1106
-    {
1107
-        return $this->spaces_remaining(true);
1108
-    }
1109
-
1110
-
1111
-    /**
1112
-     * This simply compares the internal dtt for the given string with NOW
1113
-     * and determines if the date is upcoming or not.
1114
-     *
1115
-     * @access public
1116
-     * @return boolean
1117
-     * @throws ReflectionException
1118
-     * @throws InvalidArgumentException
1119
-     * @throws InvalidInterfaceException
1120
-     * @throws InvalidDataTypeException
1121
-     * @throws EE_Error
1122
-     */
1123
-    public function is_upcoming()
1124
-    {
1125
-        return ($this->get_raw('DTT_EVT_start') > time());
1126
-    }
1127
-
1128
-
1129
-    /**
1130
-     * This simply compares the internal datetime for the given string with NOW
1131
-     * and returns if the date is active (i.e. start and end time)
1132
-     *
1133
-     * @return boolean
1134
-     * @throws ReflectionException
1135
-     * @throws InvalidArgumentException
1136
-     * @throws InvalidInterfaceException
1137
-     * @throws InvalidDataTypeException
1138
-     * @throws EE_Error
1139
-     */
1140
-    public function is_active()
1141
-    {
1142
-        return ($this->get_raw('DTT_EVT_start') < time() && $this->get_raw('DTT_EVT_end') > time());
1143
-    }
1144
-
1145
-
1146
-    /**
1147
-     * This simply compares the internal dtt for the given string with NOW
1148
-     * and determines if the date is expired or not.
1149
-     *
1150
-     * @return boolean
1151
-     * @throws ReflectionException
1152
-     * @throws InvalidArgumentException
1153
-     * @throws InvalidInterfaceException
1154
-     * @throws InvalidDataTypeException
1155
-     * @throws EE_Error
1156
-     */
1157
-    public function is_expired()
1158
-    {
1159
-        return ($this->get_raw('DTT_EVT_end') < time());
1160
-    }
1161
-
1162
-
1163
-    /**
1164
-     * This returns the active status for whether an event is active, upcoming, or expired
1165
-     *
1166
-     * @return int return value will be one of the EE_Datetime status constants.
1167
-     * @throws ReflectionException
1168
-     * @throws InvalidArgumentException
1169
-     * @throws InvalidInterfaceException
1170
-     * @throws InvalidDataTypeException
1171
-     * @throws EE_Error
1172
-     */
1173
-    public function get_active_status()
1174
-    {
1175
-        $total_tickets_for_this_dtt = $this->total_tickets_available_at_this_datetime();
1176
-        if ($total_tickets_for_this_dtt !== false && $total_tickets_for_this_dtt < 1) {
1177
-            return EE_Datetime::sold_out;
1178
-        }
1179
-        if ($this->is_expired()) {
1180
-            return EE_Datetime::expired;
1181
-        }
1182
-        if ($this->is_upcoming()) {
1183
-            return EE_Datetime::upcoming;
1184
-        }
1185
-        if ($this->is_active()) {
1186
-            return EE_Datetime::active;
1187
-        }
1188
-        return null;
1189
-    }
1190
-
1191
-
1192
-    /**
1193
-     * This returns a nice display name for the datetime that is contingent on the span between the dates and times.
1194
-     *
1195
-     * @param  boolean $use_dtt_name if TRUE then we'll use DTT->name() if its not empty.
1196
-     * @return string
1197
-     * @throws ReflectionException
1198
-     * @throws InvalidArgumentException
1199
-     * @throws InvalidInterfaceException
1200
-     * @throws InvalidDataTypeException
1201
-     * @throws EE_Error
1202
-     */
1203
-    public function get_dtt_display_name($use_dtt_name = false)
1204
-    {
1205
-        if ($use_dtt_name) {
1206
-            $dtt_name = $this->name();
1207
-            if (! empty($dtt_name)) {
1208
-                return $dtt_name;
1209
-            }
1210
-        }
1211
-        // first condition is to see if the months are different
1212
-        if (date('m', $this->get_raw('DTT_EVT_start')) !== date('m', $this->get_raw('DTT_EVT_end'))
1213
-        ) {
1214
-            $display_date = $this->start_date('M j\, Y g:i a') . ' - ' . $this->end_date('M j\, Y g:i a');
1215
-            // next condition is if its the same month but different day
1216
-        } else {
1217
-            if (date('m', $this->get_raw('DTT_EVT_start')) === date('m', $this->get_raw('DTT_EVT_end'))
1218
-                && date('d', $this->get_raw('DTT_EVT_start')) !== date('d', $this->get_raw('DTT_EVT_end'))
1219
-            ) {
1220
-                $display_date = $this->start_date('M j\, g:i a') . ' - ' . $this->end_date('M j\, g:i a Y');
1221
-            } else {
1222
-                $display_date = $this->start_date('F j\, Y')
1223
-                                . ' @ '
1224
-                                . $this->start_date('g:i a')
1225
-                                . ' - '
1226
-                                . $this->end_date('g:i a');
1227
-            }
1228
-        }
1229
-        return $display_date;
1230
-    }
1231
-
1232
-
1233
-    /**
1234
-     * Gets all the tickets for this datetime
1235
-     *
1236
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1237
-     * @return EE_Base_Class[]|EE_Ticket[]
1238
-     * @throws ReflectionException
1239
-     * @throws InvalidArgumentException
1240
-     * @throws InvalidInterfaceException
1241
-     * @throws InvalidDataTypeException
1242
-     * @throws EE_Error
1243
-     */
1244
-    public function tickets($query_params = array())
1245
-    {
1246
-        return $this->get_many_related('Ticket', $query_params);
1247
-    }
1248
-
1249
-
1250
-    /**
1251
-     * Gets all the ticket types currently available for purchase
1252
-     *
1253
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1254
-     * @return EE_Ticket[]
1255
-     * @throws ReflectionException
1256
-     * @throws InvalidArgumentException
1257
-     * @throws InvalidInterfaceException
1258
-     * @throws InvalidDataTypeException
1259
-     * @throws EE_Error
1260
-     */
1261
-    public function ticket_types_available_for_purchase($query_params = array())
1262
-    {
1263
-        // first check if datetime is valid
1264
-        if ($this->sold_out() || ! ($this->is_upcoming() || $this->is_active())) {
1265
-            return array();
1266
-        }
1267
-        if (empty($query_params)) {
1268
-            $query_params = array(
1269
-                array(
1270
-                    'TKT_start_date' => array('<=', EEM_Ticket::instance()->current_time_for_query('TKT_start_date')),
1271
-                    'TKT_end_date'   => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
1272
-                    'TKT_deleted'    => false,
1273
-                ),
1274
-            );
1275
-        }
1276
-        return $this->tickets($query_params);
1277
-    }
1278
-
1279
-
1280
-    /**
1281
-     * @return EE_Base_Class|EE_Event
1282
-     * @throws ReflectionException
1283
-     * @throws InvalidArgumentException
1284
-     * @throws InvalidInterfaceException
1285
-     * @throws InvalidDataTypeException
1286
-     * @throws EE_Error
1287
-     */
1288
-    public function event()
1289
-    {
1290
-        return $this->get_first_related('Event');
1291
-    }
1292
-
1293
-
1294
-    /**
1295
-     * Updates the DTT_sold attribute (and saves) based on the number of registrations for this datetime
1296
-     * (via the tickets).
1297
-     *
1298
-     * @return int
1299
-     * @throws ReflectionException
1300
-     * @throws InvalidArgumentException
1301
-     * @throws InvalidInterfaceException
1302
-     * @throws InvalidDataTypeException
1303
-     * @throws EE_Error
1304
-     */
1305
-    public function update_sold()
1306
-    {
1307
-        $count_regs_for_this_datetime = EEM_Registration::instance()->count(
1308
-            array(
1309
-                array(
1310
-                    'STS_ID'                 => EEM_Registration::status_id_approved,
1311
-                    'REG_deleted'            => 0,
1312
-                    'Ticket.Datetime.DTT_ID' => $this->ID(),
1313
-                ),
1314
-            )
1315
-        );
1316
-        $this->set_sold($count_regs_for_this_datetime);
1317
-        $this->save();
1318
-        return $count_regs_for_this_datetime;
1319
-    }
1320
-
1321
-
1322
-    /*******************************************************************
16
+	/**
17
+	 * constant used by get_active_status, indicates datetime has no more available spaces
18
+	 */
19
+	const sold_out = 'DTS';
20
+
21
+	/**
22
+	 * constant used by get_active_status, indicating datetime is still active (even is not over, can be registered-for)
23
+	 */
24
+	const active = 'DTA';
25
+
26
+	/**
27
+	 * constant used by get_active_status, indicating the datetime cannot be used for registrations yet, but has not
28
+	 * expired
29
+	 */
30
+	const upcoming = 'DTU';
31
+
32
+	/**
33
+	 * Datetime is postponed
34
+	 */
35
+	const postponed = 'DTP';
36
+
37
+	/**
38
+	 * Datetime is cancelled
39
+	 */
40
+	const cancelled = 'DTC';
41
+
42
+	/**
43
+	 * constant used by get_active_status, indicates datetime has expired (event is over)
44
+	 */
45
+	const expired = 'DTE';
46
+
47
+	/**
48
+	 * constant used in various places indicating that an event is INACTIVE (not yet ready to be published)
49
+	 */
50
+	const inactive = 'DTI';
51
+
52
+
53
+	/**
54
+	 * @param array  $props_n_values    incoming values
55
+	 * @param string $timezone          incoming timezone (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 date_format
57
+	 *                                  and the second value is the time format
58
+	 * @return EE_Datetime
59
+	 * @throws ReflectionException
60
+	 * @throws InvalidArgumentException
61
+	 * @throws InvalidInterfaceException
62
+	 * @throws InvalidDataTypeException
63
+	 * @throws EE_Error
64
+	 */
65
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
66
+	{
67
+		$has_object = parent::_check_for_object(
68
+			$props_n_values,
69
+			__CLASS__,
70
+			$timezone,
71
+			$date_formats
72
+		);
73
+		return $has_object
74
+			? $has_object
75
+			: new self($props_n_values, false, $timezone, $date_formats);
76
+	}
77
+
78
+
79
+	/**
80
+	 * @param array  $props_n_values  incoming values from the database
81
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
82
+	 *                                the website will be used.
83
+	 * @return EE_Datetime
84
+	 * @throws ReflectionException
85
+	 * @throws InvalidArgumentException
86
+	 * @throws InvalidInterfaceException
87
+	 * @throws InvalidDataTypeException
88
+	 * @throws EE_Error
89
+	 */
90
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
91
+	{
92
+		return new self($props_n_values, true, $timezone);
93
+	}
94
+
95
+
96
+	/**
97
+	 * @param $name
98
+	 * @throws ReflectionException
99
+	 * @throws InvalidArgumentException
100
+	 * @throws InvalidInterfaceException
101
+	 * @throws InvalidDataTypeException
102
+	 * @throws EE_Error
103
+	 */
104
+	public function set_name($name)
105
+	{
106
+		$this->set('DTT_name', $name);
107
+	}
108
+
109
+
110
+	/**
111
+	 * @param $description
112
+	 * @throws ReflectionException
113
+	 * @throws InvalidArgumentException
114
+	 * @throws InvalidInterfaceException
115
+	 * @throws InvalidDataTypeException
116
+	 * @throws EE_Error
117
+	 */
118
+	public function set_description($description)
119
+	{
120
+		$this->set('DTT_description', $description);
121
+	}
122
+
123
+
124
+	/**
125
+	 * Set event start date
126
+	 * set the start date for an event
127
+	 *
128
+	 * @param string $date a string representation of the event's date ex:  Dec. 25, 2025 or 12-25-2025
129
+	 * @throws ReflectionException
130
+	 * @throws InvalidArgumentException
131
+	 * @throws InvalidInterfaceException
132
+	 * @throws InvalidDataTypeException
133
+	 * @throws EE_Error
134
+	 */
135
+	public function set_start_date($date)
136
+	{
137
+		$this->_set_date_for($date, 'DTT_EVT_start');
138
+	}
139
+
140
+
141
+	/**
142
+	 * Set event start time
143
+	 * set the start time for an event
144
+	 *
145
+	 * @param string $time a string representation of the event time ex:  9am  or  7:30 PM
146
+	 * @throws ReflectionException
147
+	 * @throws InvalidArgumentException
148
+	 * @throws InvalidInterfaceException
149
+	 * @throws InvalidDataTypeException
150
+	 * @throws EE_Error
151
+	 */
152
+	public function set_start_time($time)
153
+	{
154
+		$this->_set_time_for($time, 'DTT_EVT_start');
155
+	}
156
+
157
+
158
+	/**
159
+	 * Set event end date
160
+	 * set the end date for an event
161
+	 *
162
+	 * @param string $date a string representation of the event's date ex:  Dec. 25, 2025 or 12-25-2025
163
+	 * @throws ReflectionException
164
+	 * @throws InvalidArgumentException
165
+	 * @throws InvalidInterfaceException
166
+	 * @throws InvalidDataTypeException
167
+	 * @throws EE_Error
168
+	 */
169
+	public function set_end_date($date)
170
+	{
171
+		$this->_set_date_for($date, 'DTT_EVT_end');
172
+	}
173
+
174
+
175
+	/**
176
+	 * Set event end time
177
+	 * set the end time for an event
178
+	 *
179
+	 * @param string $time a string representation of the event time ex:  9am  or  7:30 PM
180
+	 * @throws ReflectionException
181
+	 * @throws InvalidArgumentException
182
+	 * @throws InvalidInterfaceException
183
+	 * @throws InvalidDataTypeException
184
+	 * @throws EE_Error
185
+	 */
186
+	public function set_end_time($time)
187
+	{
188
+		$this->_set_time_for($time, 'DTT_EVT_end');
189
+	}
190
+
191
+
192
+	/**
193
+	 * Set registration limit
194
+	 * set the maximum number of attendees that can be registered for this datetime slot
195
+	 *
196
+	 * @param int $reg_limit
197
+	 * @throws ReflectionException
198
+	 * @throws InvalidArgumentException
199
+	 * @throws InvalidInterfaceException
200
+	 * @throws InvalidDataTypeException
201
+	 * @throws EE_Error
202
+	 */
203
+	public function set_reg_limit($reg_limit)
204
+	{
205
+		$this->set('DTT_reg_limit', $reg_limit);
206
+	}
207
+
208
+
209
+	/**
210
+	 * get the number of tickets sold for this datetime slot
211
+	 *
212
+	 * @return mixed int on success, FALSE on fail
213
+	 * @throws ReflectionException
214
+	 * @throws InvalidArgumentException
215
+	 * @throws InvalidInterfaceException
216
+	 * @throws InvalidDataTypeException
217
+	 * @throws EE_Error
218
+	 */
219
+	public function sold()
220
+	{
221
+		return $this->get_raw('DTT_sold');
222
+	}
223
+
224
+
225
+	/**
226
+	 * @param int $sold
227
+	 * @throws ReflectionException
228
+	 * @throws InvalidArgumentException
229
+	 * @throws InvalidInterfaceException
230
+	 * @throws InvalidDataTypeException
231
+	 * @throws EE_Error
232
+	 */
233
+	public function set_sold($sold)
234
+	{
235
+		// sold can not go below zero
236
+		$sold = max(0, $sold);
237
+		$this->set('DTT_sold', $sold);
238
+	}
239
+
240
+
241
+	/**
242
+	 * Increments sold by amount passed by $qty, and persists it immediately to the database.
243
+	 * Simultaneously decreases the reserved count, unless $also_decrease_reserved is false.
244
+	 *
245
+	 * @param int $qty
246
+	 * @param boolean $also_decrease_reserved
247
+	 * @return boolean indicating success
248
+	 * @throws ReflectionException
249
+	 * @throws InvalidArgumentException
250
+	 * @throws InvalidInterfaceException
251
+	 * @throws InvalidDataTypeException
252
+	 * @throws EE_Error
253
+	 */
254
+	public function increaseSold($qty = 1, $also_decrease_reserved = true)
255
+	{
256
+		$qty = absint($qty);
257
+		if ($also_decrease_reserved) {
258
+			$success = $this->adjustNumericFieldsInDb(
259
+				[
260
+					'DTT_reserved' => $qty * -1,
261
+					'DTT_sold' => $qty
262
+				]
263
+			);
264
+		} else {
265
+			$success = $this->adjustNumericFieldsInDb(
266
+				[
267
+					'DTT_sold' => $qty
268
+				]
269
+			);
270
+		}
271
+
272
+		do_action(
273
+			'AHEE__EE_Datetime__increase_sold',
274
+			$this,
275
+			$qty,
276
+			$this->sold(),
277
+			$success
278
+		);
279
+		return $success;
280
+	}
281
+
282
+
283
+	/**
284
+	 * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need
285
+	 * to save afterwards.)
286
+	 *
287
+	 * @param int $qty
288
+	 * @return boolean indicating success
289
+	 * @throws ReflectionException
290
+	 * @throws InvalidArgumentException
291
+	 * @throws InvalidInterfaceException
292
+	 * @throws InvalidDataTypeException
293
+	 * @throws EE_Error
294
+	 */
295
+	public function decreaseSold($qty = 1)
296
+	{
297
+		$qty = absint($qty);
298
+		$success = $this->adjustNumericFieldsInDb(
299
+			[
300
+				'DTT_sold' => $qty * -1
301
+			]
302
+		);
303
+		do_action(
304
+			'AHEE__EE_Datetime__decrease_sold',
305
+			$this,
306
+			$qty,
307
+			$this->sold(),
308
+			$success
309
+		);
310
+		return $success;
311
+	}
312
+
313
+
314
+	/**
315
+	 * Gets qty of reserved tickets for this datetime
316
+	 *
317
+	 * @return int
318
+	 * @throws ReflectionException
319
+	 * @throws InvalidArgumentException
320
+	 * @throws InvalidInterfaceException
321
+	 * @throws InvalidDataTypeException
322
+	 * @throws EE_Error
323
+	 */
324
+	public function reserved()
325
+	{
326
+		return $this->get_raw('DTT_reserved');
327
+	}
328
+
329
+
330
+	/**
331
+	 * Sets qty of reserved tickets for this datetime
332
+	 *
333
+	 * @param int $reserved
334
+	 * @throws ReflectionException
335
+	 * @throws InvalidArgumentException
336
+	 * @throws InvalidInterfaceException
337
+	 * @throws InvalidDataTypeException
338
+	 * @throws EE_Error
339
+	 */
340
+	public function set_reserved($reserved)
341
+	{
342
+		// reserved can not go below zero
343
+		$reserved = max(0, (int) $reserved);
344
+		$this->set('DTT_reserved', $reserved);
345
+	}
346
+
347
+
348
+	/**
349
+	 * Increments reserved by amount passed by $qty, and persists it immediately to the database.
350
+	 *
351
+	 * @param int $qty
352
+	 * @return boolean indicating success
353
+	 * @throws ReflectionException
354
+	 * @throws InvalidArgumentException
355
+	 * @throws InvalidInterfaceException
356
+	 * @throws InvalidDataTypeException
357
+	 * @throws EE_Error
358
+	 */
359
+	public function increaseReserved($qty = 1)
360
+	{
361
+		$qty = absint($qty);
362
+		$success = $this->incrementFieldConditionallyInDb(
363
+			'DTT_reserved',
364
+			'DTT_sold',
365
+			'DTT_reg_limit',
366
+			$qty
367
+		);
368
+		do_action(
369
+			'AHEE__EE_Datetime__increase_reserved',
370
+			$this,
371
+			$qty,
372
+			$this->reserved(),
373
+			$success
374
+		);
375
+		return $success;
376
+	}
377
+
378
+
379
+	/**
380
+	 * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
381
+	 *
382
+	 * @param int $qty
383
+	 * @return boolean indicating success
384
+	 * @throws ReflectionException
385
+	 * @throws InvalidArgumentException
386
+	 * @throws InvalidInterfaceException
387
+	 * @throws InvalidDataTypeException
388
+	 * @throws EE_Error
389
+	 */
390
+	public function decreaseReserved($qty = 1)
391
+	{
392
+		$qty = absint($qty);
393
+		$success = $this->adjustNumericFieldsInDb(
394
+			[
395
+				'DTT_reserved' => $qty * -1
396
+			]
397
+		);
398
+		do_action(
399
+			'AHEE__EE_Datetime__decrease_reserved',
400
+			$this,
401
+			$qty,
402
+			$this->reserved(),
403
+			$success
404
+		);
405
+		return $success;
406
+	}
407
+
408
+
409
+	/**
410
+	 * total sold and reserved tickets
411
+	 *
412
+	 * @return int
413
+	 * @throws ReflectionException
414
+	 * @throws InvalidArgumentException
415
+	 * @throws InvalidInterfaceException
416
+	 * @throws InvalidDataTypeException
417
+	 * @throws EE_Error
418
+	 */
419
+	public function sold_and_reserved()
420
+	{
421
+		return $this->sold() + $this->reserved();
422
+	}
423
+
424
+
425
+	/**
426
+	 * returns the datetime name
427
+	 *
428
+	 * @return string
429
+	 * @throws ReflectionException
430
+	 * @throws InvalidArgumentException
431
+	 * @throws InvalidInterfaceException
432
+	 * @throws InvalidDataTypeException
433
+	 * @throws EE_Error
434
+	 */
435
+	public function name()
436
+	{
437
+		return $this->get('DTT_name');
438
+	}
439
+
440
+
441
+	/**
442
+	 * returns the datetime description
443
+	 *
444
+	 * @return string
445
+	 * @throws ReflectionException
446
+	 * @throws InvalidArgumentException
447
+	 * @throws InvalidInterfaceException
448
+	 * @throws InvalidDataTypeException
449
+	 * @throws EE_Error
450
+	 */
451
+	public function description()
452
+	{
453
+		return $this->get('DTT_description');
454
+	}
455
+
456
+
457
+	/**
458
+	 * This helper simply returns whether the event_datetime for the current datetime is a primary datetime
459
+	 *
460
+	 * @return boolean  TRUE if is primary, FALSE if not.
461
+	 * @throws ReflectionException
462
+	 * @throws InvalidArgumentException
463
+	 * @throws InvalidInterfaceException
464
+	 * @throws InvalidDataTypeException
465
+	 * @throws EE_Error
466
+	 */
467
+	public function is_primary()
468
+	{
469
+		return $this->get('DTT_is_primary');
470
+	}
471
+
472
+
473
+	/**
474
+	 * This helper simply returns the order for the datetime
475
+	 *
476
+	 * @return int  The order of the datetime for this event.
477
+	 * @throws ReflectionException
478
+	 * @throws InvalidArgumentException
479
+	 * @throws InvalidInterfaceException
480
+	 * @throws InvalidDataTypeException
481
+	 * @throws EE_Error
482
+	 */
483
+	public function order()
484
+	{
485
+		return $this->get('DTT_order');
486
+	}
487
+
488
+
489
+	/**
490
+	 * This helper simply returns the parent id for the datetime
491
+	 *
492
+	 * @return int
493
+	 * @throws ReflectionException
494
+	 * @throws InvalidArgumentException
495
+	 * @throws InvalidInterfaceException
496
+	 * @throws InvalidDataTypeException
497
+	 * @throws EE_Error
498
+	 */
499
+	public function parent()
500
+	{
501
+		return $this->get('DTT_parent');
502
+	}
503
+
504
+
505
+	/**
506
+	 * show date and/or time
507
+	 *
508
+	 * @param string $date_or_time    whether to display a date or time or both
509
+	 * @param string $start_or_end    whether to display start or end datetimes
510
+	 * @param string $dt_frmt
511
+	 * @param string $tm_frmt
512
+	 * @param bool   $echo            whether we echo or return (note echoing uses "pretty" formats,
513
+	 *                                otherwise we use the standard formats)
514
+	 * @return string|bool  string on success, FALSE on fail
515
+	 * @throws ReflectionException
516
+	 * @throws InvalidArgumentException
517
+	 * @throws InvalidInterfaceException
518
+	 * @throws InvalidDataTypeException
519
+	 * @throws EE_Error
520
+	 */
521
+	private function _show_datetime(
522
+		$date_or_time = null,
523
+		$start_or_end = 'start',
524
+		$dt_frmt = '',
525
+		$tm_frmt = '',
526
+		$echo = false
527
+	) {
528
+		$field_name = "DTT_EVT_{$start_or_end}";
529
+		$dtt = $this->_get_datetime(
530
+			$field_name,
531
+			$dt_frmt,
532
+			$tm_frmt,
533
+			$date_or_time,
534
+			$echo
535
+		);
536
+		if (! $echo) {
537
+			return $dtt;
538
+		}
539
+		return '';
540
+	}
541
+
542
+
543
+	/**
544
+	 * get event start date.  Provide either the date format, or NULL to re-use the
545
+	 * last-used format, or '' to use the default date format
546
+	 *
547
+	 * @param string $dt_frmt string representation of date format defaults to 'F j, Y'
548
+	 * @return mixed            string on success, FALSE on fail
549
+	 * @throws ReflectionException
550
+	 * @throws InvalidArgumentException
551
+	 * @throws InvalidInterfaceException
552
+	 * @throws InvalidDataTypeException
553
+	 * @throws EE_Error
554
+	 */
555
+	public function start_date($dt_frmt = '')
556
+	{
557
+		return $this->_show_datetime('D', 'start', $dt_frmt);
558
+	}
559
+
560
+
561
+	/**
562
+	 * Echoes start_date()
563
+	 *
564
+	 * @param string $dt_frmt
565
+	 * @throws ReflectionException
566
+	 * @throws InvalidArgumentException
567
+	 * @throws InvalidInterfaceException
568
+	 * @throws InvalidDataTypeException
569
+	 * @throws EE_Error
570
+	 */
571
+	public function e_start_date($dt_frmt = '')
572
+	{
573
+		$this->_show_datetime('D', 'start', $dt_frmt, null, true);
574
+	}
575
+
576
+
577
+	/**
578
+	 * get end date. Provide either the date format, or NULL to re-use the
579
+	 * last-used format, or '' to use the default date format
580
+	 *
581
+	 * @param string $dt_frmt string representation of date format defaults to 'F j, Y'
582
+	 * @return mixed            string on success, FALSE on fail
583
+	 * @throws ReflectionException
584
+	 * @throws InvalidArgumentException
585
+	 * @throws InvalidInterfaceException
586
+	 * @throws InvalidDataTypeException
587
+	 * @throws EE_Error
588
+	 */
589
+	public function end_date($dt_frmt = '')
590
+	{
591
+		return $this->_show_datetime('D', 'end', $dt_frmt);
592
+	}
593
+
594
+
595
+	/**
596
+	 * Echoes the end date. See end_date()
597
+	 *
598
+	 * @param string $dt_frmt
599
+	 * @throws ReflectionException
600
+	 * @throws InvalidArgumentException
601
+	 * @throws InvalidInterfaceException
602
+	 * @throws InvalidDataTypeException
603
+	 * @throws EE_Error
604
+	 */
605
+	public function e_end_date($dt_frmt = '')
606
+	{
607
+		$this->_show_datetime('D', 'end', $dt_frmt, null, true);
608
+	}
609
+
610
+
611
+	/**
612
+	 * get date_range - meaning the start AND end date
613
+	 *
614
+	 * @access public
615
+	 * @param string $dt_frmt     string representation of date format defaults to WP settings
616
+	 * @param string $conjunction conjunction junction what's your function ?
617
+	 *                            this string joins the start date with the end date ie: Jan 01 "to" Dec 31
618
+	 * @return mixed              string on success, FALSE on fail
619
+	 * @throws ReflectionException
620
+	 * @throws InvalidArgumentException
621
+	 * @throws InvalidInterfaceException
622
+	 * @throws InvalidDataTypeException
623
+	 * @throws EE_Error
624
+	 */
625
+	public function date_range($dt_frmt = '', $conjunction = ' - ')
626
+	{
627
+		$dt_frmt = ! empty($dt_frmt) ? $dt_frmt : $this->_dt_frmt;
628
+		$start = str_replace(
629
+			' ',
630
+			'&nbsp;',
631
+			$this->get_i18n_datetime('DTT_EVT_start', $dt_frmt)
632
+		);
633
+		$end = str_replace(
634
+			' ',
635
+			'&nbsp;',
636
+			$this->get_i18n_datetime('DTT_EVT_end', $dt_frmt)
637
+		);
638
+		return $start !== $end ? $start . $conjunction . $end : $start;
639
+	}
640
+
641
+
642
+	/**
643
+	 * @param string $dt_frmt
644
+	 * @param string $conjunction
645
+	 * @throws ReflectionException
646
+	 * @throws InvalidArgumentException
647
+	 * @throws InvalidInterfaceException
648
+	 * @throws InvalidDataTypeException
649
+	 * @throws EE_Error
650
+	 */
651
+	public function e_date_range($dt_frmt = '', $conjunction = ' - ')
652
+	{
653
+		echo $this->date_range($dt_frmt, $conjunction);
654
+	}
655
+
656
+
657
+	/**
658
+	 * get start time
659
+	 *
660
+	 * @param string $tm_format - string representation of time format defaults to 'g:i a'
661
+	 * @return mixed        string on success, FALSE on fail
662
+	 * @throws ReflectionException
663
+	 * @throws InvalidArgumentException
664
+	 * @throws InvalidInterfaceException
665
+	 * @throws InvalidDataTypeException
666
+	 * @throws EE_Error
667
+	 */
668
+	public function start_time($tm_format = '')
669
+	{
670
+		return $this->_show_datetime('T', 'start', null, $tm_format);
671
+	}
672
+
673
+
674
+	/**
675
+	 * @param string $tm_format
676
+	 * @throws ReflectionException
677
+	 * @throws InvalidArgumentException
678
+	 * @throws InvalidInterfaceException
679
+	 * @throws InvalidDataTypeException
680
+	 * @throws EE_Error
681
+	 */
682
+	public function e_start_time($tm_format = '')
683
+	{
684
+		$this->_show_datetime('T', 'start', null, $tm_format, true);
685
+	}
686
+
687
+
688
+	/**
689
+	 * get end time
690
+	 *
691
+	 * @param string $tm_format string representation of time format defaults to 'g:i a'
692
+	 * @return mixed                string on success, FALSE on fail
693
+	 * @throws ReflectionException
694
+	 * @throws InvalidArgumentException
695
+	 * @throws InvalidInterfaceException
696
+	 * @throws InvalidDataTypeException
697
+	 * @throws EE_Error
698
+	 */
699
+	public function end_time($tm_format = '')
700
+	{
701
+		return $this->_show_datetime('T', 'end', null, $tm_format);
702
+	}
703
+
704
+
705
+	/**
706
+	 * @param string $tm_format
707
+	 * @throws ReflectionException
708
+	 * @throws InvalidArgumentException
709
+	 * @throws InvalidInterfaceException
710
+	 * @throws InvalidDataTypeException
711
+	 * @throws EE_Error
712
+	 */
713
+	public function e_end_time($tm_format = '')
714
+	{
715
+		$this->_show_datetime('T', 'end', null, $tm_format, true);
716
+	}
717
+
718
+
719
+	/**
720
+	 * get time_range
721
+	 *
722
+	 * @access public
723
+	 * @param string $tm_format   string representation of time format defaults to 'g:i a'
724
+	 * @param string $conjunction conjunction junction what's your function ?
725
+	 *                            this string joins the start date with the end date ie: Jan 01 "to" Dec 31
726
+	 * @return mixed              string on success, FALSE on fail
727
+	 * @throws ReflectionException
728
+	 * @throws InvalidArgumentException
729
+	 * @throws InvalidInterfaceException
730
+	 * @throws InvalidDataTypeException
731
+	 * @throws EE_Error
732
+	 */
733
+	public function time_range($tm_format = '', $conjunction = ' - ')
734
+	{
735
+		$tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
736
+		$start = str_replace(
737
+			' ',
738
+			'&nbsp;',
739
+			$this->get_i18n_datetime('DTT_EVT_start', $tm_format)
740
+		);
741
+		$end = str_replace(
742
+			' ',
743
+			'&nbsp;',
744
+			$this->get_i18n_datetime('DTT_EVT_end', $tm_format)
745
+		);
746
+		return $start !== $end ? $start . $conjunction . $end : $start;
747
+	}
748
+
749
+
750
+	/**
751
+	 * @param string $tm_format
752
+	 * @param string $conjunction
753
+	 * @throws ReflectionException
754
+	 * @throws InvalidArgumentException
755
+	 * @throws InvalidInterfaceException
756
+	 * @throws InvalidDataTypeException
757
+	 * @throws EE_Error
758
+	 */
759
+	public function e_time_range($tm_format = '', $conjunction = ' - ')
760
+	{
761
+		echo $this->time_range($tm_format, $conjunction);
762
+	}
763
+
764
+
765
+	/**
766
+	 * This returns a range representation of the date and times.
767
+	 * Output is dependent on the difference (or similarity) between DTT_EVT_start and DTT_EVT_end.
768
+	 * Also, the return value is localized.
769
+	 *
770
+	 * @param string $dt_format
771
+	 * @param string $tm_format
772
+	 * @param string $conjunction used between two different dates or times.
773
+	 *                            ex: Dec 1{$conjunction}}Dec 6, or 2pm{$conjunction}3pm
774
+	 * @param string $separator   used between the date and time formats.
775
+	 *                            ex: Dec 1, 2016{$separator}2pm
776
+	 * @return string
777
+	 * @throws ReflectionException
778
+	 * @throws InvalidArgumentException
779
+	 * @throws InvalidInterfaceException
780
+	 * @throws InvalidDataTypeException
781
+	 * @throws EE_Error
782
+	 */
783
+	public function date_and_time_range(
784
+		$dt_format = '',
785
+		$tm_format = '',
786
+		$conjunction = ' - ',
787
+		$separator = ' '
788
+	) {
789
+		$dt_format = ! empty($dt_format) ? $dt_format : $this->_dt_frmt;
790
+		$tm_format = ! empty($tm_format) ? $tm_format : $this->_tm_frmt;
791
+		$full_format = $dt_format . $separator . $tm_format;
792
+		// the range output depends on various conditions
793
+		switch (true) {
794
+			// start date timestamp and end date timestamp are the same.
795
+			case ($this->get_raw('DTT_EVT_start') === $this->get_raw('DTT_EVT_end')):
796
+				$output = $this->get_i18n_datetime('DTT_EVT_start', $full_format);
797
+				break;
798
+			// start and end date are the same but times are different
799
+			case ($this->start_date() === $this->end_date()):
800
+				$output = $this->get_i18n_datetime('DTT_EVT_start', $full_format)
801
+						  . $conjunction
802
+						  . $this->get_i18n_datetime('DTT_EVT_end', $tm_format);
803
+				break;
804
+			// all other conditions
805
+			default:
806
+				$output = $this->get_i18n_datetime('DTT_EVT_start', $full_format)
807
+						  . $conjunction
808
+						  . $this->get_i18n_datetime('DTT_EVT_end', $full_format);
809
+				break;
810
+		}
811
+		return $output;
812
+	}
813
+
814
+
815
+	/**
816
+	 * This echos the results of date and time range.
817
+	 *
818
+	 * @see date_and_time_range() for more details on purpose.
819
+	 * @param string $dt_format
820
+	 * @param string $tm_format
821
+	 * @param string $conjunction
822
+	 * @return void
823
+	 * @throws ReflectionException
824
+	 * @throws InvalidArgumentException
825
+	 * @throws InvalidInterfaceException
826
+	 * @throws InvalidDataTypeException
827
+	 * @throws EE_Error
828
+	 */
829
+	public function e_date_and_time_range($dt_format = '', $tm_format = '', $conjunction = ' - ')
830
+	{
831
+		echo $this->date_and_time_range($dt_format, $tm_format, $conjunction);
832
+	}
833
+
834
+
835
+	/**
836
+	 * get start date and start time
837
+	 *
838
+	 * @param    string $dt_format - string representation of date format defaults to 'F j, Y'
839
+	 * @param    string $tm_format - string representation of time format defaults to 'g:i a'
840
+	 * @return    mixed    string on success, FALSE on fail
841
+	 * @throws ReflectionException
842
+	 * @throws InvalidArgumentException
843
+	 * @throws InvalidInterfaceException
844
+	 * @throws InvalidDataTypeException
845
+	 * @throws EE_Error
846
+	 */
847
+	public function start_date_and_time($dt_format = '', $tm_format = '')
848
+	{
849
+		return $this->_show_datetime('', 'start', $dt_format, $tm_format);
850
+	}
851
+
852
+
853
+	/**
854
+	 * @param string $dt_frmt
855
+	 * @param string $tm_format
856
+	 * @throws ReflectionException
857
+	 * @throws InvalidArgumentException
858
+	 * @throws InvalidInterfaceException
859
+	 * @throws InvalidDataTypeException
860
+	 * @throws EE_Error
861
+	 */
862
+	public function e_start_date_and_time($dt_frmt = '', $tm_format = '')
863
+	{
864
+		$this->_show_datetime('', 'start', $dt_frmt, $tm_format, true);
865
+	}
866
+
867
+
868
+	/**
869
+	 * Shows the length of the event (start to end time).
870
+	 * Can be shown in 'seconds','minutes','hours', or 'days'.
871
+	 * By default, rounds up. (So if you use 'days', and then event
872
+	 * only occurs for 1 hour, it will return 1 day).
873
+	 *
874
+	 * @param string $units 'seconds','minutes','hours','days'
875
+	 * @param bool   $round_up
876
+	 * @return float|int|mixed
877
+	 * @throws ReflectionException
878
+	 * @throws InvalidArgumentException
879
+	 * @throws InvalidInterfaceException
880
+	 * @throws InvalidDataTypeException
881
+	 * @throws EE_Error
882
+	 */
883
+	public function length($units = 'seconds', $round_up = false)
884
+	{
885
+		$start = $this->get_raw('DTT_EVT_start');
886
+		$end = $this->get_raw('DTT_EVT_end');
887
+		$length_in_units = $end - $start;
888
+		switch ($units) {
889
+			// NOTE: We purposefully don't use "break;" in order to chain the divisions
890
+			/** @noinspection PhpMissingBreakStatementInspection */
891
+			// phpcs:disable PSR2.ControlStructures.SwitchDeclaration.TerminatingComment
892
+			case 'days':
893
+				$length_in_units /= 24;
894
+			/** @noinspection PhpMissingBreakStatementInspection */
895
+			case 'hours':
896
+				// fall through is intentional
897
+				$length_in_units /= 60;
898
+			/** @noinspection PhpMissingBreakStatementInspection */
899
+			case 'minutes':
900
+				// fall through is intentional
901
+				$length_in_units /= 60;
902
+			case 'seconds':
903
+			default:
904
+				$length_in_units = ceil($length_in_units);
905
+		}
906
+		// phpcs:enable
907
+		if ($round_up) {
908
+			$length_in_units = max($length_in_units, 1);
909
+		}
910
+		return $length_in_units;
911
+	}
912
+
913
+
914
+	/**
915
+	 *        get end date and time
916
+	 *
917
+	 * @param string $dt_frmt   - string representation of date format defaults to 'F j, Y'
918
+	 * @param string $tm_format - string representation of time format defaults to 'g:i a'
919
+	 * @return    mixed                string on success, FALSE on fail
920
+	 * @throws ReflectionException
921
+	 * @throws InvalidArgumentException
922
+	 * @throws InvalidInterfaceException
923
+	 * @throws InvalidDataTypeException
924
+	 * @throws EE_Error
925
+	 */
926
+	public function end_date_and_time($dt_frmt = '', $tm_format = '')
927
+	{
928
+		return $this->_show_datetime('', 'end', $dt_frmt, $tm_format);
929
+	}
930
+
931
+
932
+	/**
933
+	 * @param string $dt_frmt
934
+	 * @param string $tm_format
935
+	 * @throws ReflectionException
936
+	 * @throws InvalidArgumentException
937
+	 * @throws InvalidInterfaceException
938
+	 * @throws InvalidDataTypeException
939
+	 * @throws EE_Error
940
+	 */
941
+	public function e_end_date_and_time($dt_frmt = '', $tm_format = '')
942
+	{
943
+		$this->_show_datetime('', 'end', $dt_frmt, $tm_format, true);
944
+	}
945
+
946
+
947
+	/**
948
+	 *        get start timestamp
949
+	 *
950
+	 * @return        int
951
+	 * @throws ReflectionException
952
+	 * @throws InvalidArgumentException
953
+	 * @throws InvalidInterfaceException
954
+	 * @throws InvalidDataTypeException
955
+	 * @throws EE_Error
956
+	 */
957
+	public function start()
958
+	{
959
+		return $this->get_raw('DTT_EVT_start');
960
+	}
961
+
962
+
963
+	/**
964
+	 *        get end timestamp
965
+	 *
966
+	 * @return        int
967
+	 * @throws ReflectionException
968
+	 * @throws InvalidArgumentException
969
+	 * @throws InvalidInterfaceException
970
+	 * @throws InvalidDataTypeException
971
+	 * @throws EE_Error
972
+	 */
973
+	public function end()
974
+	{
975
+		return $this->get_raw('DTT_EVT_end');
976
+	}
977
+
978
+
979
+	/**
980
+	 *    get the registration limit for this datetime slot
981
+	 *
982
+	 * @return        mixed        int on success, FALSE on fail
983
+	 * @throws ReflectionException
984
+	 * @throws InvalidArgumentException
985
+	 * @throws InvalidInterfaceException
986
+	 * @throws InvalidDataTypeException
987
+	 * @throws EE_Error
988
+	 */
989
+	public function reg_limit()
990
+	{
991
+		return $this->get_raw('DTT_reg_limit');
992
+	}
993
+
994
+
995
+	/**
996
+	 *    have the tickets sold for this datetime, met or exceed the registration limit ?
997
+	 *
998
+	 * @return        boolean
999
+	 * @throws ReflectionException
1000
+	 * @throws InvalidArgumentException
1001
+	 * @throws InvalidInterfaceException
1002
+	 * @throws InvalidDataTypeException
1003
+	 * @throws EE_Error
1004
+	 */
1005
+	public function sold_out()
1006
+	{
1007
+		return $this->reg_limit() > 0 && $this->sold() >= $this->reg_limit();
1008
+	}
1009
+
1010
+
1011
+	/**
1012
+	 * return the total number of spaces remaining at this venue.
1013
+	 * This only takes the venue's capacity into account, NOT the tickets available for sale
1014
+	 *
1015
+	 * @param bool $consider_tickets Whether to consider tickets remaining when determining if there are any spaces left
1016
+	 *                               Because if all tickets attached to this datetime have no spaces left,
1017
+	 *                               then this datetime IS effectively sold out.
1018
+	 *                               However, there are cases where we just want to know the spaces
1019
+	 *                               remaining for this particular datetime, hence the flag.
1020
+	 * @return int
1021
+	 * @throws ReflectionException
1022
+	 * @throws InvalidArgumentException
1023
+	 * @throws InvalidInterfaceException
1024
+	 * @throws InvalidDataTypeException
1025
+	 * @throws EE_Error
1026
+	 */
1027
+	public function spaces_remaining($consider_tickets = false)
1028
+	{
1029
+		// tickets remaining available for purchase
1030
+		// no need for special checks for infinite, because if DTT_reg_limit == EE_INF, then EE_INF - x = EE_INF
1031
+		$dtt_remaining = $this->reg_limit() - $this->sold_and_reserved();
1032
+		if (! $consider_tickets) {
1033
+			return $dtt_remaining;
1034
+		}
1035
+		$tickets_remaining = $this->tickets_remaining();
1036
+		return min($dtt_remaining, $tickets_remaining);
1037
+	}
1038
+
1039
+
1040
+	/**
1041
+	 * Counts the total tickets available
1042
+	 * (from all the different types of tickets which are available for this datetime).
1043
+	 *
1044
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1045
+	 * @return int
1046
+	 * @throws ReflectionException
1047
+	 * @throws InvalidArgumentException
1048
+	 * @throws InvalidInterfaceException
1049
+	 * @throws InvalidDataTypeException
1050
+	 * @throws EE_Error
1051
+	 */
1052
+	public function tickets_remaining($query_params = array())
1053
+	{
1054
+		$sum = 0;
1055
+		$tickets = $this->tickets($query_params);
1056
+		if (! empty($tickets)) {
1057
+			foreach ($tickets as $ticket) {
1058
+				if ($ticket instanceof EE_Ticket) {
1059
+					// get the actual amount of tickets that can be sold
1060
+					$qty = $ticket->qty('saleable');
1061
+					if ($qty === EE_INF) {
1062
+						return EE_INF;
1063
+					}
1064
+					// no negative ticket quantities plz
1065
+					if ($qty > 0) {
1066
+						$sum += $qty;
1067
+					}
1068
+				}
1069
+			}
1070
+		}
1071
+		return $sum;
1072
+	}
1073
+
1074
+
1075
+	/**
1076
+	 * Gets the count of all the tickets available at this datetime (not ticket types)
1077
+	 * before any were sold
1078
+	 *
1079
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1080
+	 * @return int
1081
+	 * @throws ReflectionException
1082
+	 * @throws InvalidArgumentException
1083
+	 * @throws InvalidInterfaceException
1084
+	 * @throws InvalidDataTypeException
1085
+	 * @throws EE_Error
1086
+	 */
1087
+	public function sum_tickets_initially_available($query_params = array())
1088
+	{
1089
+		return $this->sum_related('Ticket', $query_params, 'TKT_qty');
1090
+	}
1091
+
1092
+
1093
+	/**
1094
+	 * Returns the lesser-of-the two: spaces remaining at this datetime, or
1095
+	 * the total tickets remaining (a sum of the tickets remaining for each ticket type
1096
+	 * that is available for this datetime).
1097
+	 *
1098
+	 * @return int
1099
+	 * @throws ReflectionException
1100
+	 * @throws InvalidArgumentException
1101
+	 * @throws InvalidInterfaceException
1102
+	 * @throws InvalidDataTypeException
1103
+	 * @throws EE_Error
1104
+	 */
1105
+	public function total_tickets_available_at_this_datetime()
1106
+	{
1107
+		return $this->spaces_remaining(true);
1108
+	}
1109
+
1110
+
1111
+	/**
1112
+	 * This simply compares the internal dtt for the given string with NOW
1113
+	 * and determines if the date is upcoming or not.
1114
+	 *
1115
+	 * @access public
1116
+	 * @return boolean
1117
+	 * @throws ReflectionException
1118
+	 * @throws InvalidArgumentException
1119
+	 * @throws InvalidInterfaceException
1120
+	 * @throws InvalidDataTypeException
1121
+	 * @throws EE_Error
1122
+	 */
1123
+	public function is_upcoming()
1124
+	{
1125
+		return ($this->get_raw('DTT_EVT_start') > time());
1126
+	}
1127
+
1128
+
1129
+	/**
1130
+	 * This simply compares the internal datetime for the given string with NOW
1131
+	 * and returns if the date is active (i.e. start and end time)
1132
+	 *
1133
+	 * @return boolean
1134
+	 * @throws ReflectionException
1135
+	 * @throws InvalidArgumentException
1136
+	 * @throws InvalidInterfaceException
1137
+	 * @throws InvalidDataTypeException
1138
+	 * @throws EE_Error
1139
+	 */
1140
+	public function is_active()
1141
+	{
1142
+		return ($this->get_raw('DTT_EVT_start') < time() && $this->get_raw('DTT_EVT_end') > time());
1143
+	}
1144
+
1145
+
1146
+	/**
1147
+	 * This simply compares the internal dtt for the given string with NOW
1148
+	 * and determines if the date is expired or not.
1149
+	 *
1150
+	 * @return boolean
1151
+	 * @throws ReflectionException
1152
+	 * @throws InvalidArgumentException
1153
+	 * @throws InvalidInterfaceException
1154
+	 * @throws InvalidDataTypeException
1155
+	 * @throws EE_Error
1156
+	 */
1157
+	public function is_expired()
1158
+	{
1159
+		return ($this->get_raw('DTT_EVT_end') < time());
1160
+	}
1161
+
1162
+
1163
+	/**
1164
+	 * This returns the active status for whether an event is active, upcoming, or expired
1165
+	 *
1166
+	 * @return int return value will be one of the EE_Datetime status constants.
1167
+	 * @throws ReflectionException
1168
+	 * @throws InvalidArgumentException
1169
+	 * @throws InvalidInterfaceException
1170
+	 * @throws InvalidDataTypeException
1171
+	 * @throws EE_Error
1172
+	 */
1173
+	public function get_active_status()
1174
+	{
1175
+		$total_tickets_for_this_dtt = $this->total_tickets_available_at_this_datetime();
1176
+		if ($total_tickets_for_this_dtt !== false && $total_tickets_for_this_dtt < 1) {
1177
+			return EE_Datetime::sold_out;
1178
+		}
1179
+		if ($this->is_expired()) {
1180
+			return EE_Datetime::expired;
1181
+		}
1182
+		if ($this->is_upcoming()) {
1183
+			return EE_Datetime::upcoming;
1184
+		}
1185
+		if ($this->is_active()) {
1186
+			return EE_Datetime::active;
1187
+		}
1188
+		return null;
1189
+	}
1190
+
1191
+
1192
+	/**
1193
+	 * This returns a nice display name for the datetime that is contingent on the span between the dates and times.
1194
+	 *
1195
+	 * @param  boolean $use_dtt_name if TRUE then we'll use DTT->name() if its not empty.
1196
+	 * @return string
1197
+	 * @throws ReflectionException
1198
+	 * @throws InvalidArgumentException
1199
+	 * @throws InvalidInterfaceException
1200
+	 * @throws InvalidDataTypeException
1201
+	 * @throws EE_Error
1202
+	 */
1203
+	public function get_dtt_display_name($use_dtt_name = false)
1204
+	{
1205
+		if ($use_dtt_name) {
1206
+			$dtt_name = $this->name();
1207
+			if (! empty($dtt_name)) {
1208
+				return $dtt_name;
1209
+			}
1210
+		}
1211
+		// first condition is to see if the months are different
1212
+		if (date('m', $this->get_raw('DTT_EVT_start')) !== date('m', $this->get_raw('DTT_EVT_end'))
1213
+		) {
1214
+			$display_date = $this->start_date('M j\, Y g:i a') . ' - ' . $this->end_date('M j\, Y g:i a');
1215
+			// next condition is if its the same month but different day
1216
+		} else {
1217
+			if (date('m', $this->get_raw('DTT_EVT_start')) === date('m', $this->get_raw('DTT_EVT_end'))
1218
+				&& date('d', $this->get_raw('DTT_EVT_start')) !== date('d', $this->get_raw('DTT_EVT_end'))
1219
+			) {
1220
+				$display_date = $this->start_date('M j\, g:i a') . ' - ' . $this->end_date('M j\, g:i a Y');
1221
+			} else {
1222
+				$display_date = $this->start_date('F j\, Y')
1223
+								. ' @ '
1224
+								. $this->start_date('g:i a')
1225
+								. ' - '
1226
+								. $this->end_date('g:i a');
1227
+			}
1228
+		}
1229
+		return $display_date;
1230
+	}
1231
+
1232
+
1233
+	/**
1234
+	 * Gets all the tickets for this datetime
1235
+	 *
1236
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1237
+	 * @return EE_Base_Class[]|EE_Ticket[]
1238
+	 * @throws ReflectionException
1239
+	 * @throws InvalidArgumentException
1240
+	 * @throws InvalidInterfaceException
1241
+	 * @throws InvalidDataTypeException
1242
+	 * @throws EE_Error
1243
+	 */
1244
+	public function tickets($query_params = array())
1245
+	{
1246
+		return $this->get_many_related('Ticket', $query_params);
1247
+	}
1248
+
1249
+
1250
+	/**
1251
+	 * Gets all the ticket types currently available for purchase
1252
+	 *
1253
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1254
+	 * @return EE_Ticket[]
1255
+	 * @throws ReflectionException
1256
+	 * @throws InvalidArgumentException
1257
+	 * @throws InvalidInterfaceException
1258
+	 * @throws InvalidDataTypeException
1259
+	 * @throws EE_Error
1260
+	 */
1261
+	public function ticket_types_available_for_purchase($query_params = array())
1262
+	{
1263
+		// first check if datetime is valid
1264
+		if ($this->sold_out() || ! ($this->is_upcoming() || $this->is_active())) {
1265
+			return array();
1266
+		}
1267
+		if (empty($query_params)) {
1268
+			$query_params = array(
1269
+				array(
1270
+					'TKT_start_date' => array('<=', EEM_Ticket::instance()->current_time_for_query('TKT_start_date')),
1271
+					'TKT_end_date'   => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
1272
+					'TKT_deleted'    => false,
1273
+				),
1274
+			);
1275
+		}
1276
+		return $this->tickets($query_params);
1277
+	}
1278
+
1279
+
1280
+	/**
1281
+	 * @return EE_Base_Class|EE_Event
1282
+	 * @throws ReflectionException
1283
+	 * @throws InvalidArgumentException
1284
+	 * @throws InvalidInterfaceException
1285
+	 * @throws InvalidDataTypeException
1286
+	 * @throws EE_Error
1287
+	 */
1288
+	public function event()
1289
+	{
1290
+		return $this->get_first_related('Event');
1291
+	}
1292
+
1293
+
1294
+	/**
1295
+	 * Updates the DTT_sold attribute (and saves) based on the number of registrations for this datetime
1296
+	 * (via the tickets).
1297
+	 *
1298
+	 * @return int
1299
+	 * @throws ReflectionException
1300
+	 * @throws InvalidArgumentException
1301
+	 * @throws InvalidInterfaceException
1302
+	 * @throws InvalidDataTypeException
1303
+	 * @throws EE_Error
1304
+	 */
1305
+	public function update_sold()
1306
+	{
1307
+		$count_regs_for_this_datetime = EEM_Registration::instance()->count(
1308
+			array(
1309
+				array(
1310
+					'STS_ID'                 => EEM_Registration::status_id_approved,
1311
+					'REG_deleted'            => 0,
1312
+					'Ticket.Datetime.DTT_ID' => $this->ID(),
1313
+				),
1314
+			)
1315
+		);
1316
+		$this->set_sold($count_regs_for_this_datetime);
1317
+		$this->save();
1318
+		return $count_regs_for_this_datetime;
1319
+	}
1320
+
1321
+
1322
+	/*******************************************************************
1323 1323
      ***********************  DEPRECATED METHODS  **********************
1324 1324
      *******************************************************************/
1325 1325
 
1326 1326
 
1327
-    /**
1328
-     * Increments sold by amount passed by $qty, and persists it immediately to the database.
1329
-     *
1330
-     * @deprecated 4.9.80.p
1331
-     * @param int $qty
1332
-     * @return boolean
1333
-     * @throws ReflectionException
1334
-     * @throws InvalidArgumentException
1335
-     * @throws InvalidInterfaceException
1336
-     * @throws InvalidDataTypeException
1337
-     * @throws EE_Error
1338
-     */
1339
-    public function increase_sold($qty = 1)
1340
-    {
1341
-        EE_Error::doing_it_wrong(
1342
-            __FUNCTION__,
1343
-            esc_html__('Please use EE_Datetime::increaseSold() instead', 'event_espresso'),
1344
-            '4.9.80.p',
1345
-            '5.0.0.p'
1346
-        );
1347
-        return $this->increaseSold($qty);
1348
-    }
1349
-
1350
-
1351
-    /**
1352
-     * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need
1353
-     * to save afterwards.)
1354
-     *
1355
-     * @deprecated 4.9.80.p
1356
-     * @param int $qty
1357
-     * @return boolean
1358
-     * @throws ReflectionException
1359
-     * @throws InvalidArgumentException
1360
-     * @throws InvalidInterfaceException
1361
-     * @throws InvalidDataTypeException
1362
-     * @throws EE_Error
1363
-     */
1364
-    public function decrease_sold($qty = 1)
1365
-    {
1366
-        EE_Error::doing_it_wrong(
1367
-            __FUNCTION__,
1368
-            esc_html__('Please use EE_Datetime::decreaseSold() instead', 'event_espresso'),
1369
-            '4.9.80.p',
1370
-            '5.0.0.p'
1371
-        );
1372
-        return $this->decreaseSold($qty);
1373
-    }
1374
-
1375
-
1376
-    /**
1377
-     * Increments reserved by amount passed by $qty, and persists it immediately to the database.
1378
-     *
1379
-     * @deprecated 4.9.80.p
1380
-     * @param int $qty
1381
-     * @return boolean indicating success
1382
-     * @throws ReflectionException
1383
-     * @throws InvalidArgumentException
1384
-     * @throws InvalidInterfaceException
1385
-     * @throws InvalidDataTypeException
1386
-     * @throws EE_Error
1387
-     */
1388
-    public function increase_reserved($qty = 1)
1389
-    {
1390
-        EE_Error::doing_it_wrong(
1391
-            __FUNCTION__,
1392
-            esc_html__('Please use EE_Datetime::increaseReserved() instead', 'event_espresso'),
1393
-            '4.9.80.p',
1394
-            '5.0.0.p'
1395
-        );
1396
-        return $this->increaseReserved($qty);
1397
-    }
1398
-
1399
-
1400
-    /**
1401
-     * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1402
-     *
1403
-     * @deprecated 4.9.80.p
1404
-     * @param int $qty
1405
-     * @return boolean
1406
-     * @throws ReflectionException
1407
-     * @throws InvalidArgumentException
1408
-     * @throws InvalidInterfaceException
1409
-     * @throws InvalidDataTypeException
1410
-     * @throws EE_Error
1411
-     */
1412
-    public function decrease_reserved($qty = 1)
1413
-    {
1414
-        EE_Error::doing_it_wrong(
1415
-            __FUNCTION__,
1416
-            esc_html__('Please use EE_Datetime::decreaseReserved() instead', 'event_espresso'),
1417
-            '4.9.80.p',
1418
-            '5.0.0.p'
1419
-        );
1420
-        return $this->decreaseReserved($qty);
1421
-    }
1327
+	/**
1328
+	 * Increments sold by amount passed by $qty, and persists it immediately to the database.
1329
+	 *
1330
+	 * @deprecated 4.9.80.p
1331
+	 * @param int $qty
1332
+	 * @return boolean
1333
+	 * @throws ReflectionException
1334
+	 * @throws InvalidArgumentException
1335
+	 * @throws InvalidInterfaceException
1336
+	 * @throws InvalidDataTypeException
1337
+	 * @throws EE_Error
1338
+	 */
1339
+	public function increase_sold($qty = 1)
1340
+	{
1341
+		EE_Error::doing_it_wrong(
1342
+			__FUNCTION__,
1343
+			esc_html__('Please use EE_Datetime::increaseSold() instead', 'event_espresso'),
1344
+			'4.9.80.p',
1345
+			'5.0.0.p'
1346
+		);
1347
+		return $this->increaseSold($qty);
1348
+	}
1349
+
1350
+
1351
+	/**
1352
+	 * Decrements (subtracts) sold amount passed by $qty directly in the DB and on the model object. (Ie, no need
1353
+	 * to save afterwards.)
1354
+	 *
1355
+	 * @deprecated 4.9.80.p
1356
+	 * @param int $qty
1357
+	 * @return boolean
1358
+	 * @throws ReflectionException
1359
+	 * @throws InvalidArgumentException
1360
+	 * @throws InvalidInterfaceException
1361
+	 * @throws InvalidDataTypeException
1362
+	 * @throws EE_Error
1363
+	 */
1364
+	public function decrease_sold($qty = 1)
1365
+	{
1366
+		EE_Error::doing_it_wrong(
1367
+			__FUNCTION__,
1368
+			esc_html__('Please use EE_Datetime::decreaseSold() instead', 'event_espresso'),
1369
+			'4.9.80.p',
1370
+			'5.0.0.p'
1371
+		);
1372
+		return $this->decreaseSold($qty);
1373
+	}
1374
+
1375
+
1376
+	/**
1377
+	 * Increments reserved by amount passed by $qty, and persists it immediately to the database.
1378
+	 *
1379
+	 * @deprecated 4.9.80.p
1380
+	 * @param int $qty
1381
+	 * @return boolean indicating success
1382
+	 * @throws ReflectionException
1383
+	 * @throws InvalidArgumentException
1384
+	 * @throws InvalidInterfaceException
1385
+	 * @throws InvalidDataTypeException
1386
+	 * @throws EE_Error
1387
+	 */
1388
+	public function increase_reserved($qty = 1)
1389
+	{
1390
+		EE_Error::doing_it_wrong(
1391
+			__FUNCTION__,
1392
+			esc_html__('Please use EE_Datetime::increaseReserved() instead', 'event_espresso'),
1393
+			'4.9.80.p',
1394
+			'5.0.0.p'
1395
+		);
1396
+		return $this->increaseReserved($qty);
1397
+	}
1398
+
1399
+
1400
+	/**
1401
+	 * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1402
+	 *
1403
+	 * @deprecated 4.9.80.p
1404
+	 * @param int $qty
1405
+	 * @return boolean
1406
+	 * @throws ReflectionException
1407
+	 * @throws InvalidArgumentException
1408
+	 * @throws InvalidInterfaceException
1409
+	 * @throws InvalidDataTypeException
1410
+	 * @throws EE_Error
1411
+	 */
1412
+	public function decrease_reserved($qty = 1)
1413
+	{
1414
+		EE_Error::doing_it_wrong(
1415
+			__FUNCTION__,
1416
+			esc_html__('Please use EE_Datetime::decreaseReserved() instead', 'event_espresso'),
1417
+			'4.9.80.p',
1418
+			'5.0.0.p'
1419
+		);
1420
+		return $this->decreaseReserved($qty);
1421
+	}
1422 1422
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Question_Group.class.php 1 patch
Indentation   +276 added lines, -276 removed lines patch added patch discarded remove patch
@@ -12,280 +12,280 @@
 block discarded – undo
12 12
 class EE_Question_Group extends EE_Soft_Delete_Base_Class
13 13
 {
14 14
 
15
-    /**
16
-     * @param array $props_n_values
17
-     * @return EE_Question_Group|mixed
18
-     */
19
-    public static function new_instance($props_n_values = array())
20
-    {
21
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__);
22
-        return $has_object ? $has_object : new self($props_n_values);
23
-    }
24
-
25
-
26
-    /**
27
-     * @param array $props_n_values
28
-     * @return EE_Question_Group
29
-     */
30
-    public static function new_instance_from_db($props_n_values = array())
31
-    {
32
-        return new self($props_n_values, true);
33
-    }
34
-
35
-
36
-    /**
37
-     * gets the question group's name
38
-     *
39
-     * @access public
40
-     * @param bool $pretty
41
-     * @return string
42
-     */
43
-    public function name($pretty = false)
44
-    {
45
-        return $pretty ? $this->get_pretty('QSG_name') : $this->get('QSG_name');
46
-    }
47
-
48
-
49
-    /**
50
-     * Gets the question group's internal name
51
-     *
52
-     * @access public
53
-     * @return string
54
-     */
55
-    public function identifier()
56
-    {
57
-        return $this->get('QSG_identifier');
58
-    }
59
-
60
-
61
-    /**
62
-     * Gets the question group's description
63
-     *
64
-     * @access public
65
-     * @param bool $pretty
66
-     * @return string
67
-     */
68
-    public function desc($pretty = false)
69
-    {
70
-        return $pretty ? $this->get_pretty('QSG_desc') : $this->get('QSG_desc');
71
-    }
72
-
73
-
74
-    /**
75
-     * Gets the question group's order number in a sequence
76
-     * of other question groups
77
-     *
78
-     * @access public
79
-     * @return int
80
-     */
81
-    public function order()
82
-    {
83
-        return $this->get('QSG_order');
84
-    }
85
-
86
-
87
-    /**
88
-     * Returns whether to show the group's name on the frontend
89
-     *
90
-     * @access public
91
-     * @return boolean
92
-     */
93
-    public function show_group_name()
94
-    {
95
-        return $this->get('QSG_show_group_name');
96
-    }
97
-
98
-
99
-    /**
100
-     * Returns whether to show the group's description
101
-     * on the frontend
102
-     *
103
-     * @access public
104
-     * @return boolean
105
-     */
106
-    public function show_group_desc()
107
-    {
108
-        return $this->get('QSG_show_group_desc');
109
-    }
110
-
111
-
112
-    /**
113
-     * Returns whether this is a 'system group' (meaning
114
-     * a question group integral to the system, whose questions
115
-     * relate to the attendee table)
116
-     *
117
-     * @access public
118
-     * @return int
119
-     */
120
-    public function system_group()
121
-    {
122
-        return $this->get('QSG_system');
123
-    }
124
-
125
-
126
-    /**
127
-     * get the author of the question group.
128
-     *
129
-     * @since 4.5.0
130
-     *
131
-     * @return int
132
-     */
133
-    public function wp_user()
134
-    {
135
-        return $this->get('QSG_wp_user');
136
-    }
137
-
138
-
139
-    /**
140
-     * Returns whether this question group has
141
-     * been deleted
142
-     *
143
-     * @access public
144
-     * @return boolean
145
-     */
146
-    public function deleted()
147
-    {
148
-        return $this->get('QST_deleted');
149
-    }
150
-
151
-
152
-    /**
153
-     * Gets an array of questions with questions IN the group at the start of the array and questions NOT in the group
154
-     * at the end of the array.  Questions in the group are ordered by Question_Group_Question.QGQ_order and questions
155
-     * NOT in the group are ordered by Question.QGQ_order
156
-     *
157
-     * @return EE_Question[]
158
-     */
159
-    public function questions_in_and_not_in_group()
160
-    {
161
-        $questions_in_group = $this->questions();
162
-        $exclude_question_ids = ! empty($questions_in_group) ? array_keys($questions_in_group) : array();
163
-        $questions_not_in_group = $this->questions_not_in_group($exclude_question_ids);
164
-        return $questions_in_group + $questions_not_in_group;
165
-    }
166
-
167
-
168
-    /**
169
-     * Gets all the questions which are part of this question group (ordered Question_Group_Question.QGQ_order)
170
-     *
171
-     * @param array $query_params
172
-     * @return EE_Question[]
173
-     */
174
-    public function questions($query_params = array())
175
-    {
176
-        $query_params = ! empty($query_params) ? $query_params
177
-            : array('order_by' => array('Question_Group_Question.QGQ_order' => 'ASC'));
178
-        return $this->ID() ? $this->get_many_related('Question', $query_params) : array();
179
-    }
180
-
181
-
182
-    /**
183
-     * Gets all the questions which are NOT part of this question group.
184
-     *
185
-     * @param  mixed $question_IDS_in_group if empty array then all questions returned.  if FALSE then we first get
186
-     *                                      questions in this group and exclude them from questions get all. IF empty
187
-     *                                      array then we just return all questions.
188
-     * @return EE_Question[]
189
-     */
190
-    public function questions_not_in_group($question_IDS_in_group = false)
191
-    {
192
-        if ($question_IDS_in_group === false) {
193
-            $questions = $this->questions();
194
-            $question_IDS_in_group = ! empty($questions) ? array_keys($questions) : array();
195
-        }
196
-        $_where = ! empty($question_IDS_in_group) ? array('QST_ID' => array('not_in', $question_IDS_in_group))
197
-            : array();
198
-
199
-        return EEM_Question::instance()->get_all(array($_where, 'order_by' => array('QST_ID' => 'ASC')));
200
-    }
201
-
202
-
203
-    /**
204
-     * Gets all events which are related to this question group
205
-     *
206
-     * @return EE_Event[]
207
-     */
208
-    public function events()
209
-    {
210
-        return $this->get_many_related('Event');
211
-    }
212
-
213
-
214
-    /**
215
-     * Adds the question to this question group
216
-     *
217
-     * @param EE_Question || int $question object or ID
218
-     * @return boolean if successful
219
-     */
220
-    public function add_question($questionObjectOrID)
221
-    {
222
-        return $this->_add_relation_to($questionObjectOrID, 'Question');
223
-    }
224
-
225
-
226
-    /**
227
-     * Removes the question from this question group
228
-     *
229
-     * @param EE_Question || int $question object or ID
230
-     * @return boolean of success
231
-     */
232
-    public function remove_question($questionObjectOrID)
233
-    {
234
-        return $this->_remove_relation_to($questionObjectOrID, 'Question');
235
-    }
236
-
237
-
238
-    /**
239
-     * @param $questionObjectOrID
240
-     * @param $qst_order
241
-     * @return int
242
-     */
243
-    public function update_question_order($questionObjectOrID, $qst_order)
244
-    {
245
-        $qst_ID = $questionObjectOrID instanceof EE_Question ? $questionObjectOrID->ID() : (int) $questionObjectOrID;
246
-        return EEM_Question_Group_Question::instance()->update(
247
-            array('QGQ_order' => $qst_order),
248
-            array(
249
-                array(
250
-                    'QST_ID' => $qst_ID,
251
-                    'QSG_ID' => $this->ID(),
252
-                ),
253
-            )
254
-        );
255
-    }
256
-
257
-
258
-    /**
259
-     * Basically this is method just returns whether the question group has any questions with answers.  This is used
260
-     * by the admin currently to determine whether we should display the ui for deleting permanently or not b/c
261
-     * question groups with questions that have answers should not be possible to delete permanently
262
-     *
263
-     * @return boolean true if has questions with answers, false if not.
264
-     */
265
-    public function has_questions_with_answers()
266
-    {
267
-        $has_answers = false;
268
-        $questions = $this->get_many_related('Question');
269
-        foreach ($questions as $question) {
270
-            if ($question->count_related('Answer') > 0) {
271
-                $has_answers = true;
272
-            }
273
-        }
274
-        return $has_answers;
275
-    }
276
-
277
-
278
-    /**
279
-     * The purpose of this method is set the question group order for this question group to be the max out of all
280
-     * question groups
281
-     *
282
-     * @access public
283
-     * @return void
284
-     */
285
-    public function set_order_to_latest()
286
-    {
287
-        $latest_order = $this->get_model()->get_latest_question_group_order();
288
-        $latest_order++;
289
-        $this->set('QSG_order', $latest_order);
290
-    }
15
+	/**
16
+	 * @param array $props_n_values
17
+	 * @return EE_Question_Group|mixed
18
+	 */
19
+	public static function new_instance($props_n_values = array())
20
+	{
21
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__);
22
+		return $has_object ? $has_object : new self($props_n_values);
23
+	}
24
+
25
+
26
+	/**
27
+	 * @param array $props_n_values
28
+	 * @return EE_Question_Group
29
+	 */
30
+	public static function new_instance_from_db($props_n_values = array())
31
+	{
32
+		return new self($props_n_values, true);
33
+	}
34
+
35
+
36
+	/**
37
+	 * gets the question group's name
38
+	 *
39
+	 * @access public
40
+	 * @param bool $pretty
41
+	 * @return string
42
+	 */
43
+	public function name($pretty = false)
44
+	{
45
+		return $pretty ? $this->get_pretty('QSG_name') : $this->get('QSG_name');
46
+	}
47
+
48
+
49
+	/**
50
+	 * Gets the question group's internal name
51
+	 *
52
+	 * @access public
53
+	 * @return string
54
+	 */
55
+	public function identifier()
56
+	{
57
+		return $this->get('QSG_identifier');
58
+	}
59
+
60
+
61
+	/**
62
+	 * Gets the question group's description
63
+	 *
64
+	 * @access public
65
+	 * @param bool $pretty
66
+	 * @return string
67
+	 */
68
+	public function desc($pretty = false)
69
+	{
70
+		return $pretty ? $this->get_pretty('QSG_desc') : $this->get('QSG_desc');
71
+	}
72
+
73
+
74
+	/**
75
+	 * Gets the question group's order number in a sequence
76
+	 * of other question groups
77
+	 *
78
+	 * @access public
79
+	 * @return int
80
+	 */
81
+	public function order()
82
+	{
83
+		return $this->get('QSG_order');
84
+	}
85
+
86
+
87
+	/**
88
+	 * Returns whether to show the group's name on the frontend
89
+	 *
90
+	 * @access public
91
+	 * @return boolean
92
+	 */
93
+	public function show_group_name()
94
+	{
95
+		return $this->get('QSG_show_group_name');
96
+	}
97
+
98
+
99
+	/**
100
+	 * Returns whether to show the group's description
101
+	 * on the frontend
102
+	 *
103
+	 * @access public
104
+	 * @return boolean
105
+	 */
106
+	public function show_group_desc()
107
+	{
108
+		return $this->get('QSG_show_group_desc');
109
+	}
110
+
111
+
112
+	/**
113
+	 * Returns whether this is a 'system group' (meaning
114
+	 * a question group integral to the system, whose questions
115
+	 * relate to the attendee table)
116
+	 *
117
+	 * @access public
118
+	 * @return int
119
+	 */
120
+	public function system_group()
121
+	{
122
+		return $this->get('QSG_system');
123
+	}
124
+
125
+
126
+	/**
127
+	 * get the author of the question group.
128
+	 *
129
+	 * @since 4.5.0
130
+	 *
131
+	 * @return int
132
+	 */
133
+	public function wp_user()
134
+	{
135
+		return $this->get('QSG_wp_user');
136
+	}
137
+
138
+
139
+	/**
140
+	 * Returns whether this question group has
141
+	 * been deleted
142
+	 *
143
+	 * @access public
144
+	 * @return boolean
145
+	 */
146
+	public function deleted()
147
+	{
148
+		return $this->get('QST_deleted');
149
+	}
150
+
151
+
152
+	/**
153
+	 * Gets an array of questions with questions IN the group at the start of the array and questions NOT in the group
154
+	 * at the end of the array.  Questions in the group are ordered by Question_Group_Question.QGQ_order and questions
155
+	 * NOT in the group are ordered by Question.QGQ_order
156
+	 *
157
+	 * @return EE_Question[]
158
+	 */
159
+	public function questions_in_and_not_in_group()
160
+	{
161
+		$questions_in_group = $this->questions();
162
+		$exclude_question_ids = ! empty($questions_in_group) ? array_keys($questions_in_group) : array();
163
+		$questions_not_in_group = $this->questions_not_in_group($exclude_question_ids);
164
+		return $questions_in_group + $questions_not_in_group;
165
+	}
166
+
167
+
168
+	/**
169
+	 * Gets all the questions which are part of this question group (ordered Question_Group_Question.QGQ_order)
170
+	 *
171
+	 * @param array $query_params
172
+	 * @return EE_Question[]
173
+	 */
174
+	public function questions($query_params = array())
175
+	{
176
+		$query_params = ! empty($query_params) ? $query_params
177
+			: array('order_by' => array('Question_Group_Question.QGQ_order' => 'ASC'));
178
+		return $this->ID() ? $this->get_many_related('Question', $query_params) : array();
179
+	}
180
+
181
+
182
+	/**
183
+	 * Gets all the questions which are NOT part of this question group.
184
+	 *
185
+	 * @param  mixed $question_IDS_in_group if empty array then all questions returned.  if FALSE then we first get
186
+	 *                                      questions in this group and exclude them from questions get all. IF empty
187
+	 *                                      array then we just return all questions.
188
+	 * @return EE_Question[]
189
+	 */
190
+	public function questions_not_in_group($question_IDS_in_group = false)
191
+	{
192
+		if ($question_IDS_in_group === false) {
193
+			$questions = $this->questions();
194
+			$question_IDS_in_group = ! empty($questions) ? array_keys($questions) : array();
195
+		}
196
+		$_where = ! empty($question_IDS_in_group) ? array('QST_ID' => array('not_in', $question_IDS_in_group))
197
+			: array();
198
+
199
+		return EEM_Question::instance()->get_all(array($_where, 'order_by' => array('QST_ID' => 'ASC')));
200
+	}
201
+
202
+
203
+	/**
204
+	 * Gets all events which are related to this question group
205
+	 *
206
+	 * @return EE_Event[]
207
+	 */
208
+	public function events()
209
+	{
210
+		return $this->get_many_related('Event');
211
+	}
212
+
213
+
214
+	/**
215
+	 * Adds the question to this question group
216
+	 *
217
+	 * @param EE_Question || int $question object or ID
218
+	 * @return boolean if successful
219
+	 */
220
+	public function add_question($questionObjectOrID)
221
+	{
222
+		return $this->_add_relation_to($questionObjectOrID, 'Question');
223
+	}
224
+
225
+
226
+	/**
227
+	 * Removes the question from this question group
228
+	 *
229
+	 * @param EE_Question || int $question object or ID
230
+	 * @return boolean of success
231
+	 */
232
+	public function remove_question($questionObjectOrID)
233
+	{
234
+		return $this->_remove_relation_to($questionObjectOrID, 'Question');
235
+	}
236
+
237
+
238
+	/**
239
+	 * @param $questionObjectOrID
240
+	 * @param $qst_order
241
+	 * @return int
242
+	 */
243
+	public function update_question_order($questionObjectOrID, $qst_order)
244
+	{
245
+		$qst_ID = $questionObjectOrID instanceof EE_Question ? $questionObjectOrID->ID() : (int) $questionObjectOrID;
246
+		return EEM_Question_Group_Question::instance()->update(
247
+			array('QGQ_order' => $qst_order),
248
+			array(
249
+				array(
250
+					'QST_ID' => $qst_ID,
251
+					'QSG_ID' => $this->ID(),
252
+				),
253
+			)
254
+		);
255
+	}
256
+
257
+
258
+	/**
259
+	 * Basically this is method just returns whether the question group has any questions with answers.  This is used
260
+	 * by the admin currently to determine whether we should display the ui for deleting permanently or not b/c
261
+	 * question groups with questions that have answers should not be possible to delete permanently
262
+	 *
263
+	 * @return boolean true if has questions with answers, false if not.
264
+	 */
265
+	public function has_questions_with_answers()
266
+	{
267
+		$has_answers = false;
268
+		$questions = $this->get_many_related('Question');
269
+		foreach ($questions as $question) {
270
+			if ($question->count_related('Answer') > 0) {
271
+				$has_answers = true;
272
+			}
273
+		}
274
+		return $has_answers;
275
+	}
276
+
277
+
278
+	/**
279
+	 * The purpose of this method is set the question group order for this question group to be the max out of all
280
+	 * question groups
281
+	 *
282
+	 * @access public
283
+	 * @return void
284
+	 */
285
+	public function set_order_to_latest()
286
+	{
287
+		$latest_order = $this->get_model()->get_latest_question_group_order();
288
+		$latest_order++;
289
+		$this->set('QSG_order', $latest_order);
290
+	}
291 291
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Checkin.class.php 1 patch
Indentation   +82 added lines, -82 removed lines patch added patch discarded remove patch
@@ -11,86 +11,86 @@
 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
-     *
38
-     * @param array  $props_n_values    incoming values
39
-     * @param string $timezone          incoming timezone (if not set the timezone set for the website will be used.)
40
-     * @param array  $date_formats      incoming date_formats in an array
41
-     *                                  where the first value is the date_format
42
-     *                                  and the second value is the time format
43
-     * @return EE_Checkin
44
-     * @throws EE_Error
45
-     */
46
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
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
-     */
62
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
63
-    {
64
-        return new self($props_n_values, true, $timezone);
65
-    }
66
-
67
-
68
-    public function ID()
69
-    {
70
-        return $this->get('CHK_ID');
71
-    }
72
-
73
-
74
-    public function registration_id()
75
-    {
76
-        return $this->get('REG_ID');
77
-    }
78
-
79
-
80
-    public function datetime_id()
81
-    {
82
-        return $this->get('DTT_ID');
83
-    }
84
-
85
-
86
-    public function status()
87
-    {
88
-        return $this->get('CHK_in');
89
-    }
90
-
91
-
92
-    public function timestamp()
93
-    {
94
-        return $this->get('CHK_timestamp');
95
-    }
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
+	 *
38
+	 * @param array  $props_n_values    incoming values
39
+	 * @param string $timezone          incoming timezone (if not set the timezone set for the website will be used.)
40
+	 * @param array  $date_formats      incoming date_formats in an array
41
+	 *                                  where the first value is the date_format
42
+	 *                                  and the second value is the time format
43
+	 * @return EE_Checkin
44
+	 * @throws EE_Error
45
+	 */
46
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
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
+	 */
62
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
63
+	{
64
+		return new self($props_n_values, true, $timezone);
65
+	}
66
+
67
+
68
+	public function ID()
69
+	{
70
+		return $this->get('CHK_ID');
71
+	}
72
+
73
+
74
+	public function registration_id()
75
+	{
76
+		return $this->get('REG_ID');
77
+	}
78
+
79
+
80
+	public function datetime_id()
81
+	{
82
+		return $this->get('DTT_ID');
83
+	}
84
+
85
+
86
+	public function status()
87
+	{
88
+		return $this->get('CHK_in');
89
+	}
90
+
91
+
92
+	public function timestamp()
93
+	{
94
+		return $this->get('CHK_timestamp');
95
+	}
96 96
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Currency.class.php 1 patch
Indentation   +176 added lines, -176 removed lines patch added patch discarded remove patch
@@ -12,180 +12,180 @@
 block discarded – undo
12 12
 class EE_Currency extends EE_Base_Class
13 13
 {
14 14
 
15
-    /** Currency COde @var CUR_code */
16
-    protected $_CUR_code = null;
17
-    /** Currency Name Singular @var CUR_single */
18
-    protected $_CUR_single = null;
19
-    /** Currency Name Plural @var CUR_plural */
20
-    protected $_CUR_plural = null;
21
-    /** Currency Sign @var CUR_sign */
22
-    protected $_CUR_sign = null;
23
-    /** Currency Decimal Places @var CUR_dec_plc */
24
-    protected $_CUR_dec_plc = null;
25
-    /** Active? @var CUR_active */
26
-    protected $_CUR_active = null;
27
-    protected $_Payment_Method;
28
-
29
-    /**
30
-     *
31
-     * @param array  $props_n_values          incoming values
32
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
33
-     *                                        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_Attendee
37
-     */
38
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
39
-    {
40
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
41
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
42
-    }
43
-
44
-
45
-    /**
46
-     * @param array  $props_n_values  incoming values from the database
47
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
48
-     *                                the website will be used.
49
-     * @return EE_Attendee
50
-     */
51
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
52
-    {
53
-        return new self($props_n_values, true, $timezone);
54
-    }
55
-
56
-    /**
57
-     * Gets code
58
-     *
59
-     * @return string
60
-     */
61
-    public function code()
62
-    {
63
-        return $this->get('CUR_code');
64
-    }
65
-
66
-    /**
67
-     * Sets code
68
-     *
69
-     * @param string $code
70
-     * @return boolean
71
-     */
72
-    public function set_code($code)
73
-    {
74
-        return $this->set('CUR_code', $code);
75
-    }
76
-
77
-    /**
78
-     * Gets active
79
-     *
80
-     * @return boolean
81
-     */
82
-    public function active()
83
-    {
84
-        return $this->get('CUR_active');
85
-    }
86
-
87
-    /**
88
-     * Sets active
89
-     *
90
-     * @param boolean $active
91
-     * @return boolean
92
-     */
93
-    public function set_active($active)
94
-    {
95
-        return $this->set('CUR_active', $active);
96
-    }
97
-
98
-    /**
99
-     * Gets dec_plc
100
-     *
101
-     * @return int
102
-     */
103
-    public function dec_plc()
104
-    {
105
-        return $this->get('CUR_dec_plc');
106
-    }
107
-
108
-    /**
109
-     * Sets dec_plc
110
-     *
111
-     * @param int $dec_plc
112
-     * @return boolean
113
-     */
114
-    public function set_dec_plc($dec_plc)
115
-    {
116
-        return $this->set('CUR_dec_plc', $dec_plc);
117
-    }
118
-
119
-    /**
120
-     * Gets plural
121
-     *
122
-     * @return string
123
-     */
124
-    public function plural_name()
125
-    {
126
-        return $this->get('CUR_plural');
127
-    }
128
-
129
-    /**
130
-     * Sets plural
131
-     *
132
-     * @param string $plural
133
-     * @return boolean
134
-     */
135
-    public function set_plural_name($plural)
136
-    {
137
-        return $this->set('CUR_plural', $plural);
138
-    }
139
-
140
-    /**
141
-     * Gets sign
142
-     *
143
-     * @return string
144
-     */
145
-    public function sign()
146
-    {
147
-        return $this->get('CUR_sign');
148
-    }
149
-
150
-    /**
151
-     * Sets sign
152
-     *
153
-     * @param string $sign
154
-     * @return boolean
155
-     */
156
-    public function set_sign($sign)
157
-    {
158
-        return $this->set('CUR_sign', $sign);
159
-    }
160
-
161
-    /**
162
-     * Gets single
163
-     *
164
-     * @return string
165
-     */
166
-    public function singular_name()
167
-    {
168
-        return $this->get('CUR_single');
169
-    }
170
-
171
-    /**
172
-     * Sets single
173
-     *
174
-     * @param string $single
175
-     * @return boolean
176
-     */
177
-    public function set_singular_name($single)
178
-    {
179
-        return $this->set('CUR_single', $single);
180
-    }
181
-
182
-    /**
183
-     * Gets a prettier name
184
-     *
185
-     * @return string
186
-     */
187
-    public function name()
188
-    {
189
-        return sprintf(__("%s (%s)", "event_espresso"), $this->code(), $this->plural_name());
190
-    }
15
+	/** Currency COde @var CUR_code */
16
+	protected $_CUR_code = null;
17
+	/** Currency Name Singular @var CUR_single */
18
+	protected $_CUR_single = null;
19
+	/** Currency Name Plural @var CUR_plural */
20
+	protected $_CUR_plural = null;
21
+	/** Currency Sign @var CUR_sign */
22
+	protected $_CUR_sign = null;
23
+	/** Currency Decimal Places @var CUR_dec_plc */
24
+	protected $_CUR_dec_plc = null;
25
+	/** Active? @var CUR_active */
26
+	protected $_CUR_active = null;
27
+	protected $_Payment_Method;
28
+
29
+	/**
30
+	 *
31
+	 * @param array  $props_n_values          incoming values
32
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
33
+	 *                                        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_Attendee
37
+	 */
38
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
39
+	{
40
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
41
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
42
+	}
43
+
44
+
45
+	/**
46
+	 * @param array  $props_n_values  incoming values from the database
47
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
48
+	 *                                the website will be used.
49
+	 * @return EE_Attendee
50
+	 */
51
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
52
+	{
53
+		return new self($props_n_values, true, $timezone);
54
+	}
55
+
56
+	/**
57
+	 * Gets code
58
+	 *
59
+	 * @return string
60
+	 */
61
+	public function code()
62
+	{
63
+		return $this->get('CUR_code');
64
+	}
65
+
66
+	/**
67
+	 * Sets code
68
+	 *
69
+	 * @param string $code
70
+	 * @return boolean
71
+	 */
72
+	public function set_code($code)
73
+	{
74
+		return $this->set('CUR_code', $code);
75
+	}
76
+
77
+	/**
78
+	 * Gets active
79
+	 *
80
+	 * @return boolean
81
+	 */
82
+	public function active()
83
+	{
84
+		return $this->get('CUR_active');
85
+	}
86
+
87
+	/**
88
+	 * Sets active
89
+	 *
90
+	 * @param boolean $active
91
+	 * @return boolean
92
+	 */
93
+	public function set_active($active)
94
+	{
95
+		return $this->set('CUR_active', $active);
96
+	}
97
+
98
+	/**
99
+	 * Gets dec_plc
100
+	 *
101
+	 * @return int
102
+	 */
103
+	public function dec_plc()
104
+	{
105
+		return $this->get('CUR_dec_plc');
106
+	}
107
+
108
+	/**
109
+	 * Sets dec_plc
110
+	 *
111
+	 * @param int $dec_plc
112
+	 * @return boolean
113
+	 */
114
+	public function set_dec_plc($dec_plc)
115
+	{
116
+		return $this->set('CUR_dec_plc', $dec_plc);
117
+	}
118
+
119
+	/**
120
+	 * Gets plural
121
+	 *
122
+	 * @return string
123
+	 */
124
+	public function plural_name()
125
+	{
126
+		return $this->get('CUR_plural');
127
+	}
128
+
129
+	/**
130
+	 * Sets plural
131
+	 *
132
+	 * @param string $plural
133
+	 * @return boolean
134
+	 */
135
+	public function set_plural_name($plural)
136
+	{
137
+		return $this->set('CUR_plural', $plural);
138
+	}
139
+
140
+	/**
141
+	 * Gets sign
142
+	 *
143
+	 * @return string
144
+	 */
145
+	public function sign()
146
+	{
147
+		return $this->get('CUR_sign');
148
+	}
149
+
150
+	/**
151
+	 * Sets sign
152
+	 *
153
+	 * @param string $sign
154
+	 * @return boolean
155
+	 */
156
+	public function set_sign($sign)
157
+	{
158
+		return $this->set('CUR_sign', $sign);
159
+	}
160
+
161
+	/**
162
+	 * Gets single
163
+	 *
164
+	 * @return string
165
+	 */
166
+	public function singular_name()
167
+	{
168
+		return $this->get('CUR_single');
169
+	}
170
+
171
+	/**
172
+	 * Sets single
173
+	 *
174
+	 * @param string $single
175
+	 * @return boolean
176
+	 */
177
+	public function set_singular_name($single)
178
+	{
179
+		return $this->set('CUR_single', $single);
180
+	}
181
+
182
+	/**
183
+	 * Gets a prettier name
184
+	 *
185
+	 * @return string
186
+	 */
187
+	public function name()
188
+	{
189
+		return sprintf(__("%s (%s)", "event_espresso"), $this->code(), $this->plural_name());
190
+	}
191 191
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Question_Option.class.php 1 patch
Indentation   +216 added lines, -216 removed lines patch added patch discarded remove patch
@@ -10,220 +10,220 @@
 block discarded – undo
10 10
 class EE_Question_Option extends EE_Soft_Delete_Base_Class implements EEI_Duplicatable
11 11
 {
12 12
 
13
-    /**
14
-     * Question Option Opt Group Name
15
-     *
16
-     * @access protected
17
-     * @var string
18
-     */
19
-    protected $_QSO_opt_group = null;
20
-
21
-
22
-    /**
23
-     *
24
-     * @param array  $props_n_values          incoming values
25
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
26
-     *                                        used.)
27
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
28
-     *                                        date_format and the second value is the time format
29
-     * @return EE_Attendee
30
-     */
31
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
32
-    {
33
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
34
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
35
-    }
36
-
37
-
38
-    /**
39
-     * @param array  $props_n_values  incoming values from the database
40
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
41
-     *                                the website will be used.
42
-     * @return EE_Attendee
43
-     */
44
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
45
-    {
46
-        return new self($props_n_values, true, $timezone);
47
-    }
48
-
49
-
50
-    /**
51
-     * Sets the option's key value
52
-     *
53
-     * @param string $value
54
-     * @return bool success
55
-     */
56
-    public function set_value($value)
57
-    {
58
-        $this->set('QSO_value', $value);
59
-    }
60
-
61
-
62
-    /**
63
-     * Sets the option's Display Text
64
-     *
65
-     * @param string $text
66
-     * @return bool success
67
-     */
68
-    public function set_desc($text)
69
-    {
70
-        $this->set('QSO_desc', $text);
71
-    }
72
-
73
-
74
-    /**
75
-     * Sets the order for this option
76
-     *
77
-     * @access public
78
-     * @param integer $order
79
-     * @return bool      $success
80
-     */
81
-    public function set_order($order)
82
-    {
83
-        $this->set('QSO_order', $order);
84
-    }
85
-
86
-
87
-    /**
88
-     * Sets the ID of the related question
89
-     *
90
-     * @param int $question_ID
91
-     * @return bool success
92
-     */
93
-    public function set_question_ID($question_ID)
94
-    {
95
-        $this->set('QST_ID', $question_ID);
96
-    }
97
-
98
-
99
-    /**
100
-     * Sets the option's opt_group
101
-     *
102
-     * @param string $text
103
-     * @return bool success
104
-     */
105
-    public function set_opt_group($text)
106
-    {
107
-        return $this->_QSO_opt_group = $text;
108
-    }
109
-
110
-
111
-    /**
112
-     * Gets the option's key value
113
-     *
114
-     * @return string
115
-     */
116
-    public function value()
117
-    {
118
-        return $this->get('QSO_value');
119
-    }
120
-
121
-
122
-    /**
123
-     * Gets the option's display text
124
-     *
125
-     * @return string
126
-     */
127
-    public function desc()
128
-    {
129
-        return $this->get('QSO_desc');
130
-    }
131
-
132
-
133
-    /**
134
-     * Returns whether this option has been deleted or not
135
-     *
136
-     * @return boolean
137
-     */
138
-    public function deleted()
139
-    {
140
-        return $this->get('QSO_deleted');
141
-    }
142
-
143
-
144
-    /**
145
-     * Returns the order or the Question Option
146
-     *
147
-     * @access public
148
-     * @return integer
149
-     */
150
-    public function order()
151
-    {
152
-        return $this->get('QSO_option');
153
-    }
154
-
155
-
156
-    /**
157
-     * Gets the related question's ID
158
-     *
159
-     * @return int
160
-     */
161
-    public function question_ID()
162
-    {
163
-        return $this->get('QST_ID');
164
-    }
165
-
166
-
167
-    /**
168
-     * Returns the question related to this question option
169
-     *
170
-     * @return EE_Question
171
-     */
172
-    public function question()
173
-    {
174
-        return $this->get_first_related('Question');
175
-    }
176
-
177
-
178
-    /**
179
-     * Gets the option's opt_group
180
-     *
181
-     * @return string
182
-     */
183
-    public function opt_group()
184
-    {
185
-        return $this->_QSO_opt_group;
186
-    }
187
-
188
-    /**
189
-     * Duplicates this question option. By default the new question option will be for the same question,
190
-     * but that can be overriden by setting the 'QST_ID' option
191
-     *
192
-     * @param array $options {
193
-     * @type int    $QST_ID  the QST_ID attribute of this question option, otherwise it will be for the same question
194
-     *                       as the original
195
-     */
196
-    public function duplicate($options = array())
197
-    {
198
-        $new_question_option = clone $this;
199
-        $new_question_option->set('QSO_ID', null);
200
-        if (array_key_exists(
201
-            'QST_ID',
202
-            $options
203
-        )) {// use array_key_exists instead of isset because NULL might be a valid value
204
-            $new_question_option->set_question_ID($options['QST_ID']);
205
-        }
206
-        $new_question_option->save();
207
-    }
208
-
209
-    /**
210
-     * Gets the QSO_system value
211
-     *
212
-     * @return string|null
213
-     */
214
-    public function system()
215
-    {
216
-        return $this->get('QSO_system');
217
-    }
218
-
219
-    /**
220
-     * Sets QSO_system
221
-     *
222
-     * @param string $QSO_system
223
-     * @return bool
224
-     */
225
-    public function set_system($QSO_system)
226
-    {
227
-        return $this->set('QSO_system', $QSO_system);
228
-    }
13
+	/**
14
+	 * Question Option Opt Group Name
15
+	 *
16
+	 * @access protected
17
+	 * @var string
18
+	 */
19
+	protected $_QSO_opt_group = null;
20
+
21
+
22
+	/**
23
+	 *
24
+	 * @param array  $props_n_values          incoming values
25
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
26
+	 *                                        used.)
27
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
28
+	 *                                        date_format and the second value is the time format
29
+	 * @return EE_Attendee
30
+	 */
31
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
32
+	{
33
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
34
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
35
+	}
36
+
37
+
38
+	/**
39
+	 * @param array  $props_n_values  incoming values from the database
40
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
41
+	 *                                the website will be used.
42
+	 * @return EE_Attendee
43
+	 */
44
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
45
+	{
46
+		return new self($props_n_values, true, $timezone);
47
+	}
48
+
49
+
50
+	/**
51
+	 * Sets the option's key value
52
+	 *
53
+	 * @param string $value
54
+	 * @return bool success
55
+	 */
56
+	public function set_value($value)
57
+	{
58
+		$this->set('QSO_value', $value);
59
+	}
60
+
61
+
62
+	/**
63
+	 * Sets the option's Display Text
64
+	 *
65
+	 * @param string $text
66
+	 * @return bool success
67
+	 */
68
+	public function set_desc($text)
69
+	{
70
+		$this->set('QSO_desc', $text);
71
+	}
72
+
73
+
74
+	/**
75
+	 * Sets the order for this option
76
+	 *
77
+	 * @access public
78
+	 * @param integer $order
79
+	 * @return bool      $success
80
+	 */
81
+	public function set_order($order)
82
+	{
83
+		$this->set('QSO_order', $order);
84
+	}
85
+
86
+
87
+	/**
88
+	 * Sets the ID of the related question
89
+	 *
90
+	 * @param int $question_ID
91
+	 * @return bool success
92
+	 */
93
+	public function set_question_ID($question_ID)
94
+	{
95
+		$this->set('QST_ID', $question_ID);
96
+	}
97
+
98
+
99
+	/**
100
+	 * Sets the option's opt_group
101
+	 *
102
+	 * @param string $text
103
+	 * @return bool success
104
+	 */
105
+	public function set_opt_group($text)
106
+	{
107
+		return $this->_QSO_opt_group = $text;
108
+	}
109
+
110
+
111
+	/**
112
+	 * Gets the option's key value
113
+	 *
114
+	 * @return string
115
+	 */
116
+	public function value()
117
+	{
118
+		return $this->get('QSO_value');
119
+	}
120
+
121
+
122
+	/**
123
+	 * Gets the option's display text
124
+	 *
125
+	 * @return string
126
+	 */
127
+	public function desc()
128
+	{
129
+		return $this->get('QSO_desc');
130
+	}
131
+
132
+
133
+	/**
134
+	 * Returns whether this option has been deleted or not
135
+	 *
136
+	 * @return boolean
137
+	 */
138
+	public function deleted()
139
+	{
140
+		return $this->get('QSO_deleted');
141
+	}
142
+
143
+
144
+	/**
145
+	 * Returns the order or the Question Option
146
+	 *
147
+	 * @access public
148
+	 * @return integer
149
+	 */
150
+	public function order()
151
+	{
152
+		return $this->get('QSO_option');
153
+	}
154
+
155
+
156
+	/**
157
+	 * Gets the related question's ID
158
+	 *
159
+	 * @return int
160
+	 */
161
+	public function question_ID()
162
+	{
163
+		return $this->get('QST_ID');
164
+	}
165
+
166
+
167
+	/**
168
+	 * Returns the question related to this question option
169
+	 *
170
+	 * @return EE_Question
171
+	 */
172
+	public function question()
173
+	{
174
+		return $this->get_first_related('Question');
175
+	}
176
+
177
+
178
+	/**
179
+	 * Gets the option's opt_group
180
+	 *
181
+	 * @return string
182
+	 */
183
+	public function opt_group()
184
+	{
185
+		return $this->_QSO_opt_group;
186
+	}
187
+
188
+	/**
189
+	 * Duplicates this question option. By default the new question option will be for the same question,
190
+	 * but that can be overriden by setting the 'QST_ID' option
191
+	 *
192
+	 * @param array $options {
193
+	 * @type int    $QST_ID  the QST_ID attribute of this question option, otherwise it will be for the same question
194
+	 *                       as the original
195
+	 */
196
+	public function duplicate($options = array())
197
+	{
198
+		$new_question_option = clone $this;
199
+		$new_question_option->set('QSO_ID', null);
200
+		if (array_key_exists(
201
+			'QST_ID',
202
+			$options
203
+		)) {// use array_key_exists instead of isset because NULL might be a valid value
204
+			$new_question_option->set_question_ID($options['QST_ID']);
205
+		}
206
+		$new_question_option->save();
207
+	}
208
+
209
+	/**
210
+	 * Gets the QSO_system value
211
+	 *
212
+	 * @return string|null
213
+	 */
214
+	public function system()
215
+	{
216
+		return $this->get('QSO_system');
217
+	}
218
+
219
+	/**
220
+	 * Sets QSO_system
221
+	 *
222
+	 * @param string $QSO_system
223
+	 * @return bool
224
+	 */
225
+	public function set_system($QSO_system)
226
+	{
227
+		return $this->set('QSO_system', $QSO_system);
228
+	}
229 229
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Payment_Method.class.php 2 patches
Indentation   +568 added lines, -568 removed lines patch added patch discarded remove patch
@@ -11,578 +11,578 @@
 block discarded – undo
11 11
 class EE_Payment_Method extends EE_Base_Class
12 12
 {
13 13
 
14
-    /**
15
-     * Payment Method type object, which has all the info about this type of payment method,
16
-     * including functions for processing payments, to get settings forms, etc.
17
-     *
18
-     * @var EE_PMT_Base
19
-     */
20
-    protected $_type_obj;
21
-
22
-
23
-    /**
24
-     * @param array $props_n_values
25
-     * @return EE_Payment_Method
26
-     * @throws \EE_Error
27
-     */
28
-    public static function new_instance($props_n_values = array())
29
-    {
30
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__);
31
-        return $has_object ? $has_object : new self($props_n_values, false);
32
-    }
33
-
34
-
35
-    /**
36
-     * @param array $props_n_values
37
-     * @return EE_Payment_Method
38
-     * @throws \EE_Error
39
-     */
40
-    public static function new_instance_from_db($props_n_values = array())
41
-    {
42
-        return new self($props_n_values, true);
43
-    }
44
-
45
-
46
-
47
-    /**
48
-     * Checks if there is a payment method class of the given 'PMD_type', and if so returns the classname.
49
-     * Otherwise returns a normal EE_Payment_Method
50
-     *
51
-     * @param array $props_n_values where 'PMD_type' is a gateway name like 'Paypal_Standard','Invoice',etc (basically
52
-     *                              the classname minus 'EEPM_')
53
-     * @return string
54
-     */
55
-    // private static function _payment_method_type($props_n_values)
56
-    // {
57
-    //     EE_Registry::instance()->load_lib('Payment_Method_Manager');
58
-    //     $type_string = isset($props_n_values['PMD_type']) ? $props_n_values['PMD_type'] : null;
59
-    //     if (EE_Payment_Method_Manager::instance()->payment_method_type_exists($type_string)) {
60
-    //         return 'EEPM_' . $type_string;
61
-    //     } else {
62
-    //         return __CLASS__;
63
-    //     }
64
-    // }
65
-
66
-
67
-    /**
68
-     * Gets whether this payment method can be used anywhere at all (ie frontend cart, admin, etc)
69
-     *
70
-     * @return boolean
71
-     */
72
-    public function active()
73
-    {
74
-        return array_intersect(array_keys(EEM_Payment_Method::instance()->scopes()), $this->scope());
75
-    }
76
-
77
-
78
-    /**
79
-     * Sets this PM as active by making it usable within the CART scope. Offline gateways
80
-     * are also usable from the admin-scope as well. DOES NOT SAVE it
81
-     *
82
-     * @throws \EE_Error
83
-     */
84
-    public function set_active()
85
-    {
86
-        $default_scopes = array(EEM_Payment_Method::scope_cart);
87
-        if ($this->type_obj() &&
88
-            $this->type_obj()->payment_occurs() === EE_PMT_Base::offline) {
89
-            $default_scopes[] = EEM_Payment_Method::scope_admin;
90
-        }
91
-        $this->set_scope($default_scopes);
92
-    }
93
-
94
-
95
-    /**
96
-     * Makes this payment method apply to NO scopes at all. DOES NOT SAVE it.
97
-     */
98
-    public function deactivate()
99
-    {
100
-        $this->set_scope(array());
101
-    }
102
-
103
-
104
-    /**
105
-     * Gets button_url
106
-     *
107
-     * @return string
108
-     */
109
-    public function button_url()
110
-    {
111
-        return $this->get('PMD_button_url');
112
-    }
113
-
114
-
115
-    /**
116
-     * Sets button_url
117
-     *
118
-     * @param string $button_url
119
-     */
120
-    public function set_button_url($button_url)
121
-    {
122
-        $this->set('PMD_button_url', $button_url);
123
-    }
124
-
125
-
126
-    /**
127
-     * Gets debug_mode
128
-     *
129
-     * @return boolean
130
-     */
131
-    public function debug_mode()
132
-    {
133
-        return $this->get('PMD_debug_mode');
134
-    }
135
-
136
-
137
-    /**
138
-     * Sets debug_mode
139
-     *
140
-     * @param boolean $debug_mode
141
-     */
142
-    public function set_debug_mode($debug_mode)
143
-    {
144
-        $this->set('PMD_debug_mode', $debug_mode);
145
-    }
146
-
147
-
148
-    /**
149
-     * Gets description
150
-     *
151
-     * @return string
152
-     */
153
-    public function description()
154
-    {
155
-        return $this->get('PMD_desc');
156
-    }
157
-
158
-
159
-    /**
160
-     * Sets description
161
-     *
162
-     * @param string $description
163
-     */
164
-    public function set_description($description)
165
-    {
166
-        $this->set('PMD_desc', $description);
167
-    }
168
-
169
-
170
-    /**
171
-     * Gets name
172
-     *
173
-     * @return string
174
-     */
175
-    public function name()
176
-    {
177
-        return $this->get('PMD_name');
178
-    }
179
-
180
-
181
-    /**
182
-     * Sets name
183
-     *
184
-     * @param string $name
185
-     */
186
-    public function set_name($name)
187
-    {
188
-        $this->set('PMD_name', $name);
189
-    }
190
-
191
-
192
-    /**
193
-     * Gets open_by_default
194
-     *
195
-     * @return boolean
196
-     */
197
-    public function open_by_default()
198
-    {
199
-        return $this->get('PMD_open_by_default');
200
-    }
201
-
202
-
203
-    /**
204
-     * Sets open_by_default
205
-     *
206
-     * @param boolean $open_by_default
207
-     */
208
-    public function set_open_by_default($open_by_default)
209
-    {
210
-        $this->set('PMD_open_by_default', $open_by_default);
211
-    }
212
-
213
-
214
-    /**
215
-     * Gets order
216
-     *
217
-     * @return int
218
-     */
219
-    public function order()
220
-    {
221
-        return $this->get('PMD_order');
222
-    }
223
-
224
-
225
-    /**
226
-     * Sets order
227
-     *
228
-     * @param int $order
229
-     */
230
-    public function set_order($order)
231
-    {
232
-        $this->set('PMD_order', $order);
233
-    }
234
-
235
-
236
-    /**
237
-     * Gets slug
238
-     *
239
-     * @return string
240
-     */
241
-    public function slug()
242
-    {
243
-        return $this->get('PMD_slug');
244
-    }
245
-
246
-
247
-    /**
248
-     * Sets slug
249
-     *
250
-     * @param string $slug
251
-     */
252
-    public function set_slug($slug)
253
-    {
254
-        $this->set('PMD_slug', $slug);
255
-    }
256
-
257
-
258
-    /**
259
-     * Gets type
260
-     *
261
-     * @return string
262
-     */
263
-    public function type()
264
-    {
265
-        return $this->get('PMD_type');
266
-    }
267
-
268
-
269
-    /**
270
-     * Sets type
271
-     *
272
-     * @param string $type
273
-     */
274
-    public function set_type($type)
275
-    {
276
-        $this->set('PMD_type', $type);
277
-    }
278
-
279
-
280
-    /**
281
-     * Gets wp_user
282
-     *
283
-     * @return int
284
-     */
285
-    public function wp_user()
286
-    {
287
-        return $this->get('PMD_wp_user');
288
-    }
289
-
290
-
291
-    /**
292
-     * Sets wp_user
293
-     *
294
-     * @param int $wp_user_id
295
-     */
296
-    public function set_wp_user($wp_user_id)
297
-    {
298
-        $this->set('PMD_wp_user', $wp_user_id);
299
-    }
300
-
301
-    /**
302
-     * Overrides parent so when PMD_type is changed we refresh the _type_obj
303
-     *
304
-     * @param string $field_name
305
-     * @param mixed $field_value
306
-     * @param boolean $use_default
307
-     */
308
-    public function set($field_name, $field_value, $use_default = false)
309
-    {
310
-        if ($field_name === 'PMD_type') {
311
-            // the type has probably changed, so forget about its old type object
312
-            $this->_type_obj = null;
313
-        }
314
-        parent::set($field_name, $field_value, $use_default);
315
-    }
316
-
317
-
318
-    /**
319
-     * Gets admin_name
320
-     *
321
-     * @return string
322
-     */
323
-    public function admin_name()
324
-    {
325
-        return $this->get('PMD_admin_name');
326
-    }
327
-
328
-
329
-    /**
330
-     * Sets admin_name
331
-     *
332
-     * @param string $admin_name
333
-     */
334
-    public function set_admin_name($admin_name)
335
-    {
336
-        $this->set('PMD_admin_name', $admin_name);
337
-    }
338
-
339
-
340
-    /**
341
-     * Gets admin_desc
342
-     *
343
-     * @return string
344
-     */
345
-    public function admin_desc()
346
-    {
347
-        return $this->get('PMD_admin_desc');
348
-    }
349
-
350
-
351
-    /**
352
-     * Sets admin_desc
353
-     *
354
-     * @param string $admin_desc
355
-     */
356
-    public function set_admin_desc($admin_desc)
357
-    {
358
-        $this->set('PMD_admin_desc', $admin_desc);
359
-    }
360
-
361
-
362
-    /**
363
-     * Gets scope
364
-     *
365
-     * @return array
366
-     */
367
-    public function scope()
368
-    {
369
-        return $this->get('PMD_scope');
370
-    }
371
-
372
-
373
-    /**
374
-     * Sets scope
375
-     *
376
-     * @param array $scope
377
-     */
378
-    public function set_scope($scope)
379
-    {
380
-        $this->set('PMD_scope', $scope);
381
-    }
382
-
383
-
384
-    /**
385
-     * Gets the payment method type for this payment method instance
386
-     *
387
-     * @return EE_PMT_Base
388
-     * @throws EE_Error
389
-     */
390
-    public function type_obj()
391
-    {
392
-        if (! $this->_type_obj) {
393
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
394
-            if (EE_Payment_Method_Manager::instance()->payment_method_type_exists($this->type())) {
395
-                $class_name = EE_Payment_Method_Manager::instance()->payment_method_class_from_type($this->type());
396
-                if (! class_exists($class_name)) {
397
-                    throw new EE_Error(
398
-                        sprintf(
399
-                            __(
400
-                                'An attempt to use the "%1$s" payment method failed, so it was deactivated.%2$sWas the "%1$s" Plugin recently deactivated? It can be reactivated on the %3$sPlugins Admin Page%4$s',
401
-                                'event_espresso'
402
-                            ),
403
-                            $class_name,
404
-                            '<br />',
405
-                            '<a href="' . admin_url('plugins.php') . '">',
406
-                            '</a>'
407
-                        )
408
-                    );
409
-                }
410
-                $r = new ReflectionClass($class_name);
411
-                $this->_type_obj = $r->newInstanceArgs(array($this));
412
-            } else {
413
-                throw new EE_Error(
414
-                    sprintf(
415
-                        __(
416
-                            'A payment method of type "%1$s" does not exist. Only ones existing are: %2$s',
417
-                            'event_espresso'
418
-                        ),
419
-                        $this->type(),
420
-                        implode(',', EE_Payment_Method_Manager::instance()->payment_method_type_names())
421
-                    )
422
-                );
423
-            }
424
-        }
425
-        return $this->_type_obj;
426
-    }
427
-
428
-
429
-    /**
430
-     * Returns a simple array of key-value pairs combining the payment method's fields (without the 'PMD_' prefix)
431
-     * and the extra meta. Mostly used for passing off ot gateways.     *
432
-     *
433
-     * @return array
434
-     */
435
-    public function settings_array()
436
-    {
437
-        $fields = $this->model_field_array();
438
-        $extra_meta = $this->all_extra_meta_array();
439
-        // remove the model's prefix from the fields
440
-        $combined_settings_array = array();
441
-        foreach ($fields as $key => $value) {
442
-            if (strpos($key, 'PMD_') === 0) {
443
-                $key_sans_model_prefix = str_replace('PMD_', '', $key);
444
-                $combined_settings_array [ $key_sans_model_prefix ] = $value;
445
-            }
446
-        }
447
-        $combined_settings_array = array_merge($extra_meta, $combined_settings_array);
448
-        return $combined_settings_array;
449
-    }
450
-
451
-
452
-    /**
453
-     * Gets the HTML for displaying the payment method on a page.
454
-     *
455
-     * @param string $url
456
-     * @param string $css_class
457
-     * @return string of HTML for displaying the button
458
-     * @throws \EE_Error
459
-     */
460
-    public function button_html($url = '', $css_class = '')
461
-    {
462
-        $payment_occurs = $this->type_obj()->payment_occurs();
463
-        return '
14
+	/**
15
+	 * Payment Method type object, which has all the info about this type of payment method,
16
+	 * including functions for processing payments, to get settings forms, etc.
17
+	 *
18
+	 * @var EE_PMT_Base
19
+	 */
20
+	protected $_type_obj;
21
+
22
+
23
+	/**
24
+	 * @param array $props_n_values
25
+	 * @return EE_Payment_Method
26
+	 * @throws \EE_Error
27
+	 */
28
+	public static function new_instance($props_n_values = array())
29
+	{
30
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__);
31
+		return $has_object ? $has_object : new self($props_n_values, false);
32
+	}
33
+
34
+
35
+	/**
36
+	 * @param array $props_n_values
37
+	 * @return EE_Payment_Method
38
+	 * @throws \EE_Error
39
+	 */
40
+	public static function new_instance_from_db($props_n_values = array())
41
+	{
42
+		return new self($props_n_values, true);
43
+	}
44
+
45
+
46
+
47
+	/**
48
+	 * Checks if there is a payment method class of the given 'PMD_type', and if so returns the classname.
49
+	 * Otherwise returns a normal EE_Payment_Method
50
+	 *
51
+	 * @param array $props_n_values where 'PMD_type' is a gateway name like 'Paypal_Standard','Invoice',etc (basically
52
+	 *                              the classname minus 'EEPM_')
53
+	 * @return string
54
+	 */
55
+	// private static function _payment_method_type($props_n_values)
56
+	// {
57
+	//     EE_Registry::instance()->load_lib('Payment_Method_Manager');
58
+	//     $type_string = isset($props_n_values['PMD_type']) ? $props_n_values['PMD_type'] : null;
59
+	//     if (EE_Payment_Method_Manager::instance()->payment_method_type_exists($type_string)) {
60
+	//         return 'EEPM_' . $type_string;
61
+	//     } else {
62
+	//         return __CLASS__;
63
+	//     }
64
+	// }
65
+
66
+
67
+	/**
68
+	 * Gets whether this payment method can be used anywhere at all (ie frontend cart, admin, etc)
69
+	 *
70
+	 * @return boolean
71
+	 */
72
+	public function active()
73
+	{
74
+		return array_intersect(array_keys(EEM_Payment_Method::instance()->scopes()), $this->scope());
75
+	}
76
+
77
+
78
+	/**
79
+	 * Sets this PM as active by making it usable within the CART scope. Offline gateways
80
+	 * are also usable from the admin-scope as well. DOES NOT SAVE it
81
+	 *
82
+	 * @throws \EE_Error
83
+	 */
84
+	public function set_active()
85
+	{
86
+		$default_scopes = array(EEM_Payment_Method::scope_cart);
87
+		if ($this->type_obj() &&
88
+			$this->type_obj()->payment_occurs() === EE_PMT_Base::offline) {
89
+			$default_scopes[] = EEM_Payment_Method::scope_admin;
90
+		}
91
+		$this->set_scope($default_scopes);
92
+	}
93
+
94
+
95
+	/**
96
+	 * Makes this payment method apply to NO scopes at all. DOES NOT SAVE it.
97
+	 */
98
+	public function deactivate()
99
+	{
100
+		$this->set_scope(array());
101
+	}
102
+
103
+
104
+	/**
105
+	 * Gets button_url
106
+	 *
107
+	 * @return string
108
+	 */
109
+	public function button_url()
110
+	{
111
+		return $this->get('PMD_button_url');
112
+	}
113
+
114
+
115
+	/**
116
+	 * Sets button_url
117
+	 *
118
+	 * @param string $button_url
119
+	 */
120
+	public function set_button_url($button_url)
121
+	{
122
+		$this->set('PMD_button_url', $button_url);
123
+	}
124
+
125
+
126
+	/**
127
+	 * Gets debug_mode
128
+	 *
129
+	 * @return boolean
130
+	 */
131
+	public function debug_mode()
132
+	{
133
+		return $this->get('PMD_debug_mode');
134
+	}
135
+
136
+
137
+	/**
138
+	 * Sets debug_mode
139
+	 *
140
+	 * @param boolean $debug_mode
141
+	 */
142
+	public function set_debug_mode($debug_mode)
143
+	{
144
+		$this->set('PMD_debug_mode', $debug_mode);
145
+	}
146
+
147
+
148
+	/**
149
+	 * Gets description
150
+	 *
151
+	 * @return string
152
+	 */
153
+	public function description()
154
+	{
155
+		return $this->get('PMD_desc');
156
+	}
157
+
158
+
159
+	/**
160
+	 * Sets description
161
+	 *
162
+	 * @param string $description
163
+	 */
164
+	public function set_description($description)
165
+	{
166
+		$this->set('PMD_desc', $description);
167
+	}
168
+
169
+
170
+	/**
171
+	 * Gets name
172
+	 *
173
+	 * @return string
174
+	 */
175
+	public function name()
176
+	{
177
+		return $this->get('PMD_name');
178
+	}
179
+
180
+
181
+	/**
182
+	 * Sets name
183
+	 *
184
+	 * @param string $name
185
+	 */
186
+	public function set_name($name)
187
+	{
188
+		$this->set('PMD_name', $name);
189
+	}
190
+
191
+
192
+	/**
193
+	 * Gets open_by_default
194
+	 *
195
+	 * @return boolean
196
+	 */
197
+	public function open_by_default()
198
+	{
199
+		return $this->get('PMD_open_by_default');
200
+	}
201
+
202
+
203
+	/**
204
+	 * Sets open_by_default
205
+	 *
206
+	 * @param boolean $open_by_default
207
+	 */
208
+	public function set_open_by_default($open_by_default)
209
+	{
210
+		$this->set('PMD_open_by_default', $open_by_default);
211
+	}
212
+
213
+
214
+	/**
215
+	 * Gets order
216
+	 *
217
+	 * @return int
218
+	 */
219
+	public function order()
220
+	{
221
+		return $this->get('PMD_order');
222
+	}
223
+
224
+
225
+	/**
226
+	 * Sets order
227
+	 *
228
+	 * @param int $order
229
+	 */
230
+	public function set_order($order)
231
+	{
232
+		$this->set('PMD_order', $order);
233
+	}
234
+
235
+
236
+	/**
237
+	 * Gets slug
238
+	 *
239
+	 * @return string
240
+	 */
241
+	public function slug()
242
+	{
243
+		return $this->get('PMD_slug');
244
+	}
245
+
246
+
247
+	/**
248
+	 * Sets slug
249
+	 *
250
+	 * @param string $slug
251
+	 */
252
+	public function set_slug($slug)
253
+	{
254
+		$this->set('PMD_slug', $slug);
255
+	}
256
+
257
+
258
+	/**
259
+	 * Gets type
260
+	 *
261
+	 * @return string
262
+	 */
263
+	public function type()
264
+	{
265
+		return $this->get('PMD_type');
266
+	}
267
+
268
+
269
+	/**
270
+	 * Sets type
271
+	 *
272
+	 * @param string $type
273
+	 */
274
+	public function set_type($type)
275
+	{
276
+		$this->set('PMD_type', $type);
277
+	}
278
+
279
+
280
+	/**
281
+	 * Gets wp_user
282
+	 *
283
+	 * @return int
284
+	 */
285
+	public function wp_user()
286
+	{
287
+		return $this->get('PMD_wp_user');
288
+	}
289
+
290
+
291
+	/**
292
+	 * Sets wp_user
293
+	 *
294
+	 * @param int $wp_user_id
295
+	 */
296
+	public function set_wp_user($wp_user_id)
297
+	{
298
+		$this->set('PMD_wp_user', $wp_user_id);
299
+	}
300
+
301
+	/**
302
+	 * Overrides parent so when PMD_type is changed we refresh the _type_obj
303
+	 *
304
+	 * @param string $field_name
305
+	 * @param mixed $field_value
306
+	 * @param boolean $use_default
307
+	 */
308
+	public function set($field_name, $field_value, $use_default = false)
309
+	{
310
+		if ($field_name === 'PMD_type') {
311
+			// the type has probably changed, so forget about its old type object
312
+			$this->_type_obj = null;
313
+		}
314
+		parent::set($field_name, $field_value, $use_default);
315
+	}
316
+
317
+
318
+	/**
319
+	 * Gets admin_name
320
+	 *
321
+	 * @return string
322
+	 */
323
+	public function admin_name()
324
+	{
325
+		return $this->get('PMD_admin_name');
326
+	}
327
+
328
+
329
+	/**
330
+	 * Sets admin_name
331
+	 *
332
+	 * @param string $admin_name
333
+	 */
334
+	public function set_admin_name($admin_name)
335
+	{
336
+		$this->set('PMD_admin_name', $admin_name);
337
+	}
338
+
339
+
340
+	/**
341
+	 * Gets admin_desc
342
+	 *
343
+	 * @return string
344
+	 */
345
+	public function admin_desc()
346
+	{
347
+		return $this->get('PMD_admin_desc');
348
+	}
349
+
350
+
351
+	/**
352
+	 * Sets admin_desc
353
+	 *
354
+	 * @param string $admin_desc
355
+	 */
356
+	public function set_admin_desc($admin_desc)
357
+	{
358
+		$this->set('PMD_admin_desc', $admin_desc);
359
+	}
360
+
361
+
362
+	/**
363
+	 * Gets scope
364
+	 *
365
+	 * @return array
366
+	 */
367
+	public function scope()
368
+	{
369
+		return $this->get('PMD_scope');
370
+	}
371
+
372
+
373
+	/**
374
+	 * Sets scope
375
+	 *
376
+	 * @param array $scope
377
+	 */
378
+	public function set_scope($scope)
379
+	{
380
+		$this->set('PMD_scope', $scope);
381
+	}
382
+
383
+
384
+	/**
385
+	 * Gets the payment method type for this payment method instance
386
+	 *
387
+	 * @return EE_PMT_Base
388
+	 * @throws EE_Error
389
+	 */
390
+	public function type_obj()
391
+	{
392
+		if (! $this->_type_obj) {
393
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
394
+			if (EE_Payment_Method_Manager::instance()->payment_method_type_exists($this->type())) {
395
+				$class_name = EE_Payment_Method_Manager::instance()->payment_method_class_from_type($this->type());
396
+				if (! class_exists($class_name)) {
397
+					throw new EE_Error(
398
+						sprintf(
399
+							__(
400
+								'An attempt to use the "%1$s" payment method failed, so it was deactivated.%2$sWas the "%1$s" Plugin recently deactivated? It can be reactivated on the %3$sPlugins Admin Page%4$s',
401
+								'event_espresso'
402
+							),
403
+							$class_name,
404
+							'<br />',
405
+							'<a href="' . admin_url('plugins.php') . '">',
406
+							'</a>'
407
+						)
408
+					);
409
+				}
410
+				$r = new ReflectionClass($class_name);
411
+				$this->_type_obj = $r->newInstanceArgs(array($this));
412
+			} else {
413
+				throw new EE_Error(
414
+					sprintf(
415
+						__(
416
+							'A payment method of type "%1$s" does not exist. Only ones existing are: %2$s',
417
+							'event_espresso'
418
+						),
419
+						$this->type(),
420
+						implode(',', EE_Payment_Method_Manager::instance()->payment_method_type_names())
421
+					)
422
+				);
423
+			}
424
+		}
425
+		return $this->_type_obj;
426
+	}
427
+
428
+
429
+	/**
430
+	 * Returns a simple array of key-value pairs combining the payment method's fields (without the 'PMD_' prefix)
431
+	 * and the extra meta. Mostly used for passing off ot gateways.     *
432
+	 *
433
+	 * @return array
434
+	 */
435
+	public function settings_array()
436
+	{
437
+		$fields = $this->model_field_array();
438
+		$extra_meta = $this->all_extra_meta_array();
439
+		// remove the model's prefix from the fields
440
+		$combined_settings_array = array();
441
+		foreach ($fields as $key => $value) {
442
+			if (strpos($key, 'PMD_') === 0) {
443
+				$key_sans_model_prefix = str_replace('PMD_', '', $key);
444
+				$combined_settings_array [ $key_sans_model_prefix ] = $value;
445
+			}
446
+		}
447
+		$combined_settings_array = array_merge($extra_meta, $combined_settings_array);
448
+		return $combined_settings_array;
449
+	}
450
+
451
+
452
+	/**
453
+	 * Gets the HTML for displaying the payment method on a page.
454
+	 *
455
+	 * @param string $url
456
+	 * @param string $css_class
457
+	 * @return string of HTML for displaying the button
458
+	 * @throws \EE_Error
459
+	 */
460
+	public function button_html($url = '', $css_class = '')
461
+	{
462
+		$payment_occurs = $this->type_obj()->payment_occurs();
463
+		return '
464 464
 		 <div id="'
465
-               . $this->slug()
466
-               . '-payment-option-dv" class="'
467
-               . $payment_occurs . '-payment-gateway reg-page-payment-option-dv' . $css_class . '">
465
+			   . $this->slug()
466
+			   . '-payment-option-dv" class="'
467
+			   . $payment_occurs . '-payment-gateway reg-page-payment-option-dv' . $css_class . '">
468 468
 			<a id="payment-gateway-button-' . $this->slug()
469
-               . '" class="reg-page-payment-option-lnk" rel="'
470
-               . $this->slug() . '" href="' . $url . '" >
469
+			   . '" class="reg-page-payment-option-lnk" rel="'
470
+			   . $this->slug() . '" href="' . $url . '" >
471 471
 				<img src="' . $this->button_url() . '" alt="' . sprintf(
472
-                   esc_attr__('Pay using %s', 'event_espresso'),
473
-                   $this->get_pretty('PMD_name', 'form_input')
474
-               ) . '" />
472
+				   esc_attr__('Pay using %s', 'event_espresso'),
473
+				   $this->get_pretty('PMD_name', 'form_input')
474
+			   ) . '" />
475 475
 			</a>
476 476
 		</div>
477 477
 ';
478
-    }
479
-
480
-
481
-    /**
482
-     * Gets all the currencies which are an option for this payment method
483
-     * (as defined by the gateway and the currently active currencies)
484
-     *
485
-     * @return EE_Currency[]
486
-     * @throws \EE_Error
487
-     */
488
-    public function get_all_usable_currencies()
489
-    {
490
-        return EEM_Currency::instance()->get_all_currencies_usable_by($this->type_obj());
491
-    }
492
-
493
-
494
-    /**
495
-     * Reports whether or not this payment method can be used for this payment method
496
-     *
497
-     * @param string $currency_code currency ID (code)
498
-     * @return boolean
499
-     * @throws \EE_Error
500
-     */
501
-    public function usable_for_currency($currency_code)
502
-    {
503
-        foreach ($this->get_all_usable_currencies() as $currency_obj) {
504
-            if ($currency_obj->ID() === $currency_code) {
505
-                return true;
506
-            }
507
-        }
508
-        return false;
509
-    }
510
-
511
-
512
-    /**
513
-     * Returns TRUE if this payment method's gateway is an instance of EE_Onsite_Gateway
514
-     *
515
-     * @return bool
516
-     * @throws \EE_Error
517
-     */
518
-    public function is_on_site()
519
-    {
520
-        return $this->type_obj()->payment_occurs() === EE_PMT_Base::onsite;
521
-    }
522
-
523
-
524
-    /**
525
-     * Returns TRUE if this payment method's gateway is an instance of EE_Offsite_Gateway
526
-     *
527
-     * @return bool
528
-     * @throws \EE_Error
529
-     */
530
-    public function is_off_site()
531
-    {
532
-        return $this->type_obj()->payment_occurs() === EE_PMT_Base::offsite;
533
-    }
534
-
535
-
536
-    /**
537
-     * Returns TRUE if this payment method does not utilize a gateway
538
-     *
539
-     * @return bool
540
-     * @throws \EE_Error
541
-     */
542
-    public function is_off_line()
543
-    {
544
-        return $this->type_obj()->payment_occurs() === EE_PMT_Base::offline;
545
-    }
546
-
547
-    /**
548
-     * Overrides default __sleep so the object type is NOT cached.
549
-     * This way we can rely on the normal EE_Payment_Method::type_obj() logic
550
-     * to load the required classes, and don't need them at the time of unserialization
551
-     *
552
-     * @return array
553
-     */
554
-    public function __sleep()
555
-    {
556
-        $properties = get_object_vars($this);
557
-        unset($properties['_type_obj']);
558
-        return array_keys($properties);
559
-    }
560
-
561
-
562
-    /**
563
-     * Overrides parent to add some logging for when payment methods get deactivated
564
-     *
565
-     * @param array $set_cols_n_values
566
-     * @return int @see EE_Base_Class::save()
567
-     * @throws \EE_Error
568
-     */
569
-    public function save($set_cols_n_values = array())
570
-    {
571
-        $results = parent::save($set_cols_n_values);
572
-        if ($this->get_original('PMD_scope') !== $this->get('PMD_scope')) {
573
-            EE_Log::instance()->log(
574
-                __FILE__,
575
-                __FUNCTION__,
576
-                sprintf(
577
-                    __('Set new scope on payment method %1$s to %2$s from %3$s on URL %4$s', 'event_espresso'),
578
-                    $this->name(),
579
-                    serialize($this->get_original('PMD_scope')),
580
-                    serialize($this->get('PMD_scope')),
581
-                    EE_Registry::instance()->REQ->get_current_page_permalink()
582
-                ),
583
-                'payment_method_change'
584
-            );
585
-        }
586
-        return $results;
587
-    }
478
+	}
479
+
480
+
481
+	/**
482
+	 * Gets all the currencies which are an option for this payment method
483
+	 * (as defined by the gateway and the currently active currencies)
484
+	 *
485
+	 * @return EE_Currency[]
486
+	 * @throws \EE_Error
487
+	 */
488
+	public function get_all_usable_currencies()
489
+	{
490
+		return EEM_Currency::instance()->get_all_currencies_usable_by($this->type_obj());
491
+	}
492
+
493
+
494
+	/**
495
+	 * Reports whether or not this payment method can be used for this payment method
496
+	 *
497
+	 * @param string $currency_code currency ID (code)
498
+	 * @return boolean
499
+	 * @throws \EE_Error
500
+	 */
501
+	public function usable_for_currency($currency_code)
502
+	{
503
+		foreach ($this->get_all_usable_currencies() as $currency_obj) {
504
+			if ($currency_obj->ID() === $currency_code) {
505
+				return true;
506
+			}
507
+		}
508
+		return false;
509
+	}
510
+
511
+
512
+	/**
513
+	 * Returns TRUE if this payment method's gateway is an instance of EE_Onsite_Gateway
514
+	 *
515
+	 * @return bool
516
+	 * @throws \EE_Error
517
+	 */
518
+	public function is_on_site()
519
+	{
520
+		return $this->type_obj()->payment_occurs() === EE_PMT_Base::onsite;
521
+	}
522
+
523
+
524
+	/**
525
+	 * Returns TRUE if this payment method's gateway is an instance of EE_Offsite_Gateway
526
+	 *
527
+	 * @return bool
528
+	 * @throws \EE_Error
529
+	 */
530
+	public function is_off_site()
531
+	{
532
+		return $this->type_obj()->payment_occurs() === EE_PMT_Base::offsite;
533
+	}
534
+
535
+
536
+	/**
537
+	 * Returns TRUE if this payment method does not utilize a gateway
538
+	 *
539
+	 * @return bool
540
+	 * @throws \EE_Error
541
+	 */
542
+	public function is_off_line()
543
+	{
544
+		return $this->type_obj()->payment_occurs() === EE_PMT_Base::offline;
545
+	}
546
+
547
+	/**
548
+	 * Overrides default __sleep so the object type is NOT cached.
549
+	 * This way we can rely on the normal EE_Payment_Method::type_obj() logic
550
+	 * to load the required classes, and don't need them at the time of unserialization
551
+	 *
552
+	 * @return array
553
+	 */
554
+	public function __sleep()
555
+	{
556
+		$properties = get_object_vars($this);
557
+		unset($properties['_type_obj']);
558
+		return array_keys($properties);
559
+	}
560
+
561
+
562
+	/**
563
+	 * Overrides parent to add some logging for when payment methods get deactivated
564
+	 *
565
+	 * @param array $set_cols_n_values
566
+	 * @return int @see EE_Base_Class::save()
567
+	 * @throws \EE_Error
568
+	 */
569
+	public function save($set_cols_n_values = array())
570
+	{
571
+		$results = parent::save($set_cols_n_values);
572
+		if ($this->get_original('PMD_scope') !== $this->get('PMD_scope')) {
573
+			EE_Log::instance()->log(
574
+				__FILE__,
575
+				__FUNCTION__,
576
+				sprintf(
577
+					__('Set new scope on payment method %1$s to %2$s from %3$s on URL %4$s', 'event_espresso'),
578
+					$this->name(),
579
+					serialize($this->get_original('PMD_scope')),
580
+					serialize($this->get('PMD_scope')),
581
+					EE_Registry::instance()->REQ->get_current_page_permalink()
582
+				),
583
+				'payment_method_change'
584
+			);
585
+		}
586
+		return $results;
587
+	}
588 588
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -389,11 +389,11 @@  discard block
 block discarded – undo
389 389
      */
390 390
     public function type_obj()
391 391
     {
392
-        if (! $this->_type_obj) {
392
+        if ( ! $this->_type_obj) {
393 393
             EE_Registry::instance()->load_lib('Payment_Method_Manager');
394 394
             if (EE_Payment_Method_Manager::instance()->payment_method_type_exists($this->type())) {
395 395
                 $class_name = EE_Payment_Method_Manager::instance()->payment_method_class_from_type($this->type());
396
-                if (! class_exists($class_name)) {
396
+                if ( ! class_exists($class_name)) {
397 397
                     throw new EE_Error(
398 398
                         sprintf(
399 399
                             __(
@@ -402,7 +402,7 @@  discard block
 block discarded – undo
402 402
                             ),
403 403
                             $class_name,
404 404
                             '<br />',
405
-                            '<a href="' . admin_url('plugins.php') . '">',
405
+                            '<a href="'.admin_url('plugins.php').'">',
406 406
                             '</a>'
407 407
                         )
408 408
                     );
@@ -441,7 +441,7 @@  discard block
 block discarded – undo
441 441
         foreach ($fields as $key => $value) {
442 442
             if (strpos($key, 'PMD_') === 0) {
443 443
                 $key_sans_model_prefix = str_replace('PMD_', '', $key);
444
-                $combined_settings_array [ $key_sans_model_prefix ] = $value;
444
+                $combined_settings_array [$key_sans_model_prefix] = $value;
445 445
             }
446 446
         }
447 447
         $combined_settings_array = array_merge($extra_meta, $combined_settings_array);
@@ -464,14 +464,14 @@  discard block
 block discarded – undo
464 464
 		 <div id="'
465 465
                . $this->slug()
466 466
                . '-payment-option-dv" class="'
467
-               . $payment_occurs . '-payment-gateway reg-page-payment-option-dv' . $css_class . '">
467
+               . $payment_occurs.'-payment-gateway reg-page-payment-option-dv'.$css_class.'">
468 468
 			<a id="payment-gateway-button-' . $this->slug()
469 469
                . '" class="reg-page-payment-option-lnk" rel="'
470
-               . $this->slug() . '" href="' . $url . '" >
471
-				<img src="' . $this->button_url() . '" alt="' . sprintf(
470
+               . $this->slug().'" href="'.$url.'" >
471
+				<img src="' . $this->button_url().'" alt="'.sprintf(
472 472
                    esc_attr__('Pay using %s', 'event_espresso'),
473 473
                    $this->get_pretty('PMD_name', 'form_input')
474
-               ) . '" />
474
+               ).'" />
475 475
 			</a>
476 476
 		</div>
477 477
 ';
Please login to merge, or discard this patch.
core/db_classes/EE_Event_Venue.class.php 1 patch
Indentation   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -6,23 +6,23 @@
 block discarded – undo
6 6
 class EE_Event_Venue extends EE_Base_Class
7 7
 {
8 8
 
9
-    /**
10
-     * @param array $props_n_values
11
-     * @return EE_Event_Venue|mixed
12
-     */
13
-    public static function new_instance($props_n_values = array())
14
-    {
15
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__);
16
-        return $has_object ? $has_object : new self($props_n_values);
17
-    }
9
+	/**
10
+	 * @param array $props_n_values
11
+	 * @return EE_Event_Venue|mixed
12
+	 */
13
+	public static function new_instance($props_n_values = array())
14
+	{
15
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__);
16
+		return $has_object ? $has_object : new self($props_n_values);
17
+	}
18 18
 
19 19
 
20
-    /**
21
-     * @param array $props_n_values
22
-     * @return EE_Event_Venue
23
-     */
24
-    public static function new_instance_from_db($props_n_values = array())
25
-    {
26
-        return new self($props_n_values, true);
27
-    }
20
+	/**
21
+	 * @param array $props_n_values
22
+	 * @return EE_Event_Venue
23
+	 */
24
+	public static function new_instance_from_db($props_n_values = array())
25
+	{
26
+		return new self($props_n_values, true);
27
+	}
28 28
 }
Please login to merge, or discard this patch.