Completed
Branch BUG/11155/fix-payment-capabili... (cfe1f5)
by
unknown
26:10 queued 13:36
created
core/services/context/ContextChecker.php 2 patches
Indentation   +143 added lines, -143 removed lines patch added patch discarded remove patch
@@ -22,148 +22,148 @@
 block discarded – undo
22 22
 class ContextChecker
23 23
 {
24 24
 
25
-    /**
26
-     * A unique string used to identify where this ContextChecker is being employed
27
-     * Is currently only used within the hook name for the filterable return value of isAllowed().
28
-     *
29
-     * @var string $identifier
30
-     */
31
-    private $identifier;
32
-
33
-    /**
34
-     * A list of values to be compared against the slug of the Context class passed to isAllowed()
35
-     *
36
-     * @var array $acceptable_values
37
-     */
38
-    private $acceptable_values;
39
-
40
-    /**
41
-     * Closure that will be called to perform the evaluation within isAllowed().
42
-     * If none is provided, then a simple type sensitive in_array() check will be used
43
-     * and return true if the incoming Context::slug() is found within the array of $acceptable_values.
44
-     *
45
-     * @var Closure $evaluation_callback
46
-     */
47
-    private $evaluation_callback;
48
-
49
-
50
-    /**
51
-     * ContextChecker constructor.
52
-     *
53
-     * @param string       $identifier
54
-     * @param array        $acceptable_values
55
-     * @param Closure|null $evaluation_callback [optional]
56
-     */
57
-    public function __construct($identifier, array $acceptable_values, Closure $evaluation_callback = null)
58
-    {
59
-        $this->setIdentifier($identifier);
60
-        $this->setAcceptableValues($acceptable_values);
61
-        $this->setEvaluationCallback($evaluation_callback);
62
-    }
63
-
64
-
65
-    /**
66
-     * @param string $identifier
67
-     */
68
-    private function setIdentifier($identifier)
69
-    {
70
-        $this->identifier = sanitize_key($identifier);
71
-    }
72
-
73
-
74
-    /**
75
-     * @param array $acceptable_values
76
-     */
77
-    private function setAcceptableValues(array $acceptable_values)
78
-    {
79
-        $this->acceptable_values = $acceptable_values;
80
-    }
81
-
82
-
83
-    /**
84
-     * @param Closure $evaluation_callback
85
-     */
86
-    private function setEvaluationCallback(Closure $evaluation_callback = null)
87
-    {
88
-        $this->evaluation_callback = $evaluation_callback instanceof Closure
89
-            ? $evaluation_callback
90
-            : function (ContextInterface $context, $acceptable_values) {
91
-                return in_array($context->slug(), $acceptable_values, true);
92
-            };
93
-    }
94
-
95
-
96
-    /**
97
-     * @return string
98
-     */
99
-    protected function identifier()
100
-    {
101
-        return $this->identifier;
102
-    }
103
-
104
-
105
-    /**
106
-     * @return array
107
-     */
108
-    protected function acceptableValues()
109
-    {
110
-        return apply_filters(
111
-            "FHEE__EventEspresso_core_domain_entities_context_ContextChecker__{$this->identifier}__acceptableValues",
112
-            $this->acceptable_values
113
-        );
114
-    }
115
-
116
-
117
-    /**
118
-     * @return Closure
119
-     */
120
-    protected function evaluationCallback()
121
-    {
122
-        return $this->evaluation_callback;
123
-    }
124
-
125
-
126
-
127
-    /**
128
-     * Returns true if the incoming Context class slug matches one of the preset acceptable values.
129
-     * The result is filterable using the identifier for this ContextChecker.
130
-     * example:
131
-     * If this ContextChecker's $identifier was set to "registration-checkout-type",
132
-     * then the filter here would be named:
133
-     *  "FHEE__EventEspresso_core_domain_entities_context_ContextChecker__registration-checkout-type__isAllowed".
134
-     * Other code could hook into the filter in isAllowed() using the above name
135
-     * and test for additional acceptable values.
136
-     * So if the set of $acceptable_values was: [ "initial-visit",  "revisit" ]
137
-     * then adding a filter to
138
-     *  "FHEE__EventEspresso_core_domain_entities_context_ContextChecker__registration-checkout-type__isAllowed",
139
-     * would allow you to perform your own conditional and allow "wait-list-checkout" as an acceptable value.
140
-     *  example:
141
-     *      add_filter(
142
-     *          'FHEE__EventEspresso_core_domain_entities_context_ContextChecker__registration-checkout-type__isAllowed',
143
-     *          function ($is_allowed, ContextInterface $context) {
144
-     *              return $context->slug() === 'wait-list-checkout'
145
-     *                  ? true
146
-     *                  : $is_allowed;
147
-     *          },
148
-     *          10,
149
-     *          2
150
-     *      );
151
-     *
152
-     * @param ContextInterface $context
153
-     * @return boolean
154
-     */
155
-    public function isAllowed(ContextInterface $context)
156
-    {
157
-        $evaluation_callback = $this->evaluationCallback();
158
-        return filter_var(
159
-            apply_filters(
160
-                "FHEE__EventEspresso_core_domain_entities_context_ContextChecker__{$this->identifier}__isAllowed",
161
-                $evaluation_callback($context, $this->acceptableValues()),
162
-                $context,
163
-                $this
164
-            ),
165
-            FILTER_VALIDATE_BOOLEAN
166
-        );
167
-    }
25
+	/**
26
+	 * A unique string used to identify where this ContextChecker is being employed
27
+	 * Is currently only used within the hook name for the filterable return value of isAllowed().
28
+	 *
29
+	 * @var string $identifier
30
+	 */
31
+	private $identifier;
32
+
33
+	/**
34
+	 * A list of values to be compared against the slug of the Context class passed to isAllowed()
35
+	 *
36
+	 * @var array $acceptable_values
37
+	 */
38
+	private $acceptable_values;
39
+
40
+	/**
41
+	 * Closure that will be called to perform the evaluation within isAllowed().
42
+	 * If none is provided, then a simple type sensitive in_array() check will be used
43
+	 * and return true if the incoming Context::slug() is found within the array of $acceptable_values.
44
+	 *
45
+	 * @var Closure $evaluation_callback
46
+	 */
47
+	private $evaluation_callback;
48
+
49
+
50
+	/**
51
+	 * ContextChecker constructor.
52
+	 *
53
+	 * @param string       $identifier
54
+	 * @param array        $acceptable_values
55
+	 * @param Closure|null $evaluation_callback [optional]
56
+	 */
57
+	public function __construct($identifier, array $acceptable_values, Closure $evaluation_callback = null)
58
+	{
59
+		$this->setIdentifier($identifier);
60
+		$this->setAcceptableValues($acceptable_values);
61
+		$this->setEvaluationCallback($evaluation_callback);
62
+	}
63
+
64
+
65
+	/**
66
+	 * @param string $identifier
67
+	 */
68
+	private function setIdentifier($identifier)
69
+	{
70
+		$this->identifier = sanitize_key($identifier);
71
+	}
72
+
73
+
74
+	/**
75
+	 * @param array $acceptable_values
76
+	 */
77
+	private function setAcceptableValues(array $acceptable_values)
78
+	{
79
+		$this->acceptable_values = $acceptable_values;
80
+	}
81
+
82
+
83
+	/**
84
+	 * @param Closure $evaluation_callback
85
+	 */
86
+	private function setEvaluationCallback(Closure $evaluation_callback = null)
87
+	{
88
+		$this->evaluation_callback = $evaluation_callback instanceof Closure
89
+			? $evaluation_callback
90
+			: function (ContextInterface $context, $acceptable_values) {
91
+				return in_array($context->slug(), $acceptable_values, true);
92
+			};
93
+	}
94
+
95
+
96
+	/**
97
+	 * @return string
98
+	 */
99
+	protected function identifier()
100
+	{
101
+		return $this->identifier;
102
+	}
103
+
104
+
105
+	/**
106
+	 * @return array
107
+	 */
108
+	protected function acceptableValues()
109
+	{
110
+		return apply_filters(
111
+			"FHEE__EventEspresso_core_domain_entities_context_ContextChecker__{$this->identifier}__acceptableValues",
112
+			$this->acceptable_values
113
+		);
114
+	}
115
+
116
+
117
+	/**
118
+	 * @return Closure
119
+	 */
120
+	protected function evaluationCallback()
121
+	{
122
+		return $this->evaluation_callback;
123
+	}
124
+
125
+
126
+
127
+	/**
128
+	 * Returns true if the incoming Context class slug matches one of the preset acceptable values.
129
+	 * The result is filterable using the identifier for this ContextChecker.
130
+	 * example:
131
+	 * If this ContextChecker's $identifier was set to "registration-checkout-type",
132
+	 * then the filter here would be named:
133
+	 *  "FHEE__EventEspresso_core_domain_entities_context_ContextChecker__registration-checkout-type__isAllowed".
134
+	 * Other code could hook into the filter in isAllowed() using the above name
135
+	 * and test for additional acceptable values.
136
+	 * So if the set of $acceptable_values was: [ "initial-visit",  "revisit" ]
137
+	 * then adding a filter to
138
+	 *  "FHEE__EventEspresso_core_domain_entities_context_ContextChecker__registration-checkout-type__isAllowed",
139
+	 * would allow you to perform your own conditional and allow "wait-list-checkout" as an acceptable value.
140
+	 *  example:
141
+	 *      add_filter(
142
+	 *          'FHEE__EventEspresso_core_domain_entities_context_ContextChecker__registration-checkout-type__isAllowed',
143
+	 *          function ($is_allowed, ContextInterface $context) {
144
+	 *              return $context->slug() === 'wait-list-checkout'
145
+	 *                  ? true
146
+	 *                  : $is_allowed;
147
+	 *          },
148
+	 *          10,
149
+	 *          2
150
+	 *      );
151
+	 *
152
+	 * @param ContextInterface $context
153
+	 * @return boolean
154
+	 */
155
+	public function isAllowed(ContextInterface $context)
156
+	{
157
+		$evaluation_callback = $this->evaluationCallback();
158
+		return filter_var(
159
+			apply_filters(
160
+				"FHEE__EventEspresso_core_domain_entities_context_ContextChecker__{$this->identifier}__isAllowed",
161
+				$evaluation_callback($context, $this->acceptableValues()),
162
+				$context,
163
+				$this
164
+			),
165
+			FILTER_VALIDATE_BOOLEAN
166
+		);
167
+	}
168 168
 
169 169
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -87,7 +87,7 @@
 block discarded – undo
87 87
     {
88 88
         $this->evaluation_callback = $evaluation_callback instanceof Closure
89 89
             ? $evaluation_callback
90
-            : function (ContextInterface $context, $acceptable_values) {
90
+            : function(ContextInterface $context, $acceptable_values) {
91 91
                 return in_array($context->slug(), $acceptable_values, true);
92 92
             };
93 93
     }
Please login to merge, or discard this patch.
core/db_classes/EE_Registration.class.php 1 patch
Indentation   +1979 added lines, -1979 removed lines patch added patch discarded remove patch
@@ -18,1985 +18,1985 @@
 block discarded – undo
18 18
 {
19 19
 
20 20
 
21
-    /**
22
-     * Used to reference when a registration has never been checked in.
23
-     *
24
-     * @deprecated use \EE_Checkin::status_checked_never instead
25
-     * @type int
26
-     */
27
-    const checkin_status_never = 2;
28
-
29
-    /**
30
-     * Used to reference when a registration has been checked in.
31
-     *
32
-     * @deprecated use \EE_Checkin::status_checked_in instead
33
-     * @type int
34
-     */
35
-    const checkin_status_in = 1;
36
-
37
-
38
-    /**
39
-     * Used to reference when a registration has been checked out.
40
-     *
41
-     * @deprecated use \EE_Checkin::status_checked_out instead
42
-     * @type int
43
-     */
44
-    const checkin_status_out = 0;
45
-
46
-
47
-    /**
48
-     * extra meta key for tracking reg status os trashed registrations
49
-     *
50
-     * @type string
51
-     */
52
-    const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
53
-
54
-
55
-    /**
56
-     * extra meta key for tracking if registration has reserved ticket
57
-     *
58
-     * @type string
59
-     */
60
-    const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
61
-
62
-
63
-    /**
64
-     * @param array  $props_n_values          incoming values
65
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
66
-     *                                        used.)
67
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
68
-     *                                        date_format and the second value is the time format
69
-     * @return EE_Registration
70
-     * @throws EE_Error
71
-     */
72
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
73
-    {
74
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
75
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
76
-    }
77
-
78
-
79
-    /**
80
-     * @param array  $props_n_values  incoming values from the database
81
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
82
-     *                                the website will be used.
83
-     * @return EE_Registration
84
-     */
85
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
86
-    {
87
-        return new self($props_n_values, true, $timezone);
88
-    }
89
-
90
-
91
-    /**
92
-     *        Set Event ID
93
-     *
94
-     * @param        int $EVT_ID Event ID
95
-     * @throws EE_Error
96
-     * @throws RuntimeException
97
-     */
98
-    public function set_event($EVT_ID = 0)
99
-    {
100
-        $this->set('EVT_ID', $EVT_ID);
101
-    }
102
-
103
-
104
-    /**
105
-     * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
106
-     * be routed to internal methods
107
-     *
108
-     * @param string $field_name
109
-     * @param mixed  $field_value
110
-     * @param bool   $use_default
111
-     * @throws EE_Error
112
-     * @throws EntityNotFoundException
113
-     * @throws InvalidArgumentException
114
-     * @throws InvalidDataTypeException
115
-     * @throws InvalidInterfaceException
116
-     * @throws ReflectionException
117
-     * @throws RuntimeException
118
-     */
119
-    public function set($field_name, $field_value, $use_default = false)
120
-    {
121
-        switch ($field_name) {
122
-            case 'REG_code':
123
-                if (! empty($field_value) && $this->reg_code() === null) {
124
-                    $this->set_reg_code($field_value, $use_default);
125
-                }
126
-                break;
127
-            case 'STS_ID':
128
-                $this->set_status($field_value, $use_default);
129
-                break;
130
-            default:
131
-                parent::set($field_name, $field_value, $use_default);
132
-        }
133
-    }
134
-
135
-
136
-    /**
137
-     * Set Status ID
138
-     * updates the registration status and ALSO...
139
-     * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
140
-     * calls release_registration_space() if the reg status changes FROM approved to any other reg status
141
-     *
142
-     * @param string       $new_STS_ID
143
-     * @param boolean      $use_default
144
-     * @param ContextInterface|null $context
145
-     * @return bool
146
-     * @throws EE_Error
147
-     * @throws EntityNotFoundException
148
-     * @throws InvalidArgumentException
149
-     * @throws ReflectionException
150
-     * @throws RuntimeException
151
-     * @throws InvalidDataTypeException
152
-     * @throws InvalidInterfaceException
153
-     */
154
-    public function set_status($new_STS_ID = null, $use_default = false, ContextInterface $context = null)
155
-    {
156
-        // get current REG_Status
157
-        $old_STS_ID = $this->status_ID();
158
-        // if status has changed
159
-        if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
160
-            && ! empty($old_STS_ID) // and that old status is actually set
161
-            && ! empty($new_STS_ID) // as well as the new status
162
-            && $this->ID() // ensure registration is in the db
163
-        ) {
164
-            // TO approved
165
-            if ($new_STS_ID === EEM_Registration::status_id_approved) {
166
-                // reserve a space by incrementing ticket and datetime sold values
167
-                $this->_reserve_registration_space();
168
-                do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
169
-                // OR FROM  approved
170
-            } elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
171
-                // release a space by decrementing ticket and datetime sold values
172
-                $this->_release_registration_space();
173
-                do_action(
174
-                    'AHEE__EE_Registration__set_status__from_approved',
175
-                    $this,
176
-                    $old_STS_ID,
177
-                    $new_STS_ID,
178
-                    $context
179
-                );
180
-            }
181
-            // update status
182
-            parent::set('STS_ID', $new_STS_ID, $use_default);
183
-            $this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, $context);
184
-            if($this->statusChangeUpdatesTransaction($context)) {
185
-                $this->updateTransactionAfterStatusChange();
186
-            }
187
-            do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
188
-            return true;
189
-        }
190
-        //even though the old value matches the new value, it's still good to
191
-        //allow the parent set method to have a say
192
-        parent::set('STS_ID', $new_STS_ID, $use_default);
193
-        return true;
194
-    }
195
-
196
-
197
-    /**
198
-     * update REGs and TXN when cancelled or declined registrations involved
199
-     *
200
-     * @param string       $new_STS_ID
201
-     * @param string       $old_STS_ID
202
-     * @param ContextInterface|null $context
203
-     * @throws EE_Error
204
-     * @throws InvalidArgumentException
205
-     * @throws InvalidDataTypeException
206
-     * @throws InvalidInterfaceException
207
-     * @throws ReflectionException
208
-     */
209
-    private function _update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, ContextInterface $context = null)
210
-    {
211
-        // these reg statuses should not be considered in any calculations involving monies owing
212
-        $closed_reg_statuses = EEM_Registration::closed_reg_statuses();
213
-        // true if registration has been cancelled or declined
214
-        $this->updateIfCanceled(
215
-            $closed_reg_statuses,
216
-            $new_STS_ID,
217
-            $old_STS_ID,
218
-            $context
219
-        );
220
-        $this->updateIfDeclined(
221
-            $closed_reg_statuses,
222
-            $new_STS_ID,
223
-            $old_STS_ID,
224
-            $context
225
-        );
226
-    }
227
-
228
-
229
-    /**
230
-     * update REGs and TXN when cancelled or declined registrations involved
231
-     *
232
-     * @param array        $closed_reg_statuses
233
-     * @param string       $new_STS_ID
234
-     * @param string       $old_STS_ID
235
-     * @param ContextInterface|null $context
236
-     * @throws EE_Error
237
-     * @throws InvalidArgumentException
238
-     * @throws InvalidDataTypeException
239
-     * @throws InvalidInterfaceException
240
-     * @throws ReflectionException
241
-     */
242
-    private function updateIfCanceled(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, ContextInterface $context = null)
243
-    {
244
-        // true if registration has been cancelled or declined
245
-        if (in_array($new_STS_ID, $closed_reg_statuses, true)
246
-            && ! in_array($old_STS_ID, $closed_reg_statuses, true)
247
-        ) {
248
-            /** @type EE_Registration_Processor $registration_processor */
249
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
250
-            /** @type EE_Transaction_Processor $transaction_processor */
251
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
252
-            // cancelled or declined registration
253
-            $registration_processor->update_registration_after_being_canceled_or_declined(
254
-                $this,
255
-                $closed_reg_statuses
256
-            );
257
-            $transaction_processor->update_transaction_after_canceled_or_declined_registration(
258
-                $this,
259
-                $closed_reg_statuses,
260
-                false
261
-            );
262
-            do_action(
263
-                'AHEE__EE_Registration__set_status__canceled_or_declined',
264
-                $this,
265
-                $old_STS_ID,
266
-                $new_STS_ID,
267
-                $context
268
-            );
269
-            return;
270
-        }
271
-    }
272
-
273
-
274
-    /**
275
-     * update REGs and TXN when cancelled or declined registrations involved
276
-     *
277
-     * @param array        $closed_reg_statuses
278
-     * @param string       $new_STS_ID
279
-     * @param string       $old_STS_ID
280
-     * @param ContextInterface|null $context
281
-     * @throws EE_Error
282
-     * @throws InvalidArgumentException
283
-     * @throws InvalidDataTypeException
284
-     * @throws InvalidInterfaceException
285
-     * @throws ReflectionException
286
-     */
287
-    private function updateIfDeclined(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, ContextInterface $context = null)
288
-    {
289
-        // true if reinstating cancelled or declined registration
290
-        if (in_array($old_STS_ID, $closed_reg_statuses, true)
291
-            && ! in_array($new_STS_ID, $closed_reg_statuses, true)
292
-        ) {
293
-            /** @type EE_Registration_Processor $registration_processor */
294
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
295
-            /** @type EE_Transaction_Processor $transaction_processor */
296
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
297
-            // reinstating cancelled or declined registration
298
-            $registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
299
-                $this,
300
-                $closed_reg_statuses
301
-            );
302
-            $transaction_processor->update_transaction_after_reinstating_canceled_registration(
303
-                $this,
304
-                $closed_reg_statuses,
305
-                false
306
-            );
307
-            do_action(
308
-                'AHEE__EE_Registration__set_status__after_reinstated',
309
-                $this,
310
-                $old_STS_ID,
311
-                $new_STS_ID,
312
-                $context
313
-            );
314
-        }
315
-    }
316
-
317
-
318
-    /**
319
-     * @param ContextInterface|null $context
320
-     * @return bool
321
-     */
322
-    private function statusChangeUpdatesTransaction(ContextInterface $context = null)
323
-    {
324
-        $contexts_that_do_not_update_transaction = (array) apply_filters(
325
-            'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
326
-            array('spco_reg_step_attendee_information_process_registrations'),
327
-            $context,
328
-            $this
329
-        );
330
-        return ! (
331
-            $context instanceof ContextInterface
332
-            && in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
333
-        );
334
-    }
335
-
336
-
337
-    /**
338
-     * @throws EE_Error
339
-     * @throws EntityNotFoundException
340
-     * @throws InvalidArgumentException
341
-     * @throws InvalidDataTypeException
342
-     * @throws InvalidInterfaceException
343
-     * @throws ReflectionException
344
-     * @throws RuntimeException
345
-     */
346
-    private function updateTransactionAfterStatusChange()
347
-    {
348
-        /** @type EE_Transaction_Payments $transaction_payments */
349
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
350
-        $transaction_payments->recalculate_transaction_total($this->transaction(), false);
351
-        $this->transaction()->update_status_based_on_total_paid(true);
352
-    }
353
-
354
-
355
-    /**
356
-     *        get Status ID
357
-     */
358
-    public function status_ID()
359
-    {
360
-        return $this->get('STS_ID');
361
-    }
362
-
363
-
364
-    /**
365
-     * increments this registration's related ticket sold and corresponding datetime sold values
366
-     *
367
-     * @return void
368
-     * @throws EE_Error
369
-     * @throws EntityNotFoundException
370
-     */
371
-    private function _reserve_registration_space()
372
-    {
373
-        // reserved ticket and datetime counts will be decremented as sold counts are incremented
374
-        // so stop tracking that this reg has a ticket reserved
375
-        $this->release_reserved_ticket();
376
-        $ticket = $this->ticket();
377
-        $ticket->increase_sold();
378
-        $ticket->save();
379
-        // possibly set event status to sold out
380
-        $this->event()->perform_sold_out_status_check();
381
-    }
382
-
383
-
384
-    /**
385
-     * Gets the ticket this registration is for
386
-     *
387
-     * @param boolean $include_archived whether to include archived tickets or not.
388
-     *
389
-     * @return EE_Ticket|EE_Base_Class
390
-     * @throws EE_Error
391
-     */
392
-    public function ticket($include_archived = true)
393
-    {
394
-        $query_params = array();
395
-        if ($include_archived) {
396
-            $query_params['default_where_conditions'] = 'none';
397
-        }
398
-        return $this->get_first_related('Ticket', $query_params);
399
-    }
400
-
401
-
402
-    /**
403
-     * Gets the event this registration is for
404
-     *
405
-     * @return EE_Event
406
-     * @throws EE_Error
407
-     * @throws EntityNotFoundException
408
-     */
409
-    public function event()
410
-    {
411
-        $event = $this->get_first_related('Event');
412
-        if (! $event instanceof \EE_Event) {
413
-            throw new EntityNotFoundException('Event ID', $this->event_ID());
414
-        }
415
-        return $event;
416
-    }
417
-
418
-
419
-    /**
420
-     * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
421
-     * with the author of the event this registration is for.
422
-     *
423
-     * @since 4.5.0
424
-     * @return int
425
-     * @throws EE_Error
426
-     * @throws EntityNotFoundException
427
-     */
428
-    public function wp_user()
429
-    {
430
-        $event = $this->event();
431
-        if ($event instanceof EE_Event) {
432
-            return $event->wp_user();
433
-        }
434
-        return 0;
435
-    }
436
-
437
-
438
-    /**
439
-     * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
440
-     *
441
-     * @return void
442
-     * @throws EE_Error
443
-     */
444
-    private function _release_registration_space()
445
-    {
446
-        $ticket = $this->ticket();
447
-        $ticket->decrease_sold();
448
-        $ticket->save();
449
-    }
450
-
451
-
452
-    /**
453
-     * tracks this registration's ticket reservation in extra meta
454
-     * and can increment related ticket reserved and corresponding datetime reserved values
455
-     *
456
-     * @param bool $update_ticket if true, will increment ticket and datetime reserved count
457
-     *
458
-     * @return void
459
-     * @throws EE_Error
460
-     */
461
-    public function reserve_ticket($update_ticket = false)
462
-    {
463
-        if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) === false) {
464
-            // PLZ NOTE: although checking $update_ticket first would be more efficient,
465
-            // we NEED to ALWAYS call update_extra_meta(), which is why that is done first
466
-            if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) && $update_ticket) {
467
-                $ticket = $this->ticket();
468
-                $ticket->increase_reserved();
469
-                $ticket->save();
470
-            }
471
-        }
472
-    }
473
-
474
-
475
-    /**
476
-     * stops tracking this registration's ticket reservation in extra meta
477
-     * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
478
-     *
479
-     * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
480
-     *
481
-     * @return void
482
-     * @throws EE_Error
483
-     */
484
-    public function release_reserved_ticket($update_ticket = false)
485
-    {
486
-        if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) !== false) {
487
-            // PLZ NOTE: although checking $update_ticket first would be more efficient,
488
-            // we NEED to ALWAYS call delete_extra_meta(), which is why that is done first
489
-            if ($this->delete_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY) && $update_ticket) {
490
-                $ticket = $this->ticket();
491
-                $ticket->decrease_reserved();
492
-                $ticket->save();
493
-            }
494
-        }
495
-    }
496
-
497
-
498
-    /**
499
-     * Set Attendee ID
500
-     *
501
-     * @param        int $ATT_ID Attendee ID
502
-     * @throws EE_Error
503
-     * @throws RuntimeException
504
-     */
505
-    public function set_attendee_id($ATT_ID = 0)
506
-    {
507
-        $this->set('ATT_ID', $ATT_ID);
508
-    }
509
-
510
-
511
-    /**
512
-     *        Set Transaction ID
513
-     *
514
-     * @param        int $TXN_ID Transaction ID
515
-     * @throws EE_Error
516
-     * @throws RuntimeException
517
-     */
518
-    public function set_transaction_id($TXN_ID = 0)
519
-    {
520
-        $this->set('TXN_ID', $TXN_ID);
521
-    }
522
-
523
-
524
-    /**
525
-     *        Set Session
526
-     *
527
-     * @param    string $REG_session PHP Session ID
528
-     * @throws EE_Error
529
-     * @throws RuntimeException
530
-     */
531
-    public function set_session($REG_session = '')
532
-    {
533
-        $this->set('REG_session', $REG_session);
534
-    }
535
-
536
-
537
-    /**
538
-     *        Set Registration URL Link
539
-     *
540
-     * @param    string $REG_url_link Registration URL Link
541
-     * @throws EE_Error
542
-     * @throws RuntimeException
543
-     */
544
-    public function set_reg_url_link($REG_url_link = '')
545
-    {
546
-        $this->set('REG_url_link', $REG_url_link);
547
-    }
548
-
549
-
550
-    /**
551
-     *        Set Attendee Counter
552
-     *
553
-     * @param        int $REG_count Primary Attendee
554
-     * @throws EE_Error
555
-     * @throws RuntimeException
556
-     */
557
-    public function set_count($REG_count = 1)
558
-    {
559
-        $this->set('REG_count', $REG_count);
560
-    }
561
-
562
-
563
-    /**
564
-     *        Set Group Size
565
-     *
566
-     * @param        boolean $REG_group_size Group Registration
567
-     * @throws EE_Error
568
-     * @throws RuntimeException
569
-     */
570
-    public function set_group_size($REG_group_size = false)
571
-    {
572
-        $this->set('REG_group_size', $REG_group_size);
573
-    }
574
-
575
-
576
-    /**
577
-     *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
578
-     *    EEM_Registration::status_id_not_approved
579
-     *
580
-     * @return        boolean
581
-     */
582
-    public function is_not_approved()
583
-    {
584
-        return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
585
-    }
586
-
587
-
588
-    /**
589
-     *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
590
-     *    EEM_Registration::status_id_pending_payment
591
-     *
592
-     * @return        boolean
593
-     */
594
-    public function is_pending_payment()
595
-    {
596
-        return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
597
-    }
598
-
599
-
600
-    /**
601
-     *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
602
-     *
603
-     * @return        boolean
604
-     */
605
-    public function is_approved()
606
-    {
607
-        return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
608
-    }
609
-
610
-
611
-    /**
612
-     *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
613
-     *
614
-     * @return        boolean
615
-     */
616
-    public function is_cancelled()
617
-    {
618
-        return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
619
-    }
620
-
621
-
622
-    /**
623
-     *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
624
-     *
625
-     * @return        boolean
626
-     */
627
-    public function is_declined()
628
-    {
629
-        return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
630
-    }
631
-
632
-
633
-    /**
634
-     *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
635
-     *    EEM_Registration::status_id_incomplete
636
-     *
637
-     * @return        boolean
638
-     */
639
-    public function is_incomplete()
640
-    {
641
-        return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
642
-    }
643
-
644
-
645
-    /**
646
-     *        Set Registration Date
647
-     *
648
-     * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
649
-     *                                                 Date
650
-     * @throws EE_Error
651
-     * @throws RuntimeException
652
-     */
653
-    public function set_reg_date($REG_date = false)
654
-    {
655
-        $this->set('REG_date', $REG_date);
656
-    }
657
-
658
-
659
-    /**
660
-     *    Set final price owing for this registration after all ticket/price modifications
661
-     *
662
-     * @access    public
663
-     * @param    float $REG_final_price
664
-     * @throws EE_Error
665
-     * @throws RuntimeException
666
-     */
667
-    public function set_final_price($REG_final_price = 0.00)
668
-    {
669
-        $this->set('REG_final_price', $REG_final_price);
670
-    }
671
-
672
-
673
-    /**
674
-     *    Set amount paid towards this registration's final price
675
-     *
676
-     * @access    public
677
-     * @param    float $REG_paid
678
-     * @throws EE_Error
679
-     * @throws RuntimeException
680
-     */
681
-    public function set_paid($REG_paid = 0.00)
682
-    {
683
-        $this->set('REG_paid', $REG_paid);
684
-    }
685
-
686
-
687
-    /**
688
-     *        Attendee Is Going
689
-     *
690
-     * @param        boolean $REG_att_is_going Attendee Is Going
691
-     * @throws EE_Error
692
-     * @throws RuntimeException
693
-     */
694
-    public function set_att_is_going($REG_att_is_going = false)
695
-    {
696
-        $this->set('REG_att_is_going', $REG_att_is_going);
697
-    }
698
-
699
-
700
-    /**
701
-     * Gets the related attendee
702
-     *
703
-     * @return EE_Attendee
704
-     * @throws EE_Error
705
-     */
706
-    public function attendee()
707
-    {
708
-        return $this->get_first_related('Attendee');
709
-    }
710
-
711
-
712
-    /**
713
-     *        get Event ID
714
-     */
715
-    public function event_ID()
716
-    {
717
-        return $this->get('EVT_ID');
718
-    }
719
-
720
-
721
-    /**
722
-     *        get Event ID
723
-     */
724
-    public function event_name()
725
-    {
726
-        $event = $this->event_obj();
727
-        if ($event) {
728
-            return $event->name();
729
-        } else {
730
-            return null;
731
-        }
732
-    }
733
-
734
-
735
-    /**
736
-     * Fetches the event this registration is for
737
-     *
738
-     * @return EE_Event
739
-     * @throws EE_Error
740
-     */
741
-    public function event_obj()
742
-    {
743
-        return $this->get_first_related('Event');
744
-    }
745
-
746
-
747
-    /**
748
-     *        get Attendee ID
749
-     */
750
-    public function attendee_ID()
751
-    {
752
-        return $this->get('ATT_ID');
753
-    }
754
-
755
-
756
-    /**
757
-     *        get PHP Session ID
758
-     */
759
-    public function session_ID()
760
-    {
761
-        return $this->get('REG_session');
762
-    }
763
-
764
-
765
-    /**
766
-     * Gets the string which represents the URL trigger for the receipt template in the message template system.
767
-     *
768
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
769
-     * @return string
770
-     */
771
-    public function receipt_url($messenger = 'html')
772
-    {
773
-
774
-        /**
775
-         * The below will be deprecated one version after this.  We check first if there is a custom receipt template
776
-         * already in use on old system.  If there is then we just return the standard url for it.
777
-         *
778
-         * @since 4.5.0
779
-         */
780
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
781
-        $has_custom             = EEH_Template::locate_template(
782
-            $template_relative_path,
783
-            array(),
784
-            true,
785
-            true,
786
-            true
787
-        );
788
-
789
-        if ($has_custom) {
790
-            return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
791
-        }
792
-        return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
793
-    }
794
-
795
-
796
-    /**
797
-     * Gets the string which represents the URL trigger for the invoice template in the message template system.
798
-     *
799
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
800
-     * @return string
801
-     * @throws EE_Error
802
-     */
803
-    public function invoice_url($messenger = 'html')
804
-    {
805
-        /**
806
-         * The below will be deprecated one version after this.  We check first if there is a custom invoice template
807
-         * already in use on old system.  If there is then we just return the standard url for it.
808
-         *
809
-         * @since 4.5.0
810
-         */
811
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
812
-        $has_custom             = EEH_Template::locate_template(
813
-            $template_relative_path,
814
-            array(),
815
-            true,
816
-            true,
817
-            true
818
-        );
819
-
820
-        if ($has_custom) {
821
-            if ($messenger == 'html') {
822
-                return $this->invoice_url('launch');
823
-            }
824
-            $route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
825
-
826
-            $query_args = array('ee' => $route, 'id' => $this->reg_url_link());
827
-            if ($messenger == 'html') {
828
-                $query_args['html'] = true;
829
-            }
830
-            return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
831
-        }
832
-        return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
833
-    }
834
-
835
-
836
-    /**
837
-     * get Registration URL Link
838
-     *
839
-     * @access public
840
-     * @return string
841
-     * @throws EE_Error
842
-     */
843
-    public function reg_url_link()
844
-    {
845
-        return (string) $this->get('REG_url_link');
846
-    }
847
-
848
-
849
-    /**
850
-     * Echoes out invoice_url()
851
-     *
852
-     * @param string $type 'download','launch', or 'html' (default is 'launch')
853
-     * @return void
854
-     * @throws EE_Error
855
-     */
856
-    public function e_invoice_url($type = 'launch')
857
-    {
858
-        echo $this->invoice_url($type);
859
-    }
860
-
861
-
862
-    /**
863
-     * Echoes out payment_overview_url
864
-     */
865
-    public function e_payment_overview_url()
866
-    {
867
-        echo $this->payment_overview_url();
868
-    }
869
-
870
-
871
-    /**
872
-     * Gets the URL of the thank you page with this registration REG_url_link added as
873
-     * a query parameter
874
-     *
875
-     * @param bool $clear_session Set to true when you want to clear the session on revisiting the
876
-     *                            payment overview url.
877
-     * @return string
878
-     * @throws EE_Error
879
-     */
880
-    public function payment_overview_url($clear_session = false)
881
-    {
882
-        return add_query_arg(array(
883
-            'e_reg_url_link' => $this->reg_url_link(),
884
-            'step'           => 'payment_options',
885
-            'revisit'        => true,
886
-            'clear_session' => (bool) $clear_session
887
-        ), EE_Registry::instance()->CFG->core->reg_page_url());
888
-    }
889
-
890
-
891
-    /**
892
-     * Gets the URL of the thank you page with this registration REG_url_link added as
893
-     * a query parameter
894
-     *
895
-     * @return string
896
-     * @throws EE_Error
897
-     */
898
-    public function edit_attendee_information_url()
899
-    {
900
-        return add_query_arg(array(
901
-            'e_reg_url_link' => $this->reg_url_link(),
902
-            'step'           => 'attendee_information',
903
-            'revisit'        => true,
904
-        ), EE_Registry::instance()->CFG->core->reg_page_url());
905
-    }
906
-
907
-
908
-    /**
909
-     * Simply generates and returns the appropriate admin_url link to edit this registration
910
-     *
911
-     * @return string
912
-     * @throws EE_Error
913
-     */
914
-    public function get_admin_edit_url()
915
-    {
916
-        return EEH_URL::add_query_args_and_nonce(array(
917
-            'page'    => 'espresso_registrations',
918
-            'action'  => 'view_registration',
919
-            '_REG_ID' => $this->ID(),
920
-        ), admin_url('admin.php'));
921
-    }
922
-
923
-
924
-    /**
925
-     *    is_primary_registrant?
926
-     */
927
-    public function is_primary_registrant()
928
-    {
929
-        return $this->get('REG_count') == 1 ? true : false;
930
-    }
931
-
932
-
933
-    /**
934
-     * This returns the primary registration object for this registration group (which may be this object).
935
-     *
936
-     * @return EE_Registration
937
-     * @throws EE_Error
938
-     */
939
-    public function get_primary_registration()
940
-    {
941
-        if ($this->is_primary_registrant()) {
942
-            return $this;
943
-        }
944
-
945
-        //k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
946
-        /** @var EE_Registration $primary_registrant */
947
-        $primary_registrant = EEM_Registration::instance()->get_one(array(
948
-            array(
949
-                'TXN_ID'    => $this->transaction_ID(),
950
-                'REG_count' => 1,
951
-            ),
952
-        ));
953
-        return $primary_registrant;
954
-    }
955
-
956
-
957
-    /**
958
-     *        get  Attendee Number
959
-     *
960
-     * @access        public
961
-     */
962
-    public function count()
963
-    {
964
-        return $this->get('REG_count');
965
-    }
966
-
967
-
968
-    /**
969
-     *        get Group Size
970
-     */
971
-    public function group_size()
972
-    {
973
-        return $this->get('REG_group_size');
974
-    }
975
-
976
-
977
-    /**
978
-     *        get Registration Date
979
-     */
980
-    public function date()
981
-    {
982
-        return $this->get('REG_date');
983
-    }
984
-
985
-
986
-    /**
987
-     * gets a pretty date
988
-     *
989
-     * @param string $date_format
990
-     * @param string $time_format
991
-     * @return string
992
-     * @throws EE_Error
993
-     */
994
-    public function pretty_date($date_format = null, $time_format = null)
995
-    {
996
-        return $this->get_datetime('REG_date', $date_format, $time_format);
997
-    }
998
-
999
-
1000
-    /**
1001
-     * final_price
1002
-     * the registration's share of the transaction total, so that the
1003
-     * sum of all the transaction's REG_final_prices equal the transaction's total
1004
-     *
1005
-     * @return float
1006
-     * @throws EE_Error
1007
-     */
1008
-    public function final_price()
1009
-    {
1010
-        return $this->get('REG_final_price');
1011
-    }
1012
-
1013
-
1014
-    /**
1015
-     * pretty_final_price
1016
-     *  final price as formatted string, with correct decimal places and currency symbol
1017
-     *
1018
-     * @return string
1019
-     * @throws EE_Error
1020
-     */
1021
-    public function pretty_final_price()
1022
-    {
1023
-        return $this->get_pretty('REG_final_price');
1024
-    }
1025
-
1026
-
1027
-    /**
1028
-     * get paid (yeah)
1029
-     *
1030
-     * @return float
1031
-     * @throws EE_Error
1032
-     */
1033
-    public function paid()
1034
-    {
1035
-        return $this->get('REG_paid');
1036
-    }
1037
-
1038
-
1039
-    /**
1040
-     * pretty_paid
1041
-     *
1042
-     * @return float
1043
-     * @throws EE_Error
1044
-     */
1045
-    public function pretty_paid()
1046
-    {
1047
-        return $this->get_pretty('REG_paid');
1048
-    }
1049
-
1050
-
1051
-    /**
1052
-     * owes_monies_and_can_pay
1053
-     * whether or not this registration has monies owing and it's' status allows payment
1054
-     *
1055
-     * @param array $requires_payment
1056
-     * @return bool
1057
-     * @throws EE_Error
1058
-     */
1059
-    public function owes_monies_and_can_pay($requires_payment = array())
1060
-    {
1061
-        // these reg statuses require payment (if event is not free)
1062
-        $requires_payment = ! empty($requires_payment)
1063
-            ? $requires_payment
1064
-            : EEM_Registration::reg_statuses_that_allow_payment();
1065
-        if (in_array($this->status_ID(), $requires_payment) &&
1066
-            $this->final_price() != 0 &&
1067
-            $this->final_price() != $this->paid()
1068
-        ) {
1069
-            return true;
1070
-        } else {
1071
-            return false;
1072
-        }
1073
-    }
1074
-
1075
-
1076
-    /**
1077
-     * Prints out the return value of $this->pretty_status()
1078
-     *
1079
-     * @param bool $show_icons
1080
-     * @return void
1081
-     * @throws EE_Error
1082
-     */
1083
-    public function e_pretty_status($show_icons = false)
1084
-    {
1085
-        echo $this->pretty_status($show_icons);
1086
-    }
1087
-
1088
-
1089
-    /**
1090
-     * Returns a nice version of the status for displaying to customers
1091
-     *
1092
-     * @param bool $show_icons
1093
-     * @return string
1094
-     * @throws EE_Error
1095
-     */
1096
-    public function pretty_status($show_icons = false)
1097
-    {
1098
-        $status = EEM_Status::instance()->localized_status(
1099
-            array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1100
-            false,
1101
-            'sentence'
1102
-        );
1103
-        $icon   = '';
1104
-        switch ($this->status_ID()) {
1105
-            case EEM_Registration::status_id_approved:
1106
-                $icon = $show_icons
1107
-                    ? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1108
-                    : '';
1109
-                break;
1110
-            case EEM_Registration::status_id_pending_payment:
1111
-                $icon = $show_icons
1112
-                    ? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1113
-                    : '';
1114
-                break;
1115
-            case EEM_Registration::status_id_not_approved:
1116
-                $icon = $show_icons
1117
-                    ? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1118
-                    : '';
1119
-                break;
1120
-            case EEM_Registration::status_id_cancelled:
1121
-                $icon = $show_icons
1122
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1123
-                    : '';
1124
-                break;
1125
-            case EEM_Registration::status_id_incomplete:
1126
-                $icon = $show_icons
1127
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1128
-                    : '';
1129
-                break;
1130
-            case EEM_Registration::status_id_declined:
1131
-                $icon = $show_icons
1132
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1133
-                    : '';
1134
-                break;
1135
-            case EEM_Registration::status_id_wait_list:
1136
-                $icon = $show_icons
1137
-                    ? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1138
-                    : '';
1139
-                break;
1140
-        }
1141
-        return $icon . $status[$this->status_ID()];
1142
-    }
1143
-
1144
-
1145
-    /**
1146
-     *        get Attendee Is Going
1147
-     */
1148
-    public function att_is_going()
1149
-    {
1150
-        return $this->get('REG_att_is_going');
1151
-    }
1152
-
1153
-
1154
-    /**
1155
-     * Gets related answers
1156
-     *
1157
-     * @param array $query_params like EEM_Base::get_all
1158
-     * @return EE_Answer[]
1159
-     * @throws EE_Error
1160
-     */
1161
-    public function answers($query_params = null)
1162
-    {
1163
-        return $this->get_many_related('Answer', $query_params);
1164
-    }
1165
-
1166
-
1167
-    /**
1168
-     * Gets the registration's answer value to the specified question
1169
-     * (either the question's ID or a question object)
1170
-     *
1171
-     * @param EE_Question|int $question
1172
-     * @param bool            $pretty_value
1173
-     * @return array|string if pretty_value= true, the result will always be a string
1174
-     * (because the answer might be an array of answer values, so passing pretty_value=true
1175
-     * will convert it into some kind of string)
1176
-     * @throws EE_Error
1177
-     */
1178
-    public function answer_value_to_question($question, $pretty_value = true)
1179
-    {
1180
-        $question_id = EEM_Question::instance()->ensure_is_ID($question);
1181
-        return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1182
-    }
1183
-
1184
-
1185
-    /**
1186
-     * question_groups
1187
-     * returns an array of EE_Question_Group objects for this registration
1188
-     *
1189
-     * @return EE_Question_Group[]
1190
-     * @throws EE_Error
1191
-     * @throws EntityNotFoundException
1192
-     */
1193
-    public function question_groups()
1194
-    {
1195
-        $question_groups = array();
1196
-        if ($this->event() instanceof EE_Event) {
1197
-            $question_groups = $this->event()->question_groups(
1198
-                array(
1199
-                    array(
1200
-                        'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1201
-                    ),
1202
-                    'order_by' => array('QSG_order' => 'ASC'),
1203
-                )
1204
-            );
1205
-        }
1206
-        return $question_groups;
1207
-    }
1208
-
1209
-
1210
-    /**
1211
-     * count_question_groups
1212
-     * returns a count of the number of EE_Question_Group objects for this registration
1213
-     *
1214
-     * @return int
1215
-     * @throws EE_Error
1216
-     * @throws EntityNotFoundException
1217
-     */
1218
-    public function count_question_groups()
1219
-    {
1220
-        $qg_count = 0;
1221
-        if ($this->event() instanceof EE_Event) {
1222
-            $qg_count = $this->event()->count_related(
1223
-                'Question_Group',
1224
-                array(
1225
-                    array(
1226
-                        'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1227
-                    ),
1228
-                )
1229
-            );
1230
-        }
1231
-        return $qg_count;
1232
-    }
1233
-
1234
-
1235
-    /**
1236
-     * Returns the registration date in the 'standard' string format
1237
-     * (function may be improved in the future to allow for different formats and timezones)
1238
-     *
1239
-     * @return string
1240
-     * @throws EE_Error
1241
-     */
1242
-    public function reg_date()
1243
-    {
1244
-        return $this->get_datetime('REG_date');
1245
-    }
1246
-
1247
-
1248
-    /**
1249
-     * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1250
-     * the ticket this registration purchased, or the datetime they have registered
1251
-     * to attend)
1252
-     *
1253
-     * @return EE_Datetime_Ticket
1254
-     * @throws EE_Error
1255
-     */
1256
-    public function datetime_ticket()
1257
-    {
1258
-        return $this->get_first_related('Datetime_Ticket');
1259
-    }
1260
-
1261
-
1262
-    /**
1263
-     * Sets the registration's datetime_ticket.
1264
-     *
1265
-     * @param EE_Datetime_Ticket $datetime_ticket
1266
-     * @return EE_Datetime_Ticket
1267
-     * @throws EE_Error
1268
-     */
1269
-    public function set_datetime_ticket($datetime_ticket)
1270
-    {
1271
-        return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1272
-    }
1273
-
1274
-    /**
1275
-     * Gets deleted
1276
-     *
1277
-     * @return bool
1278
-     * @throws EE_Error
1279
-     */
1280
-    public function deleted()
1281
-    {
1282
-        return $this->get('REG_deleted');
1283
-    }
1284
-
1285
-    /**
1286
-     * Sets deleted
1287
-     *
1288
-     * @param boolean $deleted
1289
-     * @return bool
1290
-     * @throws EE_Error
1291
-     * @throws RuntimeException
1292
-     */
1293
-    public function set_deleted($deleted)
1294
-    {
1295
-        if ($deleted) {
1296
-            $this->delete();
1297
-        } else {
1298
-            $this->restore();
1299
-        }
1300
-    }
1301
-
1302
-
1303
-    /**
1304
-     * Get the status object of this object
1305
-     *
1306
-     * @return EE_Status
1307
-     * @throws EE_Error
1308
-     */
1309
-    public function status_obj()
1310
-    {
1311
-        return $this->get_first_related('Status');
1312
-    }
1313
-
1314
-
1315
-    /**
1316
-     * Returns the number of times this registration has checked into any of the datetimes
1317
-     * its available for
1318
-     *
1319
-     * @return int
1320
-     * @throws EE_Error
1321
-     */
1322
-    public function count_checkins()
1323
-    {
1324
-        return $this->get_model()->count_related($this, 'Checkin');
1325
-    }
1326
-
1327
-
1328
-    /**
1329
-     * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1330
-     * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1331
-     *
1332
-     * @return int
1333
-     * @throws EE_Error
1334
-     */
1335
-    public function count_checkins_not_checkedout()
1336
-    {
1337
-        return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1338
-    }
1339
-
1340
-
1341
-    /**
1342
-     * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1343
-     *
1344
-     * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1345
-     * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1346
-     *                                          consider registration status as well as datetime access.
1347
-     * @return bool
1348
-     * @throws EE_Error
1349
-     */
1350
-    public function can_checkin($DTT_OR_ID, $check_approved = true)
1351
-    {
1352
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1353
-
1354
-        //first check registration status
1355
-        if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1356
-            return false;
1357
-        }
1358
-        //is there a datetime ticket that matches this dtt_ID?
1359
-        if (! (EEM_Datetime_Ticket::instance()->exists(array(
1360
-            array(
1361
-                'TKT_ID' => $this->get('TKT_ID'),
1362
-                'DTT_ID' => $DTT_ID,
1363
-            ),
1364
-        )))
1365
-        ) {
1366
-            return false;
1367
-        }
1368
-
1369
-        //final check is against TKT_uses
1370
-        return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1371
-    }
1372
-
1373
-
1374
-    /**
1375
-     * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1376
-     * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1377
-     * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1378
-     * then return false.  Otherwise return true.
1379
-     *
1380
-     * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1381
-     * @return bool true means can checkin.  false means cannot checkin.
1382
-     * @throws EE_Error
1383
-     */
1384
-    public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1385
-    {
1386
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1387
-
1388
-        if (! $DTT_ID) {
1389
-            return false;
1390
-        }
1391
-
1392
-        $max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1393
-
1394
-        // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1395
-        // check-in or not.
1396
-        if (! $max_uses || $max_uses === EE_INF) {
1397
-            return true;
1398
-        }
1399
-
1400
-        //does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1401
-        //go ahead and toggle.
1402
-        if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1403
-            return true;
1404
-        }
1405
-
1406
-        //made it here so the last check is whether the number of checkins per unique datetime on this registration
1407
-        //disallows further check-ins.
1408
-        $count_unique_dtt_checkins = EEM_Checkin::instance()->count(array(
1409
-            array(
1410
-                'REG_ID' => $this->ID(),
1411
-                'CHK_in' => true,
1412
-            ),
1413
-        ), 'DTT_ID', true);
1414
-        // checkins have already reached their max number of uses
1415
-        // so registrant can NOT checkin
1416
-        if ($count_unique_dtt_checkins >= $max_uses) {
1417
-            EE_Error::add_error(
1418
-                esc_html__(
1419
-                    'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1420
-                    'event_espresso'
1421
-                ),
1422
-                __FILE__,
1423
-                __FUNCTION__,
1424
-                __LINE__
1425
-            );
1426
-            return false;
1427
-        }
1428
-        return true;
1429
-    }
1430
-
1431
-
1432
-    /**
1433
-     * toggle Check-in status for this registration
1434
-     * Check-ins are toggled in the following order:
1435
-     * never checked in -> checked in
1436
-     * checked in -> checked out
1437
-     * checked out -> checked in
1438
-     *
1439
-     * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1440
-     *                      If not included or null, then it is assumed latest datetime is being toggled.
1441
-     * @param bool $verify  If true then can_checkin() is used to verify whether the person
1442
-     *                      can be checked in or not.  Otherwise this forces change in checkin status.
1443
-     * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1444
-     * @throws EE_Error
1445
-     */
1446
-    public function toggle_checkin_status($DTT_ID = null, $verify = false)
1447
-    {
1448
-        if (empty($DTT_ID)) {
1449
-            $datetime = $this->get_latest_related_datetime();
1450
-            $DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1451
-            // verify the registration can checkin for the given DTT_ID
1452
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1453
-            EE_Error::add_error(
1454
-                sprintf(
1455
-                    esc_html__(
1456
-                        'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1457
-                        'event_espresso'
1458
-                    ),
1459
-                    $this->ID(),
1460
-                    $DTT_ID
1461
-                ),
1462
-                __FILE__,
1463
-                __FUNCTION__,
1464
-                __LINE__
1465
-            );
1466
-            return false;
1467
-        }
1468
-        $status_paths = array(
1469
-            EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1470
-            EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1471
-            EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1472
-        );
1473
-        //start by getting the current status so we know what status we'll be changing to.
1474
-        $cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1475
-        $status_to  = $status_paths[$cur_status];
1476
-        // database only records true for checked IN or false for checked OUT
1477
-        // no record ( null ) means checked in NEVER, but we obviously don't save that
1478
-        $new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1479
-        // add relation - note Check-ins are always creating new rows
1480
-        // because we are keeping track of Check-ins over time.
1481
-        // Eventually we'll probably want to show a list table
1482
-        // for the individual Check-ins so that they can be managed.
1483
-        $checkin = EE_Checkin::new_instance(array(
1484
-            'REG_ID' => $this->ID(),
1485
-            'DTT_ID' => $DTT_ID,
1486
-            'CHK_in' => $new_status,
1487
-        ));
1488
-        // if the record could not be saved then return false
1489
-        if ($checkin->save() === 0) {
1490
-            if (WP_DEBUG) {
1491
-                global $wpdb;
1492
-                $error = sprintf(
1493
-                    esc_html__(
1494
-                        'Registration check in update failed because of the following database error: %1$s%2$s',
1495
-                        'event_espresso'
1496
-                    ),
1497
-                    '<br />',
1498
-                    $wpdb->last_error
1499
-                );
1500
-            } else {
1501
-                $error = esc_html__(
1502
-                    'Registration check in update failed because of an unknown database error',
1503
-                    'event_espresso'
1504
-                );
1505
-            }
1506
-            EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1507
-            return false;
1508
-        }
1509
-        return $status_to;
1510
-    }
1511
-
1512
-
1513
-    /**
1514
-     * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1515
-     * "Latest" is defined by the `DTT_EVT_start` column.
1516
-     *
1517
-     * @return EE_Datetime|null
1518
-     * @throws EE_Error
1519
-     */
1520
-    public function get_latest_related_datetime()
1521
-    {
1522
-        return EEM_Datetime::instance()->get_one(
1523
-            array(
1524
-                array(
1525
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1526
-                ),
1527
-                'order_by' => array('DTT_EVT_start' => 'DESC'),
1528
-            )
1529
-        );
1530
-    }
1531
-
1532
-
1533
-    /**
1534
-     * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1535
-     * "Earliest" is defined by the `DTT_EVT_start` column.
1536
-     *
1537
-     * @throws EE_Error
1538
-     */
1539
-    public function get_earliest_related_datetime()
1540
-    {
1541
-        return EEM_Datetime::instance()->get_one(
1542
-            array(
1543
-                array(
1544
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1545
-                ),
1546
-                'order_by' => array('DTT_EVT_start' => 'ASC'),
1547
-            )
1548
-        );
1549
-    }
1550
-
1551
-
1552
-    /**
1553
-     * This method simply returns the check-in status for this registration and the given datetime.
1554
-     * If neither the datetime nor the checkin values are provided as arguments,
1555
-     * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1556
-     *
1557
-     * @param  int       $DTT_ID  The ID of the datetime we're checking against
1558
-     *                            (if empty we'll get the primary datetime for
1559
-     *                            this registration (via event) and use it's ID);
1560
-     * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1561
-     *
1562
-     * @return int                Integer representing Check-in status.
1563
-     * @throws EE_Error
1564
-     */
1565
-    public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1566
-    {
1567
-        $checkin_query_params = array(
1568
-            'order_by' => array('CHK_timestamp' => 'DESC'),
1569
-        );
1570
-
1571
-        if ($DTT_ID > 0) {
1572
-            $checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1573
-        }
1574
-
1575
-        //get checkin object (if exists)
1576
-        $checkin = $checkin instanceof EE_Checkin
1577
-            ? $checkin
1578
-            : $this->get_first_related('Checkin', $checkin_query_params);
1579
-        if ($checkin instanceof EE_Checkin) {
1580
-            if ($checkin->get('CHK_in')) {
1581
-                return EE_Checkin::status_checked_in; //checked in
1582
-            }
1583
-            return EE_Checkin::status_checked_out; //had checked in but is now checked out.
1584
-        }
1585
-        return EE_Checkin::status_checked_never; //never been checked in
1586
-    }
1587
-
1588
-
1589
-    /**
1590
-     * This method returns a localized message for the toggled Check-in message.
1591
-     *
1592
-     * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1593
-     *                     then it is assumed Check-in for primary datetime was toggled.
1594
-     * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1595
-     *                     message can be customized with the attendee name.
1596
-     * @return string internationalized message
1597
-     * @throws EE_Error
1598
-     */
1599
-    public function get_checkin_msg($DTT_ID, $error = false)
1600
-    {
1601
-        //let's get the attendee first so we can include the name of the attendee
1602
-        $attendee = $this->get_first_related('Attendee');
1603
-        if ($attendee instanceof EE_Attendee) {
1604
-            if ($error) {
1605
-                return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1606
-            }
1607
-            $cur_status = $this->check_in_status_for_datetime($DTT_ID);
1608
-            //what is the status message going to be?
1609
-            switch ($cur_status) {
1610
-                case EE_Checkin::status_checked_never:
1611
-                    return sprintf(__("%s has been removed from Check-in records", "event_espresso"),
1612
-                        $attendee->full_name());
1613
-                    break;
1614
-                case EE_Checkin::status_checked_in:
1615
-                    return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1616
-                    break;
1617
-                case EE_Checkin::status_checked_out:
1618
-                    return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1619
-                    break;
1620
-            }
1621
-        }
1622
-        return esc_html__("The check-in status could not be determined.", "event_espresso");
1623
-    }
1624
-
1625
-
1626
-    /**
1627
-     * Returns the related EE_Transaction to this registration
1628
-     *
1629
-     * @return EE_Transaction
1630
-     * @throws EE_Error
1631
-     * @throws EntityNotFoundException
1632
-     */
1633
-    public function transaction()
1634
-    {
1635
-        $transaction = $this->get_first_related('Transaction');
1636
-        if (! $transaction instanceof \EE_Transaction) {
1637
-            throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1638
-        }
1639
-        return $transaction;
1640
-    }
1641
-
1642
-
1643
-    /**
1644
-     *        get Registration Code
1645
-     */
1646
-    public function reg_code()
1647
-    {
1648
-        return $this->get('REG_code');
1649
-    }
1650
-
1651
-
1652
-    /**
1653
-     *        get Transaction ID
1654
-     */
1655
-    public function transaction_ID()
1656
-    {
1657
-        return $this->get('TXN_ID');
1658
-    }
1659
-
1660
-
1661
-    /**
1662
-     * @return int
1663
-     * @throws EE_Error
1664
-     */
1665
-    public function ticket_ID()
1666
-    {
1667
-        return $this->get('TKT_ID');
1668
-    }
1669
-
1670
-
1671
-    /**
1672
-     *        Set Registration Code
1673
-     *
1674
-     * @access    public
1675
-     * @param    string  $REG_code Registration Code
1676
-     * @param    boolean $use_default
1677
-     * @throws EE_Error
1678
-     */
1679
-    public function set_reg_code($REG_code, $use_default = false)
1680
-    {
1681
-        if (empty($REG_code)) {
1682
-            EE_Error::add_error(
1683
-                esc_html__('REG_code can not be empty.', 'event_espresso'),
1684
-                __FILE__,
1685
-                __FUNCTION__,
1686
-                __LINE__
1687
-            );
1688
-            return;
1689
-        }
1690
-        if (! $this->reg_code()) {
1691
-            parent::set('REG_code', $REG_code, $use_default);
1692
-        } else {
1693
-            EE_Error::doing_it_wrong(
1694
-                __CLASS__ . '::' . __FUNCTION__,
1695
-                esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1696
-                '4.6.0'
1697
-            );
1698
-        }
1699
-    }
1700
-
1701
-
1702
-    /**
1703
-     * Returns all other registrations in the same group as this registrant who have the same ticket option.
1704
-     * Note, if you want to just get all registrations in the same transaction (group), use:
1705
-     *    $registration->transaction()->registrations();
1706
-     *
1707
-     * @since 4.5.0
1708
-     * @return EE_Registration[] or empty array if this isn't a group registration.
1709
-     * @throws EE_Error
1710
-     */
1711
-    public function get_all_other_registrations_in_group()
1712
-    {
1713
-        if ($this->group_size() < 2) {
1714
-            return array();
1715
-        }
1716
-
1717
-        $query[0] = array(
1718
-            'TXN_ID' => $this->transaction_ID(),
1719
-            'REG_ID' => array('!=', $this->ID()),
1720
-            'TKT_ID' => $this->ticket_ID(),
1721
-        );
1722
-        /** @var EE_Registration[] $registrations */
1723
-        $registrations = $this->get_model()->get_all($query);
1724
-        return $registrations;
1725
-    }
1726
-
1727
-    /**
1728
-     * Return the link to the admin details for the object.
1729
-     *
1730
-     * @return string
1731
-     * @throws EE_Error
1732
-     */
1733
-    public function get_admin_details_link()
1734
-    {
1735
-        EE_Registry::instance()->load_helper('URL');
1736
-        return EEH_URL::add_query_args_and_nonce(
1737
-            array(
1738
-                'page'    => 'espresso_registrations',
1739
-                'action'  => 'view_registration',
1740
-                '_REG_ID' => $this->ID(),
1741
-            ),
1742
-            admin_url('admin.php')
1743
-        );
1744
-    }
1745
-
1746
-    /**
1747
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1748
-     *
1749
-     * @return string
1750
-     * @throws EE_Error
1751
-     */
1752
-    public function get_admin_edit_link()
1753
-    {
1754
-        return $this->get_admin_details_link();
1755
-    }
1756
-
1757
-    /**
1758
-     * Returns the link to a settings page for the object.
1759
-     *
1760
-     * @return string
1761
-     * @throws EE_Error
1762
-     */
1763
-    public function get_admin_settings_link()
1764
-    {
1765
-        return $this->get_admin_details_link();
1766
-    }
1767
-
1768
-    /**
1769
-     * Returns the link to the "overview" for the object (typically the "list table" view).
1770
-     *
1771
-     * @return string
1772
-     */
1773
-    public function get_admin_overview_link()
1774
-    {
1775
-        EE_Registry::instance()->load_helper('URL');
1776
-        return EEH_URL::add_query_args_and_nonce(
1777
-            array(
1778
-                'page' => 'espresso_registrations',
1779
-            ),
1780
-            admin_url('admin.php')
1781
-        );
1782
-    }
1783
-
1784
-
1785
-    /**
1786
-     * @param array $query_params
1787
-     *
1788
-     * @return \EE_Registration[]
1789
-     * @throws EE_Error
1790
-     */
1791
-    public function payments($query_params = array())
1792
-    {
1793
-        return $this->get_many_related('Payment', $query_params);
1794
-    }
1795
-
1796
-
1797
-    /**
1798
-     * @param array $query_params
1799
-     *
1800
-     * @return \EE_Registration_Payment[]
1801
-     * @throws EE_Error
1802
-     */
1803
-    public function registration_payments($query_params = array())
1804
-    {
1805
-        return $this->get_many_related('Registration_Payment', $query_params);
1806
-    }
1807
-
1808
-
1809
-    /**
1810
-     * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1811
-     * Note: if there are no payments on the registration there will be no payment method returned.
1812
-     *
1813
-     * @return EE_Payment_Method|null
1814
-     */
1815
-    public function payment_method()
1816
-    {
1817
-        return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1818
-    }
1819
-
1820
-
1821
-    /**
1822
-     * @return \EE_Line_Item
1823
-     * @throws EntityNotFoundException
1824
-     * @throws EE_Error
1825
-     */
1826
-    public function ticket_line_item()
1827
-    {
1828
-        $ticket            = $this->ticket();
1829
-        $transaction       = $this->transaction();
1830
-        $line_item         = null;
1831
-        $ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1832
-            $transaction->total_line_item(),
1833
-            'Ticket',
1834
-            array($ticket->ID())
1835
-        );
1836
-        foreach ($ticket_line_items as $ticket_line_item) {
1837
-            if (
1838
-                $ticket_line_item instanceof \EE_Line_Item
1839
-                && $ticket_line_item->OBJ_type() === 'Ticket'
1840
-                && $ticket_line_item->OBJ_ID() === $ticket->ID()
1841
-            ) {
1842
-                $line_item = $ticket_line_item;
1843
-                break;
1844
-            }
1845
-        }
1846
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1847
-            throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1848
-        }
1849
-        return $line_item;
1850
-    }
1851
-
1852
-
1853
-    /**
1854
-     * Soft Deletes this model object.
1855
-     *
1856
-     * @return boolean | int
1857
-     * @throws RuntimeException
1858
-     * @throws EE_Error
1859
-     */
1860
-    public function delete()
1861
-    {
1862
-        if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1863
-            $this->set_status(EEM_Registration::status_id_cancelled);
1864
-        }
1865
-        return parent::delete();
1866
-    }
1867
-
1868
-
1869
-    /**
1870
-     * Restores whatever the previous status was on a registration before it was trashed (if possible)
1871
-     *
1872
-     * @throws EE_Error
1873
-     * @throws RuntimeException
1874
-     */
1875
-    public function restore()
1876
-    {
1877
-        $previous_status = $this->get_extra_meta(
1878
-            EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1879
-            true,
1880
-            EEM_Registration::status_id_cancelled
1881
-        );
1882
-        if ($previous_status) {
1883
-            $this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1884
-            $this->set_status($previous_status);
1885
-        }
1886
-        return parent::restore();
1887
-    }
1888
-
1889
-
1890
-    /**
1891
-     * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price
1892
-     *
1893
-     * @param  boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic
1894
-     *                                           depending on whether the reg status changes to or from "Approved"
1895
-     * @return boolean whether the Registration status was updated
1896
-     * @throws EE_Error
1897
-     * @throws RuntimeException
1898
-     */
1899
-    public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true)
1900
-    {
1901
-        $paid = $this->paid();
1902
-        $price = $this->final_price();
1903
-        switch(true) {
1904
-            // overpaid or paid
1905
-            case EEH_Money::compare_floats($paid, $price, '>'):
1906
-            case EEH_Money::compare_floats($paid, $price):
1907
-                $new_status = EEM_Registration::status_id_approved;
1908
-                break;
1909
-            //  underpaid
1910
-            case EEH_Money::compare_floats($paid, $price, '<'):
1911
-                $new_status = EEM_Registration::status_id_pending_payment;
1912
-                break;
1913
-            // uhhh Houston...
1914
-            default:
1915
-                throw new RuntimeException(
1916
-                    esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso')
1917
-                );
1918
-        }
1919
-        if ($new_status !== $this->status_ID()) {
1920
-            if ($trigger_set_status_logic) {
1921
-                return $this->set_status($new_status);
1922
-            }
1923
-            parent::set('STS_ID', $new_status);
1924
-            return true;
1925
-        }
1926
-        return false;
1927
-    }
1928
-
1929
-
1930
-    /*************************** DEPRECATED ***************************/
1931
-
1932
-
1933
-    /**
1934
-     * @deprecated
1935
-     * @since     4.7.0
1936
-     * @access    public
1937
-     */
1938
-    public function price_paid()
1939
-    {
1940
-        EE_Error::doing_it_wrong('EE_Registration::price_paid()',
1941
-            esc_html__('This method is deprecated, please use EE_Registration::final_price() instead.', 'event_espresso'),
1942
-            '4.7.0');
1943
-        return $this->final_price();
1944
-    }
1945
-
1946
-
1947
-    /**
1948
-     * @deprecated
1949
-     * @since     4.7.0
1950
-     * @access    public
1951
-     * @param    float $REG_final_price
1952
-     * @throws EE_Error
1953
-     * @throws RuntimeException
1954
-     */
1955
-    public function set_price_paid($REG_final_price = 0.00)
1956
-    {
1957
-        EE_Error::doing_it_wrong('EE_Registration::set_price_paid()',
1958
-            esc_html__('This method is deprecated, please use EE_Registration::set_final_price() instead.', 'event_espresso'),
1959
-            '4.7.0');
1960
-        $this->set_final_price($REG_final_price);
1961
-    }
1962
-
1963
-
1964
-    /**
1965
-     * @deprecated
1966
-     * @since 4.7.0
1967
-     * @return string
1968
-     * @throws EE_Error
1969
-     */
1970
-    public function pretty_price_paid()
1971
-    {
1972
-        EE_Error::doing_it_wrong('EE_Registration::pretty_price_paid()',
1973
-            esc_html__('This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
1974
-                'event_espresso'), '4.7.0');
1975
-        return $this->pretty_final_price();
1976
-    }
1977
-
1978
-
1979
-    /**
1980
-     * Gets the primary datetime related to this registration via the related Event to this registration
1981
-     *
1982
-     * @deprecated 4.9.17
1983
-     * @return EE_Datetime
1984
-     * @throws EE_Error
1985
-     * @throws EntityNotFoundException
1986
-     */
1987
-    public function get_related_primary_datetime()
1988
-    {
1989
-        EE_Error::doing_it_wrong(
1990
-            __METHOD__,
1991
-            esc_html__(
1992
-                'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
1993
-                'event_espresso'
1994
-            ),
1995
-            '4.9.17',
1996
-            '5.0.0'
1997
-        );
1998
-        return $this->event()->primary_datetime();
1999
-    }
21
+	/**
22
+	 * Used to reference when a registration has never been checked in.
23
+	 *
24
+	 * @deprecated use \EE_Checkin::status_checked_never instead
25
+	 * @type int
26
+	 */
27
+	const checkin_status_never = 2;
28
+
29
+	/**
30
+	 * Used to reference when a registration has been checked in.
31
+	 *
32
+	 * @deprecated use \EE_Checkin::status_checked_in instead
33
+	 * @type int
34
+	 */
35
+	const checkin_status_in = 1;
36
+
37
+
38
+	/**
39
+	 * Used to reference when a registration has been checked out.
40
+	 *
41
+	 * @deprecated use \EE_Checkin::status_checked_out instead
42
+	 * @type int
43
+	 */
44
+	const checkin_status_out = 0;
45
+
46
+
47
+	/**
48
+	 * extra meta key for tracking reg status os trashed registrations
49
+	 *
50
+	 * @type string
51
+	 */
52
+	const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
53
+
54
+
55
+	/**
56
+	 * extra meta key for tracking if registration has reserved ticket
57
+	 *
58
+	 * @type string
59
+	 */
60
+	const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
61
+
62
+
63
+	/**
64
+	 * @param array  $props_n_values          incoming values
65
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
66
+	 *                                        used.)
67
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
68
+	 *                                        date_format and the second value is the time format
69
+	 * @return EE_Registration
70
+	 * @throws EE_Error
71
+	 */
72
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
73
+	{
74
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
75
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
76
+	}
77
+
78
+
79
+	/**
80
+	 * @param array  $props_n_values  incoming values from the database
81
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
82
+	 *                                the website will be used.
83
+	 * @return EE_Registration
84
+	 */
85
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
86
+	{
87
+		return new self($props_n_values, true, $timezone);
88
+	}
89
+
90
+
91
+	/**
92
+	 *        Set Event ID
93
+	 *
94
+	 * @param        int $EVT_ID Event ID
95
+	 * @throws EE_Error
96
+	 * @throws RuntimeException
97
+	 */
98
+	public function set_event($EVT_ID = 0)
99
+	{
100
+		$this->set('EVT_ID', $EVT_ID);
101
+	}
102
+
103
+
104
+	/**
105
+	 * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
106
+	 * be routed to internal methods
107
+	 *
108
+	 * @param string $field_name
109
+	 * @param mixed  $field_value
110
+	 * @param bool   $use_default
111
+	 * @throws EE_Error
112
+	 * @throws EntityNotFoundException
113
+	 * @throws InvalidArgumentException
114
+	 * @throws InvalidDataTypeException
115
+	 * @throws InvalidInterfaceException
116
+	 * @throws ReflectionException
117
+	 * @throws RuntimeException
118
+	 */
119
+	public function set($field_name, $field_value, $use_default = false)
120
+	{
121
+		switch ($field_name) {
122
+			case 'REG_code':
123
+				if (! empty($field_value) && $this->reg_code() === null) {
124
+					$this->set_reg_code($field_value, $use_default);
125
+				}
126
+				break;
127
+			case 'STS_ID':
128
+				$this->set_status($field_value, $use_default);
129
+				break;
130
+			default:
131
+				parent::set($field_name, $field_value, $use_default);
132
+		}
133
+	}
134
+
135
+
136
+	/**
137
+	 * Set Status ID
138
+	 * updates the registration status and ALSO...
139
+	 * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
140
+	 * calls release_registration_space() if the reg status changes FROM approved to any other reg status
141
+	 *
142
+	 * @param string       $new_STS_ID
143
+	 * @param boolean      $use_default
144
+	 * @param ContextInterface|null $context
145
+	 * @return bool
146
+	 * @throws EE_Error
147
+	 * @throws EntityNotFoundException
148
+	 * @throws InvalidArgumentException
149
+	 * @throws ReflectionException
150
+	 * @throws RuntimeException
151
+	 * @throws InvalidDataTypeException
152
+	 * @throws InvalidInterfaceException
153
+	 */
154
+	public function set_status($new_STS_ID = null, $use_default = false, ContextInterface $context = null)
155
+	{
156
+		// get current REG_Status
157
+		$old_STS_ID = $this->status_ID();
158
+		// if status has changed
159
+		if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
160
+			&& ! empty($old_STS_ID) // and that old status is actually set
161
+			&& ! empty($new_STS_ID) // as well as the new status
162
+			&& $this->ID() // ensure registration is in the db
163
+		) {
164
+			// TO approved
165
+			if ($new_STS_ID === EEM_Registration::status_id_approved) {
166
+				// reserve a space by incrementing ticket and datetime sold values
167
+				$this->_reserve_registration_space();
168
+				do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
169
+				// OR FROM  approved
170
+			} elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
171
+				// release a space by decrementing ticket and datetime sold values
172
+				$this->_release_registration_space();
173
+				do_action(
174
+					'AHEE__EE_Registration__set_status__from_approved',
175
+					$this,
176
+					$old_STS_ID,
177
+					$new_STS_ID,
178
+					$context
179
+				);
180
+			}
181
+			// update status
182
+			parent::set('STS_ID', $new_STS_ID, $use_default);
183
+			$this->_update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, $context);
184
+			if($this->statusChangeUpdatesTransaction($context)) {
185
+				$this->updateTransactionAfterStatusChange();
186
+			}
187
+			do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
188
+			return true;
189
+		}
190
+		//even though the old value matches the new value, it's still good to
191
+		//allow the parent set method to have a say
192
+		parent::set('STS_ID', $new_STS_ID, $use_default);
193
+		return true;
194
+	}
195
+
196
+
197
+	/**
198
+	 * update REGs and TXN when cancelled or declined registrations involved
199
+	 *
200
+	 * @param string       $new_STS_ID
201
+	 * @param string       $old_STS_ID
202
+	 * @param ContextInterface|null $context
203
+	 * @throws EE_Error
204
+	 * @throws InvalidArgumentException
205
+	 * @throws InvalidDataTypeException
206
+	 * @throws InvalidInterfaceException
207
+	 * @throws ReflectionException
208
+	 */
209
+	private function _update_if_canceled_or_declined($new_STS_ID, $old_STS_ID, ContextInterface $context = null)
210
+	{
211
+		// these reg statuses should not be considered in any calculations involving monies owing
212
+		$closed_reg_statuses = EEM_Registration::closed_reg_statuses();
213
+		// true if registration has been cancelled or declined
214
+		$this->updateIfCanceled(
215
+			$closed_reg_statuses,
216
+			$new_STS_ID,
217
+			$old_STS_ID,
218
+			$context
219
+		);
220
+		$this->updateIfDeclined(
221
+			$closed_reg_statuses,
222
+			$new_STS_ID,
223
+			$old_STS_ID,
224
+			$context
225
+		);
226
+	}
227
+
228
+
229
+	/**
230
+	 * update REGs and TXN when cancelled or declined registrations involved
231
+	 *
232
+	 * @param array        $closed_reg_statuses
233
+	 * @param string       $new_STS_ID
234
+	 * @param string       $old_STS_ID
235
+	 * @param ContextInterface|null $context
236
+	 * @throws EE_Error
237
+	 * @throws InvalidArgumentException
238
+	 * @throws InvalidDataTypeException
239
+	 * @throws InvalidInterfaceException
240
+	 * @throws ReflectionException
241
+	 */
242
+	private function updateIfCanceled(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, ContextInterface $context = null)
243
+	{
244
+		// true if registration has been cancelled or declined
245
+		if (in_array($new_STS_ID, $closed_reg_statuses, true)
246
+			&& ! in_array($old_STS_ID, $closed_reg_statuses, true)
247
+		) {
248
+			/** @type EE_Registration_Processor $registration_processor */
249
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
250
+			/** @type EE_Transaction_Processor $transaction_processor */
251
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
252
+			// cancelled or declined registration
253
+			$registration_processor->update_registration_after_being_canceled_or_declined(
254
+				$this,
255
+				$closed_reg_statuses
256
+			);
257
+			$transaction_processor->update_transaction_after_canceled_or_declined_registration(
258
+				$this,
259
+				$closed_reg_statuses,
260
+				false
261
+			);
262
+			do_action(
263
+				'AHEE__EE_Registration__set_status__canceled_or_declined',
264
+				$this,
265
+				$old_STS_ID,
266
+				$new_STS_ID,
267
+				$context
268
+			);
269
+			return;
270
+		}
271
+	}
272
+
273
+
274
+	/**
275
+	 * update REGs and TXN when cancelled or declined registrations involved
276
+	 *
277
+	 * @param array        $closed_reg_statuses
278
+	 * @param string       $new_STS_ID
279
+	 * @param string       $old_STS_ID
280
+	 * @param ContextInterface|null $context
281
+	 * @throws EE_Error
282
+	 * @throws InvalidArgumentException
283
+	 * @throws InvalidDataTypeException
284
+	 * @throws InvalidInterfaceException
285
+	 * @throws ReflectionException
286
+	 */
287
+	private function updateIfDeclined(array $closed_reg_statuses, $new_STS_ID, $old_STS_ID, ContextInterface $context = null)
288
+	{
289
+		// true if reinstating cancelled or declined registration
290
+		if (in_array($old_STS_ID, $closed_reg_statuses, true)
291
+			&& ! in_array($new_STS_ID, $closed_reg_statuses, true)
292
+		) {
293
+			/** @type EE_Registration_Processor $registration_processor */
294
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
295
+			/** @type EE_Transaction_Processor $transaction_processor */
296
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
297
+			// reinstating cancelled or declined registration
298
+			$registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
299
+				$this,
300
+				$closed_reg_statuses
301
+			);
302
+			$transaction_processor->update_transaction_after_reinstating_canceled_registration(
303
+				$this,
304
+				$closed_reg_statuses,
305
+				false
306
+			);
307
+			do_action(
308
+				'AHEE__EE_Registration__set_status__after_reinstated',
309
+				$this,
310
+				$old_STS_ID,
311
+				$new_STS_ID,
312
+				$context
313
+			);
314
+		}
315
+	}
316
+
317
+
318
+	/**
319
+	 * @param ContextInterface|null $context
320
+	 * @return bool
321
+	 */
322
+	private function statusChangeUpdatesTransaction(ContextInterface $context = null)
323
+	{
324
+		$contexts_that_do_not_update_transaction = (array) apply_filters(
325
+			'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
326
+			array('spco_reg_step_attendee_information_process_registrations'),
327
+			$context,
328
+			$this
329
+		);
330
+		return ! (
331
+			$context instanceof ContextInterface
332
+			&& in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
333
+		);
334
+	}
335
+
336
+
337
+	/**
338
+	 * @throws EE_Error
339
+	 * @throws EntityNotFoundException
340
+	 * @throws InvalidArgumentException
341
+	 * @throws InvalidDataTypeException
342
+	 * @throws InvalidInterfaceException
343
+	 * @throws ReflectionException
344
+	 * @throws RuntimeException
345
+	 */
346
+	private function updateTransactionAfterStatusChange()
347
+	{
348
+		/** @type EE_Transaction_Payments $transaction_payments */
349
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
350
+		$transaction_payments->recalculate_transaction_total($this->transaction(), false);
351
+		$this->transaction()->update_status_based_on_total_paid(true);
352
+	}
353
+
354
+
355
+	/**
356
+	 *        get Status ID
357
+	 */
358
+	public function status_ID()
359
+	{
360
+		return $this->get('STS_ID');
361
+	}
362
+
363
+
364
+	/**
365
+	 * increments this registration's related ticket sold and corresponding datetime sold values
366
+	 *
367
+	 * @return void
368
+	 * @throws EE_Error
369
+	 * @throws EntityNotFoundException
370
+	 */
371
+	private function _reserve_registration_space()
372
+	{
373
+		// reserved ticket and datetime counts will be decremented as sold counts are incremented
374
+		// so stop tracking that this reg has a ticket reserved
375
+		$this->release_reserved_ticket();
376
+		$ticket = $this->ticket();
377
+		$ticket->increase_sold();
378
+		$ticket->save();
379
+		// possibly set event status to sold out
380
+		$this->event()->perform_sold_out_status_check();
381
+	}
382
+
383
+
384
+	/**
385
+	 * Gets the ticket this registration is for
386
+	 *
387
+	 * @param boolean $include_archived whether to include archived tickets or not.
388
+	 *
389
+	 * @return EE_Ticket|EE_Base_Class
390
+	 * @throws EE_Error
391
+	 */
392
+	public function ticket($include_archived = true)
393
+	{
394
+		$query_params = array();
395
+		if ($include_archived) {
396
+			$query_params['default_where_conditions'] = 'none';
397
+		}
398
+		return $this->get_first_related('Ticket', $query_params);
399
+	}
400
+
401
+
402
+	/**
403
+	 * Gets the event this registration is for
404
+	 *
405
+	 * @return EE_Event
406
+	 * @throws EE_Error
407
+	 * @throws EntityNotFoundException
408
+	 */
409
+	public function event()
410
+	{
411
+		$event = $this->get_first_related('Event');
412
+		if (! $event instanceof \EE_Event) {
413
+			throw new EntityNotFoundException('Event ID', $this->event_ID());
414
+		}
415
+		return $event;
416
+	}
417
+
418
+
419
+	/**
420
+	 * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
421
+	 * with the author of the event this registration is for.
422
+	 *
423
+	 * @since 4.5.0
424
+	 * @return int
425
+	 * @throws EE_Error
426
+	 * @throws EntityNotFoundException
427
+	 */
428
+	public function wp_user()
429
+	{
430
+		$event = $this->event();
431
+		if ($event instanceof EE_Event) {
432
+			return $event->wp_user();
433
+		}
434
+		return 0;
435
+	}
436
+
437
+
438
+	/**
439
+	 * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
440
+	 *
441
+	 * @return void
442
+	 * @throws EE_Error
443
+	 */
444
+	private function _release_registration_space()
445
+	{
446
+		$ticket = $this->ticket();
447
+		$ticket->decrease_sold();
448
+		$ticket->save();
449
+	}
450
+
451
+
452
+	/**
453
+	 * tracks this registration's ticket reservation in extra meta
454
+	 * and can increment related ticket reserved and corresponding datetime reserved values
455
+	 *
456
+	 * @param bool $update_ticket if true, will increment ticket and datetime reserved count
457
+	 *
458
+	 * @return void
459
+	 * @throws EE_Error
460
+	 */
461
+	public function reserve_ticket($update_ticket = false)
462
+	{
463
+		if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) === false) {
464
+			// PLZ NOTE: although checking $update_ticket first would be more efficient,
465
+			// we NEED to ALWAYS call update_extra_meta(), which is why that is done first
466
+			if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) && $update_ticket) {
467
+				$ticket = $this->ticket();
468
+				$ticket->increase_reserved();
469
+				$ticket->save();
470
+			}
471
+		}
472
+	}
473
+
474
+
475
+	/**
476
+	 * stops tracking this registration's ticket reservation in extra meta
477
+	 * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
478
+	 *
479
+	 * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
480
+	 *
481
+	 * @return void
482
+	 * @throws EE_Error
483
+	 */
484
+	public function release_reserved_ticket($update_ticket = false)
485
+	{
486
+		if ($this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true, false) !== false) {
487
+			// PLZ NOTE: although checking $update_ticket first would be more efficient,
488
+			// we NEED to ALWAYS call delete_extra_meta(), which is why that is done first
489
+			if ($this->delete_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY) && $update_ticket) {
490
+				$ticket = $this->ticket();
491
+				$ticket->decrease_reserved();
492
+				$ticket->save();
493
+			}
494
+		}
495
+	}
496
+
497
+
498
+	/**
499
+	 * Set Attendee ID
500
+	 *
501
+	 * @param        int $ATT_ID Attendee ID
502
+	 * @throws EE_Error
503
+	 * @throws RuntimeException
504
+	 */
505
+	public function set_attendee_id($ATT_ID = 0)
506
+	{
507
+		$this->set('ATT_ID', $ATT_ID);
508
+	}
509
+
510
+
511
+	/**
512
+	 *        Set Transaction ID
513
+	 *
514
+	 * @param        int $TXN_ID Transaction ID
515
+	 * @throws EE_Error
516
+	 * @throws RuntimeException
517
+	 */
518
+	public function set_transaction_id($TXN_ID = 0)
519
+	{
520
+		$this->set('TXN_ID', $TXN_ID);
521
+	}
522
+
523
+
524
+	/**
525
+	 *        Set Session
526
+	 *
527
+	 * @param    string $REG_session PHP Session ID
528
+	 * @throws EE_Error
529
+	 * @throws RuntimeException
530
+	 */
531
+	public function set_session($REG_session = '')
532
+	{
533
+		$this->set('REG_session', $REG_session);
534
+	}
535
+
536
+
537
+	/**
538
+	 *        Set Registration URL Link
539
+	 *
540
+	 * @param    string $REG_url_link Registration URL Link
541
+	 * @throws EE_Error
542
+	 * @throws RuntimeException
543
+	 */
544
+	public function set_reg_url_link($REG_url_link = '')
545
+	{
546
+		$this->set('REG_url_link', $REG_url_link);
547
+	}
548
+
549
+
550
+	/**
551
+	 *        Set Attendee Counter
552
+	 *
553
+	 * @param        int $REG_count Primary Attendee
554
+	 * @throws EE_Error
555
+	 * @throws RuntimeException
556
+	 */
557
+	public function set_count($REG_count = 1)
558
+	{
559
+		$this->set('REG_count', $REG_count);
560
+	}
561
+
562
+
563
+	/**
564
+	 *        Set Group Size
565
+	 *
566
+	 * @param        boolean $REG_group_size Group Registration
567
+	 * @throws EE_Error
568
+	 * @throws RuntimeException
569
+	 */
570
+	public function set_group_size($REG_group_size = false)
571
+	{
572
+		$this->set('REG_group_size', $REG_group_size);
573
+	}
574
+
575
+
576
+	/**
577
+	 *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
578
+	 *    EEM_Registration::status_id_not_approved
579
+	 *
580
+	 * @return        boolean
581
+	 */
582
+	public function is_not_approved()
583
+	{
584
+		return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
585
+	}
586
+
587
+
588
+	/**
589
+	 *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
590
+	 *    EEM_Registration::status_id_pending_payment
591
+	 *
592
+	 * @return        boolean
593
+	 */
594
+	public function is_pending_payment()
595
+	{
596
+		return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
597
+	}
598
+
599
+
600
+	/**
601
+	 *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
602
+	 *
603
+	 * @return        boolean
604
+	 */
605
+	public function is_approved()
606
+	{
607
+		return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
608
+	}
609
+
610
+
611
+	/**
612
+	 *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
613
+	 *
614
+	 * @return        boolean
615
+	 */
616
+	public function is_cancelled()
617
+	{
618
+		return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
619
+	}
620
+
621
+
622
+	/**
623
+	 *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
624
+	 *
625
+	 * @return        boolean
626
+	 */
627
+	public function is_declined()
628
+	{
629
+		return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
630
+	}
631
+
632
+
633
+	/**
634
+	 *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
635
+	 *    EEM_Registration::status_id_incomplete
636
+	 *
637
+	 * @return        boolean
638
+	 */
639
+	public function is_incomplete()
640
+	{
641
+		return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
642
+	}
643
+
644
+
645
+	/**
646
+	 *        Set Registration Date
647
+	 *
648
+	 * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
649
+	 *                                                 Date
650
+	 * @throws EE_Error
651
+	 * @throws RuntimeException
652
+	 */
653
+	public function set_reg_date($REG_date = false)
654
+	{
655
+		$this->set('REG_date', $REG_date);
656
+	}
657
+
658
+
659
+	/**
660
+	 *    Set final price owing for this registration after all ticket/price modifications
661
+	 *
662
+	 * @access    public
663
+	 * @param    float $REG_final_price
664
+	 * @throws EE_Error
665
+	 * @throws RuntimeException
666
+	 */
667
+	public function set_final_price($REG_final_price = 0.00)
668
+	{
669
+		$this->set('REG_final_price', $REG_final_price);
670
+	}
671
+
672
+
673
+	/**
674
+	 *    Set amount paid towards this registration's final price
675
+	 *
676
+	 * @access    public
677
+	 * @param    float $REG_paid
678
+	 * @throws EE_Error
679
+	 * @throws RuntimeException
680
+	 */
681
+	public function set_paid($REG_paid = 0.00)
682
+	{
683
+		$this->set('REG_paid', $REG_paid);
684
+	}
685
+
686
+
687
+	/**
688
+	 *        Attendee Is Going
689
+	 *
690
+	 * @param        boolean $REG_att_is_going Attendee Is Going
691
+	 * @throws EE_Error
692
+	 * @throws RuntimeException
693
+	 */
694
+	public function set_att_is_going($REG_att_is_going = false)
695
+	{
696
+		$this->set('REG_att_is_going', $REG_att_is_going);
697
+	}
698
+
699
+
700
+	/**
701
+	 * Gets the related attendee
702
+	 *
703
+	 * @return EE_Attendee
704
+	 * @throws EE_Error
705
+	 */
706
+	public function attendee()
707
+	{
708
+		return $this->get_first_related('Attendee');
709
+	}
710
+
711
+
712
+	/**
713
+	 *        get Event ID
714
+	 */
715
+	public function event_ID()
716
+	{
717
+		return $this->get('EVT_ID');
718
+	}
719
+
720
+
721
+	/**
722
+	 *        get Event ID
723
+	 */
724
+	public function event_name()
725
+	{
726
+		$event = $this->event_obj();
727
+		if ($event) {
728
+			return $event->name();
729
+		} else {
730
+			return null;
731
+		}
732
+	}
733
+
734
+
735
+	/**
736
+	 * Fetches the event this registration is for
737
+	 *
738
+	 * @return EE_Event
739
+	 * @throws EE_Error
740
+	 */
741
+	public function event_obj()
742
+	{
743
+		return $this->get_first_related('Event');
744
+	}
745
+
746
+
747
+	/**
748
+	 *        get Attendee ID
749
+	 */
750
+	public function attendee_ID()
751
+	{
752
+		return $this->get('ATT_ID');
753
+	}
754
+
755
+
756
+	/**
757
+	 *        get PHP Session ID
758
+	 */
759
+	public function session_ID()
760
+	{
761
+		return $this->get('REG_session');
762
+	}
763
+
764
+
765
+	/**
766
+	 * Gets the string which represents the URL trigger for the receipt template in the message template system.
767
+	 *
768
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
769
+	 * @return string
770
+	 */
771
+	public function receipt_url($messenger = 'html')
772
+	{
773
+
774
+		/**
775
+		 * The below will be deprecated one version after this.  We check first if there is a custom receipt template
776
+		 * already in use on old system.  If there is then we just return the standard url for it.
777
+		 *
778
+		 * @since 4.5.0
779
+		 */
780
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
781
+		$has_custom             = EEH_Template::locate_template(
782
+			$template_relative_path,
783
+			array(),
784
+			true,
785
+			true,
786
+			true
787
+		);
788
+
789
+		if ($has_custom) {
790
+			return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
791
+		}
792
+		return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
793
+	}
794
+
795
+
796
+	/**
797
+	 * Gets the string which represents the URL trigger for the invoice template in the message template system.
798
+	 *
799
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
800
+	 * @return string
801
+	 * @throws EE_Error
802
+	 */
803
+	public function invoice_url($messenger = 'html')
804
+	{
805
+		/**
806
+		 * The below will be deprecated one version after this.  We check first if there is a custom invoice template
807
+		 * already in use on old system.  If there is then we just return the standard url for it.
808
+		 *
809
+		 * @since 4.5.0
810
+		 */
811
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
812
+		$has_custom             = EEH_Template::locate_template(
813
+			$template_relative_path,
814
+			array(),
815
+			true,
816
+			true,
817
+			true
818
+		);
819
+
820
+		if ($has_custom) {
821
+			if ($messenger == 'html') {
822
+				return $this->invoice_url('launch');
823
+			}
824
+			$route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
825
+
826
+			$query_args = array('ee' => $route, 'id' => $this->reg_url_link());
827
+			if ($messenger == 'html') {
828
+				$query_args['html'] = true;
829
+			}
830
+			return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
831
+		}
832
+		return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
833
+	}
834
+
835
+
836
+	/**
837
+	 * get Registration URL Link
838
+	 *
839
+	 * @access public
840
+	 * @return string
841
+	 * @throws EE_Error
842
+	 */
843
+	public function reg_url_link()
844
+	{
845
+		return (string) $this->get('REG_url_link');
846
+	}
847
+
848
+
849
+	/**
850
+	 * Echoes out invoice_url()
851
+	 *
852
+	 * @param string $type 'download','launch', or 'html' (default is 'launch')
853
+	 * @return void
854
+	 * @throws EE_Error
855
+	 */
856
+	public function e_invoice_url($type = 'launch')
857
+	{
858
+		echo $this->invoice_url($type);
859
+	}
860
+
861
+
862
+	/**
863
+	 * Echoes out payment_overview_url
864
+	 */
865
+	public function e_payment_overview_url()
866
+	{
867
+		echo $this->payment_overview_url();
868
+	}
869
+
870
+
871
+	/**
872
+	 * Gets the URL of the thank you page with this registration REG_url_link added as
873
+	 * a query parameter
874
+	 *
875
+	 * @param bool $clear_session Set to true when you want to clear the session on revisiting the
876
+	 *                            payment overview url.
877
+	 * @return string
878
+	 * @throws EE_Error
879
+	 */
880
+	public function payment_overview_url($clear_session = false)
881
+	{
882
+		return add_query_arg(array(
883
+			'e_reg_url_link' => $this->reg_url_link(),
884
+			'step'           => 'payment_options',
885
+			'revisit'        => true,
886
+			'clear_session' => (bool) $clear_session
887
+		), EE_Registry::instance()->CFG->core->reg_page_url());
888
+	}
889
+
890
+
891
+	/**
892
+	 * Gets the URL of the thank you page with this registration REG_url_link added as
893
+	 * a query parameter
894
+	 *
895
+	 * @return string
896
+	 * @throws EE_Error
897
+	 */
898
+	public function edit_attendee_information_url()
899
+	{
900
+		return add_query_arg(array(
901
+			'e_reg_url_link' => $this->reg_url_link(),
902
+			'step'           => 'attendee_information',
903
+			'revisit'        => true,
904
+		), EE_Registry::instance()->CFG->core->reg_page_url());
905
+	}
906
+
907
+
908
+	/**
909
+	 * Simply generates and returns the appropriate admin_url link to edit this registration
910
+	 *
911
+	 * @return string
912
+	 * @throws EE_Error
913
+	 */
914
+	public function get_admin_edit_url()
915
+	{
916
+		return EEH_URL::add_query_args_and_nonce(array(
917
+			'page'    => 'espresso_registrations',
918
+			'action'  => 'view_registration',
919
+			'_REG_ID' => $this->ID(),
920
+		), admin_url('admin.php'));
921
+	}
922
+
923
+
924
+	/**
925
+	 *    is_primary_registrant?
926
+	 */
927
+	public function is_primary_registrant()
928
+	{
929
+		return $this->get('REG_count') == 1 ? true : false;
930
+	}
931
+
932
+
933
+	/**
934
+	 * This returns the primary registration object for this registration group (which may be this object).
935
+	 *
936
+	 * @return EE_Registration
937
+	 * @throws EE_Error
938
+	 */
939
+	public function get_primary_registration()
940
+	{
941
+		if ($this->is_primary_registrant()) {
942
+			return $this;
943
+		}
944
+
945
+		//k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
946
+		/** @var EE_Registration $primary_registrant */
947
+		$primary_registrant = EEM_Registration::instance()->get_one(array(
948
+			array(
949
+				'TXN_ID'    => $this->transaction_ID(),
950
+				'REG_count' => 1,
951
+			),
952
+		));
953
+		return $primary_registrant;
954
+	}
955
+
956
+
957
+	/**
958
+	 *        get  Attendee Number
959
+	 *
960
+	 * @access        public
961
+	 */
962
+	public function count()
963
+	{
964
+		return $this->get('REG_count');
965
+	}
966
+
967
+
968
+	/**
969
+	 *        get Group Size
970
+	 */
971
+	public function group_size()
972
+	{
973
+		return $this->get('REG_group_size');
974
+	}
975
+
976
+
977
+	/**
978
+	 *        get Registration Date
979
+	 */
980
+	public function date()
981
+	{
982
+		return $this->get('REG_date');
983
+	}
984
+
985
+
986
+	/**
987
+	 * gets a pretty date
988
+	 *
989
+	 * @param string $date_format
990
+	 * @param string $time_format
991
+	 * @return string
992
+	 * @throws EE_Error
993
+	 */
994
+	public function pretty_date($date_format = null, $time_format = null)
995
+	{
996
+		return $this->get_datetime('REG_date', $date_format, $time_format);
997
+	}
998
+
999
+
1000
+	/**
1001
+	 * final_price
1002
+	 * the registration's share of the transaction total, so that the
1003
+	 * sum of all the transaction's REG_final_prices equal the transaction's total
1004
+	 *
1005
+	 * @return float
1006
+	 * @throws EE_Error
1007
+	 */
1008
+	public function final_price()
1009
+	{
1010
+		return $this->get('REG_final_price');
1011
+	}
1012
+
1013
+
1014
+	/**
1015
+	 * pretty_final_price
1016
+	 *  final price as formatted string, with correct decimal places and currency symbol
1017
+	 *
1018
+	 * @return string
1019
+	 * @throws EE_Error
1020
+	 */
1021
+	public function pretty_final_price()
1022
+	{
1023
+		return $this->get_pretty('REG_final_price');
1024
+	}
1025
+
1026
+
1027
+	/**
1028
+	 * get paid (yeah)
1029
+	 *
1030
+	 * @return float
1031
+	 * @throws EE_Error
1032
+	 */
1033
+	public function paid()
1034
+	{
1035
+		return $this->get('REG_paid');
1036
+	}
1037
+
1038
+
1039
+	/**
1040
+	 * pretty_paid
1041
+	 *
1042
+	 * @return float
1043
+	 * @throws EE_Error
1044
+	 */
1045
+	public function pretty_paid()
1046
+	{
1047
+		return $this->get_pretty('REG_paid');
1048
+	}
1049
+
1050
+
1051
+	/**
1052
+	 * owes_monies_and_can_pay
1053
+	 * whether or not this registration has monies owing and it's' status allows payment
1054
+	 *
1055
+	 * @param array $requires_payment
1056
+	 * @return bool
1057
+	 * @throws EE_Error
1058
+	 */
1059
+	public function owes_monies_and_can_pay($requires_payment = array())
1060
+	{
1061
+		// these reg statuses require payment (if event is not free)
1062
+		$requires_payment = ! empty($requires_payment)
1063
+			? $requires_payment
1064
+			: EEM_Registration::reg_statuses_that_allow_payment();
1065
+		if (in_array($this->status_ID(), $requires_payment) &&
1066
+			$this->final_price() != 0 &&
1067
+			$this->final_price() != $this->paid()
1068
+		) {
1069
+			return true;
1070
+		} else {
1071
+			return false;
1072
+		}
1073
+	}
1074
+
1075
+
1076
+	/**
1077
+	 * Prints out the return value of $this->pretty_status()
1078
+	 *
1079
+	 * @param bool $show_icons
1080
+	 * @return void
1081
+	 * @throws EE_Error
1082
+	 */
1083
+	public function e_pretty_status($show_icons = false)
1084
+	{
1085
+		echo $this->pretty_status($show_icons);
1086
+	}
1087
+
1088
+
1089
+	/**
1090
+	 * Returns a nice version of the status for displaying to customers
1091
+	 *
1092
+	 * @param bool $show_icons
1093
+	 * @return string
1094
+	 * @throws EE_Error
1095
+	 */
1096
+	public function pretty_status($show_icons = false)
1097
+	{
1098
+		$status = EEM_Status::instance()->localized_status(
1099
+			array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1100
+			false,
1101
+			'sentence'
1102
+		);
1103
+		$icon   = '';
1104
+		switch ($this->status_ID()) {
1105
+			case EEM_Registration::status_id_approved:
1106
+				$icon = $show_icons
1107
+					? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1108
+					: '';
1109
+				break;
1110
+			case EEM_Registration::status_id_pending_payment:
1111
+				$icon = $show_icons
1112
+					? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1113
+					: '';
1114
+				break;
1115
+			case EEM_Registration::status_id_not_approved:
1116
+				$icon = $show_icons
1117
+					? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1118
+					: '';
1119
+				break;
1120
+			case EEM_Registration::status_id_cancelled:
1121
+				$icon = $show_icons
1122
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1123
+					: '';
1124
+				break;
1125
+			case EEM_Registration::status_id_incomplete:
1126
+				$icon = $show_icons
1127
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1128
+					: '';
1129
+				break;
1130
+			case EEM_Registration::status_id_declined:
1131
+				$icon = $show_icons
1132
+					? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1133
+					: '';
1134
+				break;
1135
+			case EEM_Registration::status_id_wait_list:
1136
+				$icon = $show_icons
1137
+					? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1138
+					: '';
1139
+				break;
1140
+		}
1141
+		return $icon . $status[$this->status_ID()];
1142
+	}
1143
+
1144
+
1145
+	/**
1146
+	 *        get Attendee Is Going
1147
+	 */
1148
+	public function att_is_going()
1149
+	{
1150
+		return $this->get('REG_att_is_going');
1151
+	}
1152
+
1153
+
1154
+	/**
1155
+	 * Gets related answers
1156
+	 *
1157
+	 * @param array $query_params like EEM_Base::get_all
1158
+	 * @return EE_Answer[]
1159
+	 * @throws EE_Error
1160
+	 */
1161
+	public function answers($query_params = null)
1162
+	{
1163
+		return $this->get_many_related('Answer', $query_params);
1164
+	}
1165
+
1166
+
1167
+	/**
1168
+	 * Gets the registration's answer value to the specified question
1169
+	 * (either the question's ID or a question object)
1170
+	 *
1171
+	 * @param EE_Question|int $question
1172
+	 * @param bool            $pretty_value
1173
+	 * @return array|string if pretty_value= true, the result will always be a string
1174
+	 * (because the answer might be an array of answer values, so passing pretty_value=true
1175
+	 * will convert it into some kind of string)
1176
+	 * @throws EE_Error
1177
+	 */
1178
+	public function answer_value_to_question($question, $pretty_value = true)
1179
+	{
1180
+		$question_id = EEM_Question::instance()->ensure_is_ID($question);
1181
+		return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1182
+	}
1183
+
1184
+
1185
+	/**
1186
+	 * question_groups
1187
+	 * returns an array of EE_Question_Group objects for this registration
1188
+	 *
1189
+	 * @return EE_Question_Group[]
1190
+	 * @throws EE_Error
1191
+	 * @throws EntityNotFoundException
1192
+	 */
1193
+	public function question_groups()
1194
+	{
1195
+		$question_groups = array();
1196
+		if ($this->event() instanceof EE_Event) {
1197
+			$question_groups = $this->event()->question_groups(
1198
+				array(
1199
+					array(
1200
+						'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1201
+					),
1202
+					'order_by' => array('QSG_order' => 'ASC'),
1203
+				)
1204
+			);
1205
+		}
1206
+		return $question_groups;
1207
+	}
1208
+
1209
+
1210
+	/**
1211
+	 * count_question_groups
1212
+	 * returns a count of the number of EE_Question_Group objects for this registration
1213
+	 *
1214
+	 * @return int
1215
+	 * @throws EE_Error
1216
+	 * @throws EntityNotFoundException
1217
+	 */
1218
+	public function count_question_groups()
1219
+	{
1220
+		$qg_count = 0;
1221
+		if ($this->event() instanceof EE_Event) {
1222
+			$qg_count = $this->event()->count_related(
1223
+				'Question_Group',
1224
+				array(
1225
+					array(
1226
+						'Event_Question_Group.EQG_primary' => $this->count() == 1 ? true : false,
1227
+					),
1228
+				)
1229
+			);
1230
+		}
1231
+		return $qg_count;
1232
+	}
1233
+
1234
+
1235
+	/**
1236
+	 * Returns the registration date in the 'standard' string format
1237
+	 * (function may be improved in the future to allow for different formats and timezones)
1238
+	 *
1239
+	 * @return string
1240
+	 * @throws EE_Error
1241
+	 */
1242
+	public function reg_date()
1243
+	{
1244
+		return $this->get_datetime('REG_date');
1245
+	}
1246
+
1247
+
1248
+	/**
1249
+	 * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1250
+	 * the ticket this registration purchased, or the datetime they have registered
1251
+	 * to attend)
1252
+	 *
1253
+	 * @return EE_Datetime_Ticket
1254
+	 * @throws EE_Error
1255
+	 */
1256
+	public function datetime_ticket()
1257
+	{
1258
+		return $this->get_first_related('Datetime_Ticket');
1259
+	}
1260
+
1261
+
1262
+	/**
1263
+	 * Sets the registration's datetime_ticket.
1264
+	 *
1265
+	 * @param EE_Datetime_Ticket $datetime_ticket
1266
+	 * @return EE_Datetime_Ticket
1267
+	 * @throws EE_Error
1268
+	 */
1269
+	public function set_datetime_ticket($datetime_ticket)
1270
+	{
1271
+		return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1272
+	}
1273
+
1274
+	/**
1275
+	 * Gets deleted
1276
+	 *
1277
+	 * @return bool
1278
+	 * @throws EE_Error
1279
+	 */
1280
+	public function deleted()
1281
+	{
1282
+		return $this->get('REG_deleted');
1283
+	}
1284
+
1285
+	/**
1286
+	 * Sets deleted
1287
+	 *
1288
+	 * @param boolean $deleted
1289
+	 * @return bool
1290
+	 * @throws EE_Error
1291
+	 * @throws RuntimeException
1292
+	 */
1293
+	public function set_deleted($deleted)
1294
+	{
1295
+		if ($deleted) {
1296
+			$this->delete();
1297
+		} else {
1298
+			$this->restore();
1299
+		}
1300
+	}
1301
+
1302
+
1303
+	/**
1304
+	 * Get the status object of this object
1305
+	 *
1306
+	 * @return EE_Status
1307
+	 * @throws EE_Error
1308
+	 */
1309
+	public function status_obj()
1310
+	{
1311
+		return $this->get_first_related('Status');
1312
+	}
1313
+
1314
+
1315
+	/**
1316
+	 * Returns the number of times this registration has checked into any of the datetimes
1317
+	 * its available for
1318
+	 *
1319
+	 * @return int
1320
+	 * @throws EE_Error
1321
+	 */
1322
+	public function count_checkins()
1323
+	{
1324
+		return $this->get_model()->count_related($this, 'Checkin');
1325
+	}
1326
+
1327
+
1328
+	/**
1329
+	 * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1330
+	 * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1331
+	 *
1332
+	 * @return int
1333
+	 * @throws EE_Error
1334
+	 */
1335
+	public function count_checkins_not_checkedout()
1336
+	{
1337
+		return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1338
+	}
1339
+
1340
+
1341
+	/**
1342
+	 * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1343
+	 *
1344
+	 * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1345
+	 * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1346
+	 *                                          consider registration status as well as datetime access.
1347
+	 * @return bool
1348
+	 * @throws EE_Error
1349
+	 */
1350
+	public function can_checkin($DTT_OR_ID, $check_approved = true)
1351
+	{
1352
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1353
+
1354
+		//first check registration status
1355
+		if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1356
+			return false;
1357
+		}
1358
+		//is there a datetime ticket that matches this dtt_ID?
1359
+		if (! (EEM_Datetime_Ticket::instance()->exists(array(
1360
+			array(
1361
+				'TKT_ID' => $this->get('TKT_ID'),
1362
+				'DTT_ID' => $DTT_ID,
1363
+			),
1364
+		)))
1365
+		) {
1366
+			return false;
1367
+		}
1368
+
1369
+		//final check is against TKT_uses
1370
+		return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1371
+	}
1372
+
1373
+
1374
+	/**
1375
+	 * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1376
+	 * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1377
+	 * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1378
+	 * then return false.  Otherwise return true.
1379
+	 *
1380
+	 * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1381
+	 * @return bool true means can checkin.  false means cannot checkin.
1382
+	 * @throws EE_Error
1383
+	 */
1384
+	public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1385
+	{
1386
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1387
+
1388
+		if (! $DTT_ID) {
1389
+			return false;
1390
+		}
1391
+
1392
+		$max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1393
+
1394
+		// if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1395
+		// check-in or not.
1396
+		if (! $max_uses || $max_uses === EE_INF) {
1397
+			return true;
1398
+		}
1399
+
1400
+		//does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1401
+		//go ahead and toggle.
1402
+		if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1403
+			return true;
1404
+		}
1405
+
1406
+		//made it here so the last check is whether the number of checkins per unique datetime on this registration
1407
+		//disallows further check-ins.
1408
+		$count_unique_dtt_checkins = EEM_Checkin::instance()->count(array(
1409
+			array(
1410
+				'REG_ID' => $this->ID(),
1411
+				'CHK_in' => true,
1412
+			),
1413
+		), 'DTT_ID', true);
1414
+		// checkins have already reached their max number of uses
1415
+		// so registrant can NOT checkin
1416
+		if ($count_unique_dtt_checkins >= $max_uses) {
1417
+			EE_Error::add_error(
1418
+				esc_html__(
1419
+					'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1420
+					'event_espresso'
1421
+				),
1422
+				__FILE__,
1423
+				__FUNCTION__,
1424
+				__LINE__
1425
+			);
1426
+			return false;
1427
+		}
1428
+		return true;
1429
+	}
1430
+
1431
+
1432
+	/**
1433
+	 * toggle Check-in status for this registration
1434
+	 * Check-ins are toggled in the following order:
1435
+	 * never checked in -> checked in
1436
+	 * checked in -> checked out
1437
+	 * checked out -> checked in
1438
+	 *
1439
+	 * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1440
+	 *                      If not included or null, then it is assumed latest datetime is being toggled.
1441
+	 * @param bool $verify  If true then can_checkin() is used to verify whether the person
1442
+	 *                      can be checked in or not.  Otherwise this forces change in checkin status.
1443
+	 * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1444
+	 * @throws EE_Error
1445
+	 */
1446
+	public function toggle_checkin_status($DTT_ID = null, $verify = false)
1447
+	{
1448
+		if (empty($DTT_ID)) {
1449
+			$datetime = $this->get_latest_related_datetime();
1450
+			$DTT_ID   = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1451
+			// verify the registration can checkin for the given DTT_ID
1452
+		} elseif (! $this->can_checkin($DTT_ID, $verify)) {
1453
+			EE_Error::add_error(
1454
+				sprintf(
1455
+					esc_html__(
1456
+						'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1457
+						'event_espresso'
1458
+					),
1459
+					$this->ID(),
1460
+					$DTT_ID
1461
+				),
1462
+				__FILE__,
1463
+				__FUNCTION__,
1464
+				__LINE__
1465
+			);
1466
+			return false;
1467
+		}
1468
+		$status_paths = array(
1469
+			EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1470
+			EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1471
+			EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1472
+		);
1473
+		//start by getting the current status so we know what status we'll be changing to.
1474
+		$cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1475
+		$status_to  = $status_paths[$cur_status];
1476
+		// database only records true for checked IN or false for checked OUT
1477
+		// no record ( null ) means checked in NEVER, but we obviously don't save that
1478
+		$new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1479
+		// add relation - note Check-ins are always creating new rows
1480
+		// because we are keeping track of Check-ins over time.
1481
+		// Eventually we'll probably want to show a list table
1482
+		// for the individual Check-ins so that they can be managed.
1483
+		$checkin = EE_Checkin::new_instance(array(
1484
+			'REG_ID' => $this->ID(),
1485
+			'DTT_ID' => $DTT_ID,
1486
+			'CHK_in' => $new_status,
1487
+		));
1488
+		// if the record could not be saved then return false
1489
+		if ($checkin->save() === 0) {
1490
+			if (WP_DEBUG) {
1491
+				global $wpdb;
1492
+				$error = sprintf(
1493
+					esc_html__(
1494
+						'Registration check in update failed because of the following database error: %1$s%2$s',
1495
+						'event_espresso'
1496
+					),
1497
+					'<br />',
1498
+					$wpdb->last_error
1499
+				);
1500
+			} else {
1501
+				$error = esc_html__(
1502
+					'Registration check in update failed because of an unknown database error',
1503
+					'event_espresso'
1504
+				);
1505
+			}
1506
+			EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1507
+			return false;
1508
+		}
1509
+		return $status_to;
1510
+	}
1511
+
1512
+
1513
+	/**
1514
+	 * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1515
+	 * "Latest" is defined by the `DTT_EVT_start` column.
1516
+	 *
1517
+	 * @return EE_Datetime|null
1518
+	 * @throws EE_Error
1519
+	 */
1520
+	public function get_latest_related_datetime()
1521
+	{
1522
+		return EEM_Datetime::instance()->get_one(
1523
+			array(
1524
+				array(
1525
+					'Ticket.Registration.REG_ID' => $this->ID(),
1526
+				),
1527
+				'order_by' => array('DTT_EVT_start' => 'DESC'),
1528
+			)
1529
+		);
1530
+	}
1531
+
1532
+
1533
+	/**
1534
+	 * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1535
+	 * "Earliest" is defined by the `DTT_EVT_start` column.
1536
+	 *
1537
+	 * @throws EE_Error
1538
+	 */
1539
+	public function get_earliest_related_datetime()
1540
+	{
1541
+		return EEM_Datetime::instance()->get_one(
1542
+			array(
1543
+				array(
1544
+					'Ticket.Registration.REG_ID' => $this->ID(),
1545
+				),
1546
+				'order_by' => array('DTT_EVT_start' => 'ASC'),
1547
+			)
1548
+		);
1549
+	}
1550
+
1551
+
1552
+	/**
1553
+	 * This method simply returns the check-in status for this registration and the given datetime.
1554
+	 * If neither the datetime nor the checkin values are provided as arguments,
1555
+	 * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1556
+	 *
1557
+	 * @param  int       $DTT_ID  The ID of the datetime we're checking against
1558
+	 *                            (if empty we'll get the primary datetime for
1559
+	 *                            this registration (via event) and use it's ID);
1560
+	 * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1561
+	 *
1562
+	 * @return int                Integer representing Check-in status.
1563
+	 * @throws EE_Error
1564
+	 */
1565
+	public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1566
+	{
1567
+		$checkin_query_params = array(
1568
+			'order_by' => array('CHK_timestamp' => 'DESC'),
1569
+		);
1570
+
1571
+		if ($DTT_ID > 0) {
1572
+			$checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1573
+		}
1574
+
1575
+		//get checkin object (if exists)
1576
+		$checkin = $checkin instanceof EE_Checkin
1577
+			? $checkin
1578
+			: $this->get_first_related('Checkin', $checkin_query_params);
1579
+		if ($checkin instanceof EE_Checkin) {
1580
+			if ($checkin->get('CHK_in')) {
1581
+				return EE_Checkin::status_checked_in; //checked in
1582
+			}
1583
+			return EE_Checkin::status_checked_out; //had checked in but is now checked out.
1584
+		}
1585
+		return EE_Checkin::status_checked_never; //never been checked in
1586
+	}
1587
+
1588
+
1589
+	/**
1590
+	 * This method returns a localized message for the toggled Check-in message.
1591
+	 *
1592
+	 * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1593
+	 *                     then it is assumed Check-in for primary datetime was toggled.
1594
+	 * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1595
+	 *                     message can be customized with the attendee name.
1596
+	 * @return string internationalized message
1597
+	 * @throws EE_Error
1598
+	 */
1599
+	public function get_checkin_msg($DTT_ID, $error = false)
1600
+	{
1601
+		//let's get the attendee first so we can include the name of the attendee
1602
+		$attendee = $this->get_first_related('Attendee');
1603
+		if ($attendee instanceof EE_Attendee) {
1604
+			if ($error) {
1605
+				return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1606
+			}
1607
+			$cur_status = $this->check_in_status_for_datetime($DTT_ID);
1608
+			//what is the status message going to be?
1609
+			switch ($cur_status) {
1610
+				case EE_Checkin::status_checked_never:
1611
+					return sprintf(__("%s has been removed from Check-in records", "event_espresso"),
1612
+						$attendee->full_name());
1613
+					break;
1614
+				case EE_Checkin::status_checked_in:
1615
+					return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1616
+					break;
1617
+				case EE_Checkin::status_checked_out:
1618
+					return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1619
+					break;
1620
+			}
1621
+		}
1622
+		return esc_html__("The check-in status could not be determined.", "event_espresso");
1623
+	}
1624
+
1625
+
1626
+	/**
1627
+	 * Returns the related EE_Transaction to this registration
1628
+	 *
1629
+	 * @return EE_Transaction
1630
+	 * @throws EE_Error
1631
+	 * @throws EntityNotFoundException
1632
+	 */
1633
+	public function transaction()
1634
+	{
1635
+		$transaction = $this->get_first_related('Transaction');
1636
+		if (! $transaction instanceof \EE_Transaction) {
1637
+			throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1638
+		}
1639
+		return $transaction;
1640
+	}
1641
+
1642
+
1643
+	/**
1644
+	 *        get Registration Code
1645
+	 */
1646
+	public function reg_code()
1647
+	{
1648
+		return $this->get('REG_code');
1649
+	}
1650
+
1651
+
1652
+	/**
1653
+	 *        get Transaction ID
1654
+	 */
1655
+	public function transaction_ID()
1656
+	{
1657
+		return $this->get('TXN_ID');
1658
+	}
1659
+
1660
+
1661
+	/**
1662
+	 * @return int
1663
+	 * @throws EE_Error
1664
+	 */
1665
+	public function ticket_ID()
1666
+	{
1667
+		return $this->get('TKT_ID');
1668
+	}
1669
+
1670
+
1671
+	/**
1672
+	 *        Set Registration Code
1673
+	 *
1674
+	 * @access    public
1675
+	 * @param    string  $REG_code Registration Code
1676
+	 * @param    boolean $use_default
1677
+	 * @throws EE_Error
1678
+	 */
1679
+	public function set_reg_code($REG_code, $use_default = false)
1680
+	{
1681
+		if (empty($REG_code)) {
1682
+			EE_Error::add_error(
1683
+				esc_html__('REG_code can not be empty.', 'event_espresso'),
1684
+				__FILE__,
1685
+				__FUNCTION__,
1686
+				__LINE__
1687
+			);
1688
+			return;
1689
+		}
1690
+		if (! $this->reg_code()) {
1691
+			parent::set('REG_code', $REG_code, $use_default);
1692
+		} else {
1693
+			EE_Error::doing_it_wrong(
1694
+				__CLASS__ . '::' . __FUNCTION__,
1695
+				esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1696
+				'4.6.0'
1697
+			);
1698
+		}
1699
+	}
1700
+
1701
+
1702
+	/**
1703
+	 * Returns all other registrations in the same group as this registrant who have the same ticket option.
1704
+	 * Note, if you want to just get all registrations in the same transaction (group), use:
1705
+	 *    $registration->transaction()->registrations();
1706
+	 *
1707
+	 * @since 4.5.0
1708
+	 * @return EE_Registration[] or empty array if this isn't a group registration.
1709
+	 * @throws EE_Error
1710
+	 */
1711
+	public function get_all_other_registrations_in_group()
1712
+	{
1713
+		if ($this->group_size() < 2) {
1714
+			return array();
1715
+		}
1716
+
1717
+		$query[0] = array(
1718
+			'TXN_ID' => $this->transaction_ID(),
1719
+			'REG_ID' => array('!=', $this->ID()),
1720
+			'TKT_ID' => $this->ticket_ID(),
1721
+		);
1722
+		/** @var EE_Registration[] $registrations */
1723
+		$registrations = $this->get_model()->get_all($query);
1724
+		return $registrations;
1725
+	}
1726
+
1727
+	/**
1728
+	 * Return the link to the admin details for the object.
1729
+	 *
1730
+	 * @return string
1731
+	 * @throws EE_Error
1732
+	 */
1733
+	public function get_admin_details_link()
1734
+	{
1735
+		EE_Registry::instance()->load_helper('URL');
1736
+		return EEH_URL::add_query_args_and_nonce(
1737
+			array(
1738
+				'page'    => 'espresso_registrations',
1739
+				'action'  => 'view_registration',
1740
+				'_REG_ID' => $this->ID(),
1741
+			),
1742
+			admin_url('admin.php')
1743
+		);
1744
+	}
1745
+
1746
+	/**
1747
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1748
+	 *
1749
+	 * @return string
1750
+	 * @throws EE_Error
1751
+	 */
1752
+	public function get_admin_edit_link()
1753
+	{
1754
+		return $this->get_admin_details_link();
1755
+	}
1756
+
1757
+	/**
1758
+	 * Returns the link to a settings page for the object.
1759
+	 *
1760
+	 * @return string
1761
+	 * @throws EE_Error
1762
+	 */
1763
+	public function get_admin_settings_link()
1764
+	{
1765
+		return $this->get_admin_details_link();
1766
+	}
1767
+
1768
+	/**
1769
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
1770
+	 *
1771
+	 * @return string
1772
+	 */
1773
+	public function get_admin_overview_link()
1774
+	{
1775
+		EE_Registry::instance()->load_helper('URL');
1776
+		return EEH_URL::add_query_args_and_nonce(
1777
+			array(
1778
+				'page' => 'espresso_registrations',
1779
+			),
1780
+			admin_url('admin.php')
1781
+		);
1782
+	}
1783
+
1784
+
1785
+	/**
1786
+	 * @param array $query_params
1787
+	 *
1788
+	 * @return \EE_Registration[]
1789
+	 * @throws EE_Error
1790
+	 */
1791
+	public function payments($query_params = array())
1792
+	{
1793
+		return $this->get_many_related('Payment', $query_params);
1794
+	}
1795
+
1796
+
1797
+	/**
1798
+	 * @param array $query_params
1799
+	 *
1800
+	 * @return \EE_Registration_Payment[]
1801
+	 * @throws EE_Error
1802
+	 */
1803
+	public function registration_payments($query_params = array())
1804
+	{
1805
+		return $this->get_many_related('Registration_Payment', $query_params);
1806
+	}
1807
+
1808
+
1809
+	/**
1810
+	 * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1811
+	 * Note: if there are no payments on the registration there will be no payment method returned.
1812
+	 *
1813
+	 * @return EE_Payment_Method|null
1814
+	 */
1815
+	public function payment_method()
1816
+	{
1817
+		return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1818
+	}
1819
+
1820
+
1821
+	/**
1822
+	 * @return \EE_Line_Item
1823
+	 * @throws EntityNotFoundException
1824
+	 * @throws EE_Error
1825
+	 */
1826
+	public function ticket_line_item()
1827
+	{
1828
+		$ticket            = $this->ticket();
1829
+		$transaction       = $this->transaction();
1830
+		$line_item         = null;
1831
+		$ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1832
+			$transaction->total_line_item(),
1833
+			'Ticket',
1834
+			array($ticket->ID())
1835
+		);
1836
+		foreach ($ticket_line_items as $ticket_line_item) {
1837
+			if (
1838
+				$ticket_line_item instanceof \EE_Line_Item
1839
+				&& $ticket_line_item->OBJ_type() === 'Ticket'
1840
+				&& $ticket_line_item->OBJ_ID() === $ticket->ID()
1841
+			) {
1842
+				$line_item = $ticket_line_item;
1843
+				break;
1844
+			}
1845
+		}
1846
+		if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1847
+			throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1848
+		}
1849
+		return $line_item;
1850
+	}
1851
+
1852
+
1853
+	/**
1854
+	 * Soft Deletes this model object.
1855
+	 *
1856
+	 * @return boolean | int
1857
+	 * @throws RuntimeException
1858
+	 * @throws EE_Error
1859
+	 */
1860
+	public function delete()
1861
+	{
1862
+		if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1863
+			$this->set_status(EEM_Registration::status_id_cancelled);
1864
+		}
1865
+		return parent::delete();
1866
+	}
1867
+
1868
+
1869
+	/**
1870
+	 * Restores whatever the previous status was on a registration before it was trashed (if possible)
1871
+	 *
1872
+	 * @throws EE_Error
1873
+	 * @throws RuntimeException
1874
+	 */
1875
+	public function restore()
1876
+	{
1877
+		$previous_status = $this->get_extra_meta(
1878
+			EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1879
+			true,
1880
+			EEM_Registration::status_id_cancelled
1881
+		);
1882
+		if ($previous_status) {
1883
+			$this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1884
+			$this->set_status($previous_status);
1885
+		}
1886
+		return parent::restore();
1887
+	}
1888
+
1889
+
1890
+	/**
1891
+	 * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price
1892
+	 *
1893
+	 * @param  boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic
1894
+	 *                                           depending on whether the reg status changes to or from "Approved"
1895
+	 * @return boolean whether the Registration status was updated
1896
+	 * @throws EE_Error
1897
+	 * @throws RuntimeException
1898
+	 */
1899
+	public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true)
1900
+	{
1901
+		$paid = $this->paid();
1902
+		$price = $this->final_price();
1903
+		switch(true) {
1904
+			// overpaid or paid
1905
+			case EEH_Money::compare_floats($paid, $price, '>'):
1906
+			case EEH_Money::compare_floats($paid, $price):
1907
+				$new_status = EEM_Registration::status_id_approved;
1908
+				break;
1909
+			//  underpaid
1910
+			case EEH_Money::compare_floats($paid, $price, '<'):
1911
+				$new_status = EEM_Registration::status_id_pending_payment;
1912
+				break;
1913
+			// uhhh Houston...
1914
+			default:
1915
+				throw new RuntimeException(
1916
+					esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso')
1917
+				);
1918
+		}
1919
+		if ($new_status !== $this->status_ID()) {
1920
+			if ($trigger_set_status_logic) {
1921
+				return $this->set_status($new_status);
1922
+			}
1923
+			parent::set('STS_ID', $new_status);
1924
+			return true;
1925
+		}
1926
+		return false;
1927
+	}
1928
+
1929
+
1930
+	/*************************** DEPRECATED ***************************/
1931
+
1932
+
1933
+	/**
1934
+	 * @deprecated
1935
+	 * @since     4.7.0
1936
+	 * @access    public
1937
+	 */
1938
+	public function price_paid()
1939
+	{
1940
+		EE_Error::doing_it_wrong('EE_Registration::price_paid()',
1941
+			esc_html__('This method is deprecated, please use EE_Registration::final_price() instead.', 'event_espresso'),
1942
+			'4.7.0');
1943
+		return $this->final_price();
1944
+	}
1945
+
1946
+
1947
+	/**
1948
+	 * @deprecated
1949
+	 * @since     4.7.0
1950
+	 * @access    public
1951
+	 * @param    float $REG_final_price
1952
+	 * @throws EE_Error
1953
+	 * @throws RuntimeException
1954
+	 */
1955
+	public function set_price_paid($REG_final_price = 0.00)
1956
+	{
1957
+		EE_Error::doing_it_wrong('EE_Registration::set_price_paid()',
1958
+			esc_html__('This method is deprecated, please use EE_Registration::set_final_price() instead.', 'event_espresso'),
1959
+			'4.7.0');
1960
+		$this->set_final_price($REG_final_price);
1961
+	}
1962
+
1963
+
1964
+	/**
1965
+	 * @deprecated
1966
+	 * @since 4.7.0
1967
+	 * @return string
1968
+	 * @throws EE_Error
1969
+	 */
1970
+	public function pretty_price_paid()
1971
+	{
1972
+		EE_Error::doing_it_wrong('EE_Registration::pretty_price_paid()',
1973
+			esc_html__('This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
1974
+				'event_espresso'), '4.7.0');
1975
+		return $this->pretty_final_price();
1976
+	}
1977
+
1978
+
1979
+	/**
1980
+	 * Gets the primary datetime related to this registration via the related Event to this registration
1981
+	 *
1982
+	 * @deprecated 4.9.17
1983
+	 * @return EE_Datetime
1984
+	 * @throws EE_Error
1985
+	 * @throws EntityNotFoundException
1986
+	 */
1987
+	public function get_related_primary_datetime()
1988
+	{
1989
+		EE_Error::doing_it_wrong(
1990
+			__METHOD__,
1991
+			esc_html__(
1992
+				'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
1993
+				'event_espresso'
1994
+			),
1995
+			'4.9.17',
1996
+			'5.0.0'
1997
+		);
1998
+		return $this->event()->primary_datetime();
1999
+	}
2000 2000
 
2001 2001
 
2002 2002
 }
Please login to merge, or discard this patch.
core/domain/entities/Context.php 1 patch
Indentation   +58 added lines, -58 removed lines patch added patch discarded remove patch
@@ -17,64 +17,64 @@
 block discarded – undo
17 17
 class Context implements ContextInterface
18 18
 {
19 19
 
20
-    /**
21
-     * @var string $slug
22
-     */
23
-    private $slug;
24
-
25
-    /**
26
-     * @var string $description
27
-     */
28
-    private $description;
29
-
30
-
31
-    /**
32
-     * Context constructor.
33
-     *
34
-     * @param string $slug
35
-     * @param string $description
36
-     */
37
-    public function __construct($slug, $description)
38
-    {
39
-        $this->setSlug($slug);
40
-        $this->setDescription($description);
41
-    }
42
-
43
-
44
-    /**
45
-     * @return string
46
-     */
47
-    public function slug()
48
-    {
49
-        return $this->slug;
50
-    }
51
-
52
-
53
-    /**
54
-     * @param string $slug
55
-     */
56
-    private function setSlug($slug)
57
-    {
58
-        $this->slug = sanitize_key($slug);
59
-    }
60
-
61
-
62
-    /**
63
-     * @return string
64
-     */
65
-    public function description()
66
-    {
67
-        return $this->description;
68
-    }
69
-
70
-
71
-    /**
72
-     * @param string $description
73
-     */
74
-    private function setDescription($description)
75
-    {
76
-        $this->description = sanitize_text_field($description);
77
-    }
20
+	/**
21
+	 * @var string $slug
22
+	 */
23
+	private $slug;
24
+
25
+	/**
26
+	 * @var string $description
27
+	 */
28
+	private $description;
29
+
30
+
31
+	/**
32
+	 * Context constructor.
33
+	 *
34
+	 * @param string $slug
35
+	 * @param string $description
36
+	 */
37
+	public function __construct($slug, $description)
38
+	{
39
+		$this->setSlug($slug);
40
+		$this->setDescription($description);
41
+	}
42
+
43
+
44
+	/**
45
+	 * @return string
46
+	 */
47
+	public function slug()
48
+	{
49
+		return $this->slug;
50
+	}
51
+
52
+
53
+	/**
54
+	 * @param string $slug
55
+	 */
56
+	private function setSlug($slug)
57
+	{
58
+		$this->slug = sanitize_key($slug);
59
+	}
60
+
61
+
62
+	/**
63
+	 * @return string
64
+	 */
65
+	public function description()
66
+	{
67
+		return $this->description;
68
+	}
69
+
70
+
71
+	/**
72
+	 * @param string $description
73
+	 */
74
+	private function setDescription($description)
75
+	{
76
+		$this->description = sanitize_text_field($description);
77
+	}
78 78
 
79 79
 }
80 80
 // Location: Context.php
Please login to merge, or discard this patch.
core/domain/entities/contexts/ContextInterface.php 1 patch
Indentation   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -18,14 +18,14 @@
 block discarded – undo
18 18
 interface ContextInterface
19 19
 {
20 20
 
21
-    /**
22
-     * @return string
23
-     */
24
-    public function slug();
21
+	/**
22
+	 * @return string
23
+	 */
24
+	public function slug();
25 25
 
26 26
 
27
-    /**
28
-     * @return string
29
-     */
30
-    public function description();
27
+	/**
28
+	 * @return string
29
+	 */
30
+	public function description();
31 31
 }
Please login to merge, or discard this patch.
core/business/EE_Registration_Processor.class.php 1 patch
Indentation   +775 added lines, -775 removed lines patch added patch discarded remove patch
@@ -27,781 +27,781 @@
 block discarded – undo
27 27
 class EE_Registration_Processor extends EE_Processor_Base
28 28
 {
29 29
 
30
-    /**
31
-     * @var EE_Registration_Processor $_instance
32
-     * @access    private
33
-     */
34
-    private static $_instance;
35
-
36
-    /**
37
-     * initial reg status at the beginning of this request.
38
-     * indexed by registration ID
39
-     *
40
-     * @var array
41
-     */
42
-    protected $_old_reg_status = array();
43
-
44
-    /**
45
-     * reg status at the end of the request after all processing.
46
-     * indexed by registration ID
47
-     *
48
-     * @var array
49
-     */
50
-    protected $_new_reg_status = array();
51
-
52
-    /**
53
-     * amounts paid at the end of the request after all processing.
54
-     * indexed by registration ID
55
-     *
56
-     * @var array
57
-     */
58
-    protected static $_amount_paid = array();
59
-
60
-    /**
61
-     * Cache of the reg final price for registrations corresponding to a ticket line item
62
-     *
63
-     * @deprecated
64
-     * @var array @see EEH_Line_Item::calculate_reg_final_prices_per_line_item()'s return value
65
-     */
66
-    protected $_reg_final_price_per_tkt_line_item;
67
-
68
-    /**
69
-     * @var EE_Request $request
70
-     */
71
-    protected $request;
72
-
73
-
74
-
75
-    /**
76
-     * @singleton method used to instantiate class object
77
-     * @param EE_Request|null $request
78
-     * @return EE_Registration_Processor instance
79
-     * @throws \InvalidArgumentException
80
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
81
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
82
-     */
83
-    public static function instance(EE_Request $request = null)
84
-    {
85
-        // check if class object is instantiated
86
-        if (! self::$_instance instanceof EE_Registration_Processor) {
87
-            if(! $request instanceof EE_Request) {
88
-                $request = LoaderFactory::getLoader()->getShared('EE_Request');
89
-            }
90
-            self::$_instance = new self($request);
91
-        }
92
-        return self::$_instance;
93
-    }
94
-
95
-
96
-    /**
97
-     * EE_Registration_Processor constructor.
98
-     *
99
-     * @param EE_Request $request
100
-     */
101
-    public function __construct(EE_Request $request)
102
-    {
103
-        $this->request = $request;
104
-    }
105
-
106
-
107
-
108
-    /**
109
-     * @param int $REG_ID
110
-     * @return string
111
-     */
112
-    public function old_reg_status($REG_ID)
113
-    {
114
-        return isset($this->_old_reg_status[$REG_ID]) ? $this->_old_reg_status[$REG_ID] : null;
115
-    }
116
-
117
-
118
-
119
-    /**
120
-     * @param int    $REG_ID
121
-     * @param string $old_reg_status
122
-     */
123
-    public function set_old_reg_status($REG_ID, $old_reg_status)
124
-    {
125
-        // only set the first time
126
-        if (! isset($this->_old_reg_status[$REG_ID])) {
127
-            $this->_old_reg_status[$REG_ID] = $old_reg_status;
128
-        }
129
-    }
130
-
131
-
132
-
133
-    /**
134
-     * @param int $REG_ID
135
-     * @return string
136
-     */
137
-    public function new_reg_status($REG_ID)
138
-    {
139
-        return isset($this->_new_reg_status[$REG_ID]) ? $this->_new_reg_status[$REG_ID] : null;
140
-    }
141
-
142
-
143
-
144
-    /**
145
-     * @param int    $REG_ID
146
-     * @param string $new_reg_status
147
-     */
148
-    public function set_new_reg_status($REG_ID, $new_reg_status)
149
-    {
150
-        $this->_new_reg_status[$REG_ID] = $new_reg_status;
151
-    }
152
-
153
-
154
-
155
-    /**
156
-     * reg_status_updated
157
-     *
158
-     * @param int $REG_ID
159
-     * @return bool
160
-     */
161
-    public function reg_status_updated($REG_ID)
162
-    {
163
-        return $this->new_reg_status($REG_ID) !== $this->old_reg_status($REG_ID);
164
-    }
165
-
166
-
167
-
168
-    /**
169
-     * @param EE_Registration $registration
170
-     * @throws EE_Error
171
-     * @throws EntityNotFoundException
172
-     * @throws InvalidArgumentException
173
-     * @throws InvalidDataTypeException
174
-     * @throws InvalidInterfaceException
175
-     * @throws ReflectionException
176
-     * @throws RuntimeException
177
-     */
178
-    public function update_registration_status_and_trigger_notifications(EE_Registration $registration)
179
-    {
180
-        $this->toggle_incomplete_registration_status_to_default($registration, false);
181
-        $this->toggle_registration_status_for_default_approved_events($registration, false);
182
-        $this->toggle_registration_status_if_no_monies_owing($registration, false);
183
-        $registration->save();
184
-        // trigger notifications
185
-        $this->trigger_registration_update_notifications($registration);
186
-    }
187
-
188
-
189
-
190
-    /**
191
-     *    manually_update_registration_status
192
-     *
193
-     * @access public
194
-     * @param EE_Registration $registration
195
-     * @param string          $new_reg_status
196
-     * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
197
-     *                              to client code
198
-     * @return bool
199
-     * @throws EE_Error
200
-     * @throws EntityNotFoundException
201
-     * @throws InvalidArgumentException
202
-     * @throws InvalidDataTypeException
203
-     * @throws InvalidInterfaceException
204
-     * @throws ReflectionException
205
-     * @throws RuntimeException
206
-     */
207
-    public function manually_update_registration_status(
208
-        EE_Registration $registration,
209
-        $new_reg_status = '',
210
-        $save = true
211
-    ) {
212
-        // set initial REG_Status
213
-        $this->set_old_reg_status($registration->ID(), $registration->status_ID());
214
-        // set incoming REG_Status
215
-        $this->set_new_reg_status($registration->ID(), $new_reg_status);
216
-        // toggle reg status but only if it has changed and the user can do so
217
-        if (
218
-            $this->reg_status_updated($registration->ID())
219
-            && (
220
-                (! $this->request->isAdmin() || $this->request->isFrontAjax())
221
-                || EE_Registry::instance()->CAP->current_user_can(
222
-                    'ee_edit_registration',
223
-                    'toggle_registration_status',
224
-                    $registration->ID()
225
-                )
226
-            )
227
-        ) {
228
-            // change status to new value
229
-            $updated = $registration->set_status($this->new_reg_status($registration->ID()));
230
-            if ($updated && $save) {
231
-                $registration->save();
232
-            }
233
-            return true;
234
-        }
235
-        return false;
236
-    }
237
-
238
-
239
-
240
-    /**
241
-     *    toggle_incomplete_registration_status_to_default
242
-     *        changes any incomplete registrations to either the event or global default registration status
243
-     *
244
-     * @access public
245
-     * @param EE_Registration $registration
246
-     * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
247
-     *                              to client code
248
-     * @param ContextInterface|null    $context
249
-     * @return void
250
-     * @throws EE_Error
251
-     * @throws InvalidArgumentException
252
-     * @throws ReflectionException
253
-     * @throws RuntimeException
254
-     * @throws EntityNotFoundException
255
-     * @throws InvalidDataTypeException
256
-     * @throws InvalidInterfaceException
257
-     */
258
-    public function toggle_incomplete_registration_status_to_default(
259
-        EE_Registration $registration,
260
-        $save = true,
261
-        ContextInterface $context = null
262
-    ) {
263
-        $existing_reg_status = $registration->status_ID();
264
-        // set initial REG_Status
265
-        $this->set_old_reg_status($registration->ID(), $existing_reg_status);
266
-        // is the registration currently incomplete ?
267
-        if ($registration->status_ID() === EEM_Registration::status_id_incomplete) {
268
-            // grab default reg status for the event, if set
269
-            $event_default_registration_status = $registration->event()->default_registration_status();
270
-            // if no default reg status is set for the event, then use the global value
271
-            $STS_ID = ! empty($event_default_registration_status)
272
-                ? $event_default_registration_status
273
-                : EE_Registry::instance()->CFG->registration->default_STS_ID;
274
-            // if the event default reg status is approved, then downgrade temporarily to payment pending to ensure that payments are triggered
275
-            $STS_ID = $STS_ID === EEM_Registration::status_id_approved ? EEM_Registration::status_id_pending_payment
276
-                : $STS_ID;
277
-            // set incoming REG_Status
278
-            $this->set_new_reg_status($registration->ID(), $STS_ID);
279
-            $registration->set_status($STS_ID, false, $context);
280
-            if ($save) {
281
-                $registration->save();
282
-            }
283
-            // don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
284
-            if (! EE_Processor_Base::$IPN) {
285
-                // otherwise, send out notifications
286
-                add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
287
-            }
288
-            // DEBUG LOG
289
-            //$this->log(
290
-            //	__CLASS__, __FUNCTION__, __LINE__,
291
-            //	$registration->transaction(),
292
-            //	array(
293
-            //		'IPN'                   => EE_Processor_Base::$IPN,
294
-            //		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
295
-            //	)
296
-            //);
297
-        }
298
-    }
299
-
300
-
301
-
302
-    /**
303
-     *    toggle_registration_status_for_default_approved_events
304
-     *
305
-     * @access public
306
-     * @param EE_Registration $registration
307
-     * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
308
-     *                              to client code
309
-     * @return bool
310
-     * @throws EE_Error
311
-     * @throws EntityNotFoundException
312
-     * @throws InvalidArgumentException
313
-     * @throws InvalidDataTypeException
314
-     * @throws InvalidInterfaceException
315
-     * @throws ReflectionException
316
-     * @throws RuntimeException
317
-     */
318
-    public function toggle_registration_status_for_default_approved_events(EE_Registration $registration, $save = true)
319
-    {
320
-        $reg_status = $registration->status_ID();
321
-        // set initial REG_Status
322
-        $this->set_old_reg_status($registration->ID(), $reg_status);
323
-        // if not already, toggle reg status to approved IF the event default reg status is approved
324
-        // ( as long as the registration wasn't cancelled or declined at some point )
325
-        if (
326
-            $reg_status !== EEM_Registration::status_id_cancelled
327
-            && $reg_status
328
-               !== EEM_Registration::status_id_declined
329
-            && $reg_status !== EEM_Registration::status_id_approved
330
-            && $registration->event()->default_registration_status() === EEM_Registration::status_id_approved
331
-        ) {
332
-            // set incoming REG_Status
333
-            $this->set_new_reg_status($registration->ID(), EEM_Registration::status_id_approved);
334
-            // toggle status to approved
335
-            $registration->set_status(EEM_Registration::status_id_approved);
336
-            if ($save) {
337
-                $registration->save();
338
-            }
339
-            // don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
340
-            if (! EE_Processor_Base::$IPN) {
341
-                // otherwise, send out notifications
342
-                add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
343
-            }
344
-            // DEBUG LOG
345
-            //$this->log(
346
-            //	__CLASS__, __FUNCTION__, __LINE__,
347
-            //	$registration->transaction(),
348
-            //	array(
349
-            //		'IPN'                   => EE_Processor_Base::$IPN,
350
-            //		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
351
-            //	)
352
-            //);
353
-            return true;
354
-        }
355
-        return false;
356
-    }
357
-
358
-
359
-
360
-    /**
361
-     *    toggle_registration_statuses_if_no_monies_owing
362
-     *
363
-     * @access public
364
-     * @param EE_Registration $registration
365
-     * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
366
-     *                              to client code
367
-     * @param array           $additional_details
368
-     * @return bool
369
-     * @throws EE_Error
370
-     * @throws EntityNotFoundException
371
-     * @throws InvalidArgumentException
372
-     * @throws InvalidDataTypeException
373
-     * @throws InvalidInterfaceException
374
-     * @throws ReflectionException
375
-     * @throws RuntimeException
376
-     */
377
-    public function toggle_registration_status_if_no_monies_owing(
378
-        EE_Registration $registration,
379
-        $save = true,
380
-        array $additional_details = array()
381
-    ) {
382
-        // set initial REG_Status
383
-        $this->set_old_reg_status($registration->ID(), $registration->status_ID());
384
-        // was a payment just made ?
385
-        $payment    = isset($additional_details['payment_updates'], $additional_details['last_payment'])
386
-                      && $additional_details['payment_updates']
387
-                      && $additional_details['last_payment'] instanceof EE_Payment
388
-            ? $additional_details['last_payment']
389
-            : null;
390
-        $total_paid = array_sum(self::$_amount_paid);
391
-        // toggle reg status to approved IF
392
-        if (
393
-            // REG status is pending payment
394
-            $registration->status_ID() === EEM_Registration::status_id_pending_payment
395
-            // AND no monies are owing
396
-            && (
397
-                (
398
-                    $registration->transaction()->is_completed()
399
-                    || $registration->transaction()->is_overpaid()
400
-                    || $registration->transaction()->is_free()
401
-                    || apply_filters(
402
-                        'FHEE__EE_Registration_Processor__toggle_registration_status_if_no_monies_owing',
403
-                        false,
404
-                        $registration
405
-                    )
406
-                )
407
-                || (
408
-                    $payment instanceof EE_Payment && $payment->is_approved()
409
-                    && // this specific registration has not yet been paid for
410
-                    ! isset(self::$_amount_paid[$registration->ID()])
411
-                    && // payment amount, less what we have already attributed to other registrations, is greater than this reg's final price
412
-                    $payment->amount() - $total_paid >= $registration->final_price()
413
-                )
414
-            )
415
-        ) {
416
-            // mark as paid
417
-            self::$_amount_paid[$registration->ID()] = $registration->final_price();
418
-            // track new REG_Status
419
-            $this->set_new_reg_status($registration->ID(), EEM_Registration::status_id_approved);
420
-            // toggle status to approved
421
-            $registration->set_status(EEM_Registration::status_id_approved);
422
-            if ($save) {
423
-                $registration->save();
424
-            }
425
-            // don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
426
-            if (! EE_Processor_Base::$IPN) {
427
-                // otherwise, send out notifications
428
-                add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
429
-            }
430
-            // DEBUG LOG
431
-            //$this->log(
432
-            //	__CLASS__, __FUNCTION__, __LINE__,
433
-            //	$registration->transaction(),
434
-            //	array(
435
-            //		'IPN'                   => EE_Processor_Base::$IPN,
436
-            //		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
437
-            //	)
438
-            //);
439
-            return true;
440
-        }
441
-        return false;
442
-    }
443
-
444
-
445
-
446
-    /**
447
-     *    registration_status_changed
448
-     *
449
-     * @access public
450
-     * @param EE_Registration $registration
451
-     * @param array           $additional_details
452
-     * @return void
453
-     */
454
-    public function trigger_registration_update_notifications($registration, array $additional_details = array())
455
-    {
456
-        try {
457
-            if (! $registration instanceof EE_Registration) {
458
-                throw new EE_Error(
459
-                    esc_html__('An invalid registration was received.', 'event_espresso')
460
-                );
461
-            }
462
-            // EE_Registry::instance()->load_helper( 'Debug_Tools' );
463
-            // EEH_Debug_Tools::log(
464
-            // 	__CLASS__,
465
-            // 	__FUNCTION__,
466
-            // 	__LINE__,
467
-            // 	array( $registration->transaction(), $additional_details ),
468
-            // 	false,
469
-            // 	'EE_Transaction: ' . $registration->transaction()->ID()
470
-            // );
471
-            if (! $registration->is_primary_registrant()) {
472
-                return;
473
-            }
474
-            do_action(
475
-                'AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
476
-                $registration,
477
-                $additional_details
478
-            );
479
-        } catch (Exception $e) {
480
-            EE_Error::add_error($e->getMessage(), $e->getFile(), 'unknown_function_from_exception', $e->getLine());
481
-        }
482
-    }
483
-
484
-
485
-
486
-    /**
487
-     * sets reg status based either on passed param or on transaction status and event pre-approval setting
488
-     *
489
-     * @param EE_Registration $registration
490
-     * @param array           $additional_details
491
-     * @return bool
492
-     * @throws EE_Error
493
-     * @throws EntityNotFoundException
494
-     * @throws InvalidArgumentException
495
-     * @throws InvalidDataTypeException
496
-     * @throws InvalidInterfaceException
497
-     * @throws ReflectionException
498
-     * @throws RuntimeException
499
-     */
500
-    public function update_registration_after_checkout_or_payment(
501
-        EE_Registration $registration,
502
-        array $additional_details = array()
503
-    ) {
504
-        // set initial REG_Status
505
-        $this->set_old_reg_status($registration->ID(), $registration->status_ID());
506
-        // if the registration status gets updated, then save the registration
507
-        if (
508
-            $this->toggle_registration_status_for_default_approved_events($registration, false)
509
-            || $this->toggle_registration_status_if_no_monies_owing(
510
-                $registration,
511
-                false,
512
-                $additional_details
513
-            )
514
-        ) {
515
-            $registration->save();
516
-        }
517
-        // set new  REG_Status
518
-        $this->set_new_reg_status($registration->ID(), $registration->status_ID());
519
-        return $this->reg_status_updated($registration->ID())
520
-               && $this->new_reg_status($registration->ID()) === EEM_Registration::status_id_approved;
521
-    }
522
-
523
-
524
-
525
-    /**
526
-     * Updates the registration' final prices based on the current line item tree (taking into account
527
-     * discounts, taxes, and other line items unrelated to tickets.)
528
-     *
529
-     * @param EE_Transaction $transaction
530
-     * @param boolean        $save_regs whether to immediately save registrations in this function or not
531
-     * @return void
532
-     * @throws EE_Error
533
-     * @throws InvalidArgumentException
534
-     * @throws InvalidDataTypeException
535
-     * @throws InvalidInterfaceException
536
-     * @throws RuntimeException
537
-     */
538
-    public function update_registration_final_prices($transaction, $save_regs = true)
539
-    {
540
-        $reg_final_price_per_ticket_line_item = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
541
-            $transaction->total_line_item()
542
-        );
543
-        foreach ($transaction->registrations() as $registration) {
544
-            /** @var EE_Line_Item $line_item */
545
-            $line_item = EEM_Line_Item::instance()->get_line_item_for_registration($registration);
546
-            if (isset($reg_final_price_per_ticket_line_item[$line_item->ID()])) {
547
-                $registration->set_final_price($reg_final_price_per_ticket_line_item[$line_item->ID()]);
548
-                if ($save_regs) {
549
-                    $registration->save();
550
-                }
551
-            }
552
-        }
553
-        //and make sure there's no rounding problem
554
-        $this->fix_reg_final_price_rounding_issue($transaction);
555
-    }
556
-
557
-
558
-
559
-    /**
560
-     * Makes sure there is no rounding errors for the REG_final_prices.
561
-     * Eg, if we have 3 registrations for $1, and there is a $0.01 discount between the three of them,
562
-     * they will each be for $0.99333333, which gets rounded to $1 again.
563
-     * So the transaction total will be $2.99, but each registration will be for $1,
564
-     * so if each registrant paid individually they will have overpaid by $0.01.
565
-     * So in order to overcome this, we check for any difference, and if there is a difference
566
-     * we just grab one registrant at random and make them responsible for it.
567
-     * This should be used after setting REG_final_prices (it's done automatically as part of
568
-     * EE_Registration_Processor::update_registration_final_prices())
569
-     *
570
-     * @param EE_Transaction $transaction
571
-     * @return bool success verifying that there is NO difference after this method is done
572
-     * @throws EE_Error
573
-     * @throws InvalidArgumentException
574
-     * @throws InvalidDataTypeException
575
-     * @throws InvalidInterfaceException
576
-     */
577
-    public function fix_reg_final_price_rounding_issue($transaction)
578
-    {
579
-        $reg_final_price_sum = EEM_Registration::instance()->sum(
580
-            array(
581
-                array(
582
-                    'TXN_ID' => $transaction->ID(),
583
-                ),
584
-            ),
585
-            'REG_final_price'
586
-        );
587
-        $diff = $transaction->total() - $reg_final_price_sum;
588
-        //ok then, just grab one of the registrations
589
-        if ($diff !== 0) {
590
-            $a_reg   = EEM_Registration::instance()->get_one(
591
-                array(
592
-                    array(
593
-                        'TXN_ID' => $transaction->ID(),
594
-                    ),
595
-                )
596
-            );
597
-            return $a_reg instanceof EE_Registration
598
-                ? (bool) $a_reg->save(array('REG_final_price' => $a_reg->final_price() + $diff))
599
-                : false;
600
-        }
601
-        return true;
602
-    }
603
-
604
-
605
-
606
-    /**
607
-     * update_registration_after_being_canceled_or_declined
608
-     *
609
-     * @param EE_Registration $registration
610
-     * @param array           $closed_reg_statuses
611
-     * @param bool            $update_reg
612
-     * @return bool
613
-     * @throws EE_Error
614
-     * @throws RuntimeException
615
-     */
616
-    public function update_registration_after_being_canceled_or_declined(
617
-        EE_Registration $registration,
618
-        array $closed_reg_statuses = array(),
619
-        $update_reg = true
620
-    ) {
621
-        // these reg statuses should not be considered in any calculations involving monies owing
622
-        $closed_reg_statuses = ! empty($closed_reg_statuses)
623
-            ? $closed_reg_statuses
624
-            : EEM_Registration::closed_reg_statuses();
625
-        if (! in_array($registration->status_ID(), $closed_reg_statuses, true)) {
626
-            return false;
627
-        }
628
-        // release a reserved ticket by decrementing ticket and datetime reserved values
629
-        $registration->release_reserved_ticket(true);
630
-        $registration->set_final_price(0);
631
-        if ($update_reg) {
632
-            $registration->save();
633
-        }
634
-        return true;
635
-    }
636
-
637
-
638
-
639
-    /**
640
-     * update_canceled_or_declined_registration_after_being_reinstated
641
-     *
642
-     * @param EE_Registration $registration
643
-     * @param array           $closed_reg_statuses
644
-     * @param bool            $update_reg
645
-     * @return bool
646
-     * @throws EE_Error
647
-     * @throws RuntimeException
648
-     */
649
-    public function update_canceled_or_declined_registration_after_being_reinstated(
650
-        EE_Registration $registration,
651
-        array $closed_reg_statuses = array(),
652
-        $update_reg = true
653
-    ) {
654
-        // these reg statuses should not be considered in any calculations involving monies owing
655
-        $closed_reg_statuses = ! empty($closed_reg_statuses) ? $closed_reg_statuses
656
-            : EEM_Registration::closed_reg_statuses();
657
-        if (in_array($registration->status_ID(), $closed_reg_statuses, true)) {
658
-            return false;
659
-        }
660
-        $ticket = $registration->ticket();
661
-        if (! $ticket instanceof EE_Ticket) {
662
-            throw new EE_Error(
663
-                sprintf(
664
-                    esc_html__(
665
-                        'The Ticket for Registration %1$d was not found or is invalid.',
666
-                        'event_espresso'
667
-                    ),
668
-                    $registration->ticket_ID()
669
-                )
670
-            );
671
-        }
672
-        $registration->set_final_price($ticket->price());
673
-        if ($update_reg) {
674
-            $registration->save();
675
-        }
676
-        return true;
677
-    }
678
-
679
-
680
-
681
-    /**
682
-     * generate_ONE_registration_from_line_item
683
-     * Although a ticket line item may have a quantity greater than 1,
684
-     * this method will ONLY CREATE ONE REGISTRATION !!!
685
-     * Regardless of the ticket line item quantity.
686
-     * This means that any code calling this method is responsible for ensuring
687
-     * that the final registration count matches the ticket line item quantity.
688
-     * This was done to make it easier to match the number of registrations
689
-     * to the number of tickets in the cart, when the cart has been edited
690
-     * after SPCO has already been initialized. So if an additional ticket was added to the cart, you can simply pass
691
-     * the line item to this method to add a second ticket, and in this case, you would not want to add 2 tickets.
692
-     *
693
-     * @deprecated
694
-     * @since 4.9.1
695
-     * @param EE_Line_Item    $line_item
696
-     * @param \EE_Transaction $transaction
697
-     * @param int             $att_nmbr
698
-     * @param int             $total_ticket_count
699
-     * @return EE_Registration | null
700
-     * @throws \OutOfRangeException
701
-     * @throws \EventEspresso\core\exceptions\UnexpectedEntityException
702
-     * @throws \EE_Error
703
-     */
704
-    public function generate_ONE_registration_from_line_item(
705
-        EE_Line_Item $line_item,
706
-        EE_Transaction $transaction,
707
-        $att_nmbr = 1,
708
-        $total_ticket_count = 1
709
-    ) {
710
-        EE_Error::doing_it_wrong(
711
-            __CLASS__ . '::' . __FUNCTION__,
712
-            sprintf(
713
-                esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
714
-                '\EventEspresso\core\domain\services\registration\CreateRegistrationService::create()'
715
-            ),
716
-            '4.9.1',
717
-            '5.0.0'
718
-        );
719
-        // grab the related ticket object for this line_item
720
-        $ticket = $line_item->ticket();
721
-        if (! $ticket instanceof EE_Ticket) {
722
-            EE_Error::add_error(
723
-                sprintf(
724
-                    esc_html__('Line item %s did not contain a valid ticket', 'event_espresso'),
725
-                    $line_item->ID()
726
-                ),
727
-                __FILE__,
728
-                __FUNCTION__,
729
-                __LINE__
730
-            );
731
-            return null;
732
-        }
733
-        $registration_service = new CreateRegistrationService();
734
-        // then generate a new registration from that
735
-        return $registration_service->create(
736
-            $ticket->get_related_event(),
737
-            $transaction,
738
-            $ticket,
739
-            $line_item,
740
-            $att_nmbr,
741
-            $total_ticket_count
742
-        );
743
-    }
744
-
745
-
746
-
747
-    /**
748
-     * generates reg_url_link
749
-     *
750
-     * @deprecated
751
-     * @since 4.9.1
752
-     * @param int                   $att_nmbr
753
-     * @param EE_Line_Item | string $item
754
-     * @return string
755
-     * @throws InvalidArgumentException
756
-     */
757
-    public function generate_reg_url_link($att_nmbr, $item)
758
-    {
759
-        EE_Error::doing_it_wrong(
760
-            __CLASS__ . '::' . __FUNCTION__,
761
-            sprintf(
762
-                esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
763
-                'EventEspresso\core\domain\entities\RegUrlLink'
764
-            ),
765
-            '4.9.1',
766
-            '5.0.0'
767
-        );
768
-        return new RegUrlLink($att_nmbr, $item);
769
-    }
770
-
771
-
772
-
773
-    /**
774
-     * generates reg code
775
-     *
776
-     * @deprecated
777
-     * @since 4.9.1
778
-     * @param EE_Registration $registration
779
-     * @return string
780
-     * @throws EE_Error
781
-     * @throws EntityNotFoundException
782
-     * @throws InvalidArgumentException
783
-     */
784
-    public function generate_reg_code(EE_Registration $registration)
785
-    {
786
-        EE_Error::doing_it_wrong(
787
-            __CLASS__ . '::' . __FUNCTION__,
788
-            sprintf(
789
-                esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
790
-                'EventEspresso\core\domain\entities\RegCode'
791
-            ),
792
-            '4.9.1',
793
-            '5.0.0'
794
-        );
795
-        return apply_filters(
796
-            'FHEE__EE_Registration_Processor___generate_reg_code__new_reg_code',
797
-            new RegCode(
798
-                RegUrlLink::fromRegistration($registration),
799
-                $registration->transaction(),
800
-                $registration->ticket()
801
-            ),
802
-            $registration
803
-        );
804
-    }
30
+	/**
31
+	 * @var EE_Registration_Processor $_instance
32
+	 * @access    private
33
+	 */
34
+	private static $_instance;
35
+
36
+	/**
37
+	 * initial reg status at the beginning of this request.
38
+	 * indexed by registration ID
39
+	 *
40
+	 * @var array
41
+	 */
42
+	protected $_old_reg_status = array();
43
+
44
+	/**
45
+	 * reg status at the end of the request after all processing.
46
+	 * indexed by registration ID
47
+	 *
48
+	 * @var array
49
+	 */
50
+	protected $_new_reg_status = array();
51
+
52
+	/**
53
+	 * amounts paid at the end of the request after all processing.
54
+	 * indexed by registration ID
55
+	 *
56
+	 * @var array
57
+	 */
58
+	protected static $_amount_paid = array();
59
+
60
+	/**
61
+	 * Cache of the reg final price for registrations corresponding to a ticket line item
62
+	 *
63
+	 * @deprecated
64
+	 * @var array @see EEH_Line_Item::calculate_reg_final_prices_per_line_item()'s return value
65
+	 */
66
+	protected $_reg_final_price_per_tkt_line_item;
67
+
68
+	/**
69
+	 * @var EE_Request $request
70
+	 */
71
+	protected $request;
72
+
73
+
74
+
75
+	/**
76
+	 * @singleton method used to instantiate class object
77
+	 * @param EE_Request|null $request
78
+	 * @return EE_Registration_Processor instance
79
+	 * @throws \InvalidArgumentException
80
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
81
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
82
+	 */
83
+	public static function instance(EE_Request $request = null)
84
+	{
85
+		// check if class object is instantiated
86
+		if (! self::$_instance instanceof EE_Registration_Processor) {
87
+			if(! $request instanceof EE_Request) {
88
+				$request = LoaderFactory::getLoader()->getShared('EE_Request');
89
+			}
90
+			self::$_instance = new self($request);
91
+		}
92
+		return self::$_instance;
93
+	}
94
+
95
+
96
+	/**
97
+	 * EE_Registration_Processor constructor.
98
+	 *
99
+	 * @param EE_Request $request
100
+	 */
101
+	public function __construct(EE_Request $request)
102
+	{
103
+		$this->request = $request;
104
+	}
105
+
106
+
107
+
108
+	/**
109
+	 * @param int $REG_ID
110
+	 * @return string
111
+	 */
112
+	public function old_reg_status($REG_ID)
113
+	{
114
+		return isset($this->_old_reg_status[$REG_ID]) ? $this->_old_reg_status[$REG_ID] : null;
115
+	}
116
+
117
+
118
+
119
+	/**
120
+	 * @param int    $REG_ID
121
+	 * @param string $old_reg_status
122
+	 */
123
+	public function set_old_reg_status($REG_ID, $old_reg_status)
124
+	{
125
+		// only set the first time
126
+		if (! isset($this->_old_reg_status[$REG_ID])) {
127
+			$this->_old_reg_status[$REG_ID] = $old_reg_status;
128
+		}
129
+	}
130
+
131
+
132
+
133
+	/**
134
+	 * @param int $REG_ID
135
+	 * @return string
136
+	 */
137
+	public function new_reg_status($REG_ID)
138
+	{
139
+		return isset($this->_new_reg_status[$REG_ID]) ? $this->_new_reg_status[$REG_ID] : null;
140
+	}
141
+
142
+
143
+
144
+	/**
145
+	 * @param int    $REG_ID
146
+	 * @param string $new_reg_status
147
+	 */
148
+	public function set_new_reg_status($REG_ID, $new_reg_status)
149
+	{
150
+		$this->_new_reg_status[$REG_ID] = $new_reg_status;
151
+	}
152
+
153
+
154
+
155
+	/**
156
+	 * reg_status_updated
157
+	 *
158
+	 * @param int $REG_ID
159
+	 * @return bool
160
+	 */
161
+	public function reg_status_updated($REG_ID)
162
+	{
163
+		return $this->new_reg_status($REG_ID) !== $this->old_reg_status($REG_ID);
164
+	}
165
+
166
+
167
+
168
+	/**
169
+	 * @param EE_Registration $registration
170
+	 * @throws EE_Error
171
+	 * @throws EntityNotFoundException
172
+	 * @throws InvalidArgumentException
173
+	 * @throws InvalidDataTypeException
174
+	 * @throws InvalidInterfaceException
175
+	 * @throws ReflectionException
176
+	 * @throws RuntimeException
177
+	 */
178
+	public function update_registration_status_and_trigger_notifications(EE_Registration $registration)
179
+	{
180
+		$this->toggle_incomplete_registration_status_to_default($registration, false);
181
+		$this->toggle_registration_status_for_default_approved_events($registration, false);
182
+		$this->toggle_registration_status_if_no_monies_owing($registration, false);
183
+		$registration->save();
184
+		// trigger notifications
185
+		$this->trigger_registration_update_notifications($registration);
186
+	}
187
+
188
+
189
+
190
+	/**
191
+	 *    manually_update_registration_status
192
+	 *
193
+	 * @access public
194
+	 * @param EE_Registration $registration
195
+	 * @param string          $new_reg_status
196
+	 * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
197
+	 *                              to client code
198
+	 * @return bool
199
+	 * @throws EE_Error
200
+	 * @throws EntityNotFoundException
201
+	 * @throws InvalidArgumentException
202
+	 * @throws InvalidDataTypeException
203
+	 * @throws InvalidInterfaceException
204
+	 * @throws ReflectionException
205
+	 * @throws RuntimeException
206
+	 */
207
+	public function manually_update_registration_status(
208
+		EE_Registration $registration,
209
+		$new_reg_status = '',
210
+		$save = true
211
+	) {
212
+		// set initial REG_Status
213
+		$this->set_old_reg_status($registration->ID(), $registration->status_ID());
214
+		// set incoming REG_Status
215
+		$this->set_new_reg_status($registration->ID(), $new_reg_status);
216
+		// toggle reg status but only if it has changed and the user can do so
217
+		if (
218
+			$this->reg_status_updated($registration->ID())
219
+			&& (
220
+				(! $this->request->isAdmin() || $this->request->isFrontAjax())
221
+				|| EE_Registry::instance()->CAP->current_user_can(
222
+					'ee_edit_registration',
223
+					'toggle_registration_status',
224
+					$registration->ID()
225
+				)
226
+			)
227
+		) {
228
+			// change status to new value
229
+			$updated = $registration->set_status($this->new_reg_status($registration->ID()));
230
+			if ($updated && $save) {
231
+				$registration->save();
232
+			}
233
+			return true;
234
+		}
235
+		return false;
236
+	}
237
+
238
+
239
+
240
+	/**
241
+	 *    toggle_incomplete_registration_status_to_default
242
+	 *        changes any incomplete registrations to either the event or global default registration status
243
+	 *
244
+	 * @access public
245
+	 * @param EE_Registration $registration
246
+	 * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
247
+	 *                              to client code
248
+	 * @param ContextInterface|null    $context
249
+	 * @return void
250
+	 * @throws EE_Error
251
+	 * @throws InvalidArgumentException
252
+	 * @throws ReflectionException
253
+	 * @throws RuntimeException
254
+	 * @throws EntityNotFoundException
255
+	 * @throws InvalidDataTypeException
256
+	 * @throws InvalidInterfaceException
257
+	 */
258
+	public function toggle_incomplete_registration_status_to_default(
259
+		EE_Registration $registration,
260
+		$save = true,
261
+		ContextInterface $context = null
262
+	) {
263
+		$existing_reg_status = $registration->status_ID();
264
+		// set initial REG_Status
265
+		$this->set_old_reg_status($registration->ID(), $existing_reg_status);
266
+		// is the registration currently incomplete ?
267
+		if ($registration->status_ID() === EEM_Registration::status_id_incomplete) {
268
+			// grab default reg status for the event, if set
269
+			$event_default_registration_status = $registration->event()->default_registration_status();
270
+			// if no default reg status is set for the event, then use the global value
271
+			$STS_ID = ! empty($event_default_registration_status)
272
+				? $event_default_registration_status
273
+				: EE_Registry::instance()->CFG->registration->default_STS_ID;
274
+			// if the event default reg status is approved, then downgrade temporarily to payment pending to ensure that payments are triggered
275
+			$STS_ID = $STS_ID === EEM_Registration::status_id_approved ? EEM_Registration::status_id_pending_payment
276
+				: $STS_ID;
277
+			// set incoming REG_Status
278
+			$this->set_new_reg_status($registration->ID(), $STS_ID);
279
+			$registration->set_status($STS_ID, false, $context);
280
+			if ($save) {
281
+				$registration->save();
282
+			}
283
+			// don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
284
+			if (! EE_Processor_Base::$IPN) {
285
+				// otherwise, send out notifications
286
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
287
+			}
288
+			// DEBUG LOG
289
+			//$this->log(
290
+			//	__CLASS__, __FUNCTION__, __LINE__,
291
+			//	$registration->transaction(),
292
+			//	array(
293
+			//		'IPN'                   => EE_Processor_Base::$IPN,
294
+			//		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
295
+			//	)
296
+			//);
297
+		}
298
+	}
299
+
300
+
301
+
302
+	/**
303
+	 *    toggle_registration_status_for_default_approved_events
304
+	 *
305
+	 * @access public
306
+	 * @param EE_Registration $registration
307
+	 * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
308
+	 *                              to client code
309
+	 * @return bool
310
+	 * @throws EE_Error
311
+	 * @throws EntityNotFoundException
312
+	 * @throws InvalidArgumentException
313
+	 * @throws InvalidDataTypeException
314
+	 * @throws InvalidInterfaceException
315
+	 * @throws ReflectionException
316
+	 * @throws RuntimeException
317
+	 */
318
+	public function toggle_registration_status_for_default_approved_events(EE_Registration $registration, $save = true)
319
+	{
320
+		$reg_status = $registration->status_ID();
321
+		// set initial REG_Status
322
+		$this->set_old_reg_status($registration->ID(), $reg_status);
323
+		// if not already, toggle reg status to approved IF the event default reg status is approved
324
+		// ( as long as the registration wasn't cancelled or declined at some point )
325
+		if (
326
+			$reg_status !== EEM_Registration::status_id_cancelled
327
+			&& $reg_status
328
+			   !== EEM_Registration::status_id_declined
329
+			&& $reg_status !== EEM_Registration::status_id_approved
330
+			&& $registration->event()->default_registration_status() === EEM_Registration::status_id_approved
331
+		) {
332
+			// set incoming REG_Status
333
+			$this->set_new_reg_status($registration->ID(), EEM_Registration::status_id_approved);
334
+			// toggle status to approved
335
+			$registration->set_status(EEM_Registration::status_id_approved);
336
+			if ($save) {
337
+				$registration->save();
338
+			}
339
+			// don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
340
+			if (! EE_Processor_Base::$IPN) {
341
+				// otherwise, send out notifications
342
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
343
+			}
344
+			// DEBUG LOG
345
+			//$this->log(
346
+			//	__CLASS__, __FUNCTION__, __LINE__,
347
+			//	$registration->transaction(),
348
+			//	array(
349
+			//		'IPN'                   => EE_Processor_Base::$IPN,
350
+			//		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
351
+			//	)
352
+			//);
353
+			return true;
354
+		}
355
+		return false;
356
+	}
357
+
358
+
359
+
360
+	/**
361
+	 *    toggle_registration_statuses_if_no_monies_owing
362
+	 *
363
+	 * @access public
364
+	 * @param EE_Registration $registration
365
+	 * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
366
+	 *                              to client code
367
+	 * @param array           $additional_details
368
+	 * @return bool
369
+	 * @throws EE_Error
370
+	 * @throws EntityNotFoundException
371
+	 * @throws InvalidArgumentException
372
+	 * @throws InvalidDataTypeException
373
+	 * @throws InvalidInterfaceException
374
+	 * @throws ReflectionException
375
+	 * @throws RuntimeException
376
+	 */
377
+	public function toggle_registration_status_if_no_monies_owing(
378
+		EE_Registration $registration,
379
+		$save = true,
380
+		array $additional_details = array()
381
+	) {
382
+		// set initial REG_Status
383
+		$this->set_old_reg_status($registration->ID(), $registration->status_ID());
384
+		// was a payment just made ?
385
+		$payment    = isset($additional_details['payment_updates'], $additional_details['last_payment'])
386
+					  && $additional_details['payment_updates']
387
+					  && $additional_details['last_payment'] instanceof EE_Payment
388
+			? $additional_details['last_payment']
389
+			: null;
390
+		$total_paid = array_sum(self::$_amount_paid);
391
+		// toggle reg status to approved IF
392
+		if (
393
+			// REG status is pending payment
394
+			$registration->status_ID() === EEM_Registration::status_id_pending_payment
395
+			// AND no monies are owing
396
+			&& (
397
+				(
398
+					$registration->transaction()->is_completed()
399
+					|| $registration->transaction()->is_overpaid()
400
+					|| $registration->transaction()->is_free()
401
+					|| apply_filters(
402
+						'FHEE__EE_Registration_Processor__toggle_registration_status_if_no_monies_owing',
403
+						false,
404
+						$registration
405
+					)
406
+				)
407
+				|| (
408
+					$payment instanceof EE_Payment && $payment->is_approved()
409
+					&& // this specific registration has not yet been paid for
410
+					! isset(self::$_amount_paid[$registration->ID()])
411
+					&& // payment amount, less what we have already attributed to other registrations, is greater than this reg's final price
412
+					$payment->amount() - $total_paid >= $registration->final_price()
413
+				)
414
+			)
415
+		) {
416
+			// mark as paid
417
+			self::$_amount_paid[$registration->ID()] = $registration->final_price();
418
+			// track new REG_Status
419
+			$this->set_new_reg_status($registration->ID(), EEM_Registration::status_id_approved);
420
+			// toggle status to approved
421
+			$registration->set_status(EEM_Registration::status_id_approved);
422
+			if ($save) {
423
+				$registration->save();
424
+			}
425
+			// don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
426
+			if (! EE_Processor_Base::$IPN) {
427
+				// otherwise, send out notifications
428
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
429
+			}
430
+			// DEBUG LOG
431
+			//$this->log(
432
+			//	__CLASS__, __FUNCTION__, __LINE__,
433
+			//	$registration->transaction(),
434
+			//	array(
435
+			//		'IPN'                   => EE_Processor_Base::$IPN,
436
+			//		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
437
+			//	)
438
+			//);
439
+			return true;
440
+		}
441
+		return false;
442
+	}
443
+
444
+
445
+
446
+	/**
447
+	 *    registration_status_changed
448
+	 *
449
+	 * @access public
450
+	 * @param EE_Registration $registration
451
+	 * @param array           $additional_details
452
+	 * @return void
453
+	 */
454
+	public function trigger_registration_update_notifications($registration, array $additional_details = array())
455
+	{
456
+		try {
457
+			if (! $registration instanceof EE_Registration) {
458
+				throw new EE_Error(
459
+					esc_html__('An invalid registration was received.', 'event_espresso')
460
+				);
461
+			}
462
+			// EE_Registry::instance()->load_helper( 'Debug_Tools' );
463
+			// EEH_Debug_Tools::log(
464
+			// 	__CLASS__,
465
+			// 	__FUNCTION__,
466
+			// 	__LINE__,
467
+			// 	array( $registration->transaction(), $additional_details ),
468
+			// 	false,
469
+			// 	'EE_Transaction: ' . $registration->transaction()->ID()
470
+			// );
471
+			if (! $registration->is_primary_registrant()) {
472
+				return;
473
+			}
474
+			do_action(
475
+				'AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
476
+				$registration,
477
+				$additional_details
478
+			);
479
+		} catch (Exception $e) {
480
+			EE_Error::add_error($e->getMessage(), $e->getFile(), 'unknown_function_from_exception', $e->getLine());
481
+		}
482
+	}
483
+
484
+
485
+
486
+	/**
487
+	 * sets reg status based either on passed param or on transaction status and event pre-approval setting
488
+	 *
489
+	 * @param EE_Registration $registration
490
+	 * @param array           $additional_details
491
+	 * @return bool
492
+	 * @throws EE_Error
493
+	 * @throws EntityNotFoundException
494
+	 * @throws InvalidArgumentException
495
+	 * @throws InvalidDataTypeException
496
+	 * @throws InvalidInterfaceException
497
+	 * @throws ReflectionException
498
+	 * @throws RuntimeException
499
+	 */
500
+	public function update_registration_after_checkout_or_payment(
501
+		EE_Registration $registration,
502
+		array $additional_details = array()
503
+	) {
504
+		// set initial REG_Status
505
+		$this->set_old_reg_status($registration->ID(), $registration->status_ID());
506
+		// if the registration status gets updated, then save the registration
507
+		if (
508
+			$this->toggle_registration_status_for_default_approved_events($registration, false)
509
+			|| $this->toggle_registration_status_if_no_monies_owing(
510
+				$registration,
511
+				false,
512
+				$additional_details
513
+			)
514
+		) {
515
+			$registration->save();
516
+		}
517
+		// set new  REG_Status
518
+		$this->set_new_reg_status($registration->ID(), $registration->status_ID());
519
+		return $this->reg_status_updated($registration->ID())
520
+			   && $this->new_reg_status($registration->ID()) === EEM_Registration::status_id_approved;
521
+	}
522
+
523
+
524
+
525
+	/**
526
+	 * Updates the registration' final prices based on the current line item tree (taking into account
527
+	 * discounts, taxes, and other line items unrelated to tickets.)
528
+	 *
529
+	 * @param EE_Transaction $transaction
530
+	 * @param boolean        $save_regs whether to immediately save registrations in this function or not
531
+	 * @return void
532
+	 * @throws EE_Error
533
+	 * @throws InvalidArgumentException
534
+	 * @throws InvalidDataTypeException
535
+	 * @throws InvalidInterfaceException
536
+	 * @throws RuntimeException
537
+	 */
538
+	public function update_registration_final_prices($transaction, $save_regs = true)
539
+	{
540
+		$reg_final_price_per_ticket_line_item = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
541
+			$transaction->total_line_item()
542
+		);
543
+		foreach ($transaction->registrations() as $registration) {
544
+			/** @var EE_Line_Item $line_item */
545
+			$line_item = EEM_Line_Item::instance()->get_line_item_for_registration($registration);
546
+			if (isset($reg_final_price_per_ticket_line_item[$line_item->ID()])) {
547
+				$registration->set_final_price($reg_final_price_per_ticket_line_item[$line_item->ID()]);
548
+				if ($save_regs) {
549
+					$registration->save();
550
+				}
551
+			}
552
+		}
553
+		//and make sure there's no rounding problem
554
+		$this->fix_reg_final_price_rounding_issue($transaction);
555
+	}
556
+
557
+
558
+
559
+	/**
560
+	 * Makes sure there is no rounding errors for the REG_final_prices.
561
+	 * Eg, if we have 3 registrations for $1, and there is a $0.01 discount between the three of them,
562
+	 * they will each be for $0.99333333, which gets rounded to $1 again.
563
+	 * So the transaction total will be $2.99, but each registration will be for $1,
564
+	 * so if each registrant paid individually they will have overpaid by $0.01.
565
+	 * So in order to overcome this, we check for any difference, and if there is a difference
566
+	 * we just grab one registrant at random and make them responsible for it.
567
+	 * This should be used after setting REG_final_prices (it's done automatically as part of
568
+	 * EE_Registration_Processor::update_registration_final_prices())
569
+	 *
570
+	 * @param EE_Transaction $transaction
571
+	 * @return bool success verifying that there is NO difference after this method is done
572
+	 * @throws EE_Error
573
+	 * @throws InvalidArgumentException
574
+	 * @throws InvalidDataTypeException
575
+	 * @throws InvalidInterfaceException
576
+	 */
577
+	public function fix_reg_final_price_rounding_issue($transaction)
578
+	{
579
+		$reg_final_price_sum = EEM_Registration::instance()->sum(
580
+			array(
581
+				array(
582
+					'TXN_ID' => $transaction->ID(),
583
+				),
584
+			),
585
+			'REG_final_price'
586
+		);
587
+		$diff = $transaction->total() - $reg_final_price_sum;
588
+		//ok then, just grab one of the registrations
589
+		if ($diff !== 0) {
590
+			$a_reg   = EEM_Registration::instance()->get_one(
591
+				array(
592
+					array(
593
+						'TXN_ID' => $transaction->ID(),
594
+					),
595
+				)
596
+			);
597
+			return $a_reg instanceof EE_Registration
598
+				? (bool) $a_reg->save(array('REG_final_price' => $a_reg->final_price() + $diff))
599
+				: false;
600
+		}
601
+		return true;
602
+	}
603
+
604
+
605
+
606
+	/**
607
+	 * update_registration_after_being_canceled_or_declined
608
+	 *
609
+	 * @param EE_Registration $registration
610
+	 * @param array           $closed_reg_statuses
611
+	 * @param bool            $update_reg
612
+	 * @return bool
613
+	 * @throws EE_Error
614
+	 * @throws RuntimeException
615
+	 */
616
+	public function update_registration_after_being_canceled_or_declined(
617
+		EE_Registration $registration,
618
+		array $closed_reg_statuses = array(),
619
+		$update_reg = true
620
+	) {
621
+		// these reg statuses should not be considered in any calculations involving monies owing
622
+		$closed_reg_statuses = ! empty($closed_reg_statuses)
623
+			? $closed_reg_statuses
624
+			: EEM_Registration::closed_reg_statuses();
625
+		if (! in_array($registration->status_ID(), $closed_reg_statuses, true)) {
626
+			return false;
627
+		}
628
+		// release a reserved ticket by decrementing ticket and datetime reserved values
629
+		$registration->release_reserved_ticket(true);
630
+		$registration->set_final_price(0);
631
+		if ($update_reg) {
632
+			$registration->save();
633
+		}
634
+		return true;
635
+	}
636
+
637
+
638
+
639
+	/**
640
+	 * update_canceled_or_declined_registration_after_being_reinstated
641
+	 *
642
+	 * @param EE_Registration $registration
643
+	 * @param array           $closed_reg_statuses
644
+	 * @param bool            $update_reg
645
+	 * @return bool
646
+	 * @throws EE_Error
647
+	 * @throws RuntimeException
648
+	 */
649
+	public function update_canceled_or_declined_registration_after_being_reinstated(
650
+		EE_Registration $registration,
651
+		array $closed_reg_statuses = array(),
652
+		$update_reg = true
653
+	) {
654
+		// these reg statuses should not be considered in any calculations involving monies owing
655
+		$closed_reg_statuses = ! empty($closed_reg_statuses) ? $closed_reg_statuses
656
+			: EEM_Registration::closed_reg_statuses();
657
+		if (in_array($registration->status_ID(), $closed_reg_statuses, true)) {
658
+			return false;
659
+		}
660
+		$ticket = $registration->ticket();
661
+		if (! $ticket instanceof EE_Ticket) {
662
+			throw new EE_Error(
663
+				sprintf(
664
+					esc_html__(
665
+						'The Ticket for Registration %1$d was not found or is invalid.',
666
+						'event_espresso'
667
+					),
668
+					$registration->ticket_ID()
669
+				)
670
+			);
671
+		}
672
+		$registration->set_final_price($ticket->price());
673
+		if ($update_reg) {
674
+			$registration->save();
675
+		}
676
+		return true;
677
+	}
678
+
679
+
680
+
681
+	/**
682
+	 * generate_ONE_registration_from_line_item
683
+	 * Although a ticket line item may have a quantity greater than 1,
684
+	 * this method will ONLY CREATE ONE REGISTRATION !!!
685
+	 * Regardless of the ticket line item quantity.
686
+	 * This means that any code calling this method is responsible for ensuring
687
+	 * that the final registration count matches the ticket line item quantity.
688
+	 * This was done to make it easier to match the number of registrations
689
+	 * to the number of tickets in the cart, when the cart has been edited
690
+	 * after SPCO has already been initialized. So if an additional ticket was added to the cart, you can simply pass
691
+	 * the line item to this method to add a second ticket, and in this case, you would not want to add 2 tickets.
692
+	 *
693
+	 * @deprecated
694
+	 * @since 4.9.1
695
+	 * @param EE_Line_Item    $line_item
696
+	 * @param \EE_Transaction $transaction
697
+	 * @param int             $att_nmbr
698
+	 * @param int             $total_ticket_count
699
+	 * @return EE_Registration | null
700
+	 * @throws \OutOfRangeException
701
+	 * @throws \EventEspresso\core\exceptions\UnexpectedEntityException
702
+	 * @throws \EE_Error
703
+	 */
704
+	public function generate_ONE_registration_from_line_item(
705
+		EE_Line_Item $line_item,
706
+		EE_Transaction $transaction,
707
+		$att_nmbr = 1,
708
+		$total_ticket_count = 1
709
+	) {
710
+		EE_Error::doing_it_wrong(
711
+			__CLASS__ . '::' . __FUNCTION__,
712
+			sprintf(
713
+				esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
714
+				'\EventEspresso\core\domain\services\registration\CreateRegistrationService::create()'
715
+			),
716
+			'4.9.1',
717
+			'5.0.0'
718
+		);
719
+		// grab the related ticket object for this line_item
720
+		$ticket = $line_item->ticket();
721
+		if (! $ticket instanceof EE_Ticket) {
722
+			EE_Error::add_error(
723
+				sprintf(
724
+					esc_html__('Line item %s did not contain a valid ticket', 'event_espresso'),
725
+					$line_item->ID()
726
+				),
727
+				__FILE__,
728
+				__FUNCTION__,
729
+				__LINE__
730
+			);
731
+			return null;
732
+		}
733
+		$registration_service = new CreateRegistrationService();
734
+		// then generate a new registration from that
735
+		return $registration_service->create(
736
+			$ticket->get_related_event(),
737
+			$transaction,
738
+			$ticket,
739
+			$line_item,
740
+			$att_nmbr,
741
+			$total_ticket_count
742
+		);
743
+	}
744
+
745
+
746
+
747
+	/**
748
+	 * generates reg_url_link
749
+	 *
750
+	 * @deprecated
751
+	 * @since 4.9.1
752
+	 * @param int                   $att_nmbr
753
+	 * @param EE_Line_Item | string $item
754
+	 * @return string
755
+	 * @throws InvalidArgumentException
756
+	 */
757
+	public function generate_reg_url_link($att_nmbr, $item)
758
+	{
759
+		EE_Error::doing_it_wrong(
760
+			__CLASS__ . '::' . __FUNCTION__,
761
+			sprintf(
762
+				esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
763
+				'EventEspresso\core\domain\entities\RegUrlLink'
764
+			),
765
+			'4.9.1',
766
+			'5.0.0'
767
+		);
768
+		return new RegUrlLink($att_nmbr, $item);
769
+	}
770
+
771
+
772
+
773
+	/**
774
+	 * generates reg code
775
+	 *
776
+	 * @deprecated
777
+	 * @since 4.9.1
778
+	 * @param EE_Registration $registration
779
+	 * @return string
780
+	 * @throws EE_Error
781
+	 * @throws EntityNotFoundException
782
+	 * @throws InvalidArgumentException
783
+	 */
784
+	public function generate_reg_code(EE_Registration $registration)
785
+	{
786
+		EE_Error::doing_it_wrong(
787
+			__CLASS__ . '::' . __FUNCTION__,
788
+			sprintf(
789
+				esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
790
+				'EventEspresso\core\domain\entities\RegCode'
791
+			),
792
+			'4.9.1',
793
+			'5.0.0'
794
+		);
795
+		return apply_filters(
796
+			'FHEE__EE_Registration_Processor___generate_reg_code__new_reg_code',
797
+			new RegCode(
798
+				RegUrlLink::fromRegistration($registration),
799
+				$registration->transaction(),
800
+				$registration->ticket()
801
+			),
802
+			$registration
803
+		);
804
+	}
805 805
 
806 806
 
807 807
 
Please login to merge, or discard this patch.
core/domain/entities/contexts/Context.php 1 patch
Indentation   +58 added lines, -58 removed lines patch added patch discarded remove patch
@@ -17,64 +17,64 @@
 block discarded – undo
17 17
 class Context implements ContextInterface
18 18
 {
19 19
 
20
-    /**
21
-     * @var string $slug
22
-     */
23
-    private $slug;
24
-
25
-    /**
26
-     * @var string $description
27
-     */
28
-    private $description;
29
-
30
-
31
-    /**
32
-     * Context constructor.
33
-     *
34
-     * @param string $slug
35
-     * @param string $description
36
-     */
37
-    public function __construct($slug, $description)
38
-    {
39
-        $this->setSlug($slug);
40
-        $this->setDescription($description);
41
-    }
42
-
43
-
44
-    /**
45
-     * @return string
46
-     */
47
-    public function slug()
48
-    {
49
-        return $this->slug;
50
-    }
51
-
52
-
53
-    /**
54
-     * @param string $slug
55
-     */
56
-    private function setSlug($slug)
57
-    {
58
-        $this->slug = sanitize_key($slug);
59
-    }
60
-
61
-
62
-    /**
63
-     * @return string
64
-     */
65
-    public function description()
66
-    {
67
-        return $this->description;
68
-    }
69
-
70
-
71
-    /**
72
-     * @param string $description
73
-     */
74
-    private function setDescription($description)
75
-    {
76
-        $this->description = sanitize_text_field($description);
77
-    }
20
+	/**
21
+	 * @var string $slug
22
+	 */
23
+	private $slug;
24
+
25
+	/**
26
+	 * @var string $description
27
+	 */
28
+	private $description;
29
+
30
+
31
+	/**
32
+	 * Context constructor.
33
+	 *
34
+	 * @param string $slug
35
+	 * @param string $description
36
+	 */
37
+	public function __construct($slug, $description)
38
+	{
39
+		$this->setSlug($slug);
40
+		$this->setDescription($description);
41
+	}
42
+
43
+
44
+	/**
45
+	 * @return string
46
+	 */
47
+	public function slug()
48
+	{
49
+		return $this->slug;
50
+	}
51
+
52
+
53
+	/**
54
+	 * @param string $slug
55
+	 */
56
+	private function setSlug($slug)
57
+	{
58
+		$this->slug = sanitize_key($slug);
59
+	}
60
+
61
+
62
+	/**
63
+	 * @return string
64
+	 */
65
+	public function description()
66
+	{
67
+		return $this->description;
68
+	}
69
+
70
+
71
+	/**
72
+	 * @param string $description
73
+	 */
74
+	private function setDescription($description)
75
+	{
76
+		$this->description = sanitize_text_field($description);
77
+	}
78 78
 
79 79
 }
80 80
 // Location: Context.php
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +191 added lines, -191 removed lines patch added patch discarded remove patch
@@ -38,216 +38,216 @@
 block discarded – undo
38 38
  * @since       4.0
39 39
  */
40 40
 if (function_exists('espresso_version')) {
41
-    if (! function_exists('espresso_duplicate_plugin_error')) {
42
-        /**
43
-         *    espresso_duplicate_plugin_error
44
-         *    displays if more than one version of EE is activated at the same time
45
-         */
46
-        function espresso_duplicate_plugin_error()
47
-        {
48
-            ?>
41
+	if (! function_exists('espresso_duplicate_plugin_error')) {
42
+		/**
43
+		 *    espresso_duplicate_plugin_error
44
+		 *    displays if more than one version of EE is activated at the same time
45
+		 */
46
+		function espresso_duplicate_plugin_error()
47
+		{
48
+			?>
49 49
             <div class="error">
50 50
                 <p>
51 51
                     <?php
52
-                    echo esc_html__(
53
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
-                        'event_espresso'
55
-                    ); ?>
52
+					echo esc_html__(
53
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
+						'event_espresso'
55
+					); ?>
56 56
                 </p>
57 57
             </div>
58 58
             <?php
59
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
60
-        }
61
-    }
62
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
59
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
60
+		}
61
+	}
62
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
63 63
 
64 64
 } else {
65
-    define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
66
-    if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
67
-        /**
68
-         * espresso_minimum_php_version_error
69
-         * @return void
70
-         */
71
-        function espresso_minimum_php_version_error()
72
-        {
73
-            ?>
65
+	define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
66
+	if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
67
+		/**
68
+		 * espresso_minimum_php_version_error
69
+		 * @return void
70
+		 */
71
+		function espresso_minimum_php_version_error()
72
+		{
73
+			?>
74 74
             <div class="error">
75 75
                 <p>
76 76
                     <?php
77
-                    printf(
78
-                        esc_html__(
79
-                            'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
-                            'event_espresso'
81
-                        ),
82
-                        EE_MIN_PHP_VER_REQUIRED,
83
-                        PHP_VERSION,
84
-                        '<br/>',
85
-                        '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
-                    );
87
-                    ?>
77
+					printf(
78
+						esc_html__(
79
+							'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
+							'event_espresso'
81
+						),
82
+						EE_MIN_PHP_VER_REQUIRED,
83
+						PHP_VERSION,
84
+						'<br/>',
85
+						'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
+					);
87
+					?>
88 88
                 </p>
89 89
             </div>
90 90
             <?php
91
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
92
-        }
91
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
92
+		}
93 93
 
94
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
-    } else {
96
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
97
-        /**
98
-         * espresso_version
99
-         * Returns the plugin version
100
-         *
101
-         * @return string
102
-         */
103
-        function espresso_version()
104
-        {
105
-            return apply_filters('FHEE__espresso__espresso_version', '4.9.55.rc.007');
106
-        }
94
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
+	} else {
96
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
97
+		/**
98
+		 * espresso_version
99
+		 * Returns the plugin version
100
+		 *
101
+		 * @return string
102
+		 */
103
+		function espresso_version()
104
+		{
105
+			return apply_filters('FHEE__espresso__espresso_version', '4.9.55.rc.007');
106
+		}
107 107
 
108
-        /**
109
-         * espresso_plugin_activation
110
-         * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
111
-         */
112
-        function espresso_plugin_activation()
113
-        {
114
-            update_option('ee_espresso_activation', true);
115
-        }
108
+		/**
109
+		 * espresso_plugin_activation
110
+		 * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
111
+		 */
112
+		function espresso_plugin_activation()
113
+		{
114
+			update_option('ee_espresso_activation', true);
115
+		}
116 116
 
117
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
118
-        /**
119
-         *    espresso_load_error_handling
120
-         *    this function loads EE's class for handling exceptions and errors
121
-         */
122
-        function espresso_load_error_handling()
123
-        {
124
-            static $error_handling_loaded = false;
125
-            if ($error_handling_loaded) {
126
-                return;
127
-            }
128
-            // load debugging tools
129
-            if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
130
-                require_once   EE_HELPERS . 'EEH_Debug_Tools.helper.php';
131
-                \EEH_Debug_Tools::instance();
132
-            }
133
-            // load error handling
134
-            if (is_readable(EE_CORE . 'EE_Error.core.php')) {
135
-                require_once EE_CORE . 'EE_Error.core.php';
136
-            } else {
137
-                wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
138
-            }
139
-            $error_handling_loaded = true;
140
-        }
117
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
118
+		/**
119
+		 *    espresso_load_error_handling
120
+		 *    this function loads EE's class for handling exceptions and errors
121
+		 */
122
+		function espresso_load_error_handling()
123
+		{
124
+			static $error_handling_loaded = false;
125
+			if ($error_handling_loaded) {
126
+				return;
127
+			}
128
+			// load debugging tools
129
+			if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
130
+				require_once   EE_HELPERS . 'EEH_Debug_Tools.helper.php';
131
+				\EEH_Debug_Tools::instance();
132
+			}
133
+			// load error handling
134
+			if (is_readable(EE_CORE . 'EE_Error.core.php')) {
135
+				require_once EE_CORE . 'EE_Error.core.php';
136
+			} else {
137
+				wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
138
+			}
139
+			$error_handling_loaded = true;
140
+		}
141 141
 
142
-        /**
143
-         *    espresso_load_required
144
-         *    given a class name and path, this function will load that file or throw an exception
145
-         *
146
-         * @param    string $classname
147
-         * @param    string $full_path_to_file
148
-         * @throws    EE_Error
149
-         */
150
-        function espresso_load_required($classname, $full_path_to_file)
151
-        {
152
-            if (is_readable($full_path_to_file)) {
153
-                require_once $full_path_to_file;
154
-            } else {
155
-                throw new \EE_Error (
156
-                    sprintf(
157
-                        esc_html__(
158
-                            'The %s class file could not be located or is not readable due to file permissions.',
159
-                            'event_espresso'
160
-                        ),
161
-                        $classname
162
-                    )
163
-                );
164
-            }
165
-        }
142
+		/**
143
+		 *    espresso_load_required
144
+		 *    given a class name and path, this function will load that file or throw an exception
145
+		 *
146
+		 * @param    string $classname
147
+		 * @param    string $full_path_to_file
148
+		 * @throws    EE_Error
149
+		 */
150
+		function espresso_load_required($classname, $full_path_to_file)
151
+		{
152
+			if (is_readable($full_path_to_file)) {
153
+				require_once $full_path_to_file;
154
+			} else {
155
+				throw new \EE_Error (
156
+					sprintf(
157
+						esc_html__(
158
+							'The %s class file could not be located or is not readable due to file permissions.',
159
+							'event_espresso'
160
+						),
161
+						$classname
162
+					)
163
+				);
164
+			}
165
+		}
166 166
 
167
-        /**
168
-         * @since 4.9.27
169
-         * @throws \EE_Error
170
-         * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
171
-         * @throws \EventEspresso\core\exceptions\InvalidEntityException
172
-         * @throws \EventEspresso\core\exceptions\InvalidIdentifierException
173
-         * @throws \EventEspresso\core\exceptions\InvalidClassException
174
-         * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
175
-         * @throws \EventEspresso\core\services\container\exceptions\ServiceExistsException
176
-         * @throws \EventEspresso\core\services\container\exceptions\ServiceNotFoundException
177
-         * @throws \OutOfBoundsException
178
-         */
179
-        function bootstrap_espresso()
180
-        {
181
-            require_once __DIR__ . '/core/espresso_definitions.php';
182
-            try {
183
-                espresso_load_error_handling();
184
-                espresso_load_required(
185
-                    'EEH_Base',
186
-                    EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php'
187
-                );
188
-                espresso_load_required(
189
-                    'EEH_File',
190
-                    EE_CORE . 'interfaces' . DS . 'EEHI_File.interface.php'
191
-                );
192
-                espresso_load_required(
193
-                    'EEH_File',
194
-                    EE_CORE . 'helpers' . DS . 'EEH_File.helper.php'
195
-                );
196
-                espresso_load_required(
197
-                    'EEH_Array',
198
-                    EE_CORE . 'helpers' . DS . 'EEH_Array.helper.php'
199
-                );
200
-                // instantiate and configure PSR4 autoloader
201
-                espresso_load_required(
202
-                    'Psr4Autoloader',
203
-                    EE_CORE . 'Psr4Autoloader.php'
204
-                );
205
-                espresso_load_required(
206
-                    'EE_Psr4AutoloaderInit',
207
-                    EE_CORE . 'EE_Psr4AutoloaderInit.core.php'
208
-                );
209
-                $AutoloaderInit = new EE_Psr4AutoloaderInit();
210
-                $AutoloaderInit->initializeAutoloader();
211
-                espresso_load_required(
212
-                    'EE_Request',
213
-                    EE_CORE . 'request_stack' . DS . 'EE_Request.core.php'
214
-                );
215
-                espresso_load_required(
216
-                    'EE_Response',
217
-                    EE_CORE . 'request_stack' . DS . 'EE_Response.core.php'
218
-                );
219
-                espresso_load_required(
220
-                    'EE_Bootstrap',
221
-                    EE_CORE . 'EE_Bootstrap.core.php'
222
-                );
223
-                // bootstrap EE and the request stack
224
-                new EE_Bootstrap(
225
-                    new EE_Request($_GET, $_POST, $_COOKIE),
226
-                    new EE_Response()
227
-                );
228
-            } catch (Exception $e) {
229
-                require_once EE_CORE . 'exceptions' . DS . 'ExceptionStackTraceDisplay.php';
230
-                new EventEspresso\core\exceptions\ExceptionStackTraceDisplay($e);
231
-            }
232
-        }
233
-        bootstrap_espresso();
234
-    }
167
+		/**
168
+		 * @since 4.9.27
169
+		 * @throws \EE_Error
170
+		 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
171
+		 * @throws \EventEspresso\core\exceptions\InvalidEntityException
172
+		 * @throws \EventEspresso\core\exceptions\InvalidIdentifierException
173
+		 * @throws \EventEspresso\core\exceptions\InvalidClassException
174
+		 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
175
+		 * @throws \EventEspresso\core\services\container\exceptions\ServiceExistsException
176
+		 * @throws \EventEspresso\core\services\container\exceptions\ServiceNotFoundException
177
+		 * @throws \OutOfBoundsException
178
+		 */
179
+		function bootstrap_espresso()
180
+		{
181
+			require_once __DIR__ . '/core/espresso_definitions.php';
182
+			try {
183
+				espresso_load_error_handling();
184
+				espresso_load_required(
185
+					'EEH_Base',
186
+					EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php'
187
+				);
188
+				espresso_load_required(
189
+					'EEH_File',
190
+					EE_CORE . 'interfaces' . DS . 'EEHI_File.interface.php'
191
+				);
192
+				espresso_load_required(
193
+					'EEH_File',
194
+					EE_CORE . 'helpers' . DS . 'EEH_File.helper.php'
195
+				);
196
+				espresso_load_required(
197
+					'EEH_Array',
198
+					EE_CORE . 'helpers' . DS . 'EEH_Array.helper.php'
199
+				);
200
+				// instantiate and configure PSR4 autoloader
201
+				espresso_load_required(
202
+					'Psr4Autoloader',
203
+					EE_CORE . 'Psr4Autoloader.php'
204
+				);
205
+				espresso_load_required(
206
+					'EE_Psr4AutoloaderInit',
207
+					EE_CORE . 'EE_Psr4AutoloaderInit.core.php'
208
+				);
209
+				$AutoloaderInit = new EE_Psr4AutoloaderInit();
210
+				$AutoloaderInit->initializeAutoloader();
211
+				espresso_load_required(
212
+					'EE_Request',
213
+					EE_CORE . 'request_stack' . DS . 'EE_Request.core.php'
214
+				);
215
+				espresso_load_required(
216
+					'EE_Response',
217
+					EE_CORE . 'request_stack' . DS . 'EE_Response.core.php'
218
+				);
219
+				espresso_load_required(
220
+					'EE_Bootstrap',
221
+					EE_CORE . 'EE_Bootstrap.core.php'
222
+				);
223
+				// bootstrap EE and the request stack
224
+				new EE_Bootstrap(
225
+					new EE_Request($_GET, $_POST, $_COOKIE),
226
+					new EE_Response()
227
+				);
228
+			} catch (Exception $e) {
229
+				require_once EE_CORE . 'exceptions' . DS . 'ExceptionStackTraceDisplay.php';
230
+				new EventEspresso\core\exceptions\ExceptionStackTraceDisplay($e);
231
+			}
232
+		}
233
+		bootstrap_espresso();
234
+	}
235 235
 }
236 236
 if (! function_exists('espresso_deactivate_plugin')) {
237
-    /**
238
-     *    deactivate_plugin
239
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
240
-     *
241
-     * @access public
242
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
243
-     * @return    void
244
-     */
245
-    function espresso_deactivate_plugin($plugin_basename = '')
246
-    {
247
-        if (! function_exists('deactivate_plugins')) {
248
-            require_once ABSPATH . 'wp-admin/includes/plugin.php';
249
-        }
250
-        unset($_GET['activate'], $_REQUEST['activate']);
251
-        deactivate_plugins($plugin_basename);
252
-    }
237
+	/**
238
+	 *    deactivate_plugin
239
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
240
+	 *
241
+	 * @access public
242
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
243
+	 * @return    void
244
+	 */
245
+	function espresso_deactivate_plugin($plugin_basename = '')
246
+	{
247
+		if (! function_exists('deactivate_plugins')) {
248
+			require_once ABSPATH . 'wp-admin/includes/plugin.php';
249
+		}
250
+		unset($_GET['activate'], $_REQUEST['activate']);
251
+		deactivate_plugins($plugin_basename);
252
+	}
253 253
 }
Please login to merge, or discard this patch.
templates/txn_admin_details_main_meta_box_txn_details.template.php 1 patch
Indentation   +81 added lines, -81 removed lines patch added patch discarded remove patch
@@ -12,7 +12,7 @@  discard block
 block discarded – undo
12 12
     <a id="display-additional-transaction-session-info" class="display-the-hidden smaller-text"
13 13
        rel="additional-transaction-session-info">
14 14
         <span class="dashicons dashicons-plus-alt"></span><?php esc_html_e('view additional transaction session details',
15
-            'event_espresso'); ?>
15
+			'event_espresso'); ?>
16 16
     </a>
17 17
 
18 18
     <div id="additional-transaction-session-info-dv" class="hidden">
@@ -20,7 +20,7 @@  discard block
 block discarded – undo
20 20
         <a id="hide-additional-transaction-session-info" class="hide-the-displayed hidden smaller-text"
21 21
            rel="additional-transaction-session-info">
22 22
             <span class="dashicons dashicons-dismiss"></span><?php esc_html_e('hide additional transaction session details',
23
-                'event_espresso'); ?>
23
+				'event_espresso'); ?>
24 24
         </a>
25 25
         <br class="clear"/>
26 26
 
@@ -45,16 +45,16 @@  discard block
 block discarded – undo
45 45
 
46 46
 
47 47
     <?php if ($attendee instanceof EE_Attendee && ($grand_raw_total > 0 || $TXN_status !== EEM_Transaction::complete_status_code || ! empty($payments))) :
48
-        $no_payment_text = $can_edit_payments
49
-            ? esc_html__(
50
-                'No payments have been applied to this transaction yet. Click "Apply Payment" below to make a payment.',
51
-                'event_espresso'
52
-            )
53
-            : esc_html__(
54
-                'No payments have been applied to this transaction yet.',
55
-                'event_espresso'
56
-            );
57
-        ?>
48
+		$no_payment_text = $can_edit_payments
49
+			? esc_html__(
50
+				'No payments have been applied to this transaction yet. Click "Apply Payment" below to make a payment.',
51
+				'event_espresso'
52
+			)
53
+			: esc_html__(
54
+				'No payments have been applied to this transaction yet.',
55
+				'event_espresso'
56
+			);
57
+		?>
58 58
 
59 59
         <h3 class="admin-primary-mbox-h4 hdr-has-icon">
60 60
             <span class="ee-icon ee-icon-cash"></span><?php esc_html_e('Payment Details', 'event_espresso'); ?>
@@ -82,10 +82,10 @@  discard block
 block discarded – undo
82 82
                 <?php if ($payments) : ?>
83 83
                     <?php $payment_total = 0; ?>
84 84
                     <?php foreach ($payments as $PAY_ID => $payment) :
85
-                        $existing_reg_payment_json = isset($existing_reg_payments[$PAY_ID])
86
-                            ? wp_json_encode($existing_reg_payments[$PAY_ID])
87
-                            : '{}';
88
-                        ?>
85
+						$existing_reg_payment_json = isset($existing_reg_payments[$PAY_ID])
86
+							? wp_json_encode($existing_reg_payments[$PAY_ID])
87
+							: '{}';
88
+						?>
89 89
                         <tr id="txn-admin-payment-tr-<?php echo $PAY_ID; ?>">
90 90
                             <td>
91 91
                                 <span id="payment-status-<?php echo $PAY_ID; ?>"
@@ -132,7 +132,7 @@  discard block
 block discarded – undo
132 132
                             <td class=" jst-left">
133 133
                                 <div id="payment-gateway-<?php echo $PAY_ID; ?>">
134 134
                                     <?php echo $payment->payment_method() ? $payment->payment_method()->admin_name() : esc_html__("Unknown",
135
-                                        'event_espresso'); ?>
135
+										'event_espresso'); ?>
136 136
                                 </div>
137 137
                                 <div id="payment-gateway-id-<?php echo $PAY_ID; ?>"
138 138
                                      class="hidden"><?php echo $payment->payment_method() ? $payment->payment_method()->ID() : 0; ?></div>
@@ -154,19 +154,19 @@  discard block
 block discarded – undo
154 154
                                 <span class="<?php echo $payment_class; ?>">
155 155
 							<div id="payment-amount-<?php echo $PAY_ID; ?>"
156 156
                                  style="display:inline;"><?php echo EEH_Template::format_currency($payment->amount(),
157
-                                    false, false); ?></div>
157
+									false, false); ?></div>
158 158
 						</span>
159 159
                             </td>
160 160
                         </tr>
161 161
                         <?php
162
-                        $payment_total += $payment->STS_ID() == 'PAP' ? $payment->amount() : 0;
163
-                        ?>
162
+						$payment_total += $payment->STS_ID() == 'PAP' ? $payment->amount() : 0;
163
+						?>
164 164
                     <?php endforeach; // $payment?>
165 165
                     <?php
166
-                    $pay_totals_class = $payment_total > $grand_raw_total ? ' important-notice' : '';
167
-                    $overpaid = $payment_total > $grand_raw_total ? '<span id="overpaid">' . esc_html__('This transaction has been overpaid ! ',
168
-                            'event_espresso') . '</span>' : '';
169
-                    ?>
166
+					$pay_totals_class = $payment_total > $grand_raw_total ? ' important-notice' : '';
167
+					$overpaid = $payment_total > $grand_raw_total ? '<span id="overpaid">' . esc_html__('This transaction has been overpaid ! ',
168
+							'event_espresso') . '</span>' : '';
169
+					?>
170 170
                     <tr id="txn-admin-no-payments-tr" class="admin-primary-mbox-total-tr hidden">
171 171
                         <td class=" jst-rght" colspan="11">
172 172
                             <span class="important-notice"><?php echo $no_payment_text; ?></span>
@@ -176,11 +176,11 @@  discard block
 block discarded – undo
176 176
                         class="admin-primary-mbox-total-tr<?php echo $pay_totals_class; ?>">
177 177
                         <th class=" jst-rght" colspan="10"><span
178 178
                                     id="payments-total-spn"><?php echo $overpaid . sprintf(esc_html__('Payments Total %s',
179
-                                        'event_espresso'),
180
-                                        '(' . EE_Registry::instance()->CFG->currency->code . ')'); ?></span></th>
179
+										'event_espresso'),
180
+										'(' . EE_Registry::instance()->CFG->currency->code . ')'); ?></span></th>
181 181
                         <th class=" jst-rght"><span
182 182
                                     id="txn-admin-payment-total"><?php echo EEH_Template::format_currency($payment_total,
183
-                                    false, false); ?></span></th>
183
+									false, false); ?></span></th>
184 184
                     </tr>
185 185
                 <?php else : ?>
186 186
                     <tr id="txn-admin-no-payments-tr" class="admin-primary-mbox-total-tr">
@@ -191,11 +191,11 @@  discard block
 block discarded – undo
191 191
                     <tr id="txn-admin-payments-total-tr" class="admin-primary-mbox-total-tr hidden">
192 192
                         <th class=" jst-rght" colspan="10"><span
193 193
                                     id="payments-total-spn"><?php echo esc_html__('Payments Total',
194
-                                    'event_espresso'); ?></span></th>
194
+									'event_espresso'); ?></span></th>
195 195
                         <th class=" jst-rght"><span id="txn-admin-payment-total"></span></th>
196 196
                     </tr>
197 197
                 <?php endif; // $payments
198
-                ?>
198
+				?>
199 199
 
200 200
                 <tr id="txn-admin-payment-empty-row-tr" class="hidden">
201 201
                     <td>
@@ -260,7 +260,7 @@  discard block
 block discarded – undo
260 260
 
261 261
         <ul id="txn-admin-payment-options-ul">
262 262
             <?php if ($can_edit_payments) :
263
-                ?>
263
+				?>
264 264
                 <li>
265 265
                     <a id="display-txn-admin-apply-payment" class="button-primary no-icon no-hide"
266 266
                        rel="txn-admin-apply-payment"> <!--display-the-hidden -->
@@ -276,7 +276,7 @@  discard block
 block discarded – undo
276 276
             <?php else : ?>
277 277
                 <li>
278 278
                     <p><?php esc_html__('You do not have access to apply payments or refunds.',
279
-                            'event_espresso'); ?></p>
279
+							'event_espresso'); ?></p>
280 280
                 </li>
281 281
             <?php endif; ?>
282 282
         </ul>
@@ -294,23 +294,23 @@  discard block
 block discarded – undo
294 294
                 style="display:none;">
295 295
                 <div class="ee-icon ee-icon-cash-edit float-left"></div>
296 296
                 <?php
297
-                echo sprintf(
298
-                    __('Edit Payment #%s for Transaction #%s', 'event_espresso'),
299
-                    '<span></span>',
300
-                    $txn_nmbr['value']
301
-                );
302
-                ?>
297
+				echo sprintf(
298
+					__('Edit Payment #%s for Transaction #%s', 'event_espresso'),
299
+					'<span></span>',
300
+					$txn_nmbr['value']
301
+				);
302
+				?>
303 303
             </h2>
304 304
 
305 305
             <h2 id="admin-modal-dialog-edit-refund-h2" class="admin-modal-dialog-h2 hdr-has-icon" style="display:none;">
306 306
                 <div class="ee-icon ee-icon-cash-edit float-left"></div>
307 307
                 <?php
308
-                echo sprintf(
309
-                    __('Edit Refund #%s for Transaction #%s', 'event_espresso'),
310
-                    '<span></span>',
311
-                    $txn_nmbr['value']
312
-                );
313
-                ?>
308
+				echo sprintf(
309
+					__('Edit Refund #%s for Transaction #%s', 'event_espresso'),
310
+					'<span></span>',
311
+					$txn_nmbr['value']
312
+				);
313
+				?>
314 314
             </h2>
315 315
 
316 316
             <h2 id="admin-modal-dialog-apply-refund-h2" class="admin-modal-dialog-h2 hdr-has-icon"
@@ -343,55 +343,55 @@  discard block
 block discarded – undo
343 343
 
344 344
                         <div class="txn-admin-apply-payment-date-dv admin-modal-dialog-row">
345 345
                             <div class="validation-notice-dv"><?php esc_html_e('The following is  a required field',
346
-                                    'event_espresso'); ?></div>
346
+									'event_espresso'); ?></div>
347 347
                             <label for="txn-admin-payment-date-inp" class=""><?php esc_html_e('Payment Date',
348
-                                    'event_espresso'); ?></label>
348
+									'event_espresso'); ?></label>
349 349
                             <input name="txn_admin_payment[date]" id="txn-admin-payment-date-inp"
350 350
                                    class="txn-admin-apply-payment-inp required" type="text"
351 351
                                    value="<?php echo date('Y-m-d g:i a', current_time('timestamp')); ?>"/>
352 352
                             <p class="description"><?php esc_html_e('The date the payment was actually made on',
353
-                                    'event_espresso'); ?></p>
353
+									'event_espresso'); ?></p>
354 354
                         </div>
355 355
 
356 356
                         <div class="txn-admin-apply-payment-amount-dv admin-modal-dialog-row">
357 357
                             <div class="validation-notice-dv"><?php esc_html_e('The following is  a required field',
358
-                                    'event_espresso'); ?></div>
358
+									'event_espresso'); ?></div>
359 359
                             <label for="txn-admin-payment-amount-inp" class=""><?php esc_html_e('Amount',
360
-                                    'event_espresso'); ?></label>
360
+									'event_espresso'); ?></label>
361 361
                             <input name="txn_admin_payment[amount]" id="txn-admin-payment-amount-inp"
362 362
                                    class="txn-admin-apply-payment-inp required" type="text" value=""/>
363 363
                             <p class="description"><?php esc_html_e('The amount of the payment',
364
-                                    'event_espresso'); ?></p>
364
+									'event_espresso'); ?></p>
365 365
                         </div>
366 366
 
367 367
                         <div class="txn-admin-apply-payment-method-dv admin-modal-dialog-row">
368 368
                             <div class="validation-notice-dv"><?php esc_html_e('The following is  a required field',
369
-                                    'event_espresso'); ?></div>
369
+									'event_espresso'); ?></div>
370 370
                             <label for="txn-admin-payment-method-inp" class=""><?php esc_html_e('Method of Payment',
371
-                                    'event_espresso'); ?></label>
371
+									'event_espresso'); ?></label>
372 372
                             <select name="txn_admin_payment[PMD_ID]" id="txn-admin-payment-method-slct"
373 373
                                     class="txn-admin-apply-payment-slct required" type="text">
374 374
                                 <?php foreach ($payment_methods as $method) : ?>
375 375
                                     <?php $selected = $method->slug() == 'cash' ? ' selected="selected"' : ''; ?>
376 376
                                     <option id="payment-method-opt-<?php echo $method->slug(); ?>"
377 377
                                             value="<?php echo $method->ID(); ?>"<?php echo $selected; ?>><?php echo sanitize_key($method->admin_desc()) ? substr($method->admin_desc(),
378
-                                            0, 128) : $method->admin_name(); ?>&nbsp;&nbsp;
378
+											0, 128) : $method->admin_name(); ?>&nbsp;&nbsp;
379 379
                                     </option>
380 380
                                 <?php endforeach; ?>
381 381
                             </select>
382 382
                             <p class="description"><?php esc_html_e('Whether the payment was made via PayPal, Credit Card, Cheque, or Cash',
383
-                                    'event_espresso'); ?></p>
383
+									'event_espresso'); ?></p>
384 384
                         </div>
385 385
 
386 386
                         <div class="mop-PP mop-CC mop-CHQ mop">
387 387
                             <div class="txn-admin-apply-payment-gw-txn-id-dv admin-modal-dialog-row">
388 388
                                 <label for="txn-admin-payment-txn-id-inp" class=""><?php esc_html_e('TXN ID / CHQ #',
389
-                                        'event_espresso'); ?></label>
389
+										'event_espresso'); ?></label>
390 390
                                 <input name="txn_admin_payment[txn_id_chq_nmbr]"
391 391
                                        id="txn-admin-payment-txn-id-chq-nmbr-inp" class="txn-admin-apply-payment-inp"
392 392
                                        type="text" maxlength="100"/>
393 393
                                 <p class="description"><?php esc_html_e('The Transaction ID sent back from the payment gateway, or the Cheque #',
394
-                                        'event_espresso'); ?></p>
394
+										'event_espresso'); ?></p>
395 395
                             </div>
396 396
                         </div>
397 397
 
@@ -403,14 +403,14 @@  discard block
 block discarded – undo
403 403
                                        id="txn-admin-payment-gateway-response-inp" class="txn-admin-apply-payment-inp"
404 404
                                        type="text"/>
405 405
                                 <p class="description"><?php esc_html_e('The gateway response string (optional)',
406
-                                        'event_espresso'); ?></p>
406
+										'event_espresso'); ?></p>
407 407
                             </div>
408 408
                         </div>
409 409
 
410 410
                         <div class="mop-PP mop-CC mop">
411 411
                             <div class="txn-admin-apply-payment-status-dv admin-modal-dialog-row">
412 412
                                 <label for="txn-admin-payment-status-inp" class=""><?php esc_html_e('Payment Status',
413
-                                        'event_espresso'); ?></label>
413
+										'event_espresso'); ?></label>
414 414
                                 <select name="txn_admin_payment[status]" id="txn-admin-payment-status-slct"
415 415
                                         class="txn-admin-apply-payment-slct" type="text">
416 416
                                     <?php foreach ($payment_status as $STS_ID => $STS_code) : ?>
@@ -422,35 +422,35 @@  discard block
 block discarded – undo
422 422
                                     <?php endforeach; ?>
423 423
                                 </select>
424 424
                                 <p class="description"><?php esc_html_e('Whether the payment was approved, cancelled, declined or failed after submission to the gateway',
425
-                                        'event_espresso'); ?></p>
425
+										'event_espresso'); ?></p>
426 426
                             </div>
427 427
                         </div>
428 428
 
429 429
                         <div class="txn-admin-apply-payment-po-nmbr-dv admin-modal-dialog-row">
430 430
                             <label for="txn-admin-payment-po-nmbr-inp" class=""><?php esc_html_e('P.O. / S.O. #',
431
-                                    'event_espresso'); ?></label>
431
+									'event_espresso'); ?></label>
432 432
                             <input name="txn_admin_payment[po_number]" id="txn-admin-payment-po-nmbr-inp"
433 433
                                    class="txn-admin-apply-payment-inp" type="text" maxlength="100"/>
434 434
                             <p class="description"><?php esc_html_e('The Purchase or Sales Order Number if any (optional)',
435
-                                    'event_espresso'); ?></p>
435
+									'event_espresso'); ?></p>
436 436
                         </div>
437 437
 
438 438
                         <div class="txn-admin-apply-payment-accounting-dv admin-modal-dialog-row">
439 439
                             <label for="txn-admin-payment-accounting-inp"
440 440
                                    class="last"><?php esc_html_e('Notes / Extra Accounting',
441
-                                    'event_espresso'); ?></label>
441
+									'event_espresso'); ?></label>
442 442
                             <input name="txn_admin_payment[accounting]" id="txn-admin-payment-accounting-inp"
443 443
                                    class="txn-admin-apply-payment-inp" type="text" value="<?php echo $REG_code; ?>"
444 444
                                    maxlength="100"/> <input type="hidden" id="txn-admin-reg-code-inp"
445 445
                                                             value="<?php echo $REG_code; ?>"/>
446 446
                             <p class="description"><?php esc_html_e('An extra field you may use for accounting purposes or simple notes. Defaults to the primary registrant\'s registration code.',
447
-                                    'event_espresso'); ?></p>
447
+									'event_espresso'); ?></p>
448 448
                         </div>
449 449
 
450 450
                         <div class="txn-admin-apply-payment-registrations-dv admin-modal-dialog-row">
451 451
                             <label for="txn-admin-payment-registrations-inp"
452 452
                                    class="last"><?php esc_html_e('Registrations to Apply Payment to:',
453
-                                    'event_espresso'); ?></label>
453
+									'event_espresso'); ?></label>
454 454
                             <label class="txn-admin-apply-payment-to-registrations-lbl">
455 455
                                 <input type="radio" value="1" id="txn-admin-apply-payment-to-all-registrations-inp"
456 456
                                        name="txn_admin_payment[apply_to_all_registrations]" checked="checked"/>
@@ -467,10 +467,10 @@  discard block
 block discarded – undo
467 467
                         <div class="txn-admin-payment-reg-status-dv admin-modal-dialog-row">
468 468
                             <label for="txn-admin-payment-reg-status-inp"
469 469
                                    class="last"><?php esc_html_e('Change Registration Status?',
470
-                                    'event_espresso'); ?></label>
470
+									'event_espresso'); ?></label>
471 471
                             <?php echo $status_change_select; ?>
472 472
                             <p class="description"><?php esc_html_e('If you wish to change the status for the registrations selected above, then select which status from this dropdown.',
473
-                                    'event_espresso'); ?></p>
473
+									'event_espresso'); ?></p>
474 474
                             <br/>
475 475
                         </div>
476 476
 
@@ -490,7 +490,7 @@  discard block
 block discarded – undo
490 490
                             </label>
491 491
                             <br class="clear-float"/>
492 492
                             <p class="description"><?php printf(esc_html__('By default %1$sa payment message is sent to the primary registrant%2$s after submitting this form.%3$sHowever, if you check the "Registration Messages" box, the system will also send any related messages matching the status of the registrations to %1$seach registration for this transaction%2$s.',
493
-                                    'event_espresso'), '<strong>', '</strong>', '<br />'); ?></p>
493
+									'event_espresso'), '<strong>', '</strong>', '<br />'); ?></p>
494 494
                             <label></label>
495 495
                         </div>
496 496
                         <div class="clear"></div>
@@ -530,7 +530,7 @@  discard block
 block discarded – undo
530 530
                     </li>
531 531
                     <li>
532 532
                         <span id="ee-ajax-processing-text" style="display:none;"><?php esc_html_e('Processing...',
533
-                                'event_espresso'); ?></span>
533
+								'event_espresso'); ?></span>
534 534
                     </li>
535 535
                 </ul>
536 536
 
@@ -545,7 +545,7 @@  discard block
 block discarded – undo
545 545
                 style="display:none;">
546 546
                 <span class="ee-icon ee-icon-cash-add"></span>
547 547
                 <?php echo esc_html__('Delete Payment/Refund for Transaction #',
548
-                        'event_espresso') . $txn_nmbr['value']; ?>
548
+						'event_espresso') . $txn_nmbr['value']; ?>
549 549
             </h2>
550 550
 
551 551
             <form name="txn-admin-delete-payment-frm" id="txn-admin-delete-payment-frm"
@@ -566,10 +566,10 @@  discard block
 block discarded – undo
566 566
                         <div class="txn-admin-apply-payment-accounting-dv admin-modal-dialog-row">
567 567
                             <label for="delete-txn-admin-payment-reg-status-inp"
568 568
                                    class="last"><?php esc_html_e('Change Registration Status?',
569
-                                    'event_espresso'); ?></label>
569
+									'event_espresso'); ?></label>
570 570
                             <?php echo $delete_status_change_select; ?>
571 571
                             <p class="description"><?php printf(esc_html__('If you wish to change the status of all the registrations associated with this transaction after deleting this payment/refund, then select which status from this dropdown. %sNote: ALL registrations associated with this transaction will be updated to this new status.%s',
572
-                                    'event_espresso'), '<strong>', '</strong>'); ?></p>
572
+									'event_espresso'), '<strong>', '</strong>'); ?></p>
573 573
                         </div>
574 574
 
575 575
                         <div class="ee-attention txn-admin-apply-payment-accounting-dv admin-modal-dialog-row">
@@ -577,7 +577,7 @@  discard block
 block discarded – undo
577 577
                                    class="last"><?php esc_html_e('Send Related Messages?', 'event_espresso'); ?></label>
578 578
                             <input type="checkbox" value="1" name="delete_txn_reg_status_change[send_notifications]">
579 579
                             <p class="description"><?php esc_html_e('If you check this box, the system will send any related registration messages matching the status of the registrations to each registration for this transaction. No Payment notifications are sent when deleting a payment.',
580
-                                    'event_espresso'); ?></p>
580
+									'event_espresso'); ?></p>
581 581
                         </div>
582 582
                         <div class="clear"></div>
583 583
 
@@ -609,13 +609,13 @@  discard block
 block discarded – undo
609 609
     <?php endif; // $grand_raw_total > 0?>
610 610
 
611 611
     <?php
612
-    if (WP_DEBUG) {
613
-        $delivered_messages = get_option('EED_Messages__payment', array());
614
-        if (isset($delivered_messages[$TXN_ID])) {
615
-            ?>
612
+	if (WP_DEBUG) {
613
+		$delivered_messages = get_option('EED_Messages__payment', array());
614
+		if (isset($delivered_messages[$TXN_ID])) {
615
+			?>
616 616
             <h4 class="admin-primary-mbox-h4 hdr-has-icon"><span
617 617
                         class="dashicons dashicons-email-alt"></span><?php esc_html_e('Messages Sent to Primary Registrant',
618
-                    'event_espresso'); ?></h4>
618
+					'event_espresso'); ?></h4>
619 619
 
620 620
             <div class="admin-primary-mbox-tbl-wrap">
621 621
                 <table class="admin-primary-mbox-tbl">
@@ -629,10 +629,10 @@  discard block
 block discarded – undo
629 629
                     </thead>
630 630
                     <tbody>
631 631
                     <?php foreach ($delivered_messages[$TXN_ID] as $timestamp => $delivered_message) :
632
-                        ?>
632
+						?>
633 633
                         <tr>
634 634
                             <td class="jst-left"><?php echo date(get_option('date_format') . ' ' . get_option('time_format'),
635
-                                    ($timestamp + (get_option('gmt_offset') * HOUR_IN_SECONDS))); ?></td>
635
+									($timestamp + (get_option('gmt_offset') * HOUR_IN_SECONDS))); ?></td>
636 636
                             <td class="jst-left"><?php echo isset($delivered_message['message_type']) ? $delivered_message['message_type'] : ''; ?></td>
637 637
                             <td class="jst-left"><?php echo isset($delivered_message['pay_status']) ? $delivered_message['pay_status'] : ''; ?></td>
638 638
                             <td class="jst-left"><?php echo isset($delivered_message['txn_status']) ? $delivered_message['txn_status'] : ''; ?></td>
@@ -642,9 +642,9 @@  discard block
 block discarded – undo
642 642
                 </table>
643 643
             </div>
644 644
             <?php
645
-        }
646
-    }
647
-    ?>
645
+		}
646
+	}
647
+	?>
648 648
 
649 649
 
650 650
 </div>
Please login to merge, or discard this patch.
admin_pages/transactions/Transactions_Admin_Page.core.php 1 patch
Indentation   +2366 added lines, -2366 removed lines patch added patch discarded remove patch
@@ -16,2370 +16,2370 @@
 block discarded – undo
16 16
 class Transactions_Admin_Page extends EE_Admin_Page
17 17
 {
18 18
 
19
-    /**
20
-     * @var EE_Transaction
21
-     */
22
-    private $_transaction;
23
-
24
-    /**
25
-     * @var EE_Session
26
-     */
27
-    private $_session;
28
-
29
-    /**
30
-     * @var array $_txn_status
31
-     */
32
-    private static $_txn_status;
33
-
34
-    /**
35
-     * @var array $_pay_status
36
-     */
37
-    private static $_pay_status;
38
-
39
-    /**
40
-     * @var array $_existing_reg_payment_REG_IDs
41
-     */
42
-    protected $_existing_reg_payment_REG_IDs = null;
43
-
44
-
45
-    /**
46
-     * @Constructor
47
-     * @access public
48
-     * @param bool $routing
49
-     * @throws EE_Error
50
-     * @throws InvalidArgumentException
51
-     * @throws ReflectionException
52
-     * @throws InvalidDataTypeException
53
-     * @throws InvalidInterfaceException
54
-     */
55
-    public function __construct($routing = true)
56
-    {
57
-        parent::__construct($routing);
58
-    }
59
-
60
-
61
-    /**
62
-     *    _init_page_props
63
-     *
64
-     * @return void
65
-     */
66
-    protected function _init_page_props()
67
-    {
68
-        $this->page_slug        = TXN_PG_SLUG;
69
-        $this->page_label       = esc_html__('Transactions', 'event_espresso');
70
-        $this->_admin_base_url  = TXN_ADMIN_URL;
71
-        $this->_admin_base_path = TXN_ADMIN;
72
-    }
73
-
74
-
75
-    /**
76
-     *    _ajax_hooks
77
-     *
78
-     * @return void
79
-     */
80
-    protected function _ajax_hooks()
81
-    {
82
-        add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds'));
83
-        add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds'));
84
-        add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment'));
85
-    }
86
-
87
-
88
-    /**
89
-     *    _define_page_props
90
-     *
91
-     * @return void
92
-     */
93
-    protected function _define_page_props()
94
-    {
95
-        $this->_admin_page_title = $this->page_label;
96
-        $this->_labels           = array(
97
-            'buttons' => array(
98
-                'add'    => esc_html__('Add New Transaction', 'event_espresso'),
99
-                'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
100
-                'delete' => esc_html__('Delete Transaction', 'event_espresso'),
101
-            ),
102
-        );
103
-    }
104
-
105
-
106
-    /**
107
-     *        grab url requests and route them
108
-     *
109
-     * @access private
110
-     * @return void
111
-     * @throws EE_Error
112
-     * @throws InvalidArgumentException
113
-     * @throws InvalidDataTypeException
114
-     * @throws InvalidInterfaceException
115
-     */
116
-    public function _set_page_routes()
117
-    {
118
-
119
-        $this->_set_transaction_status_array();
120
-
121
-        $txn_id = ! empty($this->_req_data['TXN_ID'])
122
-                  && ! is_array($this->_req_data['TXN_ID'])
123
-            ? $this->_req_data['TXN_ID']
124
-            : 0;
125
-
126
-        $this->_page_routes = array(
127
-
128
-            'default' => array(
129
-                'func'       => '_transactions_overview_list_table',
130
-                'capability' => 'ee_read_transactions',
131
-            ),
132
-
133
-            'view_transaction' => array(
134
-                'func'       => '_transaction_details',
135
-                'capability' => 'ee_read_transaction',
136
-                'obj_id'     => $txn_id,
137
-            ),
138
-
139
-            'send_payment_reminder' => array(
140
-                'func'       => '_send_payment_reminder',
141
-                'noheader'   => true,
142
-                'capability' => 'ee_send_message',
143
-            ),
144
-
145
-            'espresso_apply_payment' => array(
146
-                'func'       => 'apply_payments_or_refunds',
147
-                'noheader'   => true,
148
-                'capability' => 'ee_edit_payments',
149
-            ),
150
-
151
-            'espresso_apply_refund' => array(
152
-                'func'       => 'apply_payments_or_refunds',
153
-                'noheader'   => true,
154
-                'capability' => 'ee_edit_payments',
155
-            ),
156
-
157
-            'espresso_delete_payment' => array(
158
-                'func'       => 'delete_payment',
159
-                'noheader'   => true,
160
-                'capability' => 'ee_delete_payments',
161
-            ),
162
-
163
-        );
164
-    }
165
-
166
-
167
-    protected function _set_page_config()
168
-    {
169
-        $this->_page_config = array(
170
-            'default'          => array(
171
-                'nav'           => array(
172
-                    'label' => esc_html__('Overview', 'event_espresso'),
173
-                    'order' => 10,
174
-                ),
175
-                'list_table'    => 'EE_Admin_Transactions_List_Table',
176
-                'help_tabs'     => array(
177
-                    'transactions_overview_help_tab'                       => array(
178
-                        'title'    => esc_html__('Transactions Overview', 'event_espresso'),
179
-                        'filename' => 'transactions_overview',
180
-                    ),
181
-                    'transactions_overview_table_column_headings_help_tab' => array(
182
-                        'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
183
-                        'filename' => 'transactions_overview_table_column_headings',
184
-                    ),
185
-                    'transactions_overview_views_filters_help_tab'         => array(
186
-                        'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
187
-                        'filename' => 'transactions_overview_views_filters_search',
188
-                    ),
189
-                ),
190
-                'help_tour'     => array('Transactions_Overview_Help_Tour'),
191
-                /**
192
-                 * commented out because currently we are not displaying tips for transaction list table status but this
193
-                 * may change in a later iteration so want to keep the code for then.
194
-                 */
195
-                //'qtips' => array( 'Transactions_List_Table_Tips' ),
196
-                'require_nonce' => false,
197
-            ),
198
-            'view_transaction' => array(
199
-                'nav'       => array(
200
-                    'label'      => esc_html__('View Transaction', 'event_espresso'),
201
-                    'order'      => 5,
202
-                    'url'        => isset($this->_req_data['TXN_ID'])
203
-                        ? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']), $this->_current_page_view_url)
204
-                        : $this->_admin_base_url,
205
-                    'persistent' => false,
206
-                ),
207
-                'help_tabs' => array(
208
-                    'transactions_view_transaction_help_tab'                                              => array(
209
-                        'title'    => esc_html__('View Transaction', 'event_espresso'),
210
-                        'filename' => 'transactions_view_transaction',
211
-                    ),
212
-                    'transactions_view_transaction_transaction_details_table_help_tab'                    => array(
213
-                        'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
214
-                        'filename' => 'transactions_view_transaction_transaction_details_table',
215
-                    ),
216
-                    'transactions_view_transaction_attendees_registered_help_tab'                         => array(
217
-                        'title'    => esc_html__('Attendees Registered', 'event_espresso'),
218
-                        'filename' => 'transactions_view_transaction_attendees_registered',
219
-                    ),
220
-                    'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array(
221
-                        'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
222
-                        'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
223
-                    ),
224
-                ),
225
-                'qtips'     => array('Transaction_Details_Tips'),
226
-                'help_tour' => array('Transaction_Details_Help_Tour'),
227
-                'metaboxes' => array('_transaction_details_metaboxes'),
228
-
229
-                'require_nonce' => false,
230
-            ),
231
-        );
232
-    }
233
-
234
-
235
-    /**
236
-     * The below methods aren't used by this class currently
237
-     */
238
-    protected function _add_screen_options()
239
-    {
240
-        //noop
241
-    }
242
-
243
-    protected function _add_feature_pointers()
244
-    {
245
-        //noop
246
-    }
247
-
248
-    public function admin_init()
249
-    {
250
-        // IF a registration was JUST added via the admin...
251
-        if (isset(
252
-            $this->_req_data['redirect_from'],
253
-            $this->_req_data['EVT_ID'],
254
-            $this->_req_data['event_name']
255
-        )) {
256
-            // then set a cookie so that we can block any attempts to use
257
-            // the back button as a way to enter another registration.
258
-            setcookie(
259
-                'ee_registration_added',
260
-                $this->_req_data['EVT_ID'], time() + WEEK_IN_SECONDS, '/'
261
-            );
262
-            // and update the global
263
-            $_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID'];
264
-        }
265
-        EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
266
-            'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
267
-            'event_espresso'
268
-        );
269
-        EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__(
270
-            'An error occurred! Please refresh the page and try again.',
271
-            'event_espresso'
272
-        );
273
-        EE_Registry::$i18n_js_strings['txn_status_array']        = self::$_txn_status;
274
-        EE_Registry::$i18n_js_strings['pay_status_array']        = self::$_pay_status;
275
-        EE_Registry::$i18n_js_strings['payments_total']          = esc_html__('Payments Total', 'event_espresso');
276
-        EE_Registry::$i18n_js_strings['transaction_overpaid']    = esc_html__(
277
-            'This transaction has been overpaid ! Payments Total',
278
-            'event_espresso'
279
-        );
280
-    }
281
-
282
-    public function admin_notices()
283
-    {
284
-        //noop
285
-    }
286
-
287
-    public function admin_footer_scripts()
288
-    {
289
-        //noop
290
-    }
291
-
292
-
293
-    /**
294
-     * _set_transaction_status_array
295
-     * sets list of transaction statuses
296
-     *
297
-     * @access private
298
-     * @return void
299
-     * @throws EE_Error
300
-     * @throws InvalidArgumentException
301
-     * @throws InvalidDataTypeException
302
-     * @throws InvalidInterfaceException
303
-     */
304
-    private function _set_transaction_status_array()
305
-    {
306
-        self::$_txn_status = EEM_Transaction::instance()->status_array(true);
307
-    }
308
-
309
-
310
-    /**
311
-     * get_transaction_status_array
312
-     * return the transaction status array for wp_list_table
313
-     *
314
-     * @access public
315
-     * @return array
316
-     */
317
-    public function get_transaction_status_array()
318
-    {
319
-        return self::$_txn_status;
320
-    }
321
-
322
-
323
-    /**
324
-     *    get list of payment statuses
325
-     *
326
-     * @access private
327
-     * @return void
328
-     * @throws EE_Error
329
-     * @throws InvalidArgumentException
330
-     * @throws InvalidDataTypeException
331
-     * @throws InvalidInterfaceException
332
-     */
333
-    private function _get_payment_status_array()
334
-    {
335
-        self::$_pay_status                      = EEM_Payment::instance()->status_array(true);
336
-        $this->_template_args['payment_status'] = self::$_pay_status;
337
-
338
-    }
339
-
340
-
341
-    /**
342
-     *    _add_screen_options_default
343
-     *
344
-     * @access protected
345
-     * @return void
346
-     * @throws InvalidArgumentException
347
-     * @throws InvalidDataTypeException
348
-     * @throws InvalidInterfaceException
349
-     */
350
-    protected function _add_screen_options_default()
351
-    {
352
-        $this->_per_page_screen_option();
353
-    }
354
-
355
-
356
-    /**
357
-     * load_scripts_styles
358
-     *
359
-     * @access public
360
-     * @return void
361
-     */
362
-    public function load_scripts_styles()
363
-    {
364
-        //enqueue style
365
-        wp_register_style(
366
-            'espresso_txn',
367
-            TXN_ASSETS_URL . 'espresso_transactions_admin.css',
368
-            array(),
369
-            EVENT_ESPRESSO_VERSION
370
-        );
371
-        wp_enqueue_style('espresso_txn');
372
-        //scripts
373
-        wp_register_script('espresso_txn', TXN_ASSETS_URL . 'espresso_transactions_admin.js', array(
374
-            'ee_admin_js',
375
-            'ee-datepicker',
376
-            'jquery-ui-datepicker',
377
-            'jquery-ui-draggable',
378
-            'ee-dialog',
379
-            'ee-accounting',
380
-            'ee-serialize-full-array',
381
-        ), EVENT_ESPRESSO_VERSION, true);
382
-        wp_enqueue_script('espresso_txn');
383
-    }
384
-
385
-
386
-    /**
387
-     *    load_scripts_styles_view_transaction
388
-     *
389
-     * @access public
390
-     * @return void
391
-     */
392
-    public function load_scripts_styles_view_transaction()
393
-    {
394
-        //styles
395
-        wp_enqueue_style('espresso-ui-theme');
396
-    }
397
-
398
-
399
-    /**
400
-     *    load_scripts_styles_default
401
-     *
402
-     * @access public
403
-     * @return void
404
-     */
405
-    public function load_scripts_styles_default()
406
-    {
407
-        //styles
408
-        wp_enqueue_style('espresso-ui-theme');
409
-    }
410
-
411
-
412
-    /**
413
-     *    _set_list_table_views_default
414
-     *
415
-     * @access protected
416
-     * @return void
417
-     */
418
-    protected function _set_list_table_views_default()
419
-    {
420
-        $this->_views = array(
421
-            'all'       => array(
422
-                'slug'  => 'all',
423
-                'label' => esc_html__('View All Transactions', 'event_espresso'),
424
-                'count' => 0,
425
-            ),
426
-            'abandoned' => array(
427
-                'slug'  => 'abandoned',
428
-                'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
429
-                'count' => 0,
430
-            ),
431
-            'failed'    => array(
432
-                'slug'  => 'failed',
433
-                'label' => esc_html__('Failed Transactions', 'event_espresso'),
434
-                'count' => 0,
435
-            ),
436
-        );
437
-    }
438
-
439
-
440
-    /**
441
-     * _set_transaction_object
442
-     * This sets the _transaction property for the transaction details screen
443
-     *
444
-     * @access private
445
-     * @return void
446
-     * @throws EE_Error
447
-     * @throws InvalidArgumentException
448
-     * @throws RuntimeException
449
-     * @throws InvalidDataTypeException
450
-     * @throws InvalidInterfaceException
451
-     */
452
-    private function _set_transaction_object()
453
-    {
454
-        if ($this->_transaction instanceof EE_Transaction) {
455
-            return;
456
-        } //get out we've already set the object
457
-
458
-        $TXN_ID = ! empty($this->_req_data['TXN_ID'])
459
-            ? absint($this->_req_data['TXN_ID'])
460
-            : false;
461
-
462
-        //get transaction object
463
-        $this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
464
-        $this->_session     = $this->_transaction instanceof EE_Transaction
465
-            ? $this->_transaction->get('TXN_session_data')
466
-            : null;
467
-        $this->_transaction->verify_abandoned_transaction_status();
468
-
469
-        if (! $this->_transaction instanceof EE_Transaction) {
470
-            $error_msg = sprintf(
471
-                esc_html__(
472
-                    'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
473
-                    'event_espresso'
474
-                ),
475
-                $TXN_ID
476
-            );
477
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
478
-        }
479
-    }
480
-
481
-
482
-    /**
483
-     *    _transaction_legend_items
484
-     *
485
-     * @access protected
486
-     * @return array
487
-     * @throws EE_Error
488
-     * @throws InvalidArgumentException
489
-     * @throws ReflectionException
490
-     * @throws InvalidDataTypeException
491
-     * @throws InvalidInterfaceException
492
-     */
493
-    protected function _transaction_legend_items()
494
-    {
495
-        EE_Registry::instance()->load_helper('MSG_Template');
496
-        $items = array();
497
-
498
-        if (EE_Registry::instance()->CAP->current_user_can(
499
-            'ee_read_global_messages',
500
-            'view_filtered_messages'
501
-        )) {
502
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
503
-            if (is_array($related_for_icon)
504
-                && isset($related_for_icon['css_class'], $related_for_icon['label'])
505
-            ) {
506
-                $items['view_related_messages'] = array(
507
-                    'class' => $related_for_icon['css_class'],
508
-                    'desc'  => $related_for_icon['label'],
509
-                );
510
-            }
511
-        }
512
-
513
-        $items = apply_filters(
514
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
515
-            array_merge(
516
-                $items,
517
-                array(
518
-                    'view_details'          => array(
519
-                        'class' => 'dashicons dashicons-cart',
520
-                        'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
521
-                    ),
522
-                    'view_invoice'          => array(
523
-                        'class' => 'dashicons dashicons-media-spreadsheet',
524
-                        'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
525
-                    ),
526
-                    'view_receipt'          => array(
527
-                        'class' => 'dashicons dashicons-media-default',
528
-                        'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
529
-                    ),
530
-                    'view_registration'     => array(
531
-                        'class' => 'dashicons dashicons-clipboard',
532
-                        'desc'  => esc_html__('View Registration Details', 'event_espresso'),
533
-                    ),
534
-                    'payment_overview_link' => array(
535
-                        'class' => 'dashicons dashicons-money',
536
-                        'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
537
-                    ),
538
-                )
539
-            )
540
-        );
541
-
542
-        if (EE_Registry::instance()->CAP->current_user_can(
543
-            'ee_send_message',
544
-            'espresso_transactions_send_payment_reminder'
545
-        )) {
546
-            if (EEH_MSG_Template::is_mt_active('payment_reminder')) {
547
-                $items['send_payment_reminder'] = array(
548
-                    'class' => 'dashicons dashicons-email-alt',
549
-                    'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
550
-                );
551
-            } else {
552
-                $items['blank*'] = array(
553
-                    'class' => '',
554
-                    'desc'  => '',
555
-                );
556
-            }
557
-        } else {
558
-            $items['blank*'] = array(
559
-                'class' => '',
560
-                'desc'  => '',
561
-            );
562
-        }
563
-        $more_items = apply_filters(
564
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
565
-            array(
566
-                'overpaid'   => array(
567
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
568
-                    'desc'  => EEH_Template::pretty_status(
569
-                        EEM_Transaction::overpaid_status_code,
570
-                        false,
571
-                        'sentence'
572
-                    ),
573
-                ),
574
-                'complete'   => array(
575
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
576
-                    'desc'  => EEH_Template::pretty_status(
577
-                        EEM_Transaction::complete_status_code,
578
-                        false,
579
-                        'sentence'
580
-                    ),
581
-                ),
582
-                'incomplete' => array(
583
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
584
-                    'desc'  => EEH_Template::pretty_status(
585
-                        EEM_Transaction::incomplete_status_code,
586
-                        false,
587
-                        'sentence'
588
-                    ),
589
-                ),
590
-                'abandoned'  => array(
591
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
592
-                    'desc'  => EEH_Template::pretty_status(
593
-                        EEM_Transaction::abandoned_status_code,
594
-                        false,
595
-                        'sentence'
596
-                    ),
597
-                ),
598
-                'failed'     => array(
599
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
600
-                    'desc'  => EEH_Template::pretty_status(
601
-                        EEM_Transaction::failed_status_code,
602
-                        false,
603
-                        'sentence'
604
-                    ),
605
-                ),
606
-            )
607
-        );
608
-
609
-        return array_merge($items, $more_items);
610
-    }
611
-
612
-
613
-    /**
614
-     *    _transactions_overview_list_table
615
-     *
616
-     * @access protected
617
-     * @return void
618
-     * @throws DomainException
619
-     * @throws EE_Error
620
-     * @throws InvalidArgumentException
621
-     * @throws InvalidDataTypeException
622
-     * @throws InvalidInterfaceException
623
-     * @throws ReflectionException
624
-     */
625
-    protected function _transactions_overview_list_table()
626
-    {
627
-        $this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
628
-        $event = isset($this->_req_data['EVT_ID'])
629
-            ? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID'])
630
-            : null;
631
-        $this->_template_args['admin_page_header'] = $event instanceof EE_Event
632
-            ? sprintf(
633
-                esc_html__(
634
-                    '%sViewing Transactions for the Event: %s%s',
635
-                    'event_espresso'
636
-                ),
637
-                '<h3>',
638
-                '<a href="'
639
-                . EE_Admin_Page::add_query_args_and_nonce(
640
-                    array('action' => 'edit', 'post' => $event->ID()),
641
-                    EVENTS_ADMIN_URL
642
-                )
643
-                . '" title="'
644
-                . esc_attr__(
645
-                    'Click to Edit event',
646
-                    'event_espresso'
647
-                )
648
-                . '">' . $event->get('EVT_name') . '</a>',
649
-                '</h3>'
650
-            )
651
-            : '';
652
-        $this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
653
-        $this->display_admin_list_table_page_with_no_sidebar();
654
-    }
655
-
656
-
657
-    /**
658
-     *    _transaction_details
659
-     * generates HTML for the View Transaction Details Admin page
660
-     *
661
-     * @access protected
662
-     * @return void
663
-     * @throws DomainException
664
-     * @throws EE_Error
665
-     * @throws InvalidArgumentException
666
-     * @throws InvalidDataTypeException
667
-     * @throws InvalidInterfaceException
668
-     * @throws RuntimeException
669
-     */
670
-    protected function _transaction_details()
671
-    {
672
-        do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
673
-
674
-        $this->_set_transaction_status_array();
675
-
676
-        $this->_template_args                      = array();
677
-        $this->_template_args['transactions_page'] = $this->_wp_page_slug;
678
-
679
-        $this->_set_transaction_object();
680
-
681
-        $primary_registration = $this->_transaction->primary_registration();
682
-        $attendee = $primary_registration instanceof EE_Registration
683
-            ? $primary_registration->attendee()
684
-            : null;
685
-
686
-        $this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
687
-        $this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
688
-
689
-        $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
690
-        $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
691
-
692
-        $this->_template_args['txn_status']['value'] = self::$_txn_status[$this->_transaction->get('STS_ID')];
693
-        $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
694
-        $this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->get('STS_ID');
695
-
696
-        $this->_template_args['grand_total'] = $this->_transaction->get('TXN_total');
697
-        $this->_template_args['total_paid']  = $this->_transaction->get('TXN_paid');
698
-
699
-        if ($attendee instanceof EE_Attendee
700
-            && EE_Registry::instance()->CAP->current_user_can(
701
-                'ee_send_message',
702
-                'espresso_transactions_send_payment_reminder'
703
-            )
704
-        ) {
705
-            $this->_template_args['send_payment_reminder_button'] =
706
-                EEH_MSG_Template::is_mt_active('payment_reminder')
707
-                && $this->_transaction->get('STS_ID') !== EEM_Transaction::complete_status_code
708
-                && $this->_transaction->get('STS_ID') !== EEM_Transaction::overpaid_status_code
709
-                    ? EEH_Template::get_button_or_link(
710
-                        EE_Admin_Page::add_query_args_and_nonce(
711
-                            array(
712
-                                'action'      => 'send_payment_reminder',
713
-                                'TXN_ID'      => $this->_transaction->ID(),
714
-                                'redirect_to' => 'view_transaction',
715
-                            ),
716
-                            TXN_ADMIN_URL
717
-                        ),
718
-                        __(' Send Payment Reminder', 'event_espresso'),
719
-                        'button secondary-button right',
720
-                        'dashicons dashicons-email-alt'
721
-                    )
722
-                    : '';
723
-        } else {
724
-            $this->_template_args['send_payment_reminder_button'] = '';
725
-        }
726
-
727
-        $amount_due = $this->_transaction->get('TXN_total') - $this->_transaction->get('TXN_paid');
728
-        $this->_template_args['amount_due'] = EEH_Template::format_currency(
729
-            $amount_due,
730
-            true
731
-        );
732
-        if (EE_Registry::instance()->CFG->currency->sign_b4) {
733
-            $this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign
734
-                                                  . $this->_template_args['amount_due'];
735
-        } else {
736
-            $this->_template_args['amount_due'] .= EE_Registry::instance()->CFG->currency->sign;
737
-        }
738
-        $this->_template_args['amount_due_class'] = '';
739
-
740
-        if ($this->_transaction->get('TXN_paid') == $this->_transaction->get('TXN_total')) {
741
-            // paid in full
742
-            $this->_template_args['amount_due'] = false;
743
-        } elseif ($this->_transaction->get('TXN_paid') > $this->_transaction->get('TXN_total')) {
744
-            // overpaid
745
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
746
-        } elseif ($this->_transaction->get('TXN_total') > 0
747
-                  && $this->_transaction->get('TXN_paid') > 0
748
-        ) {
749
-            // monies owing
750
-            $this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn';
751
-        } elseif ($this->_transaction->get('TXN_total') > 0
752
-                  && $this->_transaction->get('TXN_paid') == 0
753
-        ) {
754
-            // no payments made yet
755
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
756
-        } elseif ($this->_transaction->get('TXN_total') == 0) {
757
-            // free event
758
-            $this->_template_args['amount_due'] = false;
759
-        }
760
-
761
-        $payment_method = $this->_transaction->payment_method();
762
-
763
-        $this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
764
-            ? $payment_method->admin_name()
765
-            : esc_html__('Unknown', 'event_espresso');
766
-
767
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
768
-        // link back to overview
769
-        $this->_template_args['txn_overview_url'] = ! empty($_SERVER['HTTP_REFERER'])
770
-            ? $_SERVER['HTTP_REFERER']
771
-            : TXN_ADMIN_URL;
772
-
773
-
774
-        // next link
775
-        $next_txn                                 = $this->_transaction->next(
776
-            null,
777
-            array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
778
-            'TXN_ID'
779
-        );
780
-        $this->_template_args['next_transaction'] = $next_txn
781
-            ? $this->_next_link(
782
-                EE_Admin_Page::add_query_args_and_nonce(
783
-                    array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']),
784
-                    TXN_ADMIN_URL
785
-                ),
786
-                'dashicons dashicons-arrow-right ee-icon-size-22'
787
-            )
788
-            : '';
789
-        // previous link
790
-        $previous_txn                                 = $this->_transaction->previous(
791
-            null,
792
-            array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
793
-            'TXN_ID'
794
-        );
795
-        $this->_template_args['previous_transaction'] = $previous_txn
796
-            ? $this->_previous_link(
797
-                EE_Admin_Page::add_query_args_and_nonce(
798
-                    array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']),
799
-                    TXN_ADMIN_URL
800
-                ),
801
-                'dashicons dashicons-arrow-left ee-icon-size-22'
802
-            )
803
-            : '';
804
-
805
-        // were we just redirected here after adding a new registration ???
806
-        if (isset(
807
-            $this->_req_data['redirect_from'],
808
-            $this->_req_data['EVT_ID'],
809
-            $this->_req_data['event_name']
810
-        )) {
811
-            if (EE_Registry::instance()->CAP->current_user_can(
812
-                'ee_edit_registrations',
813
-                'espresso_registrations_new_registration',
814
-                $this->_req_data['EVT_ID']
815
-            )) {
816
-                $this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="';
817
-                $this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
818
-                    array(
819
-                        'page'     => 'espresso_registrations',
820
-                        'action'   => 'new_registration',
821
-                        'return'   => 'default',
822
-                        'TXN_ID'   => $this->_transaction->ID(),
823
-                        'event_id' => $this->_req_data['EVT_ID'],
824
-                    ),
825
-                    REG_ADMIN_URL
826
-                );
827
-                $this->_admin_page_title .= '">';
828
-
829
-                $this->_admin_page_title .= sprintf(
830
-                    esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
831
-                    htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8')
832
-                );
833
-                $this->_admin_page_title .= '</a>';
834
-            }
835
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
836
-        }
837
-        // grab messages at the last second
838
-        $this->_template_args['notices'] = EE_Error::get_notices();
839
-        // path to template
840
-        $template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
841
-        $this->_template_args['admin_page_header'] = EEH_Template::display_template(
842
-            $template_path,
843
-            $this->_template_args,
844
-            true
845
-        );
846
-
847
-        // the details template wrapper
848
-        $this->display_admin_page_with_sidebar();
849
-
850
-    }
851
-
852
-
853
-    /**
854
-     *        _transaction_details_metaboxes
855
-     *
856
-     * @access protected
857
-     * @return void
858
-     * @throws EE_Error
859
-     * @throws InvalidArgumentException
860
-     * @throws InvalidDataTypeException
861
-     * @throws InvalidInterfaceException
862
-     * @throws RuntimeException
863
-     */
864
-    protected function _transaction_details_metaboxes()
865
-    {
866
-
867
-        $this->_set_transaction_object();
868
-
869
-        add_meta_box(
870
-            'edit-txn-details-mbox',
871
-            esc_html__('Transaction Details', 'event_espresso'),
872
-            array($this, 'txn_details_meta_box'),
873
-            $this->_wp_page_slug,
874
-            'normal',
875
-            'high'
876
-        );
877
-        add_meta_box(
878
-            'edit-txn-attendees-mbox',
879
-            esc_html__('Attendees Registered in this Transaction', 'event_espresso'),
880
-            array($this, 'txn_attendees_meta_box'),
881
-            $this->_wp_page_slug,
882
-            'normal',
883
-            'high',
884
-            array('TXN_ID' => $this->_transaction->ID())
885
-        );
886
-        add_meta_box(
887
-            'edit-txn-registrant-mbox',
888
-            esc_html__('Primary Contact', 'event_espresso'),
889
-            array($this, 'txn_registrant_side_meta_box'),
890
-            $this->_wp_page_slug,
891
-            'side',
892
-            'high'
893
-        );
894
-        add_meta_box(
895
-            'edit-txn-billing-info-mbox',
896
-            esc_html__('Billing Information', 'event_espresso'),
897
-            array($this, 'txn_billing_info_side_meta_box'),
898
-            $this->_wp_page_slug,
899
-            'side',
900
-            'high'
901
-        );
902
-    }
903
-
904
-
905
-    /**
906
-     * txn_details_meta_box
907
-     * generates HTML for the Transaction main meta box
908
-     *
909
-     * @access public
910
-     * @return void
911
-     * @throws DomainException
912
-     * @throws EE_Error
913
-     * @throws InvalidArgumentException
914
-     * @throws InvalidDataTypeException
915
-     * @throws InvalidInterfaceException
916
-     * @throws RuntimeException
917
-     */
918
-    public function txn_details_meta_box()
919
-    {
920
-
921
-        $this->_set_transaction_object();
922
-        $this->_template_args['TXN_ID']   = $this->_transaction->ID();
923
-        $this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration
924
-            ? $this->_transaction->primary_registration()->attendee()
925
-            : null;
926
-        $this->_template_args['can_edit_payments'] = EE_Registry::instance()->CAP->current_user_can(
927
-            'ee_edit_payments',
928
-            'apply_payment_or_refund_from_registration_details'
929
-        );
930
-        $this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->current_user_can(
931
-            'ee_delete_payments',
932
-            'delete_payment_from_registration_details'
933
-        );
934
-
935
-        //get line table
936
-        EEH_Autoloader::register_line_item_display_autoloaders();
937
-        $Line_Item_Display                       = new EE_Line_Item_Display(
938
-            'admin_table',
939
-            'EE_Admin_Table_Line_Item_Display_Strategy'
940
-        );
941
-        $this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
942
-            $this->_transaction->total_line_item()
943
-        );
944
-        $this->_template_args['REG_code']        = $this->_transaction->get_first_related('Registration')
945
-                                                                      ->get('REG_code');
946
-
947
-        // process taxes
948
-        $taxes                         = $this->_transaction->get_many_related(
949
-            'Line_Item',
950
-            array(array('LIN_type' => EEM_Line_Item::type_tax))
951
-        );
952
-        $this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
953
-
954
-        $this->_template_args['grand_total']     = EEH_Template::format_currency(
955
-            $this->_transaction->get('TXN_total'),
956
-            false,
957
-            false
958
-        );
959
-        $this->_template_args['grand_raw_total'] = $this->_transaction->get('TXN_total');
960
-        $this->_template_args['TXN_status']      = $this->_transaction->get('STS_ID');
961
-
962
-        // process payment details
963
-        $payments = $this->_transaction->get_many_related('Payment');
964
-        if (! empty($payments)) {
965
-            $this->_template_args['payments']              = $payments;
966
-            $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
967
-        } else {
968
-            $this->_template_args['payments']              = false;
969
-            $this->_template_args['existing_reg_payments'] = array();
970
-        }
971
-
972
-        $this->_template_args['edit_payment_url']   = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL);
973
-        $this->_template_args['delete_payment_url'] = add_query_arg(
974
-            array('action' => 'espresso_delete_payment'),
975
-            TXN_ADMIN_URL
976
-        );
977
-
978
-        if (isset($txn_details['invoice_number'])) {
979
-            $this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
980
-            $this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
981
-                'Invoice Number',
982
-                'event_espresso'
983
-            );
984
-        }
985
-
986
-        $this->_template_args['txn_details']['registration_session']['value'] = $this->_transaction
987
-            ->get_first_related('Registration')
988
-            ->get('REG_session');
989
-        $this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
990
-            'Registration Session',
991
-            'event_espresso'
992
-        );
993
-
994
-        $this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address'])
995
-            ? $this->_session['ip_address']
996
-            : '';
997
-        $this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
998
-            'Transaction placed from IP',
999
-            'event_espresso'
1000
-        );
1001
-
1002
-        $this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent'])
1003
-            ? $this->_session['user_agent']
1004
-            : '';
1005
-        $this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1006
-            'Registrant User Agent',
1007
-            'event_espresso'
1008
-        );
1009
-
1010
-        $reg_steps = '<ul>';
1011
-        foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1012
-            if ($reg_step_status === true) {
1013
-                $reg_steps .= '<li style="color:#70cc50">'
1014
-                              . sprintf(
1015
-                                  esc_html__('%1$s : Completed', 'event_espresso'),
1016
-                                  ucwords(str_replace('_', ' ', $reg_step))
1017
-                              )
1018
-                              . '</li>';
1019
-            } elseif (is_numeric($reg_step_status) && $reg_step_status !== false) {
1020
-                $reg_steps .= '<li style="color:#2EA2CC">'
1021
-                              . sprintf(
1022
-                                  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1023
-                                  ucwords(str_replace('_', ' ', $reg_step)),
1024
-                                  date(
1025
-                                      get_option('date_format') . ' ' . get_option('time_format'),
1026
-                                      ($reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS))
1027
-                                  )
1028
-                              )
1029
-                              . '</li>';
1030
-            } else {
1031
-                $reg_steps .= '<li style="color:#E76700">'
1032
-                              . sprintf(
1033
-                                  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1034
-                                  ucwords(str_replace('_', ' ', $reg_step))
1035
-                              )
1036
-                              . '</li>';
1037
-            }
1038
-        }
1039
-        $reg_steps                                                 .= '</ul>';
1040
-        $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1041
-        $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1042
-            'Registration Step Progress',
1043
-            'event_espresso'
1044
-        );
1045
-
1046
-
1047
-        $this->_get_registrations_to_apply_payment_to();
1048
-        $this->_get_payment_methods($payments);
1049
-        $this->_get_payment_status_array();
1050
-        $this->_get_reg_status_selection(); //sets up the template args for the reg status array for the transaction.
1051
-
1052
-        $this->_template_args['transaction_form_url']    = add_query_arg(array(
1053
-            'action'  => 'edit_transaction',
1054
-            'process' => 'transaction',
1055
-        ), TXN_ADMIN_URL);
1056
-        $this->_template_args['apply_payment_form_url']  = add_query_arg(array(
1057
-            'page'   => 'espresso_transactions',
1058
-            'action' => 'espresso_apply_payment',
1059
-        ), WP_AJAX_URL);
1060
-        $this->_template_args['delete_payment_form_url'] = add_query_arg(array(
1061
-            'page'   => 'espresso_transactions',
1062
-            'action' => 'espresso_delete_payment',
1063
-        ), WP_AJAX_URL);
1064
-
1065
-        // 'espresso_delete_payment_nonce'
1066
-
1067
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1068
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1069
-    }
1070
-
1071
-
1072
-    /**
1073
-     * _get_registration_payment_IDs
1074
-     *    generates an array of Payment IDs and their corresponding Registration IDs
1075
-     *
1076
-     * @access protected
1077
-     * @param EE_Payment[] $payments
1078
-     * @return array
1079
-     * @throws EE_Error
1080
-     * @throws InvalidArgumentException
1081
-     * @throws InvalidDataTypeException
1082
-     * @throws InvalidInterfaceException
1083
-     */
1084
-    protected function _get_registration_payment_IDs($payments = array())
1085
-    {
1086
-        $existing_reg_payments = array();
1087
-        // get all reg payments for these payments
1088
-        $reg_payments = EEM_Registration_Payment::instance()->get_all(array(
1089
-            array(
1090
-                'PAY_ID' => array(
1091
-                    'IN',
1092
-                    array_keys($payments),
1093
-                ),
1094
-            ),
1095
-        ));
1096
-        if (! empty($reg_payments)) {
1097
-            foreach ($payments as $payment) {
1098
-                if (! $payment instanceof EE_Payment) {
1099
-                    continue;
1100
-                } elseif (! isset($existing_reg_payments[$payment->ID()])) {
1101
-                    $existing_reg_payments[$payment->ID()] = array();
1102
-                }
1103
-                foreach ($reg_payments as $reg_payment) {
1104
-                    if ($reg_payment instanceof EE_Registration_Payment
1105
-                        && $reg_payment->payment_ID() === $payment->ID()
1106
-                    ) {
1107
-                        $existing_reg_payments[$payment->ID()][] = $reg_payment->registration_ID();
1108
-                    }
1109
-                }
1110
-            }
1111
-        }
1112
-
1113
-        return $existing_reg_payments;
1114
-    }
1115
-
1116
-
1117
-    /**
1118
-     * _get_registrations_to_apply_payment_to
1119
-     *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1120
-     * which allows the admin to only apply the payment to the specific registrations
1121
-     *
1122
-     * @access protected
1123
-     * @return void
1124
-     * @throws \EE_Error
1125
-     */
1126
-    protected function _get_registrations_to_apply_payment_to()
1127
-    {
1128
-        // we want any registration with an active status (ie: not deleted or cancelled)
1129
-        $query_params                      = array(
1130
-            array(
1131
-                'STS_ID' => array(
1132
-                    'IN',
1133
-                    array(
1134
-                        EEM_Registration::status_id_approved,
1135
-                        EEM_Registration::status_id_pending_payment,
1136
-                        EEM_Registration::status_id_not_approved,
1137
-                    ),
1138
-                ),
1139
-            ),
1140
-        );
1141
-        $registrations_to_apply_payment_to = EEH_HTML::br()
1142
-                                             . EEH_HTML::div(
1143
-                                                 '',
1144
-                                                 'txn-admin-apply-payment-to-registrations-dv',
1145
-                                                 '',
1146
-                                                 'clear: both; margin: 1.5em 0 0; display: none;'
1147
-                                             );
1148
-        $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1149
-        $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
1150
-        $registrations_to_apply_payment_to .= EEH_HTML::thead(
1151
-            EEH_HTML::tr(
1152
-                EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1153
-                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1154
-                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1155
-                EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1156
-                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1157
-                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1158
-                EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1159
-            )
1160
-        );
1161
-        $registrations_to_apply_payment_to .= EEH_HTML::tbody();
1162
-        // get registrations for TXN
1163
-        $registrations = $this->_transaction->registrations($query_params);
1164
-        $existing_reg_payments = $this->_template_args['existing_reg_payments'];
1165
-        foreach ($registrations as $registration) {
1166
-            if ($registration instanceof EE_Registration) {
1167
-                $attendee_name                     = $registration->attendee() instanceof EE_Attendee
1168
-                    ? $registration->attendee()->full_name()
1169
-                    : esc_html__('Unknown Attendee', 'event_espresso');
1170
-                $owing                             = $registration->final_price() - $registration->paid();
1171
-                $taxable                           = $registration->ticket()->taxable()
1172
-                    ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1173
-                    : '';
1174
-                $checked = empty($existing_reg_payments) || in_array($registration->ID(), $existing_reg_payments)
1175
-                    ? ' checked="checked"'
1176
-                    : '';
1177
-                $disabled                          = $registration->final_price() > 0 ? '' : ' disabled';
1178
-                $registrations_to_apply_payment_to .= EEH_HTML::tr(
1179
-                    EEH_HTML::td($registration->ID()) .
1180
-                    EEH_HTML::td($attendee_name) .
1181
-                    EEH_HTML::td(
1182
-                        $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1183
-                    ) .
1184
-                    EEH_HTML::td($registration->event_name()) .
1185
-                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1186
-                    EEH_HTML::td(EEH_Template::format_currency($owing), '', 'txn-admin-payment-owing-td jst-cntr') .
1187
-                    EEH_HTML::td(
1188
-                        '<input type="checkbox" value="' . $registration->ID()
1189
-                        . '" name="txn_admin_payment[registrations]"'
1190
-                        . $checked . $disabled . '>',
1191
-                        '',
1192
-                        'jst-cntr'
1193
-                    ),
1194
-                    'apply-payment-registration-row-' . $registration->ID()
1195
-                );
1196
-            }
1197
-        }
1198
-        $registrations_to_apply_payment_to                         .= EEH_HTML::tbodyx();
1199
-        $registrations_to_apply_payment_to                         .= EEH_HTML::tablex();
1200
-        $registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1201
-        $registrations_to_apply_payment_to                         .= EEH_HTML::p(
1202
-            esc_html__(
1203
-                'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1204
-                'event_espresso'
1205
-            ),
1206
-            '',
1207
-            'clear description'
1208
-        );
1209
-        $registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1210
-        $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1211
-    }
1212
-
1213
-
1214
-    /**
1215
-     * _get_reg_status_selection
1216
-     *
1217
-     * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1218
-     *         instead of events.
1219
-     * @access protected
1220
-     * @return void
1221
-     * @throws EE_Error
1222
-     */
1223
-    protected function _get_reg_status_selection()
1224
-    {
1225
-        //first get all possible statuses
1226
-        $statuses = EEM_Registration::reg_status_array(array(), true);
1227
-        //let's add a "don't change" option.
1228
-        $status_array['NAN']                                 = esc_html__('Leave the Same', 'event_espresso');
1229
-        $status_array                                        = array_merge($status_array, $statuses);
1230
-        $this->_template_args['status_change_select']        = EEH_Form_Fields::select_input(
1231
-            'txn_reg_status_change[reg_status]',
1232
-            $status_array,
1233
-            'NAN',
1234
-            'id="txn-admin-payment-reg-status-inp"',
1235
-            'txn-reg-status-change-reg-status'
1236
-        );
1237
-        $this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1238
-            'delete_txn_reg_status_change[reg_status]',
1239
-            $status_array,
1240
-            'NAN',
1241
-            'delete-txn-admin-payment-reg-status-inp',
1242
-            'delete-txn-reg-status-change-reg-status'
1243
-        );
1244
-    }
1245
-
1246
-
1247
-    /**
1248
-     *    _get_payment_methods
1249
-     * Gets all the payment methods available generally, or the ones that are already
1250
-     * selected on these payments (in case their payment methods are no longer active).
1251
-     * Has the side-effect of updating the template args' payment_methods item
1252
-     *
1253
-     * @access private
1254
-     * @param EE_Payment[] to show on this page
1255
-     * @return void
1256
-     * @throws EE_Error
1257
-     * @throws InvalidArgumentException
1258
-     * @throws InvalidDataTypeException
1259
-     * @throws InvalidInterfaceException
1260
-     */
1261
-    private function _get_payment_methods($payments = array())
1262
-    {
1263
-        $payment_methods_of_payments = array();
1264
-        foreach ($payments as $payment) {
1265
-            if ($payment instanceof EE_Payment) {
1266
-                $payment_methods_of_payments[] = $payment->get('PMD_ID');
1267
-            }
1268
-        }
1269
-        if ($payment_methods_of_payments) {
1270
-            $query_args = array(
1271
-                array(
1272
-                    'OR*payment_method_for_payment' => array(
1273
-                        'PMD_ID'    => array('IN', $payment_methods_of_payments),
1274
-                        'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'),
1275
-                    ),
1276
-                ),
1277
-            );
1278
-        } else {
1279
-            $query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1280
-        }
1281
-        $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1282
-    }
1283
-
1284
-
1285
-    /**
1286
-     * txn_attendees_meta_box
1287
-     *    generates HTML for the Attendees Transaction main meta box
1288
-     *
1289
-     * @access public
1290
-     * @param WP_Post $post
1291
-     * @param array   $metabox
1292
-     * @return void
1293
-     * @throws DomainException
1294
-     * @throws EE_Error
1295
-     */
1296
-    public function txn_attendees_meta_box($post, $metabox = array('args' => array()))
1297
-    {
1298
-
1299
-        /** @noinspection NonSecureExtractUsageInspection */
1300
-        extract($metabox['args']);
1301
-        $this->_template_args['post']            = $post;
1302
-        $this->_template_args['event_attendees'] = array();
1303
-        // process items in cart
1304
-        $line_items = $this->_transaction->get_many_related(
1305
-            'Line_Item',
1306
-            array(array('LIN_type' => 'line-item'))
1307
-        );
1308
-        if (! empty($line_items)) {
1309
-            foreach ($line_items as $item) {
1310
-                if ($item instanceof EE_Line_Item) {
1311
-                    switch ($item->OBJ_type()) {
1312
-                        case 'Event':
1313
-                            break;
1314
-                        case 'Ticket':
1315
-                            $ticket = $item->ticket();
1316
-                            //right now we're only handling tickets here.
1317
-                            //Cause its expected that only tickets will have attendees right?
1318
-                            if (! $ticket instanceof EE_Ticket) {
1319
-                                continue;
1320
-                            }
1321
-                            try {
1322
-                                $event_name = $ticket->get_event_name();
1323
-                            } catch (Exception $e) {
1324
-                                EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1325
-                                $event_name = esc_html__('Unknown Event', 'event_espresso');
1326
-                            }
1327
-                            $event_name   .= ' - ' . $item->get('LIN_name');
1328
-                            $ticket_price = EEH_Template::format_currency($item->get('LIN_unit_price'));
1329
-                            // now get all of the registrations for this transaction that use this ticket
1330
-                            $registrations = $ticket->get_many_related(
1331
-                                'Registration',
1332
-                                array(array('TXN_ID' => $this->_transaction->ID()))
1333
-                            );
1334
-                            foreach ($registrations as $registration) {
1335
-                                if (! $registration instanceof EE_Registration) {
1336
-                                    continue;
1337
-                                }
1338
-                                $this->_template_args['event_attendees'][$registration->ID()]['STS_ID']
1339
-                                    = $registration->status_ID();
1340
-                                $this->_template_args['event_attendees'][$registration->ID()]['att_num']
1341
-                                    = $registration->count();
1342
-                                $this->_template_args['event_attendees'][$registration->ID()]['event_ticket_name']
1343
-                                    = $event_name;
1344
-                                $this->_template_args['event_attendees'][$registration->ID()]['ticket_price']
1345
-                                    = $ticket_price;
1346
-                                // attendee info
1347
-                                $attendee = $registration->get_first_related('Attendee');
1348
-                                if ($attendee instanceof EE_Attendee) {
1349
-                                    $this->_template_args['event_attendees'][$registration->ID()]['att_id']
1350
-                                        = $attendee->ID();
1351
-                                    $this->_template_args['event_attendees'][$registration->ID()]['attendee']
1352
-                                        = $attendee->full_name();
1353
-                                    $this->_template_args['event_attendees'][$registration->ID()]['email']
1354
-                                        = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1355
-                                          . esc_html__(
1356
-                                              ' Event',
1357
-                                              'event_espresso'
1358
-                                          )
1359
-                                          . '">' . $attendee->email() . '</a>';
1360
-                                    $this->_template_args['event_attendees'][$registration->ID()]['address']
1361
-                                        = EEH_Address::format($attendee, 'inline', false, false);
1362
-                                } else {
1363
-                                    $this->_template_args['event_attendees'][$registration->ID()]['att_id']   = '';
1364
-                                    $this->_template_args['event_attendees'][$registration->ID()]['attendee'] = '';
1365
-                                    $this->_template_args['event_attendees'][$registration->ID()]['email']    = '';
1366
-                                    $this->_template_args['event_attendees'][$registration->ID()]['address']  = '';
1367
-                                }
1368
-                            }
1369
-                            break;
1370
-
1371
-                    }
1372
-                }
1373
-            }
1374
-
1375
-            $this->_template_args['transaction_form_url'] = add_query_arg(
1376
-                array(
1377
-                    'action'  => 'edit_transaction',
1378
-                    'process' => 'attendees',
1379
-                ),
1380
-                TXN_ADMIN_URL
1381
-            );
1382
-            echo EEH_Template::display_template(
1383
-                TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1384
-                $this->_template_args,
1385
-                true
1386
-            );
1387
-
1388
-        } else {
1389
-            echo sprintf(
1390
-                esc_html__(
1391
-                    '%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1392
-                    'event_espresso'
1393
-                ),
1394
-                '<p class="important-notice">',
1395
-                '</p>'
1396
-            );
1397
-        }
1398
-    }
1399
-
1400
-
1401
-    /**
1402
-     * txn_registrant_side_meta_box
1403
-     * generates HTML for the Edit Transaction side meta box
1404
-     *
1405
-     * @access public
1406
-     * @return void
1407
-     * @throws DomainException
1408
-     * @throws EE_Error
1409
-     * @throws InvalidArgumentException
1410
-     * @throws InvalidDataTypeException
1411
-     * @throws InvalidInterfaceException
1412
-     */
1413
-    public function txn_registrant_side_meta_box()
1414
-    {
1415
-        $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1416
-            ? $this->_transaction->primary_registration()->get_first_related('Attendee')
1417
-            : null;
1418
-        if (! $primary_att instanceof EE_Attendee) {
1419
-            $this->_template_args['no_attendee_message'] = esc_html__(
1420
-                'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1421
-                'event_espresso'
1422
-            );
1423
-            $primary_att                                 = EEM_Attendee::instance()->create_default_object();
1424
-        }
1425
-        $this->_template_args['ATT_ID']            = $primary_att->ID();
1426
-        $this->_template_args['prime_reg_fname']   = $primary_att->fname();
1427
-        $this->_template_args['prime_reg_lname']   = $primary_att->lname();
1428
-        $this->_template_args['prime_reg_email']   = $primary_att->email();
1429
-        $this->_template_args['prime_reg_phone']   = $primary_att->phone();
1430
-        $this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(array(
1431
-            'action' => 'edit_attendee',
1432
-            'post'   => $primary_att->ID(),
1433
-        ), REG_ADMIN_URL);
1434
-        // get formatted address for registrant
1435
-        $this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1436
-        echo EEH_Template::display_template(
1437
-            TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1438
-            $this->_template_args,
1439
-            true
1440
-        );
1441
-    }
1442
-
1443
-
1444
-    /**
1445
-     * txn_billing_info_side_meta_box
1446
-     *    generates HTML for the Edit Transaction side meta box
1447
-     *
1448
-     * @access public
1449
-     * @return void
1450
-     * @throws DomainException
1451
-     * @throws EE_Error
1452
-     */
1453
-    public function txn_billing_info_side_meta_box()
1454
-    {
1455
-
1456
-        $this->_template_args['billing_form']     = $this->_transaction->billing_info();
1457
-        $this->_template_args['billing_form_url'] = add_query_arg(
1458
-            array('action' => 'edit_transaction', 'process' => 'billing'),
1459
-            TXN_ADMIN_URL
1460
-        );
1461
-
1462
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1463
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);/**/
1464
-    }
1465
-
1466
-
1467
-    /**
1468
-     * apply_payments_or_refunds
1469
-     *    registers a payment or refund made towards a transaction
1470
-     *
1471
-     * @access public
1472
-     * @return void
1473
-     * @throws EE_Error
1474
-     * @throws InvalidArgumentException
1475
-     * @throws ReflectionException
1476
-     * @throws RuntimeException
1477
-     * @throws InvalidDataTypeException
1478
-     * @throws InvalidInterfaceException
1479
-     */
1480
-    public function apply_payments_or_refunds()
1481
-    {
1482
-        $json_response_data = array('return_data' => false);
1483
-        $valid_data         = $this->_validate_payment_request_data();
1484
-        $has_access = EE_Registry::instance()->CAP->current_user_can(
1485
-            'ee_edit_payments',
1486
-            'apply_payment_or_refund_from_registration_details'
1487
-        );
1488
-        if (! empty($valid_data) && $has_access) {
1489
-            $PAY_ID = $valid_data['PAY_ID'];
1490
-            //save  the new payment
1491
-            $payment = $this->_create_payment_from_request_data($valid_data);
1492
-            // get the TXN for this payment
1493
-            $transaction = $payment->transaction();
1494
-            // verify transaction
1495
-            if ($transaction instanceof EE_Transaction) {
1496
-                // calculate_total_payments_and_update_status
1497
-                $this->_process_transaction_payments($transaction);
1498
-                $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1499
-                $this->_remove_existing_registration_payments($payment, $PAY_ID);
1500
-                // apply payment to registrations (if applicable)
1501
-                if (! empty($REG_IDs)) {
1502
-                    $this->_update_registration_payments($transaction, $payment, $REG_IDs);
1503
-                    $this->_maybe_send_notifications();
1504
-                    // now process status changes for the same registrations
1505
-                    $this->_process_registration_status_change($transaction, $REG_IDs);
1506
-                }
1507
-                $this->_maybe_send_notifications($payment);
1508
-                //prepare to render page
1509
-                $json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs);
1510
-                do_action(
1511
-                    'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1512
-                    $transaction,
1513
-                    $payment
1514
-                );
1515
-            } else {
1516
-                EE_Error::add_error(
1517
-                    esc_html__(
1518
-                        'A valid Transaction for this payment could not be retrieved.',
1519
-                        'event_espresso'
1520
-                    ),
1521
-                    __FILE__,
1522
-                    __FUNCTION__,
1523
-                    __LINE__
1524
-                );
1525
-            }
1526
-        } else {
1527
-            if ($has_access) {
1528
-                EE_Error::add_error(
1529
-                    esc_html__(
1530
-                        'The payment form data could not be processed. Please try again.',
1531
-                        'event_espresso'
1532
-                    ),
1533
-                    __FILE__,
1534
-                    __FUNCTION__,
1535
-                    __LINE__
1536
-                );
1537
-            } else {
1538
-                EE_Error::add_error(
1539
-                    esc_html__(
1540
-                        'You do not have access to apply payments or refunds to a registration.',
1541
-                        'event_espresso'
1542
-                    ),
1543
-                    __FILE__,
1544
-                    __FUNCTION__,
1545
-                    __LINE__
1546
-                );
1547
-            }
1548
-        }
1549
-        $notices              = EE_Error::get_notices(
1550
-            false,
1551
-            false,
1552
-            false
1553
-        );
1554
-        $this->_template_args = array(
1555
-            'data'    => $json_response_data,
1556
-            'error'   => $notices['errors'],
1557
-            'success' => $notices['success'],
1558
-        );
1559
-        $this->_return_json();
1560
-    }
1561
-
1562
-
1563
-    /**
1564
-     * _validate_payment_request_data
1565
-     *
1566
-     * @return array
1567
-     */
1568
-    protected function _validate_payment_request_data()
1569
-    {
1570
-        if (! isset($this->_req_data['txn_admin_payment'])) {
1571
-            return false;
1572
-        }
1573
-        $payment_form = $this->_generate_payment_form_section();
1574
-        try {
1575
-            if ($payment_form->was_submitted()) {
1576
-                $payment_form->receive_form_submission();
1577
-                if (! $payment_form->is_valid()) {
1578
-                    $submission_error_messages = array();
1579
-                    foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1580
-                        if ($validation_error instanceof EE_Validation_Error) {
1581
-                            $submission_error_messages[] = sprintf(
1582
-                                _x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1583
-                                $validation_error->get_form_section()->html_label_text(),
1584
-                                $validation_error->getMessage()
1585
-                            );
1586
-                        }
1587
-                    }
1588
-                    EE_Error::add_error(
1589
-                        implode('<br />', $submission_error_messages),
1590
-                        __FILE__,
1591
-                        __FUNCTION__,
1592
-                        __LINE__
1593
-                    );
1594
-
1595
-                    return array();
1596
-                }
1597
-            }
1598
-        } catch (EE_Error $e) {
1599
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1600
-
1601
-            return array();
1602
-        }
1603
-
1604
-        return $payment_form->valid_data();
1605
-    }
1606
-
1607
-
1608
-    /**
1609
-     * _generate_payment_form_section
1610
-     *
1611
-     * @return EE_Form_Section_Proper
1612
-     */
1613
-    protected function _generate_payment_form_section()
1614
-    {
1615
-        return new EE_Form_Section_Proper(
1616
-            array(
1617
-                'name'        => 'txn_admin_payment',
1618
-                'subsections' => array(
1619
-                    'PAY_ID'          => new EE_Text_Input(
1620
-                        array(
1621
-                            'default'               => 0,
1622
-                            'required'              => false,
1623
-                            'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1624
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1625
-                        )
1626
-                    ),
1627
-                    'TXN_ID'          => new EE_Text_Input(
1628
-                        array(
1629
-                            'default'               => 0,
1630
-                            'required'              => true,
1631
-                            'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1632
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1633
-                        )
1634
-                    ),
1635
-                    'type'            => new EE_Text_Input(
1636
-                        array(
1637
-                            'default'               => 1,
1638
-                            'required'              => true,
1639
-                            'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1640
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1641
-                        )
1642
-                    ),
1643
-                    'amount'          => new EE_Text_Input(
1644
-                        array(
1645
-                            'default'               => 0,
1646
-                            'required'              => true,
1647
-                            'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1648
-                            'validation_strategies' => array(new EE_Float_Normalization()),
1649
-                        )
1650
-                    ),
1651
-                    'status'          => new EE_Text_Input(
1652
-                        array(
1653
-                            'default'         => EEM_Payment::status_id_approved,
1654
-                            'required'        => true,
1655
-                            'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1656
-                        )
1657
-                    ),
1658
-                    'PMD_ID'          => new EE_Text_Input(
1659
-                        array(
1660
-                            'default'               => 2,
1661
-                            'required'              => true,
1662
-                            'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1663
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1664
-                        )
1665
-                    ),
1666
-                    'date'            => new EE_Text_Input(
1667
-                        array(
1668
-                            'default'         => time(),
1669
-                            'required'        => true,
1670
-                            'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1671
-                        )
1672
-                    ),
1673
-                    'txn_id_chq_nmbr' => new EE_Text_Input(
1674
-                        array(
1675
-                            'default'               => '',
1676
-                            'required'              => false,
1677
-                            'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1678
-                            'validation_strategies' => array(
1679
-                                new EE_Max_Length_Validation_Strategy(
1680
-                                    esc_html__('Input too long', 'event_espresso'),
1681
-                                    100
1682
-                                ),
1683
-                            ),
1684
-                        )
1685
-                    ),
1686
-                    'po_number'       => new EE_Text_Input(
1687
-                        array(
1688
-                            'default'               => '',
1689
-                            'required'              => false,
1690
-                            'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1691
-                            'validation_strategies' => array(
1692
-                                new EE_Max_Length_Validation_Strategy(
1693
-                                    esc_html__('Input too long', 'event_espresso'),
1694
-                                    100
1695
-                                ),
1696
-                            ),
1697
-                        )
1698
-                    ),
1699
-                    'accounting'      => new EE_Text_Input(
1700
-                        array(
1701
-                            'default'               => '',
1702
-                            'required'              => false,
1703
-                            'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1704
-                            'validation_strategies' => array(
1705
-                                new EE_Max_Length_Validation_Strategy(
1706
-                                    esc_html__('Input too long', 'event_espresso'),
1707
-                                    100
1708
-                                ),
1709
-                            ),
1710
-                        )
1711
-                    ),
1712
-                ),
1713
-            )
1714
-        );
1715
-    }
1716
-
1717
-
1718
-    /**
1719
-     * _create_payment_from_request_data
1720
-     *
1721
-     * @param array $valid_data
1722
-     * @return EE_Payment
1723
-     * @throws EE_Error
1724
-     */
1725
-    protected function _create_payment_from_request_data($valid_data)
1726
-    {
1727
-        $PAY_ID = $valid_data['PAY_ID'];
1728
-        // get payment amount
1729
-        $amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1730
-        // payments have a type value of 1 and refunds have a type value of -1
1731
-        // so multiplying amount by type will give a positive value for payments, and negative values for refunds
1732
-        $amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1733
-        // for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1734
-        $date    = $valid_data['date']
1735
-            ? preg_replace('/\s+/', ' ', $valid_data['date'])
1736
-            : date('Y-m-d g:i a', current_time('timestamp'));
1737
-        $payment = EE_Payment::new_instance(
1738
-            array(
1739
-                'TXN_ID'              => $valid_data['TXN_ID'],
1740
-                'STS_ID'              => $valid_data['status'],
1741
-                'PAY_timestamp'       => $date,
1742
-                'PAY_source'          => EEM_Payment_Method::scope_admin,
1743
-                'PMD_ID'              => $valid_data['PMD_ID'],
1744
-                'PAY_amount'          => $amount,
1745
-                'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1746
-                'PAY_po_number'       => $valid_data['po_number'],
1747
-                'PAY_extra_accntng'   => $valid_data['accounting'],
1748
-                'PAY_details'         => $valid_data,
1749
-                'PAY_ID'              => $PAY_ID,
1750
-            ),
1751
-            '',
1752
-            array('Y-m-d', 'g:i a')
1753
-        );
1754
-
1755
-        if (! $payment->save()) {
1756
-            EE_Error::add_error(
1757
-                sprintf(
1758
-                    esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1759
-                    $payment->ID()
1760
-                ),
1761
-                __FILE__, __FUNCTION__, __LINE__
1762
-            );
1763
-        }
1764
-
1765
-        return $payment;
1766
-    }
1767
-
1768
-
1769
-    /**
1770
-     * _process_transaction_payments
1771
-     *
1772
-     * @param \EE_Transaction $transaction
1773
-     * @return void
1774
-     * @throws EE_Error
1775
-     * @throws InvalidArgumentException
1776
-     * @throws ReflectionException
1777
-     * @throws InvalidDataTypeException
1778
-     * @throws InvalidInterfaceException
1779
-     */
1780
-    protected function _process_transaction_payments(EE_Transaction $transaction)
1781
-    {
1782
-        /** @type EE_Transaction_Payments $transaction_payments */
1783
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1784
-        //update the transaction with this payment
1785
-        if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1786
-            EE_Error::add_success(esc_html__(
1787
-                'The payment has been processed successfully.', 'event_espresso'),
1788
-                __FILE__,
1789
-                __FUNCTION__,
1790
-                __LINE__
1791
-            );
1792
-        } else {
1793
-            EE_Error::add_error(
1794
-                esc_html__(
1795
-                    'The payment was processed successfully but the amount paid for the transaction was not updated.',
1796
-                    'event_espresso'
1797
-                )
1798
-                ,
1799
-                __FILE__,
1800
-                __FUNCTION__,
1801
-                __LINE__
1802
-            );
1803
-        }
1804
-    }
1805
-
1806
-
1807
-    /**
1808
-     * _get_REG_IDs_to_apply_payment_to
1809
-     * returns a list of registration IDs that the payment will apply to
1810
-     *
1811
-     * @param \EE_Payment $payment
1812
-     * @return array
1813
-     * @throws EE_Error
1814
-     */
1815
-    protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1816
-    {
1817
-        $REG_IDs = array();
1818
-        // grab array of IDs for specific registrations to apply changes to
1819
-        if (isset($this->_req_data['txn_admin_payment']['registrations'])) {
1820
-            $REG_IDs = (array)$this->_req_data['txn_admin_payment']['registrations'];
1821
-        }
1822
-        //nothing specified ? then get all reg IDs
1823
-        if (empty($REG_IDs)) {
1824
-            $registrations = $payment->transaction()->registrations();
1825
-            $REG_IDs       = ! empty($registrations)
1826
-                ? array_keys($registrations)
1827
-                : $this->_get_existing_reg_payment_REG_IDs($payment);
1828
-        }
1829
-
1830
-        // ensure that REG_IDs are integers and NOT strings
1831
-        return array_map('intval', $REG_IDs);
1832
-    }
1833
-
1834
-
1835
-    /**
1836
-     * @return array
1837
-     */
1838
-    public function existing_reg_payment_REG_IDs()
1839
-    {
1840
-        return $this->_existing_reg_payment_REG_IDs;
1841
-    }
1842
-
1843
-
1844
-    /**
1845
-     * @param array $existing_reg_payment_REG_IDs
1846
-     */
1847
-    public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1848
-    {
1849
-        $this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1850
-    }
1851
-
1852
-
1853
-    /**
1854
-     * _get_existing_reg_payment_REG_IDs
1855
-     * returns a list of registration IDs that the payment is currently related to
1856
-     * as recorded in the database
1857
-     *
1858
-     * @param \EE_Payment $payment
1859
-     * @return array
1860
-     * @throws EE_Error
1861
-     */
1862
-    protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
1863
-    {
1864
-        if ($this->existing_reg_payment_REG_IDs() === null) {
1865
-            // let's get any existing reg payment records for this payment
1866
-            $existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
1867
-            // but we only want the REG IDs, so grab the array keys
1868
-            $existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
1869
-                ? array_keys($existing_reg_payment_REG_IDs)
1870
-                : array();
1871
-            $this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
1872
-        }
1873
-
1874
-        return $this->existing_reg_payment_REG_IDs();
1875
-    }
1876
-
1877
-
1878
-    /**
1879
-     * _remove_existing_registration_payments
1880
-     * this calculates the difference between existing relations
1881
-     * to the supplied payment and the new list registration IDs,
1882
-     * removes any related registrations that no longer apply,
1883
-     * and then updates the registration paid fields
1884
-     *
1885
-     * @param \EE_Payment $payment
1886
-     * @param int         $PAY_ID
1887
-     * @return bool;
1888
-     * @throws EE_Error
1889
-     * @throws InvalidArgumentException
1890
-     * @throws ReflectionException
1891
-     * @throws InvalidDataTypeException
1892
-     * @throws InvalidInterfaceException
1893
-     */
1894
-    protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
1895
-    {
1896
-        // newly created payments will have nothing recorded for $PAY_ID
1897
-        if ($PAY_ID == 0) {
1898
-            return false;
1899
-        }
1900
-        $existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
1901
-        if (empty($existing_reg_payment_REG_IDs)) {
1902
-            return false;
1903
-        }
1904
-        /** @type EE_Transaction_Payments $transaction_payments */
1905
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1906
-
1907
-        return $transaction_payments->delete_registration_payments_and_update_registrations(
1908
-            $payment,
1909
-            array(
1910
-                array(
1911
-                    'PAY_ID' => $payment->ID(),
1912
-                    'REG_ID' => array('IN', $existing_reg_payment_REG_IDs),
1913
-                ),
1914
-            )
1915
-        );
1916
-    }
1917
-
1918
-
1919
-    /**
1920
-     * _update_registration_payments
1921
-     * this applies the payments to the selected registrations
1922
-     * but only if they have not already been paid for
1923
-     *
1924
-     * @param  EE_Transaction $transaction
1925
-     * @param \EE_Payment     $payment
1926
-     * @param array           $REG_IDs
1927
-     * @return void
1928
-     * @throws EE_Error
1929
-     * @throws InvalidArgumentException
1930
-     * @throws ReflectionException
1931
-     * @throws RuntimeException
1932
-     * @throws InvalidDataTypeException
1933
-     * @throws InvalidInterfaceException
1934
-     */
1935
-    protected function _update_registration_payments(
1936
-        EE_Transaction $transaction,
1937
-        EE_Payment $payment,
1938
-        $REG_IDs = array()
1939
-    ) {
1940
-        // we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
1941
-        // so let's do that using our set of REG_IDs from the form
1942
-        $registration_query_where_params = array(
1943
-            'REG_ID' => array('IN', $REG_IDs),
1944
-        );
1945
-        // but add in some conditions regarding payment,
1946
-        // so that we don't apply payments to registrations that are free or have already been paid for
1947
-        // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
1948
-        if (! $payment->is_a_refund()) {
1949
-            $registration_query_where_params['REG_final_price']  = array('!=', 0);
1950
-            $registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
1951
-        }
1952
-        $registrations = $transaction->registrations(array($registration_query_where_params));
1953
-        if (! empty($registrations)) {
1954
-            /** @type EE_Payment_Processor $payment_processor */
1955
-            $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
1956
-            $payment_processor->process_registration_payments($transaction, $payment, $registrations);
1957
-        }
1958
-    }
1959
-
1960
-
1961
-    /**
1962
-     * _process_registration_status_change
1963
-     * This processes requested registration status changes for all the registrations
1964
-     * on a given transaction and (optionally) sends out notifications for the changes.
1965
-     *
1966
-     * @param  EE_Transaction $transaction
1967
-     * @param array           $REG_IDs
1968
-     * @return bool
1969
-     * @throws EE_Error
1970
-     * @throws InvalidArgumentException
1971
-     * @throws ReflectionException
1972
-     * @throws InvalidDataTypeException
1973
-     * @throws InvalidInterfaceException
1974
-     */
1975
-    protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array())
1976
-    {
1977
-        // first if there is no change in status then we get out.
1978
-        if (
1979
-            ! isset($this->_req_data['txn_reg_status_change']['reg_status'])
1980
-            || $this->_req_data['txn_reg_status_change']['reg_status'] === 'NAN'
1981
-        ) {
1982
-            //no error message, no change requested, just nothing to do man.
1983
-            return false;
1984
-        }
1985
-        /** @type EE_Transaction_Processor $transaction_processor */
1986
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
1987
-
1988
-        // made it here dude?  Oh WOW.  K, let's take care of changing the statuses
1989
-        return $transaction_processor->manually_update_registration_statuses(
1990
-            $transaction,
1991
-            sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']),
1992
-            array(array('REG_ID' => array('IN', $REG_IDs)))
1993
-        );
1994
-    }
1995
-
1996
-
1997
-    /**
1998
-     * _build_payment_json_response
1999
-     *
2000
-     * @access public
2001
-     * @param \EE_Payment $payment
2002
-     * @param array       $REG_IDs
2003
-     * @param bool | null $delete_txn_reg_status_change
2004
-     * @return array
2005
-     * @throws EE_Error
2006
-     * @throws InvalidArgumentException
2007
-     * @throws InvalidDataTypeException
2008
-     * @throws InvalidInterfaceException
2009
-     */
2010
-    protected function _build_payment_json_response(
2011
-        EE_Payment $payment,
2012
-        $REG_IDs = array(),
2013
-        $delete_txn_reg_status_change = null
2014
-    ) {
2015
-        // was the payment deleted ?
2016
-        if (is_bool($delete_txn_reg_status_change)) {
2017
-            return array(
2018
-                'PAY_ID'                       => $payment->ID(),
2019
-                'amount'                       => $payment->amount(),
2020
-                'total_paid'                   => $payment->transaction()->paid(),
2021
-                'txn_status'                   => $payment->transaction()->status_ID(),
2022
-                'pay_status'                   => $payment->STS_ID(),
2023
-                'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2024
-                'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2025
-            );
2026
-        } else {
2027
-            $this->_get_payment_status_array();
2028
-
2029
-            return array(
2030
-                'amount'           => $payment->amount(),
2031
-                'total_paid'       => $payment->transaction()->paid(),
2032
-                'txn_status'       => $payment->transaction()->status_ID(),
2033
-                'pay_status'       => $payment->STS_ID(),
2034
-                'PAY_ID'           => $payment->ID(),
2035
-                'STS_ID'           => $payment->STS_ID(),
2036
-                'status'           => self::$_pay_status[$payment->STS_ID()],
2037
-                'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2038
-                'method'           => strtoupper($payment->source()),
2039
-                'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
2040
-                'gateway'          => $payment->payment_method()
2041
-                    ? $payment->payment_method()->admin_name()
2042
-                    : esc_html__("Unknown", 'event_espresso'),
2043
-                'gateway_response' => $payment->gateway_response(),
2044
-                'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2045
-                'po_number'        => $payment->po_number(),
2046
-                'extra_accntng'    => $payment->extra_accntng(),
2047
-                'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2048
-            );
2049
-        }
2050
-    }
2051
-
2052
-
2053
-    /**
2054
-     * delete_payment
2055
-     *    delete a payment or refund made towards a transaction
2056
-     *
2057
-     * @access public
2058
-     * @return void
2059
-     * @throws EE_Error
2060
-     * @throws InvalidArgumentException
2061
-     * @throws ReflectionException
2062
-     * @throws InvalidDataTypeException
2063
-     * @throws InvalidInterfaceException
2064
-     */
2065
-    public function delete_payment()
2066
-    {
2067
-        $json_response_data = array('return_data' => false);
2068
-        $PAY_ID             = isset($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2069
-            ? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2070
-            : 0;
2071
-        $can_delete = EE_Registry::instance()->CAP->current_user_can(
2072
-            'ee_delete_payments',
2073
-            'delete_payment_from_registration_details'
2074
-        );
2075
-        if ($PAY_ID && $can_delete) {
2076
-            $delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change'])
2077
-                ? $this->_req_data['delete_txn_reg_status_change']
2078
-                : false;
2079
-            $payment                      = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2080
-            if ($payment instanceof EE_Payment) {
2081
-                $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2082
-                /** @type EE_Transaction_Payments $transaction_payments */
2083
-                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2084
-                if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2085
-                    $json_response_data['return_data'] = $this->_build_payment_json_response(
2086
-                        $payment,
2087
-                        $REG_IDs,
2088
-                        $delete_txn_reg_status_change
2089
-                    );
2090
-                    if ($delete_txn_reg_status_change) {
2091
-                        $this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
2092
-                        //MAKE sure we also add the delete_txn_req_status_change to the
2093
-                        //$_REQUEST global because that's how messages will be looking for it.
2094
-                        $_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
2095
-                        $this->_maybe_send_notifications();
2096
-                        $this->_process_registration_status_change($payment->transaction(), $REG_IDs);
2097
-                    }
2098
-                }
2099
-            } else {
2100
-                EE_Error::add_error(
2101
-                    esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2102
-                    __FILE__, __FUNCTION__, __LINE__
2103
-                );
2104
-            }
2105
-        } else {
2106
-            if ($can_delete) {
2107
-                EE_Error::add_error(
2108
-                    esc_html__(
2109
-                        'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2110
-                        'event_espresso'
2111
-                    ),
2112
-                    __FILE__, __FUNCTION__, __LINE__
2113
-                );
2114
-            } else {
2115
-                EE_Error::add_error(
2116
-                    esc_html__(
2117
-                        'You do not have access to delete a payment.',
2118
-                        'event_espresso'
2119
-                    ),
2120
-                    __FILE__,
2121
-                    __FUNCTION__,
2122
-                    __LINE__
2123
-                );
2124
-            }
2125
-        }
2126
-        $notices              = EE_Error::get_notices(false, false, false);
2127
-        $this->_template_args = array(
2128
-            'data'      => $json_response_data,
2129
-            'success'   => $notices['success'],
2130
-            'error'     => $notices['errors'],
2131
-            'attention' => $notices['attention'],
2132
-        );
2133
-        $this->_return_json();
2134
-    }
2135
-
2136
-
2137
-    /**
2138
-     * _registration_payment_data_array
2139
-     * adds info for 'owing' and 'paid' for each registration to the json response
2140
-     *
2141
-     * @access protected
2142
-     * @param array $REG_IDs
2143
-     * @return array
2144
-     * @throws EE_Error
2145
-     * @throws InvalidArgumentException
2146
-     * @throws InvalidDataTypeException
2147
-     * @throws InvalidInterfaceException
2148
-     */
2149
-    protected function _registration_payment_data_array($REG_IDs)
2150
-    {
2151
-        $registration_payment_data = array();
2152
-        //if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2153
-        if (! empty($REG_IDs)) {
2154
-            $registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
2155
-            foreach ($registrations as $registration) {
2156
-                if ($registration instanceof EE_Registration) {
2157
-                    $registration_payment_data[$registration->ID()] = array(
2158
-                        'paid'  => $registration->pretty_paid(),
2159
-                        'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2160
-                    );
2161
-                }
2162
-            }
2163
-        }
2164
-
2165
-        return $registration_payment_data;
2166
-    }
2167
-
2168
-
2169
-    /**
2170
-     * _maybe_send_notifications
2171
-     * determines whether or not the admin has indicated that notifications should be sent.
2172
-     * If so, will toggle a filter switch for delivering registration notices.
2173
-     * If passed an EE_Payment object, then it will trigger payment notifications instead.
2174
-     *
2175
-     * @access protected
2176
-     * @param \EE_Payment | null $payment
2177
-     */
2178
-    protected function _maybe_send_notifications($payment = null)
2179
-    {
2180
-        switch ($payment instanceof EE_Payment) {
2181
-            // payment notifications
2182
-            case true :
2183
-                if (
2184
-                    isset(
2185
-                        $this->_req_data['txn_payments'],
2186
-                        $this->_req_data['txn_payments']['send_notifications']
2187
-                    ) &&
2188
-                    filter_var($this->_req_data['txn_payments']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
2189
-                ) {
2190
-                    $this->_process_payment_notification($payment);
2191
-                }
2192
-                break;
2193
-            // registration notifications
2194
-            case false :
2195
-                if (
2196
-                    isset(
2197
-                        $this->_req_data['txn_reg_status_change'],
2198
-                        $this->_req_data['txn_reg_status_change']['send_notifications']
2199
-                    ) &&
2200
-                    filter_var($this->_req_data['txn_reg_status_change']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
2201
-                ) {
2202
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2203
-                }
2204
-                break;
2205
-        }
2206
-    }
2207
-
2208
-
2209
-    /**
2210
-     * _send_payment_reminder
2211
-     *    generates HTML for the View Transaction Details Admin page
2212
-     *
2213
-     * @access protected
2214
-     * @return void
2215
-     * @throws EE_Error
2216
-     * @throws InvalidArgumentException
2217
-     * @throws InvalidDataTypeException
2218
-     * @throws InvalidInterfaceException
2219
-     */
2220
-    protected function _send_payment_reminder()
2221
-    {
2222
-        $TXN_ID      = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2223
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2224
-        $query_args  = isset($this->_req_data['redirect_to']) ? array(
2225
-            'action' => $this->_req_data['redirect_to'],
2226
-            'TXN_ID' => $this->_req_data['TXN_ID'],
2227
-        ) : array();
2228
-        do_action(
2229
-            'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2230
-            $transaction
2231
-        );
2232
-        $this->_redirect_after_action(
2233
-            false,
2234
-            esc_html__('payment reminder', 'event_espresso'),
2235
-            esc_html__('sent', 'event_espresso'),
2236
-            $query_args,
2237
-            true
2238
-        );
2239
-    }
2240
-
2241
-
2242
-    /**
2243
-     *  get_transactions
2244
-     *    get transactions for given parameters (used by list table)
2245
-     *
2246
-     * @param  int     $perpage how many transactions displayed per page
2247
-     * @param  boolean $count   return the count or objects
2248
-     * @param string   $view
2249
-     * @return mixed int = count || array of transaction objects
2250
-     * @throws EE_Error
2251
-     * @throws InvalidArgumentException
2252
-     * @throws InvalidDataTypeException
2253
-     * @throws InvalidInterfaceException
2254
-     */
2255
-    public function get_transactions($perpage, $count = false, $view = '')
2256
-    {
2257
-
2258
-        $TXN = EEM_Transaction::instance();
2259
-
2260
-        $start_date = isset($this->_req_data['txn-filter-start-date'])
2261
-            ? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
2262
-            : date(
2263
-                'm/d/Y',
2264
-                strtotime('-10 year')
2265
-            );
2266
-        $end_date   = isset($this->_req_data['txn-filter-end-date'])
2267
-            ? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
2268
-            : date('m/d/Y');
2269
-
2270
-        //make sure our timestamps start and end right at the boundaries for each day
2271
-        $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2272
-        $end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2273
-
2274
-
2275
-        //convert to timestamps
2276
-        $start_date = strtotime($start_date);
2277
-        $end_date   = strtotime($end_date);
2278
-
2279
-        //makes sure start date is the lowest value and vice versa
2280
-        $start_date = min($start_date, $end_date);
2281
-        $end_date   = max($start_date, $end_date);
2282
-
2283
-        //convert to correct format for query
2284
-        $start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2285
-            'TXN_timestamp',
2286
-            date('Y-m-d H:i:s', $start_date),
2287
-            'Y-m-d H:i:s'
2288
-        );
2289
-        $end_date   = EEM_Transaction::instance()->convert_datetime_for_query(
2290
-            'TXN_timestamp',
2291
-            date('Y-m-d H:i:s', $end_date),
2292
-            'Y-m-d H:i:s'
2293
-        );
2294
-
2295
-
2296
-        //set orderby
2297
-        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
2298
-
2299
-        switch ($this->_req_data['orderby']) {
2300
-            case 'TXN_ID':
2301
-                $orderby = 'TXN_ID';
2302
-                break;
2303
-            case 'ATT_fname':
2304
-                $orderby = 'Registration.Attendee.ATT_fname';
2305
-                break;
2306
-            case 'event_name':
2307
-                $orderby = 'Registration.Event.EVT_name';
2308
-                break;
2309
-            default: //'TXN_timestamp'
2310
-                $orderby = 'TXN_timestamp';
2311
-        }
2312
-
2313
-        $sort         = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2314
-        $current_page = ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1;
2315
-        $per_page     = ! empty($perpage) ? $perpage : 10;
2316
-        $per_page     = ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page;
2317
-
2318
-        $offset = ($current_page - 1) * $per_page;
2319
-        $limit  = array($offset, $per_page);
2320
-
2321
-        $_where = array(
2322
-            'TXN_timestamp'          => array('BETWEEN', array($start_date, $end_date)),
2323
-            'Registration.REG_count' => 1,
2324
-        );
2325
-
2326
-        if (isset($this->_req_data['EVT_ID'])) {
2327
-            $_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID'];
2328
-        }
2329
-
2330
-        if (isset($this->_req_data['s'])) {
2331
-            $search_string = '%' . $this->_req_data['s'] . '%';
2332
-            $_where['OR']  = array(
2333
-                'Registration.Event.EVT_name'         => array('LIKE', $search_string),
2334
-                'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
2335
-                'Registration.Event.EVT_short_desc'   => array('LIKE', $search_string),
2336
-                'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string),
2337
-                'Registration.Attendee.ATT_fname'     => array('LIKE', $search_string),
2338
-                'Registration.Attendee.ATT_lname'     => array('LIKE', $search_string),
2339
-                'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string),
2340
-                'Registration.Attendee.ATT_email'     => array('LIKE', $search_string),
2341
-                'Registration.Attendee.ATT_address'   => array('LIKE', $search_string),
2342
-                'Registration.Attendee.ATT_address2'  => array('LIKE', $search_string),
2343
-                'Registration.Attendee.ATT_city'      => array('LIKE', $search_string),
2344
-                'Registration.REG_final_price'        => array('LIKE', $search_string),
2345
-                'Registration.REG_code'               => array('LIKE', $search_string),
2346
-                'Registration.REG_count'              => array('LIKE', $search_string),
2347
-                'Registration.REG_group_size'         => array('LIKE', $search_string),
2348
-                'Registration.Ticket.TKT_name'        => array('LIKE', $search_string),
2349
-                'Registration.Ticket.TKT_description' => array('LIKE', $search_string),
2350
-                'Payment.PAY_source'                  => array('LIKE', $search_string),
2351
-                'Payment.Payment_Method.PMD_name'     => array('LIKE', $search_string),
2352
-                'TXN_session_data'                    => array('LIKE', $search_string),
2353
-                'Payment.PAY_txn_id_chq_nmbr'         => array('LIKE', $search_string),
2354
-            );
2355
-        }
2356
-
2357
-        //failed transactions
2358
-        $failed    = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count)
2359
-                     || ($count && $view === 'failed');
2360
-        $abandoned = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count)
2361
-                     || ($count && $view === 'abandoned');
2362
-
2363
-        if ($failed) {
2364
-            $_where['STS_ID'] = EEM_Transaction::failed_status_code;
2365
-        } else if ($abandoned) {
2366
-            $_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2367
-        } else {
2368
-            $_where['STS_ID']  = array('!=', EEM_Transaction::failed_status_code);
2369
-            $_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code);
2370
-        }
2371
-
2372
-        $query_params = array(
2373
-            $_where,
2374
-            'order_by'                 => array($orderby => $sort),
2375
-            'limit'                    => $limit,
2376
-            'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2377
-        );
2378
-
2379
-        $transactions = $count
2380
-            ? $TXN->count(array($_where), 'TXN_ID', true)
2381
-            : $TXN->get_all($query_params);
2382
-
2383
-        return $transactions;
2384
-    }
19
+	/**
20
+	 * @var EE_Transaction
21
+	 */
22
+	private $_transaction;
23
+
24
+	/**
25
+	 * @var EE_Session
26
+	 */
27
+	private $_session;
28
+
29
+	/**
30
+	 * @var array $_txn_status
31
+	 */
32
+	private static $_txn_status;
33
+
34
+	/**
35
+	 * @var array $_pay_status
36
+	 */
37
+	private static $_pay_status;
38
+
39
+	/**
40
+	 * @var array $_existing_reg_payment_REG_IDs
41
+	 */
42
+	protected $_existing_reg_payment_REG_IDs = null;
43
+
44
+
45
+	/**
46
+	 * @Constructor
47
+	 * @access public
48
+	 * @param bool $routing
49
+	 * @throws EE_Error
50
+	 * @throws InvalidArgumentException
51
+	 * @throws ReflectionException
52
+	 * @throws InvalidDataTypeException
53
+	 * @throws InvalidInterfaceException
54
+	 */
55
+	public function __construct($routing = true)
56
+	{
57
+		parent::__construct($routing);
58
+	}
59
+
60
+
61
+	/**
62
+	 *    _init_page_props
63
+	 *
64
+	 * @return void
65
+	 */
66
+	protected function _init_page_props()
67
+	{
68
+		$this->page_slug        = TXN_PG_SLUG;
69
+		$this->page_label       = esc_html__('Transactions', 'event_espresso');
70
+		$this->_admin_base_url  = TXN_ADMIN_URL;
71
+		$this->_admin_base_path = TXN_ADMIN;
72
+	}
73
+
74
+
75
+	/**
76
+	 *    _ajax_hooks
77
+	 *
78
+	 * @return void
79
+	 */
80
+	protected function _ajax_hooks()
81
+	{
82
+		add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds'));
83
+		add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds'));
84
+		add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment'));
85
+	}
86
+
87
+
88
+	/**
89
+	 *    _define_page_props
90
+	 *
91
+	 * @return void
92
+	 */
93
+	protected function _define_page_props()
94
+	{
95
+		$this->_admin_page_title = $this->page_label;
96
+		$this->_labels           = array(
97
+			'buttons' => array(
98
+				'add'    => esc_html__('Add New Transaction', 'event_espresso'),
99
+				'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
100
+				'delete' => esc_html__('Delete Transaction', 'event_espresso'),
101
+			),
102
+		);
103
+	}
104
+
105
+
106
+	/**
107
+	 *        grab url requests and route them
108
+	 *
109
+	 * @access private
110
+	 * @return void
111
+	 * @throws EE_Error
112
+	 * @throws InvalidArgumentException
113
+	 * @throws InvalidDataTypeException
114
+	 * @throws InvalidInterfaceException
115
+	 */
116
+	public function _set_page_routes()
117
+	{
118
+
119
+		$this->_set_transaction_status_array();
120
+
121
+		$txn_id = ! empty($this->_req_data['TXN_ID'])
122
+				  && ! is_array($this->_req_data['TXN_ID'])
123
+			? $this->_req_data['TXN_ID']
124
+			: 0;
125
+
126
+		$this->_page_routes = array(
127
+
128
+			'default' => array(
129
+				'func'       => '_transactions_overview_list_table',
130
+				'capability' => 'ee_read_transactions',
131
+			),
132
+
133
+			'view_transaction' => array(
134
+				'func'       => '_transaction_details',
135
+				'capability' => 'ee_read_transaction',
136
+				'obj_id'     => $txn_id,
137
+			),
138
+
139
+			'send_payment_reminder' => array(
140
+				'func'       => '_send_payment_reminder',
141
+				'noheader'   => true,
142
+				'capability' => 'ee_send_message',
143
+			),
144
+
145
+			'espresso_apply_payment' => array(
146
+				'func'       => 'apply_payments_or_refunds',
147
+				'noheader'   => true,
148
+				'capability' => 'ee_edit_payments',
149
+			),
150
+
151
+			'espresso_apply_refund' => array(
152
+				'func'       => 'apply_payments_or_refunds',
153
+				'noheader'   => true,
154
+				'capability' => 'ee_edit_payments',
155
+			),
156
+
157
+			'espresso_delete_payment' => array(
158
+				'func'       => 'delete_payment',
159
+				'noheader'   => true,
160
+				'capability' => 'ee_delete_payments',
161
+			),
162
+
163
+		);
164
+	}
165
+
166
+
167
+	protected function _set_page_config()
168
+	{
169
+		$this->_page_config = array(
170
+			'default'          => array(
171
+				'nav'           => array(
172
+					'label' => esc_html__('Overview', 'event_espresso'),
173
+					'order' => 10,
174
+				),
175
+				'list_table'    => 'EE_Admin_Transactions_List_Table',
176
+				'help_tabs'     => array(
177
+					'transactions_overview_help_tab'                       => array(
178
+						'title'    => esc_html__('Transactions Overview', 'event_espresso'),
179
+						'filename' => 'transactions_overview',
180
+					),
181
+					'transactions_overview_table_column_headings_help_tab' => array(
182
+						'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
183
+						'filename' => 'transactions_overview_table_column_headings',
184
+					),
185
+					'transactions_overview_views_filters_help_tab'         => array(
186
+						'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
187
+						'filename' => 'transactions_overview_views_filters_search',
188
+					),
189
+				),
190
+				'help_tour'     => array('Transactions_Overview_Help_Tour'),
191
+				/**
192
+				 * commented out because currently we are not displaying tips for transaction list table status but this
193
+				 * may change in a later iteration so want to keep the code for then.
194
+				 */
195
+				//'qtips' => array( 'Transactions_List_Table_Tips' ),
196
+				'require_nonce' => false,
197
+			),
198
+			'view_transaction' => array(
199
+				'nav'       => array(
200
+					'label'      => esc_html__('View Transaction', 'event_espresso'),
201
+					'order'      => 5,
202
+					'url'        => isset($this->_req_data['TXN_ID'])
203
+						? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']), $this->_current_page_view_url)
204
+						: $this->_admin_base_url,
205
+					'persistent' => false,
206
+				),
207
+				'help_tabs' => array(
208
+					'transactions_view_transaction_help_tab'                                              => array(
209
+						'title'    => esc_html__('View Transaction', 'event_espresso'),
210
+						'filename' => 'transactions_view_transaction',
211
+					),
212
+					'transactions_view_transaction_transaction_details_table_help_tab'                    => array(
213
+						'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
214
+						'filename' => 'transactions_view_transaction_transaction_details_table',
215
+					),
216
+					'transactions_view_transaction_attendees_registered_help_tab'                         => array(
217
+						'title'    => esc_html__('Attendees Registered', 'event_espresso'),
218
+						'filename' => 'transactions_view_transaction_attendees_registered',
219
+					),
220
+					'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array(
221
+						'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
222
+						'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
223
+					),
224
+				),
225
+				'qtips'     => array('Transaction_Details_Tips'),
226
+				'help_tour' => array('Transaction_Details_Help_Tour'),
227
+				'metaboxes' => array('_transaction_details_metaboxes'),
228
+
229
+				'require_nonce' => false,
230
+			),
231
+		);
232
+	}
233
+
234
+
235
+	/**
236
+	 * The below methods aren't used by this class currently
237
+	 */
238
+	protected function _add_screen_options()
239
+	{
240
+		//noop
241
+	}
242
+
243
+	protected function _add_feature_pointers()
244
+	{
245
+		//noop
246
+	}
247
+
248
+	public function admin_init()
249
+	{
250
+		// IF a registration was JUST added via the admin...
251
+		if (isset(
252
+			$this->_req_data['redirect_from'],
253
+			$this->_req_data['EVT_ID'],
254
+			$this->_req_data['event_name']
255
+		)) {
256
+			// then set a cookie so that we can block any attempts to use
257
+			// the back button as a way to enter another registration.
258
+			setcookie(
259
+				'ee_registration_added',
260
+				$this->_req_data['EVT_ID'], time() + WEEK_IN_SECONDS, '/'
261
+			);
262
+			// and update the global
263
+			$_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID'];
264
+		}
265
+		EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
266
+			'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
267
+			'event_espresso'
268
+		);
269
+		EE_Registry::$i18n_js_strings['error_occurred']          = esc_html__(
270
+			'An error occurred! Please refresh the page and try again.',
271
+			'event_espresso'
272
+		);
273
+		EE_Registry::$i18n_js_strings['txn_status_array']        = self::$_txn_status;
274
+		EE_Registry::$i18n_js_strings['pay_status_array']        = self::$_pay_status;
275
+		EE_Registry::$i18n_js_strings['payments_total']          = esc_html__('Payments Total', 'event_espresso');
276
+		EE_Registry::$i18n_js_strings['transaction_overpaid']    = esc_html__(
277
+			'This transaction has been overpaid ! Payments Total',
278
+			'event_espresso'
279
+		);
280
+	}
281
+
282
+	public function admin_notices()
283
+	{
284
+		//noop
285
+	}
286
+
287
+	public function admin_footer_scripts()
288
+	{
289
+		//noop
290
+	}
291
+
292
+
293
+	/**
294
+	 * _set_transaction_status_array
295
+	 * sets list of transaction statuses
296
+	 *
297
+	 * @access private
298
+	 * @return void
299
+	 * @throws EE_Error
300
+	 * @throws InvalidArgumentException
301
+	 * @throws InvalidDataTypeException
302
+	 * @throws InvalidInterfaceException
303
+	 */
304
+	private function _set_transaction_status_array()
305
+	{
306
+		self::$_txn_status = EEM_Transaction::instance()->status_array(true);
307
+	}
308
+
309
+
310
+	/**
311
+	 * get_transaction_status_array
312
+	 * return the transaction status array for wp_list_table
313
+	 *
314
+	 * @access public
315
+	 * @return array
316
+	 */
317
+	public function get_transaction_status_array()
318
+	{
319
+		return self::$_txn_status;
320
+	}
321
+
322
+
323
+	/**
324
+	 *    get list of payment statuses
325
+	 *
326
+	 * @access private
327
+	 * @return void
328
+	 * @throws EE_Error
329
+	 * @throws InvalidArgumentException
330
+	 * @throws InvalidDataTypeException
331
+	 * @throws InvalidInterfaceException
332
+	 */
333
+	private function _get_payment_status_array()
334
+	{
335
+		self::$_pay_status                      = EEM_Payment::instance()->status_array(true);
336
+		$this->_template_args['payment_status'] = self::$_pay_status;
337
+
338
+	}
339
+
340
+
341
+	/**
342
+	 *    _add_screen_options_default
343
+	 *
344
+	 * @access protected
345
+	 * @return void
346
+	 * @throws InvalidArgumentException
347
+	 * @throws InvalidDataTypeException
348
+	 * @throws InvalidInterfaceException
349
+	 */
350
+	protected function _add_screen_options_default()
351
+	{
352
+		$this->_per_page_screen_option();
353
+	}
354
+
355
+
356
+	/**
357
+	 * load_scripts_styles
358
+	 *
359
+	 * @access public
360
+	 * @return void
361
+	 */
362
+	public function load_scripts_styles()
363
+	{
364
+		//enqueue style
365
+		wp_register_style(
366
+			'espresso_txn',
367
+			TXN_ASSETS_URL . 'espresso_transactions_admin.css',
368
+			array(),
369
+			EVENT_ESPRESSO_VERSION
370
+		);
371
+		wp_enqueue_style('espresso_txn');
372
+		//scripts
373
+		wp_register_script('espresso_txn', TXN_ASSETS_URL . 'espresso_transactions_admin.js', array(
374
+			'ee_admin_js',
375
+			'ee-datepicker',
376
+			'jquery-ui-datepicker',
377
+			'jquery-ui-draggable',
378
+			'ee-dialog',
379
+			'ee-accounting',
380
+			'ee-serialize-full-array',
381
+		), EVENT_ESPRESSO_VERSION, true);
382
+		wp_enqueue_script('espresso_txn');
383
+	}
384
+
385
+
386
+	/**
387
+	 *    load_scripts_styles_view_transaction
388
+	 *
389
+	 * @access public
390
+	 * @return void
391
+	 */
392
+	public function load_scripts_styles_view_transaction()
393
+	{
394
+		//styles
395
+		wp_enqueue_style('espresso-ui-theme');
396
+	}
397
+
398
+
399
+	/**
400
+	 *    load_scripts_styles_default
401
+	 *
402
+	 * @access public
403
+	 * @return void
404
+	 */
405
+	public function load_scripts_styles_default()
406
+	{
407
+		//styles
408
+		wp_enqueue_style('espresso-ui-theme');
409
+	}
410
+
411
+
412
+	/**
413
+	 *    _set_list_table_views_default
414
+	 *
415
+	 * @access protected
416
+	 * @return void
417
+	 */
418
+	protected function _set_list_table_views_default()
419
+	{
420
+		$this->_views = array(
421
+			'all'       => array(
422
+				'slug'  => 'all',
423
+				'label' => esc_html__('View All Transactions', 'event_espresso'),
424
+				'count' => 0,
425
+			),
426
+			'abandoned' => array(
427
+				'slug'  => 'abandoned',
428
+				'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
429
+				'count' => 0,
430
+			),
431
+			'failed'    => array(
432
+				'slug'  => 'failed',
433
+				'label' => esc_html__('Failed Transactions', 'event_espresso'),
434
+				'count' => 0,
435
+			),
436
+		);
437
+	}
438
+
439
+
440
+	/**
441
+	 * _set_transaction_object
442
+	 * This sets the _transaction property for the transaction details screen
443
+	 *
444
+	 * @access private
445
+	 * @return void
446
+	 * @throws EE_Error
447
+	 * @throws InvalidArgumentException
448
+	 * @throws RuntimeException
449
+	 * @throws InvalidDataTypeException
450
+	 * @throws InvalidInterfaceException
451
+	 */
452
+	private function _set_transaction_object()
453
+	{
454
+		if ($this->_transaction instanceof EE_Transaction) {
455
+			return;
456
+		} //get out we've already set the object
457
+
458
+		$TXN_ID = ! empty($this->_req_data['TXN_ID'])
459
+			? absint($this->_req_data['TXN_ID'])
460
+			: false;
461
+
462
+		//get transaction object
463
+		$this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
464
+		$this->_session     = $this->_transaction instanceof EE_Transaction
465
+			? $this->_transaction->get('TXN_session_data')
466
+			: null;
467
+		$this->_transaction->verify_abandoned_transaction_status();
468
+
469
+		if (! $this->_transaction instanceof EE_Transaction) {
470
+			$error_msg = sprintf(
471
+				esc_html__(
472
+					'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
473
+					'event_espresso'
474
+				),
475
+				$TXN_ID
476
+			);
477
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
478
+		}
479
+	}
480
+
481
+
482
+	/**
483
+	 *    _transaction_legend_items
484
+	 *
485
+	 * @access protected
486
+	 * @return array
487
+	 * @throws EE_Error
488
+	 * @throws InvalidArgumentException
489
+	 * @throws ReflectionException
490
+	 * @throws InvalidDataTypeException
491
+	 * @throws InvalidInterfaceException
492
+	 */
493
+	protected function _transaction_legend_items()
494
+	{
495
+		EE_Registry::instance()->load_helper('MSG_Template');
496
+		$items = array();
497
+
498
+		if (EE_Registry::instance()->CAP->current_user_can(
499
+			'ee_read_global_messages',
500
+			'view_filtered_messages'
501
+		)) {
502
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
503
+			if (is_array($related_for_icon)
504
+				&& isset($related_for_icon['css_class'], $related_for_icon['label'])
505
+			) {
506
+				$items['view_related_messages'] = array(
507
+					'class' => $related_for_icon['css_class'],
508
+					'desc'  => $related_for_icon['label'],
509
+				);
510
+			}
511
+		}
512
+
513
+		$items = apply_filters(
514
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
515
+			array_merge(
516
+				$items,
517
+				array(
518
+					'view_details'          => array(
519
+						'class' => 'dashicons dashicons-cart',
520
+						'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
521
+					),
522
+					'view_invoice'          => array(
523
+						'class' => 'dashicons dashicons-media-spreadsheet',
524
+						'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
525
+					),
526
+					'view_receipt'          => array(
527
+						'class' => 'dashicons dashicons-media-default',
528
+						'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
529
+					),
530
+					'view_registration'     => array(
531
+						'class' => 'dashicons dashicons-clipboard',
532
+						'desc'  => esc_html__('View Registration Details', 'event_espresso'),
533
+					),
534
+					'payment_overview_link' => array(
535
+						'class' => 'dashicons dashicons-money',
536
+						'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
537
+					),
538
+				)
539
+			)
540
+		);
541
+
542
+		if (EE_Registry::instance()->CAP->current_user_can(
543
+			'ee_send_message',
544
+			'espresso_transactions_send_payment_reminder'
545
+		)) {
546
+			if (EEH_MSG_Template::is_mt_active('payment_reminder')) {
547
+				$items['send_payment_reminder'] = array(
548
+					'class' => 'dashicons dashicons-email-alt',
549
+					'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
550
+				);
551
+			} else {
552
+				$items['blank*'] = array(
553
+					'class' => '',
554
+					'desc'  => '',
555
+				);
556
+			}
557
+		} else {
558
+			$items['blank*'] = array(
559
+				'class' => '',
560
+				'desc'  => '',
561
+			);
562
+		}
563
+		$more_items = apply_filters(
564
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
565
+			array(
566
+				'overpaid'   => array(
567
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
568
+					'desc'  => EEH_Template::pretty_status(
569
+						EEM_Transaction::overpaid_status_code,
570
+						false,
571
+						'sentence'
572
+					),
573
+				),
574
+				'complete'   => array(
575
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
576
+					'desc'  => EEH_Template::pretty_status(
577
+						EEM_Transaction::complete_status_code,
578
+						false,
579
+						'sentence'
580
+					),
581
+				),
582
+				'incomplete' => array(
583
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
584
+					'desc'  => EEH_Template::pretty_status(
585
+						EEM_Transaction::incomplete_status_code,
586
+						false,
587
+						'sentence'
588
+					),
589
+				),
590
+				'abandoned'  => array(
591
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
592
+					'desc'  => EEH_Template::pretty_status(
593
+						EEM_Transaction::abandoned_status_code,
594
+						false,
595
+						'sentence'
596
+					),
597
+				),
598
+				'failed'     => array(
599
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
600
+					'desc'  => EEH_Template::pretty_status(
601
+						EEM_Transaction::failed_status_code,
602
+						false,
603
+						'sentence'
604
+					),
605
+				),
606
+			)
607
+		);
608
+
609
+		return array_merge($items, $more_items);
610
+	}
611
+
612
+
613
+	/**
614
+	 *    _transactions_overview_list_table
615
+	 *
616
+	 * @access protected
617
+	 * @return void
618
+	 * @throws DomainException
619
+	 * @throws EE_Error
620
+	 * @throws InvalidArgumentException
621
+	 * @throws InvalidDataTypeException
622
+	 * @throws InvalidInterfaceException
623
+	 * @throws ReflectionException
624
+	 */
625
+	protected function _transactions_overview_list_table()
626
+	{
627
+		$this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
628
+		$event = isset($this->_req_data['EVT_ID'])
629
+			? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID'])
630
+			: null;
631
+		$this->_template_args['admin_page_header'] = $event instanceof EE_Event
632
+			? sprintf(
633
+				esc_html__(
634
+					'%sViewing Transactions for the Event: %s%s',
635
+					'event_espresso'
636
+				),
637
+				'<h3>',
638
+				'<a href="'
639
+				. EE_Admin_Page::add_query_args_and_nonce(
640
+					array('action' => 'edit', 'post' => $event->ID()),
641
+					EVENTS_ADMIN_URL
642
+				)
643
+				. '" title="'
644
+				. esc_attr__(
645
+					'Click to Edit event',
646
+					'event_espresso'
647
+				)
648
+				. '">' . $event->get('EVT_name') . '</a>',
649
+				'</h3>'
650
+			)
651
+			: '';
652
+		$this->_template_args['after_list_table']  = $this->_display_legend($this->_transaction_legend_items());
653
+		$this->display_admin_list_table_page_with_no_sidebar();
654
+	}
655
+
656
+
657
+	/**
658
+	 *    _transaction_details
659
+	 * generates HTML for the View Transaction Details Admin page
660
+	 *
661
+	 * @access protected
662
+	 * @return void
663
+	 * @throws DomainException
664
+	 * @throws EE_Error
665
+	 * @throws InvalidArgumentException
666
+	 * @throws InvalidDataTypeException
667
+	 * @throws InvalidInterfaceException
668
+	 * @throws RuntimeException
669
+	 */
670
+	protected function _transaction_details()
671
+	{
672
+		do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
673
+
674
+		$this->_set_transaction_status_array();
675
+
676
+		$this->_template_args                      = array();
677
+		$this->_template_args['transactions_page'] = $this->_wp_page_slug;
678
+
679
+		$this->_set_transaction_object();
680
+
681
+		$primary_registration = $this->_transaction->primary_registration();
682
+		$attendee = $primary_registration instanceof EE_Registration
683
+			? $primary_registration->attendee()
684
+			: null;
685
+
686
+		$this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
687
+		$this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
688
+
689
+		$this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
690
+		$this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
691
+
692
+		$this->_template_args['txn_status']['value'] = self::$_txn_status[$this->_transaction->get('STS_ID')];
693
+		$this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
694
+		$this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->get('STS_ID');
695
+
696
+		$this->_template_args['grand_total'] = $this->_transaction->get('TXN_total');
697
+		$this->_template_args['total_paid']  = $this->_transaction->get('TXN_paid');
698
+
699
+		if ($attendee instanceof EE_Attendee
700
+			&& EE_Registry::instance()->CAP->current_user_can(
701
+				'ee_send_message',
702
+				'espresso_transactions_send_payment_reminder'
703
+			)
704
+		) {
705
+			$this->_template_args['send_payment_reminder_button'] =
706
+				EEH_MSG_Template::is_mt_active('payment_reminder')
707
+				&& $this->_transaction->get('STS_ID') !== EEM_Transaction::complete_status_code
708
+				&& $this->_transaction->get('STS_ID') !== EEM_Transaction::overpaid_status_code
709
+					? EEH_Template::get_button_or_link(
710
+						EE_Admin_Page::add_query_args_and_nonce(
711
+							array(
712
+								'action'      => 'send_payment_reminder',
713
+								'TXN_ID'      => $this->_transaction->ID(),
714
+								'redirect_to' => 'view_transaction',
715
+							),
716
+							TXN_ADMIN_URL
717
+						),
718
+						__(' Send Payment Reminder', 'event_espresso'),
719
+						'button secondary-button right',
720
+						'dashicons dashicons-email-alt'
721
+					)
722
+					: '';
723
+		} else {
724
+			$this->_template_args['send_payment_reminder_button'] = '';
725
+		}
726
+
727
+		$amount_due = $this->_transaction->get('TXN_total') - $this->_transaction->get('TXN_paid');
728
+		$this->_template_args['amount_due'] = EEH_Template::format_currency(
729
+			$amount_due,
730
+			true
731
+		);
732
+		if (EE_Registry::instance()->CFG->currency->sign_b4) {
733
+			$this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign
734
+												  . $this->_template_args['amount_due'];
735
+		} else {
736
+			$this->_template_args['amount_due'] .= EE_Registry::instance()->CFG->currency->sign;
737
+		}
738
+		$this->_template_args['amount_due_class'] = '';
739
+
740
+		if ($this->_transaction->get('TXN_paid') == $this->_transaction->get('TXN_total')) {
741
+			// paid in full
742
+			$this->_template_args['amount_due'] = false;
743
+		} elseif ($this->_transaction->get('TXN_paid') > $this->_transaction->get('TXN_total')) {
744
+			// overpaid
745
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
746
+		} elseif ($this->_transaction->get('TXN_total') > 0
747
+				  && $this->_transaction->get('TXN_paid') > 0
748
+		) {
749
+			// monies owing
750
+			$this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn';
751
+		} elseif ($this->_transaction->get('TXN_total') > 0
752
+				  && $this->_transaction->get('TXN_paid') == 0
753
+		) {
754
+			// no payments made yet
755
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
756
+		} elseif ($this->_transaction->get('TXN_total') == 0) {
757
+			// free event
758
+			$this->_template_args['amount_due'] = false;
759
+		}
760
+
761
+		$payment_method = $this->_transaction->payment_method();
762
+
763
+		$this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
764
+			? $payment_method->admin_name()
765
+			: esc_html__('Unknown', 'event_espresso');
766
+
767
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
768
+		// link back to overview
769
+		$this->_template_args['txn_overview_url'] = ! empty($_SERVER['HTTP_REFERER'])
770
+			? $_SERVER['HTTP_REFERER']
771
+			: TXN_ADMIN_URL;
772
+
773
+
774
+		// next link
775
+		$next_txn                                 = $this->_transaction->next(
776
+			null,
777
+			array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
778
+			'TXN_ID'
779
+		);
780
+		$this->_template_args['next_transaction'] = $next_txn
781
+			? $this->_next_link(
782
+				EE_Admin_Page::add_query_args_and_nonce(
783
+					array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']),
784
+					TXN_ADMIN_URL
785
+				),
786
+				'dashicons dashicons-arrow-right ee-icon-size-22'
787
+			)
788
+			: '';
789
+		// previous link
790
+		$previous_txn                                 = $this->_transaction->previous(
791
+			null,
792
+			array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
793
+			'TXN_ID'
794
+		);
795
+		$this->_template_args['previous_transaction'] = $previous_txn
796
+			? $this->_previous_link(
797
+				EE_Admin_Page::add_query_args_and_nonce(
798
+					array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']),
799
+					TXN_ADMIN_URL
800
+				),
801
+				'dashicons dashicons-arrow-left ee-icon-size-22'
802
+			)
803
+			: '';
804
+
805
+		// were we just redirected here after adding a new registration ???
806
+		if (isset(
807
+			$this->_req_data['redirect_from'],
808
+			$this->_req_data['EVT_ID'],
809
+			$this->_req_data['event_name']
810
+		)) {
811
+			if (EE_Registry::instance()->CAP->current_user_can(
812
+				'ee_edit_registrations',
813
+				'espresso_registrations_new_registration',
814
+				$this->_req_data['EVT_ID']
815
+			)) {
816
+				$this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="';
817
+				$this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
818
+					array(
819
+						'page'     => 'espresso_registrations',
820
+						'action'   => 'new_registration',
821
+						'return'   => 'default',
822
+						'TXN_ID'   => $this->_transaction->ID(),
823
+						'event_id' => $this->_req_data['EVT_ID'],
824
+					),
825
+					REG_ADMIN_URL
826
+				);
827
+				$this->_admin_page_title .= '">';
828
+
829
+				$this->_admin_page_title .= sprintf(
830
+					esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
831
+					htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8')
832
+				);
833
+				$this->_admin_page_title .= '</a>';
834
+			}
835
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
836
+		}
837
+		// grab messages at the last second
838
+		$this->_template_args['notices'] = EE_Error::get_notices();
839
+		// path to template
840
+		$template_path                             = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
841
+		$this->_template_args['admin_page_header'] = EEH_Template::display_template(
842
+			$template_path,
843
+			$this->_template_args,
844
+			true
845
+		);
846
+
847
+		// the details template wrapper
848
+		$this->display_admin_page_with_sidebar();
849
+
850
+	}
851
+
852
+
853
+	/**
854
+	 *        _transaction_details_metaboxes
855
+	 *
856
+	 * @access protected
857
+	 * @return void
858
+	 * @throws EE_Error
859
+	 * @throws InvalidArgumentException
860
+	 * @throws InvalidDataTypeException
861
+	 * @throws InvalidInterfaceException
862
+	 * @throws RuntimeException
863
+	 */
864
+	protected function _transaction_details_metaboxes()
865
+	{
866
+
867
+		$this->_set_transaction_object();
868
+
869
+		add_meta_box(
870
+			'edit-txn-details-mbox',
871
+			esc_html__('Transaction Details', 'event_espresso'),
872
+			array($this, 'txn_details_meta_box'),
873
+			$this->_wp_page_slug,
874
+			'normal',
875
+			'high'
876
+		);
877
+		add_meta_box(
878
+			'edit-txn-attendees-mbox',
879
+			esc_html__('Attendees Registered in this Transaction', 'event_espresso'),
880
+			array($this, 'txn_attendees_meta_box'),
881
+			$this->_wp_page_slug,
882
+			'normal',
883
+			'high',
884
+			array('TXN_ID' => $this->_transaction->ID())
885
+		);
886
+		add_meta_box(
887
+			'edit-txn-registrant-mbox',
888
+			esc_html__('Primary Contact', 'event_espresso'),
889
+			array($this, 'txn_registrant_side_meta_box'),
890
+			$this->_wp_page_slug,
891
+			'side',
892
+			'high'
893
+		);
894
+		add_meta_box(
895
+			'edit-txn-billing-info-mbox',
896
+			esc_html__('Billing Information', 'event_espresso'),
897
+			array($this, 'txn_billing_info_side_meta_box'),
898
+			$this->_wp_page_slug,
899
+			'side',
900
+			'high'
901
+		);
902
+	}
903
+
904
+
905
+	/**
906
+	 * txn_details_meta_box
907
+	 * generates HTML for the Transaction main meta box
908
+	 *
909
+	 * @access public
910
+	 * @return void
911
+	 * @throws DomainException
912
+	 * @throws EE_Error
913
+	 * @throws InvalidArgumentException
914
+	 * @throws InvalidDataTypeException
915
+	 * @throws InvalidInterfaceException
916
+	 * @throws RuntimeException
917
+	 */
918
+	public function txn_details_meta_box()
919
+	{
920
+
921
+		$this->_set_transaction_object();
922
+		$this->_template_args['TXN_ID']   = $this->_transaction->ID();
923
+		$this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration
924
+			? $this->_transaction->primary_registration()->attendee()
925
+			: null;
926
+		$this->_template_args['can_edit_payments'] = EE_Registry::instance()->CAP->current_user_can(
927
+			'ee_edit_payments',
928
+			'apply_payment_or_refund_from_registration_details'
929
+		);
930
+		$this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->current_user_can(
931
+			'ee_delete_payments',
932
+			'delete_payment_from_registration_details'
933
+		);
934
+
935
+		//get line table
936
+		EEH_Autoloader::register_line_item_display_autoloaders();
937
+		$Line_Item_Display                       = new EE_Line_Item_Display(
938
+			'admin_table',
939
+			'EE_Admin_Table_Line_Item_Display_Strategy'
940
+		);
941
+		$this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
942
+			$this->_transaction->total_line_item()
943
+		);
944
+		$this->_template_args['REG_code']        = $this->_transaction->get_first_related('Registration')
945
+																	  ->get('REG_code');
946
+
947
+		// process taxes
948
+		$taxes                         = $this->_transaction->get_many_related(
949
+			'Line_Item',
950
+			array(array('LIN_type' => EEM_Line_Item::type_tax))
951
+		);
952
+		$this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
953
+
954
+		$this->_template_args['grand_total']     = EEH_Template::format_currency(
955
+			$this->_transaction->get('TXN_total'),
956
+			false,
957
+			false
958
+		);
959
+		$this->_template_args['grand_raw_total'] = $this->_transaction->get('TXN_total');
960
+		$this->_template_args['TXN_status']      = $this->_transaction->get('STS_ID');
961
+
962
+		// process payment details
963
+		$payments = $this->_transaction->get_many_related('Payment');
964
+		if (! empty($payments)) {
965
+			$this->_template_args['payments']              = $payments;
966
+			$this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
967
+		} else {
968
+			$this->_template_args['payments']              = false;
969
+			$this->_template_args['existing_reg_payments'] = array();
970
+		}
971
+
972
+		$this->_template_args['edit_payment_url']   = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL);
973
+		$this->_template_args['delete_payment_url'] = add_query_arg(
974
+			array('action' => 'espresso_delete_payment'),
975
+			TXN_ADMIN_URL
976
+		);
977
+
978
+		if (isset($txn_details['invoice_number'])) {
979
+			$this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
980
+			$this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
981
+				'Invoice Number',
982
+				'event_espresso'
983
+			);
984
+		}
985
+
986
+		$this->_template_args['txn_details']['registration_session']['value'] = $this->_transaction
987
+			->get_first_related('Registration')
988
+			->get('REG_session');
989
+		$this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
990
+			'Registration Session',
991
+			'event_espresso'
992
+		);
993
+
994
+		$this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address'])
995
+			? $this->_session['ip_address']
996
+			: '';
997
+		$this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
998
+			'Transaction placed from IP',
999
+			'event_espresso'
1000
+		);
1001
+
1002
+		$this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent'])
1003
+			? $this->_session['user_agent']
1004
+			: '';
1005
+		$this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1006
+			'Registrant User Agent',
1007
+			'event_espresso'
1008
+		);
1009
+
1010
+		$reg_steps = '<ul>';
1011
+		foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1012
+			if ($reg_step_status === true) {
1013
+				$reg_steps .= '<li style="color:#70cc50">'
1014
+							  . sprintf(
1015
+								  esc_html__('%1$s : Completed', 'event_espresso'),
1016
+								  ucwords(str_replace('_', ' ', $reg_step))
1017
+							  )
1018
+							  . '</li>';
1019
+			} elseif (is_numeric($reg_step_status) && $reg_step_status !== false) {
1020
+				$reg_steps .= '<li style="color:#2EA2CC">'
1021
+							  . sprintf(
1022
+								  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1023
+								  ucwords(str_replace('_', ' ', $reg_step)),
1024
+								  date(
1025
+									  get_option('date_format') . ' ' . get_option('time_format'),
1026
+									  ($reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS))
1027
+								  )
1028
+							  )
1029
+							  . '</li>';
1030
+			} else {
1031
+				$reg_steps .= '<li style="color:#E76700">'
1032
+							  . sprintf(
1033
+								  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1034
+								  ucwords(str_replace('_', ' ', $reg_step))
1035
+							  )
1036
+							  . '</li>';
1037
+			}
1038
+		}
1039
+		$reg_steps                                                 .= '</ul>';
1040
+		$this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1041
+		$this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1042
+			'Registration Step Progress',
1043
+			'event_espresso'
1044
+		);
1045
+
1046
+
1047
+		$this->_get_registrations_to_apply_payment_to();
1048
+		$this->_get_payment_methods($payments);
1049
+		$this->_get_payment_status_array();
1050
+		$this->_get_reg_status_selection(); //sets up the template args for the reg status array for the transaction.
1051
+
1052
+		$this->_template_args['transaction_form_url']    = add_query_arg(array(
1053
+			'action'  => 'edit_transaction',
1054
+			'process' => 'transaction',
1055
+		), TXN_ADMIN_URL);
1056
+		$this->_template_args['apply_payment_form_url']  = add_query_arg(array(
1057
+			'page'   => 'espresso_transactions',
1058
+			'action' => 'espresso_apply_payment',
1059
+		), WP_AJAX_URL);
1060
+		$this->_template_args['delete_payment_form_url'] = add_query_arg(array(
1061
+			'page'   => 'espresso_transactions',
1062
+			'action' => 'espresso_delete_payment',
1063
+		), WP_AJAX_URL);
1064
+
1065
+		// 'espresso_delete_payment_nonce'
1066
+
1067
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1068
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1069
+	}
1070
+
1071
+
1072
+	/**
1073
+	 * _get_registration_payment_IDs
1074
+	 *    generates an array of Payment IDs and their corresponding Registration IDs
1075
+	 *
1076
+	 * @access protected
1077
+	 * @param EE_Payment[] $payments
1078
+	 * @return array
1079
+	 * @throws EE_Error
1080
+	 * @throws InvalidArgumentException
1081
+	 * @throws InvalidDataTypeException
1082
+	 * @throws InvalidInterfaceException
1083
+	 */
1084
+	protected function _get_registration_payment_IDs($payments = array())
1085
+	{
1086
+		$existing_reg_payments = array();
1087
+		// get all reg payments for these payments
1088
+		$reg_payments = EEM_Registration_Payment::instance()->get_all(array(
1089
+			array(
1090
+				'PAY_ID' => array(
1091
+					'IN',
1092
+					array_keys($payments),
1093
+				),
1094
+			),
1095
+		));
1096
+		if (! empty($reg_payments)) {
1097
+			foreach ($payments as $payment) {
1098
+				if (! $payment instanceof EE_Payment) {
1099
+					continue;
1100
+				} elseif (! isset($existing_reg_payments[$payment->ID()])) {
1101
+					$existing_reg_payments[$payment->ID()] = array();
1102
+				}
1103
+				foreach ($reg_payments as $reg_payment) {
1104
+					if ($reg_payment instanceof EE_Registration_Payment
1105
+						&& $reg_payment->payment_ID() === $payment->ID()
1106
+					) {
1107
+						$existing_reg_payments[$payment->ID()][] = $reg_payment->registration_ID();
1108
+					}
1109
+				}
1110
+			}
1111
+		}
1112
+
1113
+		return $existing_reg_payments;
1114
+	}
1115
+
1116
+
1117
+	/**
1118
+	 * _get_registrations_to_apply_payment_to
1119
+	 *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1120
+	 * which allows the admin to only apply the payment to the specific registrations
1121
+	 *
1122
+	 * @access protected
1123
+	 * @return void
1124
+	 * @throws \EE_Error
1125
+	 */
1126
+	protected function _get_registrations_to_apply_payment_to()
1127
+	{
1128
+		// we want any registration with an active status (ie: not deleted or cancelled)
1129
+		$query_params                      = array(
1130
+			array(
1131
+				'STS_ID' => array(
1132
+					'IN',
1133
+					array(
1134
+						EEM_Registration::status_id_approved,
1135
+						EEM_Registration::status_id_pending_payment,
1136
+						EEM_Registration::status_id_not_approved,
1137
+					),
1138
+				),
1139
+			),
1140
+		);
1141
+		$registrations_to_apply_payment_to = EEH_HTML::br()
1142
+											 . EEH_HTML::div(
1143
+												 '',
1144
+												 'txn-admin-apply-payment-to-registrations-dv',
1145
+												 '',
1146
+												 'clear: both; margin: 1.5em 0 0; display: none;'
1147
+											 );
1148
+		$registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1149
+		$registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
1150
+		$registrations_to_apply_payment_to .= EEH_HTML::thead(
1151
+			EEH_HTML::tr(
1152
+				EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1153
+				EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1154
+				EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1155
+				EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1156
+				EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1157
+				EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1158
+				EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1159
+			)
1160
+		);
1161
+		$registrations_to_apply_payment_to .= EEH_HTML::tbody();
1162
+		// get registrations for TXN
1163
+		$registrations = $this->_transaction->registrations($query_params);
1164
+		$existing_reg_payments = $this->_template_args['existing_reg_payments'];
1165
+		foreach ($registrations as $registration) {
1166
+			if ($registration instanceof EE_Registration) {
1167
+				$attendee_name                     = $registration->attendee() instanceof EE_Attendee
1168
+					? $registration->attendee()->full_name()
1169
+					: esc_html__('Unknown Attendee', 'event_espresso');
1170
+				$owing                             = $registration->final_price() - $registration->paid();
1171
+				$taxable                           = $registration->ticket()->taxable()
1172
+					? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1173
+					: '';
1174
+				$checked = empty($existing_reg_payments) || in_array($registration->ID(), $existing_reg_payments)
1175
+					? ' checked="checked"'
1176
+					: '';
1177
+				$disabled                          = $registration->final_price() > 0 ? '' : ' disabled';
1178
+				$registrations_to_apply_payment_to .= EEH_HTML::tr(
1179
+					EEH_HTML::td($registration->ID()) .
1180
+					EEH_HTML::td($attendee_name) .
1181
+					EEH_HTML::td(
1182
+						$registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1183
+					) .
1184
+					EEH_HTML::td($registration->event_name()) .
1185
+					EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1186
+					EEH_HTML::td(EEH_Template::format_currency($owing), '', 'txn-admin-payment-owing-td jst-cntr') .
1187
+					EEH_HTML::td(
1188
+						'<input type="checkbox" value="' . $registration->ID()
1189
+						. '" name="txn_admin_payment[registrations]"'
1190
+						. $checked . $disabled . '>',
1191
+						'',
1192
+						'jst-cntr'
1193
+					),
1194
+					'apply-payment-registration-row-' . $registration->ID()
1195
+				);
1196
+			}
1197
+		}
1198
+		$registrations_to_apply_payment_to                         .= EEH_HTML::tbodyx();
1199
+		$registrations_to_apply_payment_to                         .= EEH_HTML::tablex();
1200
+		$registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1201
+		$registrations_to_apply_payment_to                         .= EEH_HTML::p(
1202
+			esc_html__(
1203
+				'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1204
+				'event_espresso'
1205
+			),
1206
+			'',
1207
+			'clear description'
1208
+		);
1209
+		$registrations_to_apply_payment_to                         .= EEH_HTML::divx();
1210
+		$this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1211
+	}
1212
+
1213
+
1214
+	/**
1215
+	 * _get_reg_status_selection
1216
+	 *
1217
+	 * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1218
+	 *         instead of events.
1219
+	 * @access protected
1220
+	 * @return void
1221
+	 * @throws EE_Error
1222
+	 */
1223
+	protected function _get_reg_status_selection()
1224
+	{
1225
+		//first get all possible statuses
1226
+		$statuses = EEM_Registration::reg_status_array(array(), true);
1227
+		//let's add a "don't change" option.
1228
+		$status_array['NAN']                                 = esc_html__('Leave the Same', 'event_espresso');
1229
+		$status_array                                        = array_merge($status_array, $statuses);
1230
+		$this->_template_args['status_change_select']        = EEH_Form_Fields::select_input(
1231
+			'txn_reg_status_change[reg_status]',
1232
+			$status_array,
1233
+			'NAN',
1234
+			'id="txn-admin-payment-reg-status-inp"',
1235
+			'txn-reg-status-change-reg-status'
1236
+		);
1237
+		$this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1238
+			'delete_txn_reg_status_change[reg_status]',
1239
+			$status_array,
1240
+			'NAN',
1241
+			'delete-txn-admin-payment-reg-status-inp',
1242
+			'delete-txn-reg-status-change-reg-status'
1243
+		);
1244
+	}
1245
+
1246
+
1247
+	/**
1248
+	 *    _get_payment_methods
1249
+	 * Gets all the payment methods available generally, or the ones that are already
1250
+	 * selected on these payments (in case their payment methods are no longer active).
1251
+	 * Has the side-effect of updating the template args' payment_methods item
1252
+	 *
1253
+	 * @access private
1254
+	 * @param EE_Payment[] to show on this page
1255
+	 * @return void
1256
+	 * @throws EE_Error
1257
+	 * @throws InvalidArgumentException
1258
+	 * @throws InvalidDataTypeException
1259
+	 * @throws InvalidInterfaceException
1260
+	 */
1261
+	private function _get_payment_methods($payments = array())
1262
+	{
1263
+		$payment_methods_of_payments = array();
1264
+		foreach ($payments as $payment) {
1265
+			if ($payment instanceof EE_Payment) {
1266
+				$payment_methods_of_payments[] = $payment->get('PMD_ID');
1267
+			}
1268
+		}
1269
+		if ($payment_methods_of_payments) {
1270
+			$query_args = array(
1271
+				array(
1272
+					'OR*payment_method_for_payment' => array(
1273
+						'PMD_ID'    => array('IN', $payment_methods_of_payments),
1274
+						'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'),
1275
+					),
1276
+				),
1277
+			);
1278
+		} else {
1279
+			$query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1280
+		}
1281
+		$this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1282
+	}
1283
+
1284
+
1285
+	/**
1286
+	 * txn_attendees_meta_box
1287
+	 *    generates HTML for the Attendees Transaction main meta box
1288
+	 *
1289
+	 * @access public
1290
+	 * @param WP_Post $post
1291
+	 * @param array   $metabox
1292
+	 * @return void
1293
+	 * @throws DomainException
1294
+	 * @throws EE_Error
1295
+	 */
1296
+	public function txn_attendees_meta_box($post, $metabox = array('args' => array()))
1297
+	{
1298
+
1299
+		/** @noinspection NonSecureExtractUsageInspection */
1300
+		extract($metabox['args']);
1301
+		$this->_template_args['post']            = $post;
1302
+		$this->_template_args['event_attendees'] = array();
1303
+		// process items in cart
1304
+		$line_items = $this->_transaction->get_many_related(
1305
+			'Line_Item',
1306
+			array(array('LIN_type' => 'line-item'))
1307
+		);
1308
+		if (! empty($line_items)) {
1309
+			foreach ($line_items as $item) {
1310
+				if ($item instanceof EE_Line_Item) {
1311
+					switch ($item->OBJ_type()) {
1312
+						case 'Event':
1313
+							break;
1314
+						case 'Ticket':
1315
+							$ticket = $item->ticket();
1316
+							//right now we're only handling tickets here.
1317
+							//Cause its expected that only tickets will have attendees right?
1318
+							if (! $ticket instanceof EE_Ticket) {
1319
+								continue;
1320
+							}
1321
+							try {
1322
+								$event_name = $ticket->get_event_name();
1323
+							} catch (Exception $e) {
1324
+								EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1325
+								$event_name = esc_html__('Unknown Event', 'event_espresso');
1326
+							}
1327
+							$event_name   .= ' - ' . $item->get('LIN_name');
1328
+							$ticket_price = EEH_Template::format_currency($item->get('LIN_unit_price'));
1329
+							// now get all of the registrations for this transaction that use this ticket
1330
+							$registrations = $ticket->get_many_related(
1331
+								'Registration',
1332
+								array(array('TXN_ID' => $this->_transaction->ID()))
1333
+							);
1334
+							foreach ($registrations as $registration) {
1335
+								if (! $registration instanceof EE_Registration) {
1336
+									continue;
1337
+								}
1338
+								$this->_template_args['event_attendees'][$registration->ID()]['STS_ID']
1339
+									= $registration->status_ID();
1340
+								$this->_template_args['event_attendees'][$registration->ID()]['att_num']
1341
+									= $registration->count();
1342
+								$this->_template_args['event_attendees'][$registration->ID()]['event_ticket_name']
1343
+									= $event_name;
1344
+								$this->_template_args['event_attendees'][$registration->ID()]['ticket_price']
1345
+									= $ticket_price;
1346
+								// attendee info
1347
+								$attendee = $registration->get_first_related('Attendee');
1348
+								if ($attendee instanceof EE_Attendee) {
1349
+									$this->_template_args['event_attendees'][$registration->ID()]['att_id']
1350
+										= $attendee->ID();
1351
+									$this->_template_args['event_attendees'][$registration->ID()]['attendee']
1352
+										= $attendee->full_name();
1353
+									$this->_template_args['event_attendees'][$registration->ID()]['email']
1354
+										= '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1355
+										  . esc_html__(
1356
+											  ' Event',
1357
+											  'event_espresso'
1358
+										  )
1359
+										  . '">' . $attendee->email() . '</a>';
1360
+									$this->_template_args['event_attendees'][$registration->ID()]['address']
1361
+										= EEH_Address::format($attendee, 'inline', false, false);
1362
+								} else {
1363
+									$this->_template_args['event_attendees'][$registration->ID()]['att_id']   = '';
1364
+									$this->_template_args['event_attendees'][$registration->ID()]['attendee'] = '';
1365
+									$this->_template_args['event_attendees'][$registration->ID()]['email']    = '';
1366
+									$this->_template_args['event_attendees'][$registration->ID()]['address']  = '';
1367
+								}
1368
+							}
1369
+							break;
1370
+
1371
+					}
1372
+				}
1373
+			}
1374
+
1375
+			$this->_template_args['transaction_form_url'] = add_query_arg(
1376
+				array(
1377
+					'action'  => 'edit_transaction',
1378
+					'process' => 'attendees',
1379
+				),
1380
+				TXN_ADMIN_URL
1381
+			);
1382
+			echo EEH_Template::display_template(
1383
+				TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1384
+				$this->_template_args,
1385
+				true
1386
+			);
1387
+
1388
+		} else {
1389
+			echo sprintf(
1390
+				esc_html__(
1391
+					'%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1392
+					'event_espresso'
1393
+				),
1394
+				'<p class="important-notice">',
1395
+				'</p>'
1396
+			);
1397
+		}
1398
+	}
1399
+
1400
+
1401
+	/**
1402
+	 * txn_registrant_side_meta_box
1403
+	 * generates HTML for the Edit Transaction side meta box
1404
+	 *
1405
+	 * @access public
1406
+	 * @return void
1407
+	 * @throws DomainException
1408
+	 * @throws EE_Error
1409
+	 * @throws InvalidArgumentException
1410
+	 * @throws InvalidDataTypeException
1411
+	 * @throws InvalidInterfaceException
1412
+	 */
1413
+	public function txn_registrant_side_meta_box()
1414
+	{
1415
+		$primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1416
+			? $this->_transaction->primary_registration()->get_first_related('Attendee')
1417
+			: null;
1418
+		if (! $primary_att instanceof EE_Attendee) {
1419
+			$this->_template_args['no_attendee_message'] = esc_html__(
1420
+				'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1421
+				'event_espresso'
1422
+			);
1423
+			$primary_att                                 = EEM_Attendee::instance()->create_default_object();
1424
+		}
1425
+		$this->_template_args['ATT_ID']            = $primary_att->ID();
1426
+		$this->_template_args['prime_reg_fname']   = $primary_att->fname();
1427
+		$this->_template_args['prime_reg_lname']   = $primary_att->lname();
1428
+		$this->_template_args['prime_reg_email']   = $primary_att->email();
1429
+		$this->_template_args['prime_reg_phone']   = $primary_att->phone();
1430
+		$this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(array(
1431
+			'action' => 'edit_attendee',
1432
+			'post'   => $primary_att->ID(),
1433
+		), REG_ADMIN_URL);
1434
+		// get formatted address for registrant
1435
+		$this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1436
+		echo EEH_Template::display_template(
1437
+			TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1438
+			$this->_template_args,
1439
+			true
1440
+		);
1441
+	}
1442
+
1443
+
1444
+	/**
1445
+	 * txn_billing_info_side_meta_box
1446
+	 *    generates HTML for the Edit Transaction side meta box
1447
+	 *
1448
+	 * @access public
1449
+	 * @return void
1450
+	 * @throws DomainException
1451
+	 * @throws EE_Error
1452
+	 */
1453
+	public function txn_billing_info_side_meta_box()
1454
+	{
1455
+
1456
+		$this->_template_args['billing_form']     = $this->_transaction->billing_info();
1457
+		$this->_template_args['billing_form_url'] = add_query_arg(
1458
+			array('action' => 'edit_transaction', 'process' => 'billing'),
1459
+			TXN_ADMIN_URL
1460
+		);
1461
+
1462
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1463
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);/**/
1464
+	}
1465
+
1466
+
1467
+	/**
1468
+	 * apply_payments_or_refunds
1469
+	 *    registers a payment or refund made towards a transaction
1470
+	 *
1471
+	 * @access public
1472
+	 * @return void
1473
+	 * @throws EE_Error
1474
+	 * @throws InvalidArgumentException
1475
+	 * @throws ReflectionException
1476
+	 * @throws RuntimeException
1477
+	 * @throws InvalidDataTypeException
1478
+	 * @throws InvalidInterfaceException
1479
+	 */
1480
+	public function apply_payments_or_refunds()
1481
+	{
1482
+		$json_response_data = array('return_data' => false);
1483
+		$valid_data         = $this->_validate_payment_request_data();
1484
+		$has_access = EE_Registry::instance()->CAP->current_user_can(
1485
+			'ee_edit_payments',
1486
+			'apply_payment_or_refund_from_registration_details'
1487
+		);
1488
+		if (! empty($valid_data) && $has_access) {
1489
+			$PAY_ID = $valid_data['PAY_ID'];
1490
+			//save  the new payment
1491
+			$payment = $this->_create_payment_from_request_data($valid_data);
1492
+			// get the TXN for this payment
1493
+			$transaction = $payment->transaction();
1494
+			// verify transaction
1495
+			if ($transaction instanceof EE_Transaction) {
1496
+				// calculate_total_payments_and_update_status
1497
+				$this->_process_transaction_payments($transaction);
1498
+				$REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1499
+				$this->_remove_existing_registration_payments($payment, $PAY_ID);
1500
+				// apply payment to registrations (if applicable)
1501
+				if (! empty($REG_IDs)) {
1502
+					$this->_update_registration_payments($transaction, $payment, $REG_IDs);
1503
+					$this->_maybe_send_notifications();
1504
+					// now process status changes for the same registrations
1505
+					$this->_process_registration_status_change($transaction, $REG_IDs);
1506
+				}
1507
+				$this->_maybe_send_notifications($payment);
1508
+				//prepare to render page
1509
+				$json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs);
1510
+				do_action(
1511
+					'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1512
+					$transaction,
1513
+					$payment
1514
+				);
1515
+			} else {
1516
+				EE_Error::add_error(
1517
+					esc_html__(
1518
+						'A valid Transaction for this payment could not be retrieved.',
1519
+						'event_espresso'
1520
+					),
1521
+					__FILE__,
1522
+					__FUNCTION__,
1523
+					__LINE__
1524
+				);
1525
+			}
1526
+		} else {
1527
+			if ($has_access) {
1528
+				EE_Error::add_error(
1529
+					esc_html__(
1530
+						'The payment form data could not be processed. Please try again.',
1531
+						'event_espresso'
1532
+					),
1533
+					__FILE__,
1534
+					__FUNCTION__,
1535
+					__LINE__
1536
+				);
1537
+			} else {
1538
+				EE_Error::add_error(
1539
+					esc_html__(
1540
+						'You do not have access to apply payments or refunds to a registration.',
1541
+						'event_espresso'
1542
+					),
1543
+					__FILE__,
1544
+					__FUNCTION__,
1545
+					__LINE__
1546
+				);
1547
+			}
1548
+		}
1549
+		$notices              = EE_Error::get_notices(
1550
+			false,
1551
+			false,
1552
+			false
1553
+		);
1554
+		$this->_template_args = array(
1555
+			'data'    => $json_response_data,
1556
+			'error'   => $notices['errors'],
1557
+			'success' => $notices['success'],
1558
+		);
1559
+		$this->_return_json();
1560
+	}
1561
+
1562
+
1563
+	/**
1564
+	 * _validate_payment_request_data
1565
+	 *
1566
+	 * @return array
1567
+	 */
1568
+	protected function _validate_payment_request_data()
1569
+	{
1570
+		if (! isset($this->_req_data['txn_admin_payment'])) {
1571
+			return false;
1572
+		}
1573
+		$payment_form = $this->_generate_payment_form_section();
1574
+		try {
1575
+			if ($payment_form->was_submitted()) {
1576
+				$payment_form->receive_form_submission();
1577
+				if (! $payment_form->is_valid()) {
1578
+					$submission_error_messages = array();
1579
+					foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1580
+						if ($validation_error instanceof EE_Validation_Error) {
1581
+							$submission_error_messages[] = sprintf(
1582
+								_x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1583
+								$validation_error->get_form_section()->html_label_text(),
1584
+								$validation_error->getMessage()
1585
+							);
1586
+						}
1587
+					}
1588
+					EE_Error::add_error(
1589
+						implode('<br />', $submission_error_messages),
1590
+						__FILE__,
1591
+						__FUNCTION__,
1592
+						__LINE__
1593
+					);
1594
+
1595
+					return array();
1596
+				}
1597
+			}
1598
+		} catch (EE_Error $e) {
1599
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1600
+
1601
+			return array();
1602
+		}
1603
+
1604
+		return $payment_form->valid_data();
1605
+	}
1606
+
1607
+
1608
+	/**
1609
+	 * _generate_payment_form_section
1610
+	 *
1611
+	 * @return EE_Form_Section_Proper
1612
+	 */
1613
+	protected function _generate_payment_form_section()
1614
+	{
1615
+		return new EE_Form_Section_Proper(
1616
+			array(
1617
+				'name'        => 'txn_admin_payment',
1618
+				'subsections' => array(
1619
+					'PAY_ID'          => new EE_Text_Input(
1620
+						array(
1621
+							'default'               => 0,
1622
+							'required'              => false,
1623
+							'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1624
+							'validation_strategies' => array(new EE_Int_Normalization()),
1625
+						)
1626
+					),
1627
+					'TXN_ID'          => new EE_Text_Input(
1628
+						array(
1629
+							'default'               => 0,
1630
+							'required'              => true,
1631
+							'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1632
+							'validation_strategies' => array(new EE_Int_Normalization()),
1633
+						)
1634
+					),
1635
+					'type'            => new EE_Text_Input(
1636
+						array(
1637
+							'default'               => 1,
1638
+							'required'              => true,
1639
+							'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1640
+							'validation_strategies' => array(new EE_Int_Normalization()),
1641
+						)
1642
+					),
1643
+					'amount'          => new EE_Text_Input(
1644
+						array(
1645
+							'default'               => 0,
1646
+							'required'              => true,
1647
+							'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1648
+							'validation_strategies' => array(new EE_Float_Normalization()),
1649
+						)
1650
+					),
1651
+					'status'          => new EE_Text_Input(
1652
+						array(
1653
+							'default'         => EEM_Payment::status_id_approved,
1654
+							'required'        => true,
1655
+							'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1656
+						)
1657
+					),
1658
+					'PMD_ID'          => new EE_Text_Input(
1659
+						array(
1660
+							'default'               => 2,
1661
+							'required'              => true,
1662
+							'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1663
+							'validation_strategies' => array(new EE_Int_Normalization()),
1664
+						)
1665
+					),
1666
+					'date'            => new EE_Text_Input(
1667
+						array(
1668
+							'default'         => time(),
1669
+							'required'        => true,
1670
+							'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1671
+						)
1672
+					),
1673
+					'txn_id_chq_nmbr' => new EE_Text_Input(
1674
+						array(
1675
+							'default'               => '',
1676
+							'required'              => false,
1677
+							'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1678
+							'validation_strategies' => array(
1679
+								new EE_Max_Length_Validation_Strategy(
1680
+									esc_html__('Input too long', 'event_espresso'),
1681
+									100
1682
+								),
1683
+							),
1684
+						)
1685
+					),
1686
+					'po_number'       => new EE_Text_Input(
1687
+						array(
1688
+							'default'               => '',
1689
+							'required'              => false,
1690
+							'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1691
+							'validation_strategies' => array(
1692
+								new EE_Max_Length_Validation_Strategy(
1693
+									esc_html__('Input too long', 'event_espresso'),
1694
+									100
1695
+								),
1696
+							),
1697
+						)
1698
+					),
1699
+					'accounting'      => new EE_Text_Input(
1700
+						array(
1701
+							'default'               => '',
1702
+							'required'              => false,
1703
+							'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1704
+							'validation_strategies' => array(
1705
+								new EE_Max_Length_Validation_Strategy(
1706
+									esc_html__('Input too long', 'event_espresso'),
1707
+									100
1708
+								),
1709
+							),
1710
+						)
1711
+					),
1712
+				),
1713
+			)
1714
+		);
1715
+	}
1716
+
1717
+
1718
+	/**
1719
+	 * _create_payment_from_request_data
1720
+	 *
1721
+	 * @param array $valid_data
1722
+	 * @return EE_Payment
1723
+	 * @throws EE_Error
1724
+	 */
1725
+	protected function _create_payment_from_request_data($valid_data)
1726
+	{
1727
+		$PAY_ID = $valid_data['PAY_ID'];
1728
+		// get payment amount
1729
+		$amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1730
+		// payments have a type value of 1 and refunds have a type value of -1
1731
+		// so multiplying amount by type will give a positive value for payments, and negative values for refunds
1732
+		$amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1733
+		// for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1734
+		$date    = $valid_data['date']
1735
+			? preg_replace('/\s+/', ' ', $valid_data['date'])
1736
+			: date('Y-m-d g:i a', current_time('timestamp'));
1737
+		$payment = EE_Payment::new_instance(
1738
+			array(
1739
+				'TXN_ID'              => $valid_data['TXN_ID'],
1740
+				'STS_ID'              => $valid_data['status'],
1741
+				'PAY_timestamp'       => $date,
1742
+				'PAY_source'          => EEM_Payment_Method::scope_admin,
1743
+				'PMD_ID'              => $valid_data['PMD_ID'],
1744
+				'PAY_amount'          => $amount,
1745
+				'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1746
+				'PAY_po_number'       => $valid_data['po_number'],
1747
+				'PAY_extra_accntng'   => $valid_data['accounting'],
1748
+				'PAY_details'         => $valid_data,
1749
+				'PAY_ID'              => $PAY_ID,
1750
+			),
1751
+			'',
1752
+			array('Y-m-d', 'g:i a')
1753
+		);
1754
+
1755
+		if (! $payment->save()) {
1756
+			EE_Error::add_error(
1757
+				sprintf(
1758
+					esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1759
+					$payment->ID()
1760
+				),
1761
+				__FILE__, __FUNCTION__, __LINE__
1762
+			);
1763
+		}
1764
+
1765
+		return $payment;
1766
+	}
1767
+
1768
+
1769
+	/**
1770
+	 * _process_transaction_payments
1771
+	 *
1772
+	 * @param \EE_Transaction $transaction
1773
+	 * @return void
1774
+	 * @throws EE_Error
1775
+	 * @throws InvalidArgumentException
1776
+	 * @throws ReflectionException
1777
+	 * @throws InvalidDataTypeException
1778
+	 * @throws InvalidInterfaceException
1779
+	 */
1780
+	protected function _process_transaction_payments(EE_Transaction $transaction)
1781
+	{
1782
+		/** @type EE_Transaction_Payments $transaction_payments */
1783
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1784
+		//update the transaction with this payment
1785
+		if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1786
+			EE_Error::add_success(esc_html__(
1787
+				'The payment has been processed successfully.', 'event_espresso'),
1788
+				__FILE__,
1789
+				__FUNCTION__,
1790
+				__LINE__
1791
+			);
1792
+		} else {
1793
+			EE_Error::add_error(
1794
+				esc_html__(
1795
+					'The payment was processed successfully but the amount paid for the transaction was not updated.',
1796
+					'event_espresso'
1797
+				)
1798
+				,
1799
+				__FILE__,
1800
+				__FUNCTION__,
1801
+				__LINE__
1802
+			);
1803
+		}
1804
+	}
1805
+
1806
+
1807
+	/**
1808
+	 * _get_REG_IDs_to_apply_payment_to
1809
+	 * returns a list of registration IDs that the payment will apply to
1810
+	 *
1811
+	 * @param \EE_Payment $payment
1812
+	 * @return array
1813
+	 * @throws EE_Error
1814
+	 */
1815
+	protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1816
+	{
1817
+		$REG_IDs = array();
1818
+		// grab array of IDs for specific registrations to apply changes to
1819
+		if (isset($this->_req_data['txn_admin_payment']['registrations'])) {
1820
+			$REG_IDs = (array)$this->_req_data['txn_admin_payment']['registrations'];
1821
+		}
1822
+		//nothing specified ? then get all reg IDs
1823
+		if (empty($REG_IDs)) {
1824
+			$registrations = $payment->transaction()->registrations();
1825
+			$REG_IDs       = ! empty($registrations)
1826
+				? array_keys($registrations)
1827
+				: $this->_get_existing_reg_payment_REG_IDs($payment);
1828
+		}
1829
+
1830
+		// ensure that REG_IDs are integers and NOT strings
1831
+		return array_map('intval', $REG_IDs);
1832
+	}
1833
+
1834
+
1835
+	/**
1836
+	 * @return array
1837
+	 */
1838
+	public function existing_reg_payment_REG_IDs()
1839
+	{
1840
+		return $this->_existing_reg_payment_REG_IDs;
1841
+	}
1842
+
1843
+
1844
+	/**
1845
+	 * @param array $existing_reg_payment_REG_IDs
1846
+	 */
1847
+	public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
1848
+	{
1849
+		$this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
1850
+	}
1851
+
1852
+
1853
+	/**
1854
+	 * _get_existing_reg_payment_REG_IDs
1855
+	 * returns a list of registration IDs that the payment is currently related to
1856
+	 * as recorded in the database
1857
+	 *
1858
+	 * @param \EE_Payment $payment
1859
+	 * @return array
1860
+	 * @throws EE_Error
1861
+	 */
1862
+	protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
1863
+	{
1864
+		if ($this->existing_reg_payment_REG_IDs() === null) {
1865
+			// let's get any existing reg payment records for this payment
1866
+			$existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
1867
+			// but we only want the REG IDs, so grab the array keys
1868
+			$existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
1869
+				? array_keys($existing_reg_payment_REG_IDs)
1870
+				: array();
1871
+			$this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
1872
+		}
1873
+
1874
+		return $this->existing_reg_payment_REG_IDs();
1875
+	}
1876
+
1877
+
1878
+	/**
1879
+	 * _remove_existing_registration_payments
1880
+	 * this calculates the difference between existing relations
1881
+	 * to the supplied payment and the new list registration IDs,
1882
+	 * removes any related registrations that no longer apply,
1883
+	 * and then updates the registration paid fields
1884
+	 *
1885
+	 * @param \EE_Payment $payment
1886
+	 * @param int         $PAY_ID
1887
+	 * @return bool;
1888
+	 * @throws EE_Error
1889
+	 * @throws InvalidArgumentException
1890
+	 * @throws ReflectionException
1891
+	 * @throws InvalidDataTypeException
1892
+	 * @throws InvalidInterfaceException
1893
+	 */
1894
+	protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
1895
+	{
1896
+		// newly created payments will have nothing recorded for $PAY_ID
1897
+		if ($PAY_ID == 0) {
1898
+			return false;
1899
+		}
1900
+		$existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
1901
+		if (empty($existing_reg_payment_REG_IDs)) {
1902
+			return false;
1903
+		}
1904
+		/** @type EE_Transaction_Payments $transaction_payments */
1905
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1906
+
1907
+		return $transaction_payments->delete_registration_payments_and_update_registrations(
1908
+			$payment,
1909
+			array(
1910
+				array(
1911
+					'PAY_ID' => $payment->ID(),
1912
+					'REG_ID' => array('IN', $existing_reg_payment_REG_IDs),
1913
+				),
1914
+			)
1915
+		);
1916
+	}
1917
+
1918
+
1919
+	/**
1920
+	 * _update_registration_payments
1921
+	 * this applies the payments to the selected registrations
1922
+	 * but only if they have not already been paid for
1923
+	 *
1924
+	 * @param  EE_Transaction $transaction
1925
+	 * @param \EE_Payment     $payment
1926
+	 * @param array           $REG_IDs
1927
+	 * @return void
1928
+	 * @throws EE_Error
1929
+	 * @throws InvalidArgumentException
1930
+	 * @throws ReflectionException
1931
+	 * @throws RuntimeException
1932
+	 * @throws InvalidDataTypeException
1933
+	 * @throws InvalidInterfaceException
1934
+	 */
1935
+	protected function _update_registration_payments(
1936
+		EE_Transaction $transaction,
1937
+		EE_Payment $payment,
1938
+		$REG_IDs = array()
1939
+	) {
1940
+		// we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
1941
+		// so let's do that using our set of REG_IDs from the form
1942
+		$registration_query_where_params = array(
1943
+			'REG_ID' => array('IN', $REG_IDs),
1944
+		);
1945
+		// but add in some conditions regarding payment,
1946
+		// so that we don't apply payments to registrations that are free or have already been paid for
1947
+		// but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
1948
+		if (! $payment->is_a_refund()) {
1949
+			$registration_query_where_params['REG_final_price']  = array('!=', 0);
1950
+			$registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
1951
+		}
1952
+		$registrations = $transaction->registrations(array($registration_query_where_params));
1953
+		if (! empty($registrations)) {
1954
+			/** @type EE_Payment_Processor $payment_processor */
1955
+			$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
1956
+			$payment_processor->process_registration_payments($transaction, $payment, $registrations);
1957
+		}
1958
+	}
1959
+
1960
+
1961
+	/**
1962
+	 * _process_registration_status_change
1963
+	 * This processes requested registration status changes for all the registrations
1964
+	 * on a given transaction and (optionally) sends out notifications for the changes.
1965
+	 *
1966
+	 * @param  EE_Transaction $transaction
1967
+	 * @param array           $REG_IDs
1968
+	 * @return bool
1969
+	 * @throws EE_Error
1970
+	 * @throws InvalidArgumentException
1971
+	 * @throws ReflectionException
1972
+	 * @throws InvalidDataTypeException
1973
+	 * @throws InvalidInterfaceException
1974
+	 */
1975
+	protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array())
1976
+	{
1977
+		// first if there is no change in status then we get out.
1978
+		if (
1979
+			! isset($this->_req_data['txn_reg_status_change']['reg_status'])
1980
+			|| $this->_req_data['txn_reg_status_change']['reg_status'] === 'NAN'
1981
+		) {
1982
+			//no error message, no change requested, just nothing to do man.
1983
+			return false;
1984
+		}
1985
+		/** @type EE_Transaction_Processor $transaction_processor */
1986
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
1987
+
1988
+		// made it here dude?  Oh WOW.  K, let's take care of changing the statuses
1989
+		return $transaction_processor->manually_update_registration_statuses(
1990
+			$transaction,
1991
+			sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']),
1992
+			array(array('REG_ID' => array('IN', $REG_IDs)))
1993
+		);
1994
+	}
1995
+
1996
+
1997
+	/**
1998
+	 * _build_payment_json_response
1999
+	 *
2000
+	 * @access public
2001
+	 * @param \EE_Payment $payment
2002
+	 * @param array       $REG_IDs
2003
+	 * @param bool | null $delete_txn_reg_status_change
2004
+	 * @return array
2005
+	 * @throws EE_Error
2006
+	 * @throws InvalidArgumentException
2007
+	 * @throws InvalidDataTypeException
2008
+	 * @throws InvalidInterfaceException
2009
+	 */
2010
+	protected function _build_payment_json_response(
2011
+		EE_Payment $payment,
2012
+		$REG_IDs = array(),
2013
+		$delete_txn_reg_status_change = null
2014
+	) {
2015
+		// was the payment deleted ?
2016
+		if (is_bool($delete_txn_reg_status_change)) {
2017
+			return array(
2018
+				'PAY_ID'                       => $payment->ID(),
2019
+				'amount'                       => $payment->amount(),
2020
+				'total_paid'                   => $payment->transaction()->paid(),
2021
+				'txn_status'                   => $payment->transaction()->status_ID(),
2022
+				'pay_status'                   => $payment->STS_ID(),
2023
+				'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2024
+				'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2025
+			);
2026
+		} else {
2027
+			$this->_get_payment_status_array();
2028
+
2029
+			return array(
2030
+				'amount'           => $payment->amount(),
2031
+				'total_paid'       => $payment->transaction()->paid(),
2032
+				'txn_status'       => $payment->transaction()->status_ID(),
2033
+				'pay_status'       => $payment->STS_ID(),
2034
+				'PAY_ID'           => $payment->ID(),
2035
+				'STS_ID'           => $payment->STS_ID(),
2036
+				'status'           => self::$_pay_status[$payment->STS_ID()],
2037
+				'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2038
+				'method'           => strtoupper($payment->source()),
2039
+				'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
2040
+				'gateway'          => $payment->payment_method()
2041
+					? $payment->payment_method()->admin_name()
2042
+					: esc_html__("Unknown", 'event_espresso'),
2043
+				'gateway_response' => $payment->gateway_response(),
2044
+				'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2045
+				'po_number'        => $payment->po_number(),
2046
+				'extra_accntng'    => $payment->extra_accntng(),
2047
+				'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2048
+			);
2049
+		}
2050
+	}
2051
+
2052
+
2053
+	/**
2054
+	 * delete_payment
2055
+	 *    delete a payment or refund made towards a transaction
2056
+	 *
2057
+	 * @access public
2058
+	 * @return void
2059
+	 * @throws EE_Error
2060
+	 * @throws InvalidArgumentException
2061
+	 * @throws ReflectionException
2062
+	 * @throws InvalidDataTypeException
2063
+	 * @throws InvalidInterfaceException
2064
+	 */
2065
+	public function delete_payment()
2066
+	{
2067
+		$json_response_data = array('return_data' => false);
2068
+		$PAY_ID             = isset($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2069
+			? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2070
+			: 0;
2071
+		$can_delete = EE_Registry::instance()->CAP->current_user_can(
2072
+			'ee_delete_payments',
2073
+			'delete_payment_from_registration_details'
2074
+		);
2075
+		if ($PAY_ID && $can_delete) {
2076
+			$delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change'])
2077
+				? $this->_req_data['delete_txn_reg_status_change']
2078
+				: false;
2079
+			$payment                      = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2080
+			if ($payment instanceof EE_Payment) {
2081
+				$REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2082
+				/** @type EE_Transaction_Payments $transaction_payments */
2083
+				$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2084
+				if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2085
+					$json_response_data['return_data'] = $this->_build_payment_json_response(
2086
+						$payment,
2087
+						$REG_IDs,
2088
+						$delete_txn_reg_status_change
2089
+					);
2090
+					if ($delete_txn_reg_status_change) {
2091
+						$this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
2092
+						//MAKE sure we also add the delete_txn_req_status_change to the
2093
+						//$_REQUEST global because that's how messages will be looking for it.
2094
+						$_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
2095
+						$this->_maybe_send_notifications();
2096
+						$this->_process_registration_status_change($payment->transaction(), $REG_IDs);
2097
+					}
2098
+				}
2099
+			} else {
2100
+				EE_Error::add_error(
2101
+					esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2102
+					__FILE__, __FUNCTION__, __LINE__
2103
+				);
2104
+			}
2105
+		} else {
2106
+			if ($can_delete) {
2107
+				EE_Error::add_error(
2108
+					esc_html__(
2109
+						'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2110
+						'event_espresso'
2111
+					),
2112
+					__FILE__, __FUNCTION__, __LINE__
2113
+				);
2114
+			} else {
2115
+				EE_Error::add_error(
2116
+					esc_html__(
2117
+						'You do not have access to delete a payment.',
2118
+						'event_espresso'
2119
+					),
2120
+					__FILE__,
2121
+					__FUNCTION__,
2122
+					__LINE__
2123
+				);
2124
+			}
2125
+		}
2126
+		$notices              = EE_Error::get_notices(false, false, false);
2127
+		$this->_template_args = array(
2128
+			'data'      => $json_response_data,
2129
+			'success'   => $notices['success'],
2130
+			'error'     => $notices['errors'],
2131
+			'attention' => $notices['attention'],
2132
+		);
2133
+		$this->_return_json();
2134
+	}
2135
+
2136
+
2137
+	/**
2138
+	 * _registration_payment_data_array
2139
+	 * adds info for 'owing' and 'paid' for each registration to the json response
2140
+	 *
2141
+	 * @access protected
2142
+	 * @param array $REG_IDs
2143
+	 * @return array
2144
+	 * @throws EE_Error
2145
+	 * @throws InvalidArgumentException
2146
+	 * @throws InvalidDataTypeException
2147
+	 * @throws InvalidInterfaceException
2148
+	 */
2149
+	protected function _registration_payment_data_array($REG_IDs)
2150
+	{
2151
+		$registration_payment_data = array();
2152
+		//if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2153
+		if (! empty($REG_IDs)) {
2154
+			$registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
2155
+			foreach ($registrations as $registration) {
2156
+				if ($registration instanceof EE_Registration) {
2157
+					$registration_payment_data[$registration->ID()] = array(
2158
+						'paid'  => $registration->pretty_paid(),
2159
+						'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2160
+					);
2161
+				}
2162
+			}
2163
+		}
2164
+
2165
+		return $registration_payment_data;
2166
+	}
2167
+
2168
+
2169
+	/**
2170
+	 * _maybe_send_notifications
2171
+	 * determines whether or not the admin has indicated that notifications should be sent.
2172
+	 * If so, will toggle a filter switch for delivering registration notices.
2173
+	 * If passed an EE_Payment object, then it will trigger payment notifications instead.
2174
+	 *
2175
+	 * @access protected
2176
+	 * @param \EE_Payment | null $payment
2177
+	 */
2178
+	protected function _maybe_send_notifications($payment = null)
2179
+	{
2180
+		switch ($payment instanceof EE_Payment) {
2181
+			// payment notifications
2182
+			case true :
2183
+				if (
2184
+					isset(
2185
+						$this->_req_data['txn_payments'],
2186
+						$this->_req_data['txn_payments']['send_notifications']
2187
+					) &&
2188
+					filter_var($this->_req_data['txn_payments']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
2189
+				) {
2190
+					$this->_process_payment_notification($payment);
2191
+				}
2192
+				break;
2193
+			// registration notifications
2194
+			case false :
2195
+				if (
2196
+					isset(
2197
+						$this->_req_data['txn_reg_status_change'],
2198
+						$this->_req_data['txn_reg_status_change']['send_notifications']
2199
+					) &&
2200
+					filter_var($this->_req_data['txn_reg_status_change']['send_notifications'], FILTER_VALIDATE_BOOLEAN)
2201
+				) {
2202
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2203
+				}
2204
+				break;
2205
+		}
2206
+	}
2207
+
2208
+
2209
+	/**
2210
+	 * _send_payment_reminder
2211
+	 *    generates HTML for the View Transaction Details Admin page
2212
+	 *
2213
+	 * @access protected
2214
+	 * @return void
2215
+	 * @throws EE_Error
2216
+	 * @throws InvalidArgumentException
2217
+	 * @throws InvalidDataTypeException
2218
+	 * @throws InvalidInterfaceException
2219
+	 */
2220
+	protected function _send_payment_reminder()
2221
+	{
2222
+		$TXN_ID      = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2223
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2224
+		$query_args  = isset($this->_req_data['redirect_to']) ? array(
2225
+			'action' => $this->_req_data['redirect_to'],
2226
+			'TXN_ID' => $this->_req_data['TXN_ID'],
2227
+		) : array();
2228
+		do_action(
2229
+			'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2230
+			$transaction
2231
+		);
2232
+		$this->_redirect_after_action(
2233
+			false,
2234
+			esc_html__('payment reminder', 'event_espresso'),
2235
+			esc_html__('sent', 'event_espresso'),
2236
+			$query_args,
2237
+			true
2238
+		);
2239
+	}
2240
+
2241
+
2242
+	/**
2243
+	 *  get_transactions
2244
+	 *    get transactions for given parameters (used by list table)
2245
+	 *
2246
+	 * @param  int     $perpage how many transactions displayed per page
2247
+	 * @param  boolean $count   return the count or objects
2248
+	 * @param string   $view
2249
+	 * @return mixed int = count || array of transaction objects
2250
+	 * @throws EE_Error
2251
+	 * @throws InvalidArgumentException
2252
+	 * @throws InvalidDataTypeException
2253
+	 * @throws InvalidInterfaceException
2254
+	 */
2255
+	public function get_transactions($perpage, $count = false, $view = '')
2256
+	{
2257
+
2258
+		$TXN = EEM_Transaction::instance();
2259
+
2260
+		$start_date = isset($this->_req_data['txn-filter-start-date'])
2261
+			? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
2262
+			: date(
2263
+				'm/d/Y',
2264
+				strtotime('-10 year')
2265
+			);
2266
+		$end_date   = isset($this->_req_data['txn-filter-end-date'])
2267
+			? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
2268
+			: date('m/d/Y');
2269
+
2270
+		//make sure our timestamps start and end right at the boundaries for each day
2271
+		$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2272
+		$end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2273
+
2274
+
2275
+		//convert to timestamps
2276
+		$start_date = strtotime($start_date);
2277
+		$end_date   = strtotime($end_date);
2278
+
2279
+		//makes sure start date is the lowest value and vice versa
2280
+		$start_date = min($start_date, $end_date);
2281
+		$end_date   = max($start_date, $end_date);
2282
+
2283
+		//convert to correct format for query
2284
+		$start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2285
+			'TXN_timestamp',
2286
+			date('Y-m-d H:i:s', $start_date),
2287
+			'Y-m-d H:i:s'
2288
+		);
2289
+		$end_date   = EEM_Transaction::instance()->convert_datetime_for_query(
2290
+			'TXN_timestamp',
2291
+			date('Y-m-d H:i:s', $end_date),
2292
+			'Y-m-d H:i:s'
2293
+		);
2294
+
2295
+
2296
+		//set orderby
2297
+		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
2298
+
2299
+		switch ($this->_req_data['orderby']) {
2300
+			case 'TXN_ID':
2301
+				$orderby = 'TXN_ID';
2302
+				break;
2303
+			case 'ATT_fname':
2304
+				$orderby = 'Registration.Attendee.ATT_fname';
2305
+				break;
2306
+			case 'event_name':
2307
+				$orderby = 'Registration.Event.EVT_name';
2308
+				break;
2309
+			default: //'TXN_timestamp'
2310
+				$orderby = 'TXN_timestamp';
2311
+		}
2312
+
2313
+		$sort         = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2314
+		$current_page = ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1;
2315
+		$per_page     = ! empty($perpage) ? $perpage : 10;
2316
+		$per_page     = ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page;
2317
+
2318
+		$offset = ($current_page - 1) * $per_page;
2319
+		$limit  = array($offset, $per_page);
2320
+
2321
+		$_where = array(
2322
+			'TXN_timestamp'          => array('BETWEEN', array($start_date, $end_date)),
2323
+			'Registration.REG_count' => 1,
2324
+		);
2325
+
2326
+		if (isset($this->_req_data['EVT_ID'])) {
2327
+			$_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID'];
2328
+		}
2329
+
2330
+		if (isset($this->_req_data['s'])) {
2331
+			$search_string = '%' . $this->_req_data['s'] . '%';
2332
+			$_where['OR']  = array(
2333
+				'Registration.Event.EVT_name'         => array('LIKE', $search_string),
2334
+				'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
2335
+				'Registration.Event.EVT_short_desc'   => array('LIKE', $search_string),
2336
+				'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string),
2337
+				'Registration.Attendee.ATT_fname'     => array('LIKE', $search_string),
2338
+				'Registration.Attendee.ATT_lname'     => array('LIKE', $search_string),
2339
+				'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string),
2340
+				'Registration.Attendee.ATT_email'     => array('LIKE', $search_string),
2341
+				'Registration.Attendee.ATT_address'   => array('LIKE', $search_string),
2342
+				'Registration.Attendee.ATT_address2'  => array('LIKE', $search_string),
2343
+				'Registration.Attendee.ATT_city'      => array('LIKE', $search_string),
2344
+				'Registration.REG_final_price'        => array('LIKE', $search_string),
2345
+				'Registration.REG_code'               => array('LIKE', $search_string),
2346
+				'Registration.REG_count'              => array('LIKE', $search_string),
2347
+				'Registration.REG_group_size'         => array('LIKE', $search_string),
2348
+				'Registration.Ticket.TKT_name'        => array('LIKE', $search_string),
2349
+				'Registration.Ticket.TKT_description' => array('LIKE', $search_string),
2350
+				'Payment.PAY_source'                  => array('LIKE', $search_string),
2351
+				'Payment.Payment_Method.PMD_name'     => array('LIKE', $search_string),
2352
+				'TXN_session_data'                    => array('LIKE', $search_string),
2353
+				'Payment.PAY_txn_id_chq_nmbr'         => array('LIKE', $search_string),
2354
+			);
2355
+		}
2356
+
2357
+		//failed transactions
2358
+		$failed    = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count)
2359
+					 || ($count && $view === 'failed');
2360
+		$abandoned = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count)
2361
+					 || ($count && $view === 'abandoned');
2362
+
2363
+		if ($failed) {
2364
+			$_where['STS_ID'] = EEM_Transaction::failed_status_code;
2365
+		} else if ($abandoned) {
2366
+			$_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2367
+		} else {
2368
+			$_where['STS_ID']  = array('!=', EEM_Transaction::failed_status_code);
2369
+			$_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code);
2370
+		}
2371
+
2372
+		$query_params = array(
2373
+			$_where,
2374
+			'order_by'                 => array($orderby => $sort),
2375
+			'limit'                    => $limit,
2376
+			'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2377
+		);
2378
+
2379
+		$transactions = $count
2380
+			? $TXN->count(array($_where), 'TXN_ID', true)
2381
+			: $TXN->get_all($query_params);
2382
+
2383
+		return $transactions;
2384
+	}
2385 2385
 }
Please login to merge, or discard this patch.